https://github.com/NeKon69 updated https://github.com/llvm/llvm-project/pull/200147
>From a250e901477a5a567f06607612302c5e9f22210a Mon Sep 17 00:00:00 2001 From: NeKon69 <[email protected]> Date: Thu, 28 May 2026 12:54:31 +0300 Subject: [PATCH 1/2] [LifetimeSafety] Improve dangling field/global diagnostics --- .../clang/Basic/DiagnosticSemaKinds.td | 8 +-- clang/lib/Sema/SemaLifetimeSafety.h | 20 ++++--- .../Sema/warn-lifetime-analysis-nocfg.cpp | 12 ++--- .../warn-lifetime-safety-dangling-field.cpp | 54 +++++++++---------- .../warn-lifetime-safety-dangling-global.cpp | 6 +-- .../Sema/warn-lifetime-safety-suggestions.cpp | 2 +- clang/test/Sema/warn-lifetime-safety.cpp | 10 ++-- 7 files changed, 58 insertions(+), 54 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index e330ea03d0544..9bb64bb0f5b84 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -10999,21 +10999,21 @@ def warn_lifetime_safety_invalidated_global DefaultIgnore; def warn_lifetime_safety_dangling_field - : Warning<"address of stack memory escapes to a field">, + : Warning<"%0 escapes to a field and will dangle">, InGroup<LifetimeSafetyDanglingField>, DefaultIgnore; def warn_lifetime_safety_dangling_field_moved - : Warning<"address of stack memory escapes to a field. " + : Warning<"%0 may escape to a field and dangle. " "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<LifetimeSafetyDanglingFieldMoved>, DefaultIgnore; def warn_lifetime_safety_dangling_global - : Warning<"address of stack memory escapes to global or static storage">, + : Warning<"%0 escapes to global or static storage and will dangle">, InGroup<LifetimeSafetyDanglingGlobal>, DefaultIgnore; def warn_lifetime_safety_dangling_global_moved - : Warning<"address of stack memory escapes to global or static storage. " + : Warning<"%0 may escape to global or static storage and dangle. " "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<LifetimeSafetyDanglingGlobalMoved>, diff --git a/clang/lib/Sema/SemaLifetimeSafety.h b/clang/lib/Sema/SemaLifetimeSafety.h index 0305510c1a233..005d3187d27ec 100644 --- a/clang/lib/Sema/SemaLifetimeSafety.h +++ b/clang/lib/Sema/SemaLifetimeSafety.h @@ -95,10 +95,12 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper { const FieldDecl *DanglingField, const Expr *MovedExpr, SourceLocation ExpiryLoc) override { - S.Diag(IssueExpr->getExprLoc(), - MovedExpr ? diag::warn_lifetime_safety_dangling_field_moved - : diag::warn_lifetime_safety_dangling_field) - << IssueExpr->getSourceRange(); + unsigned DiagID = MovedExpr + ? diag::warn_lifetime_safety_dangling_field_moved + : diag::warn_lifetime_safety_dangling_field; + + S.Diag(IssueExpr->getExprLoc(), DiagID) + << getDiagSubjectDescription(IssueExpr) << IssueExpr->getSourceRange(); if (MovedExpr) S.Diag(MovedExpr->getExprLoc(), diag::note_lifetime_safety_moved_here) << MovedExpr->getSourceRange(); @@ -111,10 +113,12 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper { const VarDecl *DanglingGlobal, const Expr *MovedExpr, SourceLocation ExpiryLoc) override { - S.Diag(IssueExpr->getExprLoc(), - MovedExpr ? diag::warn_lifetime_safety_dangling_global_moved - : diag::warn_lifetime_safety_dangling_global) - << IssueExpr->getSourceRange(); + unsigned DiagID = MovedExpr + ? diag::warn_lifetime_safety_dangling_global_moved + : diag::warn_lifetime_safety_dangling_global; + + S.Diag(IssueExpr->getExprLoc(), DiagID) + << getDiagSubjectDescription(IssueExpr) << IssueExpr->getSourceRange(); if (MovedExpr) S.Diag(MovedExpr->getExprLoc(), diag::note_lifetime_safety_moved_here) << MovedExpr->getSourceRange(); diff --git a/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp b/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp index 9c53129ff707d..c4acaf9092bae 100644 --- a/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp +++ b/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp @@ -86,13 +86,13 @@ struct DanglingGslPtrField { MyLongPointerFromConversion p2; // expected-note {{pointer member declared here}} \ // cfg-note 2 {{this field dangles}} - DanglingGslPtrField(int i) : p(&i) {} // cfg-warning {{address of stack memory escapes to a field}} + DanglingGslPtrField(int i) : p(&i) {} // cfg-warning {{parameter 'i' escapes to a field and will dangle}} DanglingGslPtrField() : p2(MyLongOwnerWithConversion{}) {} // expected-warning {{initializing pointer member 'p2' to point to a temporary object whose lifetime is shorter than the lifetime of the constructed object}} \ - // cfg-warning {{address of stack memory escapes to a field}} + // cfg-warning {{local temporary object escapes to a field and will dangle}} DanglingGslPtrField(double) : p(MyIntOwner{}) {} // expected-warning {{initializing pointer member 'p' to point to a temporary object whose lifetime is shorter than the lifetime of the constructed object}} \ - // cfg-warning {{address of stack memory escapes to a field}} - DanglingGslPtrField(MyIntOwner io) : p(io) {} // cfg-warning {{address of stack memory escapes to a field}} - DanglingGslPtrField(MyLongOwnerWithConversion lo) : p2(lo) {} // cfg-warning {{address of stack memory escapes to a field}} + // cfg-warning {{local temporary object escapes to a field and will dangle}} + DanglingGslPtrField(MyIntOwner io) : p(io) {} // cfg-warning {{parameter 'io' escapes to a field and will dangle}} + DanglingGslPtrField(MyLongOwnerWithConversion lo) : p2(lo) {} // cfg-warning {{parameter 'lo' escapes to a field and will dangle}} }; MyIntPointer danglingGslPtrFromLocal() { @@ -1124,7 +1124,7 @@ struct Foo2 { }; struct Test { - Test(Foo2 foo) : bar(foo.bar.get()), // cfg-warning-re {{address of stack memory escapes to a field. {{.*}} may have been moved}} + Test(Foo2 foo) : bar(foo.bar.get()), // cfg-warning-re {{parameter 'foo' may escape to a field and dangle. {{.*}} may have been moved}} storage(std::move(foo.bar)) {}; // cfg-note {{potentially moved here}} Bar* bar; // cfg-note {{this field dangles}} diff --git a/clang/test/Sema/warn-lifetime-safety-dangling-field.cpp b/clang/test/Sema/warn-lifetime-safety-dangling-field.cpp index 5a4de105f217d..21c3afe2aee89 100644 --- a/clang/test/Sema/warn-lifetime-safety-dangling-field.cpp +++ b/clang/test/Sema/warn-lifetime-safety-dangling-field.cpp @@ -11,23 +11,23 @@ std::string_view construct_view(const std::string& str [[clang::lifetimebound]]) struct CtorInit { std::string_view view; // expected-note {{this field dangles}} - CtorInit(std::string s) : view(s) {} // expected-warning {{address of stack memory escapes to a field}} + CtorInit(std::string s) : view(s) {} // expected-warning {{parameter 's' escapes to a field and will dangle}} }; struct CtorSet { std::string_view view; // expected-note {{this field dangles}} - CtorSet(std::string s) { view = s; } // expected-warning {{address of stack memory escapes to a field}} + CtorSet(std::string s) { view = s; } // expected-warning {{parameter 's' escapes to a field and will dangle}} }; struct CtorInitLifetimeBound { std::string_view view; // expected-note {{this field dangles}} - CtorInitLifetimeBound(std::string s) : view(construct_view(s)) {} // expected-warning {{address of stack memory escapes to a field}} + CtorInitLifetimeBound(std::string s) : view(construct_view(s)) {} // expected-warning {{parameter 's' escapes to a field and will dangle}} }; struct CtorInitButMoved { std::string_view view; // expected-note {{this field dangles}} CtorInitButMoved(std::string s) - : view(s) { // expected-warning-re {{address of stack memory escapes to a field. {{.*}} may have been moved}} + : view(s) { // expected-warning-re {{parameter 's' may escape to a field and dangle. {{.*}} may have been moved}} takeString(std::move(s)); // expected-note {{potentially moved here}} } }; @@ -36,7 +36,7 @@ struct CtorInitButMovedOwned { std::string_view view; // expected-note {{this field dangles}} std::string owned; CtorInitButMovedOwned(std::string s) - : view(s), // expected-warning-re {{address of stack memory escapes to a field. {{.*}} may have been moved}} + : view(s), // expected-warning-re {{parameter 's' may escape to a field and dangle. {{.*}} may have been moved}} owned(std::move(s)) {} // expected-note {{potentially moved here}} }; @@ -50,28 +50,28 @@ struct CtorInitButMovedOwnedOrderedCorrectly { struct CtorInitMultipleViews { std::string_view view1; // expected-note {{this field dangles}} std::string_view view2; // expected-note {{this field dangles}} - CtorInitMultipleViews(std::string s) : view1(s), // expected-warning {{address of stack memory escapes to a field}} - view2(s) {} // expected-warning {{address of stack memory escapes to a field}} + CtorInitMultipleViews(std::string s) : view1(s), // expected-warning {{parameter 's' escapes to a field and will dangle}} + view2(s) {} // expected-warning {{parameter 's' escapes to a field and will dangle}} }; struct CtorInitMultipleParams { std::string_view view1; // expected-note {{this field dangles}} std::string_view view2; // expected-note {{this field dangles}} - CtorInitMultipleParams(std::string s1, std::string s2) : view1(s1), // expected-warning {{address of stack memory escapes to a field}} - view2(s2) {} // expected-warning {{address of stack memory escapes to a field}} + CtorInitMultipleParams(std::string s1, std::string s2) : view1(s1), // expected-warning {{parameter 's1' escapes to a field and will dangle}} + view2(s2) {} // expected-warning {{parameter 's2' escapes to a field and will dangle}} }; struct CtorRefField { const std::string& str; // expected-note {{this field dangles}} const std::string_view& view; // expected-note {{this field dangles}} - CtorRefField(std::string s, std::string_view v) : str(s), // expected-warning {{address of stack memory escapes to a field}} - view(v) {} // expected-warning {{address of stack memory escapes to a field}} + CtorRefField(std::string s, std::string_view v) : str(s), // expected-warning {{parameter 's' escapes to a field and will dangle}} + view(v) {} // expected-warning {{parameter 'v' escapes to a field and will dangle}} CtorRefField(Dummy<1> ok, const std::string& s, const std::string_view& v): str(s), view(v) {} }; struct CtorPointerField { const char* ptr; // expected-note {{this field dangles}} - CtorPointerField(std::string s) : ptr(s.data()) {} // expected-warning {{address of stack memory escapes to a field}} + CtorPointerField(std::string s) : ptr(s.data()) {} // expected-warning {{parameter 's' escapes to a field and will dangle}} CtorPointerField(Dummy<1> ok, const std::string& s) : ptr(s.data()) {} CtorPointerField(Dummy<2> ok, std::string_view view) : ptr(view.data()) {} }; @@ -81,13 +81,13 @@ struct MemberSetters { const char* p; // expected-note 6 {{this field dangles}} void setWithParam(std::string s) { - view = s; // expected-warning {{address of stack memory escapes to a field}} - p = s.data(); // expected-warning {{address of stack memory escapes to a field}} + view = s; // expected-warning {{parameter 's' escapes to a field and will dangle}} + p = s.data(); // expected-warning {{parameter 's' escapes to a field and will dangle}} } void setWithParamAndReturn(std::string s) { - view = s; // expected-warning {{address of stack memory escapes to a field}} - p = s.data(); // expected-warning {{address of stack memory escapes to a field}} + view = s; // expected-warning {{parameter 's' escapes to a field and will dangle}} + p = s.data(); // expected-warning {{parameter 's' escapes to a field and will dangle}} return; } @@ -104,14 +104,14 @@ struct MemberSetters { void setWithLocal() { std::string s; - view = s; // expected-warning {{address of stack memory escapes to a field}} - p = s.data(); // expected-warning {{address of stack memory escapes to a field}} + view = s; // expected-warning {{local variable 's' escapes to a field and will dangle}} + p = s.data(); // expected-warning {{local variable 's' escapes to a field and will dangle}} } void setWithLocalButMoved() { std::string s; - view = s; // expected-warning-re {{address of stack memory escapes to a field. {{.*}} may have been moved}} - p = s.data(); // expected-warning-re {{address of stack memory escapes to a field. {{.*}} may have been moved}} + view = s; // expected-warning-re {{local variable 's' may escape to a field and dangle. {{.*}} may have been moved}} + p = s.data(); // expected-warning-re {{local variable 's' may escape to a field and dangle. {{.*}} may have been moved}} takeString(std::move(s)); // expected-note 2 {{potentially moved here}} } @@ -134,15 +134,15 @@ struct MemberSetters { p = kGlobal.data(); std::string local; - view = local; // expected-warning {{address of stack memory escapes to a field}} - p = local.data(); // expected-warning {{address of stack memory escapes to a field}} + view = local; // expected-warning {{local variable 'local' escapes to a field and will dangle}} + p = local.data(); // expected-warning {{local variable 'local' escapes to a field and will dangle}} } void use_after_scope() { { std::string local; - view = local; // expected-warning {{address of stack memory escapes to a field}} - p = local.data(); // expected-warning {{address of stack memory escapes to a field}} + view = local; // expected-warning {{local variable 'local' escapes to a field and will dangle}} + p = local.data(); // expected-warning {{local variable 'local' escapes to a field and will dangle}} } (void)view; (void)p; @@ -193,7 +193,7 @@ struct BaseWithPointer { struct DerivedWithCtor : BaseWithPointer { DerivedWithCtor(std::string s) { - view = s; // expected-warning {{address of stack memory escapes to a field}} + view = s; // expected-warning {{parameter 's' escapes to a field and will dangle}} } }; } // namespace DanglingPointerFieldInBaseClass @@ -205,7 +205,7 @@ struct HasCallback { void set_callback() { int local; - callback = [&local]() { (void)local; }; // expected-warning {{address of stack memory escapes to a field}} + callback = [&local]() { (void)local; }; // expected-warning {{local variable 'local' escapes to a field and will dangle}} } }; @@ -222,7 +222,7 @@ struct HasUniquePtrField { std::unique_ptr<LifetimeBoundCtor> field; // tu-note {{this field dangles}} void setWithParam(MyObj obj) { - field = std::make_unique<LifetimeBoundCtor>(obj); // tu-warning {{address of stack memory escapes to a field}} + field = std::make_unique<LifetimeBoundCtor>(obj); // tu-warning {{parameter 'obj' escapes to a field and will dangle}} } }; } // namespace MakeUnique diff --git a/clang/test/Sema/warn-lifetime-safety-dangling-global.cpp b/clang/test/Sema/warn-lifetime-safety-dangling-global.cpp index ac40c7df5a8f5..f8d5481377e47 100644 --- a/clang/test/Sema/warn-lifetime-safety-dangling-global.cpp +++ b/clang/test/Sema/warn-lifetime-safety-dangling-global.cpp @@ -22,14 +22,14 @@ void invoke_function_with_side_effects() { // We can however catch the inlined one of course! void inlined() { int local; - global = &local; // expected-warning {{address of stack memory escapes to global or static storage}} + global = &local; // expected-warning {{local variable 'local' escapes to global or static storage and will dangle}} global_backup = global; global = nullptr; } void store_local_in_global() { int local; - global = &local; // expected-warning {{address of stack memory escapes to global or static storage}} + global = &local; // expected-warning {{local variable 'local' escapes to global or static storage and will dangle}} } void store_then_clear() { @@ -40,5 +40,5 @@ void store_then_clear() { void dangling_static_field() { int local; - ObjWithStaticField::static_field = &local; // expected-warning {{address of stack memory escapes to global or static storage}} + ObjWithStaticField::static_field = &local; // expected-warning {{local variable 'local' escapes to global or static storage and will dangle}} } \ No newline at end of file diff --git a/clang/test/Sema/warn-lifetime-safety-suggestions.cpp b/clang/test/Sema/warn-lifetime-safety-suggestions.cpp index 24aacc9480533..32ef6e54d7f1c 100644 --- a/clang/test/Sema/warn-lifetime-safety-suggestions.cpp +++ b/clang/test/Sema/warn-lifetime-safety-suggestions.cpp @@ -665,7 +665,7 @@ struct HasSetterField { } void reset() { MyObj obj; - field = new LifetimeBoundCtor(obj); // expected-warning {{address of stack memory escapes to a field}} + field = new LifetimeBoundCtor(obj); // expected-warning {{local variable 'obj' escapes to a field and will dangle}} } }; diff --git a/clang/test/Sema/warn-lifetime-safety.cpp b/clang/test/Sema/warn-lifetime-safety.cpp index d5f558c7918b3..ee453b7341369 100644 --- a/clang/test/Sema/warn-lifetime-safety.cpp +++ b/clang/test/Sema/warn-lifetime-safety.cpp @@ -2448,7 +2448,7 @@ void from_template_instantiation() { struct FieldInitFromLifetimebound { S value; // expected-note {{this field dangles}} - FieldInitFromLifetimebound() : value(getS(std::string("temp"))) {} // expected-warning {{address of stack memory escapes to a field}} + FieldInitFromLifetimebound() : value(getS(std::string("temp"))) {} // expected-warning {{local temporary object escapes to a field and will dangle}} }; S S::return_self_after_registration() const { @@ -2638,12 +2638,12 @@ void nested_local_pointer() { struct PFieldFromParam { Pointer<Bar> value; // expected-note {{this field dangles}} - PFieldFromParam(Bar bar) : value(bar) {} // expected-warning {{address of stack memory escapes to a field}} + PFieldFromParam(Bar bar) : value(bar) {} // expected-warning {{parameter 'bar' escapes to a field and will dangle}} }; struct PFieldFromTemp { Pointer<Bar> value; // expected-note {{this field dangles}} - PFieldFromTemp() : value(Bar{}) {} // expected-warning {{address of stack memory escapes to a field}} + PFieldFromTemp() : value(Bar{}) {} // expected-warning {{local temporary object escapes to a field and will dangle}} }; } // namespace gslpointer_construction_from_lifetimebound @@ -3198,7 +3198,7 @@ struct S2 : S { namespace CXXDefaultInitExprTests { struct Holder { - std::string_view view = std::string("temporary"); // expected-warning {{address of stack memory escapes to a field}} expected-note {{this field dangles}} + std::string_view view = std::string("temporary"); // expected-warning {{local temporary object escapes to a field and will dangle}} expected-note {{this field dangles}} Holder() {} }; } // namespace CXXDefaultInitExprTests @@ -3210,7 +3210,7 @@ struct Y : X { void bar() { { int a; - x = &a; // expected-warning {{address of stack memory escapes to a field}} + x = &a; // expected-warning {{local variable 'a' escapes to a field and will dangle}} } (void)x; } >From 091a37eb5ceac8f242b445ee5cdfde0f30f0d9e5 Mon Sep 17 00:00:00 2001 From: NeKon69 <[email protected]> Date: Thu, 28 May 2026 14:07:36 +0300 Subject: [PATCH 2/2] Improve more diags --- .../clang/Basic/DiagnosticSemaKinds.td | 16 ++-- clang/lib/Sema/SemaLifetimeSafety.h | 78 ++++++++-------- .../Sema/warn-lifetime-analysis-nocfg.cpp | 24 ++--- .../warn-lifetime-safety-dangling-field.cpp | 88 +++++++++---------- .../warn-lifetime-safety-dangling-global.cpp | 12 +-- .../warn-lifetime-safety-invalidations.cpp | 32 +++---- .../Sema/warn-lifetime-safety-noescape.cpp | 10 +-- .../Sema/warn-lifetime-safety-suggestions.cpp | 18 ++-- clang/test/Sema/warn-lifetime-safety.cpp | 18 ++-- 9 files changed, 145 insertions(+), 151 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 9bb64bb0f5b84..83d32b501a0c6 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -10999,21 +10999,21 @@ def warn_lifetime_safety_invalidated_global DefaultIgnore; def warn_lifetime_safety_dangling_field - : Warning<"%0 escapes to a field and will dangle">, + : Warning<"stack memory associated with %0 escapes to a field which will dangle">, InGroup<LifetimeSafetyDanglingField>, DefaultIgnore; def warn_lifetime_safety_dangling_field_moved - : Warning<"%0 may escape to a field and dangle. " + : Warning<"stack memory associated with %0 may escape to a field which will dangle. " "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<LifetimeSafetyDanglingFieldMoved>, DefaultIgnore; def warn_lifetime_safety_dangling_global - : Warning<"%0 escapes to global or static storage and will dangle">, + : Warning<"stack memory associated with %0 escapes to global or static storage which will dangle">, InGroup<LifetimeSafetyDanglingGlobal>, DefaultIgnore; def warn_lifetime_safety_dangling_global_moved - : Warning<"%0 may escape to global or static storage and dangle. " + : Warning<"stack memory associated with %0 may escape to global or static storage which will dangle. " "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<LifetimeSafetyDanglingGlobalMoved>, @@ -11040,12 +11040,8 @@ def note_lifetime_safety_destroyed_here : Note<"destroyed here">; def note_lifetime_safety_freed_here : Note<"freed here">; def note_lifetime_safety_returned_here : Note<"returned here">; def note_lifetime_safety_moved_here : Note<"potentially moved here">; -def note_lifetime_safety_dangling_field_here: Note<"this field dangles">; -def note_lifetime_safety_dangling_global_here: Note<"this global dangles">; -def note_lifetime_safety_dangling_static_here: Note<"this static storage dangles">; -def note_lifetime_safety_escapes_to_field_here: Note<"escapes to this field">; -def note_lifetime_safety_escapes_to_global_here: Note<"escapes to this global storage">; -def note_lifetime_safety_escapes_to_static_storage_here: Note<"escapes to this static storage">; +def note_lifetime_safety_dangles_here: Note<"%0 dangles">; +def note_lifetime_safety_escapes_here: Note<"escapes to %0">; def note_lifetime_safety_lifetimebound_here: Note<"'lifetimebound' attribute appears here on the definition">; def warn_lifetime_safety_intra_tu_param_suggestion diff --git a/clang/lib/Sema/SemaLifetimeSafety.h b/clang/lib/Sema/SemaLifetimeSafety.h index 005d3187d27ec..bcebc9f3ed2eb 100644 --- a/clang/lib/Sema/SemaLifetimeSafety.h +++ b/clang/lib/Sema/SemaLifetimeSafety.h @@ -105,7 +105,8 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper { S.Diag(MovedExpr->getExprLoc(), diag::note_lifetime_safety_moved_here) << MovedExpr->getSourceRange(); S.Diag(DanglingField->getLocation(), - diag::note_lifetime_safety_dangling_field_here) + diag::note_lifetime_safety_dangles_here) + << getDiagSubjectDescription(DanglingField) << DanglingField->getEndLoc(); } @@ -122,14 +123,10 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper { if (MovedExpr) S.Diag(MovedExpr->getExprLoc(), diag::note_lifetime_safety_moved_here) << MovedExpr->getSourceRange(); - if (DanglingGlobal->isStaticLocal() || DanglingGlobal->isStaticDataMember()) - S.Diag(DanglingGlobal->getLocation(), - diag::note_lifetime_safety_dangling_static_here) - << DanglingGlobal->getEndLoc(); - else - S.Diag(DanglingGlobal->getLocation(), - diag::note_lifetime_safety_dangling_global_here) - << DanglingGlobal->getEndLoc(); + S.Diag(DanglingGlobal->getLocation(), + diag::note_lifetime_safety_dangles_here) + << getDiagSubjectDescription(DanglingGlobal) + << DanglingGlobal->getEndLoc(); } void reportUseAfterInvalidation(const Expr *IssueExpr, const Expr *UseExpr, @@ -177,7 +174,8 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper { S.Diag(InvalidationExpr->getExprLoc(), InvalidationDiag) << InvalidationExpr->getSourceRange(); S.Diag(DanglingField->getLocation(), - diag::note_lifetime_safety_dangling_field_here) + diag::note_lifetime_safety_dangles_here) + << getDiagSubjectDescription(DanglingField) << DanglingField->getEndLoc(); } @@ -193,7 +191,8 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper { S.Diag(InvalidationExpr->getExprLoc(), InvalidationDiag) << InvalidationExpr->getSourceRange(); S.Diag(DanglingField->getLocation(), - diag::note_lifetime_safety_dangling_field_here) + diag::note_lifetime_safety_dangles_here) + << getDiagSubjectDescription(DanglingField) << DanglingField->getEndLoc(); } @@ -208,14 +207,10 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper { << false << IssueExpr->getSourceRange(); S.Diag(InvalidationExpr->getExprLoc(), InvalidationDiag) << InvalidationExpr->getSourceRange(); - if (DanglingGlobal->isStaticLocal() || DanglingGlobal->isStaticDataMember()) - S.Diag(DanglingGlobal->getLocation(), - diag::note_lifetime_safety_dangling_static_here) - << DanglingGlobal->getEndLoc(); - else - S.Diag(DanglingGlobal->getLocation(), - diag::note_lifetime_safety_dangling_global_here) - << DanglingGlobal->getEndLoc(); + S.Diag(DanglingGlobal->getLocation(), + diag::note_lifetime_safety_dangles_here) + << getDiagSubjectDescription(DanglingGlobal) + << DanglingGlobal->getEndLoc(); } void reportInvalidatedGlobal(const ParmVarDecl *PVD, @@ -229,14 +224,10 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper { << true << PVD->getSourceRange(); S.Diag(InvalidationExpr->getExprLoc(), InvalidationDiag) << InvalidationExpr->getSourceRange(); - if (DanglingGlobal->isStaticLocal() || DanglingGlobal->isStaticDataMember()) - S.Diag(DanglingGlobal->getLocation(), - diag::note_lifetime_safety_dangling_static_here) - << DanglingGlobal->getEndLoc(); - else - S.Diag(DanglingGlobal->getLocation(), - diag::note_lifetime_safety_dangling_global_here) - << DanglingGlobal->getEndLoc(); + S.Diag(DanglingGlobal->getLocation(), + diag::note_lifetime_safety_dangles_here) + << getDiagSubjectDescription(DanglingGlobal) + << DanglingGlobal->getEndLoc(); } void suggestLifetimeboundToParmVar(WarningScope Scope, @@ -271,7 +262,8 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper { << EscapeExpr->getSourceRange(); else if (const auto *EscapeField = Target.dyn_cast<const FieldDecl *>()) S.Diag(EscapeField->getLocation(), - diag::note_lifetime_safety_escapes_to_field_here) + diag::note_lifetime_safety_escapes_here) + << getDiagSubjectDescription(EscapeField) << EscapeField->getSourceRange(); } @@ -378,9 +370,8 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper { diag::warn_lifetime_safety_noescape_escapes) << ParmWithNoescape->getSourceRange(); - S.Diag(EscapeField->getLocation(), - diag::note_lifetime_safety_escapes_to_field_here) - << EscapeField->getEndLoc(); + S.Diag(EscapeField->getLocation(), diag::note_lifetime_safety_escapes_here) + << getDiagSubjectDescription(EscapeField) << EscapeField->getEndLoc(); } void reportNoescapeViolation(const ParmVarDecl *ParmWithNoescape, @@ -388,14 +379,8 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper { S.Diag(ParmWithNoescape->getBeginLoc(), diag::warn_lifetime_safety_noescape_escapes) << ParmWithNoescape->getSourceRange(); - if (EscapeGlobal->isStaticLocal() || EscapeGlobal->isStaticDataMember()) - S.Diag(EscapeGlobal->getLocation(), - diag::note_lifetime_safety_escapes_to_static_storage_here) - << EscapeGlobal->getEndLoc(); - else - S.Diag(EscapeGlobal->getLocation(), - diag::note_lifetime_safety_escapes_to_global_here) - << EscapeGlobal->getEndLoc(); + S.Diag(EscapeGlobal->getLocation(), diag::note_lifetime_safety_escapes_here) + << getDiagSubjectDescription(EscapeGlobal) << EscapeGlobal->getEndLoc(); } void addLifetimeBoundToImplicitThis(const CXXMethodDecl *MD) override { @@ -406,7 +391,20 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper { std::string getDiagSubjectDescription(const ValueDecl *VD) { std::string Res; llvm::raw_string_ostream OS(Res); - OS << (isa<ParmVarDecl>(VD) ? "parameter" : "local variable"); + if (isa<FieldDecl>(VD)) { + OS << "field"; + } else if (isa<ParmVarDecl>(VD)) { + OS << "parameter"; + } else if (const auto *Var = dyn_cast<VarDecl>(VD)) { + if (Var->isStaticLocal() || Var->isStaticDataMember()) + OS << "static variable"; + else if (Var->hasGlobalStorage()) + OS << "global variable"; + else + OS << "local variable"; + } else { + OS << "local variable"; + } OS << " '"; VD->getNameForDiagnostic(OS, S.getPrintingPolicy(), /*Qualified=*/false); OS << "'"; diff --git a/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp b/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp index c4acaf9092bae..89a04bb06f295 100644 --- a/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp +++ b/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp @@ -82,17 +82,17 @@ void dangligGslPtrFromTemporary() { struct DanglingGslPtrField { MyIntPointer p; // expected-note {{pointer member declared here}} \ - // cfg-note 3 {{this field dangles}} + // cfg-note 3 {{field 'p' dangles}} MyLongPointerFromConversion p2; // expected-note {{pointer member declared here}} \ - // cfg-note 2 {{this field dangles}} + // cfg-note 2 {{field 'p2' dangles}} - DanglingGslPtrField(int i) : p(&i) {} // cfg-warning {{parameter 'i' escapes to a field and will dangle}} + DanglingGslPtrField(int i) : p(&i) {} // cfg-warning {{stack memory associated with parameter 'i' escapes to a field which will dangle}} DanglingGslPtrField() : p2(MyLongOwnerWithConversion{}) {} // expected-warning {{initializing pointer member 'p2' to point to a temporary object whose lifetime is shorter than the lifetime of the constructed object}} \ - // cfg-warning {{local temporary object escapes to a field and will dangle}} + // cfg-warning {{stack memory associated with local temporary object escapes to a field which will dangle}} DanglingGslPtrField(double) : p(MyIntOwner{}) {} // expected-warning {{initializing pointer member 'p' to point to a temporary object whose lifetime is shorter than the lifetime of the constructed object}} \ - // cfg-warning {{local temporary object escapes to a field and will dangle}} - DanglingGslPtrField(MyIntOwner io) : p(io) {} // cfg-warning {{parameter 'io' escapes to a field and will dangle}} - DanglingGslPtrField(MyLongOwnerWithConversion lo) : p2(lo) {} // cfg-warning {{parameter 'lo' escapes to a field and will dangle}} + // cfg-warning {{stack memory associated with local temporary object escapes to a field which will dangle}} + DanglingGslPtrField(MyIntOwner io) : p(io) {} // cfg-warning {{stack memory associated with parameter 'io' escapes to a field which will dangle}} + DanglingGslPtrField(MyLongOwnerWithConversion lo) : p2(lo) {} // cfg-warning {{stack memory associated with parameter 'lo' escapes to a field which will dangle}} }; MyIntPointer danglingGslPtrFromLocal() { @@ -361,8 +361,8 @@ struct X { pointee(*up), // cfg-warning {{may have been moved.}} pointee2(up.get()), // cfg-warning {{may have been moved.}} pointer(std::move(up)) {} // cfg-note 2 {{potentially moved here}} - int &pointee; // cfg-note {{this field dangles}} - int *pointee2; // cfg-note {{this field dangles}} + int &pointee; // cfg-note {{field 'pointee' dangles}} + int *pointee2; // cfg-note {{field 'pointee2' dangles}} std::unique_ptr<int> pointer; }; @@ -375,7 +375,7 @@ struct X2 { X2(XOwner owner) : pointee(owner.get()), // cfg-warning {{may have been moved.}} owner(std::move(owner)) {} // cfg-note {{potentially moved here}} - int* pointee; // cfg-note {{this field dangles}} + int* pointee; // cfg-note {{field 'pointee' dangles}} XOwner owner; }; @@ -1124,10 +1124,10 @@ struct Foo2 { }; struct Test { - Test(Foo2 foo) : bar(foo.bar.get()), // cfg-warning-re {{parameter 'foo' may escape to a field and dangle. {{.*}} may have been moved}} + Test(Foo2 foo) : bar(foo.bar.get()), // cfg-warning-re {{stack memory associated with parameter 'foo' may escape to a field which will dangle. {{.*}} may have been moved}} storage(std::move(foo.bar)) {}; // cfg-note {{potentially moved here}} - Bar* bar; // cfg-note {{this field dangles}} + Bar* bar; // cfg-note {{field 'bar' dangles}} std::unique_ptr<Bar> storage; }; diff --git a/clang/test/Sema/warn-lifetime-safety-dangling-field.cpp b/clang/test/Sema/warn-lifetime-safety-dangling-field.cpp index 21c3afe2aee89..55ba0be87f2d7 100644 --- a/clang/test/Sema/warn-lifetime-safety-dangling-field.cpp +++ b/clang/test/Sema/warn-lifetime-safety-dangling-field.cpp @@ -10,33 +10,33 @@ void takeString(std::string&& s); std::string_view construct_view(const std::string& str [[clang::lifetimebound]]); struct CtorInit { - std::string_view view; // expected-note {{this field dangles}} - CtorInit(std::string s) : view(s) {} // expected-warning {{parameter 's' escapes to a field and will dangle}} + std::string_view view; // expected-note {{field 'view' dangles}} + CtorInit(std::string s) : view(s) {} // expected-warning {{stack memory associated with parameter 's' escapes to a field which will dangle}} }; struct CtorSet { - std::string_view view; // expected-note {{this field dangles}} - CtorSet(std::string s) { view = s; } // expected-warning {{parameter 's' escapes to a field and will dangle}} + std::string_view view; // expected-note {{field 'view' dangles}} + CtorSet(std::string s) { view = s; } // expected-warning {{stack memory associated with parameter 's' escapes to a field which will dangle}} }; struct CtorInitLifetimeBound { - std::string_view view; // expected-note {{this field dangles}} - CtorInitLifetimeBound(std::string s) : view(construct_view(s)) {} // expected-warning {{parameter 's' escapes to a field and will dangle}} + std::string_view view; // expected-note {{field 'view' dangles}} + CtorInitLifetimeBound(std::string s) : view(construct_view(s)) {} // expected-warning {{stack memory associated with parameter 's' escapes to a field which will dangle}} }; struct CtorInitButMoved { - std::string_view view; // expected-note {{this field dangles}} + std::string_view view; // expected-note {{field 'view' dangles}} CtorInitButMoved(std::string s) - : view(s) { // expected-warning-re {{parameter 's' may escape to a field and dangle. {{.*}} may have been moved}} + : view(s) { // expected-warning-re {{stack memory associated with parameter 's' may escape to a field which will dangle. {{.*}} may have been moved}} takeString(std::move(s)); // expected-note {{potentially moved here}} } }; struct CtorInitButMovedOwned { - std::string_view view; // expected-note {{this field dangles}} + std::string_view view; // expected-note {{field 'view' dangles}} std::string owned; CtorInitButMovedOwned(std::string s) - : view(s), // expected-warning-re {{parameter 's' may escape to a field and dangle. {{.*}} may have been moved}} + : view(s), // expected-warning-re {{stack memory associated with parameter 's' may escape to a field which will dangle. {{.*}} may have been moved}} owned(std::move(s)) {} // expected-note {{potentially moved here}} }; @@ -48,46 +48,46 @@ struct CtorInitButMovedOwnedOrderedCorrectly { }; struct CtorInitMultipleViews { - std::string_view view1; // expected-note {{this field dangles}} - std::string_view view2; // expected-note {{this field dangles}} - CtorInitMultipleViews(std::string s) : view1(s), // expected-warning {{parameter 's' escapes to a field and will dangle}} - view2(s) {} // expected-warning {{parameter 's' escapes to a field and will dangle}} + std::string_view view1; // expected-note {{field 'view1' dangles}} + std::string_view view2; // expected-note {{field 'view2' dangles}} + CtorInitMultipleViews(std::string s) : view1(s), // expected-warning {{stack memory associated with parameter 's' escapes to a field which will dangle}} + view2(s) {} // expected-warning {{stack memory associated with parameter 's' escapes to a field which will dangle}} }; struct CtorInitMultipleParams { - std::string_view view1; // expected-note {{this field dangles}} - std::string_view view2; // expected-note {{this field dangles}} - CtorInitMultipleParams(std::string s1, std::string s2) : view1(s1), // expected-warning {{parameter 's1' escapes to a field and will dangle}} - view2(s2) {} // expected-warning {{parameter 's2' escapes to a field and will dangle}} + std::string_view view1; // expected-note {{field 'view1' dangles}} + std::string_view view2; // expected-note {{field 'view2' dangles}} + CtorInitMultipleParams(std::string s1, std::string s2) : view1(s1), // expected-warning {{stack memory associated with parameter 's1' escapes to a field which will dangle}} + view2(s2) {} // expected-warning {{stack memory associated with parameter 's2' escapes to a field which will dangle}} }; struct CtorRefField { - const std::string& str; // expected-note {{this field dangles}} - const std::string_view& view; // expected-note {{this field dangles}} - CtorRefField(std::string s, std::string_view v) : str(s), // expected-warning {{parameter 's' escapes to a field and will dangle}} - view(v) {} // expected-warning {{parameter 'v' escapes to a field and will dangle}} + const std::string& str; // expected-note {{field 'str' dangles}} + const std::string_view& view; // expected-note {{field 'view' dangles}} + CtorRefField(std::string s, std::string_view v) : str(s), // expected-warning {{stack memory associated with parameter 's' escapes to a field which will dangle}} + view(v) {} // expected-warning {{stack memory associated with parameter 'v' escapes to a field which will dangle}} CtorRefField(Dummy<1> ok, const std::string& s, const std::string_view& v): str(s), view(v) {} }; struct CtorPointerField { - const char* ptr; // expected-note {{this field dangles}} - CtorPointerField(std::string s) : ptr(s.data()) {} // expected-warning {{parameter 's' escapes to a field and will dangle}} + const char* ptr; // expected-note {{field 'ptr' dangles}} + CtorPointerField(std::string s) : ptr(s.data()) {} // expected-warning {{stack memory associated with parameter 's' escapes to a field which will dangle}} CtorPointerField(Dummy<1> ok, const std::string& s) : ptr(s.data()) {} CtorPointerField(Dummy<2> ok, std::string_view view) : ptr(view.data()) {} }; struct MemberSetters { - std::string_view view; // expected-note 6 {{this field dangles}} - const char* p; // expected-note 6 {{this field dangles}} + std::string_view view; // expected-note 6 {{field 'view' dangles}} + const char* p; // expected-note 6 {{field 'p' dangles}} void setWithParam(std::string s) { - view = s; // expected-warning {{parameter 's' escapes to a field and will dangle}} - p = s.data(); // expected-warning {{parameter 's' escapes to a field and will dangle}} + view = s; // expected-warning {{stack memory associated with parameter 's' escapes to a field which will dangle}} + p = s.data(); // expected-warning {{stack memory associated with parameter 's' escapes to a field which will dangle}} } void setWithParamAndReturn(std::string s) { - view = s; // expected-warning {{parameter 's' escapes to a field and will dangle}} - p = s.data(); // expected-warning {{parameter 's' escapes to a field and will dangle}} + view = s; // expected-warning {{stack memory associated with parameter 's' escapes to a field which will dangle}} + p = s.data(); // expected-warning {{stack memory associated with parameter 's' escapes to a field which will dangle}} return; } @@ -104,14 +104,14 @@ struct MemberSetters { void setWithLocal() { std::string s; - view = s; // expected-warning {{local variable 's' escapes to a field and will dangle}} - p = s.data(); // expected-warning {{local variable 's' escapes to a field and will dangle}} + view = s; // expected-warning {{stack memory associated with local variable 's' escapes to a field which will dangle}} + p = s.data(); // expected-warning {{stack memory associated with local variable 's' escapes to a field which will dangle}} } void setWithLocalButMoved() { std::string s; - view = s; // expected-warning-re {{local variable 's' may escape to a field and dangle. {{.*}} may have been moved}} - p = s.data(); // expected-warning-re {{local variable 's' may escape to a field and dangle. {{.*}} may have been moved}} + view = s; // expected-warning-re {{stack memory associated with local variable 's' may escape to a field which will dangle. {{.*}} may have been moved}} + p = s.data(); // expected-warning-re {{stack memory associated with local variable 's' may escape to a field which will dangle. {{.*}} may have been moved}} takeString(std::move(s)); // expected-note 2 {{potentially moved here}} } @@ -134,15 +134,15 @@ struct MemberSetters { p = kGlobal.data(); std::string local; - view = local; // expected-warning {{local variable 'local' escapes to a field and will dangle}} - p = local.data(); // expected-warning {{local variable 'local' escapes to a field and will dangle}} + view = local; // expected-warning {{stack memory associated with local variable 'local' escapes to a field which will dangle}} + p = local.data(); // expected-warning {{stack memory associated with local variable 'local' escapes to a field which will dangle}} } void use_after_scope() { { std::string local; - view = local; // expected-warning {{local variable 'local' escapes to a field and will dangle}} - p = local.data(); // expected-warning {{local variable 'local' escapes to a field and will dangle}} + view = local; // expected-warning {{stack memory associated with local variable 'local' escapes to a field which will dangle}} + p = local.data(); // expected-warning {{stack memory associated with local variable 'local' escapes to a field which will dangle}} } (void)view; (void)p; @@ -188,12 +188,12 @@ struct IndirectEscape2 { namespace DanglingPointerFieldInBaseClass { struct BaseWithPointer { - std::string_view view; // expected-note {{this field dangles}} + std::string_view view; // expected-note {{field 'view' dangles}} }; struct DerivedWithCtor : BaseWithPointer { DerivedWithCtor(std::string s) { - view = s; // expected-warning {{parameter 's' escapes to a field and will dangle}} + view = s; // expected-warning {{stack memory associated with parameter 's' escapes to a field which will dangle}} } }; } // namespace DanglingPointerFieldInBaseClass @@ -201,11 +201,11 @@ struct DerivedWithCtor : BaseWithPointer { namespace callable_wrappers { struct HasCallback { - std::function<void()> callback; // expected-note {{this field dangles}} + std::function<void()> callback; // expected-note {{field 'callback' dangles}} void set_callback() { int local; - callback = [&local]() { (void)local; }; // expected-warning {{local variable 'local' escapes to a field and will dangle}} + callback = [&local]() { (void)local; }; // expected-warning {{stack memory associated with local variable 'local' escapes to a field which will dangle}} } }; @@ -219,10 +219,10 @@ struct LifetimeBoundCtor { }; struct HasUniquePtrField { - std::unique_ptr<LifetimeBoundCtor> field; // tu-note {{this field dangles}} + std::unique_ptr<LifetimeBoundCtor> field; // tu-note {{field 'field' dangles}} void setWithParam(MyObj obj) { - field = std::make_unique<LifetimeBoundCtor>(obj); // tu-warning {{parameter 'obj' escapes to a field and will dangle}} + field = std::make_unique<LifetimeBoundCtor>(obj); // tu-warning {{stack memory associated with parameter 'obj' escapes to a field which will dangle}} } }; } // namespace MakeUnique diff --git a/clang/test/Sema/warn-lifetime-safety-dangling-global.cpp b/clang/test/Sema/warn-lifetime-safety-dangling-global.cpp index f8d5481377e47..a1adc930c2281 100644 --- a/clang/test/Sema/warn-lifetime-safety-dangling-global.cpp +++ b/clang/test/Sema/warn-lifetime-safety-dangling-global.cpp @@ -1,10 +1,10 @@ // RUN: %clang_cc1 -fsyntax-only -Wlifetime-safety -Wno-dangling -verify %s -int *global; // expected-note {{this global dangles}} -int *global_backup; // expected-note {{this global dangles}} +int *global; // expected-note {{global variable 'global' dangles}} +int *global_backup; // expected-note {{global variable 'global_backup' dangles}} struct ObjWithStaticField { - static int *static_field; // expected-note {{this static storage dangles}} + static int *static_field; // expected-note {{static variable 'static_field' dangles}} }; void save_global() { @@ -22,14 +22,14 @@ void invoke_function_with_side_effects() { // We can however catch the inlined one of course! void inlined() { int local; - global = &local; // expected-warning {{local variable 'local' escapes to global or static storage and will dangle}} + global = &local; // expected-warning {{stack memory associated with local variable 'local' escapes to global or static storage which will dangle}} global_backup = global; global = nullptr; } void store_local_in_global() { int local; - global = &local; // expected-warning {{local variable 'local' escapes to global or static storage and will dangle}} + global = &local; // expected-warning {{stack memory associated with local variable 'local' escapes to global or static storage which will dangle}} } void store_then_clear() { @@ -40,5 +40,5 @@ void store_then_clear() { void dangling_static_field() { int local; - ObjWithStaticField::static_field = &local; // expected-warning {{local variable 'local' escapes to global or static storage and will dangle}} + ObjWithStaticField::static_field = &local; // expected-warning {{stack memory associated with local variable 'local' escapes to global or static storage which will dangle}} } \ No newline at end of file diff --git a/clang/test/Sema/warn-lifetime-safety-invalidations.cpp b/clang/test/Sema/warn-lifetime-safety-invalidations.cpp index 35077b547fc95..62ccee0dd4da4 100644 --- a/clang/test/Sema/warn-lifetime-safety-invalidations.cpp +++ b/clang/test/Sema/warn-lifetime-safety-invalidations.cpp @@ -518,7 +518,7 @@ std::string StableString; // FIXME: Distinguish owner-borrow from interior-borrow. struct SinkOwnerBorrow { - std::string *dest_; // expected-note {{this field dangles}} + std::string *dest_; // expected-note {{field 'dest_' dangles}} SinkOwnerBorrow(std::string *dest, int n) : dest_(dest) { // expected-warning {{parameter which escapes to a field is later invalidated}} if (n > 0) @@ -527,7 +527,7 @@ struct SinkOwnerBorrow { }; struct SinkInteriorBorrow { - const char *dest_; // expected-note {{this field dangles}} + const char *dest_; // expected-note {{field 'dest_' dangles}} SinkInteriorBorrow(std::string *dest, int n) : dest_(dest->data()) { // expected-warning {{parameter which escapes to a field is later invalidated}} if (n > 0) @@ -536,13 +536,13 @@ struct SinkInteriorBorrow { }; struct S { - std::string_view FieldFromLocalVector; // expected-note {{this field dangles}} - std::string_view FieldFromByValueParamVector; // expected-note {{this field dangles}} - std::string_view FieldFromLocalString; // expected-note {{this field dangles}} - std::string_view FieldFromByValueParamString; // expected-note {{this field dangles}} - std::string_view FieldFromRefParamString; // expected-note {{this field dangles}} - int *FieldFromNew; // expected-note {{this field dangles}} - int *FieldFromPointerParam; // expected-note {{this field dangles}} + std::string_view FieldFromLocalVector; // expected-note {{field 'FieldFromLocalVector' dangles}} + std::string_view FieldFromByValueParamVector; // expected-note {{field 'FieldFromByValueParamVector' dangles}} + std::string_view FieldFromLocalString; // expected-note {{field 'FieldFromLocalString' dangles}} + std::string_view FieldFromByValueParamString; // expected-note {{field 'FieldFromByValueParamString' dangles}} + std::string_view FieldFromRefParamString; // expected-note {{field 'FieldFromRefParamString' dangles}} + int *FieldFromNew; // expected-note {{field 'FieldFromNew' dangles}} + int *FieldFromPointerParam; // expected-note {{field 'FieldFromPointerParam' dangles}} std::string_view FieldReassigned; void InvalidatedFieldLocalVector() { @@ -594,15 +594,15 @@ struct S { namespace InvalidatedGlobal { std::string StableString; -std::string_view GlobalFromLocalVector; // expected-note {{this global dangles}} -std::string_view GlobalFromByValueParamString; // expected-note {{this global dangles}} -std::string_view GlobalFromRefParamString; // expected-note {{this global dangles}} -int *GlobalFromNew; // expected-note {{this global dangles}} -int *GlobalFromPointerParam; // expected-note {{this global dangles}} +std::string_view GlobalFromLocalVector; // expected-note {{global variable 'GlobalFromLocalVector' dangles}} +std::string_view GlobalFromByValueParamString; // expected-note {{global variable 'GlobalFromByValueParamString' dangles}} +std::string_view GlobalFromRefParamString; // expected-note {{global variable 'GlobalFromRefParamString' dangles}} +int *GlobalFromNew; // expected-note {{global variable 'GlobalFromNew' dangles}} +int *GlobalFromPointerParam; // expected-note {{global variable 'GlobalFromPointerParam' dangles}} std::string_view GlobalReassigned; struct S { - static std::string_view StaticMember; // expected-note {{this static storage dangles}} + static std::string_view StaticMember; // expected-note {{static variable 'StaticMember' dangles}} }; void InvalidatedGlobalLocalVector() { @@ -633,7 +633,7 @@ void InvalidatedGlobalDeleteParam(int *p) { // expected-warning {{parameter whic } void InvalidatedStaticLocalString() { - static std::string_view StaticFromLocalString; // expected-note {{this static storage dangles}} + static std::string_view StaticFromLocalString; // expected-note {{static variable 'StaticFromLocalString' dangles}} std::string s; StaticFromLocalString = s; // expected-warning {{object whose reference escapes to global or static storage is later invalidated}} s.clear(); // expected-note {{invalidated here}} diff --git a/clang/test/Sema/warn-lifetime-safety-noescape.cpp b/clang/test/Sema/warn-lifetime-safety-noescape.cpp index 4bb57e6b9df95..b3d371f899ae2 100644 --- a/clang/test/Sema/warn-lifetime-safety-noescape.cpp +++ b/clang/test/Sema/warn-lifetime-safety-noescape.cpp @@ -113,13 +113,13 @@ View escape_through_unannotated_call(const MyObj& in [[clang::noescape]]) { // e return no_annotation_identity(in); // expected-note {{returned here}} } -View global_view; // expected-note {{escapes to this global storage}} +View global_view; // expected-note {{escapes to global variable 'global_view'}} void escape_through_global_var(const MyObj& in [[clang::noescape]]) { // expected-warning {{parameter is marked [[clang::noescape]] but escapes}} global_view = in; } struct ObjWithStaticField { - static int *static_field; // expected-note {{escapes to this static storage}} + static int *static_field; // expected-note {{escapes to static variable 'static_field'}} }; void escape_to_static_data_member(int *data [[clang::noescape]]) { // expected-warning {{parameter is marked [[clang::noescape]] but escapes}} @@ -129,11 +129,11 @@ void escape_to_static_data_member(int *data [[clang::noescape]]) { // expected-w void escape_through_static_local(int *data [[clang::noescape]]) { // expected-warning {{parameter is marked [[clang::noescape]] but escapes}} - static int *static_local; // expected-note {{escapes to this static storage}} + static int *static_local; // expected-note {{escapes to static variable 'static_local'}} static_local = data; } -thread_local int *thread_local_storage; // expected-note {{escapes to this global storage}} +thread_local int *thread_local_storage; // expected-note {{escapes to global variable 'thread_local_storage'}} void escape_through_thread_local(int *data [[clang::noescape]]) { // expected-warning {{parameter is marked [[clang::noescape]] but escapes}} // FIXME: We might want to report whenever anything derived from a @@ -147,7 +147,7 @@ struct ObjConsumer { member_view = in; } - View member_view; // expected-note {{escapes to this field}} + View member_view; // expected-note {{escapes to field 'member_view'}} }; // FIXME: Escaping through another param is not detected. diff --git a/clang/test/Sema/warn-lifetime-safety-suggestions.cpp b/clang/test/Sema/warn-lifetime-safety-suggestions.cpp index 32ef6e54d7f1c..6b8d8908f11cb 100644 --- a/clang/test/Sema/warn-lifetime-safety-suggestions.cpp +++ b/clang/test/Sema/warn-lifetime-safety-suggestions.cpp @@ -518,7 +518,7 @@ S forward(const MyObj &obj) { // expected-warning {{parameter in intra-TU functi namespace capturing_constructor { struct CaptureRefToView { - View v; // expected-note {{escapes to this field}} + View v; // expected-note {{escapes to field 'v'}} CaptureRefToView(const MyObj& obj) : v(obj) {} // expected-warning {{parameter in intra-TU function should be marked [[clang::lifetimebound]]}} }; @@ -529,7 +529,7 @@ CaptureRefToView test_ref_to_view() { } struct CaptureRefToPtr { - const MyObj* p; // expected-note {{escapes to this field}} + const MyObj* p; // expected-note {{escapes to field 'p'}} CaptureRefToPtr(const MyObj& obj) : p(&obj) {} // expected-warning {{parameter in intra-TU function should be marked [[clang::lifetimebound]]}} }; @@ -540,7 +540,7 @@ CaptureRefToPtr test_ref_to_ptr() { } struct CaptureViewToView { - View v; // expected-note {{escapes to this field}} + View v; // expected-note {{escapes to field 'v'}} CaptureViewToView(View v_param) : v(v_param) {} // expected-warning {{parameter in intra-TU function should be marked [[clang::lifetimebound]]}} }; @@ -552,7 +552,7 @@ CaptureViewToView test_view_to_view() { } struct CapturePtrToPtr { - const MyObj* p; // expected-note {{escapes to this field}} + const MyObj* p; // expected-note {{escapes to field 'p'}} CapturePtrToPtr(const MyObj* p_param) : p(p_param) {} // expected-warning {{parameter in intra-TU function should be marked [[clang::lifetimebound]]}} }; @@ -563,7 +563,7 @@ CapturePtrToPtr test_ptr_to_ptr() { } struct CaptureRefToRef { - const MyObj& r; // expected-note {{escapes to this field}} + const MyObj& r; // expected-note {{escapes to field 'r'}} CaptureRefToRef(const MyObj& obj) : r(obj) {} // expected-warning {{parameter in intra-TU function should be marked [[clang::lifetimebound]]}} }; @@ -574,7 +574,7 @@ CaptureRefToRef test_ref_to_ref() { } struct BaseWithView { - View v; // expected-note {{escapes to this field}} + View v; // expected-note {{escapes to field 'v'}} }; struct CaptureRefToBaseView : BaseWithView { CaptureRefToBaseView(const MyObj& obj) { // expected-warning {{parameter in intra-TU function should be marked [[clang::lifetimebound]]}} @@ -647,7 +647,7 @@ struct LifetimeBoundCtor { }; struct HasCtorField { - LifetimeBoundCtor* field; // expected-note {{escapes to this field}} + LifetimeBoundCtor* field; // expected-note {{escapes to field 'field'}} HasCtorField(const MyObj& obj) : field(new LifetimeBoundCtor(obj)) {} // expected-warning {{parameter in intra-TU function should be marked [[clang::lifetimebound]]}} }; @@ -658,14 +658,14 @@ HasCtorField test_dangling_field_ctor() { } struct HasSetterField { - LifetimeBoundCtor* field; // expected-note {{this field dangles}} + LifetimeBoundCtor* field; // expected-note {{field 'field' dangles}} // FIXME: Does not currently suggest `lifetime_capture_by(this)` (even without `new`) void set(const MyObj& obj) { field = new LifetimeBoundCtor(obj); } void reset() { MyObj obj; - field = new LifetimeBoundCtor(obj); // expected-warning {{local variable 'obj' escapes to a field and will dangle}} + field = new LifetimeBoundCtor(obj); // expected-warning {{stack memory associated with local variable 'obj' escapes to a field which will dangle}} } }; diff --git a/clang/test/Sema/warn-lifetime-safety.cpp b/clang/test/Sema/warn-lifetime-safety.cpp index ee453b7341369..dd8aa66cea042 100644 --- a/clang/test/Sema/warn-lifetime-safety.cpp +++ b/clang/test/Sema/warn-lifetime-safety.cpp @@ -2447,8 +2447,8 @@ void from_template_instantiation() { } struct FieldInitFromLifetimebound { - S value; // expected-note {{this field dangles}} - FieldInitFromLifetimebound() : value(getS(std::string("temp"))) {} // expected-warning {{local temporary object escapes to a field and will dangle}} + S value; // expected-note {{field 'value' dangles}} + FieldInitFromLifetimebound() : value(getS(std::string("temp"))) {} // expected-warning {{stack memory associated with local temporary object escapes to a field which will dangle}} }; S S::return_self_after_registration() const { @@ -2637,13 +2637,13 @@ void nested_local_pointer() { } struct PFieldFromParam { - Pointer<Bar> value; // expected-note {{this field dangles}} - PFieldFromParam(Bar bar) : value(bar) {} // expected-warning {{parameter 'bar' escapes to a field and will dangle}} + Pointer<Bar> value; // expected-note {{field 'value' dangles}} + PFieldFromParam(Bar bar) : value(bar) {} // expected-warning {{stack memory associated with parameter 'bar' escapes to a field which will dangle}} }; struct PFieldFromTemp { - Pointer<Bar> value; // expected-note {{this field dangles}} - PFieldFromTemp() : value(Bar{}) {} // expected-warning {{local temporary object escapes to a field and will dangle}} + Pointer<Bar> value; // expected-note {{field 'value' dangles}} + PFieldFromTemp() : value(Bar{}) {} // expected-warning {{stack memory associated with local temporary object escapes to a field which will dangle}} }; } // namespace gslpointer_construction_from_lifetimebound @@ -3198,19 +3198,19 @@ struct S2 : S { namespace CXXDefaultInitExprTests { struct Holder { - std::string_view view = std::string("temporary"); // expected-warning {{local temporary object escapes to a field and will dangle}} expected-note {{this field dangles}} + std::string_view view = std::string("temporary"); // expected-warning {{stack memory associated with local temporary object escapes to a field which will dangle}} expected-note {{field 'view' dangles}} Holder() {} }; } // namespace CXXDefaultInitExprTests namespace base_class_fields { -struct X { int* x; }; // expected-note {{this field dangles}} +struct X { int* x; }; // expected-note {{field 'x' dangles}} struct Y : X { int* y; void bar() { { int a; - x = &a; // expected-warning {{local variable 'a' escapes to a field and will dangle}} + x = &a; // expected-warning {{stack memory associated with local variable 'a' escapes to a field which will dangle}} } (void)x; } _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
