blob: 84176c9097ca85f8c89caf99296d16d982c97a91 [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
90//---------------
91// other checks
92//---------------
93
Anton Yartsevcb2ccd62013-04-10 22:21:41 +000094class SomeClass {
95public:
96 void f(int *p);
97};
Anton Yartsev13df0362013-03-25 01:35:45 +000098
Anton Yartsevcb2ccd62013-04-10 22:21:41 +000099void f(int *p1, int *p2 = 0, int *p3 = 0);
100void g(SomeClass &c, ...);
101
102void testUseFirstArgAfterDelete() {
Anton Yartsev13df0362013-03-25 01:35:45 +0000103 int *p = new int;
104 delete p;
105 f(p); // expected-warning{{Use of memory after it is freed}}
106}
107
Anton Yartsevcb2ccd62013-04-10 22:21:41 +0000108void testUseMiddleArgAfterDelete(int *p) {
109 delete p;
110 f(0, p); // expected-warning{{Use of memory after it is freed}}
111}
112
113void testUseLastArgAfterDelete(int *p) {
114 delete p;
115 f(0, 0, p); // expected-warning{{Use of memory after it is freed}}
116}
117
Anton Yartsev8fc29db2013-04-10 22:36:16 +0000118void testUseSeveralArgsAfterDelete(int *p) {
119 delete p;
120 f(p, p, p); // expected-warning{{Use of memory after it is freed}}
121}
122
Anton Yartsevcb2ccd62013-04-10 22:21:41 +0000123void testUseRefArgAfterDelete(SomeClass &c) {
124 delete &c;
125 g(c); // expected-warning{{Use of memory after it is freed}}
126}
127
128void testVariadicArgAfterDelete() {
129 SomeClass c;
130 int *p = new int;
131 delete p;
132 g(c, 0, p); // expected-warning{{Use of memory after it is freed}}
133}
134
135void testUseMethodArgAfterDelete(int *p) {
136 SomeClass *c = new SomeClass;
137 delete p;
138 c->f(p); // expected-warning{{Use of memory after it is freed}}
139}
140
141void testUseThisAfterDelete() {
142 SomeClass *c = new SomeClass;
143 delete c;
144 c->f(0); // expected-warning{{Use of memory after it is freed}}
145}
146
Anton Yartsev13df0362013-03-25 01:35:45 +0000147void testDeleteAlloca() {
148 int *p = (int *)__builtin_alloca(sizeof(int));
Anton Yartsev05789592013-03-28 17:05:19 +0000149 delete p; // expected-warning{{Memory allocated by alloca() should not be deallocated}}
Anton Yartsev13df0362013-03-25 01:35:45 +0000150}
151
152void testDoubleDelete() {
153 int *p = new int;
154 delete p;
155 delete p; // expected-warning{{Attempt to free released memory}}
156}
157
158void testExprDeleteArg() {
159 int i;
Anton Yartsev05789592013-03-28 17:05:19 +0000160 delete &i; // expected-warning{{Argument to 'delete' is the address of the local variable 'i', which is not memory allocated by 'new'}}
161}
Anton Yartsev13df0362013-03-25 01:35:45 +0000162
163void testExprDeleteArrArg() {
164 int i;
Anton Yartsev05789592013-03-28 17:05:19 +0000165 delete[] &i; // expected-warning{{Argument to 'delete[]' is the address of the local variable 'i', which is not memory allocated by 'new[]'}}
166}
Anton Yartsev13df0362013-03-25 01:35:45 +0000167
168void testAllocDeallocNames() {
169 int *p = new(std::nothrow) int[1];
Anton Yartsev05789592013-03-28 17:05:19 +0000170 delete[] (++p); // expected-warning{{Argument to 'delete[]' is offset by 4 bytes from the start of memory allocated by 'new[]'}}
171}
Anton Yartsev13df0362013-03-25 01:35:45 +0000172
Anna Zaks333481b2013-03-28 23:15:29 +0000173//--------------------------------
174// Test escape of newed const pointer. Note, a const pointer can be deleted.
175//--------------------------------
176struct StWithConstPtr {
177 const int *memp;
178};
179void escape(const int &x);
180void escapeStruct(const StWithConstPtr &x);
181void escapePtr(const StWithConstPtr *x);
182void escapeVoidPtr(const void *x);
183
184void testConstEscape() {
185 int *p = new int(1);
186 escape(*p);
187} // no-warning
188
189void testConstEscapeStruct() {
190 StWithConstPtr *St = new StWithConstPtr();
191 escapeStruct(*St);
192} // no-warning
193
194void testConstEscapeStructPtr() {
195 StWithConstPtr *St = new StWithConstPtr();
196 escapePtr(St);
197} // no-warning
198
199void testConstEscapeMember() {
200 StWithConstPtr St;
201 St.memp = new int(2);
202 escapeVoidPtr(St.memp);
203} // no-warning
204
205void testConstEscapePlacementNew() {
206 int *x = (int *)malloc(sizeof(int));
207 void *y = new (x) int;
208 escapeVoidPtr(y);
209} // no-warning
Jordan Rosefbe4d852013-05-17 02:16:49 +0000210
Jordan Rose867b185e2013-08-09 00:55:47 +0000211//============== Test Uninitialized delete delete[]========================
212void testUninitDelete() {
213 int *x;
214 int * y = new int;
215 delete y;
216 delete x; // expected-warning{{Argument to 'delete' is uninitialized}}
217}
218
219void testUninitDeleteArray() {
220 int *x;
221 int * y = new int[5];
222 delete[] y;
223 delete[] x; // expected-warning{{Argument to 'delete[]' is uninitialized}}
224}
225
226void testUninitFree() {
227 int *x;
228 free(x); // expected-warning{{Function call argument is an uninitialized value}}
229}
230
231void testUninitDeleteSink() {
232 int *x;
233 delete x; // expected-warning{{Argument to 'delete' is uninitialized}}
234 (*(volatile int *)0 = 1); // no warn
235}
236
237void testUninitDeleteArraySink() {
238 int *x;
239 delete[] x; // expected-warning{{Argument to 'delete[]' is uninitialized}}
240 (*(volatile int *)0 = 1); // no warn
241}
Jordan Rosefbe4d852013-05-17 02:16:49 +0000242
243namespace reference_count {
244 class control_block {
245 unsigned count;
246 public:
247 control_block() : count(0) {}
248 void retain() { ++count; }
249 int release() { return --count; }
250 };
251
252 template <typename T>
253 class shared_ptr {
254 T *p;
255 control_block *control;
256
257 public:
258 shared_ptr() : p(0), control(0) {}
259 explicit shared_ptr(T *p) : p(p), control(new control_block) {
260 control->retain();
261 }
262 shared_ptr(shared_ptr &other) : p(other.p), control(other.control) {
263 if (control)
264 control->retain();
265 }
266 ~shared_ptr() {
267 if (control && control->release() == 0) {
268 delete p;
269 delete control;
270 }
271 };
272
273 T &operator *() {
274 return *p;
275 };
276
277 void swap(shared_ptr &other) {
278 T *tmp = p;
279 p = other.p;
280 other.p = tmp;
281
282 control_block *ctrlTmp = control;
283 control = other.control;
284 other.control = ctrlTmp;
285 }
286 };
287
288 void testSingle() {
289 shared_ptr<int> a(new int);
290 *a = 1;
291 }
292
293 void testDouble() {
294 shared_ptr<int> a(new int);
295 shared_ptr<int> b = a;
296 *a = 1;
297 }
298
299 void testInvalidated() {
300 shared_ptr<int> a(new int);
301 shared_ptr<int> b = a;
302 *a = 1;
303
304 extern void use(shared_ptr<int> &);
305 use(b);
306 }
307
308 void testNestedScope() {
309 shared_ptr<int> a(new int);
310 {
311 shared_ptr<int> b = a;
312 }
313 *a = 1;
314 }
315
316 void testSwap() {
317 shared_ptr<int> a(new int);
318 shared_ptr<int> b;
319 shared_ptr<int> c = a;
320 shared_ptr<int>(c).swap(b);
321 }
322
323 void testUseAfterFree() {
324 int *p = new int;
325 {
326 shared_ptr<int> a(p);
327 shared_ptr<int> b = a;
328 }
329
330 // FIXME: We should get a warning here, but we don't because we've
331 // conservatively modeled ~shared_ptr.
332 *p = 1;
333 }
334}
335
Jordan Rose1ccc43d2013-09-25 16:06:17 +0000336// Test double delete
337class DerefClass{
338public:
339 int *x;
340 DerefClass() {}
Jordan Rose656fdd52014-01-08 18:46:55 +0000341 ~DerefClass() {*x = 1;}
Jordan Rose1ccc43d2013-09-25 16:06:17 +0000342};
343
344void testDoubleDeleteClassInstance() {
345 DerefClass *foo = new DerefClass();
346 delete foo;
Jordan Rose656fdd52014-01-08 18:46:55 +0000347 delete foo; // expected-warning {{Attempt to delete released memory}}
Jordan Rose1ccc43d2013-09-25 16:06:17 +0000348}
349
350class EmptyClass{
351public:
352 EmptyClass() {}
353 ~EmptyClass() {}
354};
355
356void testDoubleDeleteEmptyClass() {
357 EmptyClass *foo = new EmptyClass();
358 delete foo;
Jordan Rose656fdd52014-01-08 18:46:55 +0000359 delete foo; // expected-warning {{Attempt to delete released memory}}
Jordan Rose1ccc43d2013-09-25 16:06:17 +0000360}