Define C23 header version macros
Joseph Myers
josmyers@redhat.com
Fri Nov 21 22:02:40 GMT 2025
On Thu, 20 Nov 2025, Paul Eggert wrote:
> > --- a/assert/assert.h
> > +++ b/assert/assert.h
> > @@ -34,6 +34,12 @@
> > #define _ASSERT_H 1
> > #include <features.h>
> > +#if __GLIBC_USE (ISOC23)
> > +# ifndef __STDC_VERSION_ASSERT_H__
> > +# define __STDC_VERSION_ASSERT_H__ 202311L
> > +# endif
> > +#endif
>
> assert.h is special because it can be multiply included with different effects
> each time. So shouldn't this be done like other assert macros? That is, define
> __STDC_VERSION_ASSERT_H__ without using the ifndef here, and near the file's
> start if _ASSERT_H is already defined then #undef __STDC_VERSION_ASSERT_H__
> there. Although this sort of thing matters only if the user fiddles with
> _ISOC23_SOURCE (which the user shouldn't do of course) it would be a bit more
> robust in that fiddly situation.
I don't think there can be any reasonable expectations for how
__STDC_VERSION_ASSERT_H__ is or isn't defined if the header is included
more than once with different standard versions. features.h *does* have
multiple include guards (and bits/libc-header-start.h is only for C
standard feature test macros), so fiddling with _ISOC23_SOURCE after
including a header wouldn't even do anything useful.
> Also, suppose the user compiles with --std=gnu2y? What should the value of
> __STDC_VERSION_ASSERT_H__ be then? Perhaps it should be some intermediate
> value like 202505L for the latest C2y draft that glibc supports? Similarly for
> other __STDC_VERSION_*_H__ macros.
At the February 2023 WG14 meeting, there was a discussion of whether
__has_c_attribute values should change in future standard versions if
there are no changes to a particular attribute, and the opinion poll
expressed the view that such values should not change in that case. That
doesn't say what would happen for __STDC_VERSION_*_H__ but does tend to
suggest not changing the values in the absence of changes to a header
(which is consistent with how the working draft has been edited so far for
C2y), so that those macros are handled consistently with
__has_c_attribute. (It was agreed for __has_c_attribute to make the value
reflect the __STDC_VERSION__ value for the final published standard, even
when lower values were first put in working drafts as placeholders before
the final __STDC_VERSION__ value for that version of the standard was
known.)
If a particular header has changes in C2y *and* we've implemented all of
them, we could choose to change the value like that. It would need to be
conditional on __GLIBC_USE (ISOC2Y), since each standard version says what
the value of the macros is - *not* that they might have a higher value as
well.
It's not always clear what's enough of a change to be worth updating the
value of such a macro (or defining it for the first time); consider e.g.
the version macro in <setjmp.h>, where it's questionable if there were
really feature changes meriting defining a version macro (but CD1 comment
GB-188 on that subject received no consensus in the vote at the February
2023 meeting; the actual change to <setjmp.h> in C23 was to declare
longjmp with [[noreturn]] instead of _Noreturn in the prototype given in
the function description in the standard).
> > +# ifndef __STDC_VERSION_LIMITS_H__
> > +# define __STDC_VERSION_LIMITS_H__ 202311L
> > +# endif
>
> Why is the ifndef needed here, instead of a plain #define? Other places don't
> have such an ifndef (except for assert.h, which is special because it can be
> multiply included and which I discussed above).
(a) <limits.h> can get included together with GCC's <limits.h>, which
might or might not define the macro depending on the GCC version (macro
definition introduced in GCC 13), and (b) GCC diagnoses duplicate
definitions of __STDC_* macros, even with the same value, which is why we
need to take steps to avoid such duplicates in cases where some kind of
multiple inclusion is possible.
> > +#if __GLIBC_USE (ISOC23)
> > +# define __STDC_VERSION_STDIO_H__ 202311L
> > +#endif
>
> Since glibc supports C23 <stdio.h>'s features regardless of whether
> __GLIBC_USE (ISOC23) is true, how about doing this #define unconditionally?
Whether scanf functions handle 0b and 0B as binary for %i depends on
__GLIBC_USE (ISOC23).
> Similarly for other __STDC_VERSION_*_H__ macros: the idea is to define each
> such macro if the corresponding C23 features are supported, regardless of
> whether __GLIBC_USE (ISOC23) is true.
Technically that would be valid in cases where no new declarations or
macro definitions or semantics conditional on the language version are
involved. But given that if standard version X defines a value for the
macro and standard version Y defines a new value, we can't use standard
Y's value when compiling for standard X, doing something different just
for the case where the standard imposes no constraints on the presence or
value of such a macro (i.e. for standard versions before the macro was
introduced for that header) doesn't seem that useful.
--
Joseph S. Myers
josmyers@redhat.com
More information about the Libc-alpha
mailing list