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
);
44 //----- Standard non-placement operators
45 void testGlobalOpNew() {
46 void *p
= operator new(0);
47 } // leak-warning{{Potential leak of memory pointed to by 'p'}}
49 void testGlobalOpNewArray() {
50 void *p
= operator new[](0);
51 } // leak-warning{{Potential leak of memory pointed to by 'p'}}
53 void testGlobalNewExpr() {
55 } // leak-warning{{Potential leak of memory pointed to by 'p'}}
57 void testGlobalNewExprArray() {
59 } // leak-warning{{Potential leak of memory pointed to by 'p'}}
61 //----- Standard nothrow placement operators
62 void testGlobalNoThrowPlacementOpNewBeforeOverload() {
63 void *p
= operator new(0, std::nothrow
);
64 } // leak-warning{{Potential leak of memory pointed to by 'p'}}
66 void testGlobalNoThrowPlacementExprNewBeforeOverload() {
67 int *p
= new(std::nothrow
) int;
68 } // leak-warning{{Potential leak of memory pointed to by 'p'}}
70 //----- Standard pointer placement operators
71 void testGlobalPointerPlacementNew() {
74 void *p1
= operator new(0, &i
); // no warn
76 void *p2
= operator new[](0, &i
); // no warn
78 int *p3
= new(&i
) int; // no warn
80 int *p4
= new(&i
) int[0]; // no warn
84 void testNewMemoryIsInHeap() {
86 if (global
!= p
) // condition is always true as 'p' wraps a heap region that
87 // is different from a region wrapped by 'global'
88 global
= p
; // pointer escapes
94 PtrWrapper(int *input
) : x(input
) {}
97 void testNewInvalidationPlacement(PtrWrapper
*w
) {
98 // Ensure that we don't consider this a leak.
99 new (w
) PtrWrapper(new int); // no warn
102 //-----------------------------------------
103 // check for usage of zero-allocated memory
104 //-----------------------------------------
106 void testUseZeroAlloc1() {
107 int *p
= (int *)operator new(0);
108 *p
= 1; // newdelete-warning {{Use of memory allocated with size zero}}
112 int testUseZeroAlloc2() {
113 int *p
= (int *)operator new[](0);
114 return p
[0]; // newdelete-warning {{Use of memory allocated with size zero}}
120 void testUseZeroAlloc3() {
122 f(*p
); // newdelete-warning {{Use of memory allocated with size zero}}
135 void f(int *p1
, int *p2
= 0, int *p3
= 0);
136 void g(SomeClass
&c
, ...);
138 void testUseFirstArgAfterDelete() {
141 f(p
); // newdelete-warning{{Use of memory after it is freed}}
144 void testUseMiddleArgAfterDelete(int *p
) {
146 f(0, p
); // newdelete-warning{{Use of memory after it is freed}}
149 void testUseLastArgAfterDelete(int *p
) {
151 f(0, 0, p
); // newdelete-warning{{Use of memory after it is freed}}
154 void testUseSeveralArgsAfterDelete(int *p
) {
156 f(p
, p
, p
); // newdelete-warning{{Use of memory after it is freed}}
159 void testUseRefArgAfterDelete(SomeClass
&c
) {
161 g(c
); // newdelete-warning{{Use of memory after it is freed}}
164 void testVariadicArgAfterDelete() {
168 g(c
, 0, p
); // newdelete-warning{{Use of memory after it is freed}}
171 void testUseMethodArgAfterDelete(int *p
) {
172 SomeClass
*c
= new SomeClass
;
174 c
->f(p
); // newdelete-warning{{Use of memory after it is freed}}
177 void testUseThisAfterDelete() {
178 SomeClass
*c
= new SomeClass
;
180 c
->f(0); // newdelete-warning{{Use of memory after it is freed}}
183 void testDoubleDelete() {
186 delete p
; // newdelete-warning{{Attempt to free released memory}}
189 void testExprDeleteArg() {
191 delete &i
; // newdelete-warning{{Argument to 'delete' is the address of the local variable 'i', which is not memory allocated by 'new'}}
194 void testExprDeleteArrArg() {
196 delete[] & i
; // newdelete-warning{{Argument to 'delete[]' is the address of the local variable 'i', which is not memory allocated by 'new[]'}}
199 void testAllocDeallocNames() {
200 int *p
= new(std::nothrow
) int[1];
202 // newdelete-warning@-1{{Argument to 'delete[]' is offset by 4 bytes from the start of memory allocated by 'new[]'}}
205 //--------------------------------
206 // Test escape of newed const pointer. Note, a const pointer can be deleted.
207 //--------------------------------
208 struct StWithConstPtr
{
211 void escape(const int &x
);
212 void escapeStruct(const StWithConstPtr
&x
);
213 void escapePtr(const StWithConstPtr
*x
);
214 void escapeVoidPtr(const void *x
);
216 void testConstEscape() {
221 void testConstEscapeStruct() {
222 StWithConstPtr
*St
= new StWithConstPtr();
226 void testConstEscapeStructPtr() {
227 StWithConstPtr
*St
= new StWithConstPtr();
231 void testConstEscapeMember() {
233 St
.memp
= new int(2);
234 escapeVoidPtr(St
.memp
);
237 void testConstEscapePlacementNew() {
238 int *x
= (int *)malloc(sizeof(int));
239 void *y
= new (x
) int;
243 //============== Test Uninitialized delete delete[]========================
244 void testUninitDelete() {
248 delete x
; // expected-warning{{Argument to 'delete' is uninitialized}}
251 void testUninitDeleteArray() {
253 int * y
= new int[5];
255 delete[] x
; // expected-warning{{Argument to 'delete[]' is uninitialized}}
258 void testUninitFree() {
260 free(x
); // expected-warning{{1st function call argument is an uninitialized value}}
263 void testUninitDeleteSink() {
265 delete x
; // expected-warning{{Argument to 'delete' is uninitialized}}
266 (*(volatile int *)0 = 1); // no warn
269 void testUninitDeleteArraySink() {
271 delete[] x
; // expected-warning{{Argument to 'delete[]' is uninitialized}}
272 (*(volatile int *)0 = 1); // no warn
275 namespace reference_count
{
276 class control_block
{
279 control_block() : count(0) {}
280 void retain() { ++count
; }
281 int release() { return --count
; }
284 template <typename T
>
287 control_block
*control
;
290 shared_ptr() : p(0), control(0) {}
291 explicit shared_ptr(T
*p
) : p(p
), control(new control_block
) {
294 shared_ptr(const shared_ptr
&other
) : p(other
.p
), control(other
.control
) {
299 if (control
&& control
->release() == 0) {
309 void swap(shared_ptr
&other
) {
314 control_block
*ctrlTmp
= control
;
315 control
= other
.control
;
316 other
.control
= ctrlTmp
;
320 template <typename T
, typename
... Args
>
321 shared_ptr
<T
> make_shared(Args
&&...args
) {
322 return shared_ptr
<T
>(new T(static_cast<Args
&&>(args
)...));
326 shared_ptr
<int> a(new int);
331 shared_ptr
<int> a
= make_shared
<int>();
335 void testMakeInParens() {
336 shared_ptr
<int> a
= (make_shared
<int>()); // no warn
341 shared_ptr
<int> a(new int);
342 shared_ptr
<int> b
= a
;
346 void testInvalidated() {
347 shared_ptr
<int> a(new int);
348 shared_ptr
<int> b
= a
;
351 extern void use(shared_ptr
<int> &);
355 void testNestedScope() {
356 shared_ptr
<int> a(new int);
358 shared_ptr
<int> b
= a
;
364 shared_ptr
<int> a(new int);
366 shared_ptr
<int> c
= a
;
367 shared_ptr
<int>(c
).swap(b
);
370 void testUseAfterFree() {
373 shared_ptr
<int> a(p
);
374 shared_ptr
<int> b
= a
;
377 // FIXME: We should get a warning here, but we don't because we've
378 // conservatively modeled ~shared_ptr.
383 // Test double delete
395 void testDoubleDeleteClassInstance() {
396 DerefClass
*foo
= new DerefClass();
398 delete foo
; // newdelete-warning {{Attempt to delete released memory}}
407 void testDoubleDeleteEmptyClass() {
408 EmptyClass
*foo
= new EmptyClass();
410 delete foo
; // newdelete-warning {{Attempt to delete released memory}}
417 struct Derived
: Base
{
424 void shouldNotReportLeak() {
425 Derived
*p
= (Derived
*)allocate();
429 template<void *allocate_fn(size_t)>
430 void* allocate_via_nttp(size_t n
) {
431 return allocate_fn(n
);
434 template<void deallocate_fn(void*)>
435 void deallocate_via_nttp(void* ptr
) {
439 void testNTTPNewNTTPDelete() {
440 void* p
= allocate_via_nttp
<::operator new>(10);
441 deallocate_via_nttp
<::operator delete>(p
);
444 void testNTTPNewDirectDelete() {
445 void* p
= allocate_via_nttp
<::operator new>(10);
446 ::operator delete(p
);
449 void testDirectNewNTTPDelete() {
450 void* p
= ::operator new(10);
451 deallocate_via_nttp
<::operator delete>(p
);
454 void not_free(void*) {
457 void testLeakBecauseNTTPIsNotDeallocation() {
458 void* p
= ::operator new(10);
459 deallocate_via_nttp
<not_free
>(p
);
460 } // leak-warning{{Potential leak of memory pointed to by 'p'}}