[clang] 342328d - [CLANG] Emit warning in finite math mode when INF and NAN are used. (#99672)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Jul 25 09:32:37 PDT 2024
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 at +2 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}}
+// no-inf-no-nan-warning at +4 {{use of infinity is undefined behavior due to the currently enabled floating-point options}}
+// no-inf-no-nan-warning at +3 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}}
+// no-inf-warning at +2 {{use of infinity is undefined behavior due to the currently enabled floating-point options}}
// no-inf-warning at +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 at +2 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}}
+// no-inf-no-nan-warning at +4 {{use of infinity is undefined behavior due to the currently enabled floating-point options}}
+// no-inf-no-nan-warning at +3 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}}
+// no-inf-warning at +2 {{use of infinity is undefined behavior due to the currently enabled floating-point options}}
// no-inf-warning at +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 at +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 at +2 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}}
+// no-inf-no-nan-warning at +4 {{use of infinity is undefined behavior due to the currently enabled floating-point options}}
+// no-inf-no-nan-warning at +3 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}}
+// no-inf-warning at +2 {{use of infinity is undefined behavior due to the currently enabled floating-point options}}
// no-inf-warning at +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 at +2 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}}
+// no-inf-no-nan-warning at +4 {{use of infinity is undefined behavior due to the currently enabled floating-point options}}
+// no-inf-no-nan-warning at +3 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}}
+// no-inf-warning at +2 {{use of infinity is undefined behavior due to the currently enabled floating-point options}}
// no-inf-warning at +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 at +1 {{use of NaN is undefined behavior due to the currently enabled floating-point options}}
j = isunorderedf(a, NAN);
-// no-inf-no-nan-warning at +2 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}}
+// no-inf-no-nan-warning at +4 {{use of infinity is undefined behavior due to the currently enabled floating-point options}}
+// no-inf-no-nan-warning at +3 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}}
+// no-inf-warning at +2 {{use of infinity is undefined behavior due to the currently enabled floating-point options}}
// no-inf-warning at +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 at +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 at +4 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}}
-// no-inf-no-nan-warning at +3 {{use of NaN is undefined behavior due to the currently enabled floating-point options}}
-// no-inf-warning at +2 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}}
+// no-inf-no-nan-warning at +6 {{use of infinity is undefined behavior due to the currently enabled floating-point options}}
+// no-inf-no-nan-warning at +5 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}}
+// no-inf-no-nan-warning at +4 {{use of NaN is undefined behavior due to the currently enabled floating-point options}}
+// no-inf-warning at +3 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}}
+// no-inf-warning at +2 {{use of infinity is undefined behavior due to the currently enabled floating-point options}}
// no-nan-warning at +1 {{use of NaN is undefined behavior due to the currently enabled floating-point options}}
i = std::isunordered(a, INFINITY);
More information about the cfe-commits
mailing list