On Sat, 2025-01-11 at 13:55 -0500, David Malcolm wrote:
> PR c/116871 notes that our diagnostics about incompatible function
> types
> could be improved.
>
> In particular, for the case of migrating to C23 I'm seeing a lot of
> build failures with signal handlers similar to this (simplified from
> alsa-tools-1.2.11, envy24control/profiles.c; see rhbz#2336278):
>
> typedef void (*__sighandler_t) (int);
>
> extern __sighandler_t signal (int __sig, __sighandler_t __handler)
> __attribute__ ((__nothrow__ , __leaf__));
>
> void new_process(void)
> {
> void (*int_stat)();
>
> int_stat = signal(2, ((__sighandler_t) 1));
>
> signal(2, int_stat);
> }
>
> With trunk, cc1 fails with this message:
>
> t.c: In function 'new_process':
> t.c:18:12: error: assignment to 'void (*)(void)' from incompatible
> pointer type '__sighandler_t' {aka 'void (*)(int)'} [-Wincompatible-
> pointer-types]
> 18 | int_stat = signal(2, ((__sighandler_t) 1));
> | ^
> t.c:20:13: error: passing argument 2 of 'signal' from incompatible
> pointer type [-Wincompatible-pointer-types]
> 20 | signal(2, int_stat);
> | ^~~~~~~~
> | |
> | void (*)(void)
> t.c:11:57: note: expected '__sighandler_t' {aka 'void (*)(int)'} but
> argument is of type 'void (*)(void)'
> 11 | extern __sighandler_t signal (int __sig, __sighandler_t
> __handler)
> |
> ~~~~~~~~~~~~~~~^~~~~~~~~
>
> With this patch, cc1 emits:
>
> t.c: In function 'new_process':
> t.c:18:12: error: assignment to 'void (*)(void)' from incompatible
> pointer type '__sighandler_t' {aka 'void (*)(int)'} [-Wincompatible-
> pointer-types]
> 18 | int_stat = signal(2, ((__sighandler_t) 1));
> | ^
> t.c:9:16: note: '__sighandler_t' declared here
> 9 | typedef void (*__sighandler_t) (int);
> | ^~~~~~~~~~~~~~
> cc1: note: the meaning of '()' in function declarations changed in
> C23 from '(int)' to '(void)'
> t.c:20:13: error: passing argument 2 of 'signal' from incompatible
> pointer type [-Wincompatible-pointer-types]
> 20 | signal(2, int_stat);
> | ^~~~~~~~
> | |
> | void (*)(void)
> t.c:11:57: note: expected '__sighandler_t' {aka 'void (*)(int)'} but
> argument is of type 'void (*)(void)'
> 11 | extern __sighandler_t signal (int __sig, __sighandler_t
> __handler)
> |
> ~~~~~~~~~~~~~~~^~~~~~~~~
> t.c:9:16: note: '__sighandler_t' declared here
> 9 | typedef void (*__sighandler_t) (int);
> | ^~~~~~~~~~~~~~
>
> showing the location of the pertinent typedef ("__sighandler_t"), and
> emitting the note
> "the meaning of '()' in function declarations changed in C23
> from '(int)' to '(void)'"
>
> Another example, simplfied from a52dec-0.7.4: src/a52dec.c
> (rhbz#2336013):
>
> typedef void (*__sighandler_t) (int);
>
> extern __sighandler_t signal (int __sig, __sighandler_t __handler)
> __attribute__ ((__nothrow__ , __leaf__));
>
> /* Mismatching return type. */
> #define RETSIGTYPE int
> static RETSIGTYPE signal_handler (int sig)
> {
> }
>
> static void print_fps (int final)
> {
> signal (42, signal_handler);
> }
>
> With trunk, cc1 emits:
>
> t2.c: In function 'print_fps':
> t2.c:22:15: error: passing argument 2 of 'signal' from incompatible
> pointer type [-Wincompatible-pointer-types]
> 22 | signal (42, signal_handler);
> | ^~~~~~~~~~~~~~
> | |
> | int (*)(int)
> t2.c:11:57: note: expected '__sighandler_t' {aka 'void (*)(int)'} but
> argument is of type 'int (*)(int)'
> 11 | extern __sighandler_t signal (int __sig, __sighandler_t
> __handler)
> |
> ~~~~~~~~~~~~~~~^~~~~~~~~
>
> With this patch cc1 emits:
>
> t2.c: In function 'print_fps':
> t2.c:22:15: error: passing argument 2 of 'signal' from incompatible
> pointer type [-Wincompatible-pointer-types]
> 22 | signal (42, signal_handler);
> | ^~~~~~~~~~~~~~
> | |
> | int (*)(int)
> t2.c:11:57: note: expected '__sighandler_t' {aka 'void (*)(int)'} but
> argument is of type 'int (*)(int)'
> 11 | extern __sighandler_t signal (int __sig, __sighandler_t
> __handler)
> |
> ~~~~~~~~~~~~~~~^~~~~~~~~
> t2.c:16:19: note: 'signal_handler' declared here
> 16 | static RETSIGTYPE signal_handler (int sig)
> | ^~~~~~~~~~~~~~
> t2.c:9:16: note: '__sighandler_t' declared here
> 9 | typedef void (*__sighandler_t) (int);
> | ^~~~~~~~~~~~~~
>
> showing the location of the pertinent fndecl ("signal_handler"), and,
> as before, the pertinent typedef.
>
> The patch also updates the colorization in the messages to visually
> link and contrast the different types and typedefs; I'm going to
> upload screenshots to the bug.
I've uploaded screenshots as attachments to
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116871
cc1 output from before the patch:
https://gcc.gnu.org/bugzilla/attachment.cgi?id=60117
cc1 output from after the patch:
https://gcc.gnu.org/bugzilla/attachment.cgi?id=60118
>
> [...snip...]
Dave