[LV] Add test showing debug output for loops with uncountable BTCs.
[llvm-project.git] / clang / test / Sema / warn-lifetime-analysis-nocfg.cpp
blob4c19367bb7f3ddc1732019d527fc87e5a3e81548
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 };
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();
18 struct MySpecialIntPointer : MyIntPointer {
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 {
26 struct [[gsl::Pointer(long)]] MyLongPointerFromConversion {
27 MyLongPointerFromConversion(long *p = nullptr);
28 long &operator*();
31 struct [[gsl::Owner(long)]] MyLongOwnerWithConversion {
32 MyLongOwnerWithConversion();
33 operator MyLongPointerFromConversion();
34 long &operator*();
35 MyIntPointer releaseAsMyPointer();
36 long *releaseAsRawPointer();
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}}
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});
53 MyIntPointer ownershipTransferToMyPointer() {
54 MyLongOwnerWithConversion t;
55 return t.releaseAsMyPointer(); // ok
58 long *ownershipTransferToRawPointer() {
59 MyLongOwnerWithConversion t;
60 return t.releaseAsRawPointer(); // ok
63 struct Y {
64 int a[4];
67 void dangligGslPtrFromTemporary() {
68 MyIntPointer p = Y{}.a; // TODO
69 (void)p;
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}}
80 MyIntPointer danglingGslPtrFromLocal() {
81 int j;
82 return &j; // TODO
85 MyIntPointer returningLocalPointer() {
86 MyIntPointer localPointer;
87 return localPointer; // ok
90 MyIntPointer daglingGslPtrFromLocalOwner() {
91 MyIntOwner localOwner;
92 return localOwner; // expected-warning {{address of stack memory associated with local variable 'localOwner' returned}}
95 MyLongPointerFromConversion daglingGslPtrFromLocalOwnerConv() {
96 MyLongOwnerWithConversion localOwner;
97 return localOwner; // expected-warning {{address of stack memory associated with local variable 'localOwner' returned}}
100 MyIntPointer danglingGslPtrFromTemporary() {
101 return MyIntOwner{}; // expected-warning {{returning address of local temporary object}}
104 MyIntOwner makeTempOwner();
106 MyIntPointer danglingGslPtrFromTemporary2() {
107 return makeTempOwner(); // expected-warning {{returning address of local temporary object}}
110 MyLongPointerFromConversion danglingGslPtrFromTemporaryConv() {
111 return MyLongOwnerWithConversion{}; // expected-warning {{returning address of local temporary object}}
114 int *noFalsePositive(MyIntOwner &o) {
115 MyIntPointer p = o;
116 return &*p; // ok
119 MyIntPointer global;
120 MyLongPointerFromConversion global2;
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 }}
134 struct Unannotated {
135 typedef std::vector<int>::iterator iterator;
136 iterator begin();
137 operator iterator() const;
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;
145 std::vector<int>::iterator modelIteratorReturn() {
146 return std::vector<int>().begin(); // expected-warning {{returning address of local temporary object}}
149 const int *modelFreeFunctions() {
150 return std::data(std::vector<int>()); // expected-warning {{returning address of local temporary object}}
153 int &modelAnyCast() {
154 return std::any_cast<int&>(std::any{}); // expected-warning {{returning reference to local temporary object}}
157 int modelAnyCast2() {
158 return std::any_cast<int>(std::any{}); // ok
161 int modelAnyCast3() {
162 return std::any_cast<int&>(std::any{}); // ok
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}}
170 int &danglingRawPtrFromLocal2() {
171 std::optional<int> o;
172 return o.value(); // expected-warning {{reference to stack memory associated with local variable 'o' returned}}
175 int &danglingRawPtrFromLocal3() {
176 std::optional<int> o;
177 return *o; // expected-warning {{reference to stack memory associated with local variable 'o' returned}}
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}}
185 // no warning on constructing from gsl-pointer
186 std::string_view c2 = std::vector<std::string_view>().at(0);
188 std::vector<std::string> local;
189 return local.at(0); // expected-warning {{address of stack memory associated with local variable}}
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.
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
208 const char *danglingRawPtrFromTemp() {
209 return std::basic_string<char>().c_str(); // expected-warning {{returning address of local temporary object}}
212 std::unique_ptr<int> getUniquePtr();
214 int *danglingUniquePtrFromTemp() {
215 return getUniquePtr().get(); // expected-warning {{returning address of local temporary object}}
218 int *danglingUniquePtrFromTemp2() {
219 return std::unique_ptr<int>().get(); // expected-warning {{returning address of local temporary object}}
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}}
229 std::vector<int> getTempVec();
230 std::optional<std::vector<int>> getTempOptVec();
232 void testLoops() {
233 for (auto i : getTempVec()) // ok
235 for (auto i : *getTempOptVec()) // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}}
239 int &usedToBeFalsePositive(std::vector<int> &v) {
240 std::vector<int>::iterator it = v.begin();
241 int& value = *it;
242 return value; // ok
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
252 const char *trackThroughMultiplePointer() {
253 return std::basic_string_view<char>(std::basic_string<char>()).begin(); // expected-warning {{returning address of local temporary object}}
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;
264 struct [[gsl::Owner]] XOwner {
265 int* get() const [[clang::lifetimebound]];
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;
277 std::vector<int>::iterator getIt();
278 std::vector<int> getVec();
280 const int &handleGslPtrInitsThroughReference() {
281 const auto &it = getIt(); // Ok, it is lifetime extended.
282 return *it;
285 void handleGslPtrInitsThroughReference2() {
286 const std::vector<int> &v = getVec();
287 const int *val = v.data(); // Ok, it is lifetime extended.
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}}
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}}
301 std::reference_wrapper<int> danglingPtrFromNonOwnerLocal() {
302 int i = 5;
303 return i; // TODO
306 std::reference_wrapper<int> danglingPtrFromNonOwnerLocal2() {
307 int i = 5;
308 return std::ref(i); // TODO
311 std::reference_wrapper<int> danglingPtrFromNonOwnerLocal3() {
312 int i = 5;
313 return std::reference_wrapper<int>(i); // TODO
316 std::reference_wrapper<Unannotated> danglingPtrFromNonOwnerLocal4() {
317 Unannotated i;
318 return std::reference_wrapper<Unannotated>(i); // TODO
321 std::reference_wrapper<Unannotated> danglingPtrFromNonOwnerLocal5() {
322 Unannotated i;
323 return std::ref(i); // TODO
326 int *returnPtrToLocalArray() {
327 int a[5];
328 return std::begin(a); // TODO
331 struct ptr_wrapper {
332 std::vector<int>::iterator member;
335 ptr_wrapper getPtrWrapper();
337 std::vector<int>::iterator returnPtrFromWrapper() {
338 ptr_wrapper local = getPtrWrapper();
339 return local.member;
342 std::vector<int>::iterator returnPtrFromWrapperThroughRef() {
343 ptr_wrapper local = getPtrWrapper();
344 ptr_wrapper &local2 = local;
345 return local2.member;
348 std::vector<int>::iterator returnPtrFromWrapperThroughRef2() {
349 ptr_wrapper local = getPtrWrapper();
350 std::vector<int>::iterator &local2 = local.member;
351 return local2;
354 void checkPtrMemberFromAggregate() {
355 std::vector<int>::iterator local = getPtrWrapper().member; // OK.
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);
364 std::vector<int>::iterator doNotInterferWithUnannotated2() {
365 Unannotated value;
366 return value;
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;
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;
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;
408 MyIntPointer handleDerivedToBaseCast1(MySpecialIntPointer ptr) {
409 return ptr;
412 MyIntPointer handleDerivedToBaseCast2(MyOwnerIntPointer ptr) {
413 return ptr; // expected-warning {{address of stack memory associated with parameter 'ptr' returned}}
416 std::vector<int>::iterator noFalsePositiveWithVectorOfPointers() {
417 std::vector<std::vector<int>::iterator> iters;
418 return iters.at(0);
421 void testForBug49342()
423 auto it = std::iter<char>{} - 2; // Used to be false positive.
426 namespace GH93386 {
427 // verify no duplicated diagnostics are emitted.
428 struct [[gsl::Pointer]] S {
429 S(const std::vector<int>& abc [[clang::lifetimebound]]);
432 S test(std::vector<int> a) {
433 return S(a); // expected-warning {{address of stack memory associated with}}
436 auto s = S(std::vector<int>()); // expected-warning {{temporary whose address is used as value of local variable}}
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());
445 struct Foo;
446 struct FooView {
447 FooView(const Foo& foo [[clang::lifetimebound]]);
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}}
454 } // namespace GH93386
456 namespace GH100549 {
457 struct UrlAnalyzed {
458 UrlAnalyzed(std::string_view url [[clang::lifetimebound]]);
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}}
465 std::string_view ReturnStringView(std::string_view abc [[clang::lifetimebound]]);
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}}
470 } // namespace GH100549
472 namespace GH108272 {
473 template <typename T>
474 struct [[gsl::Owner]] StatusOr {
475 const T &value() [[clang::lifetimebound]];
478 template <typename V>
479 class Wrapper1 {
480 public:
481 operator V() const;
482 V value;
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();
492 template <typename V>
493 class Wrapper2 {
494 public:
495 operator V() const [[clang::lifetimebound]];
496 V value;
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}}
504 } // namespace GH108272
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()
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}}
518 std::optional<std::string_view> o1 = std::string(); // expected-warning {{object backing the pointer}}
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);
529 // FIXME: should work for assignment cases
530 v1 = {std::string()};
531 o1 = std::string();
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");
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());
550 class Foo {
551 public:
552 operator std::string_view() const { return ""; }
554 class [[gsl::Owner]] FooOwner {
555 public:
556 operator std::string_view() const { return ""; }
558 std::optional<Foo> GetFoo();
559 std::optional<FooOwner> GetFooOwner();
561 template <typename T>
562 struct [[gsl::Owner]] Container1 {
563 Container1();
565 template <typename T>
566 struct [[gsl::Owner]] Container2 {
567 template<typename U>
568 Container2(const Container1<U>& C2);
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}}
583 std::optional<int*> test4(int a) {
584 return std::make_optional(nullptr); // fine
588 template <typename T>
589 struct [[gsl::Owner]] StatusOr {
590 const T &valueLB() const [[clang::lifetimebound]];
591 const T &valueNoLB() const;
594 template<typename T>
595 struct [[gsl::Pointer]] Span {
596 Span(const std::vector<T> &V);
598 const int& getFieldLB() const [[clang::lifetimebound]];
599 const int& getFieldNoLB() const;
603 /////// From Owner<Pointer> ///////
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
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();
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}}
624 /////// From Owner<Owner<Pointer>> ///////
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.
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();
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.
644 /////// From Owner<Owner> ///////
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.
652 /////// From Owner<Pointer<Owner>> ///////
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.
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.
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*>{};
670 std::optional<Span<int>> t = std::vector<int> {}; // expected-warning {{object backing the pointer will be destroyed}}
673 } // namespace GH100526
675 namespace std {
676 template <typename T>
677 class __set_iterator {};
679 template<typename T>
680 struct BB {
681 typedef __set_iterator<T> iterator;
684 template <typename T>
685 class set {
686 public:
687 typedef typename BB<T>::iterator iterator;
688 iterator begin() const;
690 } // namespace std
691 namespace GH118064{
693 void test() {
694 auto y = std::set<int>{}.begin(); // expected-warning {{object backing the pointer}}
696 } // namespace GH118064
698 namespace LifetimeboundInterleave {
700 const std::string& Ref(const std::string& abc [[clang::lifetimebound]]);
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]]);
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}}
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}}
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}}
720 std::string_view t4 = TakeStr(std::string());
721 t4 = TakeStr(std::string());
722 return TakeStr(std::string());
725 template <typename T>
726 struct Foo {
727 const T& get() const [[clang::lifetimebound]];
728 const T& getNoLB() const;
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}}
735 std::string_view t2 = Foo<std::string_view>().get();
736 t2 = Foo<std::string_view>().get();
737 return r2.get();
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();
745 struct Bar {};
746 struct [[gsl::Pointer]] Pointer {
747 Pointer(const Bar & bar [[clang::lifetimebound]]);
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}}
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]];
761 template <typename T>
762 typename MySpan<T>::iterator ReturnFirstIt(const MySpan<T>& v [[clang::lifetimebound]]);
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();
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}}
779 } // namespace LifetimeboundInterleave
781 namespace GH120206 {
782 struct S {
783 std::string_view s;
786 struct [[gsl::Owner]] Q1 {
787 const S* get() const [[clang::lifetimebound]];
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;
797 struct Q2 {
798 const S* get() const [[clang::lifetimebound]];
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;
808 } // namespace GH120206