1 // PR66516 - missing diagnostic on taking the address of a builtin function
5 // Define type_info type to be able to use typeid in tests without
6 // having to include <typeinfo>.
10 explicit type_info (const char *s): name_ (s) { }
11 const char* name() const { return name_; }
15 // Extern "C" since builtin functions used in tests have C linkage.
19 typedef __UINTPTR_TYPE__ uintptr_t;
21 // Utility function to test passing built-in functions as an ordinary
22 // argument and via the ellipsis.
23 static void func_arg (F*, ...);
25 // Utility function with which, along with the built-in function,
26 // to instantiate the C98 multi-parameter or C11 variadic tempates
33 // Utility templates to test specializing templates on pointers and
34 // references to built-in functions.
35 template <F*> struct TestPointer { };
36 template <F&> struct TestReference { };
38 #if 201103 <= __cplusplus
40 template <F*...> struct TestPointers { };
41 template <F&...> struct TestReferences { };
45 template <F* = &f, F* = &f> struct TestPointers { };
46 template <F& = f, F& = f> struct TestReferences { };
50 static F* test_taking_address_of_gcc_builtin ()
52 enum UINTPTR_E { e = ~(uintptr_t)0 };
58 __builtin_trap (); // okay
59 (void)__builtin_trap; // okay
60 __builtin_trap; // okay (if pointless)
63 typedef __typeof__ (__builtin_trap) F; // okay
66 #if 201103 <= __cplusplus
68 typedef decltype (__builtin_trap) F; // okay
70 a = noexcept (&__builtin_trap);
74 // Address and indirection operators.
75 p = &__builtin_trap; // { dg-error "built-in" }
76 p = *__builtin_trap; // { dg-error "built-in" }
79 // GCC issues two diagnostics here for some reason, so account for both.
80 a = !__builtin_trap; // { dg-error "built-in|unary" }
83 p = (F*)__builtin_trap; // { dg-error "built-in" }
85 p = &(F&)__builtin_trap; // { dg-error "built-in" }
87 p = &reinterpret_cast<F&>(__builtin_trap); // { dg-error "built-in" }
88 p = &static_cast<F&>(__builtin_trap); // { dg-error "built-in" }
90 p = reinterpret_cast<F*>(__builtin_trap); // { dg-error "built-in" }
91 p = static_cast<F*>(__builtin_trap); // { dg-error "built-in" }
93 // Expect a diagnostic for an invalid static_cast of a function to
94 // either uintptr_t or enum, rather than one for the argument being
95 // a built-in function, since the former is more relevant than the latter.
96 a = static_cast<uintptr_t>(__builtin_trap); // { dg-error "invalid" }
97 a = static_cast<UINTPTR_E>(__builtin_trap); // { dg-error "invalid" }
99 // Reinterpret cast can cast a function to uintptr_t or enum,
100 // so verify that a diagnostic is issued for the use of a builtin.
101 a = reinterpret_cast<uintptr_t>(__builtin_trap); // { dg-error "built-in" }
102 a = reinterpret_cast<UINTPTR_E>(__builtin_trap); // { dg-error "built-in" }
104 // Additive operator. Ill-formed but allowed with -fpermissive.
105 p = __builtin_trap + 0; // { dg-error "built-in" }
106 p = __builtin_trap - 0; // { dg-error "built-in" }
107 a = __builtin_trap - p; // { dg-error "built-in" }
108 a = p - __builtin_trap; // { dg-error "built-in" }
110 // Relational operators. Ill-formed but allowed with -fpermissive.
111 a = __builtin_trap < p; // { dg-error "built-in" }
112 a = p < __builtin_trap; // { dg-error "built-in" }
114 a = __builtin_trap <= p; // { dg-error "built-in" }
115 a = p <= __builtin_trap; // { dg-error "built-in" }
117 a = __builtin_trap > p; // { dg-error "built-in" }
118 a = p > __builtin_trap; // { dg-error "built-in" }
120 a = __builtin_trap > p; // { dg-error "built-in" }
121 a = p > __builtin_trap; // { dg-error "built-in" }
123 a = __builtin_trap <= p; // { dg-error "built-in" }
124 a = p <= __builtin_trap; // { dg-error "built-in" }
126 a = __builtin_trap <= p; // { dg-error "built-in" }
127 a = p <= __builtin_trap; // { dg-error "built-in" }
129 // Equality operators.
130 a = __builtin_trap == p; // { dg-error "built-in" }
131 a = p == __builtin_trap; // { dg-error "built-in" }
132 a = __builtin_trap != p; // { dg-error "built-in" }
133 a = p != __builtin_trap; // { dg-error "built-in" }
135 // Logical AND and OR.
136 a = __builtin_trap && p; // { dg-error "built-in" }
137 a = p && __builtin_trap; // { dg-error "built-in" }
139 a = __builtin_trap || p; // { dg-error "built-in" }
140 a = p || __builtin_trap; // { dg-error "built-in" }
142 // Conditional operator.
143 a = __builtin_trap ? 1 : 0; // { dg-error "built-in" }
144 p = a ? __builtin_trap : 0; // { dg-error "built-in" }
145 p = a ? 0 : __builtin_trap; // { dg-error "built-in" }
147 // Assignment operator.
148 p = __builtin_trap; // { dg-error "built-in" }
150 // Passing as an argument.
151 func_arg (__builtin_trap); // { dg-error "built-in" }
152 func_arg (&__builtin_trap); // { dg-error "built-in" }
153 func_arg (*__builtin_trap); // { dg-error "built-in" }
155 // Passing through ellipsis.
156 func_arg (0, __builtin_trap); // { dg-error "built-in" }
157 func_arg (0, &__builtin_trap); // { dg-error "built-in" }
158 func_arg (0, *__builtin_trap); // { dg-error "built-in" }
161 // Template specialization.
162 // GCC issues two diagnostics and we must account for both.
163 TestPointer<__builtin_trap> tp; // { dg-error "built-in|could not convert" }
164 TestReference<__builtin_trap> tr; // { dg-error "built-in|could not convert" }
166 TestPointers<__builtin_trap> tp1; // { dg-error "built-in|could not convert" }
167 TestReferences<__builtin_trap> tr1; // { dg-error "built-in|could not convert" }
169 TestPointers<f, __builtin_trap> tp2; // { dg-error "built-in|could not convert" }
170 TestReferences<f, __builtin_trap> tr2; // { dg-error "built-in|could not convert" }
172 TestPointers<__builtin_trap, f> tp3; // { dg-error "built-in|could not convert" }
173 TestReferences<__builtin_trap, f> tr3; // { dg-error "built-in|could not convert" }
177 throw __builtin_trap; // { dg-error "built-in" }
181 return __builtin_trap; // { dg-error "built-in" }
188 // Make sure operators new and delete don't trigger false positives
189 // (they return true from DECL_IS_BUILTIN(DECL) -- see tree.h).
190 void test_taking_address_of_op_new_and_delete ()
192 typedef __SIZE_TYPE__ size_t;
194 typedef void* (OpNew) (size_t);
195 typedef void (OpDelete) (void*);
197 OpNew &newr = operator new;
198 OpNew &newra = operator new[];
199 OpNew *newp = &operator new;
200 newp = &operator new[];
202 OpDelete &delr = operator delete;
203 OpDelete &delra = operator delete[];
204 OpDelete *delp = &operator delete;
205 delp = &operator delete[];
215 // Helper declaration to verify that it's possible to take the address
216 // of a user-declared function that's also a GCC built-in.
217 extern int abs (int);
219 typedef __SIZE_TYPE__ size_t;
220 extern size_t strlen (const char*);
222 // Creating a reference to or taking the address of a built-in with
223 // a library "fallback" must be allowed.
224 void test_taking_address_of_library_builtin ()
229 F &r1 = __builtin_abs;
230 F &r2 = *__builtin_abs;
231 F *p = __builtin_abs;
253 typedef __SIZE_TYPE__ size_t;
254 typedef size_t F (const char*);
255 F &r1 = __builtin_strlen;
256 F &r2 = *__builtin_strlen;
257 F *p = __builtin_strlen;
258 p = &__builtin_strlen;
259 p = *__builtin_strlen;
266 typedef size_t F (const char*);