1*61e7adefSGabor Horvath // RUN: %clang_cc1 -analyze -analyzer-checker=alpha.cplusplus.DeleteWithNonVirtualDtor -std=c++11 -verify -analyzer-output=text %s 2*61e7adefSGabor Horvath 3*61e7adefSGabor Horvath struct Virtual { ~VirtualVirtual4*61e7adefSGabor Horvath virtual ~Virtual() {} 5*61e7adefSGabor Horvath }; 6*61e7adefSGabor Horvath 7*61e7adefSGabor Horvath struct VDerived : public Virtual {}; 8*61e7adefSGabor Horvath 9*61e7adefSGabor Horvath struct NonVirtual { ~NonVirtualNonVirtual10*61e7adefSGabor Horvath ~NonVirtual() {} 11*61e7adefSGabor Horvath }; 12*61e7adefSGabor Horvath 13*61e7adefSGabor Horvath struct NVDerived : public NonVirtual {}; 14*61e7adefSGabor Horvath struct NVDoubleDerived : public NVDerived {}; 15*61e7adefSGabor Horvath 16*61e7adefSGabor Horvath struct Base { 17*61e7adefSGabor Horvath virtual void destroy() = 0; 18*61e7adefSGabor Horvath }; 19*61e7adefSGabor Horvath 20*61e7adefSGabor Horvath class PrivateDtor final : public Base { 21*61e7adefSGabor Horvath public: destroy()22*61e7adefSGabor Horvath void destroy() { delete this; } 23*61e7adefSGabor Horvath private: ~PrivateDtor()24*61e7adefSGabor Horvath ~PrivateDtor() {} 25*61e7adefSGabor Horvath }; 26*61e7adefSGabor Horvath 27*61e7adefSGabor Horvath struct ImplicitNV { 28*61e7adefSGabor Horvath virtual void f(); 29*61e7adefSGabor Horvath }; 30*61e7adefSGabor Horvath 31*61e7adefSGabor Horvath struct ImplicitNVDerived : public ImplicitNV {}; 32*61e7adefSGabor Horvath 33*61e7adefSGabor Horvath NVDerived *get(); 34*61e7adefSGabor Horvath create()35*61e7adefSGabor HorvathNonVirtual *create() { 36*61e7adefSGabor Horvath NonVirtual *x = new NVDerived(); // expected-note{{Conversion from derived to base happened here}} 37*61e7adefSGabor Horvath return x; 38*61e7adefSGabor Horvath } 39*61e7adefSGabor Horvath sink(NonVirtual * x)40*61e7adefSGabor Horvathvoid sink(NonVirtual *x) { 41*61e7adefSGabor Horvath delete x; // expected-warning{{Destruction of a polymorphic object with no virtual destructor}} 42*61e7adefSGabor Horvath // expected-note@-1{{Destruction of a polymorphic object with no virtual destructor}} 43*61e7adefSGabor Horvath } 44*61e7adefSGabor Horvath sinkCast(NonVirtual * y)45*61e7adefSGabor Horvathvoid sinkCast(NonVirtual *y) { 46*61e7adefSGabor Horvath delete reinterpret_cast<NVDerived*>(y); 47*61e7adefSGabor Horvath } 48*61e7adefSGabor Horvath sinkParamCast(NVDerived * z)49*61e7adefSGabor Horvathvoid sinkParamCast(NVDerived *z) { 50*61e7adefSGabor Horvath delete z; 51*61e7adefSGabor Horvath } 52*61e7adefSGabor Horvath singleDerived()53*61e7adefSGabor Horvathvoid singleDerived() { 54*61e7adefSGabor Horvath NonVirtual *sd; 55*61e7adefSGabor Horvath sd = new NVDerived(); // expected-note{{Conversion from derived to base happened here}} 56*61e7adefSGabor Horvath delete sd; // expected-warning{{Destruction of a polymorphic object with no virtual destructor}} 57*61e7adefSGabor Horvath // expected-note@-1{{Destruction of a polymorphic object with no virtual destructor}} 58*61e7adefSGabor Horvath } 59*61e7adefSGabor Horvath singleDerivedArr()60*61e7adefSGabor Horvathvoid singleDerivedArr() { 61*61e7adefSGabor Horvath NonVirtual *sda = new NVDerived[5]; // expected-note{{Conversion from derived to base happened here}} 62*61e7adefSGabor Horvath delete[] sda; // expected-warning{{Destruction of a polymorphic object with no virtual destructor}} 63*61e7adefSGabor Horvath // expected-note@-1{{Destruction of a polymorphic object with no virtual destructor}} 64*61e7adefSGabor Horvath } 65*61e7adefSGabor Horvath doubleDerived()66*61e7adefSGabor Horvathvoid doubleDerived() { 67*61e7adefSGabor Horvath NonVirtual *dd = new NVDoubleDerived(); // expected-note{{Conversion from derived to base happened here}} 68*61e7adefSGabor Horvath delete (dd); // expected-warning{{Destruction of a polymorphic object with no virtual destructor}} 69*61e7adefSGabor Horvath // expected-note@-1{{Destruction of a polymorphic object with no virtual destructor}} 70*61e7adefSGabor Horvath } 71*61e7adefSGabor Horvath assignThroughFunction()72*61e7adefSGabor Horvathvoid assignThroughFunction() { 73*61e7adefSGabor Horvath NonVirtual *atf = get(); // expected-note{{Conversion from derived to base happened here}} 74*61e7adefSGabor Horvath delete atf; // expected-warning{{Destruction of a polymorphic object with no virtual destructor}} 75*61e7adefSGabor Horvath // expected-note@-1{{Destruction of a polymorphic object with no virtual destructor}} 76*61e7adefSGabor Horvath } 77*61e7adefSGabor Horvath assignThroughFunction2()78*61e7adefSGabor Horvathvoid assignThroughFunction2() { 79*61e7adefSGabor Horvath NonVirtual *atf2; 80*61e7adefSGabor Horvath atf2 = get(); // expected-note{{Conversion from derived to base happened here}} 81*61e7adefSGabor Horvath delete atf2; // expected-warning{{Destruction of a polymorphic object with no virtual destructor}} 82*61e7adefSGabor Horvath // expected-note@-1{{Destruction of a polymorphic object with no virtual destructor}} 83*61e7adefSGabor Horvath } 84*61e7adefSGabor Horvath createThroughFunction()85*61e7adefSGabor Horvathvoid createThroughFunction() { 86*61e7adefSGabor Horvath NonVirtual *ctf = create(); // expected-note{{Calling 'create'}} 87*61e7adefSGabor Horvath // expected-note@-1{{Returning from 'create'}} 88*61e7adefSGabor Horvath delete ctf; // expected-warning {{Destruction of a polymorphic object with no virtual destructor}} 89*61e7adefSGabor Horvath // expected-note@-1{{Destruction of a polymorphic object with no virtual destructor}} 90*61e7adefSGabor Horvath } 91*61e7adefSGabor Horvath deleteThroughFunction()92*61e7adefSGabor Horvathvoid deleteThroughFunction() { 93*61e7adefSGabor Horvath NonVirtual *dtf = new NVDerived(); // expected-note{{Conversion from derived to base happened here}} 94*61e7adefSGabor Horvath sink(dtf); // expected-note{{Calling 'sink'}} 95*61e7adefSGabor Horvath } 96*61e7adefSGabor Horvath singleCastCStyle()97*61e7adefSGabor Horvathvoid singleCastCStyle() { 98*61e7adefSGabor Horvath NVDerived *sccs = new NVDerived(); 99*61e7adefSGabor Horvath NonVirtual *sccs2 = (NonVirtual*)sccs; // expected-note{{Conversion from derived to base happened here}} 100*61e7adefSGabor Horvath delete sccs2; // expected-warning{{Destruction of a polymorphic object with no virtual destructor}} 101*61e7adefSGabor Horvath // expected-note@-1{{Destruction of a polymorphic object with no virtual destructor}} 102*61e7adefSGabor Horvath } 103*61e7adefSGabor Horvath doubleCastCStyle()104*61e7adefSGabor Horvathvoid doubleCastCStyle() { 105*61e7adefSGabor Horvath NonVirtual *dccs = new NVDerived(); 106*61e7adefSGabor Horvath NVDerived *dccs2 = (NVDerived*)dccs; 107*61e7adefSGabor Horvath dccs = (NonVirtual*)dccs2; // expected-note{{Conversion from derived to base happened here}} 108*61e7adefSGabor Horvath delete dccs; // expected-warning{{Destruction of a polymorphic object with no virtual destructor}} 109*61e7adefSGabor Horvath // expected-note@-1{{Destruction of a polymorphic object with no virtual destructor}} 110*61e7adefSGabor Horvath } 111*61e7adefSGabor Horvath singleCast()112*61e7adefSGabor Horvathvoid singleCast() { 113*61e7adefSGabor Horvath NVDerived *sc = new NVDerived(); 114*61e7adefSGabor Horvath NonVirtual *sc2 = reinterpret_cast<NonVirtual*>(sc); // expected-note{{Conversion from derived to base happened here}} 115*61e7adefSGabor Horvath delete sc2; // expected-warning{{Destruction of a polymorphic object with no virtual destructor}} 116*61e7adefSGabor Horvath // expected-note@-1{{Destruction of a polymorphic object with no virtual destructor}} 117*61e7adefSGabor Horvath } 118*61e7adefSGabor Horvath doubleCast()119*61e7adefSGabor Horvathvoid doubleCast() { 120*61e7adefSGabor Horvath NonVirtual *dd = new NVDerived(); 121*61e7adefSGabor Horvath NVDerived *dd2 = reinterpret_cast<NVDerived*>(dd); 122*61e7adefSGabor Horvath dd = reinterpret_cast<NonVirtual*>(dd2); // expected-note {{Conversion from derived to base happened here}} 123*61e7adefSGabor Horvath delete dd; // expected-warning {{Destruction of a polymorphic object with no virtual destructor}} 124*61e7adefSGabor Horvath // expected-note@-1{{Destruction of a polymorphic object with no virtual destructor}} 125*61e7adefSGabor Horvath } 126*61e7adefSGabor Horvath implicitNV()127*61e7adefSGabor Horvathvoid implicitNV() { 128*61e7adefSGabor Horvath ImplicitNV *invd = new ImplicitNVDerived(); // expected-note{{Conversion from derived to base happened here}} 129*61e7adefSGabor Horvath delete invd; // expected-warning{{Destruction of a polymorphic object with no virtual destructor}} 130*61e7adefSGabor Horvath // expected-note@-1{{Destruction of a polymorphic object with no virtual destructor}} 131*61e7adefSGabor Horvath } 132*61e7adefSGabor Horvath doubleDecl()133*61e7adefSGabor Horvathvoid doubleDecl() { 134*61e7adefSGabor Horvath ImplicitNV *dd1, *dd2; 135*61e7adefSGabor Horvath dd1 = new ImplicitNVDerived(); // expected-note{{Conversion from derived to base happened here}} 136*61e7adefSGabor Horvath delete dd1; // expected-warning{{Destruction of a polymorphic object with no virtual destructor}} 137*61e7adefSGabor Horvath // expected-note@-1{{Destruction of a polymorphic object with no virtual destructor}} 138*61e7adefSGabor Horvath } 139*61e7adefSGabor Horvath virtualBase()140*61e7adefSGabor Horvathvoid virtualBase() { 141*61e7adefSGabor Horvath Virtual *vb = new VDerived(); 142*61e7adefSGabor Horvath delete vb; // no-warning 143*61e7adefSGabor Horvath } 144*61e7adefSGabor Horvath notDerived()145*61e7adefSGabor Horvathvoid notDerived() { 146*61e7adefSGabor Horvath NonVirtual *nd = new NonVirtual(); 147*61e7adefSGabor Horvath delete nd; // no-warning 148*61e7adefSGabor Horvath } 149*61e7adefSGabor Horvath notDerivedArr()150*61e7adefSGabor Horvathvoid notDerivedArr() { 151*61e7adefSGabor Horvath NonVirtual *nda = new NonVirtual[3]; 152*61e7adefSGabor Horvath delete[] nda; // no-warning 153*61e7adefSGabor Horvath } 154*61e7adefSGabor Horvath cast()155*61e7adefSGabor Horvathvoid cast() { 156*61e7adefSGabor Horvath NonVirtual *c = new NVDerived(); 157*61e7adefSGabor Horvath delete reinterpret_cast<NVDerived*>(c); // no-warning 158*61e7adefSGabor Horvath } 159*61e7adefSGabor Horvath deleteThroughFunction2()160*61e7adefSGabor Horvathvoid deleteThroughFunction2() { 161*61e7adefSGabor Horvath NonVirtual *dtf2 = new NVDerived(); 162*61e7adefSGabor Horvath sinkCast(dtf2); // no-warning 163*61e7adefSGabor Horvath } 164*61e7adefSGabor Horvath deleteThroughFunction3()165*61e7adefSGabor Horvathvoid deleteThroughFunction3() { 166*61e7adefSGabor Horvath NVDerived *dtf3; 167*61e7adefSGabor Horvath dtf3 = new NVDerived(); 168*61e7adefSGabor Horvath sinkParamCast(dtf3); // no-warning 169*61e7adefSGabor Horvath } 170*61e7adefSGabor Horvath stackVar()171*61e7adefSGabor Horvathvoid stackVar() { 172*61e7adefSGabor Horvath NonVirtual sv2; 173*61e7adefSGabor Horvath delete &sv2; // no-warning 174*61e7adefSGabor Horvath } 175*61e7adefSGabor Horvath 176*61e7adefSGabor Horvath // Deleting a polymorphic object with a non-virtual dtor 177*61e7adefSGabor Horvath // is not a problem if it is referenced by its precise type. 178*61e7adefSGabor Horvath preciseType()179*61e7adefSGabor Horvathvoid preciseType() { 180*61e7adefSGabor Horvath NVDerived *pt = new NVDerived(); 181*61e7adefSGabor Horvath delete pt; // no-warning 182*61e7adefSGabor Horvath } 183*61e7adefSGabor Horvath privateDtor()184*61e7adefSGabor Horvathvoid privateDtor() { 185*61e7adefSGabor Horvath Base *pd = new PrivateDtor(); 186*61e7adefSGabor Horvath pd->destroy(); // no-warning 187*61e7adefSGabor Horvath } 188