NewDelete-checker-test.cpp revision 8e452e7d6ee00a7d12eb54b91498b59b6fefef4f
1// RUN: %clang_cc1 -analyze -analyzer-checker=core,cplusplus.NewDelete,unix.Malloc -analyzer-store region -std=c++11 -fblocks -verify %s
2#include "Inputs/system-header-simulator-cxx.h"
3
4typedef __typeof__(sizeof(int)) size_t;
5extern "C" void *malloc(size_t);
6int *global;
7
8//------------------
9// check for leaks
10//------------------
11
12//----- Standard non-placement operators
13void testGlobalOpNew() {
14  void *p = operator new(0);
15} // expected-warning{{Memory is never released; potential leak}}
16
17void testGlobalOpNewArray() {
18  void *p = operator new[](0);
19} // expected-warning{{Memory is never released; potential leak}}
20
21void testGlobalNewExpr() {
22  int *p = new int;
23} // expected-warning{{Memory is never released; potential leak}}
24
25void testGlobalNewExprArray() {
26  int *p = new int[0];
27} // expected-warning{{Memory is never released; potential leak}}
28
29//----- Standard nothrow placement operators
30void testGlobalNoThrowPlacementOpNewBeforeOverload() {
31  void *p = operator new(0, std::nothrow);
32} // expected-warning{{Memory is never released; potential leak}}
33
34void testGlobalNoThrowPlacementExprNewBeforeOverload() {
35  int *p = new(std::nothrow) int;
36} // expected-warning{{Memory is never released; potential leak}}
37
38
39//----- Standard pointer placement operators
40void testGlobalPointerPlacementNew() {
41  int i;
42
43  void *p1 = operator new(0, &i); // no warn
44
45  void *p2 = operator new[](0, &i); // no warn
46
47  int *p3 = new(&i) int; // no warn
48
49  int *p4 = new(&i) int[0]; // no warn
50}
51
52//----- Other cases
53void testNewMemoryIsInHeap() {
54  int *p = new int;
55  if (global != p) // condition is always true as 'p' wraps a heap region that
56                   // is different from a region wrapped by 'global'
57    global = p; // pointer escapes
58}
59
60struct PtrWrapper {
61  int *x;
62
63  PtrWrapper(int *input) : x(input) {}
64};
65
66void testNewInvalidationPlacement(PtrWrapper *w) {
67  // Ensure that we don't consider this a leak.
68  new (w) PtrWrapper(new int); // no warn
69}
70
71//---------------
72// other checks
73//---------------
74
75void f(int *);
76
77void testUseAfterDelete() {
78  int *p = new int;
79  delete p;
80  f(p); // expected-warning{{Use of memory after it is freed}}
81}
82
83void testDeleteAlloca() {
84  int *p = (int *)__builtin_alloca(sizeof(int));
85  delete p; // expected-warning{{Memory allocated by alloca() should not be deallocated}}
86}
87
88void testDoubleDelete() {
89  int *p = new int;
90  delete p;
91  delete p; // expected-warning{{Attempt to free released memory}}
92}
93
94void testExprDeleteArg() {
95  int i;
96  delete &i; // expected-warning{{Argument to 'delete' is the address of the local variable 'i', which is not memory allocated by 'new'}}
97}
98
99void testExprDeleteArrArg() {
100  int i;
101  delete[] &i; // expected-warning{{Argument to 'delete[]' is the address of the local variable 'i', which is not memory allocated by 'new[]'}}
102}
103
104void testAllocDeallocNames() {
105  int *p = new(std::nothrow) int[1];
106  delete[] (++p); // expected-warning{{Argument to 'delete[]' is offset by 4 bytes from the start of memory allocated by 'new[]'}}
107}
108
109//--------------------------------
110// Test escape of newed const pointer. Note, a const pointer can be deleted.
111//--------------------------------
112struct StWithConstPtr {
113  const int *memp;
114};
115void escape(const int &x);
116void escapeStruct(const StWithConstPtr &x);
117void escapePtr(const StWithConstPtr *x);
118void escapeVoidPtr(const void *x);
119
120void testConstEscape() {
121  int *p = new int(1);
122  escape(*p);
123} // no-warning
124
125void testConstEscapeStruct() {
126  StWithConstPtr *St = new StWithConstPtr();
127  escapeStruct(*St);
128} // no-warning
129
130void testConstEscapeStructPtr() {
131  StWithConstPtr *St = new StWithConstPtr();
132  escapePtr(St);
133} // no-warning
134
135void testConstEscapeMember() {
136  StWithConstPtr St;
137  St.memp = new int(2);
138  escapeVoidPtr(St.memp);
139} // no-warning
140
141void testConstEscapePlacementNew() {
142  int *x = (int *)malloc(sizeof(int));
143  void *y = new (x) int;
144  escapeVoidPtr(y);
145} // no-warning
146