Author: Zahira Ammarguellat Date: 2024-07-25T12:32:34-04:00 New Revision: 342328db6b2a69cf59c01a6115b1baab925c0736
URL: https://github.com/llvm/llvm-project/commit/342328db6b2a69cf59c01a6115b1baab925c0736 DIFF: https://github.com/llvm/llvm-project/commit/342328db6b2a69cf59c01a6115b1baab925c0736.diff LOG: [CLANG] Emit warning in finite math mode when INF and NAN are used. (#99672) In finite math mode when special math builtins `__builtin_inf` and `__builtin_nan` are used a warning is emitted when the builtin is expanded and at call point. This warning at call point was missing for` __builtin_inf` and this patch fixes the issue (https://github.com/llvm/llvm-project/issues/98018). Added: Modified: clang/lib/Sema/SemaChecking.cpp clang/test/Headers/float.c clang/test/Sema/warn-infinity-nan-disabled-lnx.cpp Removed: ################################################################################ diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index cf1196ad23c21..99a1471d9d06d 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -8202,20 +8202,47 @@ static bool IsStdFunction(const FunctionDecl *FDecl, return true; } +enum class MathCheck { NaN, Inf }; +static bool IsInfOrNanFunction(StringRef calleeName, MathCheck Check) { + auto MatchesAny = [&](std::initializer_list<llvm::StringRef> names) { + return std::any_of(names.begin(), names.end(), [&](llvm::StringRef name) { + return calleeName == name; + }); + }; + + switch (Check) { + case MathCheck::NaN: + return MatchesAny({"__builtin_nan", "__builtin_nanf", "__builtin_nanl", + "__builtin_nanf16", "__builtin_nanf128"}); + case MathCheck::Inf: + return MatchesAny({"__builtin_inf", "__builtin_inff", "__builtin_infl", + "__builtin_inff16", "__builtin_inff128"}); + default: + return false; + } +} + void Sema::CheckInfNaNFunction(const CallExpr *Call, const FunctionDecl *FDecl) { FPOptions FPO = Call->getFPFeaturesInEffect(getLangOpts()); - if ((IsStdFunction(FDecl, "isnan") || IsStdFunction(FDecl, "isunordered") || - (Call->getBuiltinCallee() == Builtin::BI__builtin_nanf)) && - FPO.getNoHonorNaNs()) + bool HasIdentifier = FDecl->getIdentifier() != nullptr; + bool IsNaNOrIsUnordered = + IsStdFunction(FDecl, "isnan") || IsStdFunction(FDecl, "isunordered"); + bool IsSpecialNaN = + HasIdentifier && IsInfOrNanFunction(FDecl->getName(), MathCheck::NaN); + if ((IsNaNOrIsUnordered || IsSpecialNaN) && FPO.getNoHonorNaNs()) { Diag(Call->getBeginLoc(), diag::warn_fp_nan_inf_when_disabled) << 1 << 0 << Call->getSourceRange(); - else if ((IsStdFunction(FDecl, "isinf") || - (IsStdFunction(FDecl, "isfinite") || - (FDecl->getIdentifier() && FDecl->getName() == "infinity"))) && - FPO.getNoHonorInfs()) - Diag(Call->getBeginLoc(), diag::warn_fp_nan_inf_when_disabled) - << 0 << 0 << Call->getSourceRange(); + } else { + bool IsInfOrIsFinite = + IsStdFunction(FDecl, "isinf") || IsStdFunction(FDecl, "isfinite"); + bool IsInfinityOrIsSpecialInf = + HasIdentifier && ((FDecl->getName() == "infinity") || + IsInfOrNanFunction(FDecl->getName(), MathCheck::Inf)); + if ((IsInfOrIsFinite || IsInfinityOrIsSpecialInf) && FPO.getNoHonorInfs()) + Diag(Call->getBeginLoc(), diag::warn_fp_nan_inf_when_disabled) + << 0 << 0 << Call->getSourceRange(); + } } void Sema::CheckAbsoluteValueFunction(const CallExpr *Call, diff --git a/clang/test/Headers/float.c b/clang/test/Headers/float.c index d524d0e53f3fd..051c50561c252 100644 --- a/clang/test/Headers/float.c +++ b/clang/test/Headers/float.c @@ -223,8 +223,9 @@ #ifndef NAN #error "Mandatory macro NAN is missing." #endif - // FIXME: the NAN diagnostic should only be issued once, not twice. - _Static_assert(_Generic(INFINITY, float : 1, default : 0), ""); // finite-warning {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}} +// FIXME: the NAN and INF diagnostics should only be issued once, not twice. + _Static_assert(_Generic(INFINITY, float : 1, default : 0), ""); // finite-warning {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}} \ + finite-warning {{use of infinity is undefined behavior due to the currently enabled floating-point options}} _Static_assert(_Generic(NAN, float : 1, default : 0), ""); // finite-warning {{use of NaN is undefined behavior due to the currently enabled floating-point options}} \ finite-warning {{use of NaN via a macro is undefined behavior due to the currently enabled floating-point options}} diff --git a/clang/test/Sema/warn-infinity-nan-disabled-lnx.cpp b/clang/test/Sema/warn-infinity-nan-disabled-lnx.cpp index 03a432e05851d..d18aaad0e6925 100644 --- a/clang/test/Sema/warn-infinity-nan-disabled-lnx.cpp +++ b/clang/test/Sema/warn-infinity-nan-disabled-lnx.cpp @@ -87,11 +87,15 @@ class numeric_limits<double> { int compareit(float a, float b) { volatile int i, j, k, l, m, n, o, p; -// no-inf-no-nan-warning@+2 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}} +// no-inf-no-nan-warning@+4 {{use of infinity is undefined behavior due to the currently enabled floating-point options}} +// no-inf-no-nan-warning@+3 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}} +// no-inf-warning@+2 {{use of infinity is undefined behavior due to the currently enabled floating-point options}} // no-inf-warning@+1 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}} i = a == INFINITY; -// no-inf-no-nan-warning@+2 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}} +// no-inf-no-nan-warning@+4 {{use of infinity is undefined behavior due to the currently enabled floating-point options}} +// no-inf-no-nan-warning@+3 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}} +// no-inf-warning@+2 {{use of infinity is undefined behavior due to the currently enabled floating-point options}} // no-inf-warning@+1 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}} j = INFINITY == a; @@ -107,11 +111,15 @@ int compareit(float a, float b) { // no-nan-warning@+1 {{use of NaN via a macro is undefined behavior due to the currently enabled floating-point options}} j = NAN == a; -// no-inf-no-nan-warning@+2 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}} +// no-inf-no-nan-warning@+4 {{use of infinity is undefined behavior due to the currently enabled floating-point options}} +// no-inf-no-nan-warning@+3 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}} +// no-inf-warning@+2 {{use of infinity is undefined behavior due to the currently enabled floating-point options}} // no-inf-warning@+1 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}} j = INFINITY <= a; -// no-inf-no-nan-warning@+2 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}} +// no-inf-no-nan-warning@+4 {{use of infinity is undefined behavior due to the currently enabled floating-point options}} +// no-inf-no-nan-warning@+3 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}} +// no-inf-warning@+2 {{use of infinity is undefined behavior due to the currently enabled floating-point options}} // no-inf-warning@+1 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}} j = INFINITY < a; @@ -192,7 +200,9 @@ int compareit(float a, float b) { // no-nan-warning@+1 {{use of NaN is undefined behavior due to the currently enabled floating-point options}} j = isunorderedf(a, NAN); -// no-inf-no-nan-warning@+2 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}} +// no-inf-no-nan-warning@+4 {{use of infinity is undefined behavior due to the currently enabled floating-point options}} +// no-inf-no-nan-warning@+3 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}} +// no-inf-warning@+2 {{use of infinity is undefined behavior due to the currently enabled floating-point options}} // no-inf-warning@+1 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}} j = isunorderedf(a, INFINITY); @@ -204,9 +214,11 @@ int compareit(float a, float b) { // no-nan-warning@+1 {{use of NaN is undefined behavior due to the currently enabled floating-point options}} i = std::isunordered(a, NAN); -// no-inf-no-nan-warning@+4 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}} -// no-inf-no-nan-warning@+3 {{use of NaN is undefined behavior due to the currently enabled floating-point options}} -// no-inf-warning@+2 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}} +// no-inf-no-nan-warning@+6 {{use of infinity is undefined behavior due to the currently enabled floating-point options}} +// no-inf-no-nan-warning@+5 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}} +// no-inf-no-nan-warning@+4 {{use of NaN is undefined behavior due to the currently enabled floating-point options}} +// no-inf-warning@+3 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}} +// no-inf-warning@+2 {{use of infinity is undefined behavior due to the currently enabled floating-point options}} // no-nan-warning@+1 {{use of NaN is undefined behavior due to the currently enabled floating-point options}} i = std::isunordered(a, INFINITY); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits