Implement C23 const-preserving standard library macros
Joseph Myers
josmyers@redhat.com
Wed Nov 19 13:29:20 GMT 2025
On Tue, 18 Nov 2025, Paul Eggert wrote:
> On 2025-11-18 13:27, Joseph Myers wrote:
> > +#if __HAVE_GENERIC_SELECTION
> > +/* If PTR is a pointer to const, return CALL cast to type CTYPE,
> > + otherwise return CALL. Pointers to types with non-const qualifiers
> > + are not valid. This should not be defined for C++, as macros are
> > + not an appropriate way of implementing such qualifier-generic
> > + operations for C++. */
> > +# define __glibc_const_generic(PTR, CTYPE, CALL) \
> > + _Generic (0 ? (PTR) : (void *) 1, \
>
> Any reason this is (void *) 1 and not (void *) 0? I worry some compilers might
> diagnose the (void *) 1.
The requirement is that it's a pointer to (unqualified) void that's not a
null pointer constant, to ensure the result is of type pointer to
(qualified) void regardless of the original pointer target type. (void *) 0
is a null pointer constant, which affects the rules for the result type of
a conditional expression.
> > + const void *: (CTYPE) (CALL), \
> > + void *: (CALL))
> > +#endif
>
> With GCC this turns some warnings into errors. For example:
>
> int
> foo (char volatile *p)
> {
> return !strchr (p, 'x');
> }
>
> is currently a warning, but would become an error. To avoid this problem, you
> can change "void *: (CALL)" to "default: (CALL)". Or better, to "default:
> CALL" since the parentheses are unnecessary.
Note that calling these functions with a pointer-to-volatile has never
been valid and still isn't valid (but it's not necessary to turn it into
an error if we don't want to do so).
--
Joseph S. Myers
josmyers@redhat.com
More information about the Libc-alpha
mailing list