[clang] [LifetimeSafety] Fix capture_by argument mapping for explicit object params (PR #228979)

Zeyi Xu via cfe-commits cfe-commits at lists.llvm.org
Sun Oct 4 22:53:58 PDT 2026


https://github.com/zeyi2 created https://github.com/llvm/llvm-project/pull/228979

None

>From c8aa9e478f232948319a915badd9345e3df88603 Mon Sep 17 00:00:00 2001
From: Zeyi Xu <mitchell.xu2 at gmail.com>
Date: Mon, 5 Oct 2026 13:53:39 +0800
Subject: [PATCH] [LifetimeSafety] Fix capture_by argument mapping for explicit
 object params

---
 .../Analysis/LifetimeSafety/FactsGenerator.cpp  | 10 ++++++----
 .../explicit-object-param-no-crash.cpp          | 17 +++++++++++++++++
 2 files changed, 23 insertions(+), 4 deletions(-)

diff --git a/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp b/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp
index 2457b8270cb80..d1113783ab882 100644
--- a/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp
@@ -1008,10 +1008,12 @@ void FactsGenerator::handleLifetimeCaptureBy(const FunctionDecl *FD,
   if (isa<CXXConstructorDecl>(FD))
     return;
   const auto *Method = dyn_cast<CXXMethodDecl>(FD);
-  bool IsInstance =
-      Method && Method->isInstance() && !isa<CXXConstructorDecl>(FD);
-  auto getParamDeclAt = [FD, IsInstance](unsigned I) -> const ParmVarDecl * {
-    if (IsInstance) {
+  bool HasImplicitObjectArg = Method &&
+                              Method->isImplicitObjectMemberFunction() &&
+                              !isa<CXXConstructorDecl>(FD);
+  auto getParamDeclAt =
+      [FD, HasImplicitObjectArg](unsigned I) -> const ParmVarDecl * {
+    if (HasImplicitObjectArg) {
       // FIXME: Add support for I == 0 i.e. capture_by on function declarations
       if (I > 0 && I - 1 < FD->getNumParams())
         return FD->getParamDecl(I - 1);
diff --git a/clang/test/Sema/LifetimeSafety/explicit-object-param-no-crash.cpp b/clang/test/Sema/LifetimeSafety/explicit-object-param-no-crash.cpp
index 71c86b9f793fb..f755390d2a7b2 100644
--- a/clang/test/Sema/LifetimeSafety/explicit-object-param-no-crash.cpp
+++ b/clang/test/Sema/LifetimeSafety/explicit-object-param-no-crash.cpp
@@ -85,3 +85,20 @@ const int *t2(Holder h) {
   std::move(h).consume();
   return ptr; // expected-note {{returned here}}
 }
+
+struct Set {
+  void insert(this Set &self, const int &x [[clang::lifetime_capture_by(self)]],
+              const int &hint);
+};
+
+int global;
+
+void capture_by_explicit_object() {
+  Set s;
+  {
+    int local = 0;
+    s.insert(local, global); // expected-warning {{local variable 'local' does not live long enough}}
+    s.insert(global, local);
+  }                          // expected-note {{destroyed here}}
+  use(s);                    // expected-note {{later used here}}
+}



More information about the cfe-commits mailing list