NewDelete-checker-test.cpp revision 68eb4c25e961d18f82b47a0a385f90d7af09bcc3
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
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// other checks
92//---------------
93
94void f(int *);
95
96void testUseAfterDelete() {
97  int *p = new int;
98  delete p;
99  f(p); // expected-warning{{Use of memory after it is freed}}
100}
101
102void testDeleteAlloca() {
103  int *p = (int *)__builtin_alloca(sizeof(int));
104  delete p; // expected-warning{{Memory allocated by alloca() should not be deallocated}}
105}
106
107void testDoubleDelete() {
108  int *p = new int;
109  delete p;
110  delete p; // expected-warning{{Attempt to free released memory}}
111}
112
113void testExprDeleteArg() {
114  int i;
115  delete &i; // expected-warning{{Argument to 'delete' is the address of the local variable 'i', which is not memory allocated by 'new'}}
116}
117
118void testExprDeleteArrArg() {
119  int i;
120  delete[] &i; // expected-warning{{Argument to 'delete[]' is the address of the local variable 'i', which is not memory allocated by 'new[]'}}
121}
122
123void testAllocDeallocNames() {
124  int *p = new(std::nothrow) int[1];
125  delete[] (++p); // expected-warning{{Argument to 'delete[]' is offset by 4 bytes from the start of memory allocated by 'new[]'}}
126}
127
128//--------------------------------
129// Test escape of newed const pointer. Note, a const pointer can be deleted.
130//--------------------------------
131struct StWithConstPtr {
132  const int *memp;
133};
134void escape(const int &x);
135void escapeStruct(const StWithConstPtr &x);
136void escapePtr(const StWithConstPtr *x);
137void escapeVoidPtr(const void *x);
138
139void testConstEscape() {
140  int *p = new int(1);
141  escape(*p);
142} // no-warning
143
144void testConstEscapeStruct() {
145  StWithConstPtr *St = new StWithConstPtr();
146  escapeStruct(*St);
147} // no-warning
148
149void testConstEscapeStructPtr() {
150  StWithConstPtr *St = new StWithConstPtr();
151  escapePtr(St);
152} // no-warning
153
154void testConstEscapeMember() {
155  StWithConstPtr St;
156  St.memp = new int(2);
157  escapeVoidPtr(St.memp);
158} // no-warning
159
160void testConstEscapePlacementNew() {
161  int *x = (int *)malloc(sizeof(int));
162  void *y = new (x) int;
163  escapeVoidPtr(y);
164} // no-warning
165