1 /* PR c/83656 - missing -Wbuiltin-declaration-mismatch on declaration
2    without prototype
3    { dg-do compile }
4    { dg-options "-Wbuiltin-declaration-mismatch" } */
5 
6 typedef __SIZE_TYPE__ size_t;
7 
8 /* Built-ins declared without a prototype are not diagnosed by default
9    (without -Wextra) except when their return type doesn't match.  */
10 int abort ();       /* { dg-warning "\\\[-Wbuiltin-declaration-mismatch]" } */
11 
12 /* Built-ins declared without a prototype are not diagnosed without -Wextra.  */
13 void exit ();
14 void* memcpy ();
15 void* memset ();
16 
17 
test_call_abort(void)18 void test_call_abort (void)
19 {
20   /* Verify that a valid call to abort() is not diagnosed.  */
21   abort ();
22 
23   /* Unfortunately, the incompatible declaration above makes GCC "forget"
24      that abort() is a built-in and so the invalid calls below aren't
25      diagnosed.  The only saving grace is that the invalid declaration
26      that differs in the return type is diagnosed by default. */
27   abort (1);        /* { dg-warning "too many arguments to built-in function .abort. expecting 0" "pr?????" { xfail *-*-* } } */
28 
29   abort (1, 2);     /* { dg-warning "too many arguments" "pr?????" { xfail *-*-* } } */
30 }
31 
32 
test_call_exit(void)33 void test_call_exit (void)
34 {
35   /* Verify that valid calls to exit are not diagnosed.  */
36   exit ('\0');
37   exit (0);
38 
39   /* Also verify calls to the built-in.  */
40   __builtin_exit ('\0');
41   __builtin_exit (0);
42   __builtin_exit (0.0);
43 
44   exit ();          /* { dg-warning "too few arguments to built-in function 'exit' expecting 1" } */
45 
46   exit (1, 2);      /* { dg-warning "too many arguments" } */
47 
48   /* Verify that passing incompatible arguments triggers a warning.  */
49   exit ("");        /* { dg-warning "\\\[-Wint-conversion]" } */
50 
51   struct S { int i; } s = { 0 };
52   exit (s);         /* { dg-warning "incompatible type for argument 1" } */
53 }
54 
55 
test_call_memcpy(void * p,const void * q,size_t n)56 void test_call_memcpy (void *p, const void *q, size_t n)
57 {
58   memcpy (p, q, n);
59 
60   memcpy ();        /* { dg-warning "too few arguments to built-in function 'memcpy' expecting 3" } */
61 
62   memcpy (p);       /* { dg-warning "too few arguments to built-in function 'memcpy' expecting 3" } */
63 
64   memcpy (p, q);     /* { dg-warning "too few arguments to built-in function 'memcpy' expecting 3" } */
65 
66   memcpy (q, p, n); /* { dg-warning "\\\[-Wdiscarded-qualifiers]" } */
67 
68   memcpy (p, n, q); /* { dg-warning "\\\[-Wint-conversion]" } */
69 
70   memcpy (p, q, n, 0); /* { dg-warning "too many arguments to built-in function 'memcpy' expecting 3" } */
71 }
72 
73 
74 typedef void* (memcpy_t)(void*, const void*, size_t);
75 typedef void* (memset_t)(void*, int, size_t);
76 
test_init(void)77 void test_init (void)
78 {
79   /* Verify that initialization of a pointer by the address of a built-in
80      function of a matching type declared without a prototype doesn't
81      trigger a warning...  */
82   memset_t *pmemset = memset;
83 
84   /* ...but initialization by the address of an incompatible built-in
85      does even without -Wextra.  */
86   memcpy_t *pmemcpy = memset;           /* { dg-warning "\\\[-Wincompatible-pointer-types]" } */
87 }
88 
89 
test_assign(void)90 void test_assign (void)
91 {
92   /* Same as above but for assignment.  */
93   memset_t *pmemset;
94   pmemset = memset;
95 
96   memcpy_t *pmemcpy;
97   pmemcpy = memset;                     /* { dg-warning "\\\[-Wincompatible-pointer-types]" } */
98 }
99 
100 
101 /* Verify that passing built-ins declared without a prototype to
102    functions that expect a pointer to a function of a specific type
103    is diagnosed.  Ditto for return statements.  */
104 
105 void take_memcpy (memcpy_t*);
106 void take_any (int, ...);
107 
pass_args(int i)108 memset_t* pass_args (int i)
109 {
110   take_memcpy (memcpy);
111   take_memcpy (memset);                 /* { dg-warning "\\\[-Wincompatible-pointer-types]" } */
112 
113   take_any (0, i ? memcpy : memset);    /* { dg-warning "\\\[-Wincompatible-pointer-types]" } */
114 
115   return memcpy;                        /* { dg-warning "\\\[-Wincompatible-pointer-types]" } */
116 }
117