https://github.com/usx95 created 
https://github.com/llvm/llvm-project/pull/177878

None

>From c1f904456718865ccbfed37052cf030d30bbbddc Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena <[email protected]>
Date: Sat, 24 Jan 2026 20:02:17 +0000
Subject: [PATCH] Handle non-trivial view types of temporaries

---
 .../Analyses/LifetimeSafety/FactsGenerator.h  |  1 +
 .../LifetimeSafety/FactsGenerator.cpp         | 13 ++++++++++-
 clang/test/Sema/warn-lifetime-safety.cpp      | 23 +++++++++++++++++++
 3 files changed, 36 insertions(+), 1 deletion(-)

diff --git 
a/clang/include/clang/Analysis/Analyses/LifetimeSafety/FactsGenerator.h 
b/clang/include/clang/Analysis/Analyses/LifetimeSafety/FactsGenerator.h
index e4487b0d1dbc7..8b45337bee218 100644
--- a/clang/include/clang/Analysis/Analyses/LifetimeSafety/FactsGenerator.h
+++ b/clang/include/clang/Analysis/Analyses/LifetimeSafety/FactsGenerator.h
@@ -48,6 +48,7 @@ class FactsGenerator : public 
ConstStmtVisitor<FactsGenerator> {
   void VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *OCE);
   void VisitCXXFunctionalCastExpr(const CXXFunctionalCastExpr *FCE);
   void VisitInitListExpr(const InitListExpr *ILE);
+  void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *BTE);
   void VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *MTE);
 
 private:
diff --git a/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp 
b/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp
index d1875ef8edb44..f1d7656e15ca8 100644
--- a/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp
@@ -418,12 +418,23 @@ void FactsGenerator::VisitInitListExpr(const InitListExpr 
*ILE) {
     killAndFlowOrigin(*ILE, *ILE->getInit(0));
 }
 
+void FactsGenerator::VisitCXXBindTemporaryExpr(
+    const CXXBindTemporaryExpr *BTE) {
+  killAndFlowOrigin(*BTE, *BTE->getSubExpr());
+}
+
 void FactsGenerator::VisitMaterializeTemporaryExpr(
     const MaterializeTemporaryExpr *MTE) {
   assert(MTE->isGLValue());
   // We defer from handling lifetime extended materializations.
-  if (MTE->getStorageDuration() != SD_FullExpression)
+  if (MTE->getStorageDuration() != SD_FullExpression) {
+    assert(MTE->getLifetimeExtendedTemporaryDecl());
+    OriginList *MTEList = getOriginsList(*MTE);
+    assert(MTEList && "Lifetime-extended MTE should have an origin list");
+    OriginList *SubExprList = getOriginsList(*MTE->getSubExpr());
+    flow(MTEList->peelOuterOrigin(), SubExprList, /*Kill=*/true);
     return;
+  }
   OriginList *MTEList = getOriginsList(*MTE);
   if (!MTEList)
     return;
diff --git a/clang/test/Sema/warn-lifetime-safety.cpp 
b/clang/test/Sema/warn-lifetime-safety.cpp
index a3ff4cd99288b..537a1909f2afe 100644
--- a/clang/test/Sema/warn-lifetime-safety.cpp
+++ b/clang/test/Sema/warn-lifetime-safety.cpp
@@ -1575,3 +1575,26 @@ 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 non_trivial_views {
+struct [[gsl::Pointer]] View {
+    View(const std::string&);
+    ~View(); // Forces a CXXBindTemporaryExpr.
+};
+
+View test1(std::string a) {
+  // Make sure we handle CXXBindTemporaryExpr of view types.
+  return View(a); // expected-warning {{address of stack memory is returned 
later}} expected-note {{returned here}}
+}
+
+View test2(std::string a) {
+  View b = View(a); // expected-warning {{address of stack memory is returned 
later}}
+  return b;  // expected-note {{returned here}}
+}
+
+View test3(std::string a) {
+  const View& b = View(a); // expected-warning {{address of stack memory is 
returned later}}
+  return b;  // expected-note {{returned here}}
+}
+
+} // namespace non_trivial_views

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

Reply via email to