brintos

brintos / llvm-project-archived public Read only

0
0
Text · 30.3 KiB · 1191469 Raw
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