This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG706e89db97d3: Fix interaction of pragma FENV_ACCESS with 
other pragmas (authored by sepavloff).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D126364

Files:
  clang/include/clang/Basic/FPOptions.def
  clang/include/clang/Basic/LangOptions.def
  clang/include/clang/Basic/LangOptions.h
  clang/include/clang/Driver/Options.td
  clang/include/clang/Sema/Sema.h
  clang/lib/AST/ExprConstant.cpp
  clang/lib/CodeGen/CGCall.cpp
  clang/lib/CodeGen/CodeGenFunction.cpp
  clang/lib/Frontend/CompilerInstance.cpp
  clang/lib/Parse/ParsePragma.cpp
  clang/lib/Sema/SemaAttr.cpp
  clang/test/AST/ast-dump-fpfeatures.cpp
  clang/test/CodeGen/pragma-fenv_access.c

Index: clang/test/CodeGen/pragma-fenv_access.c
===================================================================
--- clang/test/CodeGen/pragma-fenv_access.c
+++ clang/test/CodeGen/pragma-fenv_access.c
@@ -1,5 +1,15 @@
-// RUN: %clang_cc1 -fexperimental-strict-floating-point -ffp-exception-behavior=strict -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck %s
-// RUN: %clang_cc1 -fexperimental-strict-floating-point -ffp-exception-behavior=strict -triple %itanium_abi_triple -emit-llvm %s -o - -fms-extensions -DMS | FileCheck %s
+// RUN: %clang_cc1 -fexperimental-strict-floating-point -ffp-exception-behavior=strict -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck --check-prefixes=CHECK,STRICT %s
+// RUN: %clang_cc1 -fexperimental-strict-floating-point -ffp-exception-behavior=strict -triple %itanium_abi_triple -emit-llvm %s -o - -fms-extensions -DMS | FileCheck --check-prefixes=CHECK,STRICT %s
+// RUN: %clang_cc1 -fexperimental-strict-floating-point -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck --check-prefixes=CHECK,DEFAULT %s
+
+
+float func_00(float x, float y) {
+  return x + y;
+}
+// CHECK-LABEL: @func_00
+// STRICT: call float @llvm.experimental.constrained.fadd.f32(float {{.*}}, float {{.*}}, metadata !"round.tonearest", metadata !"fpexcept.strict")
+// DEFAULT: fadd float
+
 
 #ifdef MS
 #pragma fenv_access (on)
@@ -20,7 +30,7 @@
   return x + y;
 }
 // CHECK-LABEL: @func_02
-// CHECK: call float @llvm.experimental.constrained.fadd.f32(float {{.*}}, float {{.*}}, metadata !"round.dynamic", metadata !"fpexcept.ignore")
+// CHECK: call float @llvm.experimental.constrained.fadd.f32(float {{.*}}, float {{.*}}, metadata !"round.tonearest", metadata !"fpexcept.ignore")
 
 
 float func_03(float x, float y) {
@@ -41,7 +51,16 @@
   return x + y;
 }
 // CHECK-LABEL: @func_04
-// CHECK: call float @llvm.experimental.constrained.fadd.f32(float {{.*}}, float {{.*}}, metadata !"round.dynamic", metadata !"fpexcept.ignore")
+// STRICT: call float @llvm.experimental.constrained.fadd.f32(float {{.*}}, float {{.*}}, metadata !"round.tonearest", metadata !"fpexcept.ignore")
+// DEFAULT: fadd float
+
+
+float func_04a(float x, float y) {
+  #pragma float_control(except, on)
+  return x + y;
+}
+// CHECK-LABEL: @func_04a
+// CHECK: call float @llvm.experimental.constrained.fadd.f32(float {{.*}}, float {{.*}}, metadata !"round.tonearest", metadata !"fpexcept.strict")
 
 
 float func_05(float x, float y) {
@@ -57,18 +76,151 @@
   return x + y;
 }
 // CHECK-LABEL: @func_06
-// CHECK: call float @llvm.experimental.constrained.fadd.f32(float {{.*}}, float {{.*}}, metadata !"round.dynamic", metadata !"fpexcept.ignore")
+// STRICT: call float @llvm.experimental.constrained.fadd.f32(float {{.*}}, float {{.*}}, metadata !"round.tonearest", metadata !"fpexcept.ignore")
+// DEFAULT: fadd float
 
 
 float func_07(float x, float y) {
   x -= y;
   if (x) {
     #pragma STDC FENV_ACCESS ON
-    y *= 2;
+    y *= 2.0F;
   }
-  return y + 4;
+  return y + 4.0F;
 }
 // CHECK-LABEL: @func_07
-// CHECK: call float @llvm.experimental.constrained.fsub.f32(float {{.*}}, float {{.*}}, metadata !"round.dynamic", metadata !"fpexcept.strict")
-// CHECK: call float @llvm.experimental.constrained.fmul.f32(float {{.*}}, float {{.*}}, metadata !"round.dynamic", metadata !"fpexcept.strict")
+// STRICT: call float @llvm.experimental.constrained.fsub.f32(float {{.*}}, float {{.*}}, metadata !"round.tonearest", metadata !"fpexcept.strict")
+// STRICT: call float @llvm.experimental.constrained.fmul.f32(float {{.*}}, float {{.*}}, metadata !"round.dynamic", metadata !"fpexcept.strict")
+// STRICT: call float @llvm.experimental.constrained.fadd.f32(float {{.*}}, float {{.*}}, metadata !"round.tonearest", metadata !"fpexcept.strict")
+// DEFAULT: call float @llvm.experimental.constrained.fsub.f32(float {{.*}}, float {{.*}}, metadata !"round.tonearest", metadata !"fpexcept.ignore")
+// DEFAULT: call float @llvm.experimental.constrained.fmul.f32(float {{.*}}, float {{.*}}, metadata !"round.dynamic", metadata !"fpexcept.strict")
+// DEFAULT: call float @llvm.experimental.constrained.fadd.f32(float {{.*}}, float {{.*}}, metadata !"round.tonearest", metadata !"fpexcept.ignore")
+
+
+float func_08(float x, float y) {
+  #pragma STDC FENV_ROUND FE_UPWARD
+  #pragma STDC FENV_ACCESS ON
+  return x + y;
+}
+// CHECK-LABEL: @func_08
+// CHECK:  call float @llvm.experimental.constrained.fadd.f32({{.*}}, metadata !"round.upward", metadata !"fpexcept.strict")
+
+
+float func_09(float x, float y) {
+  #pragma STDC FENV_ROUND FE_TONEAREST
+  #pragma STDC FENV_ACCESS ON
+  return x + y;
+}
+// CHECK-LABEL: @func_09
+// CHECK: call float @llvm.experimental.constrained.fadd.f32(float {{.*}}, float {{.*}}, metadata !"round.tonearest", metadata !"fpexcept.strict")
+
+
+float func_10(float x, float y) {
+  #pragma STDC FENV_ROUND FE_TONEAREST
+  #pragma clang fp exceptions(ignore)
+  #pragma STDC FENV_ACCESS ON
+  return x + y;
+}
+// CHECK-LABEL: @func_10
+// CHECK: call float @llvm.experimental.constrained.fadd.f32(float {{.*}}, float {{.*}}, metadata !"round.tonearest", metadata !"fpexcept.ignore")
+
+
+float func_11(float x, float y) {
+  #pragma STDC FENV_ROUND FE_TONEAREST
+  #pragma clang fp exceptions(ignore)
+  #pragma STDC FENV_ACCESS OFF
+  return x + y;
+}
+// CHECK-LABEL: @func_11
+// STRICT: call float @llvm.experimental.constrained.fadd.f32(float {{.*}}, float {{.*}}, metadata !"round.tonearest", metadata !"fpexcept.ignore")
+// DEFAULT: fadd float
+
+
+float func_12(float x, float y) {
+  #pragma clang fp exceptions(maytrap)
+  #pragma STDC FENV_ACCESS ON
+  return x + y;
+}
+// CHECK-LABEL: @func_12
+// CHECK:  call float @llvm.experimental.constrained.fadd.f32({{.*}}, metadata !"round.dynamic", metadata !"fpexcept.maytrap")
+
+
+float func_13(float x, float y) {
+  #pragma clang fp exceptions(maytrap)
+  #pragma STDC FENV_ROUND FE_UPWARD
+  #pragma STDC FENV_ACCESS ON
+  return x + y;
+}
+// CHECK-LABEL: @func_13
+// CHECK:  call float @llvm.experimental.constrained.fadd.f32({{.*}}, metadata !"round.upward", metadata !"fpexcept.maytrap")
+
+
+float func_14(float x, float y, float z) {
+  #pragma STDC FENV_ACCESS ON
+  float res = x * y;
+  {
+    #pragma STDC FENV_ACCESS OFF
+    return res + z;
+  }
+}
+// CHECK-LABEL: @func_14
+// STRICT:  call float @llvm.experimental.constrained.fmul.f32({{.*}}, metadata !"round.dynamic", metadata !"fpexcept.strict")
+// STRICT:  call float @llvm.experimental.constrained.fadd.f32({{.*}}, metadata !"round.tonearest", metadata !"fpexcept.strict")
+// DEFAULT: call float @llvm.experimental.constrained.fmul.f32({{.*}}, metadata !"round.dynamic", metadata !"fpexcept.strict")
+// DEFAULT: call float @llvm.experimental.constrained.fadd.f32({{.*}}, metadata !"round.tonearest", metadata !"fpexcept.ignore")
+
+
+float func_15(float x, float y, float z) {
+  #pragma STDC FENV_ROUND FE_TOWARDZERO
+  #pragma STDC FENV_ACCESS ON
+  float res = x * y;
+  {
+    #pragma STDC FENV_ACCESS OFF
+    return res + z;
+  }
+}
+// CHECK-LABEL: @func_15
+// STRICT:  call float @llvm.experimental.constrained.fmul.f32({{.*}}, metadata !"round.towardzero", metadata !"fpexcept.strict")
+// STRICT:  call float @llvm.experimental.constrained.fadd.f32({{.*}}, metadata !"round.towardzero", metadata !"fpexcept.strict")
+// DEFAULT: call float @llvm.experimental.constrained.fmul.f32({{.*}}, metadata !"round.towardzero", metadata !"fpexcept.strict")
+// DEFAULT: call float @llvm.experimental.constrained.fadd.f32({{.*}}, metadata !"round.towardzero", metadata !"fpexcept.ignore")
+
+
+float func_16(float x, float y) {
+  x -= y;
+  {
+    #pragma STDC FENV_ROUND FE_TONEAREST
+    #pragma STDC FENV_ACCESS ON
+    y *= 2.0F;
+  }
+  {
+    #pragma STDC FENV_ACCESS ON
+    return y + 4.0F;
+  }
+}
+// CHECK-LABEL: @func_16
+// STRICT: call float @llvm.experimental.constrained.fsub.f32(float {{.*}}, float {{.*}}, metadata !"round.tonearest", metadata !"fpexcept.strict")
+// STRICT: call float @llvm.experimental.constrained.fmul.f32(float {{.*}}, float {{.*}}, metadata !"round.tonearest", metadata !"fpexcept.strict")
+// STRICT: call float @llvm.experimental.constrained.fadd.f32(float {{.*}}, float {{.*}}, metadata !"round.dynamic", metadata !"fpexcept.strict")
+// DEFAULT: call float @llvm.experimental.constrained.fsub.f32(float {{.*}}, float {{.*}}, metadata !"round.tonearest", metadata !"fpexcept.ignore")
+// DEFAULT: call float @llvm.experimental.constrained.fmul.f32(float {{.*}}, float {{.*}}, metadata !"round.tonearest", metadata !"fpexcept.strict")
+// DEFAULT: call float @llvm.experimental.constrained.fadd.f32(float {{.*}}, float {{.*}}, metadata !"round.dynamic", metadata !"fpexcept.strict")
+
+
+float func_17(float x, float y) {
+  #pragma STDC FENV_ROUND FE_DYNAMIC
+  #pragma STDC FENV_ACCESS ON
+  return x + y;
+}
+// CHECK-LABEL: @func_17
 // CHECK: call float @llvm.experimental.constrained.fadd.f32(float {{.*}}, float {{.*}}, metadata !"round.dynamic", metadata !"fpexcept.strict")
+
+
+float func_18(float x, float y) {
+  #pragma STDC FENV_ROUND FE_DYNAMIC
+  return x + y;
+}
+// CHECK-LABEL: @func_18
+// STRICT: call float @llvm.experimental.constrained.fadd.f32(float {{.*}}, float {{.*}}, metadata !"round.tonearest", metadata !"fpexcept.strict")
+// DEFAULT: fadd float
+
Index: clang/test/AST/ast-dump-fpfeatures.cpp
===================================================================
--- clang/test/AST/ast-dump-fpfeatures.cpp
+++ clang/test/AST/ast-dump-fpfeatures.cpp
@@ -87,7 +87,7 @@
 }
 
 // CHECK-LABEL: FunctionDecl {{.*}} func_10 'float (float, float)'
-// CHECK:         BinaryOperator {{.*}} 'float' '+' RoundingMode=downward
+// CHECK:         BinaryOperator {{.*}} 'float' '+' ConstRoundingMode=downward
 
 float func_11(float x, float y) {
   if (x < 0) {
@@ -98,8 +98,8 @@
 }
 
 // CHECK-LABEL: FunctionDecl {{.*}} func_11 'float (float, float)'
-// CHECK:         BinaryOperator {{.*}} 'float' '+' RoundingMode=upward
-// CHECK:         BinaryOperator {{.*}} 'float' '-' RoundingMode=downward
+// CHECK:         BinaryOperator {{.*}} 'float' '+' ConstRoundingMode=upward
+// CHECK:         BinaryOperator {{.*}} 'float' '-' ConstRoundingMode=downward
 
 
 #pragma STDC FENV_ROUND FE_DYNAMIC
@@ -109,7 +109,7 @@
 }
 
 // CHECK-LABEL: FunctionDecl {{.*}} func_12 'float (float, float)'
-// CHECK:         BinaryOperator {{.*}} 'float' '+' RoundingMode=tonearest
+// CHECK:         BinaryOperator {{.*}} 'float' '+' ConstRoundingMode=dynamic
 
 #pragma STDC FENV_ROUND FE_TONEAREST
 
@@ -118,7 +118,7 @@
 }
 
 // CHECK-LABEL: FunctionDecl {{.*}} func_13 'float (float, float)'
-// CHECK:         BinaryOperator {{.*}} 'float' '+' RoundingMode=tonearest
+// CHECK:         BinaryOperator {{.*}} 'float' '+' ConstRoundingMode=tonearest
 
 
 template <typename T>
@@ -136,8 +136,8 @@
 // CHECK:         FunctionDecl {{.*}} func_14 'T (T, T)'
 // CHECK:           CompoundStmt
 // CHECK-NEXT:        ReturnStmt
-// CHECK-NEXT:          BinaryOperator {{.*}} '+' RoundingMode=towardzero
+// CHECK-NEXT:          BinaryOperator {{.*}} '+' ConstRoundingMode=towardzero
 // CHECK:         FunctionDecl {{.*}} func_14 'float (float, float)'
 // CHECK:           CompoundStmt
 // CHECK-NEXT:        ReturnStmt
-// CHECK-NEXT:          BinaryOperator {{.*}} 'float' '+' RoundingMode=towardzero
+// CHECK-NEXT:          BinaryOperator {{.*}} 'float' '+' ConstRoundingMode=towardzero
Index: clang/lib/Sema/SemaAttr.cpp
===================================================================
--- clang/lib/Sema/SemaAttr.cpp
+++ clang/lib/Sema/SemaAttr.cpp
@@ -571,7 +571,7 @@
       PP.setCurrentFPEvalMethod(SourceLocation(), PP.getLastFPEvalMethod());
     break;
   case PFC_NoPrecise:
-    if (CurFPFeatures.getFPExceptionMode() == LangOptions::FPE_Strict)
+    if (CurFPFeatures.getExceptionMode() == LangOptions::FPE_Strict)
       Diag(Loc, diag::err_pragma_fc_noprecise_requires_noexcept);
     else if (CurFPFeatures.getAllowFEnvAccess())
       Diag(Loc, diag::err_pragma_fc_noprecise_requires_nofenv);
@@ -587,11 +587,11 @@
     if (!isPreciseFPEnabled())
       Diag(Loc, diag::err_pragma_fc_except_requires_precise);
     else
-      NewFPFeatures.setFPExceptionModeOverride(LangOptions::FPE_Strict);
+      NewFPFeatures.setSpecifiedExceptionModeOverride(LangOptions::FPE_Strict);
     FpPragmaStack.Act(Loc, Action, StringRef(), NewFPFeatures);
     break;
   case PFC_NoExcept:
-    NewFPFeatures.setFPExceptionModeOverride(LangOptions::FPE_Ignore);
+    NewFPFeatures.setSpecifiedExceptionModeOverride(LangOptions::FPE_Ignore);
     FpPragmaStack.Act(Loc, Action, StringRef(), NewFPFeatures);
     break;
   case PFC_Push:
@@ -1294,16 +1294,9 @@
   CurFPFeatures = NewFPFeatures.applyOverrides(getLangOpts());
 }
 
-void Sema::setRoundingMode(SourceLocation Loc, llvm::RoundingMode FPR) {
-  // C2x: 7.6.2p3  If the FE_DYNAMIC mode is specified and FENV_ACCESS is "off",
-  // the translator may assume that the default rounding mode is in effect.
-  if (FPR == llvm::RoundingMode::Dynamic &&
-      !CurFPFeatures.getAllowFEnvAccess() &&
-      CurFPFeatures.getFPExceptionMode() == LangOptions::FPE_Ignore)
-    FPR = llvm::RoundingMode::NearestTiesToEven;
-
+void Sema::ActOnPragmaFEnvRound(SourceLocation Loc, llvm::RoundingMode FPR) {
   FPOptionsOverride NewFPFeatures = CurFPFeatureOverrides();
-  NewFPFeatures.setRoundingModeOverride(FPR);
+  NewFPFeatures.setConstRoundingModeOverride(FPR);
   FpPragmaStack.Act(Loc, PSK_Set, StringRef(), NewFPFeatures);
   CurFPFeatures = NewFPFeatures.applyOverrides(getLangOpts());
 }
@@ -1311,14 +1304,13 @@
 void Sema::setExceptionMode(SourceLocation Loc,
                             LangOptions::FPExceptionModeKind FPE) {
   FPOptionsOverride NewFPFeatures = CurFPFeatureOverrides();
-  NewFPFeatures.setFPExceptionModeOverride(FPE);
+  NewFPFeatures.setSpecifiedExceptionModeOverride(FPE);
   FpPragmaStack.Act(Loc, PSK_Set, StringRef(), NewFPFeatures);
   CurFPFeatures = NewFPFeatures.applyOverrides(getLangOpts());
 }
 
 void Sema::ActOnPragmaFEnvAccess(SourceLocation Loc, bool IsEnabled) {
   FPOptionsOverride NewFPFeatures = CurFPFeatureOverrides();
-  auto LO = getLangOpts();
   if (IsEnabled) {
     // Verify Microsoft restriction:
     // You can't enable fenv_access unless precise semantics are enabled.
@@ -1326,16 +1318,10 @@
     // pragma, or by using the /fp:precise or /fp:strict compiler options
     if (!isPreciseFPEnabled())
       Diag(Loc, diag::err_pragma_fenv_requires_precise);
-    NewFPFeatures.setAllowFEnvAccessOverride(true);
-    // Enabling FENV access sets the RoundingMode to Dynamic.
-    // and ExceptionBehavior to Strict
-    NewFPFeatures.setRoundingModeOverride(llvm::RoundingMode::Dynamic);
-    NewFPFeatures.setFPExceptionModeOverride(LangOptions::FPE_Strict);
-  } else {
-    NewFPFeatures.setAllowFEnvAccessOverride(false);
   }
+  NewFPFeatures.setAllowFEnvAccessOverride(IsEnabled);
   FpPragmaStack.Act(Loc, PSK_Set, StringRef(), NewFPFeatures);
-  CurFPFeatures = NewFPFeatures.applyOverrides(LO);
+  CurFPFeatures = NewFPFeatures.applyOverrides(getLangOpts());
 }
 
 void Sema::ActOnPragmaFPExceptions(SourceLocation Loc,
Index: clang/lib/Parse/ParsePragma.cpp
===================================================================
--- clang/lib/Parse/ParsePragma.cpp
+++ clang/lib/Parse/ParsePragma.cpp
@@ -804,7 +804,7 @@
       reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
 
   SourceLocation PragmaLoc = ConsumeAnnotationToken();
-  Actions.setRoundingMode(PragmaLoc, RM);
+  Actions.ActOnPragmaFEnvRound(PragmaLoc, RM);
 }
 
 StmtResult Parser::HandlePragmaCaptured()
Index: clang/lib/Frontend/CompilerInstance.cpp
===================================================================
--- clang/lib/Frontend/CompilerInstance.cpp
+++ clang/lib/Frontend/CompilerInstance.cpp
@@ -123,12 +123,12 @@
   }
 
   if (!getTarget().hasStrictFP() && !getLangOpts().ExpStrictFP) {
-    if (getLangOpts().getFPRoundingMode() !=
-        llvm::RoundingMode::NearestTiesToEven) {
+    if (getLangOpts().RoundingMath) {
       getDiagnostics().Report(diag::warn_fe_backend_unsupported_fp_rounding);
-      getLangOpts().setFPRoundingMode(llvm::RoundingMode::NearestTiesToEven);
+      getLangOpts().RoundingMath = false;
     }
-    if (getLangOpts().getFPExceptionMode() != LangOptions::FPE_Ignore) {
+    auto FPExc = getLangOpts().getFPExceptionMode();
+    if (FPExc != LangOptions::FPE_Default && FPExc != LangOptions::FPE_Ignore) {
       getDiagnostics().Report(diag::warn_fe_backend_unsupported_fp_exceptions);
       getLangOpts().setFPExceptionMode(LangOptions::FPE_Ignore);
     }
Index: clang/lib/CodeGen/CodeGenFunction.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenFunction.cpp
+++ clang/lib/CodeGen/CodeGenFunction.cpp
@@ -105,8 +105,9 @@
   case LangOptions::FPE_Ignore:  return llvm::fp::ebIgnore;
   case LangOptions::FPE_MayTrap: return llvm::fp::ebMayTrap;
   case LangOptions::FPE_Strict:  return llvm::fp::ebStrict;
+  default:
+    llvm_unreachable("Unsupported FP Exception Behavior");
   }
-  llvm_unreachable("Unsupported FP Exception Behavior");
 }
 
 void CodeGenFunction::SetFastMathFlags(FPOptions FPFeatures) {
@@ -145,12 +146,11 @@
 
   FMFGuard.emplace(CGF.Builder);
 
-  llvm::RoundingMode NewRoundingBehavior =
-      static_cast<llvm::RoundingMode>(FPFeatures.getRoundingMode());
+  llvm::RoundingMode NewRoundingBehavior = FPFeatures.getRoundingMode();
   CGF.Builder.setDefaultConstrainedRounding(NewRoundingBehavior);
   auto NewExceptionBehavior =
       ToConstrainedExceptMD(static_cast<LangOptions::FPExceptionModeKind>(
-          FPFeatures.getFPExceptionMode()));
+          FPFeatures.getExceptionMode()));
   CGF.Builder.setDefaultConstrainedExcept(NewExceptionBehavior);
 
   CGF.SetFastMathFlags(FPFeatures);
@@ -971,9 +971,9 @@
              (getLangOpts().CUDA && FD->hasAttr<CUDAGlobalAttr>())))
     Fn->addFnAttr(llvm::Attribute::NoRecurse);
 
-  llvm::RoundingMode RM = getLangOpts().getFPRoundingMode();
+  llvm::RoundingMode RM = getLangOpts().getDefaultRoundingMode();
   llvm::fp::ExceptionBehavior FPExceptionBehavior =
-      ToConstrainedExceptMD(getLangOpts().getFPExceptionMode());
+      ToConstrainedExceptMD(getLangOpts().getDefaultExceptionMode());
   Builder.setDefaultConstrainedRounding(RM);
   Builder.setDefaultConstrainedExcept(FPExceptionBehavior);
   if ((FD && (FD->UsesFPIntrin() || FD->hasAttr<StrictFPAttr>())) ||
Index: clang/lib/CodeGen/CGCall.cpp
===================================================================
--- clang/lib/CodeGen/CGCall.cpp
+++ clang/lib/CodeGen/CGCall.cpp
@@ -1849,7 +1849,7 @@
           CodeGenOpts.FP32DenormalMode.str());
     }
 
-    if (LangOpts.getFPExceptionMode() == LangOptions::FPE_Ignore)
+    if (LangOpts.getDefaultExceptionMode() == LangOptions::FPE_Ignore)
       FuncAttrs.addAttribute("no-trapping-math", "true");
 
     // TODO: Are these all needed?
Index: clang/lib/AST/ExprConstant.cpp
===================================================================
--- clang/lib/AST/ExprConstant.cpp
+++ clang/lib/AST/ExprConstant.cpp
@@ -2584,14 +2584,14 @@
 
   if ((St != APFloat::opOK) &&
       (FPO.getRoundingMode() == llvm::RoundingMode::Dynamic ||
-       FPO.getFPExceptionMode() != LangOptions::FPE_Ignore ||
+       FPO.getExceptionMode() != LangOptions::FPE_Ignore ||
        FPO.getAllowFEnvAccess())) {
     Info.FFDiag(E, diag::note_constexpr_float_arithmetic_strict);
     return false;
   }
 
   if ((St & APFloat::opStatus::opInvalidOp) &&
-      FPO.getFPExceptionMode() != LangOptions::FPE_Ignore) {
+      FPO.getExceptionMode() != LangOptions::FPE_Ignore) {
     // There is no usefully definable result.
     Info.FFDiag(E);
     return false;
Index: clang/include/clang/Sema/Sema.h
===================================================================
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -10311,7 +10311,7 @@
                                LangOptions::FPExceptionModeKind);
 
   /// Called to set constant rounding mode for floating point operations.
-  void setRoundingMode(SourceLocation Loc, llvm::RoundingMode);
+  void ActOnPragmaFEnvRound(SourceLocation Loc, llvm::RoundingMode);
 
   /// Called to set exception behavior for floating point operations.
   void setExceptionMode(SourceLocation Loc, LangOptions::FPExceptionModeKind);
Index: clang/include/clang/Driver/Options.td
===================================================================
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -1544,7 +1544,7 @@
   HelpText<"Specifies the exception behavior of floating-point operations.">,
   Values<"ignore,maytrap,strict">, NormalizedValuesScope<"LangOptions">,
   NormalizedValues<["FPE_Ignore", "FPE_MayTrap", "FPE_Strict"]>,
-  MarshallingInfoEnum<LangOpts<"FPExceptionMode">, "FPE_Ignore">;
+  MarshallingInfoEnum<LangOpts<"FPExceptionMode">, "FPE_Default">;
 defm fast_math : BoolFOption<"fast-math",
   LangOpts<"FastMath">, DefaultFalse,
   PosFlag<SetTrue, [CC1Option], "Allow aggressive, lossy floating-point optimizations",
@@ -1866,7 +1866,7 @@
 def : Flag<["-"], "fhonor-infinites">, Alias<fhonor_infinities>;
 def : Flag<["-"], "fno-honor-infinites">, Alias<fno_honor_infinities>;
 def frounding_math : Flag<["-"], "frounding-math">, Group<f_Group>, Flags<[CC1Option]>,
-  MarshallingInfoFlag<LangOpts<"FPRoundingMode">, "llvm::RoundingMode::NearestTiesToEven">,
+  MarshallingInfoFlag<LangOpts<"RoundingMath">>,
   Normalizer<"makeFlagToValueNormalizer(llvm::RoundingMode::Dynamic)">;
 def fno_rounding_math : Flag<["-"], "fno-rounding-math">, Group<f_Group>, Flags<[CC1Option]>;
 def ftrapping_math : Flag<["-"], "ftrapping-math">, Group<f_Group>;
Index: clang/include/clang/Basic/LangOptions.h
===================================================================
--- clang/include/clang/Basic/LangOptions.h
+++ clang/include/clang/Basic/LangOptions.h
@@ -259,10 +259,6 @@
     FPM_FastHonorPragmas
   };
 
-  /// Alias for RoundingMode::NearestTiesToEven.
-  static constexpr unsigned FPR_ToNearest =
-      static_cast<unsigned>(llvm::RoundingMode::NearestTiesToEven);
-
   /// Possible floating point exception behavior.
   enum FPExceptionModeKind {
     /// Assume that floating-point exceptions are masked.
@@ -270,7 +266,9 @@
     /// Transformations do not cause new exceptions but may hide some.
     FPE_MayTrap,
     /// Strictly preserve the floating-point exception semantics.
-    FPE_Strict
+    FPE_Strict,
+    /// Used internally to represent initial unspecified value.
+    FPE_Default
   };
 
   /// Possible float expression evaluation method choices.
@@ -610,6 +608,18 @@
 
   /// Remap path prefix according to -fmacro-prefix-path option.
   void remapPathPrefix(SmallVectorImpl<char> &Path) const;
+
+  RoundingMode getDefaultRoundingMode() const {
+    return RoundingMath ? RoundingMode::Dynamic
+                        : RoundingMode::NearestTiesToEven;
+  }
+
+  FPExceptionModeKind getDefaultExceptionMode() const {
+    FPExceptionModeKind EM = getFPExceptionMode();
+    if (EM == FPExceptionModeKind::FPE_Default)
+      return FPExceptionModeKind::FPE_Ignore;
+    return EM;
+  }
 };
 
 /// Floating point control options
@@ -617,7 +627,7 @@
 class FPOptions {
 public:
   // We start by defining the layout.
-  using storage_type = uint16_t;
+  using storage_type = uint32_t;
 
   using RoundingMode = llvm::RoundingMode;
 
@@ -646,8 +656,8 @@
 public:
   FPOptions() : Value(0) {
     setFPContractMode(LangOptions::FPM_Off);
-    setRoundingMode(static_cast<RoundingMode>(LangOptions::FPR_ToNearest));
-    setFPExceptionMode(LangOptions::FPE_Ignore);
+    setConstRoundingMode(RoundingMode::Dynamic);
+    setSpecifiedExceptionMode(LangOptions::FPE_Default);
   }
   explicit FPOptions(const LangOptions &LO) {
     Value = 0;
@@ -658,8 +668,9 @@
     if (LangOptContractMode == LangOptions::FPM_FastHonorPragmas)
       LangOptContractMode = LangOptions::FPM_Fast;
     setFPContractMode(LangOptContractMode);
-    setRoundingMode(LO.getFPRoundingMode());
-    setFPExceptionMode(LO.getFPExceptionMode());
+    setRoundingMath(LO.RoundingMath);
+    setConstRoundingMode(LangOptions::RoundingMode::Dynamic);
+    setSpecifiedExceptionMode(LO.getFPExceptionMode());
     setAllowFPReassociate(LO.AllowFPReassoc);
     setNoHonorNaNs(LO.NoHonorNaNs);
     setNoHonorInfs(LO.NoHonorInfs);
@@ -668,7 +679,7 @@
     setAllowApproxFunc(LO.ApproxFunc);
     if (getFPContractMode() == LangOptions::FPM_On &&
         getRoundingMode() == llvm::RoundingMode::Dynamic &&
-        getFPExceptionMode() == LangOptions::FPE_Strict)
+        getExceptionMode() == LangOptions::FPE_Strict)
       // If the FP settings are set to the "strict" model, then
       // FENV access is set to true. (ffp-model=strict)
       setAllowFEnvAccess(true);
@@ -692,10 +703,33 @@
 
   bool isFPConstrained() const {
     return getRoundingMode() != llvm::RoundingMode::NearestTiesToEven ||
-           getFPExceptionMode() != LangOptions::FPE_Ignore ||
+           getExceptionMode() != LangOptions::FPE_Ignore ||
            getAllowFEnvAccess();
   }
 
+  RoundingMode getRoundingMode() const {
+    RoundingMode RM = getConstRoundingMode();
+    if (RM == RoundingMode::Dynamic) {
+      // C2x: 7.6.2p3  If the FE_DYNAMIC mode is specified and FENV_ACCESS is
+      // "off", the translator may assume that the default rounding mode is in
+      // effect.
+      if (!getAllowFEnvAccess() && !getRoundingMath())
+        RM = RoundingMode::NearestTiesToEven;
+    }
+    return RM;
+  }
+
+  LangOptions::FPExceptionModeKind getExceptionMode() const {
+    LangOptions::FPExceptionModeKind EM = getSpecifiedExceptionMode();
+    if (EM == LangOptions::FPExceptionModeKind::FPE_Default) {
+      if (getAllowFEnvAccess())
+        return LangOptions::FPExceptionModeKind::FPE_Strict;
+      else
+        return LangOptions::FPExceptionModeKind::FPE_Ignore;
+    }
+    return EM;
+  }
+
   bool operator==(FPOptions other) const { return Value == other.Value; }
 
   /// Return the default value of FPOptions that's used when trailing
@@ -743,7 +777,7 @@
 
   /// The type suitable for storing values of FPOptionsOverride. Must be twice
   /// as wide as bit size of FPOption.
-  using storage_type = uint32_t;
+  using storage_type = uint64_t;
   static_assert(sizeof(storage_type) >= 2 * sizeof(FPOptions::storage_type),
                 "Too short type for FPOptionsOverride");
 
Index: clang/include/clang/Basic/LangOptions.def
===================================================================
--- clang/include/clang/Basic/LangOptions.def
+++ clang/include/clang/Basic/LangOptions.def
@@ -311,8 +311,8 @@
 /// FP_CONTRACT mode (on/off/fast).
 BENIGN_ENUM_LANGOPT(DefaultFPContractMode, FPModeKind, 2, FPM_Off, "FP contraction type")
 COMPATIBLE_LANGOPT(ExpStrictFP, 1, false, "Enable experimental strict floating point")
-BENIGN_ENUM_LANGOPT(FPRoundingMode, RoundingMode, 3, RoundingMode::NearestTiesToEven, "FP Rounding Mode type")
-BENIGN_ENUM_LANGOPT(FPExceptionMode, FPExceptionModeKind, 2, FPE_Ignore, "FP Exception Behavior Mode type")
+BENIGN_LANGOPT(RoundingMath, 1, false, "Do not assume default floating-point rounding behavior")
+BENIGN_ENUM_LANGOPT(FPExceptionMode, FPExceptionModeKind, 2, FPE_Default, "FP Exception Behavior Mode type")
 BENIGN_ENUM_LANGOPT(FPEvalMethod, FPEvalMethodKind, 2, FEM_UnsetOnCommandLine, "FP type used for floating point arithmetic")
 LANGOPT(NoBitFieldTypeAlign , 1, 0, "bit-field type alignment")
 LANGOPT(HexagonQdsp6Compat , 1, 0, "hexagon-qdsp6 backward compatibility")
Index: clang/include/clang/Basic/FPOptions.def
===================================================================
--- clang/include/clang/Basic/FPOptions.def
+++ clang/include/clang/Basic/FPOptions.def
@@ -14,9 +14,10 @@
 
 // OPTION(name, type, width, previousName)
 OPTION(FPContractMode, LangOptions::FPModeKind, 2, First)
-OPTION(RoundingMode, LangOptions::RoundingMode, 3, FPContractMode)
-OPTION(FPExceptionMode, LangOptions::FPExceptionModeKind, 2, RoundingMode)
-OPTION(AllowFEnvAccess, bool, 1, FPExceptionMode)
+OPTION(RoundingMath, bool, 1, FPContractMode)
+OPTION(ConstRoundingMode, LangOptions::RoundingMode, 3, RoundingMath)
+OPTION(SpecifiedExceptionMode, LangOptions::FPExceptionModeKind, 2, ConstRoundingMode)
+OPTION(AllowFEnvAccess, bool, 1, SpecifiedExceptionMode)
 OPTION(AllowFPReassociate, bool, 1, AllowFEnvAccess)
 OPTION(NoHonorNaNs, bool, 1, AllowFPReassociate)
 OPTION(NoHonorInfs, bool, 1, NoHonorNaNs)
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to