sepavloff updated this revision to Diff 298119.
sepavloff added a comment.

Updated patch

- Reverted check to the previous version, in which it applied to C++ file level 
variables also.
- Added workaround for constexpr functions. Now they are parsed with constant 
rounding mode, which allows to use them with option `-frounding-math`.

Setting call-site rounding mode is not implemented yet.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D88498/new/

https://reviews.llvm.org/D88498

Files:
  clang/include/clang/Basic/LangOptions.h
  clang/include/clang/Sema/Sema.h
  clang/lib/Parse/ParseDecl.cpp
  clang/lib/Parse/ParseStmt.cpp
  clang/test/AST/const-fpfeatures-strict.c

Index: clang/test/AST/const-fpfeatures-strict.c
===================================================================
--- /dev/null
+++ clang/test/AST/const-fpfeatures-strict.c
@@ -0,0 +1,41 @@
+// RUN: %clang_cc1 -S -emit-llvm -ffp-exception-behavior=strict -Wno-unknown-pragmas %s -o - | FileCheck %s
+
+// nextUp(1.F) == 0x1.000002p0F
+
+struct S {
+  float f;
+};
+
+static struct S var_01 = {0x1.000001p0};
+struct S *func_01() {
+  return &var_01;
+}
+
+struct S var_02 = {0x1.000001p0};
+
+struct S *func_03() {
+  static struct S var_03 = {0x1.000001p0};
+  return &var_03;
+}
+
+// CHECK: @var_01 = {{.*}} %struct.S { float 1.000000e+00 }
+// CHECK: @var_02 = {{.*}} %struct.S { float 1.000000e+00 }
+// CHECK: @func_03.var_03 = {{.*}} %struct.S { float 1.000000e+00 }
+
+#pragma STDC FENV_ROUND FE_UPWARD
+
+static struct S var_04 = {0x1.000001p0};
+struct S *func_04() {
+  return &var_04;
+}
+
+struct S var_05 = {0x1.000001p0};
+
+struct S *func_06() {
+  static struct S var_06 = {0x1.000001p0};
+  return &var_06;
+}
+
+// CHECK: @var_04 = {{.*}} %struct.S { float 0x3FF0000020000000 }
+// CHECK: @var_05 = {{.*}} %struct.S { float 0x3FF0000020000000 }
+// CHECK: @func_06.var_06 = {{.*}} %struct.S { float 0x3FF0000020000000 }
Index: clang/lib/Parse/ParseStmt.cpp
===================================================================
--- clang/lib/Parse/ParseStmt.cpp
+++ clang/lib/Parse/ParseStmt.cpp
@@ -2253,6 +2253,11 @@
   Sema::PragmaStackSentinelRAII
     PragmaStackSentinel(Actions, "InternalPragmaState", IsCXXMethod);
 
+  Sema::FPFeaturesStateRAII SavedFPFeatues(Actions);
+  if (auto Fn = dyn_cast_or_null<FunctionDecl>(Decl))
+    if (Fn->isConstexpr())
+      Actions.adjustFPFeaturesForGlobal();
+
   // Do not enter a scope for the brace, as the arguments are in the same scope
   // (the function body) as the body itself.  Instead, just read the statement
   // list and put it into a CompoundStmt for safe keeping.
Index: clang/lib/Parse/ParseDecl.cpp
===================================================================
--- clang/lib/Parse/ParseDecl.cpp
+++ clang/lib/Parse/ParseDecl.cpp
@@ -2284,6 +2284,17 @@
       }
 
       PreferredType.enterVariableInit(Tok.getLocation(), ThisDecl);
+
+      Sema::FPFeaturesStateRAII FPO(Actions);
+      if (auto VD = dyn_cast_or_null<VarDecl>(ThisDecl))
+        if (!VD->isInvalidDecl()) {
+          // If variable requires constant initialization, set constant
+          // rounding mode.
+          if (VD->isFileVarDecl() || VD->isConstexpr() ||
+              (!getLangOpts().CPlusPlus && VD->isStaticLocal()))
+            Actions.adjustFPFeaturesForGlobal();
+        }
+
       ExprResult Init = ParseInitializer();
 
       // If this is the only decl in (possibly) range based for statement,
Index: clang/include/clang/Sema/Sema.h
===================================================================
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -589,13 +589,7 @@
   // This stack tracks the current state of Sema.CurFPFeatures.
   PragmaStack<FPOptionsOverride> FpPragmaStack;
   FPOptionsOverride CurFPFeatureOverrides() {
-    FPOptionsOverride result;
-    if (!FpPragmaStack.hasValue()) {
-      result = FPOptionsOverride();
-    } else {
-      result = FpPragmaStack.CurrentValue;
-    }
-    return result;
+    return FpPragmaStack.CurrentValue;
   }
 
   // RAII object to push / pop sentinel slots for all MS #pragma stacks.
@@ -1429,7 +1423,6 @@
 
   const LangOptions &getLangOpts() const { return LangOpts; }
   OpenCLOptions &getOpenCLOptions() { return OpenCLFeatures; }
-  FPOptions     &getCurFPFeatures() { return CurFPFeatures; }
 
   DiagnosticsEngine &getDiagnostics() const { return Diags; }
   SourceManager &getSourceManager() const { return SourceMgr; }
@@ -1439,6 +1432,24 @@
   ASTMutationListener *getASTMutationListener() const;
   ExternalSemaSource* getExternalSource() const { return ExternalSource; }
 
+  const FPOptions &getCurFPFeatures() const { return CurFPFeatures; }
+  void setCurFPFeatures(FPOptions FPO) {
+    FpPragmaStack.CurrentValue = FPOptionsOverride(FPO, CurFPFeatures);
+    CurFPFeatures = FPO;
+  }
+
+  /// Adjust floating point options applied to parsing some global objects.
+  void adjustFPFeaturesForGlobal() {
+    if (getCurFPFeatures().getRoundingMode() == llvm::RoundingMode::Dynamic) {
+      // If current rounding mode is 'dynamic', it means that a command
+      // line option line like `-ffpmodel=strict` is in effect. Set
+      // constant rounding to default in this case.
+      FPOptions NewFPO = getCurFPFeatures();
+      NewFPO.setRoundingMode(llvm::RoundingMode::NearestTiesToEven);
+      setCurFPFeatures(NewFPO);
+    }
+  }
+
   ///Registers an external source. If an external source already exists,
   /// creates a multiplex external source and appends to it.
   ///
Index: clang/include/clang/Basic/LangOptions.h
===================================================================
--- clang/include/clang/Basic/LangOptions.h
+++ clang/include/clang/Basic/LangOptions.h
@@ -450,6 +450,15 @@
     return Opts;
   }
 
+  storage_type getDiffWith(FPOptions FPO) const {
+    storage_type Diff = 0;
+#define OPTION(NAME, TYPE, WIDTH, PREVIOUS)                                    \
+  if (get##NAME() != FPO.get##NAME())                                          \
+    Diff |= NAME##Mask;
+#include "clang/Basic/FPOptions.def"
+    return Diff;
+  }
+
   // We can define most of the accessors automatically:
 #define OPTION(NAME, TYPE, WIDTH, PREVIOUS)                                    \
   TYPE get##NAME() const {                                                     \
@@ -498,6 +507,8 @@
       : Options(LO), OverrideMask(OverrideMaskBits) {}
   FPOptionsOverride(FPOptions FPO)
       : Options(FPO), OverrideMask(OverrideMaskBits) {}
+  FPOptionsOverride(FPOptions New, FPOptions Old)
+      : Options(New), OverrideMask(New.getDiffWith(Old)) {}
 
   bool requiresTrailingStorage() const { return OverrideMask != 0; }
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to