117 lines
3.7 KiB
C
117 lines
3.7 KiB
C
/* 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]" } */
|
|
}
|