Index: clang/include/clang/Basic/DiagnosticCommonKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticCommonKinds.td +++ clang/include/clang/Basic/DiagnosticCommonKinds.td @@ -124,6 +124,9 @@ "'consteval' specifier is incompatible with C++ standards before C++20">, InGroup, DefaultIgnore; +def warn_eval_method_setting_is_meaningless_in_value_unsafe_context: Warning< + "setting the eval method via the `ffp-eval-method` option or the `pragma clang fp eval_method`" + " is meaningless when numeric results of floating-point calculations aren't value-safe.">, InGroup; } let CategoryName = "Nullability Issue" in { Index: clang/lib/Parse/ParseStmt.cpp =================================================================== --- clang/lib/Parse/ParseStmt.cpp +++ clang/lib/Parse/ParseStmt.cpp @@ -1062,6 +1062,13 @@ StmtVector Stmts; + if (Tok.isNot(tok::annot_pragma_fp) && + getLangOpts().getFPEvalMethod() != LangOptions::FEM_UnsetOnCommandLine && + (getLangOpts().ApproxFunc || getLangOpts().AllowFPReassoc || + getLangOpts().AllowRecip)) + Diag(Tok.getLocation(), + diag::warn_eval_method_setting_is_meaningless_in_value_unsafe_context); + // "__label__ X, Y, Z;" is the GNU "Local Label" extension. These are // only allowed at the start of a compound stmt regardless of the language. while (Tok.is(tok::kw___label__)) { Index: clang/lib/Sema/SemaAttr.cpp =================================================================== --- clang/lib/Sema/SemaAttr.cpp +++ clang/lib/Sema/SemaAttr.cpp @@ -486,6 +486,10 @@ NewFPFeatures.setFPEvalMethodOverride(LangOptions::FEM_Extended); break; } + if (getLangOpts().ApproxFunc || getLangOpts().AllowFPReassoc || + getLangOpts().AllowRecip) + Diag(Loc, + diag::warn_eval_method_setting_is_meaningless_in_value_unsafe_context); FpPragmaStack.Act(Loc, PSK_Set, StringRef(), NewFPFeatures); CurFPFeatures = NewFPFeatures.applyOverrides(getLangOpts()); PP.setCurrentFPEvalMethod(Loc, Value); Index: clang/test/Sema/eval-method-with-unsafe-math.c =================================================================== --- /dev/null +++ clang/test/Sema/eval-method-with-unsafe-math.c @@ -0,0 +1,42 @@ +// RUN: %clang_cc1 -fexperimental-strict-floating-point \ +// RUN: -triple x86_64-linux-gnu -ffp-eval-method=source \ +// RUN: -verify %s + +// RUN: %clang_cc1 -fexperimental-strict-floating-point \ +// RUN: -triple x86_64-linux-gnu -fapprox-func -ffp-eval-method=source \ +// RUN: -verify %s -DWARN + +// RUN: %clang_cc1 -fexperimental-strict-floating-point \ +// RUN: -triple x86_64-linux-gnu -freciprocal-math -ffp-eval-method=source \ +// RUN: -verify %s -DWARN + +// RUN: %clang_cc1 -fexperimental-strict-floating-point \ +// RUN: -triple x86_64-linux-gnu -mreassociate -ffp-eval-method=source \ +// RUN: -verify %s -DWARN + +#ifndef WARN +// expected-no-diagnostics +float f1(float a, float b, float c) { + return a * b + c; +} + +float f2(float a, float b, float c) { +#pragma clang fp eval_method(double) + return a * b + c; +} + +#endif + +#ifdef WARN +float f3(float a, float b, float c) { + // expected-warning@+1{{setting the eval method via the `ffp-eval-method` option or the `pragma clang fp eval_method` is meaningless when numeric results of floating-point calculations aren't value-safe.}} + return a * b + c; +} + +float f4(float a, float b, float c) { + // expected-warning@+1{{setting the eval method via the `ffp-eval-method` option or the `pragma clang fp eval_method` is meaningless when numeric results of floating-point calculations aren't value-safe.}} +#pragma clang fp eval_method(double) + // expected-warning@+1{{setting the eval method via the `ffp-eval-method` option or the `pragma clang fp eval_method` is meaningless when numeric results of floating-point calculations aren't value-safe.}} + return a * b + c; +} +#endif