[clang] [CLANG] Add warning when INF or NAN are used in a binary operation or as function argument in fast math mode. (PR #76873)
Zahira Ammarguellat via cfe-commits
cfe-commits at lists.llvm.org
Sat Jan 13 08:23:46 PST 2024
https://github.com/zahiraam updated https://github.com/llvm/llvm-project/pull/76873
>From 7dbaf037b6b2196cee7c0c837e0a89ce3c2556ed Mon Sep 17 00:00:00 2001
From: Ammarguellat <zahira.ammarguellat at intel.com>
Date: Wed, 3 Jan 2024 14:37:17 -0800
Subject: [PATCH 1/5] [CLANG] Add warning when comparing to INF or NAN in fast
math mode.
---
.../clang/Basic/DiagnosticSemaKinds.td | 3 +
clang/include/clang/Sema/Sema.h | 4 +
clang/lib/Sema/SemaChecking.cpp | 65 +++++++
clang/lib/Sema/SemaExpr.cpp | 7 +-
clang/test/Sema/warn-fp-fast-compare.cpp | 171 ++++++++++++++++++
5 files changed, 248 insertions(+), 2 deletions(-)
create mode 100644 clang/test/Sema/warn-fp-fast-compare.cpp
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index e54f969c19039d..1b75ae8f678b68 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -6771,6 +6771,9 @@ def warn_pointer_sub_null_ptr : Warning<
def warn_floatingpoint_eq : Warning<
"comparing floating point with == or != is unsafe">,
InGroup<DiagGroup<"float-equal">>, DefaultIgnore;
+def warn_fast_floatingpoint_eq : Warning<
+ "explicit comparison with %0 in fast floating point mode">,
+ InGroup<TautologicalConstantCompare>;
def err_setting_eval_method_used_in_unsafe_context : Error <
"%select{'#pragma clang fp eval_method'|option 'ffp-eval-method'}0 cannot be used with "
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 5e3b57ea33220b..6125e7ebb6b48a 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -13998,6 +13998,8 @@ class Sema final {
SourceRange range,
llvm::SmallBitVector &CheckedVarArgs);
+ void CheckInfNaNFunction(const CallExpr *Call, const FunctionDecl *FDecl);
+
void CheckAbsoluteValueFunction(const CallExpr *Call,
const FunctionDecl *FDecl);
@@ -14024,6 +14026,8 @@ class Sema final {
public:
void CheckFloatComparison(SourceLocation Loc, Expr *LHS, Expr *RHS,
BinaryOperatorKind Opcode);
+ void CheckInfNaNFloatComparison(SourceLocation Loc, Expr *LHS, Expr *RHS,
+ BinaryOperatorKind Opcode);
private:
void CheckImplicitConversions(Expr *E, SourceLocation CC = SourceLocation());
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 3168d38dd66c36..2e9f61f40b795b 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -2169,6 +2169,7 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
ICEArguments &= ~(1 << ArgNo);
}
+ FPOptions FPO;
switch (BuiltinID) {
case Builtin::BI__builtin___CFStringMakeConstantString:
// CFStringMakeConstantString is currently not implemented for GOFF (i.e.,
@@ -2245,6 +2246,11 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
case Builtin::BI__builtin_islessequal:
case Builtin::BI__builtin_islessgreater:
case Builtin::BI__builtin_isunordered:
+ if (BuiltinID == Builtin::BI__builtin_isunordered) {
+ if (TheCall->getFPFeaturesInEffect(getLangOpts()).getNoHonorNaNs())
+ Diag(TheCall->getBeginLoc(), diag::warn_fast_floatingpoint_eq)
+ << "NaN" << TheCall->getSourceRange();
+ }
if (SemaBuiltinUnorderedCompare(TheCall))
return ExprError();
break;
@@ -2267,6 +2273,16 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
case Builtin::BI__builtin_signbit:
case Builtin::BI__builtin_signbitf:
case Builtin::BI__builtin_signbitl:
+ FPO = TheCall->getFPFeaturesInEffect(getLangOpts());
+ if (FPO.getNoHonorInfs() && (BuiltinID == Builtin::BI__builtin_isfinite ||
+ BuiltinID == Builtin::BI__builtin_isinf ||
+ BuiltinID == Builtin::BI__builtin_isinf_sign))
+ Diag(TheCall->getBeginLoc(), diag::warn_fast_floatingpoint_eq)
+ << "infinity" << TheCall->getSourceRange();
+ if (FPO.getNoHonorNaNs() && (BuiltinID == Builtin::BI__builtin_isnan ||
+ BuiltinID == Builtin::BI__builtin_isunordered))
+ Diag(TheCall->getBeginLoc(), diag::warn_fast_floatingpoint_eq)
+ << "NaN" << TheCall->getSourceRange();
if (SemaBuiltinFPClassification(TheCall, 1))
return ExprError();
break;
@@ -7621,6 +7637,7 @@ bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall,
CheckAbsoluteValueFunction(TheCall, FDecl);
CheckMaxUnsignedZero(TheCall, FDecl);
+ CheckInfNaNFunction(TheCall, FDecl);
if (getLangOpts().ObjC)
DiagnoseCStringFormatDirectiveInCFAPI(*this, FDecl, Args, NumArgs);
@@ -12878,6 +12895,23 @@ static bool IsStdFunction(const FunctionDecl *FDecl,
return true;
}
+void Sema::CheckInfNaNFunction(const CallExpr *Call,
+ const FunctionDecl *FDecl) {
+ if (Call->getNumArgs() != 1 && Call->getNumArgs() != 2)
+ return;
+
+ FPOptions FPO = Call->getFPFeaturesInEffect(getLangOpts());
+ if ((IsStdFunction(FDecl, "isnan") || IsStdFunction(FDecl, "isunordered")) &&
+ FPO.getNoHonorNaNs())
+ Diag(Call->getBeginLoc(), diag::warn_fast_floatingpoint_eq)
+ << "NaN" << Call->getSourceRange();
+ else if ((IsStdFunction(FDecl, "isinf") ||
+ (IsStdFunction(FDecl, "isfinite"))) &&
+ FPO.getNoHonorInfs())
+ Diag(Call->getBeginLoc(), diag::warn_fast_floatingpoint_eq)
+ << "infinity" << Call->getSourceRange();
+}
+
// Warn when using the wrong abs() function.
void Sema::CheckAbsoluteValueFunction(const CallExpr *Call,
const FunctionDecl *FDecl) {
@@ -13846,6 +13880,37 @@ Sema::CheckReturnValExpr(Expr *RetValExp, QualType lhsType,
CheckPPCMMAType(RetValExp->getType(), ReturnLoc);
}
+/// Diagnose comparison to NAN or INFINITY in fast math modes.
+/// The comparison to NaN or INFINITY is always false in
+/// fast modes: float evaluation will not result in inf or nan.
+void Sema::CheckInfNaNFloatComparison(SourceLocation Loc, Expr *LHS, Expr *RHS,
+ BinaryOperatorKind Opcode) {
+ Expr *LeftExprSansParen = LHS->IgnoreParenImpCasts();
+ Expr *RightExprSansParen = RHS->IgnoreParenImpCasts();
+
+ FPOptions FPO = LHS->getFPFeaturesInEffect(getLangOpts());
+ bool NoHonorNaNs = FPO.getNoHonorNaNs();
+ bool NoHonorInfs = FPO.getNoHonorInfs();
+ llvm::APFloat Value(0.0);
+ bool IsConstant;
+ IsConstant = !LHS->isValueDependent() &&
+ LeftExprSansParen->EvaluateAsFloat(Value, Context,
+ Expr::SE_AllowSideEffects);
+ if (IsConstant &&
+ ((NoHonorNaNs && Value.isNaN()) || (NoHonorInfs && Value.isInfinity())))
+ Diag(Loc, diag::warn_fast_floatingpoint_eq)
+ << (Value.isNaN() ? "NaN" : "infinity") << LHS->getSourceRange()
+ << RHS->getSourceRange();
+ IsConstant = !RHS->isValueDependent() &&
+ RightExprSansParen->EvaluateAsFloat(Value, Context,
+ Expr::SE_AllowSideEffects);
+ if (IsConstant &&
+ ((NoHonorNaNs && Value.isNaN()) || (NoHonorInfs && Value.isInfinity())))
+ Diag(Loc, diag::warn_fast_floatingpoint_eq)
+ << (Value.isNaN() ? "NaN" : "infinity") << LHS->getSourceRange()
+ << RHS->getSourceRange();
+}
+
/// Check for comparisons of floating-point values using == and !=. Issue a
/// warning if the comparison is not likely to do what the programmer intended.
void Sema::CheckFloatComparison(SourceLocation Loc, Expr *LHS, Expr *RHS,
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 960f513d1111b2..005ddfa882195d 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -13044,9 +13044,12 @@ static QualType checkArithmeticOrEnumeralCompare(Sema &S, ExprResult &LHS,
if (Type->isAnyComplexType() && BinaryOperator::isRelationalOp(Opc))
return S.InvalidOperands(Loc, LHS, RHS);
- // Check for comparisons of floating point operands using != and ==.
- if (Type->hasFloatingRepresentation())
+ if (Type->hasFloatingRepresentation()) {
+ // Check for comparisons to NAN or INFINITY in fast math mode.
+ S.CheckInfNaNFloatComparison(Loc, LHS.get(), RHS.get(), Opc);
+ // Check for comparisons of floating point operands using != and ==.
S.CheckFloatComparison(Loc, LHS.get(), RHS.get(), Opc);
+ }
// The result of comparisons is 'bool' in C++, 'int' in C.
return S.Context.getLogicalOperationType();
diff --git a/clang/test/Sema/warn-fp-fast-compare.cpp b/clang/test/Sema/warn-fp-fast-compare.cpp
new file mode 100644
index 00000000000000..07eeaf0eeab125
--- /dev/null
+++ b/clang/test/Sema/warn-fp-fast-compare.cpp
@@ -0,0 +1,171 @@
+// RUN: %clang_cc1 -x c++ -verify -triple powerpc64le-unknown-unknown %s \
+// RUN: -menable-no-infs -menable-no-nans -DFAST=1
+
+// RUN: %clang_cc1 -x c++ -verify -triple powerpc64le-unknown-unknown %s \
+// RUN: -DNOFAST=1
+
+// RUN: %clang_cc1 -x c++ -verify -triple powerpc64le-unknown-unknown %s \
+// RUN: -menable-no-infs -DNO_INFS=1
+
+// RUN: %clang_cc1 -x c++ -verify -triple powerpc64le-unknown-unknown %s \
+// RUN: -menable-no-nans -DNO_NANS=1
+
+int isunorderedf (float x, float y);
+#if NOFAST
+// expected-no-diagnostics
+#endif
+extern "C++" {
+namespace std __attribute__((__visibility__("default"))) {
+ bool
+ isinf(float __x);
+ bool
+ isinf(double __x);
+ bool
+ isinf(long double __x);
+ bool
+ isnan(float __x);
+ bool
+ isnan(double __x);
+ bool
+ isnan(long double __x);
+bool
+ isfinite(float __x);
+ bool
+ isfinite(double __x);
+ bool
+ isfinte(long double __x);
+ bool
+ isunordered(float __x, float __y);
+ bool
+ isunordered(double __x, double __y);
+ bool
+ isunordered(long double __x, long double __y);
+} // namespace )
+}
+#define NAN (__builtin_nanf(""))
+#define INFINITY (__builtin_inff())
+
+int compareit(float a, float b) {
+ volatile int i, j, k, l, m, n, o, p;
+#if FAST
+// expected-warning at +5 {{explicit comparison with infinity in fast floating point mode}}
+#endif
+#if NO_INFS
+// expected-warning at +2 {{explicit comparison with infinity in fast floating point mode}}
+#endif
+ i = a == INFINITY;
+#if FAST
+// expected-warning at +5 {{explicit comparison with infinity in fast floating point mode}}
+#endif
+#if NO_INFS
+// expected-warning at +2 {{explicit comparison with infinity in fast floating point mode}}
+#endif
+ j = INFINITY == a;
+#if FAST
+// expected-warning at +5 {{explicit comparison with NaN in fast floating point mode}}
+#endif
+#if NO_NANS
+// expected-warning at +2 {{explicit comparison with NaN in fast floating point mode}}
+#endif
+ i = a == NAN;
+#if FAST
+// expected-warning at +5 {{explicit comparison with NaN in fast floating point mode}}
+#endif
+#if NO_NANS
+// expected-warning at +2 {{explicit comparison with NaN in fast floating point mode}}
+#endif
+ j = NAN == a;
+#if FAST
+// expected-warning at +5 {{explicit comparison with infinity in fast floating point mode}}
+#endif
+#if NO_INFS
+// expected-warning at +2 {{explicit comparison with infinity in fast floating point mode}}
+#endif
+ j = INFINITY <= a;
+#if FAST
+// expected-warning at +5 {{explicit comparison with infinity in fast floating point mode}}
+#endif
+#if NO_INFS
+// expected-warning at +2 {{explicit comparison with infinity in fast floating point mode}}
+#endif
+ j = INFINITY < a;
+#if FAST
+// expected-warning at +5 {{explicit comparison with NaN in fast floating point mode}}
+#endif
+#if NO_NANS
+// expected-warning at +2 {{explicit comparison with NaN in fast floating point mode}}
+#endif
+ j = a > NAN;
+#if FAST
+// expected-warning at +5 {{explicit comparison with NaN in fast floating point mode}}
+#endif
+#if NO_NANS
+// expected-warning at +2 {{explicit comparison with NaN in fast floating point mode}}
+#endif
+ j = a >= NAN;
+#if FAST
+// expected-warning at +5 {{explicit comparison with infinity in fast floating point mode}}
+#endif
+#if NO_INFS
+// expected-warning at +2 {{explicit comparison with infinity in fast floating point mode}}
+#endif
+k = std::isinf(a);
+#if FAST
+// expected-warning at +5 {{explicit comparison with NaN in fast floating point mode}}
+#endif
+#if NO_NANS
+// expected-warning at +2 {{explicit comparison with NaN in fast floating point mode}}
+#endif
+ l = std::isnan(a);
+#if FAST
+// expected-warning at +5 {{explicit comparison with infinity in fast floating point mode}}
+#endif
+#if NO_INFS
+//expected-warning at +2 {{explicit comparison with infinity in fast floating point mode}}
+#endif
+ o = std::isfinite(a);
+#if FAST
+// expected-warning at +5 {{explicit comparison with infinity in fast floating point mode}}
+#endif
+#if NO_INFS
+// expected-warning at +2 {{explicit comparison with infinity in fast floating point mode}}
+#endif
+ m = __builtin_isinf(a);
+#if FAST
+// expected-warning at +5 {{explicit comparison with NaN in fast floating point mode}}
+#endif
+#if NO_NANS
+// expected-warning at +2 {{explicit comparison with NaN in fast floating point mode}}
+#endif
+ n = __builtin_isnan(a);
+#if FAST
+//expected-warning at +5 {{explicit comparison with infinity in fast floating point mode}}
+#endif
+#if NO_INFS
+//expected-warning at +2 {{explicit comparison with infinity in fast floating point mode}}
+#endif
+ p = __builtin_isfinite(a);
+
+ // These should NOT warn, since they are not comparing with NaN or infinity.
+ j = a > 1.1;
+ j = b < 1.1;
+ j = a >= 1.1;
+ j = b <= 1.1;
+ j = isunorderedf(a, NAN);
+ j = isunorderedf(a, INFINITY);
+#if FAST
+// expected-warning at +5 {{explicit comparison with NaN in fast floating point mode}}
+#endif
+#if NO_NANS
+// expected-warning at +2 {{explicit comparison with NaN in fast floating point mode}}
+#endif
+ i = std::isunordered(a, NAN);
+#if FAST
+// expected-warning at +5 {{explicit comparison with NaN in fast floating point mode}}
+#endif
+#if NO_NANS
+// expected-warning at +2 {{explicit comparison with NaN in fast floating point mode}}
+#endif
+ i = std::isunordered(a, INFINITY);
+ return 0;
+}
>From f4aa37980d861617719b3f027f69e652c0502515 Mon Sep 17 00:00:00 2001
From: Ammarguellat <zahira.ammarguellat at intel.com>
Date: Fri, 5 Jan 2024 13:54:42 -0800
Subject: [PATCH 2/5] Addressed review comments.
---
.../clang/Basic/DiagnosticSemaKinds.td | 2 +-
clang/include/clang/Sema/Sema.h | 5 +-
clang/lib/Sema/SemaChecking.cpp | 73 ++++-----
clang/test/Sema/warn-fp-fast-compare.cpp | 138 ++++++++++++++----
4 files changed, 148 insertions(+), 70 deletions(-)
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 1b75ae8f678b68..d19be567a1bf66 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -6772,7 +6772,7 @@ def warn_floatingpoint_eq : Warning<
"comparing floating point with == or != is unsafe">,
InGroup<DiagGroup<"float-equal">>, DefaultIgnore;
def warn_fast_floatingpoint_eq : Warning<
- "explicit comparison with %0 in fast floating point mode">,
+ "explicit comparison with %0 when the program is assumed to not use or produce %0">,
InGroup<TautologicalConstantCompare>;
def err_setting_eval_method_used_in_unsafe_context : Error <
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 6125e7ebb6b48a..b19ce6312e83bc 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -13893,8 +13893,9 @@ class Sema final {
bool SemaBuiltinVAStart(unsigned BuiltinID, CallExpr *TheCall);
bool SemaBuiltinVAStartARMMicrosoft(CallExpr *Call);
- bool SemaBuiltinUnorderedCompare(CallExpr *TheCall);
- bool SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs);
+ bool SemaBuiltinUnorderedCompare(CallExpr *TheCall, unsigned BuiltinID);
+ bool SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs,
+ unsigned BuiltinID);
bool SemaBuiltinComplex(CallExpr *TheCall);
bool SemaBuiltinVSX(CallExpr *TheCall);
bool SemaBuiltinOSLogFormat(CallExpr *TheCall);
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 2e9f61f40b795b..2c4d628ab160d2 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -2246,20 +2246,15 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
case Builtin::BI__builtin_islessequal:
case Builtin::BI__builtin_islessgreater:
case Builtin::BI__builtin_isunordered:
- if (BuiltinID == Builtin::BI__builtin_isunordered) {
- if (TheCall->getFPFeaturesInEffect(getLangOpts()).getNoHonorNaNs())
- Diag(TheCall->getBeginLoc(), diag::warn_fast_floatingpoint_eq)
- << "NaN" << TheCall->getSourceRange();
- }
- if (SemaBuiltinUnorderedCompare(TheCall))
+ if (SemaBuiltinUnorderedCompare(TheCall, BuiltinID))
return ExprError();
break;
case Builtin::BI__builtin_fpclassify:
- if (SemaBuiltinFPClassification(TheCall, 6))
+ if (SemaBuiltinFPClassification(TheCall, 6, BuiltinID))
return ExprError();
break;
case Builtin::BI__builtin_isfpclass:
- if (SemaBuiltinFPClassification(TheCall, 2))
+ if (SemaBuiltinFPClassification(TheCall, 2, BuiltinID))
return ExprError();
break;
case Builtin::BI__builtin_isfinite:
@@ -2273,17 +2268,7 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
case Builtin::BI__builtin_signbit:
case Builtin::BI__builtin_signbitf:
case Builtin::BI__builtin_signbitl:
- FPO = TheCall->getFPFeaturesInEffect(getLangOpts());
- if (FPO.getNoHonorInfs() && (BuiltinID == Builtin::BI__builtin_isfinite ||
- BuiltinID == Builtin::BI__builtin_isinf ||
- BuiltinID == Builtin::BI__builtin_isinf_sign))
- Diag(TheCall->getBeginLoc(), diag::warn_fast_floatingpoint_eq)
- << "infinity" << TheCall->getSourceRange();
- if (FPO.getNoHonorNaNs() && (BuiltinID == Builtin::BI__builtin_isnan ||
- BuiltinID == Builtin::BI__builtin_isunordered))
- Diag(TheCall->getBeginLoc(), diag::warn_fast_floatingpoint_eq)
- << "NaN" << TheCall->getSourceRange();
- if (SemaBuiltinFPClassification(TheCall, 1))
+ if (SemaBuiltinFPClassification(TheCall, 1, BuiltinID))
return ExprError();
break;
case Builtin::BI__builtin_shufflevector:
@@ -9107,10 +9092,16 @@ bool Sema::SemaBuiltinVAStartARMMicrosoft(CallExpr *Call) {
/// SemaBuiltinUnorderedCompare - Handle functions like __builtin_isgreater and
/// friends. This is declared to take (...), so we have to check everything.
-bool Sema::SemaBuiltinUnorderedCompare(CallExpr *TheCall) {
+bool Sema::SemaBuiltinUnorderedCompare(CallExpr *TheCall, unsigned BuiltinID) {
if (checkArgCount(*this, TheCall, 2))
return true;
+ if (BuiltinID == Builtin::BI__builtin_isunordered) {
+ if (TheCall->getFPFeaturesInEffect(getLangOpts()).getNoHonorNaNs())
+ Diag(TheCall->getBeginLoc(), diag::warn_fast_floatingpoint_eq)
+ << "NaN" << TheCall->getSourceRange();
+ }
+
ExprResult OrigArg0 = TheCall->getArg(0);
ExprResult OrigArg1 = TheCall->getArg(1);
@@ -9145,10 +9136,22 @@ bool Sema::SemaBuiltinUnorderedCompare(CallExpr *TheCall) {
/// SemaBuiltinSemaBuiltinFPClassification - Handle functions like
/// __builtin_isnan and friends. This is declared to take (...), so we have
/// to check everything.
-bool Sema::SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs) {
+bool Sema::SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs,
+ unsigned BuiltinID) {
if (checkArgCount(*this, TheCall, NumArgs))
return true;
+ FPOptions FPO = TheCall->getFPFeaturesInEffect(getLangOpts());
+ if (FPO.getNoHonorInfs() && (BuiltinID == Builtin::BI__builtin_isfinite ||
+ BuiltinID == Builtin::BI__builtin_isinf ||
+ BuiltinID == Builtin::BI__builtin_isinf_sign))
+ Diag(TheCall->getBeginLoc(), diag::warn_fast_floatingpoint_eq)
+ << "infinity" << TheCall->getSourceRange();
+ if (FPO.getNoHonorNaNs() && (BuiltinID == Builtin::BI__builtin_isnan ||
+ BuiltinID == Builtin::BI__builtin_isunordered))
+ Diag(TheCall->getBeginLoc(), diag::warn_fast_floatingpoint_eq)
+ << "NaN" << TheCall->getSourceRange();
+
bool IsFPClass = NumArgs == 2;
// Find out position of floating-point argument.
@@ -12897,16 +12900,15 @@ static bool IsStdFunction(const FunctionDecl *FDecl,
void Sema::CheckInfNaNFunction(const CallExpr *Call,
const FunctionDecl *FDecl) {
- if (Call->getNumArgs() != 1 && Call->getNumArgs() != 2)
- return;
-
FPOptions FPO = Call->getFPFeaturesInEffect(getLangOpts());
- if ((IsStdFunction(FDecl, "isnan") || IsStdFunction(FDecl, "isunordered")) &&
+ if ((IsStdFunction(FDecl, "isnan") || IsStdFunction(FDecl, "isunordered") ||
+ (Call->getBuiltinCallee() == Builtin::BI__builtin_nanf)) &&
FPO.getNoHonorNaNs())
Diag(Call->getBeginLoc(), diag::warn_fast_floatingpoint_eq)
<< "NaN" << Call->getSourceRange();
else if ((IsStdFunction(FDecl, "isinf") ||
- (IsStdFunction(FDecl, "isfinite"))) &&
+ (IsStdFunction(FDecl, "isfinite") ||
+ (Call->getBuiltinCallee() == Builtin::BI__builtin_inff))) &&
FPO.getNoHonorInfs())
Diag(Call->getBeginLoc(), diag::warn_fast_floatingpoint_eq)
<< "infinity" << Call->getSourceRange();
@@ -13892,19 +13894,20 @@ void Sema::CheckInfNaNFloatComparison(SourceLocation Loc, Expr *LHS, Expr *RHS,
bool NoHonorNaNs = FPO.getNoHonorNaNs();
bool NoHonorInfs = FPO.getNoHonorInfs();
llvm::APFloat Value(0.0);
- bool IsConstant;
- IsConstant = !LHS->isValueDependent() &&
- LeftExprSansParen->EvaluateAsFloat(Value, Context,
- Expr::SE_AllowSideEffects);
- if (IsConstant &&
+
+ auto IsConstant = [&Value](Expr *E, Expr *ESansParen, ASTContext &Context) {
+ return !E->isValueDependent() &&
+ ESansParen->EvaluateAsFloat(Value, Context,
+ Expr::SE_AllowSideEffects);
+ };
+
+ if (IsConstant(LHS, LeftExprSansParen, Context) &&
((NoHonorNaNs && Value.isNaN()) || (NoHonorInfs && Value.isInfinity())))
Diag(Loc, diag::warn_fast_floatingpoint_eq)
<< (Value.isNaN() ? "NaN" : "infinity") << LHS->getSourceRange()
<< RHS->getSourceRange();
- IsConstant = !RHS->isValueDependent() &&
- RightExprSansParen->EvaluateAsFloat(Value, Context,
- Expr::SE_AllowSideEffects);
- if (IsConstant &&
+
+ if (IsConstant(RHS, RightExprSansParen, Context) &&
((NoHonorNaNs && Value.isNaN()) || (NoHonorInfs && Value.isInfinity())))
Diag(Loc, diag::warn_fast_floatingpoint_eq)
<< (Value.isNaN() ? "NaN" : "infinity") << LHS->getSourceRange()
diff --git a/clang/test/Sema/warn-fp-fast-compare.cpp b/clang/test/Sema/warn-fp-fast-compare.cpp
index 07eeaf0eeab125..df8c8145f538ad 100644
--- a/clang/test/Sema/warn-fp-fast-compare.cpp
+++ b/clang/test/Sema/warn-fp-fast-compare.cpp
@@ -48,101 +48,149 @@ bool
int compareit(float a, float b) {
volatile int i, j, k, l, m, n, o, p;
#if FAST
-// expected-warning at +5 {{explicit comparison with infinity in fast floating point mode}}
+// expected-warning at +11 {{explicit comparison with infinity when the program is assumed to not use or produce infinity}}
+#endif
+#if FAST
+// expected-warning at +8 {{explicit comparison with infinity when the program is assumed to not use or produce infinity}}
+#endif
+#if NO_INFS
+// expected-warning at +5 {{explicit comparison with infinity when the program is assumed to not use or produce infinity}}
#endif
#if NO_INFS
-// expected-warning at +2 {{explicit comparison with infinity in fast floating point mode}}
+// expected-warning at +2 {{explicit comparison with infinity when the program is assumed to not use or produce infinity}}
#endif
i = a == INFINITY;
#if FAST
-// expected-warning at +5 {{explicit comparison with infinity in fast floating point mode}}
+// expected-warning at +11 {{explicit comparison with infinity when the program is assumed to not use or produce infinity}}
+#endif
+#if FAST
+// expected-warning at +8 {{explicit comparison with infinity when the program is assumed to not use or produce infinity}}
#endif
#if NO_INFS
-// expected-warning at +2 {{explicit comparison with infinity in fast floating point mode}}
+// expected-warning at +5 {{explicit comparison with infinity when the program is assumed to not use or produce infinity}}
+#endif
+#if NO_INFS
+// expected-warning at +2 {{explicit comparison with infinity when the program is assumed to not use or produce infinity}}
#endif
j = INFINITY == a;
#if FAST
-// expected-warning at +5 {{explicit comparison with NaN in fast floating point mode}}
+// expected-warning at +11 {{explicit comparison with NaN when the program is assumed to not use or produce NaN}}
+#endif
+#if FAST
+// expected-warning at +8 {{explicit comparison with NaN when the program is assumed to not use or produce NaN}}
#endif
#if NO_NANS
-// expected-warning at +2 {{explicit comparison with NaN in fast floating point mode}}
+// expected-warning at +5 {{explicit comparison with NaN when the program is assumed to not use or produce NaN}}
+#endif
+#if NO_NANS
+// expected-warning at +2 {{explicit comparison with NaN when the program is assumed to not use or produce NaN}}
#endif
i = a == NAN;
#if FAST
-// expected-warning at +5 {{explicit comparison with NaN in fast floating point mode}}
+// expected-warning at +11 {{explicit comparison with NaN when the program is assumed to not use or produce NaN}}
+#endif
+#if FAST
+// expected-warning at +8 {{explicit comparison with NaN when the program is assumed to not use or produce NaN}}
+#endif
+#if NO_NANS
+// expected-warning at +5 {{explicit comparison with NaN when the program is assumed to not use or produce NaN}}
#endif
#if NO_NANS
-// expected-warning at +2 {{explicit comparison with NaN in fast floating point mode}}
+// expected-warning at +2 {{explicit comparison with NaN when the program is assumed to not use or produce NaN}}
#endif
j = NAN == a;
#if FAST
-// expected-warning at +5 {{explicit comparison with infinity in fast floating point mode}}
+// expected-warning at +11 {{explicit comparison with infinity when the program is assumed to not use or produce infinity}}
+#endif
+#if FAST
+// expected-warning at +8 {{explicit comparison with infinity when the program is assumed to not use or produce infinity}}
+#endif
+#if NO_INFS
+// expected-warning at +5 {{explicit comparison with infinity when the program is assumed to not use or produce infinity}}
#endif
#if NO_INFS
-// expected-warning at +2 {{explicit comparison with infinity in fast floating point mode}}
+// expected-warning at +2 {{explicit comparison with infinity when the program is assumed to not use or produce infinity}}
#endif
j = INFINITY <= a;
#if FAST
-// expected-warning at +5 {{explicit comparison with infinity in fast floating point mode}}
+// expected-warning at +11 {{explicit comparison with infinity when the program is assumed to not use or produce infinity}}
+#endif
+#if FAST
+// expected-warning at +8 {{explicit comparison with infinity when the program is assumed to not use or produce infinity}}
#endif
#if NO_INFS
-// expected-warning at +2 {{explicit comparison with infinity in fast floating point mode}}
+ // expected-warning at +5 {{explicit comparison with infinity when the program is assumed to not use or produce infinity}}
+#endif
+#if NO_INFS
+// expected-warning at +2 {{explicit comparison with infinity when the program is assumed to not use or produce infinity}}
#endif
j = INFINITY < a;
#if FAST
-// expected-warning at +5 {{explicit comparison with NaN in fast floating point mode}}
+// expected-warning at +11 {{explicit comparison with NaN when the program is assumed to not use or produce NaN}}
+#endif
+#if FAST
+// expected-warning at +8 {{explicit comparison with NaN when the program is assumed to not use or produce NaN}}
+#endif
+#if NO_NANS
+// expected-warning at +5 {{explicit comparison with NaN when the program is assumed to not use or produce NaN}}
#endif
#if NO_NANS
-// expected-warning at +2 {{explicit comparison with NaN in fast floating point mode}}
+ // expected-warning at +2 {{explicit comparison with NaN when the program is assumed to not use or produce NaN}}
#endif
j = a > NAN;
#if FAST
-// expected-warning at +5 {{explicit comparison with NaN in fast floating point mode}}
+// expected-warning at +11 {{explicit comparison with NaN when the program is assumed to not use or produce NaN}}
+#endif
+#if FAST
+// expected-warning at +8 {{explicit comparison with NaN when the program is assumed to not use or produce NaN}}
+#endif
+#if NO_NANS
+// expected-warning at +5 {{explicit comparison with NaN when the program is assumed to not use or produce NaN}}
#endif
#if NO_NANS
-// expected-warning at +2 {{explicit comparison with NaN in fast floating point mode}}
+// expected-warning at +2 {{explicit comparison with NaN when the program is assumed to not use or produce NaN}}
#endif
j = a >= NAN;
#if FAST
-// expected-warning at +5 {{explicit comparison with infinity in fast floating point mode}}
+// expected-warning at +5 {{explicit comparison with infinity when the program is assumed to not use or produce infinity}}
#endif
#if NO_INFS
-// expected-warning at +2 {{explicit comparison with infinity in fast floating point mode}}
+// expected-warning at +2 {{explicit comparison with infinity when the program is assumed to not use or produce infinity}}
#endif
k = std::isinf(a);
#if FAST
-// expected-warning at +5 {{explicit comparison with NaN in fast floating point mode}}
+// expected-warning at +5 {{explicit comparison with NaN when the program is assumed to not use or produce NaN}}
#endif
#if NO_NANS
-// expected-warning at +2 {{explicit comparison with NaN in fast floating point mode}}
+// expected-warning at +2 {{explicit comparison with NaN when the program is assumed to not use or produce NaN}}
#endif
l = std::isnan(a);
#if FAST
-// expected-warning at +5 {{explicit comparison with infinity in fast floating point mode}}
+// expected-warning at +5 {{explicit comparison with infinity when the program is assumed to not use or produce infinity}}
#endif
#if NO_INFS
-//expected-warning at +2 {{explicit comparison with infinity in fast floating point mode}}
+// expected-warning at +2 {{explicit comparison with infinity when the program is assumed to not use or produce infinity}}
#endif
o = std::isfinite(a);
#if FAST
-// expected-warning at +5 {{explicit comparison with infinity in fast floating point mode}}
+// expected-warning at +5 {{explicit comparison with infinity when the program is assumed to not use or produce infinity}}
#endif
#if NO_INFS
-// expected-warning at +2 {{explicit comparison with infinity in fast floating point mode}}
+// expected-warning at +2 {{explicit comparison with infinity when the program is assumed to not use or produce infinity}}
#endif
m = __builtin_isinf(a);
#if FAST
-// expected-warning at +5 {{explicit comparison with NaN in fast floating point mode}}
+// expected-warning at +5 {{explicit comparison with NaN when the program is assumed to not use or produce NaN}}
#endif
#if NO_NANS
-// expected-warning at +2 {{explicit comparison with NaN in fast floating point mode}}
+// expected-warning at +2 {{explicit comparison with NaN when the program is assumed to not use or produce NaN}}
#endif
n = __builtin_isnan(a);
#if FAST
-//expected-warning at +5 {{explicit comparison with infinity in fast floating point mode}}
+// expected-warning at +5 {{explicit comparison with infinity when the program is assumed to not use or produce infinity}}
#endif
#if NO_INFS
-//expected-warning at +2 {{explicit comparison with infinity in fast floating point mode}}
+// expected-warning at +2 {{explicit comparison with infinity when the program is assumed to not use or produce infinity}}
#endif
p = __builtin_isfinite(a);
@@ -151,20 +199,46 @@ k = std::isinf(a);
j = b < 1.1;
j = a >= 1.1;
j = b <= 1.1;
+ j = isunorderedf(a, b);
+
+#if FAST
+// expected-warning at +5 {{explicit comparison with NaN when the program is assumed to not use or produce NaN}}
+#endif
+#if NO_NANS
+// expected-warning at +2 {{explicit comparison with NaN when the program is assumed to not use or produce NaN}}
+#endif
j = isunorderedf(a, NAN);
+#if FAST
+// expected-warning at +5 {{explicit comparison with infinity when the program is assumed to not use or produce infinity}}
+#endif
+#if NO_INFS
+// expected-warning at +2 {{explicit comparison with infinity when the program is assumed to not use or produce infinity}}
+#endif
j = isunorderedf(a, INFINITY);
#if FAST
-// expected-warning at +5 {{explicit comparison with NaN in fast floating point mode}}
+// expected-warning at +11 {{explicit comparison with NaN when the program is assumed to not use or produce NaN}}
+#endif
+#if FAST
+// expected-warning at +8 {{explicit comparison with NaN when the program is assumed to not use or produce NaN}}
#endif
#if NO_NANS
-// expected-warning at +2 {{explicit comparison with NaN in fast floating point mode}}
+// expected-warning at +5 {{explicit comparison with NaN when the program is assumed to not use or produce NaN}}
+#endif
+#if NO_NANS
+// expected-warning at +2 {{explicit comparison with NaN when the program is assumed to not use or produce NaN}}
#endif
i = std::isunordered(a, NAN);
#if FAST
-// expected-warning at +5 {{explicit comparison with NaN in fast floating point mode}}
+// expected-warning at +11 {{explicit comparison with infinity when the program is assumed to not use or produce infinity}}
+#endif
+#if FAST
+// expected-warning at +8 {{explicit comparison with NaN when the program is assumed to not use or produce NaN}}
#endif
#if NO_NANS
-// expected-warning at +2 {{explicit comparison with NaN in fast floating point mode}}
+// expected-warning at +5 {{explicit comparison with NaN when the program is assumed to not use or produce NaN}}
+#endif
+#if NO_INFS
+// expected-warning at +2 {{explicit comparison with infinity when the program is assumed to not use or produce infinity}}
#endif
i = std::isunordered(a, INFINITY);
return 0;
>From 948ace771f6e696c8246789f11248ee0d237a623 Mon Sep 17 00:00:00 2001
From: Ammarguellat <zahira.ammarguellat at intel.com>
Date: Thu, 11 Jan 2024 12:47:03 -0800
Subject: [PATCH 3/5] Addressed review comments.
---
.../clang/Basic/DiagnosticSemaKinds.td | 4 +-
clang/lib/Sema/SemaChecking.cpp | 29 ++--
clang/test/Sema/warn-fp-fast-compare.cpp | 151 +++++++++++-------
3 files changed, 109 insertions(+), 75 deletions(-)
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index d19be567a1bf66..e1164ef34a1b6c 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -6772,7 +6772,9 @@ def warn_floatingpoint_eq : Warning<
"comparing floating point with == or != is unsafe">,
InGroup<DiagGroup<"float-equal">>, DefaultIgnore;
def warn_fast_floatingpoint_eq : Warning<
- "explicit comparison with %0 when the program is assumed to not use or produce %0">,
+ "use of %select{infinity|NaN}0 will always be 'false' because "
+ "%select{infinity|NaN}0 will not be produced according to the currently "
+ "enabled floating-point options">,
InGroup<TautologicalConstantCompare>;
def err_setting_eval_method_used_in_unsafe_context : Error <
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 2c4d628ab160d2..027cfac1c5a641 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -9096,11 +9096,9 @@ bool Sema::SemaBuiltinUnorderedCompare(CallExpr *TheCall, unsigned BuiltinID) {
if (checkArgCount(*this, TheCall, 2))
return true;
- if (BuiltinID == Builtin::BI__builtin_isunordered) {
- if (TheCall->getFPFeaturesInEffect(getLangOpts()).getNoHonorNaNs())
- Diag(TheCall->getBeginLoc(), diag::warn_fast_floatingpoint_eq)
- << "NaN" << TheCall->getSourceRange();
- }
+ if (BuiltinID == Builtin::BI__builtin_isunordered &&
+ TheCall->getFPFeaturesInEffect(getLangOpts()).getNoHonorNaNs())
+ Diag(TheCall->getBeginLoc(), diag::warn_fast_floatingpoint_eq) << 1 << 1;
ExprResult OrigArg0 = TheCall->getArg(0);
ExprResult OrigArg1 = TheCall->getArg(1);
@@ -9145,12 +9143,10 @@ bool Sema::SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs,
if (FPO.getNoHonorInfs() && (BuiltinID == Builtin::BI__builtin_isfinite ||
BuiltinID == Builtin::BI__builtin_isinf ||
BuiltinID == Builtin::BI__builtin_isinf_sign))
- Diag(TheCall->getBeginLoc(), diag::warn_fast_floatingpoint_eq)
- << "infinity" << TheCall->getSourceRange();
+ Diag(TheCall->getBeginLoc(), diag::warn_fast_floatingpoint_eq) << 0 << 0;
if (FPO.getNoHonorNaNs() && (BuiltinID == Builtin::BI__builtin_isnan ||
BuiltinID == Builtin::BI__builtin_isunordered))
- Diag(TheCall->getBeginLoc(), diag::warn_fast_floatingpoint_eq)
- << "NaN" << TheCall->getSourceRange();
+ Diag(TheCall->getBeginLoc(), diag::warn_fast_floatingpoint_eq) << 1 << 1;
bool IsFPClass = NumArgs == 2;
@@ -12904,14 +12900,13 @@ void Sema::CheckInfNaNFunction(const CallExpr *Call,
if ((IsStdFunction(FDecl, "isnan") || IsStdFunction(FDecl, "isunordered") ||
(Call->getBuiltinCallee() == Builtin::BI__builtin_nanf)) &&
FPO.getNoHonorNaNs())
- Diag(Call->getBeginLoc(), diag::warn_fast_floatingpoint_eq)
- << "NaN" << Call->getSourceRange();
+ Diag(Call->getBeginLoc(), diag::warn_fast_floatingpoint_eq) << 1 << 1;
else if ((IsStdFunction(FDecl, "isinf") ||
(IsStdFunction(FDecl, "isfinite") ||
- (Call->getBuiltinCallee() == Builtin::BI__builtin_inff))) &&
+ (Call->getBuiltinCallee() == Builtin::BI__builtin_inff)) ||
+ (FDecl->getIdentifier() && FDecl->getName() == "infinity")) &&
FPO.getNoHonorInfs())
- Diag(Call->getBeginLoc(), diag::warn_fast_floatingpoint_eq)
- << "infinity" << Call->getSourceRange();
+ Diag(Call->getBeginLoc(), diag::warn_fast_floatingpoint_eq) << 0 << 0;
}
// Warn when using the wrong abs() function.
@@ -13904,14 +13899,12 @@ void Sema::CheckInfNaNFloatComparison(SourceLocation Loc, Expr *LHS, Expr *RHS,
if (IsConstant(LHS, LeftExprSansParen, Context) &&
((NoHonorNaNs && Value.isNaN()) || (NoHonorInfs && Value.isInfinity())))
Diag(Loc, diag::warn_fast_floatingpoint_eq)
- << (Value.isNaN() ? "NaN" : "infinity") << LHS->getSourceRange()
- << RHS->getSourceRange();
+ << (Value.isNaN() ? 1 : 0) << (Value.isNaN() ? 1 : 0);
if (IsConstant(RHS, RightExprSansParen, Context) &&
((NoHonorNaNs && Value.isNaN()) || (NoHonorInfs && Value.isInfinity())))
Diag(Loc, diag::warn_fast_floatingpoint_eq)
- << (Value.isNaN() ? "NaN" : "infinity") << LHS->getSourceRange()
- << RHS->getSourceRange();
+ << (Value.isNaN() ? 1 : 0) << (Value.isNaN() ? 1 : 0);
}
/// Check for comparisons of floating-point values using == and !=. Issue a
diff --git a/clang/test/Sema/warn-fp-fast-compare.cpp b/clang/test/Sema/warn-fp-fast-compare.cpp
index df8c8145f538ad..430fb58dfd7473 100644
--- a/clang/test/Sema/warn-fp-fast-compare.cpp
+++ b/clang/test/Sema/warn-fp-fast-compare.cpp
@@ -45,152 +45,175 @@ bool
#define NAN (__builtin_nanf(""))
#define INFINITY (__builtin_inff())
+template <class _Ty>
+class numeric_limits {
+public:
+ [[nodiscard]] static constexpr _Ty infinity() noexcept {
+ return _Ty();
+ }
+};
+
+template <>
+class numeric_limits<float> {
+public:
+ [[nodiscard]] static constexpr float infinity() noexcept {
+ return __builtin_huge_val();
+ }
+};
+template <>
+class numeric_limits<double> {
+public:
+ [[nodiscard]] static constexpr double infinity() noexcept {
+ return __builtin_huge_val();
+ }
+};
+
int compareit(float a, float b) {
volatile int i, j, k, l, m, n, o, p;
#if FAST
-// expected-warning at +11 {{explicit comparison with infinity when the program is assumed to not use or produce infinity}}
+// expected-warning at +11 {{use of infinity will always be 'false' because infinity will not be produced according to the currently enabled floating-point options}}
#endif
#if FAST
-// expected-warning at +8 {{explicit comparison with infinity when the program is assumed to not use or produce infinity}}
+// expected-warning at +8 {{use of infinity will always be 'false' because infinity will not be produced according to the currently enabled floating-point options}}
#endif
#if NO_INFS
-// expected-warning at +5 {{explicit comparison with infinity when the program is assumed to not use or produce infinity}}
+// expected-warning at +5 {{use of infinity will always be 'false' because infinity will not be produced according to the currently enabled floating-point options}}
#endif
#if NO_INFS
-// expected-warning at +2 {{explicit comparison with infinity when the program is assumed to not use or produce infinity}}
+// expected-warning at +2 {{use of infinity will always be 'false' because infinity will not be produced according to the currently enabled floating-point options}}
#endif
i = a == INFINITY;
#if FAST
-// expected-warning at +11 {{explicit comparison with infinity when the program is assumed to not use or produce infinity}}
+// expected-warning at +11 {{use of infinity will always be 'false' because infinity will not be produced according to the currently enabled floating-point options}}
#endif
#if FAST
-// expected-warning at +8 {{explicit comparison with infinity when the program is assumed to not use or produce infinity}}
+// expected-warning at +8 {{use of infinity will always be 'false' because infinity will not be produced according to the currently enabled floating-point options}}
#endif
#if NO_INFS
-// expected-warning at +5 {{explicit comparison with infinity when the program is assumed to not use or produce infinity}}
+// expected-warning at +5 {{use of infinity will always be 'false' because infinity will not be produced according to the currently enabled floating-point options}}
#endif
#if NO_INFS
-// expected-warning at +2 {{explicit comparison with infinity when the program is assumed to not use or produce infinity}}
+// expected-warning at +2 {{use of infinity will always be 'false' because infinity will not be produced according to the currently enabled floating-point options}}
#endif
j = INFINITY == a;
#if FAST
-// expected-warning at +11 {{explicit comparison with NaN when the program is assumed to not use or produce NaN}}
+// expected-warning at +11 {{use of NaN will always be 'false' because NaN will not be produced according to the currently enabled floating-point options}}
#endif
#if FAST
-// expected-warning at +8 {{explicit comparison with NaN when the program is assumed to not use or produce NaN}}
+// expected-warning at +8 {{use of NaN will always be 'false' because NaN will not be produced according to the currently enabled floating-point options}}
#endif
#if NO_NANS
-// expected-warning at +5 {{explicit comparison with NaN when the program is assumed to not use or produce NaN}}
+// expected-warning at +5 {{use of NaN will always be 'false' because NaN will not be produced according to the currently enabled floating-point options}}
#endif
#if NO_NANS
-// expected-warning at +2 {{explicit comparison with NaN when the program is assumed to not use or produce NaN}}
+// expected-warning at +2 {{use of NaN will always be 'false' because NaN will not be produced according to the currently enabled floating-point options}}
#endif
i = a == NAN;
#if FAST
-// expected-warning at +11 {{explicit comparison with NaN when the program is assumed to not use or produce NaN}}
+// expected-warning at +11 {{use of NaN will always be 'false' because NaN will not be produced according to the currently enabled floating-point options}}
#endif
#if FAST
-// expected-warning at +8 {{explicit comparison with NaN when the program is assumed to not use or produce NaN}}
+// expected-warning at +8 {{use of NaN will always be 'false' because NaN will not be produced according to the currently enabled floating-point options}}
#endif
#if NO_NANS
-// expected-warning at +5 {{explicit comparison with NaN when the program is assumed to not use or produce NaN}}
+// expected-warning at +5 {{use of NaN will always be 'false' because NaN will not be produced according to the currently enabled floating-point options}}
#endif
#if NO_NANS
-// expected-warning at +2 {{explicit comparison with NaN when the program is assumed to not use or produce NaN}}
+// expected-warning at +2 {{use of NaN will always be 'false' because NaN will not be produced according to the currently enabled floating-point options}}
#endif
j = NAN == a;
#if FAST
-// expected-warning at +11 {{explicit comparison with infinity when the program is assumed to not use or produce infinity}}
+// expected-warning at +11 {{use of infinity will always be 'false' because infinity will not be produced according to the currently enabled floating-point options}}
#endif
#if FAST
-// expected-warning at +8 {{explicit comparison with infinity when the program is assumed to not use or produce infinity}}
+// expected-warning at +8 {{use of infinity will always be 'false' because infinity will not be produced according to the currently enabled floating-point options}}
#endif
#if NO_INFS
-// expected-warning at +5 {{explicit comparison with infinity when the program is assumed to not use or produce infinity}}
+// expected-warning at +5 {{use of infinity will always be 'false' because infinity will not be produced according to the currently enabled floating-point options}}
#endif
#if NO_INFS
-// expected-warning at +2 {{explicit comparison with infinity when the program is assumed to not use or produce infinity}}
+// expected-warning at +2 {{use of infinity will always be 'false' because infinity will not be produced according to the currently enabled floating-point options}}
#endif
j = INFINITY <= a;
#if FAST
-// expected-warning at +11 {{explicit comparison with infinity when the program is assumed to not use or produce infinity}}
+// expected-warning at +11 {{use of infinity will always be 'false' because infinity will not be produced according to the currently enabled floating-point options}}
#endif
#if FAST
-// expected-warning at +8 {{explicit comparison with infinity when the program is assumed to not use or produce infinity}}
+// expected-warning at +8 {{use of infinity will always be 'false' because infinity will not be produced according to the currently enabled floating-point options}}
#endif
#if NO_INFS
- // expected-warning at +5 {{explicit comparison with infinity when the program is assumed to not use or produce infinity}}
+ // expected-warning at +5 {{use of infinity will always be 'false' because infinity will not be produced according to the currently enabled floating-point options}}
#endif
#if NO_INFS
-// expected-warning at +2 {{explicit comparison with infinity when the program is assumed to not use or produce infinity}}
+// expected-warning at +2 {{use of infinity will always be 'false' because infinity will not be produced according to the currently enabled floating-point options}}
#endif
j = INFINITY < a;
#if FAST
-// expected-warning at +11 {{explicit comparison with NaN when the program is assumed to not use or produce NaN}}
+// expected-warning at +11 {{use of NaN will always be 'false' because NaN will not be produced according to the currently enabled floating-point options}}
#endif
#if FAST
-// expected-warning at +8 {{explicit comparison with NaN when the program is assumed to not use or produce NaN}}
+// expected-warning at +8 {{use of NaN will always be 'false' because NaN will not be produced according to the currently enabled floating-point options}}
#endif
#if NO_NANS
-// expected-warning at +5 {{explicit comparison with NaN when the program is assumed to not use or produce NaN}}
+// expected-warning at +5 {{use of NaN will always be 'false' because NaN will not be produced according to the currently enabled floating-point options}}
#endif
#if NO_NANS
- // expected-warning at +2 {{explicit comparison with NaN when the program is assumed to not use or produce NaN}}
+ // expected-warning at +2 {{use of NaN will always be 'false' because NaN will not be produced according to the currently enabled floating-point options}}
#endif
j = a > NAN;
#if FAST
-// expected-warning at +11 {{explicit comparison with NaN when the program is assumed to not use or produce NaN}}
+// expected-warning at +11 {{use of NaN will always be 'false' because NaN will not be produced according to the currently enabled floating-point options}}
#endif
#if FAST
-// expected-warning at +8 {{explicit comparison with NaN when the program is assumed to not use or produce NaN}}
+// expected-warning at +8 {{use of NaN will always be 'false' because NaN will not be produced according to the currently enabled floating-point options}}
#endif
#if NO_NANS
-// expected-warning at +5 {{explicit comparison with NaN when the program is assumed to not use or produce NaN}}
+// expected-warning at +5 {{use of NaN will always be 'false' because NaN will not be produced according to the currently enabled floating-point options}}
#endif
#if NO_NANS
-// expected-warning at +2 {{explicit comparison with NaN when the program is assumed to not use or produce NaN}}
+// expected-warning at +2 {{use of NaN will always be 'false' because NaN will not be produced according to the currently enabled floating-point options}}
#endif
j = a >= NAN;
#if FAST
-// expected-warning at +5 {{explicit comparison with infinity when the program is assumed to not use or produce infinity}}
+// expected-warning at +5 {{use of infinity will always be 'false' because infinity will not be produced according to the currently enabled floating-point options}}
#endif
#if NO_INFS
-// expected-warning at +2 {{explicit comparison with infinity when the program is assumed to not use or produce infinity}}
+// expected-warning at +2 {{use of infinity will always be 'false' because infinity will not be produced according to the currently enabled floating-point options}}
#endif
k = std::isinf(a);
#if FAST
-// expected-warning at +5 {{explicit comparison with NaN when the program is assumed to not use or produce NaN}}
+// expected-warning at +5 {{use of NaN will always be 'false' because NaN will not be produced according to the currently enabled floating-point options}}
#endif
#if NO_NANS
-// expected-warning at +2 {{explicit comparison with NaN when the program is assumed to not use or produce NaN}}
+// expected-warning at +2 {{use of NaN will always be 'false' because NaN will not be produced according to the currently enabled floating-point options}}
#endif
l = std::isnan(a);
#if FAST
-// expected-warning at +5 {{explicit comparison with infinity when the program is assumed to not use or produce infinity}}
+// expected-warning at +5 {{use of infinity will always be 'false' because infinity will not be produced according to the currently enabled floating-point options}}
#endif
#if NO_INFS
-// expected-warning at +2 {{explicit comparison with infinity when the program is assumed to not use or produce infinity}}
+// expected-warning at +2 {{use of infinity will always be 'false' because infinity will not be produced according to the currently enabled floating-point options}}
#endif
o = std::isfinite(a);
#if FAST
-// expected-warning at +5 {{explicit comparison with infinity when the program is assumed to not use or produce infinity}}
+// expected-warning at +5 {{use of infinity will always be 'false' because infinity will not be produced according to the currently enabled floating-point options}}
#endif
#if NO_INFS
-// expected-warning at +2 {{explicit comparison with infinity when the program is assumed to not use or produce infinity}}
+// expected-warning at +2 {{use of infinity will always be 'false' because infinity will not be produced according to the currently enabled floating-point options}}
#endif
m = __builtin_isinf(a);
#if FAST
-// expected-warning at +5 {{explicit comparison with NaN when the program is assumed to not use or produce NaN}}
+// expected-warning at +5 {{use of NaN will always be 'false' because NaN will not be produced according to the currently enabled floating-point options}}
#endif
#if NO_NANS
-// expected-warning at +2 {{explicit comparison with NaN when the program is assumed to not use or produce NaN}}
+// expected-warning at +2 {{use of NaN will always be 'false' because NaN will not be produced according to the currently enabled floating-point options}}
#endif
n = __builtin_isnan(a);
#if FAST
-// expected-warning at +5 {{explicit comparison with infinity when the program is assumed to not use or produce infinity}}
+// expected-warning at +5 {{use of infinity will always be 'false' because infinity will not be produced according to the currently enabled floating-point options}}
#endif
#if NO_INFS
-// expected-warning at +2 {{explicit comparison with infinity when the program is assumed to not use or produce infinity}}
+// expected-warning at +2 {{use of infinity will always be 'false' because infinity will not be produced according to the currently enabled floating-point options}}
#endif
p = __builtin_isfinite(a);
@@ -202,44 +225,60 @@ k = std::isinf(a);
j = isunorderedf(a, b);
#if FAST
-// expected-warning at +5 {{explicit comparison with NaN when the program is assumed to not use or produce NaN}}
+// expected-warning at +5 {{use of NaN will always be 'false' because NaN will not be produced according to the currently enabled floating-point options}}
#endif
#if NO_NANS
-// expected-warning at +2 {{explicit comparison with NaN when the program is assumed to not use or produce NaN}}
+// expected-warning at +2 {{use of NaN will always be 'false' because NaN will not be produced according to the currently enabled floating-point options}}
#endif
j = isunorderedf(a, NAN);
#if FAST
-// expected-warning at +5 {{explicit comparison with infinity when the program is assumed to not use or produce infinity}}
+// expected-warning at +5 {{use of infinity will always be 'false' because infinity will not be produced according to the currently enabled floating-point options}}
#endif
#if NO_INFS
-// expected-warning at +2 {{explicit comparison with infinity when the program is assumed to not use or produce infinity}}
+// expected-warning at +2 {{use of infinity will always be 'false' because infinity will not be produced according to the currently enabled floating-point options}}
#endif
j = isunorderedf(a, INFINITY);
#if FAST
-// expected-warning at +11 {{explicit comparison with NaN when the program is assumed to not use or produce NaN}}
+// expected-warning at +11 {{use of NaN will always be 'false' because NaN will not be produced according to the currently enabled floating-point options}}
#endif
#if FAST
-// expected-warning at +8 {{explicit comparison with NaN when the program is assumed to not use or produce NaN}}
+// expected-warning at +8 {{use of NaN will always be 'false' because NaN will not be produced according to the currently enabled floating-point options}}
#endif
#if NO_NANS
-// expected-warning at +5 {{explicit comparison with NaN when the program is assumed to not use or produce NaN}}
+// expected-warning at +5 {{use of NaN will always be 'false' because NaN will not be produced according to the currently enabled floating-point options}}
#endif
#if NO_NANS
-// expected-warning at +2 {{explicit comparison with NaN when the program is assumed to not use or produce NaN}}
+// expected-warning at +2 {{use of NaN will always be 'false' because NaN will not be produced according to the currently enabled floating-point options}}
#endif
i = std::isunordered(a, NAN);
#if FAST
-// expected-warning at +11 {{explicit comparison with infinity when the program is assumed to not use or produce infinity}}
+// expected-warning at +11 {{use of infinity will always be 'false' because infinity will not be produced according to the currently enabled floating-point options}}
#endif
#if FAST
-// expected-warning at +8 {{explicit comparison with NaN when the program is assumed to not use or produce NaN}}
+// expected-warning at +8 {{use of NaN will always be 'false' because NaN will not be produced according to the currently enabled floating-point options}}
#endif
#if NO_NANS
-// expected-warning at +5 {{explicit comparison with NaN when the program is assumed to not use or produce NaN}}
+// expected-warning at +5 {{use of NaN will always be 'false' because NaN will not be produced according to the currently enabled floating-point options}}
#endif
#if NO_INFS
-// expected-warning at +2 {{explicit comparison with infinity when the program is assumed to not use or produce infinity}}
+// expected-warning at +2 {{use of infinity will always be 'false' because infinity will not be produced according to the currently enabled floating-point options}}
#endif
i = std::isunordered(a, INFINITY);
+#if FAST
+// expected-warning at +5 {{use of infinity will always be 'false' because infinity will not be produced according to the currently enabled floating-point options}}
+#endif
+#if NO_INFS
+// expected-warning at +2 {{use of infinity will always be 'false' because infinity will not be produced according to the currently enabled floating-point options}}
+#endif
+ double y = i * numeric_limits<double>::infinity();
+
+#if FAST
+// expected-warning at +5 {{use of infinity will always be 'false' because infinity will not be produced according to the currently enabled floating-point options}}
+#endif
+#if NO_INFS
+// expected-warning at +2 {{use of infinity will always be 'false' because infinity will not be produced according to the currently enabled floating-point options}}
+#endif
+ j = numeric_limits<float>::infinity();
return 0;
+
}
>From d82f5690f4811552241b22b425de30dfbc84b049 Mon Sep 17 00:00:00 2001
From: Ammarguellat <zahira.ammarguellat at intel.com>
Date: Sat, 13 Jan 2024 08:16:01 -0800
Subject: [PATCH 4/5] Fixed the diagnostic message.
---
clang/docs/ReleaseNotes.rst | 4 +
.../clang/Basic/DiagnosticSemaKinds.td | 7 +-
clang/lib/Sema/SemaChecking.cpp | 14 +-
clang/test/Sema/warn-fp-fast-compare.cpp | 126 +++++++++---------
4 files changed, 78 insertions(+), 73 deletions(-)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 778ce0e0e52d06..94a91e3b13dcb0 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -519,6 +519,10 @@ Improvements to Clang's diagnostics
- Clang now diagnoses narrowing conversions involving const references.
(`#63151: <https://github.com/llvm/llvm-project/issues/63151>`_).
- Clang now diagnoses unexpanded packs within the template argument lists of function template specializations.
+- Clang's ``-Wtautological-logical-constant-compare`` flag now diagnoses
+ when ``INFINITY`` or ``NAN`` are used in arithmetic operations or function
+ arguments in floating-points mode where ``INFINITY`` or ``NAN`` don't have the
+ expected values.
Improvements to Clang's time-trace
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index e1164ef34a1b6c..856022f51fad7d 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -6772,9 +6772,10 @@ def warn_floatingpoint_eq : Warning<
"comparing floating point with == or != is unsafe">,
InGroup<DiagGroup<"float-equal">>, DefaultIgnore;
def warn_fast_floatingpoint_eq : Warning<
- "use of %select{infinity|NaN}0 will always be 'false' because "
- "%select{infinity|NaN}0 will not be produced according to the currently "
- "enabled floating-point options">,
+ "%select{explicit comparison with|use of}0 %select{infinity|nan}1 "
+ "%select{will always return 'false'|as a function argument will not always be interpreted as such}0 "
+ "because %select{infinity|nan}1 will not be produced according to the "
+ "currently enabled floating-point options">,
InGroup<TautologicalConstantCompare>;
def err_setting_eval_method_used_in_unsafe_context : Error <
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 027cfac1c5a641..f2a49f89b9b1ec 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -9098,7 +9098,7 @@ bool Sema::SemaBuiltinUnorderedCompare(CallExpr *TheCall, unsigned BuiltinID) {
if (BuiltinID == Builtin::BI__builtin_isunordered &&
TheCall->getFPFeaturesInEffect(getLangOpts()).getNoHonorNaNs())
- Diag(TheCall->getBeginLoc(), diag::warn_fast_floatingpoint_eq) << 1 << 1;
+ Diag(TheCall->getBeginLoc(), diag::warn_fast_floatingpoint_eq) << 0 << 1 << 0 << 1;
ExprResult OrigArg0 = TheCall->getArg(0);
ExprResult OrigArg1 = TheCall->getArg(1);
@@ -9143,10 +9143,10 @@ bool Sema::SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs,
if (FPO.getNoHonorInfs() && (BuiltinID == Builtin::BI__builtin_isfinite ||
BuiltinID == Builtin::BI__builtin_isinf ||
BuiltinID == Builtin::BI__builtin_isinf_sign))
- Diag(TheCall->getBeginLoc(), diag::warn_fast_floatingpoint_eq) << 0 << 0;
+ Diag(TheCall->getBeginLoc(), diag::warn_fast_floatingpoint_eq) << 0 << 0 << 0 << 0;
if (FPO.getNoHonorNaNs() && (BuiltinID == Builtin::BI__builtin_isnan ||
BuiltinID == Builtin::BI__builtin_isunordered))
- Diag(TheCall->getBeginLoc(), diag::warn_fast_floatingpoint_eq) << 1 << 1;
+ Diag(TheCall->getBeginLoc(), diag::warn_fast_floatingpoint_eq) << 1 << 1 << 1 << 1;
bool IsFPClass = NumArgs == 2;
@@ -12900,13 +12900,13 @@ void Sema::CheckInfNaNFunction(const CallExpr *Call,
if ((IsStdFunction(FDecl, "isnan") || IsStdFunction(FDecl, "isunordered") ||
(Call->getBuiltinCallee() == Builtin::BI__builtin_nanf)) &&
FPO.getNoHonorNaNs())
- Diag(Call->getBeginLoc(), diag::warn_fast_floatingpoint_eq) << 1 << 1;
+ Diag(Call->getBeginLoc(), diag::warn_fast_floatingpoint_eq) << 1 << 1 << 1 << 1;
else if ((IsStdFunction(FDecl, "isinf") ||
(IsStdFunction(FDecl, "isfinite") ||
(Call->getBuiltinCallee() == Builtin::BI__builtin_inff)) ||
(FDecl->getIdentifier() && FDecl->getName() == "infinity")) &&
FPO.getNoHonorInfs())
- Diag(Call->getBeginLoc(), diag::warn_fast_floatingpoint_eq) << 0 << 0;
+ Diag(Call->getBeginLoc(), diag::warn_fast_floatingpoint_eq) << 1 << 0 << 1 << 0;
}
// Warn when using the wrong abs() function.
@@ -13899,12 +13899,12 @@ void Sema::CheckInfNaNFloatComparison(SourceLocation Loc, Expr *LHS, Expr *RHS,
if (IsConstant(LHS, LeftExprSansParen, Context) &&
((NoHonorNaNs && Value.isNaN()) || (NoHonorInfs && Value.isInfinity())))
Diag(Loc, diag::warn_fast_floatingpoint_eq)
- << (Value.isNaN() ? 1 : 0) << (Value.isNaN() ? 1 : 0);
+ << 0 << (Value.isNaN() ? 1 : 0) << 0 << (Value.isNaN() ? 1 : 0);
if (IsConstant(RHS, RightExprSansParen, Context) &&
((NoHonorNaNs && Value.isNaN()) || (NoHonorInfs && Value.isInfinity())))
Diag(Loc, diag::warn_fast_floatingpoint_eq)
- << (Value.isNaN() ? 1 : 0) << (Value.isNaN() ? 1 : 0);
+ << 0 << (Value.isNaN() ? 1 : 0) << 0 << (Value.isNaN() ? 1 : 0);
}
/// Check for comparisons of floating-point values using == and !=. Issue a
diff --git a/clang/test/Sema/warn-fp-fast-compare.cpp b/clang/test/Sema/warn-fp-fast-compare.cpp
index 430fb58dfd7473..c6f746c3f8de11 100644
--- a/clang/test/Sema/warn-fp-fast-compare.cpp
+++ b/clang/test/Sema/warn-fp-fast-compare.cpp
@@ -71,149 +71,149 @@ class numeric_limits<double> {
int compareit(float a, float b) {
volatile int i, j, k, l, m, n, o, p;
#if FAST
-// expected-warning at +11 {{use of infinity will always be 'false' because infinity will not be produced according to the currently enabled floating-point options}}
+// expected-warning at +11 {{use of infinity as a function argument will not always be interpreted as such because infinity will not be produced according to the currently enabled floating-point options}}
#endif
#if FAST
-// expected-warning at +8 {{use of infinity will always be 'false' because infinity will not be produced according to the currently enabled floating-point options}}
+// expected-warning at +8 {{explicit comparison with infinity will always return 'false' because infinity will not be produced according to the currently enabled floating-point options}}
#endif
#if NO_INFS
-// expected-warning at +5 {{use of infinity will always be 'false' because infinity will not be produced according to the currently enabled floating-point options}}
+// expected-warning at +5 {{use of infinity as a function argument will not always be interpreted as such because infinity will not be produced according to the currently enabled floating-point options}}
#endif
#if NO_INFS
-// expected-warning at +2 {{use of infinity will always be 'false' because infinity will not be produced according to the currently enabled floating-point options}}
+// expected-warning at +2 {{explicit comparison with infinity will always return 'false' because infinity will not be produced according to the currently enabled floating-point options}}
#endif
i = a == INFINITY;
#if FAST
-// expected-warning at +11 {{use of infinity will always be 'false' because infinity will not be produced according to the currently enabled floating-point options}}
+// expected-warning at +11 {{use of infinity as a function argument will not always be interpreted as such because infinity will not be produced according to the currently enabled floating-point options}}
#endif
#if FAST
-// expected-warning at +8 {{use of infinity will always be 'false' because infinity will not be produced according to the currently enabled floating-point options}}
+// expected-warning at +8 {{explicit comparison with infinity will always return 'false' because infinity will not be produced according to the currently enabled floating-point options}}
#endif
#if NO_INFS
-// expected-warning at +5 {{use of infinity will always be 'false' because infinity will not be produced according to the currently enabled floating-point options}}
+// expected-warning at +5 {{use of infinity as a function argument will not always be interpreted as such because infinity will not be produced according to the currently enabled floating-point options}}
#endif
#if NO_INFS
-// expected-warning at +2 {{use of infinity will always be 'false' because infinity will not be produced according to the currently enabled floating-point options}}
+// expected-warning at +2 {{explicit comparison with infinity will always return 'false' because infinity will not be produced according to the currently enabled floating-point options}}
#endif
j = INFINITY == a;
#if FAST
-// expected-warning at +11 {{use of NaN will always be 'false' because NaN will not be produced according to the currently enabled floating-point options}}
+// expected-warning at +11 {{use of nan as a function argument will not always be interpreted as such because nan will not be produced according to the currently enabled floating-point options}}
#endif
#if FAST
-// expected-warning at +8 {{use of NaN will always be 'false' because NaN will not be produced according to the currently enabled floating-point options}}
+// expected-warning at +8 {{explicit comparison with nan will always return 'false' because nan will not be produced according to the currently enabled floating-point options}}
#endif
#if NO_NANS
-// expected-warning at +5 {{use of NaN will always be 'false' because NaN will not be produced according to the currently enabled floating-point options}}
+// expected-warning at +5 {{use of nan as a function argument will not always be interpreted as such because nan will not be produced according to the currently enabled floating-point options}}
#endif
#if NO_NANS
-// expected-warning at +2 {{use of NaN will always be 'false' because NaN will not be produced according to the currently enabled floating-point options}}
+// expected-warning at +2 {{explicit comparison with nan will always return 'false' because nan will not be produced according to the currently enabled floating-point options}}
#endif
i = a == NAN;
#if FAST
-// expected-warning at +11 {{use of NaN will always be 'false' because NaN will not be produced according to the currently enabled floating-point options}}
+// expected-warning at +11 {{use of nan as a function argument will not always be interpreted as such because nan will not be produced according to the currently enabled floating-point options}}
#endif
#if FAST
-// expected-warning at +8 {{use of NaN will always be 'false' because NaN will not be produced according to the currently enabled floating-point options}}
+// expected-warning at +8 {{explicit comparison with nan will always return 'false' because nan will not be produced according to the currently enabled floating-point options}}
#endif
#if NO_NANS
-// expected-warning at +5 {{use of NaN will always be 'false' because NaN will not be produced according to the currently enabled floating-point options}}
+// expected-warning at +5 {{use of nan as a function argument will not always be interpreted as such because nan will not be produced according to the currently enabled floating-point options}}
#endif
#if NO_NANS
-// expected-warning at +2 {{use of NaN will always be 'false' because NaN will not be produced according to the currently enabled floating-point options}}
+// expected-warning at +2 {{explicit comparison with nan will always return 'false' because nan will not be produced according to the currently enabled floating-point options}}
#endif
j = NAN == a;
#if FAST
-// expected-warning at +11 {{use of infinity will always be 'false' because infinity will not be produced according to the currently enabled floating-point options}}
+// expected-warning at +11 {{use of infinity as a function argument will not always be interpreted as such because infinity will not be produced according to the currently enabled floating-point options}}
#endif
#if FAST
-// expected-warning at +8 {{use of infinity will always be 'false' because infinity will not be produced according to the currently enabled floating-point options}}
+// expected-warning at +8 {{explicit comparison with infinity will always return 'false' because infinity will not be produced according to the currently enabled floating-point options}}
#endif
#if NO_INFS
-// expected-warning at +5 {{use of infinity will always be 'false' because infinity will not be produced according to the currently enabled floating-point options}}
+// expected-warning at +5 {{use of infinity as a function argument will not always be interpreted as such because infinity will not be produced according to the currently enabled floating-point options}}
#endif
#if NO_INFS
-// expected-warning at +2 {{use of infinity will always be 'false' because infinity will not be produced according to the currently enabled floating-point options}}
+// expected-warning at +2 {{explicit comparison with infinity will always return 'false' because infinity will not be produced according to the currently enabled floating-point options}}
#endif
j = INFINITY <= a;
#if FAST
-// expected-warning at +11 {{use of infinity will always be 'false' because infinity will not be produced according to the currently enabled floating-point options}}
+// expected-warning at +11 {{use of infinity as a function argument will not always be interpreted as such because infinity will not be produced according to the currently enabled floating-point options}}
#endif
#if FAST
-// expected-warning at +8 {{use of infinity will always be 'false' because infinity will not be produced according to the currently enabled floating-point options}}
+// expected-warning at +8 {{explicit comparison with infinity will always return 'false' because infinity will not be produced according to the currently enabled floating-point options}}
#endif
#if NO_INFS
- // expected-warning at +5 {{use of infinity will always be 'false' because infinity will not be produced according to the currently enabled floating-point options}}
+// expected-warning at +5 {{use of infinity as a function argument will not always be interpreted as such because infinity will not be produced according to the currently enabled floating-point options}}
#endif
#if NO_INFS
-// expected-warning at +2 {{use of infinity will always be 'false' because infinity will not be produced according to the currently enabled floating-point options}}
+// expected-warning at +2 {{explicit comparison with infinity will always return 'false' because infinity will not be produced according to the currently enabled floating-point options}}
#endif
j = INFINITY < a;
#if FAST
-// expected-warning at +11 {{use of NaN will always be 'false' because NaN will not be produced according to the currently enabled floating-point options}}
+// expected-warning at +11 {{use of nan as a function argument will not always be interpreted as such because nan will not be produced according to the currently enabled floating-point options}}
#endif
#if FAST
-// expected-warning at +8 {{use of NaN will always be 'false' because NaN will not be produced according to the currently enabled floating-point options}}
+// expected-warning at +8 {{explicit comparison with nan will always return 'false' because nan will not be produced according to the currently enabled floating-point options}}
#endif
#if NO_NANS
-// expected-warning at +5 {{use of NaN will always be 'false' because NaN will not be produced according to the currently enabled floating-point options}}
+// expected-warning at +5 {{use of nan as a function argument will not always be interpreted as such because nan will not be produced according to the currently enabled floating-point options}}
#endif
#if NO_NANS
- // expected-warning at +2 {{use of NaN will always be 'false' because NaN will not be produced according to the currently enabled floating-point options}}
+// expected-warning at +2 {{explicit comparison with nan will always return 'false' because nan will not be produced according to the currently enabled floating-point options}}
#endif
j = a > NAN;
#if FAST
-// expected-warning at +11 {{use of NaN will always be 'false' because NaN will not be produced according to the currently enabled floating-point options}}
+// expected-warning at +11 {{use of nan as a function argument will not always be interpreted as such because nan will not be produced according to the currently enabled floating-point options}}
#endif
#if FAST
-// expected-warning at +8 {{use of NaN will always be 'false' because NaN will not be produced according to the currently enabled floating-point options}}
+// expected-warning at +8 {{explicit comparison with nan will always return 'false' because nan will not be produced according to the currently enabled floating-point options}}
#endif
#if NO_NANS
-// expected-warning at +5 {{use of NaN will always be 'false' because NaN will not be produced according to the currently enabled floating-point options}}
+// expected-warning at +5 {{use of nan as a function argument will not always be interpreted as such because nan will not be produced according to the currently enabled floating-point options}}
#endif
#if NO_NANS
-// expected-warning at +2 {{use of NaN will always be 'false' because NaN will not be produced according to the currently enabled floating-point options}}
+// expected-warning at +2 {{explicit comparison with nan will always return 'false' because nan will not be produced according to the currently enabled floating-point options}}
#endif
j = a >= NAN;
#if FAST
-// expected-warning at +5 {{use of infinity will always be 'false' because infinity will not be produced according to the currently enabled floating-point options}}
+// expected-warning at +5 {{use of infinity as a function argument will not always be interpreted as such because infinity will not be produced according to the currently enabled floating-point options}}
#endif
#if NO_INFS
-// expected-warning at +2 {{use of infinity will always be 'false' because infinity will not be produced according to the currently enabled floating-point options}}
+// expected-warning at +2 {{use of infinity as a function argument will not always be interpreted as such because infinity will not be produced according to the currently enabled floating-point options}}
#endif
-k = std::isinf(a);
+ k = std::isinf(a);
#if FAST
-// expected-warning at +5 {{use of NaN will always be 'false' because NaN will not be produced according to the currently enabled floating-point options}}
+// expected-warning at +5 {{use of nan as a function argument will not always be interpreted as such because nan will not be produced according to the currently enabled floating-point options}}
#endif
#if NO_NANS
-// expected-warning at +2 {{use of NaN will always be 'false' because NaN will not be produced according to the currently enabled floating-point options}}
+// expected-warning at +2 {{use of nan as a function argument will not always be interpreted as such because nan will not be produced according to the currently enabled floating-point options}}
#endif
l = std::isnan(a);
#if FAST
-// expected-warning at +5 {{use of infinity will always be 'false' because infinity will not be produced according to the currently enabled floating-point options}}
+// expected-warning at +5 {{use of infinity as a function argument will not always be interpreted as such because infinity will not be produced according to the currently enabled floating-point options}}
#endif
#if NO_INFS
-// expected-warning at +2 {{use of infinity will always be 'false' because infinity will not be produced according to the currently enabled floating-point options}}
+// expected-warning at +2 {{use of infinity as a function argument will not always be interpreted as such because infinity will not be produced according to the currently enabled floating-point options}}
#endif
o = std::isfinite(a);
#if FAST
-// expected-warning at +5 {{use of infinity will always be 'false' because infinity will not be produced according to the currently enabled floating-point options}}
+// expected-warning at +5 {{explicit comparison with infinity will always return 'false' because infinity will not be produced according to the currently enabled floating-point options}}
#endif
#if NO_INFS
-// expected-warning at +2 {{use of infinity will always be 'false' because infinity will not be produced according to the currently enabled floating-point options}}
+// expected-warning at +2 {{explicit comparison with infinity will always return 'false' because infinity will not be produced according to the currently enabled floating-point options}}
#endif
m = __builtin_isinf(a);
#if FAST
-// expected-warning at +5 {{use of NaN will always be 'false' because NaN will not be produced according to the currently enabled floating-point options}}
+// expected-warning at +5 {{use of nan as a function argument will not always be interpreted as such because nan will not be produced according to the currently enabled floating-point options}}
#endif
#if NO_NANS
-// expected-warning at +2 {{use of NaN will always be 'false' because NaN will not be produced according to the currently enabled floating-point options}}
+// expected-warning at +2 {{use of nan as a function argument will not always be interpreted as such because nan will not be produced according to the currently enabled floating-point options}}
#endif
n = __builtin_isnan(a);
#if FAST
-// expected-warning at +5 {{use of infinity will always be 'false' because infinity will not be produced according to the currently enabled floating-point options}}
+// expected-warning at +5 {{explicit comparison with infinity will always return 'false' because infinity will not be produced according to the currently enabled floating-point options}}
#endif
#if NO_INFS
-// expected-warning at +2 {{use of infinity will always be 'false' because infinity will not be produced according to the currently enabled floating-point options}}
+// expected-warning at +2 {{explicit comparison with infinity will always return 'false' because infinity will not be produced according to the currently enabled floating-point options}}
#endif
p = __builtin_isfinite(a);
@@ -225,58 +225,58 @@ k = std::isinf(a);
j = isunorderedf(a, b);
#if FAST
-// expected-warning at +5 {{use of NaN will always be 'false' because NaN will not be produced according to the currently enabled floating-point options}}
+// expected-warning at +5 {{use of nan as a function argument will not always be interpreted as such because nan will not be produced according to the currently enabled floating-point options}}
#endif
#if NO_NANS
-// expected-warning at +2 {{use of NaN will always be 'false' because NaN will not be produced according to the currently enabled floating-point options}}
+// expected-warning at +2 {{use of nan as a function argument will not always be interpreted as such because nan will not be produced according to the currently enabled floating-point options}}
#endif
j = isunorderedf(a, NAN);
#if FAST
-// expected-warning at +5 {{use of infinity will always be 'false' because infinity will not be produced according to the currently enabled floating-point options}}
+// expected-warning at +5 {{use of infinity as a function argument will not always be interpreted as such because infinity will not be produced according to the currently enabled floating-point options}}
#endif
#if NO_INFS
-// expected-warning at +2 {{use of infinity will always be 'false' because infinity will not be produced according to the currently enabled floating-point options}}
+// expected-warning at +2 {{use of infinity as a function argument will not always be interpreted as such because infinity will not be produced according to the currently enabled floating-point options}}
#endif
j = isunorderedf(a, INFINITY);
#if FAST
-// expected-warning at +11 {{use of NaN will always be 'false' because NaN will not be produced according to the currently enabled floating-point options}}
+// expected-warning at +11 {{use of nan as a function argument will not always be interpreted as such because nan will not be produced according to the currently enabled floating-point options}}
#endif
#if FAST
-// expected-warning at +8 {{use of NaN will always be 'false' because NaN will not be produced according to the currently enabled floating-point options}}
+// expected-warning at +8 {{use of nan as a function argument will not always be interpreted as such because nan will not be produced according to the currently enabled floating-point options}}
#endif
#if NO_NANS
-// expected-warning at +5 {{use of NaN will always be 'false' because NaN will not be produced according to the currently enabled floating-point options}}
+// expected-warning at +5 {{use of nan as a function argument will not always be interpreted as such because nan will not be produced according to the currently enabled floating-point options}}
#endif
#if NO_NANS
-// expected-warning at +2 {{use of NaN will always be 'false' because NaN will not be produced according to the currently enabled floating-point options}}
+// expected-warning at +2 {{use of nan as a function argument will not always be interpreted as such because nan will not be produced according to the currently enabled floating-point options}}
#endif
i = std::isunordered(a, NAN);
#if FAST
-// expected-warning at +11 {{use of infinity will always be 'false' because infinity will not be produced according to the currently enabled floating-point options}}
+// expected-warning at +11 {{use of infinity as a function argument will not always be interpreted as such because infinity will not be produced according to the currently enabled floating-point options}}
#endif
#if FAST
-// expected-warning at +8 {{use of NaN will always be 'false' because NaN will not be produced according to the currently enabled floating-point options}}
-#endif
-#if NO_NANS
-// expected-warning at +5 {{use of NaN will always be 'false' because NaN will not be produced according to the currently enabled floating-point options}}
+// expected-warning at +8 {{use of nan as a function argument will not always be interpreted as such because nan will not be produced according to the currently enabled floating-point options}}
#endif
#if NO_INFS
-// expected-warning at +2 {{use of infinity will always be 'false' because infinity will not be produced according to the currently enabled floating-point options}}
+// expected-warning at +5 {{use of infinity as a function argument will not always be interpreted as such because infinity will not be produced according to the currently enabled floating-point options}}
+#endif
+#if NO_NANS
+// expected-warning at +2 {{use of nan as a function argument will not always be interpreted as such because nan will not be produced according to the currently enabled floating-point options}}
#endif
i = std::isunordered(a, INFINITY);
#if FAST
-// expected-warning at +5 {{use of infinity will always be 'false' because infinity will not be produced according to the currently enabled floating-point options}}
+// expected-warning at +5 {{use of infinity as a function argument will not always be interpreted as such because infinity will not be produced according to the currently enabled floating-point options}}
#endif
#if NO_INFS
-// expected-warning at +2 {{use of infinity will always be 'false' because infinity will not be produced according to the currently enabled floating-point options}}
+// expected-warning at +2 {{use of infinity as a function argument will not always be interpreted as such because infinity will not be produced according to the currently enabled floating-point options}}
#endif
double y = i * numeric_limits<double>::infinity();
#if FAST
-// expected-warning at +5 {{use of infinity will always be 'false' because infinity will not be produced according to the currently enabled floating-point options}}
+// expected-warning at +5 {{use of infinity as a function argument will not always be interpreted as such because infinity will not be produced according to the currently enabled floating-point options}}
#endif
#if NO_INFS
-// expected-warning at +2 {{use of infinity will always be 'false' because infinity will not be produced according to the currently enabled floating-point options}}
+// expected-warning at +2 {{use of infinity as a function argument will not always be interpreted as such because infinity will not be produced according to the currently enabled floating-point options}}
#endif
j = numeric_limits<float>::infinity();
return 0;
>From b603724027071ae75ce509f69c3dbb8445edd42f Mon Sep 17 00:00:00 2001
From: Ammarguellat <zahira.ammarguellat at intel.com>
Date: Sat, 13 Jan 2024 08:23:24 -0800
Subject: [PATCH 5/5] Fix format.
---
clang/lib/Sema/SemaChecking.cpp | 17 +++++++++++------
1 file changed, 11 insertions(+), 6 deletions(-)
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index f2a49f89b9b1ec..4a8078a772006e 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -9098,7 +9098,8 @@ bool Sema::SemaBuiltinUnorderedCompare(CallExpr *TheCall, unsigned BuiltinID) {
if (BuiltinID == Builtin::BI__builtin_isunordered &&
TheCall->getFPFeaturesInEffect(getLangOpts()).getNoHonorNaNs())
- Diag(TheCall->getBeginLoc(), diag::warn_fast_floatingpoint_eq) << 0 << 1 << 0 << 1;
+ Diag(TheCall->getBeginLoc(), diag::warn_fast_floatingpoint_eq)
+ << 0 << 1 << 0 << 1;
ExprResult OrigArg0 = TheCall->getArg(0);
ExprResult OrigArg1 = TheCall->getArg(1);
@@ -9143,10 +9144,12 @@ bool Sema::SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs,
if (FPO.getNoHonorInfs() && (BuiltinID == Builtin::BI__builtin_isfinite ||
BuiltinID == Builtin::BI__builtin_isinf ||
BuiltinID == Builtin::BI__builtin_isinf_sign))
- Diag(TheCall->getBeginLoc(), diag::warn_fast_floatingpoint_eq) << 0 << 0 << 0 << 0;
+ Diag(TheCall->getBeginLoc(), diag::warn_fast_floatingpoint_eq)
+ << 0 << 0 << 0 << 0;
if (FPO.getNoHonorNaNs() && (BuiltinID == Builtin::BI__builtin_isnan ||
BuiltinID == Builtin::BI__builtin_isunordered))
- Diag(TheCall->getBeginLoc(), diag::warn_fast_floatingpoint_eq) << 1 << 1 << 1 << 1;
+ Diag(TheCall->getBeginLoc(), diag::warn_fast_floatingpoint_eq)
+ << 1 << 1 << 1 << 1;
bool IsFPClass = NumArgs == 2;
@@ -12900,13 +12903,15 @@ void Sema::CheckInfNaNFunction(const CallExpr *Call,
if ((IsStdFunction(FDecl, "isnan") || IsStdFunction(FDecl, "isunordered") ||
(Call->getBuiltinCallee() == Builtin::BI__builtin_nanf)) &&
FPO.getNoHonorNaNs())
- Diag(Call->getBeginLoc(), diag::warn_fast_floatingpoint_eq) << 1 << 1 << 1 << 1;
+ Diag(Call->getBeginLoc(), diag::warn_fast_floatingpoint_eq)
+ << 1 << 1 << 1 << 1;
else if ((IsStdFunction(FDecl, "isinf") ||
(IsStdFunction(FDecl, "isfinite") ||
(Call->getBuiltinCallee() == Builtin::BI__builtin_inff)) ||
(FDecl->getIdentifier() && FDecl->getName() == "infinity")) &&
FPO.getNoHonorInfs())
- Diag(Call->getBeginLoc(), diag::warn_fast_floatingpoint_eq) << 1 << 0 << 1 << 0;
+ Diag(Call->getBeginLoc(), diag::warn_fast_floatingpoint_eq)
+ << 1 << 0 << 1 << 0;
}
// Warn when using the wrong abs() function.
@@ -13904,7 +13909,7 @@ void Sema::CheckInfNaNFloatComparison(SourceLocation Loc, Expr *LHS, Expr *RHS,
if (IsConstant(RHS, RightExprSansParen, Context) &&
((NoHonorNaNs && Value.isNaN()) || (NoHonorInfs && Value.isInfinity())))
Diag(Loc, diag::warn_fast_floatingpoint_eq)
- << 0 << (Value.isNaN() ? 1 : 0) << 0 << (Value.isNaN() ? 1 : 0);
+ << 0 << (Value.isNaN() ? 1 : 0) << 0 << (Value.isNaN() ? 1 : 0);
}
/// Check for comparisons of floating-point values using == and !=. Issue a
More information about the cfe-commits
mailing list