946 lines · cpp
1// RUN: %clang_cc1 -fsyntax-only -fexperimental-lifetime-safety -Wexperimental-lifetime-safety -Wno-dangling -verify %s2 3struct MyObj {4 int id;5 ~MyObj() {} // Non-trivial destructor6 MyObj operator+(MyObj);7};8 9struct [[gsl::Pointer()]] View {10 View(const MyObj&); // Borrows from MyObj11 View();12 void use() const;13};14 15class TriviallyDestructedClass {16 View a, b;17};18 19//===----------------------------------------------------------------------===//20// Basic Definite Use-After-Free (-W...permissive)21// These are cases where the pointer is guaranteed to be dangling at the use site.22//===----------------------------------------------------------------------===//23 24void definite_simple_case() {25 MyObj* p;26 {27 MyObj s;28 p = &s; // expected-warning {{object whose reference is captured does not live long enough}}29 } // expected-note {{destroyed here}}30 (void)*p; // expected-note {{later used here}}31}32 33void definite_simple_case_gsl() {34 View v;35 {36 MyObj s;37 v = s; // expected-warning {{object whose reference is captured does not live long enough}}38 } // expected-note {{destroyed here}}39 v.use(); // expected-note {{later used here}}40}41 42void no_use_no_error() {43 MyObj* p;44 {45 MyObj s;46 p = &s;47 }48 // 'p' is dangling here, but since it is never used, no warning is issued.49}50 51void no_use_no_error_gsl() {52 View v;53 {54 MyObj s;55 v = s;56 }57 // 'v' is dangling here, but since it is never used, no warning is issued.58}59 60void definite_pointer_chain() {61 MyObj* p;62 MyObj* q;63 {64 MyObj s;65 p = &s; // expected-warning {{does not live long enough}}66 q = p;67 } // expected-note {{destroyed here}}68 (void)*q; // expected-note {{later used here}}69}70 71void definite_propagation_gsl() {72 View v1, v2;73 {74 MyObj s;75 v1 = s; // expected-warning {{object whose reference is captured does not live long enough}}76 v2 = v1;77 } // expected-note {{destroyed here}}78 v2.use(); // expected-note {{later used here}}79}80 81void definite_multiple_uses_one_warning() {82 MyObj* p;83 {84 MyObj s;85 p = &s; // expected-warning {{does not live long enough}}86 } // expected-note {{destroyed here}}87 (void)*p; // expected-note {{later used here}}88 // No second warning for the same loan.89 p->id = 1;90 MyObj* q = p;91 (void)*q;92}93 94void definite_multiple_pointers() {95 MyObj *p, *q, *r;96 {97 MyObj s;98 p = &s; // expected-warning {{does not live long enough}}99 q = &s; // expected-warning {{does not live long enough}}100 r = &s; // expected-warning {{does not live long enough}}101 } // expected-note 3 {{destroyed here}}102 (void)*p; // expected-note {{later used here}}103 (void)*q; // expected-note {{later used here}}104 (void)*r; // expected-note {{later used here}}105}106 107void definite_single_pointer_multiple_loans(bool cond) {108 MyObj *p;109 if (cond){110 MyObj s;111 p = &s; // expected-warning {{does not live long enough}}112 } // expected-note {{destroyed here}}113 else {114 MyObj t;115 p = &t; // expected-warning {{does not live long enough}}116 } // expected-note {{destroyed here}}117 (void)*p; // expected-note 2 {{later used here}}118}119 120void definite_single_pointer_multiple_loans_gsl(bool cond) {121 View v;122 if (cond){123 MyObj s;124 v = s; // expected-warning {{object whose reference is captured does not live long enough}}125 } // expected-note {{destroyed here}}126 else {127 MyObj t;128 v = t; // expected-warning {{object whose reference is captured does not live long enough}}129 } // expected-note {{destroyed here}}130 v.use(); // expected-note 2 {{later used here}}131}132 133void definite_if_branch(bool cond) {134 MyObj safe;135 MyObj* p = &safe;136 if (cond) {137 MyObj temp;138 p = &temp; // expected-warning {{object whose reference is captured does not live long enough}}139 } // expected-note {{destroyed here}}140 (void)*p; // expected-note {{later used here}}141}142 143void potential_if_branch(bool cond) {144 MyObj safe;145 MyObj* p = &safe;146 if (cond) {147 MyObj temp;148 p = &temp; // expected-warning {{object whose reference is captured may not live long enough}}149 } // expected-note {{destroyed here}}150 if (!cond)151 (void)*p; // expected-note {{later used here}}152 else153 p = &safe;154}155 156void definite_if_branch_gsl(bool cond) {157 MyObj safe;158 View v = safe;159 if (cond) {160 MyObj temp;161 v = temp; // expected-warning {{object whose reference is captured does not live long enough}}162 } // expected-note {{destroyed here}}163 v.use(); // expected-note {{later used here}}164}165 166void definite_potential_together(bool cond) {167 MyObj safe;168 MyObj* p_maybe = &safe;169 MyObj* p_definite = nullptr;170 171 {172 MyObj s;173 if (cond)174 p_definite = &s; // expected-warning {{does not live long enough}}175 if (cond)176 p_maybe = &s; // expected-warning {{may not live long enough}} 177 } // expected-note 2 {{destroyed here}}178 (void)*p_definite; // expected-note {{later used here}}179 if (!cond)180 (void)*p_maybe; // expected-note {{later used here}}181}182 183void definite_overrides_potential(bool cond) {184 MyObj safe;185 MyObj* p;186 MyObj* q;187 {188 MyObj s;189 q = &s; // expected-warning {{does not live long enough}}190 p = q;191 } // expected-note {{destroyed here}}192 193 if (cond) {194 // 'q' is conditionally "rescued". 'p' is not.195 q = &safe;196 }197 198 // The use of 'p' is a definite error because it was never rescued.199 (void)*q;200 (void)*p; // expected-note {{later used here}}201 (void)*q;202}203 204void potential_due_to_conditional_killing(bool cond) {205 MyObj safe;206 MyObj* q;207 {208 MyObj s;209 q = &s; // expected-warning {{may not live long enough}}210 } // expected-note {{destroyed here}}211 if (cond) {212 // 'q' is conditionally "rescued". 'p' is not.213 q = &safe;214 }215 (void)*q; // expected-note {{later used here}}216}217 218void potential_for_loop_use_after_loop_body(MyObj safe) {219 MyObj* p = &safe;220 for (int i = 0; i < 1; ++i) {221 MyObj s;222 p = &s; // expected-warning {{may not live long enough}}223 } // expected-note {{destroyed here}}224 (void)*p; // expected-note {{later used here}}225}226 227void potential_for_loop_gsl() {228 MyObj safe;229 View v = safe;230 for (int i = 0; i < 1; ++i) {231 MyObj s;232 v = s; // expected-warning {{object whose reference is captured may not live long enough}}233 } // expected-note {{destroyed here}}234 v.use(); // expected-note {{later used here}}235}236 237void potential_for_loop_use_before_loop_body(MyObj safe) {238 MyObj* p = &safe;239 // Prefer the earlier use for diagnsotics.240 for (int i = 0; i < 1; ++i) {241 (void)*p; // expected-note {{later used here}}242 MyObj s;243 p = &s; // expected-warning {{does not live long enough}}244 } // expected-note {{destroyed here}}245 (void)*p;246}247 248void definite_loop_with_break(bool cond) {249 MyObj safe;250 MyObj* p = &safe;251 for (int i = 0; i < 10; ++i) {252 if (cond) {253 MyObj temp;254 p = &temp; // expected-warning {{does not live long enough}}255 break; // expected-note {{destroyed here}}256 } 257 } 258 (void)*p; // expected-note {{later used here}}259}260 261void definite_loop_with_break_gsl(bool cond) {262 MyObj safe;263 View v = safe;264 for (int i = 0; i < 10; ++i) {265 if (cond) {266 MyObj temp;267 v = temp; // expected-warning {{object whose reference is captured does not live long enough}}268 break; // expected-note {{destroyed here}}269 }270 }271 v.use(); // expected-note {{later used here}}272}273 274void potential_multiple_expiry_of_same_loan(bool cond) {275 // Choose the last expiry location for the loan (e.g., through scope-ends and break statements).276 MyObj safe;277 MyObj* p = &safe;278 for (int i = 0; i < 10; ++i) {279 MyObj unsafe;280 if (cond) {281 p = &unsafe; // expected-warning {{does not live long enough}}282 break; // expected-note {{destroyed here}} 283 }284 }285 (void)*p; // expected-note {{later used here}}286 287 p = &safe;288 for (int i = 0; i < 10; ++i) {289 MyObj unsafe;290 if (cond) {291 p = &unsafe; // expected-warning {{does not live long enough}}292 if (cond)293 break; // expected-note {{destroyed here}}294 }295 }296 (void)*p; // expected-note {{later used here}}297 298 p = &safe;299 for (int i = 0; i < 10; ++i) {300 if (cond) {301 MyObj unsafe2;302 p = &unsafe2; // expected-warning {{does not live long enough}}303 break; // expected-note {{destroyed here}}304 }305 }306 307 // TODO: This can be argued to be a "maybe" warning. This is because308 // we only check for confidence of liveness and not the confidence of309 // the loan contained in an origin. To deal with this, we can introduce310 // a confidence in loan propagation analysis as well like liveness.311 (void)*p; // expected-note {{later used here}}312 313 p = &safe;314 for (int i = 0; i < 10; ++i) {315 MyObj unsafe;316 if (cond)317 p = &unsafe; // expected-warning {{does not live long enough}}318 if (cond)319 break; // expected-note {{destroyed here}}320 }321 (void)*p; // expected-note {{later used here}}322}323 324void potential_switch(int mode) {325 MyObj safe;326 MyObj* p = &safe;327 switch (mode) {328 case 1: {329 MyObj temp;330 p = &temp; // expected-warning {{object whose reference is captured may not live long enough}}331 break; // expected-note {{destroyed here}}332 }333 case 2: {334 p = &safe; // This path is okay.335 break;336 }337 }338 if (mode == 2)339 (void)*p; // expected-note {{later used here}}340}341 342void definite_switch(int mode) {343 MyObj safe;344 MyObj* p = &safe;345 // A use domintates all the loan expires --> all definite error.346 switch (mode) {347 case 1: {348 MyObj temp1;349 p = &temp1; // expected-warning {{does not live long enough}}350 break; // expected-note {{destroyed here}}351 }352 case 2: {353 MyObj temp2;354 p = &temp2; // expected-warning {{does not live long enough}}355 break; // expected-note {{destroyed here}}356 }357 default: {358 MyObj temp2;359 p = &temp2; // expected-warning {{does not live long enough}}360 break; // expected-note {{destroyed here}}361 }362 }363 (void)*p; // expected-note 3 {{later used here}}364}365 366void definite_switch_gsl(int mode) {367 View v;368 switch (mode) {369 case 1: {370 MyObj temp1;371 v = temp1; // expected-warning {{object whose reference is captured does not live long enough}}372 break; // expected-note {{destroyed here}}373 }374 case 2: {375 MyObj temp2;376 v = temp2; // expected-warning {{object whose reference is captured does not live long enough}}377 break; // expected-note {{destroyed here}}378 }379 default: {380 MyObj temp3;381 v = temp3; // expected-warning {{object whose reference is captured does not live long enough}}382 break; // expected-note {{destroyed here}}383 }384 }385 v.use(); // expected-note 3 {{later used here}}386}387 388void loan_from_previous_iteration(MyObj safe, bool condition) {389 MyObj* p = &safe;390 MyObj* q = &safe;391 392 while (condition) {393 MyObj x;394 p = &x; // expected-warning {{may not live long enough}}395 396 if (condition)397 q = p;398 (void)*p;399 (void)*q; // expected-note {{later used here}}400 } // expected-note {{destroyed here}}401}402 403void trivial_int_uaf() {404 int * a;405 {406 int b = 1;407 a = &b; // expected-warning {{object whose reference is captured does not live long enough}}408 } // expected-note {{destroyed here}}409 (void)*a; // expected-note {{later used here}}410}411 412void trivial_class_uaf() {413 TriviallyDestructedClass* ptr;414 {415 TriviallyDestructedClass s;416 ptr = &s; // expected-warning {{object whose reference is captured does not live long enough}}417 } // expected-note {{destroyed here}}418 (void)ptr; // expected-note {{later used here}}419}420 421//===----------------------------------------------------------------------===//422// Basic Definite Use-After-Return (Return-Stack-Address) (-W...permissive)423// These are cases where the pointer is guaranteed to be dangling at the use site.424//===----------------------------------------------------------------------===//425 426MyObj* simple_return_stack_address() {427 MyObj s; 428 MyObj* p = &s; // expected-warning {{address of stack memory is returned later}}429 return p; // expected-note {{returned here}}430}431 432MyObj* direct_return() {433 MyObj s; 434 return &s; // expected-warning {{address of stack memory is returned later}}435 // expected-note@-1 {{returned here}}436}437 438const MyObj* conditional_assign_unconditional_return(const MyObj& safe, bool c) {439 MyObj s; 440 const MyObj* p = &safe;441 if (c) {442 p = &s; // expected-warning {{address of stack memory is returned later}}443 } 444 return p; // expected-note {{returned here}}445}446 447View conditional_assign_both_branches(const MyObj& safe, bool c) {448 MyObj s;449 View p;450 if (c) {451 p = s; // expected-warning {{address of stack memory is returned later}}452 } 453 else {454 p = safe;455 }456 return p; // expected-note {{returned here}}457 458}459 460View reassign_safe_to_local(const MyObj& safe) {461 MyObj local;462 View p = safe;463 p = local; // expected-warning {{address of stack memory is returned later}}464 return p; // expected-note {{returned here}}465}466 467View pointer_chain_to_local() {468 MyObj local;469 View p1 = local; // expected-warning {{address of stack memory is returned later}}470 View p2 = p1; 471 return p2; // expected-note {{returned here}}472}473 474View multiple_assign_multiple_return(const MyObj& safe, bool c1, bool c2) {475 MyObj local1;476 MyObj local2;477 View p;478 if (c1) {479 p = local1; // expected-warning {{address of stack memory is returned later}}480 return p; // expected-note {{returned here}}481 }482 else if (c2) {483 p = local2; // expected-warning {{address of stack memory is returned later}}484 return p; // expected-note {{returned here}}485 }486 p = safe;487 return p;488}489 490View multiple_assign_single_return(const MyObj& safe, bool c1, bool c2) {491 MyObj local1;492 MyObj local2;493 View p;494 if (c1) {495 p = local1; // expected-warning {{address of stack memory is returned later}}496 }497 else if (c2) {498 p = local2; // expected-warning {{address of stack memory is returned later}}499 }500 else {501 p = safe;502 }503 return p; // expected-note 2 {{returned here}}504}505 506View direct_return_of_local() {507 MyObj stack; 508 return stack; // expected-warning {{address of stack memory is returned later}}509 // expected-note@-1 {{returned here}}510}511 512MyObj& reference_return_of_local() {513 MyObj stack; 514 return stack; // expected-warning {{address of stack memory is returned later}}515 // expected-note@-1 {{returned here}}516}517 518int* trivial_int_uar() {519 int *a;520 int b = 1;521 a = &b; // expected-warning {{address of stack memory is returned later}}522 return a; // expected-note {{returned here}}523}524 525TriviallyDestructedClass* trivial_class_uar () {526 TriviallyDestructedClass *ptr;527 TriviallyDestructedClass s;528 ptr = &s; // expected-warning {{address of stack memory is returned later}}529 return ptr; // expected-note {{returned here}}530}531 532const int& return_parameter(int a) { 533 return a; // expected-warning {{address of stack memory is returned later}}534 // expected-note@-1 {{returned here}}535}536 537int* return_pointer_to_parameter(int a) {538 return &a; // expected-warning {{address of stack memory is returned later}}539 // expected-note@-1 {{returned here}}540}541 542const int& return_reference_to_parameter(int a)543{544 const int &b = a; 545 return b; // expected-warning {{address of stack memory is returned later}}546 // expected-note@-1 {{returned here}}547}548 549const int& get_ref_to_local() {550 int a = 42;551 return a; // expected-warning {{address of stack memory is returned later}}552 // expected-note@-1 {{returned here}}553}554 555//===----------------------------------------------------------------------===//556// Use-After-Scope & Use-After-Return (Return-Stack-Address) Combined557// These are cases where the diagnostic kind is determined by location558//===----------------------------------------------------------------------===//559 560MyObj* uaf_before_uar() {561 MyObj* p;562 {563 MyObj local_obj; 564 p = &local_obj; // expected-warning {{object whose reference is captured does not live long enough}}565 } // expected-note {{destroyed here}}566 return p; // expected-note {{later used here}}567}568 569View uar_before_uaf(const MyObj& safe, bool c) {570 View p;571 {572 MyObj local_obj; 573 p = local_obj; // expected-warning {{address of stack memory is returned later}}574 if (c) {575 return p; // expected-note {{returned here}}576 }577 }578 p.use();579 p = safe;580 return p;581}582 583//===----------------------------------------------------------------------===//584// No-Error Cases585//===----------------------------------------------------------------------===//586void no_error_if_dangle_then_rescue() {587 MyObj safe;588 MyObj* p;589 {590 MyObj temp;591 p = &temp; // p is temporarily dangling.592 }593 p = &safe; // p is "rescued" before use.594 (void)*p; // This is safe.595}596 597void no_error_if_dangle_then_rescue_gsl() {598 MyObj safe;599 View v;600 {601 MyObj temp;602 v = temp; // 'v' is temporarily dangling.603 }604 v = safe; // 'v' is "rescued" before use by reassigning to a valid object.605 v.use(); // This is safe.606}607 608void no_error_loan_from_current_iteration(bool cond) {609 // See https://github.com/llvm/llvm-project/issues/156959.610 MyObj b;611 while (cond) {612 MyObj a;613 View p = b;614 if (cond) {615 p = a;616 }617 (void)p;618 }619}620 621View safe_return(const MyObj& safe) {622 MyObj local;623 View p = local;624 p = safe; // p has been reassigned625 return p; // This is safe626}627 628//===----------------------------------------------------------------------===//629// Lifetimebound Attribute Tests630//===----------------------------------------------------------------------===//631 632View Identity(View v [[clang::lifetimebound]]);633const MyObj& IdentityRef(const MyObj& obj [[clang::lifetimebound]]);634MyObj* Identity(MyObj* v [[clang::lifetimebound]]);635View Choose(bool cond, View a [[clang::lifetimebound]], View b [[clang::lifetimebound]]);636MyObj* GetPointer(const MyObj& obj [[clang::lifetimebound]]);637 638struct [[gsl::Pointer()]] LifetimeBoundView {639 LifetimeBoundView();640 LifetimeBoundView(const MyObj& obj [[clang::lifetimebound]]);641 LifetimeBoundView pass() [[clang::lifetimebound]] { return *this; }642 operator View() const [[clang::lifetimebound]];643};644 645void lifetimebound_simple_function() {646 View v;647 {648 MyObj obj;649 v = Identity(obj); // expected-warning {{object whose reference is captured does not live long enough}}650 } // expected-note {{destroyed here}}651 v.use(); // expected-note {{later used here}}652}653 654void lifetimebound_multiple_args_definite() {655 View v;656 {657 MyObj obj1, obj2;658 v = Choose(true,659 obj1, // expected-warning {{object whose reference is captured does not live long enough}}660 obj2); // expected-warning {{object whose reference is captured does not live long enough}}661 } // expected-note 2 {{destroyed here}}662 v.use(); // expected-note 2 {{later used here}}663}664 665void lifetimebound_multiple_args_potential(bool cond) {666 MyObj safe;667 View v = safe;668 {669 MyObj obj1;670 if (cond) {671 MyObj obj2;672 v = Choose(true,673 obj1, // expected-warning {{object whose reference is captured does not live long enough}}674 obj2); // expected-warning {{object whose reference is captured does not live long enough}}675 } // expected-note {{destroyed here}}676 } // expected-note {{destroyed here}}677 v.use(); // expected-note 2 {{later used here}}678}679 680View SelectFirst(View a [[clang::lifetimebound]], View b);681void lifetimebound_mixed_args() {682 View v;683 {684 MyObj obj1, obj2;685 v = SelectFirst(obj1, // expected-warning {{object whose reference is captured does not live long enough}}686 obj2);687 } // expected-note {{destroyed here}}688 v.use(); // expected-note {{later used here}}689}690 691void lifetimebound_member_function() {692 LifetimeBoundView lbv, lbv2;693 {694 MyObj obj;695 lbv = obj; // expected-warning {{object whose reference is captured does not live long enough}}696 lbv2 = lbv.pass();697 } // expected-note {{destroyed here}}698 View v = lbv2; // expected-note {{later used here}}699 v.use();700}701 702void lifetimebound_conversion_operator() {703 View v;704 {705 MyObj obj;706 LifetimeBoundView lbv = obj; // expected-warning {{object whose reference is captured does not live long enough}}707 v = lbv; // Conversion operator is lifetimebound708 } // expected-note {{destroyed here}}709 v.use(); // expected-note {{later used here}}710}711 712void lifetimebound_chained_calls() {713 View v;714 {715 MyObj obj;716 v = Identity(Identity(Identity(obj))); // expected-warning {{object whose reference is captured does not live long enough}}717 } // expected-note {{destroyed here}}718 v.use(); // expected-note {{later used here}}719}720 721void lifetimebound_with_pointers() {722 MyObj* ptr;723 {724 MyObj obj;725 ptr = GetPointer(obj); // expected-warning {{object whose reference is captured does not live long enough}}726 } // expected-note {{destroyed here}}727 (void)*ptr; // expected-note {{later used here}}728}729 730void lifetimebound_no_error_safe_usage() {731 MyObj obj;732 View v1 = Identity(obj); // No warning - obj lives long enough733 View v2 = Choose(true, v1, Identity(obj)); // No warning - all args are safe734 v2.use(); // Safe usage735}736 737void lifetimebound_partial_safety(bool cond) {738 MyObj safe_obj;739 View v = safe_obj;740 741 if (cond) {742 MyObj temp_obj;743 v = Choose(true, 744 safe_obj,745 temp_obj); // expected-warning {{object whose reference is captured does not live long enough}}746 } // expected-note {{destroyed here}}747 v.use(); // expected-note {{later used here}}748}749 750// FIXME: Warning should be on the 'GetObject' call, not the assignment to 'ptr'. 751// The loan from the lifetimebound argument is not propagated to the call expression itself.752const MyObj& GetObject(View v [[clang::lifetimebound]]);753void lifetimebound_return_reference() {754 View v;755 const MyObj* ptr;756 {757 MyObj obj;758 View temp_v = obj;759 const MyObj& ref = GetObject(temp_v);760 ptr = &ref; // expected-warning {{object whose reference is captured does not live long enough}}761 } // expected-note {{destroyed here}}762 (void)*ptr; // expected-note {{later used here}}763}764 765// FIXME: No warning for non gsl::Pointer types. Origin tracking is only supported for pointer types.766struct LifetimeBoundCtor {767 LifetimeBoundCtor();768 LifetimeBoundCtor(const MyObj& obj [[clang::lifetimebound]]);769};770void lifetimebound_ctor() {771 LifetimeBoundCtor v;772 {773 MyObj obj;774 v = obj;775 }776 (void)v;777}778 779View lifetimebound_return_of_local() {780 MyObj stack;781 return Identity(stack); // expected-warning {{address of stack memory is returned later}}782 // expected-note@-1 {{returned here}}783}784 785const MyObj& lifetimebound_return_ref_to_local() {786 MyObj stack;787 return IdentityRef(stack); // expected-warning {{address of stack memory is returned later}}788 // expected-note@-1 {{returned here}}789}790 791View lifetimebound_return_by_value_param(MyObj stack_param) {792 return Identity(stack_param); // expected-warning {{address of stack memory is returned later}}793 // expected-note@-1 {{returned here}}794}795 796View lifetimebound_return_by_value_multiple_param(int cond, MyObj a, MyObj b, MyObj c) {797 if (cond == 1) 798 return Identity(a); // expected-warning {{address of stack memory is returned later}}799 // expected-note@-1 {{returned here}}800 if (cond == 2) 801 return Identity(b); // expected-warning {{address of stack memory is returned later}}802 // expected-note@-1 {{returned here}}803 return Identity(c); // expected-warning {{address of stack memory is returned later}}804 // expected-note@-1 {{returned here}}805}806 807template<class T>808View lifetimebound_return_by_value_param_template(T t) {809 return Identity(t); // expected-warning {{address of stack memory is returned later}}810 // expected-note@-1 {{returned here}}811}812void use_lifetimebound_return_by_value_param_template() { 813 lifetimebound_return_by_value_param_template(MyObj{}); // expected-note {{in instantiation of}}814}815 816void lambda_uar_param() {817 auto lambda = [](MyObj stack_param) {818 return Identity(stack_param); // expected-warning {{address of stack memory is returned later}}819 // expected-note@-1 {{returned here}}820 };821 lambda(MyObj{});822}823 824// FIXME: This should be detected. We see correct destructors but origin flow breaks somewhere.825namespace VariadicTemplatedParamsUAR{826 827template<typename... Args>828View Max(Args... args [[clang::lifetimebound]]);829 830template<typename... Args>831View lifetimebound_return_of_variadic_param(Args... args) {832 return Max(args...);833}834void test_variadic() {835 lifetimebound_return_of_variadic_param(MyObj{1}, MyObj{2}, MyObj{3});836}837}838 839// FIXME: Fails to diagnose UAF when a reference to a by-value param escapes via an out-param.840void uaf_from_by_value_param_failing(MyObj param, View* out_p) {841 *out_p = Identity(param);842}843 844// Conditional operator.845void conditional_operator_one_unsafe_branch(bool cond) {846 MyObj safe;847 MyObj* p = &safe;848 {849 MyObj temp;850 p = cond ? &temp // expected-warning {{object whose reference is captured may not live long enough}}851 : &safe;852 } // expected-note {{destroyed here}}853 854 // This is not a use-after-free for any value of `cond` but the analysis855 // cannot reason this and marks the above as a false positive. This 856 // ensures safety regardless of cond's value.857 if (cond) 858 p = &safe;859 (void)*p; // expected-note {{later used here}}860}861 862void conditional_operator_two_unsafe_branches(bool cond) {863 MyObj* p;864 {865 MyObj a, b;866 p = cond ? &a // expected-warning {{object whose reference is captured does not live long enough}}867 : &b; // expected-warning {{object whose reference is captured does not live long enough}}868 } // expected-note 2 {{destroyed here}}869 (void)*p; // expected-note 2 {{later used here}}870}871 872void conditional_operator_nested(bool cond) {873 MyObj* p;874 {875 MyObj a, b, c, d;876 p = cond ? cond ? &a // expected-warning {{object whose reference is captured does not live long enough}}.877 : &b // expected-warning {{object whose reference is captured does not live long enough}}.878 : cond ? &c // expected-warning {{object whose reference is captured does not live long enough}}.879 : &d; // expected-warning {{object whose reference is captured does not live long enough}}.880 } // expected-note 4 {{destroyed here}}881 (void)*p; // expected-note 4 {{later used here}}882}883 884void conditional_operator_lifetimebound(bool cond) {885 MyObj* p;886 {887 MyObj a, b;888 p = Identity(cond ? &a // expected-warning {{object whose reference is captured does not live long enough}}889 : &b); // expected-warning {{object whose reference is captured does not live long enough}}890 } // expected-note 2 {{destroyed here}}891 (void)*p; // expected-note 2 {{later used here}}892}893 894void conditional_operator_lifetimebound_nested(bool cond) {895 MyObj* p;896 {897 MyObj a, b;898 p = Identity(cond ? Identity(&a) // expected-warning {{object whose reference is captured does not live long enough}}899 : Identity(&b)); // expected-warning {{object whose reference is captured does not live long enough}}900 } // expected-note 2 {{destroyed here}}901 (void)*p; // expected-note 2 {{later used here}}902}903 904void conditional_operator_lifetimebound_nested_deep(bool cond) {905 MyObj* p;906 {907 MyObj a, b, c, d;908 p = Identity(cond ? Identity(cond ? &a // expected-warning {{object whose reference is captured does not live long enough}}909 : &b) // expected-warning {{object whose reference is captured does not live long enough}}910 : Identity(cond ? &c // expected-warning {{object whose reference is captured does not live long enough}}911 : &d)); // expected-warning {{object whose reference is captured does not live long enough}}912 } // expected-note 4 {{destroyed here}}913 (void)*p; // expected-note 4 {{later used here}}914}915 916void parentheses(bool cond) {917 MyObj* p;918 {919 MyObj a;920 p = &((((a)))); // expected-warning {{object whose reference is captured does not live long enough}}921 } // expected-note {{destroyed here}}922 (void)*p; // expected-note {{later used here}}923 924 {925 MyObj a;926 p = ((GetPointer((a)))); // expected-warning {{object whose reference is captured does not live long enough}}927 } // expected-note {{destroyed here}}928 (void)*p; // expected-note {{later used here}}929 930 {931 MyObj a, b, c, d;932 p = &(cond ? (cond ? a // expected-warning {{object whose reference is captured does not live long enough}}.933 : b) // expected-warning {{object whose reference is captured does not live long enough}}.934 : (cond ? c // expected-warning {{object whose reference is captured does not live long enough}}.935 : d)); // expected-warning {{object whose reference is captured does not live long enough}}.936 } // expected-note 4 {{destroyed here}}937 (void)*p; // expected-note 4 {{later used here}}938 939 {940 MyObj a, b, c, d;941 p = ((cond ? (((cond ? &a : &b))) // expected-warning 2 {{object whose reference is captured does not live long enough}}.942 : &(((cond ? c : d))))); // expected-warning 2 {{object whose reference is captured does not live long enough}}.943 } // expected-note 4 {{destroyed here}}944 (void)*p; // expected-note 4 {{later used here}}945}946