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