[clang] [LifetimeSafety] Add details for `-Wlifetime-safety-return-stack-addr` diagnostic (PR #199432)
via cfe-commits
cfe-commits at lists.llvm.org
Sun May 24 09:21:26 PDT 2026
https://github.com/NeKon69 updated https://github.com/llvm/llvm-project/pull/199432
>From f09e32af0f00fc0fe0e0df8834befe8244ab85d1 Mon Sep 17 00:00:00 2001
From: NeKon69 <nobodqwe at gmail.com>
Date: Sun, 24 May 2026 19:08:42 +0300
Subject: [PATCH 1/2] [LifetimeSafety] Add details for
-Wlifetime-safety-return-stack-addr diagnostic
---
.../Analyses/LifetimeSafety/LifetimeSafety.h | 9 +-
.../clang/Basic/DiagnosticSemaKinds.td | 31 ++-
clang/lib/Analysis/LifetimeSafety/Checker.cpp | 19 +-
clang/lib/Sema/SemaLifetimeSafety.h | 30 ++-
.../Sema/warn-lifetime-analysis-nocfg.cpp | 88 ++++----
.../Sema/warn-lifetime-safety-suggestions.cpp | 24 +-
clang/test/Sema/warn-lifetime-safety.cpp | 212 +++++++++---------
7 files changed, 230 insertions(+), 183 deletions(-)
diff --git a/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h b/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h
index ec9f83748ad8d..895d64713f2da 100644
--- a/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h
+++ b/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h
@@ -65,10 +65,13 @@ class LifetimeSafetySemaHelper {
const Expr *MovedExpr,
SourceLocation FreeLoc) {}
- virtual void reportUseAfterReturn(const Expr *IssueExpr,
+ virtual void reportUseAfterReturn(const ValueDecl *VD, const Expr *IssueExpr,
const Expr *ReturnExpr,
- const Expr *MovedExpr,
- SourceLocation ExpiryLoc) {}
+ const Expr *MovedExpr, bool IsReference) {}
+
+ virtual void reportUseAfterReturn(const MaterializeTemporaryExpr *MTE,
+ const Expr *ReturnExpr,
+ const Expr *MovedExpr, bool IsReference) {}
virtual void reportDanglingField(const Expr *IssueExpr,
const FieldDecl *Field,
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index dbe6cb2c3a41c..de0efde20a642 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -10967,16 +10967,27 @@ def warn_lifetime_safety_use_after_free : Warning<
"%select{allocated object|parameter}0 does not live long enough">,
InGroup<LifetimeSafetyUseAfterFree>, DefaultIgnore;
-def warn_lifetime_safety_return_stack_addr
- : Warning<"address of stack memory is returned later">,
- InGroup<LifetimeSafetyReturnStackAddr>,
- DefaultIgnore;
-def warn_lifetime_safety_return_stack_addr_moved
- : Warning<"address of stack memory may be returned later. "
- "This could be false positive as the storage may have been moved. "
- "Consider moving first and then aliasing later to resolve the issue">,
- InGroup<LifetimeSafetyReturnStackAddrMoved>,
- DefaultIgnore;
+def warn_lifetime_safety_return_stack_addr : Warning<
+ "%select{address of|reference to}0 stack memory associated with "
+ "%select{local variable|parameter}2 %1 returned">,
+ InGroup<LifetimeSafetyReturnStackAddr>, DefaultIgnore;
+
+def warn_lifetime_safety_return_temp_stack_addr : Warning<
+ "returning %select{address of|reference to}0 local temporary object">,
+ InGroup<LifetimeSafetyReturnStackAddr>, DefaultIgnore;
+
+def warn_lifetime_safety_return_temp_stack_addr_moved : Warning<
+ "returning %select{address of|reference to}0 local temporary object. "
+ "This could be a false positive as the storage may have been moved. "
+ "Consider moving first and then aliasing later to resolve the issue">,
+ InGroup<LifetimeSafetyReturnStackAddrMoved>, DefaultIgnore;
+
+def warn_lifetime_safety_return_stack_addr_moved : Warning<
+ "%select{address of|reference to}0 stack memory associated with "
+ "%select{local variable|parameter}2 %1 may be returned later. "
+ "This could be a false positive as the storage may have been moved. "
+ "Consider moving first and then aliasing later to resolve the issue">,
+ InGroup<LifetimeSafetyReturnStackAddrMoved>, DefaultIgnore;
def warn_lifetime_safety_invalidation
: Warning<"%select{object whose reference is captured|parameter}0 is later invalidated">,
diff --git a/clang/lib/Analysis/LifetimeSafety/Checker.cpp b/clang/lib/Analysis/LifetimeSafety/Checker.cpp
index d6a15139aa4ea..2a7b28afb0c9f 100644
--- a/clang/lib/Analysis/LifetimeSafety/Checker.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/Checker.cpp
@@ -297,11 +297,22 @@ class LifetimeChecker {
// FIXME: Diagnose invalidated return escapes separately.
} else
llvm_unreachable("Unhandled OriginEscapesFact type");
- } else if (const auto *RetEscape = dyn_cast<ReturnEscapeFact>(OEF))
+ } else if (const auto *RetEscape = dyn_cast<ReturnEscapeFact>(OEF)) {
// Return stack address.
- SemaHelper->reportUseAfterReturn(
- IssueExpr, RetEscape->getReturnExpr(), MovedExpr, ExpiryLoc);
- else if (const auto *FieldEscape = dyn_cast<FieldEscapeFact>(OEF))
+ const AccessPath &Path = L->getAccessPath();
+ bool IsReference =
+ cast<FunctionDecl>(FD)->getReturnType()->isReferenceType();
+ if (const auto *VD = Path.getAsValueDecl())
+ SemaHelper->reportUseAfterReturn(VD, IssueExpr,
+ RetEscape->getReturnExpr(),
+ MovedExpr, IsReference);
+ else if (const auto *MTE = Path.getAsMaterializeTemporaryExpr())
+ SemaHelper->reportUseAfterReturn(MTE, RetEscape->getReturnExpr(),
+ MovedExpr, IsReference);
+ else
+ llvm_unreachable(
+ "unexpected loan kind for return stack address warning");
+ } else if (const auto *FieldEscape = dyn_cast<FieldEscapeFact>(OEF))
// Dangling field.
SemaHelper->reportDanglingField(
IssueExpr, FieldEscape->getFieldDecl(), MovedExpr, ExpiryLoc);
diff --git a/clang/lib/Sema/SemaLifetimeSafety.h b/clang/lib/Sema/SemaLifetimeSafety.h
index af5202c33fed0..6bd78f79da802 100644
--- a/clang/lib/Sema/SemaLifetimeSafety.h
+++ b/clang/lib/Sema/SemaLifetimeSafety.h
@@ -74,12 +74,16 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper {
<< UseExpr->getSourceRange();
}
- void reportUseAfterReturn(const Expr *IssueExpr, const Expr *ReturnExpr,
+ void reportUseAfterReturn(const ValueDecl *VD, const Expr *IssueExpr,
+ const Expr *ReturnExpr,
const Expr *MovedExpr,
- SourceLocation ExpiryLoc) override {
- S.Diag(IssueExpr->getExprLoc(),
- MovedExpr ? diag::warn_lifetime_safety_return_stack_addr_moved
- : diag::warn_lifetime_safety_return_stack_addr)
+ bool IsReference) override {
+ unsigned DiagID = MovedExpr
+ ? diag::warn_lifetime_safety_return_stack_addr_moved
+ : diag::warn_lifetime_safety_return_stack_addr;
+
+ S.Diag(IssueExpr->getExprLoc(), DiagID)
+ << IsReference << VD << isa<ParmVarDecl>(VD)
<< IssueExpr->getSourceRange();
if (MovedExpr)
S.Diag(MovedExpr->getExprLoc(), diag::note_lifetime_safety_moved_here)
@@ -88,6 +92,22 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper {
<< ReturnExpr->getSourceRange();
}
+ void reportUseAfterReturn(const MaterializeTemporaryExpr *MTE,
+ const Expr *ReturnExpr,
+ const Expr *MovedExpr,
+ bool IsReference) override {
+ unsigned DiagID =
+ MovedExpr ? diag::warn_lifetime_safety_return_temp_stack_addr_moved
+ : diag::warn_lifetime_safety_return_temp_stack_addr;
+
+ S.Diag(MTE->getExprLoc(), DiagID) << IsReference << MTE->getSourceRange();
+ if (MovedExpr)
+ S.Diag(MovedExpr->getExprLoc(), diag::note_lifetime_safety_moved_here)
+ << MovedExpr->getSourceRange();
+ S.Diag(ReturnExpr->getExprLoc(), diag::note_lifetime_safety_returned_here)
+ << ReturnExpr->getSourceRange();
+ }
+
void reportDanglingField(const Expr *IssueExpr,
const FieldDecl *DanglingField,
const Expr *MovedExpr,
diff --git a/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp b/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp
index 00d45caae3b09..73a16f8184368 100644
--- a/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp
+++ b/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp
@@ -98,7 +98,7 @@ struct DanglingGslPtrField {
MyIntPointer danglingGslPtrFromLocal() {
int j;
// Detected only by CFG analysis.
- return &j; // cfg-warning {{address of stack memory is returned later}} cfg-note {{returned here}}
+ return &j; // cfg-warning {{address of stack memory associated with local variable 'j' returned}} cfg-note {{returned here}}
}
MyIntPointer returningLocalPointer() {
@@ -109,30 +109,30 @@ MyIntPointer returningLocalPointer() {
MyIntPointer daglingGslPtrFromLocalOwner() {
MyIntOwner localOwner;
return localOwner; // expected-warning {{address of stack memory associated with local variable 'localOwner' returned}} \
- // cfg-warning {{address of stack memory is returned later}} cfg-note {{returned here}}
+ // cfg-warning {{address of stack memory associated with local variable 'localOwner' returned}} cfg-note {{returned here}}
}
MyLongPointerFromConversion daglingGslPtrFromLocalOwnerConv() {
MyLongOwnerWithConversion localOwner;
return localOwner; // expected-warning {{address of stack memory associated with local variable 'localOwner' returned}} \
- // cfg-warning {{address of stack memory is returned later}} cfg-note {{returned here}}
+ // cfg-warning {{address of stack memory associated with local variable 'localOwner' returned}} cfg-note {{returned here}}
}
MyIntPointer danglingGslPtrFromTemporary() {
return MyIntOwner{}; // expected-warning {{returning address of local temporary object}} \
- // cfg-warning {{address of stack memory is returned later}} cfg-note {{returned here}}
+ // cfg-warning {{returning address of local temporary object}} cfg-note {{returned here}}
}
MyIntOwner makeTempOwner();
MyIntPointer danglingGslPtrFromTemporary2() {
return makeTempOwner(); // expected-warning {{returning address of local temporary object}} \
- // cfg-warning {{address of stack memory is returned later}} cfg-note {{returned here}}
+ // cfg-warning {{returning address of local temporary object}} cfg-note {{returned here}}
}
MyLongPointerFromConversion danglingGslPtrFromTemporaryConv() {
return MyLongOwnerWithConversion{}; // expected-warning {{returning address of local temporary object}} \
- // cfg-warning {{address of stack memory is returned later}} cfg-note {{returned here}}
+ // cfg-warning {{returning address of local temporary object}} cfg-note {{returned here}}
}
int *noFalsePositive(MyIntOwner &o) {
@@ -180,7 +180,7 @@ struct LifetimeBoundCtor {
};
auto lifetimebound_make_unique_single_param() {
- return std::make_unique<LifetimeBoundCtor>(MyIntOwner{}); // tu-warning {{address of stack memory is returned later}} tu-note {{returned here}}
+ return std::make_unique<LifetimeBoundCtor>(MyIntOwner{}); // tu-warning {{returning address of local temporary object}} tu-note {{returned here}}
}
@@ -199,17 +199,17 @@ void modelIterators() {
std::vector<int>::iterator modelIteratorReturn() {
return std::vector<int>().begin(); // expected-warning {{returning address of local temporary object}} \
- // cfg-warning {{address of stack memory is returned later}} cfg-note {{returned here}}
+ // cfg-warning {{returning address of local temporary object}} cfg-note {{returned here}}
}
const int *modelFreeFunctions() {
return std::data(std::vector<int>()); // expected-warning {{returning address of local temporary object}} \
- // cfg-warning {{address of stack memory is returned later}} cfg-note {{returned here}}
+ // cfg-warning {{returning address of local temporary object}} cfg-note {{returned here}}
}
int &modelAnyCast() {
return std::any_cast<int&>(std::any{}); // expected-warning {{returning reference to local temporary object}} \
- // cfg-warning {{address of stack memory is returned later}} cfg-note {{returned here}}
+ // cfg-warning {{returning reference to local temporary object}} cfg-note {{returned here}}
}
int modelAnyCast2() {
@@ -223,19 +223,19 @@ int modelAnyCast3() {
const char *danglingRawPtrFromLocal() {
std::basic_string<char> s;
return s.c_str(); // expected-warning {{address of stack memory associated with local variable 's' returned}} \
- // cfg-warning {{address of stack memory is returned later}} cfg-note {{returned here}}
+ // cfg-warning {{address of stack memory associated with local variable 's' returned}} cfg-note {{returned here}}
}
int &danglingRawPtrFromLocal2() {
std::optional<int> o;
return o.value(); // expected-warning {{reference to stack memory associated with local variable 'o' returned}} \
- // cfg-warning {{address of stack memory is returned later}} cfg-note {{returned here}}
+ // cfg-warning {{reference to stack memory associated with local variable 'o' returned}} cfg-note {{returned here}}
}
int &danglingRawPtrFromLocal3() {
std::optional<int> o;
return *o; // expected-warning {{reference to stack memory associated with local variable 'o' returned}} \
- // cfg-warning {{address of stack memory is returned later}} cfg-note {{returned here}}
+ // cfg-warning {{reference to stack memory associated with local variable 'o' returned}} cfg-note {{returned here}}
}
// GH100384
@@ -254,14 +254,14 @@ std::string_view containerWithAnnotatedElements() {
std::vector<std::string> local;
return local.at(0); // expected-warning {{address of stack memory associated with local variable}} \
- // cfg-warning {{address of stack memory is returned later}} cfg-note {{returned here}}
+ // cfg-warning {{address of stack memory associated with local variable 'local' returned}} cfg-note {{returned here}}
}
std::string_view localUniquePtr(int i) {
std::unique_ptr<std::string> c1;
if (i)
return *c1; // expected-warning {{address of stack memory associated with local variable}} \
- // cfg-warning {{address of stack memory is returned later}} cfg-note {{returned here}}
+ // cfg-warning {{address of stack memory associated with local variable 'c1' returned}} cfg-note {{returned here}}
std::unique_ptr<std::string_view> c2;
return *c2; // expect no-warning.
}
@@ -270,38 +270,38 @@ std::string_view localOptional(int i) {
std::optional<std::string> o;
if (i)
return o.value(); // expected-warning {{address of stack memory associated with local variable}} \
- // cfg-warning {{address of stack memory is returned later}} cfg-note {{returned here}}
+ // cfg-warning {{address of stack memory associated with local variable 'o' returned}} cfg-note {{returned here}}
std::optional<std::string_view> abc;
return abc.value(); // expect no warning
}
const char *danglingRawPtrFromTemp() {
return std::basic_string<char>().c_str(); // expected-warning {{returning address of local temporary object}} \
- // cfg-warning {{address of stack memory is returned later}} cfg-note {{returned here}}
+ // cfg-warning {{returning address of local temporary object}} cfg-note {{returned here}}
}
std::unique_ptr<int> getUniquePtr();
int *danglingUniquePtrFromTemp() {
return getUniquePtr().get(); // expected-warning {{returning address of local temporary object}} \
- // cfg-warning {{address of stack memory is returned later}} cfg-note {{returned here}}
+ // cfg-warning {{returning address of local temporary object}} cfg-note {{returned here}}
}
int *danglingUniquePtrFromTemp2() {
return std::unique_ptr<int>().get(); // expected-warning {{returning address of local temporary object}} \
- // cfg-warning {{address of stack memory is returned later}} cfg-note {{returned here}}
+ // cfg-warning {{returning address of local temporary object}} cfg-note {{returned here}}
}
const int& danglingRefToOptionalFromTemp3() {
return std::optional<int>().value(); // expected-warning {{returning reference to local temporary object}} \
- // cfg-warning {{address of stack memory is returned later}} cfg-note {{returned here}}
+ // cfg-warning {{returning reference to local temporary object}} cfg-note {{returned here}}
}
std::optional<std::string> getTempOptStr();
std::string_view danglingRefToOptionalFromTemp4() {
return getTempOptStr().value(); // expected-warning {{returning address of local temporary object}} \
- // cfg-warning {{address of stack memory is returned later}} cfg-note {{returned here}}
+ // cfg-warning {{returning address of local temporary object}} cfg-note {{returned here}}
}
void danglingReferenceFromTempOwner() {
@@ -346,14 +346,14 @@ int &usedToBeFalsePositive(std::vector<int> &v) {
int &doNotFollowReferencesForLocalOwner() {
// Warning caught by CFG analysis.
std::unique_ptr<int> localOwner;
- int &p = *localOwner // cfg-warning {{address of stack memory is returned later}}
+ int &p = *localOwner // cfg-warning {{reference to stack memory associated with local variable 'localOwner' returned}}
.get();
return p; // cfg-note {{returned here}}
}
const char *trackThroughMultiplePointer() {
return std::basic_string_view<char>(std::basic_string<char>()).begin(); // expected-warning {{returning address of local temporary object}} \
- // cfg-warning {{address of stack memory is returned later}} cfg-note {{returned here}}
+ // cfg-warning {{returning address of local temporary object}} cfg-note {{returned here}}
}
struct X {
@@ -447,11 +447,11 @@ std::vector<std::string_view> GetTemporaryView();
std::string_view test_str_local() {
std::vector<std::string> v;
- return *std::find(v.begin(), // cfg-warning {{address of stack memory is returned later}} cfg-note {{returned here}}
+ return *std::find(v.begin(), // cfg-warning {{address of stack memory associated with local variable 'v' returned}} cfg-note {{returned here}}
v.end(), "42");
}
std::string_view test_str_temporary() {
- return *std::find(GetTemporaryString().begin(), // cfg-warning {{address of stack memory is returned later}} cfg-note {{returned here}}
+ return *std::find(GetTemporaryString().begin(), // cfg-warning {{returning address of local temporary object}} cfg-note {{returned here}}
GetTemporaryString().end(), "42");
}
std::string_view test_view() {
@@ -566,7 +566,7 @@ struct [[gsl::Pointer]] S {
S test(std::vector<int> a) {
return S(a); // expected-warning {{address of stack memory associated with}} \
- // cfg-warning {{address of stack memory is returned later}} cfg-note {{returned here}}
+ // cfg-warning {{address of stack memory associated with parameter 'a' returned}} cfg-note {{returned here}}
}
// FIXME: Detect this using the CFG-based lifetime analysis (global initialisation).
@@ -586,10 +586,10 @@ struct FooView {
FooView test3(int i, std::optional<Foo> a) {
if (i)
return *a; // expected-warning {{address of stack memory}} \
- // cfg-warning {{address of stack memory is returned later}} \
+ // cfg-warning {{address of stack memory associated with parameter 'a' returned}} \
// cfg-note {{returned here}}
return a.value(); // expected-warning {{address of stack memory}} \
- // cfg-warning {{address of stack memory is returned later}} \
+ // cfg-warning {{address of stack memory associated with parameter 'a' returned}} \
// cfg-note {{returned here}}
}
} // namespace GH93386
@@ -649,7 +649,7 @@ std::string_view test2() {
std::string_view bad = StatusOr<Wrapper2<std::string_view>>().value(); // expected-warning {{temporary whose address is used as value of}}
return k.value(); // expected-warning {{address of stack memory associated}} \
- // cfg-warning {{address of stack memory is returned later}} cfg-note {{returned here}}
+ // cfg-warning {{address of stack memory associated with local variable 'k' returned}} cfg-note {{returned here}}
}
} // namespace GH108272
@@ -781,7 +781,7 @@ Span<int*> test6(std::vector<int*> v) {
Span<int *> dangling = std::vector<int*>(); // expected-warning {{object backing the pointer}}
dangling = std::vector<int*>(); // expected-warning {{object backing the pointer}}
return v; // expected-warning {{address of stack memory}} \
- // cfg-warning {{address of stack memory is returned later}} cfg-note {{returned here}}
+ // cfg-warning {{address of stack memory associated with parameter 'v' returned}} cfg-note {{returned here}}
}
/////// From Owner<Owner<Pointer>> ///////
@@ -801,7 +801,7 @@ std::vector<int*> test8(StatusOr<std::vector<int*>> aa) {
// Pointer<Pointer> from Owner<Owner<Pointer>>
Span<int*> test9(StatusOr<std::vector<int*>> aa) {
return aa.valueLB(); // expected-warning {{address of stack memory associated}} \
- // cfg-warning {{address of stack memory is returned later}} cfg-note {{returned here}}
+ // cfg-warning {{address of stack memory associated with parameter 'aa' returned}} cfg-note {{returned here}}
return aa.valueNoLB(); // OK.
}
@@ -810,7 +810,7 @@ Span<int*> test9(StatusOr<std::vector<int*>> aa) {
// Pointer<Owner>> from Owner<Owner>
Span<std::string> test10(StatusOr<std::vector<std::string>> aa) {
return aa.valueLB(); // expected-warning {{address of stack memory}} \
- // cfg-warning {{address of stack memory is returned later}} cfg-note {{returned here}}
+ // cfg-warning {{address of stack memory associated with parameter 'aa' returned}} cfg-note {{returned here}}
return aa.valueNoLB(); // OK.
}
@@ -825,7 +825,7 @@ Span<std::string> test11(StatusOr<Span<std::string>> aa) {
// Lifetimebound and gsl::Pointer.
const int& test12(Span<int> a) {
return a.getFieldLB(); // expected-warning {{reference to stack memory associated}} \
- // cfg-warning {{address of stack memory is returned later}} cfg-note {{returned here}}
+ // cfg-warning {{reference to stack memory associated with parameter 'a' returned}} cfg-note {{returned here}}
return a.getFieldNoLB(); // OK.
}
@@ -865,7 +865,7 @@ std::string_view test1_1() {
// cfg-warning {{object whose reference is captured does not live long enough}} cfg-note {{destroyed here}}
use(t1); // cfg-note {{later used here}}
return Ref(std::string()); // expected-warning {{returning address}} \
- // cfg-warning {{address of stack memory is returned later}} cfg-note {{returned here}}
+ // cfg-warning {{returning address of local temporary object}} cfg-note {{returned here}}
}
std::string_view test1_2() {
@@ -877,7 +877,7 @@ std::string_view test1_2() {
use(t2); // cfg-note {{later used here}}
return TakeSv(std::string()); // expected-warning {{returning address}} \
- // cfg-warning {{address of stack memory is returned later}} cfg-note {{returned here}}
+ // cfg-warning {{returning address of local temporary object}} cfg-note {{returned here}}
}
std::string_view test1_3() {
@@ -888,7 +888,7 @@ std::string_view test1_3() {
// cfg-warning {{object whose reference is captured does not live long enough}} cfg-note {{destroyed here}}
use(t3); // cfg-note {{later used here}}
return TakeStrRef(std::string()); // expected-warning {{returning address}} \
- // cfg-warning {{address of stack memory is returned later}} cfg-note {{returned here}}
+ // cfg-warning {{returning address of local temporary object}} cfg-note {{returned here}}
}
std::string_view test1_4() {
@@ -913,7 +913,7 @@ std::string_view test2_1(Foo<std::string> r1, Foo<std::string_view> r2) {
// cfg-warning {{object whose reference is captured does not live long enough}} cfg-note {{destroyed here}}
use(t1); // cfg-note {{later used here}}
return r1.get(); // expected-warning {{address of stack}} \
- // cfg-warning {{address of stack memory is returned later}} cfg-note {{returned here}}
+ // cfg-warning {{address of stack memory associated with parameter 'r1' returned}} cfg-note {{returned here}}
}
std::string_view test2_2(Foo<std::string> r1, Foo<std::string_view> r2) {
std::string_view t2 = Foo<std::string_view>().get();
@@ -943,7 +943,7 @@ Pointer test3(Bar bar) {
use(p); // cfg-note {{later used here}}
p = Pointer(Bar()); // expected-warning {{object backing}} cfg-warning {{object whose reference is captured does not live long enough}} cfg-note {{destroyed here}}
use(p); // cfg-note {{later used here}}
- return bar; // expected-warning {{address of stack}} cfg-warning {{address of stack memory is returned later}} cfg-note {{returned here}}
+ return bar; // expected-warning {{address of stack}} cfg-warning {{address of stack memory associated with parameter 'bar' returned}} cfg-note {{returned here}}
}
template<typename T>
@@ -980,14 +980,14 @@ void test4() {
namespace range_based_for_loop_variables {
std::string_view test_view_loop_var(std::vector<std::string> strings) {
- for (std::string_view s : strings) { // cfg-warning {{address of stack memory is returned later}}
+ for (std::string_view s : strings) { // cfg-warning {{address of stack memory associated with parameter 'strings' returned}}
return s; //cfg-note {{returned here}}
}
return "";
}
const char* test_view_loop_var_with_data(std::vector<std::string> strings) {
- for (std::string_view s : strings) { // cfg-warning {{address of stack memory is returned later}}
+ for (std::string_view s : strings) { // cfg-warning {{address of stack memory associated with parameter 'strings' returned}}
return s.data(); //cfg-note {{returned here}}
}
return "";
@@ -1001,14 +1001,14 @@ std::string_view test_no_error_for_views(std::vector<std::string_view> views) {
}
std::string_view test_string_ref_var(std::vector<std::string> strings) {
- for (const std::string& s : strings) { // cfg-warning {{address of stack memory is returned later}}
+ for (const std::string& s : strings) { // cfg-warning {{address of stack memory associated with parameter 'strings' returned}}
return s; //cfg-note {{returned here}}
}
return "";
}
std::string_view test_opt_strings(std::optional<std::vector<std::string>> strings_or) {
- for (const std::string& s : *strings_or) { // cfg-warning {{address of stack memory is returned later}}
+ for (const std::string& s : *strings_or) { // cfg-warning {{address of stack memory associated with parameter 'strings_or' returned}}
return s; //cfg-note {{returned here}}
}
return "";
@@ -1018,7 +1018,7 @@ std::string_view test_opt_strings(std::optional<std::vector<std::string>> string
namespace iterator_arrow {
std::string_view test() {
std::vector<std::string> strings;
- return strings.begin()->data(); // cfg-warning {{address of stack memory is returned later}} cfg-note {{returned here}}
+ return strings.begin()->data(); // cfg-warning {{address of stack memory associated with local variable 'strings' returned}} cfg-note {{returned here}}
}
void operator_star_arrow_reference() {
@@ -1143,7 +1143,7 @@ struct StatusOr {
const char* foo() {
StatusOr<std::string> s;
return s->data(); // expected-warning {{address of stack memory associated with local variable}} \
- // cfg-warning {{address of stack memory is returned later}} cfg-note {{returned here}}
+ // cfg-warning {{address of stack memory associated with local variable 's' returned}} cfg-note {{returned here}}
StatusOr<std::string_view> s2;
return s2->data();
diff --git a/clang/test/Sema/warn-lifetime-safety-suggestions.cpp b/clang/test/Sema/warn-lifetime-safety-suggestions.cpp
index 973c610eb58ab..e3946f3fe2695 100644
--- a/clang/test/Sema/warn-lifetime-safety-suggestions.cpp
+++ b/clang/test/Sema/warn-lifetime-safety-suggestions.cpp
@@ -316,7 +316,7 @@ View inference_caller_forwards_callee(View a) { // expected-warning {{parameter
View inference_top_level_return_stack_view() {
MyObj local_stack;
- return inference_caller_forwards_callee(local_stack); // expected-warning {{address of stack memory is returned later}}
+ return inference_caller_forwards_callee(local_stack); // expected-warning {{address of stack memory associated with local variable 'local_stack' returned}}
// expected-note at -1 {{returned here}}
}
} // namespace simple_annotation_inference
@@ -334,7 +334,7 @@ View inference_caller_forwards_callee(View a) { // expected-warning {{paramete
View inference_top_level_return_stack_view() {
MyObj local_stack;
- return inference_caller_forwards_callee(local_stack); // expected-warning {{address of stack memory is returned later}}
+ return inference_caller_forwards_callee(local_stack); // expected-warning {{address of stack memory associated with local variable 'local_stack' returned}}
// expected-note at -1 {{returned here}}
}
} // namespace inference_in_order_with_redecls
@@ -352,7 +352,7 @@ T* template_caller(T* a) { // expected-warning {{parameter in intra
MyObj* test_template_inference_with_stack() {
MyObj local_stack;
- return template_caller(&local_stack); // expected-warning {{address of stack memory is returned later}}
+ return template_caller(&local_stack); // expected-warning {{address of stack memory associated with local variable 'local_stack' returned}}
// expected-note at -1 {{returned here}}
}
} // namespace inference_with_templates
@@ -413,7 +413,9 @@ void Foo(int, int*, const MyObj&, View);
auto implicit_ref_capture(int integer, int* ptr,
const MyObj& ref, // expected-warning {{parameter in intra-TU function should be marked [[clang::lifetimebound]]}}
View view) {
- return [&]() { Foo(integer, ptr, ref, view); }; // expected-warning 3 {{address of stack memory is returned later}} \
+ return [&]() { Foo(integer, ptr, ref, view); }; // expected-warning {{address of stack memory associated with parameter 'ptr' returned}} \
+ // expected-warning {{address of stack memory associated with parameter 'view' returned}} \
+ // expected-warning {{address of stack memory associated with parameter 'integer' returned}} \
// expected-note 3 {{returned here}} \
// expected-note {{param returned here}}
}
@@ -467,7 +469,7 @@ struct CaptureRefToView {
CaptureRefToView test_ref_to_view() {
MyObj obj;
- CaptureRefToView x(obj); // expected-warning {{address of stack memory is returned later}}
+ CaptureRefToView x(obj); // expected-warning {{address of stack memory associated with local variable 'obj' returned}}
return x; // expected-note {{returned here}}
}
@@ -478,7 +480,7 @@ struct CaptureRefToPtr {
CaptureRefToPtr test_ref_to_ptr() {
MyObj obj;
- CaptureRefToPtr x(obj); // expected-warning {{address of stack memory is returned later}}
+ CaptureRefToPtr x(obj); // expected-warning {{address of stack memory associated with local variable 'obj' returned}}
return x; // expected-note {{returned here}}
}
@@ -489,7 +491,7 @@ struct CaptureViewToView {
CaptureViewToView test_view_to_view() {
MyObj obj;
- View v(obj); // expected-warning {{address of stack memory is returned later}}
+ View v(obj); // expected-warning {{address of stack memory associated with local variable 'obj' returned}}
CaptureViewToView x(v);
return x; // expected-note {{returned here}}
}
@@ -501,7 +503,7 @@ struct CapturePtrToPtr {
CapturePtrToPtr test_ptr_to_ptr() {
MyObj obj;
- CapturePtrToPtr x(&obj); // expected-warning {{address of stack memory is returned later}}
+ CapturePtrToPtr x(&obj); // expected-warning {{address of stack memory associated with local variable 'obj' returned}}
return x; // expected-note {{returned here}}
}
@@ -512,7 +514,7 @@ struct CaptureRefToRef {
CaptureRefToRef test_ref_to_ref() {
MyObj obj;
- CaptureRefToRef x(obj); // expected-warning {{address of stack memory is returned later}}
+ CaptureRefToRef x(obj); // expected-warning {{address of stack memory associated with local variable 'obj' returned}}
return x; // expected-note {{returned here}}
}
@@ -527,7 +529,7 @@ struct CaptureRefToBaseView : BaseWithView {
CaptureRefToBaseView test_ref_to_base_view() {
MyObj obj;
- CaptureRefToBaseView x(obj); // expected-warning {{address of stack memory is returned later}}
+ CaptureRefToBaseView x(obj); // expected-warning {{address of stack memory associated with local variable 'obj' returned}}
return x; // expected-note {{returned here}}
}
} // namespace capturing_constructor
@@ -596,7 +598,7 @@ struct HasCtorField {
HasCtorField test_dangling_field_ctor() {
MyObj obj;
- HasCtorField x(obj); // expected-warning {{address of stack memory is returned later}}
+ HasCtorField x(obj); // expected-warning {{address of stack memory associated with local variable 'obj' returned}}
return x; // expected-note {{returned here}}
}
diff --git a/clang/test/Sema/warn-lifetime-safety.cpp b/clang/test/Sema/warn-lifetime-safety.cpp
index 70ec968dfd5c1..5b92ebeea4358 100644
--- a/clang/test/Sema/warn-lifetime-safety.cpp
+++ b/clang/test/Sema/warn-lifetime-safety.cpp
@@ -488,13 +488,13 @@ void small_scope_reference_var_no_error() {
MyObj* simple_return_stack_address() {
MyObj s;
- MyObj* p = &s; // expected-warning {{address of stack memory is returned later}}
+ MyObj* p = &s; // expected-warning {{address of stack memory associated with local variable 's' returned}}
return p; // expected-note {{returned here}}
}
MyObj* direct_return() {
MyObj s;
- return &s; // expected-warning {{address of stack memory is returned later}}
+ return &s; // expected-warning {{address of stack memory associated with local variable 's' returned}}
// expected-note at -1 {{returned here}}
}
@@ -517,7 +517,7 @@ const MyObj* conditional_assign_unconditional_return(const MyObj& safe, bool c)
MyObj s;
const MyObj* p = &safe;
if (c) {
- p = &s; // expected-warning {{address of stack memory is returned later}}
+ p = &s; // expected-warning {{address of stack memory associated with local variable 's' returned}}
}
return p; // expected-note {{returned here}}
}
@@ -526,7 +526,7 @@ View conditional_assign_both_branches(const MyObj& safe, bool c) {
MyObj s;
View p;
if (c) {
- p = s; // expected-warning {{address of stack memory is returned later}}
+ p = s; // expected-warning {{address of stack memory associated with local variable 's' returned}}
}
else {
p = safe;
@@ -538,13 +538,13 @@ View conditional_assign_both_branches(const MyObj& safe, bool c) {
View reassign_safe_to_local(const MyObj& safe) {
MyObj local;
View p = safe;
- p = local; // expected-warning {{address of stack memory is returned later}}
+ p = local; // expected-warning {{address of stack memory associated with local variable 'local' returned}}
return p; // expected-note {{returned here}}
}
View pointer_chain_to_local() {
MyObj local;
- View p1 = local; // expected-warning {{address of stack memory is returned later}}
+ View p1 = local; // expected-warning {{address of stack memory associated with local variable 'local' returned}}
View p2 = p1;
return p2; // expected-note {{returned here}}
}
@@ -554,11 +554,11 @@ View multiple_assign_multiple_return(const MyObj& safe, bool c1, bool c2) {
MyObj local2;
View p;
if (c1) {
- p = local1; // expected-warning {{address of stack memory is returned later}}
+ p = local1; // expected-warning {{address of stack memory associated with local variable 'local1' returned}}
return p; // expected-note {{returned here}}
}
else if (c2) {
- p = local2; // expected-warning {{address of stack memory is returned later}}
+ p = local2; // expected-warning {{address of stack memory associated with local variable 'local2' returned}}
return p; // expected-note {{returned here}}
}
p = safe;
@@ -570,10 +570,10 @@ View multiple_assign_single_return(const MyObj& safe, bool c1, bool c2) {
MyObj local2;
View p;
if (c1) {
- p = local1; // expected-warning {{address of stack memory is returned later}}
+ p = local1; // expected-warning {{address of stack memory associated with local variable 'local1' returned}}
}
else if (c2) {
- p = local2; // expected-warning {{address of stack memory is returned later}}
+ p = local2; // expected-warning {{address of stack memory associated with local variable 'local2' returned}}
}
else {
p = safe;
@@ -583,42 +583,42 @@ View multiple_assign_single_return(const MyObj& safe, bool c1, bool c2) {
View direct_return_of_local() {
MyObj stack;
- return stack; // expected-warning {{address of stack memory is returned later}}
+ return stack; // expected-warning {{address of stack memory associated with local variable 'stack' returned}}
// expected-note at -1 {{returned here}}
}
MyObj& reference_return_of_local() {
MyObj stack;
- return stack; // expected-warning {{address of stack memory is returned later}}
+ return stack; // expected-warning {{reference to stack memory associated with local variable 'stack' returned}}
// expected-note at -1 {{returned here}}
}
int* trivial_int_uar() {
int *a;
int b = 1;
- a = &b; // expected-warning {{address of stack memory is returned later}}
+ a = &b; // expected-warning {{address of stack memory associated with local variable 'b' returned}}
return a; // expected-note {{returned here}}
}
TriviallyDestructedClass* trivial_class_uar () {
TriviallyDestructedClass *ptr;
TriviallyDestructedClass s;
- ptr = &s; // expected-warning {{address of stack memory is returned later}}
+ ptr = &s; // expected-warning {{address of stack memory associated with local variable 's' returned}}
return ptr; // expected-note {{returned here}}
}
const int& return_parameter(int a) {
- return a; // expected-warning {{address of stack memory is returned later}}
+ return a; // expected-warning {{reference to stack memory associated with parameter 'a' returned}}
// expected-note at -1 {{returned here}}
}
int* return_pointer_to_parameter(int a) {
- return &a; // expected-warning {{address of stack memory is returned later}}
+ return &a; // expected-warning {{address of stack memory associated with parameter 'a' returned}}
// expected-note at -1 {{returned here}}
}
const int& return_reference_to_parameter(int a) {
- const int &b = a; // expected-warning {{address of stack memory is returned later}}
+ const int &b = a; // expected-warning {{reference to stack memory associated with parameter 'a' returned}}
return b; // expected-note {{returned here}}
}
int return_reference_to_parameter_no_error(int a) {
@@ -628,30 +628,30 @@ int return_reference_to_parameter_no_error(int a) {
MyObj*& return_ref_to_local_ptr_pointing_to_local() {
MyObj local;
- MyObj* p = &local; // expected-warning {{address of stack memory is returned later}}
+ MyObj* p = &local; // expected-warning {{reference to stack memory associated with local variable 'local' returned}}
return p; // expected-note {{returned here}} \
- // expected-warning {{address of stack memory is returned later}} \
+ // expected-warning {{reference to stack memory associated with local variable 'p' returned}} \
// expected-note {{returned here}}
}
const int& reference_via_conditional(int a, int b, bool cond) {
- const int &c = (cond ? ((a)) : (b)); // expected-warning 2 {{address of stack memory is returned later}}
+ const int &c = (cond ? ((a)) : (b)); // expected-warning {{reference to stack memory associated with parameter 'b' returned}} expected-warning {{reference to stack memory associated with parameter 'a' returned}}
return c; // expected-note 2 {{returned here}}
}
const int* return_pointer_to_parameter_via_reference(int a, int b, bool cond) {
- const int &c = cond ? a : b; // expected-warning 2 {{address of stack memory is returned later}}
+ const int &c = cond ? a : b; // expected-warning {{address of stack memory associated with parameter 'b' returned}} expected-warning {{address of stack memory associated with parameter 'a' returned}}
const int* d = &c;
return d; // expected-note 2 {{returned here}}
}
const int& return_pointer_to_parameter_via_reference_1(int a) {
- const int* d = &a; // expected-warning {{address of stack memory is returned later}}
+ const int* d = &a; // expected-warning {{reference to stack memory associated with parameter 'a' returned}}
return *d; // expected-note {{returned here}}
}
const int& get_ref_to_local() {
int a = 42;
- return a; // expected-warning {{address of stack memory is returned later}}
+ return a; // expected-warning {{reference to stack memory associated with local variable 'a' returned}}
// expected-note at -1 {{returned here}}
}
@@ -680,7 +680,7 @@ struct PtrHolder {
int* const& test_ref_to_ptr() {
PtrHolder a;
- int *const &ref = a.getRef(); // expected-warning {{address of stack memory is returned later}}
+ int *const &ref = a.getRef(); // expected-warning {{reference to stack memory associated with local variable 'a' returned}}
return ref; // expected-note {{returned here}}
}
int* const test_ref_to_ptr_no_error() {
@@ -715,9 +715,9 @@ void test_assign_through_double_ptr() {
int** test_ternary_double_ptr(bool cond) {
int a = 1, b = 2;
- int* pa = &a; // expected-warning {{address of stack memory is returned later}}
- int* pb = &b; // expected-warning {{address of stack memory is returned later}}
- int** result = cond ? &pa : &pb; // expected-warning 2 {{address of stack memory is returned later}}
+ int* pa = &a; // expected-warning {{address of stack memory associated with local variable 'a' returned}}
+ int* pb = &b; // expected-warning {{address of stack memory associated with local variable 'b' returned}}
+ int** result = cond ? &pa : &pb; // expected-warning {{address of stack memory associated with local variable 'pb' returned}} expected-warning {{address of stack memory associated with local variable 'pa' returned}}
return result; // expected-note 4 {{returned here}}
}
//===----------------------------------------------------------------------===//
@@ -738,7 +738,7 @@ View uar_before_uaf(const MyObj& safe, bool c) {
View p;
{
MyObj local_obj;
- p = local_obj; // expected-warning {{ddress of stack memory is returned later}}
+ p = local_obj; // expected-warning {{address of stack memory associated with local variable 'local_obj' returned}}
if (c) {
return p; // expected-note {{returned here}}
}
@@ -1100,35 +1100,35 @@ void lifetimebound_make_unique_multi_params3_2() {
View lifetimebound_return_of_local() {
MyObj stack;
- return Identity(stack); // expected-warning {{address of stack memory is returned later}}
+ return Identity(stack); // expected-warning {{address of stack memory associated with local variable 'stack' returned}}
// expected-note at -1 {{returned here}}
}
const MyObj& lifetimebound_return_ref_to_local() {
MyObj stack;
- return IdentityRef(stack); // expected-warning {{address of stack memory is returned later}}
+ return IdentityRef(stack); // expected-warning {{reference to stack memory associated with local variable 'stack' returned}}
// expected-note at -1 {{returned here}}
}
View lifetimebound_return_by_value_param(MyObj stack_param) {
- return Identity(stack_param); // expected-warning {{address of stack memory is returned later}}
+ return Identity(stack_param); // expected-warning {{address of stack memory associated with parameter 'stack_param' returned}}
// expected-note at -1 {{returned here}}
}
View lifetimebound_return_by_value_multiple_param(int cond, MyObj a, MyObj b, MyObj c) {
if (cond == 1)
- return Identity(a); // expected-warning {{address of stack memory is returned later}}
+ return Identity(a); // expected-warning {{address of stack memory associated with parameter 'a' returned}}
// expected-note at -1 {{returned here}}
if (cond == 2)
- return Identity(b); // expected-warning {{address of stack memory is returned later}}
+ return Identity(b); // expected-warning {{address of stack memory associated with parameter 'b' returned}}
// expected-note at -1 {{returned here}}
- return Identity(c); // expected-warning {{address of stack memory is returned later}}
+ return Identity(c); // expected-warning {{address of stack memory associated with parameter 'c' returned}}
// expected-note at -1 {{returned here}}
}
template<class T>
View lifetimebound_return_by_value_param_template(T t) {
- return Identity(t); // expected-warning {{address of stack memory is returned later}}
+ return Identity(t); // expected-warning {{address of stack memory associated with parameter 't' returned}}
// expected-note at -1 {{returned here}}
}
void use_lifetimebound_return_by_value_param_template() {
@@ -1137,7 +1137,7 @@ void use_lifetimebound_return_by_value_param_template() {
void lambda_uar_param() {
auto lambda = [](MyObj stack_param) {
- return Identity(stack_param); // expected-warning {{address of stack memory is returned later}}
+ return Identity(stack_param); // expected-warning {{address of stack memory associated with parameter 'stack_param' returned}}
// expected-note at -1 {{returned here}}
};
lambda(MyObj{});
@@ -1353,10 +1353,10 @@ void range_based_for_use_after_scope() {
View range_based_for_use_after_return() {
MyObjStorage s;
- for (const MyObj &o : s) { // expected-warning {{address of stack memory is returned later}}
+ for (const MyObj &o : s) { // expected-warning {{address of stack memory associated with local variable 's' returned}}
return o; // expected-note {{returned here}}
}
- return *s.begin(); // expected-warning {{address of stack memory is returned later}}
+ return *s.begin(); // expected-warning {{address of stack memory associated with local variable 's' returned}}
// expected-note at -1 {{returned here}}
}
@@ -1406,7 +1406,7 @@ void test_user_defined_deref_uaf() {
MyObj& test_user_defined_deref_uar() {
MyObj obj;
SmartPtr<MyObj> smart_ptr(&obj);
- return *smart_ptr; // expected-warning {{address of stack memory is returned later}}
+ return *smart_ptr; // expected-warning {{reference to stack memory associated with local variable 'smart_ptr' returned}}
// expected-note at -1 {{returned here}}
}
@@ -1469,29 +1469,29 @@ T&& MaxT(T&& a [[clang::lifetimebound]], T&& b [[clang::lifetimebound]]);
const MyObj& call_max_with_obj() {
MyObj oa, ob;
- return MaxT(oa, // expected-warning {{address of stack memory is returned later}}
+ return MaxT(oa, // expected-warning {{reference to stack memory associated with local variable 'oa' returned}}
// expected-note at -1 2 {{returned here}}
- ob); // expected-warning {{address of stack memory is returned later}}
+ ob); // expected-warning {{reference to stack memory associated with local variable 'ob' returned}}
}
MyObj* call_max_with_obj_error() {
MyObj oa, ob;
- return &MaxT(oa, // expected-warning {{address of stack memory is returned later}}
+ return &MaxT(oa, // expected-warning {{address of stack memory associated with local variable 'oa' returned}}
// expected-note at -1 2 {{returned here}}
- ob); // expected-warning {{address of stack memory is returned later}}
+ ob); // expected-warning {{address of stack memory associated with local variable 'ob' returned}}
}
const MyObj* call_max_with_ref_obj_error() {
MyObj oa, ob;
- const MyObj& refa = oa; // expected-warning {{address of stack memory is returned later}}
- const MyObj& refb = ob; // expected-warning {{address of stack memory is returned later}}
+ const MyObj& refa = oa; // expected-warning {{address of stack memory associated with local variable 'oa' returned}}
+ const MyObj& refb = ob; // expected-warning {{address of stack memory associated with local variable 'ob' returned}}
return &MaxT(refa, refb); // expected-note 2 {{returned here}}
}
const MyObj& call_max_with_ref_obj_return_ref_error() {
MyObj oa, ob;
- const MyObj& refa = oa; // expected-warning {{address of stack memory is returned later}}
- const MyObj& refb = ob; // expected-warning {{address of stack memory is returned later}}
+ const MyObj& refa = oa; // expected-warning {{reference to stack memory associated with local variable 'oa' returned}}
+ const MyObj& refb = ob; // expected-warning {{reference to stack memory associated with local variable 'ob' returned}}
return MaxT(refa, refb); // expected-note 2 {{returned here}}
}
@@ -1506,47 +1506,47 @@ const MyObj& call_max_with_ref_obj_no_error(const MyObj& a, const MyObj& b) {
const View& call_max_with_view_with_error() {
View va, vb;
- return MaxT(va, // expected-warning {{address of stack memory is returned later}}
+ return MaxT(va, // expected-warning {{reference to stack memory associated with local variable 'va' returned}}
// expected-note at -1 2 {{returned here}}
- vb); // expected-warning {{address of stack memory is returned later}}
+ vb); // expected-warning {{reference to stack memory associated with local variable 'vb' returned}}
}
struct [[gsl::Pointer]] NonTrivialPointer { ~NonTrivialPointer(); };
const NonTrivialPointer& call_max_with_non_trivial_view_with_error() {
NonTrivialPointer va, vb;
- return MaxT(va, // expected-warning {{address of stack memory is returned later}}
+ return MaxT(va, // expected-warning {{reference to stack memory associated with local variable 'va' returned}}
// expected-note at -1 2 {{returned here}}
- vb); // expected-warning {{address of stack memory is returned later}}
+ vb); // expected-warning {{reference to stack memory associated with local variable 'vb' returned}}
}
namespace MultiPointerTypes {
int** return_2p() {
int a = 1;
- int* b = &a; // expected-warning {{address of stack memory is returned later}}
- int** c = &b; // expected-warning {{address of stack memory is returned later}}
+ int* b = &a; // expected-warning {{address of stack memory associated with local variable 'a' returned}}
+ int** c = &b; // expected-warning {{address of stack memory associated with local variable 'b' returned}}
return c; // expected-note 2 {{returned here}}
}
int** return_2p_one_is_safe(int& a) {
int* b = &a;
- int** c = &b; // expected-warning {{address of stack memory is returned later}}
+ int** c = &b; // expected-warning {{address of stack memory associated with local variable 'b' returned}}
return c; // expected-note {{returned here}}
}
int*** return_3p() {
int a = 1;
- int* b = &a; // expected-warning {{address of stack memory is returned later}}
- int** c = &b; // expected-warning {{address of stack memory is returned later}}
- int*** d = &c; // expected-warning {{address of stack memory is returned later}}
+ int* b = &a; // expected-warning {{address of stack memory associated with local variable 'a' returned}}
+ int** c = &b; // expected-warning {{address of stack memory associated with local variable 'b' returned}}
+ int*** d = &c; // expected-warning {{address of stack memory associated with local variable 'c' returned}}
return d; // expected-note 3 {{returned here}}
}
View** return_view_p() {
MyObj a;
- View b = a; // expected-warning {{address of stack memory is returned later}}
- View* c = &b; // expected-warning {{address of stack memory is returned later}}
- View** d = &c; // expected-warning {{address of stack memory is returned later}}
+ View b = a; // expected-warning {{address of stack memory associated with local variable 'a' returned}}
+ View* c = &b; // expected-warning {{address of stack memory associated with local variable 'b' returned}}
+ View** d = &c; // expected-warning {{address of stack memory associated with local variable 'c' returned}}
return d; // expected-note 3 {{returned here}}
}
@@ -1670,24 +1670,24 @@ void bar() {
namespace DereferenceViews {
const MyObj& testDeref(MyObj obj) {
- View v = obj; // expected-warning {{address of stack memory is returned later}}
+ View v = obj; // expected-warning {{reference to stack memory associated with parameter 'obj' returned}}
return *v; // expected-note {{returned here}}
}
const MyObj* testDerefAddr(MyObj obj) {
- View v = obj; // expected-warning {{address of stack memory is returned later}}
+ View v = obj; // expected-warning {{address of stack memory associated with parameter 'obj' returned}}
return &*v; // expected-note {{returned here}}
}
const MyObj* testData(MyObj obj) {
- View v = obj; // expected-warning {{address of stack memory is returned later}}
+ View v = obj; // expected-warning {{address of stack memory associated with parameter 'obj' returned}}
return v.data(); // expected-note {{returned here}}
}
const int* testLifetimeboundAccessorOfMyObj(MyObj obj) {
- View v = obj; // expected-warning {{address of stack memory is returned later}}
+ View v = obj; // expected-warning {{address of stack memory associated with parameter 'obj' returned}}
const MyObj* ptr = v.data();
return ptr->getData(); // expected-note {{returned here}}
}
const int* testLifetimeboundAccessorOfMyObjThroughDeref(MyObj obj) {
- View v = obj; // expected-warning {{address of stack memory is returned later}}
+ View v = obj; // expected-warning {{address of stack memory associated with parameter 'obj' returned}}
return v->getData(); // expected-note {{returned here}}
}
} // namespace DereferenceViews
@@ -1711,17 +1711,17 @@ It end() const [[clang::lifetimebound]];
MyObj Global;
const MyObj& ContainerMyObjReturnRef(Container<MyObj> c) {
- for (const MyObj& x : c) { // expected-warning {{address of stack memory is returned later}}
+ for (const MyObj& x : c) { // expected-warning {{reference to stack memory associated with parameter 'c' returned}}
return x; // expected-note {{returned here}}
}
return Global;
}
View ContainerMyObjReturnView(Container<MyObj> c) {
- for (const MyObj& x : c) { // expected-warning {{address of stack memory is returned later}}
+ for (const MyObj& x : c) { // expected-warning {{address of stack memory associated with parameter 'c' returned}}
return x; // expected-note {{returned here}}
}
- for (View x : c) { // expected-warning {{address of stack memory is returned later}}
+ for (View x : c) { // expected-warning {{address of stack memory associated with parameter 'c' returned}}
return x; // expected-note {{returned here}}
}
return Global;
@@ -1849,12 +1849,12 @@ struct RefMember {
std::string_view refMemberReturnView1(RefMember a) { return a.str_ref; }
std::string_view refMemberReturnView2(RefMember a) { return *a.str_ptr; }
-std::string_view refMemberReturnView3(RefMember a) { return a.str; } // expected-warning {{address of stack memory is returned later}} expected-note {{returned here}}
+std::string_view refMemberReturnView3(RefMember a) { return a.str; } // expected-warning {{address of stack memory associated with parameter 'a' returned}} expected-note {{returned here}}
std::string& refMemberReturnRef1(RefMember a) { return a.str_ref; }
std::string& refMemberReturnRef2(RefMember a) { return *a.str_ptr; }
-std::string& refMemberReturnRef3(RefMember a) { return a.str; } // expected-warning {{address of stack memory is returned later}} expected-note {{returned here}}
+std::string& refMemberReturnRef3(RefMember a) { return a.str; } // expected-warning {{reference to stack memory associated with parameter 'a' returned}} expected-note {{returned here}}
std::string_view refViewMemberReturnView1(RefMember a) { return a.view; }
-std::string_view& refViewMemberReturnView2(RefMember a) { return a.view; } // expected-warning {{address of stack memory is returned later}} expected-note {{returned here}}
+std::string_view& refViewMemberReturnView2(RefMember a) { return a.view; } // expected-warning {{reference to stack memory associated with parameter 'a' returned}} expected-note {{returned here}}
std::string_view refViewMemberReturnRefView1(RefMember a) { return a.view_ref; }
std::string_view& refViewMemberReturnRefView2(RefMember a) { return a.view_ref; }
} // namespace field_access
@@ -1908,16 +1908,16 @@ struct [[gsl::Pointer]] View {
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}}
+ return View(a); // expected-warning {{address of stack memory associated with parameter 'a' returned}} expected-note {{returned here}}
}
View test2(std::string a) {
- View b = View(a); // expected-warning {{address of stack memory is returned later}}
+ View b = View(a); // expected-warning {{address of stack memory associated with parameter 'a' returned}}
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}}
+ const View& b = View(a); // expected-warning {{address of stack memory associated with parameter 'a' returned}}
return b; // expected-note {{returned here}}
}
} // namespace non_trivial_views
@@ -1963,7 +1963,7 @@ void test_optional_view_arrow() {
namespace lambda_captures {
auto return_ref_capture() {
int local = 1;
- auto lambda = [&local]() { return local; }; // expected-warning {{address of stack memory is returned later}}
+ auto lambda = [&local]() { return local; }; // expected-warning {{address of stack memory associated with local variable 'local' returned}}
return lambda; // expected-note {{returned here}}
}
@@ -1981,7 +1981,7 @@ auto capture_int_by_value() {
auto capture_view_by_value() {
MyObj obj;
- View v(obj); // expected-warning {{address of stack memory is returned later}}
+ View v(obj); // expected-warning {{address of stack memory associated with local variable 'obj' returned}}
auto lambda = [v]() { return v; };
return lambda; // expected-note {{returned here}}
}
@@ -1996,57 +1996,57 @@ void capture_view_by_value_safe() {
auto capture_pointer_by_ref() {
MyObj obj;
MyObj* p = &obj;
- auto lambda = [&p]() { return p; }; // expected-warning {{address of stack memory is returned later}}
+ auto lambda = [&p]() { return p; }; // expected-warning {{address of stack memory associated with local variable 'p' returned}}
return lambda; // expected-note {{returned here}}
}
auto capture_multiple() {
int a, b;
auto lambda = [
- &a, // expected-warning {{address of stack memory is returned later}}
- &b // expected-warning {{address of stack memory is returned later}}
+ &a, // expected-warning {{address of stack memory associated with local variable 'a' returned}}
+ &b // expected-warning {{address of stack memory associated with local variable 'b' returned}}
]() { return a + b; };
return lambda; // expected-note 2 {{returned here}}
}
auto capture_raw_pointer_by_value() {
int x;
- int* p = &x; // expected-warning {{address of stack memory is returned later}}
+ int* p = &x; // expected-warning {{address of stack memory associated with local variable 'x' returned}}
auto lambda = [p]() { return p; };
return lambda; // expected-note {{returned here}}
}
auto capture_raw_pointer_init_capture() {
int x;
- int* p = &x; // expected-warning {{address of stack memory is returned later}}
+ int* p = &x; // expected-warning {{address of stack memory associated with local variable 'x' returned}}
auto lambda = [q = p]() { return q; };
return lambda; // expected-note {{returned here}}
}
auto capture_view_init_capture() {
MyObj obj;
- View v(obj); // expected-warning {{address of stack memory is returned later}}
+ View v(obj); // expected-warning {{address of stack memory associated with local variable 'obj' returned}}
auto lambda = [w = v]() { return w; };
return lambda; // expected-note {{returned here}}
}
auto capture_lambda() {
int x;
- auto inner = [&x]() { return x; }; // expected-warning {{address of stack memory is returned later}}
+ auto inner = [&x]() { return x; }; // expected-warning {{address of stack memory associated with local variable 'x' returned}}
auto outer = [inner]() { return inner(); };
return outer; // expected-note {{returned here}}
}
auto return_copied_lambda() {
int local = 1;
- auto lambda = [&local]() { return local; }; // expected-warning {{address of stack memory is returned later}}
+ auto lambda = [&local]() { return local; }; // expected-warning {{address of stack memory associated with local variable 'local' returned}}
auto lambda_copy = lambda;
return lambda_copy; // expected-note {{returned here}}
}
auto implicit_ref_capture() {
int local = 1;
- auto lambda = [&]() { return local; }; // expected-warning {{address of stack memory is returned later}}
+ auto lambda = [&]() { return local; }; // expected-warning {{address of stack memory associated with local variable 'local' returned}}
return lambda; // expected-note {{returned here}}
}
@@ -2055,20 +2055,20 @@ auto implicit_ref_capture() {
// can point to the same source location.
auto implicit_ref_capture_multiple() {
int local = 1, local2 = 2;
- auto lambda = [&]() { return local + local2; }; // expected-warning 2 {{address of stack memory is returned later}}
+ auto lambda = [&]() { return local + local2; }; // expected-warning {{address of stack memory associated with local variable 'local2' returned}} expected-warning {{address of stack memory associated with local variable 'local' returned}}
return lambda; // expected-note 2 {{returned here}}
}
auto implicit_value_capture() {
MyObj obj;
- View v(obj); // expected-warning {{address of stack memory is returned later}}
+ View v(obj); // expected-warning {{address of stack memory associated with local variable 'obj' returned}}
auto lambda = [=]() { return v; };
return lambda; // expected-note {{returned here}}
}
auto* pointer_to_lambda_outlives() {
auto lambda = []() { return 42; };
- return λ // expected-warning {{address of stack memory is returned later}} \
+ return λ // expected-warning {{address of stack memory associated with local variable 'lambda' returned}} \
// expected-note {{returned here}}
}
@@ -2093,15 +2093,15 @@ auto capture_static_address_by_value() {
auto capture_static_address_by_ref() {
static int local = 1;
int* p = &local;
- auto lambda = [&p]() { return p; }; // expected-warning {{address of stack memory is returned later}}
+ auto lambda = [&p]() { return p; }; // expected-warning {{address of stack memory associated with local variable 'p' returned}}
return lambda; // expected-note {{returned here}}
}
auto capture_multilevel_pointer() {
int x;
- int *p = &x; // expected-warning {{address of stack memory is returned later}}
- int **q = &p; // expected-warning {{address of stack memory is returned later}}
- int ***r = &q; // expected-warning {{address of stack memory is returned later}}
+ int *p = &x; // expected-warning {{address of stack memory associated with local variable 'x' returned}}
+ int **q = &p; // expected-warning {{address of stack memory associated with local variable 'p' returned}}
+ int ***r = &q; // expected-warning {{address of stack memory associated with local variable 'q' returned}}
auto lambda = [=]() { return *p + **q + ***r; };
return lambda; // expected-note 3 {{returned here}}
}
@@ -2168,7 +2168,7 @@ void element_use_after_scope() {
int* element_use_after_return() {
int a[10]{};
- int* p = &a[0]; // expected-warning {{address of stack memory is returned later}}
+ int* p = &a[0]; // expected-warning {{address of stack memory associated with local variable 'a' returned}}
return p; // expected-note {{returned here}}
}
@@ -2231,7 +2231,7 @@ void reversed_subscript_use_after_scope() {
int* return_decayed_array() {
int a[10]{};
- int *p = a; // expected-warning {{address of stack memory is returned later}}
+ int *p = a; // expected-warning {{address of stack memory associated with local variable 'a' returned}}
return p; // expected-note {{returned here}}
}
@@ -2377,7 +2377,7 @@ void same_scope() {
S copy_propagation() {
std::string str{"abc"};
- S a = getS(str); // expected-warning {{address of stack memory is returned later}}
+ S a = getS(str); // expected-warning {{address of stack memory associated with local variable 'str' returned}}
S b = a;
return b; // expected-note {{returned here}}
}
@@ -2421,7 +2421,7 @@ S getS2(const std::string &a [[clang::lifetimebound]], const std::string &b [[cl
S multiple_lifetimebound_params() {
std::string str{"abc"};
- S s = getS2(str, std::string("temp")); // expected-warning {{address of stack memory is returned later}} \
+ S s = getS2(str, std::string("temp")); // expected-warning {{address of stack memory associated with local variable 'str' returned}} \
// expected-warning {{object whose reference is captured does not live long enough}} \
// expected-note {{destroyed here}}
return s; // expected-note {{returned here}} \
@@ -2539,7 +2539,7 @@ DefaultedOuter getDefaultedOuter(const std::string &s [[clang::lifetimebound]]);
// pattern does not fit the ownership model this analysis supports.
DefaultedOuter nested_defaulted_outer_with_user_defined_inner() {
std::string str{"abc"};
- DefaultedOuter o = getDefaultedOuter(str); // expected-warning {{address of stack memory is returned later}}
+ DefaultedOuter o = getDefaultedOuter(str); // expected-warning {{address of stack memory associated with local variable 'str' returned}}
DefaultedOuter copy = o;
return copy; // expected-note {{returned here}}
}
@@ -2571,7 +2571,7 @@ std::vector<std::string_view> createViews(const std::string &s [[clang::lifetime
std::span<std::string_view> owner_to_pointer_via_gsl_construction() {
std::string local;
auto views = createViews(local);
- return views; // expected-warning {{address of stack memory is returned later}} \
+ return views; // expected-warning {{address of stack memory associated with local variable 'views' returned}} \
// expected-note {{returned here}}
}
@@ -2586,7 +2586,7 @@ void owner_return_unique_ptr_s() {
std::string_view return_dangling_view_through_owner() {
std::string local;
auto ups = getUniqueS(local);
- S* s = ups.get(); // expected-warning {{address of stack memory is returned later}}
+ S* s = ups.get(); // expected-warning {{address of stack memory associated with local variable 'ups' returned}}
std::string_view sv = s->getData();
return sv; // expected-note {{returned here}}
}
@@ -2683,12 +2683,12 @@ int *constexpr_dead_nested(int *num) {
int *constexpr_live_false(int *num) {
int local = 0;
- return kFalse ? num : f(&local); // expected-warning {{address of stack memory is returned later}} // expected-note {{returned here}}
+ return kFalse ? num : f(&local); // expected-warning {{address of stack memory associated with local variable 'local' returned}} // expected-note {{returned here}}
}
int *constexpr_live_nested(int *num) {
int local = 0;
- return kTrue ? (kFalse ? num : f(&local)) : num; // expected-warning {{address of stack memory is returned later}} // expected-note {{returned here}}
+ return kTrue ? (kFalse ? num : f(&local)) : num; // expected-warning {{address of stack memory associated with local variable 'local' returned}} // expected-note {{returned here}}
}
int *noreturn_dead_false(bool cond, int *num) {
int local = 0;
@@ -3221,20 +3221,20 @@ namespace callable_wrappers {
std::function<void()> direct_return() {
int x;
- return [&x]() { (void)x; }; // expected-warning {{address of stack memory is returned later}} \
+ return [&x]() { (void)x; }; // expected-warning {{address of stack memory associated with local variable 'x' returned}} \
// expected-note {{returned here}}
}
std::function<void()> copy_function() {
int x;
- std::function<void()> f = [&x]() { (void)x; }; // expected-warning {{address of stack memory is returned later}}
+ std::function<void()> f = [&x]() { (void)x; }; // expected-warning {{address of stack memory associated with local variable 'x' returned}}
std::function<void()> f2 = f;
return f2; // expected-note {{returned here}}
}
std::function<void()> copy_assign() {
int x;
- std::function<void()> f = [&x]() { (void)x; }; // expected-warning {{address of stack memory is returned later}}
+ std::function<void()> f = [&x]() { (void)x; }; // expected-warning {{address of stack memory associated with local variable 'x' returned}}
std::function<void()> f2 = []() {};
f2 = f;
return f2; // expected-note {{returned here}}
@@ -3242,7 +3242,7 @@ std::function<void()> copy_assign() {
std::function<void()> chained_copy_assign() {
int x;
- std::function<void()> f = [&x]() { (void)x; }; // expected-warning {{address of stack memory is returned later}}
+ std::function<void()> f = [&x]() { (void)x; }; // expected-warning {{address of stack memory associated with local variable 'x' returned}}
std::function<void()> f2 = []() {};
std::function<void()> f3 = []() {};
f3 = f2 = f;
@@ -3264,7 +3264,7 @@ std::function<void()> reassign_safe_then_unsafe() {
static int safe = 1;
int local = 2;
std::function<void()> f = []() { (void)safe; };
- f = [&local]() { (void)local; }; // expected-warning {{address of stack memory is returned later}}
+ f = [&local]() { (void)local; }; // expected-warning {{address of stack memory associated with local variable 'local' returned}}
return f; // expected-note {{returned here}}
}
>From 48b2133a22218f964e01e5a2ec294079284b876a Mon Sep 17 00:00:00 2001
From: NeKon69 <nobodqwe at gmail.com>
Date: Sun, 24 May 2026 19:21:12 +0300
Subject: [PATCH 2/2] clang-format
---
clang/lib/Sema/SemaLifetimeSafety.h | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/clang/lib/Sema/SemaLifetimeSafety.h b/clang/lib/Sema/SemaLifetimeSafety.h
index 6bd78f79da802..a65b88553033c 100644
--- a/clang/lib/Sema/SemaLifetimeSafety.h
+++ b/clang/lib/Sema/SemaLifetimeSafety.h
@@ -75,8 +75,7 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper {
}
void reportUseAfterReturn(const ValueDecl *VD, const Expr *IssueExpr,
- const Expr *ReturnExpr,
- const Expr *MovedExpr,
+ const Expr *ReturnExpr, const Expr *MovedExpr,
bool IsReference) override {
unsigned DiagID = MovedExpr
? diag::warn_lifetime_safety_return_stack_addr_moved
@@ -93,8 +92,7 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper {
}
void reportUseAfterReturn(const MaterializeTemporaryExpr *MTE,
- const Expr *ReturnExpr,
- const Expr *MovedExpr,
+ const Expr *ReturnExpr, const Expr *MovedExpr,
bool IsReference) override {
unsigned DiagID =
MovedExpr ? diag::warn_lifetime_safety_return_temp_stack_addr_moved
More information about the cfe-commits
mailing list