1 // RUN: %clang_analyze_cc1 -std=c++11 -fblocks %s \
2 // RUN: -verify=expected,newdelete \
3 // RUN: -analyzer-checker=core \
4 // RUN: -analyzer-checker=cplusplus.NewDelete
6 // RUN: %clang_analyze_cc1 -DLEAKS -std=c++11 -fblocks %s \
7 // RUN: -verify=expected,newdelete,leak \
8 // RUN: -analyzer-checker=core \
9 // RUN: -analyzer-checker=cplusplus.NewDelete \
10 // RUN: -analyzer-checker=cplusplus.NewDeleteLeaks
12 // RUN: %clang_analyze_cc1 -std=c++11 -fblocks -verify %s \
13 // RUN: -verify=expected,leak \
14 // RUN: -analyzer-checker=core \
15 // RUN: -analyzer-checker=cplusplus.NewDeleteLeaks
17 // RUN: %clang_analyze_cc1 -std=c++17 -fblocks %s \
18 // RUN: -verify=expected,newdelete \
19 // RUN: -analyzer-checker=core \
20 // RUN: -analyzer-checker=cplusplus.NewDelete
22 // RUN: %clang_analyze_cc1 -DLEAKS -std=c++17 -fblocks %s \
23 // RUN: -verify=expected,newdelete,leak \
24 // RUN: -analyzer-checker=core \
25 // RUN: -analyzer-checker=cplusplus.NewDelete \
26 // RUN: -analyzer-checker=cplusplus.NewDeleteLeaks
28 // RUN: %clang_analyze_cc1 -std=c++17 -fblocks -verify %s \
29 // RUN: -verify=expected,leak \
30 // RUN: -analyzer-checker=core \
31 // RUN: -analyzer-checker=cplusplus.NewDeleteLeaks
33 #include "Inputs/system-header-simulator-cxx.h"
35 typedef __typeof__(sizeof(int)) size_t;
36 extern "C" void *malloc(size_t);
37 extern "C" void free (void* ptr
);
40 //----- Standard non-placement operators
41 void testGlobalOpNew() {
42 void *p
= operator new(0);
43 } // leak-warning{{Potential leak of memory pointed to by 'p'}}
45 void testGlobalOpNewArray() {
46 void *p
= operator new[](0);
47 } // leak-warning{{Potential leak of memory pointed to by 'p'}}
49 void testGlobalNewExpr() {
51 } // leak-warning{{Potential leak of memory pointed to by 'p'}}
53 void testGlobalNewExprArray() {
55 } // leak-warning{{Potential leak of memory pointed to by 'p'}}
57 //----- Standard nothrow placement operators
58 void testGlobalNoThrowPlacementOpNewBeforeOverload() {
59 void *p
= operator new(0, std::nothrow
);
60 } // leak-warning{{Potential leak of memory pointed to by 'p'}}
62 void testGlobalNoThrowPlacementExprNewBeforeOverload() {
63 int *p
= new(std::nothrow
) int;
64 } // leak-warning{{Potential leak of memory pointed to by 'p'}}
67 void testNewMemoryIsInHeap() {
69 if (global
!= p
) // condition is always true as 'p' wraps a heap region that
70 // is different from a region wrapped by 'global'
71 global
= p
; // pointer escapes
77 PtrWrapper(int *input
) : x(input
) {}
80 void testNewInvalidationPlacement(PtrWrapper
*w
) {
81 // Ensure that we don't consider this a leak.
82 new (w
) PtrWrapper(new int); // no warn
85 //-----------------------------------------
86 // check for usage of zero-allocated memory
87 //-----------------------------------------
89 void testUseZeroAlloc1() {
90 int *p
= (int *)operator new(0);
91 *p
= 1; // newdelete-warning {{Use of memory allocated with size zero}}
95 int testUseZeroAlloc2() {
96 int *p
= (int *)operator new[](0);
97 return p
[0]; // newdelete-warning {{Use of memory allocated with size zero}}
103 void testUseZeroAlloc3() {
105 f(*p
); // newdelete-warning {{Use of memory allocated with size zero}}
118 void f(int *p1
, int *p2
= 0, int *p3
= 0);
119 void g(SomeClass
&c
, ...);
121 void testUseFirstArgAfterDelete() {
124 f(p
); // newdelete-warning{{Use of memory after it is freed}}
127 void testUseMiddleArgAfterDelete(int *p
) {
129 f(0, p
); // newdelete-warning{{Use of memory after it is freed}}
132 void testUseLastArgAfterDelete(int *p
) {
134 f(0, 0, p
); // newdelete-warning{{Use of memory after it is freed}}
137 void testUseSeveralArgsAfterDelete(int *p
) {
139 f(p
, p
, p
); // newdelete-warning{{Use of memory after it is freed}}
142 void testUseRefArgAfterDelete(SomeClass
&c
) {
144 g(c
); // newdelete-warning{{Use of memory after it is freed}}
147 void testVariadicArgAfterDelete() {
151 g(c
, 0, p
); // newdelete-warning{{Use of memory after it is freed}}
154 void testUseMethodArgAfterDelete(int *p
) {
155 SomeClass
*c
= new SomeClass
;
157 c
->f(p
); // newdelete-warning{{Use of memory after it is freed}}
160 void testUseThisAfterDelete() {
161 SomeClass
*c
= new SomeClass
;
163 c
->f(0); // newdelete-warning{{Use of memory after it is freed}}
166 void testDoubleDelete() {
169 delete p
; // newdelete-warning{{Attempt to free released memory}}
172 void testExprDeleteArg() {
174 delete &i
; // newdelete-warning{{Argument to 'delete' is the address of the local variable 'i', which is not memory allocated by 'new'}}
177 void testExprDeleteArrArg() {
179 delete[] & i
; // newdelete-warning{{Argument to 'delete[]' is the address of the local variable 'i', which is not memory allocated by 'new[]'}}
182 void testAllocDeallocNames() {
183 int *p
= new(std::nothrow
) int[1];
185 // newdelete-warning@-1{{Argument to 'delete[]' is offset by 4 bytes from the start of memory allocated by 'new[]'}}
188 //--------------------------------
189 // Test escape of newed const pointer. Note, a const pointer can be deleted.
190 //--------------------------------
191 struct StWithConstPtr
{
194 void escape(const int &x
);
195 void escapeStruct(const StWithConstPtr
&x
);
196 void escapePtr(const StWithConstPtr
*x
);
197 void escapeVoidPtr(const void *x
);
199 void testConstEscape() {
204 void testConstEscapeStruct() {
205 StWithConstPtr
*St
= new StWithConstPtr();
209 void testConstEscapeStructPtr() {
210 StWithConstPtr
*St
= new StWithConstPtr();
214 void testConstEscapeMember() {
216 St
.memp
= new int(2);
217 escapeVoidPtr(St
.memp
);
220 void testConstEscapePlacementNew() {
221 int *x
= (int *)malloc(sizeof(int));
222 void *y
= new (x
) int;
226 //============== Test Uninitialized delete delete[]========================
227 void testUninitDelete() {
231 delete x
; // expected-warning{{Argument to 'delete' is uninitialized}}
234 void testUninitDeleteArray() {
236 int * y
= new int[5];
238 delete[] x
; // expected-warning{{Argument to 'delete[]' is uninitialized}}
241 void testUninitFree() {
243 free(x
); // expected-warning{{1st function call argument is an uninitialized value}}
246 void testUninitDeleteSink() {
248 delete x
; // expected-warning{{Argument to 'delete' is uninitialized}}
249 (*(volatile int *)0 = 1); // no warn
252 void testUninitDeleteArraySink() {
254 delete[] x
; // expected-warning{{Argument to 'delete[]' is uninitialized}}
255 (*(volatile int *)0 = 1); // no warn
258 namespace reference_count
{
259 class control_block
{
262 control_block() : count(0) {}
263 void retain() { ++count
; }
264 int release() { return --count
; }
267 template <typename T
>
270 control_block
*control
;
273 shared_ptr() : p(0), control(0) {}
274 explicit shared_ptr(T
*p
) : p(p
), control(new control_block
) {
277 shared_ptr(const shared_ptr
&other
) : p(other
.p
), control(other
.control
) {
282 if (control
&& control
->release() == 0) {
292 void swap(shared_ptr
&other
) {
297 control_block
*ctrlTmp
= control
;
298 control
= other
.control
;
299 other
.control
= ctrlTmp
;
303 template <typename T
, typename
... Args
>
304 shared_ptr
<T
> make_shared(Args
&&...args
) {
305 return shared_ptr
<T
>(new T(static_cast<Args
&&>(args
)...));
309 shared_ptr
<int> a(new int);
314 shared_ptr
<int> a
= make_shared
<int>();
318 void testMakeInParens() {
319 shared_ptr
<int> a
= (make_shared
<int>()); // no warn
324 shared_ptr
<int> a(new int);
325 shared_ptr
<int> b
= a
;
329 void testInvalidated() {
330 shared_ptr
<int> a(new int);
331 shared_ptr
<int> b
= a
;
334 extern void use(shared_ptr
<int> &);
338 void testNestedScope() {
339 shared_ptr
<int> a(new int);
341 shared_ptr
<int> b
= a
;
347 shared_ptr
<int> a(new int);
349 shared_ptr
<int> c
= a
;
350 shared_ptr
<int>(c
).swap(b
);
353 void testUseAfterFree() {
356 shared_ptr
<int> a(p
);
357 shared_ptr
<int> b
= a
;
360 // FIXME: We should get a warning here, but we don't because we've
361 // conservatively modeled ~shared_ptr.
366 // Test double delete
378 void testDoubleDeleteClassInstance() {
379 DerefClass
*foo
= new DerefClass();
381 delete foo
; // newdelete-warning {{Attempt to delete released memory}}
390 void testDoubleDeleteEmptyClass() {
391 EmptyClass
*foo
= new EmptyClass();
393 delete foo
; // newdelete-warning {{Attempt to delete released memory}}
400 struct Derived
: Base
{
407 void shouldNotReportLeak() {
408 Derived
*p
= (Derived
*)allocate();
412 template<void *allocate_fn(size_t)>
413 void* allocate_via_nttp(size_t n
) {
414 return allocate_fn(n
);
417 template<void deallocate_fn(void*)>
418 void deallocate_via_nttp(void* ptr
) {
422 void testNTTPNewNTTPDelete() {
423 void* p
= allocate_via_nttp
<::operator new>(10);
424 deallocate_via_nttp
<::operator delete>(p
);
427 void testNTTPNewDirectDelete() {
428 void* p
= allocate_via_nttp
<::operator new>(10);
429 ::operator delete(p
);
432 void testDirectNewNTTPDelete() {
433 void* p
= ::operator new(10);
434 deallocate_via_nttp
<::operator delete>(p
);
437 void not_free(void*) {
440 void testLeakBecauseNTTPIsNotDeallocation() {
441 void* p
= ::operator new(10);
442 deallocate_via_nttp
<not_free
>(p
);
443 } // leak-warning{{Potential leak of memory pointed to by 'p'}}