brintos

brintos / llvm-project-archived public Read only

0
0
Text · 26.8 KiB · 7634dbf Raw
879 lines · cpp
1// RUN: %clang_cc1 -fsyntax-only -Wdangling -Wdangling-field -Wreturn-stack-address -verify %s2#include "Inputs/lifetime-analysis.h"3struct [[gsl::Owner(int)]] MyIntOwner {4  MyIntOwner();5  int &operator*();6};7 8struct [[gsl::Pointer(int)]] MyIntPointer {9  MyIntPointer(int *p = nullptr);10  // Conversion operator and constructor conversion will result in two11  // different ASTs. The former is tested with another owner and12  // pointer type.13  MyIntPointer(const MyIntOwner &);14  int &operator*();15  MyIntOwner toOwner();16};17 18struct MySpecialIntPointer : MyIntPointer {19};20 21// We did see examples in the wild when a derived class changes22// the ownership model. So we have a test for it.23struct [[gsl::Owner(int)]] MyOwnerIntPointer : MyIntPointer {24};25 26struct [[gsl::Pointer(long)]] MyLongPointerFromConversion {27  MyLongPointerFromConversion(long *p = nullptr);28  long &operator*();29};30 31struct [[gsl::Owner(long)]] MyLongOwnerWithConversion {32  MyLongOwnerWithConversion();33  operator MyLongPointerFromConversion();34  long &operator*();35  MyIntPointer releaseAsMyPointer();36  long *releaseAsRawPointer();37};38 39void danglingHeapObject() {40  new MyLongPointerFromConversion(MyLongOwnerWithConversion{}); // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}}41  new MyIntPointer(MyIntOwner{}); // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}}42}43 44void intentionalFalseNegative() {45  int i;46  MyIntPointer p{&i};47  // In this case we do not have enough information in a statement local48  // analysis to detect the problem.49  new MyIntPointer(p);50  new MyIntPointer(MyIntPointer{p});51}52 53MyIntPointer ownershipTransferToMyPointer() {54  MyLongOwnerWithConversion t;55  return t.releaseAsMyPointer(); // ok56}57 58long *ownershipTransferToRawPointer() {59  MyLongOwnerWithConversion t;60  return t.releaseAsRawPointer(); // ok61}62 63struct Y {64  int a[4];65};66 67void dangligGslPtrFromTemporary() {68  MyIntPointer p = Y{}.a; // TODO69  (void)p;70}71 72struct DanglingGslPtrField {73  MyIntPointer p; // expected-note {{pointer member declared here}}74  MyLongPointerFromConversion p2; // expected-note {{pointer member declared here}}75  DanglingGslPtrField(int i) : p(&i) {} // TODO76  DanglingGslPtrField() : p2(MyLongOwnerWithConversion{}) {} // expected-warning {{initializing pointer member 'p2' to point to a temporary object whose lifetime is shorter than the lifetime of the constructed object}}77  DanglingGslPtrField(double) : p(MyIntOwner{}) {} // expected-warning {{initializing pointer member 'p' to point to a temporary object whose lifetime is shorter than the lifetime of the constructed object}}78};79 80MyIntPointer danglingGslPtrFromLocal() {81  int j;82  return &j; // TODO83}84 85MyIntPointer returningLocalPointer() {86  MyIntPointer localPointer;87  return localPointer; // ok88}89 90MyIntPointer daglingGslPtrFromLocalOwner() {91  MyIntOwner localOwner;92  return localOwner; // expected-warning {{address of stack memory associated with local variable 'localOwner' returned}}93}94 95MyLongPointerFromConversion daglingGslPtrFromLocalOwnerConv() {96  MyLongOwnerWithConversion localOwner;97  return localOwner; // expected-warning {{address of stack memory associated with local variable 'localOwner' returned}}98}99 100MyIntPointer danglingGslPtrFromTemporary() {101  return MyIntOwner{}; // expected-warning {{returning address of local temporary object}}102}103 104MyIntOwner makeTempOwner();105 106MyIntPointer danglingGslPtrFromTemporary2() {107  return makeTempOwner(); // expected-warning {{returning address of local temporary object}}108}109 110MyLongPointerFromConversion danglingGslPtrFromTemporaryConv() {111  return MyLongOwnerWithConversion{}; // expected-warning {{returning address of local temporary object}}112}113 114int *noFalsePositive(MyIntOwner &o) {115  MyIntPointer p = o;116  return &*p; // ok117}118 119MyIntPointer global;120MyLongPointerFromConversion global2;121 122void initLocalGslPtrWithTempOwner() {123  MyIntPointer p = MyIntOwner{}; // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}}124  MyIntPointer pp = p = MyIntOwner{}; // expected-warning {{object backing the pointer 'p' will be}}125  p = MyIntOwner{}; // expected-warning {{object backing the pointer 'p' }}126  pp = p; // no warning127  global = MyIntOwner{}; // expected-warning {{object backing the pointer 'global' }}128  MyLongPointerFromConversion p2 = MyLongOwnerWithConversion{}; // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}}129  p2 = MyLongOwnerWithConversion{}; // expected-warning {{object backing the pointer 'p2' }}130  global2 = MyLongOwnerWithConversion{}; // expected-warning {{object backing the pointer 'global2' }}131}132 133 134struct Unannotated {135  typedef std::vector<int>::iterator iterator;136  iterator begin();137  operator iterator() const;138};139 140void modelIterators() {141  std::vector<int>::iterator it = std::vector<int>().begin(); // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}}142  (void)it;143}144 145std::vector<int>::iterator modelIteratorReturn() {146  return std::vector<int>().begin(); // expected-warning {{returning address of local temporary object}}147}148 149const int *modelFreeFunctions() {150  return std::data(std::vector<int>()); // expected-warning {{returning address of local temporary object}}151}152 153int &modelAnyCast() {154  return std::any_cast<int&>(std::any{}); // expected-warning {{returning reference to local temporary object}}155}156 157int modelAnyCast2() {158  return std::any_cast<int>(std::any{}); // ok159}160 161int modelAnyCast3() {162  return std::any_cast<int&>(std::any{}); // ok163}164 165const char *danglingRawPtrFromLocal() {166  std::basic_string<char> s;167  return s.c_str(); // expected-warning {{address of stack memory associated with local variable 's' returned}}168}169 170int &danglingRawPtrFromLocal2() {171  std::optional<int> o;172  return o.value(); // expected-warning {{reference to stack memory associated with local variable 'o' returned}}173}174 175int &danglingRawPtrFromLocal3() {176  std::optional<int> o;177  return *o; // expected-warning {{reference to stack memory associated with local variable 'o' returned}}178}179 180// GH100384181std::string_view containerWithAnnotatedElements() {182  std::string_view c1 = std::vector<std::string>().at(0); // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}}183  c1 = std::vector<std::string>().at(0); // expected-warning {{object backing the pointer}}184 185  // no warning on constructing from gsl-pointer186  std::string_view c2 = std::vector<std::string_view>().at(0);187 188  std::vector<std::string> local;189  return local.at(0); // expected-warning {{address of stack memory associated with local variable}}190}191 192std::string_view localUniquePtr(int i) {193  std::unique_ptr<std::string> c1;194  if (i)195    return *c1; // expected-warning {{address of stack memory associated with local variable}}196  std::unique_ptr<std::string_view> c2;197  return *c2; // expect no-warning.198}199 200std::string_view localOptional(int i) {201  std::optional<std::string> o;202  if (i)203    return o.value(); // expected-warning {{address of stack memory associated with local variable}}204  std::optional<std::string_view> abc;205  return abc.value(); // expect no warning206}207 208const char *danglingRawPtrFromTemp() {209  return std::basic_string<char>().c_str(); // expected-warning {{returning address of local temporary object}}210}211 212std::unique_ptr<int> getUniquePtr();213 214int *danglingUniquePtrFromTemp() {215  return getUniquePtr().get(); // expected-warning {{returning address of local temporary object}}216}217 218int *danglingUniquePtrFromTemp2() {219  return std::unique_ptr<int>().get(); // expected-warning {{returning address of local temporary object}}220}221 222void danglingReferenceFromTempOwner() {223  int &&r = *std::optional<int>();          // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}}224  int &&r2 = *std::optional<int>(5);        // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}}225  int &&r3 = std::optional<int>(5).value(); // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}}226  int &r4 = std::vector<int>().at(3);       // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}}227}228 229std::vector<int> getTempVec();230std::optional<std::vector<int>> getTempOptVec();231 232void testLoops() {233  for (auto i : getTempVec()) // ok234    ;235  for (auto i : *getTempOptVec()) // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}}236    ;237}238 239int &usedToBeFalsePositive(std::vector<int> &v) {240  std::vector<int>::iterator it = v.begin();241  int& value = *it;242  return value; // ok243}244 245int &doNotFollowReferencesForLocalOwner() {246  std::unique_ptr<int> localOwner;247  int &p = *localOwner.get();248  // In real world code localOwner is usually moved here.249  return p; // ok250}251 252const char *trackThroughMultiplePointer() {253  return std::basic_string_view<char>(std::basic_string<char>()).begin(); // expected-warning {{returning address of local temporary object}}254}255 256struct X {257  X(std::unique_ptr<int> up) :258    pointee(*up), pointee2(up.get()), pointer(std::move(up)) {}259  int &pointee;260  int *pointee2;261  std::unique_ptr<int> pointer;262};263 264struct [[gsl::Owner]] XOwner {265  int* get() const [[clang::lifetimebound]];266};267struct X2 {268  // A common usage that moves the passing owner to the class.269  // verify no warning on this case.270  X2(XOwner owner) :271    pointee(owner.get()),272    owner(std::move(owner)) {}273  int* pointee;274  XOwner owner;275};276 277std::vector<int>::iterator getIt();278std::vector<int> getVec();279 280const int &handleGslPtrInitsThroughReference() {281  const auto &it = getIt(); // Ok, it is lifetime extended.282  return *it;283}284 285void handleGslPtrInitsThroughReference2() {286  const std::vector<int> &v = getVec();287  const int *val = v.data(); // Ok, it is lifetime extended.288}289 290void handleTernaryOperator(bool cond) {291    std::basic_string<char> def;292    std::basic_string_view<char> v = cond ? def : ""; // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}}293}294 295std::string operator+(std::string_view s1, std::string_view s2);296void danglingStringviewAssignment(std::string_view a1, std::string_view a2) {297  a1 = std::string(); // expected-warning {{object backing}}298  a2 = a1 + a1; // expected-warning {{object backing}}299}300 301std::reference_wrapper<int> danglingPtrFromNonOwnerLocal() {302  int i = 5;303  return i; // TODO304}305 306std::reference_wrapper<int> danglingPtrFromNonOwnerLocal2() {307  int i = 5;308  return std::ref(i); // TODO309}310 311std::reference_wrapper<int> danglingPtrFromNonOwnerLocal3() {312  int i = 5;313  return std::reference_wrapper<int>(i); // TODO314}315 316std::reference_wrapper<Unannotated> danglingPtrFromNonOwnerLocal4() {317  Unannotated i;318  return std::reference_wrapper<Unannotated>(i); // TODO319}320 321std::reference_wrapper<Unannotated> danglingPtrFromNonOwnerLocal5() {322  Unannotated i;323  return std::ref(i); // TODO324}325 326int *returnPtrToLocalArray() {327  int a[5];328  return std::begin(a); // TODO329}330 331struct ptr_wrapper {332  std::vector<int>::iterator member;333};334 335ptr_wrapper getPtrWrapper();336 337std::vector<int>::iterator returnPtrFromWrapper() {338  ptr_wrapper local = getPtrWrapper();339  return local.member;340}341 342std::vector<int>::iterator returnPtrFromWrapperThroughRef() {343  ptr_wrapper local = getPtrWrapper();344  ptr_wrapper &local2 = local;345  return local2.member;346}347 348std::vector<int>::iterator returnPtrFromWrapperThroughRef2() {349  ptr_wrapper local = getPtrWrapper();350  std::vector<int>::iterator &local2 = local.member;351  return local2;352}353 354void checkPtrMemberFromAggregate() {355  std::vector<int>::iterator local = getPtrWrapper().member; // OK.356}357 358std::vector<int>::iterator doNotInterferWithUnannotated() {359  Unannotated value;360  // Conservative choice for now. Probably not ok, but we do not warn.361  return std::begin(value);362}363 364std::vector<int>::iterator doNotInterferWithUnannotated2() {365  Unannotated value;366  return value;367}368 369std::vector<int>::iterator supportDerefAddrofChain(int a, std::vector<int>::iterator value) {370  switch (a)  {371    default:372      return value;373    case 1:374      return *&value;375    case 2:376      return *&*&value;377    case 3:378      return *&*&*&value;379  }380}381 382int &supportDerefAddrofChain2(int a, std::vector<int>::iterator value) {383  switch (a)  {384    default:385      return *value;386    case 1:387      return **&value;388    case 2:389      return **&*&value;390    case 3:391      return **&*&*&value;392  }393}394 395int *supportDerefAddrofChain3(int a, std::vector<int>::iterator value) {396  switch (a)  {397    default:398      return &*value;399    case 1:400      return &*&*value;401    case 2:402      return &*&**&value;403    case 3:404      return &*&**&*&value;405  }406}407 408MyIntPointer handleDerivedToBaseCast1(MySpecialIntPointer ptr) {409  return ptr;410}411 412MyIntPointer handleDerivedToBaseCast2(MyOwnerIntPointer ptr) {413  return ptr; // expected-warning {{address of stack memory associated with parameter 'ptr' returned}}414}415 416std::vector<int>::iterator noFalsePositiveWithVectorOfPointers() {417  std::vector<std::vector<int>::iterator> iters;418  return iters.at(0);419}420 421void testForBug49342()422{423  auto it = std::iter<char>{} - 2; // Used to be false positive.424}425 426namespace GH93386 {427// verify no duplicated diagnostics are emitted.428struct [[gsl::Pointer]] S {429  S(const std::vector<int>& abc [[clang::lifetimebound]]);430};431 432S test(std::vector<int> a) {433  return S(a);  // expected-warning {{address of stack memory associated with}}434}435 436auto s = S(std::vector<int>()); // expected-warning {{temporary whose address is used as value of local variable}}437 438// Verify no regression on the follow case.439std::string_view test2(int i, std::optional<std::string_view> a) {440  if (i)441    return std::move(*a);442  return std::move(a.value());443}444 445struct Foo;446struct FooView {447  FooView(const Foo& foo [[clang::lifetimebound]]);448};449FooView test3(int i, std::optional<Foo> a) {450  if (i)451    return *a; // expected-warning {{address of stack memory}}452  return a.value(); // expected-warning {{address of stack memory}}453}454} // namespace GH93386455 456namespace GH100549 {457struct UrlAnalyzed {458  UrlAnalyzed(std::string_view url [[clang::lifetimebound]]);459};460std::string StrCat(std::string_view, std::string_view);461void test1() {462  UrlAnalyzed url(StrCat("abc", "bcd")); // expected-warning {{object backing the pointer will be destroyed}}463}464 465std::string_view ReturnStringView(std::string_view abc [[clang::lifetimebound]]);466 467void test() {468  std::string_view svjkk1 = ReturnStringView(StrCat("bar", "x")); // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}}469}470} // namespace GH100549471 472namespace GH108272 {473template <typename T>474struct [[gsl::Owner]] StatusOr {475  const T &value() [[clang::lifetimebound]];476};477 478template <typename V>479class Wrapper1 {480 public:481  operator V() const;482  V value;483};484std::string_view test1() {485  StatusOr<Wrapper1<std::string_view>> k;486  // Be conservative in this case, as there is not enough information available487  // to infer the lifetime relationship for the Wrapper1 type.488  std::string_view good = StatusOr<Wrapper1<std::string_view>>().value();489  return k.value();490}491 492template <typename V>493class Wrapper2 {494 public:495  operator V() const [[clang::lifetimebound]];496  V value;497};498std::string_view test2() {499  StatusOr<Wrapper2<std::string_view>> k;500  // We expect dangling issues as the conversion operator is lifetimebound。501  std::string_view bad = StatusOr<Wrapper2<std::string_view>>().value(); // expected-warning {{temporary whose address is used as value of}}502  return k.value(); // expected-warning {{address of stack memory associated}}503}504} // namespace GH108272505 506namespace GH100526 {507void test() {508  std::vector<std::string_view> v1({std::string()}); // expected-warning {{object backing the pointer will be destroyed at the end}}509  std::vector<std::string_view> v2({510    std::string(), // expected-warning {{object backing the pointer will be destroyed at the end}}511    std::string_view()512  });513  std::vector<std::string_view> v3({514    std::string_view(),515    std::string()  // expected-warning {{object backing the pointer will be destroyed at the end}}516  });517 518  std::optional<std::string_view> o1 = std::string(); // expected-warning {{object backing the pointer}}519 520  std::string s;521  // This is a tricky use-after-free case, what it does:522  //   1. make_optional creates a temporary "optional<string>"" object523  //   2. the temporary object owns the underlying string which is copied from s.524  //   3. the t3 object holds the view to the underlying string of the temporary object.525  std::optional<std::string_view> o2 = std::make_optional(s); // expected-warning {{object backing the pointer}}526  std::optional<std::string_view> o3 = std::optional<std::string>(s); // expected-warning {{object backing the pointer}}527  std::optional<std::string_view> o4 = std::optional<std::string_view>(s);528 529  // FIXME: should work for assignment cases530  v1 = {std::string()};531  o1 = std::string();532 533  // no warning on copying pointers.534  std::vector<std::string_view> n1 = {std::string_view()};535  std::optional<std::string_view> n2 = {std::string_view()};536  std::optional<std::string_view> n3 = std::string_view();537  std::optional<std::string_view> n4 = std::make_optional(std::string_view());538  const char* b = "";539  std::optional<std::string_view> n5 = std::make_optional(b);540  std::optional<std::string_view> n6 = std::make_optional("test");541}542 543std::vector<std::string_view> test2(int i) {544  std::vector<std::string_view> t;545  if (i)546    return t; // this is fine, no dangling547  return std::vector<std::string_view>(t.begin(), t.end());548}549 550class Foo {551  public:552   operator std::string_view() const { return ""; }553};554class [[gsl::Owner]] FooOwner {555  public:556   operator std::string_view() const { return ""; }557};558std::optional<Foo> GetFoo();559std::optional<FooOwner> GetFooOwner();560 561template <typename T>562struct [[gsl::Owner]] Container1 {563   Container1();564};565template <typename T>566struct [[gsl::Owner]] Container2 {567  template<typename U>568  Container2(const Container1<U>& C2);569};570 571std::optional<std::string_view> test3(int i) {572  std::string s;573  std::string_view sv;574  if (i)575   return s; // expected-warning {{address of stack memory associated}}576  return sv; // fine577  Container2<std::string_view> c1 = Container1<Foo>(); // no diagnostic as Foo is not an Owner.578  Container2<std::string_view> c2 = Container1<FooOwner>(); // expected-warning {{object backing the pointer will be destroyed}}579  return GetFoo(); // fine, we don't know Foo is owner or not, be conservative.580  return GetFooOwner(); // expected-warning {{returning address of local temporary object}}581}582 583std::optional<int*> test4(int a) {584  return std::make_optional(nullptr); // fine585}586 587 588template <typename T>589struct [[gsl::Owner]] StatusOr {590  const T &valueLB() const [[clang::lifetimebound]];591  const T &valueNoLB() const;592};593 594template<typename T>595struct [[gsl::Pointer]] Span {596  Span(const std::vector<T> &V);597 598  const int& getFieldLB() const [[clang::lifetimebound]];599  const int& getFieldNoLB() const;600};601 602 603/////// From Owner<Pointer> ///////604 605// Pointer from Owner<Pointer>606std::string_view test5() {607  // The Owner<Pointer> doesn't own the object which its inner pointer points to.608  std::string_view a = StatusOr<std::string_view>().valueLB(); // OK609  return StatusOr<std::string_view>().valueLB(); // OK610 611  // No dangling diagnostics on non-lifetimebound methods.612  std::string_view b = StatusOr<std::string_view>().valueNoLB();613  return StatusOr<std::string_view>().valueNoLB();614}615 616// Pointer<Pointer> from Owner<Pointer>617// Prevent regression GH108463618Span<int*> test6(std::vector<int*> v) {619  Span<int *> dangling = std::vector<int*>(); // expected-warning {{object backing the pointer}}620  dangling = std::vector<int*>(); // expected-warning {{object backing the pointer}}621  return v; // expected-warning {{address of stack memory}}622}623 624/////// From Owner<Owner<Pointer>> ///////625 626// Pointer from Owner<Owner<Pointer>>627int* test7(StatusOr<StatusOr<int*>> aa) {628  // No dangling diagnostic on pointer.629  return aa.valueLB().valueLB(); // OK.630}631 632// Owner<Pointer> from Owner<Owner<Pointer>>633std::vector<int*> test8(StatusOr<std::vector<int*>> aa) {634  return aa.valueLB(); // OK, no pointer being construct on this case.635  return aa.valueNoLB();636}637 638// Pointer<Pointer> from Owner<Owner<Pointer>>639Span<int*> test9(StatusOr<std::vector<int*>> aa) {640  return aa.valueLB(); // expected-warning {{address of stack memory associated}}641  return aa.valueNoLB(); // OK.642}643 644/////// From Owner<Owner> ///////645 646// Pointer<Owner>> from Owner<Owner>647Span<std::string> test10(StatusOr<std::vector<std::string>> aa) {648  return aa.valueLB(); // expected-warning {{address of stack memory}}649  return aa.valueNoLB(); // OK.650}651 652/////// From Owner<Pointer<Owner>> ///////653 654// Pointer<Owner>> from Owner<Pointer<Owner>>655Span<std::string> test11(StatusOr<Span<std::string>> aa) {656  return aa.valueLB(); // OK657  return aa.valueNoLB(); // OK.658}659 660// Lifetimebound and gsl::Pointer.661const int& test12(Span<int> a) {662  return a.getFieldLB(); // expected-warning {{reference to stack memory associated}}663  return a.getFieldNoLB(); // OK.664}665 666void test13() {667  // FIXME: RHS is Owner<Pointer>, we skip this case to avoid false positives.668  std::optional<Span<int*>> abc = std::vector<int*>{};669 670  std::optional<Span<int>> t = std::vector<int> {}; // expected-warning {{object backing the pointer will be destroyed}}671}672 673} // namespace GH100526674 675namespace std {676template <typename T>677class __set_iterator {};678 679template<typename T>680struct BB {681  typedef  __set_iterator<T> iterator;682};683 684template <typename T>685class set {686public:687  typedef typename BB<T>::iterator iterator;688  iterator begin() const;689};690} // namespace std691namespace GH118064{692 693void test() {694  auto y = std::set<int>{}.begin(); // expected-warning {{object backing the pointer}}695}696} // namespace GH118064697 698namespace LifetimeboundInterleave {699 700const std::string& Ref(const std::string& abc [[clang::lifetimebound]]);701 702std::string_view TakeSv(std::string_view abc [[clang::lifetimebound]]);703std::string_view TakeStrRef(const std::string& abc [[clang::lifetimebound]]);704std::string_view TakeStr(std::string abc [[clang::lifetimebound]]);705 706std::string_view test1() {707  std::string_view t1 = Ref(std::string()); // expected-warning {{object backing}}708  t1 = Ref(std::string()); // expected-warning {{object backing}}709  return Ref(std::string()); // expected-warning {{returning address}}710 711  std::string_view t2 = TakeSv(std::string()); // expected-warning {{object backing}}712  t2 = TakeSv(std::string()); // expected-warning {{object backing}}713  return TakeSv(std::string()); // expected-warning {{returning address}}714 715  std::string_view t3 = TakeStrRef(std::string()); // expected-warning {{temporary}}716  t3 = TakeStrRef(std::string()); // expected-warning {{object backing}}717  return TakeStrRef(std::string()); // expected-warning {{returning address}}718 719 720  std::string_view t4 = TakeStr(std::string());721  t4 = TakeStr(std::string());722  return TakeStr(std::string());723}724 725template <typename T>726struct Foo {727  const T& get() const [[clang::lifetimebound]];728  const T& getNoLB() const;729};730std::string_view test2(Foo<std::string> r1, Foo<std::string_view> r2) {731  std::string_view t1 = Foo<std::string>().get(); // expected-warning {{object backing}}732  t1 = Foo<std::string>().get(); // expected-warning {{object backing}}733  return r1.get(); // expected-warning {{address of stack}}734 735  std::string_view t2 = Foo<std::string_view>().get();736  t2 = Foo<std::string_view>().get();737  return r2.get();738 739  // no warning on no-LB-annotated method.740  std::string_view t3 = Foo<std::string>().getNoLB();741  t3 = Foo<std::string>().getNoLB();742  return r1.getNoLB();743}744 745struct Bar {};746struct [[gsl::Pointer]] Pointer {747  Pointer(const Bar & bar [[clang::lifetimebound]]);748};749Pointer test3(Bar bar) {750  Pointer p = Pointer(Bar()); // expected-warning {{temporary}}751  p = Pointer(Bar()); // expected-warning {{object backing}}752  return bar; // expected-warning {{address of stack}}753}754 755template<typename T>756struct MySpan {757  MySpan(const std::vector<T>& v);758  using iterator = std::iterator<T>;759  iterator begin() const [[clang::lifetimebound]];760};761template <typename T>762typename MySpan<T>::iterator ReturnFirstIt(const MySpan<T>& v [[clang::lifetimebound]]);763 764void test4() {765  std::vector<int> v{1};766  // MySpan<T> doesn't own any underlying T objects, the pointee object of767  // the MySpan iterator is still alive when the whole span is destroyed, thus768  // no diagnostic.769  const int& t1 = *MySpan<int>(v).begin();770  const int& t2 = *ReturnFirstIt(MySpan<int>(v));771  // Ideally, we would diagnose the following case, but due to implementation772  // constraints, we do not.773  const int& t4 = *MySpan<int>(std::vector<int>{}).begin();774 775  auto it1 = MySpan<int>(v).begin(); // expected-warning {{temporary whose address is use}}776  auto it2 = ReturnFirstIt(MySpan<int>(v)); // expected-warning {{temporary whose address is used}}777}778 779} // namespace LifetimeboundInterleave780 781namespace GH120206 {782struct S {783  std::string_view s;784};785 786struct [[gsl::Owner]] Q1 {787  const S* get() const [[clang::lifetimebound]];788};789std::string_view test1(int c, std::string_view sv) {790  std::string_view k = c > 1 ? Q1().get()->s : sv;791  if (c == 1)792    return  c > 1 ? Q1().get()->s : sv;793  Q1 q;794  return c > 1 ? q.get()->s : sv;795}796 797struct Q2 {798  const S* get() const [[clang::lifetimebound]];799};800std::string_view test2(int c, std::string_view sv) {801  std::string_view k = c > 1 ? Q2().get()->s : sv;802  if (c == 1)803    return c > 1 ? Q2().get()->s : sv;804  Q2 q;805  return c > 1 ? q.get()->s : sv;806}807 808} // namespace GH120206809 810namespace GH120543 {811struct S {812  std::string_view sv;813  std::string s;814};815struct Q {816  const S* get() const [[clang::lifetimebound]];817};818 819std::string_view foo(std::string_view sv [[clang::lifetimebound]]);820 821void test1() {822  std::string_view k1 = S().sv; // OK823  std::string_view k2 = S().s; // expected-warning {{object backing the pointer will}}824 825  std::string_view k3 = Q().get()->sv; // OK826  std::string_view k4  = Q().get()->s; // expected-warning {{object backing the pointer will}}827 828  std::string_view lb1 = foo(S().s); // expected-warning {{object backing the pointer will}}829  std::string_view lb2 = foo(Q().get()->s); // expected-warning {{object backing the pointer will}}830}831 832struct Bar {};833struct Foo {834  std::vector<Bar> v;835};836Foo getFoo();837void test2() {838  const Foo& foo = getFoo();839  const Bar& bar = foo.v.back(); // OK840}841 842struct Foo2 {843   std::unique_ptr<Bar> bar;844};845 846struct Test {847  Test(Foo2 foo) : bar(foo.bar.get()), // OK848      storage(std::move(foo.bar)) {};849 850  Bar* bar;851  std::unique_ptr<Bar> storage;852};853 854} // namespace GH120543855 856namespace GH127195 {857template <typename T>858struct StatusOr {859  T* operator->() [[clang::lifetimebound]];860  T* value() [[clang::lifetimebound]];861};862 863const char* foo() {864  StatusOr<std::string> s;865  return s->data(); // expected-warning {{address of stack memory associated with local variable}}866 867  StatusOr<std::string_view> s2;868  return s2->data();869 870  StatusOr<StatusOr<std::string_view>> s3;871  return s3.value()->value()->data();872 873  // FIXME: nested cases are not supported now.874  StatusOr<StatusOr<std::string>> s4;875  return s4.value()->value()->data();876}877 878} // namespace GH127195879