https://github.com/adams381 updated https://github.com/llvm/llvm-project/pull/198362
>From 08d84c084b42cd5be105fd1f7fb60dde90c9ae29 Mon Sep 17 00:00:00 2001 From: Adam Smith <[email protected]> Date: Thu, 14 May 2026 15:34:30 -0700 Subject: [PATCH 1/4] [CIR] Report NYI for STDC FENV_ACCESS under -fclangir CIR does not implement constrained floating-point codegen. Functions that use FENV_ACCESS (or get implicit StrictFP from it) now hit errorNYI at function entry instead of asserting or emitting plain fadd. generateCode skips the body after the diagnostic. The RAII helper reports the same NYI if a constrained pragma is seen on a path that was not caught earlier. The test expects CIR compilation to fail under -verify. --- clang/lib/CIR/CodeGen/CIRGenFunction.cpp | 17 +++++++++++------ clang/test/CIR/CodeGen/fp-pragma-fenv-access.c | 11 +++++++++++ 2 files changed, 22 insertions(+), 6 deletions(-) create mode 100644 clang/test/CIR/CodeGen/fp-pragma-fenv-access.c diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp index c64000d2a1c4b..2bf0ce1b73ffa 100644 --- a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp @@ -499,6 +499,9 @@ void CIRGenFunction::startFunction(GlobalDecl gd, QualType returnType, const auto *fd = dyn_cast_or_null<FunctionDecl>(d); curFuncDecl = (d ? d->getNonClosureContext() : nullptr); + if (fd && (fd->UsesFPIntrin() || fd->hasAttr<StrictFPAttr>())) + cgm.errorNYI(loc, "STDC FENV_ACCESS"); + prologueCleanupDepth = ehStack.stable_begin(); mlir::Block *entryBB = &fn.getBlocks().front(); @@ -777,6 +780,8 @@ cir::FuncOp CIRGenFunction::generateCode(clang::GlobalDecl gd, cir::FuncOp fn, // Emit the standard function prologue. startFunction(gd, retTy, fn, funcType, args, loc, bodyRange.getBegin()); + if (cgm.getDiags().hasErrorOccurred()) + return fn; // Save parameters for coroutine function. if (body && isa_and_nonnull<CoroutineBodyStmt>(body)) @@ -1364,12 +1369,12 @@ void CIRGenFunction::CIRGenFPOptionsRAII::ConstructorHelper( // TODO(cir): override FP flags once FM configs are guarded. assert(!cir::MissingFeatures::fastMathFlags()); - assert((cgf.curFuncDecl == nullptr || cgf.builder.getIsFPConstrained() || - isa<CXXConstructorDecl>(cgf.curFuncDecl) || - isa<CXXDestructorDecl>(cgf.curFuncDecl) || - (newExceptionBehavior == llvm::fp::ebIgnore && - newRoundingBehavior == llvm::RoundingMode::NearestTiesToEven)) && - "FPConstrained should be enabled on entire function"); + if (cgf.curFuncDecl && !cgf.builder.getIsFPConstrained() && + !isa<CXXConstructorDecl>(cgf.curFuncDecl) && + !isa<CXXDestructorDecl>(cgf.curFuncDecl) && + (newExceptionBehavior != llvm::fp::ebIgnore || + newRoundingBehavior != llvm::RoundingMode::NearestTiesToEven)) + cgf.cgm.errorNYI(cgf.curFuncDecl->getLocation(), "STDC FENV_ACCESS"); // TODO(cir): mark CIR function with fast math attributes. assert(!cir::MissingFeatures::fastMathFuncAttributes()); diff --git a/clang/test/CIR/CodeGen/fp-pragma-fenv-access.c b/clang/test/CIR/CodeGen/fp-pragma-fenv-access.c new file mode 100644 index 0000000000000..88899e95bd43a --- /dev/null +++ b/clang/test/CIR/CodeGen/fp-pragma-fenv-access.c @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir %s -verify -emit-cir -o - + +extern void use(float f); +float a, b; + +// expected-error@+1 {{ClangIR code gen Not Yet Implemented: STDC FENV_ACCESS}} +void fenv_access(void) { + #pragma STDC FENV_ACCESS ON + __builtin_set_flt_rounds(0); + use(a + b); +} >From 8857df6fdc039851931953e4183a83caa9f7d0ad Mon Sep 17 00:00:00 2001 From: Adam Smith <[email protected]> Date: Mon, 18 May 2026 19:31:53 -0700 Subject: [PATCH 2/4] [CIR] Scope FENV NYI body skip to the current function generateCode used hasErrorOccurred() after startFunction, so any earlier NYI in the translation unit skipped later function bodies. That broke CIR/CodeGenOpenMP/parallel.c and CIR/CodeGenHLSL/matrix-element-expr-load.hlsl when combined with the FENV NYI path on #198362. Use a per-function skipFunctionBody flag set only when this function reports STDC FENV_ACCESS NYI. Stop emitting further statements in that function via emitStmt once the flag is set. Remove fp-pragma-fenv-access.c per review on #198362. --- clang/lib/CIR/CodeGen/CIRGenFunction.cpp | 11 ++++++++--- clang/lib/CIR/CodeGen/CIRGenFunction.h | 3 +++ clang/lib/CIR/CodeGen/CIRGenStmt.cpp | 3 +++ clang/test/CIR/CodeGen/fp-pragma-fenv-access.c | 11 ----------- 4 files changed, 14 insertions(+), 14 deletions(-) delete mode 100644 clang/test/CIR/CodeGen/fp-pragma-fenv-access.c diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp index 2bf0ce1b73ffa..4affcba8095b3 100644 --- a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp @@ -499,8 +499,10 @@ void CIRGenFunction::startFunction(GlobalDecl gd, QualType returnType, const auto *fd = dyn_cast_or_null<FunctionDecl>(d); curFuncDecl = (d ? d->getNonClosureContext() : nullptr); - if (fd && (fd->UsesFPIntrin() || fd->hasAttr<StrictFPAttr>())) + if (fd && (fd->UsesFPIntrin() || fd->hasAttr<StrictFPAttr>())) { + skipFunctionBody = true; cgm.errorNYI(loc, "STDC FENV_ACCESS"); + } prologueCleanupDepth = ehStack.stable_begin(); @@ -706,6 +708,7 @@ static void eraseEmptyAndUnusedBlocks(cir::FuncOp func) { cir::FuncOp CIRGenFunction::generateCode(clang::GlobalDecl gd, cir::FuncOp fn, cir::FuncType funcType) { + skipFunctionBody = false; const auto *funcDecl = cast<FunctionDecl>(gd.getDecl()); curGD = gd; @@ -780,7 +783,7 @@ cir::FuncOp CIRGenFunction::generateCode(clang::GlobalDecl gd, cir::FuncOp fn, // Emit the standard function prologue. startFunction(gd, retTy, fn, funcType, args, loc, bodyRange.getBegin()); - if (cgm.getDiags().hasErrorOccurred()) + if (skipFunctionBody) return fn; // Save parameters for coroutine function. @@ -1373,8 +1376,10 @@ void CIRGenFunction::CIRGenFPOptionsRAII::ConstructorHelper( !isa<CXXConstructorDecl>(cgf.curFuncDecl) && !isa<CXXDestructorDecl>(cgf.curFuncDecl) && (newExceptionBehavior != llvm::fp::ebIgnore || - newRoundingBehavior != llvm::RoundingMode::NearestTiesToEven)) + newRoundingBehavior != llvm::RoundingMode::NearestTiesToEven)) { + cgf.skipFunctionBody = true; cgf.cgm.errorNYI(cgf.curFuncDecl->getLocation(), "STDC FENV_ACCESS"); + } // TODO(cir): mark CIR function with fast math attributes. assert(!cir::MissingFeatures::fastMathFuncAttributes()); diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h index dcc80817c866b..66ab11d5b2c37 100644 --- a/clang/lib/CIR/CodeGen/CIRGenFunction.h +++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h @@ -196,6 +196,9 @@ class CIRGenFunction : public CIRGenTypeCache { // Holds the Decl for the current outermost non-closure context const clang::Decl *curFuncDecl = nullptr; + /// When true, generateCode must not emit the function body after the + /// prologue (e.g. after reporting STDC FENV_ACCESS NYI for this function). + bool skipFunctionBody = false; /// This is the inner-most code context, which includes blocks. const clang::Decl *curCodeDecl = nullptr; const CIRGenFunctionInfo *curFnInfo = nullptr; diff --git a/clang/lib/CIR/CodeGen/CIRGenStmt.cpp b/clang/lib/CIR/CodeGen/CIRGenStmt.cpp index a64a2a080bade..0adb258ef6e0d 100644 --- a/clang/lib/CIR/CodeGen/CIRGenStmt.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenStmt.cpp @@ -143,6 +143,9 @@ void CIRGenFunction::emitStopPoint(const Stmt *s) { mlir::LogicalResult CIRGenFunction::emitStmt(const Stmt *s, bool useCurrentScope, ArrayRef<const Attr *> attr) { + if (skipFunctionBody) + return mlir::success(); + if (mlir::succeeded(emitSimpleStmt(s, useCurrentScope))) return mlir::success(); diff --git a/clang/test/CIR/CodeGen/fp-pragma-fenv-access.c b/clang/test/CIR/CodeGen/fp-pragma-fenv-access.c deleted file mode 100644 index 88899e95bd43a..0000000000000 --- a/clang/test/CIR/CodeGen/fp-pragma-fenv-access.c +++ /dev/null @@ -1,11 +0,0 @@ -// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir %s -verify -emit-cir -o - - -extern void use(float f); -float a, b; - -// expected-error@+1 {{ClangIR code gen Not Yet Implemented: STDC FENV_ACCESS}} -void fenv_access(void) { - #pragma STDC FENV_ACCESS ON - __builtin_set_flt_rounds(0); - use(a + b); -} >From c4e5a79246e134914c29ebf63985027b24e38487 Mon Sep 17 00:00:00 2001 From: Adam Smith <[email protected]> Date: Tue, 19 May 2026 13:10:34 -0700 Subject: [PATCH 3/4] [CIR] Simplify FENV_ACCESS NYI after review Drop skipFunctionBody. Report errorNYI in startFunction for UsesFPIntrin/StrictFP functions and return from generateCode before emitting the body. Per review: no NYI test. --- clang/lib/CIR/CodeGen/CIRGenFunction.cpp | 21 ++++++++------------- clang/lib/CIR/CodeGen/CIRGenFunction.h | 3 --- clang/lib/CIR/CodeGen/CIRGenStmt.cpp | 3 --- 3 files changed, 8 insertions(+), 19 deletions(-) diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp index 4affcba8095b3..73b2cd9c17fe2 100644 --- a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp @@ -499,10 +499,8 @@ void CIRGenFunction::startFunction(GlobalDecl gd, QualType returnType, const auto *fd = dyn_cast_or_null<FunctionDecl>(d); curFuncDecl = (d ? d->getNonClosureContext() : nullptr); - if (fd && (fd->UsesFPIntrin() || fd->hasAttr<StrictFPAttr>())) { - skipFunctionBody = true; + if (fd && (fd->UsesFPIntrin() || fd->hasAttr<StrictFPAttr>())) cgm.errorNYI(loc, "STDC FENV_ACCESS"); - } prologueCleanupDepth = ehStack.stable_begin(); @@ -708,7 +706,6 @@ static void eraseEmptyAndUnusedBlocks(cir::FuncOp func) { cir::FuncOp CIRGenFunction::generateCode(clang::GlobalDecl gd, cir::FuncOp fn, cir::FuncType funcType) { - skipFunctionBody = false; const auto *funcDecl = cast<FunctionDecl>(gd.getDecl()); curGD = gd; @@ -783,7 +780,7 @@ cir::FuncOp CIRGenFunction::generateCode(clang::GlobalDecl gd, cir::FuncOp fn, // Emit the standard function prologue. startFunction(gd, retTy, fn, funcType, args, loc, bodyRange.getBegin()); - if (skipFunctionBody) + if (funcDecl->UsesFPIntrin() || funcDecl->hasAttr<StrictFPAttr>()) return fn; // Save parameters for coroutine function. @@ -1372,14 +1369,12 @@ void CIRGenFunction::CIRGenFPOptionsRAII::ConstructorHelper( // TODO(cir): override FP flags once FM configs are guarded. assert(!cir::MissingFeatures::fastMathFlags()); - if (cgf.curFuncDecl && !cgf.builder.getIsFPConstrained() && - !isa<CXXConstructorDecl>(cgf.curFuncDecl) && - !isa<CXXDestructorDecl>(cgf.curFuncDecl) && - (newExceptionBehavior != llvm::fp::ebIgnore || - newRoundingBehavior != llvm::RoundingMode::NearestTiesToEven)) { - cgf.skipFunctionBody = true; - cgf.cgm.errorNYI(cgf.curFuncDecl->getLocation(), "STDC FENV_ACCESS"); - } + assert((cgf.curFuncDecl == nullptr || cgf.builder.getIsFPConstrained() || + isa<CXXConstructorDecl>(cgf.curFuncDecl) || + isa<CXXDestructorDecl>(cgf.curFuncDecl) || + (newExceptionBehavior == llvm::fp::ebIgnore && + newRoundingBehavior == llvm::RoundingMode::NearestTiesToEven)) && + "FPConstrained should be enabled on entire function"); // TODO(cir): mark CIR function with fast math attributes. assert(!cir::MissingFeatures::fastMathFuncAttributes()); diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h index 66ab11d5b2c37..dcc80817c866b 100644 --- a/clang/lib/CIR/CodeGen/CIRGenFunction.h +++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h @@ -196,9 +196,6 @@ class CIRGenFunction : public CIRGenTypeCache { // Holds the Decl for the current outermost non-closure context const clang::Decl *curFuncDecl = nullptr; - /// When true, generateCode must not emit the function body after the - /// prologue (e.g. after reporting STDC FENV_ACCESS NYI for this function). - bool skipFunctionBody = false; /// This is the inner-most code context, which includes blocks. const clang::Decl *curCodeDecl = nullptr; const CIRGenFunctionInfo *curFnInfo = nullptr; diff --git a/clang/lib/CIR/CodeGen/CIRGenStmt.cpp b/clang/lib/CIR/CodeGen/CIRGenStmt.cpp index 0adb258ef6e0d..a64a2a080bade 100644 --- a/clang/lib/CIR/CodeGen/CIRGenStmt.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenStmt.cpp @@ -143,9 +143,6 @@ void CIRGenFunction::emitStopPoint(const Stmt *s) { mlir::LogicalResult CIRGenFunction::emitStmt(const Stmt *s, bool useCurrentScope, ArrayRef<const Attr *> attr) { - if (skipFunctionBody) - return mlir::success(); - if (mlir::succeeded(emitSimpleStmt(s, useCurrentScope))) return mlir::success(); >From 50379a0283f6f601af2640774f9f0a7885f46ea7 Mon Sep 17 00:00:00 2001 From: Adam Smith <[email protected]> Date: Tue, 26 May 2026 14:46:43 -0700 Subject: [PATCH 4/4] [CIR] Move FENV_ACCESS errorNYI from startFunction to generateCode Move the FP-constrained NYI diagnostic out of startFunction and into generateCode, immediately before the early return that skips body emission. startFunction is responsible for function setup, not for gating body codegen; putting the errorNYI in generateCode keeps both responsibilities clear at the call site. Co-Authored-By: Claude Sonnet 4.6 <[email protected]> --- clang/lib/CIR/CodeGen/CIRGenFunction.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp index 73b2cd9c17fe2..f7391d64320a6 100644 --- a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp @@ -499,9 +499,6 @@ void CIRGenFunction::startFunction(GlobalDecl gd, QualType returnType, const auto *fd = dyn_cast_or_null<FunctionDecl>(d); curFuncDecl = (d ? d->getNonClosureContext() : nullptr); - if (fd && (fd->UsesFPIntrin() || fd->hasAttr<StrictFPAttr>())) - cgm.errorNYI(loc, "STDC FENV_ACCESS"); - prologueCleanupDepth = ehStack.stable_begin(); mlir::Block *entryBB = &fn.getBlocks().front(); @@ -780,8 +777,10 @@ cir::FuncOp CIRGenFunction::generateCode(clang::GlobalDecl gd, cir::FuncOp fn, // Emit the standard function prologue. startFunction(gd, retTy, fn, funcType, args, loc, bodyRange.getBegin()); - if (funcDecl->UsesFPIntrin() || funcDecl->hasAttr<StrictFPAttr>()) + if (funcDecl->UsesFPIntrin() || funcDecl->hasAttr<StrictFPAttr>()) { + cgm.errorNYI(loc, "STDC FENV_ACCESS"); return fn; + } // Save parameters for coroutine function. if (body && isa_and_nonnull<CoroutineBodyStmt>(body)) _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
