1// RUN: %clang_cc1 -analyze -analyzer-checker=core,cplusplus.NewDelete -std=c++11 -fblocks -verify %s
2// RUN: %clang_cc1 -analyze -analyzer-checker=core,cplusplus.NewDeleteLeaks -DLEAKS -std=c++11 -fblocks -verify %s
3#include "Inputs/system-header-simulator-cxx.h"
4
5typedef __typeof__(sizeof(int)) size_t;
6extern "C" void *malloc(size_t);
7extern "C" void free (void* ptr);
8int *global;
9
10//------------------
11// check for leaks
12//------------------
13
14//----- Standard non-placement operators
15void testGlobalOpNew() {
16  void *p = operator new(0);
17}
18#ifdef LEAKS
19// expected-warning@-2{{Potential leak of memory pointed to by 'p'}}
20#endif
21
22void testGlobalOpNewArray() {
23  void *p = operator new[](0);
24}
25#ifdef LEAKS
26// expected-warning@-2{{Potential leak of memory pointed to by 'p'}}
27#endif
28
29void testGlobalNewExpr() {
30  int *p = new int;
31}
32#ifdef LEAKS
33// expected-warning@-2{{Potential leak of memory pointed to by 'p'}}
34#endif
35
36void testGlobalNewExprArray() {
37  int *p = new int[0];
38}
39#ifdef LEAKS
40// expected-warning@-2{{Potential leak of memory pointed to by 'p'}}
41#endif
42
43//----- Standard nothrow placement operators
44void testGlobalNoThrowPlacementOpNewBeforeOverload() {
45  void *p = operator new(0, std::nothrow);
46}
47#ifdef LEAKS
48// expected-warning@-2{{Potential leak of memory pointed to by 'p'}}
49#endif
50
51void testGlobalNoThrowPlacementExprNewBeforeOverload() {
52  int *p = new(std::nothrow) int;
53}
54#ifdef LEAKS
55// expected-warning@-2{{Potential leak of memory pointed to by 'p'}}
56#endif
57
58//----- Standard pointer placement operators
59void testGlobalPointerPlacementNew() {
60  int i;
61
62  void *p1 = operator new(0, &i); // no warn
63
64  void *p2 = operator new[](0, &i); // no warn
65
66  int *p3 = new(&i) int; // no warn
67
68  int *p4 = new(&i) int[0]; // no warn
69}
70
71//----- 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
77}
78
79struct PtrWrapper {
80  int *x;
81
82  PtrWrapper(int *input) : x(input) {}
83};
84
85void testNewInvalidationPlacement(PtrWrapper *w) {
86  // Ensure that we don't consider this a leak.
87  new (w) PtrWrapper(new int); // no warn
88}
89
90//-----------------------------------------
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
114//---------------
115// other checks
116//---------------
117
118class SomeClass {
119public:
120  void f(int *p);
121};
122
123void f(int *p1, int *p2 = 0, int *p3 = 0);
124void g(SomeClass &c, ...);
125
126void testUseFirstArgAfterDelete() {
127  int *p = new int;
128  delete p;
129  f(p); // expected-warning{{Use of memory after it is freed}}
130}
131
132void 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
142void testUseSeveralArgsAfterDelete(int *p) {
143  delete p;
144  f(p, p, p); // expected-warning{{Use of memory after it is freed}}
145}
146
147void 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
171void 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;
179  delete &i; // expected-warning{{Argument to 'delete' is the address of the local variable 'i', which is not memory allocated by 'new'}}
180}
181
182void testExprDeleteArrArg() {
183  int i;
184  delete[] &i; // expected-warning{{Argument to 'delete[]' is the address of the local variable 'i', which is not memory allocated by 'new[]'}}
185}
186
187void testAllocDeallocNames() {
188  int *p = new(std::nothrow) int[1];
189  delete[] (++p); // expected-warning{{Argument to 'delete[]' is offset by 4 bytes from the start of memory allocated by 'new[]'}}
190}
191
192//--------------------------------
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
229
230//============== 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}
261
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
355// Test double delete
356class DerefClass{
357public:
358  int *x;
359  DerefClass() {}
360  ~DerefClass() {*x = 1;}
361};
362
363void testDoubleDeleteClassInstance() {
364  DerefClass *foo = new DerefClass();
365  delete foo;
366  delete foo; // expected-warning {{Attempt to delete released memory}}
367}
368
369class EmptyClass{
370public:
371  EmptyClass() {}
372  ~EmptyClass() {}
373};
374
375void testDoubleDeleteEmptyClass() {
376  EmptyClass *foo = new EmptyClass();
377  delete foo;
378  delete foo;  // expected-warning {{Attempt to delete released memory}}
379}
380