[clang] 1e2a4cc - [CLANG] Add warning when INF or NAN are used in a binary operation or as function argument in fast math mode. (#76873)

via cfe-commits cfe-commits at lists.llvm.org
Mon Jan 22 11:38:34 PST 2024


Author: Zahira Ammarguellat
Date: 2024-01-22T14:38:30-05:00
New Revision: 1e2a4ccb6237b6db9db7dc3fd11a94410ec9b0df

URL: https://github.com/llvm/llvm-project/commit/1e2a4ccb6237b6db9db7dc3fd11a94410ec9b0df
DIFF: https://github.com/llvm/llvm-project/commit/1e2a4ccb6237b6db9db7dc3fd11a94410ec9b0df.diff

LOG: [CLANG] Add warning when INF or NAN are used in a binary operation or as function argument in fast math mode. (#76873)

Check for operations using INF or NaN when in ffast-math mode and
generate a warning.

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

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/include/clang/Basic/DiagnosticCommonKinds.td
    clang/include/clang/Lex/Preprocessor.h
    clang/include/clang/Sema/Sema.h
    clang/lib/Lex/Preprocessor.cpp
    clang/lib/Sema/SemaChecking.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 5846503af3acdf..13e6c5e8db3ea9 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -596,6 +596,11 @@ 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.
+- The warning `-Wnan-infinity-disabled` is now emitted when ``INFINITY``
+  or ``NAN`` are used in arithmetic operations or function arguments in
+  floating-point mode where ``INFINITY`` or ``NAN`` don't have the expected
+  values.
+
 - Clang now diagnoses attempts to bind a bitfield to an NTTP of a reference type as erroneous
   converted constant expression and not as a reference to subobject.
 - Clang now diagnoses ``auto`` and ``decltype(auto)`` in declarations of conversion function template

diff  --git a/clang/include/clang/Basic/DiagnosticCommonKinds.td b/clang/include/clang/Basic/DiagnosticCommonKinds.td
index 5544dc88004d9a..b1bada65cb6b28 100644
--- a/clang/include/clang/Basic/DiagnosticCommonKinds.td
+++ b/clang/include/clang/Basic/DiagnosticCommonKinds.td
@@ -70,6 +70,10 @@ def warn_pragma_debug_missing_argument : Warning<
 def warn_pragma_debug_unexpected_argument : Warning<
   "unexpected argument to debug command">, InGroup<IgnoredPragmas>;
 
+def warn_fp_nan_inf_when_disabled : Warning<
+  "use of %select{infinity|NaN}0%select{| via a macro}1 is undefined behavior "
+  "due to the currently enabled floating-point options">,
+  InGroup<DiagGroup<"nan-infinity-disabled">>;
 }
 
 // Parse && Sema

diff  --git a/clang/include/clang/Lex/Preprocessor.h b/clang/include/clang/Lex/Preprocessor.h
index 4ec21a8b6be2c8..fed3c1b7703837 100644
--- a/clang/include/clang/Lex/Preprocessor.h
+++ b/clang/include/clang/Lex/Preprocessor.h
@@ -2835,6 +2835,13 @@ class Preprocessor {
     if (Identifier.getIdentifierInfo()->isRestrictExpansion() &&
         !SourceMgr.isInMainFile(Identifier.getLocation()))
       emitRestrictExpansionWarning(Identifier);
+
+    if (Identifier.getIdentifierInfo()->getName() == "INFINITY")
+      if (getLangOpts().NoHonorInfs)
+        emitRestrictInfNaNWarning(Identifier, 0);
+    if (Identifier.getIdentifierInfo()->getName() == "NAN")
+      if (getLangOpts().NoHonorNaNs)
+        emitRestrictInfNaNWarning(Identifier, 1);
   }
 
   static void processPathForFileMacro(SmallVectorImpl<char> &Path,
@@ -2850,6 +2857,8 @@ class Preprocessor {
   void emitMacroDeprecationWarning(const Token &Identifier) const;
   void emitRestrictExpansionWarning(const Token &Identifier) const;
   void emitFinalMacroWarning(const Token &Identifier, bool IsUndef) const;
+  void emitRestrictInfNaNWarning(const Token &Identifier,
+                                 unsigned DiagSelection) const;
 
   /// This boolean state keeps track if the current scanned token (by this PP)
   /// is in an "-Wunsafe-buffer-usage" opt-out region. Assuming PP scans a

diff  --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index d0f62afdf7bb16..1f1cbd11ff7358 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -13932,8 +13932,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);
@@ -14037,6 +14038,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);
 

diff  --git a/clang/lib/Lex/Preprocessor.cpp b/clang/lib/Lex/Preprocessor.cpp
index 64f54c6fc6382f..7fdb5d4c0d7b82 100644
--- a/clang/lib/Lex/Preprocessor.cpp
+++ b/clang/lib/Lex/Preprocessor.cpp
@@ -1457,6 +1457,11 @@ void Preprocessor::emitRestrictExpansionWarning(const Token &Identifier) const {
   Diag(Info.Location, diag::note_pp_macro_annotation) << 1;
 }
 
+void Preprocessor::emitRestrictInfNaNWarning(const Token &Identifier,
+                                             unsigned DiagSelection) const {
+  Diag(Identifier, diag::warn_fp_nan_inf_when_disabled) << DiagSelection << 1;
+}
+
 void Preprocessor::emitFinalMacroWarning(const Token &Identifier,
                                          bool IsUndef) const {
   const MacroAnnotations &A =

diff  --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 3e0d94e8176348..28f5667a1b6ba1 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,15 +2246,15 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
   case Builtin::BI__builtin_islessequal:
   case Builtin::BI__builtin_islessgreater:
   case Builtin::BI__builtin_isunordered:
-    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:
@@ -2267,7 +2268,7 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
   case Builtin::BI__builtin_signbit:
   case Builtin::BI__builtin_signbitf:
   case Builtin::BI__builtin_signbitl:
-    if (SemaBuiltinFPClassification(TheCall, 1))
+    if (SemaBuiltinFPClassification(TheCall, 1, BuiltinID))
       return ExprError();
     break;
   case Builtin::BI__builtin_shufflevector:
@@ -7648,6 +7649,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);
@@ -9117,10 +9119,15 @@ 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 &&
+      TheCall->getFPFeaturesInEffect(getLangOpts()).getNoHonorNaNs())
+    Diag(TheCall->getBeginLoc(), diag::warn_fp_nan_inf_when_disabled)
+        << 1 << 0 << TheCall->getSourceRange();
+
   ExprResult OrigArg0 = TheCall->getArg(0);
   ExprResult OrigArg1 = TheCall->getArg(1);
 
@@ -9155,10 +9162,23 @@ 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_fp_nan_inf_when_disabled)
+        << 0 << 0 << TheCall->getSourceRange();
+
+  if (FPO.getNoHonorNaNs() && (BuiltinID == Builtin::BI__builtin_isnan ||
+                               BuiltinID == Builtin::BI__builtin_isunordered))
+    Diag(TheCall->getBeginLoc(), diag::warn_fp_nan_inf_when_disabled)
+        << 1 << 0 << TheCall->getSourceRange();
+
   bool IsFPClass = NumArgs == 2;
 
   // Find out position of floating-point argument.
@@ -12905,6 +12925,22 @@ static bool IsStdFunction(const FunctionDecl *FDecl,
   return true;
 }
 
+void Sema::CheckInfNaNFunction(const CallExpr *Call,
+                               const FunctionDecl *FDecl) {
+  FPOptions FPO = Call->getFPFeaturesInEffect(getLangOpts());
+  if ((IsStdFunction(FDecl, "isnan") || IsStdFunction(FDecl, "isunordered") ||
+       (Call->getBuiltinCallee() == Builtin::BI__builtin_nanf)) &&
+      FPO.getNoHonorNaNs())
+    Diag(Call->getBeginLoc(), diag::warn_fp_nan_inf_when_disabled)
+        << 1 << 0 << Call->getSourceRange();
+  else if ((IsStdFunction(FDecl, "isinf") ||
+            (IsStdFunction(FDecl, "isfinite") ||
+             (FDecl->getIdentifier() && FDecl->getName() == "infinity"))) &&
+           FPO.getNoHonorInfs())
+    Diag(Call->getBeginLoc(), diag::warn_fp_nan_inf_when_disabled)
+        << 0 << 0 << Call->getSourceRange();
+}
+
 // Warn when using the wrong abs() function.
 void Sema::CheckAbsoluteValueFunction(const CallExpr *Call,
                                       const FunctionDecl *FDecl) {

diff  --git a/clang/test/Sema/warn-infinity-nan-disabled-lnx.cpp b/clang/test/Sema/warn-infinity-nan-disabled-lnx.cpp
new file mode 100644
index 00000000000000..8a610fa0e737e1
--- /dev/null
+++ b/clang/test/Sema/warn-infinity-nan-disabled-lnx.cpp
@@ -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 at +2 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}}
+// no-inf-warning at +1 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}}
+  i = a == INFINITY;
+
+// no-inf-no-nan-warning at +2 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}}
+// no-inf-warning at +1 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}}
+  j = INFINITY == a;
+
+// no-inf-no-nan-warning at +4 {{use of NaN is undefined behavior due to the currently enabled floating-point options}}
+// no-inf-no-nan-warning at +3 {{use of NaN via a macro is undefined behavior due to the currently enabled floating-point options}}
+// no-nan-warning at +2 {{use of NaN via a macro is undefined behavior due to the currently enabled floating-point options}}
+// no-nan-warning at +1 {{use of NaN is undefined behavior due to the currently enabled floating-point options}}
+  i = a == NAN;
+
+// no-inf-no-nan-warning at +4 {{use of NaN via a macro is undefined behavior due to the currently enabled floating-point options}}
+// no-inf-no-nan-warning at +3 {{use of NaN is undefined behavior due to the currently enabled floating-point options}}
+// no-nan-warning at +2 {{use of NaN is undefined behavior due to the currently enabled floating-point options}}
+// no-nan-warning at +1 {{use of NaN via a macro is undefined behavior due to the currently enabled floating-point options}}
+  j = NAN == a;
+
+// no-inf-no-nan-warning at +2 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}}
+// no-inf-warning at +1 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}}
+  j = INFINITY <= a;
+
+// no-inf-no-nan-warning at +2 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}}
+// no-inf-warning at +1 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}}
+  j = INFINITY < a;
+
+// no-inf-no-nan-warning at +4 {{use of NaN via a macro is undefined behavior due to the currently enabled floating-point options}}
+// no-inf-no-nan-warning at +3 {{use of NaN is undefined behavior due to the currently enabled floating-point options}}
+// no-nan-warning at +2 {{use of NaN via a macro is undefined behavior due to the currently enabled floating-point options}}
+// no-nan-warning at +1 {{use of NaN is undefined behavior due to the currently enabled floating-point options}}
+  j = a > NAN;
+
+// no-inf-no-nan-warning at +4 {{use of NaN via a macro is undefined behavior due to the currently enabled floating-point options}}
+// no-inf-no-nan-warning at +3 {{use of NaN is undefined behavior due to the currently enabled floating-point options}}
+// no-nan-warning at +2 {{use of NaN is undefined behavior due to the currently enabled floating-point options}}
+// no-nan-warning at +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 at +2 {{use of infinity is undefined behavior due to the currently enabled floating-point options}}
+// no-inf-warning at +1 {{use of infinity is undefined behavior due to the currently enabled floating-point options}}
+  k = std::isinf(a);
+
+// no-inf-no-nan-warning at +2 {{use of NaN is undefined behavior due to the currently enabled floating-point option}}
+// no-nan-warning at +1 {{use of NaN is undefined behavior due to the currently enabled floating-point options}}
+  l = std::isnan(a);
+
+// no-inf-no-nan-warning at +2 {{use of infinity is undefined behavior due to the currently enabled floating-point options}}
+// no-inf-warning at +1 {{use of infinity is undefined behavior due to the currently enabled floating-point options}}
+  o = std::isfinite(a);
+
+// no-inf-no-nan-warning at +2 {{use of infinity is undefined behavior due to the currently enabled floating-point options}}
+// no-inf-warning at +1 {{use of infinity is undefined behavior due to the currently enabled floating-point options}}
+  m = __builtin_isinf(a);
+
+// no-inf-no-nan-warning at +2 {{use of NaN is undefined behavior due to the currently enabled floating-point options}}
+// no-nan-warning at +1 {{use of NaN is undefined behavior due to the currently enabled floating-point options}}
+  n = __builtin_isnan(a);
+
+// no-inf-no-nan-warning at +2 {{use of infinity is undefined behavior due to the currently enabled floating-point options}}
+// no-inf-warning at +1 {{use of infinity 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 at +4 {{use of NaN via a macro is undefined behavior due to the currently enabled floating-point options}}
+// no-inf-no-nan-warning at +3 {{use of NaN is undefined behavior due to the currently enabled floating-point options}}
+// no-nan-warning at +2 {{use of NaN via a macro is undefined behavior due to the currently enabled floating-point options}}
+// no-nan-warning at +1 {{use of NaN is undefined behavior due to the currently enabled floating-point options}}
+  j = isunorderedf(a, NAN);
+
+// no-inf-no-nan-warning at +2 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}}
+// no-inf-warning at +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 at +6 {{use of NaN via a macro is undefined behavior due to the currently enabled floating-point options}}
+// no-inf-no-nan-warning at +5 {{use of NaN is undefined behavior due to the currently enabled floating-point options}}
+// no-inf-no-nan-warning at +4 {{use of NaN is undefined behavior due to the currently enabled floating-point options}}
+// no-nan-warning at +3 {{use of NaN via a macro is undefined behavior due to the currently enabled floating-point options}}
+// no-nan-warning at +2 {{use of NaN is undefined behavior due to the currently enabled floating-point options}}
+// no-nan-warning at +1 {{use of NaN is undefined behavior due to the currently enabled floating-point options}}
+  i = std::isunordered(a, NAN);
+
+// no-inf-no-nan-warning at +4 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}}
+// no-inf-no-nan-warning at +3 {{use of NaN is undefined behavior due to the currently enabled floating-point options}}
+// no-inf-warning at +2 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}}
+// no-nan-warning at +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 at +2 {{use of infinity is undefined behavior due to the currently enabled floating-point options}}
+// no-inf-warning at +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 at +2 {{use of infinity is undefined behavior due to the currently enabled floating-point options}}
+// no-inf-warning at +1 {{use of infinity is undefined behavior due to the currently enabled floating-point options}}
+  j = numeric_limits<float>::infinity();
+  return 0;
+
+}  

diff  --git a/clang/test/Sema/warn-infinity-nan-disabled-win.cpp b/clang/test/Sema/warn-infinity-nan-disabled-win.cpp
new file mode 100644
index 00000000000000..19a575386e3293
--- /dev/null
+++ b/clang/test/Sema/warn-infinity-nan-disabled-win.cpp
@@ -0,0 +1,179 @@
+// Use of NAN macro will trigger a warning "infinity defined in macro" because
+// on Windows the NAN macro is defined using INFINITY. See below.
+
+// 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 INFINITY ((float)(1e+300 * 1e+300))
+#define NAN      (-(float)(INFINITY * 0.0F))
+
+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 at +2 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}}
+// no-inf-warning at +1 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}}
+  i = a == INFINITY;
+
+// no-inf-no-nan-warning at +2 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}}
+// no-inf-warning at +1 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}}
+  j = INFINITY == a;
+
+// no-inf-no-nan-warning at +4 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}}
+// no-inf-no-nan-warning at +3 {{use of NaN via a macro is undefined behavior due to the currently enabled floating-point options}}
+// no-inf-warning at +2 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}}
+// no-nan-warning at +1 {{use of NaN via a macro is undefined behavior due to the currently enabled floating-point options}}
+  i = a == NAN;
+
+// no-inf-no-nan-warning at +4 {{use of NaN via a macro is undefined behavior due to the currently enabled floating-point options}}
+// no-inf-no-nan-warning at +3 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}}
+// no-inf-warning at +2 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}}
+// no-nan-warning at +1 {{use of NaN via a macro is undefined behavior due to the currently enabled floating-point options}}
+  j = NAN == a;
+
+// no-inf-no-nan-warning at +2 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}}
+// no-inf-warning at +1 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}}
+  j = INFINITY <= a;
+
+// no-inf-no-nan-warning at +2 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}}
+// no-inf-warning at +1 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}}
+  j = INFINITY < a;
+
+// no-inf-no-nan-warning at +4 {{use of NaN via a macro is undefined behavior due to the currently enabled floating-point options}}
+// no-inf-no-nan-warning at +3 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}}
+// no-inf-warning at +2 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}}
+// no-nan-warning at +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 at +4 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}}
+// no-inf-no-nan-warning at +3 {{use of NaN via a macro is undefined behavior due to the currently enabled floating-point options}}
+// no-inf-warning at +2 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}}
+// no-nan-warning at +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 at +2 {{use of infinity is undefined behavior due to the currently enabled floating-point options}}
+// no-inf-warning at +1 {{use of infinity is undefined behavior due to the currently enabled floating-point options}}
+  k = std::isinf(a);
+
+// no-inf-no-nan-warning at +2 {{use of NaN is undefined behavior due to the currently enabled floating-point options}}
+// no-nan-warning at +1 {{use of NaN is undefined behavior due to the currently enabled floating-point options}}
+  l = std::isnan(a);
+
+// no-inf-no-nan-warning at +2 {{use of infinity is undefined behavior due to the currently enabled floating-point options}}
+// no-inf-warning at +1 {{use of infinity is undefined behavior due to the currently enabled floating-point options}}
+  o = std::isfinite(a);
+
+// no-inf-no-nan-warning at +2 {{use of infinity is undefined behavior due to the currently enabled floating-point options}}
+// no-inf-warning at +1 {{use of infinity is undefined behavior due to the currently enabled floating-point options}}
+  m = __builtin_isinf(a);
+
+// no-inf-no-nan-warning at +2 {{use of NaN is undefined behavior due to the currently enabled floating-point options}}
+// no-nan-warning at +1 {{use of NaN is undefined behavior due to the currently enabled floating-point options}}
+  n = __builtin_isnan(a);
+
+// no-inf-no-nan-warning at +2 {{use of infinity is undefined behavior due to the currently enabled floating-point options}}
+// no-inf-warning at +1 {{use of infinity 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 at +4 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point option}}
+// no-inf-no-nan-warning at +3 {{use of NaN via a macro is undefined behavior due to the currently enabled floating-point options}}
+// no-inf-warning at +2 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}}
+// no-nan-warning at +1 {{use of NaN via a macro is undefined behavior due to the currently enabled floating-point options}}
+  j = isunorderedf(a, NAN);
+
+// no-inf-no-nan-warning at +2 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}}
+// no-inf-warning at +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 at +6 {{use of NaN via a macro is undefined behavior due to the currently enabled floating-point options}}
+// no-inf-no-nan-warning at +5 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}}
+// no-inf-no-nan-warning at +4 {{use of NaN is undefined behavior due to the currently enabled floating-point options}}
+// no-inf-warning at +3 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}}
+// no-nan-warning at +2 {{use of NaN via a macro is undefined behavior due to the currently enabled floating-point options}}
+// no-nan-warning at +1 {{use of NaN is undefined behavior due to the currently enabled floating-point options}}
+  i = std::isunordered(a, NAN);
+
+// no-inf-no-nan-warning at +4 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}}
+// no-inf-no-nan-warning at +3 {{use of NaN is undefined behavior due to the currently enabled floating-point options}}
+// no-inf-warning at +2 {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}}
+// no-nan-warning at +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 at +2 {{use of infinity is undefined behavior due to the currently enabled floating-point options}}
+// no-inf-warning at +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 at +2 {{use of infinity is undefined behavior due to the currently enabled floating-point options}}
+// no-inf-warning at +1 {{use of infinity is undefined behavior due to the currently enabled floating-point options}}
+  j = numeric_limits<float>::infinity();
+  return 0;
+
+}  


        


More information about the cfe-commits mailing list