1 // RUN: %clang_cc1 -std=c++11 -fsyntax-only -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -verify %s
2 class A {
3 public:
4   ~A();
5 };
6 
7 class B {
8 public:
9   ~B() { }
10 };
11 
12 class C {
13 public:
14   (~C)() { }
15 };
16 
17 struct D {
18   static void ~D(int, ...) const { } //                          \
19     // expected-error{{static member function cannot have 'const' qualifier}} \
20     // expected-error{{destructor cannot be declared 'static'}}  \
21     // expected-error{{destructor cannot have any parameters}}   \
22     // expected-error{{destructor cannot be variadic}} \
23     // expected-error{{destructor cannot have a return type}} \
24     // expected-error{{'const' qualifier is not allowed on a destructor}}
25 };
26 
27 struct D2 {
28   void ~D2() { } //                          \
29   // expected-error{{destructor cannot have a return type}}
30 };
31 
32 
33 struct E;
34 
35 typedef E E_typedef;
36 struct E {
37   ~E_typedef(); // expected-error{{destructor cannot be declared using a typedef 'E_typedef' (aka 'E') of the class name}}
38 };
39 
40 struct F {
41   (~F)(); // expected-note {{previous declaration is here}}
42   ~F(); // expected-error {{destructor cannot be redeclared}}
43 };
44 
45 ~; // expected-error {{expected a class name after '~' to name a destructor}}
46 ~undef(); // expected-error {{expected the class name after '~' to name a destructor}}
47 ~operator+(int, int);  // expected-error {{expected a class name after '~' to name a destructor}}
48 ~F(){} // expected-error {{destructor must be a non-static member function}}
49 
50 struct G {
51   ~G();
52 };
53 
54 G::~G() { }
55 
56 // <rdar://problem/6841210>
57 struct H {
58   ~H(void) { }
59 };
60 
61 struct X {};
62 
63 struct Y {
64   ~X(); // expected-error {{expected the class name after '~' to name the enclosing class}}
65 };
66 
67 namespace PR6421 {
68   class T; // expected-note{{forward declaration}}
69 
70   class QGenericArgument // expected-note{{declared here}}
71   {
72     template<typename U>
73     void foo(T t) // expected-error{{variable has incomplete type}}
74     { }
75 
76     void disconnect()
77     {
78       T* t;
79       bob<QGenericArgument>(t); // expected-error{{undeclared identifier 'bob'}} \
80       // expected-error{{does not refer to a value}}
81     }
82   };
83 }
84 
85 namespace PR6709 {
86   template<class T> class X { T v; ~X() { ++*v; } };
87   void a(X<int> x) {}
88 }
89 
90 struct X0 { virtual ~X0() throw(); };
91 struct X1 : public X0 { };
92 
93 // Make sure we instantiate operator deletes when building a virtual
94 // destructor.
95 namespace test6 {
96   template <class T> class A {
97   public:
98     void *operator new(__SIZE_TYPE__);
99     void operator delete(void *p) {
100       T::deleteIt(p); // expected-error {{type 'int' cannot be used prior to '::'}}
101     }
102 
103     virtual ~A() {}
104   };
105 
106   class B : A<int> { B(); }; // expected-note {{in instantiation of member function 'test6::A<int>::operator delete' requested here}}
107   B::B() {}
108 }
109 
110 // Make sure classes are marked invalid when they have invalid
111 // members.  This avoids a crash-on-invalid.
112 namespace test7 {
113   struct A {
114     ~A() const; // expected-error {{'const' qualifier is not allowed on a destructor}}
115   };
116   struct B : A {};
117 
118   void test() {
119     B *b;
120     b->~B();
121   }
122 }
123 
124 namespace nonvirtualdtor {
125 struct S1 { // expected-warning {{has virtual functions but non-virtual destructor}}
126   virtual void m();
127 };
128 
129 struct S2 {
130   ~S2(); // expected-warning {{has virtual functions but non-virtual destructor}}
131   virtual void m();
132 };
133 
134 struct S3 : public S1 {  // expected-warning {{has virtual functions but non-virtual destructor}}
135   virtual void m();
136 };
137 
138 struct S4 : public S2 {  // expected-warning {{has virtual functions but non-virtual destructor}}
139   virtual void m();
140 };
141 
142 struct B {
143   virtual ~B();
144   virtual void m();
145 };
146 
147 struct S5 : public B {
148   virtual void m();
149 };
150 
151 struct S6 {
152   virtual void m();
153 private:
154   ~S6();
155 };
156 
157 struct S7 {
158   virtual void m();
159 protected:
160   ~S7();
161 };
162 
163 template<class T> class TS : public B {
164   virtual void m();
165 };
166 
167 TS<int> baz;
168 
169 template<class T> class TS2 { // expected-warning {{'nonvirtualdtor::TS2<int>' has virtual functions but non-virtual destructor}}
170   virtual void m();
171 };
172 
173 TS2<int> foo; // expected-note {{instantiation}}
174 }
175 
176 namespace dnvd { // delete-non-virtual-dtor warning
177 struct NP {};
178 
179 struct B { // expected-warning {{has virtual functions but non-virtual destructor}}
180   virtual void foo();
181 };
182 
183 struct D: B {}; // expected-warning {{has virtual functions but non-virtual destructor}}
184 
185 struct F final: B {}; // expected-warning {{has virtual functions but non-virtual destructor}}
186 
187 struct VB {
188   virtual void foo();
189   virtual ~VB();
190 };
191 
192 struct VD: VB {};
193 
194 struct VF final: VB {};
195 
196 template <typename T>
197 class simple_ptr {
198 public:
199   simple_ptr(T* t): _ptr(t) {}
200   ~simple_ptr() { delete _ptr; } // \
201     // expected-warning {{delete called on 'dnvd::B' that has virtual functions but non-virtual destructor}} \
202     // expected-warning {{delete called on 'dnvd::D' that has virtual functions but non-virtual destructor}}
203   T& operator*() const { return *_ptr; }
204 private:
205   T* _ptr;
206 };
207 
208 template <typename T>
209 class simple_ptr2 {
210 public:
211   simple_ptr2(T* t): _ptr(t) {}
212   ~simple_ptr2() { delete _ptr; } // expected-warning {{delete called on 'dnvd::B' that has virtual functions but non-virtual destructor}}
213   T& operator*() const { return *_ptr; }
214 private:
215   T* _ptr;
216 };
217 
218 void use(B&);
219 void use(VB&);
220 
221 void nowarnstack() {
222   B b; use(b);
223   D d; use(d);
224   F f; use(f);
225   VB vb; use(vb);
226   VD vd; use(vd);
227   VF vf; use(vf);
228 }
229 
230 void nowarnnonpoly() {
231   {
232     NP* np = new NP();
233     delete np;
234   }
235   {
236     NP* np = new NP[4];
237     delete[] np;
238   }
239 }
240 
241 void nowarnarray() {
242   {
243     B* b = new B[4];
244     delete[] b;
245   }
246   {
247     D* d = new D[4];
248     delete[] d;
249   }
250   {
251     VB* vb = new VB[4];
252     delete[] vb;
253   }
254   {
255     VD* vd = new VD[4];
256     delete[] vd;
257   }
258 }
259 
260 template <typename T>
261 void nowarntemplate() {
262   {
263     T* t = new T();
264     delete t;
265   }
266   {
267     T* t = new T[4];
268     delete[] t;
269   }
270 }
271 
272 void nowarn0() {
273   {
274     F* f = new F();
275     delete f;
276   }
277   {
278     VB* vb = new VB();
279     delete vb;
280   }
281   {
282     VB* vb = new VD();
283     delete vb;
284   }
285   {
286     VD* vd = new VD();
287     delete vd;
288   }
289   {
290     VF* vf = new VF();
291     delete vf;
292   }
293 }
294 
295 void warn0() {
296   {
297     B* b = new B();
298     delete b; // expected-warning {{delete called on 'dnvd::B' that has virtual functions but non-virtual destructor}}
299   }
300   {
301     B* b = new D();
302     delete b; // expected-warning {{delete called on 'dnvd::B' that has virtual functions but non-virtual destructor}}
303   }
304   {
305     D* d = new D();
306     delete d; // expected-warning {{delete called on 'dnvd::D' that has virtual functions but non-virtual destructor}}
307   }
308 }
309 
310 void nowarn1() {
311   {
312     simple_ptr<F> f(new F());
313     use(*f);
314   }
315   {
316     simple_ptr<VB> vb(new VB());
317     use(*vb);
318   }
319   {
320     simple_ptr<VB> vb(new VD());
321     use(*vb);
322   }
323   {
324     simple_ptr<VD> vd(new VD());
325     use(*vd);
326   }
327   {
328     simple_ptr<VF> vf(new VF());
329     use(*vf);
330   }
331 }
332 
333 void warn1() {
334   {
335     simple_ptr<B> b(new B()); // expected-note {{in instantiation of member function 'dnvd::simple_ptr<dnvd::B>::~simple_ptr' requested here}}
336     use(*b);
337   }
338   {
339     simple_ptr2<B> b(new D()); // expected-note {{in instantiation of member function 'dnvd::simple_ptr2<dnvd::B>::~simple_ptr2' requested here}}
340     use(*b);
341   }
342   {
343     simple_ptr<D> d(new D()); // expected-note {{in instantiation of member function 'dnvd::simple_ptr<dnvd::D>::~simple_ptr' requested here}}
344     use(*d);
345   }
346 }
347 }
348 
349 namespace PR9238 {
350   class B { public: ~B(); };
351   class C : virtual B { public: ~C() { } };
352 }
353 
354 namespace PR7900 {
355   struct A { // expected-note 2{{type 'PR7900::A' is declared here}}
356   };
357   struct B : public A {
358   };
359   void foo() {
360     B b;
361     b.~B();
362     b.~A(); // expected-error{{destructor type 'PR7900::A' in object destruction expression does not match the type 'PR7900::B' of the object being destroyed}}
363     (&b)->~A(); // expected-error{{destructor type 'PR7900::A' in object destruction expression does not match the type 'PR7900::B' of the object being destroyed}}
364   }
365 }
366 
367 namespace PR16892 {
368   auto p = &A::~A; // expected-error{{taking the address of a destructor}}
369 }
370