Index: clang/include/clang/Basic/DiagnosticASTKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticASTKinds.td +++ clang/include/clang/Basic/DiagnosticASTKinds.td @@ -371,6 +371,15 @@ def warn_fixedpoint_constant_overflow : Warning< "overflow in expression; result is %0 with type %1">, InGroup>; +def warn_fp_infinity : Warning< + "floating-point infinity may be optimized out of computation or comparison">, + InGroup; +def warn_fp_nan: Warning< + "floating-point NaN may be optimized out of computation or comparison">, + InGroup; +def warn_fp_negzero: Warning< + "floating-point -0.0 may be optimized out of computation or comparison">, + InGroup; // This is a temporary diagnostic, and shall be removed once our // implementation is complete, and like the preceding constexpr notes belongs Index: clang/lib/AST/ExprConstant.cpp =================================================================== --- clang/lib/AST/ExprConstant.cpp +++ clang/lib/AST/ExprConstant.cpp @@ -13563,10 +13563,22 @@ }; } // end anonymous namespace -static bool EvaluateFloat(const Expr* E, APFloat& Result, EvalInfo &Info) { +static bool EvaluateFloat(const Expr *E, APFloat &Result, EvalInfo &Info) { assert(!E->isValueDependent()); assert(E->isPRValue() && E->getType()->isRealFloatingType()); - return FloatExprEvaluator(Info, Result).Visit(E); + bool Status = FloatExprEvaluator(Info, Result).Visit(E); + + // Warn if we encounter a floating-point special value that is potentially + // constant-folded by the optimizer. + const FPOptions &FPO = E->getFPFeaturesInEffect(Info.Ctx.getLangOpts()); + if (Result.isInfinity() && FPO.getNoHonorInfs()) + Info.Ctx.getDiagnostics().Report(E->getExprLoc(), diag::warn_fp_infinity); + else if (Result.isNaN() && FPO.getNoHonorNaNs()) + Info.Ctx.getDiagnostics().Report(E->getExprLoc(), diag::warn_fp_nan); + else if (Result.isNegZero() && FPO.getNoSignedZero()) + Info.Ctx.getDiagnostics().Report(E->getExprLoc(), diag::warn_fp_negzero); + + return Status; } static bool TryEvaluateBuiltinNaN(const ASTContext &Context, Index: clang/test/AST/warn-fp-values.c =================================================================== --- /dev/null +++ clang/test/AST/warn-fp-values.c @@ -0,0 +1,50 @@ +// RUN: %clang_cc1 %s -triple x86_64-unknown-unknown -verify -fsyntax-only -ffast-math -Wliteral-range + +#define INFINITY_MATH_MACRO 1.0 / 0.0 + +#define NAN_MATH_MACRO 0.0f / 0.0f + +// Infinity + +double inf_by_macro() { + double d = INFINITY_MATH_MACRO; // expected-warning {{floating-point infinity may be optimized}} + return d; +} + +float inf_by_overflow() { + const float huge_literal = 10e100f; // expected-warning {{magnitude of floating-point constant too large}} {{floating-point infinity may be optimized}} + return huge_literal; +} + +double inf_by_builtin() { + double b = __builtin_inf(); // shows warning if compile continues with -emit-llvm + return b; +} + +float inf_by_builtin_cast() { + float b = __builtin_inf(); // expected-warning {{floating-point infinity may be optimized}} + return b; +} + +// NaN + +float nan_by_macro() { + float f = NAN_MATH_MACRO; // expected-warning {{floating-point NaN may be optimized}} + return f; +} + +double nan_by_builtin() { + double b = __builtin_nan(""); // shows warning if compile continues with -emit-llvm + return b; +} + +float nan_by_builtin_cast() { + float b = __builtin_nan(""); // expected-warning {{floating-point NaN may be optimized}} + return b; +} + +// -0.0 + +double neg_zero_literal() { + return -0.0; // shows warning if compile continues with -emit-llvm +}