diff --git a/clang/lib/Sema/SemaAttr.cpp b/clang/lib/Sema/SemaAttr.cpp index b0849c74e375e..d3cf42251be2e 100644 --- a/clang/lib/Sema/SemaAttr.cpp +++ b/clang/lib/Sema/SemaAttr.cpp @@ -287,7 +287,12 @@ void Sema::inferLifetimeCaptureByAttribute(FunctionDecl *FD) { if (PVD->hasAttr()) return; for (ParmVarDecl *PVD : MD->parameters()) { - if (sema::isPointerLikeType(PVD->getType().getNonReferenceType())) { + // Methods in standard containers that capture values typically accept + // reference-type parameters, e.g., `void push_back(const T& value)`. + // 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())) { 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 c3afe267301ad..debad9b7204d7 100644 --- a/clang/test/AST/attr-lifetime-capture-by.cpp +++ b/clang/test/AST/attr-lifetime-capture-by.cpp @@ -37,67 +37,53 @@ struct vector { struct [[gsl::Pointer()]] View {}; std::vector views; // CHECK: ClassTemplateSpecializationDecl {{.*}} struct vector definition implicit_instantiation -// CHECK: TemplateArgument type 'View' -// CHECK-NOT: LifetimeCaptureByAttr // CHECK: CXXMethodDecl {{.*}} push_back 'void (const View &)' -// CHECK: ParmVarDecl {{.*}} 'const View &' -// CHECK: LifetimeCaptureByAttr {{.*}} Implicit -// CHECK-NOT: LifetimeCaptureByAttr +// CHECK-NEXT: ParmVarDecl {{.*}} 'const View &' +// CHECK-NEXT: LifetimeCaptureByAttr {{.*}} Implicit // CHECK: CXXMethodDecl {{.*}} push_back 'void (View &&)' -// CHECK: ParmVarDecl {{.*}} 'View &&' -// CHECK: LifetimeCaptureByAttr {{.*}} Implicit +// CHECK-NEXT: ParmVarDecl {{.*}} 'View &&' +// CHECK-NEXT: LifetimeCaptureByAttr {{.*}} Implicit // CHECK: CXXMethodDecl {{.*}} insert 'void (iterator, View &&)' -// CHECK: ParmVarDecl {{.*}} 'iterator' -// CHECK: LifetimeCaptureByAttr {{.*}} Implicit -// CHECK: ParmVarDecl {{.*}} 'View &&' -// CHECK: LifetimeCaptureByAttr {{.*}} Implicit -// CHECK-NOT: LifetimeCaptureByAttr +// CHECK-NEXT: ParmVarDecl {{.*}} 'iterator' +// CHECK-NEXT: ParmVarDecl {{.*}} 'View &&' +// CHECK-NEXT: LifetimeCaptureByAttr {{.*}} Implicit template struct [[gsl::Pointer()]] ViewTemplate {}; std::vector> templated_views; -// CHECK: ClassTemplateSpecializationDecl {{.*}} struct vector definition implicit_instantiation -// CHECK: TemplateArgument type 'ViewTemplate' -// CHECK-NOT: LifetimeCaptureByAttr +// CHECK: ClassTemplateSpecializationDecl {{.*}} struct vector definition implicit_instantiation // CHECK: CXXMethodDecl {{.*}} push_back 'void (const ViewTemplate &)' -// CHECK: ParmVarDecl {{.*}} 'const ViewTemplate &' -// CHECK: LifetimeCaptureByAttr {{.*}} Implicit +// CHECK-NEXT: ParmVarDecl {{.*}} 'const ViewTemplate &' +// CHECK-NEXT: LifetimeCaptureByAttr {{.*}} Implicit // CHECK-NOT: LifetimeCaptureByAttr // CHECK: CXXMethodDecl {{.*}} push_back 'void (ViewTemplate &&)' -// CHECK: ParmVarDecl {{.*}} 'ViewTemplate &&' -// CHECK: LifetimeCaptureByAttr {{.*}} Implicit +// CHECK-NEXT: ParmVarDecl {{.*}} 'ViewTemplate &&' +// CHECK-NEXT: LifetimeCaptureByAttr {{.*}} Implicit // CHECK: CXXMethodDecl {{.*}} insert 'void (iterator, ViewTemplate &&)' -// CHECK: ParmVarDecl {{.*}} 'iterator' -// CHECK: LifetimeCaptureByAttr {{.*}} Implicit -// CHECK: ParmVarDecl {{.*}} 'ViewTemplate &&' -// CHECK: LifetimeCaptureByAttr {{.*}} Implicit -// CHECK-NOT: LifetimeCaptureByAttr +// CHECK-NEXT: ParmVarDecl {{.*}} 'iterator' +// CHECK-NEXT: ParmVarDecl {{.*}} 'ViewTemplate &&' +// CHECK-NEXT: LifetimeCaptureByAttr {{.*}} Implicit std::vector pointers; // CHECK: ClassTemplateSpecializationDecl {{.*}} struct vector definition implicit_instantiation -// CHECK: TemplateArgument type 'int *' -// CHECK-NOT: LifetimeCaptureByAttr // CHECK: CXXMethodDecl {{.*}} push_back 'void (int *const &)' -// CHECK: ParmVarDecl {{.*}} 'int *const &' -// CHECK: LifetimeCaptureByAttr {{.*}} Implicit -// CHECK-NOT: LifetimeCaptureByAttr +// CHECK-NEXT: ParmVarDecl {{.*}} 'int *const &' +// CHECK-NEXT: LifetimeCaptureByAttr {{.*}} Implicit // CHECK: CXXMethodDecl {{.*}} push_back 'void (int *&&)' -// CHECK: ParmVarDecl {{.*}} 'int *&&' -// CHECK: LifetimeCaptureByAttr {{.*}} Implicit +// CHECK-NEXT: ParmVarDecl {{.*}} 'int *&&' +// CHECK-NEXT: LifetimeCaptureByAttr {{.*}} Implicit // CHECK: CXXMethodDecl {{.*}} insert 'void (iterator, int *&&)' -// CHECK: ParmVarDecl {{.*}} 'iterator' -// CHECK: LifetimeCaptureByAttr {{.*}} Implicit -// CHECK: ParmVarDecl {{.*}} 'int *&&' -// CHECK: LifetimeCaptureByAttr {{.*}} Implicit -// CHECK-NOT: LifetimeCaptureByAttr +// CHECK-NEXT: ParmVarDecl {{.*}} 'iterator' +// CHECK-NEXT: ParmVarDecl {{.*}} 'int *&&' +// CHECK-NEXT: LifetimeCaptureByAttr {{.*}} Implicit std::vector ints; // CHECK: ClassTemplateSpecializationDecl {{.*}} struct vector definition implicit_instantiation @@ -110,6 +96,6 @@ std::vector ints; // CHECK-NOT: LifetimeCaptureByAttr // CHECK: CXXMethodDecl {{.*}} insert 'void (iterator, int &&)' -// CHECK: ParmVarDecl {{.*}} 'iterator' -// CHECK: LifetimeCaptureByAttr {{.*}} Implicit +// CHECK-NEXT: ParmVarDecl {{.*}} 'iterator' +// CHECK-NEXT: ParmVarDecl {{.*}} 'int &&' // CHECK-NOT: LifetimeCaptureByAttr