Clang Project

clang_source_code/test/Analysis/DeleteWithNonVirtualDtor.cpp
1// 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}
188