xref: /llvm-project/clang/test/SemaCXX/destructor.cpp (revision d49a2d2bc9c65c787bfa04ac8ece614da48a8cd5)
1 // RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -fsyntax-only -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -fcxx-exceptions -verify %s -pedantic
2 // RUN: %clang_cc1 -std=c++11 -triple %ms_abi_triple -DMSABI -fsyntax-only -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -verify %s -pedantic
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 {{undeclared identifier 'undef' in destructor name}}
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 struct H {
89   ~H(void) { }
90 };
91 
92 struct X {};
93 
94 struct Y {
95   ~X(); // expected-error {{expected the class name after '~' to name the enclosing class}}
96 };
97 
98 namespace PR6421 {
99   class T; // expected-note{{forward declaration}}
100 
101   class QGenericArgument
102   {
103     template<typename U>
104     void foo(T t) // expected-error{{variable has incomplete type}}
105     { }
106 
107     void disconnect()
108     {
109       T* t;
110       bob<QGenericArgument>(t); // expected-error{{undeclared identifier 'bob'}}
111     }
112   };
113 }
114 
115 namespace PR6709 {
116 #ifdef MSABI
117   // This bug, "Clang instantiates destructor for function argument" is intended
118   // behaviour in the Microsoft ABI because the callee needs to destruct the arguments.
119   // expected-error@+3 {{indirection requires pointer operand ('int' invalid)}}
120   // expected-note@+3 {{in instantiation of member function 'PR6709::X<int>::~X' requested here}}
121 #endif
122   template<class T> class X { T v; ~X() { ++*v; } };
123   void a(X<int> x) {}
124 }
125 
126 struct X0 { virtual ~X0() throw(); };
127 struct X1 : public X0 { };
128 
129 // Make sure we instantiate operator deletes when building a virtual
130 // destructor.
131 namespace test6 {
132   template <class T> class A {
133   public:
134     void *operator new(__SIZE_TYPE__);
135     void operator delete(void *p) {
136       T::deleteIt(p); // expected-error {{type 'int' cannot be used prior to '::'}}
137     }
138 
139 #ifdef MSABI
140     // expected-note@+2 {{in instantiation of member function 'test6::A<int>::operator delete' requested here}}
141 #endif
142     virtual ~A() {}
143   };
144 
145 #ifndef MSABI
146     // expected-note@+2 {{in instantiation of member function 'test6::A<int>::operator delete' requested here}}
147 #endif
148   class B : A<int> { B(); };
149   B::B() {}
150 }
151 
152 // Make sure classes are marked invalid when they have invalid
153 // members.  This avoids a crash-on-invalid.
154 namespace test7 {
155   struct A {
156     ~A() const; // expected-error {{'const' qualifier is not allowed on a destructor}}
157   };
158   struct B : A {};
159 
160   void test() {
161     B *b;
162     b->~B();
163   }
164 }
165 
166 namespace nonvirtualdtor {
167 struct S1 { // expected-warning {{has virtual functions but non-virtual destructor}}
168   virtual void m();
169 };
170 
171 struct S2 {
172   ~S2(); // expected-warning {{has virtual functions but non-virtual destructor}}
173   virtual void m();
174 };
175 
176 struct S3 : public S1 {  // expected-warning {{has virtual functions but non-virtual destructor}}
177   virtual void m();
178 };
179 
180 struct S4 : public S2 {  // expected-warning {{has virtual functions but non-virtual destructor}}
181   virtual void m();
182 };
183 
184 struct B {
185   virtual ~B();
186   virtual void m();
187 };
188 
189 struct S5 : public B {
190   virtual void m();
191 };
192 
193 struct S6 {
194   virtual void m();
195 private:
196   ~S6();
197 };
198 
199 struct S7 {
200   virtual void m();
201 protected:
202   ~S7();
203 };
204 
205 struct S8 {} s8;
206 
207 UnknownType S8::~S8() { // expected-error {{unknown type name 'UnknownType'}}
208   s8.~S8();
209 }
210 
211 template<class T> class TS : public B {
212   virtual void m();
213 };
214 
215 TS<int> baz;
216 
217 template<class T> class TS2 { // expected-warning {{'nonvirtualdtor::TS2<int>' has virtual functions but non-virtual destructor}}
218   virtual void m();
219 };
220 
221 TS2<int> foo; // expected-note {{instantiation}}
222 }
223 
224 namespace dnvd { // delete-non-virtual-dtor warning
225 struct NP {};
226 
227 struct B { // expected-warning {{has virtual functions but non-virtual destructor}}
228   virtual void foo();
229 };
230 
231 struct D: B {}; // expected-warning {{has virtual functions but non-virtual destructor}}
232 
233 struct F final : B {};
234 
235 struct VB {
236   virtual void foo();
237   virtual ~VB();
238 };
239 
240 struct VD: VB {};
241 
242 struct VF final: VB {};
243 
244 template <typename T>
245 class simple_ptr2 {
246 public:
247   simple_ptr2(T* t): _ptr(t) {}
248   ~simple_ptr2() { delete _ptr; } // expected-warning {{delete called on non-final 'dnvd::B' that has virtual functions but non-virtual destructor}}
249   T& operator*() const { return *_ptr; }
250 private:
251   T* _ptr;
252 };
253 
254 void use(B&);
255 void use(SystemB&);
256 void use(VB&);
257 
258 void nowarnstack() {
259   B b; use(b);
260   D d; use(d);
261   F f; use(f);
262   VB vb; use(vb);
263   VD vd; use(vd);
264   VF vf; use(vf);
265 }
266 
267 void nowarnnonpoly() {
268   {
269     NP* np = new NP();
270     delete np;
271   }
272   {
273     NP* np = new NP[4];
274     delete[] np;
275   }
276 }
277 
278 // FIXME: Why are these supposed to not warn?
279 void nowarnarray() {
280   {
281     B* b = new B[4];
282     delete[] b;
283   }
284   {
285     D* d = new D[4];
286     delete[] d;
287   }
288   {
289     VB* vb = new VB[4];
290     delete[] vb;
291   }
292   {
293     VD* vd = new VD[4];
294     delete[] vd;
295   }
296 }
297 
298 template <typename T>
299 void nowarntemplate() {
300   {
301     T* t = new T();
302     delete t;
303   }
304   {
305     T* t = new T[4];
306     delete[] t;
307   }
308 }
309 
310 void nowarn0() {
311   {
312     F* f = new F();
313     delete f;
314   }
315   {
316     VB* vb = new VB();
317     delete vb;
318   }
319   {
320     VB* vb = new VD();
321     delete vb;
322   }
323   {
324     VD* vd = new VD();
325     delete vd;
326   }
327   {
328     VF* vf = new VF();
329     delete vf;
330   }
331 }
332 
333 void nowarn0_explicit_dtor(F* f, VB* vb, VD* vd, VF* vf) {
334   f->~F();
335   f->~F();
336   vb->~VB();
337   vd->~VD();
338   vf->~VF();
339 }
340 
341 void warn0() {
342   {
343     B* b = new B();
344     delete b; // expected-warning {{delete called on non-final 'dnvd::B' that has virtual functions but non-virtual destructor}}
345   }
346   {
347     B* b = new D();
348     delete b; // expected-warning {{delete called on non-final 'dnvd::B' that has virtual functions but non-virtual destructor}}
349   }
350   {
351     D* d = new D();
352     delete d; // expected-warning {{delete called on non-final 'dnvd::D' that has virtual functions but non-virtual destructor}}
353   }
354 }
355 
356 // Taken from libc++, slightly simplified.
357 template <class>
358 struct __is_destructible_apply { typedef int type; };
359 struct __two {char __lx[2];};
360 template <typename _Tp>
361 struct __is_destructor_wellformed {
362   template <typename _Tp1>
363   static char __test(typename __is_destructible_apply<
364                        decltype(_Tp1().~_Tp1())>::type);
365   template <typename _Tp1>
366   static __two __test (...);
367 
368   static const bool value = sizeof(__test<_Tp>(12)) == sizeof(char);
369 };
370 
371 void warn0_explicit_dtor(B* b, B& br, D* d) {
372   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}}
373   b->B::~B(); // No warning when the call isn't virtual.
374 
375   // No warning in unevaluated contexts.
376   (void)__is_destructor_wellformed<B>::value;
377 
378   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}}
379   br.B::~B();
380 
381   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}}
382   d->D::~D();
383 }
384 
385 void nowarn1() {
386   {
387     simple_ptr<F> f(new F());
388     use(*f);
389   }
390   {
391     simple_ptr<VB> vb(new VB());
392     use(*vb);
393   }
394   {
395     simple_ptr<VB> vb(new VD());
396     use(*vb);
397   }
398   {
399     simple_ptr<VD> vd(new VD());
400     use(*vd);
401   }
402   {
403     simple_ptr<VF> vf(new VF());
404     use(*vf);
405   }
406   {
407     simple_ptr<SystemB> sb(new SystemB());
408     use(*sb);
409   }
410 }
411 
412 void warn1() {
413   {
414     simple_ptr<B> b(new B()); // expected-note {{in instantiation of member function 'dnvd::simple_ptr<dnvd::B>::~simple_ptr' requested here}}
415     use(*b);
416   }
417   {
418     simple_ptr2<B> b(new D()); // expected-note {{in instantiation of member function 'dnvd::simple_ptr2<dnvd::B>::~simple_ptr2' requested here}}
419     use(*b);
420   }
421   {
422     simple_ptr<D> d(new D()); // expected-note {{in instantiation of member function 'dnvd::simple_ptr<dnvd::D>::~simple_ptr' requested here}}
423     use(*d);
424   }
425 }
426 }
427 
428 namespace PR9238 {
429   class B { public: ~B(); };
430   class C : virtual B { public: ~C() { } };
431 }
432 
433 namespace PR7900 {
434   struct A { // expected-note 2{{type 'PR7900::A' found by destructor name lookup}}
435   };
436   struct B : public A {
437   };
438   void foo() {
439     B b;
440     b.~B();
441     b.~A(); // expected-error{{destructor type 'PR7900::A' in object destruction expression does not match the type 'B' of the object being destroyed}}
442     (&b)->~A(); // expected-error{{destructor type 'PR7900::A' in object destruction expression does not match the type 'B' of the object being destroyed}}
443   }
444 }
445 
446 namespace PR16892 {
447   auto p = &A::~A; // expected-error{{taking the address of a destructor}}
448 }
449 
450 namespace PR20238 {
451 struct S {
452   volatile ~S() { } // expected-error{{destructor cannot have a return type}}
453 };
454 }
455 
456 namespace PR22668 {
457 struct S {
458 };
459 void f(S s) {
460   (s.~S)();
461 }
462 void g(S s) {
463   (s.~S); // expected-error{{reference to destructor must be called}}
464 }
465 }
466 
467 class Invalid {
468     ~Invalid();
469     UnknownType xx; // expected-error{{unknown type name}}
470 };
471 
472 // The constructor definition should not have errors
473 Invalid::~Invalid() {}
474 
475 namespace PR30361 {
476 template <typename T>
477 struct C1 {
478   ~C1() {}
479   operator C1<T>* () { return nullptr; }
480   void foo1();
481 };
482 
483 template<typename T>
484 void C1<T>::foo1() {
485   C1::operator C1<T>*();
486   C1::~C1();
487 }
488 
489 void foo1() {
490   C1<int> x;
491   x.foo1();
492 }
493 }
494 
495 namespace DtorTypedef {
496   struct A { ~A(); };
497   using A = A;
498   DtorTypedef::A::~A() {}
499 
500   // This is invalid, but compilers accept it.
501   struct B { ~B(); };
502   namespace N { using B = B; }
503   N::B::~B() {} // expected-error {{destructor cannot be declared using a type alias}}
504 
505 #pragma clang diagnostic push
506 #pragma clang diagnostic ignored "-Wdtor-typedef"
507   struct C { ~C(); };
508   namespace N { using C = C; }
509   N::C::~C() {}
510 #pragma clang diagnostic pop
511 }
512 
513 // Ignore ambiguity errors in destructor name lookup. This matches the observed
514 // behavior of ICC, and is compatible with the observed behavior of GCC (which
515 // appears to ignore lookups that result in ambiguity) and MSVC (which appears
516 // to perform the lookups in the opposite order from Clang).
517 namespace PR44978 {
518   // All compilers accept this despite it being clearly ill-formed per the
519   // current wording.
520   namespace n {
521     class Foo {}; // expected-note {{found}}
522   }
523   class Foo {}; // expected-note {{found}}
524   using namespace n;
525   static void func(n::Foo *p) { p->~Foo(); } // expected-warning {{ambiguous}}
526 
527   // GCC rejects this case, ICC accepts, despite the class member lookup being
528   // ambiguous.
529   struct Z;
530   struct X { using T = Z; }; // expected-note {{found}}
531   struct Y { using T = int; }; // expected-note {{found}}
532   struct Z : X, Y {};
533   void f(Z *p) { p->~T(); } // expected-warning {{ambiguous}}
534 
535   // GCC accepts this and ignores the ambiguous class member lookup.
536   //
537   // FIXME: We should warn on the ambiguity here too, but that requires us to
538   // keep doing lookups after we've already found the type we want.
539   using T = Z;
540   void g(Z *p) { p->~T(); }
541 
542   // ICC accepts this and ignores the ambiguous unqualified lookup.
543   struct Q {};
544   namespace { using U = Q; } // expected-note {{candidate}} expected-note {{found}}
545   using U = int; // expected-note {{candidate}} expected-note {{found}}
546   void f(Q *p) { p->~U(); } // expected-warning {{ambiguous}}
547 
548   // We still diagnose if the unqualified lookup is dependent, though.
549   template<typename T> void f(T *p) { p->~U(); } // expected-error {{ambiguous}}
550 }
551 
552 namespace crash_on_invalid_base_dtor {
553 struct Test {
554   virtual ~Test();
555 };
556 struct Baz : public Test { // expected-warning {{non-virtual destructor}}
557   Baz() {}
558   ~Baz() = defaul; // expected-error {{undeclared identifier 'defaul'}} \
559                    // expected-error {{initializer on function}} \
560                    // expected-note {{overridden virtual function is here}}
561 };
562 struct Foo : public Baz { // expected-error {{cannot override a non-deleted function}} \
563                           // expected-note {{destructor of 'Foo' is implicitly deleted}}
564   Foo() {}
565 };
566 }
567 
568 namespace GH89544 {
569 class Foo {
570   ~Foo() = {}
571   // expected-error@-1 {{initializer on function does not look like a pure-specifier}}
572   // expected-error@-2 {{expected ';' at end of declaration list}}
573 };
574 
575 static_assert(!__is_trivially_constructible(Foo), "");
576 static_assert(!__is_trivially_constructible(Foo, const Foo &), "");
577 static_assert(!__is_trivially_constructible(Foo, Foo &&), "");
578 } // namespace GH89544
579 
580 namespace GH97230 {
581 struct X {
582   ~X() = defaul; // expected-error {{initializer on function does not look like a pure-specifier}} \
583                  // expected-error {{use of undeclared identifier 'defaul'}}
584 };
585 struct Y : X {} y1{ }; // expected-error {{call to implicitly-deleted default constructor of 'struct Y'}} \
586                        // expected-note {{default constructor of 'Y' is implicitly deleted because base class 'X' has no destructor}}
587 }
588 
589 namespace GH121706 {
590 struct A {
591   *&~A(); // expected-error {{invalid destructor declaration}}
592 };
593 
594 struct B {
595   *&&~B(); // expected-error {{invalid destructor declaration}}
596 };
597 
598 struct C {
599   *const ~C(); // expected-error {{invalid destructor declaration}}
600 };
601 
602 struct D {
603   *const * ~D(); // expected-error {{invalid destructor declaration}}
604 };
605 
606 struct E {
607   *E::*~E(); // expected-error {{invalid destructor declaration}}
608 };
609 
610 struct F {
611   *F::*const ~F(); // expected-error {{invalid destructor declaration}}
612 };
613 
614 struct G {
615   ****~G(); // expected-error {{invalid destructor declaration}}
616 };
617 
618 struct H {
619   **~H(); // expected-error {{invalid destructor declaration}}
620 };
621 
622 struct I {
623   *~I(); // expected-error {{invalid destructor declaration}}
624 };
625 
626 struct J {
627   *&~J(); // expected-error {{invalid destructor declaration}}
628 };
629 
630 struct K {
631   **&&~K(); // expected-error {{invalid destructor declaration}}
632 };
633 }
634 
635 #endif // BE_THE_HEADER
636