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 <[email protected]>
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@-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@-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

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to