Home | History | Annotate | Download | only in SemaCXX
      1 // RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -fsyntax-only -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -fcxx-exceptions -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:
     10   ~B() { }
     11 };
     12 
     13 class C {
     14 public:
     15   (~C)() { }
     16 };
     17 
     18 struct 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 
     28 struct D2 {
     29   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}}
     49 ~F(){} // expected-error {{destructor must be a non-static member function}}
     50 
     51 struct G {
     52   ~G();
     53 };
     54 
     55 G::~G() { }
     56 
     57 // <rdar://problem/6841210>
     58 struct H {
     59   ~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>
     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 
     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
     93   template<class T> class X { T v; ~X() { ++*v; } };
     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__);
    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.
    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 
    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 struct S8 {} s8;
    177 
    178 UnknownType S8::~S8() { // expected-error {{unknown type name 'UnknownType'}}
    179   s8.~S8();
    180 }
    181 
    182 template<class T> class TS : public B {
    183   virtual void m();
    184 };
    185 
    186 TS<int> baz;
    187 
    188 template<class T> class TS2 { // expected-warning {{'nonvirtualdtor::TS2<int>' has virtual functions but non-virtual destructor}}
    189   virtual void m();
    190 };
    191 
    192 TS2<int> foo; // expected-note {{instantiation}}
    193 }
    194 
    195 namespace dnvd { // delete-non-virtual-dtor warning
    196 struct NP {};
    197 
    198 struct B { // expected-warning {{has virtual functions but non-virtual destructor}}
    199   virtual void foo();
    200 };
    201 
    202 struct D: B {}; // expected-warning {{has virtual functions but non-virtual destructor}}
    203 
    204 struct F final : B {};
    205 
    206 struct VB {
    207   virtual void foo();
    208   virtual ~VB();
    209 };
    210 
    211 struct VD: VB {};
    212 
    213 struct VF final: VB {};
    214 
    215 template <typename T>
    216 class simple_ptr {
    217 public:
    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; }
    223 private:
    224   T* _ptr;
    225 };
    226 
    227 template <typename T>
    228 class simple_ptr2 {
    229 public:
    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; }
    233 private:
    234   T* _ptr;
    235 };
    236 
    237 void use(B&);
    238 void use(VB&);
    239 
    240 void 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 
    249 void nowarnnonpoly() {
    250   {
    251     NP* np = new NP();
    252     delete np;
    253   }
    254   {
    255     NP* np = new NP[4];
    256     delete[] np;
    257   }
    258 }
    259 
    260 // FIXME: Why are these supposed to not warn?
    261 void nowarnarray() {
    262   {
    263     B* b = new B[4];
    264     delete[] b;
    265   }
    266   {
    267     D* d = new D[4];
    268     delete[] d;
    269   }
    270   {
    271     VB* vb = new VB[4];
    272     delete[] vb;
    273   }
    274   {
    275     VD* vd = new VD[4];
    276     delete[] vd;
    277   }
    278 }
    279 
    280 template <typename T>
    281 void nowarntemplate() {
    282   {
    283     T* t = new T();
    284     delete t;
    285   }
    286   {
    287     T* t = new T[4];
    288     delete[] t;
    289   }
    290 }
    291 
    292 void nowarn0() {
    293   {
    294     F* f = new F();
    295     delete f;
    296   }
    297   {
    298     VB* vb = new VB();
    299     delete vb;
    300   }
    301   {
    302     VB* vb = new VD();
    303     delete vb;
    304   }
    305   {
    306     VD* vd = new VD();
    307     delete vd;
    308   }
    309   {
    310     VF* vf = new VF();
    311     delete vf;
    312   }
    313 }
    314 
    315 void nowarn0_explicit_dtor(F* f, VB* vb, VD* vd, VF* vf) {
    316   f->~F();
    317   f->~F();
    318   vb->~VB();
    319   vd->~VD();
    320   vf->~VF();
    321 }
    322 
    323 void warn0() {
    324   {
    325     B* b = new B();
    326     delete b; // expected-warning {{delete called on non-final 'dnvd::B' that has virtual functions but non-virtual destructor}}
    327   }
    328   {
    329     B* b = new D();
    330     delete b; // expected-warning {{delete called on non-final 'dnvd::B' that has virtual functions but non-virtual destructor}}
    331   }
    332   {
    333     D* d = new D();
    334     delete d; // expected-warning {{delete called on non-final 'dnvd::D' that has virtual functions but non-virtual destructor}}
    335   }
    336 }
    337 
    338 void warn0_explicit_dtor(B* b, B& br, D* d) {
    339   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}}
    340   b->B::~B(); // No warning when the call isn't virtual.
    341 
    342   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}}
    343   br.B::~B();
    344 
    345   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}}
    346   d->D::~D();
    347 }
    348 
    349 void nowarn1() {
    350   {
    351     simple_ptr<F> f(new F());
    352     use(*f);
    353   }
    354   {
    355     simple_ptr<VB> vb(new VB());
    356     use(*vb);
    357   }
    358   {
    359     simple_ptr<VB> vb(new VD());
    360     use(*vb);
    361   }
    362   {
    363     simple_ptr<VD> vd(new VD());
    364     use(*vd);
    365   }
    366   {
    367     simple_ptr<VF> vf(new VF());
    368     use(*vf);
    369   }
    370 }
    371 
    372 void warn1() {
    373   {
    374     simple_ptr<B> b(new B()); // expected-note {{in instantiation of member function 'dnvd::simple_ptr<dnvd::B>::~simple_ptr' requested here}}
    375     use(*b);
    376   }
    377   {
    378     simple_ptr2<B> b(new D()); // expected-note {{in instantiation of member function 'dnvd::simple_ptr2<dnvd::B>::~simple_ptr2' requested here}}
    379     use(*b);
    380   }
    381   {
    382     simple_ptr<D> d(new D()); // expected-note {{in instantiation of member function 'dnvd::simple_ptr<dnvd::D>::~simple_ptr' requested here}}
    383     use(*d);
    384   }
    385 }
    386 }
    387 
    388 namespace PR9238 {
    389   class B { public: ~B(); };
    390   class C : virtual B { public: ~C() { } };
    391 }
    392 
    393 namespace PR7900 {
    394   struct A { // expected-note 2{{type 'PR7900::A' is declared here}}
    395   };
    396   struct B : public A {
    397   };
    398   void foo() {
    399     B b;
    400     b.~B();
    401     b.~A(); // expected-error{{destructor type 'PR7900::A' in object destruction expression does not match the type 'PR7900::B' of the object being destroyed}}
    402     (&b)->~A(); // expected-error{{destructor type 'PR7900::A' in object destruction expression does not match the type 'PR7900::B' of the object being destroyed}}
    403   }
    404 }
    405 
    406 namespace PR16892 {
    407   auto p = &A::~A; // expected-error{{taking the address of a destructor}}
    408 }
    409 
    410 namespace PR20238 {
    411 struct S {
    412   volatile ~S() { } // expected-error{{destructor cannot have a return type}}
    413 };
    414 }
    415 
    416 namespace PR22668 {
    417 struct S {
    418 };
    419 void f(S s) {
    420   (s.~S)();
    421 }
    422 void g(S s) {
    423   (s.~S); // expected-error{{reference to destructor must be called}}
    424 }
    425 }
    426 
    427 class Invalid {
    428     ~Invalid();
    429     UnknownType xx; // expected-error{{unknown type name}}
    430 };
    431 
    432 // The constructor definition should not have errors
    433 Invalid::~Invalid() {}
    434