111
|
1 /* PR66516 - missing diagnostic on taking the address of a builtin function
|
|
2 { dg-do compile } */
|
|
3
|
|
4 typedef void (F)(void);
|
|
5 typedef __UINTPTR_TYPE__ uintptr_t;
|
|
6
|
|
7 /* Utility function to test passing built-in functions as an ordinary
|
|
8 argument and via the ellipsis. */
|
|
9 static void func_arg (F *p, ...) { (void)p; }
|
|
10
|
|
11 static F* test_taking_address_of_gcc_builtin (void)
|
|
12 {
|
|
13 F *p;
|
|
14 void *q;
|
|
15 uintptr_t a;
|
|
16
|
|
17 /* Call, cast to void, and id are allowed. */
|
|
18 __builtin_trap ();
|
|
19 (void)__builtin_trap;
|
|
20 __builtin_trap;
|
|
21
|
|
22 {
|
|
23 typedef __typeof__ (__builtin_trap) F; /* Okay. */
|
|
24 }
|
|
25
|
|
26 /* Address and indirection operators. */
|
|
27 p = &__builtin_trap; /* { dg-error "built-in function" } */
|
|
28 p = *__builtin_trap; /* { dg-error "built-in function" } */
|
|
29
|
|
30 /* Unary NOT. */
|
|
31 a = !__builtin_trap; /* { dg-error "built-in function" } */
|
|
32
|
|
33 /* Sizeof and _Alignof are disallowed by C but allowed by GCC
|
|
34 and there's no reason to reject built-ins as operands since
|
|
35 doing so doesn't yield their address. */
|
|
36 #pragma GCC diagnostic push
|
|
37 /* Disable: invalid application of 'sizeof' to a function type. */
|
|
38 #pragma GCC diagnostic ignored "-Wpointer-arith"
|
|
39 a = sizeof __builtin_trap;
|
|
40 #pragma GCC diagnostic pop
|
|
41
|
|
42 #ifndef __STDC_VERSION__
|
|
43 # pragma GCC diagnostic push
|
|
44 /* Disable: ISO C90 does not support '_Alignof'. */
|
|
45 # pragma GCC diagnostic ignored "-Wpedantic"
|
|
46 #endif
|
|
47
|
|
48 a = _Alignof __builtin_trap;
|
|
49
|
|
50 #ifndef __STDC_VERSION__
|
|
51 # pragma GCC diagnostic pop
|
|
52 #endif
|
|
53
|
|
54 /* Casts. */
|
|
55 p = (F*)__builtin_trap; /* { dg-error "built-in function" } */
|
|
56 a = (uintptr_t)__builtin_trap; /* { dg-error "built-in function" } */
|
|
57
|
|
58 /* Additive operator. */
|
|
59 p = __builtin_trap + 0; /* { dg-error "built-in function" } */
|
|
60 p = __builtin_trap - 0; /* { dg-error "built-in function" } */
|
|
61 a = __builtin_trap - p; /* { dg-error "built-in function" } */
|
|
62 a = p - __builtin_trap; /* { dg-error "built-in function" } */
|
|
63
|
|
64 /* Relational operators. */
|
|
65 a = __builtin_trap < p; /* { dg-error "built-in function" } */
|
|
66 a = p < __builtin_trap; /* { dg-error "built-in function" } */
|
|
67
|
|
68 a = __builtin_trap <= p; /* { dg-error "built-in function" } */
|
|
69 a = p <= __builtin_trap; /* { dg-error "built-in function" } */
|
|
70
|
|
71 a = __builtin_trap > p; /* { dg-error "built-in function" } */
|
|
72 a = p > __builtin_trap; /* { dg-error "built-in function" } */
|
|
73
|
|
74 a = __builtin_trap > p; /* { dg-error "built-in function" } */
|
|
75 a = p > __builtin_trap; /* { dg-error "built-in function" } */
|
|
76
|
|
77 a = __builtin_trap <= p; /* { dg-error "built-in function" } */
|
|
78 a = p <= __builtin_trap; /* { dg-error "built-in function" } */
|
|
79
|
|
80 a = __builtin_trap <= p; /* { dg-error "built-in function" } */
|
|
81 a = p <= __builtin_trap; /* { dg-error "built-in function" } */
|
|
82
|
|
83 /* Equality operators. */
|
|
84 a = __builtin_trap == p; /* { dg-error "built-in function" } */
|
|
85 a = p == __builtin_trap; /* { dg-error "built-in function" } */
|
|
86 a = __builtin_trap != p; /* { dg-error "built-in function" } */
|
|
87 a = p != __builtin_trap; /* { dg-error "built-in function" } */
|
|
88
|
|
89 /* Logical AND and OR. */
|
|
90 a = __builtin_trap && p; /* { dg-error "built-in function" } */
|
|
91 a = p && __builtin_trap; /* { dg-error "built-in function" } */
|
|
92
|
|
93 a = __builtin_trap || p; /* { dg-error "built-in function" } */
|
|
94 a = p || __builtin_trap; /* { dg-error "built-in function" } */
|
|
95
|
|
96 /* Conditional operator. */
|
|
97 a = __builtin_trap ? 1 : 0; /* { dg-error "built-in function" } */
|
|
98 p = a ? __builtin_trap : 0; /* { dg-error "built-in function" } */
|
|
99 p = a ? 0 : __builtin_trap; /* { dg-error "built-in function" } */
|
|
100
|
|
101 /* Assignment operator. */
|
|
102 p = __builtin_trap; /* { dg-error "built-in function" } */
|
|
103
|
|
104 q = __builtin_trap; /* { dg-error "built-in function" } */
|
|
105 a = __builtin_trap; /* { dg-error "built-in function" } */
|
|
106
|
|
107 /* Passing as an argument. */
|
|
108 func_arg (__builtin_trap); /* { dg-error "built-in function" } */
|
|
109
|
|
110 /* Passing through the ellipsis. */
|
|
111 func_arg (0, __builtin_trap); /* { dg-error "built-in function" } */
|
|
112
|
|
113 /* Return statement. */
|
|
114 return __builtin_trap; /* { dg-error "built-in function" } */
|
|
115
|
|
116 (void)a;
|
|
117 (void)p;
|
|
118 (void)q;
|
|
119 }
|
|
120
|
|
121 /* Helper declarations to verify that it's possible to take the address
|
|
122 of a user-declared function that's also a GCC built-in. */
|
|
123 extern int abs (int);
|
|
124
|
|
125 extern __SIZE_TYPE__ strlen (const char*);
|
|
126
|
|
127 /* Taking the address of a builtin with a library "fallback" must be
|
|
128 allowed, either using the __builtin_xxx form or the xxx form, when
|
|
129 the library fallback is declared either explicitly or implicitly
|
|
130 by virtue of first calling the function. */
|
|
131 void test_taking_address_of_library_builtin (int i)
|
|
132 {
|
|
133 {
|
|
134 typedef int F (int);
|
|
135
|
|
136 /* Compute the address of libc's abs using the implicitly declared
|
|
137 __builtin_abs form (all expressions are valid). */
|
|
138 F *p = __builtin_abs;
|
|
139 p = &__builtin_abs;
|
|
140 p = *__builtin_abs;
|
|
141
|
|
142 /* Compute the address of libc's abs declared above. */
|
|
143 p = abs;
|
|
144 p = &abs;
|
|
145 p = *abs;
|
|
146 (void)p;
|
|
147 }
|
|
148
|
|
149 {
|
|
150 typedef __SIZE_TYPE__ size_t;
|
|
151 typedef size_t F (const char*);
|
|
152
|
|
153 /* Compute the address of libc's strlen using the implicitly
|
|
154 declared __builtin_strlen form. */
|
|
155 F *p = __builtin_strlen;
|
|
156 p = &__builtin_strlen;
|
|
157 p = *__builtin_strlen;
|
|
158
|
|
159 /* Compute the address of libc's strlen declared above. */
|
|
160 p = strlen;
|
|
161 p = &strlen;
|
|
162 p = *strlen;
|
|
163 (void)p;
|
|
164 }
|
|
165
|
|
166 {
|
|
167 typedef int F (int);
|
|
168
|
|
169 /* Compute the address of libc's isxxx functions using the implicitly
|
|
170 declared __builtin_xxx form. */
|
|
171 F *p = __builtin_isalnum;
|
|
172 p = &__builtin_isalpha;
|
|
173 p = *__builtin_iscntrl;
|
|
174
|
|
175 /* According to C90 (see also the discussion in c/67386):
|
|
176 If the expression that precedes the parenthesized argument list
|
|
177 in a function call consists solely of an identifier, and if no
|
|
178 declaration is visible for this identifier, the identifier is
|
|
179 implicitly declared exactly as if, in the innermost block
|
|
180 containing the function call, the declaration
|
|
181 extern int identifier();
|
|
182 appeared. */
|
|
183
|
|
184 /* Call the functions first to have their declarations "injected"
|
|
185 into the enclosing block. Suppress warnings. */
|
|
186 #pragma GCC diagnostic push
|
|
187 #pragma GCC diagnostic ignored "-Wimplicit-function-declaration"
|
|
188 i = isalnum (i) || isalpha (i) || iscntrl (i);
|
|
189 #pragma GCC diagnostic pop
|
|
190
|
|
191 /* Take the address of the functions relying on their declarations
|
|
192 having been implicitly provided by the calls above. */
|
|
193 p = isalnum;
|
|
194 p = &isalpha;
|
|
195 p = *iscntrl;
|
|
196 (void)p;
|
|
197 }
|
|
198 }
|