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
3 class A {
4 public:
5 ~A();
6 };
7
8 class B {
9 public:
~B()10 ~B() { }
11 };
12
13 class C {
14 public:
15 (~C)() { }
16 };
17
18 struct D {
~DD19 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
28 struct D2 {
~D2D229 void ~D2() { } // \
30 // expected-error{{destructor cannot have a return type}}
31 };
32
33
34 struct E;
35
36 typedef E E_typedef;
37 struct E {
38 ~E_typedef(); // expected-error{{destructor cannot be declared using a typedef 'E_typedef' (aka 'E') of the class name}}
39 };
40
41 struct 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}}
~F()49 ~F(){} // expected-error {{destructor must be a non-static member function}}
50
51 struct G {
52 ~G();
53 };
54
~G()55 G::~G() { }
56
57 // <rdar://problem/6841210>
58 struct H {
~HH59 ~H(void) { }
60 };
61
62 struct X {};
63
64 struct Y {
65 ~X(); // expected-error {{expected the class name after '~' to name the enclosing class}}
66 };
67
68 namespace PR6421 {
69 class T; // expected-note{{forward declaration}}
70
71 class QGenericArgument // expected-note{{declared here}}
72 {
73 template<typename U>
foo(T t)74 void foo(T t) // expected-error{{variable has incomplete type}}
75 { }
76
disconnect()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
86 namespace 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
~X()93 template<class T> class X { T v; ~X() { ++*v; } };
a(X<int> x)94 void a(X<int> x) {}
95 }
96
97 struct X0 { virtual ~X0() throw(); };
98 struct X1 : public X0 { };
99
100 // Make sure we instantiate operator deletes when building a virtual
101 // destructor.
102 namespace test6 {
103 template <class T> class A {
104 public:
105 void *operator new(__SIZE_TYPE__);
operator delete(void * p)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
~A()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(); };
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.
125 namespace test7 {
126 struct A {
127 ~A() const; // expected-error {{'const' qualifier is not allowed on a destructor}}
128 };
129 struct B : A {};
130
test()131 void test() {
132 B *b;
133 b->~B();
134 }
135 }
136
137 namespace nonvirtualdtor {
138 struct S1 { // expected-warning {{has virtual functions but non-virtual destructor}}
139 virtual void m();
140 };
141
142 struct S2 {
143 ~S2(); // expected-warning {{has virtual functions but non-virtual destructor}}
144 virtual void m();
145 };
146
147 struct S3 : public S1 { // expected-warning {{has virtual functions but non-virtual destructor}}
148 virtual void m();
149 };
150
151 struct S4 : public S2 { // expected-warning {{has virtual functions but non-virtual destructor}}
152 virtual void m();
153 };
154
155 struct B {
156 virtual ~B();
157 virtual void m();
158 };
159
160 struct S5 : public B {
161 virtual void m();
162 };
163
164 struct S6 {
165 virtual void m();
166 private:
167 ~S6();
168 };
169
170 struct S7 {
171 virtual void m();
172 protected:
173 ~S7();
174 };
175
176 template<class T> class TS : public B {
177 virtual void m();
178 };
179
180 TS<int> baz;
181
182 template<class T> class TS2 { // expected-warning {{'nonvirtualdtor::TS2<int>' has virtual functions but non-virtual destructor}}
183 virtual void m();
184 };
185
186 TS2<int> foo; // expected-note {{instantiation}}
187 }
188
189 namespace dnvd { // delete-non-virtual-dtor warning
190 struct NP {};
191
192 struct B { // expected-warning {{has virtual functions but non-virtual destructor}}
193 virtual void foo();
194 };
195
196 struct D: B {}; // expected-warning {{has virtual functions but non-virtual destructor}}
197
198 struct F final : B {};
199
200 struct VB {
201 virtual void foo();
202 virtual ~VB();
203 };
204
205 struct VD: VB {};
206
207 struct VF final: VB {};
208
209 template <typename T>
210 class simple_ptr {
211 public:
simple_ptr(T * t)212 simple_ptr(T* t): _ptr(t) {}
~simple_ptr()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}}
operator *() const216 T& operator*() const { return *_ptr; }
217 private:
218 T* _ptr;
219 };
220
221 template <typename T>
222 class simple_ptr2 {
223 public:
simple_ptr2(T * t)224 simple_ptr2(T* t): _ptr(t) {}
~simple_ptr2()225 ~simple_ptr2() { delete _ptr; } // expected-warning {{delete called on 'dnvd::B' that has virtual functions but non-virtual destructor}}
operator *() const226 T& operator*() const { return *_ptr; }
227 private:
228 T* _ptr;
229 };
230
231 void use(B&);
232 void use(VB&);
233
nowarnstack()234 void 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
nowarnnonpoly()243 void nowarnnonpoly() {
244 {
245 NP* np = new NP();
246 delete np;
247 }
248 {
249 NP* np = new NP[4];
250 delete[] np;
251 }
252 }
253
nowarnarray()254 void 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
273 template <typename T>
nowarntemplate()274 void nowarntemplate() {
275 {
276 T* t = new T();
277 delete t;
278 }
279 {
280 T* t = new T[4];
281 delete[] t;
282 }
283 }
284
nowarn0()285 void 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
warn0()308 void 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
nowarn1()323 void 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
warn1()346 void 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
362 namespace PR9238 {
363 class B { public: ~B(); };
~C()364 class C : virtual B { public: ~C() { } };
365 }
366
367 namespace PR7900 {
368 struct A { // expected-note 2{{type 'PR7900::A' is declared here}}
369 };
370 struct B : public A {
371 };
foo()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
380 namespace PR16892 {
381 auto p = &A::~A; // expected-error{{taking the address of a destructor}}
382 }
383
384 namespace PR20238 {
385 struct S {
~SPR20238::S386 volatile ~S() { } // expected-error{{destructor cannot have a return type}}
387 };
388 }
389