[clang] [LifetimeSafety] Fix 'this' origin handling in lambdas (PR #182300)
Utkarsh Saxena via cfe-commits
cfe-commits at lists.llvm.org
Thu Feb 19 07:24:25 PST 2026
https://github.com/usx95 updated https://github.com/llvm/llvm-project/pull/182300
>From bca86f81fb4cbeac1876e7371d2e665dae0840b1 Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena <usx at google.com>
Date: Thu, 19 Feb 2026 14:50:25 +0000
Subject: [PATCH] lambda and captured this
---
.../Analysis/LifetimeSafety/FactsGenerator.cpp | 8 ++++----
clang/lib/Analysis/LifetimeSafety/Origins.cpp | 16 ++++++++++------
.../Sema/warn-lifetime-safety-suggestions.cpp | 10 ++++++++++
3 files changed, 24 insertions(+), 10 deletions(-)
diff --git a/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp b/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp
index 0b25a6a401e08..0b6e70212003c 100644
--- a/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp
@@ -711,10 +711,10 @@ llvm::SmallVector<Fact *> FactsGenerator::issuePlaceholderLoans() {
return {};
llvm::SmallVector<Fact *> PlaceholderLoanFacts;
- if (const auto *MD = dyn_cast<CXXMethodDecl>(FD); MD && MD->isInstance()) {
- OriginList *List = *FactMgr.getOriginMgr().getThisOrigins();
- const PlaceholderLoan *L =
- FactMgr.getLoanMgr().createLoan<PlaceholderLoan>(MD);
+ if (auto ThisOrigins = FactMgr.getOriginMgr().getThisOrigins()) {
+ OriginList *List = *ThisOrigins;
+ const PlaceholderLoan *L = FactMgr.getLoanMgr().createLoan<PlaceholderLoan>(
+ cast<CXXMethodDecl>(FD));
PlaceholderLoanFacts.push_back(
FactMgr.createFact<IssueFact>(L->getID(), List->getOuterOriginID()));
}
diff --git a/clang/lib/Analysis/LifetimeSafety/Origins.cpp b/clang/lib/Analysis/LifetimeSafety/Origins.cpp
index 9141859a81345..88ae559b3d863 100644
--- a/clang/lib/Analysis/LifetimeSafety/Origins.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/Origins.cpp
@@ -88,9 +88,15 @@ bool doesDeclHaveStorage(const ValueDecl *D) {
}
OriginManager::OriginManager(ASTContext &AST, const Decl *D) : AST(AST) {
- if (const auto *MD = llvm::dyn_cast_or_null<CXXMethodDecl>(D);
- MD && MD->isInstance())
- ThisOrigins = buildListForType(MD->getThisType(), MD);
+ // Create OriginList for 'this' expr.
+ const auto *MD = llvm::dyn_cast_or_null<CXXMethodDecl>(D);
+ if (!MD || !MD->isInstance())
+ return;
+ // Lambda's can capture 'this' from surrounding context but it does not refer
+ // to the lambda object.
+ if (const CXXRecordDecl *P = MD->getParent(); P && P->isLambda())
+ return;
+ ThisOrigins = buildListForType(MD->getThisType(), MD);
}
OriginList *OriginManager::createNode(const ValueDecl *D, QualType QT) {
@@ -146,10 +152,8 @@ OriginList *OriginManager::getOrCreateList(const Expr *E) {
QualType Type = E->getType();
// Special handling for 'this' expressions to share origins with the method's
// implicit object parameter.
- if (llvm::isa<CXXThisExpr>(E)) {
- assert(ThisOrigins && "origins for 'this' should be set for a method decl");
+ if (isa<CXXThisExpr>(E) && ThisOrigins)
return *ThisOrigins;
- }
// Special handling for expressions referring to a decl to share origins with
// the underlying decl.
diff --git a/clang/test/Sema/warn-lifetime-safety-suggestions.cpp b/clang/test/Sema/warn-lifetime-safety-suggestions.cpp
index 1887b2f257226..4bd8a717d9d30 100644
--- a/clang/test/Sema/warn-lifetime-safety-suggestions.cpp
+++ b/clang/test/Sema/warn-lifetime-safety-suggestions.cpp
@@ -393,3 +393,13 @@ View Reassigned(View a) {
a = Global;
return a;
}
+
+struct NoSuggestionForThisCapturedByLambda {
+ MyObj s;
+ bool cond;
+ void foo() {
+ auto x = [&]() {
+ return cond > 0 ? &this->s : &s;
+ };
+ }
+};
More information about the cfe-commits
mailing list