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
3class A {
4public:
5  ~A();
6};
7
8class B {
9public:
10  ~B() { }
11};
12
13class C {
14public:
15  (~C)() { }
16};
17
18struct D {
19  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
28struct D2 {
29  void ~D2() { } //                          \
30  // expected-error{{destructor cannot have a return type}}
31};
32
33
34struct E;
35
36typedef E E_typedef;
37struct E {
38  ~E_typedef(); // expected-error{{destructor cannot be declared using a typedef 'E_typedef' (aka 'E') of the class name}}
39};
40
41struct 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}}
49~F(){} // expected-error {{destructor must be a non-static member function}}
50
51struct G {
52  ~G();
53};
54
55G::~G() { }
56
57// <rdar://problem/6841210>
58struct H {
59  ~H(void) { }
60};
61
62struct X {};
63
64struct Y {
65  ~X(); // expected-error {{expected the class name after '~' to name the enclosing class}}
66};
67
68namespace PR6421 {
69  class T; // expected-note{{forward declaration}}
70
71  class QGenericArgument // expected-note{{declared here}}
72  {
73    template<typename U>
74    void foo(T t) // expected-error{{variable has incomplete type}}
75    { }
76
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
86namespace 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
93  template<class T> class X { T v; ~X() { ++*v; } };
94  void a(X<int> x) {}
95}
96
97struct X0 { virtual ~X0() throw(); };
98struct X1 : public X0 { };
99
100// Make sure we instantiate operator deletes when building a virtual
101// destructor.
102namespace test6 {
103  template <class T> class A {
104  public:
105    void *operator new(__SIZE_TYPE__);
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
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(); };
120  B::B() {}
121}
122
123// Make sure classes are marked invalid when they have invalid
124// members.  This avoids a crash-on-invalid.
125namespace test7 {
126  struct A {
127    ~A() const; // expected-error {{'const' qualifier is not allowed on a destructor}}
128  };
129  struct B : A {};
130
131  void test() {
132    B *b;
133    b->~B();
134  }
135}
136
137namespace nonvirtualdtor {
138struct S1 { // expected-warning {{has virtual functions but non-virtual destructor}}
139  virtual void m();
140};
141
142struct S2 {
143  ~S2(); // expected-warning {{has virtual functions but non-virtual destructor}}
144  virtual void m();
145};
146
147struct S3 : public S1 {  // expected-warning {{has virtual functions but non-virtual destructor}}
148  virtual void m();
149};
150
151struct S4 : public S2 {  // expected-warning {{has virtual functions but non-virtual destructor}}
152  virtual void m();
153};
154
155struct B {
156  virtual ~B();
157  virtual void m();
158};
159
160struct S5 : public B {
161  virtual void m();
162};
163
164struct S6 {
165  virtual void m();
166private:
167  ~S6();
168};
169
170struct S7 {
171  virtual void m();
172protected:
173  ~S7();
174};
175
176struct S8 {} s8;
177
178UnknownType S8::~S8() { // expected-error {{unknown type name 'UnknownType'}}
179  s8.~S8();
180}
181
182template<class T> class TS : public B {
183  virtual void m();
184};
185
186TS<int> baz;
187
188template<class T> class TS2 { // expected-warning {{'nonvirtualdtor::TS2<int>' has virtual functions but non-virtual destructor}}
189  virtual void m();
190};
191
192TS2<int> foo; // expected-note {{instantiation}}
193}
194
195namespace dnvd { // delete-non-virtual-dtor warning
196struct NP {};
197
198struct B { // expected-warning {{has virtual functions but non-virtual destructor}}
199  virtual void foo();
200};
201
202struct D: B {}; // expected-warning {{has virtual functions but non-virtual destructor}}
203
204struct F final : B {};
205
206struct VB {
207  virtual void foo();
208  virtual ~VB();
209};
210
211struct VD: VB {};
212
213struct VF final: VB {};
214
215template <typename T>
216class simple_ptr {
217public:
218  simple_ptr(T* t): _ptr(t) {}
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}}
222  T& operator*() const { return *_ptr; }
223private:
224  T* _ptr;
225};
226
227template <typename T>
228class simple_ptr2 {
229public:
230  simple_ptr2(T* t): _ptr(t) {}
231  ~simple_ptr2() { delete _ptr; } // expected-warning {{delete called on non-final 'dnvd::B' that has virtual functions but non-virtual destructor}}
232  T& operator*() const { return *_ptr; }
233private:
234  T* _ptr;
235};
236
237void use(B&);
238void use(VB&);
239
240void 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
249void 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?
261void 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
280template <typename T>
281void nowarntemplate() {
282  {
283    T* t = new T();
284    delete t;
285  }
286  {
287    T* t = new T[4];
288    delete[] t;
289  }
290}
291
292void 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
315void 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
323void 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
338void 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
349void 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
372void 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
388namespace PR9238 {
389  class B { public: ~B(); };
390  class C : virtual B { public: ~C() { } };
391}
392
393namespace PR7900 {
394  struct A { // expected-note 2{{type 'PR7900::A' is declared here}}
395  };
396  struct B : public A {
397  };
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
406namespace PR16892 {
407  auto p = &A::~A; // expected-error{{taking the address of a destructor}}
408}
409
410namespace PR20238 {
411struct S {
412  volatile ~S() { } // expected-error{{destructor cannot have a return type}}
413};
414}
415
416namespace PR22668 {
417struct S {
418};
419void f(S s) {
420  (s.~S)();
421}
422void g(S s) {
423  (s.~S); // expected-error{{reference to destructor must be called}}
424}
425}
426
427class Invalid {
428    ~Invalid();
429    UnknownType xx; // expected-error{{unknown type name}}
430};
431
432// The constructor definition should not have errors
433Invalid::~Invalid() {}
434