[clang] use-after-scope through fields (PR #191865)
Utkarsh Saxena via cfe-commits
cfe-commits at lists.llvm.org
Thu Apr 16 00:55:36 PDT 2026
https://github.com/usx95 updated https://github.com/llvm/llvm-project/pull/191865
>From 957197623e0d2fc62c06183ea090ebd1459d4d71 Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena <usx at google.com>
Date: Mon, 13 Apr 2026 18:13:49 +0000
Subject: [PATCH] use-after-scope through fields
---
.../LifetimeSafety/FactsGenerator.cpp | 1 +
clang/lib/Analysis/LifetimeSafety/Origins.cpp | 2 +-
.../warn-lifetime-safety-dangling-field.cpp | 24 +++++++++----------
clang/test/Sema/warn-lifetime-safety.cpp | 9 +++----
4 files changed, 19 insertions(+), 17 deletions(-)
diff --git a/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp b/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp
index 5adf842e5f6d0..55d1961ff8e7f 100644
--- a/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp
@@ -259,6 +259,7 @@ void FactsGenerator::VisitMemberExpr(const MemberExpr *ME) {
assert(Dst && "Field member should have an origin list as it is GL value");
OriginList *Src = getOriginsList(*ME->getBase());
assert(Src && "Base expression should be a pointer/reference type");
+ handleUse(ME);
// The field's glvalue (outermost origin) holds the same loans as the base
// expression.
CurrentBlockFacts.push_back(FactMgr.createFact<OriginFlowFact>(
diff --git a/clang/lib/Analysis/LifetimeSafety/Origins.cpp b/clang/lib/Analysis/LifetimeSafety/Origins.cpp
index 033cbdd75352c..505ae5146d5ba 100644
--- a/clang/lib/Analysis/LifetimeSafety/Origins.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/Origins.cpp
@@ -240,7 +240,7 @@ OriginList *OriginManager::getOrCreateList(const Expr *E) {
ReferencedDecl = DRE->getDecl();
else if (auto *ME = dyn_cast<MemberExpr>(E))
if (auto *Field = dyn_cast<FieldDecl>(ME->getMemberDecl());
- Field && isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
+ Field && isa<CXXThisExpr>(ME->getBase()->IgnoreImpCasts()))
ReferencedDecl = Field;
if (ReferencedDecl) {
OriginList *Head = nullptr;
diff --git a/clang/test/Sema/warn-lifetime-safety-dangling-field.cpp b/clang/test/Sema/warn-lifetime-safety-dangling-field.cpp
index 2afcd4a3dd97b..cecb0f795518f 100644
--- a/clang/test/Sema/warn-lifetime-safety-dangling-field.cpp
+++ b/clang/test/Sema/warn-lifetime-safety-dangling-field.cpp
@@ -76,8 +76,8 @@ struct CtorPointerField {
};
struct MemberSetters {
- std::string_view view; // expected-note 6 {{this field dangles}}
- const char* p; // expected-note 6 {{this field dangles}}
+ std::string_view view; // expected-note 5 {{this field dangles}}
+ const char* p; // expected-note 5 {{this field dangles}}
void setWithParam(std::string s) {
view = s; // expected-warning {{address of stack memory escapes to a field}}
@@ -140,21 +140,21 @@ struct MemberSetters {
void use_after_scope() {
{
std::string local;
- view = local; // expected-warning {{address of stack memory escapes to a field}}
- p = local.data(); // expected-warning {{address of stack memory escapes to a field}}
- }
- (void)view;
- (void)p;
+ view = local; // expected-warning {{object whose reference is captured does not live long enough}}
+ p = local.data(); // expected-warning {{object whose reference is captured does not live long enough}}
+ } // expected-note 2 {{destroyed here}}
+ (void)view; // expected-note {{later used here}}
+ (void)p; // expected-note {{later used here}}
}
void use_after_scope_saved_after_reassignment() {
{
std::string local;
- view = local;
- p = local.data();
- }
- (void)view;
- (void)p;
+ view = local; // expected-warning {{object whose reference is captured does not live long enough}}
+ p = local.data(); // expected-warning {{object whose reference is captured does not live long enough}}
+ } // expected-note 2 {{destroyed here}}
+ (void)view; // expected-note {{later used here}}
+ (void)p; // expected-note {{later used here}}
view = kGlobal;
p = kGlobal.data();
diff --git a/clang/test/Sema/warn-lifetime-safety.cpp b/clang/test/Sema/warn-lifetime-safety.cpp
index 082db5d5cbf15..68af1d4451f68 100644
--- a/clang/test/Sema/warn-lifetime-safety.cpp
+++ b/clang/test/Sema/warn-lifetime-safety.cpp
@@ -2634,15 +2634,16 @@ struct Holder {
} // namespace CXXDefaultInitExprTests
namespace base_class_fields {
-struct X { int* x; }; // expected-note {{this field dangles}}
+struct X { int* x; };
struct Y : X {
int* y;
void bar() {
{
int a;
- x = &a; // expected-warning {{address of stack memory escapes to a field}}
- }
- (void)x;
+ x = &a; // expected-warning {{object whose reference is captured does not live long enough}}
+ } // expected-note {{destroyed here}}
+ (void)x; // expected-note {{later used here}}
+ x = nullptr;
}
};
} // namespace base_class_fields
More information about the cfe-commits
mailing list