PR c++/85462
[official-gcc.git] / gcc / testsuite / g++.dg / addr_builtin-1.C
blobe8ba31f994c3f5bc378f04a7b6e5ff3ef8c47a3b
1 // PR66516 - missing diagnostic on taking the address of a builtin function
2 // { dg-do compile }
4 namespace std {
5   // Define type_info type to be able to use typeid in tests without
6   // having to include <typeinfo>.
7   struct type_info {
8     const char *name_;
10     explicit type_info (const char *s): name_ (s) { }
11     const char* name() const { return name_; }
12   };
15 // Extern "C" since builtin functions used in tests have C linkage.
16 extern "C" {
18 typedef void (F)();
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
27 // below.
28 void f () { }
30 }   // extern "C"
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 { };
43 #else
45 template <F* = &f, F* = &f> struct TestPointers { };
46 template <F& = f, F& = f> struct TestReferences { };
48 #endif
50 static F* test_taking_address_of_gcc_builtin ()
52   enum UINTPTR_E { e = ~(uintptr_t)0 };
54   F *p;
55   void *q;
56   uintptr_t a;
58   __builtin_trap ();                           // okay
59   (void)__builtin_trap;                        // okay
60   __builtin_trap;                              // okay (if pointless)
62   {
63     typedef __typeof__ (__builtin_trap) F;     // okay
64   }
66 #if 201103 <= __cplusplus
67   {
68     typedef decltype (__builtin_trap) F;       // okay
70     a = noexcept (&__builtin_trap);
71   }
72 #endif
74   // Address and indirection operators.
75   p = &__builtin_trap;                       // { dg-error "built-in" }
76   p = *__builtin_trap;                       // { dg-error "built-in" }
78   // Unary NOT.
79   // GCC issues two diagnostics here for some reason, so account for both.
80   a = !__builtin_trap;                   // { dg-error "built-in|unary" }
82   // Casts.
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" }
160   {
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" }
174   }
176   try {
177     throw __builtin_trap;                 // { dg-error "built-in" }
178   }
179   catch (F) { }
181   return __builtin_trap;                    // { dg-error "built-in" }
183   (void)a;
184   (void)p;
185   (void)q;
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[];
207   (void)newr;
208   (void)newra;
209   (void)newp;
210   (void)delr;
211   (void)delra;
212   (void)delp;
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 ()
226   {
227     typedef int F (int);
229     F &r1 = __builtin_abs;
230     F &r2 = *__builtin_abs;
231     F *p = __builtin_abs;
232     p = &__builtin_abs;
233     p = *__builtin_abs;
234     (void)p;
235     (void)r1;
236     (void)r2;
237   }
239   {
240     typedef int F (int);
242     F &r1 = abs;
243     F &r2 = *abs;
244     F *p = abs;
245     p = &abs;
246     p = *abs;
247     (void)p;
248     (void)r1;
249     (void)r2;
250   }
252   {
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;
260     (void)p;
261     (void)r1;
262     (void)r2;
263   }
265   {
266     typedef size_t F (const char*);
267     F &r1 = strlen;
268     F &r2 = *strlen;
269     F *p = strlen;
270     p = &strlen;
271     p = *strlen;
272     (void)p;
273     (void)r1;
274     (void)r2;
275   }