1 /* PR66516 - missing diagnostic on taking the address of a builtin function
4 typedef void (F
)(void);
5 typedef __UINTPTR_TYPE__
uintptr_t;
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
; }
11 static F
* test_taking_address_of_gcc_builtin (void)
17 /* Call, cast to void, and id are allowed. */
23 typedef __typeof__ (__builtin_trap
) F
; /* Okay. */
26 /* Address and indirection operators. */
27 p
= &__builtin_trap
; /* { dg-error "built-in function" } */
28 p
= *__builtin_trap
; /* { dg-error "built-in function" } */
31 a
= !__builtin_trap
; /* { dg-error "built-in function" } */
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
42 #ifndef __STDC_VERSION__
43 # pragma GCC diagnostic push
44 /* Disable: ISO C90 does not support '_Alignof'. */
45 # pragma GCC diagnostic ignored "-Wpedantic"
48 a
= _Alignof __builtin_trap
;
50 #ifndef __STDC_VERSION__
51 # pragma GCC diagnostic pop
55 p
= (F
*)__builtin_trap
; /* { dg-error "built-in function" } */
56 a
= (uintptr_t)__builtin_trap
; /* { dg-error "built-in function" } */
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" } */
64 /* Relational operators. */
65 a
= __builtin_trap
< p
; /* { dg-error "built-in function" } */
66 a
= p
< __builtin_trap
; /* { dg-error "built-in function" } */
68 a
= __builtin_trap
<= p
; /* { dg-error "built-in function" } */
69 a
= p
<= __builtin_trap
; /* { dg-error "built-in function" } */
71 a
= __builtin_trap
> p
; /* { dg-error "built-in function" } */
72 a
= p
> __builtin_trap
; /* { dg-error "built-in function" } */
74 a
= __builtin_trap
> p
; /* { dg-error "built-in function" } */
75 a
= p
> __builtin_trap
; /* { dg-error "built-in function" } */
77 a
= __builtin_trap
<= p
; /* { dg-error "built-in function" } */
78 a
= p
<= __builtin_trap
; /* { dg-error "built-in function" } */
80 a
= __builtin_trap
<= p
; /* { dg-error "built-in function" } */
81 a
= p
<= __builtin_trap
; /* { dg-error "built-in function" } */
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" } */
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" } */
93 a
= __builtin_trap
|| p
; /* { dg-error "built-in function" } */
94 a
= p
|| __builtin_trap
; /* { dg-error "built-in function" } */
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" } */
101 /* Assignment operator. */
102 p
= __builtin_trap
; /* { dg-error "built-in function" } */
104 q
= __builtin_trap
; /* { dg-error "built-in function" } */
105 a
= __builtin_trap
; /* { dg-error "built-in function" } */
107 /* Passing as an argument. */
108 func_arg (__builtin_trap
); /* { dg-error "built-in function" } */
110 /* Passing through the ellipsis. */
111 func_arg (0, __builtin_trap
); /* { dg-error "built-in function" } */
113 /* Return statement. */
114 return __builtin_trap
; /* { dg-error "built-in function" } */
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);
125 extern __SIZE_TYPE__
strlen (const char*);
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
)
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
;
142 /* Compute the address of libc's abs declared above. */
150 typedef __SIZE_TYPE__
size_t;
151 typedef size_t F (const char*);
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
;
159 /* Compute the address of libc's strlen declared above. */
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
;
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();
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
191 /* Take the address of the functions relying on their declarations
192 having been implicitly provided by the calls above. */