1// RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -fsyntax-only -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -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
176template<class T> class TS : public B {
177  virtual void m();
178};
179
180TS<int> baz;
181
182template<class T> class TS2 { // expected-warning {{'nonvirtualdtor::TS2<int>' has virtual functions but non-virtual destructor}}
183  virtual void m();
184};
185
186TS2<int> foo; // expected-note {{instantiation}}
187}
188
189namespace dnvd { // delete-non-virtual-dtor warning
190struct NP {};
191
192struct B { // expected-warning {{has virtual functions but non-virtual destructor}}
193  virtual void foo();
194};
195
196struct D: B {}; // expected-warning {{has virtual functions but non-virtual destructor}}
197
198struct F final : B {};
199
200struct VB {
201  virtual void foo();
202  virtual ~VB();
203};
204
205struct VD: VB {};
206
207struct VF final: VB {};
208
209template <typename T>
210class simple_ptr {
211public:
212  simple_ptr(T* t): _ptr(t) {}
213  ~simple_ptr() { delete _ptr; } // \
214    // expected-warning {{delete called on 'dnvd::B' that has virtual functions but non-virtual destructor}} \
215    // expected-warning {{delete called on 'dnvd::D' that has virtual functions but non-virtual destructor}}
216  T& operator*() const { return *_ptr; }
217private:
218  T* _ptr;
219};
220
221template <typename T>
222class simple_ptr2 {
223public:
224  simple_ptr2(T* t): _ptr(t) {}
225  ~simple_ptr2() { delete _ptr; } // expected-warning {{delete called on 'dnvd::B' that has virtual functions but non-virtual destructor}}
226  T& operator*() const { return *_ptr; }
227private:
228  T* _ptr;
229};
230
231void use(B&);
232void use(VB&);
233
234void nowarnstack() {
235  B b; use(b);
236  D d; use(d);
237  F f; use(f);
238  VB vb; use(vb);
239  VD vd; use(vd);
240  VF vf; use(vf);
241}
242
243void nowarnnonpoly() {
244  {
245    NP* np = new NP();
246    delete np;
247  }
248  {
249    NP* np = new NP[4];
250    delete[] np;
251  }
252}
253
254void nowarnarray() {
255  {
256    B* b = new B[4];
257    delete[] b;
258  }
259  {
260    D* d = new D[4];
261    delete[] d;
262  }
263  {
264    VB* vb = new VB[4];
265    delete[] vb;
266  }
267  {
268    VD* vd = new VD[4];
269    delete[] vd;
270  }
271}
272
273template <typename T>
274void nowarntemplate() {
275  {
276    T* t = new T();
277    delete t;
278  }
279  {
280    T* t = new T[4];
281    delete[] t;
282  }
283}
284
285void nowarn0() {
286  {
287    F* f = new F();
288    delete f;
289  }
290  {
291    VB* vb = new VB();
292    delete vb;
293  }
294  {
295    VB* vb = new VD();
296    delete vb;
297  }
298  {
299    VD* vd = new VD();
300    delete vd;
301  }
302  {
303    VF* vf = new VF();
304    delete vf;
305  }
306}
307
308void warn0() {
309  {
310    B* b = new B();
311    delete b; // expected-warning {{delete called on 'dnvd::B' that has virtual functions but non-virtual destructor}}
312  }
313  {
314    B* b = new D();
315    delete b; // expected-warning {{delete called on 'dnvd::B' that has virtual functions but non-virtual destructor}}
316  }
317  {
318    D* d = new D();
319    delete d; // expected-warning {{delete called on 'dnvd::D' that has virtual functions but non-virtual destructor}}
320  }
321}
322
323void nowarn1() {
324  {
325    simple_ptr<F> f(new F());
326    use(*f);
327  }
328  {
329    simple_ptr<VB> vb(new VB());
330    use(*vb);
331  }
332  {
333    simple_ptr<VB> vb(new VD());
334    use(*vb);
335  }
336  {
337    simple_ptr<VD> vd(new VD());
338    use(*vd);
339  }
340  {
341    simple_ptr<VF> vf(new VF());
342    use(*vf);
343  }
344}
345
346void warn1() {
347  {
348    simple_ptr<B> b(new B()); // expected-note {{in instantiation of member function 'dnvd::simple_ptr<dnvd::B>::~simple_ptr' requested here}}
349    use(*b);
350  }
351  {
352    simple_ptr2<B> b(new D()); // expected-note {{in instantiation of member function 'dnvd::simple_ptr2<dnvd::B>::~simple_ptr2' requested here}}
353    use(*b);
354  }
355  {
356    simple_ptr<D> d(new D()); // expected-note {{in instantiation of member function 'dnvd::simple_ptr<dnvd::D>::~simple_ptr' requested here}}
357    use(*d);
358  }
359}
360}
361
362namespace PR9238 {
363  class B { public: ~B(); };
364  class C : virtual B { public: ~C() { } };
365}
366
367namespace PR7900 {
368  struct A { // expected-note 2{{type 'PR7900::A' is declared here}}
369  };
370  struct B : public A {
371  };
372  void foo() {
373    B b;
374    b.~B();
375    b.~A(); // expected-error{{destructor type 'PR7900::A' in object destruction expression does not match the type 'PR7900::B' of the object being destroyed}}
376    (&b)->~A(); // expected-error{{destructor type 'PR7900::A' in object destruction expression does not match the type 'PR7900::B' of the object being destroyed}}
377  }
378}
379
380namespace PR16892 {
381  auto p = &A::~A; // expected-error{{taking the address of a destructor}}
382}
383
384namespace PR20238 {
385struct S {
386  volatile ~S() { } // expected-error{{destructor cannot have a return type}}
387};
388}
389