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 -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 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:
    212   simple_ptr(T* t): _ptr(t) {}
    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}}
    216   T& operator*() const { return *_ptr; }
    217 private:
    218   T* _ptr;
    219 };
    220 
    221 template <typename T>
    222 class simple_ptr2 {
    223 public:
    224   simple_ptr2(T* t): _ptr(t) {}
    225   ~simple_ptr2() { delete _ptr; } // expected-warning {{delete called on 'dnvd::B' that has virtual functions but non-virtual destructor}}
    226   T& operator*() const { return *_ptr; }
    227 private:
    228   T* _ptr;
    229 };
    230 
    231 void use(B&);
    232 void use(VB&);
    233 
    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 
    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 
    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>
    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 
    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 
    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 
    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 
    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(); };
    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   };
    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 {
    386   volatile ~S() { } // expected-error{{destructor cannot have a return type}}
    387 };
    388 }
    389