llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Haojian Wu (hokein) <details> <summary>Changes</summary> --- Full diff: https://github.com/llvm/llvm-project/pull/118078.diff 2 Files Affected: - (modified) clang/lib/Sema/SemaAttr.cpp (+37-22) - (modified) clang/test/AST/attr-lifetime-capture-by.cpp (+16) ``````````diff diff --git a/clang/lib/Sema/SemaAttr.cpp b/clang/lib/Sema/SemaAttr.cpp index d3cf42251be2e7..3279f4109a9c02 100644 --- a/clang/lib/Sema/SemaAttr.cpp +++ b/clang/lib/Sema/SemaAttr.cpp @@ -270,34 +270,49 @@ void Sema::inferLifetimeBoundAttribute(FunctionDecl *FD) { } void Sema::inferLifetimeCaptureByAttribute(FunctionDecl *FD) { - if (!FD) + auto *MD = dyn_cast_if_present<CXXMethodDecl>(FD); + if (!MD || !MD->getParent()->isInStdNamespace()) return; - auto *MD = dyn_cast<CXXMethodDecl>(FD); - if (!MD || !MD->getIdentifier() || !MD->getParent()->isInStdNamespace()) + auto Annotate = [this](const FunctionDecl *MD) { + // Do not infer if any parameter is explicitly annotated. + for (ParmVarDecl *PVD : MD->parameters()) + if (PVD->hasAttr<LifetimeCaptureByAttr>()) + return; + for (ParmVarDecl *PVD : MD->parameters()) { + // 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)); + } + } + }; + + if (!MD->getIdentifier()) { + static const llvm::StringSet<> MapLikeContainer{ + "map", + "multimap", + "unordered_map", + "unordered_multimap", + }; + // Infer for the map's operator []: + // std::map<string_view, ...> m; + // m[ReturnString(..)] = ...; // !dangling references in m. + if (MD->getOverloadedOperator() != OO_Subscript || + !MapLikeContainer.contains(MD->getParent()->getName())) + return; + Annotate(MD); return; - // FIXME: Infer for operator[] for map-like containers. For example: - // std::map<string_view, ...> m; - // m[ReturnString(..)] = ...; + } static const llvm::StringSet<> CapturingMethods{"insert", "push", "push_front", "push_back"}; if (!CapturingMethods.contains(MD->getName())) return; - // Do not infer if any parameter is explicitly annotated. - for (ParmVarDecl *PVD : MD->parameters()) - if (PVD->hasAttr<LifetimeCaptureByAttr>()) - return; - for (ParmVarDecl *PVD : MD->parameters()) { - // 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)); - } - } + Annotate(MD); } void Sema::inferNullableClassAttribute(CXXRecordDecl *CRD) { diff --git a/clang/test/AST/attr-lifetime-capture-by.cpp b/clang/test/AST/attr-lifetime-capture-by.cpp index debad9b7204d72..71b348dac764bc 100644 --- a/clang/test/AST/attr-lifetime-capture-by.cpp +++ b/clang/test/AST/attr-lifetime-capture-by.cpp @@ -30,6 +30,12 @@ struct vector { void insert(iterator, T&&); }; + +template <typename Key, typename Value> +struct map { + Value& operator[](Key&& p); + Value& operator[](const Key& p); +}; } // namespace std // CHECK-NOT: LifetimeCaptureByAttr @@ -99,3 +105,13 @@ std::vector<int> ints; // CHECK-NEXT: ParmVarDecl {{.*}} 'iterator' // CHECK-NEXT: ParmVarDecl {{.*}} 'int &&' // CHECK-NOT: LifetimeCaptureByAttr + +std::map<View, int> map; +// CHECK: ClassTemplateSpecializationDecl {{.*}} struct map definition implicit_instantiation + +// CHECK: CXXMethodDecl {{.*}} operator[] 'int &(View &&)' implicit_instantiation +// CHECK-NEXT: ParmVarDecl {{.*}} p 'View &&' +// CHECK-NEXT: LifetimeCaptureByAttr {{.*}} Implicit +// CHECK: CXXMethodDecl {{.*}} operator[] 'int &(const View &)' implicit_instantiation +// CHECK-NEXT: ParmVarDecl {{.*}} p 'const View &' +// CHECK-NEXT: LifetimeCaptureByAttr {{.*}} Implicit `````````` </details> https://github.com/llvm/llvm-project/pull/118078 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits