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
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
260void nowarnarray() {
261  {
262    B* b = new B[4];
263    delete[] b;
264  }
265  {
266    D* d = new D[4];
267    delete[] d;
268  }
269  {
270    VB* vb = new VB[4];
271    delete[] vb;
272  }
273  {
274    VD* vd = new VD[4];
275    delete[] vd;
276  }
277}
278
279template <typename T>
280void nowarntemplate() {
281  {
282    T* t = new T();
283    delete t;
284  }
285  {
286    T* t = new T[4];
287    delete[] t;
288  }
289}
290
291void nowarn0() {
292  {
293    F* f = new F();
294    delete f;
295  }
296  {
297    VB* vb = new VB();
298    delete vb;
299  }
300  {
301    VB* vb = new VD();
302    delete vb;
303  }
304  {
305    VD* vd = new VD();
306    delete vd;
307  }
308  {
309    VF* vf = new VF();
310    delete vf;
311  }
312}
313
314void warn0() {
315  {
316    B* b = new B();
317    delete b; // expected-warning {{delete called on non-final 'dnvd::B' that has virtual functions but non-virtual destructor}}
318  }
319  {
320    B* b = new D();
321    delete b; // expected-warning {{delete called on non-final 'dnvd::B' that has virtual functions but non-virtual destructor}}
322  }
323  {
324    D* d = new D();
325    delete d; // expected-warning {{delete called on non-final 'dnvd::D' that has virtual functions but non-virtual destructor}}
326  }
327}
328
329void nowarn1() {
330  {
331    simple_ptr<F> f(new F());
332    use(*f);
333  }
334  {
335    simple_ptr<VB> vb(new VB());
336    use(*vb);
337  }
338  {
339    simple_ptr<VB> vb(new VD());
340    use(*vb);
341  }
342  {
343    simple_ptr<VD> vd(new VD());
344    use(*vd);
345  }
346  {
347    simple_ptr<VF> vf(new VF());
348    use(*vf);
349  }
350}
351
352void warn1() {
353  {
354    simple_ptr<B> b(new B()); // expected-note {{in instantiation of member function 'dnvd::simple_ptr<dnvd::B>::~simple_ptr' requested here}}
355    use(*b);
356  }
357  {
358    simple_ptr2<B> b(new D()); // expected-note {{in instantiation of member function 'dnvd::simple_ptr2<dnvd::B>::~simple_ptr2' requested here}}
359    use(*b);
360  }
361  {
362    simple_ptr<D> d(new D()); // expected-note {{in instantiation of member function 'dnvd::simple_ptr<dnvd::D>::~simple_ptr' requested here}}
363    use(*d);
364  }
365}
366}
367
368namespace PR9238 {
369  class B { public: ~B(); };
370  class C : virtual B { public: ~C() { } };
371}
372
373namespace PR7900 {
374  struct A { // expected-note 2{{type 'PR7900::A' is declared here}}
375  };
376  struct B : public A {
377  };
378  void foo() {
379    B b;
380    b.~B();
381    b.~A(); // expected-error{{destructor type 'PR7900::A' in object destruction expression does not match the type 'PR7900::B' of the object being destroyed}}
382    (&b)->~A(); // expected-error{{destructor type 'PR7900::A' in object destruction expression does not match the type 'PR7900::B' of the object being destroyed}}
383  }
384}
385
386namespace PR16892 {
387  auto p = &A::~A; // expected-error{{taking the address of a destructor}}
388}
389
390namespace PR20238 {
391struct S {
392  volatile ~S() { } // expected-error{{destructor cannot have a return type}}
393};
394}
395
396namespace PR22668 {
397struct S {
398};
399void f(S s) {
400  (s.~S)();
401}
402void g(S s) {
403  (s.~S); // expected-error{{reference to destructor must be called}}
404}
405}
406