NewDelete-checker-test.cpp revision 3d11708c491a96198ebfee49079ae458ed90eaf8
1// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.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