[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