1 | // RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -fsyntax-only -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -fcxx-exceptions -verify %s |
2 | // RUN: %clang_cc1 -std=c++11 -triple %ms_abi_triple -DMSABI -fsyntax-only -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -verify %s |
3 | |
4 | #if defined(BE_THE_HEADER) |
5 | |
6 | // Wdelete-non-virtual-dtor should warn about the delete from smart pointer |
7 | // classes in system headers (std::unique_ptr...) too. |
8 | |
9 | #pragma clang system_header |
10 | namespace dnvd { |
11 | |
12 | struct SystemB { |
13 | virtual void foo(); |
14 | }; |
15 | |
16 | template <typename T> |
17 | class simple_ptr { |
18 | public: |
19 | simple_ptr(T* t): _ptr(t) {} |
20 | ~simple_ptr() { delete _ptr; } // \ |
21 | // expected-warning {{delete called on non-final 'dnvd::B' that has virtual functions but non-virtual destructor}} \ |
22 | // expected-warning {{delete called on non-final 'dnvd::D' that has virtual functions but non-virtual destructor}} |
23 | T& operator*() const { return *_ptr; } |
24 | private: |
25 | T* _ptr; |
26 | }; |
27 | } |
28 | |
29 | #else |
30 | |
31 | #define BE_THE_HEADER |
32 | #include __FILE__ |
33 | |
34 | class A { |
35 | public: |
36 | ~A(); |
37 | }; |
38 | |
39 | class B { |
40 | public: |
41 | ~B() { } |
42 | }; |
43 | |
44 | class C { |
45 | public: |
46 | (~C)() { } |
47 | }; |
48 | |
49 | struct D { |
50 | static void ~D(int, ...) const { } // \ |
51 | // expected-error{{static member function cannot have 'const' qualifier}} \ |
52 | // expected-error{{destructor cannot be declared 'static'}} \ |
53 | // expected-error{{destructor cannot have any parameters}} \ |
54 | // expected-error{{destructor cannot be variadic}} \ |
55 | // expected-error{{destructor cannot have a return type}} \ |
56 | // expected-error{{'const' qualifier is not allowed on a destructor}} |
57 | }; |
58 | |
59 | struct D2 { |
60 | void ~D2() { } // \ |
61 | // expected-error{{destructor cannot have a return type}} |
62 | }; |
63 | |
64 | |
65 | struct E; |
66 | |
67 | typedef E E_typedef; |
68 | struct E { |
69 | ~E_typedef(); // expected-error{{destructor cannot be declared using a typedef 'E_typedef' (aka 'E') of the class name}} |
70 | }; |
71 | |
72 | struct F { |
73 | (~F)(); // expected-note {{previous declaration is here}} |
74 | ~F(); // expected-error {{destructor cannot be redeclared}} |
75 | }; |
76 | |
77 | ~; // expected-error {{expected a class name after '~' to name a destructor}} |
78 | ~undef(); // expected-error {{expected the class name after '~' to name a destructor}} |
79 | ~operator+(int, int); // expected-error {{expected a class name after '~' to name a destructor}} |
80 | ~F(){} // expected-error {{destructor must be a non-static member function}} |
81 | |
82 | struct G { |
83 | ~G(); |
84 | }; |
85 | |
86 | G::~G() { } |
87 | |
88 | // <rdar://problem/6841210> |
89 | struct H { |
90 | ~H(void) { } |
91 | }; |
92 | |
93 | struct X {}; |
94 | |
95 | struct Y { |
96 | ~X(); // expected-error {{expected the class name after '~' to name the enclosing class}} |
97 | }; |
98 | |
99 | namespace PR6421 { |
100 | class T; // expected-note{{forward declaration}} |
101 | |
102 | class QGenericArgument // expected-note{{declared here}} |
103 | { |
104 | template<typename U> |
105 | void foo(T t) // expected-error{{variable has incomplete type}} |
106 | { } |
107 | |
108 | void disconnect() |
109 | { |
110 | T* t; |
111 | bob<QGenericArgument>(t); // expected-error{{undeclared identifier 'bob'}} \ |
112 | // expected-error{{does not refer to a value}} |
113 | } |
114 | }; |
115 | } |
116 | |
117 | namespace PR6709 { |
118 | #ifdef MSABI |
119 | // This bug, "Clang instantiates destructor for function argument" is intended |
120 | // behaviour in the Microsoft ABI because the callee needs to destruct the arguments. |
121 | // expected-error@+3 {{indirection requires pointer operand ('int' invalid)}} |
122 | // expected-note@+3 {{in instantiation of member function 'PR6709::X<int>::~X' requested here}} |
123 | #endif |
124 | template<class T> class X { T v; ~X() { ++*v; } }; |
125 | void a(X<int> x) {} |
126 | } |
127 | |
128 | struct X0 { virtual ~X0() throw(); }; |
129 | struct X1 : public X0 { }; |
130 | |
131 | // Make sure we instantiate operator deletes when building a virtual |
132 | // destructor. |
133 | namespace test6 { |
134 | template <class T> class A { |
135 | public: |
136 | void *operator new(__SIZE_TYPE__); |
137 | void operator delete(void *p) { |
138 | T::deleteIt(p); // expected-error {{type 'int' cannot be used prior to '::'}} |
139 | } |
140 | |
141 | #ifdef MSABI |
142 | // expected-note@+2 {{in instantiation of member function 'test6::A<int>::operator delete' requested here}} |
143 | #endif |
144 | virtual ~A() {} |
145 | }; |
146 | |
147 | #ifndef MSABI |
148 | // expected-note@+2 {{in instantiation of member function 'test6::A<int>::operator delete' requested here}} |
149 | #endif |
150 | class B : A<int> { B(); }; |
151 | B::B() {} |
152 | } |
153 | |
154 | // Make sure classes are marked invalid when they have invalid |
155 | // members. This avoids a crash-on-invalid. |
156 | namespace test7 { |
157 | struct A { |
158 | ~A() const; // expected-error {{'const' qualifier is not allowed on a destructor}} |
159 | }; |
160 | struct B : A {}; |
161 | |
162 | void test() { |
163 | B *b; |
164 | b->~B(); |
165 | } |
166 | } |
167 | |
168 | namespace nonvirtualdtor { |
169 | struct S1 { // expected-warning {{has virtual functions but non-virtual destructor}} |
170 | virtual void m(); |
171 | }; |
172 | |
173 | struct S2 { |
174 | ~S2(); // expected-warning {{has virtual functions but non-virtual destructor}} |
175 | virtual void m(); |
176 | }; |
177 | |
178 | struct S3 : public S1 { // expected-warning {{has virtual functions but non-virtual destructor}} |
179 | virtual void m(); |
180 | }; |
181 | |
182 | struct S4 : public S2 { // expected-warning {{has virtual functions but non-virtual destructor}} |
183 | virtual void m(); |
184 | }; |
185 | |
186 | struct B { |
187 | virtual ~B(); |
188 | virtual void m(); |
189 | }; |
190 | |
191 | struct S5 : public B { |
192 | virtual void m(); |
193 | }; |
194 | |
195 | struct S6 { |
196 | virtual void m(); |
197 | private: |
198 | ~S6(); |
199 | }; |
200 | |
201 | struct S7 { |
202 | virtual void m(); |
203 | protected: |
204 | ~S7(); |
205 | }; |
206 | |
207 | struct S8 {} s8; |
208 | |
209 | UnknownType S8::~S8() { // expected-error {{unknown type name 'UnknownType'}} |
210 | s8.~S8(); |
211 | } |
212 | |
213 | template<class T> class TS : public B { |
214 | virtual void m(); |
215 | }; |
216 | |
217 | TS<int> baz; |
218 | |
219 | template<class T> class TS2 { // expected-warning {{'nonvirtualdtor::TS2<int>' has virtual functions but non-virtual destructor}} |
220 | virtual void m(); |
221 | }; |
222 | |
223 | TS2<int> foo; // expected-note {{instantiation}} |
224 | } |
225 | |
226 | namespace dnvd { // delete-non-virtual-dtor warning |
227 | struct NP {}; |
228 | |
229 | struct B { // expected-warning {{has virtual functions but non-virtual destructor}} |
230 | virtual void foo(); |
231 | }; |
232 | |
233 | struct D: B {}; // expected-warning {{has virtual functions but non-virtual destructor}} |
234 | |
235 | struct F final : B {}; |
236 | |
237 | struct VB { |
238 | virtual void foo(); |
239 | virtual ~VB(); |
240 | }; |
241 | |
242 | struct VD: VB {}; |
243 | |
244 | struct VF final: VB {}; |
245 | |
246 | template <typename T> |
247 | class simple_ptr2 { |
248 | public: |
249 | simple_ptr2(T* t): _ptr(t) {} |
250 | ~simple_ptr2() { delete _ptr; } // expected-warning {{delete called on non-final 'dnvd::B' that has virtual functions but non-virtual destructor}} |
251 | T& operator*() const { return *_ptr; } |
252 | private: |
253 | T* _ptr; |
254 | }; |
255 | |
256 | void use(B&); |
257 | void use(SystemB&); |
258 | void use(VB&); |
259 | |
260 | void nowarnstack() { |
261 | B b; use(b); |
262 | D d; use(d); |
263 | F f; use(f); |
264 | VB vb; use(vb); |
265 | VD vd; use(vd); |
266 | VF vf; use(vf); |
267 | } |
268 | |
269 | void nowarnnonpoly() { |
270 | { |
271 | NP* np = new NP(); |
272 | delete np; |
273 | } |
274 | { |
275 | NP* np = new NP[4]; |
276 | delete[] np; |
277 | } |
278 | } |
279 | |
280 | // FIXME: Why are these supposed to not warn? |
281 | void nowarnarray() { |
282 | { |
283 | B* b = new B[4]; |
284 | delete[] b; |
285 | } |
286 | { |
287 | D* d = new D[4]; |
288 | delete[] d; |
289 | } |
290 | { |
291 | VB* vb = new VB[4]; |
292 | delete[] vb; |
293 | } |
294 | { |
295 | VD* vd = new VD[4]; |
296 | delete[] vd; |
297 | } |
298 | } |
299 | |
300 | template <typename T> |
301 | void nowarntemplate() { |
302 | { |
303 | T* t = new T(); |
304 | delete t; |
305 | } |
306 | { |
307 | T* t = new T[4]; |
308 | delete[] t; |
309 | } |
310 | } |
311 | |
312 | void nowarn0() { |
313 | { |
314 | F* f = new F(); |
315 | delete f; |
316 | } |
317 | { |
318 | VB* vb = new VB(); |
319 | delete vb; |
320 | } |
321 | { |
322 | VB* vb = new VD(); |
323 | delete vb; |
324 | } |
325 | { |
326 | VD* vd = new VD(); |
327 | delete vd; |
328 | } |
329 | { |
330 | VF* vf = new VF(); |
331 | delete vf; |
332 | } |
333 | } |
334 | |
335 | void nowarn0_explicit_dtor(F* f, VB* vb, VD* vd, VF* vf) { |
336 | f->~F(); |
337 | f->~F(); |
338 | vb->~VB(); |
339 | vd->~VD(); |
340 | vf->~VF(); |
341 | } |
342 | |
343 | void warn0() { |
344 | { |
345 | B* b = new B(); |
346 | delete b; // expected-warning {{delete called on non-final 'dnvd::B' that has virtual functions but non-virtual destructor}} |
347 | } |
348 | { |
349 | B* b = new D(); |
350 | delete b; // expected-warning {{delete called on non-final 'dnvd::B' that has virtual functions but non-virtual destructor}} |
351 | } |
352 | { |
353 | D* d = new D(); |
354 | delete d; // expected-warning {{delete called on non-final 'dnvd::D' that has virtual functions but non-virtual destructor}} |
355 | } |
356 | } |
357 | |
358 | // Taken from libc++, slightly simplified. |
359 | template <class> |
360 | struct __is_destructible_apply { typedef int type; }; |
361 | struct __two {char __lx[2];}; |
362 | template <typename _Tp> |
363 | struct __is_destructor_wellformed { |
364 | template <typename _Tp1> |
365 | static char __test(typename __is_destructible_apply< |
366 | decltype(_Tp1().~_Tp1())>::type); |
367 | template <typename _Tp1> |
368 | static __two __test (...); |
369 | |
370 | static const bool value = sizeof(__test<_Tp>(12)) == sizeof(char); |
371 | }; |
372 | |
373 | void warn0_explicit_dtor(B* b, B& br, D* d) { |
374 | b->~B(); // expected-warning {{destructor called on non-final 'dnvd::B' that has virtual functions but non-virtual destructor}} expected-note{{qualify call to silence this warning}} |
375 | b->B::~B(); // No warning when the call isn't virtual. |
376 | |
377 | // No warning in unevaluated contexts. |
378 | (void)__is_destructor_wellformed<B>::value; |
379 | |
380 | br.~B(); // expected-warning {{destructor called on non-final 'dnvd::B' that has virtual functions but non-virtual destructor}} expected-note{{qualify call to silence this warning}} |
381 | br.B::~B(); |
382 | |
383 | d->~D(); // expected-warning {{destructor called on non-final 'dnvd::D' that has virtual functions but non-virtual destructor}} expected-note{{qualify call to silence this warning}} |
384 | d->D::~D(); |
385 | } |
386 | |
387 | void nowarn1() { |
388 | { |
389 | simple_ptr<F> f(new F()); |
390 | use(*f); |
391 | } |
392 | { |
393 | simple_ptr<VB> vb(new VB()); |
394 | use(*vb); |
395 | } |
396 | { |
397 | simple_ptr<VB> vb(new VD()); |
398 | use(*vb); |
399 | } |
400 | { |
401 | simple_ptr<VD> vd(new VD()); |
402 | use(*vd); |
403 | } |
404 | { |
405 | simple_ptr<VF> vf(new VF()); |
406 | use(*vf); |
407 | } |
408 | { |
409 | simple_ptr<SystemB> sb(new SystemB()); |
410 | use(*sb); |
411 | } |
412 | } |
413 | |
414 | void warn1() { |
415 | { |
416 | simple_ptr<B> b(new B()); // expected-note {{in instantiation of member function 'dnvd::simple_ptr<dnvd::B>::~simple_ptr' requested here}} |
417 | use(*b); |
418 | } |
419 | { |
420 | simple_ptr2<B> b(new D()); // expected-note {{in instantiation of member function 'dnvd::simple_ptr2<dnvd::B>::~simple_ptr2' requested here}} |
421 | use(*b); |
422 | } |
423 | { |
424 | simple_ptr<D> d(new D()); // expected-note {{in instantiation of member function 'dnvd::simple_ptr<dnvd::D>::~simple_ptr' requested here}} |
425 | use(*d); |
426 | } |
427 | } |
428 | } |
429 | |
430 | namespace PR9238 { |
431 | class B { public: ~B(); }; |
432 | class C : virtual B { public: ~C() { } }; |
433 | } |
434 | |
435 | namespace PR7900 { |
436 | struct A { // expected-note 2{{type 'PR7900::A' is declared here}} |
437 | }; |
438 | struct B : public A { |
439 | }; |
440 | void foo() { |
441 | B b; |
442 | b.~B(); |
443 | b.~A(); // expected-error{{destructor type 'PR7900::A' in object destruction expression does not match the type 'PR7900::B' of the object being destroyed}} |
444 | (&b)->~A(); // expected-error{{destructor type 'PR7900::A' in object destruction expression does not match the type 'PR7900::B' of the object being destroyed}} |
445 | } |
446 | } |
447 | |
448 | namespace PR16892 { |
449 | auto p = &A::~A; // expected-error{{taking the address of a destructor}} |
450 | } |
451 | |
452 | namespace PR20238 { |
453 | struct S { |
454 | volatile ~S() { } // expected-error{{destructor cannot have a return type}} |
455 | }; |
456 | } |
457 | |
458 | namespace PR22668 { |
459 | struct S { |
460 | }; |
461 | void f(S s) { |
462 | (s.~S)(); |
463 | } |
464 | void g(S s) { |
465 | (s.~S); // expected-error{{reference to destructor must be called}} |
466 | } |
467 | } |
468 | |
469 | class Invalid { |
470 | ~Invalid(); |
471 | UnknownType xx; // expected-error{{unknown type name}} |
472 | }; |
473 | |
474 | // The constructor definition should not have errors |
475 | Invalid::~Invalid() {} |
476 | |
477 | namespace PR30361 { |
478 | template <typename T> |
479 | struct C1 { |
480 | ~C1() {} |
481 | operator C1<T>* () { return nullptr; } |
482 | void foo1(); |
483 | }; |
484 | |
485 | template<typename T> |
486 | void C1<T>::foo1() { |
487 | C1::operator C1<T>*(); |
488 | C1::~C1(); |
489 | } |
490 | |
491 | void foo1() { |
492 | C1<int> x; |
493 | x.foo1(); |
494 | } |
495 | } |
496 | #endif // BE_THE_HEADER |
497 | |