https://github.com/NeKon69 updated https://github.com/llvm/llvm-project/pull/199432
>From f09e32af0f00fc0fe0e0df8834befe8244ab85d1 Mon Sep 17 00:00:00 2001 From: NeKon69 <[email protected]> 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@-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@-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@-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@-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@-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@-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@-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@-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@-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@-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@-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@-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@-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@-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@-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@-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@-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@-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@-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@-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@-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@-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@-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 <[email protected]> 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 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
