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}}
88 // <rdar://problem/6841210>
96 ~X(); // expected-error {{expected the class name after '~' to name the enclosing class}}
100 class T
; // expected-note{{forward declaration}}
102 class QGenericArgument
105 void foo(T t
) // expected-error{{variable has incomplete type}}
111 bob
<QGenericArgument
>(t
); // expected-error{{undeclared identifier 'bob'}}
118 // This bug, "Clang instantiates destructor for function argument" is intended
119 // behaviour in the Microsoft ABI because the callee needs to destruct the arguments.
120 // expected-error@+3 {{indirection requires pointer operand ('int' invalid)}}
121 // expected-note@+3 {{in instantiation of member function 'PR6709::X<int>::~X' requested here}}
123 template<class T
> class X
{ T v
; ~X() { ++*v
; } };
127 struct X0
{ virtual ~X0() throw(); };
128 struct X1
: public X0
{ };
130 // Make sure we instantiate operator deletes when building a virtual
133 template <class T
> class A
{
135 void *operator new(__SIZE_TYPE__
);
136 void operator delete(void *p
) {
137 T::deleteIt(p
); // expected-error {{type 'int' cannot be used prior to '::'}}
141 // expected-note@+2 {{in instantiation of member function 'test6::A<int>::operator delete' requested here}}
147 // expected-note@+2 {{in instantiation of member function 'test6::A<int>::operator delete' requested here}}
149 class B
: A
<int> { B(); };
153 // Make sure classes are marked invalid when they have invalid
154 // members. This avoids a crash-on-invalid.
157 ~A() const; // expected-error {{'const' qualifier is not allowed on a destructor}}
167 namespace nonvirtualdtor
{
168 struct S1
{ // expected-warning {{has virtual functions but non-virtual destructor}}
173 ~S2(); // expected-warning {{has virtual functions but non-virtual destructor}}
177 struct S3
: public S1
{ // expected-warning {{has virtual functions but non-virtual destructor}}
181 struct S4
: public S2
{ // expected-warning {{has virtual functions but non-virtual destructor}}
190 struct S5
: public B
{
208 UnknownType
S8::~S8() { // expected-error {{unknown type name 'UnknownType'}}
212 template<class T
> class TS
: public B
{
218 template<class T
> class TS2
{ // expected-warning {{'nonvirtualdtor::TS2<int>' has virtual functions but non-virtual destructor}}
222 TS2
<int> foo
; // expected-note {{instantiation}}
225 namespace dnvd
{ // delete-non-virtual-dtor warning
228 struct B
{ // expected-warning {{has virtual functions but non-virtual destructor}}
232 struct D
: B
{}; // expected-warning {{has virtual functions but non-virtual destructor}}
234 struct F final
: B
{};
243 struct VF final
: VB
{};
245 template <typename T
>
248 simple_ptr2(T
* t
): _ptr(t
) {}
249 ~simple_ptr2() { delete _ptr
; } // expected-warning {{delete called on non-final 'dnvd::B' that has virtual functions but non-virtual destructor}}
250 T
& operator*() const { return *_ptr
; }
268 void nowarnnonpoly() {
279 // FIXME: Why are these supposed to not warn?
299 template <typename T
>
300 void nowarntemplate() {
334 void nowarn0_explicit_dtor(F
* f
, VB
* vb
, VD
* vd
, VF
* vf
) {
345 delete b
; // expected-warning {{delete called on non-final 'dnvd::B' that has virtual functions but non-virtual destructor}}
349 delete b
; // expected-warning {{delete called on non-final 'dnvd::B' that has virtual functions but non-virtual destructor}}
353 delete d
; // expected-warning {{delete called on non-final 'dnvd::D' that has virtual functions but non-virtual destructor}}
357 // Taken from libc++, slightly simplified.
359 struct __is_destructible_apply
{ typedef int type
; };
360 struct __two
{char __lx
[2];};
361 template <typename _Tp
>
362 struct __is_destructor_wellformed
{
363 template <typename _Tp1
>
364 static char __test(typename __is_destructible_apply
<
365 decltype(_Tp1().~_Tp1())>::type
);
366 template <typename _Tp1
>
367 static __two
__test (...);
369 static const bool value
= sizeof(__test
<_Tp
>(12)) == sizeof(char);
372 void warn0_explicit_dtor(B
* b
, B
& br
, D
* d
) {
373 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}}
374 b
->B::~B(); // No warning when the call isn't virtual.
376 // No warning in unevaluated contexts.
377 (void)__is_destructor_wellformed
<B
>::value
;
379 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}}
382 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}}
388 simple_ptr
<F
> f(new F());
392 simple_ptr
<VB
> vb(new VB());
396 simple_ptr
<VB
> vb(new VD());
400 simple_ptr
<VD
> vd(new VD());
404 simple_ptr
<VF
> vf(new VF());
408 simple_ptr
<SystemB
> sb(new SystemB());
415 simple_ptr
<B
> b(new B()); // expected-note {{in instantiation of member function 'dnvd::simple_ptr<dnvd::B>::~simple_ptr' requested here}}
419 simple_ptr2
<B
> b(new D()); // expected-note {{in instantiation of member function 'dnvd::simple_ptr2<dnvd::B>::~simple_ptr2' requested here}}
423 simple_ptr
<D
> d(new D()); // expected-note {{in instantiation of member function 'dnvd::simple_ptr<dnvd::D>::~simple_ptr' requested here}}
430 class B
{ public: ~B(); };
431 class C
: virtual B
{ public: ~C() { } };
435 struct A
{ // expected-note 2{{type 'PR7900::A' found by destructor name lookup}}
437 struct B
: public A
{
442 b
.~A(); // expected-error{{destructor type 'PR7900::A' in object destruction expression does not match the type 'PR7900::B' of the object being destroyed}}
443 (&b
)->~A(); // expected-error{{destructor type 'PR7900::A' in object destruction expression does not match the type 'PR7900::B' of the object being destroyed}}
448 auto p
= &A::~A
; // expected-error{{taking the address of a destructor}}
453 volatile ~S() { } // expected-error{{destructor cannot have a return type}}
464 (s
.~S
); // expected-error{{reference to destructor must be called}}
470 UnknownType xx
; // expected-error{{unknown type name}}
473 // The constructor definition should not have errors
474 Invalid::~Invalid() {}
477 template <typename T
>
480 operator C1
<T
>* () { return nullptr; }
486 C1::operator C1
<T
>*();
496 namespace DtorTypedef
{
499 DtorTypedef::A::~A() {}
501 // This is invalid, but compilers accept it.
503 namespace N
{ using B
= B
; }
504 N::B::~B() {} // expected-error {{destructor cannot be declared using a type alias}}
506 #pragma clang diagnostic push
507 #pragma clang diagnostic ignored "-Wdtor-typedef"
509 namespace N
{ using C
= C
; }
511 #pragma clang diagnostic pop
514 // Ignore ambiguity errors in destructor name lookup. This matches the observed
515 // behavior of ICC, and is compatible with the observed behavior of GCC (which
516 // appears to ignore lookups that result in ambiguity) and MSVC (which appears
517 // to perform the lookups in the opposite order from Clang).
519 // All compilers accept this despite it being clearly ill-formed per the
522 class Foo
{}; // expected-note {{found}}
524 class Foo
{}; // expected-note {{found}}
526 static void func(n::Foo
*p
) { p
->~Foo(); } // expected-warning {{ambiguous}}
528 // GCC rejects this case, ICC accepts, despite the class member lookup being
531 struct X
{ using T
= Z
; }; // expected-note {{found}}
532 struct Y
{ using T
= int; }; // expected-note {{found}}
534 void f(Z
*p
) { p
->~T(); } // expected-warning {{ambiguous}}
536 // GCC accepts this and ignores the ambiguous class member lookup.
538 // FIXME: We should warn on the ambiguity here too, but that requires us to
539 // keep doing lookups after we've already found the type we want.
541 void g(Z
*p
) { p
->~T(); }
543 // ICC accepts this and ignores the ambiguous unqualified lookup.
545 namespace { using U
= Q
; } // expected-note {{candidate}} expected-note {{found}}
546 using U
= int; // expected-note {{candidate}} expected-note {{found}}
547 void f(Q
*p
) { p
->~U(); } // expected-warning {{ambiguous}}
549 // We still diagnose if the unqualified lookup is dependent, though.
550 template<typename T
> void f(T
*p
) { p
->~U(); } // expected-error {{ambiguous}}
553 #endif // BE_THE_HEADER