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-----