NewDelete-checker-test.cpp revision 1f3b5d990e9afa0b2b8db0908f46d8de7818e642
1// RUN: %clang_cc1 -analyze -analyzer-checker=core,cplusplus.NewDelete -analyzer-store region -std=c++11 -fblocks -verify %s
2#include "Inputs/system-header-simulator-cxx.h"
3#include "Inputs/system-header-simulator-objc.h"
4
5typedef __typeof__(sizeof(int)) size_t;
6extern "C" void *malloc(size_t);
7extern "C" void free(void *);
8int *global;
9
10//------------------
11// check for leaks
12//------------------
13
14//----- Standard non-placement operators
15void testGlobalOpNew() {
16  void *p = operator new(0);
17} // expected-warning{{Memory is never released; potential leak}}
18
19void testGlobalOpNewArray() {
20  void *p = operator new[](0);
21} // expected-warning{{Memory is never released; potential leak}}
22
23void testGlobalNewExpr() {
24  int *p = new int;
25} // expected-warning{{Memory is never released; potential leak}}
26
27void testGlobalNewExprArray() {
28  int *p = new int[0];
29} // expected-warning{{Memory is never released; potential leak}}
30
31//----- Standard nothrow placement operators
32void testGlobalNoThrowPlacementOpNewBeforeOverload() {
33  void *p = operator new(0, std::nothrow);
34} // expected-warning{{Memory is never released; potential leak}}
35
36void testGlobalNoThrowPlacementExprNewBeforeOverload() {
37  int *p = new(std::nothrow) int;
38} // expected-warning{{Memory is never released; potential leak}}
39
40
41//----- Standard pointer placement operators
42void testGlobalPointerPlacementNew() {
43  int i;
44
45  void *p1 = operator new(0, &i); // no warn
46
47  void *p2 = operator new[](0, &i); // no warn
48
49  int *p3 = new(&i) int; // no warn
50
51  int *p4 = new(&i) int[0]; // no warn
52}
53
54//----- Other cases
55void testNewMemoryIsInHeap() {
56  int *p = new int;
57  if (global != p) // condition is always true as 'p' wraps a heap region that
58                   // is different from a region wrapped by 'global'
59    global = p; // pointer escapes
60}
61
62struct PtrWrapper {
63  int *x;
64
65  PtrWrapper(int *input) : x(input) {}
66};
67
68void testNewInvalidationPlacement(PtrWrapper *w) {
69  // Ensure that we don't consider this a leak.
70  new (w) PtrWrapper(new int); // no warn
71}
72
73//---------------
74// other checks
75//---------------
76
77void f(int *);
78
79void testUseAfterDelete() {
80  int *p = new int;
81  delete p;
82  f(p); // expected-warning{{Use of memory after it is freed}}
83}
84
85void testDeleteAlloca() {
86  int *p = (int *)__builtin_alloca(sizeof(int));
87  delete p; // expected-warning{{Memory allocated by alloca() should not be deallocated}}
88}
89
90void testDoubleDelete() {
91  int *p = new int;
92  delete p;
93  delete p; // expected-warning{{Attempt to free released memory}}
94}
95
96void testExprDeleteArg() {
97  int i;
98  delete &i; // expected-warning{{Argument to 'delete' is the address of the local variable 'i', which is not memory allocated by 'new'}}
99}
100
101void testExprDeleteArrArg() {
102  int i;
103  delete[] &i; // expected-warning{{Argument to 'delete[]' is the address of the local variable 'i', which is not memory allocated by 'new[]'}}
104}
105
106void testAllocDeallocNames() {
107  int *p = new(std::nothrow) int[1];
108  delete[] (++p); // expected-warning{{Argument to 'delete[]' is offset by 4 bytes from the start of memory allocated by 'new[]'}}
109}
110
111//----------------------------------------------------------------------------
112// Check for intersections with unix.Malloc and unix.MallocWithAnnotations
113// checkers bounded with cplusplus.NewDelete.
114//----------------------------------------------------------------------------
115
116// malloc()/free() are subjects of unix.Malloc and unix.MallocWithAnnotations
117void testMallocFreeNoWarn() {
118  int i;
119  free(&i); // no warn
120
121  int *p1 = (int *)malloc(sizeof(int));
122  free(++p1); // no warn
123
124  int *p2 = (int *)malloc(sizeof(int));
125  free(p2);
126  free(p2); // no warn
127
128  int *p3 = (int *)malloc(sizeof(int)); // no warn
129}
130
131//----- Test free standard new
132void testFreeOpNew() {
133  void *p = operator new(0);
134  free(p);
135} // expected-warning{{Memory is never released; potential leak}}
136// FIXME: Pointer should escape
137
138void testFreeNewExpr() {
139  int *p = new int;
140  free(p);
141} // expected-warning{{Memory is never released; potential leak}}
142// FIXME: Pointer should escape
143
144void testObjcFreeNewed() {
145  int *p = new int;
146  NSData *nsdata = [NSData dataWithBytesNoCopy:p length:sizeof(int) freeWhenDone:1]; // expected-warning{{Memory is never released; potential leak}}
147}
148// FIXME: Pointer should escape
149
150void testFreeAfterDelete() {
151  int *p = new int;
152  delete p;
153  free(p); // expected-warning{{Use of memory after it is freed}}
154}
155
156void testStandardPlacementNewAfterDelete() {
157  int *p = new int;
158  delete p;
159  p = new(p) int; // expected-warning{{Use of memory after it is freed}}
160}
161
162//--------------------------------
163// Test escape of newed const pointer. Note, a const pointer can be deleted.
164//--------------------------------
165struct StWithConstPtr {
166  const int *memp;
167};
168void escape(const int &x);
169void escapeStruct(const StWithConstPtr &x);
170void escapePtr(const StWithConstPtr *x);
171void escapeVoidPtr(const void *x);
172
173void testConstEscape() {
174  int *p = new int(1);
175  escape(*p);
176} // no-warning
177
178void testConstEscapeStruct() {
179  StWithConstPtr *St = new StWithConstPtr();
180  escapeStruct(*St);
181} // no-warning
182
183void testConstEscapeStructPtr() {
184  StWithConstPtr *St = new StWithConstPtr();
185  escapePtr(St);
186} // no-warning
187
188void testConstEscapeMember() {
189  StWithConstPtr St;
190  St.memp = new int(2);
191  escapeVoidPtr(St.memp);
192} // no-warning
193
194void testConstEscapePlacementNew() {
195  int *x = (int *)malloc(sizeof(int));
196  void *y = new (x) int;
197  escapeVoidPtr(y);
198} // no-warning
199
200
201