`pragma clang fp eval_method`.
https://reviews.llvm.org/D109239
...
}
+``#pragma clang fp eval_method`` allows floating-point behavior to be specified
+for a section of the source code. This pragma can appear at file or namespace
+scope, or at the start of a compound statement (excluding comments).
+The pragma is active within the scope of the compound statement.
+
+When ``pragma clang fp eval_method(source)`` is enabled, the section of code
+governed by the pragma behaves as though the command-line option
+``-ffp-eval-method=source`` is enabled. Rounds intermediate results to
+source-defined precision.
+
+When ``pragma clang fp eval_method(double)`` is enabled, the section of code
+governed by the pragma behaves as though the command-line option
+``-ffp-eval-method=double`` is enabled. Rounds intermediate results to
+``double`` precision.
+
+When ``pragma clang fp eval_method(extended)`` is enabled, the section of code
+governed by the pragma behaves as though the command-line option
+``-ffp-eval-method=extended`` is enabled. Rounds intermediate results to
+target-dependent ``long double`` precision. In Win32 programming, for instance,
+the long double data type maps to the double, 64-bit precision data type.
+
+The full syntax this pragma supports is
+``#pragma clang fp eval_method(source|double|extended)``.
+
+.. code-block:: c++
+
+ for(...) {
+ // The compiler will use long double as the floating-point evaluation
+ // method.
+ #pragma clang fp eval_method(extended)
+ a = b[i] * c[i] + e;
+ }
The ``#pragma float_control`` pragma allows precise floating-point
semantics and floating-point exception behavior to be specified
* ``maytrap`` The compiler avoids transformations that may raise exceptions that would not have been raised by the original code. Constant folding performed by the compiler is exempt from this option.
* ``strict`` The compiler ensures that all transformations strictly preserve the floating point exception semantics of the original code.
+.. option:: -ffp-eval-method=<value>
+
+ Specify the floating-point evaluation method for intermediate results within
+ a single expression of the code.
+
+ Valid values are: ``source``, ``double``, and ``extended``.
+ For 64-bit targets, the default value is ``source``. For 32-bit x86 targets
+ however, in the case of NETBSD 6.99.26 and under, the default value is
+ ``double``; in the case of NETBSD greater than 6.99.26, with NoSSE, the
+ default value is ``extended``, with SSE the default value is ``source``.
+ Details:
+
+ * ``source`` The compiler uses the floating-point type declared in the source program as the evaluation method.
+ * ``double`` The compiler uses ``double`` as the floating-point evaluation method for all float expressions of type that is narrower than ``double``.
+ * ``extended`` The compiler uses ``long double`` as the floating-point evaluation method for all float expressions of type that is narrower than ``long double``.
+
.. option:: -f[no-]protect-parens:
This option pertains to floating-point types, complex types with
has no effect because the optimizer is prohibited from making unsafe
transformations.
+.. _FLT_EVAL_METHOD:
+
+A note about ``__FLT_EVAL_METHOD__``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+The macro ``__FLT_EVAL_METHOD__`` will expand to either the value set from the
+command line option ``ffp-eval-method`` or to the value from the target info
+setting. The ``__FLT_EVAL_METHOD__`` macro cannot expand to the correct
+evaluation method in the presence of a ``#pragma`` which alters the evaluation
+method. An error is issued if ``__FLT_EVAL_METHOD__`` is expanded inside a scope
+modified by ``#pragma clang fp eval_method``.
+
.. _fp-constant-eval:
A note about Floating Point Constant Evaluation
"header '%0' is an implementation detail; #include %select{'%2'|either '%2' "
"or '%3'|one of %2}1 instead">;
+def err_illegal_use_of_flt_eval_macro : Error<
+ "'__FLT_EVAL_METHOD__' cannot be expanded inside a scope containing "
+ "'#pragma clang fp eval_method'">;
+
def pp_poisoning_existing_macro : Warning<"poisoning existing macro">;
def pp_out_of_date_dependency : Warning<
"current file is older than dependency %0">;
def note_pragma_attribute_namespace_on_attribute : Note<
"omit the namespace to add attributes to the most-recently"
" pushed attribute group">;
+def warn_no_support_for_eval_method_source_on_m32 : Warning<
+ "Setting the floating point evaluation method to `source` on a target"
+ " without SSE is not supported.">, InGroup<Pragmas>;
// OpenCL EXTENSION pragma (OpenCL 1.1 [9.1])
def warn_pragma_expected_colon : Warning<
OPTION(NoSignedZero, bool, 1, NoHonorInfs)
OPTION(AllowReciprocal, bool, 1, NoSignedZero)
OPTION(AllowApproxFunc, bool, 1, AllowReciprocal)
+OPTION(FPEvalMethod, LangOptions::FPEvalMethodKind, 2, AllowApproxFunc)
#undef OPTION
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_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")
LANGOPT(ObjCAutoRefCount , 1, 0, "Objective-C automated reference counting")
FPE_Strict
};
+ /// Possible float expression evaluation method choices.
+ enum FPEvalMethodKind {
+ /// The evaluation method cannot be determined or is inconsistent for this
+ /// target.
+ FEM_Indeterminable = -1,
+ /// Use the declared type for fp arithmetic.
+ FEM_Source = 0,
+ /// Use the type double for fp arithmetic.
+ FEM_Double = 1,
+ /// Use extended type for fp arithmetic.
+ FEM_Extended = 2,
+ /// Used only for FE option processing; this is only used to indicate that
+ /// the user did not specify an explicit evaluation method on the command
+ /// line and so the target should be queried for its default evaluation
+ /// method instead.
+ FEM_UnsetOnCommandLine = 3
+ };
+
/// Possible exception handling behavior.
enum class ExceptionHandlingKind { None, SjLj, WinEH, DwarfCFI, Wasm };
}
/// Return the value for the C99 FLT_EVAL_METHOD macro.
- virtual unsigned getFloatEvalMethod() const { return 0; }
+ virtual LangOptions::FPEvalMethodKind getFPEvalMethod() const {
+ return LangOptions::FPEvalMethodKind::FEM_Source;
+ }
+
+ virtual bool supportSourceEvalMethod() const { return true; }
// getLargeArrayMinWidth/Align - Return the minimum array size that is
// 'large' and its alignment.
def : Flag<["-"], "fno-extended-identifiers">, Group<f_Group>, Flags<[Unsupported]>;
def fhosted : Flag<["-"], "fhosted">, Group<f_Group>;
def fdenormal_fp_math_EQ : Joined<["-"], "fdenormal-fp-math=">, Group<f_Group>, Flags<[CC1Option]>;
+def ffp_eval_method_EQ : Joined<["-"], "ffp-eval-method=">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Specifies the evaluation method to use for floating-point arithmetic.">,
+ Values<"source,double,extended">, NormalizedValuesScope<"LangOptions">,
+ NormalizedValues<["FEM_Source", "FEM_Double", "FEM_Extended"]>,
+ MarshallingInfoEnum<LangOpts<"FPEvalMethod">, "FEM_UnsetOnCommandLine">;
def ffp_model_EQ : Joined<["-"], "ffp-model=">, Group<f_Group>, Flags<[NoXarchOption]>,
HelpText<"Controls the semantics of floating-point calculations.">;
def ffp_exception_behavior_EQ : Joined<["-"], "ffp-exception-behavior=">, Group<f_Group>, Flags<[CC1Option]>,
IdentifierInfo *Ident__is_target_vendor; // __is_target_vendor
IdentifierInfo *Ident__is_target_os; // __is_target_os
IdentifierInfo *Ident__is_target_environment; // __is_target_environment
+ IdentifierInfo *Ident__FLT_EVAL_METHOD__; // __FLT_EVAL_METHOD
// Weak, only valid (and set) while InMacroArgs is true.
Token* ArgMacro;
SourceLocation DATELoc, TIMELoc;
+ // FEM_UnsetOnCommandLine means that an explicit evaluation method was
+ // not specified on the command line. The target is queried to set the
+ // default evaluation method.
+ LangOptions::FPEvalMethodKind CurrentFPEvalMethod =
+ LangOptions::FPEvalMethodKind::FEM_UnsetOnCommandLine;
+
+ // The most recent pragma location where the floating point evaluation
+ // method was modified. This is used to determine whether the
+ // 'pragma clang fp eval_method' was used whithin the current scope.
+ SourceLocation LastFPEvalPragmaLocation;
+
+ LangOptions::FPEvalMethodKind TUFPEvalMethod =
+ LangOptions::FPEvalMethodKind::FEM_UnsetOnCommandLine;
+
// Next __COUNTER__ value, starts at 0.
unsigned CounterValue = 0;
unsigned getCounterValue() const { return CounterValue; }
void setCounterValue(unsigned V) { CounterValue = V; }
+ LangOptions::FPEvalMethodKind getCurrentFPEvalMethod() const {
+ assert(CurrentFPEvalMethod != LangOptions::FEM_UnsetOnCommandLine &&
+ "FPEvalMethod should be set either from command line or from the "
+ "target info");
+ return CurrentFPEvalMethod;
+ }
+
+ LangOptions::FPEvalMethodKind getTUFPEvalMethod() const {
+ return TUFPEvalMethod;
+ }
+
+ SourceLocation getLastFPEvalPragmaLocation() const {
+ return LastFPEvalPragmaLocation;
+ }
+
+ void setCurrentFPEvalMethod(SourceLocation PragmaLoc,
+ LangOptions::FPEvalMethodKind Val) {
+ assert(Val != LangOptions::FEM_UnsetOnCommandLine &&
+ "FPEvalMethod should never be set to FEM_UnsetOnCommandLine");
+ // This is the location of the '#pragma float_control" where the
+ // execution state is modifed.
+ LastFPEvalPragmaLocation = PragmaLoc;
+ CurrentFPEvalMethod = Val;
+ TUFPEvalMethod = Val;
+ }
+
/// Retrieves the module that we're currently building, if any.
Module *getCurrentModule();
std::unique_ptr<PragmaHandler> PCSectionHandler;
std::unique_ptr<PragmaHandler> MSCommentHandler;
std::unique_ptr<PragmaHandler> MSDetectMismatchHandler;
+ std::unique_ptr<PragmaHandler> FPEvalMethodHandler;
std::unique_ptr<PragmaHandler> FloatControlHandler;
std::unique_ptr<PragmaHandler> MSPointersToMembers;
std::unique_ptr<PragmaHandler> MSVtorDisp;
/// statements.
class FPFeaturesStateRAII {
public:
- FPFeaturesStateRAII(Sema &S) : S(S), OldFPFeaturesState(S.CurFPFeatures) {
- OldOverrides = S.FpPragmaStack.CurrentValue;
- }
- ~FPFeaturesStateRAII() {
- S.CurFPFeatures = OldFPFeaturesState;
- S.FpPragmaStack.CurrentValue = OldOverrides;
- }
+ FPFeaturesStateRAII(Sema &S);
+ ~FPFeaturesStateRAII();
FPOptionsOverride getOverrides() { return OldOverrides; }
private:
Sema& S;
FPOptions OldFPFeaturesState;
FPOptionsOverride OldOverrides;
+ LangOptions::FPEvalMethodKind OldEvalMethod;
+ SourceLocation OldFPPragmaLocation;
};
void addImplicitTypedef(StringRef Name, QualType T);
!CurFPFeatures.getAllowApproxFunc();
}
+ void ActOnPragmaFPEvalMethod(SourceLocation Loc,
+ LangOptions::FPEvalMethodKind Value);
+
/// ActOnPragmaFloatControl - Call on well-formed \#pragma float_control
void ActOnPragmaFloatControl(SourceLocation Loc, PragmaMsStackAction Action,
PragmaFloatControlKind Value);
}
// AIX sets FLT_EVAL_METHOD to be 1.
- unsigned getFloatEvalMethod() const override { return 1; }
+ LangOptions::FPEvalMethodKind getFPEvalMethod() const override {
+ return LangOptions::FPEvalMethodKind::FEM_Double;
+ }
bool defaultsToAIXPowerAlignment() const override { return true; }
};
return LongDoubleFormat == &llvm::APFloat::IEEEquad() ? "g" : "e";
}
- unsigned getFloatEvalMethod() const override {
+ LangOptions::FPEvalMethodKind getFPEvalMethod() const override {
// X87 evaluates with 80 bits "long double" precision.
- return SSELevel == NoSSE ? 2 : 0;
+ return SSELevel == NoSSE ? LangOptions::FPEvalMethodKind::FEM_Extended
+ : LangOptions::FPEvalMethodKind::FEM_Source;
}
+ // EvalMethod `source` is not supported for targets with `NoSSE` feature.
+ bool supportSourceEvalMethod() const override { return SSELevel > NoSSE; }
+
ArrayRef<const char *> getGCCRegNames() const override;
ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
NetBSDI386TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
: NetBSDTargetInfo<X86_32TargetInfo>(Triple, Opts) {}
- unsigned getFloatEvalMethod() const override {
+ LangOptions::FPEvalMethodKind getFPEvalMethod() const override {
VersionTuple OsVersion = getTriple().getOSVersion();
// New NetBSD uses the default rounding mode.
if (OsVersion >= VersionTuple(6, 99, 26) || OsVersion.getMajor() == 0)
- return X86_32TargetInfo::getFloatEvalMethod();
+ return X86_32TargetInfo::getFPEvalMethod();
// NetBSD before 6.99.26 defaults to "double" rounding.
- return 1;
+ return LangOptions::FPEvalMethodKind::FEM_Double;
}
};
StringRef FPModel = "";
// -ffp-exception-behavior options: strict, maytrap, ignore
StringRef FPExceptionBehavior = "";
+ // -ffp-eval-method options: double, extended, source
+ StringRef FPEvalMethod = "";
const llvm::DenormalMode DefaultDenormalFPMath =
TC.getDefaultDenormalModeForType(Args, JA);
const llvm::DenormalMode DefaultDenormalFP32Math =
break;
}
+ // Validate and pass through -ffp-eval-method option.
+ case options::OPT_ffp_eval_method_EQ: {
+ StringRef Val = A->getValue();
+ if (Val.equals("double") || Val.equals("extended") ||
+ Val.equals("source"))
+ FPEvalMethod = Val;
+ else
+ D.Diag(diag::err_drv_unsupported_option_argument)
+ << A->getOption().getName() << Val;
+ break;
+ }
+
case options::OPT_ffinite_math_only:
HonorINFs = false;
HonorNaNs = false;
CmdArgs.push_back(Args.MakeArgString("-ffp-exception-behavior=" +
FPExceptionBehavior));
+ if (!FPEvalMethod.empty())
+ CmdArgs.push_back(Args.MakeArgString("-ffp-eval-method=" + FPEvalMethod));
+
ParseMRecip(D, Args, CmdArgs);
// -ffast-math enables the __FAST_MATH__ preprocessor macro, but check for the
}
// Macros to control C99 numerics and <float.h>
- Builder.defineMacro("__FLT_EVAL_METHOD__", Twine(TI.getFloatEvalMethod()));
Builder.defineMacro("__FLT_RADIX__", "2");
Builder.defineMacro("__DECIMAL_DIG__", "__LDBL_DECIMAL_DIG__");
Ident__TIME__ = RegisterBuiltinMacro(*this, "__TIME__");
Ident__COUNTER__ = RegisterBuiltinMacro(*this, "__COUNTER__");
Ident_Pragma = RegisterBuiltinMacro(*this, "_Pragma");
+ Ident__FLT_EVAL_METHOD__ = RegisterBuiltinMacro(*this, "__FLT_EVAL_METHOD__");
// C++ Standing Document Extensions.
if (getLangOpts().CPlusPlus)
// Surround the string with " and strip the trailing newline.
OS << '"' << StringRef(Result).drop_back() << '"';
Tok.setKind(tok::string_literal);
+ } else if (II == Ident__FLT_EVAL_METHOD__) {
+ // __FLT_EVAL_METHOD__ is set to the default value.
+ OS << getTUFPEvalMethod();
+ // __FLT_EVAL_METHOD__ expands to a simple numeric value.
+ Tok.setKind(tok::numeric_constant);
+ if (getLastFPEvalPragmaLocation().isValid()) {
+ // The program is ill-formed. The value of __FLT_EVAL_METHOD__ is altered
+ // by the pragma.
+ Diag(Tok, diag::err_illegal_use_of_flt_eval_macro);
+ Diag(getLastFPEvalPragmaLocation(), diag::note_pragma_entered_here);
+ }
} else if (II == Ident__COUNTER__) {
// __COUNTER__ expands to a simple numeric value.
OS << CounterValue++;
namespace {
/// Used as the annotation value for tok::annot_pragma_fp.
struct TokFPAnnotValue {
- enum FlagKinds { Contract, Reassociate, Exceptions };
+ enum FlagKinds { Contract, Reassociate, Exceptions, EvalMethod };
enum FlagValues { On, Off, Fast };
llvm::Optional<LangOptions::FPModeKind> ContractValue;
llvm::Optional<LangOptions::FPModeKind> ReassociateValue;
llvm::Optional<LangOptions::FPExceptionModeKind> ExceptionsValue;
+ llvm::Optional<LangOptions::FPEvalMethodKind> EvalMethodValue;
};
} // end anonymous namespace
.Case("contract", TokFPAnnotValue::Contract)
.Case("reassociate", TokFPAnnotValue::Reassociate)
.Case("exceptions", TokFPAnnotValue::Exceptions)
+ .Case("eval_method", TokFPAnnotValue::EvalMethod)
.Default(None);
if (!FlagKind) {
PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_option)
return;
}
PP.Lex(Tok);
+ bool isEvalMethodDouble =
+ Tok.is(tok::kw_double) && FlagKind == TokFPAnnotValue::EvalMethod;
- if (Tok.isNot(tok::identifier)) {
+ // Don't diagnose if we have an eval_metod pragma with "double" kind.
+ if (Tok.isNot(tok::identifier) && !isEvalMethodDouble) {
PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
<< PP.getSpelling(Tok) << OptionInfo->getName()
<< static_cast<int>(*FlagKind);
<< PP.getSpelling(Tok) << OptionInfo->getName() << *FlagKind;
return;
}
+ } else if (FlagKind == TokFPAnnotValue::EvalMethod) {
+ AnnotValue->EvalMethodValue =
+ llvm::StringSwitch<llvm::Optional<LangOptions::FPEvalMethodKind>>(
+ II->getName())
+ .Case("source", LangOptions::FPEvalMethodKind::FEM_Source)
+ .Case("double", LangOptions::FPEvalMethodKind::FEM_Double)
+ .Case("extended", LangOptions::FPEvalMethodKind::FEM_Extended)
+ .Default(llvm::None);
+ if (!AnnotValue->EvalMethodValue) {
+ PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
+ << PP.getSpelling(Tok) << OptionInfo->getName() << *FlagKind;
+ return;
+ }
}
PP.Lex(Tok);
if (AnnotValue->ExceptionsValue)
Actions.ActOnPragmaFPExceptions(Tok.getLocation(),
*AnnotValue->ExceptionsValue);
+ if (AnnotValue->EvalMethodValue)
+ Actions.ActOnPragmaFPEvalMethod(Tok.getLocation(),
+ *AnnotValue->EvalMethodValue);
ConsumeAnnotationToken();
}
if (R.isUsable())
Stmts.push_back(R.get());
}
+ // Warn the user that using option `-ffp-eval-method=source` on a
+ // 32-bit target and feature `sse` disabled, or using
+ // `pragma clang fp eval_method=source` and feature `sse` disabled, is not
+ // supported.
+ if (!PP.getTargetInfo().supportSourceEvalMethod() &&
+ (PP.getLastFPEvalPragmaLocation().isValid() ||
+ PP.getCurrentFPEvalMethod() ==
+ LangOptions::FPEvalMethodKind::FEM_Source))
+ Diag(Tok.getLocation(),
+ diag::warn_no_support_for_eval_method_source_on_m32);
SourceLocation CloseLoc = Tok.getLocation();
SemaPPCallbackHandler = Callbacks.get();
PP.addPPCallbacks(std::move(Callbacks));
SemaPPCallbackHandler->set(*this);
+ if (getLangOpts().getFPEvalMethod() == LangOptions::FEM_UnsetOnCommandLine)
+ // Use setting from TargetInfo.
+ PP.setCurrentFPEvalMethod(SourceLocation(),
+ ctxt.getTargetInfo().getFPEvalMethod());
+ else
+ // Set initial value of __FLT_EVAL_METHOD__ from the command line.
+ PP.setCurrentFPEvalMethod(SourceLocation(),
+ getLangOpts().getFPEvalMethod());
+ CurFPFeatures.setFPEvalMethod(PP.getCurrentFPEvalMethod());
}
// Anchor Sema's type info to this TU.
Sema::getMismatchingDeleteExpressions() const {
return DeleteExprs;
}
+
+Sema::FPFeaturesStateRAII::FPFeaturesStateRAII(Sema &S)
+ : S(S), OldFPFeaturesState(S.CurFPFeatures),
+ OldOverrides(S.FpPragmaStack.CurrentValue),
+ OldEvalMethod(S.PP.getCurrentFPEvalMethod()),
+ OldFPPragmaLocation(S.PP.getLastFPEvalPragmaLocation()) {}
+
+Sema::FPFeaturesStateRAII::~FPFeaturesStateRAII() {
+ S.CurFPFeatures = OldFPFeaturesState;
+ S.FpPragmaStack.CurrentValue = OldOverrides;
+ S.PP.setCurrentFPEvalMethod(OldFPPragmaLocation, OldEvalMethod);
+}
Consumer.HandleTopLevelDecl(DeclGroupRef(PDMD));
}
+void Sema::ActOnPragmaFPEvalMethod(SourceLocation Loc,
+ LangOptions::FPEvalMethodKind Value) {
+ FPOptionsOverride NewFPFeatures = CurFPFeatureOverrides();
+ switch (Value) {
+ default:
+ llvm_unreachable("invalid pragma eval_method kind");
+ case LangOptions::FEM_Source:
+ NewFPFeatures.setFPEvalMethodOverride(LangOptions::FEM_Source);
+ break;
+ case LangOptions::FEM_Double:
+ NewFPFeatures.setFPEvalMethodOverride(LangOptions::FEM_Double);
+ break;
+ case LangOptions::FEM_Extended:
+ NewFPFeatures.setFPEvalMethodOverride(LangOptions::FEM_Extended);
+ break;
+ }
+ FpPragmaStack.Act(Loc, PSK_Set, StringRef(), NewFPFeatures);
+ CurFPFeatures = NewFPFeatures.applyOverrides(getLangOpts());
+ PP.setCurrentFPEvalMethod(Loc, Value);
+}
+
void Sema::ActOnPragmaFloatControl(SourceLocation Loc,
PragmaMsStackAction Action,
PragmaFloatControlKind Value) {
QualType Ty = E->getType();
assert(!Ty.isNull() && "UsualUnaryConversions - missing type");
+ LangOptions::FPEvalMethodKind EvalMethod = CurFPFeatures.getFPEvalMethod();
+ if (EvalMethod != LangOptions::FEM_Source && Ty->isFloatingType() &&
+ (getLangOpts().getFPEvalMethod() !=
+ LangOptions::FPEvalMethodKind::FEM_UnsetOnCommandLine ||
+ PP.getLastFPEvalPragmaLocation().isValid())) {
+ switch (EvalMethod) {
+ default:
+ llvm_unreachable("Unrecognized float evaluation method");
+ break;
+ case LangOptions::FEM_UnsetOnCommandLine:
+ llvm_unreachable("Float evaluation method should be set by now");
+ break;
+ case LangOptions::FEM_Double:
+ if (Context.getFloatingTypeOrder(Context.DoubleTy, Ty) > 0)
+ // Widen the expression to double.
+ return Ty->isComplexType()
+ ? ImpCastExprToType(E,
+ Context.getComplexType(Context.DoubleTy),
+ CK_FloatingComplexCast)
+ : ImpCastExprToType(E, Context.DoubleTy, CK_FloatingCast);
+ break;
+ case LangOptions::FEM_Extended:
+ if (Context.getFloatingTypeOrder(Context.LongDoubleTy, Ty) > 0)
+ // Widen the expression to long double.
+ return Ty->isComplexType()
+ ? ImpCastExprToType(
+ E, Context.getComplexType(Context.LongDoubleTy),
+ CK_FloatingComplexCast)
+ : ImpCastExprToType(E, Context.LongDoubleTy,
+ CK_FloatingCast);
+ break;
+ }
+ }
+
// Half FP have to be promoted to float unless it is natively supported
if (Ty->isHalfType() && !getLangOpts().NativeHalfType)
return ImpCastExprToType(Res.get(), Context.FloatTy, CK_FloatingCast);
--- /dev/null
+// SSE
+// RUN: %clang_cc1 \
+// RUN: -triple i386-pc-windows -target-cpu pentium4 -target-feature +sse \
+// RUN: -emit-llvm -o - %s | FileCheck -check-prefix=CHECK %s
+
+// NO SSE
+// RUN: %clang_cc1 \
+// RUN: -triple i386-pc-windows -target-cpu pentium4 -target-feature -sse \
+// RUN: -emit-llvm -o - %s | FileCheck -check-prefix=CHECK %s
+
+// NO SSE Fast Math
+// RUN: %clang_cc1 \
+// RUN: -triple i386-pc-windows -target-cpu pentium4 -target-feature -sse \
+// RUN: -ffast-math -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-FM %s
+
+float addit(float a, float b, float c) {
+ // CHECK: load float, float*
+ // CHECK: load float, float*
+ // CHECK: fadd float
+ // CHECK: load float, float*
+ // CHECK: fadd float
+
+ // CHECK-FM: load float, float*
+ // CHECK-FM: load float, float*
+ // CHECK-FM: fadd reassoc nnan ninf nsz arcp afn float
+ // CHECK-FM: load float, float*
+ // CHECK-FM: fadd reassoc nnan ninf nsz arcp afn float
+
+ return a + b + c;
+}
--- /dev/null
+// SSE
+// RUN: %clang_cc1 -fexperimental-strict-floating-point \
+// RUN: -triple i386-pc-windows -target-cpu pentium4 -target-feature +sse \
+// RUN: -emit-llvm -o - %s -ffp-eval-method=source \
+// RUN: | FileCheck -check-prefix=CHECK-SRC %s
+
+// RUN: %clang_cc1 -fexperimental-strict-floating-point \
+// RUN: -triple i386-pc-windows -target-cpu pentium4 -target-feature +sse \
+// RUN: -emit-llvm -o - %s -ffp-eval-method=double \
+// RUN: | FileCheck -check-prefix=CHECK-DBL %s
+
+// RUN: %clang_cc1 -fexperimental-strict-floating-point \
+// RUN: -triple i386-pc-windows -target-cpu pentium4 -target-feature +sse \
+// RUN: -emit-llvm -o - %s -ffp-eval-method=extended \
+// RUN: | FileCheck -check-prefix=CHECK-DBL %s
+
+// SSE Fast Math
+// RUN: %clang_cc1 -fexperimental-strict-floating-point \
+// RUN: -triple i386-pc-windows -target-cpu pentium4 -target-feature +sse \
+// RUN: -emit-llvm -o - %s -ffp-eval-method=source \
+// RUN: -ffast-math | FileCheck -check-prefix=CHECK-FM-SRC %s
+
+// RUN: %clang_cc1 -fexperimental-strict-floating-point \
+// RUN: -triple i386-pc-windows -target-cpu pentium4 -target-feature +sse \
+// RUN: -emit-llvm -o - %s -ffp-eval-method=double \
+// RUN: -ffast-math | FileCheck -check-prefix=CHECK-FM %s
+
+// RUN: %clang_cc1 -fexperimental-strict-floating-point \
+// RUN: -triple i386-pc-windows -target-cpu pentium4 -target-feature +sse \
+// RUN: -emit-llvm -o - %s -ffp-eval-method=extended \
+// RUN: -ffast-math | FileCheck -check-prefix=CHECK-FM %s
+
+// NO SSE
+// RUN: %clang_cc1 -fexperimental-strict-floating-point \
+// RUN: -triple i386-pc-windows -target-cpu pentium4 -target-feature -sse \
+// RUN: -emit-llvm -o - %s -ffp-eval-method=source \
+// RUN: | FileCheck -check-prefix=CHECK-SRC %s
+
+// RUN: %clang_cc1 -fexperimental-strict-floating-point \
+// RUN: -triple i386-pc-windows -target-cpu pentium4 -target-feature -sse \
+// RUN: -emit-llvm -o - %s -ffp-eval-method=double \
+// RUN: | FileCheck -check-prefix=CHECK-DBL %s
+
+// RUN: %clang_cc1 -fexperimental-strict-floating-point \
+// RUN: -triple i386-pc-windows -target-cpu pentium4 -target-feature -sse \
+// RUN: -emit-llvm -o - %s -ffp-eval-method=extended \
+// RUN: | FileCheck -check-prefix=CHECK-DBL %s
+
+// NO SSE Fast Math
+// RUN: %clang_cc1 -fexperimental-strict-floating-point \
+// RUN: -triple i386-pc-windows -target-cpu pentium4 -target-feature -sse \
+// RUN: -emit-llvm -o - %s -ffp-eval-method=source \
+// RUN: -ffast-math | FileCheck -check-prefix=CHECK %s
+
+// RUN: %clang_cc1 -fexperimental-strict-floating-point \
+// RUN: -triple i386-pc-windows -target-cpu pentium4 -target-feature -sse \
+// RUN: -emit-llvm -o - %s -ffp-eval-method=double \
+// RUN: -ffast-math | FileCheck -check-prefix=CHECK-DBL-FM %s
+
+// RUN: %clang_cc1 -fexperimental-strict-floating-point \
+// RUN: -triple i386-pc-windows -target-cpu pentium4 -target-feature -sse \
+// RUN: -emit-llvm -o - %s -ffp-eval-method=extended \
+// RUN: -ffast-math | FileCheck -check-prefix=CHECK-DBL-FM %s
+
+float addit(float a, float b, float c) {
+ // CHECK-SRC: load float, float*
+ // CHECK-SRC: load float, float*
+ // CHECK-SRC: fadd float
+ // CHECK-SRC: load float, float*
+ // CHECK-SRC: fadd float
+
+ // CHECK-FM-SRC: load float, float*
+ // CHECK-FM-SRC: load float, float*
+ // CHECK-FM-SRC: fadd reassoc nnan ninf nsz arcp afn float
+ // CHECK-FM-SRC: load float, float*
+ // CHECK-FM-SRC: fadd reassoc nnan ninf nsz arcp afn float
+
+ // CHECK-FM: load float, float*
+ // CHECK-FM: fpext float {{.*}} to double
+ // CHECK-FM: load float, float*
+ // CHECK-FM: fpext float {{.*}} to double
+ // CHECK-FM: fadd reassoc nnan ninf nsz arcp afn double
+ // CHECK-FM: load float, float*
+ // CHECK-FM: fadd reassoc nnan ninf nsz arcp afn double
+ // CHECK-FM: fptrunc double {{.*}} to float
+
+ // CHECK-DBL: load float, float*
+ // CHECK-DBL: fpext float {{.*}} to double
+ // CHECK-DBL: load float, float*
+ // CHECK-DBL: fpext float {{.*}} to double
+ // CHECK-DBL: fadd double
+ // CHECK-DBL: load float, float*
+ // CHECK-DBL: fpext float {{.*}} to double
+ // CHECK-DBL: fadd double
+ // CHECK-DBL: fptrunc double {{.*}} to float
+
+ // CHECK-DBL-FM: load float, float*
+ // CHECK-DBL-FM: fpext float {{.*}} to double
+ // CHECK-DBL-FM: load float, float*
+ // CHECK-DBL-FM: fpext float {{.*}} to double
+ // CHECK-DBL-FM: fadd reassoc nnan ninf nsz arcp afn double
+ // CHECK-DBL-FM: load float, float*
+ // CHECK-DBL-FM: fpext float {{.*}} to double
+ // CHECK-DBL-FM: fadd reassoc nnan ninf nsz arcp afn double
+ // CHECK-DBL-FM: fptrunc double {{.*}} to float
+
+ // CHECK: ret float
+ return a + b + c;
+}
--- /dev/null
+// RUN: %clang_cc1 -triple i386-unknown-netbsd6 -emit-llvm -o - %s \
+// RUN: | FileCheck %s -check-prefixes=CHECK
+
+// RUN: %clang_cc1 -triple i386-unknown-netbsd7 -emit-llvm -o - %s \
+// RUN: | FileCheck %s -check-prefixes=CHECK-EXT
+
+// RUN: %clang_cc1 -triple i386--linux -emit-llvm -o - %s \
+// RUN: | FileCheck %s -check-prefixes=CHECK-EXT
+
+float f(float x, float y) {
+ // CHECK: define{{.*}} float @f
+ // CHECK: fadd float
+ return 2.0f + x + y;
+}
+
+int getEvalMethod() {
+ // CHECK: ret i32 1
+ // CHECK-EXT: ret i32 2
+ return __FLT_EVAL_METHOD__;
+}
--- /dev/null
+// RUN: %clang_cc1 -fexperimental-strict-floating-point -DEXCEPT=1 \
+// RUN: -fcxx-exceptions -triple x86_64-linux-gnu -emit-llvm -o - %s \
+// RUN: | FileCheck -check-prefix=CHECK-SRC %s
+
+// RUN: %clang_cc1 -fexperimental-strict-floating-point \
+// RUN: -triple x86_64-linux-gnu -emit-llvm -o - %s -ffp-eval-method=source \
+// RUN: | FileCheck -check-prefix=CHECK-SRC %s
+
+// RUN: %clang_cc1 -fexperimental-strict-floating-point \
+// RUN: -triple x86_64-linux-gnu -emit-llvm -o - %s -ffp-eval-method=double \
+// RUN: | FileCheck -check-prefixes=CHECK-DBL %s
+
+// RUN: %clang_cc1 -fexperimental-strict-floating-point \
+// RUN: -triple x86_64-linux-gnu -emit-llvm -o - %s -ffp-eval-method=extended \
+// RUN: | FileCheck -check-prefixes=CHECK-EXT-FLT %s
+
+// RUN: %clang_cc1 -triple powerpc-unknown-aix -emit-llvm -o - %s \
+// RUN: | FileCheck %s -check-prefix=CHECK-DBL-PPC
+
+// RUN: %clang_cc1 -fexperimental-strict-floating-point -triple i386-linux-gnu \
+// RUN: -emit-llvm -o - %s -ffp-eval-method=extended -mlong-double-80 \
+// RUN: | FileCheck %s -check-prefix=CHECK-EXT-FLT
+
+int getFEM() {
+ // LABEL: define {{.*}}getFEM{{.*}}
+ return __FLT_EVAL_METHOD__;
+ // CHECK-SRC: ret {{.*}} 0
+ // CHECK-DBL: ret {{.*}} 1
+ // CHECK-DBL-PPC: ret {{.*}} 1
+ // CHECK-EXT-FLT: ret {{.*}} 2
+}
+
+float func() {
+ // LABEL: define {{.*}}@_Z4func{{.*}}
+ float X = 100.0f;
+ float Y = -45.3f;
+ float Z = 393.78f;
+ float temp;
+#if __FLT_EVAL_METHOD__ == 0
+ temp = X + Y + Z;
+#elif __FLT_EVAL_METHOD__ == 1
+ temp = X * Y * Z;
+#elif __FLT_EVAL_METHOD__ == 2
+ temp = X * Y - Z;
+#endif
+ // CHECK-SRC: load float, float*
+ // CHECK-SRC: load float, float*
+ // CHECK-SRC: fadd float
+ // CHECK-SRC: load float, float*
+ // CHECK-SRC: fadd float
+
+ // CHECK-DBL: load float, float*
+ // CHECK-DBL: fpext float
+ // CHECK-DBL: load float, float*
+ // CHECK-DBL: fpext float
+ // CHECK-DBL: fmul double
+ // CHECK-DBL: load float, float*
+ // CHECK-DBL: fpext float
+ // CHECK-DBL: fmul double
+ // CHECK-DBL: fptrunc double
+
+ // CHECK-EXT-FLT: load float, float*
+ // CHECK-EXT-FLT: fpext float
+ // CHECK-EXT-FLT: load float, float*
+ // CHECK-EXT-FLT: fpext float
+ // CHECK-EXT-FLT: fmul x86_fp80
+ // CHECK-EXT-FLT: load float, float*
+ // CHECK-EXT-FLT: fpext float
+ // CHECK-EXT-FLT: fsub x86_fp80
+ // CHECK-EXT-FLT: fptrunc x86_fp80
+
+ // CHECK-DBL-PPC: load float, float*
+ // CHECK-DBL-PPC: load float, float*
+ // CHECK-DBL-PPC: fmul float
+ // CHECK-DBL-PPC: load float, float*
+ // CHECK-DBL-PPC: fmul float
+
+ return temp;
+}
-// RUN: %clang_cc1 -fexperimental-strict-floating-point -DEXCEPT=1 -fcxx-exceptions -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-NS %s
-// RUN: %clang_cc1 -fexperimental-strict-floating-point -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck %s
-// RUN: %clang_cc1 -fexperimental-strict-floating-point -DFENV_ON=1 -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-FENV %s
-// RUN: %clang_cc1 -fexperimental-strict-floating-point -triple %itanium_abi_triple -O3 -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-O3 %s
+// RUN: %clang_cc1 -fexperimental-strict-floating-point -DEXCEPT=1 \
+// RUN: -fcxx-exceptions -triple x86_64-linux-gnu -emit-llvm -o - %s \
+// RUN: | FileCheck -check-prefix=CHECK-NS %s
+
+// RUN: %clang_cc1 -fexperimental-strict-floating-point \
+// RUN: -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck %s \
+// RUN: -check-prefixes=CHECK-DEFAULT,CHECK-CONST-ARGS
+
+// RUN: %clang_cc1 -fexperimental-strict-floating-point -DFENV_ON=1 \
+// RUN: -triple x86_64-linux-gnu -emit-llvm -o - %s \
+// RUN: | FileCheck -check-prefix=CHECK-FENV %s
+
+// RUN: %clang_cc1 -fexperimental-strict-floating-point -DNF128 \
+// RUN: -triple %itanium_abi_triple -O3 -emit-llvm -o - %s \
+// RUN: | FileCheck -check-prefix=CHECK-O3 %s
+
+// RUN: %clang_cc1 -fexperimental-strict-floating-point \
+// RUN: -triple x86_64-linux-gnu -emit-llvm -o - %s -ffp-eval-method=source \
+// RUN: | FileCheck %s -check-prefixes=CHECK-SOURCE,CHECK-CONST-ARGS
+
+// RUN: %clang_cc1 -fexperimental-strict-floating-point \
+// RUN: -triple x86_64-linux-gnu -emit-llvm -o - %s -ffp-eval-method=double \
+// RUN: | FileCheck %s -check-prefixes=CHECK-DOUBLE,CHECK-CONST-ARGS
+
+// RUN: %clang_cc1 -fexperimental-strict-floating-point \
+// RUN: -triple x86_64-linux-gnu -emit-llvm -o - %s -ffp-eval-method=extended \
+// RUN: -mlong-double-80 | FileCheck %s \
+// RUN: -check-prefixes=CHECK-EXTENDED,CHECK-CONST-ARGS
+
+// RUN: %clang_cc1 -fexperimental-strict-floating-point \
+// RUN: -triple i386-linux-gnu -emit-llvm -o - %s -ffp-eval-method=source \
+// RUN: | FileCheck %s -check-prefix=CHECK-SOURCE
+
+// RUN: %clang_cc1 -fexperimental-strict-floating-point -triple i386-linux-gnu \
+// RUN: -emit-llvm -o - %s -ffp-eval-method=double | FileCheck %s \
+// RUN: -check-prefix=CHECK-DOUBLE
+
+// RUN: %clang_cc1 -fexperimental-strict-floating-point -triple i386-linux-gnu \
+// RUN: -emit-llvm -o - %s -ffp-eval-method=extended -mlong-double-80 \
+// RUN: | FileCheck %s -check-prefix=CHECK-EXTENDED
+
+// RUN: %clang_cc1 -triple powerpc-unknown-aix -DNF128 -emit-llvm -o - %s \
+// RUN: | FileCheck %s -check-prefix=CHECK-AIX
+
+bool f() {
+ // CHECK: define {{.*}}f{{.*}}
+ return __FLT_EVAL_METHOD__ < 0 &&
+ __FLT_EVAL_METHOD__ == -1;
+ // CHECK: ret {{.*}} true
+}
// Verify float_control(precise, off) enables fast math flags on fp operations.
float fp_precise_1(float a, float b, float c) {
result = x + t;
return result;
}
+
+float mySub(float x, float y) {
+ // CHECK: define {{.*}}float {{.*}}mySub{{.*}}
+ // CHECK-NS: fsub float
+ // CHECK-SOURCE: fsub float
+ // CHECK-DOUBLE: fpext float
+ // CHECK-DOUBLE: fpext float
+ // CHECK-DOUBLE: fsub double
+ // CHECK-DOUBLE: fptrunc double {{.*}} to float
+ // CHECK-EXTENDED: fpext float
+ // CHECK-EXTENDED: fpext float
+ // CHECK-EXTENDED: fsub double
+ // CHECK-EXTENDED: fptrunc double {{.*}} to float
+ return x - y;
+}
+
+float mySubSource(float x, float y) {
+// CHECK: define {{.*}}float {{.*}}mySubSource{{.*}}
+#pragma clang fp eval_method(source)
+ return x - y;
+ // CHECK: fsub float
+}
+
+float mySubExtended(float x, float y) {
+// CHECK: define {{.*}}float {{.*}}mySubExtended{{.*}}
+#pragma clang fp eval_method(extended)
+ return x - y;
+ // CHECK: fpext float
+ // CHECK: fpext float
+ // CHECK: fsub x86_fp80
+ // CHECK: fptrunc x86_fp80 {{.*}} to float
+ // CHECK-AIX: fsub double
+ // CHECK-AIX: fptrunc double
+}
+
+float mySubDouble(float x, float y) {
+// CHECK: define {{.*}}float {{.*}}mySubDouble{{.*}}
+#pragma clang fp eval_method(double)
+ return x - y;
+ // CHECK: fpext float
+ // CHECK: fpext float
+ // CHECK: fsub double
+ // CHECK: fptrunc double {{.*}} to float
+}
+
+#ifndef NF128
+__float128 mySub128(__float128 x, __float128 y) {
+ // CHECK: define {{.*}}mySub128{{.*}}
+ // Expect no fpext since fp128 is already widest
+ // CHECK: load fp128
+ // CHECK-NEXT: load fp128
+ // CHECK-NEXT: fsub fp128
+ // CHECK-NEXT: ret fp128
+ return x - y;
+}
+#endif
+
+void mySubfp16(__fp16 *res, __fp16 *x, __fp16 *y) {
+ // CHECK: define {{.*}}mySubfp16{{.*}}
+ *res = *x - *y;
+ // CHECK: load half
+ // CHECK-NEXT: load half
+ // CHECK-NEXT: fpext half{{.*}}
+ // CHECK-NEXT: load half
+ // CHECK-NEXT: load half
+ // CHECK-NS: fpext half{{.*}} to float
+ // CHECK-DEFAULT: fpext half{{.*}} to float
+ // CHECK-DOUBLE: fpext half{{.*}} to float
+ // CHECK-EXTENDED: fpext half{{.*}} to float
+ // CHECK-NEXT: fsub
+ // CHECK-NEXT: fptrunc {{.*}}to half
+ // CHECK-NS: fptrunc float {{.*}} to half
+ // CHECK-DOUBLE: fptrunc float {{.*}} to half
+ // CHECK-EXTENDED: fptrunc float {{.*}} to half
+}
+
+float Div(float x, float y, float z) {
+ // CHECK: define{{.*}}float {{.*}}Div{{.*}}
+ // CHECK-CONST-ARGS: fdiv float
+ return x / (y / z);
+}
+
+float DivExtended(float x, float y, float z) {
+// CHECK: define{{.*}}float {{.*}}DivExtended{{.*}}
+#pragma clang fp eval_method(extended)
+ // CHECK-CONST-ARGS: fdiv x86_fp80
+ // CHECK-CONST-ARGS: fptrunc x86_fp80
+ return x / (y / z);
+}
+
+float DivDouble(float x, float y, float z) {
+// CHECK: define{{.*}}float {{.*}}DivDouble{{.*}}
+#pragma clang fp eval_method(double)
+ // CHECK-CONST-ARGS: fdiv double
+ // CHECK-CONST-ARGS: fptrunc double
+ return x / (y / z);
+}
+
+float DivSource(float x, float y, float z) {
+// CHECK: define{{.*}}float {{.*}}DivSource{{.*}}
+#pragma clang fp eval_method(source)
+ // CHECK-CONST-ARGS: fdiv float
+ return x / (y / z);
+}
+
+int main() {
+ float f = Div(4.2f, 1.0f, 3.0f);
+ float fextended = DivExtended(4.2f, 1.0f, 3.0f);
+ float fdouble = DivDouble(4.2f, 1.0f, 3.0f);
+ float fsource = DivSource(4.2f, 1.0f, 3.0f);
+ // CHECK: store float
+}
--- /dev/null
+// RUN: %clang_cc1 -E -dM %s -o - | FileCheck %s -strict-whitespace
+
+#ifdef __FLT_EVAL_METHOD__
+#if __FLT_EVAL_METHOD__ == 3
+#define __GLIBC_FLT_EVAL_METHOD 2
+#else
+#define __GLIBC_FLT_EVAL_METHOD __FLT_EVAL_METHOD__
+#endif
+#elif defined __x86_64__
+#define __GLIBC_FLT_EVAL_METHOD 0
+#else
+#define __GLIBC_FLT_EVAL_METHOD 2
+#endif
+
+#if __GLIBC_FLT_EVAL_METHOD == 0 || __GLIBC_FLT_EVAL_METHOD == 16
+#define Name "One"
+#elif __GLIBC_FLT_EVAL_METHOD == 1
+#define Name "Two"
+#elif __GLIBC_FLT_EVAL_METHOD == 2
+#define Name "Unset on command line"
+#elif __GLIBC_FLT_EVAL_METHOD == 32
+#define Name "Four"
+#elif __GLIBC_FLT_EVAL_METHOD == 33
+#define Name "Five"
+#elif __GLIBC_FLT_EVAL_METHOD == 64
+#define Name "Six"
+#elif __GLIBC_FLT_EVAL_METHOD == 65
+#define Name "Seven"
+#elif __GLIBC_FLT_EVAL_METHOD == 128
+#define Name "Eight"
+#elif __GLIBC_FLT_EVAL_METHOD == 129
+#define Name "Nine"
+#else
+#error "Unknown __GLIBC_FLT_EVAL_METHOD"
+#endif
+
+int foo() {
+ // CHECK: #define Name "Unset on command line"
+ return Name;
+}
+
+#if __FLT_EVAL_METHOD__ == 3
+#define Val "val0"
+#endif
+
+#pragma fp eval_method(double)
+
+#if __FLT_EVAL_METHOD__ == 0
+#define Val "val1"
+#elif __FLT_EVAL_METHOD__ == 1
+#define Val "val2"
+#elif __FLT_EVAL_METHOD__ == 2
+#define Val "val3"
+#endif
+
+int goo() {
+ // CHECK: #define Val "val0"
+ return Name;
+}
// AARCH64-NEXT: #define __FLT_DENORM_MIN__ 1.40129846e-45F
// AARCH64-NEXT: #define __FLT_DIG__ 6
// AARCH64-NEXT: #define __FLT_EPSILON__ 1.19209290e-7F
-// AARCH64-NEXT: #define __FLT_EVAL_METHOD__ 0
// AARCH64-NEXT: #define __FLT_HAS_DENORM__ 1
// AARCH64-NEXT: #define __FLT_HAS_INFINITY__ 1
// AARCH64-NEXT: #define __FLT_HAS_QUIET_NAN__ 1
// AARCH64-DARWIN: #define __FLT_DENORM_MIN__ 1.40129846e-45F
// AARCH64-DARWIN: #define __FLT_DIG__ 6
// AARCH64-DARWIN: #define __FLT_EPSILON__ 1.19209290e-7F
-// AARCH64-DARWIN: #define __FLT_EVAL_METHOD__ 0
// AARCH64-DARWIN: #define __FLT_HAS_DENORM__ 1
// AARCH64-DARWIN: #define __FLT_HAS_INFINITY__ 1
// AARCH64-DARWIN: #define __FLT_HAS_QUIET_NAN__ 1
// AARCH64-MSVC: #define __FLT_DENORM_MIN__ 1.40129846e-45F
// AARCH64-MSVC: #define __FLT_DIG__ 6
// AARCH64-MSVC: #define __FLT_EPSILON__ 1.19209290e-7F
-// AARCH64-MSVC: #define __FLT_EVAL_METHOD__ 0
// AARCH64-MSVC: #define __FLT_HAS_DENORM__ 1
// AARCH64-MSVC: #define __FLT_HAS_INFINITY__ 1
// AARCH64-MSVC: #define __FLT_HAS_QUIET_NAN__ 1
// ARM:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// ARM:#define __FLT_DIG__ 6
// ARM:#define __FLT_EPSILON__ 1.19209290e-7F
-// ARM:#define __FLT_EVAL_METHOD__ 0
// ARM:#define __FLT_HAS_DENORM__ 1
// ARM:#define __FLT_HAS_INFINITY__ 1
// ARM:#define __FLT_HAS_QUIET_NAN__ 1
// ARM-BE:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// ARM-BE:#define __FLT_DIG__ 6
// ARM-BE:#define __FLT_EPSILON__ 1.19209290e-7F
-// ARM-BE:#define __FLT_EVAL_METHOD__ 0
// ARM-BE:#define __FLT_HAS_DENORM__ 1
// ARM-BE:#define __FLT_HAS_INFINITY__ 1
// ARM-BE:#define __FLT_HAS_QUIET_NAN__ 1
// ARMEABISOFTFP:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// ARMEABISOFTFP:#define __FLT_DIG__ 6
// ARMEABISOFTFP:#define __FLT_EPSILON__ 1.19209290e-7F
-// ARMEABISOFTFP:#define __FLT_EVAL_METHOD__ 0
// ARMEABISOFTFP:#define __FLT_HAS_DENORM__ 1
// ARMEABISOFTFP:#define __FLT_HAS_INFINITY__ 1
// ARMEABISOFTFP:#define __FLT_HAS_QUIET_NAN__ 1
// ARMEABIHARDFP:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// ARMEABIHARDFP:#define __FLT_DIG__ 6
// ARMEABIHARDFP:#define __FLT_EPSILON__ 1.19209290e-7F
-// ARMEABIHARDFP:#define __FLT_EVAL_METHOD__ 0
// ARMEABIHARDFP:#define __FLT_HAS_DENORM__ 1
// ARMEABIHARDFP:#define __FLT_HAS_INFINITY__ 1
// ARMEABIHARDFP:#define __FLT_HAS_QUIET_NAN__ 1
// ARM-NETBSD:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// ARM-NETBSD:#define __FLT_DIG__ 6
// ARM-NETBSD:#define __FLT_EPSILON__ 1.19209290e-7F
-// ARM-NETBSD:#define __FLT_EVAL_METHOD__ 0
// ARM-NETBSD:#define __FLT_HAS_DENORM__ 1
// ARM-NETBSD:#define __FLT_HAS_INFINITY__ 1
// ARM-NETBSD:#define __FLT_HAS_QUIET_NAN__ 1
// MIPS32BE:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// MIPS32BE:#define __FLT_DIG__ 6
// MIPS32BE:#define __FLT_EPSILON__ 1.19209290e-7F
-// MIPS32BE:#define __FLT_EVAL_METHOD__ 0
// MIPS32BE:#define __FLT_HAS_DENORM__ 1
// MIPS32BE:#define __FLT_HAS_INFINITY__ 1
// MIPS32BE:#define __FLT_HAS_QUIET_NAN__ 1
// MIPS32EL:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// MIPS32EL:#define __FLT_DIG__ 6
// MIPS32EL:#define __FLT_EPSILON__ 1.19209290e-7F
-// MIPS32EL:#define __FLT_EVAL_METHOD__ 0
// MIPS32EL:#define __FLT_HAS_DENORM__ 1
// MIPS32EL:#define __FLT_HAS_INFINITY__ 1
// MIPS32EL:#define __FLT_HAS_QUIET_NAN__ 1
// MIPSN32BE: #define __FLT_DENORM_MIN__ 1.40129846e-45F
// MIPSN32BE: #define __FLT_DIG__ 6
// MIPSN32BE: #define __FLT_EPSILON__ 1.19209290e-7F
-// MIPSN32BE: #define __FLT_EVAL_METHOD__ 0
// MIPSN32BE: #define __FLT_HAS_DENORM__ 1
// MIPSN32BE: #define __FLT_HAS_INFINITY__ 1
// MIPSN32BE: #define __FLT_HAS_QUIET_NAN__ 1
// MIPSN32EL: #define __FLT_DENORM_MIN__ 1.40129846e-45F
// MIPSN32EL: #define __FLT_DIG__ 6
// MIPSN32EL: #define __FLT_EPSILON__ 1.19209290e-7F
-// MIPSN32EL: #define __FLT_EVAL_METHOD__ 0
// MIPSN32EL: #define __FLT_HAS_DENORM__ 1
// MIPSN32EL: #define __FLT_HAS_INFINITY__ 1
// MIPSN32EL: #define __FLT_HAS_QUIET_NAN__ 1
// MIPS64BE:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// MIPS64BE:#define __FLT_DIG__ 6
// MIPS64BE:#define __FLT_EPSILON__ 1.19209290e-7F
-// MIPS64BE:#define __FLT_EVAL_METHOD__ 0
// MIPS64BE:#define __FLT_HAS_DENORM__ 1
// MIPS64BE:#define __FLT_HAS_INFINITY__ 1
// MIPS64BE:#define __FLT_HAS_QUIET_NAN__ 1
// MIPS64EL:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// MIPS64EL:#define __FLT_DIG__ 6
// MIPS64EL:#define __FLT_EPSILON__ 1.19209290e-7F
-// MIPS64EL:#define __FLT_EVAL_METHOD__ 0
// MIPS64EL:#define __FLT_HAS_DENORM__ 1
// MIPS64EL:#define __FLT_HAS_INFINITY__ 1
// MIPS64EL:#define __FLT_HAS_QUIET_NAN__ 1
// PPC603E:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// PPC603E:#define __FLT_DIG__ 6
// PPC603E:#define __FLT_EPSILON__ 1.19209290e-7F
-// PPC603E:#define __FLT_EVAL_METHOD__ 0
// PPC603E:#define __FLT_HAS_DENORM__ 1
// PPC603E:#define __FLT_HAS_INFINITY__ 1
// PPC603E:#define __FLT_HAS_QUIET_NAN__ 1
// PPC:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// PPC:#define __FLT_DIG__ 6
// PPC:#define __FLT_EPSILON__ 1.19209290e-7F
-// PPC:#define __FLT_EVAL_METHOD__ 0
// PPC:#define __FLT_HAS_DENORM__ 1
// PPC:#define __FLT_HAS_INFINITY__ 1
// PPC:#define __FLT_HAS_QUIET_NAN__ 1
// PPC-AIX:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// PPC-AIX:#define __FLT_DIG__ 6
// PPC-AIX:#define __FLT_EPSILON__ 1.19209290e-7F
-// PPC-AIX:#define __FLT_EVAL_METHOD__ 1
// PPC-AIX:#define __FLT_HAS_DENORM__ 1
// PPC-AIX:#define __FLT_HAS_INFINITY__ 1
// PPC-AIX:#define __FLT_HAS_QUIET_NAN__ 1
// PPC-LINUX:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// PPC-LINUX:#define __FLT_DIG__ 6
// PPC-LINUX:#define __FLT_EPSILON__ 1.19209290e-7F
-// PPC-LINUX:#define __FLT_EVAL_METHOD__ 0
// PPC-LINUX:#define __FLT_HAS_DENORM__ 1
// PPC-LINUX:#define __FLT_HAS_INFINITY__ 1
// PPC-LINUX:#define __FLT_HAS_QUIET_NAN__ 1
// PPC-DARWIN:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// PPC-DARWIN:#define __FLT_DIG__ 6
// PPC-DARWIN:#define __FLT_EPSILON__ 1.19209290e-7F
-// PPC-DARWIN:#define __FLT_EVAL_METHOD__ 0
// PPC-DARWIN:#define __FLT_HAS_DENORM__ 1
// PPC-DARWIN:#define __FLT_HAS_INFINITY__ 1
// PPC-DARWIN:#define __FLT_HAS_QUIET_NAN__ 1
// PPC64:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// PPC64:#define __FLT_DIG__ 6
// PPC64:#define __FLT_EPSILON__ 1.19209290e-7F
-// PPC64:#define __FLT_EVAL_METHOD__ 0
// PPC64:#define __FLT_HAS_DENORM__ 1
// PPC64:#define __FLT_HAS_INFINITY__ 1
// PPC64:#define __FLT_HAS_QUIET_NAN__ 1
// PPC64LE:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// PPC64LE:#define __FLT_DIG__ 6
// PPC64LE:#define __FLT_EPSILON__ 1.19209290e-7F
-// PPC64LE:#define __FLT_EVAL_METHOD__ 0
// PPC64LE:#define __FLT_HAS_DENORM__ 1
// PPC64LE:#define __FLT_HAS_INFINITY__ 1
// PPC64LE:#define __FLT_HAS_QUIET_NAN__ 1
// PPC64-AIX:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// PPC64-AIX:#define __FLT_DIG__ 6
// PPC64-AIX:#define __FLT_EPSILON__ 1.19209290e-7F
-// PPC64-AIX:#define __FLT_EVAL_METHOD__ 1
// PPC64-AIX:#define __FLT_HAS_DENORM__ 1
// PPC64-AIX:#define __FLT_HAS_INFINITY__ 1
// PPC64-AIX:#define __FLT_HAS_QUIET_NAN__ 1
// PPC64-LINUX:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// PPC64-LINUX:#define __FLT_DIG__ 6
// PPC64-LINUX:#define __FLT_EPSILON__ 1.19209290e-7F
-// PPC64-LINUX:#define __FLT_EVAL_METHOD__ 0
// PPC64-LINUX:#define __FLT_HAS_DENORM__ 1
// PPC64-LINUX:#define __FLT_HAS_INFINITY__ 1
// PPC64-LINUX:#define __FLT_HAS_QUIET_NAN__ 1
// S390X:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// S390X:#define __FLT_DIG__ 6
// S390X:#define __FLT_EPSILON__ 1.19209290e-7F
-// S390X:#define __FLT_EVAL_METHOD__ 0
// S390X:#define __FLT_HAS_DENORM__ 1
// S390X:#define __FLT_HAS_INFINITY__ 1
// S390X:#define __FLT_HAS_QUIET_NAN__ 1
// CHECK: #define __FLT_DENORM_MIN__ 1.40129846e-45F
// CHECK: #define __FLT_DIG__ 6
// CHECK: #define __FLT_EPSILON__ 1.19209290e-7F
-// CHECK: #define __FLT_EVAL_METHOD__ 0
// CHECK: #define __FLT_HAS_DENORM__ 1
// CHECK: #define __FLT_HAS_INFINITY__ 1
// CHECK: #define __FLT_HAS_QUIET_NAN__ 1
// I386:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// I386:#define __FLT_DIG__ 6
// I386:#define __FLT_EPSILON__ 1.19209290e-7F
-// I386:#define __FLT_EVAL_METHOD__ 2
// I386:#define __FLT_HAS_DENORM__ 1
// I386:#define __FLT_HAS_INFINITY__ 1
// I386:#define __FLT_HAS_QUIET_NAN__ 1
// I386-LINUX:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// I386-LINUX:#define __FLT_DIG__ 6
// I386-LINUX:#define __FLT_EPSILON__ 1.19209290e-7F
-// I386-LINUX:#define __FLT_EVAL_METHOD__ 0
// I386-LINUX:#define __FLT_HAS_DENORM__ 1
// I386-LINUX:#define __FLT_HAS_INFINITY__ 1
// I386-LINUX:#define __FLT_HAS_QUIET_NAN__ 1
// I386-NETBSD:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// I386-NETBSD:#define __FLT_DIG__ 6
// I386-NETBSD:#define __FLT_EPSILON__ 1.19209290e-7F
-// I386-NETBSD:#define __FLT_EVAL_METHOD__ 2
// I386-NETBSD:#define __FLT_HAS_DENORM__ 1
// I386-NETBSD:#define __FLT_HAS_INFINITY__ 1
// I386-NETBSD:#define __FLT_HAS_QUIET_NAN__ 1
// I386-NETBSD:#define __i386__ 1
// I386-NETBSD:#define i386 1
-// RUN: %clang_cc1 -E -dM -ffreestanding -triple=i386-netbsd -target-feature +sse2 < /dev/null | FileCheck -match-full-lines -check-prefix I386-NETBSD-SSE %s
-// I386-NETBSD-SSE:#define __FLT_EVAL_METHOD__ 0
-// RUN: %clang_cc1 -E -dM -ffreestanding -triple=i386-netbsd6 < /dev/null | FileCheck -match-full-lines -check-prefix I386-NETBSD6 %s
-// I386-NETBSD6:#define __FLT_EVAL_METHOD__ 1
-// RUN: %clang_cc1 -E -dM -ffreestanding -triple=i386-netbsd6 -target-feature +sse2 < /dev/null | FileCheck -match-full-lines -check-prefix I386-NETBSD6-SSE %s
-// I386-NETBSD6-SSE:#define __FLT_EVAL_METHOD__ 1
-
// RUN: %clang_cc1 -E -dM -triple=i686-pc-mingw32 < /dev/null | FileCheck -match-full-lines -check-prefix I386-DECLSPEC %s
// RUN: %clang_cc1 -E -dM -fms-extensions -triple=i686-pc-mingw32 < /dev/null | FileCheck -match-full-lines -check-prefix I386-DECLSPEC %s
// RUN: %clang_cc1 -E -dM -triple=i686-unknown-cygwin < /dev/null | FileCheck -match-full-lines -check-prefix I386-DECLSPEC %s
// X86_64:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// X86_64:#define __FLT_DIG__ 6
// X86_64:#define __FLT_EPSILON__ 1.19209290e-7F
-// X86_64:#define __FLT_EVAL_METHOD__ 0
// X86_64:#define __FLT_HAS_DENORM__ 1
// X86_64:#define __FLT_HAS_INFINITY__ 1
// X86_64:#define __FLT_HAS_QUIET_NAN__ 1
// X32:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// X32:#define __FLT_DIG__ 6
// X32:#define __FLT_EPSILON__ 1.19209290e-7F
-// X32:#define __FLT_EVAL_METHOD__ 0
// X32:#define __FLT_HAS_DENORM__ 1
// X32:#define __FLT_HAS_INFINITY__ 1
// X32:#define __FLT_HAS_QUIET_NAN__ 1
// X86_64-CLOUDABI:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// X86_64-CLOUDABI:#define __FLT_DIG__ 6
// X86_64-CLOUDABI:#define __FLT_EPSILON__ 1.19209290e-7F
-// X86_64-CLOUDABI:#define __FLT_EVAL_METHOD__ 0
// X86_64-CLOUDABI:#define __FLT_HAS_DENORM__ 1
// X86_64-CLOUDABI:#define __FLT_HAS_INFINITY__ 1
// X86_64-CLOUDABI:#define __FLT_HAS_QUIET_NAN__ 1
// X86_64-LINUX:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// X86_64-LINUX:#define __FLT_DIG__ 6
// X86_64-LINUX:#define __FLT_EPSILON__ 1.19209290e-7F
-// X86_64-LINUX:#define __FLT_EVAL_METHOD__ 0
// X86_64-LINUX:#define __FLT_HAS_DENORM__ 1
// X86_64-LINUX:#define __FLT_HAS_INFINITY__ 1
// X86_64-LINUX:#define __FLT_HAS_QUIET_NAN__ 1
// X86_64-NETBSD:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// X86_64-NETBSD:#define __FLT_DIG__ 6
// X86_64-NETBSD:#define __FLT_EPSILON__ 1.19209290e-7F
-// X86_64-NETBSD:#define __FLT_EVAL_METHOD__ 0
// X86_64-NETBSD:#define __FLT_HAS_DENORM__ 1
// X86_64-NETBSD:#define __FLT_HAS_INFINITY__ 1
// X86_64-NETBSD:#define __FLT_HAS_QUIET_NAN__ 1
// MSP430:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// MSP430:#define __FLT_DIG__ 6
// MSP430:#define __FLT_EPSILON__ 1.19209290e-7F
-// MSP430:#define __FLT_EVAL_METHOD__ 0
// MSP430:#define __FLT_HAS_DENORM__ 1
// MSP430:#define __FLT_HAS_INFINITY__ 1
// MSP430:#define __FLT_HAS_QUIET_NAN__ 1
// NVPTX32:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// NVPTX32:#define __FLT_DIG__ 6
// NVPTX32:#define __FLT_EPSILON__ 1.19209290e-7F
-// NVPTX32:#define __FLT_EVAL_METHOD__ 0
// NVPTX32:#define __FLT_HAS_DENORM__ 1
// NVPTX32:#define __FLT_HAS_INFINITY__ 1
// NVPTX32:#define __FLT_HAS_QUIET_NAN__ 1
// NVPTX64:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// NVPTX64:#define __FLT_DIG__ 6
// NVPTX64:#define __FLT_EPSILON__ 1.19209290e-7F
-// NVPTX64:#define __FLT_EVAL_METHOD__ 0
// NVPTX64:#define __FLT_HAS_DENORM__ 1
// NVPTX64:#define __FLT_HAS_INFINITY__ 1
// NVPTX64:#define __FLT_HAS_QUIET_NAN__ 1
// SPARC:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// SPARC:#define __FLT_DIG__ 6
// SPARC:#define __FLT_EPSILON__ 1.19209290e-7F
-// SPARC:#define __FLT_EVAL_METHOD__ 0
// SPARC:#define __FLT_HAS_DENORM__ 1
// SPARC:#define __FLT_HAS_INFINITY__ 1
// SPARC:#define __FLT_HAS_QUIET_NAN__ 1
// TCE:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// TCE:#define __FLT_DIG__ 6
// TCE:#define __FLT_EPSILON__ 1.19209290e-7F
-// TCE:#define __FLT_EVAL_METHOD__ 0
// TCE:#define __FLT_HAS_DENORM__ 1
// TCE:#define __FLT_HAS_INFINITY__ 1
// TCE:#define __FLT_HAS_QUIET_NAN__ 1
// PS4:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// PS4:#define __FLT_DIG__ 6
// PS4:#define __FLT_EPSILON__ 1.19209290e-7F
-// PS4:#define __FLT_EVAL_METHOD__ 0
// PS4:#define __FLT_HAS_DENORM__ 1
// PS4:#define __FLT_HAS_INFINITY__ 1
// PS4:#define __FLT_HAS_QUIET_NAN__ 1
// WEBASSEMBLY-NEXT:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// WEBASSEMBLY-NEXT:#define __FLT_DIG__ 6
// WEBASSEMBLY-NEXT:#define __FLT_EPSILON__ 1.19209290e-7F
-// WEBASSEMBLY-NEXT:#define __FLT_EVAL_METHOD__ 0
// WEBASSEMBLY-NEXT:#define __FLT_HAS_DENORM__ 1
// WEBASSEMBLY-NEXT:#define __FLT_HAS_INFINITY__ 1
// WEBASSEMBLY-NEXT:#define __FLT_HAS_QUIET_NAN__ 1
// AVR:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// AVR:#define __FLT_DIG__ 6
// AVR:#define __FLT_EPSILON__ 1.19209290e-7F
-// AVR:#define __FLT_EVAL_METHOD__ 0
// AVR:#define __FLT_HAS_DENORM__ 1
// AVR:#define __FLT_HAS_INFINITY__ 1
// AVR:#define __FLT_HAS_QUIET_NAN__ 1
// AVR:#define __WCHAR_TYPE__ int
// AVR:#define __WINT_TYPE__ int
-
// RUN: %clang_cc1 -E -dM -ffreestanding \
// RUN: -triple i686-windows-msvc -fms-compatibility -x c++ < /dev/null \
// RUN: | FileCheck -match-full-lines -check-prefix MSVC-X32 %s
// RISCV32: #define __FLT_DENORM_MIN__ 1.40129846e-45F
// RISCV32: #define __FLT_DIG__ 6
// RISCV32: #define __FLT_EPSILON__ 1.19209290e-7F
-// RISCV32: #define __FLT_EVAL_METHOD__ 0
// RISCV32: #define __FLT_HAS_DENORM__ 1
// RISCV32: #define __FLT_HAS_INFINITY__ 1
// RISCV32: #define __FLT_HAS_QUIET_NAN__ 1
// RISCV64: #define __FLT_DENORM_MIN__ 1.40129846e-45F
// RISCV64: #define __FLT_DIG__ 6
// RISCV64: #define __FLT_EPSILON__ 1.19209290e-7F
-// RISCV64: #define __FLT_EVAL_METHOD__ 0
// RISCV64: #define __FLT_HAS_DENORM__ 1
// RISCV64: #define __FLT_HAS_INFINITY__ 1
// RISCV64: #define __FLT_HAS_QUIET_NAN__ 1
--- /dev/null
+// RUN: %clang_cc1 -fexperimental-strict-floating-point \
+// RUN: -triple x86_64-linux-gnu -emit-llvm -o - -verify %s
+//
+// RUN: %clang_cc1 -fexperimental-strict-floating-point \
+// RUN: -triple x86_64-linux-gnu -emit-llvm -o - -verify %s \
+// RUN: -ffp-eval-method=source
+//
+// RUN: %clang_cc1 -fexperimental-strict-floating-point \
+// RUN: -triple x86_64-linux-gnu -emit-llvm -o - -verify %s \
+// RUN: -ffp-eval-method=double
+
+extern "C" int printf(const char *, ...);
+
+void foo1() {
+ printf("FP: %d\n", __FLT_EVAL_METHOD__);
+}
+
+void apply_pragma() {
+ // expected-note@+1{{#pragma entered here}}
+#pragma clang fp eval_method(double)
+ // expected-error@+1{{'__FLT_EVAL_METHOD__' cannot be expanded inside a scope containing '#pragma clang fp eval_method'}}
+ printf("FP: %d\n", __FLT_EVAL_METHOD__);
+}
+
+int foo2() {
+ apply_pragma();
+ return 0;
+}
+
+void foo() {
+ auto a = __FLT_EVAL_METHOD__;
+ {
+ // expected-note@+1{{#pragma entered here}}
+#pragma clang fp eval_method(double)
+ // expected-error@+1{{'__FLT_EVAL_METHOD__' cannot be expanded inside a scope containing '#pragma clang fp eval_method'}}
+ auto b = __FLT_EVAL_METHOD__;
+ }
+ auto c = __FLT_EVAL_METHOD__;
+}
+
+void func() {
+ {
+ {
+#pragma clang fp eval_method(source)
+ }
+ int i = __FLT_EVAL_METHOD__; // ok, not in a scope changed by the pragma
+ }
+ {
+ // expected-note@+1{{#pragma entered here}}
+#pragma clang fp eval_method(source)
+ // expected-error@+1{{'__FLT_EVAL_METHOD__' cannot be expanded inside a scope containing '#pragma clang fp eval_method'}}
+ int i = __FLT_EVAL_METHOD__;
+ }
+}
+
+float G;
+
+int f(float x, float y, float z) {
+ G = x * y + z;
+ return __FLT_EVAL_METHOD__;
+}
+
+int foo(int flag, float x, float y, float z) {
+ if (flag) {
+ // expected-note@+1{{#pragma entered here}}
+#pragma clang fp eval_method(double)
+ G = x + y + z;
+ // expected-error@+1{{'__FLT_EVAL_METHOD__' cannot be expanded inside a scope containing '#pragma clang fp eval_method'}}
+ return __FLT_EVAL_METHOD__;
+ } else {
+ // expected-note@+1{{#pragma entered here}}
+#pragma clang fp eval_method(extended)
+ G = x + y + z;
+ // expected-error@+1{{'__FLT_EVAL_METHOD__' cannot be expanded inside a scope containing '#pragma clang fp eval_method'}}
+ return __FLT_EVAL_METHOD__;
+ }
+}
+
+#if __FLT_EVAL_METHOD__ == 1
+#endif
+#pragma clang fp eval_method(source)
+
+// expected-note@+1{{#pragma entered here}}
+#pragma clang fp eval_method(double)
+// expected-error@+1{{'__FLT_EVAL_METHOD__' cannot be expanded inside a scope containing '#pragma clang fp eval_method'}}
+#if __FLT_EVAL_METHOD__ == 1
+#endif
--- /dev/null
+// RUN: %clang_cc1 -fexperimental-strict-floating-point \
+// RUN: -triple i386-pc-windows -target-cpu pentium4 -target-feature -sse \
+// RUN: -emit-llvm -ffp-eval-method=source -o - -verify=warn %s
+//
+// RUN: %clang_cc1 -fexperimental-strict-floating-point \
+// RUN: -triple i386-pc-windows -target-cpu pentium4 \
+// RUN: -emit-llvm -ffp-eval-method=source -o - -verify=no-warn %s
+
+// no-warn-no-diagnostics
+
+float add1(float a, float b, float c) {
+ return a + b + c;
+} // warn-warning{{Setting the floating point evaluation method to `source` on a target without SSE is not supported.}}
+
+float add2(float a, float b, float c) {
+#pragma clang fp eval_method(source)
+ return a + b + c;
+} // warn-warning{{Setting the floating point evaluation method to `source` on a target without SSE is not supported.}}
--- /dev/null
+// RUN: %clang_cc1 -fexperimental-strict-floating-point \
+// RUN: -triple x86_64-linux-gnu -target-feature -sse -emit-llvm \
+// RUN: -o - -verify=warn %s
+//
+// RUN: %clang_cc1 -fexperimental-strict-floating-point \
+// RUN: -triple x86_64-linux-gnu -emit-llvm -o - -verify=no-warn %s
+
+// no-warn-no-diagnostics
+
+float add2(float a, float b, float c) {
+#pragma clang fp eval_method(source)
+ return a + b + c;
+} // warn-warning{{Setting the floating point evaluation method to `source` on a target without SSE is not supported.}}