-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[C23] Support the SNAN macros in <float.h> #162858
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
base: main
Are you sure you want to change the base?
Conversation
These macros were brought in as part of the TS 18661-1 integration in C23, and then renamed in WG14 N2710. Test coverage is being added to WG14 N3364 from C2y because that paper was fixing a bug with the way these macros are handled with unary + and - operators, so all the existing test coverage was there, just needed to use a header file instead of defining the macros manually. Fixes llvm#162830
@llvm/pr-subscribers-backend-x86 @llvm/pr-subscribers-clang Author: Aaron Ballman (AaronBallman) ChangesThese macros were brought in as part of the TS 18661-1 integration in C23, and then renamed in WG14 N2710. Test coverage is being added to WG14 N3364 from C2y because that paper was fixing a bug with the way these macros are handled with unary + and
Fixes #162830 Full diff: https://github.com/llvm/llvm-project/pull/162858.diff 3 Files Affected:
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 99aa545831240..2fead354e2252 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -184,6 +184,9 @@ C2y Feature Support
C23 Feature Support
^^^^^^^^^^^^^^^^^^^
+- Added ``FLT_SNAN``, ``DBL_SNAN``, and ``LDBL_SNAN`` to Clang's ``<float.h>``
+ header in C23 and later modes. This implements
+ `WG14 N2710 <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2710.htm>`_.
Non-comprehensive list of changes in this release
-------------------------------------------------
diff --git a/clang/lib/Headers/float.h b/clang/lib/Headers/float.h
index 84551af473b28..30427c29dcdbd 100644
--- a/clang/lib/Headers/float.h
+++ b/clang/lib/Headers/float.h
@@ -89,6 +89,9 @@
!defined(__STRICT_ANSI__)
# undef INFINITY
# undef NAN
+# undef FLT_SNAN
+# undef DBL_SNAN
+# undef LDBL_SNAN
#endif
/* Characteristics of floating point types, C99 5.2.4.2.2 */
@@ -160,9 +163,15 @@
#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L) || \
!defined(__STRICT_ANSI__)
+ /* C23 5.2.5.3.2p28 */
+# define FLT_SNAN (__builtin_nansf(""))
+# define DBL_SNAN (__builtin_nans(""))
+# define LDBL_SNAN (__builtin_nansl(""))
+
/* C23 5.2.5.3.3p29-30 */
# define INFINITY (__builtin_inff())
# define NAN (__builtin_nanf(""))
+
/* C23 5.2.5.3.3p32 */
# define FLT_NORM_MAX __FLT_NORM_MAX__
# define DBL_NORM_MAX __DBL_NORM_MAX__
diff --git a/clang/test/C/C2y/n3364.c b/clang/test/C/C2y/n3364.c
index 277b2643edd6b..d75f17d0a7a84 100644
--- a/clang/test/C/C2y/n3364.c
+++ b/clang/test/C/C2y/n3364.c
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -verify -std=c2y -Wall -pedantic -emit-llvm -o - %s
-// RUN: %clang_cc1 -verify -Wall -pedantic -emit-llvm -o - %s
+// RUN: %clang_cc1 -verify -std=c2y -ffreestanding -Wall -pedantic -emit-llvm -o - %s
+// RUN: %clang_cc1 -verify -ffreestanding -Wall -pedantic -emit-llvm -o - %s
// expected-no-diagnostics
/* WG14 N3364: Yes
@@ -7,11 +7,18 @@
*
* Ensure that initializing from a signaling NAN (optionally with a unary + or
* -) at translation time behaves correctly at runtime.
+ *
+ * This also serves as a test for C23's WG14 N2710 which introduces these
+ * macros into float.h in Clang 22.
*/
-#define FLT_SNAN __builtin_nansf("1")
-#define DBL_SNAN __builtin_nans("1")
-#define LD_SNAN __builtin_nansl("1")
+#if __STDC_VERSION__ >= 202311L
+#include <float.h>
+#else
+#define FLT_SNAN __builtin_nansf("")
+#define DBL_SNAN __builtin_nans("")
+#define LDBL_SNAN __builtin_nansl("")
+#endif
float f1 = FLT_SNAN;
float f2 = +FLT_SNAN;
@@ -27,9 +34,9 @@ double d3 = -DBL_SNAN;
// CHECK: @d2 = {{.*}}global double 0x7FF0000000000001
// CHECK: @d3 = {{.*}}global double 0xFFF0000000000001
-long double ld1 = LD_SNAN;
-long double ld2 = +LD_SNAN;
-long double ld3 = -LD_SNAN;
+long double ld1 = LDBL_SNAN;
+long double ld2 = +LDBL_SNAN;
+long double ld3 = -LDBL_SNAN;
// CHECK: @ld1 = {{.*}}global {{double 0x7FF0000000000001|x86_fp80 0xK7FFF8000000000000001|fp128 0xL00000000000000017FFF000000000000}}
// CHECK: @ld2 = {{.*}}global {{double 0x7FF0000000000001|x86_fp80 0xK7FFF8000000000000001|fp128 0xL00000000000000017FFF000000000000}}
// CHECK: @ld3 = {{.*}}global {{double 0xFFF0000000000001|x86_fp80 0xKFFFF8000000000000001|fp128 0xL0000000000000001FFFF000000000000}}
|
You can test this locally with the following command:git-clang-format --diff origin/main HEAD --extensions h,c -- clang/lib/Headers/float.h clang/test/C/C2y/n3364.c
View the diff from clang-format here.diff --git a/clang/lib/Headers/float.h b/clang/lib/Headers/float.h
index 30427c29d..9dc06c7c0 100644
--- a/clang/lib/Headers/float.h
+++ b/clang/lib/Headers/float.h
@@ -89,9 +89,9 @@
!defined(__STRICT_ANSI__)
# undef INFINITY
# undef NAN
-# undef FLT_SNAN
-# undef DBL_SNAN
-# undef LDBL_SNAN
+#undef FLT_SNAN
+#undef DBL_SNAN
+#undef LDBL_SNAN
#endif
/* Characteristics of floating point types, C99 5.2.4.2.2 */
@@ -163,12 +163,12 @@
#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L) || \
!defined(__STRICT_ANSI__)
- /* C23 5.2.5.3.2p28 */
-# define FLT_SNAN (__builtin_nansf(""))
-# define DBL_SNAN (__builtin_nans(""))
-# define LDBL_SNAN (__builtin_nansl(""))
+/* C23 5.2.5.3.2p28 */
+#define FLT_SNAN (__builtin_nansf(""))
+#define DBL_SNAN (__builtin_nans(""))
+#define LDBL_SNAN (__builtin_nansl(""))
- /* C23 5.2.5.3.3p29-30 */
+/* C23 5.2.5.3.3p29-30 */
# define INFINITY (__builtin_inff())
# define NAN (__builtin_nanf(""))
|
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.
I have a question about interpreting the standard. The standard says each of these macros "is defined if and only if the respective type contains signaling NaNs." Given that by default LLVM IR gives the compiler permission to treat all NaNs as if they were quiet NaNs, should we really be defining these macros in the default mode?
My understanding is that these built-ins will indeed produce a signaling NaN value, but the quiet/signaling behavior may not be respected by the optimizer.
I think we likely want them defined for GCC compatibility: https://godbolt.org/z/9PjdfM8hx they still define the macro even when passing |
The way I interpret the standard, it discusses whether or not the format of the type supports sNaNs, not whether or not the current floating-point model has full sNaN operational semantics. Since the IEEE 754 types support sNaNs, then they should have sNaN support enabled for them. Whether or not the sNaN types are actually usable is actually envisioned by the standard--there's actually a |
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.
Given the clarifications on standard interpretation and GCC behavior, I'm happy with this.
These macros were brought in as part of the TS 18661-1 integration in C23, and then renamed in WG14 N2710.
Test coverage is being added to WG14 N3364 from C2y because that paper was fixing a bug with the way these macros are handled with unary + and
Fixes #162830