[clang] [clang] Add __builtin_isnanf and __builtin_isnanl (PR #218004)

Nick Desaulniers via cfe-commits cfe-commits at lists.llvm.org
Fri Aug 21 12:06:58 PDT 2026


https://github.com/nickdesaulniers created https://github.com/llvm/llvm-project/pull/218004

Android's C runtime (Bionic) maintainer pointed out Clang lacks
__builtin_isnan{f,l} despite supporting __builtin_isnan and llvm having
corresponding intrinsics already (@llvm.is.fpclass.f{32,128}). Add them.

This should help simplify Bionic's libm implementation.

Assisted-by: Gemini


>From b14c2ae601de3a1ca30d052417ce10d7943910df Mon Sep 17 00:00:00 2001
From: Nick Desaulniers <ndesaulniers at google.com>
Date: Fri, 21 Aug 2026 10:08:48 -0700
Subject: [PATCH] [clang] Add __builtin_isnanf and __builtin_isnanl

Android's C runtime (Bionic) maintainer pointed out Clang lacks
__builtin_isnan{f,l} despite supporting __builtin_isnan and llvm having
corresponding intrinsics already (@llvm.is.fpclass.f{32,128}). Add them.

This should help simplify Bionic's libm implementation.

Assisted-by: Gemini
---
 clang/docs/LanguageExtensions.md              |  2 +
 clang/docs/ReleaseNotes.md                    |  2 +
 clang/include/clang/Basic/Builtins.td         | 14 +++++
 clang/lib/AST/ByteCode/InterpBuiltin.cpp      |  2 +
 clang/lib/AST/ExprConstant.cpp                |  4 +-
 clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp       |  4 +-
 clang/lib/CodeGen/CGBuiltin.cpp               |  4 +-
 clang/lib/CodeGen/Targets/SystemZ.cpp         |  2 +
 clang/lib/Sema/SemaChecking.cpp               |  4 ++
 clang/test/AST/ByteCode/builtin-functions.cpp | 30 ++++++++++
 .../test/CodeGen/SystemZ/strictfp_builtins.c  | 25 +++++++++
 clang/test/CodeGen/builtins.c                 |  2 +
 clang/test/CodeGen/isfpclass.c                | 22 ++++++++
 clang/test/Sema/builtins.c                    | 21 +++++++
 clang/test/Sema/constant-builtins-2.c         | 56 +++++++++++++++++++
 15 files changed, 191 insertions(+), 3 deletions(-)

diff --git a/clang/docs/LanguageExtensions.md b/clang/docs/LanguageExtensions.md
index 3fbdbd9a511f3..7d706552dd18b 100644
--- a/clang/docs/LanguageExtensions.md
+++ b/clang/docs/LanguageExtensions.md
@@ -6765,6 +6765,8 @@ The following builtin intrinsics can be used in constant expressions:
 - `__builtin_isinf_sign`
 - `__builtin_isfinite`
 - `__builtin_isnan`
+- `__builtin_isnanf`
+- `__builtin_isnanl`
 - `__builtin_isnormal`
 - `__builtin_nan`
 - `__builtin_nans`
diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index 64979e07021dc..e2e1a01f0b92b 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -195,6 +195,8 @@ features cannot lower the translation-unit ABI level;
 - Clang now allows GNU computed `goto` extension in `constexpr` functions, matching the relaxed
   `constexpr` function body rules introduced in C++23.
 
+- Added support for `__builtin_isnanf` and `__builtin_isnanl`.
+
 ### New Compiler Flags
 
 - New option `-fdefined-pointer-subtraction` added to preserve stable semantics
diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td
index 88aa8aee01e4b..265fd30aab908 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -635,6 +635,20 @@ def IsNan : Builtin {
   let Prototype = "int(...)";
 }
 
+def IsNanF : Builtin {
+  let Spellings = ["__builtin_isnanf"];
+  let Attributes = [FunctionWithBuiltinPrefix, NoThrow, Const,
+                    Constexpr];
+  let Prototype = "int(float)";
+}
+
+def IsNanL : Builtin {
+  let Spellings = ["__builtin_isnanl"];
+  let Attributes = [FunctionWithBuiltinPrefix, NoThrow, Const,
+                    Constexpr];
+  let Prototype = "int(long double)";
+}
+
 def IsNormal : Builtin {
   let Spellings = ["__builtin_isnormal"];
   let Attributes = [FunctionWithBuiltinPrefix, NoThrow, Const,
diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
index 17a0983059bc7..b4bdce178540c 100644
--- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp
+++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
@@ -4835,6 +4835,8 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
     return interp__builtin_fmax(S, OpPC, Frame, /*IsNumBuiltin=*/true);
 
   case Builtin::BI__builtin_isnan:
+  case Builtin::BI__builtin_isnanf:
+  case Builtin::BI__builtin_isnanl:
     return interp__builtin_isnan(S, OpPC, Frame, Call);
 
   case Builtin::BI__builtin_issignaling:
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 7aff17100d4ff..08047ffff1d1a 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -17376,7 +17376,9 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
            Success(Val.isFinite() ? 1 : 0, E);
   }
 
-  case Builtin::BI__builtin_isnan: {
+  case Builtin::BI__builtin_isnan:
+  case Builtin::BI__builtin_isnanf:
+  case Builtin::BI__builtin_isnanl: {
     APFloat Val(0.0);
     return EvaluateFloat(E->getArg(0), Val, Info) &&
            Success(Val.isNaN() ? 1 : 0, E);
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
index 27dc8b1c7d889..9469616f1a9b0 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
@@ -1604,7 +1604,9 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID,
   //  isnan, isinf, isfinite and some others defined by the C standard. It tests
   //  if the floating-point value, specified by the first argument, falls into
   //  any of data classes, specified by the second argument.
-  case Builtin::BI__builtin_isnan: {
+  case Builtin::BI__builtin_isnan:
+  case Builtin::BI__builtin_isnanf:
+  case Builtin::BI__builtin_isnanl: {
     CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(*this, e);
     mlir::Value v = emitScalarExpr(e->getArg(0));
     mlir::Location loc = getLoc(e->getBeginLoc());
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 3f7b090315f5e..3ebad5f63fb11 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -4171,7 +4171,9 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
     return RValue::get(Builder.CreateZExt(LHS, ConvertType(E->getType())));
   }
 
-  case Builtin::BI__builtin_isnan: {
+  case Builtin::BI__builtin_isnan:
+  case Builtin::BI__builtin_isnanf:
+  case Builtin::BI__builtin_isnanl: {
     CodeGenFunction::CGFPOptionsRAII FPOptsRAII(*this, E);
     Value *V = EmitScalarExpr(E->getArg(0));
     if (Value *Result = tryUseTestFPKind(*this, BuiltinID, V))
diff --git a/clang/lib/CodeGen/Targets/SystemZ.cpp b/clang/lib/CodeGen/Targets/SystemZ.cpp
index a27fee633ead2..2e18185b3d120 100644
--- a/clang/lib/CodeGen/Targets/SystemZ.cpp
+++ b/clang/lib/CodeGen/Targets/SystemZ.cpp
@@ -116,6 +116,8 @@ class SystemZTargetCodeGenInfo : public TargetCodeGenInfo {
       unsigned TDCBits = 0;
       switch (BuiltinID) {
       case Builtin::BI__builtin_isnan:
+      case Builtin::BI__builtin_isnanf:
+      case Builtin::BI__builtin_isnanl:
         TDCBits = 0xf;
         break;
       case Builtin::BIfinite:
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 3e6266b8ac542..1f04b4a82b1d0 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -3207,6 +3207,8 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
   case Builtin::BI__builtin_isinf:
   case Builtin::BI__builtin_isinf_sign:
   case Builtin::BI__builtin_isnan:
+  case Builtin::BI__builtin_isnanf:
+  case Builtin::BI__builtin_isnanl:
   case Builtin::BI__builtin_issignaling:
   case Builtin::BI__builtin_isnormal:
   case Builtin::BI__builtin_issubnormal:
@@ -6426,6 +6428,8 @@ bool Sema::BuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs,
         << 0 << 0 << TheCall->getSourceRange();
 
   if (FPO.getNoHonorNaNs() && (BuiltinID == Builtin::BI__builtin_isnan ||
+                               BuiltinID == Builtin::BI__builtin_isnanf ||
+                               BuiltinID == Builtin::BI__builtin_isnanl ||
                                BuiltinID == Builtin::BI__builtin_isunordered))
     Diag(TheCall->getBeginLoc(), diag::warn_fp_nan_inf_when_disabled)
         << 1 << 0 << TheCall->getSourceRange();
diff --git a/clang/test/AST/ByteCode/builtin-functions.cpp b/clang/test/AST/ByteCode/builtin-functions.cpp
index 87ffb1cc5b609..d4c5edfc0d21c 100644
--- a/clang/test/AST/ByteCode/builtin-functions.cpp
+++ b/clang/test/AST/ByteCode/builtin-functions.cpp
@@ -258,6 +258,32 @@ namespace nan {
                                              // expected-note {{read of dereferenced one-past-the-end pointer}}
   static_assert(!__builtin_issignaling(__builtin_nan("")), "");
   static_assert(__builtin_issignaling(__builtin_nans("")), "");
+  static_assert(__builtin_isnan(__builtin_nan("")), "");
+  static_assert(__builtin_isnan(-__builtin_nan("")), "");
+  static_assert(__builtin_isnan(__builtin_nans("")), "");
+  static_assert(__builtin_isnan(-__builtin_nans("")), "");
+  static_assert(__builtin_isnan(__builtin_nan("0x123")), "");
+  static_assert(__builtin_isnan(-__builtin_nan("0x123")), "");
+  static_assert(__builtin_isnan(__builtin_nans("0x123")), "");
+  static_assert(__builtin_isnan(-__builtin_nans("0x123")), "");
+
+  static_assert(__builtin_isnanf(__builtin_nanf("")), "");
+  static_assert(__builtin_isnanf(-__builtin_nanf("")), "");
+  static_assert(__builtin_isnanf(__builtin_nansf("")), "");
+  static_assert(__builtin_isnanf(-__builtin_nansf("")), "");
+  static_assert(__builtin_isnanf(__builtin_nanf("0x123")), "");
+  static_assert(__builtin_isnanf(-__builtin_nanf("0x123")), "");
+  static_assert(__builtin_isnanf(__builtin_nansf("0x123")), "");
+  static_assert(__builtin_isnanf(-__builtin_nansf("0x123")), "");
+
+  static_assert(__builtin_isnanl(__builtin_nanl("")), "");
+  static_assert(__builtin_isnanl(-__builtin_nanl("")), "");
+  static_assert(__builtin_isnanl(__builtin_nansl("")), "");
+  static_assert(__builtin_isnanl(-__builtin_nansl("")), "");
+  static_assert(__builtin_isnanl(__builtin_nanl("0x123")), "");
+  static_assert(__builtin_isnanl(-__builtin_nanl("0x123")), "");
+  static_assert(__builtin_isnanl(__builtin_nansl("0x123")), "");
+  static_assert(__builtin_isnanl(-__builtin_nansl("0x123")), "");
 }
 
 namespace fmin {
@@ -1240,8 +1266,12 @@ namespace FunctionStart {
 namespace BuiltinInImplicitCtor {
   constexpr struct {
     int a = __builtin_isnan(1.0);
+    int b = __builtin_isnanf(1.0f);
+    int c = __builtin_isnanl(1.0L);
   } Foo;
   static_assert(Foo.a == 0, "");
+  static_assert(Foo.b == 0, "");
+  static_assert(Foo.c == 0, "");
 }
 
 typedef double vector4double __attribute__((__vector_size__(32)));
diff --git a/clang/test/CodeGen/SystemZ/strictfp_builtins.c b/clang/test/CodeGen/SystemZ/strictfp_builtins.c
index f871debde067e..432b67fcec99f 100644
--- a/clang/test/CodeGen/SystemZ/strictfp_builtins.c
+++ b/clang/test/CodeGen/SystemZ/strictfp_builtins.c
@@ -28,6 +28,18 @@ int test_isnan_float(float f) {
   return __builtin_isnan(f);
 }
 
+// CHECK-LABEL: @test_isnanf(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[F_ADDR:%.*]] = alloca float, align 4
+// CHECK-NEXT:    store float [[F:%.*]], ptr [[F_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load float, ptr [[F_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.s390.tdc.f32(float [[TMP0]], i64 15) #[[ATTR2]]
+// CHECK-NEXT:    ret i32 [[TMP1]]
+//
+int test_isnanf(float f) {
+  return __builtin_isnanf(f);
+}
+
 // CHECK-LABEL: @test_isnan_double(
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    [[D_ADDR:%.*]] = alloca double, align 8
@@ -53,6 +65,19 @@ int test_isnan_long_double(long double ld) {
   return __builtin_isnan(ld);
 }
 
+// CHECK-LABEL: @test_isnanl(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[LD_ADDR:%.*]] = alloca fp128, align 8
+// CHECK-NEXT:    [[LD:%.*]] = load fp128, ptr [[TMP0:%.*]], align 8
+// CHECK-NEXT:    store fp128 [[LD]], ptr [[LD_ADDR]], align 8
+// CHECK-NEXT:    [[TMP1:%.*]] = load fp128, ptr [[LD_ADDR]], align 8
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.s390.tdc.f128(fp128 [[TMP1]], i64 15) #[[ATTR2]]
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+int test_isnanl(long double ld) {
+  return __builtin_isnanl(ld);
+}
+
 // CHECK-LABEL: @test_isinf_float(
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    [[F_ADDR:%.*]] = alloca float, align 4
diff --git a/clang/test/CodeGen/builtins.c b/clang/test/CodeGen/builtins.c
index e605c21454efa..b88a4835d10f6 100644
--- a/clang/test/CodeGen/builtins.c
+++ b/clang/test/CodeGen/builtins.c
@@ -71,6 +71,8 @@ int main(void) {
   P(isinf, (1.));
   P(isinf_sign, (1.));
   P(isnan, (1.));
+  P(isnanf, (1.f));
+  P(isnanl, (1.L));
   P(isfinite, (1.));
   P(iszero, (1.));
   P(issubnormal, (1.));
diff --git a/clang/test/CodeGen/isfpclass.c b/clang/test/CodeGen/isfpclass.c
index 73dcbfd133981..247371deb9546 100644
--- a/clang/test/CodeGen/isfpclass.c
+++ b/clang/test/CodeGen/isfpclass.c
@@ -97,6 +97,28 @@ _Bool check_isnan(float x) {
   return __builtin_isnan(x);
 }
 
+// CHECK-LABEL: define dso_local noundef i1 @check_isnanf(
+// CHECK-SAME: float noundef [[X:%.*]]) local_unnamed_addr #[[ATTR2]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[TMP0:%.*]] = tail call i1 @llvm.is.fpclass.f32(float [[X]], /* (nan) */ i32 3) #[[ATTR5]]
+// CHECK-NEXT:    ret i1 [[TMP0]]
+//
+_Bool check_isnanf(float x) {
+#pragma STDC FENV_ACCESS ON
+  return __builtin_isnanf(x);
+}
+
+// CHECK-LABEL: define dso_local noundef i1 @check_isnanl(
+// CHECK-SAME: fp128 noundef [[X:%.*]]) local_unnamed_addr #[[ATTR2]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[TMP0:%.*]] = tail call i1 @llvm.is.fpclass.f128(fp128 [[X]], /* (nan) */ i32 3) #[[ATTR5]]
+// CHECK-NEXT:    ret i1 [[TMP0]]
+//
+_Bool check_isnanl(long double x) {
+#pragma STDC FENV_ACCESS ON
+  return __builtin_isnanl(x);
+}
+
 // CHECK-LABEL: define dso_local noundef i1 @check_isinf(
 // CHECK-SAME: float noundef [[X:%.*]]) local_unnamed_addr #[[ATTR2]] {
 // CHECK-NEXT:  [[ENTRY:.*:]]
diff --git a/clang/test/Sema/builtins.c b/clang/test/Sema/builtins.c
index b669ee68cdd95..53fc8fc614e83 100644
--- a/clang/test/Sema/builtins.c
+++ b/clang/test/Sema/builtins.c
@@ -337,6 +337,27 @@ void test22(void) {
   (void)__builtin_signbitl(1.0);
   (void)__builtin_signbitl(1.0f);
   (void)__builtin_signbitl(1.0L);
+
+  (void)__builtin_isnan(); // expected-error{{too few arguments to function call, expected 1, have 0}}
+  (void)__builtin_isnan(1.0, 2.0, 3.0); // expected-error{{too many arguments to function call, expected 1, have 3}}
+  (void)__builtin_isnan(1); // expected-error {{floating point classification requires argument of floating point type (passed in 'int')}}
+  (void)__builtin_isnan(1.0);
+  (void)__builtin_isnan(1.0f);
+  (void)__builtin_isnan(1.0L);
+
+  (void)__builtin_isnanf(); // expected-error{{too few arguments to function call, expected 1, have 0}}
+  (void)__builtin_isnanf(1.0, 2.0, 3.0); // expected-error{{too many arguments to function call, expected 1, have 3}}
+  (void)__builtin_isnanf(1);
+  (void)__builtin_isnanf(1.0);
+  (void)__builtin_isnanf(1.0f);
+  (void)__builtin_isnanf(1.0L);
+
+  (void)__builtin_isnanl(); // expected-error{{too few arguments to function call, expected 1, have 0}}
+  (void)__builtin_isnanl(1.0, 2.0, 3.0); // expected-error{{too many arguments to function call, expected 1, have 3}}
+  (void)__builtin_isnanl(1);
+  (void)__builtin_isnanl(1.0);
+  (void)__builtin_isnanl(1.0f);
+  (void)__builtin_isnanl(1.0L);
 }
 
 #define memcpy(x,y,z) __builtin___memcpy_chk(x,y,z, __builtin_object_size(x,0))
diff --git a/clang/test/Sema/constant-builtins-2.c b/clang/test/Sema/constant-builtins-2.c
index fd3643bbdb7c8..7a562aa5872e7 100644
--- a/clang/test/Sema/constant-builtins-2.c
+++ b/clang/test/Sema/constant-builtins-2.c
@@ -110,6 +110,46 @@ char isnan_neg    [!__builtin_isnan(-1.0) ? 1 : -1];
 char isnan_inf_neg[!__builtin_isnan(-__builtin_inf()) ? 1 : -1];
 char isnan_nan    [__builtin_isnan(__builtin_nan("")) ? 1 : -1];
 char isnan_snan   [__builtin_isnan(__builtin_nans("")) ? 1 : -1];
+char isnan_negnan [__builtin_isnan(-__builtin_nan("")) ? 1 : -1];
+char isnan_negsnan[__builtin_isnan(-__builtin_nans("")) ? 1 : -1];
+char isnan_nan_payload [__builtin_isnan(__builtin_nan("0x123")) ? 1 : -1];
+char isnan_snan_payload[__builtin_isnan(__builtin_nans("0x123")) ? 1 : -1];
+char isnan_negnan_payload [__builtin_isnan(-__builtin_nan("0x123")) ? 1 : -1];
+char isnan_negsnan_payload[__builtin_isnan(-__builtin_nans("0x123")) ? 1 : -1];
+
+char isnanf_inf_pos[!__builtin_isnanf(__builtin_inff()) ? 1 : -1];
+char isnanf_pos    [!__builtin_isnanf(1.0f) ? 1 : -1];
+char isnanf_normf  [!__builtin_isnanf(1e-37f) ? 1 : -1];
+char isnanf_denormf[!__builtin_isnanf(1e-38f) ? 1 : -1];
+char isnanf_zero   [!__builtin_isnanf(0.0f) ? 1 : -1];
+char isnanf_negzero[!__builtin_isnanf(-0.0f) ? 1 : -1];
+char isnanf_neg    [!__builtin_isnanf(-1.0f) ? 1 : -1];
+char isnanf_inf_neg[!__builtin_isnanf(-__builtin_inff()) ? 1 : -1];
+char isnanf_nan    [__builtin_isnanf(__builtin_nanf("")) ? 1 : -1];
+char isnanf_snan   [__builtin_isnanf(__builtin_nansf("")) ? 1 : -1];
+char isnanf_negnan [__builtin_isnanf(-__builtin_nanf("")) ? 1 : -1];
+char isnanf_negsnan[__builtin_isnanf(-__builtin_nansf("")) ? 1 : -1];
+char isnanf_nan_payload [__builtin_isnanf(__builtin_nanf("0x123")) ? 1 : -1];
+char isnanf_snan_payload[__builtin_isnanf(__builtin_nansf("0x123")) ? 1 : -1];
+char isnanf_negnan_payload [__builtin_isnanf(-__builtin_nanf("0x123")) ? 1 : -1];
+char isnanf_negsnan_payload[__builtin_isnanf(-__builtin_nansf("0x123")) ? 1 : -1];
+
+char isnanl_inf_pos[!__builtin_isnanl(__builtin_infl()) ? 1 : -1];
+char isnanl_pos    [!__builtin_isnanl(1.0L) ? 1 : -1];
+char isnanl_norm   [!__builtin_isnanl(1e-307L) ? 1 : -1];
+char isnanl_denorm [!__builtin_isnanl(1e-308L) ? 1 : -1];
+char isnanl_zero   [!__builtin_isnanl(0.0L) ? 1 : -1];
+char isnanl_negzero[!__builtin_isnanl(-0.0L) ? 1 : -1];
+char isnanl_neg    [!__builtin_isnanl(-1.0L) ? 1 : -1];
+char isnanl_inf_neg[!__builtin_isnanl(-__builtin_infl()) ? 1 : -1];
+char isnanl_nan    [__builtin_isnanl(__builtin_nanl("")) ? 1 : -1];
+char isnanl_snan   [__builtin_isnanl(__builtin_nansl("")) ? 1 : -1];
+char isnanl_negnan [__builtin_isnanl(-__builtin_nanl("")) ? 1 : -1];
+char isnanl_negsnan[__builtin_isnanl(-__builtin_nansl("")) ? 1 : -1];
+char isnanl_nan_payload [__builtin_isnanl(__builtin_nanl("0x123")) ? 1 : -1];
+char isnanl_snan_payload[__builtin_isnanl(__builtin_nansl("0x123")) ? 1 : -1];
+char isnanl_negnan_payload [__builtin_isnanl(-__builtin_nanl("0x123")) ? 1 : -1];
+char isnanl_negsnan_payload[__builtin_isnanl(-__builtin_nansl("0x123")) ? 1 : -1];
 
 char isnormal_inf_pos[!__builtin_isnormal(__builtin_inf()) ? 1 : -1];
 char isnormal_pos    [__builtin_isnormal(1.0) ? 1 : -1];
@@ -216,6 +256,22 @@ __extension__ _Static_assert(
   1, ""
 );
 
+__extension__ _Static_assert(
+  __builtin_isnan(__builtin_nan("")) && __builtin_isnan(-__builtin_nan("")) &&
+  __builtin_isnan(__builtin_nans("")) && __builtin_isnan(-__builtin_nans("")) &&
+  __builtin_isnan(__builtin_nan("0x123")) && __builtin_isnan(-__builtin_nan("0x123")) &&
+  __builtin_isnan(__builtin_nans("0x123")) && __builtin_isnan(-__builtin_nans("0x123")) &&
+  __builtin_isnanf(__builtin_nanf("")) && __builtin_isnanf(-__builtin_nanf("")) &&
+  __builtin_isnanf(__builtin_nansf("")) && __builtin_isnanf(-__builtin_nansf("")) &&
+  __builtin_isnanf(__builtin_nanf("0x123")) && __builtin_isnanf(-__builtin_nanf("0x123")) &&
+  __builtin_isnanf(__builtin_nansf("0x123")) && __builtin_isnanf(-__builtin_nansf("0x123")) &&
+  __builtin_isnanl(__builtin_nanl("")) && __builtin_isnanl(-__builtin_nanl("")) &&
+  __builtin_isnanl(__builtin_nansl("")) && __builtin_isnanl(-__builtin_nansl("")) &&
+  __builtin_isnanl(__builtin_nanl("0x123")) && __builtin_isnanl(-__builtin_nanl("0x123")) &&
+  __builtin_isnanl(__builtin_nansl("0x123")) && __builtin_isnanl(-__builtin_nansl("0x123")),
+  ""
+);
+
 #define LESS(X, Y) \
   !__builtin_isgreater(X, Y) && __builtin_isgreater(Y, X) &&             \
   !__builtin_isgreaterequal(X, Y) && __builtin_isgreaterequal(Y, X) &&   \



More information about the cfe-commits mailing list