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