blob: 2d15614012848d380867d7e9c684b6f7985f1f90 [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
Anton Yartsev13df0362013-03-25 01:35:45 +00005#include "Inputs/system-header-simulator-cxx.h"
Anton Yartsev13df0362013-03-25 01:35:45 +00006
7typedef __typeof__(sizeof(int)) size_t;
8extern "C" void *malloc(size_t);
Jordan Rose867b185e2013-08-09 00:55:47 +00009extern "C" void free (void* ptr);
Anton Yartsev13df0362013-03-25 01:35:45 +000010int *global;
11
12//------------------
13// check for leaks
14//------------------
15
Anton Yartsev8b662702013-03-28 16:10:38 +000016//----- Standard non-placement operators
17void testGlobalOpNew() {
Anton Yartsev13df0362013-03-25 01:35:45 +000018 void *p = operator new(0);
Jordan Rose26330562013-04-05 17:55:00 +000019}
20#ifdef LEAKS
Anna Zaksa1de8562013-04-06 00:41:36 +000021// expected-warning@-2{{Potential leak of memory pointed to by 'p'}}
Jordan Rose26330562013-04-05 17:55:00 +000022#endif
Anton Yartsev13df0362013-03-25 01:35:45 +000023
Anton Yartsev8b662702013-03-28 16:10:38 +000024void testGlobalOpNewArray() {
25 void *p = operator new[](0);
Jordan Rose26330562013-04-05 17:55:00 +000026}
27#ifdef LEAKS
Anna Zaksa1de8562013-04-06 00:41:36 +000028// expected-warning@-2{{Potential leak of memory pointed to by 'p'}}
Jordan Rose26330562013-04-05 17:55:00 +000029#endif
Anton Yartsev8b662702013-03-28 16:10:38 +000030
31void testGlobalNewExpr() {
Anton Yartsev13df0362013-03-25 01:35:45 +000032 int *p = new int;
Jordan Rose26330562013-04-05 17:55:00 +000033}
34#ifdef LEAKS
Anna Zaksa1de8562013-04-06 00:41:36 +000035// expected-warning@-2{{Potential leak of memory pointed to by 'p'}}
Jordan Rose26330562013-04-05 17:55:00 +000036#endif
Anton Yartsev13df0362013-03-25 01:35:45 +000037
Anton Yartsev8b662702013-03-28 16:10:38 +000038void testGlobalNewExprArray() {
39 int *p = new int[0];
Jordan Rose26330562013-04-05 17:55:00 +000040}
41#ifdef LEAKS
Anna Zaksa1de8562013-04-06 00:41:36 +000042// expected-warning@-2{{Potential leak of memory pointed to by 'p'}}
Jordan Rose26330562013-04-05 17:55:00 +000043#endif
Anton Yartsev13df0362013-03-25 01:35:45 +000044
Anton Yartsev8b662702013-03-28 16:10:38 +000045//----- Standard nothrow placement operators
46void testGlobalNoThrowPlacementOpNewBeforeOverload() {
47 void *p = operator new(0, std::nothrow);
Jordan Rose26330562013-04-05 17:55:00 +000048}
49#ifdef LEAKS
Anna Zaksa1de8562013-04-06 00:41:36 +000050// expected-warning@-2{{Potential leak of memory pointed to by 'p'}}
Jordan Rose26330562013-04-05 17:55:00 +000051#endif
Anton Yartsev8b662702013-03-28 16:10:38 +000052
53void testGlobalNoThrowPlacementExprNewBeforeOverload() {
54 int *p = new(std::nothrow) int;
Jordan Rose26330562013-04-05 17:55:00 +000055}
56#ifdef LEAKS
Anna Zaksa1de8562013-04-06 00:41:36 +000057// expected-warning@-2{{Potential leak of memory pointed to by 'p'}}
Jordan Rose26330562013-04-05 17:55:00 +000058#endif
Anton Yartsev8b662702013-03-28 16:10:38 +000059
Anton Yartsev8b662702013-03-28 16:10:38 +000060//----- Standard pointer placement operators
61void testGlobalPointerPlacementNew() {
Anton Yartsev13df0362013-03-25 01:35:45 +000062 int i;
Anton Yartsev13df0362013-03-25 01:35:45 +000063
Anton Yartsev8b662702013-03-28 16:10:38 +000064 void *p1 = operator new(0, &i); // no warn
Anton Yartsev13df0362013-03-25 01:35:45 +000065
Anton Yartsev8b662702013-03-28 16:10:38 +000066 void *p2 = operator new[](0, &i); // no warn
Anton Yartsev13df0362013-03-25 01:35:45 +000067
Anton Yartsev8b662702013-03-28 16:10:38 +000068 int *p3 = new(&i) int; // no warn
Anton Yartsev13df0362013-03-25 01:35:45 +000069
Anton Yartsev8b662702013-03-28 16:10:38 +000070 int *p4 = new(&i) int[0]; // no warn
Anton Yartsev13df0362013-03-25 01:35:45 +000071}
72
Anton Yartsev8b662702013-03-28 16:10:38 +000073//----- Other cases
74void testNewMemoryIsInHeap() {
75 int *p = new int;
76 if (global != p) // condition is always true as 'p' wraps a heap region that
77 // is different from a region wrapped by 'global'
78 global = p; // pointer escapes
Anton Yartsev13df0362013-03-25 01:35:45 +000079}
80
Anton Yartsev8b662702013-03-28 16:10:38 +000081struct PtrWrapper {
82 int *x;
Anton Yartsev13df0362013-03-25 01:35:45 +000083
Anton Yartsev8b662702013-03-28 16:10:38 +000084 PtrWrapper(int *input) : x(input) {}
85};
Anton Yartsev13df0362013-03-25 01:35:45 +000086
Anton Yartsev8b662702013-03-28 16:10:38 +000087void testNewInvalidationPlacement(PtrWrapper *w) {
88 // Ensure that we don't consider this a leak.
89 new (w) PtrWrapper(new int); // no warn
Anton Yartsev13df0362013-03-25 01:35:45 +000090}
91
Anton Yartsevb50f4ba2015-04-14 14:18:04 +000092//-----------------------------------------
93// check for usage of zero-allocated memory
94//-----------------------------------------
95
96void testUseZeroAlloc1() {
97 int *p = (int *)operator new(0);
98 *p = 1; // expected-warning {{Use of zero-allocated memory}}
99 delete p;
100}
101
102int testUseZeroAlloc2() {
103 int *p = (int *)operator new[](0);
104 return p[0]; // expected-warning {{Use of zero-allocated memory}}
105 delete[] p;
106}
107
108void f(int);
109
110void testUseZeroAlloc3() {
111 int *p = new int[0];
112 f(*p); // expected-warning {{Use of zero-allocated memory}}
113 delete[] p;
114}
115
Anton Yartsev13df0362013-03-25 01:35:45 +0000116//---------------
117// other checks
118//---------------
119
Anton Yartsevcb2ccd62013-04-10 22:21:41 +0000120class SomeClass {
121public:
122 void f(int *p);
123};
Anton Yartsev13df0362013-03-25 01:35:45 +0000124
Anton Yartsevcb2ccd62013-04-10 22:21:41 +0000125void f(int *p1, int *p2 = 0, int *p3 = 0);
126void g(SomeClass &c, ...);
127
128void testUseFirstArgAfterDelete() {
Anton Yartsev13df0362013-03-25 01:35:45 +0000129 int *p = new int;
130 delete p;
131 f(p); // expected-warning{{Use of memory after it is freed}}
132}
133
Anton Yartsevcb2ccd62013-04-10 22:21:41 +0000134void testUseMiddleArgAfterDelete(int *p) {
135 delete p;
136 f(0, p); // expected-warning{{Use of memory after it is freed}}
137}
138
139void testUseLastArgAfterDelete(int *p) {
140 delete p;
141 f(0, 0, p); // expected-warning{{Use of memory after it is freed}}
142}
143
Anton Yartsev8fc29db2013-04-10 22:36:16 +0000144void testUseSeveralArgsAfterDelete(int *p) {
145 delete p;
146 f(p, p, p); // expected-warning{{Use of memory after it is freed}}
147}
148
Anton Yartsevcb2ccd62013-04-10 22:21:41 +0000149void testUseRefArgAfterDelete(SomeClass &c) {
150 delete &c;
151 g(c); // expected-warning{{Use of memory after it is freed}}
152}
153
154void testVariadicArgAfterDelete() {
155 SomeClass c;
156 int *p = new int;
157 delete p;
158 g(c, 0, p); // expected-warning{{Use of memory after it is freed}}
159}
160
161void testUseMethodArgAfterDelete(int *p) {
162 SomeClass *c = new SomeClass;
163 delete p;
164 c->f(p); // expected-warning{{Use of memory after it is freed}}
165}
166
167void testUseThisAfterDelete() {
168 SomeClass *c = new SomeClass;
169 delete c;
170 c->f(0); // expected-warning{{Use of memory after it is freed}}
171}
172
Anton Yartsev13df0362013-03-25 01:35:45 +0000173void testDoubleDelete() {
174 int *p = new int;
175 delete p;
176 delete p; // expected-warning{{Attempt to free released memory}}
177}
178
179void testExprDeleteArg() {
180 int i;
Anton Yartsev05789592013-03-28 17:05:19 +0000181 delete &i; // expected-warning{{Argument to 'delete' is the address of the local variable 'i', which is not memory allocated by 'new'}}
182}
Anton Yartsev13df0362013-03-25 01:35:45 +0000183
184void testExprDeleteArrArg() {
185 int i;
Anton Yartsev05789592013-03-28 17:05:19 +0000186 delete[] &i; // expected-warning{{Argument to 'delete[]' is the address of the local variable 'i', which is not memory allocated by 'new[]'}}
187}
Anton Yartsev13df0362013-03-25 01:35:45 +0000188
189void testAllocDeallocNames() {
190 int *p = new(std::nothrow) int[1];
Anton Yartsev05789592013-03-28 17:05:19 +0000191 delete[] (++p); // expected-warning{{Argument to 'delete[]' is offset by 4 bytes from the start of memory allocated by 'new[]'}}
192}
Anton Yartsev13df0362013-03-25 01:35:45 +0000193
Anna Zaks333481b2013-03-28 23:15:29 +0000194//--------------------------------
195// Test escape of newed const pointer. Note, a const pointer can be deleted.
196//--------------------------------
197struct StWithConstPtr {
198 const int *memp;
199};
200void escape(const int &x);
201void escapeStruct(const StWithConstPtr &x);
202void escapePtr(const StWithConstPtr *x);
203void escapeVoidPtr(const void *x);
204
205void testConstEscape() {
206 int *p = new int(1);
207 escape(*p);
208} // no-warning
209
210void testConstEscapeStruct() {
211 StWithConstPtr *St = new StWithConstPtr();
212 escapeStruct(*St);
213} // no-warning
214
215void testConstEscapeStructPtr() {
216 StWithConstPtr *St = new StWithConstPtr();
217 escapePtr(St);
218} // no-warning
219
220void testConstEscapeMember() {
221 StWithConstPtr St;
222 St.memp = new int(2);
223 escapeVoidPtr(St.memp);
224} // no-warning
225
226void testConstEscapePlacementNew() {
227 int *x = (int *)malloc(sizeof(int));
228 void *y = new (x) int;
229 escapeVoidPtr(y);
230} // no-warning
Jordan Rosefbe4d852013-05-17 02:16:49 +0000231
Jordan Rose867b185e2013-08-09 00:55:47 +0000232//============== Test Uninitialized delete delete[]========================
233void testUninitDelete() {
234 int *x;
235 int * y = new int;
236 delete y;
237 delete x; // expected-warning{{Argument to 'delete' is uninitialized}}
238}
239
240void testUninitDeleteArray() {
241 int *x;
242 int * y = new int[5];
243 delete[] y;
244 delete[] x; // expected-warning{{Argument to 'delete[]' is uninitialized}}
245}
246
247void testUninitFree() {
248 int *x;
Daniel Marjamaki3d8d6ed2017-03-08 15:22:24 +0000249 free(x); // expected-warning{{1st function call argument is an uninitialized value}}
Jordan Rose867b185e2013-08-09 00:55:47 +0000250}
251
252void testUninitDeleteSink() {
253 int *x;
254 delete x; // expected-warning{{Argument to 'delete' is uninitialized}}
255 (*(volatile int *)0 = 1); // no warn
256}
257
258void testUninitDeleteArraySink() {
259 int *x;
260 delete[] x; // expected-warning{{Argument to 'delete[]' is uninitialized}}
261 (*(volatile int *)0 = 1); // no warn
262}
Jordan Rosefbe4d852013-05-17 02:16:49 +0000263
264namespace reference_count {
265 class control_block {
266 unsigned count;
267 public:
268 control_block() : count(0) {}
269 void retain() { ++count; }
270 int release() { return --count; }
271 };
272
273 template <typename T>
274 class shared_ptr {
275 T *p;
276 control_block *control;
277
278 public:
279 shared_ptr() : p(0), control(0) {}
280 explicit shared_ptr(T *p) : p(p), control(new control_block) {
281 control->retain();
282 }
283 shared_ptr(shared_ptr &other) : p(other.p), control(other.control) {
284 if (control)
285 control->retain();
286 }
287 ~shared_ptr() {
288 if (control && control->release() == 0) {
289 delete p;
290 delete control;
291 }
292 };
293
294 T &operator *() {
295 return *p;
296 };
297
298 void swap(shared_ptr &other) {
299 T *tmp = p;
300 p = other.p;
301 other.p = tmp;
302
303 control_block *ctrlTmp = control;
304 control = other.control;
305 other.control = ctrlTmp;
306 }
307 };
308
309 void testSingle() {
310 shared_ptr<int> a(new int);
311 *a = 1;
312 }
313
314 void testDouble() {
315 shared_ptr<int> a(new int);
316 shared_ptr<int> b = a;
317 *a = 1;
318 }
319
320 void testInvalidated() {
321 shared_ptr<int> a(new int);
322 shared_ptr<int> b = a;
323 *a = 1;
324
325 extern void use(shared_ptr<int> &);
326 use(b);
327 }
328
329 void testNestedScope() {
330 shared_ptr<int> a(new int);
331 {
332 shared_ptr<int> b = a;
333 }
334 *a = 1;
335 }
336
337 void testSwap() {
338 shared_ptr<int> a(new int);
339 shared_ptr<int> b;
340 shared_ptr<int> c = a;
341 shared_ptr<int>(c).swap(b);
342 }
343
344 void testUseAfterFree() {
345 int *p = new int;
346 {
347 shared_ptr<int> a(p);
348 shared_ptr<int> b = a;
349 }
350
351 // FIXME: We should get a warning here, but we don't because we've
352 // conservatively modeled ~shared_ptr.
353 *p = 1;
354 }
355}
356
Jordan Rose1ccc43d2013-09-25 16:06:17 +0000357// Test double delete
358class DerefClass{
359public:
360 int *x;
361 DerefClass() {}
Jordan Rose656fdd52014-01-08 18:46:55 +0000362 ~DerefClass() {*x = 1;}
Jordan Rose1ccc43d2013-09-25 16:06:17 +0000363};
364
365void testDoubleDeleteClassInstance() {
366 DerefClass *foo = new DerefClass();
367 delete foo;
Jordan Rose656fdd52014-01-08 18:46:55 +0000368 delete foo; // expected-warning {{Attempt to delete released memory}}
Jordan Rose1ccc43d2013-09-25 16:06:17 +0000369}
370
371class EmptyClass{
372public:
373 EmptyClass() {}
374 ~EmptyClass() {}
375};
376
377void testDoubleDeleteEmptyClass() {
378 EmptyClass *foo = new EmptyClass();
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}
Gabor Horvath44583ce62016-08-08 09:22:59 +0000382
383struct Base {
384 virtual ~Base() {}
385};
386
387struct Derived : Base {
388};
389
390Base *allocate() {
391 return new Derived;
392}
393
394void shouldNotReportLeak() {
395 Derived *p = (Derived *)allocate();
396 delete p;
397}