blob: 620237cd6edeb5b6016ffaa66095933d6661d8f7 [file] [log] [blame]
Dominic Chen184c6242017-03-03 18:02:02 +00001// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDelete -std=c++11 -fblocks -verify %s
2// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDeleteLeaks -DLEAKS -std=c++11 -fblocks -verify %s
Artem Dergachev1084de52018-01-17 22:58:35 +00003// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDelete -std=c++11 -fblocks -analyzer-config c++-allocator-inlining=true -verify %s
4// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDeleteLeaks -DLEAKS -std=c++11 -fblocks -analyzer-config c++-allocator-inlining=true -verify %s
Artem Dergachevd3c54312018-01-24 21:24:10 +00005// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDelete -std=c++11 -fblocks -DTEST_INLINABLE_ALLOCATORS -verify %s
6// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDeleteLeaks -DLEAKS -std=c++11 -fblocks -DTEST_INLINABLE_ALLOCATORS -verify %s
7// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDelete -std=c++11 -fblocks -analyzer-config c++-allocator-inlining=true -DTEST_INLINABLE_ALLOCATORS -verify %s
8// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDeleteLeaks -DLEAKS -std=c++11 -fblocks -analyzer-config c++-allocator-inlining=true -DTEST_INLINABLE_ALLOCATORS -verify %s
9
Anton Yartsev13df0362013-03-25 01:35:45 +000010#include "Inputs/system-header-simulator-cxx.h"
Anton Yartsev13df0362013-03-25 01:35:45 +000011
12typedef __typeof__(sizeof(int)) size_t;
13extern "C" void *malloc(size_t);
Jordan Rose867b185e2013-08-09 00:55:47 +000014extern "C" void free (void* ptr);
Anton Yartsev13df0362013-03-25 01:35:45 +000015int *global;
16
17//------------------
18// check for leaks
19//------------------
20
Anton Yartsev8b662702013-03-28 16:10:38 +000021//----- Standard non-placement operators
22void testGlobalOpNew() {
Anton Yartsev13df0362013-03-25 01:35:45 +000023 void *p = operator new(0);
Jordan Rose26330562013-04-05 17:55:00 +000024}
25#ifdef LEAKS
Anna Zaksa1de8562013-04-06 00:41:36 +000026// expected-warning@-2{{Potential leak of memory pointed to by 'p'}}
Jordan Rose26330562013-04-05 17:55:00 +000027#endif
Anton Yartsev13df0362013-03-25 01:35:45 +000028
Anton Yartsev8b662702013-03-28 16:10:38 +000029void testGlobalOpNewArray() {
30 void *p = operator new[](0);
Jordan Rose26330562013-04-05 17:55:00 +000031}
32#ifdef LEAKS
Anna Zaksa1de8562013-04-06 00:41:36 +000033// expected-warning@-2{{Potential leak of memory pointed to by 'p'}}
Jordan Rose26330562013-04-05 17:55:00 +000034#endif
Anton Yartsev8b662702013-03-28 16:10:38 +000035
36void testGlobalNewExpr() {
Anton Yartsev13df0362013-03-25 01:35:45 +000037 int *p = new int;
Jordan Rose26330562013-04-05 17:55:00 +000038}
39#ifdef LEAKS
Anna Zaksa1de8562013-04-06 00:41:36 +000040// expected-warning@-2{{Potential leak of memory pointed to by 'p'}}
Jordan Rose26330562013-04-05 17:55:00 +000041#endif
Anton Yartsev13df0362013-03-25 01:35:45 +000042
Anton Yartsev8b662702013-03-28 16:10:38 +000043void testGlobalNewExprArray() {
44 int *p = new int[0];
Jordan Rose26330562013-04-05 17:55:00 +000045}
46#ifdef LEAKS
Anna Zaksa1de8562013-04-06 00:41:36 +000047// expected-warning@-2{{Potential leak of memory pointed to by 'p'}}
Jordan Rose26330562013-04-05 17:55:00 +000048#endif
Anton Yartsev13df0362013-03-25 01:35:45 +000049
Anton Yartsev8b662702013-03-28 16:10:38 +000050//----- Standard nothrow placement operators
51void testGlobalNoThrowPlacementOpNewBeforeOverload() {
52 void *p = operator new(0, std::nothrow);
Jordan Rose26330562013-04-05 17:55:00 +000053}
54#ifdef LEAKS
Artem Dergachevd3c54312018-01-24 21:24:10 +000055#ifndef TEST_INLINABLE_ALLOCATORS
56// expected-warning@-3{{Potential leak of memory pointed to by 'p'}}
57#endif
Jordan Rose26330562013-04-05 17:55:00 +000058#endif
Anton Yartsev8b662702013-03-28 16:10:38 +000059
60void testGlobalNoThrowPlacementExprNewBeforeOverload() {
61 int *p = new(std::nothrow) int;
Jordan Rose26330562013-04-05 17:55:00 +000062}
63#ifdef LEAKS
Artem Dergachevd3c54312018-01-24 21:24:10 +000064#ifndef TEST_INLINABLE_ALLOCATORS
65// expected-warning@-3{{Potential leak of memory pointed to by 'p'}}
66#endif
Jordan Rose26330562013-04-05 17:55:00 +000067#endif
Anton Yartsev8b662702013-03-28 16:10:38 +000068
Anton Yartsev8b662702013-03-28 16:10:38 +000069//----- Standard pointer placement operators
70void testGlobalPointerPlacementNew() {
Anton Yartsev13df0362013-03-25 01:35:45 +000071 int i;
Anton Yartsev13df0362013-03-25 01:35:45 +000072
Anton Yartsev8b662702013-03-28 16:10:38 +000073 void *p1 = operator new(0, &i); // no warn
Anton Yartsev13df0362013-03-25 01:35:45 +000074
Anton Yartsev8b662702013-03-28 16:10:38 +000075 void *p2 = operator new[](0, &i); // no warn
Anton Yartsev13df0362013-03-25 01:35:45 +000076
Anton Yartsev8b662702013-03-28 16:10:38 +000077 int *p3 = new(&i) int; // no warn
Anton Yartsev13df0362013-03-25 01:35:45 +000078
Anton Yartsev8b662702013-03-28 16:10:38 +000079 int *p4 = new(&i) int[0]; // no warn
Anton Yartsev13df0362013-03-25 01:35:45 +000080}
81
Anton Yartsev8b662702013-03-28 16:10:38 +000082//----- Other cases
83void testNewMemoryIsInHeap() {
84 int *p = new int;
85 if (global != p) // condition is always true as 'p' wraps a heap region that
86 // is different from a region wrapped by 'global'
87 global = p; // pointer escapes
Anton Yartsev13df0362013-03-25 01:35:45 +000088}
89
Anton Yartsev8b662702013-03-28 16:10:38 +000090struct PtrWrapper {
91 int *x;
Anton Yartsev13df0362013-03-25 01:35:45 +000092
Anton Yartsev8b662702013-03-28 16:10:38 +000093 PtrWrapper(int *input) : x(input) {}
94};
Anton Yartsev13df0362013-03-25 01:35:45 +000095
Anton Yartsev8b662702013-03-28 16:10:38 +000096void testNewInvalidationPlacement(PtrWrapper *w) {
97 // Ensure that we don't consider this a leak.
98 new (w) PtrWrapper(new int); // no warn
Anton Yartsev13df0362013-03-25 01:35:45 +000099}
100
Anton Yartsevb50f4ba2015-04-14 14:18:04 +0000101//-----------------------------------------
102// check for usage of zero-allocated memory
103//-----------------------------------------
104
105void testUseZeroAlloc1() {
106 int *p = (int *)operator new(0);
107 *p = 1; // expected-warning {{Use of zero-allocated memory}}
108 delete p;
109}
110
111int testUseZeroAlloc2() {
112 int *p = (int *)operator new[](0);
113 return p[0]; // expected-warning {{Use of zero-allocated memory}}
114 delete[] p;
115}
116
117void f(int);
118
119void testUseZeroAlloc3() {
120 int *p = new int[0];
121 f(*p); // expected-warning {{Use of zero-allocated memory}}
122 delete[] p;
123}
124
Anton Yartsev13df0362013-03-25 01:35:45 +0000125//---------------
126// other checks
127//---------------
128
Anton Yartsevcb2ccd62013-04-10 22:21:41 +0000129class SomeClass {
130public:
131 void f(int *p);
132};
Anton Yartsev13df0362013-03-25 01:35:45 +0000133
Anton Yartsevcb2ccd62013-04-10 22:21:41 +0000134void f(int *p1, int *p2 = 0, int *p3 = 0);
135void g(SomeClass &c, ...);
136
137void testUseFirstArgAfterDelete() {
Anton Yartsev13df0362013-03-25 01:35:45 +0000138 int *p = new int;
139 delete p;
140 f(p); // expected-warning{{Use of memory after it is freed}}
141}
142
Anton Yartsevcb2ccd62013-04-10 22:21:41 +0000143void testUseMiddleArgAfterDelete(int *p) {
144 delete p;
145 f(0, p); // expected-warning{{Use of memory after it is freed}}
146}
147
148void testUseLastArgAfterDelete(int *p) {
149 delete p;
150 f(0, 0, p); // expected-warning{{Use of memory after it is freed}}
151}
152
Anton Yartsev8fc29db2013-04-10 22:36:16 +0000153void testUseSeveralArgsAfterDelete(int *p) {
154 delete p;
155 f(p, p, p); // expected-warning{{Use of memory after it is freed}}
156}
157
Anton Yartsevcb2ccd62013-04-10 22:21:41 +0000158void testUseRefArgAfterDelete(SomeClass &c) {
159 delete &c;
160 g(c); // expected-warning{{Use of memory after it is freed}}
161}
162
163void testVariadicArgAfterDelete() {
164 SomeClass c;
165 int *p = new int;
166 delete p;
167 g(c, 0, p); // expected-warning{{Use of memory after it is freed}}
168}
169
170void testUseMethodArgAfterDelete(int *p) {
171 SomeClass *c = new SomeClass;
172 delete p;
173 c->f(p); // expected-warning{{Use of memory after it is freed}}
174}
175
176void testUseThisAfterDelete() {
177 SomeClass *c = new SomeClass;
178 delete c;
179 c->f(0); // expected-warning{{Use of memory after it is freed}}
180}
181
Anton Yartsev13df0362013-03-25 01:35:45 +0000182void testDoubleDelete() {
183 int *p = new int;
184 delete p;
185 delete p; // expected-warning{{Attempt to free released memory}}
186}
187
188void testExprDeleteArg() {
189 int i;
Anton Yartsev05789592013-03-28 17:05:19 +0000190 delete &i; // expected-warning{{Argument to 'delete' is the address of the local variable 'i', which is not memory allocated by 'new'}}
191}
Anton Yartsev13df0362013-03-25 01:35:45 +0000192
193void testExprDeleteArrArg() {
194 int i;
Anton Yartsev05789592013-03-28 17:05:19 +0000195 delete[] &i; // expected-warning{{Argument to 'delete[]' is the address of the local variable 'i', which is not memory allocated by 'new[]'}}
196}
Anton Yartsev13df0362013-03-25 01:35:45 +0000197
198void testAllocDeallocNames() {
199 int *p = new(std::nothrow) int[1];
Artem Dergachevd3c54312018-01-24 21:24:10 +0000200 delete[] (++p);
201#ifndef TEST_INLINABLE_ALLOCATORS
202 // expected-warning@-2{{Argument to 'delete[]' is offset by 4 bytes from the start of memory allocated by 'new[]'}}
203#endif
Anton Yartsev05789592013-03-28 17:05:19 +0000204}
Anton Yartsev13df0362013-03-25 01:35:45 +0000205
Anna Zaks333481b2013-03-28 23:15:29 +0000206//--------------------------------
207// Test escape of newed const pointer. Note, a const pointer can be deleted.
208//--------------------------------
209struct StWithConstPtr {
210 const int *memp;
211};
212void escape(const int &x);
213void escapeStruct(const StWithConstPtr &x);
214void escapePtr(const StWithConstPtr *x);
215void escapeVoidPtr(const void *x);
216
217void testConstEscape() {
218 int *p = new int(1);
219 escape(*p);
220} // no-warning
221
222void testConstEscapeStruct() {
223 StWithConstPtr *St = new StWithConstPtr();
224 escapeStruct(*St);
225} // no-warning
226
227void testConstEscapeStructPtr() {
228 StWithConstPtr *St = new StWithConstPtr();
229 escapePtr(St);
230} // no-warning
231
232void testConstEscapeMember() {
233 StWithConstPtr St;
234 St.memp = new int(2);
235 escapeVoidPtr(St.memp);
236} // no-warning
237
238void testConstEscapePlacementNew() {
239 int *x = (int *)malloc(sizeof(int));
240 void *y = new (x) int;
241 escapeVoidPtr(y);
242} // no-warning
Jordan Rosefbe4d852013-05-17 02:16:49 +0000243
Jordan Rose867b185e2013-08-09 00:55:47 +0000244//============== Test Uninitialized delete delete[]========================
245void testUninitDelete() {
246 int *x;
247 int * y = new int;
248 delete y;
249 delete x; // expected-warning{{Argument to 'delete' is uninitialized}}
250}
251
252void testUninitDeleteArray() {
253 int *x;
254 int * y = new int[5];
255 delete[] y;
256 delete[] x; // expected-warning{{Argument to 'delete[]' is uninitialized}}
257}
258
259void testUninitFree() {
260 int *x;
Daniel Marjamaki3d8d6ed2017-03-08 15:22:24 +0000261 free(x); // expected-warning{{1st function call argument is an uninitialized value}}
Jordan Rose867b185e2013-08-09 00:55:47 +0000262}
263
264void testUninitDeleteSink() {
265 int *x;
266 delete x; // expected-warning{{Argument to 'delete' is uninitialized}}
267 (*(volatile int *)0 = 1); // no warn
268}
269
270void testUninitDeleteArraySink() {
271 int *x;
272 delete[] x; // expected-warning{{Argument to 'delete[]' is uninitialized}}
273 (*(volatile int *)0 = 1); // no warn
274}
Jordan Rosefbe4d852013-05-17 02:16:49 +0000275
276namespace reference_count {
277 class control_block {
278 unsigned count;
279 public:
280 control_block() : count(0) {}
281 void retain() { ++count; }
282 int release() { return --count; }
283 };
284
285 template <typename T>
286 class shared_ptr {
287 T *p;
288 control_block *control;
289
290 public:
291 shared_ptr() : p(0), control(0) {}
292 explicit shared_ptr(T *p) : p(p), control(new control_block) {
293 control->retain();
294 }
295 shared_ptr(shared_ptr &other) : p(other.p), control(other.control) {
296 if (control)
297 control->retain();
298 }
299 ~shared_ptr() {
300 if (control && control->release() == 0) {
301 delete p;
302 delete control;
303 }
304 };
305
306 T &operator *() {
307 return *p;
308 };
309
310 void swap(shared_ptr &other) {
311 T *tmp = p;
312 p = other.p;
313 other.p = tmp;
314
315 control_block *ctrlTmp = control;
316 control = other.control;
317 other.control = ctrlTmp;
318 }
319 };
320
321 void testSingle() {
322 shared_ptr<int> a(new int);
323 *a = 1;
324 }
325
326 void testDouble() {
327 shared_ptr<int> a(new int);
328 shared_ptr<int> b = a;
329 *a = 1;
330 }
331
332 void testInvalidated() {
333 shared_ptr<int> a(new int);
334 shared_ptr<int> b = a;
335 *a = 1;
336
337 extern void use(shared_ptr<int> &);
338 use(b);
339 }
340
341 void testNestedScope() {
342 shared_ptr<int> a(new int);
343 {
344 shared_ptr<int> b = a;
345 }
346 *a = 1;
347 }
348
349 void testSwap() {
350 shared_ptr<int> a(new int);
351 shared_ptr<int> b;
352 shared_ptr<int> c = a;
353 shared_ptr<int>(c).swap(b);
354 }
355
356 void testUseAfterFree() {
357 int *p = new int;
358 {
359 shared_ptr<int> a(p);
360 shared_ptr<int> b = a;
361 }
362
363 // FIXME: We should get a warning here, but we don't because we've
364 // conservatively modeled ~shared_ptr.
365 *p = 1;
366 }
367}
368
Jordan Rose1ccc43d2013-09-25 16:06:17 +0000369// Test double delete
370class DerefClass{
371public:
372 int *x;
373 DerefClass() {}
Jordan Rose656fdd52014-01-08 18:46:55 +0000374 ~DerefClass() {*x = 1;}
Jordan Rose1ccc43d2013-09-25 16:06:17 +0000375};
376
377void testDoubleDeleteClassInstance() {
378 DerefClass *foo = new DerefClass();
379 delete foo;
Jordan Rose656fdd52014-01-08 18:46:55 +0000380 delete foo; // expected-warning {{Attempt to delete released memory}}
Jordan Rose1ccc43d2013-09-25 16:06:17 +0000381}
382
383class EmptyClass{
384public:
385 EmptyClass() {}
386 ~EmptyClass() {}
387};
388
389void testDoubleDeleteEmptyClass() {
390 EmptyClass *foo = new EmptyClass();
391 delete foo;
Jordan Rose656fdd52014-01-08 18:46:55 +0000392 delete foo; // expected-warning {{Attempt to delete released memory}}
Jordan Rose1ccc43d2013-09-25 16:06:17 +0000393}
Gabor Horvath44583ce62016-08-08 09:22:59 +0000394
395struct Base {
396 virtual ~Base() {}
397};
398
399struct Derived : Base {
400};
401
402Base *allocate() {
403 return new Derived;
404}
405
406void shouldNotReportLeak() {
407 Derived *p = (Derived *)allocate();
408 delete p;
409}