1// RUN: %clang_cc1 -fsyntax-only -verify -fblocks %s -Wno-error=non-pod-varargs
2// RUN: %clang_cc1 -fsyntax-only -verify -fblocks -std=c++98 %s -Wno-error=non-pod-varargs
3// RUN: %clang_cc1 -fsyntax-only -verify -fblocks -std=c++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=c++98 %s -Wno-error=non-pod-varargs -fms-compatibility
8// RUN: %clang_cc1 -fsyntax-only -verify -fblocks -std=c++11 %s -Wno-error=non-pod-varargs -fms-compatibility
9
10extern char version[];
11
12class C {
13public:
14  C(int);
15  void g(int a, ...);
16  static void h(int a, ...);
17};
18
19void g(int a, ...);
20
21void 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
41void 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
76int (^block)(int, ...);
77
78void 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
90class D {
91public:
92  void operator() (int a, ...);
93};
94
95void 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
109class E {
110  E(int, ...); // expected-note 2{{implicitly declared private here}}
111};
112
113void 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
131class Foo {
132 public:
133  Foo() {}
134};
135
136int Helper(...);
137const int size = sizeof(Helper(Foo()));
138
139namespace std {
140  class type_info { };
141}
142
143struct Base { virtual ~Base(); };
144Base &get_base(...);
145int eat_base(...);
146
147void 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// rdar://7985267 - Shouldn't warn, doesn't actually use __builtin_va_start is
160// magic.
161
162void t6(Foo somearg, ... ) {
163  __builtin_va_list list;
164  __builtin_va_start(list, somearg);
165}
166
167void t7(int n, ...) {
168  __builtin_va_list list;
169  __builtin_va_start(list, n);
170  (void)__builtin_va_arg(list, C); // expected-warning{{second argument to 'va_arg' is of non-POD type 'C'}}
171  __builtin_va_end(list);
172}
173
174struct Abstract {
175  virtual void doit() = 0; // expected-note{{unimplemented pure virtual method}}
176};
177
178void t8(int n, ...) {
179  __builtin_va_list list;
180  __builtin_va_start(list, n);
181  (void)__builtin_va_arg(list, Abstract); // expected-error{{second argument to 'va_arg' is of abstract type 'Abstract'}}
182  __builtin_va_end(list);
183}
184
185int t9(int n) {
186  // Make sure the error works in potentially-evaluated sizeof
187  return (int)sizeof(*(Helper(Foo()), (int (*)[n])0));
188#if __cplusplus <= 199711L
189  // expected-warning@-2 {{cannot pass object of non-POD type 'Foo' through variadic function; call will abort at runtime}}
190#endif
191}
192
193// PR14057
194namespace t10 {
195  struct F {
196    F();
197  };
198
199  struct S {
200    void operator()(F, ...);
201  };
202
203  void foo() {
204    S s;
205    F f;
206    s.operator()(f);
207    s(f);
208  }
209}
210
211namespace t11 {
212  typedef void(*function_ptr)(int, ...);
213  typedef void(C::*member_ptr)(int, ...);
214  typedef void(^block_ptr)(int, ...);
215
216  function_ptr get_f_ptr();
217  member_ptr get_m_ptr();
218  block_ptr get_b_ptr();
219
220  function_ptr arr_f_ptr[5];
221  member_ptr arr_m_ptr[5];
222  block_ptr arr_b_ptr[5];
223
224  void test() {
225    C c(10);
226
227    (get_f_ptr())(10, c);
228#if __cplusplus <= 199711L
229    // expected-warning@-2 {{cannot pass object of non-POD type 'C' through variadic function; call will abort at runtime}}
230#endif
231    (get_f_ptr())(10, version);
232
233    (c.*get_m_ptr())(10, c);
234#if __cplusplus <= 199711L
235    // expected-warning@-2 {{cannot pass object of non-POD type 'C' through variadic method; call will abort at runtime}}
236#endif
237    (c.*get_m_ptr())(10, version);
238
239    (get_b_ptr())(10, c);
240#if __cplusplus <= 199711L
241    // expected-warning@-2 {{cannot pass object of non-POD type 'C' through variadic block; call will abort at runtime}}
242#endif
243
244    (get_b_ptr())(10, version);
245
246    (arr_f_ptr[3])(10, c);
247#if __cplusplus <= 199711L
248    // expected-warning@-2 {{cannot pass object of non-POD type 'C' through variadic function; call will abort at runtime}}
249#endif
250
251    (arr_f_ptr[3])(10, version);
252
253    (c.*arr_m_ptr[3])(10, c);
254#if __cplusplus <= 199711L
255    // expected-warning@-2 {{cannot pass object of non-POD type 'C' through variadic method; call will abort at runtime}}
256#endif
257
258    (c.*arr_m_ptr[3])(10, version);
259
260    (arr_b_ptr[3])(10, c);
261#if __cplusplus <= 199711L
262    // expected-warning@-2 {{cannot pass object of non-POD type 'C' through variadic block; call will abort at runtime}}
263#endif
264    (arr_b_ptr[3])(10, version);
265  }
266}
267