1 // RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -fsyntax-only -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -fcxx-exceptions -verify %s -pedantic
2 // RUN: %clang_cc1 -std=c++11 -triple %ms_abi_triple -DMSABI -fsyntax-only -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -verify %s -pedantic
4 #if defined(BE_THE_HEADER)
6 // Wdelete-non-virtual-dtor should warn about the delete from smart pointer
7 // classes in system headers (std::unique_ptr...) too.
9 #pragma clang system_header
19 simple_ptr(T
* t
): _ptr(t
) {}
20 ~simple_ptr() { delete _ptr
; } // \
21 // expected-warning {{delete called on non-final 'dnvd::B' that has virtual functions but non-virtual destructor}} \
22 // expected-warning {{delete called on non-final 'dnvd::D' that has virtual functions but non-virtual destructor}}
23 T
& operator*() const { return *_ptr
; }
50 static void ~D(int, ...) const { } // \
51 // expected-error{{static member function cannot have 'const' qualifier}} \
52 // expected-error{{destructor cannot be declared 'static'}} \
53 // expected-error{{destructor cannot have any parameters}} \
54 // expected-error{{destructor cannot be variadic}} \
55 // expected-error{{destructor cannot have a return type}} \
56 // expected-error{{'const' qualifier is not allowed on a destructor}}
61 // expected-error{{destructor cannot have a return type}}
69 ~E_typedef(); // expected-error{{destructor cannot be declared using a typedef 'E_typedef' (aka 'E') of the class name}}
73 (~F
)(); // expected-note {{previous declaration is here}}
74 ~F(); // expected-error {{destructor cannot be redeclared}}
77 ~; // expected-error {{expected a class name after '~' to name a destructor}}
78 ~undef(); // expected-error {{undeclared identifier 'undef' in destructor name}}
79 ~operator+(int, int); // expected-error {{expected a class name after '~' to name a destructor}}
80 ~F(){} // expected-error {{destructor must be a non-static member function}}
95 ~X(); // expected-error {{expected the class name after '~' to name the enclosing class}}
99 class T
; // expected-note{{forward declaration}}
101 class QGenericArgument
104 void foo(T t
) // expected-error{{variable has incomplete type}}
110 bob
<QGenericArgument
>(t
); // expected-error{{undeclared identifier 'bob'}}
117 // This bug, "Clang instantiates destructor for function argument" is intended
118 // behaviour in the Microsoft ABI because the callee needs to destruct the arguments.
119 // expected-error@+3 {{indirection requires pointer operand ('int' invalid)}}
120 // expected-note@+3 {{in instantiation of member function 'PR6709::X<int>::~X' requested here}}
122 template<class T
> class X
{ T v
; ~X() { ++*v
; } };
126 struct X0
{ virtual ~X0() throw(); };
127 struct X1
: public X0
{ };
129 // Make sure we instantiate operator deletes when building a virtual
132 template <class T
> class A
{
134 void *operator new(__SIZE_TYPE__
);
135 void operator delete(void *p
) {
136 T::deleteIt(p
); // expected-error {{type 'int' cannot be used prior to '::'}}
140 // expected-note@+2 {{in instantiation of member function 'test6::A<int>::operator delete' requested here}}
146 // expected-note@+2 {{in instantiation of member function 'test6::A<int>::operator delete' requested here}}
148 class B
: A
<int> { B(); };
152 // Make sure classes are marked invalid when they have invalid
153 // members. This avoids a crash-on-invalid.
156 ~A() const; // expected-error {{'const' qualifier is not allowed on a destructor}}
166 namespace nonvirtualdtor
{
167 struct S1
{ // expected-warning {{has virtual functions but non-virtual destructor}}
172 ~S2(); // expected-warning {{has virtual functions but non-virtual destructor}}
176 struct S3
: public S1
{ // expected-warning {{has virtual functions but non-virtual destructor}}
180 struct S4
: public S2
{ // expected-warning {{has virtual functions but non-virtual destructor}}
189 struct S5
: public B
{
207 UnknownType
S8::~S8() { // expected-error {{unknown type name 'UnknownType'}}
211 template<class T
> class TS
: public B
{
217 template<class T
> class TS2
{ // expected-warning {{'nonvirtualdtor::TS2<int>' has virtual functions but non-virtual destructor}}
221 TS2
<int> foo
; // expected-note {{instantiation}}
224 namespace dnvd
{ // delete-non-virtual-dtor warning
227 struct B
{ // expected-warning {{has virtual functions but non-virtual destructor}}
231 struct D
: B
{}; // expected-warning {{has virtual functions but non-virtual destructor}}
233 struct F final
: B
{};
242 struct VF final
: VB
{};
244 template <typename T
>
247 simple_ptr2(T
* t
): _ptr(t
) {}
248 ~simple_ptr2() { delete _ptr
; } // expected-warning {{delete called on non-final 'dnvd::B' that has virtual functions but non-virtual destructor}}
249 T
& operator*() const { return *_ptr
; }
267 void nowarnnonpoly() {
278 // FIXME: Why are these supposed to not warn?
298 template <typename T
>
299 void nowarntemplate() {
333 void nowarn0_explicit_dtor(F
* f
, VB
* vb
, VD
* vd
, VF
* vf
) {
344 delete b
; // expected-warning {{delete called on non-final 'dnvd::B' that has virtual functions but non-virtual destructor}}
348 delete b
; // expected-warning {{delete called on non-final 'dnvd::B' that has virtual functions but non-virtual destructor}}
352 delete d
; // expected-warning {{delete called on non-final 'dnvd::D' that has virtual functions but non-virtual destructor}}
356 // Taken from libc++, slightly simplified.
358 struct __is_destructible_apply
{ typedef int type
; };
359 struct __two
{char __lx
[2];};
360 template <typename _Tp
>
361 struct __is_destructor_wellformed
{
362 template <typename _Tp1
>
363 static char __test(typename __is_destructible_apply
<
364 decltype(_Tp1().~_Tp1())>::type
);
365 template <typename _Tp1
>
366 static __two
__test (...);
368 static const bool value
= sizeof(__test
<_Tp
>(12)) == sizeof(char);
371 void warn0_explicit_dtor(B
* b
, B
& br
, D
* d
) {
372 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}}
373 b
->B::~B(); // No warning when the call isn't virtual.
375 // No warning in unevaluated contexts.
376 (void)__is_destructor_wellformed
<B
>::value
;
378 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}}
381 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}}
387 simple_ptr
<F
> f(new F());
391 simple_ptr
<VB
> vb(new VB());
395 simple_ptr
<VB
> vb(new VD());
399 simple_ptr
<VD
> vd(new VD());
403 simple_ptr
<VF
> vf(new VF());
407 simple_ptr
<SystemB
> sb(new SystemB());
414 simple_ptr
<B
> b(new B()); // expected-note {{in instantiation of member function 'dnvd::simple_ptr<dnvd::B>::~simple_ptr' requested here}}
418 simple_ptr2
<B
> b(new D()); // expected-note {{in instantiation of member function 'dnvd::simple_ptr2<dnvd::B>::~simple_ptr2' requested here}}
422 simple_ptr
<D
> d(new D()); // expected-note {{in instantiation of member function 'dnvd::simple_ptr<dnvd::D>::~simple_ptr' requested here}}
429 class B
{ public: ~B(); };
430 class C
: virtual B
{ public: ~C() { } };
434 struct A
{ // expected-note 2{{type 'PR7900::A' found by destructor name lookup}}
436 struct B
: public A
{
441 b
.~A(); // expected-error{{destructor type 'PR7900::A' in object destruction expression does not match the type 'B' of the object being destroyed}}
442 (&b
)->~A(); // expected-error{{destructor type 'PR7900::A' in object destruction expression does not match the type 'B' of the object being destroyed}}
447 auto p
= &A::~A
; // expected-error{{taking the address of a destructor}}
452 volatile ~S() { } // expected-error{{destructor cannot have a return type}}
463 (s
.~S
); // expected-error{{reference to destructor must be called}}
469 UnknownType xx
; // expected-error{{unknown type name}}
472 // The constructor definition should not have errors
473 Invalid::~Invalid() {}
476 template <typename T
>
479 operator C1
<T
>* () { return nullptr; }
485 C1::operator C1
<T
>*();
495 namespace DtorTypedef
{
498 DtorTypedef::A::~A() {}
500 // This is invalid, but compilers accept it.
502 namespace N
{ using B
= B
; }
503 N::B::~B() {} // expected-error {{destructor cannot be declared using a type alias}}
505 #pragma clang diagnostic push
506 #pragma clang diagnostic ignored "-Wdtor-typedef"
508 namespace N
{ using C
= C
; }
510 #pragma clang diagnostic pop
513 // Ignore ambiguity errors in destructor name lookup. This matches the observed
514 // behavior of ICC, and is compatible with the observed behavior of GCC (which
515 // appears to ignore lookups that result in ambiguity) and MSVC (which appears
516 // to perform the lookups in the opposite order from Clang).
518 // All compilers accept this despite it being clearly ill-formed per the
521 class Foo
{}; // expected-note {{found}}
523 class Foo
{}; // expected-note {{found}}
525 static void func(n::Foo
*p
) { p
->~Foo(); } // expected-warning {{ambiguous}}
527 // GCC rejects this case, ICC accepts, despite the class member lookup being
530 struct X
{ using T
= Z
; }; // expected-note {{found}}
531 struct Y
{ using T
= int; }; // expected-note {{found}}
533 void f(Z
*p
) { p
->~T(); } // expected-warning {{ambiguous}}
535 // GCC accepts this and ignores the ambiguous class member lookup.
537 // FIXME: We should warn on the ambiguity here too, but that requires us to
538 // keep doing lookups after we've already found the type we want.
540 void g(Z
*p
) { p
->~T(); }
542 // ICC accepts this and ignores the ambiguous unqualified lookup.
544 namespace { using U
= Q
; } // expected-note {{candidate}} expected-note {{found}}
545 using U
= int; // expected-note {{candidate}} expected-note {{found}}
546 void f(Q
*p
) { p
->~U(); } // expected-warning {{ambiguous}}
548 // We still diagnose if the unqualified lookup is dependent, though.
549 template<typename T
> void f(T
*p
) { p
->~U(); } // expected-error {{ambiguous}}
552 namespace crash_on_invalid_base_dtor
{
556 struct Baz
: public Test
{ // expected-warning {{non-virtual destructor}}
558 ~Baz() = defaul
; // expected-error {{undeclared identifier 'defaul'}} \
559 // expected-error {{initializer on function}} \
560 // expected-note {{overridden virtual function is here}}
562 struct Foo
: public Baz
{ // expected-error {{cannot override a non-deleted function}} \
563 // expected-note {{destructor of 'Foo' is implicitly deleted}}
568 #endif // BE_THE_HEADER