Re: Minor cleanup after adding more warnings to CFLAGS

Alejandro Colomar via Mutt-dev <[email protected]>
Newsgroups gmane.mail.mutt.devel
Message-ID <aeF5M6eOVsGnO_Jw@devuan>
Hi Steffen,

On 2026-04-17T01:53:43+0200, Steffen Nurpmeso wrote:
> ok sorry i should not post at all .. i realized in the meantime
> this C23 was on the table at first long ago, by Rene Kita,
> already..  but
> 
> Alejandro Colomar via Mutt-dev wrote in
>  <aeDEw-PCa6n1P_4R@devuan>:
>  ..
>  |I've implemented a patch for musl (which hasn't been merged yet).
>  |It only needs C11 features.

Plus typeof, which I give as granted, of course.

> 
> This is very (, very) cool.

Thanks!  :)

> 
>  |You can have a look at it to see how that is implemented:
>  |<https://www.openwall.com/lists/musl/2026/02/23/2>
> 
>  |It's much simpler than the glibc implementation, IMO.
>  |
>  |I'll paste here the essentials:
>  |
>  | #define __QVoidptrof(p)  typeof(1?(p):(void*){0})
>  | #define __QCharptrof(s)  typeof                               \
>  | (                                                             \
>  |  _Generic((__QVoidptrof(s)){0},                        \
>  |   const void *: (const char *) 0,               \
>  |   void *:       (char *) 0                      \
>  |  )                                                     \
>  | )
>  |
>  | #define memchr(p, ...)      ((__QVoidptrof(p)) memchr(p, __VA_ARGS__))
>  | #define memmem(p, ...)      ((__QVoidptrof(p)) memmem(p, __VA_ARGS__))
>  | #define memrchr(p, ...)     ((__QVoidptrof(p)) memrchr(p, __VA_ARGS__))
>  |
>  | #define strchr(s, ...)      ((__QCharptrof(s)) strchr(s, __VA_ARGS__))
>  | #define strrchr(s, ...)     ((__QCharptrof(s)) strrchr(s, __VA_ARGS__))
>  | #define strpbrk(s, ...)     ((__QCharptrof(s)) strpbrk(s, __VA_ARGS__))
>  | #define strstr(s, ...)      ((__QCharptrof(s)) strstr(s, __VA_ARGS__))
>  | #define strchrnul(s, ...)   ((__QCharptrof(s)) strchrnul(s, __VA_ARGS__))
>  | #define strcasestr(s, ...)  ((__QCharptrof(s)) strcasestr(s, __VA_ARGS__))
> 
> That __Qvoidptr() really is magic to me.
> I still do not get it, and your "how" did not give any glue.

Yup, I meant how it can be done, not really an explanation of how the
magic works.  I guess I should have explained it, as it's really not
obvious.

The macro is

	#define __QVoidptrof(p)  typeof(1?(p):(void*){0})

The interesting thing is the third operand to the ternary operator.

One thing to know is that the null pointer constant is magic, and
different from a regular null pointer of type void*.

Here's a relevant quote from C11 about the conditional operator:

<https://port70.net/~nsz/c/c11/n1570.html#6.5.15p6>

	If both the second and third operands are pointers
	or one is a null pointer constant and the other is a pointer,
	the result type is
	a pointer to a type
		qualified with all the type qualifiers
		of the types referenced by both operands.
	Furthermore,
	if both operands are pointers to compatible types
	or to differently qualified versions of compatible types,
	the result type is
	a pointer to
		an appropriately qualified version
		of the composite type;
	if one operand is a null pointer constant,
	the result has the type
		of the other operand;
	otherwise,
	one operand is a pointer to void or a qualified version of void,
	in which case the result type is
		a pointer to an appropriately qualified version
		of void.

This means that

	const    int  *p;
	volatile int  *q;

	typeof(1 ? p : q)            x;  // const volatile int  *
	typeof(1 ? p : NULL)         y;  // const          int  *
	typeof(1 ? p : (void *){0})  z;  // const          void *

In the case of x, the clause 'Furthermore, ...' applies.
In the case of y, the clause 'if one operand is a null pointer
constant, ...' applies.
In the case of z, since (void*){0} is not a null pointer constant, but
it is a pointer to void, the last clause applies, and thus we get an
appropriately qualified version of void.

This can be shown with the following program:

	alx@devuan:~/tmp$ cat t.c 
	#include <stddef.h>

	int
	main(void)
	{
		const    int  *p;
		volatile int  *q;

		_Generic(typeof(1 ? p : q),           const volatile int  *: 0);
		_Generic(typeof(1 ? p : NULL),        const          int  *: 0);
		_Generic(typeof(1 ? p : (void *){0}), const          void *: 0);
	}
	alx@devuan:~/tmp$ gcc -Wall -Wextra -Wno-unused t.c 
	alx@devuan:~/tmp$ 

About why the compound literal (void *){0} is not a null pointer
constant, it's because the null pointer constants are very limited.
<https://port70.net/~nsz/c/c11/n1570.html#6.3.2.3p3>

	An integer constant expression with the value 0,
	or such an expression cast to type void *,
	is called a null pointer constant.

Since a compound literal is none of that, it can't be a null pointer
constant, which gives us the interesting properties we get here.

(BTW, an integer constant expression with the value 0 will eventually
 stop being a null pointer constant.  GCC has added
 -Wzero-as-null-pointer-constant in C mode recently, and some
 C Committee members --including myself, and some GCC contributors-- are
 planning the removal in the standard in a way that will have a
 relatively smooth transition.  Then, the only null pointer constant
 will be (void*)0, and of course the horrible nullptr, but we better
 act as if that never existed.)

[...]
> 
> But that __Qvoidptr() totally escapes me.
> Ie decay (Joy Division is greeting) back and forth, i must specify
> a compatible pointer type, and no matter whether i say
>   typeof(true ? x : y)
> or
>   typeof(false ? x : y)
> or the order of x and y, i will always get a "void [const]*".
> 
> I mean, "all pointer types implicitly convert to void*".
> But it is total magic!

:-)


Have a lovely night!
Alex

> 
> --steffen
> |
> |Der Kragenbaer,                The moon bear,
> |der holt sich munter           he cheerfully and one by one
> |einen nach dem anderen runter  wa.ks himself off
> |(By Robert Gernhardt)

-- 
<https://www.alejandro-colomar.es>
signature.asc (application/pgp-signature, 833 B)
-----BEGIN PGP SIGNATURE-----

iQIzBAABCgAdFiEES7Jt9u9GbmlWADAi64mZXMKQwqkFAmnhf1EACgkQ64mZXMKQ
wqkMbQ/+KxjPL5NlGWZ1t64nEFfTJPsS8sOoQkHUe3P6/asdNkFMMWzH1T198J0P
m7pRYdNbkJAF+QGp7tA40z6mt+Qld43I107NtLjcsVUjkqwgBoTZCao+W/RmV/bs
lNnOppvR+5jesP0pCIBgcXfdZD58iZyFu90443mtzOkm1mhMc8RkAnaw3BR7gWrQ
DbpO/0EbkSh2hxCRDC7WRT4Rv6yr9Y/iXp5yX0gzQ2i7mX1+G1TopxlSs7fdUZWY
grVgZ0lqtmPW/PkV9LsD+X1GGuHSnHRt3byGYiBLqitLRMKfAOfIdvW5boHir2wg
nPZB7u/GzmVQ5GdUe3CuHeXJ6aKBsbqZX4v4il7YYgjXmiwZZmi1lQzrklfdxKiy
yGujSxNLVHjdzDp1t5oNydndw6BT4S1v0EcDo71OECUyui+zpNthTgix9xt4f17R
vt226ptTN462zy/Ur1bmqrLkJX1X2cY5wtFciqhczc5tHryaKiH4gWeV0klxaJD3
bJrLGycy2R1mJWM7UQU3GxCfbpVmhidGcK82EanNb/Cg+dMNesPDp+wE4Q6vzryK
KcJ1uu5VM/mKNL808QsUEBhAIM2FZVgX2F2L8AQnAJO4TBWTovO9oxcshjKPt2nr
ENVrNZDPLOdJAdXEvHpptw8qTKQVASCS+SrUErO+zFxfPA/Kdmc=
=VDYy
-----END PGP SIGNATURE-----
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.