Clang Project

clang_source_code/test/SemaCXX/destructor.cpp
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
10namespace dnvd {
11
12struct SystemB {
13  virtual void foo();
14};
15
16template <typename T>
17class simple_ptr {
18public:
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; }
24private:
25  T* _ptr;
26};
27}
28
29#else
30
31#define BE_THE_HEADER
32#include __FILE__
33
34class A {
35public:
36  ~A();
37};
38
39class B {
40public:
41  ~B() { }
42};
43
44class C {
45public:
46  (~C)() { }
47};
48
49struct 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
59struct D2 {
60  void ~D2() { } //                          \
61  // expected-error{{destructor cannot have a return type}}  
62};
63
64
65struct E;
66
67typedef E E_typedef;
68struct E {
69  ~E_typedef(); // expected-error{{destructor cannot be declared using a typedef 'E_typedef' (aka 'E') of the class name}}
70};
71
72struct 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
82struct G {
83  ~G();
84};
85
86G::~G() { }
87
88// <rdar://problem/6841210>
89struct H {
90  ~H(void) { } 
91};
92
93struct X {};
94
95struct Y {
96  ~X(); // expected-error {{expected the class name after '~' to name the enclosing class}}
97};
98
99namespace 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
117namespace 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
128struct X0 { virtual ~X0() throw(); };
129struct X1 : public X0 { };
130
131// Make sure we instantiate operator deletes when building a virtual
132// destructor.
133namespace 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.
156namespace 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
168namespace nonvirtualdtor {
169struct S1 { // expected-warning {{has virtual functions but non-virtual destructor}}
170  virtual void m();
171};
172
173struct S2 {
174  ~S2(); // expected-warning {{has virtual functions but non-virtual destructor}}
175  virtual void m();
176};
177
178struct S3 : public S1 {  // expected-warning {{has virtual functions but non-virtual destructor}}
179  virtual void m();
180};
181
182struct S4 : public S2 {  // expected-warning {{has virtual functions but non-virtual destructor}}
183  virtual void m();
184};
185
186struct B {
187  virtual ~B();
188  virtual void m();
189};
190
191struct S5 : public B {
192  virtual void m();
193};
194
195struct S6 {
196  virtual void m();
197private:
198  ~S6();
199};
200
201struct S7 {
202  virtual void m();
203protected:
204  ~S7();
205};
206
207struct S8 {} s8;
208
209UnknownType S8::~S8() { // expected-error {{unknown type name 'UnknownType'}}
210  s8.~S8();
211}
212
213template<class T> class TS : public B {
214  virtual void m();
215};
216
217TS<int> baz;
218
219template<class T> class TS2 { // expected-warning {{'nonvirtualdtor::TS2<int>' has virtual functions but non-virtual destructor}}
220  virtual void m();
221};
222
223TS2<int> foo; // expected-note {{instantiation}}
224}
225
226namespace dnvd { // delete-non-virtual-dtor warning
227struct NP {};
228
229struct B { // expected-warning {{has virtual functions but non-virtual destructor}}
230  virtual void foo();
231};
232
233struct D: B {}; // expected-warning {{has virtual functions but non-virtual destructor}}
234
235struct F final : B {};
236
237struct VB {
238  virtual void foo();
239  virtual ~VB();
240};
241
242struct VD: VB {};
243
244struct VF final: VB {};
245
246template <typename T>
247class simple_ptr2 {
248public:
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; }
252private:
253  T* _ptr;
254};
255
256void use(B&);
257void use(SystemB&);
258void use(VB&);
259
260void 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
269void 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?
281void 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
300template <typename T>
301void nowarntemplate() {
302  {
303    T* t = new T();
304    delete t;
305  }
306  {
307    T* t = new T[4];
308    delete[] t;
309  }
310}
311
312void 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
335void 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
343void 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.
359template <class>
360struct __is_destructible_apply { typedef int type; };
361struct __two {char __lx[2];};
362template <typename _Tp>
363struct __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
373void 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
387void 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
414void 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
430namespace PR9238 {
431  class B { public: ~B(); };
432  class C : virtual B { public: ~C() { } };
433}
434
435namespace 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
448namespace PR16892 {
449  auto p = &A::~A; // expected-error{{taking the address of a destructor}}
450}
451
452namespace PR20238 {
453struct S {
454  volatile ~S() { } // expected-error{{destructor cannot have a return type}}
455};
456}
457
458namespace PR22668 {
459struct S {
460};
461void f(S s) {
462  (s.~S)();
463}
464void g(S s) {
465  (s.~S); // expected-error{{reference to destructor must be called}}
466}
467}
468
469class Invalid {
470    ~Invalid();
471    UnknownType xx; // expected-error{{unknown type name}}
472};
473
474// The constructor definition should not have errors
475Invalid::~Invalid() {}
476
477namespace PR30361 {
478template <typename T>
479struct C1 {
480  ~C1() {}
481  operator C1<T>* () { return nullptr; }
482  void foo1();
483};
484
485template<typename T>
486void C1<T>::foo1() {
487  C1::operator C1<T>*();
488  C1::~C1();
489}
490
491void foo1() {
492  C1<int> x;
493  x.foo1();
494}
495}
496#endif // BE_THE_HEADER
497