diff options
Diffstat (limited to 'clang/test/Analysis/DeleteWithNonVirtualDtor.cpp')
-rw-r--r-- | clang/test/Analysis/DeleteWithNonVirtualDtor.cpp | 187 |
1 files changed, 187 insertions, 0 deletions
diff --git a/clang/test/Analysis/DeleteWithNonVirtualDtor.cpp b/clang/test/Analysis/DeleteWithNonVirtualDtor.cpp new file mode 100644 index 00000000000..a9b8a11f348 --- /dev/null +++ b/clang/test/Analysis/DeleteWithNonVirtualDtor.cpp @@ -0,0 +1,187 @@ +// RUN: %clang_cc1 -analyze -analyzer-checker=alpha.cplusplus.DeleteWithNonVirtualDtor -std=c++11 -verify -analyzer-output=text %s + +struct Virtual { + virtual ~Virtual() {} +}; + +struct VDerived : public Virtual {}; + +struct NonVirtual { + ~NonVirtual() {} +}; + +struct NVDerived : public NonVirtual {}; +struct NVDoubleDerived : public NVDerived {}; + +struct Base { + virtual void destroy() = 0; +}; + +class PrivateDtor final : public Base { +public: + void destroy() { delete this; } +private: + ~PrivateDtor() {} +}; + +struct ImplicitNV { + virtual void f(); +}; + +struct ImplicitNVDerived : public ImplicitNV {}; + +NVDerived *get(); + +NonVirtual *create() { + NonVirtual *x = new NVDerived(); // expected-note{{Conversion from derived to base happened here}} + return x; +} + +void sink(NonVirtual *x) { + delete x; // expected-warning{{Destruction of a polymorphic object with no virtual destructor}} + // expected-note@-1{{Destruction of a polymorphic object with no virtual destructor}} +} + +void sinkCast(NonVirtual *y) { + delete reinterpret_cast<NVDerived*>(y); +} + +void sinkParamCast(NVDerived *z) { + delete z; +} + +void singleDerived() { + NonVirtual *sd; + sd = new NVDerived(); // expected-note{{Conversion from derived to base happened here}} + delete sd; // expected-warning{{Destruction of a polymorphic object with no virtual destructor}} + // expected-note@-1{{Destruction of a polymorphic object with no virtual destructor}} +} + +void singleDerivedArr() { + NonVirtual *sda = new NVDerived[5]; // expected-note{{Conversion from derived to base happened here}} + delete[] sda; // expected-warning{{Destruction of a polymorphic object with no virtual destructor}} + // expected-note@-1{{Destruction of a polymorphic object with no virtual destructor}} +} + +void doubleDerived() { + NonVirtual *dd = new NVDoubleDerived(); // expected-note{{Conversion from derived to base happened here}} + delete (dd); // expected-warning{{Destruction of a polymorphic object with no virtual destructor}} + // expected-note@-1{{Destruction of a polymorphic object with no virtual destructor}} +} + +void assignThroughFunction() { + NonVirtual *atf = get(); // expected-note{{Conversion from derived to base happened here}} + delete atf; // expected-warning{{Destruction of a polymorphic object with no virtual destructor}} + // expected-note@-1{{Destruction of a polymorphic object with no virtual destructor}} +} + +void assignThroughFunction2() { + NonVirtual *atf2; + atf2 = get(); // expected-note{{Conversion from derived to base happened here}} + delete atf2; // expected-warning{{Destruction of a polymorphic object with no virtual destructor}} + // expected-note@-1{{Destruction of a polymorphic object with no virtual destructor}} +} + +void createThroughFunction() { + NonVirtual *ctf = create(); // expected-note{{Calling 'create'}} + // expected-note@-1{{Returning from 'create'}} + delete ctf; // expected-warning {{Destruction of a polymorphic object with no virtual destructor}} + // expected-note@-1{{Destruction of a polymorphic object with no virtual destructor}} +} + +void deleteThroughFunction() { + NonVirtual *dtf = new NVDerived(); // expected-note{{Conversion from derived to base happened here}} + sink(dtf); // expected-note{{Calling 'sink'}} +} + +void singleCastCStyle() { + NVDerived *sccs = new NVDerived(); + NonVirtual *sccs2 = (NonVirtual*)sccs; // expected-note{{Conversion from derived to base happened here}} + delete sccs2; // expected-warning{{Destruction of a polymorphic object with no virtual destructor}} + // expected-note@-1{{Destruction of a polymorphic object with no virtual destructor}} +} + +void doubleCastCStyle() { + NonVirtual *dccs = new NVDerived(); + NVDerived *dccs2 = (NVDerived*)dccs; + dccs = (NonVirtual*)dccs2; // expected-note{{Conversion from derived to base happened here}} + delete dccs; // expected-warning{{Destruction of a polymorphic object with no virtual destructor}} + // expected-note@-1{{Destruction of a polymorphic object with no virtual destructor}} +} + +void singleCast() { + NVDerived *sc = new NVDerived(); + NonVirtual *sc2 = reinterpret_cast<NonVirtual*>(sc); // expected-note{{Conversion from derived to base happened here}} + delete sc2; // expected-warning{{Destruction of a polymorphic object with no virtual destructor}} + // expected-note@-1{{Destruction of a polymorphic object with no virtual destructor}} +} + +void doubleCast() { + NonVirtual *dd = new NVDerived(); + NVDerived *dd2 = reinterpret_cast<NVDerived*>(dd); + dd = reinterpret_cast<NonVirtual*>(dd2); // expected-note {{Conversion from derived to base happened here}} + delete dd; // expected-warning {{Destruction of a polymorphic object with no virtual destructor}} + // expected-note@-1{{Destruction of a polymorphic object with no virtual destructor}} +} + +void implicitNV() { + ImplicitNV *invd = new ImplicitNVDerived(); // expected-note{{Conversion from derived to base happened here}} + delete invd; // expected-warning{{Destruction of a polymorphic object with no virtual destructor}} + // expected-note@-1{{Destruction of a polymorphic object with no virtual destructor}} +} + +void doubleDecl() { + ImplicitNV *dd1, *dd2; + dd1 = new ImplicitNVDerived(); // expected-note{{Conversion from derived to base happened here}} + delete dd1; // expected-warning{{Destruction of a polymorphic object with no virtual destructor}} + // expected-note@-1{{Destruction of a polymorphic object with no virtual destructor}} +} + +void virtualBase() { + Virtual *vb = new VDerived(); + delete vb; // no-warning +} + +void notDerived() { + NonVirtual *nd = new NonVirtual(); + delete nd; // no-warning +} + +void notDerivedArr() { + NonVirtual *nda = new NonVirtual[3]; + delete[] nda; // no-warning +} + +void cast() { + NonVirtual *c = new NVDerived(); + delete reinterpret_cast<NVDerived*>(c); // no-warning +} + +void deleteThroughFunction2() { + NonVirtual *dtf2 = new NVDerived(); + sinkCast(dtf2); // no-warning +} + +void deleteThroughFunction3() { + NVDerived *dtf3; + dtf3 = new NVDerived(); + sinkParamCast(dtf3); // no-warning +} + +void stackVar() { + NonVirtual sv2; + delete &sv2; // no-warning +} + +// Deleting a polymorphic object with a non-virtual dtor +// is not a problem if it is referenced by its precise type. + +void preciseType() { + NVDerived *pt = new NVDerived(); + delete pt; // no-warning +} + +void privateDtor() { + Base *pd = new PrivateDtor(); + pd->destroy(); // no-warning +} |