Skip to content

Commit 342328d

Browse files
authored
[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 (#98018).
1 parent 1db7d2a commit 342328d

File tree

3 files changed

+59
-19
lines changed

3 files changed

+59
-19
lines changed

clang/lib/Sema/SemaChecking.cpp

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8202,20 +8202,47 @@ static bool IsStdFunction(const FunctionDecl *FDecl,
82028202
return true;
82038203
}
82048204

8205+
enum class MathCheck { NaN, Inf };
8206+
static bool IsInfOrNanFunction(StringRef calleeName, MathCheck Check) {
8207+
auto MatchesAny = [&](std::initializer_list<llvm::StringRef> names) {
8208+
return std::any_of(names.begin(), names.end(), [&](llvm::StringRef name) {
8209+
return calleeName == name;
8210+
});
8211+
};
8212+
8213+
switch (Check) {
8214+
case MathCheck::NaN:
8215+
return MatchesAny({"__builtin_nan", "__builtin_nanf", "__builtin_nanl",
8216+
"__builtin_nanf16", "__builtin_nanf128"});
8217+
case MathCheck::Inf:
8218+
return MatchesAny({"__builtin_inf", "__builtin_inff", "__builtin_infl",
8219+
"__builtin_inff16", "__builtin_inff128"});
8220+
default:
8221+
return false;
8222+
}
8223+
}
8224+
82058225
void Sema::CheckInfNaNFunction(const CallExpr *Call,
82068226
const FunctionDecl *FDecl) {
82078227
FPOptions FPO = Call->getFPFeaturesInEffect(getLangOpts());
8208-
if ((IsStdFunction(FDecl, "isnan") || IsStdFunction(FDecl, "isunordered") ||
8209-
(Call->getBuiltinCallee() == Builtin::BI__builtin_nanf)) &&
8210-
FPO.getNoHonorNaNs())
8228+
bool HasIdentifier = FDecl->getIdentifier() != nullptr;
8229+
bool IsNaNOrIsUnordered =
8230+
IsStdFunction(FDecl, "isnan") || IsStdFunction(FDecl, "isunordered");
8231+
bool IsSpecialNaN =
8232+
HasIdentifier && IsInfOrNanFunction(FDecl->getName(), MathCheck::NaN);
8233+
if ((IsNaNOrIsUnordered || IsSpecialNaN) && FPO.getNoHonorNaNs()) {
82118234
Diag(Call->getBeginLoc(), diag::warn_fp_nan_inf_when_disabled)
82128235
<< 1 << 0 << Call->getSourceRange();
8213-
else if ((IsStdFunction(FDecl, "isinf") ||
8214-
(IsStdFunction(FDecl, "isfinite") ||
8215-
(FDecl->getIdentifier() && FDecl->getName() == "infinity"))) &&
8216-
FPO.getNoHonorInfs())
8217-
Diag(Call->getBeginLoc(), diag::warn_fp_nan_inf_when_disabled)
8218-
<< 0 << 0 << Call->getSourceRange();
8236+
} else {
8237+
bool IsInfOrIsFinite =
8238+
IsStdFunction(FDecl, "isinf") || IsStdFunction(FDecl, "isfinite");
8239+
bool IsInfinityOrIsSpecialInf =
8240+
HasIdentifier && ((FDecl->getName() == "infinity") ||
8241+
IsInfOrNanFunction(FDecl->getName(), MathCheck::Inf));
8242+
if ((IsInfOrIsFinite || IsInfinityOrIsSpecialInf) && FPO.getNoHonorInfs())
8243+
Diag(Call->getBeginLoc(), diag::warn_fp_nan_inf_when_disabled)
8244+
<< 0 << 0 << Call->getSourceRange();
8245+
}
82198246
}
82208247

82218248
void Sema::CheckAbsoluteValueFunction(const CallExpr *Call,

clang/test/Headers/float.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -223,8 +223,9 @@
223223
#ifndef NAN
224224
#error "Mandatory macro NAN is missing."
225225
#endif
226-
// FIXME: the NAN diagnostic should only be issued once, not twice.
227-
_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}}
226+
// FIXME: the NAN and INF diagnostics should only be issued once, not twice.
227+
_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}} \
228+
finite-warning {{use of infinity is undefined behavior due to the currently enabled floating-point options}}
228229
_Static_assert(_Generic(NAN, float : 1, default : 0), ""); // finite-warning {{use of NaN is undefined behavior due to the currently enabled floating-point options}} \
229230
finite-warning {{use of NaN via a macro is undefined behavior due to the currently enabled floating-point options}}
230231

clang/test/Sema/warn-infinity-nan-disabled-lnx.cpp

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -87,11 +87,15 @@ class numeric_limits<double> {
8787

8888
int compareit(float a, float b) {
8989
volatile int i, j, k, l, m, n, o, p;
90-
// no-inf-no-nan-warning@+2 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}}
90+
// no-inf-no-nan-warning@+4 {{use of infinity is undefined behavior due to the currently enabled floating-point options}}
91+
// no-inf-no-nan-warning@+3 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}}
92+
// no-inf-warning@+2 {{use of infinity is undefined behavior due to the currently enabled floating-point options}}
9193
// no-inf-warning@+1 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}}
9294
i = a == INFINITY;
9395

94-
// no-inf-no-nan-warning@+2 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}}
96+
// no-inf-no-nan-warning@+4 {{use of infinity is undefined behavior due to the currently enabled floating-point options}}
97+
// no-inf-no-nan-warning@+3 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}}
98+
// no-inf-warning@+2 {{use of infinity is undefined behavior due to the currently enabled floating-point options}}
9599
// no-inf-warning@+1 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}}
96100
j = INFINITY == a;
97101

@@ -107,11 +111,15 @@ int compareit(float a, float b) {
107111
// no-nan-warning@+1 {{use of NaN via a macro is undefined behavior due to the currently enabled floating-point options}}
108112
j = NAN == a;
109113

110-
// no-inf-no-nan-warning@+2 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}}
114+
// no-inf-no-nan-warning@+4 {{use of infinity is undefined behavior due to the currently enabled floating-point options}}
115+
// no-inf-no-nan-warning@+3 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}}
116+
// no-inf-warning@+2 {{use of infinity is undefined behavior due to the currently enabled floating-point options}}
111117
// no-inf-warning@+1 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}}
112118
j = INFINITY <= a;
113119

114-
// no-inf-no-nan-warning@+2 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}}
120+
// no-inf-no-nan-warning@+4 {{use of infinity is undefined behavior due to the currently enabled floating-point options}}
121+
// no-inf-no-nan-warning@+3 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}}
122+
// no-inf-warning@+2 {{use of infinity is undefined behavior due to the currently enabled floating-point options}}
115123
// no-inf-warning@+1 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}}
116124
j = INFINITY < a;
117125

@@ -192,7 +200,9 @@ int compareit(float a, float b) {
192200
// no-nan-warning@+1 {{use of NaN is undefined behavior due to the currently enabled floating-point options}}
193201
j = isunorderedf(a, NAN);
194202

195-
// no-inf-no-nan-warning@+2 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}}
203+
// no-inf-no-nan-warning@+4 {{use of infinity is undefined behavior due to the currently enabled floating-point options}}
204+
// no-inf-no-nan-warning@+3 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}}
205+
// no-inf-warning@+2 {{use of infinity is undefined behavior due to the currently enabled floating-point options}}
196206
// no-inf-warning@+1 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}}
197207
j = isunorderedf(a, INFINITY);
198208

@@ -204,9 +214,11 @@ int compareit(float a, float b) {
204214
// no-nan-warning@+1 {{use of NaN is undefined behavior due to the currently enabled floating-point options}}
205215
i = std::isunordered(a, NAN);
206216

207-
// no-inf-no-nan-warning@+4 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}}
208-
// no-inf-no-nan-warning@+3 {{use of NaN is undefined behavior due to the currently enabled floating-point options}}
209-
// no-inf-warning@+2 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}}
217+
// no-inf-no-nan-warning@+6 {{use of infinity is undefined behavior due to the currently enabled floating-point options}}
218+
// no-inf-no-nan-warning@+5 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}}
219+
// no-inf-no-nan-warning@+4 {{use of NaN is undefined behavior due to the currently enabled floating-point options}}
220+
// no-inf-warning@+3 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}}
221+
// no-inf-warning@+2 {{use of infinity is undefined behavior due to the currently enabled floating-point options}}
210222
// no-nan-warning@+1 {{use of NaN is undefined behavior due to the currently enabled floating-point options}}
211223
i = std::isunordered(a, INFINITY);
212224

0 commit comments

Comments
 (0)