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:
simple_ptr(T * t)19 simple_ptr(T* t): _ptr(t) {}
~simple_ptr()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}}
operator *() const23 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:
~B()41 ~B() { }
42 };
43
44 class C {
45 public:
46 (~C)() { }
47 };
48
49 struct D {
~DD50 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 {
~D2D260 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}}
~F()80 ~F(){} // expected-error {{destructor must be a non-static member function}}
81
82 struct G {
83 ~G();
84 };
85
~G()86 G::~G() { }
87
88 // <rdar://problem/6841210>
89 struct H {
~HH90 ~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>
foo(T t)105 void foo(T t) // expected-error{{variable has incomplete type}}
106 { }
107
disconnect()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
~X()124 template<class T> class X { T v; ~X() { ++*v; } };
a(X<int> x)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__);
operator delete(void * p)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
~A()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(); };
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
test()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
~S8()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:
simple_ptr2(T * t)249 simple_ptr2(T* t): _ptr(t) {}
~simple_ptr2()250 ~simple_ptr2() { delete _ptr; } // expected-warning {{delete called on non-final 'dnvd::B' that has virtual functions but non-virtual destructor}}
operator *() const251 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
nowarnstack()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
nowarnnonpoly()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?
nowarnarray()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>
nowarntemplate()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
nowarn0()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
nowarn0_explicit_dtor(F * f,VB * vb,VD * vd,VF * vf)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
warn0()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
warn0_explicit_dtor(B * b,B & br,D * d)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
nowarn1()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
warn1()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(); };
~C()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 };
foo()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 {
~SPR20238::S454 volatile ~S() { } // expected-error{{destructor cannot have a return type}}
455 };
456 }
457
458 namespace PR22668 {
459 struct S {
460 };
f(S s)461 void f(S s) {
462 (s.~S)();
463 }
g(S s)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
~Invalid()475 Invalid::~Invalid() {}
476
477 namespace PR30361 {
478 template <typename T>
479 struct C1 {
~C1PR30361::C1480 ~C1() {}
operator C1<T>*PR30361::C1481 operator C1<T>* () { return nullptr; }
482 void foo1();
483 };
484
485 template<typename T>
foo1()486 void C1<T>::foo1() {
487 C1::operator C1<T>*();
488 C1::~C1();
489 }
490
foo1()491 void foo1() {
492 C1<int> x;
493 x.foo1();
494 }
495 }
496 #endif // BE_THE_HEADER
497