blob: a9b8a11f3482f3ec58329e80bafc2f6a4a78cbe3 [file] [log] [blame]
Gabor Horvath61e7ade2017-09-22 10:16:33 +00001// RUN: %clang_cc1 -analyze -analyzer-checker=alpha.cplusplus.DeleteWithNonVirtualDtor -std=c++11 -verify -analyzer-output=text %s
2
3struct Virtual {
4 virtual ~Virtual() {}
5};
6
7struct VDerived : public Virtual {};
8
9struct NonVirtual {
10 ~NonVirtual() {}
11};
12
13struct NVDerived : public NonVirtual {};
14struct NVDoubleDerived : public NVDerived {};
15
16struct Base {
17 virtual void destroy() = 0;
18};
19
20class PrivateDtor final : public Base {
21public:
22 void destroy() { delete this; }
23private:
24 ~PrivateDtor() {}
25};
26
27struct ImplicitNV {
28 virtual void f();
29};
30
31struct ImplicitNVDerived : public ImplicitNV {};
32
33NVDerived *get();
34
35NonVirtual *create() {
36 NonVirtual *x = new NVDerived(); // expected-note{{Conversion from derived to base happened here}}
37 return x;
38}
39
40void 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
45void sinkCast(NonVirtual *y) {
46 delete reinterpret_cast<NVDerived*>(y);
47}
48
49void sinkParamCast(NVDerived *z) {
50 delete z;
51}
52
53void 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
60void 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
66void 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
72void 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
78void 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
85void 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
92void deleteThroughFunction() {
93 NonVirtual *dtf = new NVDerived(); // expected-note{{Conversion from derived to base happened here}}
94 sink(dtf); // expected-note{{Calling 'sink'}}
95}
96
97void 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
104void 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
112void 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
119void 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
127void 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
133void 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
140void virtualBase() {
141 Virtual *vb = new VDerived();
142 delete vb; // no-warning
143}
144
145void notDerived() {
146 NonVirtual *nd = new NonVirtual();
147 delete nd; // no-warning
148}
149
150void notDerivedArr() {
151 NonVirtual *nda = new NonVirtual[3];
152 delete[] nda; // no-warning
153}
154
155void cast() {
156 NonVirtual *c = new NVDerived();
157 delete reinterpret_cast<NVDerived*>(c); // no-warning
158}
159
160void deleteThroughFunction2() {
161 NonVirtual *dtf2 = new NVDerived();
162 sinkCast(dtf2); // no-warning
163}
164
165void deleteThroughFunction3() {
166 NVDerived *dtf3;
167 dtf3 = new NVDerived();
168 sinkParamCast(dtf3); // no-warning
169}
170
171void 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
179void preciseType() {
180 NVDerived *pt = new NVDerived();
181 delete pt; // no-warning
182}
183
184void privateDtor() {
185 Base *pd = new PrivateDtor();
186 pd->destroy(); // no-warning
187}