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
