blob: f2ec32595461e5fb9266693e8dbe50574d766e3a [file] [log] [blame]
/* 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]" } */
}