blob: 83796357b4c3cbae783f966baa4fb842838e418c [file] [log] [blame]
Jordan Rosee449edc2013-04-05 17:55:07 +00001// RUN: %clang_cc1 -analyze -analyzer-checker=core,cplusplus.NewDelete -std=c++11 -fblocks -verify %s
Anton Yartsev9df151c2013-04-12 23:25:40 +00002// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.cplusplus.NewDeleteLeaks -DLEAKS -std=c++11 -fblocks -verify %s
Anton Yartsev2de19ed2013-03-25 01:35:45 +00003#include "Inputs/system-header-simulator-cxx.h"
Anton Yartsev2de19ed2013-03-25 01:35:45 +00004
5typedef __typeof__(sizeof(int)) size_t;
6extern "C" void *malloc(size_t);
Anton Yartsev2de19ed2013-03-25 01:35:45 +00007int *global;
8
9//------------------
10// check for leaks
11//------------------
12
Anton Yartsev69746282013-03-28 16:10:38 +000013//----- Standard non-placement operators
14void testGlobalOpNew() {
Anton Yartsev2de19ed2013-03-25 01:35:45 +000015 void *p = operator new(0);
Jordan Rosee85deb32013-04-05 17:55:00 +000016}
17#ifdef LEAKS
Anna Zaks68eb4c22013-04-06 00:41:36 +000018// expected-warning@-2{{Potential leak of memory pointed to by 'p'}}
Jordan Rosee85deb32013-04-05 17:55:00 +000019#endif
Anton Yartsev2de19ed2013-03-25 01:35:45 +000020
Anton Yartsev69746282013-03-28 16:10:38 +000021void testGlobalOpNewArray() {
22 void *p = operator new[](0);
Jordan Rosee85deb32013-04-05 17:55:00 +000023}
24#ifdef LEAKS
Anna Zaks68eb4c22013-04-06 00:41:36 +000025// expected-warning@-2{{Potential leak of memory pointed to by 'p'}}
Jordan Rosee85deb32013-04-05 17:55:00 +000026#endif
Anton Yartsev69746282013-03-28 16:10:38 +000027
28void testGlobalNewExpr() {
Anton Yartsev2de19ed2013-03-25 01:35:45 +000029 int *p = new int;
Jordan Rosee85deb32013-04-05 17:55:00 +000030}
31#ifdef LEAKS
Anna Zaks68eb4c22013-04-06 00:41:36 +000032// expected-warning@-2{{Potential leak of memory pointed to by 'p'}}
Jordan Rosee85deb32013-04-05 17:55:00 +000033#endif
Anton Yartsev2de19ed2013-03-25 01:35:45 +000034
Anton Yartsev69746282013-03-28 16:10:38 +000035void testGlobalNewExprArray() {
36 int *p = new int[0];
Jordan Rosee85deb32013-04-05 17:55:00 +000037}
38#ifdef LEAKS
Anna Zaks68eb4c22013-04-06 00:41:36 +000039// expected-warning@-2{{Potential leak of memory pointed to by 'p'}}
Jordan Rosee85deb32013-04-05 17:55:00 +000040#endif
Anton Yartsev2de19ed2013-03-25 01:35:45 +000041
Anton Yartsev69746282013-03-28 16:10:38 +000042//----- Standard nothrow placement operators
43void testGlobalNoThrowPlacementOpNewBeforeOverload() {
44 void *p = operator new(0, std::nothrow);
Jordan Rosee85deb32013-04-05 17:55:00 +000045}
46#ifdef LEAKS
Anna Zaks68eb4c22013-04-06 00:41:36 +000047// expected-warning@-2{{Potential leak of memory pointed to by 'p'}}
Jordan Rosee85deb32013-04-05 17:55:00 +000048#endif
Anton Yartsev69746282013-03-28 16:10:38 +000049
50void testGlobalNoThrowPlacementExprNewBeforeOverload() {
51 int *p = new(std::nothrow) int;
Jordan Rosee85deb32013-04-05 17:55:00 +000052}
53#ifdef LEAKS
Anna Zaks68eb4c22013-04-06 00:41:36 +000054// expected-warning@-2{{Potential leak of memory pointed to by 'p'}}
Jordan Rosee85deb32013-04-05 17:55:00 +000055#endif
Anton Yartsev69746282013-03-28 16:10:38 +000056
Anton Yartsev69746282013-03-28 16:10:38 +000057//----- Standard pointer placement operators
58void testGlobalPointerPlacementNew() {
Anton Yartsev2de19ed2013-03-25 01:35:45 +000059 int i;
Anton Yartsev2de19ed2013-03-25 01:35:45 +000060
Anton Yartsev69746282013-03-28 16:10:38 +000061 void *p1 = operator new(0, &i); // no warn
Anton Yartsev2de19ed2013-03-25 01:35:45 +000062
Anton Yartsev69746282013-03-28 16:10:38 +000063 void *p2 = operator new[](0, &i); // no warn
Anton Yartsev2de19ed2013-03-25 01:35:45 +000064
Anton Yartsev69746282013-03-28 16:10:38 +000065 int *p3 = new(&i) int; // no warn
Anton Yartsev2de19ed2013-03-25 01:35:45 +000066
Anton Yartsev69746282013-03-28 16:10:38 +000067 int *p4 = new(&i) int[0]; // no warn
Anton Yartsev2de19ed2013-03-25 01:35:45 +000068}
69
Anton Yartsev69746282013-03-28 16:10:38 +000070//----- Other cases
71void testNewMemoryIsInHeap() {
72 int *p = new int;
73 if (global != p) // condition is always true as 'p' wraps a heap region that
74 // is different from a region wrapped by 'global'
75 global = p; // pointer escapes
Anton Yartsev2de19ed2013-03-25 01:35:45 +000076}
77
Anton Yartsev69746282013-03-28 16:10:38 +000078struct PtrWrapper {
79 int *x;
Anton Yartsev2de19ed2013-03-25 01:35:45 +000080
Anton Yartsev69746282013-03-28 16:10:38 +000081 PtrWrapper(int *input) : x(input) {}
82};
Anton Yartsev2de19ed2013-03-25 01:35:45 +000083
Anton Yartsev69746282013-03-28 16:10:38 +000084void testNewInvalidationPlacement(PtrWrapper *w) {
85 // Ensure that we don't consider this a leak.
86 new (w) PtrWrapper(new int); // no warn
Anton Yartsev2de19ed2013-03-25 01:35:45 +000087}
88
89//---------------
90// other checks
91//---------------
92
Anton Yartsev55e57a52013-04-10 22:21:41 +000093class SomeClass {
94public:
95 void f(int *p);
96};
Anton Yartsev2de19ed2013-03-25 01:35:45 +000097
Anton Yartsev55e57a52013-04-10 22:21:41 +000098void f(int *p1, int *p2 = 0, int *p3 = 0);
99void g(SomeClass &c, ...);
100
101void testUseFirstArgAfterDelete() {
Anton Yartsev2de19ed2013-03-25 01:35:45 +0000102 int *p = new int;
103 delete p;
104 f(p); // expected-warning{{Use of memory after it is freed}}
105}
106
Anton Yartsev55e57a52013-04-10 22:21:41 +0000107void testUseMiddleArgAfterDelete(int *p) {
108 delete p;
109 f(0, p); // expected-warning{{Use of memory after it is freed}}
110}
111
112void testUseLastArgAfterDelete(int *p) {
113 delete p;
114 f(0, 0, p); // expected-warning{{Use of memory after it is freed}}
115}
116
Anton Yartsev337ad762013-04-10 22:36:16 +0000117void testUseSeveralArgsAfterDelete(int *p) {
118 delete p;
119 f(p, p, p); // expected-warning{{Use of memory after it is freed}}
120}
121
Anton Yartsev55e57a52013-04-10 22:21:41 +0000122void testUseRefArgAfterDelete(SomeClass &c) {
123 delete &c;
124 g(c); // expected-warning{{Use of memory after it is freed}}
125}
126
127void testVariadicArgAfterDelete() {
128 SomeClass c;
129 int *p = new int;
130 delete p;
131 g(c, 0, p); // expected-warning{{Use of memory after it is freed}}
132}
133
134void testUseMethodArgAfterDelete(int *p) {
135 SomeClass *c = new SomeClass;
136 delete p;
137 c->f(p); // expected-warning{{Use of memory after it is freed}}
138}
139
140void testUseThisAfterDelete() {
141 SomeClass *c = new SomeClass;
142 delete c;
143 c->f(0); // expected-warning{{Use of memory after it is freed}}
144}
145
Anton Yartsev2de19ed2013-03-25 01:35:45 +0000146void testDeleteAlloca() {
147 int *p = (int *)__builtin_alloca(sizeof(int));
Anton Yartsev849c7bf2013-03-28 17:05:19 +0000148 delete p; // expected-warning{{Memory allocated by alloca() should not be deallocated}}
Anton Yartsev2de19ed2013-03-25 01:35:45 +0000149}
150
151void testDoubleDelete() {
152 int *p = new int;
153 delete p;
154 delete p; // expected-warning{{Attempt to free released memory}}
155}
156
157void testExprDeleteArg() {
158 int i;
Anton Yartsev849c7bf2013-03-28 17:05:19 +0000159 delete &i; // expected-warning{{Argument to 'delete' is the address of the local variable 'i', which is not memory allocated by 'new'}}
160}
Anton Yartsev2de19ed2013-03-25 01:35:45 +0000161
162void testExprDeleteArrArg() {
163 int i;
Anton Yartsev849c7bf2013-03-28 17:05:19 +0000164 delete[] &i; // expected-warning{{Argument to 'delete[]' is the address of the local variable 'i', which is not memory allocated by 'new[]'}}
165}
Anton Yartsev2de19ed2013-03-25 01:35:45 +0000166
167void testAllocDeallocNames() {
168 int *p = new(std::nothrow) int[1];
Anton Yartsev849c7bf2013-03-28 17:05:19 +0000169 delete[] (++p); // expected-warning{{Argument to 'delete[]' is offset by 4 bytes from the start of memory allocated by 'new[]'}}
170}
Anton Yartsev2de19ed2013-03-25 01:35:45 +0000171
Anna Zaks41988f32013-03-28 23:15:29 +0000172//--------------------------------
173// Test escape of newed const pointer. Note, a const pointer can be deleted.
174//--------------------------------
175struct StWithConstPtr {
176 const int *memp;
177};
178void escape(const int &x);
179void escapeStruct(const StWithConstPtr &x);
180void escapePtr(const StWithConstPtr *x);
181void escapeVoidPtr(const void *x);
182
183void testConstEscape() {
184 int *p = new int(1);
185 escape(*p);
186} // no-warning
187
188void testConstEscapeStruct() {
189 StWithConstPtr *St = new StWithConstPtr();
190 escapeStruct(*St);
191} // no-warning
192
193void testConstEscapeStructPtr() {
194 StWithConstPtr *St = new StWithConstPtr();
195 escapePtr(St);
196} // no-warning
197
198void testConstEscapeMember() {
199 StWithConstPtr St;
200 St.memp = new int(2);
201 escapeVoidPtr(St.memp);
202} // no-warning
203
204void testConstEscapePlacementNew() {
205 int *x = (int *)malloc(sizeof(int));
206 void *y = new (x) int;
207 escapeVoidPtr(y);
208} // no-warning
Jordan Rose50fa64d2013-05-17 02:16:49 +0000209
210
211namespace reference_count {
212 class control_block {
213 unsigned count;
214 public:
215 control_block() : count(0) {}
216 void retain() { ++count; }
217 int release() { return --count; }
218 };
219
220 template <typename T>
221 class shared_ptr {
222 T *p;
223 control_block *control;
224
225 public:
226 shared_ptr() : p(0), control(0) {}
227 explicit shared_ptr(T *p) : p(p), control(new control_block) {
228 control->retain();
229 }
230 shared_ptr(shared_ptr &other) : p(other.p), control(other.control) {
231 if (control)
232 control->retain();
233 }
234 ~shared_ptr() {
235 if (control && control->release() == 0) {
236 delete p;
237 delete control;
238 }
239 };
240
241 T &operator *() {
242 return *p;
243 };
244
245 void swap(shared_ptr &other) {
246 T *tmp = p;
247 p = other.p;
248 other.p = tmp;
249
250 control_block *ctrlTmp = control;
251 control = other.control;
252 other.control = ctrlTmp;
253 }
254 };
255
256 void testSingle() {
257 shared_ptr<int> a(new int);
258 *a = 1;
259 }
260
261 void testDouble() {
262 shared_ptr<int> a(new int);
263 shared_ptr<int> b = a;
264 *a = 1;
265 }
266
267 void testInvalidated() {
268 shared_ptr<int> a(new int);
269 shared_ptr<int> b = a;
270 *a = 1;
271
272 extern void use(shared_ptr<int> &);
273 use(b);
274 }
275
276 void testNestedScope() {
277 shared_ptr<int> a(new int);
278 {
279 shared_ptr<int> b = a;
280 }
281 *a = 1;
282 }
283
284 void testSwap() {
285 shared_ptr<int> a(new int);
286 shared_ptr<int> b;
287 shared_ptr<int> c = a;
288 shared_ptr<int>(c).swap(b);
289 }
290
291 void testUseAfterFree() {
292 int *p = new int;
293 {
294 shared_ptr<int> a(p);
295 shared_ptr<int> b = a;
296 }
297
298 // FIXME: We should get a warning here, but we don't because we've
299 // conservatively modeled ~shared_ptr.
300 *p = 1;
301 }
302}
303