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

Reply via email to