https://github.com/usx95 updated https://github.com/llvm/llvm-project/pull/203577
>From 961f92d6392188517ef9b4d5360897bad44f899b Mon Sep 17 00:00:00 2001 From: Utkarsh Saxena <[email protected]> Date: Fri, 12 Jun 2026 16:25:09 +0000 Subject: [PATCH] users/usx95/helpful-invalidations --- .../clang/Basic/DiagnosticSemaKinds.td | 8 +- clang/lib/Sema/SemaLifetimeSafety.h | 20 ++- .../Sema/LifetimeSafety/invalidations.cpp | 148 +++++++++--------- clang/test/Sema/LifetimeSafety/safety.cpp | 8 +- 4 files changed, 96 insertions(+), 88 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 9691963d4fe7e..8097800e6744a 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -10981,7 +10981,7 @@ def warn_lifetime_safety_use_after_scope_moved : Warning< InGroup<LifetimeSafetyUseAfterScopeMoved>, DefaultIgnore; def warn_lifetime_safety_use_after_free : Warning< - "%select{allocated object|parameter}0 does not live long enough">, + "%0 does not live long enough">, InGroup<LifetimeSafetyUseAfterFree>, DefaultIgnore; def warn_lifetime_safety_return_stack_addr : Warning< @@ -10995,15 +10995,15 @@ def warn_lifetime_safety_return_stack_addr_moved : Warning< InGroup<LifetimeSafetyReturnStackAddrMoved>, DefaultIgnore; def warn_lifetime_safety_invalidation - : Warning<"%select{object whose reference is captured|parameter}0 is later invalidated">, + : Warning<"%0 is later invalidated">, InGroup<LifetimeSafetyInvalidation>, DefaultIgnore; def warn_lifetime_safety_invalidated_field - : Warning<"%select{object whose reference|parameter which}0 escapes to a field is later invalidated">, + : Warning<"%0 escapes to the %1 and is later invalidated">, InGroup<LifetimeSafetyInvalidation>, DefaultIgnore; def warn_lifetime_safety_invalidated_global - : Warning<"%select{object whose reference|parameter which}0 escapes to global or static storage is later invalidated">, + : Warning<"%0 escapes to the %1 and is later invalidated">, InGroup<LifetimeSafetyInvalidation>, DefaultIgnore; diff --git a/clang/lib/Sema/SemaLifetimeSafety.h b/clang/lib/Sema/SemaLifetimeSafety.h index 565c30f74cf9a..36ad0a8a358ae 100644 --- a/clang/lib/Sema/SemaLifetimeSafety.h +++ b/clang/lib/Sema/SemaLifetimeSafety.h @@ -151,7 +151,7 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper { ? diag::note_lifetime_safety_freed_here : diag::note_lifetime_safety_invalidated_here; S.Diag(IssueExpr->getExprLoc(), WarnDiag) - << false << IssueExpr->getSourceRange(); + << getDiagSubjectDescription(IssueExpr) << IssueExpr->getSourceRange(); S.Diag(InvalidationExpr->getExprLoc(), UseDiag) << InvalidationExpr->getSourceRange(); S.Diag(UseExpr->getExprLoc(), diag::note_lifetime_safety_used_here) @@ -168,7 +168,7 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper { : diag::note_lifetime_safety_invalidated_here; S.Diag(PVD->getSourceRange().getBegin(), WarnDiag) - << true << PVD->getSourceRange(); + << getDiagSubjectDescription(PVD) << PVD->getSourceRange(); S.Diag(InvalidationExpr->getExprLoc(), UseDiag) << InvalidationExpr->getSourceRange(); S.Diag(UseExpr->getExprLoc(), diag::note_lifetime_safety_used_here) @@ -183,7 +183,9 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper { : diag::note_lifetime_safety_invalidated_here; S.Diag(IssueExpr->getExprLoc(), diag::warn_lifetime_safety_invalidated_field) - << false << IssueExpr->getSourceRange(); + << getDiagSubjectDescription(IssueExpr) + << getDiagSubjectDescription(DanglingField) + << IssueExpr->getSourceRange(); S.Diag(InvalidationExpr->getExprLoc(), InvalidationDiag) << InvalidationExpr->getSourceRange(); S.Diag(DanglingField->getLocation(), @@ -199,7 +201,8 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper { : diag::note_lifetime_safety_invalidated_here; S.Diag(PVD->getSourceRange().getBegin(), diag::warn_lifetime_safety_invalidated_field) - << true << PVD->getSourceRange(); + << getDiagSubjectDescription(PVD) + << getDiagSubjectDescription(DanglingField) << PVD->getSourceRange(); S.Diag(InvalidationExpr->getExprLoc(), InvalidationDiag) << InvalidationExpr->getSourceRange(); S.Diag(DanglingField->getLocation(), @@ -215,7 +218,9 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper { : diag::note_lifetime_safety_invalidated_here; S.Diag(IssueExpr->getExprLoc(), diag::warn_lifetime_safety_invalidated_global) - << false << IssueExpr->getSourceRange(); + << getDiagSubjectDescription(IssueExpr) + << getDiagSubjectDescription(DanglingGlobal) + << IssueExpr->getSourceRange(); S.Diag(InvalidationExpr->getExprLoc(), InvalidationDiag) << InvalidationExpr->getSourceRange(); if (DanglingGlobal->isStaticLocal() || DanglingGlobal->isStaticDataMember()) @@ -236,7 +241,8 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper { : diag::note_lifetime_safety_invalidated_here; S.Diag(PVD->getSourceRange().getBegin(), diag::warn_lifetime_safety_invalidated_global) - << true << PVD->getSourceRange(); + << getDiagSubjectDescription(PVD) + << getDiagSubjectDescription(DanglingGlobal) << PVD->getSourceRange(); S.Diag(InvalidationExpr->getExprLoc(), InvalidationDiag) << InvalidationExpr->getSourceRange(); if (DanglingGlobal->isStaticLocal() || DanglingGlobal->isStaticDataMember()) @@ -487,6 +493,8 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper { E = E->IgnoreImpCasts(); if (isa<MaterializeTemporaryExpr>(E)) return "temporary object"; + if (isa<CXXNewExpr>(E)) + return "allocated object"; if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) return getDiagSubjectDescription(DRE->getDecl()); diff --git a/clang/test/Sema/LifetimeSafety/invalidations.cpp b/clang/test/Sema/LifetimeSafety/invalidations.cpp index 35077b547fc95..301822f066de8 100644 --- a/clang/test/Sema/LifetimeSafety/invalidations.cpp +++ b/clang/test/Sema/LifetimeSafety/invalidations.cpp @@ -7,7 +7,7 @@ bool Bool(); namespace SimpleResize { void IteratorInvalidAfterResize(int new_size) { std::vector<int> v; - auto it = std::begin(v); // expected-warning {{object whose reference is captured is later invalidated}} + auto it = std::begin(v); // expected-warning {{local variable 'v' is later invalidated}} v.resize(new_size); // expected-note {{invalidated here}} *it; // expected-note {{later used here}} } @@ -48,7 +48,7 @@ void PointerToContainerTest(std::vector<int>* v) { namespace InvalidateBeforeSwap { void InvalidateBeforeSwapIterators(std::vector<int> v1, std::vector<int> v2) { - auto it1 = std::begin(v1); // expected-warning {{object whose reference is captured is later invalidated}} + auto it1 = std::begin(v1); // expected-warning {{parameter 'v1' is later invalidated}} auto it2 = std::begin(v2); if (it1 == std::end(v1) || it2 == std::end(v2)) return; *it1 = 0; // ok @@ -62,7 +62,7 @@ void InvalidateBeforeSwapIterators(std::vector<int> v1, std::vector<int> v2) { } void InvalidateBeforeSwapContainers(std::vector<int> v1, std::vector<int> v2) { - auto it1 = std::begin(v1); // expected-warning {{object whose reference is captured is later invalidated}} + auto it1 = std::begin(v1); // expected-warning {{parameter 'v1' is later invalidated}} auto it2 = std::begin(v2); if (it1 == std::end(v1) || it2 == std::end(v2)) return; *it1 = 0; // ok @@ -77,7 +77,7 @@ bool A(); bool B(); void SameConditionInvalidatesThenValidatesIterator() { std::vector<int> container; - auto it = container.begin(); // expected-warning {{object whose reference is captured is later invalidated}} + auto it = container.begin(); // expected-warning {{local variable 'container' is later invalidated}} if (it == container.end()) return; const bool a = A(); if (a) { @@ -108,7 +108,7 @@ void MergeWithDifferentContainerValuesInvalidated() { std::vector<int> v1, v2, v3; auto it = std::find(v1.begin(), v1.end(), 10); if (Bool()) { - it = std::find(v2.begin(), v2.end(), 10); // expected-warning {{object whose reference is captured is later invalidated}} + it = std::find(v2.begin(), v2.end(), 10); // expected-warning {{local variable 'v2' is later invalidated}} } else { it = std::find(v3.begin(), v3.end(), 10); } @@ -119,7 +119,7 @@ void MergeWithDifferentContainerValuesInvalidated() { namespace InvalidationInLoops { void IteratorInvalidationInAForLoop(std::vector<int> v) { - for (auto it = std::begin(v); // expected-warning {{object whose reference is captured is later invalidated}} + for (auto it = std::begin(v); // expected-warning {{parameter 'v' is later invalidated}} it != std::end(v); ++it) { // expected-note {{later used here}} if (Bool()) { @@ -129,7 +129,7 @@ void IteratorInvalidationInAForLoop(std::vector<int> v) { } void IteratorInvalidationInAWhileLoop(std::vector<int> v) { - auto it = std::begin(v); // expected-warning {{object whose reference is captured is later invalidated}} + auto it = std::begin(v); // expected-warning {{parameter 'v' is later invalidated}} while (it != std::end(v)) { if (Bool()) { v.erase(it); // expected-note {{invalidated here}} @@ -154,7 +154,7 @@ void NoIteratorInvalidationInAWhileLoopErase(std::unordered_map<int, int> mp) { } void IteratorInvalidationInAForeachLoop(std::vector<int> v) { - for (int& x : v) { // expected-warning {{object whose reference is captured is later invalidated}} \ + for (int& x : v) { // expected-warning {{parameter 'v' is later invalidated}} \ // expected-note {{later used here}} if (x % 2 == 0) { v.erase(std::find(v.begin(), v.end(), 1)); // expected-note {{invalidated here}} @@ -183,7 +183,7 @@ void IteratorCheckedAfterFind(std::vector<int> v) { } void IteratorCheckedAfterFindThenErased(std::vector<int> v) { - auto it = std::find(std::begin(v), std::end(v), 3); // expected-warning {{object whose reference is captured is later invalidated}} + auto it = std::find(std::begin(v), std::end(v), 3); // expected-warning {{parameter 'v' is later invalidated}} if (it != std::end(v)) { v.erase(it); // expected-note {{invalidated here}} } @@ -201,7 +201,7 @@ void UseReturnedIteratorAfterInsert(std::vector<int> v) { } void UseInvalidIteratorAfterInsert(std::vector<int> v) { - auto it = std::begin(v); // expected-warning {{object whose reference is captured is later invalidated}} + auto it = std::begin(v); // expected-warning {{parameter 'v' is later invalidated}} v.insert(it, 10); // expected-note {{invalidated here}} if (it != std::end(v)) { // expected-note {{later used here}} *it; @@ -220,7 +220,7 @@ void IteratorValidAfterInsert(std::vector<int> v) { } void IteratorInvalidAfterInsert(std::vector<int> v, int value) { - auto it = std::begin(v); // expected-warning {{object whose reference is captured is later invalidated}} + auto it = std::begin(v); // expected-warning {{parameter 'v' is later invalidated}} v.insert(it, 0); // expected-note {{invalidated here}} *it; // expected-note {{later used here}} } @@ -228,7 +228,7 @@ void IteratorInvalidAfterInsert(std::vector<int> v, int value) { namespace SimpleInvalidIterators { void IteratorUsedAfterErase(std::vector<int> v) { - auto it = std::begin(v); // expected-warning {{object whose reference is captured is later invalidated}} + auto it = std::begin(v); // expected-warning {{parameter 'v' is later invalidated}} for (; it != std::end(v); ++it) { // expected-note {{later used here}} if (*it > 3) { v.erase(it); // expected-note {{invalidated here}} @@ -236,7 +236,7 @@ void IteratorUsedAfterErase(std::vector<int> v) { } } -void IteratorUsedAfterPushBackParam(std::vector<int>& v) { // expected-warning {{parameter is later invalidated}} +void IteratorUsedAfterPushBackParam(std::vector<int>& v) { // expected-warning {{parameter 'v' is later invalidated}} auto it = std::begin(v); if (it != std::end(v) && *it == 3) { v.push_back(4); // expected-note {{invalidated here}} @@ -245,7 +245,7 @@ void IteratorUsedAfterPushBackParam(std::vector<int>& v) { // expected-warning { } void IteratorUsedAfterPushBack(std::vector<int> v) { - auto it = std::begin(v); // expected-warning {{object whose reference is captured is later invalidated}} + auto it = std::begin(v); // expected-warning {{parameter 'v' is later invalidated}} if (it != std::end(v) && *it == 3) { v.push_back(4); // expected-note {{invalidated here}} } @@ -254,14 +254,14 @@ void IteratorUsedAfterPushBack(std::vector<int> v) { void IteratorUsedAfterPreIncrement() { std::vector<int> v; - auto it = v.begin(); // expected-warning {{object whose reference is captured is later invalidated}} + auto it = v.begin(); // expected-warning {{local variable 'v' is later invalidated}} auto next = ++it; v.push_back(1); // expected-note {{invalidated here}} (void)*next; // expected-note {{later used here}} } void IteratorUsedAfterPostDecrement(std::vector<int> v) { - auto it = v.rbegin(); // expected-warning {{object whose reference is captured is later invalidated}} + auto it = v.rbegin(); // expected-warning {{parameter 'v' is later invalidated}} auto prev = it--; v.push_back(1); // expected-note {{invalidated here}} (void)*prev; // expected-note {{later used here}} @@ -269,21 +269,21 @@ void IteratorUsedAfterPostDecrement(std::vector<int> v) { void IteratorUsedAfterAddition() { std::vector<int> v; - auto it = v.cbegin(); // expected-warning {{object whose reference is captured is later invalidated}} + auto it = v.cbegin(); // expected-warning {{local variable 'v' is later invalidated}} auto next = it + 5; v.push_back(1); // expected-note {{invalidated here}} (void)*next; // expected-note {{later used here}} } void IteratorUsedAfterReverseSubtraction(std::vector<int> v) { - auto it = v.crbegin(); // expected-warning {{object whose reference is captured is later invalidated}} + auto it = v.crbegin(); // expected-warning {{parameter 'v' is later invalidated}} auto prev = 5 - it; v.push_back(1); // expected-note {{invalidated here}} (void)*prev; // expected-note {{later used here}} } void IteratorUsedAfterAddAdd(std::vector<int> v) { - auto it = v.cbegin(); // expected-warning {{object whose reference is captured is later invalidated}} + auto it = v.cbegin(); // expected-warning {{parameter 'v' is later invalidated}} auto next = (it + 5) + 5; v.push_back(1); // expected-note {{invalidated here}} (void)*next; // expected-note {{later used here}} @@ -291,14 +291,14 @@ void IteratorUsedAfterAddAdd(std::vector<int> v) { void IteratorUsedAfterMixedAddition() { std::vector<int> v; - auto it = v.cbegin(); // expected-warning {{object whose reference is captured is later invalidated}} + auto it = v.cbegin(); // expected-warning {{local variable 'v' is later invalidated}} auto next = 1 + it + 2 + 3; v.push_back(1); // expected-note {{invalidated here}} (void)*next; // expected-note {{later used here}} } void IteratorUsedAfterPreIncrementAddAssign(std::vector<int> v) { - auto it = v.begin(); // expected-warning {{object whose reference is captured is later invalidated}} + auto it = v.begin(); // expected-warning {{parameter 'v' is later invalidated}} it = ++it + 1 + 2; v.push_back(1); // expected-note {{invalidated here}} (void)*it; // expected-note {{later used here}} @@ -306,7 +306,7 @@ void IteratorUsedAfterPreIncrementAddAssign(std::vector<int> v) { void IteratorUsedAfterBeginAddAssign() { std::vector<int> v; - auto it = v.begin() + 1; // expected-warning {{object whose reference is captured is later invalidated}} + auto it = v.begin() + 1; // expected-warning {{local variable 'v' is later invalidated}} v.push_back(1); // expected-note {{invalidated here}} (void)*it; // expected-note {{later used here}} } @@ -314,7 +314,7 @@ void IteratorUsedAfterBeginAddAssign() { void IteratorUsedAfterStdBeginAddAssign() { std::vector<int> v; std::vector<int>::iterator it; - it = std::begin(v) + 1; // expected-warning {{object whose reference is captured is later invalidated}} + it = std::begin(v) + 1; // expected-warning {{local variable 'v' is later invalidated}} v.push_back(1); // expected-note {{invalidated here}} (void)*it; // expected-note {{later used here}} } @@ -324,12 +324,12 @@ namespace InvalidatingThroughContainerAliases { void IteratorInvalidatedThroughLocalReferenceAlias() { std::vector<int> vv; std::vector<int> &v = vv; - auto it = vv.begin(); // expected-warning {{object whose reference is captured is later invalidated}} + auto it = vv.begin(); // expected-warning {{local variable 'vv' is later invalidated}} v.push_back(42); // expected-note {{invalidated here}} (void)it; // expected-note {{later used here}} } -void IteratorInvalidatedThroughPointerParameter(std::vector<int> *v) { // expected-warning {{parameter is later invalidated}} +void IteratorInvalidatedThroughPointerParameter(std::vector<int> *v) { // expected-warning {{parameter 'v' is later invalidated}} auto it = v->begin(); v->push_back(42); // expected-note {{invalidated here}} (void)it; // expected-note {{later used here}} @@ -347,7 +347,7 @@ void ParenthesizedContainerInvalidatesIterator() { namespace ContainerObjectAliases { // FIXME: Distinguish owner-borrow from content-borrow. -void PointerParameterObjectUseIsOk(std::vector<int> *v) { // expected-warning {{parameter is later invalidated}} +void PointerParameterObjectUseIsOk(std::vector<int> *v) { // expected-warning {{parameter 'v' is later invalidated}} v->push_back(42); // expected-note {{invalidated here}} (void)v; // expected-note {{later used here}} } @@ -355,7 +355,7 @@ void PointerParameterObjectUseIsOk(std::vector<int> *v) { // expected-warning {{ // FIXME: Distinguish owner-borrow from content-borrow. void LocalPointerAliasObjectUseIsOk() { std::vector<int> vv; - std::vector<int> *v = &vv; // expected-warning {{object whose reference is captured is later invalidated}} + std::vector<int> *v = &vv; // expected-warning {{local variable 'vv' is later invalidated}} v->push_back(42); // expected-note {{invalidated here}} (void)*v; // expected-note {{later used here}} } @@ -363,7 +363,7 @@ void LocalPointerAliasObjectUseIsOk() { // FIXME: Distinguish owner-borrow from content-borrow. void LocalReferenceAliasObjectUseIsOk() { std::vector<int> vv; - std::vector<int> &v = vv; // expected-warning {{object whose reference is captured is later invalidated}} + std::vector<int> &v = vv; // expected-warning {{local variable 'vv' is later invalidated}} v.push_back(42); // expected-note {{invalidated here}} (void)v; // expected-note {{later used here}} } @@ -374,7 +374,7 @@ namespace ElementReferences { void ReferenceToVectorElement() { std::vector<int> v = {1, 2, 3}; - int& ref = v[0]; // expected-warning {{object whose reference is captured is later invalidated}} + int& ref = v[0]; // expected-warning {{local variable 'v' is later invalidated}} v.push_back(4); // expected-note {{invalidated here}} ref = 10; // expected-note {{later used here}} (void)ref; @@ -382,14 +382,14 @@ void ReferenceToVectorElement() { void PointerRefToVectorElement() { std::vector<int*> v = {nullptr, nullptr}; - int*& ref = v[0]; // expected-warning {{object whose reference is captured is later invalidated}} + int*& ref = v[0]; // expected-warning {{local variable 'v' is later invalidated}} v.push_back(nullptr); // expected-note {{invalidated here}} ref = nullptr; // expected-note {{later used here}} } void PointerToVectorElement() { std::vector<int> v = {1, 2, 3}; - int* ptr = &v[0]; // expected-warning {{object whose reference is captured is later invalidated}} + int* ptr = &v[0]; // expected-warning {{local variable 'v' is later invalidated}} v.resize(100); // expected-note {{invalidated here}} *ptr = 10; // expected-note {{later used here}} } @@ -405,13 +405,13 @@ void SelfInvalidatingMap() { mp[1] = "42"; mp[2] // expected-note {{invalidated here}} = - mp[1]; // expected-warning {{object whose reference is captured is later invalidated}} expected-note {{later used here}} + mp[1]; // expected-warning {{local variable 'mp' is later invalidated}} expected-note {{later used here}} } void InvalidateErase() { std::flat_map<int, std::string> mp; // None of these containers provide iterator stability. So following is unsafe: - auto it = mp.find(3); // expected-warning {{object whose reference is captured is later invalidated}} + auto it = mp.find(3); // expected-warning {{local variable 'mp' is later invalidated}} mp.erase(mp.find(4)); // expected-note {{invalidated here}} if (it != mp.end()) // expected-note {{later used here}} *it; @@ -421,12 +421,12 @@ void InvalidateErase() { namespace Strings { void append(std::string str) { - std::string_view view = str; // expected-warning {{object whose reference is captured is later invalidated}} + std::string_view view = str; // expected-warning {{parameter 'str' is later invalidated}} str += "456"; // expected-note {{invalidated here}} (void)view; // expected-note {{later used here}} } void reassign(std::string str, std::string str2) { - std::string_view view = str; // expected-warning {{object whose reference is captured is later invalidated}} + std::string_view view = str; // expected-warning {{parameter 'str' is later invalidated}} str = str2; // expected-note {{invalidated here}} (void)view; // expected-note {{later used here}} } @@ -434,7 +434,7 @@ void reassign(std::string str, std::string str2) { // FIXME: This should be diagnosed as use-after-invalidation but with potential move. void ReassigningAfterMove(std::string str, std::string str2) { - std::string_view view = str; // expected-warning {{object whose reference is captured is later invalidated}} + std::string_view view = str; // expected-warning {{parameter 'str' is later invalidated}} std::vector<std::string> someStorage; someStorage.push_back(std::move(str)); str = str2; // expected-note {{invalidated here}} @@ -478,7 +478,7 @@ void ConditionalFieldInvalidatesIterator(bool flag) { // FIXME: Requires field-sensitive AccessPaths to fix. void Invalidate1Use2ViaRefIsOk() { S s; - auto it = s.strings2.begin(); // expected-warning {{object whose reference is captured is later invalidated}} + auto it = s.strings2.begin(); // expected-warning {{local variable 's' is later invalidated}} auto& strings1 = s.strings1; strings1.push_back("1"); // expected-note {{invalidated here}} *it; // expected-note {{later used here}} @@ -492,13 +492,13 @@ void Invalidate1UseSIsOk() { // FIXME: Distinguish owner-borrow from content-borrow. void PointerToContainerIsOk() { std::vector<std::string> s; - std::vector<std::string>* p = &s; // expected-warning {{object whose reference is captured is later invalidated}} + std::vector<std::string>* p = &s; // expected-warning {{local variable 's' is later invalidated}} p->push_back("1"); // expected-note {{invalidated here}} (void)*p; // expected-note {{later used here}} } void IteratorFromPointerToContainerIsInvalidated() { std::vector<std::string> s; - std::vector<std::string>* p = &s; // expected-warning {{object whose reference is captured is later invalidated}} + std::vector<std::string>* p = &s; // expected-warning {{local variable 's' is later invalidated}} auto it = p->begin(); p->push_back("1"); // expected-note {{invalidated here}} *it; // expected-note {{later used here}} @@ -507,7 +507,7 @@ void IteratorFromPointerToContainerIsInvalidated() { // iterators into the outer container. void ChangingRegionOwnedByContainerIsOk() { std::vector<std::string> subdirs; - for (std::string& path : subdirs) // expected-warning {{object whose reference is captured is later invalidated}} expected-note {{later used here}} + for (std::string& path : subdirs) // expected-warning {{local variable 'subdirs' is later invalidated}} expected-note {{later used here}} path = std::string(); // expected-note {{invalidated here}} } @@ -520,7 +520,7 @@ std::string StableString; struct SinkOwnerBorrow { std::string *dest_; // expected-note {{this field dangles}} - SinkOwnerBorrow(std::string *dest, int n) : dest_(dest) { // expected-warning {{parameter which escapes to a field is later invalidated}} + SinkOwnerBorrow(std::string *dest, int n) : dest_(dest) { // expected-warning {{parameter 'dest' escapes to the field 'dest_' and is later invalidated}} if (n > 0) dest->clear(); // expected-note {{invalidated here}} } @@ -529,7 +529,7 @@ struct SinkOwnerBorrow { struct SinkInteriorBorrow { const char *dest_; // expected-note {{this field dangles}} - SinkInteriorBorrow(std::string *dest, int n) : dest_(dest->data()) { // expected-warning {{parameter which escapes to a field is later invalidated}} + SinkInteriorBorrow(std::string *dest, int n) : dest_(dest->data()) { // expected-warning {{parameter 'dest' escapes to the field 'dest_' and is later invalidated}} if (n > 0) dest->clear(); // expected-note {{invalidated here}} } @@ -547,38 +547,38 @@ struct S { void InvalidatedFieldLocalVector() { std::vector<std::string> strings; - FieldFromLocalVector = *strings.begin(); // expected-warning {{object whose reference escapes to a field is later invalidated}} + FieldFromLocalVector = *strings.begin(); // expected-warning {{local variable 'strings' escapes to the field 'FieldFromLocalVector' and is later invalidated}} strings.push_back("1"); // expected-note {{invalidated here}} } void InvalidatedFieldByValueParamVector(std::vector<std::string> strings) { - FieldFromByValueParamVector = *strings.begin(); // expected-warning {{object whose reference escapes to a field is later invalidated}} + FieldFromByValueParamVector = *strings.begin(); // expected-warning {{parameter 'strings' escapes to the field 'FieldFromByValueParamVector' and is later invalidated}} strings.push_back("1"); // expected-note {{invalidated here}} } void InvalidatedFieldLocalString() { std::string s; - FieldFromLocalString = s; // expected-warning {{object whose reference escapes to a field is later invalidated}} + FieldFromLocalString = s; // expected-warning {{local variable 's' escapes to the field 'FieldFromLocalString' and is later invalidated}} s.clear(); // expected-note {{invalidated here}} } void InvalidatedFieldByValueParamString(std::string s) { - FieldFromByValueParamString = s; // expected-warning {{object whose reference escapes to a field is later invalidated}} + FieldFromByValueParamString = s; // expected-warning {{parameter 's' escapes to the field 'FieldFromByValueParamString' and is later invalidated}} s.clear(); // expected-note {{invalidated here}} } - void InvalidatedFieldRefParamString(std::string &s) { // expected-warning {{parameter which escapes to a field is later invalidated}} + void InvalidatedFieldRefParamString(std::string &s) { // expected-warning {{parameter 's' escapes to the field 'FieldFromRefParamString' and is later invalidated}} FieldFromRefParamString = s; s.~basic_string(); // expected-note {{invalidated here}} } void InvalidatedFieldDelete() { - int *p = new int; // expected-warning {{object whose reference escapes to a field is later invalidated}} + int *p = new int; // expected-warning {{allocated object escapes to the field 'FieldFromNew' and is later invalidated}} FieldFromNew = p; delete p; // expected-note {{freed here}} } - void InvalidatedFieldDeleteParam(int *p) { // expected-warning {{parameter which escapes to a field is later invalidated}} + void InvalidatedFieldDeleteParam(int *p) { // expected-warning {{parameter 'p' escapes to the field 'FieldFromPointerParam' and is later invalidated}} FieldFromPointerParam = p; delete p; // expected-note {{freed here}} } @@ -607,27 +607,27 @@ struct S { void InvalidatedGlobalLocalVector() { std::vector<std::string> strings; - GlobalFromLocalVector = *strings.begin(); // expected-warning {{object whose reference escapes to global or static storage is later invalidated}} + GlobalFromLocalVector = *strings.begin(); // expected-warning {{local variable 'strings' escapes to the global variable 'GlobalFromLocalVector' and is later invalidated}} strings.push_back("1"); // expected-note {{invalidated here}} } void InvalidatedGlobalByValueParamString(std::string s) { - GlobalFromByValueParamString = s; // expected-warning {{object whose reference escapes to global or static storage is later invalidated}} + GlobalFromByValueParamString = s; // expected-warning {{parameter 's' escapes to the global variable 'GlobalFromByValueParamString' and is later invalidated}} s.clear(); // expected-note {{invalidated here}} } -void InvalidatedGlobalRefParamString(std::string &s) { // expected-warning {{parameter which escapes to global or static storage is later invalidated}} +void InvalidatedGlobalRefParamString(std::string &s) { // expected-warning {{parameter 's' escapes to the global variable 'GlobalFromRefParamString' and is later invalidated}} GlobalFromRefParamString = s; s.~basic_string(); // expected-note {{invalidated here}} } void InvalidatedGlobalDelete() { - int *p = new int; // expected-warning {{object whose reference escapes to global or static storage is later invalidated}} + int *p = new int; // expected-warning {{allocated object escapes to the global variable 'GlobalFromNew' and is later invalidated}} GlobalFromNew = p; delete p; // expected-note {{freed here}} } -void InvalidatedGlobalDeleteParam(int *p) { // expected-warning {{parameter which escapes to global or static storage is later invalidated}} +void InvalidatedGlobalDeleteParam(int *p) { // expected-warning {{parameter 'p' escapes to the global variable 'GlobalFromPointerParam' and is later invalidated}} GlobalFromPointerParam = p; delete p; // expected-note {{freed here}} } @@ -635,13 +635,13 @@ void InvalidatedGlobalDeleteParam(int *p) { // expected-warning {{parameter whic void InvalidatedStaticLocalString() { static std::string_view StaticFromLocalString; // expected-note {{this static storage dangles}} std::string s; - StaticFromLocalString = s; // expected-warning {{object whose reference escapes to global or static storage is later invalidated}} + StaticFromLocalString = s; // expected-warning {{local variable 's' escapes to the static variable 'StaticFromLocalString' and is later invalidated}} s.clear(); // expected-note {{invalidated here}} } void InvalidatedStaticMemberString() { std::string s; - S::StaticMember = s; // expected-warning {{object whose reference escapes to global or static storage is later invalidated}} + S::StaticMember = s; // expected-warning {{local variable 's' escapes to the static variable 'StaticMember' and is later invalidated}} s.clear(); // expected-note {{invalidated here}} } @@ -714,14 +714,14 @@ void SetExtractDoesNotInvalidateOthers() { void SetClearInvalidates() { std::set<int> s; - auto it = s.begin(); // expected-warning {{object whose reference is captured is later invalidated}} + auto it = s.begin(); // expected-warning {{local variable 's' is later invalidated}} s.clear(); // expected-note {{invalidated here}} *it; // expected-note {{later used here}} } void MapClearInvalidates() { std::map<int, int> m; - auto it = m.begin(); // expected-warning {{object whose reference is captured is later invalidated}} + auto it = m.begin(); // expected-warning {{local variable 'm' is later invalidated}} m.clear(); // expected-note {{invalidated here}} *it; // expected-note {{later used here}} } @@ -740,7 +740,7 @@ void MapSubscriptMultipleCallsDoesNotInvalidate(std::map<int, int> mp, int a, in } void FlatMapSubscriptMultipleCallsInvalidate(std::flat_map<int, int> mp, int a, int b) { - PrintMax(mp[a], mp[b]); // expected-warning {{object whose reference is captured is later invalidated}} \ + PrintMax(mp[a], mp[b]); // expected-warning {{parameter 'mp' is later invalidated}} \ // expected-note {{invalidated here}} \ // expected-note {{later used here}} } @@ -750,7 +750,7 @@ void FlatMapSubscriptMultipleCallsInvalidate(std::flat_map<int, int> mp, int a, namespace lambda_capture_invalidation { void captured_view_invalidated_by_owner() { std::string s = "42"; - std::string_view p = s; // expected-warning {{object whose reference is captured is later invalidated}} + std::string_view p = s; // expected-warning {{local variable 's' is later invalidated}} auto lambda = [=]() { return p; }; s.push_back('c'); // expected-note {{invalidated here}} lambda(); // expected-note {{later used here}} @@ -758,7 +758,7 @@ void captured_view_invalidated_by_owner() { void multiple_captures_one_invalidated() { std::string s1 = "a", s2 = "b"; - std::string_view p1 = s1, p2 = s2; // expected-warning {{object whose reference is captured is later invalidated}} + std::string_view p1 = s1, p2 = s2; // expected-warning {{local variable 's1' is later invalidated}} auto lambda = [=]() { return p1.size() + p2.size(); }; s1.clear(); // expected-note {{invalidated here}} lambda(); // expected-note {{later used here}} @@ -793,7 +793,7 @@ struct S { void bar(); void baz(){ std::vector<std::string> vec = {"42"}; - v = vec[0]; // expected-warning {{object whose reference is captured is later invalidated}} + v = vec[0]; // expected-warning {{local variable 'vec' is later invalidated}} vec.push_back("1"); // expected-note {{invalidated here}} bar(); // expected-note {{later used here}} v = nullptr; @@ -806,7 +806,7 @@ namespace callable_wrappers { void function_captured_ref_invalidated() { std::vector<int> v; v.push_back(1); - std::function<void()> f = [&r = v[0]]() { (void)r; }; // expected-warning {{object whose reference is captured is later invalidated}} + std::function<void()> f = [&r = v[0]]() { (void)r; }; // expected-warning {{local variable 'v' is later invalidated}} v.push_back(2); // expected-note {{invalidated here}} (void)f; // expected-note {{later used here}} } @@ -818,14 +818,14 @@ namespace explicit_destructor { void explicit_destructor_invalidates_pointer() { std::string s = "42"; - const char *p = s.data(); // expected-warning {{object whose reference is captured is later invalidated}} + const char *p = s.data(); // expected-warning {{local variable 's' is later invalidated}} s.~basic_string(); // expected-note {{invalidated here}} (void)*p; // expected-note {{later used here}} } void pointer_destructor_invalidates_pointer() { char storage[sizeof(std::string)]; - std::string *obj = new (storage) std::string("42"); // expected-warning {{object whose reference is captured is later invalidated}} + std::string *obj = new (storage) std::string("42"); // expected-warning {{local variable 'storage' is later invalidated}} const char *p = obj->data(); obj->~basic_string(); // expected-note {{invalidated here}} (void)*p; // expected-note {{later used here}} @@ -833,7 +833,7 @@ void pointer_destructor_invalidates_pointer() { void destroy_at_invalidates_pointer() { char storage[sizeof(std::string)]; - std::string *obj = new (storage) std::string("42"); // expected-warning {{object whose reference is captured is later invalidated}} + std::string *obj = new (storage) std::string("42"); // expected-warning {{local variable 'storage' is later invalidated}} const char *p = obj->data(); std::destroy_at(obj); // expected-note {{invalidated here}} (void)*p; // expected-note {{later used here}} @@ -852,21 +852,21 @@ void destroy_at_then_placement_new_rescues_pointer() { void destroy_at_invalidates_array_pointer() { std::string arr[1] = {"42"}; std::string (&arr_ref)[1] = arr; - const char *p = arr[0].data(); // expected-warning {{object whose reference is captured is later invalidated}} + const char *p = arr[0].data(); // expected-warning {{local variable 'arr' is later invalidated}} std::destroy_at(&arr_ref); // expected-note {{invalidated here}} (void)*p; // expected-note {{later used here}} } void reference_destructor_invalidates_pointer() { std::string s = "42"; - std::string &ref = s; // expected-warning {{object whose reference is captured is later invalidated}} + std::string &ref = s; // expected-warning {{local variable 's' is later invalidated}} const char *p = ref.data(); std::destroy_at(&ref); // expected-note {{invalidated here}} (void)*p; // expected-note {{later used here}} } void destroy_at_ternary_operator(bool flag) { - std::string* str1 = new std::string; // expected-warning {{object whose reference is captured is later invalidated}} + std::string* str1 = new std::string; // expected-warning {{allocated object is later invalidated}} std::string* str2 = new std::string; const char *p = str1->data(); std::destroy_at(flag ? str1 : str2); // expected-note {{invalidated here}} @@ -880,7 +880,7 @@ struct StringOwner { // FIXME: False-positive void member_destructor_invalidates_pointer() { StringOwner owner = {"42", "43"}; - const char *p = owner.s.data(); // expected-warning {{object whose reference is captured is later invalidated}} + const char *p = owner.s.data(); // expected-warning {{local variable 'owner' is later invalidated}} owner.t.~basic_string(); // expected-note {{invalidated here}} (void)*p; // expected-note {{later used here}} } @@ -891,7 +891,7 @@ namespace unique_ptr_invalidation { void invalid_after_reset() { std::unique_ptr<int> up(new int); - int *p = up.get(); // expected-warning {{object whose reference is captured is later invalidated}} + int *p = up.get(); // expected-warning {{local variable 'up' is later invalidated}} up.reset(); // expected-note {{invalidated here}} (void)*p; // expected-note {{later used here}} } @@ -899,14 +899,14 @@ void invalid_after_reset() { void invalid_after_move_assign() { std::unique_ptr<int> up(new int); std::unique_ptr<int> other(new int); - int *p = up.get(); // expected-warning {{object whose reference is captured is later invalidated}} + int *p = up.get(); // expected-warning {{local variable 'up' is later invalidated}} up = std::move(other); // expected-note {{invalidated here}} (void)*p; // expected-note {{later used here}} } void invalid_after_null_assign() { std::unique_ptr<int> up(new int); - int *p = up.get(); // expected-warning {{object whose reference is captured is later invalidated}} + int *p = up.get(); // expected-warning {{local variable 'up' is later invalidated}} up = nullptr; // expected-note {{invalidated here}} (void)*p; // expected-note {{later used here}} } @@ -914,7 +914,7 @@ void invalid_after_null_assign() { void invalid_after_ternary_reset(bool flag) { std::unique_ptr<int> up(new int); std::unique_ptr<int> other(new int); - int *p = flag ? up.get() : other.get(); // expected-warning {{object whose reference is captured is later invalidated}} + int *p = flag ? up.get() : other.get(); // expected-warning {{local variable 'up' is later invalidated}} up.reset(); // expected-note {{invalidated here}} (void)*p; // expected-note {{later used here}} } diff --git a/clang/test/Sema/LifetimeSafety/safety.cpp b/clang/test/Sema/LifetimeSafety/safety.cpp index d976baa545b8c..1c4b3c117fb00 100644 --- a/clang/test/Sema/LifetimeSafety/safety.cpp +++ b/clang/test/Sema/LifetimeSafety/safety.cpp @@ -2943,7 +2943,7 @@ void delete_pointer_propagation_use_after_free() { (void)(*pp)->id; // expected-note {{later used here}} } -void delete_param_pointer(int* x) { // expected-warning {{parameter does not live long enough}} +void delete_param_pointer(int* x) { // expected-warning {{parameter 'x' does not live long enough}} delete x; // expected-note {{freed here}} (void)x; // expected-note {{later used here}} } @@ -2957,7 +2957,7 @@ struct S { } }; -void use_inner_origin_after_delete(MyObj* obj) { // expected-warning {{parameter does not live long enough}} +void use_inner_origin_after_delete(MyObj* obj) { // expected-warning {{parameter 'obj' does not live long enough}} int* p = &obj->id; delete obj; // expected-note {{freed here}} (void)*p; // expected-note {{later used here}} @@ -3009,14 +3009,14 @@ void delete_through_pointer_field() { void delete_stack_object() { MyObj obj; - MyObj* p = &obj; // expected-warning {{allocated object does not live long enough}} + MyObj* p = &obj; // expected-warning {{local variable 'obj' does not live long enough}} delete &obj; // expected-note {{freed here}} (void)p->id; // expected-note {{later used here}} } void delete_stack_object_int() { int obj; - int* p = &obj; // expected-warning {{allocated object does not live long enough}} + int* p = &obj; // expected-warning {{local variable 'obj' does not live long enough}} delete &obj; // expected-note {{freed here}} (void)*p; // expected-note {{later used here}} } _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
