[clang] [Lifetime] Track CXXBindTemporaryExpr in facts generation (PR #178218)
Baranov Victor via cfe-commits
cfe-commits at lists.llvm.org
Tue Jan 27 06:51:18 PST 2026
https://github.com/vbvictor created https://github.com/llvm/llvm-project/pull/178218
Closes https://github.com/llvm/llvm-project/issues/177802.
>From 24c3c8357b8dcd4d829d36cea5a10e789b0e21eb Mon Sep 17 00:00:00 2001
From: Victor Baranov <bar.victor.2002 at gmail.com>
Date: Tue, 27 Jan 2026 17:50:18 +0300
Subject: [PATCH] [Lifetime] Track CXXBindTemporaryExpr in facts generation
---
.../Analyses/LifetimeSafety/FactsGenerator.h | 1 +
.../LifetimeSafety/FactsGenerator.cpp | 6 +++
clang/test/Sema/warn-lifetime-safety.cpp | 50 +++++++++++++++++++
3 files changed, 57 insertions(+)
diff --git a/clang/include/clang/Analysis/Analyses/LifetimeSafety/FactsGenerator.h b/clang/include/clang/Analysis/Analyses/LifetimeSafety/FactsGenerator.h
index a47505ee9f159..0d619d31f251b 100644
--- a/clang/include/clang/Analysis/Analyses/LifetimeSafety/FactsGenerator.h
+++ b/clang/include/clang/Analysis/Analyses/LifetimeSafety/FactsGenerator.h
@@ -49,6 +49,7 @@ class FactsGenerator : public ConstStmtVisitor<FactsGenerator> {
void VisitCXXFunctionalCastExpr(const CXXFunctionalCastExpr *FCE);
void VisitInitListExpr(const InitListExpr *ILE);
void VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *MTE);
+ void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *BTE);
private:
OriginList *getOriginsList(const ValueDecl &D);
diff --git a/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp b/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp
index c982b255d54ea..06fec43172732 100644
--- a/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp
@@ -417,6 +417,12 @@ void FactsGenerator::VisitMaterializeTemporaryExpr(
flow(MTEList, SubExprList, /*Kill=*/true);
}
+void FactsGenerator::VisitCXXBindTemporaryExpr(
+ const CXXBindTemporaryExpr *BTE) {
+ if (hasOrigins(BTE))
+ killAndFlowOrigin(*BTE, *BTE->getSubExpr());
+}
+
void FactsGenerator::handleLifetimeEnds(const CFGLifetimeEnds &LifetimeEnds) {
/// TODO: Handle loans to temporaries.
const VarDecl *LifetimeEndsVD = LifetimeEnds.getVarDecl();
diff --git a/clang/test/Sema/warn-lifetime-safety.cpp b/clang/test/Sema/warn-lifetime-safety.cpp
index a3ff4cd99288b..93181b052ee6c 100644
--- a/clang/test/Sema/warn-lifetime-safety.cpp
+++ b/clang/test/Sema/warn-lifetime-safety.cpp
@@ -27,6 +27,13 @@ struct [[gsl::Pointer()]] View {
void use() const;
};
+struct [[gsl::Pointer]] ViewWithDtor {
+ ViewWithDtor(const MyObj&);
+ ViewWithDtor();
+ ~ViewWithDtor();
+ void use() const;
+};
+
class TriviallyDestructedClass {
View a, b;
};
@@ -1575,3 +1582,46 @@ std::string_view& refViewMemberReturnView2(RefMember a) { return a.view; } // ex
std::string_view refViewMemberReturnRefView1(RefMember a) { return a.view_ref; }
std::string_view& refViewMemberReturnRefView2(RefMember a) { return a.view_ref; }
} // namespace field_access
+
+namespace nontrivial_view_types {
+
+ViewWithDtor return_view_from_param(MyObj a) {
+ return ViewWithDtor(a); // expected-warning {{address of stack memory is returned later}}
+} // expected-note at -1 {{returned here}}
+
+ViewWithDtor return_view_via_local(MyObj a) {
+ auto v = ViewWithDtor(a); // expected-warning {{address of stack memory is returned later}}
+ return v; // expected-note {{returned here}}
+}
+
+void uaf_nontrivial_view() {
+ ViewWithDtor v = ViewWithDtor(MyObj{}); // expected-warning {{does not live long enough}}
+ v.use(); // expected-note {{later used here}}
+} // expected-note at -2 {{destroyed here}}
+
+void chain_nontrivial_view() {
+ ViewWithDtor v1, v2;
+ {
+ MyObj obj;
+ v1 = ViewWithDtor(obj); // expected-warning {{does not live long enough}}
+ v2 = v1;
+ } // expected-note {{destroyed here}}
+ v2.use(); // expected-note {{later used here}}
+}
+
+void safe_nontrivial_view() {
+ MyObj obj;
+ ViewWithDtor v = ViewWithDtor(obj);
+ v.use();
+}
+
+void assign_nontrivial_view() {
+ ViewWithDtor v;
+ {
+ MyObj obj;
+ v = ViewWithDtor(obj); // expected-warning {{does not live long enough}}
+ } // expected-note {{destroyed here}}
+ v.use(); // expected-note {{later used here}}
+}
+
+} // namespace nontrivial_view_types
More information about the cfe-commits
mailing list