1f4a2713aSLionel Sambuc // RUN: %clang_cc1 -analyze -analyzer-checker=core,cplusplus.NewDelete -std=c++11 -fblocks -verify %s
2*0a6a1f1dSLionel Sambuc // RUN: %clang_cc1 -analyze -analyzer-checker=core,cplusplus.NewDeleteLeaks -DLEAKS -std=c++11 -fblocks -verify %s
3f4a2713aSLionel Sambuc #include "Inputs/system-header-simulator-cxx.h"
4f4a2713aSLionel Sambuc
5f4a2713aSLionel Sambuc typedef __typeof__(sizeof(int)) size_t;
6f4a2713aSLionel Sambuc extern "C" void *malloc(size_t);
7f4a2713aSLionel Sambuc extern "C" void free (void* ptr);
8f4a2713aSLionel Sambuc int *global;
9f4a2713aSLionel Sambuc
10f4a2713aSLionel Sambuc //------------------
11f4a2713aSLionel Sambuc // check for leaks
12f4a2713aSLionel Sambuc //------------------
13f4a2713aSLionel Sambuc
14f4a2713aSLionel Sambuc //----- Standard non-placement operators
testGlobalOpNew()15f4a2713aSLionel Sambuc void testGlobalOpNew() {
16f4a2713aSLionel Sambuc void *p = operator new(0);
17f4a2713aSLionel Sambuc }
18f4a2713aSLionel Sambuc #ifdef LEAKS
19f4a2713aSLionel Sambuc // expected-warning@-2{{Potential leak of memory pointed to by 'p'}}
20f4a2713aSLionel Sambuc #endif
21f4a2713aSLionel Sambuc
testGlobalOpNewArray()22f4a2713aSLionel Sambuc void testGlobalOpNewArray() {
23f4a2713aSLionel Sambuc void *p = operator new[](0);
24f4a2713aSLionel Sambuc }
25f4a2713aSLionel Sambuc #ifdef LEAKS
26f4a2713aSLionel Sambuc // expected-warning@-2{{Potential leak of memory pointed to by 'p'}}
27f4a2713aSLionel Sambuc #endif
28f4a2713aSLionel Sambuc
testGlobalNewExpr()29f4a2713aSLionel Sambuc void testGlobalNewExpr() {
30f4a2713aSLionel Sambuc int *p = new int;
31f4a2713aSLionel Sambuc }
32f4a2713aSLionel Sambuc #ifdef LEAKS
33f4a2713aSLionel Sambuc // expected-warning@-2{{Potential leak of memory pointed to by 'p'}}
34f4a2713aSLionel Sambuc #endif
35f4a2713aSLionel Sambuc
testGlobalNewExprArray()36f4a2713aSLionel Sambuc void testGlobalNewExprArray() {
37f4a2713aSLionel Sambuc int *p = new int[0];
38f4a2713aSLionel Sambuc }
39f4a2713aSLionel Sambuc #ifdef LEAKS
40f4a2713aSLionel Sambuc // expected-warning@-2{{Potential leak of memory pointed to by 'p'}}
41f4a2713aSLionel Sambuc #endif
42f4a2713aSLionel Sambuc
43f4a2713aSLionel Sambuc //----- Standard nothrow placement operators
testGlobalNoThrowPlacementOpNewBeforeOverload()44f4a2713aSLionel Sambuc void testGlobalNoThrowPlacementOpNewBeforeOverload() {
45f4a2713aSLionel Sambuc void *p = operator new(0, std::nothrow);
46f4a2713aSLionel Sambuc }
47f4a2713aSLionel Sambuc #ifdef LEAKS
48f4a2713aSLionel Sambuc // expected-warning@-2{{Potential leak of memory pointed to by 'p'}}
49f4a2713aSLionel Sambuc #endif
50f4a2713aSLionel Sambuc
testGlobalNoThrowPlacementExprNewBeforeOverload()51f4a2713aSLionel Sambuc void testGlobalNoThrowPlacementExprNewBeforeOverload() {
52f4a2713aSLionel Sambuc int *p = new(std::nothrow) int;
53f4a2713aSLionel Sambuc }
54f4a2713aSLionel Sambuc #ifdef LEAKS
55f4a2713aSLionel Sambuc // expected-warning@-2{{Potential leak of memory pointed to by 'p'}}
56f4a2713aSLionel Sambuc #endif
57f4a2713aSLionel Sambuc
58f4a2713aSLionel Sambuc //----- Standard pointer placement operators
testGlobalPointerPlacementNew()59f4a2713aSLionel Sambuc void testGlobalPointerPlacementNew() {
60f4a2713aSLionel Sambuc int i;
61f4a2713aSLionel Sambuc
62f4a2713aSLionel Sambuc void *p1 = operator new(0, &i); // no warn
63f4a2713aSLionel Sambuc
64f4a2713aSLionel Sambuc void *p2 = operator new[](0, &i); // no warn
65f4a2713aSLionel Sambuc
66f4a2713aSLionel Sambuc int *p3 = new(&i) int; // no warn
67f4a2713aSLionel Sambuc
68f4a2713aSLionel Sambuc int *p4 = new(&i) int[0]; // no warn
69f4a2713aSLionel Sambuc }
70f4a2713aSLionel Sambuc
71f4a2713aSLionel Sambuc //----- Other cases
testNewMemoryIsInHeap()72f4a2713aSLionel Sambuc void testNewMemoryIsInHeap() {
73f4a2713aSLionel Sambuc int *p = new int;
74f4a2713aSLionel Sambuc if (global != p) // condition is always true as 'p' wraps a heap region that
75f4a2713aSLionel Sambuc // is different from a region wrapped by 'global'
76f4a2713aSLionel Sambuc global = p; // pointer escapes
77f4a2713aSLionel Sambuc }
78f4a2713aSLionel Sambuc
79f4a2713aSLionel Sambuc struct PtrWrapper {
80f4a2713aSLionel Sambuc int *x;
81f4a2713aSLionel Sambuc
PtrWrapperPtrWrapper82f4a2713aSLionel Sambuc PtrWrapper(int *input) : x(input) {}
83f4a2713aSLionel Sambuc };
84f4a2713aSLionel Sambuc
testNewInvalidationPlacement(PtrWrapper * w)85f4a2713aSLionel Sambuc void testNewInvalidationPlacement(PtrWrapper *w) {
86f4a2713aSLionel Sambuc // Ensure that we don't consider this a leak.
87f4a2713aSLionel Sambuc new (w) PtrWrapper(new int); // no warn
88f4a2713aSLionel Sambuc }
89f4a2713aSLionel Sambuc
90f4a2713aSLionel Sambuc //---------------
91f4a2713aSLionel Sambuc // other checks
92f4a2713aSLionel Sambuc //---------------
93f4a2713aSLionel Sambuc
94f4a2713aSLionel Sambuc class SomeClass {
95f4a2713aSLionel Sambuc public:
96f4a2713aSLionel Sambuc void f(int *p);
97f4a2713aSLionel Sambuc };
98f4a2713aSLionel Sambuc
99f4a2713aSLionel Sambuc void f(int *p1, int *p2 = 0, int *p3 = 0);
100f4a2713aSLionel Sambuc void g(SomeClass &c, ...);
101f4a2713aSLionel Sambuc
testUseFirstArgAfterDelete()102f4a2713aSLionel Sambuc void testUseFirstArgAfterDelete() {
103f4a2713aSLionel Sambuc int *p = new int;
104f4a2713aSLionel Sambuc delete p;
105f4a2713aSLionel Sambuc f(p); // expected-warning{{Use of memory after it is freed}}
106f4a2713aSLionel Sambuc }
107f4a2713aSLionel Sambuc
testUseMiddleArgAfterDelete(int * p)108f4a2713aSLionel Sambuc void testUseMiddleArgAfterDelete(int *p) {
109f4a2713aSLionel Sambuc delete p;
110f4a2713aSLionel Sambuc f(0, p); // expected-warning{{Use of memory after it is freed}}
111f4a2713aSLionel Sambuc }
112f4a2713aSLionel Sambuc
testUseLastArgAfterDelete(int * p)113f4a2713aSLionel Sambuc void testUseLastArgAfterDelete(int *p) {
114f4a2713aSLionel Sambuc delete p;
115f4a2713aSLionel Sambuc f(0, 0, p); // expected-warning{{Use of memory after it is freed}}
116f4a2713aSLionel Sambuc }
117f4a2713aSLionel Sambuc
testUseSeveralArgsAfterDelete(int * p)118f4a2713aSLionel Sambuc void testUseSeveralArgsAfterDelete(int *p) {
119f4a2713aSLionel Sambuc delete p;
120f4a2713aSLionel Sambuc f(p, p, p); // expected-warning{{Use of memory after it is freed}}
121f4a2713aSLionel Sambuc }
122f4a2713aSLionel Sambuc
testUseRefArgAfterDelete(SomeClass & c)123f4a2713aSLionel Sambuc void testUseRefArgAfterDelete(SomeClass &c) {
124f4a2713aSLionel Sambuc delete &c;
125f4a2713aSLionel Sambuc g(c); // expected-warning{{Use of memory after it is freed}}
126f4a2713aSLionel Sambuc }
127f4a2713aSLionel Sambuc
testVariadicArgAfterDelete()128f4a2713aSLionel Sambuc void testVariadicArgAfterDelete() {
129f4a2713aSLionel Sambuc SomeClass c;
130f4a2713aSLionel Sambuc int *p = new int;
131f4a2713aSLionel Sambuc delete p;
132f4a2713aSLionel Sambuc g(c, 0, p); // expected-warning{{Use of memory after it is freed}}
133f4a2713aSLionel Sambuc }
134f4a2713aSLionel Sambuc
testUseMethodArgAfterDelete(int * p)135f4a2713aSLionel Sambuc void testUseMethodArgAfterDelete(int *p) {
136f4a2713aSLionel Sambuc SomeClass *c = new SomeClass;
137f4a2713aSLionel Sambuc delete p;
138f4a2713aSLionel Sambuc c->f(p); // expected-warning{{Use of memory after it is freed}}
139f4a2713aSLionel Sambuc }
140f4a2713aSLionel Sambuc
testUseThisAfterDelete()141f4a2713aSLionel Sambuc void testUseThisAfterDelete() {
142f4a2713aSLionel Sambuc SomeClass *c = new SomeClass;
143f4a2713aSLionel Sambuc delete c;
144f4a2713aSLionel Sambuc c->f(0); // expected-warning{{Use of memory after it is freed}}
145f4a2713aSLionel Sambuc }
146f4a2713aSLionel Sambuc
testDeleteAlloca()147f4a2713aSLionel Sambuc void testDeleteAlloca() {
148f4a2713aSLionel Sambuc int *p = (int *)__builtin_alloca(sizeof(int));
149f4a2713aSLionel Sambuc delete p; // expected-warning{{Memory allocated by alloca() should not be deallocated}}
150f4a2713aSLionel Sambuc }
151f4a2713aSLionel Sambuc
testDoubleDelete()152f4a2713aSLionel Sambuc void testDoubleDelete() {
153f4a2713aSLionel Sambuc int *p = new int;
154f4a2713aSLionel Sambuc delete p;
155f4a2713aSLionel Sambuc delete p; // expected-warning{{Attempt to free released memory}}
156f4a2713aSLionel Sambuc }
157f4a2713aSLionel Sambuc
testExprDeleteArg()158f4a2713aSLionel Sambuc void testExprDeleteArg() {
159f4a2713aSLionel Sambuc int i;
160f4a2713aSLionel Sambuc delete &i; // expected-warning{{Argument to 'delete' is the address of the local variable 'i', which is not memory allocated by 'new'}}
161f4a2713aSLionel Sambuc }
162f4a2713aSLionel Sambuc
testExprDeleteArrArg()163f4a2713aSLionel Sambuc void testExprDeleteArrArg() {
164f4a2713aSLionel Sambuc int i;
165f4a2713aSLionel Sambuc delete[] &i; // expected-warning{{Argument to 'delete[]' is the address of the local variable 'i', which is not memory allocated by 'new[]'}}
166f4a2713aSLionel Sambuc }
167f4a2713aSLionel Sambuc
testAllocDeallocNames()168f4a2713aSLionel Sambuc void testAllocDeallocNames() {
169f4a2713aSLionel Sambuc int *p = new(std::nothrow) int[1];
170f4a2713aSLionel Sambuc delete[] (++p); // expected-warning{{Argument to 'delete[]' is offset by 4 bytes from the start of memory allocated by 'new[]'}}
171f4a2713aSLionel Sambuc }
172f4a2713aSLionel Sambuc
173f4a2713aSLionel Sambuc //--------------------------------
174f4a2713aSLionel Sambuc // Test escape of newed const pointer. Note, a const pointer can be deleted.
175f4a2713aSLionel Sambuc //--------------------------------
176f4a2713aSLionel Sambuc struct StWithConstPtr {
177f4a2713aSLionel Sambuc const int *memp;
178f4a2713aSLionel Sambuc };
179f4a2713aSLionel Sambuc void escape(const int &x);
180f4a2713aSLionel Sambuc void escapeStruct(const StWithConstPtr &x);
181f4a2713aSLionel Sambuc void escapePtr(const StWithConstPtr *x);
182f4a2713aSLionel Sambuc void escapeVoidPtr(const void *x);
183f4a2713aSLionel Sambuc
testConstEscape()184f4a2713aSLionel Sambuc void testConstEscape() {
185f4a2713aSLionel Sambuc int *p = new int(1);
186f4a2713aSLionel Sambuc escape(*p);
187f4a2713aSLionel Sambuc } // no-warning
188f4a2713aSLionel Sambuc
testConstEscapeStruct()189f4a2713aSLionel Sambuc void testConstEscapeStruct() {
190f4a2713aSLionel Sambuc StWithConstPtr *St = new StWithConstPtr();
191f4a2713aSLionel Sambuc escapeStruct(*St);
192f4a2713aSLionel Sambuc } // no-warning
193f4a2713aSLionel Sambuc
testConstEscapeStructPtr()194f4a2713aSLionel Sambuc void testConstEscapeStructPtr() {
195f4a2713aSLionel Sambuc StWithConstPtr *St = new StWithConstPtr();
196f4a2713aSLionel Sambuc escapePtr(St);
197f4a2713aSLionel Sambuc } // no-warning
198f4a2713aSLionel Sambuc
testConstEscapeMember()199f4a2713aSLionel Sambuc void testConstEscapeMember() {
200f4a2713aSLionel Sambuc StWithConstPtr St;
201f4a2713aSLionel Sambuc St.memp = new int(2);
202f4a2713aSLionel Sambuc escapeVoidPtr(St.memp);
203f4a2713aSLionel Sambuc } // no-warning
204f4a2713aSLionel Sambuc
testConstEscapePlacementNew()205f4a2713aSLionel Sambuc void testConstEscapePlacementNew() {
206f4a2713aSLionel Sambuc int *x = (int *)malloc(sizeof(int));
207f4a2713aSLionel Sambuc void *y = new (x) int;
208f4a2713aSLionel Sambuc escapeVoidPtr(y);
209f4a2713aSLionel Sambuc } // no-warning
210f4a2713aSLionel Sambuc
211f4a2713aSLionel Sambuc //============== Test Uninitialized delete delete[]========================
testUninitDelete()212f4a2713aSLionel Sambuc void testUninitDelete() {
213f4a2713aSLionel Sambuc int *x;
214f4a2713aSLionel Sambuc int * y = new int;
215f4a2713aSLionel Sambuc delete y;
216f4a2713aSLionel Sambuc delete x; // expected-warning{{Argument to 'delete' is uninitialized}}
217f4a2713aSLionel Sambuc }
218f4a2713aSLionel Sambuc
testUninitDeleteArray()219f4a2713aSLionel Sambuc void testUninitDeleteArray() {
220f4a2713aSLionel Sambuc int *x;
221f4a2713aSLionel Sambuc int * y = new int[5];
222f4a2713aSLionel Sambuc delete[] y;
223f4a2713aSLionel Sambuc delete[] x; // expected-warning{{Argument to 'delete[]' is uninitialized}}
224f4a2713aSLionel Sambuc }
225f4a2713aSLionel Sambuc
testUninitFree()226f4a2713aSLionel Sambuc void testUninitFree() {
227f4a2713aSLionel Sambuc int *x;
228f4a2713aSLionel Sambuc free(x); // expected-warning{{Function call argument is an uninitialized value}}
229f4a2713aSLionel Sambuc }
230f4a2713aSLionel Sambuc
testUninitDeleteSink()231f4a2713aSLionel Sambuc void testUninitDeleteSink() {
232f4a2713aSLionel Sambuc int *x;
233f4a2713aSLionel Sambuc delete x; // expected-warning{{Argument to 'delete' is uninitialized}}
234f4a2713aSLionel Sambuc (*(volatile int *)0 = 1); // no warn
235f4a2713aSLionel Sambuc }
236f4a2713aSLionel Sambuc
testUninitDeleteArraySink()237f4a2713aSLionel Sambuc void testUninitDeleteArraySink() {
238f4a2713aSLionel Sambuc int *x;
239f4a2713aSLionel Sambuc delete[] x; // expected-warning{{Argument to 'delete[]' is uninitialized}}
240f4a2713aSLionel Sambuc (*(volatile int *)0 = 1); // no warn
241f4a2713aSLionel Sambuc }
242f4a2713aSLionel Sambuc
243f4a2713aSLionel Sambuc namespace reference_count {
244f4a2713aSLionel Sambuc class control_block {
245f4a2713aSLionel Sambuc unsigned count;
246f4a2713aSLionel Sambuc public:
control_block()247f4a2713aSLionel Sambuc control_block() : count(0) {}
retain()248f4a2713aSLionel Sambuc void retain() { ++count; }
release()249f4a2713aSLionel Sambuc int release() { return --count; }
250f4a2713aSLionel Sambuc };
251f4a2713aSLionel Sambuc
252f4a2713aSLionel Sambuc template <typename T>
253f4a2713aSLionel Sambuc class shared_ptr {
254f4a2713aSLionel Sambuc T *p;
255f4a2713aSLionel Sambuc control_block *control;
256f4a2713aSLionel Sambuc
257f4a2713aSLionel Sambuc public:
shared_ptr()258f4a2713aSLionel Sambuc shared_ptr() : p(0), control(0) {}
shared_ptr(T * p)259f4a2713aSLionel Sambuc explicit shared_ptr(T *p) : p(p), control(new control_block) {
260f4a2713aSLionel Sambuc control->retain();
261f4a2713aSLionel Sambuc }
shared_ptr(shared_ptr & other)262f4a2713aSLionel Sambuc shared_ptr(shared_ptr &other) : p(other.p), control(other.control) {
263f4a2713aSLionel Sambuc if (control)
264f4a2713aSLionel Sambuc control->retain();
265f4a2713aSLionel Sambuc }
~shared_ptr()266f4a2713aSLionel Sambuc ~shared_ptr() {
267f4a2713aSLionel Sambuc if (control && control->release() == 0) {
268f4a2713aSLionel Sambuc delete p;
269f4a2713aSLionel Sambuc delete control;
270f4a2713aSLionel Sambuc }
271f4a2713aSLionel Sambuc };
272f4a2713aSLionel Sambuc
operator *()273f4a2713aSLionel Sambuc T &operator *() {
274f4a2713aSLionel Sambuc return *p;
275f4a2713aSLionel Sambuc };
276f4a2713aSLionel Sambuc
swap(shared_ptr & other)277f4a2713aSLionel Sambuc void swap(shared_ptr &other) {
278f4a2713aSLionel Sambuc T *tmp = p;
279f4a2713aSLionel Sambuc p = other.p;
280f4a2713aSLionel Sambuc other.p = tmp;
281f4a2713aSLionel Sambuc
282f4a2713aSLionel Sambuc control_block *ctrlTmp = control;
283f4a2713aSLionel Sambuc control = other.control;
284f4a2713aSLionel Sambuc other.control = ctrlTmp;
285f4a2713aSLionel Sambuc }
286f4a2713aSLionel Sambuc };
287f4a2713aSLionel Sambuc
testSingle()288f4a2713aSLionel Sambuc void testSingle() {
289f4a2713aSLionel Sambuc shared_ptr<int> a(new int);
290f4a2713aSLionel Sambuc *a = 1;
291f4a2713aSLionel Sambuc }
292f4a2713aSLionel Sambuc
testDouble()293f4a2713aSLionel Sambuc void testDouble() {
294f4a2713aSLionel Sambuc shared_ptr<int> a(new int);
295f4a2713aSLionel Sambuc shared_ptr<int> b = a;
296f4a2713aSLionel Sambuc *a = 1;
297f4a2713aSLionel Sambuc }
298f4a2713aSLionel Sambuc
testInvalidated()299f4a2713aSLionel Sambuc void testInvalidated() {
300f4a2713aSLionel Sambuc shared_ptr<int> a(new int);
301f4a2713aSLionel Sambuc shared_ptr<int> b = a;
302f4a2713aSLionel Sambuc *a = 1;
303f4a2713aSLionel Sambuc
304f4a2713aSLionel Sambuc extern void use(shared_ptr<int> &);
305f4a2713aSLionel Sambuc use(b);
306f4a2713aSLionel Sambuc }
307f4a2713aSLionel Sambuc
testNestedScope()308f4a2713aSLionel Sambuc void testNestedScope() {
309f4a2713aSLionel Sambuc shared_ptr<int> a(new int);
310f4a2713aSLionel Sambuc {
311f4a2713aSLionel Sambuc shared_ptr<int> b = a;
312f4a2713aSLionel Sambuc }
313f4a2713aSLionel Sambuc *a = 1;
314f4a2713aSLionel Sambuc }
315f4a2713aSLionel Sambuc
testSwap()316f4a2713aSLionel Sambuc void testSwap() {
317f4a2713aSLionel Sambuc shared_ptr<int> a(new int);
318f4a2713aSLionel Sambuc shared_ptr<int> b;
319f4a2713aSLionel Sambuc shared_ptr<int> c = a;
320f4a2713aSLionel Sambuc shared_ptr<int>(c).swap(b);
321f4a2713aSLionel Sambuc }
322f4a2713aSLionel Sambuc
testUseAfterFree()323f4a2713aSLionel Sambuc void testUseAfterFree() {
324f4a2713aSLionel Sambuc int *p = new int;
325f4a2713aSLionel Sambuc {
326f4a2713aSLionel Sambuc shared_ptr<int> a(p);
327f4a2713aSLionel Sambuc shared_ptr<int> b = a;
328f4a2713aSLionel Sambuc }
329f4a2713aSLionel Sambuc
330f4a2713aSLionel Sambuc // FIXME: We should get a warning here, but we don't because we've
331f4a2713aSLionel Sambuc // conservatively modeled ~shared_ptr.
332f4a2713aSLionel Sambuc *p = 1;
333f4a2713aSLionel Sambuc }
334f4a2713aSLionel Sambuc }
335f4a2713aSLionel Sambuc
336f4a2713aSLionel Sambuc // Test double delete
337f4a2713aSLionel Sambuc class DerefClass{
338f4a2713aSLionel Sambuc public:
339f4a2713aSLionel Sambuc int *x;
DerefClass()340f4a2713aSLionel Sambuc DerefClass() {}
~DerefClass()341*0a6a1f1dSLionel Sambuc ~DerefClass() {*x = 1;}
342f4a2713aSLionel Sambuc };
343f4a2713aSLionel Sambuc
testDoubleDeleteClassInstance()344f4a2713aSLionel Sambuc void testDoubleDeleteClassInstance() {
345f4a2713aSLionel Sambuc DerefClass *foo = new DerefClass();
346f4a2713aSLionel Sambuc delete foo;
347*0a6a1f1dSLionel Sambuc delete foo; // expected-warning {{Attempt to delete released memory}}
348f4a2713aSLionel Sambuc }
349f4a2713aSLionel Sambuc
350f4a2713aSLionel Sambuc class EmptyClass{
351f4a2713aSLionel Sambuc public:
EmptyClass()352f4a2713aSLionel Sambuc EmptyClass() {}
~EmptyClass()353f4a2713aSLionel Sambuc ~EmptyClass() {}
354f4a2713aSLionel Sambuc };
355f4a2713aSLionel Sambuc
testDoubleDeleteEmptyClass()356f4a2713aSLionel Sambuc void testDoubleDeleteEmptyClass() {
357f4a2713aSLionel Sambuc EmptyClass *foo = new EmptyClass();
358f4a2713aSLionel Sambuc delete foo;
359*0a6a1f1dSLionel Sambuc delete foo; // expected-warning {{Attempt to delete released memory}}
360f4a2713aSLionel Sambuc }
361