NewDelete-checker-test.cpp revision 55e57a50a36749ce0483db2f16259649c9d25792
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.NewDelete,alpha.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);
7int *global;
8
9//------------------
10// check for leaks
11//------------------
12
13//----- Standard non-placement operators
14void testGlobalOpNew() {
15  void *p = operator new(0);
16}
17#ifdef LEAKS
18// expected-warning@-2{{Potential leak of memory pointed to by 'p'}}
19#endif
20
21void testGlobalOpNewArray() {
22  void *p = operator new[](0);
23}
24#ifdef LEAKS
25// expected-warning@-2{{Potential leak of memory pointed to by 'p'}}
26#endif
27
28void testGlobalNewExpr() {
29  int *p = new int;
30}
31#ifdef LEAKS
32// expected-warning@-2{{Potential leak of memory pointed to by 'p'}}
33#endif
34
35void testGlobalNewExprArray() {
36  int *p = new int[0];
37}
38#ifdef LEAKS
39// expected-warning@-2{{Potential leak of memory pointed to by 'p'}}
40#endif
41
42//----- Standard nothrow placement operators
43void testGlobalNoThrowPlacementOpNewBeforeOverload() {
44  void *p = operator new(0, std::nothrow);
45}
46#ifdef LEAKS
47// expected-warning@-2{{Potential leak of memory pointed to by 'p'}}
48#endif
49
50void testGlobalNoThrowPlacementExprNewBeforeOverload() {
51  int *p = new(std::nothrow) int;
52}
53#ifdef LEAKS
54// expected-warning@-2{{Potential leak of memory pointed to by 'p'}}
55#endif
56
57//----- Standard pointer placement operators
58void testGlobalPointerPlacementNew() {
59  int i;
60
61  void *p1 = operator new(0, &i); // no warn
62
63  void *p2 = operator new[](0, &i); // no warn
64
65  int *p3 = new(&i) int; // no warn
66
67  int *p4 = new(&i) int[0]; // no warn
68}
69
70//----- 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
76}
77
78struct PtrWrapper {
79  int *x;
80
81  PtrWrapper(int *input) : x(input) {}
82};
83
84void testNewInvalidationPlacement(PtrWrapper *w) {
85  // Ensure that we don't consider this a leak.
86  new (w) PtrWrapper(new int); // no warn
87}
88
89//---------------
90// other checks
91//---------------
92
93class SomeClass {
94public:
95  void f(int *p);
96};
97
98void f(int *p1, int *p2 = 0, int *p3 = 0);
99void g(SomeClass &c, ...);
100
101void testUseFirstArgAfterDelete() {
102  int *p = new int;
103  delete p;
104  f(p); // expected-warning{{Use of memory after it is freed}}
105}
106
107void 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
117void testUseRefArgAfterDelete(SomeClass &c) {
118  delete &c;
119  g(c); // expected-warning{{Use of memory after it is freed}}
120}
121
122void testVariadicArgAfterDelete() {
123  SomeClass c;
124  int *p = new int;
125  delete p;
126  g(c, 0, p); // expected-warning{{Use of memory after it is freed}}
127}
128
129void testUseMethodArgAfterDelete(int *p) {
130  SomeClass *c = new SomeClass;
131  delete p;
132  c->f(p); // expected-warning{{Use of memory after it is freed}}
133}
134
135void testUseThisAfterDelete() {
136  SomeClass *c = new SomeClass;
137  delete c;
138  c->f(0); // expected-warning{{Use of memory after it is freed}}
139}
140
141void testDeleteAlloca() {
142  int *p = (int *)__builtin_alloca(sizeof(int));
143  delete p; // expected-warning{{Memory allocated by alloca() should not be deallocated}}
144}
145
146void testDoubleDelete() {
147  int *p = new int;
148  delete p;
149  delete p; // expected-warning{{Attempt to free released memory}}
150}
151
152void testExprDeleteArg() {
153  int i;
154  delete &i; // expected-warning{{Argument to 'delete' is the address of the local variable 'i', which is not memory allocated by 'new'}}
155}
156
157void testExprDeleteArrArg() {
158  int i;
159  delete[] &i; // expected-warning{{Argument to 'delete[]' is the address of the local variable 'i', which is not memory allocated by 'new[]'}}
160}
161
162void testAllocDeallocNames() {
163  int *p = new(std::nothrow) int[1];
164  delete[] (++p); // expected-warning{{Argument to 'delete[]' is offset by 4 bytes from the start of memory allocated by 'new[]'}}
165}
166
167//--------------------------------
168// Test escape of newed const pointer. Note, a const pointer can be deleted.
169//--------------------------------
170struct StWithConstPtr {
171  const int *memp;
172};
173void escape(const int &x);
174void escapeStruct(const StWithConstPtr &x);
175void escapePtr(const StWithConstPtr *x);
176void escapeVoidPtr(const void *x);
177
178void testConstEscape() {
179  int *p = new int(1);
180  escape(*p);
181} // no-warning
182
183void testConstEscapeStruct() {
184  StWithConstPtr *St = new StWithConstPtr();
185  escapeStruct(*St);
186} // no-warning
187
188void testConstEscapeStructPtr() {
189  StWithConstPtr *St = new StWithConstPtr();
190  escapePtr(St);
191} // no-warning
192
193void testConstEscapeMember() {
194  StWithConstPtr St;
195  St.memp = new int(2);
196  escapeVoidPtr(St.memp);
197} // no-warning
198
199void testConstEscapePlacementNew() {
200  int *x = (int *)malloc(sizeof(int));
201  void *y = new (x) int;
202  escapeVoidPtr(y);
203} // no-warning
204