[clang] [clang] Fix incorrect inferred lifetime_capture_by attr on STL (PR #118013)

Haojian Wu via cfe-commits cfe-commits at lists.llvm.org
Fri Nov 29 00:15:31 PST 2024


https://github.com/hokein updated https://github.com/llvm/llvm-project/pull/118013

>From feb9445efffa69c158407bda6f5981a033197567 Mon Sep 17 00:00:00 2001
From: Haojian Wu <hokein.wu at gmail.com>
Date: Thu, 28 Nov 2024 14:27:23 +0100
Subject: [PATCH 1/3] [clang] NFC, simplify the attr-lifetime-capture-by.test

---
 clang/test/AST/attr-lifetime-capture-by.cpp | 66 +++++++++------------
 1 file changed, 28 insertions(+), 38 deletions(-)

diff --git a/clang/test/AST/attr-lifetime-capture-by.cpp b/clang/test/AST/attr-lifetime-capture-by.cpp
index c3afe267301ad7..3f22322719b6ab 100644
--- a/clang/test/AST/attr-lifetime-capture-by.cpp
+++ b/clang/test/AST/attr-lifetime-capture-by.cpp
@@ -37,67 +37,56 @@ struct vector {
 struct [[gsl::Pointer()]] View {};
 std::vector<View> 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:               LifetimeCaptureByAttr {{.*}} Implicit
+// CHECK-NEXT:           ParmVarDecl {{.*}} 'View &&'
+// CHECK-NEXT:               LifetimeCaptureByAttr {{.*}} Implicit
 
 template <class T> struct [[gsl::Pointer()]] ViewTemplate {};
 std::vector<ViewTemplate<int>> templated_views;
-// CHECK:   ClassTemplateSpecializationDecl {{.*}} struct vector definition implicit_instantiation
-// CHECK:       TemplateArgument type 'ViewTemplate<int>'
-// CHECK-NOT:   LifetimeCaptureByAttr
+// CHECK:       ClassTemplateSpecializationDecl {{.*}} struct vector definition implicit_instantiation
 
 // CHECK:       CXXMethodDecl {{.*}} push_back 'void (const ViewTemplate<int> &)'
-// CHECK:           ParmVarDecl {{.*}} 'const ViewTemplate<int> &'
-// CHECK:               LifetimeCaptureByAttr {{.*}} Implicit
+// CHECK-NEXT:           ParmVarDecl {{.*}} 'const ViewTemplate<int> &'
+// CHECK-NEXT:               LifetimeCaptureByAttr {{.*}} Implicit
 // CHECK-NOT:   LifetimeCaptureByAttr
 
 // CHECK:       CXXMethodDecl {{.*}} push_back 'void (ViewTemplate<int> &&)'
-// CHECK:           ParmVarDecl {{.*}} 'ViewTemplate<int> &&'
-// CHECK:               LifetimeCaptureByAttr {{.*}} Implicit
+// CHECK-NEXT:           ParmVarDecl {{.*}} 'ViewTemplate<int> &&'
+// CHECK-NEXT:               LifetimeCaptureByAttr {{.*}} Implicit
 
 // CHECK:       CXXMethodDecl {{.*}} insert 'void (iterator, ViewTemplate<int> &&)'
-// CHECK:           ParmVarDecl {{.*}} 'iterator'
-// CHECK:               LifetimeCaptureByAttr {{.*}} Implicit
-// CHECK:           ParmVarDecl {{.*}} 'ViewTemplate<int> &&'
-// CHECK:               LifetimeCaptureByAttr {{.*}} Implicit
-// CHECK-NOT:   LifetimeCaptureByAttr
+// CHECK-NEXT:           ParmVarDecl {{.*}} 'iterator'
+// CHECK-NEXT:               LifetimeCaptureByAttr {{.*}} Implicit
+// CHECK-NEXT:           ParmVarDecl {{.*}} 'ViewTemplate<int> &&'
+// CHECK-NEXT:               LifetimeCaptureByAttr {{.*}} Implicit
 
 std::vector<int*> 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:               LifetimeCaptureByAttr {{.*}} Implicit
+// CHECK-NEXT:           ParmVarDecl {{.*}} 'int *&&'
+// CHECK-NEXT:               LifetimeCaptureByAttr {{.*}} Implicit
 
 std::vector<int> ints;
 // CHECK:   ClassTemplateSpecializationDecl {{.*}} struct vector definition implicit_instantiation
@@ -110,6 +99,7 @@ std::vector<int> ints;
 // CHECK-NOT:   LifetimeCaptureByAttr
 
 // CHECK:       CXXMethodDecl {{.*}} insert 'void (iterator, int &&)'
-// CHECK:           ParmVarDecl {{.*}} 'iterator'
-// CHECK:               LifetimeCaptureByAttr {{.*}} Implicit
+// CHECK-NEXT:           ParmVarDecl {{.*}} 'iterator'
+// CHECK-NEXT:               LifetimeCaptureByAttr {{.*}} Implicit
+// CHECK-NEXT:           ParmVarDecl {{.*}} 'int &&'
 // CHECK-NOT:   LifetimeCaptureByAttr

>From 2b3e35acf143be6aecb59c70be403ce7376c40a9 Mon Sep 17 00:00:00 2001
From: Haojian Wu <hokein.wu at gmail.com>
Date: Thu, 28 Nov 2024 15:32:10 +0100
Subject: [PATCH 2/3] [clang] Fix incorrect inferred lifetime_capture_by attr
 on STL.

We incorrectly annotate the iterator parameter for `insert` method
(`void insert(const_iterator, const value_type& value)`), because
iterator happens to be a gsl-pointer type. This patch fixes it.
---
 clang/lib/Sema/SemaAttr.cpp                 | 7 ++++++-
 clang/test/AST/attr-lifetime-capture-by.cpp | 8 ++++----
 2 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/clang/lib/Sema/SemaAttr.cpp b/clang/lib/Sema/SemaAttr.cpp
index b0849c74e375ed..d3cf42251be2e7 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<LifetimeCaptureByAttr>())
       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 3f22322719b6ab..2a568b0f00d3ae 100644
--- a/clang/test/AST/attr-lifetime-capture-by.cpp
+++ b/clang/test/AST/attr-lifetime-capture-by.cpp
@@ -48,7 +48,7 @@ std::vector<View> views;
 
 // CHECK:       CXXMethodDecl {{.*}} insert 'void (iterator, View &&)'
 // CHECK-NEXT:           ParmVarDecl {{.*}} 'iterator'
-// CHECK-NEXT:               LifetimeCaptureByAttr {{.*}} Implicit
+// CHECK-NOT:               LifetimeCaptureByAttr {{.*}} Implicit
 // CHECK-NEXT:           ParmVarDecl {{.*}} 'View &&'
 // CHECK-NEXT:               LifetimeCaptureByAttr {{.*}} Implicit
 
@@ -67,7 +67,7 @@ std::vector<ViewTemplate<int>> templated_views;
 
 // CHECK:       CXXMethodDecl {{.*}} insert 'void (iterator, ViewTemplate<int> &&)'
 // CHECK-NEXT:           ParmVarDecl {{.*}} 'iterator'
-// CHECK-NEXT:               LifetimeCaptureByAttr {{.*}} Implicit
+// CHECK-NOT:               LifetimeCaptureByAttr {{.*}} Implicit
 // CHECK-NEXT:           ParmVarDecl {{.*}} 'ViewTemplate<int> &&'
 // CHECK-NEXT:               LifetimeCaptureByAttr {{.*}} Implicit
 
@@ -84,7 +84,7 @@ std::vector<int*> pointers;
 
 // CHECK:       CXXMethodDecl {{.*}} insert 'void (iterator, int *&&)'
 // CHECK-NEXT:           ParmVarDecl {{.*}} 'iterator'
-// CHECK-NEXT:               LifetimeCaptureByAttr {{.*}} Implicit
+// CHECK-NOT:               LifetimeCaptureByAttr {{.*}} Implicit
 // CHECK-NEXT:           ParmVarDecl {{.*}} 'int *&&'
 // CHECK-NEXT:               LifetimeCaptureByAttr {{.*}} Implicit
 
@@ -100,6 +100,6 @@ std::vector<int> ints;
 
 // CHECK:       CXXMethodDecl {{.*}} insert 'void (iterator, int &&)'
 // CHECK-NEXT:           ParmVarDecl {{.*}} 'iterator'
-// CHECK-NEXT:               LifetimeCaptureByAttr {{.*}} Implicit
+// CHECK-NOT:               LifetimeCaptureByAttr {{.*}} Implicit
 // CHECK-NEXT:           ParmVarDecl {{.*}} 'int &&'
 // CHECK-NOT:   LifetimeCaptureByAttr

>From 5abab4968b689f3e91e30ced4174c7819ebffeae Mon Sep 17 00:00:00 2001
From: Haojian Wu <hokein.wu at gmail.com>
Date: Fri, 29 Nov 2024 09:14:31 +0100
Subject: [PATCH 3/3] Address review comments.

---
 clang/test/AST/attr-lifetime-capture-by.cpp | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/clang/test/AST/attr-lifetime-capture-by.cpp b/clang/test/AST/attr-lifetime-capture-by.cpp
index 2a568b0f00d3ae..debad9b7204d72 100644
--- a/clang/test/AST/attr-lifetime-capture-by.cpp
+++ b/clang/test/AST/attr-lifetime-capture-by.cpp
@@ -48,7 +48,6 @@ std::vector<View> views;
 
 // CHECK:       CXXMethodDecl {{.*}} insert 'void (iterator, View &&)'
 // CHECK-NEXT:           ParmVarDecl {{.*}} 'iterator'
-// CHECK-NOT:               LifetimeCaptureByAttr {{.*}} Implicit
 // CHECK-NEXT:           ParmVarDecl {{.*}} 'View &&'
 // CHECK-NEXT:               LifetimeCaptureByAttr {{.*}} Implicit
 
@@ -67,7 +66,6 @@ std::vector<ViewTemplate<int>> templated_views;
 
 // CHECK:       CXXMethodDecl {{.*}} insert 'void (iterator, ViewTemplate<int> &&)'
 // CHECK-NEXT:           ParmVarDecl {{.*}} 'iterator'
-// CHECK-NOT:               LifetimeCaptureByAttr {{.*}} Implicit
 // CHECK-NEXT:           ParmVarDecl {{.*}} 'ViewTemplate<int> &&'
 // CHECK-NEXT:               LifetimeCaptureByAttr {{.*}} Implicit
 
@@ -84,7 +82,6 @@ std::vector<int*> pointers;
 
 // CHECK:       CXXMethodDecl {{.*}} insert 'void (iterator, int *&&)'
 // CHECK-NEXT:           ParmVarDecl {{.*}} 'iterator'
-// CHECK-NOT:               LifetimeCaptureByAttr {{.*}} Implicit
 // CHECK-NEXT:           ParmVarDecl {{.*}} 'int *&&'
 // CHECK-NEXT:               LifetimeCaptureByAttr {{.*}} Implicit
 
@@ -100,6 +97,5 @@ std::vector<int> ints;
 
 // CHECK:       CXXMethodDecl {{.*}} insert 'void (iterator, int &&)'
 // CHECK-NEXT:           ParmVarDecl {{.*}} 'iterator'
-// CHECK-NOT:               LifetimeCaptureByAttr {{.*}} Implicit
 // CHECK-NEXT:           ParmVarDecl {{.*}} 'int &&'
 // CHECK-NOT:   LifetimeCaptureByAttr



More information about the cfe-commits mailing list