1 // RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -analyzer-config c++-inlining=destructors -verify -std=c++11 %s
2 // RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -analyzer-config c++-inlining=destructors -verify -std=c++17 %s
3
4 using size_t = __typeof(sizeof(int));
5
6 void clang_analyzer_eval(bool);
7 void clang_analyzer_checkInlined(bool);
8 void clang_analyzer_warnIfReached();
9 void clang_analyzer_explain(int);
10
11 int a, b, c, d;
12
13 struct InlineDtor {
14 static int cnt;
15 static int dtorCalled;
~InlineDtorInlineDtor16 ~InlineDtor() {
17 switch (dtorCalled % 4) {
18 case 0:
19 a = cnt++;
20 break;
21 case 1:
22 b = cnt++;
23 break;
24 case 2:
25 c = cnt++;
26 break;
27 case 3:
28 d = cnt++;
29 break;
30 }
31
32 ++dtorCalled;
33 }
34 };
35
36 int InlineDtor::cnt = 0;
37 int InlineDtor::dtorCalled = 0;
38
foo()39 void foo() {
40 InlineDtor::cnt = 0;
41 InlineDtor::dtorCalled = 0;
42 InlineDtor arr[4];
43 }
44
testAutoDtor()45 void testAutoDtor() {
46 foo();
47
48 clang_analyzer_eval(a == 0); // expected-warning {{TRUE}}
49 clang_analyzer_eval(b == 1); // expected-warning {{TRUE}}
50 clang_analyzer_eval(c == 2); // expected-warning {{TRUE}}
51 clang_analyzer_eval(d == 3); // expected-warning {{TRUE}}
52 }
53
testDeleteDtor()54 void testDeleteDtor() {
55 InlineDtor::cnt = 10;
56 InlineDtor::dtorCalled = 0;
57
58 InlineDtor *arr = new InlineDtor[4];
59 delete[] arr;
60
61 clang_analyzer_eval(a == 10); // expected-warning {{TRUE}}
62 clang_analyzer_eval(b == 11); // expected-warning {{TRUE}}
63 clang_analyzer_eval(c == 12); // expected-warning {{TRUE}}
64 clang_analyzer_eval(d == 13); // expected-warning {{TRUE}}
65 }
66
67 struct MemberDtor {
68 InlineDtor arr[4];
69 };
70
testMemberDtor()71 void testMemberDtor() {
72 InlineDtor::cnt = 5;
73 InlineDtor::dtorCalled = 0;
74
75 MemberDtor *MD = new MemberDtor{};
76 delete MD;
77
78 clang_analyzer_eval(a == 5); // expected-warning {{TRUE}}
79 clang_analyzer_eval(b == 6); // expected-warning {{TRUE}}
80 clang_analyzer_eval(c == 7); // expected-warning {{TRUE}}
81 clang_analyzer_eval(d == 8); // expected-warning {{TRUE}}
82 }
83
84 struct MultipleMemberDtor
85 {
86 InlineDtor arr[4];
87 InlineDtor arr2[4];
88 };
89
testMultipleMemberDtor()90 void testMultipleMemberDtor() {
91 InlineDtor::cnt = 30;
92 InlineDtor::dtorCalled = 0;
93
94 MultipleMemberDtor *MD = new MultipleMemberDtor{};
95 delete MD;
96
97 clang_analyzer_eval(a == 34); // expected-warning {{TRUE}}
98 clang_analyzer_eval(b == 35); // expected-warning {{TRUE}}
99 clang_analyzer_eval(c == 36); // expected-warning {{TRUE}}
100 clang_analyzer_eval(d == 37); // expected-warning {{TRUE}}
101 }
102
103 int EvalOrderArr[4];
104
105 struct EvalOrder
106 {
107 int ctor = 0;
108 static int dtorCalled;
109 static int ctorCalled;
110
EvalOrderEvalOrder111 EvalOrder() { ctor = ctorCalled++; };
112
~EvalOrderEvalOrder113 ~EvalOrder() { EvalOrderArr[ctor] = dtorCalled++; }
114 };
115
116 int EvalOrder::ctorCalled = 0;
117 int EvalOrder::dtorCalled = 0;
118
dtorEvaluationOrder()119 void dtorEvaluationOrder() {
120 EvalOrder::ctorCalled = 0;
121 EvalOrder::dtorCalled = 0;
122
123 EvalOrder* eptr = new EvalOrder[4];
124 delete[] eptr;
125
126 clang_analyzer_eval(EvalOrder::dtorCalled == 4); // expected-warning {{TRUE}}
127 clang_analyzer_eval(EvalOrder::dtorCalled == EvalOrder::ctorCalled); // expected-warning {{TRUE}}
128
129 clang_analyzer_eval(EvalOrderArr[0] == 3); // expected-warning {{TRUE}}
130 clang_analyzer_eval(EvalOrderArr[1] == 2); // expected-warning {{TRUE}}
131 clang_analyzer_eval(EvalOrderArr[2] == 1); // expected-warning {{TRUE}}
132 clang_analyzer_eval(EvalOrderArr[3] == 0); // expected-warning {{TRUE}}
133 }
134
135 struct EmptyDtor {
~EmptyDtorEmptyDtor136 ~EmptyDtor(){};
137 };
138
139 struct DefaultDtor {
140 ~DefaultDtor() = default;
141 };
142
143 // This function used to fail on an assertion.
no_crash()144 void no_crash() {
145 EmptyDtor* eptr = new EmptyDtor[4];
146 delete[] eptr;
147 clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
148
149 DefaultDtor* dptr = new DefaultDtor[4];
150 delete[] dptr;
151 clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
152 }
153
154 // This snippet used to crash.
155 namespace crash2
156 {
157 template <class _Tp> class unique_ptr {
158 typedef _Tp *pointer;
159 pointer __ptr_;
160
161 public:
unique_ptr(pointer __p)162 unique_ptr(pointer __p) : __ptr_(__p) {}
~unique_ptr()163 ~unique_ptr() { reset(); }
get()164 pointer get() { return __ptr_;}
reset()165 void reset() {}
166 };
167
168 struct S;
169
170 S *makeS();
171 int bar(S *x, S *y);
172
foo()173 void foo() {
174 unique_ptr<S> x(makeS()), y(makeS());
175 bar(x.get(), y.get());
176 }
177
bar()178 void bar() {
179 foo();
180 clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
181 }
182
183 } // namespace crash2
184
185 // This snippet used to crash.
186 namespace crash3
187 {
188 struct InlineDtor {
~InlineDtorcrash3::InlineDtor189 ~InlineDtor() {}
190 };
191 struct MultipleMemberDtor
192 {
193 InlineDtor arr[4];
194 InlineDtor arr2[4];
195 };
196
foo()197 void foo(){
198 auto *arr = new MultipleMemberDtor[4];
199 delete[] arr;
200 clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
201 }
202 } // namespace crash3
203
204 namespace crash4 {
205 struct a {
206 a *b;
207 };
208 struct c {
209 a d;
210 c();
~ccrash4::c211 ~c() {
212 for (a e = d;; e = *e.b)
213 ;
214 }
215 };
f()216 void f() {
217 c g;
218 clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
219 }
220
221 } // namespace crash4
222
223 namespace crash5 {
224 namespace std {
225 template <class _Tp> class unique_ptr {
226 _Tp *__ptr_;
227 public:
unique_ptr(_Tp * __p)228 unique_ptr(_Tp *__p) : __ptr_(__p) {}
~unique_ptr()229 ~unique_ptr() {}
230 };
231 } // namespace std
232
SSL_use_certificate(int * arg)233 int SSL_use_certificate(int *arg) {
234 std::unique_ptr<int> free_x509(arg);
235 {
236 if (SSL_use_certificate(arg)) {
237 return 0;
238 }
239 }
240 clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
241 return 1;
242 }
243
244 } // namespace crash5
245
zeroLength()246 void zeroLength(){
247 InlineDtor::dtorCalled = 0;
248
249 auto *arr = new InlineDtor[0];
250 delete[] arr;
251
252 auto *arr2 = new InlineDtor[2][0][2];
253 delete[] arr2;
254
255 auto *arr3 = new InlineDtor[0][2][2];
256 delete[] arr3;
257
258 auto *arr4 = new InlineDtor[2][2][0];
259 delete[] arr4;
260
261 clang_analyzer_eval(InlineDtor::dtorCalled == 0); // expected-warning {{TRUE}}
262 }
263
264
evalOrderPrep()265 void evalOrderPrep() {
266 EvalOrderArr[0] = 0;
267 EvalOrderArr[1] = 0;
268 EvalOrderArr[2] = 0;
269 EvalOrderArr[3] = 0;
270
271 EvalOrder::ctorCalled = 0;
272 EvalOrder::dtorCalled = 0;
273 }
274
multidimensionalPrep()275 void multidimensionalPrep(){
276 EvalOrder::ctorCalled = 0;
277 EvalOrder::dtorCalled = 0;
278
279 EvalOrder arr[2][2];
280 }
281
multidimensional()282 void multidimensional(){
283 evalOrderPrep();
284 multidimensionalPrep();
285
286 clang_analyzer_eval(EvalOrder::dtorCalled == 4); // expected-warning {{TRUE}}
287 clang_analyzer_eval(EvalOrder::dtorCalled == EvalOrder::ctorCalled); // expected-warning {{TRUE}}
288
289 clang_analyzer_eval(EvalOrderArr[0] == 3); // expected-warning {{TRUE}}
290 clang_analyzer_eval(EvalOrderArr[1] == 2); // expected-warning {{TRUE}}
291 clang_analyzer_eval(EvalOrderArr[2] == 1); // expected-warning {{TRUE}}
292 clang_analyzer_eval(EvalOrderArr[3] == 0); // expected-warning {{TRUE}}
293 }
294
multidimensionalHeap()295 void multidimensionalHeap() {
296 evalOrderPrep();
297
298 auto* eptr = new EvalOrder[2][2];
299 delete[] eptr;
300
301 clang_analyzer_eval(EvalOrder::dtorCalled == 4); // expected-warning {{TRUE}}
302 clang_analyzer_eval(EvalOrder::dtorCalled == EvalOrder::ctorCalled); // expected-warning {{TRUE}}
303
304 clang_analyzer_eval(EvalOrderArr[0] == 3); // expected-warning {{TRUE}}
305 clang_analyzer_eval(EvalOrderArr[1] == 2); // expected-warning {{TRUE}}
306 clang_analyzer_eval(EvalOrderArr[2] == 1); // expected-warning {{TRUE}}
307 clang_analyzer_eval(EvalOrderArr[3] == 0); // expected-warning {{TRUE}}
308 }
309
310 struct MultiWrapper{
311 EvalOrder arr[2][2];
312 };
313
multidimensionalMember()314 void multidimensionalMember(){
315 evalOrderPrep();
316
317 auto* mptr = new MultiWrapper;
318 delete mptr;
319
320 clang_analyzer_eval(EvalOrder::dtorCalled == 4); // expected-warning {{TRUE}}
321 clang_analyzer_eval(EvalOrder::dtorCalled == EvalOrder::ctorCalled); // expected-warning {{TRUE}}
322
323 clang_analyzer_eval(EvalOrderArr[0] == 3); // expected-warning {{TRUE}}
324 clang_analyzer_eval(EvalOrderArr[1] == 2); // expected-warning {{TRUE}}
325 clang_analyzer_eval(EvalOrderArr[2] == 1); // expected-warning {{TRUE}}
326 clang_analyzer_eval(EvalOrderArr[3] == 0); // expected-warning {{TRUE}}
327 }
328
329 void *memset(void *, int, size_t);
330 void clang_analyzer_dumpElementCount(InlineDtor *);
331
nonConstantRegionExtent()332 void nonConstantRegionExtent(){
333
334 InlineDtor::dtorCalled = 0;
335
336 int x = 3;
337 memset(&x, 1, sizeof(x));
338
339 InlineDtor *arr = new InlineDtor[x];
340 clang_analyzer_dumpElementCount(arr); // expected-warning {{conj_$0}}
341 delete [] arr;
342
343 //FIXME: This should be TRUE but memset also sets this
344 // region to a conjured symbol.
345 clang_analyzer_eval(InlineDtor::dtorCalled == 0); // expected-warning {{TRUE}} expected-warning {{FALSE}}
346 }
347
348 namespace crash6 {
349
350 struct NonTrivialItem {
351 ~NonTrivialItem();
352 };
353
354 struct WeirdVec {
clearcrash6::WeirdVec355 void clear() {
356 delete[] data;
357 size = 0;
358 }
359 NonTrivialItem *data;
360 unsigned size;
361 };
362
top(int j)363 void top(int j) {
364 WeirdVec *p = new WeirdVec;
365
366 p[j].size = 0;
367 delete[] p->data; // no-crash
368 }
369
370 template <typename T>
make_unknown()371 T make_unknown() {
372 return reinterpret_cast<T>(static_cast<int>(0.404));
373 }
374
directUnknownSymbol()375 void directUnknownSymbol() {
376 delete[] make_unknown<NonTrivialItem*>(); // no-crash
377 }
378
379 }
380