1// RUN: %clang_cc1 -std=c++11 -fsyntax-only -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -verify %s
2class A {
3public:
4  ~A();
5};
6
7class B {
8public:
9  ~B() { }
10};
11
12class C {
13public:
14  (~C)() { }
15};
16
17struct 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
27struct D2 {
28  void ~D2() { } //                          \
29  // expected-error{{destructor cannot have a return type}}
30};
31
32
33struct E;
34
35typedef E E_typedef;
36struct E {
37  ~E_typedef(); // expected-error{{destructor cannot be declared using a typedef 'E_typedef' (aka 'E') of the class name}}
38};
39
40struct 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
50struct G {
51  ~G();
52};
53
54G::~G() { }
55
56// <rdar://problem/6841210>
57struct H {
58  ~H(void) { }
59};
60
61struct X {};
62
63struct Y {
64  ~X(); // expected-error {{expected the class name after '~' to name the enclosing class}}
65};
66
67namespace 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
85namespace PR6709 {
86  template<class T> class X { T v; ~X() { ++*v; } };
87  void a(X<int> x) {}
88}
89
90struct X0 { virtual ~X0() throw(); };
91struct X1 : public X0 { };
92
93// Make sure we instantiate operator deletes when building a virtual
94// destructor.
95namespace 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.
112namespace 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
124namespace nonvirtualdtor {
125struct S1 { // expected-warning {{has virtual functions but non-virtual destructor}}
126  virtual void m();
127};
128
129struct S2 {
130  ~S2(); // expected-warning {{has virtual functions but non-virtual destructor}}
131  virtual void m();
132};
133
134struct S3 : public S1 {  // expected-warning {{has virtual functions but non-virtual destructor}}
135  virtual void m();
136};
137
138struct S4 : public S2 {  // expected-warning {{has virtual functions but non-virtual destructor}}
139  virtual void m();
140};
141
142struct B {
143  virtual ~B();
144  virtual void m();
145};
146
147struct S5 : public B {
148  virtual void m();
149};
150
151struct S6 {
152  virtual void m();
153private:
154  ~S6();
155};
156
157struct S7 {
158  virtual void m();
159protected:
160  ~S7();
161};
162
163template<class T> class TS : public B {
164  virtual void m();
165};
166
167TS<int> baz;
168
169template<class T> class TS2 { // expected-warning {{'nonvirtualdtor::TS2<int>' has virtual functions but non-virtual destructor}}
170  virtual void m();
171};
172
173TS2<int> foo; // expected-note {{instantiation}}
174}
175
176namespace dnvd { // delete-non-virtual-dtor warning
177struct NP {};
178
179struct B { // expected-warning {{has virtual functions but non-virtual destructor}}
180  virtual void foo();
181};
182
183struct D: B {}; // expected-warning {{has virtual functions but non-virtual destructor}}
184
185struct F final: B {}; // expected-warning {{has virtual functions but non-virtual destructor}}
186
187struct VB {
188  virtual void foo();
189  virtual ~VB();
190};
191
192struct VD: VB {};
193
194struct VF final: VB {};
195
196template <typename T>
197class simple_ptr {
198public:
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; }
204private:
205  T* _ptr;
206};
207
208template <typename T>
209class simple_ptr2 {
210public:
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; }
214private:
215  T* _ptr;
216};
217
218void use(B&);
219void use(VB&);
220
221void 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
230void nowarnnonpoly() {
231  {
232    NP* np = new NP();
233    delete np;
234  }
235  {
236    NP* np = new NP[4];
237    delete[] np;
238  }
239}
240
241void 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
260template <typename T>
261void nowarntemplate() {
262  {
263    T* t = new T();
264    delete t;
265  }
266  {
267    T* t = new T[4];
268    delete[] t;
269  }
270}
271
272void 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
295void 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
310void 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
333void 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
349namespace PR9238 {
350  class B { public: ~B(); };
351  class C : virtual B { public: ~C() { } };
352}
353
354namespace 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