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