diff --git a/clang/lib/Sema/CheckExprLifetime.cpp b/clang/lib/Sema/CheckExprLifetime.cpp index 7109de03cadd1..837414c4840d7 100644 --- a/clang/lib/Sema/CheckExprLifetime.cpp +++ b/clang/lib/Sema/CheckExprLifetime.cpp @@ -281,9 +281,11 @@ template static bool isRecordWithAttr(QualType Type) { return Result; } -bool isPointerLikeType(QualType QT) { - return isRecordWithAttr(QT) || QT->isPointerType() || - QT->isNullPtrType(); +// Tells whether the type is annotated with [[gsl::Pointer]]. +bool isGLSPointerType(QualType QT) { return isRecordWithAttr(QT); } + +static bool isPointerLikeType(QualType QT) { + return isGLSPointerType(QT) || QT->isPointerType() || QT->isNullPtrType(); } // Decl::isInStdNamespace will return false for iterators in some STL diff --git a/clang/lib/Sema/CheckExprLifetime.h b/clang/lib/Sema/CheckExprLifetime.h index 95c249c610977..6351e52a362f1 100644 --- a/clang/lib/Sema/CheckExprLifetime.h +++ b/clang/lib/Sema/CheckExprLifetime.h @@ -18,9 +18,8 @@ namespace clang::sema { -// Tells whether the type is annotated with [[gsl::Pointer]] or is a pointer -// type. -bool isPointerLikeType(QualType QT); +// Tells whether the type is annotated with [[gsl::Pointer]]. +bool isGLSPointerType(QualType QT); /// Describes an entity that is being assigned. struct AssignedEntity { diff --git a/clang/lib/Sema/SemaAttr.cpp b/clang/lib/Sema/SemaAttr.cpp index 42aa68d2905c0..6907fa91e28c2 100644 --- a/clang/lib/Sema/SemaAttr.cpp +++ b/clang/lib/Sema/SemaAttr.cpp @@ -284,7 +284,7 @@ void Sema::inferLifetimeCaptureByAttribute(FunctionDecl *FD) { // We only apply the lifetime_capture_by attribute to parameters of // pointer-like reference types (`const T&`, `T&&`). if (PVD->getType()->isReferenceType() && - sema::isPointerLikeType(PVD->getType().getNonReferenceType())) { + sema::isGLSPointerType(PVD->getType().getNonReferenceType())) { int CaptureByThis[] = {LifetimeCaptureByAttr::THIS}; PVD->addAttr( LifetimeCaptureByAttr::CreateImplicit(Context, CaptureByThis, 1)); diff --git a/clang/test/AST/attr-lifetime-capture-by.cpp b/clang/test/AST/attr-lifetime-capture-by.cpp index 71b348dac764b..b453bef018c0b 100644 --- a/clang/test/AST/attr-lifetime-capture-by.cpp +++ b/clang/test/AST/attr-lifetime-capture-by.cpp @@ -80,16 +80,16 @@ std::vector pointers; // CHECK: CXXMethodDecl {{.*}} push_back 'void (int *const &)' // CHECK-NEXT: ParmVarDecl {{.*}} 'int *const &' -// CHECK-NEXT: LifetimeCaptureByAttr {{.*}} Implicit +// CHECK-NOT: LifetimeCaptureByAttr // CHECK: CXXMethodDecl {{.*}} push_back 'void (int *&&)' // CHECK-NEXT: ParmVarDecl {{.*}} 'int *&&' -// CHECK-NEXT: LifetimeCaptureByAttr {{.*}} Implicit +// CHECK-NOT: LifetimeCaptureByAttr // CHECK: CXXMethodDecl {{.*}} insert 'void (iterator, int *&&)' // CHECK-NEXT: ParmVarDecl {{.*}} 'iterator' // CHECK-NEXT: ParmVarDecl {{.*}} 'int *&&' -// CHECK-NEXT: LifetimeCaptureByAttr {{.*}} Implicit +// CHECK-NOT: LifetimeCaptureByAttr std::vector ints; // CHECK: ClassTemplateSpecializationDecl {{.*}} struct vector definition implicit_instantiation diff --git a/clang/test/Sema/warn-lifetime-analysis-capture-by.cpp b/clang/test/Sema/warn-lifetime-analysis-capture-by.cpp index 12b933e63edd7..2877d8d6cd5f9 100644 --- a/clang/test/Sema/warn-lifetime-analysis-capture-by.cpp +++ b/clang/test/Sema/warn-lifetime-analysis-capture-by.cpp @@ -406,7 +406,7 @@ void use() { strings.insert(strings.begin(), std::string()); std::vector pointers; - pointers.push_back(getLifetimeBoundPointer(std::string())); // expected-warning {{object whose reference is captured by 'pointers' will be destroyed at the end of the full-expression}} + pointers.push_back(getLifetimeBoundPointer(std::string())); pointers.push_back(&local); } @@ -451,3 +451,24 @@ void test() { T2(1, a); // expected-warning {{object whose reference is captured by}} } } // namespace on_constructor + +namespace GH121391 { + +struct Foo {}; + +template +struct Container { + const T& tt() [[clang::lifetimebound]]; +}; +template +struct StatusOr { + T* get() [[clang::lifetimebound]]; +}; +StatusOr> getContainer(); + +void test() { + std::vector vv; + vv.push_back(getContainer().get()->tt()); // OK +} + +} // namespace GH121391