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