|
|
Message-ID: <20251126211823.GZ1827@brightrain.aerifal.cx>
Date: Wed, 26 Nov 2025 16:18:25 -0500
From: Rich Felker <dalias@...c.org>
To: Alejandro Colomar <alx@...nel.org>
Cc: musl@...ts.openwall.com
Subject: Re: [PATCH v2 1/1] include/string.h: Implement QChar wrappers
standardized in C23
On Wed, Nov 26, 2025 at 04:36:38PM +0100, Alejandro Colomar wrote:
> Hi Rich,
>
> On Wed, Nov 26, 2025 at 10:02:22AM -0500, Rich Felker wrote:
> > On Wed, Nov 26, 2025 at 03:56:21PM +0100, Alejandro Colomar wrote:
> [...]
> > It doesn't have to be functionally breaking common code in the wild to
> > be breaking the *contract*. You'd not allowed to change them because
> > the specification fixes the signatures in stone.
>
> Agree. Given how few functions use QChar in the standard library, and
> how stable the standard library is, typos would be unlikely and would be
> obvious enough that they wouldn't pass any review.
>
> > > > > > Also, can't __Qcharof just be defined as something like
> > > > > > typeof(1?(s):"") without any fancy _Generic machinery?
> > > > >
> > > > > This wouldn't accept void*, and these functions should accept void*
> > > > > arguments.
> > > >
> > > > I was thinking the ternary of char* and void* would produce char*, but
> > > > indeed I'm always wrong about that.
> > >
> > > You weren't totally wrong. There's special case where that's true: NULL
> > >
> > > alx@...uan:~/tmp$ cat typeof.c
> > > #include <stdio.h>
> > > int
> > > main(void)
> > > {
> > > const char *cc;
> > > const void *cv;
> > > char *c;
> > > void *v;
> > >
> > > _Generic(typeof(1?cc:""), const char *: 0);
> > > _Generic(typeof(1?cv:""), const char *: 0);
> > > _Generic(typeof(1? c:""), char *: 0);
> > > _Generic(typeof(1? v:""), char *: 0);
> > >
> > > _Generic(typeof(1?(void *) 0:""), const char *: 0);
> > > _Generic(typeof(1?(const void *)0:""), char *: 0);
> > > }
> > > alx@...uan:~/tmp$ gcc typeof.c
> > > typeof.c: In function ‘main’:
> > > typeof.c:11:18: error: ‘_Generic’ selector of type ‘const void *’ is not compatible with any association
> > > 11 | _Generic(typeof(1?cv:""), const char *: 0);
> > > | ^~~~~~
> > > typeof.c:13:18: error: ‘_Generic’ selector of type ‘void *’ is not compatible with any association
> > > 13 | _Generic(typeof(1? v:""), char *: 0);
> > > | ^~~~~~
> > > typeof.c:15:18: error: ‘_Generic’ selector of type ‘char *’ is not compatible with any association
> > > 15 | _Generic(typeof(1?(void *) 0:""), const char *: 0);
> > > | ^~~~~~
> > > typeof.c:16:18: error: ‘_Generic’ selector of type ‘const void *’ is not compatible with any association
> > > 16 | _Generic(typeof(1?(const void *)0:""), char *: 0);
> > > | ^~~~~~
> > >
> > > As you can see, typeof(1?(void*)0:"") produces a char*. Any other void*
> > > doesn't. This means that the type of NULL is a magic type different
> > > from void*, but which is compatible with void*. This is slightly
> > > different from nullptr_t in that _Generic(3) is able to distinguish
> > > nullptr_t form void*, but not the type of NULL from void*, but it's
> > > pretty similar.
> >
> > typeof(1?"":(typeof(s))0) maybe? I think it works!
>
> Almost! It's closer. :)
>
> alx@...uan:~/tmp$ cat typeof.c
> #include <stdio.h>
>
> #if defined TRY1
> # define QCharptrof(s) typeof(1?s:"")
>
> #elif defined TRY2
> # define QCharptrof(s) typeof(1?"":(typeof(s))0)
>
> #else
> # define QCharptrof(s) typeof(QCharof(s) *)
> # define QCharof(s) typeof \
> ( \
> _Generic(s, \
> const char *: (const char){}, \
> const void *: (const char){}, \
> char *: (char){}, \
> void *: (char){} \
> ) \
> )
> #endif
>
> int
> main(void)
> {
> const char *cc;
> const void *cv;
> char *c;
> void *v;
>
> _Generic(QCharptrof( cc), const char *: 0);
> _Generic(QCharptrof( cv), const char *: 0);
> _Generic(QCharptrof( c), char *: 0);
> _Generic(QCharptrof( v), char *: 0);
> _Generic(QCharptrof(NULL), char *: 0);
> }
>
> alx@...uan:~/tmp$ gcc typeof.c
> alx@...uan:~/tmp$ gcc -D TRY1 typeof.c
> typeof.c: In function ‘main’:
> typeof.c:4:25: error: ‘_Generic’ selector of type ‘const void *’ is not compatible with any association
> 4 | # define QCharptrof(s) typeof(1?s:"")
> | ^~~~~~
> typeof.c:31:18: note: in expansion of macro ‘QCharptrof’
> 31 | _Generic(QCharptrof( cv), const char *: 0);
> | ^~~~~~~~~~
> typeof.c:4:25: error: ‘_Generic’ selector of type ‘void *’ is not compatible with any association
> 4 | # define QCharptrof(s) typeof(1?s:"")
> | ^~~~~~
> typeof.c:33:18: note: in expansion of macro ‘QCharptrof’
> 33 | _Generic(QCharptrof( v), char *: 0);
> | ^~~~~~~~~~
> alx@...uan:~/tmp$ gcc -D TRY2 typeof.c
> typeof.c: In function ‘main’:
> typeof.c:7:25: error: ‘_Generic’ selector of type ‘const void *’ is not compatible with any association
> 7 | # define QCharptrof(s) typeof(1?"":(typeof(s))0)
> | ^~~~~~
> typeof.c:31:18: note: in expansion of macro ‘QCharptrof’
> 31 | _Generic(QCharptrof( cv), const char *: 0);
> | ^~~~~~~~~~
Hmm, maybe it doesn't work. It looks like only exactly (void *)0 is a
null pointer constant. A cast to a qualified void pointer type isn't
one. I'm not sure if it's fixable.
Rich
Powered by blists - more mailing lists
Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.