-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[CLANG] Add warning when INF or NAN are used in a binary operation or as function argument in fast math mode. #76873
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
7dbaf03
[CLANG] Add warning when comparing to INF or NAN in fast math mode.
zahiraam f4aa379
Addressed review comments.
zahiraam 948ace7
Addressed review comments.
zahiraam d82f569
Fixed the diagnostic message.
zahiraam b603724
Fix format.
zahiraam 51db96f
Merge remote-tracking branch 'origin/main' into WarnInfNanFastMode
zahiraam 0b2cec2
After discussion with Aaron separated the warning so one is triggered
zahiraam 71431de
Fixed the diagnostics and RN.
zahiraam c874335
Fixed diag's comment and added NAN to the macro testing.
zahiraam c0bd9e5
Fixed LIT tests, RN and warning message.
zahiraam 3506625
Fix LIT tests.
zahiraam File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,176 @@ | ||
// RUN: %clang_cc1 -x c++ -verify=no-inf-no-nan -triple powerpc64le-unknown-unknown %s \ | ||
// RUN: -menable-no-infs -menable-no-nans | ||
|
||
// RUN: %clang_cc1 -x c++ -verify=no-fast -triple powerpc64le-unknown-unknown %s | ||
|
||
// RUN: %clang_cc1 -x c++ -verify=no-inf -triple powerpc64le-unknown-unknown %s \ | ||
// RUN: -menable-no-infs | ||
|
||
// RUN: %clang_cc1 -x c++ -verify=no-nan -triple powerpc64le-unknown-unknown %s \ | ||
// RUN: -menable-no-nans | ||
|
||
// no-fast-no-diagnostics | ||
|
||
int isunorderedf (float x, float y); | ||
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()) | ||
|
||
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; | ||
// no-inf-no-nan-warning@+2 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}} | ||
// no-inf-warning@+1 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}} | ||
i = a == INFINITY; | ||
|
||
// no-inf-no-nan-warning@+2 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}} | ||
// no-inf-warning@+1 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}} | ||
j = INFINITY == a; | ||
|
||
// no-inf-no-nan-warning@+4 {{use of NaN is undefined behavior due to the currently enabled floating-point options}} | ||
// no-inf-no-nan-warning@+3 {{use of NaN via a macro is undefined behavior due to the currently enabled floating-point options}} | ||
// no-nan-warning@+2 {{use of NaN via a macro is undefined behavior due to the currently enabled floating-point options}} | ||
// no-nan-warning@+1 {{use of NaN is undefined behavior due to the currently enabled floating-point options}} | ||
i = a == NAN; | ||
|
||
// no-inf-no-nan-warning@+4 {{use of NaN via a macro is undefined behavior due to the currently enabled floating-point options}} | ||
// no-inf-no-nan-warning@+3 {{use of NaN is undefined behavior due to the currently enabled floating-point options}} | ||
// no-nan-warning@+2 {{use of NaN is undefined behavior due to the currently enabled floating-point options}} | ||
// no-nan-warning@+1 {{use of NaN via a macro is undefined behavior due to the currently enabled floating-point options}} | ||
j = NAN == a; | ||
|
||
// no-inf-no-nan-warning@+2 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}} | ||
// no-inf-warning@+1 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}} | ||
j = INFINITY <= a; | ||
|
||
// no-inf-no-nan-warning@+2 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}} | ||
// no-inf-warning@+1 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}} | ||
j = INFINITY < a; | ||
|
||
// no-inf-no-nan-warning@+4 {{use of NaN via a macro is undefined behavior due to the currently enabled floating-point options}} | ||
// no-inf-no-nan-warning@+3 {{use of NaN is undefined behavior due to the currently enabled floating-point options}} | ||
// no-nan-warning@+2 {{use of NaN via a macro is undefined behavior due to the currently enabled floating-point options}} | ||
// no-nan-warning@+1 {{use of NaN is undefined behavior due to the currently enabled floating-point options}} | ||
j = a > NAN; | ||
|
||
// no-inf-no-nan-warning@+4 {{use of NaN via a macro is undefined behavior due to the currently enabled floating-point options}} | ||
// no-inf-no-nan-warning@+3 {{use of NaN is undefined behavior due to the currently enabled floating-point options}} | ||
// no-nan-warning@+2 {{use of NaN is undefined behavior due to the currently enabled floating-point options}} | ||
// no-nan-warning@+1 {{use of NaN via a macro is undefined behavior due to the currently enabled floating-point options}} | ||
j = a >= NAN; | ||
|
||
// no-inf-no-nan-warning@+2 {{use of infinity is undefined behavior due to the currently enabled floating-point options}} | ||
// no-inf-warning@+1 {{use of infinity is undefined behavior due to the currently enabled floating-point options}} | ||
k = std::isinf(a); | ||
|
||
// no-inf-no-nan-warning@+2 {{use of NaN is undefined behavior due to the currently enabled floating-point option}} | ||
// no-nan-warning@+1 {{use of NaN is undefined behavior due to the currently enabled floating-point options}} | ||
l = std::isnan(a); | ||
|
||
// no-inf-no-nan-warning@+2 {{use of infinity is undefined behavior due to the currently enabled floating-point options}} | ||
// no-inf-warning@+1 {{use of infinity is undefined behavior due to the currently enabled floating-point options}} | ||
o = std::isfinite(a); | ||
|
||
// no-inf-no-nan-warning@+2 {{use of infinity is undefined behavior due to the currently enabled floating-point options}} | ||
// no-inf-warning@+1 {{use of infinity is undefined behavior due to the currently enabled floating-point options}} | ||
m = __builtin_isinf(a); | ||
|
||
// no-inf-no-nan-warning@+2 {{use of NaN is undefined behavior due to the currently enabled floating-point options}} | ||
// no-nan-warning@+1 {{use of NaN is undefined behavior due to the currently enabled floating-point options}} | ||
n = __builtin_isnan(a); | ||
|
||
// no-inf-no-nan-warning@+2 {{use of infinity is undefined behavior due to the currently enabled floating-point options}} | ||
// no-inf-warning@+1 {{use of infinity is undefined behavior due to the currently enabled floating-point options}} | ||
p = __builtin_isfinite(a); | ||
|
||
// These should NOT warn, since they are not using NaN or infinity. | ||
j = a > 1.1; | ||
j = b < 1.1; | ||
j = a >= 1.1; | ||
j = b <= 1.1; | ||
j = isunorderedf(a, b); | ||
|
||
// no-inf-no-nan-warning@+4 {{use of NaN via a macro is undefined behavior due to the currently enabled floating-point options}} | ||
// no-inf-no-nan-warning@+3 {{use of NaN is undefined behavior due to the currently enabled floating-point options}} | ||
// no-nan-warning@+2 {{use of NaN via a macro is undefined behavior due to the currently enabled floating-point options}} | ||
// no-nan-warning@+1 {{use of NaN is undefined behavior due to the currently enabled floating-point options}} | ||
j = isunorderedf(a, NAN); | ||
|
||
// no-inf-no-nan-warning@+2 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}} | ||
// no-inf-warning@+1 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}} | ||
j = isunorderedf(a, INFINITY); | ||
|
||
// no-inf-no-nan-warning@+6 {{use of NaN via a macro is undefined behavior due to the currently enabled floating-point options}} | ||
// no-inf-no-nan-warning@+5 {{use of NaN is undefined behavior due to the currently enabled floating-point options}} | ||
// no-inf-no-nan-warning@+4 {{use of NaN is undefined behavior due to the currently enabled floating-point options}} | ||
// no-nan-warning@+3 {{use of NaN via a macro is undefined behavior due to the currently enabled floating-point options}} | ||
// no-nan-warning@+2 {{use of NaN is undefined behavior due to the currently enabled floating-point options}} | ||
// no-nan-warning@+1 {{use of NaN is undefined behavior due to the currently enabled floating-point options}} | ||
i = std::isunordered(a, NAN); | ||
|
||
// no-inf-no-nan-warning@+4 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}} | ||
// no-inf-no-nan-warning@+3 {{use of NaN is undefined behavior due to the currently enabled floating-point options}} | ||
// no-inf-warning@+2 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}} | ||
// no-nan-warning@+1 {{use of NaN is undefined behavior due to the currently enabled floating-point options}} | ||
i = std::isunordered(a, INFINITY); | ||
|
||
// no-inf-no-nan-warning@+2 {{use of infinity is undefined behavior due to the currently enabled floating-point options}} | ||
// no-inf-warning@+1 {{use of infinity is undefined behavior due to the currently enabled floating-point options}} | ||
double y = i * numeric_limits<double>::infinity(); | ||
|
||
// no-inf-no-nan-warning@+2 {{use of infinity is undefined behavior due to the currently enabled floating-point options}} | ||
// no-inf-warning@+1 {{use of infinity is undefined behavior due to the currently enabled floating-point options}} | ||
j = numeric_limits<float>::infinity(); | ||
return 0; | ||
|
||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about
NAN
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since NAN is defined as (-(float)(INFINITY * 0.0F)) when used in the program it will trigger the "use of infinity via a macro results in undefined behavior due to the currently enabled floating-point options [-Wnan-and-infinity-disabled]". Wouldn't that be enough? If I add NaN here we would get 2 warnings.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because there are other C standard libraries which do something different. For example, musl: https://git.musl-libc.org/cgit/musl/tree/include/math.h#n18
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is actually a bit unfortunate. If I use "-fhonor-nans -fno-honor-infinities" this definition of NAN will trigger a warning, even though I expect that we'll constant-fold it as expected without regard to the "no-honor-infinities" setting.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We will?
the multiplication for
INFINITY
won't form an actual infinity value in that case, so why would the multiplication with0.0
not generate a NAN macro that folds to 0.0F?If use of
INFINITY
is undefined behavior when-fno-honor-infinities
is passed... it makes sense to me that the definition ofNAN
usingINFINITY
is UB by the same logic.