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