blob: 78a0015ca5325084a766cf7143cd0cd5e1e8abce [file] [log] [blame]
Jordan Rose10ad0812013-04-05 17:55:07 +00001// RUN: %clang_cc1 -analyze -analyzer-checker=core,cplusplus.NewDelete -std=c++11 -fblocks -verify %s
Anton Yartsev6ca45c92014-10-21 12:41:36 +00002// RUN: %clang_cc1 -analyze -analyzer-checker=core,cplusplus.NewDeleteLeaks -DLEAKS -std=c++11 -fblocks -verify %s
Anton Yartsev13df0362013-03-25 01:35:45 +00003#include "Inputs/system-header-simulator-cxx.h"
Anton Yartsev13df0362013-03-25 01:35:45 +00004
5typedef __typeof__(sizeof(int)) size_t;
6extern "C" void *malloc(size_t);
Jordan Rose867b185e2013-08-09 00:55:47 +00007extern "C" void free (void* ptr);
Anton Yartsev13df0362013-03-25 01:35:45 +00008int *global;
9
10//------------------
11// check for leaks
12//------------------
13
Anton Yartsev8b662702013-03-28 16:10:38 +000014//----- Standard non-placement operators
15void testGlobalOpNew() {
Anton Yartsev13df0362013-03-25 01:35:45 +000016 void *p = operator new(0);
Jordan Rose26330562013-04-05 17:55:00 +000017}
18#ifdef LEAKS
Anna Zaksa1de8562013-04-06 00:41:36 +000019// expected-warning@-2{{Potential leak of memory pointed to by 'p'}}
Jordan Rose26330562013-04-05 17:55:00 +000020#endif
Anton Yartsev13df0362013-03-25 01:35:45 +000021
Anton Yartsev8b662702013-03-28 16:10:38 +000022void testGlobalOpNewArray() {
23 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 Yartsev8b662702013-03-28 16:10:38 +000028
29void testGlobalNewExpr() {
Anton Yartsev13df0362013-03-25 01:35:45 +000030 int *p = new int;
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 Yartsev13df0362013-03-25 01:35:45 +000035
Anton Yartsev8b662702013-03-28 16:10:38 +000036void testGlobalNewExprArray() {
37 int *p = new int[0];
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 +000043//----- Standard nothrow placement operators
44void testGlobalNoThrowPlacementOpNewBeforeOverload() {
45 void *p = operator new(0, std::nothrow);
Jordan Rose26330562013-04-05 17:55:00 +000046}
47#ifdef LEAKS
Anna Zaksa1de8562013-04-06 00:41:36 +000048// expected-warning@-2{{Potential leak of memory pointed to by 'p'}}
Jordan Rose26330562013-04-05 17:55:00 +000049#endif
Anton Yartsev8b662702013-03-28 16:10:38 +000050
51void testGlobalNoThrowPlacementExprNewBeforeOverload() {
52 int *p = new(std::nothrow) int;
Jordan Rose26330562013-04-05 17:55:00 +000053}
54#ifdef LEAKS
Anna Zaksa1de8562013-04-06 00:41:36 +000055// expected-warning@-2{{Potential leak of memory pointed to by 'p'}}
Jordan Rose26330562013-04-05 17:55:00 +000056#endif
Anton Yartsev8b662702013-03-28 16:10:38 +000057
Anton Yartsev8b662702013-03-28 16:10:38 +000058//----- Standard pointer placement operators
59void testGlobalPointerPlacementNew() {
Anton Yartsev13df0362013-03-25 01:35:45 +000060 int i;
Anton Yartsev13df0362013-03-25 01:35:45 +000061
Anton Yartsev8b662702013-03-28 16:10:38 +000062 void *p1 = operator new(0, &i); // no warn
Anton Yartsev13df0362013-03-25 01:35:45 +000063
Anton Yartsev8b662702013-03-28 16:10:38 +000064 void *p2 = operator new[](0, &i); // no warn
Anton Yartsev13df0362013-03-25 01:35:45 +000065
Anton Yartsev8b662702013-03-28 16:10:38 +000066 int *p3 = new(&i) int; // no warn
Anton Yartsev13df0362013-03-25 01:35:45 +000067
Anton Yartsev8b662702013-03-28 16:10:38 +000068 int *p4 = new(&i) int[0]; // no warn
Anton Yartsev13df0362013-03-25 01:35:45 +000069}
70
Anton Yartsev8b662702013-03-28 16:10:38 +000071//----- Other cases
72void testNewMemoryIsInHeap() {
73 int *p = new int;
74 if (global != p) // condition is always true as 'p' wraps a heap region that
75 // is different from a region wrapped by 'global'
76 global = p; // pointer escapes
Anton Yartsev13df0362013-03-25 01:35:45 +000077}
78
Anton Yartsev8b662702013-03-28 16:10:38 +000079struct PtrWrapper {
80 int *x;
Anton Yartsev13df0362013-03-25 01:35:45 +000081
Anton Yartsev8b662702013-03-28 16:10:38 +000082 PtrWrapper(int *input) : x(input) {}
83};
Anton Yartsev13df0362013-03-25 01:35:45 +000084
Anton Yartsev8b662702013-03-28 16:10:38 +000085void testNewInvalidationPlacement(PtrWrapper *w) {
86 // Ensure that we don't consider this a leak.
87 new (w) PtrWrapper(new int); // no warn
Anton Yartsev13df0362013-03-25 01:35:45 +000088}
89
Anton Yartsevb50f4ba2015-04-14 14:18:04 +000090//-----------------------------------------
91// check for usage of zero-allocated memory
92//-----------------------------------------
93
94void testUseZeroAlloc1() {
95 int *p = (int *)operator new(0);
96 *p = 1; // expected-warning {{Use of zero-allocated memory}}
97 delete p;
98}
99
100int testUseZeroAlloc2() {
101 int *p = (int *)operator new[](0);
102 return p[0]; // expected-warning {{Use of zero-allocated memory}}
103 delete[] p;
104}
105
106void f(int);
107
108void testUseZeroAlloc3() {
109 int *p = new int[0];
110 f(*p); // expected-warning {{Use of zero-allocated memory}}
111 delete[] p;
112}
113
Anton Yartsev13df0362013-03-25 01:35:45 +0000114//---------------
115// other checks
116//---------------
117
Anton Yartsevcb2ccd62013-04-10 22:21:41 +0000118class SomeClass {
119public:
120 void f(int *p);
121};
Anton Yartsev13df0362013-03-25 01:35:45 +0000122
Anton Yartsevcb2ccd62013-04-10 22:21:41 +0000123void f(int *p1, int *p2 = 0, int *p3 = 0);
124void g(SomeClass &c, ...);
125
126void testUseFirstArgAfterDelete() {
Anton Yartsev13df0362013-03-25 01:35:45 +0000127 int *p = new int;
128 delete p;
129 f(p); // expected-warning{{Use of memory after it is freed}}
130}
131
Anton Yartsevcb2ccd62013-04-10 22:21:41 +0000132void testUseMiddleArgAfterDelete(int *p) {
133 delete p;
134 f(0, p); // expected-warning{{Use of memory after it is freed}}
135}
136
137void testUseLastArgAfterDelete(int *p) {
138 delete p;
139 f(0, 0, p); // expected-warning{{Use of memory after it is freed}}
140}
141
Anton Yartsev8fc29db2013-04-10 22:36:16 +0000142void testUseSeveralArgsAfterDelete(int *p) {
143 delete p;
144 f(p, p, p); // expected-warning{{Use of memory after it is freed}}
145}
146
Anton Yartsevcb2ccd62013-04-10 22:21:41 +0000147void testUseRefArgAfterDelete(SomeClass &c) {
148 delete &c;
149 g(c); // expected-warning{{Use of memory after it is freed}}
150}
151
152void testVariadicArgAfterDelete() {
153 SomeClass c;
154 int *p = new int;
155 delete p;
156 g(c, 0, p); // expected-warning{{Use of memory after it is freed}}
157}
158
159void testUseMethodArgAfterDelete(int *p) {
160 SomeClass *c = new SomeClass;
161 delete p;
162 c->f(p); // expected-warning{{Use of memory after it is freed}}
163}
164
165void testUseThisAfterDelete() {
166 SomeClass *c = new SomeClass;
167 delete c;
168 c->f(0); // expected-warning{{Use of memory after it is freed}}
169}
170
Anton Yartsev13df0362013-03-25 01:35:45 +0000171void testDoubleDelete() {
172 int *p = new int;
173 delete p;
174 delete p; // expected-warning{{Attempt to free released memory}}
175}
176
177void testExprDeleteArg() {
178 int i;
Anton Yartsev05789592013-03-28 17:05:19 +0000179 delete &i; // expected-warning{{Argument to 'delete' is the address of the local variable 'i', which is not memory allocated by 'new'}}
180}
Anton Yartsev13df0362013-03-25 01:35:45 +0000181
182void testExprDeleteArrArg() {
183 int i;
Anton Yartsev05789592013-03-28 17:05:19 +0000184 delete[] &i; // expected-warning{{Argument to 'delete[]' is the address of the local variable 'i', which is not memory allocated by 'new[]'}}
185}
Anton Yartsev13df0362013-03-25 01:35:45 +0000186
187void testAllocDeallocNames() {
188 int *p = new(std::nothrow) int[1];
Anton Yartsev05789592013-03-28 17:05:19 +0000189 delete[] (++p); // expected-warning{{Argument to 'delete[]' is offset by 4 bytes from the start of memory allocated by 'new[]'}}
190}
Anton Yartsev13df0362013-03-25 01:35:45 +0000191
Anna Zaks333481b2013-03-28 23:15:29 +0000192//--------------------------------
193// Test escape of newed const pointer. Note, a const pointer can be deleted.
194//--------------------------------
195struct StWithConstPtr {
196 const int *memp;
197};
198void escape(const int &x);
199void escapeStruct(const StWithConstPtr &x);
200void escapePtr(const StWithConstPtr *x);
201void escapeVoidPtr(const void *x);
202
203void testConstEscape() {
204 int *p = new int(1);
205 escape(*p);
206} // no-warning
207
208void testConstEscapeStruct() {
209 StWithConstPtr *St = new StWithConstPtr();
210 escapeStruct(*St);
211} // no-warning
212
213void testConstEscapeStructPtr() {
214 StWithConstPtr *St = new StWithConstPtr();
215 escapePtr(St);
216} // no-warning
217
218void testConstEscapeMember() {
219 StWithConstPtr St;
220 St.memp = new int(2);
221 escapeVoidPtr(St.memp);
222} // no-warning
223
224void testConstEscapePlacementNew() {
225 int *x = (int *)malloc(sizeof(int));
226 void *y = new (x) int;
227 escapeVoidPtr(y);
228} // no-warning
Jordan Rosefbe4d852013-05-17 02:16:49 +0000229
Jordan Rose867b185e2013-08-09 00:55:47 +0000230//============== Test Uninitialized delete delete[]========================
231void testUninitDelete() {
232 int *x;
233 int * y = new int;
234 delete y;
235 delete x; // expected-warning{{Argument to 'delete' is uninitialized}}
236}
237
238void testUninitDeleteArray() {
239 int *x;
240 int * y = new int[5];
241 delete[] y;
242 delete[] x; // expected-warning{{Argument to 'delete[]' is uninitialized}}
243}
244
245void testUninitFree() {
246 int *x;
247 free(x); // expected-warning{{Function call argument is an uninitialized value}}
248}
249
250void testUninitDeleteSink() {
251 int *x;
252 delete x; // expected-warning{{Argument to 'delete' is uninitialized}}
253 (*(volatile int *)0 = 1); // no warn
254}
255
256void testUninitDeleteArraySink() {
257 int *x;
258 delete[] x; // expected-warning{{Argument to 'delete[]' is uninitialized}}
259 (*(volatile int *)0 = 1); // no warn
260}
Jordan Rosefbe4d852013-05-17 02:16:49 +0000261
262namespace reference_count {
263 class control_block {
264 unsigned count;
265 public:
266 control_block() : count(0) {}
267 void retain() { ++count; }
268 int release() { return --count; }
269 };
270
271 template <typename T>
272 class shared_ptr {
273 T *p;
274 control_block *control;
275
276 public:
277 shared_ptr() : p(0), control(0) {}
278 explicit shared_ptr(T *p) : p(p), control(new control_block) {
279 control->retain();
280 }
281 shared_ptr(shared_ptr &other) : p(other.p), control(other.control) {
282 if (control)
283 control->retain();
284 }
285 ~shared_ptr() {
286 if (control && control->release() == 0) {
287 delete p;
288 delete control;
289 }
290 };
291
292 T &operator *() {
293 return *p;
294 };
295
296 void swap(shared_ptr &other) {
297 T *tmp = p;
298 p = other.p;
299 other.p = tmp;
300
301 control_block *ctrlTmp = control;
302 control = other.control;
303 other.control = ctrlTmp;
304 }
305 };
306
307 void testSingle() {
308 shared_ptr<int> a(new int);
309 *a = 1;
310 }
311
312 void testDouble() {
313 shared_ptr<int> a(new int);
314 shared_ptr<int> b = a;
315 *a = 1;
316 }
317
318 void testInvalidated() {
319 shared_ptr<int> a(new int);
320 shared_ptr<int> b = a;
321 *a = 1;
322
323 extern void use(shared_ptr<int> &);
324 use(b);
325 }
326
327 void testNestedScope() {
328 shared_ptr<int> a(new int);
329 {
330 shared_ptr<int> b = a;
331 }
332 *a = 1;
333 }
334
335 void testSwap() {
336 shared_ptr<int> a(new int);
337 shared_ptr<int> b;
338 shared_ptr<int> c = a;
339 shared_ptr<int>(c).swap(b);
340 }
341
342 void testUseAfterFree() {
343 int *p = new int;
344 {
345 shared_ptr<int> a(p);
346 shared_ptr<int> b = a;
347 }
348
349 // FIXME: We should get a warning here, but we don't because we've
350 // conservatively modeled ~shared_ptr.
351 *p = 1;
352 }
353}
354
Jordan Rose1ccc43d2013-09-25 16:06:17 +0000355// Test double delete
356class DerefClass{
357public:
358 int *x;
359 DerefClass() {}
Jordan Rose656fdd52014-01-08 18:46:55 +0000360 ~DerefClass() {*x = 1;}
Jordan Rose1ccc43d2013-09-25 16:06:17 +0000361};
362
363void testDoubleDeleteClassInstance() {
364 DerefClass *foo = new DerefClass();
365 delete foo;
Jordan Rose656fdd52014-01-08 18:46:55 +0000366 delete foo; // expected-warning {{Attempt to delete released memory}}
Jordan Rose1ccc43d2013-09-25 16:06:17 +0000367}
368
369class EmptyClass{
370public:
371 EmptyClass() {}
372 ~EmptyClass() {}
373};
374
375void testDoubleDeleteEmptyClass() {
376 EmptyClass *foo = new EmptyClass();
377 delete foo;
Jordan Rose656fdd52014-01-08 18:46:55 +0000378 delete foo; // expected-warning {{Attempt to delete released memory}}
Jordan Rose1ccc43d2013-09-25 16:06:17 +0000379}
Gabor Horvath44583ce62016-08-08 09:22:59 +0000380
381struct Base {
382 virtual ~Base() {}
383};
384
385struct Derived : Base {
386};
387
388Base *allocate() {
389 return new Derived;
390}
391
392void shouldNotReportLeak() {
393 Derived *p = (Derived *)allocate();
394 delete p;
395}