[ELF] Avoid make in elf::writeARMCmseImportLib
[llvm-project.git] / clang / test / Analysis / stack-addr-ps.cpp
blob73e9dbeca460f603945dd51435c2334c99baf200
1 // RUN: %clang_analyze_cc1 \
2 // RUN: -analyzer-checker=core,debug.ExprInspection \
3 // RUN: -verify %s \
4 // RUN: -Wno-undefined-bool-conversion
5 // RUN: %clang_analyze_cc1 \
6 // RUN: -analyzer-checker=core,debug.ExprInspection,unix.Malloc \
7 // RUN: -verify %s \
8 // RUN: -Wno-undefined-bool-conversion
9 // unix.Malloc is necessary to model __builtin_alloca,
10 // which could trigger an "unexpected region" bug in StackAddrEscapeChecker.
12 typedef __INTPTR_TYPE__ intptr_t;
14 template <typename T>
15 void clang_analyzer_dump(T x);
17 using size_t = decltype(sizeof(int));
18 void * malloc(size_t size);
19 void free(void*);
21 const int& g() {
22 int s;
23 return s; // expected-warning{{Address of stack memory associated with local variable 's' returned}} expected-warning{{reference to stack memory associated with local variable 's' returned}}
26 const int& g2() {
27 int s1;
28 int &s2 = s1; // expected-note {{binding reference variable 's2' here}}
29 return s2; // expected-warning{{Address of stack memory associated with local variable 's1' returned}} expected-warning {{reference to stack memory associated with local variable 's1' returned}}
32 const int& g3() {
33 int s1;
34 int &s2 = s1; // expected-note {{binding reference variable 's2' here}}
35 int &s3 = s2; // expected-note {{binding reference variable 's3' here}}
36 return s3; // expected-warning{{Address of stack memory associated with local variable 's1' returned}} expected-warning {{reference to stack memory associated with local variable 's1' returned}}
39 void g4() {
40 static const int &x = 3; // no warning
43 int get_value();
45 const int &get_reference1() { return get_value(); } // expected-warning{{Address of stack memory associated with temporary object of type 'int' returned}} expected-warning {{returning reference to local temporary}}
47 const int &get_reference2() {
48 const int &x = get_value(); // expected-note {{binding reference variable 'x' here}}
49 return x; // expected-warning{{Address of stack memory associated with temporary object of type 'int' lifetime extended by local variable 'x' returned to caller}} expected-warning {{returning reference to local temporary}}
52 const int &get_reference3() {
53 const int &x1 = get_value(); // expected-note {{binding reference variable 'x1' here}}
54 const int &x2 = x1; // expected-note {{binding reference variable 'x2' here}}
55 return x2; // expected-warning{{Address of stack memory associated with temporary object of type 'int' lifetime extended by local variable 'x1' returned to caller}} expected-warning {{returning reference to local temporary}}
58 int global_var;
59 int *f1() {
60 int &y = global_var;
61 return &y;
64 int *f2() {
65 int x1;
66 int &x2 = x1; // expected-note {{binding reference variable 'x2' here}}
67 return &x2; // expected-warning{{Address of stack memory associated with local variable 'x1' returned}} expected-warning {{address of stack memory associated with local variable 'x1' returned}}
70 int *f3() {
71 int x1;
72 int *const &x2 = &x1; // expected-note {{binding reference variable 'x2' here}}
73 return x2; // expected-warning {{address of stack memory associated with local variable 'x1' returned}} expected-warning {{Address of stack memory associated with local variable 'x1' returned to caller}}
76 const int *f4() {
77 const int &x1 = get_value(); // expected-note {{binding reference variable 'x1' here}}
78 const int &x2 = x1; // expected-note {{binding reference variable 'x2' here}}
79 return &x2; // expected-warning{{Address of stack memory associated with temporary object of type 'int' lifetime extended by local variable 'x1' returned to caller}} expected-warning {{returning address of local temporary}}
82 struct S {
83 int x;
86 int *mf() {
87 S s1;
88 S &s2 = s1; // expected-note {{binding reference variable 's2' here}}
89 int &x = s2.x; // expected-note {{binding reference variable 'x' here}}
90 return &x; // expected-warning{{Address of stack memory associated with local variable 's1' returned}} expected-warning {{address of stack memory associated with local variable 's1' returned}}
93 void *lf() {
94 label:
95 void *const &x = &&label; // expected-note {{binding reference variable 'x' here}}
96 return x; // expected-warning {{returning address of label, which is local}}
99 template <typename T>
100 struct TS {
101 int *get();
102 int *m() {
103 int *&x = get();
104 return x;
108 int* f5() {
109 int& i = i; // expected-warning {{Assigned value is garbage or undefined}} expected-warning{{reference 'i' is not yet bound to a value when used within its own initialization}}
110 return &i;
113 void *radar13226577() {
114 void *p = &p;
115 return p; // expected-warning {{stack memory associated with local variable 'p' returned to caller}}
118 namespace rdar13296133 {
119 class ConvertsToBool {
120 public:
121 operator bool() const { return this; }
124 class ConvertsToIntptr {
125 public:
126 operator intptr_t() const { return reinterpret_cast<intptr_t>(this); }
129 class ConvertsToPointer {
130 public:
131 operator const void *() const { return this; }
134 intptr_t returnAsNonLoc() {
135 ConvertsToIntptr obj;
136 return obj; // expected-warning{{Address of stack memory associated with local variable 'obj' returned to caller}}
139 bool returnAsBool() {
140 ConvertsToBool obj;
141 return obj; // no-warning
144 intptr_t returnAsNonLocViaPointer() {
145 ConvertsToPointer obj;
146 return reinterpret_cast<intptr_t>(static_cast<const void *>(obj)); // expected-warning{{Address of stack memory associated with local variable 'obj' returned to caller}}
149 bool returnAsBoolViaPointer() {
150 ConvertsToPointer obj;
151 return obj; // no-warning
153 } // namespace rdar13296133
155 void write_stack_address_to(char **q) {
156 char local;
157 *q = &local;
158 // expected-warning@-1 {{Address of stack memory associated with local \
159 variable 'local' is still referred to by the caller variable 'p' upon \
160 returning to the caller}}
163 void test_stack() {
164 char *p;
165 write_stack_address_to(&p);
168 struct C {
169 ~C() {} // non-trivial class
172 C make1() {
173 C c;
174 return c; // no-warning
177 void test_copy_elision() {
178 C c1 = make1();
181 namespace leaking_via_direct_pointer {
182 void* returned_direct_pointer_top() {
183 int local = 42;
184 int* p = &local;
185 return p; // expected-warning{{associated with local variable 'local' returned}}
188 int* returned_direct_pointer_callee() {
189 int local = 42;
190 int* p = &local;
191 return p; // expected-warning{{associated with local variable 'local' returned}}
194 void returned_direct_pointer_caller() {
195 int* loc_ptr = nullptr;
196 loc_ptr = returned_direct_pointer_callee();
197 (void)loc_ptr;
200 void* global_ptr;
202 void global_direct_pointer() {
203 int local = 42;
204 global_ptr = &local; // expected-warning{{local variable 'local' is still referred to by the global variable 'global_ptr'}}
207 void static_direct_pointer_top() {
208 int local = 42;
209 static int* p = &local;
210 (void)p; // expected-warning{{local variable 'local' is still referred to by the static variable 'p'}}
213 void static_direct_pointer_callee() {
214 int local = 42;
215 static int* p = &local;
216 (void)p; // expected-warning{{local variable 'local' is still referred to by the static variable 'p'}}
219 void static_direct_pointer_caller() {
220 static_direct_pointer_callee();
223 void lambda_to_global_direct_pointer() {
224 auto lambda = [&] {
225 int local = 42;
226 global_ptr = &local; // expected-warning{{local variable 'local' is still referred to by the global variable 'global_ptr'}}
228 lambda();
231 void lambda_to_context_direct_pointer() {
232 int *p = nullptr;
233 auto lambda = [&] {
234 int local = 42;
235 p = &local; // expected-warning{{local variable 'local' is still referred to by the caller variable 'p'}}
237 lambda();
238 (void)p;
241 template<typename Callable>
242 class MyFunction {
243 Callable* fptr;
244 public:
245 MyFunction(Callable* callable) :fptr(callable) {}
248 void* lambda_to_context_direct_pointer_uncalled() {
249 int *p = nullptr;
250 auto lambda = [&] {
251 int local = 42;
252 p = &local; // no-warning: analyzed only as top-level, ignored explicitly by the checker
254 return new MyFunction(&lambda);
257 void lambda_to_context_direct_pointer_lifetime_extended() {
258 int *p = nullptr;
259 auto lambda = [&] {
260 int&& local = 42;
261 p = &local; // expected-warning{{'int' lifetime extended by local variable 'local' is still referred to by the caller variable 'p'}}
263 lambda();
264 (void)p;
267 template<typename Callback>
268 void lambda_param_capture_direct_pointer_callee(Callback& callee) {
269 int local = 42;
270 callee(local); // expected-warning{{'local' is still referred to by the caller variable 'p'}}
273 void lambda_param_capture_direct_pointer_caller() {
274 int* p = nullptr;
275 auto capt = [&p](int& param) {
276 p = &param;
278 lambda_param_capture_direct_pointer_callee(capt);
280 } // namespace leaking_via_direct_pointer
282 namespace leaking_via_ptr_to_ptr {
283 void** returned_ptr_to_ptr_top() {
284 int local = 42;
285 int* p = &local;
286 void** pp = (void**)&p;
287 return pp; // expected-warning{{associated with local variable 'p' returned}}
290 void** global_pp;
292 void global_ptr_local_to_ptr() {
293 int local = 42;
294 int* p = &local;
295 global_pp = (void**)&p; // expected-warning{{local variable 'p' is still referred to by the global variable 'global_pp'}}
298 void global_ptr_to_ptr() {
299 int local = 42;
300 *global_pp = &local; // expected-warning{{local variable 'local' is still referred to by the global variable 'global_pp'}}
303 void *** global_ppp;
305 void global_ptr_to_ptr_to_ptr() {
306 int local = 42;
307 **global_ppp = &local; // expected-warning{{local variable 'local' is still referred to by the global variable 'global_ppp'}}
310 void** get_some_pp();
312 void static_ptr_to_ptr() {
313 int local = 42;
314 static void** pp = get_some_pp();
315 *pp = &local;
316 } // no-warning False Negative, requires relating multiple bindings to cross the invented pointer.
318 void param_ptr_to_ptr_top(void** pp) {
319 int local = 42;
320 *pp = &local; // expected-warning{{local variable 'local' is still referred to by the caller variable 'pp'}}
323 void param_ptr_to_ptr_callee(void** pp) {
324 int local = 42;
325 *pp = &local; // expected-warning{{local variable 'local' is still referred to by the caller variable 'p'}}
328 void param_ptr_to_ptr_caller() {
329 void* p = nullptr;
330 param_ptr_to_ptr_callee((void**)&p);
333 void param_ptr_to_ptr_to_ptr_top(void*** ppp) {
334 int local = 42;
335 **ppp = &local; // expected-warning {{local variable 'local' is still referred to by the caller variable 'ppp'}}
338 void param_ptr_to_ptr_to_ptr_callee(void*** ppp) {
339 int local = 42;
340 **ppp = &local; // expected-warning{{local variable 'local' is still referred to by the caller variable 'pp'}}
343 void param_ptr_to_ptr_to_ptr_caller(void** pp) {
344 param_ptr_to_ptr_to_ptr_callee(&pp);
347 void lambda_to_context_ptr_to_ptr(int **pp) {
348 auto lambda = [&] {
349 int local = 42;
350 *pp = &local; // expected-warning{{local variable 'local' is still referred to by the caller variable 'pp'}}
352 lambda();
353 (void)*pp;
356 void param_ptr_to_ptr_fptr(int **pp) {
357 int local = 42;
358 *pp = &local; // expected-warning{{local variable 'local' is still referred to by the caller variable 'p'}}
361 void param_ptr_to_ptr_fptr_caller(void (*fptr)(int**)) {
362 int* p = nullptr;
363 fptr(&p);
366 void param_ptr_to_ptr_caller_caller() {
367 void (*fptr)(int**) = param_ptr_to_ptr_fptr;
368 param_ptr_to_ptr_fptr_caller(fptr);
370 } // namespace leaking_via_ptr_to_ptr
372 namespace leaking_via_ref_to_ptr {
373 void** make_ptr_to_ptr();
374 void*& global_rtp = *make_ptr_to_ptr();
376 void global_ref_to_ptr() {
377 int local = 42;
378 int* p = &local;
379 global_rtp = p; // expected-warning{{local variable 'local' is still referred to by the global variable 'global_rtp'}}
382 void static_ref_to_ptr() {
383 int local = 42;
384 static void*& p = *make_ptr_to_ptr();
385 p = &local;
386 (void)p;
387 } // no-warning False Negative, requires relating multiple bindings to cross the invented pointer.
389 void param_ref_to_ptr_top(void*& rp) {
390 int local = 42;
391 int* p = &local;
392 rp = p; // expected-warning{{local variable 'local' is still referred to by the caller variable 'rp'}}
395 void param_ref_to_ptr_callee(void*& rp) {
396 int local = 42;
397 int* p = &local;
398 rp = p; // expected-warning{{local variable 'local' is still referred to by the caller variable 'p'}}
401 void param_ref_to_ptr_caller() {
402 void* p = nullptr;
403 param_ref_to_ptr_callee(p);
405 } // namespace leaking_via_ref_to_ptr
407 namespace leaking_via_arr_of_ptr_static_idx {
408 void** returned_arr_of_ptr_top() {
409 int local = 42;
410 int* p = &local;
411 void** arr = new void*[2];
412 arr[1] = p;
413 return arr;
414 } // no-warning False Negative
416 void** returned_arr_of_ptr_callee() {
417 int local = 42;
418 int* p = &local;
419 void** arr = new void*[2];
420 arr[1] = p;
421 return arr;
422 } // no-warning False Negative
424 void returned_arr_of_ptr_caller() {
425 void** arr = returned_arr_of_ptr_callee();
426 (void)arr[1];
429 void* global_aop[2];
431 void global_arr_of_ptr() {
432 int local = 42;
433 int* p = &local;
434 global_aop[1] = p; // expected-warning{{local variable 'local' is still referred to by the global variable 'global_aop'}}
437 void static_arr_of_ptr() {
438 int local = 42;
439 static void* arr[2];
440 arr[1] = &local;
441 (void)arr[1]; // expected-warning{{local variable 'local' is still referred to by the static variable 'arr'}}
444 void param_arr_of_ptr_top(void* arr[2]) {
445 int local = 42;
446 int* p = &local;
447 arr[1] = p; // expected-warning{{local variable 'local' is still referred to by the caller variable 'arr'}}
450 void param_arr_of_ptr_callee(void* arr[2]) {
451 int local = 42;
452 int* p = &local;
453 arr[1] = p; // expected-warning{{local variable 'local' is still referred to by the caller variable 'arrStack'}}
456 void param_arr_of_ptr_caller() {
457 void* arrStack[2];
458 param_arr_of_ptr_callee(arrStack);
459 (void)arrStack[1];
461 } // namespace leaking_via_arr_of_ptr_static_idx
463 namespace leaking_via_arr_of_ptr_dynamic_idx {
464 void** returned_arr_of_ptr_top(int idx) {
465 int local = 42;
466 int* p = &local;
467 void** arr = new void*[2];
468 arr[idx] = p;
469 return arr;
470 } // no-warning False Negative
472 void** returned_arr_of_ptr_callee(int idx) {
473 int local = 42;
474 int* p = &local;
475 void** arr = new void*[2];
476 arr[idx] = p;
477 return arr;
478 } // no-warning False Negative
480 void returned_arr_of_ptr_caller(int idx) {
481 void** arr = returned_arr_of_ptr_callee(idx);
482 (void)arr[idx];
485 void* global_aop[2];
487 void global_arr_of_ptr(int idx) {
488 int local = 42;
489 int* p = &local;
490 global_aop[idx] = p; // expected-warning{{local variable 'local' is still referred to by the global variable 'global_aop'}}
493 void static_arr_of_ptr(int idx) {
494 int local = 42;
495 static void* arr[2];
496 arr[idx] = &local;
497 (void)arr[idx]; // expected-warning{{local variable 'local' is still referred to by the static variable 'arr'}}
500 void param_arr_of_ptr_top(void* arr[2], int idx) {
501 int local = 42;
502 int* p = &local;
503 arr[idx] = p; // expected-warning{{local variable 'local' is still referred to by the caller variable 'arr'}}
506 void param_arr_of_ptr_callee(void* arr[2], int idx) {
507 int local = 42;
508 int* p = &local;
509 arr[idx] = p; // expected-warning{{local variable 'local' is still referred to by the caller variable 'arrStack'}}
512 void param_arr_of_ptr_caller(int idx) {
513 void* arrStack[2];
514 param_arr_of_ptr_callee(arrStack, idx);
515 (void)arrStack[idx];
517 } // namespace leaking_via_arr_of_ptr_dynamic_idx
519 namespace leaking_via_struct_with_ptr {
520 struct S {
521 int* p;
524 S returned_struct_with_ptr_top() {
525 int local = 42;
526 S s;
527 s.p = &local;
528 return s;
529 } // no-warning False Negative, requires traversing returned LazyCompoundVals
531 S returned_struct_with_ptr_callee() {
532 int local = 42;
533 S s;
534 s.p = &local;
535 return s; // expected-warning{{'local' is still referred to by the caller variable 's'}}
538 void returned_struct_with_ptr_caller() {
539 S s = returned_struct_with_ptr_callee();
540 (void)s.p;
543 S global_s;
545 void global_struct_with_ptr() {
546 int local = 42;
547 global_s.p = &local; // expected-warning{{'local' is still referred to by the global variable 'global_s'}}
550 void static_struct_with_ptr() {
551 int local = 42;
552 static S s;
553 s.p = &local;
554 (void)s.p; // expected-warning{{'local' is still referred to by the static variable 's'}}
556 } // namespace leaking_via_struct_with_ptr
558 namespace leaking_via_ref_to_struct_with_ptr {
559 struct S {
560 int* p;
563 S &global_s = *(new S);
565 void global_ref_to_struct_with_ptr() {
566 int local = 42;
567 global_s.p = &local; // expected-warning{{'local' is still referred to by the global variable 'global_s'}}
570 void static_ref_to_struct_with_ptr() {
571 int local = 42;
572 static S &s = *(new S);
573 s.p = &local;
574 (void)s.p;
575 } // no-warning False Negative, requires relating multiple bindings to cross a heap region.
577 void param_ref_to_struct_with_ptr_top(S &s) {
578 int local = 42;
579 s.p = &local; // expected-warning{{'local' is still referred to by the caller variable 's'}}
582 void param_ref_to_struct_with_ptr_callee(S &s) {
583 int local = 42;
584 s.p = &local; // expected-warning{{'local' is still referred to by the caller variable 'sStack'}}
587 void param_ref_to_struct_with_ptr_caller() {
588 S sStack;
589 param_ref_to_struct_with_ptr_callee(sStack);
592 template<typename Callable>
593 void lambda_param_capture_callee(Callable& callee) {
594 int local = 42;
595 callee(local); // expected-warning{{'local' is still referred to by the caller variable 'p'}}
598 void lambda_param_capture_caller() {
599 int* p = nullptr;
600 auto capt = [&p](int& param) {
601 p = &param;
603 lambda_param_capture_callee(capt);
605 } // namespace leaking_via_ref_to_struct_with_ptr
607 namespace leaking_via_ptr_to_struct_with_ptr {
608 struct S {
609 int* p;
612 S* returned_ptr_to_struct_with_ptr_top() {
613 int local = 42;
614 S* s = new S;
615 s->p = &local;
616 return s;
617 } // no-warning False Negative
619 S* returned_ptr_to_struct_with_ptr_callee() {
620 int local = 42;
621 S* s = new S;
622 s->p = &local;
623 return s;
624 } // no-warning False Negative
626 void returned_ptr_to_struct_with_ptr_caller() {
627 S* s = returned_ptr_to_struct_with_ptr_callee();
628 (void)s->p;
631 S* global_s;
633 void global_ptr_to_struct_with_ptr() {
634 int local = 42;
635 global_s->p = &local; // expected-warning{{'local' is still referred to by the global variable 'global_s'}}
638 void static_ptr_to_struct_with_ptr_new() {
639 int local = 42;
640 static S* s = new S;
641 s->p = &local;
642 (void)s->p;
643 } // no-warning False Negative, requires relating multiple bindings to cross a heap region.
645 S* get_some_s();
647 void static_ptr_to_struct_with_ptr_generated() {
648 int local = 42;
649 static S* s = get_some_s();
650 s->p = &local;
651 } // no-warning False Negative, requires relating multiple bindings to cross the invented pointer.
653 void param_ptr_to_struct_with_ptr_top(S* s) {
654 int local = 42;
655 s->p = &local; // expected-warning{{'local' is still referred to by the caller variable 's'}}
658 void param_ptr_to_struct_with_ptr_callee(S* s) {
659 int local = 42;
660 s->p = &local; // expected-warning{{'local' is still referred to by the caller variable 's'}}
663 void param_ptr_to_struct_with_ptr_caller() {
664 S s;
665 param_ptr_to_struct_with_ptr_callee(&s);
666 (void)s.p;
668 } // namespace leaking_via_ptr_to_struct_with_ptr
670 namespace leaking_via_arr_of_struct_with_ptr {
671 struct S {
672 int* p;
675 S* returned_ptr_to_struct_with_ptr_top() {
676 int local = 42;
677 S* s = new S[2];
678 s[1].p = &local;
679 return s;
680 } // no-warning False Negative
682 S* returned_ptr_to_struct_with_ptr_callee() {
683 int local = 42;
684 S* s = new S[2];
685 s[1].p = &local;
686 return s;
687 } // no-warning False Negative
689 void returned_ptr_to_struct_with_ptr_caller() {
690 S* s = returned_ptr_to_struct_with_ptr_callee();
691 (void)s[1].p;
694 S global_s[2];
696 void global_ptr_to_struct_with_ptr() {
697 int local = 42;
698 global_s[1].p = &local; // expected-warning{{'local' is still referred to by the global variable 'global_s'}}
701 void static_ptr_to_struct_with_ptr_new() {
702 int local = 42;
703 static S* s = new S[2];
704 s[1].p = &local;
705 (void)s[1].p;
708 S* get_some_s();
710 void static_ptr_to_struct_with_ptr_generated() {
711 int local = 42;
712 static S* s = get_some_s();
713 s[1].p = &local;
714 } // no-warning False Negative, requires relating multiple bindings to cross the invented pointer.
716 void param_ptr_to_struct_with_ptr_top(S s[2]) {
717 int local = 42;
718 s[1].p = &local; // expected-warning{{'local' is still referred to by the caller variable 's'}}
721 void param_ptr_to_struct_with_ptr_callee(S s[2]) {
722 int local = 42;
723 s[1].p = &local; // expected-warning{{'local' is still referred to by the caller variable 's'}}
726 void param_ptr_to_struct_with_ptr_caller() {
727 S s[2];
728 param_ptr_to_struct_with_ptr_callee(s);
729 (void)s[1].p;
731 } // namespace leaking_via_arr_of_struct_with_ptr
733 namespace leaking_via_nested_and_indirect {
734 struct NestedAndTransitive {
735 int** p;
736 NestedAndTransitive* next[3];
739 NestedAndTransitive global_nat;
741 void global_nested_and_transitive() {
742 int local = 42;
743 *global_nat.next[2]->next[1]->p = &local; // expected-warning{{'local' is still referred to by the global variable 'global_nat'}}
746 void param_nested_and_transitive_top(NestedAndTransitive* nat) {
747 int local = 42;
748 *nat->next[2]->next[1]->p = &local; // expected-warning{{'local' is still referred to by the caller variable 'nat'}}
751 void param_nested_and_transitive_callee(NestedAndTransitive* nat) {
752 int local = 42;
753 *nat->next[2]->next[1]->p = &local; // expected-warning{{'local' is still referred to by the caller variable 'natCaller'}}
756 void param_nested_and_transitive_caller(NestedAndTransitive natCaller) {
757 param_nested_and_transitive_callee(&natCaller);
760 } // namespace leaking_via_nested_and_indirect
762 namespace leaking_as_member {
763 class CRef {
764 int& ref; // expected-note{{reference member declared here}}
765 CRef(int x) : ref(x) {}
766 // expected-warning@-1 {{binding reference member 'ref' to stack allocated parameter 'x'}}
769 class CPtr {
770 int* ptr;
771 void memFun(int x) {
772 ptr = &x;
775 } // namespace leaking_as_member
777 namespace origin_region_limitation {
778 void leaker(int ***leakerArg) {
779 int local;
780 clang_analyzer_dump(*leakerArg); // expected-warning{{&SymRegion{reg_$0<int ** arg>}}}
781 // Incorrect message: 'arg', after it is reinitialized with value returned by 'tweak'
782 // is no longer relevant.
783 // The message must refer to 'original_arg' instead, but there is no easy way to
784 // connect the SymRegion stored in 'original_arg' and 'original_arg' as variable.
785 **leakerArg = &local; // expected-warning{{ 'local' is still referred to by the caller variable 'arg'}}
788 int **tweak();
790 void foo(int **arg) {
791 int **original_arg = arg;
792 arg = tweak();
793 leaker(&original_arg);
795 } // namespace origin_region_limitation
797 namespace leaking_via_indirect_global_invalidated {
798 void** global_pp;
799 void opaque();
800 void global_ptr_to_ptr() {
801 int local = 42;
802 *global_pp = &local;
803 opaque();
804 *global_pp = nullptr;
806 } // namespace leaking_via_indirect_global_invalidated
808 namespace not_leaking_via_simple_ptr {
809 void simple_ptr(const char *p) {
810 char tmp;
811 p = &tmp; // no-warning
814 void ref_ptr(const char *&p) {
815 char tmp;
816 p = &tmp; // expected-warning{{variable 'tmp' is still referred to by the caller variable 'p'}}
819 struct S {
820 const char *p;
823 void struct_ptr(S s) {
824 char tmp;
825 s.p = &tmp; // no-warning
828 void array(const char arr[2]) {
829 char tmp;
830 arr = &tmp; // no-warning
833 extern void copy(char *output, const char *input, unsigned size);
834 extern bool foo(const char *input);
835 extern void bar(char *output, unsigned count);
836 extern bool baz(char *output, const char *input);
838 void repo(const char *input, char *output) {
839 char temp[64];
840 copy(temp, input, sizeof(temp));
842 char result[64];
843 input = temp;
844 if (foo(temp)) {
845 bar(result, sizeof(result));
846 input = result;
848 if (!baz(output, input)) {
849 copy(output, input, sizeof(result));
852 } // namespace not_leaking_via_simple_ptr
854 namespace early_reclaim_dead_limitation {
855 void foo();
856 void top(char **p) {
857 char local;
858 *p = &local;
859 foo(); // no-warning FIXME: p binding is reclaimed before the function end
861 } // namespace early_reclaim_dead_limitation
863 namespace alloca_region_pointer {
864 void callee(char **pptr) {
865 char local;
866 *pptr = &local;
867 } // no crash
869 void top_alloca_no_crash_fn() {
870 char **pptr = (char**)__builtin_alloca(sizeof(char*));
871 callee(pptr);
874 void top_malloc_no_crash_fn() {
875 char **pptr = (char**)malloc(sizeof(char*));
876 callee(pptr);
877 free(pptr);
879 } // namespace alloca_region_pointer