1// RUN: %clang_cc1 -fsyntax-only -verify -fblocks %s -Wno-error=non-pod-varargs
2
3// Check that the warning is still there under -fms-compatibility.
4// RUN: %clang_cc1 -fsyntax-only -verify -fblocks %s -Wno-error=non-pod-varargs -fms-compatibility
5
6extern char version[];
7
8class C {
9public:
10  C(int);
11  void g(int a, ...);
12  static void h(int a, ...);
13};
14
15void g(int a, ...);
16
17void t1()
18{
19  C c(10);
20
21  g(10, c); // expected-warning{{cannot pass object of non-POD type 'C' through variadic function; call will abort at runtime}}
22  g(10, version);
23
24  void (*ptr)(int, ...) = g;
25  ptr(10, c); // expected-warning{{cannot pass object of non-POD type 'C' through variadic function; call will abort at runtime}}
26  ptr(10, version);
27}
28
29void t2()
30{
31  C c(10);
32
33  c.g(10, c); // expected-warning{{cannot pass object of non-POD type 'C' through variadic method; call will abort at runtime}}
34  c.g(10, version);
35
36  void (C::*ptr)(int, ...) = &C::g;
37  (c.*ptr)(10, c); // expected-warning{{cannot pass object of non-POD type 'C' through variadic method; call will abort at runtime}}
38  (c.*ptr)(10, version);
39
40  C::h(10, c); // expected-warning{{cannot pass object of non-POD type 'C' through variadic function; call will abort at runtime}}
41  C::h(10, version);
42
43  void (*static_ptr)(int, ...) = &C::h;
44  static_ptr(10, c); // expected-warning{{cannot pass object of non-POD type 'C' through variadic function; call will abort at runtime}}
45  static_ptr(10, version);
46}
47
48int (^block)(int, ...);
49
50void t3()
51{
52  C c(10);
53
54  block(10, c); // expected-warning{{cannot pass object of non-POD type 'C' through variadic block; call will abort at runtime}}
55  block(10, version);
56}
57
58class D {
59public:
60  void operator() (int a, ...);
61};
62
63void t4()
64{
65  C c(10);
66
67  D d;
68
69  d(10, c); // expected-warning{{cannot pass object of non-POD type 'C' through variadic method; call will abort at runtime}}
70  d(10, version);
71}
72
73class E {
74  E(int, ...); // expected-note 2{{implicitly declared private here}}
75};
76
77void t5()
78{
79  C c(10);
80
81  E e(10, c); // expected-warning{{cannot pass object of non-POD type 'C' through variadic constructor; call will abort at runtime}} \
82    // expected-error{{calling a private constructor of class 'E'}}
83  (void)E(10, c); // expected-warning{{cannot pass object of non-POD type 'C' through variadic constructor; call will abort at runtime}} \
84    // expected-error{{calling a private constructor of class 'E'}}
85
86}
87
88// PR5761: unevaluated operands and the non-POD warning
89class Foo {
90 public:
91  Foo() {}
92};
93
94int Helper(...);
95const int size = sizeof(Helper(Foo()));
96
97namespace std {
98  class type_info { };
99}
100
101struct Base { virtual ~Base(); };
102Base &get_base(...);
103int eat_base(...);
104
105void test_typeid(Base &base) {
106  (void)typeid(get_base(base)); // expected-warning{{cannot pass object of non-POD type 'Base' through variadic function; call will abort at runtime}} expected-warning{{expression with side effects will be evaluated despite being used as an operand to 'typeid'}}
107  (void)typeid(eat_base(base)); // okay
108}
109
110
111// rdar://7985267 - Shouldn't warn, doesn't actually use __builtin_va_start is
112// magic.
113
114void t6(Foo somearg, ... ) {
115  __builtin_va_list list;
116  __builtin_va_start(list, somearg);
117}
118
119void t7(int n, ...) {
120  __builtin_va_list list;
121  __builtin_va_start(list, n);
122  (void)__builtin_va_arg(list, C); // expected-warning{{second argument to 'va_arg' is of non-POD type 'C'}}
123  __builtin_va_end(list);
124}
125
126struct Abstract {
127  virtual void doit() = 0; // expected-note{{unimplemented pure virtual method}}
128};
129
130void t8(int n, ...) {
131  __builtin_va_list list;
132  __builtin_va_start(list, n);
133  (void)__builtin_va_arg(list, Abstract); // expected-error{{second argument to 'va_arg' is of abstract type 'Abstract'}}
134  __builtin_va_end(list);
135}
136
137int t9(int n) {
138  // Make sure the error works in potentially-evaluated sizeof
139  return (int)sizeof(*(Helper(Foo()), (int (*)[n])0)); // expected-warning{{cannot pass object of non-POD type}}
140}
141
142// PR14057
143namespace t10 {
144  struct F {
145    F();
146  };
147
148  struct S {
149    void operator()(F, ...);
150  };
151
152  void foo() {
153    S s;
154    F f;
155    s.operator()(f);
156    s(f);
157  }
158}
159
160namespace t11 {
161  typedef void(*function_ptr)(int, ...);
162  typedef void(C::*member_ptr)(int, ...);
163  typedef void(^block_ptr)(int, ...);
164
165  function_ptr get_f_ptr();
166  member_ptr get_m_ptr();
167  block_ptr get_b_ptr();
168
169  function_ptr arr_f_ptr[5];
170  member_ptr arr_m_ptr[5];
171  block_ptr arr_b_ptr[5];
172
173  void test() {
174    C c(10);
175
176    (get_f_ptr())(10, c); // expected-warning{{cannot pass object of non-POD type 'C' through variadic function; call will abort at runtime}}
177    (get_f_ptr())(10, version);
178
179    (c.*get_m_ptr())(10, c); // expected-warning{{cannot pass object of non-POD type 'C' through variadic method; call will abort at runtime}}
180    (c.*get_m_ptr())(10, version);
181
182    (get_b_ptr())(10, c); // expected-warning{{cannot pass object of non-POD type 'C' through variadic block; call will abort at runtime}}
183    (get_b_ptr())(10, version);
184
185    (arr_f_ptr[3])(10, c); // expected-warning{{cannot pass object of non-POD type 'C' through variadic function; call will abort at runtime}}
186    (arr_f_ptr[3])(10, version);
187
188    (c.*arr_m_ptr[3])(10, c); // expected-warning{{cannot pass object of non-POD type 'C' through variadic method; call will abort at runtime}}
189    (c.*arr_m_ptr[3])(10, version);
190
191    (arr_b_ptr[3])(10, c); // expected-warning{{cannot pass object of non-POD type 'C' through variadic block; call will abort at runtime}}
192    (arr_b_ptr[3])(10, version);
193  }
194}
195