Skip to content

Commit 32d808a

Browse files
committed
[clang] Don't consider the lifetimeboundCall when analyzing the gsl
pointer construction.
1 parent 35f6cc6 commit 32d808a

File tree

3 files changed

+55
-7
lines changed

3 files changed

+55
-7
lines changed

clang/lib/Sema/CheckExprLifetime.cpp

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1094,6 +1094,24 @@ static bool pathOnlyHandlesGslPointer(IndirectLocalPath &Path) {
10941094
return false;
10951095
}
10961096

1097+
static bool
1098+
isLifetimeboundInterleaveInGSL(llvm::ArrayRef<IndirectLocalPathEntry> PathRef) {
1099+
if (auto FirstGSLPointer = llvm::find_if(
1100+
PathRef,
1101+
[](const IndirectLocalPathEntry &Path) {
1102+
return Path.Kind == IndirectLocalPathEntry::GslPointerInit ||
1103+
Path.Kind == IndirectLocalPathEntry::GslPointerAssignment;
1104+
});
1105+
FirstGSLPointer != PathRef.end()) {
1106+
return llvm::find_if(
1107+
PathRef.drop_front(FirstGSLPointer - PathRef.begin() + 1),
1108+
[](const IndirectLocalPathEntry &Path) {
1109+
return Path.Kind == IndirectLocalPathEntry::LifetimeBoundCall;
1110+
}) != PathRef.end();
1111+
}
1112+
return false;
1113+
}
1114+
10971115
static bool isAssignmentOperatorLifetimeBound(CXXMethodDecl *CMD) {
10981116
if (!CMD)
10991117
return false;
@@ -1141,7 +1159,8 @@ static void checkExprLifetimeImpl(Sema &SemaRef,
11411159
// someContainer.add(std::move(localUniquePtr));
11421160
// return p;
11431161
IsLocalGslOwner = isRecordWithAttr<OwnerAttr>(L->getType());
1144-
if (pathContainsInit(Path) || !IsLocalGslOwner)
1162+
if (pathContainsInit(Path) || !IsLocalGslOwner ||
1163+
isLifetimeboundInterleaveInGSL(Path))
11451164
return false;
11461165
} else {
11471166
IsGslPtrValueFromGslTempOwner =
@@ -1152,6 +1171,8 @@ static void checkExprLifetimeImpl(Sema &SemaRef,
11521171
// a local or temporary owner or the address of a local variable/param.
11531172
if (!IsGslPtrValueFromGslTempOwner)
11541173
return true;
1174+
if (isLifetimeboundInterleaveInGSL(Path))
1175+
return false;
11551176
}
11561177
}
11571178

clang/test/Sema/warn-lifetime-analysis-nocfg.cpp

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -714,8 +714,8 @@ struct [[gsl::Pointer]] Span {
714714

715715
// Pointer from Owner<Pointer>
716716
std::string_view test5() {
717-
std::string_view a = StatusOr<std::string_view>().valueLB(); // expected-warning {{object backing the pointer will be dest}}
718-
return StatusOr<std::string_view>().valueLB(); // expected-warning {{returning address of local temporary}}
717+
std::string_view a = StatusOr<std::string_view>().valueLB();
718+
return StatusOr<std::string_view>().valueLB();
719719

720720
// No dangling diagnostics on non-lifetimebound methods.
721721
std::string_view b = StatusOr<std::string_view>().valueNoLB();
@@ -746,23 +746,23 @@ std::vector<int*> test8(StatusOr<std::vector<int*>> aa) {
746746

747747
// Pointer<Pointer> from Owner<Owner<Pointer>>
748748
Span<int*> test9(StatusOr<std::vector<int*>> aa) {
749-
return aa.valueLB(); // expected-warning {{address of stack memory associated}}
749+
return aa.valueLB(); //
750750
return aa.valueNoLB(); // OK.
751751
}
752752

753753
/////// From Owner<Owner> ///////
754754

755755
// Pointer<Owner>> from Owner<Owner>
756756
Span<std::string> test10(StatusOr<std::vector<std::string>> aa) {
757-
return aa.valueLB(); // expected-warning {{address of stack memory}}
757+
return aa.valueLB(); //
758758
return aa.valueNoLB(); // OK.
759759
}
760760

761761
/////// From Owner<Pointer<Owner>> ///////
762762

763763
// Pointer<Owner>> from Owner<Pointer<Owner>>
764764
Span<std::string> test11(StatusOr<Span<std::string>> aa) {
765-
return aa.valueLB(); // expected-warning {{address of stack memory}}
765+
return aa.valueLB(); //
766766
return aa.valueNoLB(); // OK.
767767
}
768768

@@ -780,3 +780,30 @@ void test13() {
780780
}
781781

782782
} // namespace GH100526
783+
784+
namespace test {
785+
786+
struct [[gsl::Pointer]] FooOwner {};
787+
struct [[gsl::Pointer]] FooPointer {
788+
FooPointer(const FooOwner&);
789+
};
790+
791+
template<typename T>
792+
struct [[gsl::Owner]] Container {
793+
const T& get() const [[clang::lifetimebound]];
794+
};
795+
796+
FooPointer func() {
797+
Container<FooPointer> foo;
798+
799+
FooPointer p = Container<FooPointer>().get();
800+
p = Container<FooPointer>().get();
801+
return foo.get();
802+
803+
FooPointer p2 = Container<FooOwner>().get();
804+
p2 = Container<FooOwner>().get();
805+
Container<FooOwner> foo2;
806+
return foo2.get();
807+
}
808+
809+
}

clang/test/SemaCXX/attr-lifetimebound.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ namespace p0936r0_examples {
153153
void f() {
154154
std::string_view sv = "hi";
155155
std::string_view sv2 = sv + sv; // expected-warning {{temporary}}
156-
sv2 = sv + sv; // expected-warning {{object backing the pointer}}
156+
sv2 = sv + sv; // FIXME: warn here too.
157157
}
158158

159159
struct X { int a, b; };

0 commit comments

Comments
 (0)