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