| /* PR c/83656 - missing -Wbuiltin-declaration-mismatch on declaration |
| without prototype |
| { dg-do compile } |
| { dg-options "-Wbuiltin-declaration-mismatch" } */ |
| |
| typedef __SIZE_TYPE__ size_t; |
| |
| /* Built-ins declared without a prototype are not diagnosed by default |
| (without -Wextra) except when their return type doesn't match. */ |
| int abort (); /* { dg-warning "\\\[-Wbuiltin-declaration-mismatch]" } */ |
| |
| /* Built-ins declared without a prototype are not diagnosed without -Wextra. */ |
| void exit (); |
| void* memcpy (); |
| void* memset (); |
| |
| |
| void test_call_abort (void) |
| { |
| /* Verify that a valid call to abort() is not diagnosed. */ |
| abort (); |
| |
| /* Unfortunately, the incompatible declaration above makes GCC "forget" |
| that abort() is a built-in and so the invalid calls below aren't |
| diagnosed. The only saving grace is that the invalid declaration |
| that differs in the return type is diagnosed by default. */ |
| abort (1); /* { dg-warning "too many arguments to built-in function .abort. expecting 0" "pr?????" { xfail *-*-* } } */ |
| |
| abort (1, 2); /* { dg-warning "too many arguments" "pr?????" { xfail *-*-* } } */ |
| } |
| |
| |
| void test_call_exit (void) |
| { |
| /* Verify that valid calls to exit are not diagnosed. */ |
| exit ('\0'); |
| exit (0); |
| |
| /* Also verify calls to the built-in. */ |
| __builtin_exit ('\0'); |
| __builtin_exit (0); |
| __builtin_exit (0.0); |
| |
| exit (); /* { dg-warning "too few arguments to built-in function 'exit' expecting 1" } */ |
| |
| exit (1, 2); /* { dg-warning "too many arguments" } */ |
| |
| /* Verify that passing incompatible arguments triggers a warning. */ |
| exit (""); /* { dg-warning "\\\[-Wint-conversion]" } */ |
| |
| struct S { int i; } s = { 0 }; |
| exit (s); /* { dg-warning "incompatible type for argument 1" } */ |
| } |
| |
| |
| void test_call_memcpy (void *p, const void *q, size_t n) |
| { |
| memcpy (p, q, n); |
| |
| memcpy (); /* { dg-warning "too few arguments to built-in function 'memcpy' expecting 3" } */ |
| |
| memcpy (p); /* { dg-warning "too few arguments to built-in function 'memcpy' expecting 3" } */ |
| |
| memcpy (p, q); /* { dg-warning "too few arguments to built-in function 'memcpy' expecting 3" } */ |
| |
| memcpy (q, p, n); /* { dg-warning "\\\[-Wdiscarded-qualifiers]" } */ |
| |
| memcpy (p, n, q); /* { dg-warning "\\\[-Wint-conversion]" } */ |
| |
| memcpy (p, q, n, 0); /* { dg-warning "too many arguments to built-in function 'memcpy' expecting 3" } */ |
| } |
| |
| |
| typedef void* (memcpy_t)(void*, const void*, size_t); |
| typedef void* (memset_t)(void*, int, size_t); |
| |
| void test_init (void) |
| { |
| /* Verify that initialization of a pointer by the address of a built-in |
| function of a matching type declared without a prototype doesn't |
| trigger a warning... */ |
| memset_t *pmemset = memset; |
| |
| /* ...but initialization by the address of an incompatible built-in |
| does even without -Wextra. */ |
| memcpy_t *pmemcpy = memset; /* { dg-warning "\\\[-Wincompatible-pointer-types]" } */ |
| } |
| |
| |
| void test_assign (void) |
| { |
| /* Same as above but for assignment. */ |
| memset_t *pmemset; |
| pmemset = memset; |
| |
| memcpy_t *pmemcpy; |
| pmemcpy = memset; /* { dg-warning "\\\[-Wincompatible-pointer-types]" } */ |
| } |
| |
| |
| /* Verify that passing built-ins declared without a prototype to |
| functions that expect a pointer to a function of a specific type |
| is diagnosed. Ditto for return statements. */ |
| |
| void take_memcpy (memcpy_t*); |
| void take_any (int, ...); |
| |
| memset_t* pass_args (int i) |
| { |
| take_memcpy (memcpy); |
| take_memcpy (memset); /* { dg-warning "\\\[-Wincompatible-pointer-types]" } */ |
| |
| take_any (0, i ? memcpy : memset); /* { dg-warning "\\\[-Wincompatible-pointer-types]" } */ |
| |
| return memcpy; /* { dg-warning "\\\[-Wincompatible-pointer-types]" } */ |
| } |