xref: /llvm-project/clang/test/SemaCXX/vararg-non-pod.cpp (revision 84a3aadf0f2483dde0acfc4e79f2a075a5f35bd1)
1 // RUN: %clang_cc1 -fsyntax-only -verify -fblocks %s -Wno-error=non-pod-varargs
2 // RUN: %clang_cc1 -fsyntax-only -verify -fblocks -std=gnu++98 %s -Wno-error=non-pod-varargs
3 // RUN: %clang_cc1 -fsyntax-only -verify -fblocks -std=gnu++11 %s -Wno-error=non-pod-varargs
4 
5 // Check that the warning is still there under -fms-compatibility.
6 // RUN: %clang_cc1 -fsyntax-only -verify -fblocks %s -Wno-error=non-pod-varargs -fms-compatibility
7 // RUN: %clang_cc1 -fsyntax-only -verify -fblocks -std=gnu++98 %s -Wno-error=non-pod-varargs -fms-compatibility
8 // RUN: %clang_cc1 -fsyntax-only -verify -fblocks -std=gnu++11 %s -Wno-error=non-pod-varargs -fms-compatibility
9 
10 extern char version[];
11 
12 class C {
13 public:
14   C(int);
15   void g(int a, ...);
16   static void h(int a, ...);
17 };
18 
19 void g(int a, ...);
20 
t1()21 void t1()
22 {
23   C c(10);
24 
25   g(10, c);
26 #if __cplusplus <= 199711L
27   // expected-warning@-2 {{cannot pass object of non-POD type 'C' through variadic function; call will abort at runtime}}
28 #endif
29 
30   g(10, version);
31 
32   void (*ptr)(int, ...) = g;
33   ptr(10, c);
34 #if __cplusplus <= 199711L
35   // expected-warning@-2 {{cannot pass object of non-POD type 'C' through variadic function; call will abort at runtime}}
36 #endif
37 
38   ptr(10, version);
39 }
40 
t2()41 void t2()
42 {
43   C c(10);
44 
45   c.g(10, c);
46 #if __cplusplus <= 199711L
47   // expected-warning@-2 {{cannot pass object of non-POD type 'C' through variadic method; call will abort at runtime}}
48 #endif
49 
50   c.g(10, version);
51 
52   void (C::*ptr)(int, ...) = &C::g;
53   (c.*ptr)(10, c);
54 #if __cplusplus <= 199711L
55   // expected-warning@-2 {{cannot pass object of non-POD type 'C' through variadic method; call will abort at runtime}}
56 #endif
57 
58   (c.*ptr)(10, version);
59 
60   C::h(10, c);
61 #if __cplusplus <= 199711L
62   // expected-warning@-2 {{cannot pass object of non-POD type 'C' through variadic function; call will abort at runtime}}
63 #endif
64 
65   C::h(10, version);
66 
67   void (*static_ptr)(int, ...) = &C::h;
68   static_ptr(10, c);
69 #if __cplusplus <= 199711L
70   // expected-warning@-2 {{cannot pass object of non-POD type 'C' through variadic function; call will abort at runtime}}
71 #endif
72 
73   static_ptr(10, version);
74 }
75 
76 int (^block)(int, ...);
77 
t3()78 void t3()
79 {
80   C c(10);
81 
82   block(10, c);
83 #if __cplusplus <= 199711L
84   // expected-warning@-2 {{cannot pass object of non-POD type 'C' through variadic block; call will abort at runtime}}
85 #endif
86 
87   block(10, version);
88 }
89 
90 class D {
91 public:
92   void operator() (int a, ...);
93 };
94 
t4()95 void t4()
96 {
97   C c(10);
98 
99   D d;
100 
101   d(10, c);
102 #if __cplusplus <= 199711L
103   // expected-warning@-2 {{cannot pass object of non-POD type 'C' through variadic method; call will abort at runtime}}
104 #endif
105 
106   d(10, version);
107 }
108 
109 class E {
110   E(int, ...); // expected-note 2{{implicitly declared private here}}
111 };
112 
t5()113 void t5()
114 {
115   C c(10);
116 
117   E e(10, c);
118 #if __cplusplus <= 199711L
119   // expected-warning@-2 {{cannot pass object of non-POD type 'C' through variadic constructor; call will abort at runtime}}
120 #endif
121   // expected-error@-4 {{calling a private constructor of class 'E'}}
122   (void)E(10, c);
123 #if __cplusplus <= 199711L
124   // expected-warning@-2 {{cannot pass object of non-POD type 'C' through variadic constructor; call will abort at runtime}}
125 #endif
126   // expected-error@-4 {{calling a private constructor of class 'E'}}
127 
128 }
129 
130 // PR5761: unevaluated operands and the non-POD warning
131 class Foo {
132  public:
Foo()133   Foo() {}
134 };
135 
136 int Helper(...);
137 const int size = sizeof(Helper(Foo()));
138 
139 namespace std {
140   class type_info { };
141 }
142 
143 struct Base { virtual ~Base(); };
144 Base &get_base(...);
145 int eat_base(...);
146 
test_typeid(Base & base)147 void test_typeid(Base &base) {
148   (void)typeid(get_base(base));
149 #if __cplusplus <= 199711L
150   // expected-warning@-2 {{cannot pass object of non-POD type 'Base' through variadic function; call will abort at runtime}}
151 #else
152   // expected-warning@-4 {{cannot pass object of non-trivial type 'Base' through variadic function; call will abort at runtime}}
153 #endif
154   // expected-warning@-6 {{expression with side effects will be evaluated despite being used as an operand to 'typeid'}}
155   (void)typeid(eat_base(base)); // okay
156 }
157 
158 
159 // Shouldn't warn, doesn't actually use __builtin_va_start is magic.
160 
t6(Foo somearg,...)161 void t6(Foo somearg, ... ) {
162   __builtin_va_list list;
163   __builtin_va_start(list, somearg);
164 }
165 
166 // __builtin_stdarg_start is a compatibility alias for __builtin_va_start,
167 // it should behave the same
t6b(Foo somearg,...)168 void t6b(Foo somearg, ... ) {
169   __builtin_va_list list;
170   __builtin_stdarg_start(list, somearg); // second argument to 'va_start' is not the last named parameter [-Wvarargs]
171 }
172 
t7(int n,...)173 void t7(int n, ...) {
174   __builtin_va_list list;
175   __builtin_va_start(list, n);
176   (void)__builtin_va_arg(list, C); // expected-warning{{second argument to 'va_arg' is of non-POD type 'C'}}
177   __builtin_va_end(list);
178 }
179 
180 struct Abstract {
181   virtual void doit() = 0; // expected-note{{unimplemented pure virtual method}}
182 };
183 
t8(int n,...)184 void t8(int n, ...) {
185   __builtin_va_list list;
186   __builtin_va_start(list, n);
187   (void)__builtin_va_arg(list, Abstract); // expected-error{{second argument to 'va_arg' is of abstract type 'Abstract'}}
188   __builtin_va_end(list);
189 }
190 
t9(int n)191 int t9(int n) {
192   // Make sure the error works in potentially-evaluated sizeof
193   return (int)sizeof(*(Helper(Foo()), (int (*)[n])0));
194 #if __cplusplus <= 199711L
195   // expected-warning@-2 {{cannot pass object of non-POD type 'Foo' through variadic function; call will abort at runtime}}
196 #endif
197 }
198 
199 // PR14057
200 namespace t10 {
201   struct F {
202     F();
203   };
204 
205   struct S {
206     void operator()(F, ...);
207   };
208 
foo()209   void foo() {
210     S s;
211     F f;
212     s.operator()(f);
213     s(f);
214   }
215 }
216 
217 namespace t11 {
218   typedef void(*function_ptr)(int, ...);
219   typedef void(C::*member_ptr)(int, ...);
220   typedef void(^block_ptr)(int, ...);
221 
222   function_ptr get_f_ptr();
223   member_ptr get_m_ptr();
224   block_ptr get_b_ptr();
225 
226   function_ptr arr_f_ptr[5];
227   member_ptr arr_m_ptr[5];
228   block_ptr arr_b_ptr[5];
229 
test()230   void test() {
231     C c(10);
232 
233     (get_f_ptr())(10, c);
234 #if __cplusplus <= 199711L
235     // expected-warning@-2 {{cannot pass object of non-POD type 'C' through variadic function; call will abort at runtime}}
236 #endif
237     (get_f_ptr())(10, version);
238 
239     (c.*get_m_ptr())(10, c);
240 #if __cplusplus <= 199711L
241     // expected-warning@-2 {{cannot pass object of non-POD type 'C' through variadic method; call will abort at runtime}}
242 #endif
243     (c.*get_m_ptr())(10, version);
244 
245     (get_b_ptr())(10, c);
246 #if __cplusplus <= 199711L
247     // expected-warning@-2 {{cannot pass object of non-POD type 'C' through variadic block; call will abort at runtime}}
248 #endif
249 
250     (get_b_ptr())(10, version);
251 
252     (arr_f_ptr[3])(10, c);
253 #if __cplusplus <= 199711L
254     // expected-warning@-2 {{cannot pass object of non-POD type 'C' through variadic function; call will abort at runtime}}
255 #endif
256 
257     (arr_f_ptr[3])(10, version);
258 
259     (c.*arr_m_ptr[3])(10, c);
260 #if __cplusplus <= 199711L
261     // expected-warning@-2 {{cannot pass object of non-POD type 'C' through variadic method; call will abort at runtime}}
262 #endif
263 
264     (c.*arr_m_ptr[3])(10, version);
265 
266     (arr_b_ptr[3])(10, c);
267 #if __cplusplus <= 199711L
268     // expected-warning@-2 {{cannot pass object of non-POD type 'C' through variadic block; call will abort at runtime}}
269 #endif
270     (arr_b_ptr[3])(10, version);
271   }
272 }
273