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