1 // RUN: %clang_analyze_cc1 -verify -analyzer-output=text %s \
2 // RUN: -analyzer-checker=core \
3 // RUN: -analyzer-checker=cplusplus \
4 // RUN: -analyzer-checker=unix \
5 // RUN: -analyzer-config \
6 // RUN: unix.DynamicMemoryModeling:AddNoOwnershipChangeNotes=false
8 // RUN: %clang_analyze_cc1 -verify=expected,ownership -analyzer-output=text %s \
9 // RUN: -analyzer-checker=core \
10 // RUN: -analyzer-checker=cplusplus \
11 // RUN: -analyzer-checker=unix \
12 // RUN: -analyzer-config \
13 // RUN: unix.DynamicMemoryModeling:AddNoOwnershipChangeNotes=true
15 #include "Inputs/system-header-simulator-for-malloc.h"
17 //===----------------------------------------------------------------------===//
18 // Report for which we expect NoOwnershipChangeVisitor to add a new note.
19 //===----------------------------------------------------------------------===//
23 // TODO: AST analysis of sink would reveal that it doesn't intent to free the
24 // allocated memory, but in this instance, its also the only function with
25 // the ability to do so, we should see a note here.
26 namespace memory_allocated_in_fn_call
{
32 sink(new int(5)); // expected-note {{Memory is allocated}}
33 } // expected-warning {{Potential memory leak [cplusplus.NewDeleteLeaks]}}
34 // expected-note@-1 {{Potential memory leak}}
36 } // namespace memory_allocated_in_fn_call
38 // Realize that sink() intends to deallocate memory, assume that it should've
39 // taken care of the leaked object as well.
40 namespace memory_passed_to_fn_call_delete
{
43 if (coin()) // ownership-note {{Assuming the condition is false}}
44 // ownership-note@-1 {{Taking false branch}}
46 } // ownership-note {{Returning without deallocating memory or storing the pointer for later deallocation}}
49 int *ptr
= new int(5); // expected-note {{Memory is allocated}}
50 sink(ptr
); // ownership-note {{Calling 'sink'}}
51 // ownership-note@-1 {{Returning from 'sink'}}
52 } // expected-warning {{Potential leak of memory pointed to by 'ptr' [cplusplus.NewDeleteLeaks]}}
53 // expected-note@-1 {{Potential leak}}
55 } // namespace memory_passed_to_fn_call_delete
57 namespace memory_passed_to_fn_call_free
{
60 if (coin()) // ownership-note {{Assuming the condition is false}}
61 // ownership-note@-1 {{Taking false branch}}
63 } // ownership-note {{Returning without deallocating memory or storing the pointer for later deallocation}}
66 int *ptr
= (int *)malloc(sizeof(int)); // expected-note {{Memory is allocated}}
67 sink(ptr
); // ownership-note {{Calling 'sink'}}
68 // ownership-note@-1 {{Returning from 'sink'}}
69 } // expected-warning {{Potential leak of memory pointed to by 'ptr' [unix.Malloc]}}
70 // expected-note@-1 {{Potential leak}}
72 } // namespace memory_passed_to_fn_call_free
74 // Function pointers cannot be resolved syntactically.
75 namespace memory_passed_to_fn_call_free_through_fn_ptr
{
76 void (*freeFn
)(void *) = free
;
84 int *ptr
= (int *)malloc(sizeof(int)); // expected-note {{Memory is allocated}}
86 } // expected-warning {{Potential leak of memory pointed to by 'ptr' [unix.Malloc]}}
87 // expected-note@-1 {{Potential leak}}
89 } // namespace memory_passed_to_fn_call_free_through_fn_ptr
91 namespace memory_shared_with_ptr_of_shorter_lifetime
{
95 if (coin()) // ownership-note {{Assuming the condition is false}}
96 // ownership-note@-1 {{Taking false branch}}
99 } // ownership-note {{Returning without deallocating memory or storing the pointer for later deallocation}}
102 int *ptr
= new int(5); // expected-note {{Memory is allocated}}
103 sink(ptr
); // ownership-note {{Calling 'sink'}}
104 // ownership-note@-1 {{Returning from 'sink'}}
105 } // expected-warning {{Potential leak of memory pointed to by 'ptr' [cplusplus.NewDeleteLeaks]}}
106 // expected-note@-1 {{Potential leak}}
108 } // namespace memory_shared_with_ptr_of_shorter_lifetime
110 //===----------------------------------------------------------------------===//
111 // Report for which we *do not* expect NoOwnershipChangeVisitor add a new note,
112 // nor do we want it to.
113 //===----------------------------------------------------------------------===//
115 namespace memory_not_passed_to_fn_call
{
123 int *ptr
= new int(5); // expected-note {{Memory is allocated}}
127 } // expected-warning {{Potential leak of memory pointed to by 'ptr' [cplusplus.NewDeleteLeaks]}}
128 // expected-note@-1 {{Potential leak}}
130 } // namespace memory_not_passed_to_fn_call
132 namespace memory_shared_with_ptr_of_same_lifetime
{
134 void sink(int *P
, int **Q
) {
135 // NOTE: Not a job of NoOwnershipChangeVisitor, but maybe this could be
136 // highlighted still?
141 int *ptr
= new int(5); // expected-note {{Memory is allocated}}
144 } // expected-warning {{Potential leak of memory pointed to by 'q' [cplusplus.NewDeleteLeaks]}}
145 // expected-note@-1 {{Potential leak}}
147 } // namespace memory_shared_with_ptr_of_same_lifetime
149 namespace memory_passed_into_fn_that_doesnt_intend_to_free
{
155 int *ptr
= new int(5); // expected-note {{Memory is allocated}}
157 } // expected-warning {{Potential leak of memory pointed to by 'ptr' [cplusplus.NewDeleteLeaks]}}
158 // expected-note@-1 {{Potential leak}}
160 } // namespace memory_passed_into_fn_that_doesnt_intend_to_free
162 namespace memory_passed_into_fn_that_doesnt_intend_to_free2
{
167 // Correctly realize that calling bar() doesn't mean that this function would
168 // like to deallocate anything.
173 int *ptr
= new int(5); // expected-note {{Memory is allocated}}
175 } // expected-warning {{Potential leak of memory pointed to by 'ptr' [cplusplus.NewDeleteLeaks]}}
176 // expected-note@-1 {{Potential leak}}
178 } // namespace memory_passed_into_fn_that_doesnt_intend_to_free2
180 namespace refkind_from_unoallocated_to_allocated
{
182 // RefKind of the symbol changed from nothing to Allocated. We don't want to
183 // emit notes when the RefKind changes in the stack frame.
184 static char *malloc_wrapper_ret() {
185 return (char *)malloc(12); // expected-note {{Memory is allocated}}
189 v
= malloc_wrapper_ret(); // expected-note {{Calling 'malloc_wrapper_ret'}}
190 // expected-note@-1 {{Returned allocated memory}}
191 } // expected-warning {{Potential leak of memory pointed to by 'v' [unix.Malloc]}}
192 // expected-note@-1 {{Potential leak of memory pointed to by 'v'}}
194 } // namespace refkind_from_unoallocated_to_allocated
196 // Check that memory leak is reported against a symbol if the last place it's
197 // mentioned is a base region of a lazy compound value, as the program cannot
198 // possibly free that memory.
199 namespace symbol_reaper_lifetime
{
207 Nested
allocateWrappingAndReturnNested() {
208 // expected-note@+1 {{Memory is allocated}}
209 Wrapping
const* p
= new Wrapping();
210 // expected-warning@+2 {{Potential leak of memory pointed to by 'p'}}
211 // expected-note@+1 {{Potential leak of memory pointed to by 'p'}}
216 // expected-note@+1 {{Calling 'allocateWrappingAndReturnNested'}}
217 Nested n
= allocateWrappingAndReturnNested();
219 } // no-warning: No potential memory leak here, because that's been already reported.
220 } // namespace symbol_reaper_lifetime