/* Verify that when we complain about incompatible pointer types involving function pointers, we show the declaration of the function. */ /* { dg-do compile } */ /* { dg-options "-std=c23 -pedantic-errors" } */ /* We're pretending that this is legacy code that was written before C23, hence it uses NULL rather than nullptr. */ #define NULL ((void*)0) typedef void (*void_int_fnptr_t) (int); extern void takes_void_int_fnptr (void_int_fnptr_t fn); /* { dg-message "expected 'void_int_fnptr_t' \\{aka '\[^\n\r\]*'\\} but argument is of type '\[^\n\r\]*'" } */ extern void fn_argpass(); /* { dg-message "declared here" } */ void test_argpass () { takes_void_int_fnptr (&fn_argpass); /* { dg-error "passing argument 1 of 'takes_void_int_fnptr' from incompatible pointer type" } */ } extern void fn_assign(); /* { dg-message "declared here" } */ void test_assign () { void (*assigned_to) (int); assigned_to = &fn_assign; /* { dg-error "assignment to '\[^\n\r\]*' from incompatible pointer type '\[^\n\r\]*'" } */ } extern void fn_init(); /* { dg-message "declared here" } */ void test_init () { void (*initialized) (int) = &fn_init; /* { dg-error "initialization of '\[^\n\r\]*' from incompatible pointer type '\[^\n\r\]*'" } */ } extern void fn_return(); /* { dg-message "declared here" } */ void_int_fnptr_t test_return () { return &fn_return; /* { dg-error "returning '\[^\n\r\]*' from a function with incompatible return type '\[^\n\r\]*'" } */ } /* Test of storing a sighandler_t with a function signature mismatch. In particular, verify that we show the locations of typedefs. */ typedef void (*sighandler_t)(int); /* { dg-message "'sighandler_t' declared here" } */ sighandler_t signal(int signum, sighandler_t handler); typedef void (*wrong_sighandler_t)(void); /* { dg-message "'wrong_sighandler_t' declared here" } */ extern void takes_wrong_sighandler_type (wrong_sighandler_t fn); /* { dg-message "expected 'wrong_sighandler_t' \\{aka '\[^\n\r\]*'\\} but argument is of type 'sighandler_t' \\{aka '\[^\n\r\]*'\\}" } */ void test_argpass_from_signal_result () { takes_wrong_sighandler_type (signal (42, NULL)); /* { dg-error "passing argument 1 of 'takes_wrong_sighandler_type' from incompatible pointer type" } */ } void test_assign_from_signal_result () { wrong_sighandler_t assigned_to; assigned_to = signal (42, NULL); /* { dg-error "assignment to 'wrong_sighandler_t' \\{aka '\[^\n\r\]*'\\} from incompatible pointer type 'sighandler_t' \\{aka '\[^\n\r\]*'\\}" } */ } void test_init_from_signal_result () { wrong_sighandler_t initialized = signal (42, NULL); /* { dg-error "initialization of 'wrong_sighandler_t' \\{aka '\[^\n\r\]*'\\} from incompatible pointer type 'sighandler_t' \\{aka '\[^\n\r\]*'\\}" } */ } wrong_sighandler_t test_return_signal_result () { return signal (42, NULL); /* { dg-error "returning 'sighandler_t' \\{aka '\[^\n\r\]*'\\} from a function with incompatible return type 'wrong_sighandler_t' \\{aka '\[^\n\r\]*'\\}" } */ }