[llvm-branch-commits] [clang] Handle non-trivial view types of temporaries (PR #177878)
Utkarsh Saxena via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Tue Jan 27 03:47:33 PST 2026
https://github.com/usx95 updated https://github.com/llvm/llvm-project/pull/177878
>From 229a2fb6e951c8e2674a3136b2af939434340ad1 Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena <usx at google.com>
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 98fadaa11137f..c85bcf6775e98 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 c80556715fedf..01e10ca5aa2b6 100644
--- a/clang/test/Sema/warn-lifetime-safety.cpp
+++ b/clang/test/Sema/warn-lifetime-safety.cpp
@@ -1691,3 +1691,26 @@ void test() {
}
} // namespace attr_on_template_params
+
+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
More information about the llvm-branch-commits
mailing list