[clang] Handle __declspec() attributes in using
[llvm-project.git] / clang / test / Analysis / NewDeleteLeaks.cpp
blobb2bad7e76fad0605b4e78ec90903550cc5bacb84
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 //===----------------------------------------------------------------------===//
21 bool coin();
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 {
28 void sink(int *P) {
31 void foo() {
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 {
42 void sink(int *P) {
43 if (coin()) // ownership-note {{Assuming the condition is false}}
44 // ownership-note@-1 {{Taking false branch}}
45 delete P;
46 } // ownership-note {{Returning without deallocating memory or storing the pointer for later deallocation}}
48 void foo() {
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 {
59 void sink(int *P) {
60 if (coin()) // ownership-note {{Assuming the condition is false}}
61 // ownership-note@-1 {{Taking false branch}}
62 free(P);
63 } // ownership-note {{Returning without deallocating memory or storing the pointer for later deallocation}}
65 void foo() {
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;
78 void sink(int *P) {
79 if (coin())
80 freeFn(P);
83 void foo() {
84 int *ptr = (int *)malloc(sizeof(int)); // expected-note {{Memory is allocated}}
85 sink(ptr);
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 {
93 void sink(int *P) {
94 int *Q = P;
95 if (coin()) // ownership-note {{Assuming the condition is false}}
96 // ownership-note@-1 {{Taking false branch}}
97 delete P;
98 (void)Q;
99 } // ownership-note {{Returning without deallocating memory or storing the pointer for later deallocation}}
101 void foo() {
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 {
117 void sink(int *P) {
118 if (coin())
119 delete P;
122 void foo() {
123 int *ptr = new int(5); // expected-note {{Memory is allocated}}
124 int *q = nullptr;
125 sink(q);
126 (void)ptr;
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?
137 *Q = P;
140 void foo() {
141 int *ptr = new int(5); // expected-note {{Memory is allocated}}
142 int *q = nullptr;
143 sink(ptr, &q);
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 {
151 void sink(int *P) {
154 void foo() {
155 int *ptr = new int(5); // expected-note {{Memory is allocated}}
156 sink(ptr);
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 {
164 void bar();
166 void sink(int *P) {
167 // Correctly realize that calling bar() doesn't mean that this function would
168 // like to deallocate anything.
169 bar();
172 void foo() {
173 int *ptr = new int(5); // expected-note {{Memory is allocated}}
174 sink(ptr);
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}}
187 void use_ret() {
188 char *v;
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 {
200 struct Nested {
201 int buf[2];
203 struct Wrapping {
204 Nested data;
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'}}
212 return p->data;
215 void caller() {
216 // expected-note@+1 {{Calling 'allocateWrappingAndReturnNested'}}
217 Nested n = allocateWrappingAndReturnNested();
218 (void)n;
219 } // no-warning: No potential memory leak here, because that's been already reported.
220 } // namespace symbol_reaper_lifetime