diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -1133,9 +1133,9 @@ // - #pragma stdc unknown def ext_stdc_pragma_ignored : ExtWarn<"unknown pragma in STDC namespace">, InGroup; -def warn_stdc_fenv_access_not_supported : - Warning<"pragma STDC FENV_ACCESS ON is not supported, ignoring pragma">, - InGroup; +def err_pragma_stdc_fenv_access_scope : Error< + "'#pragma STDC FENV_ACCESS' can only appear at file scope or at the start of a " + "compound statement">; def warn_stdc_fenv_round_not_supported : Warning<"pragma STDC FENV_ROUND is not supported">, InGroup; diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -4329,6 +4329,7 @@ void ActOnFinishOfCompoundStmt(); StmtResult ActOnCompoundStmt(SourceLocation L, SourceLocation R, ArrayRef Elts, bool isStmtExpr); + void ActOnAfterCompoundStatementLeadingPragmas(); /// A RAII object to enter scope of a compound statement. class CompoundScopeRAII { diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -772,6 +772,10 @@ /// not supported by the interpreter, an error is triggered. bool EnableNewConstInterp; + /// Strict floating point is enabled, this inhibits + /// floating ponit constant folding. + bool isStrictFP; + /// BottomFrame - The frame in which evaluation started. This must be /// initialized after CurrentCall and CallStackDepth. CallStackFrame BottomFrame; @@ -923,11 +927,13 @@ return CheckingForUndefinedBehavior; } - EvalInfo(const ASTContext &C, Expr::EvalStatus &S, EvaluationMode Mode) + EvalInfo(const ASTContext &C, Expr::EvalStatus &S, EvaluationMode Mode, + bool SuppressFPFolding) : Ctx(const_cast(C)), EvalStatus(S), CurrentCall(nullptr), CallStackDepth(0), NextCallIndex(1), StepsLeft(C.getLangOpts().ConstexprStepLimit), EnableNewConstInterp(C.getLangOpts().EnableNewConstInterp), + isStrictFP(SuppressFPFolding), BottomFrame(*this, SourceLocation(), nullptr, nullptr, nullptr), EvaluatingDecl((const ValueDecl *)nullptr), EvaluatingDeclValue(nullptr), HasActiveDiagnostic(false), @@ -13188,6 +13194,8 @@ static bool EvaluateFloat(const Expr* E, APFloat& Result, EvalInfo &Info) { assert(E->isRValue() && E->getType()->isRealFloatingType()); + if (Info.isStrictFP) + return false; return FloatExprEvaluator(Info, Result).Visit(E); } @@ -14287,6 +14295,14 @@ return true; } +static bool isStrictFPEnabled(const ASTContext &Ctx, const Expr *E) { + if (const BinaryOperator *BE = dyn_cast(E)) + return BE->getFPFeaturesInEffect(Ctx.getLangOpts()).isFPConstrained(); + if (const CallExpr *CE = dyn_cast(E)) + return CE->getFPFeaturesInEffect(Ctx.getLangOpts()).isFPConstrained(); + return false; +} + /// EvaluateAsRValue - Return true if this is a constant which we can fold using /// any crazy technique (that has nothing to do with language standards) that /// we want to. If this function returns true, it returns the folded constant @@ -14296,7 +14312,8 @@ bool InConstantContext) const { assert(!isValueDependent() && "Expression evaluator can't be called on a dependent expression."); - EvalInfo Info(Ctx, Result, EvalInfo::EM_IgnoreSideEffects); + EvalInfo Info(Ctx, Result, EvalInfo::EM_IgnoreSideEffects, + isStrictFPEnabled(Ctx, this)); Info.InConstantContext = InConstantContext; return ::EvaluateAsRValue(this, Result, Ctx, Info); } @@ -14315,7 +14332,8 @@ bool InConstantContext) const { assert(!isValueDependent() && "Expression evaluator can't be called on a dependent expression."); - EvalInfo Info(Ctx, Result, EvalInfo::EM_IgnoreSideEffects); + EvalInfo Info(Ctx, Result, EvalInfo::EM_IgnoreSideEffects, + isStrictFPEnabled(Ctx, this)); Info.InConstantContext = InConstantContext; return ::EvaluateAsInt(this, Result, Ctx, AllowSideEffects, Info); } @@ -14325,7 +14343,8 @@ bool InConstantContext) const { assert(!isValueDependent() && "Expression evaluator can't be called on a dependent expression."); - EvalInfo Info(Ctx, Result, EvalInfo::EM_IgnoreSideEffects); + EvalInfo Info(Ctx, Result, EvalInfo::EM_IgnoreSideEffects, + isStrictFPEnabled(Ctx, this)); Info.InConstantContext = InConstantContext; return ::EvaluateAsFixedPoint(this, Result, Ctx, AllowSideEffects, Info); } @@ -14354,7 +14373,8 @@ assert(!isValueDependent() && "Expression evaluator can't be called on a dependent expression."); - EvalInfo Info(Ctx, Result, EvalInfo::EM_ConstantFold); + EvalInfo Info(Ctx, Result, EvalInfo::EM_ConstantFold, + isStrictFPEnabled(Ctx, this)); Info.InConstantContext = InConstantContext; LValue LV; CheckedTemporaries CheckedTemps; @@ -14375,7 +14395,8 @@ "Expression evaluator can't be called on a dependent expression."); EvalInfo::EvaluationMode EM = EvalInfo::EM_ConstantExpression; - EvalInfo Info(Ctx, Result, EM); + EvalInfo Info(Ctx, Result, EM, + isStrictFPEnabled(Ctx, this)); Info.InConstantContext = true; if (InPlace) { @@ -14413,7 +14434,8 @@ EvalInfo Info(Ctx, EStatus, VD->isConstexpr() ? EvalInfo::EM_ConstantExpression - : EvalInfo::EM_ConstantFold); + : EvalInfo::EM_ConstantFold, + isStrictFPEnabled(Ctx, this)); Info.setEvaluatingDecl(VD, Value); Info.InConstantContext = true; @@ -14458,7 +14480,8 @@ else if (!getDefaultInitValue(getType(), DestroyedValue)) return false; - EvalInfo Info(getASTContext(), EStatus, EvalInfo::EM_ConstantExpression); + EvalInfo Info(getASTContext(), EStatus, EvalInfo::EM_ConstantExpression, + /* strict fp enabled */ false); Info.setEvaluatingDecl(this, DestroyedValue, EvalInfo::EvaluatingDeclKind::Dtor); Info.InConstantContext = true; @@ -14498,7 +14521,8 @@ EvalResult EVResult; EVResult.Diag = Diag; - EvalInfo Info(Ctx, EVResult, EvalInfo::EM_IgnoreSideEffects); + EvalInfo Info(Ctx, EVResult, EvalInfo::EM_IgnoreSideEffects, + isStrictFPEnabled(Ctx, this)); Info.InConstantContext = true; bool Result = ::EvaluateAsRValue(this, EVResult, Ctx, Info); @@ -14516,7 +14540,8 @@ EvalResult EVResult; EVResult.Diag = Diag; - EvalInfo Info(Ctx, EVResult, EvalInfo::EM_IgnoreSideEffects); + EvalInfo Info(Ctx, EVResult, EvalInfo::EM_IgnoreSideEffects, + isStrictFPEnabled(Ctx, this)); Info.InConstantContext = true; Info.CheckingForUndefinedBehavior = true; @@ -14535,7 +14560,8 @@ bool IsConst; EvalResult EVResult; if (!FastEvaluateAsRValue(this, EVResult, Ctx, IsConst)) { - EvalInfo Info(Ctx, EVResult, EvalInfo::EM_IgnoreSideEffects); + EvalInfo Info(Ctx, EVResult, EvalInfo::EM_IgnoreSideEffects, + isStrictFPEnabled(Ctx, this)); Info.CheckingForUndefinedBehavior = true; (void)::EvaluateAsRValue(Info, this, EVResult.Val); } @@ -14591,7 +14617,8 @@ static ICEDiag CheckEvalInICE(const Expr* E, const ASTContext &Ctx) { Expr::EvalResult EVResult; Expr::EvalStatus Status; - EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantExpression); + EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantExpression, + isStrictFPEnabled(Ctx, E)); Info.InConstantContext = true; if (!::EvaluateAsRValue(E, EVResult, Ctx, Info) || EVResult.HasSideEffects || @@ -15066,7 +15093,8 @@ // value. EvalResult ExprResult; Expr::EvalStatus Status; - EvalInfo Info(Ctx, Status, EvalInfo::EM_IgnoreSideEffects); + EvalInfo Info(Ctx, Status, EvalInfo::EM_IgnoreSideEffects, + isStrictFPEnabled(Ctx, this)); Info.InConstantContext = true; if (!::EvaluateAsInt(this, ExprResult, Ctx, SE_AllowSideEffects, Info)) @@ -15095,7 +15123,8 @@ Expr::EvalStatus Status; SmallVector Diags; Status.Diag = &Diags; - EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantExpression); + EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantExpression, + isStrictFPEnabled(Ctx, this)); APValue Scratch; bool IsConstExpr = @@ -15123,7 +15152,8 @@ "Expression evaluator can't be called on a dependent expression."); Expr::EvalStatus Status; - EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantExpressionUnevaluated); + EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantExpressionUnevaluated, + isStrictFPEnabled(Ctx, this)); Info.InConstantContext = true; LValue ThisVal; @@ -15193,7 +15223,8 @@ Expr::EvalStatus Status; Status.Diag = &Diags; - EvalInfo Info(FD->getASTContext(), Status, EvalInfo::EM_ConstantExpression); + EvalInfo Info(FD->getASTContext(), Status, EvalInfo::EM_ConstantExpression, + /* is FP constant folding enabled */ false); Info.InConstantContext = true; Info.CheckingPotentialConstantExpression = true; @@ -15240,7 +15271,8 @@ Status.Diag = &Diags; EvalInfo Info(FD->getASTContext(), Status, - EvalInfo::EM_ConstantExpressionUnevaluated); + EvalInfo::EM_ConstantExpressionUnevaluated, + isStrictFPEnabled(FD->getASTContext(), E)); Info.InConstantContext = true; Info.CheckingPotentialConstantExpression = true; @@ -15264,6 +15296,7 @@ return false; Expr::EvalStatus Status; - EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantFold); + EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantFold, + isStrictFPEnabled(Ctx, this)); return tryEvaluateBuiltinObjectSize(this, Type, Info, Result); } diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -900,8 +900,10 @@ if (const FunctionDecl *FD = dyn_cast_or_null(D)) { Builder.setIsFPConstrained(FD->usesFPIntrin()); - if (FD->usesFPIntrin()) + if (FD->usesFPIntrin()) { Fn->addFnAttr(llvm::Attribute::StrictFP); + Builder.setIsFPConstrained(true); + } } // If a custom alignment is used, force realigning to this alignment on diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/lib/CodeGen/CodeGenModule.h @@ -1137,6 +1137,10 @@ /// definition. void SetLLVMFunctionAttributesForDefinition(const Decl *D, llvm::Function *F); + /// Set the LLVM function attributes that represent floating point + /// environment. + void setLLVMFunctionFEnvAttributes(const FunctionDecl *D, llvm::Function *F); + /// Return true iff the given type uses 'sret' when used as a return type. bool ReturnTypeUsesSRet(const CGFunctionInfo &FI); diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -1725,6 +1725,15 @@ } } +void CodeGenModule::setLLVMFunctionFEnvAttributes(const FunctionDecl *D, + llvm::Function *F) { + if (D->usesFPIntrin()) { + llvm::AttrBuilder FuncAttrs; + FuncAttrs.addAttribute("strictfp"); + F->addAttributes(llvm::AttributeList::FunctionIndex, FuncAttrs); + } +} + void CodeGenModule::SetCommonAttributes(GlobalDecl GD, llvm::GlobalValue *GV) { const Decl *D = GD.getDecl(); if (dyn_cast_or_null(D)) @@ -4554,9 +4563,11 @@ MaybeHandleStaticInExternC(D, Fn); - maybeSetTrivialComdat(*D, *Fn); + // Set CodeGen attributes that represent floating point environment. + setLLVMFunctionFEnvAttributes(D, Fn); + CodeGenFunction(*this).GenerateCode(GD, Fn, FI); setNonAliasAttributes(GD, Fn); diff --git a/clang/lib/Parse/ParsePragma.cpp b/clang/lib/Parse/ParsePragma.cpp --- a/clang/lib/Parse/ParsePragma.cpp +++ b/clang/lib/Parse/ParsePragma.cpp @@ -106,10 +106,6 @@ tok::OnOffSwitch OOS; if (PP.LexOnOffSwitch(OOS)) return; - if (OOS == tok::OOS_ON) { - PP.Diag(Tok, diag::warn_stdc_fenv_access_not_supported); - return; - } MutableArrayRef Toks(PP.getPreprocessorAllocator().Allocate(1), 1); diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp --- a/clang/lib/Parse/ParseStmt.cpp +++ b/clang/lib/Parse/ParseStmt.cpp @@ -366,7 +366,8 @@ case tok::annot_pragma_fenv_access: ProhibitAttributes(Attrs); - HandlePragmaFEnvAccess(); + Diag(Tok, diag::err_pragma_stdc_fenv_access_scope); + ConsumeAnnotationToken(); return StmtEmpty(); case tok::annot_pragma_fenv_round: @@ -1033,9 +1034,9 @@ Tok.getLocation(), "in compound statement ('{}')"); - // Record the state of the FPFeatures, restore on leaving the + // Record the current FPFeatures, restore on leaving the // compound statement. - Sema::FPFeaturesStateRAII SaveFPContractState(Actions); + Sema::FPFeaturesStateRAII SaveFPFeatures(Actions); InMessageExpressionRAIIObject InMessage(*this, false); BalancedDelimiterTracker T(*this, tok::l_brace); @@ -1046,6 +1047,7 @@ // Parse any pragmas at the beginning of the compound statement. ParseCompoundStatementLeadingPragmas(); + Actions.ActOnAfterCompoundStatementLeadingPragmas(); StmtVector Stmts; diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -389,6 +389,13 @@ PopCompoundScope(); } +void Sema::ActOnAfterCompoundStatementLeadingPragmas() { + if (getCurFPFeatures().getAllowFEnvAccess()) { + FunctionDecl *F = getCurFunctionDecl(); + F->setUsesFPIntrin(true); + } +} + sema::CompoundScopeInfo &Sema::getCurCompoundScope() const { return getCurFunction()->CompoundScopes.back(); } diff --git a/clang/test/CodeGen/fp-floatcontrol-pragma.cpp b/clang/test/CodeGen/fp-floatcontrol-pragma.cpp --- a/clang/test/CodeGen/fp-floatcontrol-pragma.cpp +++ b/clang/test/CodeGen/fp-floatcontrol-pragma.cpp @@ -1,6 +1,6 @@ // RUN: %clang_cc1 -DEXCEPT=1 -fcxx-exceptions -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-NS %s // RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck %s -// RUN: %clang_cc1 -verify -DFENV_ON=1 -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -DFENV_ON=1 -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-FENV %s // RUN: %clang_cc1 -triple %itanium_abi_triple -O3 -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-O3 %s // Verify float_control(precise, off) enables fast math flags on fp operations. @@ -138,7 +138,6 @@ // CHECK-LABEL define float {{.*}}test_OperatorCall{{.*}} #if FENV_ON -// expected-warning@+1{{pragma STDC FENV_ACCESS ON is not supported, ignoring pragma}} #pragma STDC FENV_ACCESS ON #endif // CHECK-LABEL: define {{.*}}callt{{.*}} @@ -146,7 +145,21 @@ void callt() { volatile float z; z = z * z; -//CHECK: = fmul float + //CHECK-FENV: llvm.experimental.constrained.fmul{{.*}} +} + +// CHECK-LABEL: define {{.*}}myAdd{{.*}} +float myAdd(int i) { + if (i<0) + return 1.0 + 2.0; + // Check that floating point constant folding doesn't occur if + // #pragma STC FENV_ACCESS is enabled. + //CHECK-FENV: llvm.experimental.constrained.fadd{{.*}}double 1.0{{.*}}double 2.0{{.*}} + //CHECK: store float 3.0{{.*}}retval{{.*}} + static double v = 1.0 / 3.0; + //CHECK-FENV: llvm.experimental.constrained.fdiv{{.*}}double 1.0{{.*}}double 3.0{{.*}} + //CHECK-NOT: fdiv + return v; } #if EXCEPT diff --git a/clang/test/CodeGen/pragma-fenv_access.c b/clang/test/CodeGen/pragma-fenv_access.c new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/pragma-fenv_access.c @@ -0,0 +1,66 @@ +// xxx: %clang_cc1 -ffp-exception-behavior=strict -frounding-math -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -ffp-exception-behavior=strict -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck %s + +#pragma STDC FENV_ACCESS ON + +float func_01(float x, float y) { + return x + y; +} +// CHECK-LABEL: @func_01 +// CHECK: call float @llvm.experimental.constrained.fadd.f32(float {{.*}}, float {{.*}}, metadata !"round.tonearest", metadata !"fpexcept.strict") + + +float func_02(float x, float y) { + #pragma float_control(except, off) + #pragma STDC FENV_ACCESS OFF + return x + y; +} +// CHECK-LABEL: @func_02 +// CHECK: fadd float {{.*}} + + +float func_03(float x, float y) { + return x + y; +} +// CHECK-LABEL: @func_03 +// CHECK: call float @llvm.experimental.constrained.fadd.f32(float {{.*}}, float {{.*}}, metadata !"round.tonearest", metadata !"fpexcept.strict") + + +#pragma STDC FENV_ACCESS OFF + +float func_04(float x, float y) { + #pragma float_control(except, off) + return x + y; +} +// CHECK-LABEL: @func_04 +// CHECK: fadd float {{.*}} + + +float func_05(float x, float y) { + #pragma STDC FENV_ACCESS ON + return x + y; +} +// CHECK-LABEL: @func_05 +// CHECK: call float @llvm.experimental.constrained.fadd.f32(float {{.*}}, float {{.*}}, metadata !"round.tonearest", metadata !"fpexcept.strict") + + +float func_06(float x, float y) { + #pragma float_control(except, off) + return x + y; +} +// CHECK-LABEL: @func_06 +// CHECK: fadd float {{.*}} + + +float func_07(float x, float y) { + x -= y; + if (x) { + #pragma STDC FENV_ACCESS ON + y *= 2; + } + return y + 4; +} +// CHECK-LABEL: @func_07 +// CHECK: call float @llvm.experimental.constrained.fsub.f32(float {{.*}}, float {{.*}}, metadata !"round.tonearest", metadata !"fpexcept.strict") +// CHECK: call float @llvm.experimental.constrained.fmul.f32(float {{.*}}, float {{.*}}, metadata !"round.tonearest", metadata !"fpexcept.strict") +// CHECK: call float @llvm.experimental.constrained.fadd.f32(float {{.*}}, float {{.*}}, metadata !"round.tonearest", metadata !"fpexcept.strict") diff --git a/clang/test/Parser/fp-floatcontrol-syntax.cpp b/clang/test/Parser/fp-floatcontrol-syntax.cpp --- a/clang/test/Parser/fp-floatcontrol-syntax.cpp +++ b/clang/test/Parser/fp-floatcontrol-syntax.cpp @@ -26,19 +26,14 @@ double a = 0.0; double b = 1.0; -//FIXME At some point this warning will be removed, until then -// document the warning -#ifdef FAST -// expected-warning@+1{{pragma STDC FENV_ACCESS ON is not supported, ignoring pragma}} -#pragma STDC FENV_ACCESS ON -#else -#pragma STDC FENV_ACCESS ON // expected-warning{{pragma STDC FENV_ACCESS ON is not supported, ignoring pragma}} -#endif #ifdef STRICT #pragma float_control(precise, off) // expected-error {{'#pragma float_control(precise, off)' is illegal when except is enabled}} #else +#ifndef FAST // Currently FENV_ACCESS cannot be enabled by pragma, skip error check -#pragma float_control(precise, off) // not-expected-error {{'#pragma float_control(precise, off)' is illegal when fenv_access is enabled}} +#pragma STDC FENV_ACCESS ON +#pragma float_control(precise, off) // expected-error {{'#pragma float_control(precise, off)' is illegal when fenv_access is enabled}} +#endif #endif #pragma float_control(precise, on) diff --git a/clang/test/Parser/pragma-fenv_access.c b/clang/test/Parser/pragma-fenv_access.c new file mode 100644 --- /dev/null +++ b/clang/test/Parser/pragma-fenv_access.c @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +#pragma STDC FENV_ACCESS IN_BETWEEN // expected-warning {{expected 'ON' or 'OFF' or 'DEFAULT' in pragma}} + +#pragma STDC FENV_ACCESS OFF + +float func_04(int x, float y) { + if (x) + return y + 2; + #pragma STDC FENV_ACCESS ON // expected-error{{'#pragma STDC FENV_ACCESS' can only appear at file scope or at the start of a compound statement}} + return x + y; +} diff --git a/clang/test/Preprocessor/pragma_unknown.c b/clang/test/Preprocessor/pragma_unknown.c --- a/clang/test/Preprocessor/pragma_unknown.c +++ b/clang/test/Preprocessor/pragma_unknown.c @@ -16,15 +16,6 @@ // CHECK: {{^}}#pragma STDC FP_CONTRACT DEFAULT{{$}} // CHECK: {{^}}#pragma STDC FP_CONTRACT IN_BETWEEN{{$}} -#pragma STDC FENV_ACCESS ON // expected-warning {{pragma STDC FENV_ACCESS ON is not supported, ignoring pragma}} -#pragma STDC FENV_ACCESS OFF -#pragma STDC FENV_ACCESS DEFAULT -#pragma STDC FENV_ACCESS IN_BETWEEN // expected-warning {{expected 'ON' or 'OFF' or 'DEFAULT' in pragma}} -// CHECK: {{^}}#pragma STDC FENV_ACCESS ON{{$}} -// CHECK: {{^}}#pragma STDC FENV_ACCESS OFF{{$}} -// CHECK: {{^}}#pragma STDC FENV_ACCESS DEFAULT{{$}} -// CHECK: {{^}}#pragma STDC FENV_ACCESS IN_BETWEEN{{$}} - #pragma STDC CX_LIMITED_RANGE ON #pragma STDC CX_LIMITED_RANGE OFF #pragma STDC CX_LIMITED_RANGE DEFAULT