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
{
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
13 MyIntPointer(const MyIntOwner
&);
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);
31 struct [[gsl::Owner(long)]] MyLongOwnerWithConversion
{
32 MyLongOwnerWithConversion();
33 operator MyLongPointerFromConversion();
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() {
47 // In this case we do not have enough information in a statement local
48 // analysis to detect the problem.
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
67 void dangligGslPtrFromTemporary() {
68 MyIntPointer p
= Y
{}.a
; // TODO
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() {
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
) {
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 }}
135 typedef std::vector
<int>::iterator iterator
;
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}}
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}}
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
;
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
;
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();
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();
245 int &doNotFollowReferencesForLocalOwner() {
246 std::unique_ptr
<int> localOwner
;
247 int &p
= *localOwner
.get();
248 // In real world code localOwner is usually moved here.
252 const char *trackThroughMultiplePointer() {
253 return std::basic_string_view
<char>(std::basic_string
<char>()).begin(); // expected-warning {{returning address of local temporary object}}
257 X(std::unique_ptr
<int> up
) :
258 pointee(*up
), pointee2(up
.get()), pointer(std::move(up
)) {}
261 std::unique_ptr
<int> pointer
;
264 struct [[gsl::Owner
]] XOwner
{
265 int* get() const [[clang::lifetimebound
]];
268 // A common usage that moves the passing owner to the class.
269 // verify no warning on this case.
271 pointee(owner
.get()),
272 owner(std::move(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.
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() {
306 std::reference_wrapper
<int> danglingPtrFromNonOwnerLocal2() {
308 return std::ref(i
); // TODO
311 std::reference_wrapper
<int> danglingPtrFromNonOwnerLocal3() {
313 return std::reference_wrapper
<int>(i
); // TODO
316 std::reference_wrapper
<Unannotated
> danglingPtrFromNonOwnerLocal4() {
318 return std::reference_wrapper
<Unannotated
>(i
); // TODO
321 std::reference_wrapper
<Unannotated
> danglingPtrFromNonOwnerLocal5() {
323 return std::ref(i
); // TODO
326 int *returnPtrToLocalArray() {
328 return std::begin(a
); // TODO
332 std::vector
<int>::iterator member
;
335 ptr_wrapper
getPtrWrapper();
337 std::vector
<int>::iterator
returnPtrFromWrapper() {
338 ptr_wrapper local
= getPtrWrapper();
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
;
354 void checkPtrMemberFromAggregate() {
355 std::vector
<int>::iterator local
= getPtrWrapper().member
; // OK.
358 std::vector
<int>::iterator
doNotInterferWithUnannotated() {
360 // Conservative choice for now. Probably not ok, but we do not warn.
361 return std::begin(value
);
364 std::vector
<int>::iterator
doNotInterferWithUnannotated2() {
369 std::vector
<int>::iterator
supportDerefAddrofChain(int a
, std::vector
<int>::iterator value
) {
382 int &supportDerefAddrofChain2(int a
, std::vector
<int>::iterator value
) {
395 int *supportDerefAddrofChain3(int a
, std::vector
<int>::iterator value
) {
404 return &*&**&*&value
;
408 MyIntPointer
handleDerivedToBaseCast1(MySpecialIntPointer 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
;
421 void testForBug49342()
423 auto it
= std::iter
<char>{} - 2; // Used to be false positive.
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
) {
441 return std::move(*a
);
442 return std::move(a
.value());
447 FooView(const Foo
& foo
[[clang::lifetimebound
]]);
449 FooView
test3(int i
, std::optional
<Foo
> a
) {
451 return *a
; // expected-warning {{address of stack memory}}
452 return a
.value(); // expected-warning {{address of stack memory}}
454 } // namespace GH93386
458 UrlAnalyzed(std::string_view url
[[clang::lifetimebound
]]);
460 std::string
StrCat(std::string_view
, std::string_view
);
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
]]);
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
473 template <typename T
>
474 struct [[gsl::Owner
]] StatusOr
{
475 const T
&value() [[clang::lifetimebound
]];
478 template <typename V
>
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();
492 template <typename V
>
495 operator V() const [[clang::lifetimebound
]];
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
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}}
513 std::vector
<std::string_view
> v3({
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}}
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()};
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());
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
;
546 return t
; // this is fine, no dangling
547 return std::vector
<std::string_view
>(t
.begin(), t
.end());
552 operator std::string_view() const { return ""; }
554 class [[gsl::Owner
]] FooOwner
{
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
{
565 template <typename T
>
566 struct [[gsl::Owner
]] Container2
{
568 Container2(const Container1
<U
>& C2
);
571 std::optional
<std::string_view
> test3(int i
) {
575 return s
; // expected-warning {{address of stack memory associated}}
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;
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.
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
676 template <typename T
>
677 class __set_iterator
{};
681 typedef __set_iterator
<T
> iterator
;
684 template <typename T
>
687 typedef typename BB
<T
>::iterator iterator
;
688 iterator
begin() const;
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
>
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();
739 // no warning on no-LB-annotated method.
740 std::string_view t3
= Foo
<std::string
>().getNoLB();
741 t3
= Foo
<std::string
>().getNoLB();
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}}
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
]]);
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
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
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
;
792 return c
> 1 ? Q1().get()->s
: sv
;
794 return c
> 1 ? q
.get()->s
: sv
;
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
;
803 return c
> 1 ? Q2().get()->s
: sv
;
805 return c
> 1 ? q
.get()->s
: sv
;
808 } // namespace GH120206