xref: /llvm-project/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp (revision bd56950b9cd5b6b07e1ccb9b02c5d8a7125a23b6)
1 // RUN: %clang_cc1 -fsyntax-only -Wdangling -Wdangling-field -Wreturn-stack-address -verify %s
2 #include "Inputs/lifetime-analysis.h"
3 struct [[gsl::Owner(int)]] MyIntOwner {
4   MyIntOwner();
5   int &operator*();
6 };
7 
8 struct [[gsl::Pointer(int)]] MyIntPointer {
9   MyIntPointer(int *p = nullptr);
10   // Conversion operator and constructor conversion will result in two
11   // different ASTs. The former is tested with another owner and
12   // pointer type.
13   MyIntPointer(const MyIntOwner &);
14   int &operator*();
15   MyIntOwner toOwner();
16 };
17 
18 struct MySpecialIntPointer : MyIntPointer {
19 };
20 
21 // We did see examples in the wild when a derived class changes
22 // the ownership model. So we have a test for it.
23 struct [[gsl::Owner(int)]] MyOwnerIntPointer : MyIntPointer {
24 };
25 
26 struct [[gsl::Pointer(long)]] MyLongPointerFromConversion {
27   MyLongPointerFromConversion(long *p = nullptr);
28   long &operator*();
29 };
30 
31 struct [[gsl::Owner(long)]] MyLongOwnerWithConversion {
32   MyLongOwnerWithConversion();
33   operator MyLongPointerFromConversion();
34   long &operator*();
35   MyIntPointer releaseAsMyPointer();
36   long *releaseAsRawPointer();
37 };
38 
39 void 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 
44 void intentionalFalseNegative() {
45   int i;
46   MyIntPointer p{&i};
47   // In this case we do not have enough information in a statement local
48   // analysis to detect the problem.
49   new MyIntPointer(p);
50   new MyIntPointer(MyIntPointer{p});
51 }
52 
53 MyIntPointer ownershipTransferToMyPointer() {
54   MyLongOwnerWithConversion t;
55   return t.releaseAsMyPointer(); // ok
56 }
57 
58 long *ownershipTransferToRawPointer() {
59   MyLongOwnerWithConversion t;
60   return t.releaseAsRawPointer(); // ok
61 }
62 
63 struct Y {
64   int a[4];
65 };
66 
67 void dangligGslPtrFromTemporary() {
68   MyIntPointer p = Y{}.a; // TODO
69   (void)p;
70 }
71 
72 struct 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) {} // TODO
76   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 
80 MyIntPointer danglingGslPtrFromLocal() {
81   int j;
82   return &j; // TODO
83 }
84 
85 MyIntPointer returningLocalPointer() {
86   MyIntPointer localPointer;
87   return localPointer; // ok
88 }
89 
90 MyIntPointer daglingGslPtrFromLocalOwner() {
91   MyIntOwner localOwner;
92   return localOwner; // expected-warning {{address of stack memory associated with local variable 'localOwner' returned}}
93 }
94 
95 MyLongPointerFromConversion daglingGslPtrFromLocalOwnerConv() {
96   MyLongOwnerWithConversion localOwner;
97   return localOwner; // expected-warning {{address of stack memory associated with local variable 'localOwner' returned}}
98 }
99 
100 MyIntPointer danglingGslPtrFromTemporary() {
101   return MyIntOwner{}; // expected-warning {{returning address of local temporary object}}
102 }
103 
104 MyIntOwner makeTempOwner();
105 
106 MyIntPointer danglingGslPtrFromTemporary2() {
107   return makeTempOwner(); // expected-warning {{returning address of local temporary object}}
108 }
109 
110 MyLongPointerFromConversion danglingGslPtrFromTemporaryConv() {
111   return MyLongOwnerWithConversion{}; // expected-warning {{returning address of local temporary object}}
112 }
113 
114 int *noFalsePositive(MyIntOwner &o) {
115   MyIntPointer p = o;
116   return &*p; // ok
117 }
118 
119 MyIntPointer global;
120 MyLongPointerFromConversion global2;
121 
122 void 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 warning
127   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 
134 struct Unannotated {
135   typedef std::vector<int>::iterator iterator;
136   iterator begin();
137   operator iterator() const;
138 };
139 
140 void 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 
145 std::vector<int>::iterator modelIteratorReturn() {
146   return std::vector<int>().begin(); // expected-warning {{returning address of local temporary object}}
147 }
148 
149 const int *modelFreeFunctions() {
150   return std::data(std::vector<int>()); // expected-warning {{returning address of local temporary object}}
151 }
152 
153 int &modelAnyCast() {
154   return std::any_cast<int&>(std::any{}); // expected-warning {{returning reference to local temporary object}}
155 }
156 
157 int modelAnyCast2() {
158   return std::any_cast<int>(std::any{}); // ok
159 }
160 
161 int modelAnyCast3() {
162   return std::any_cast<int&>(std::any{}); // ok
163 }
164 
165 const 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 
170 int &danglingRawPtrFromLocal2() {
171   std::optional<int> o;
172   return o.value(); // expected-warning {{reference to stack memory associated with local variable 'o' returned}}
173 }
174 
175 int &danglingRawPtrFromLocal3() {
176   std::optional<int> o;
177   return *o; // expected-warning {{reference to stack memory associated with local variable 'o' returned}}
178 }
179 
180 // GH100384
181 std::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-pointer
186   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 
192 std::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 
200 std::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 warning
206 }
207 
208 const char *danglingRawPtrFromTemp() {
209   return std::basic_string<char>().c_str(); // expected-warning {{returning address of local temporary object}}
210 }
211 
212 std::unique_ptr<int> getUniquePtr();
213 
214 int *danglingUniquePtrFromTemp() {
215   return getUniquePtr().get(); // expected-warning {{returning address of local temporary object}}
216 }
217 
218 int *danglingUniquePtrFromTemp2() {
219   return std::unique_ptr<int>().get(); // expected-warning {{returning address of local temporary object}}
220 }
221 
222 void 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 
229 std::vector<int> getTempVec();
230 std::optional<std::vector<int>> getTempOptVec();
231 
232 void testLoops() {
233   for (auto i : getTempVec()) // ok
234     ;
235   for (auto i : *getTempOptVec()) // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}}
236     ;
237 }
238 
239 int &usedToBeFalsePositive(std::vector<int> &v) {
240   std::vector<int>::iterator it = v.begin();
241   int& value = *it;
242   return value; // ok
243 }
244 
245 int &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; // ok
250 }
251 
252 const char *trackThroughMultiplePointer() {
253   return std::basic_string_view<char>(std::basic_string<char>()).begin(); // expected-warning {{returning address of local temporary object}}
254 }
255 
256 struct 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 
264 struct [[gsl::Owner]] XOwner {
265   int* get() const [[clang::lifetimebound]];
266 };
267 struct 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 
277 std::vector<int>::iterator getIt();
278 std::vector<int> getVec();
279 
280 const int &handleGslPtrInitsThroughReference() {
281   const auto &it = getIt(); // Ok, it is lifetime extended.
282   return *it;
283 }
284 
285 void handleGslPtrInitsThroughReference2() {
286   const std::vector<int> &v = getVec();
287   const int *val = v.data(); // Ok, it is lifetime extended.
288 }
289 
290 void 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 
295 std::string operator+(std::string_view s1, std::string_view s2);
296 void 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 
301 std::reference_wrapper<int> danglingPtrFromNonOwnerLocal() {
302   int i = 5;
303   return i; // TODO
304 }
305 
306 std::reference_wrapper<int> danglingPtrFromNonOwnerLocal2() {
307   int i = 5;
308   return std::ref(i); // TODO
309 }
310 
311 std::reference_wrapper<int> danglingPtrFromNonOwnerLocal3() {
312   int i = 5;
313   return std::reference_wrapper<int>(i); // TODO
314 }
315 
316 std::reference_wrapper<Unannotated> danglingPtrFromNonOwnerLocal4() {
317   Unannotated i;
318   return std::reference_wrapper<Unannotated>(i); // TODO
319 }
320 
321 std::reference_wrapper<Unannotated> danglingPtrFromNonOwnerLocal5() {
322   Unannotated i;
323   return std::ref(i); // TODO
324 }
325 
326 int *returnPtrToLocalArray() {
327   int a[5];
328   return std::begin(a); // TODO
329 }
330 
331 struct ptr_wrapper {
332   std::vector<int>::iterator member;
333 };
334 
335 ptr_wrapper getPtrWrapper();
336 
337 std::vector<int>::iterator returnPtrFromWrapper() {
338   ptr_wrapper local = getPtrWrapper();
339   return local.member;
340 }
341 
342 std::vector<int>::iterator returnPtrFromWrapperThroughRef() {
343   ptr_wrapper local = getPtrWrapper();
344   ptr_wrapper &local2 = local;
345   return local2.member;
346 }
347 
348 std::vector<int>::iterator returnPtrFromWrapperThroughRef2() {
349   ptr_wrapper local = getPtrWrapper();
350   std::vector<int>::iterator &local2 = local.member;
351   return local2;
352 }
353 
354 void checkPtrMemberFromAggregate() {
355   std::vector<int>::iterator local = getPtrWrapper().member; // OK.
356 }
357 
358 std::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 
364 std::vector<int>::iterator doNotInterferWithUnannotated2() {
365   Unannotated value;
366   return value;
367 }
368 
369 std::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 
382 int &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 
395 int *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 
408 MyIntPointer handleDerivedToBaseCast1(MySpecialIntPointer ptr) {
409   return ptr;
410 }
411 
412 MyIntPointer handleDerivedToBaseCast2(MyOwnerIntPointer ptr) {
413   return ptr; // expected-warning {{address of stack memory associated with parameter 'ptr' returned}}
414 }
415 
416 std::vector<int>::iterator noFalsePositiveWithVectorOfPointers() {
417   std::vector<std::vector<int>::iterator> iters;
418   return iters.at(0);
419 }
420 
421 void testForBug49342()
422 {
423   auto it = std::iter<char>{} - 2; // Used to be false positive.
424 }
425 
426 namespace GH93386 {
427 // verify no duplicated diagnostics are emitted.
428 struct [[gsl::Pointer]] S {
429   S(const std::vector<int>& abc [[clang::lifetimebound]]);
430 };
431 
432 S test(std::vector<int> a) {
433   return S(a);  // expected-warning {{address of stack memory associated with}}
434 }
435 
436 auto 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.
439 std::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 
445 struct Foo;
446 struct FooView {
447   FooView(const Foo& foo [[clang::lifetimebound]]);
448 };
449 FooView 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 GH93386
455 
456 namespace GH100549 {
457 struct UrlAnalyzed {
458   UrlAnalyzed(std::string_view url [[clang::lifetimebound]]);
459 };
460 std::string StrCat(std::string_view, std::string_view);
461 void test1() {
462   UrlAnalyzed url(StrCat("abc", "bcd")); // expected-warning {{object backing the pointer will be destroyed}}
463 }
464 
465 std::string_view ReturnStringView(std::string_view abc [[clang::lifetimebound]]);
466 
467 void 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 GH100549
471 
472 namespace GH108272 {
473 template <typename T>
474 struct [[gsl::Owner]] StatusOr {
475   const T &value() [[clang::lifetimebound]];
476 };
477 
478 template <typename V>
479 class Wrapper1 {
480  public:
481   operator V() const;
482   V value;
483 };
484 std::string_view test1() {
485   StatusOr<Wrapper1<std::string_view>> k;
486   // Be conservative in this case, as there is not enough information available
487   // 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 
492 template <typename V>
493 class Wrapper2 {
494  public:
495   operator V() const [[clang::lifetimebound]];
496   V value;
497 };
498 std::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 GH108272
505 
506 namespace GH100526 {
507 void 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>"" object
523   //   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 cases
530   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 
543 std::vector<std::string_view> test2(int i) {
544   std::vector<std::string_view> t;
545   if (i)
546     return t; // this is fine, no dangling
547   return std::vector<std::string_view>(t.begin(), t.end());
548 }
549 
550 class Foo {
551   public:
552    operator std::string_view() const { return ""; }
553 };
554 class [[gsl::Owner]] FooOwner {
555   public:
556    operator std::string_view() const { return ""; }
557 };
558 std::optional<Foo> GetFoo();
559 std::optional<FooOwner> GetFooOwner();
560 
561 template <typename T>
562 struct [[gsl::Owner]] Container1 {
563    Container1();
564 };
565 template <typename T>
566 struct [[gsl::Owner]] Container2 {
567   template<typename U>
568   Container2(const Container1<U>& C2);
569 };
570 
571 std::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; // fine
577   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 
583 std::optional<int*> test4(int a) {
584   return std::make_optional(nullptr); // fine
585 }
586 
587 
588 template <typename T>
589 struct [[gsl::Owner]] StatusOr {
590   const T &valueLB() const [[clang::lifetimebound]];
591   const T &valueNoLB() const;
592 };
593 
594 template<typename T>
595 struct [[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>
606 std::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(); // OK
609   return StatusOr<std::string_view>().valueLB(); // OK
610 
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 GH108463
618 Span<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>>
627 int* 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>>
633 std::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>>
639 Span<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>
647 Span<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>>
655 Span<std::string> test11(StatusOr<Span<std::string>> aa) {
656   return aa.valueLB(); // OK
657   return aa.valueNoLB(); // OK.
658 }
659 
660 // Lifetimebound and gsl::Pointer.
661 const int& test12(Span<int> a) {
662   return a.getFieldLB(); // expected-warning {{reference to stack memory associated}}
663   return a.getFieldNoLB(); // OK.
664 }
665 
666 void 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 GH100526
674 
675 namespace std {
676 template <typename T>
677 class __set_iterator {};
678 
679 template<typename T>
680 struct BB {
681   typedef  __set_iterator<T> iterator;
682 };
683 
684 template <typename T>
685 class set {
686 public:
687   typedef typename BB<T>::iterator iterator;
688   iterator begin() const;
689 };
690 } // namespace std
691 namespace GH118064{
692 
693 void test() {
694   auto y = std::set<int>{}.begin(); // expected-warning {{object backing the pointer}}
695 }
696 } // namespace GH118064
697 
698 namespace LifetimeboundInterleave {
699 
700 const std::string& Ref(const std::string& abc [[clang::lifetimebound]]);
701 
702 std::string_view TakeSv(std::string_view abc [[clang::lifetimebound]]);
703 std::string_view TakeStrRef(const std::string& abc [[clang::lifetimebound]]);
704 std::string_view TakeStr(std::string abc [[clang::lifetimebound]]);
705 
706 std::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 
725 template <typename T>
726 struct Foo {
727   const T& get() const [[clang::lifetimebound]];
728   const T& getNoLB() const;
729 };
730 std::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 
745 struct Bar {};
746 struct [[gsl::Pointer]] Pointer {
747   Pointer(const Bar & bar [[clang::lifetimebound]]);
748 };
749 Pointer 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 
755 template<typename T>
756 struct MySpan {
757   MySpan(const std::vector<T>& v);
758   using iterator = std::iterator<T>;
759   iterator begin() const [[clang::lifetimebound]];
760 };
761 template <typename T>
762 typename MySpan<T>::iterator ReturnFirstIt(const MySpan<T>& v [[clang::lifetimebound]]);
763 
764 void test4() {
765   std::vector<int> v{1};
766   // MySpan<T> doesn't own any underlying T objects, the pointee object of
767   // the MySpan iterator is still alive when the whole span is destroyed, thus
768   // 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 implementation
772   // 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 LifetimeboundInterleave
780 
781 namespace GH120206 {
782 struct S {
783   std::string_view s;
784 };
785 
786 struct [[gsl::Owner]] Q1 {
787   const S* get() const [[clang::lifetimebound]];
788 };
789 std::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 
797 struct Q2 {
798   const S* get() const [[clang::lifetimebound]];
799 };
800 std::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 GH120206
809 
810 namespace GH120543 {
811 struct S {
812   std::string_view sv;
813   std::string s;
814 };
815 struct Q {
816   const S* get() const [[clang::lifetimebound]];
817 };
818 
819 std::string_view foo(std::string_view sv [[clang::lifetimebound]]);
820 
821 void test1() {
822   std::string_view k1 = S().sv; // OK
823   std::string_view k2 = S().s; // expected-warning {{object backing the pointer will}}
824 
825   std::string_view k3 = Q().get()->sv; // OK
826   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 
832 struct Bar {};
833 struct Foo {
834   std::vector<Bar> v;
835 };
836 Foo getFoo();
837 void test2() {
838   const Foo& foo = getFoo();
839   const Bar& bar = foo.v.back(); // OK
840 }
841 
842 struct Foo2 {
843    std::unique_ptr<Bar> bar;
844 };
845 
846 struct Test {
847   Test(Foo2 foo) : bar(foo.bar.get()), // OK
848       storage(std::move(foo.bar)) {};
849 
850   Bar* bar;
851   std::unique_ptr<Bar> storage;
852 };
853 
854 } // namespace GH120543
855