-
Notifications
You must be signed in to change notification settings - Fork 12.2k
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
[C23] Add INFINITY and NAN macros to <float.h> #96659
Conversation
This is in support of WG14 N2848 which only define the macros if infinity and nan are supported, so use of -ffinite-math will cause the macros to not be defined.
@llvm/pr-subscribers-backend-x86 @llvm/pr-subscribers-clang Author: Aaron Ballman (AaronBallman) ChangesThis is in support of WG14 N2848 which only define the macros if Full diff: https://github.com/llvm/llvm-project/pull/96659.diff 4 Files Affected:
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index df579ae398c5e..45c9a2cc47b09 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -336,6 +336,11 @@ C23 Feature Support
- Properly promote bit-fields of bit-precise integer types to the field's type
rather than to ``int``. #GH87641
+- Added the ``INFINITY`` and ``NAN`` macros to Clang's ``<float.h>``
+ freestanding implementation; these macros were defined in C99 but Clang
+ implements the macros as described by C23 in
+ `WG14 N2848 <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2848.pdf>`_.
+
Non-comprehensive list of changes in this release
-------------------------------------------------
diff --git a/clang/lib/Headers/float.h b/clang/lib/Headers/float.h
index 642c8f06cc938..929c0854a865b 100644
--- a/clang/lib/Headers/float.h
+++ b/clang/lib/Headers/float.h
@@ -47,6 +47,8 @@
(defined(__cplusplus) && __cplusplus >= 201103L) || \
(__STDC_HOSTED__ && defined(_AIX) && defined(_ALL_SOURCE))
# undef DECIMAL_DIG
+# undef INFINITY
+# undef NAN
# endif
# undef FLT_DIG
# undef DBL_DIG
@@ -93,6 +95,10 @@
#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \
(defined(__cplusplus) && __cplusplus >= 201103L)
#define FLT_EVAL_METHOD __FLT_EVAL_METHOD__
+#if defined(__FINITE_MATH_ONLY__) && !__FINITE_MATH_ONLY__
+# define INFINITY (__builtin_infinity())
+# define NAN (__builtin_nan(""))
+#endif
#endif
#define FLT_ROUNDS (__builtin_flt_rounds())
#define FLT_RADIX __FLT_RADIX__
diff --git a/clang/test/Headers/float.c b/clang/test/Headers/float.c
index 70c11b0537537..8dfbc32521ade 100644
--- a/clang/test/Headers/float.c
+++ b/clang/test/Headers/float.c
@@ -1,9 +1,13 @@
// RUN: %clang_cc1 -fsyntax-only -verify -std=c89 -ffreestanding %s
// RUN: %clang_cc1 -fsyntax-only -verify -std=c99 -ffreestanding %s
// RUN: %clang_cc1 -fsyntax-only -verify -std=c11 -ffreestanding %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c23 -ffreestanding %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c23 -ffreestanding -ffinite-math-only %s
// RUN: %clang_cc1 -fsyntax-only -verify -xc++ -std=c++11 -ffreestanding %s
// RUN: %clang_cc1 -fsyntax-only -verify -xc++ -std=c++14 -ffreestanding %s
// RUN: %clang_cc1 -fsyntax-only -verify -xc++ -std=c++17 -ffreestanding %s
+// RUN: %clang_cc1 -fsyntax-only -verify -xc++ -std=c++23 -ffreestanding %s
+// RUN: %clang_cc1 -fsyntax-only -verify -xc++ -std=c++23 -ffreestanding -ffinite-math-only %s
// expected-no-diagnostics
/* Basic floating point conformance checks against:
@@ -107,10 +111,35 @@
#elif DECIMAL_DIG < 10
#error "Mandatory macro DECIMAL_DIG is invalid."
#endif
+
+ #if __FINITE_MATH_ONLY__ == 0
+ #ifndef INFINITY
+ #error "Mandatory macro INFINITY is missing."
+ #endif
+ #ifndef NAN
+ #error "Mandatory macro NAN is missing."
+ #endif
+ #else
+ #ifdef INFINITY
+ #error "Macro INFINITY should not be defined."
+ #endif
+
+ #ifdef NAN
+ #error "Macro NAN should not be defined."
+ #endif
+ #endif
#else
#ifdef DECIMAL_DIG
#error "Macro DECIMAL_DIG should not be defined."
#endif
+
+ #ifdef INFINITY
+ #error "Macro INFINITY should not be defined."
+ #endif
+
+ #ifdef NAN
+ #error "Macro NAN should not be defined."
+ #endif
#endif
diff --git a/clang/www/c_status.html b/clang/www/c_status.html
index 04c1df9ebc050..bc37f8cd5e404 100644
--- a/clang/www/c_status.html
+++ b/clang/www/c_status.html
@@ -991,7 +991,7 @@ <h2 id="c2x">C23 implementation status</h2>
<tr>
<td>Contradiction about INFINITY macro</td>
<td><a href="https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2848.pdf">N2848</a></td>
- <td class="unknown" align="center">Unknown</td>
+ <td class="unreleased" align="center">Clang 19</td>
</tr>
<tr>
<td>Require exact-width integer type interfaces</td>
|
Link to WG14 N2848: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2848.pdf |
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'm not sure about tying this to __FINITE_MATH_ONLY__
; -ffinite-math-only doesn't mean infinity doesn't exist, it just means you're promising that you won't use floating-point arithmetic/comparison ops on infinity. Which is weird, but that's fast-math. Also, other implementations don't do this.
In C99, INFINITY and NAN are macros in math.h, not float.h. Is it correct to check __STDC_VERSION__ >= 199901L
?
The requirement that you only define the macro if inf/nan "is supported" is new in C23, so I don't expect anyone to have implemented this yet. As for
In C99, C11, and C17 |
It's undefined behavior at runtime. I don't think we need to worry too much about what the C standard says here; the language around floating-point types that don't have infinity was written in the old days before everyone settled on using IEEE math. And I think the warning we currently produce is probably more helpful in practice than "INFINITY not defined". What I was getting at with the standard version thing is that in standard versions before C23, I don't think NAN is a reserved identifier if you don't include math.h. So it's forbidden for float.h to define it. |
I looked at my meeting notes for discussion of this paper and I think we do need to worry about what the C standard says. From my notes: Also, we can't really rely on UB at runtime because of constant expressions have a constraint that says constant expressions have to evaluate to a constant in the range of representable values for its type. With C23 adding
Oh, that's a good point! I'll guard this by C23 and not C99 once we figure out what it means to "support an infinity". |
I went looking through the CFP history of the proposal. It's based on a comp.std.c thread here: https://groups.google.com/g/comp.std.c/c/XCzEiwD9n_A, which became a CFP discussion here: https://mailman.oakapple.net/pipermail/cfp-interest/2021-October/002216.html (and more in the September portion of the archives, but the relevant part of the discussion is in October), and the minutes of the CFP meeting where this was discussed here: https://mailman.oakapple.net/pipermail/cfp-interest/2021-October/002253.html The entire history of this discussion is about FP types that do not have a format for infinity (say, VAX FP), and there was commentary on the CFP thread that there was evidence that users thought that |
I spoke with the chair of CFP and he agreed with my assessment that Aside from "compatibility/historically", do we have any technical arguments against following the intent of the standard here? (We already deviate from GCC in so many other ways, I'm not worried about a deviation here; I would presume GCC will eventually get around to doing the same thing, at least for C23 and up). |
I was thinking about this more last night. The standard says:
Some interesting things to note:
I think that not defining WDYT? |
Some thoughts of my own: The decision being discussed here has two main repercussions:
In the first case, I think you get a better error message with the Most programmers, if they have any understanding of floating-point, would understand floating point only in terms of IEEE 754 types, which have an infinity; the existence of floating-point formats that lack infinities is going to be new to them, much less the ability to test such systems. So the lack of an Code that attempts to intentionally use infinity in a If the user is explicitly savvy about the existence of fast-math, they already have the opportunity to protect themselves from users who blindly apply In short: IMHO, |
@jcranmer-intel and I had a really nice offline discussion on this topic and I've come around to his view. I was thinking that the fact we don't currently diagnose use of So let's split this PR into two parts: 1) I'll update this PR to always define |
* Now defines the macros even in -ffinite-math-only mode * Defines the macros only in C23 and up, not in C99 and up * Fixed the test coverage, added tests for use in a constant expression * Fixed the expansion of the INFINITY macro (should resolve a precommit CI issue)
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 already have -Wnan-infinity-disabled
, which I think is sufficient on the warning side? Haven't checked carefully to see what cases it covers.
Not this one. :-D https://godbolt.org/z/hq8jvse9o But yeah, that may be a good diagnostic to consider putting this under, but I think that diagnostic should be enabled by default when passing -Wfinite-math-only or other flags that disable infinity or nan support. |
You can test this locally with the following command:git-clang-format --diff de68294b4dd31370773cb7a976b2d59e0e8b9bcc 3f6278781a1cd8d2366e0c55cd19e559e6ee1549 -- clang/lib/Headers/float.h clang/test/Headers/float.c View the diff from clang-format here.diff --git a/clang/lib/Headers/float.h b/clang/lib/Headers/float.h
index a565a33243..77e48138b9 100644
--- a/clang/lib/Headers/float.h
+++ b/clang/lib/Headers/float.h
@@ -90,8 +90,8 @@
#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L) || \
!defined(__STRICT_ANSI__)
-# undef INFINITY
-# undef NAN
+#undef INFINITY
+#undef NAN
#endif
/* Characteristics of floating point types, C99 5.2.4.2.2 */
@@ -163,9 +163,9 @@
#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L) || \
!defined(__STRICT_ANSI__)
- /* C23 5.2.5.3.3p29-30 */
-# define INFINITY (__builtin_inf())
-# define NAN (__builtin_nan(""))
+/* C23 5.2.5.3.3p29-30 */
+#define INFINITY (__builtin_inf())
+#define NAN (__builtin_nan(""))
#endif
#ifdef __STDC_WANT_IEC_60559_TYPES_EXT__
|
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.
LGTM
This is in support of WG14 N2848 which only define the macros if an infinity or nan are supported. However, because we support builtins that can produce an infinity or a NAN, and because we have pragmas that control infinity or NAN behavior, we always define the macros even if the user passed -ffinite-math-only on the command line.
This is in support of WG14 N2848 which only define the macros if an infinity or nan are supported. However, because we support builtins that can produce an infinity or a NAN, and because we have pragmas that control infinity or NAN behavior, we always define the macros even if the user passed -ffinite-math-only on the command line.
@AaronBallman N2848 explicitly mentions that
|
WHOOOOOOPPPPSSS yup, looks like I also missed some test coverage. :-D I'll get that fixed up ASAP, thank you! |
This should be fixed now in 2f2b931, thank you! |
Thanks a lot for the quick fix! |
since C23 this macro is defined by float.h, which clang implements in it's float.h since #96659 landed. However, regcomp.c in LLVMSupport happened to define it's own macro with that name, leading to problems when bootstrapping. This change renames the offending macro.
since C23 this macro is defined by float.h, which clang implements in it's float.h since llvm#96659 landed. However, regcomp.c in LLVMSupport happened to define it's own macro with that name, leading to problems when bootstrapping. This change renames the offending macro. (cherry picked from commit 899f648)
since C23 this macro is defined by float.h, which clang implements in it's float.h since llvm#96659 landed. However, regcomp.c in LLVMSupport happened to define it's own macro with that name, leading to problems when bootstrapping. This change renames the offending macro. (cherry picked from commit 899f648)
since C23 this macro is defined by float.h, which clang implements in it's float.h since llvm#96659 landed. However, regcomp.c in LLVMSupport happened to define it's own macro with that name, leading to problems when bootstrapping. This change renames the offending macro.
This is in support of WG14 N2848 which only define the macros if
infinity and nan are supported, so use of -ffinite-math will cause the
macros to not be defined.