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

via cfe-commits cfe-commits at lists.llvm.org
Sun Oct 4 23:03:52 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang-analysis

Author: Zeyi Xu (zeyi2)

<details>
<summary>Changes</summary>

`isInstance()` is also true for explicit object member functions, but their object argument binds to a real parameter, so arguments and parameters line up one-to-one. This commit fixes the problem by using `isImplicitObjectMemberFunction()`.

---
Full diff: https://github.com/llvm/llvm-project/pull/228979.diff


2 Files Affected:

- (modified) clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp (+6-4) 
- (modified) clang/test/Sema/LifetimeSafety/explicit-object-param-no-crash.cpp (+17) 


``````````diff
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}}
+}

``````````

</details>


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


More information about the cfe-commits mailing list