[clang] [LifetimeSafety] Improve destroyed and invalidated diagnostic notes (PR #204900)
via cfe-commits
cfe-commits at lists.llvm.org
Sun Jun 21 23:16:41 PDT 2026
https://github.com/iitianpushkar updated https://github.com/llvm/llvm-project/pull/204900
>From 9d03e57fe0ae3543622d4cdfcc951369cac05faa Mon Sep 17 00:00:00 2001
From: iitianpushkar <pushkarsingh0587 at gmail.com>
Date: Sat, 20 Jun 2026 02:02:02 +0530
Subject: [PATCH 01/14] added storage description in destroyed/invalidated here
notes
---
clang/include/clang/Basic/DiagnosticSemaKinds.td | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index f84cd8dca6d4c..92e80f299dbbb 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -11052,8 +11052,10 @@ def warn_lifetime_safety_inapplicable_lifetimebound
DefaultIgnore;
def note_lifetime_safety_used_here : Note<"later used here">;
-def note_lifetime_safety_invalidated_here : Note<"invalidated here">;
-def note_lifetime_safety_destroyed_here : Note<"destroyed here">;
+def note_lifetime_safety_invalidated_here : Note<"%0 is invalidated here">;
+def note_lifetime_safety_destroyed_here : Note<
+ "%0 is destroyed here at the end of "
+ "%select{its scope|the full-expression}1">;
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">;
>From 382e367e9aef80ece6dbc89b23b2b83f6f21f267 Mon Sep 17 00:00:00 2001
From: iitianpushkar <pushkarsingh0587 at gmail.com>
Date: Sat, 20 Jun 2026 03:58:57 +0530
Subject: [PATCH 02/14] passed AccessPath info in the header
---
.../Analyses/LifetimeSafety/LifetimeSafety.h | 27 ++++++++++++++-----
1 file changed, 20 insertions(+), 7 deletions(-)
diff --git a/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h b/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h
index 28886b826f72f..3e03de134ea6b 100644
--- a/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h
+++ b/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h
@@ -64,6 +64,7 @@ class LifetimeSafetySemaHelper {
virtual void reportUseAfterScope(const Expr *IssueExpr, const Expr *UseExpr,
const Expr *MovedExpr,
SourceLocation FreeLoc,
+ const internal::AccessPath &ExpiredPath,
llvm::ArrayRef<const Expr *> ExprChain) {}
virtual void reportUseAfterReturn(const Expr *IssueExpr,
@@ -82,24 +83,36 @@ class LifetimeSafetySemaHelper {
// Reports when a reference/iterator is used after the container operation
// that invalidated it.
- virtual void reportUseAfterInvalidation(const Expr *IssueExpr,
+ virtual void reportUseAfterInvalidation(const Expr *IssueExpr,
const Expr *UseExpr,
- const Expr *InvalidationExpr) {}
+ const Expr *InvalidationExpr,
+ const internal::AccessPath
+ &InvalidatedPath) {}
virtual void reportUseAfterInvalidation(const ParmVarDecl *PVD,
const Expr *UseExpr,
- const Expr *InvalidationExpr) {}
+ const Expr *InvalidationExpr,
+ const internal::AccessPath
+ &InvalidatedPath) {}
virtual void reportInvalidatedField(const Expr *IssueExpr,
const FieldDecl *Field,
- const Expr *InvalidationExpr) {}
+ const Expr *InvalidationExpr,
+ const internal::AccessPath
+ &InvalidatedPath) {}
virtual void reportInvalidatedField(const ParmVarDecl *PVD,
const FieldDecl *Field,
- const Expr *InvalidationExpr) {}
+ const Expr *InvalidationExpr,
+ const internal::AccessPath
+ &InvalidatedPath) {}
virtual void reportInvalidatedGlobal(const Expr *IssueExpr,
const VarDecl *Global,
- const Expr *InvalidationExpr) {}
+ const Expr *InvalidationExpr,
+ const internal::AccessPath
+ &InvalidatedPath) {}
virtual void reportInvalidatedGlobal(const ParmVarDecl *PVD,
const VarDecl *Global,
- const Expr *InvalidationExpr) {}
+ const Expr *InvalidationExpr,
+ const internal::AccessPath
+ &InvalidatedPath) {}
using EscapingTarget =
llvm::PointerUnion<const Expr *, const FieldDecl *, const VarDecl *>;
>From 717a38322cb430a237a73762b77206fc4fa51cba Mon Sep 17 00:00:00 2001
From: iitianpushkar <pushkarsingh0587 at gmail.com>
Date: Sat, 20 Jun 2026 04:30:01 +0530
Subject: [PATCH 03/14] implemented method to create storage-aware destruction
and invalidation notes
---
clang/lib/Sema/SemaLifetimeSafety.h | 115 ++++++++++++++++------------
1 file changed, 68 insertions(+), 47 deletions(-)
diff --git a/clang/lib/Sema/SemaLifetimeSafety.h b/clang/lib/Sema/SemaLifetimeSafety.h
index a8bde363e3397..e67478afcf351 100644
--- a/clang/lib/Sema/SemaLifetimeSafety.h
+++ b/clang/lib/Sema/SemaLifetimeSafety.h
@@ -82,6 +82,7 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper {
void reportUseAfterScope(const Expr *IssueExpr, const Expr *UseExpr,
const Expr *MovedExpr, SourceLocation FreeLoc,
+ const internal::AccessPath &ExpiredPath,
llvm::ArrayRef<const Expr *> ExprChain) override {
unsigned DiagID = MovedExpr
? diag::warn_lifetime_safety_use_after_scope_moved
@@ -92,7 +93,10 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper {
if (MovedExpr)
S.Diag(MovedExpr->getExprLoc(), diag::note_lifetime_safety_moved_here)
<< MovedExpr->getSourceRange();
- S.Diag(FreeLoc, diag::note_lifetime_safety_destroyed_here);
+ S.Diag(FreeLoc, diag::note_lifetime_safety_destroyed_here)
+ << getDiagStorageDescription(ExpiredPath)
+ << (ExpiredPath.getKind() ==
+ internal::AccessPath::Kind::MaterializeTemporary);
reportAliasingChain(ExprChain);
@@ -161,87 +165,72 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper {
<< DanglingGlobal->getEndLoc();
}
- void reportUseAfterInvalidation(const Expr *IssueExpr, const Expr *UseExpr,
- const Expr *InvalidationExpr) override {
+ void reportUseAfterInvalidation(
+ const Expr *IssueExpr, const Expr *UseExpr, const Expr *InvalidationExpr,
+ const internal::AccessPath &InvalidatedPath) override {
auto WarnDiag = isa<CXXDeleteExpr>(InvalidationExpr)
? diag::warn_lifetime_safety_use_after_free
: diag::warn_lifetime_safety_invalidation;
- auto UseDiag = isa<CXXDeleteExpr>(InvalidationExpr)
- ? diag::note_lifetime_safety_freed_here
- : diag::note_lifetime_safety_invalidated_here;
S.Diag(IssueExpr->getExprLoc(), WarnDiag)
<< getDiagSubjectDescription(IssueExpr) << IssueExpr->getSourceRange();
- S.Diag(InvalidationExpr->getExprLoc(), UseDiag)
- << InvalidationExpr->getSourceRange();
+ reportInvalidationNote(InvalidationExpr, InvalidatedPath);
S.Diag(UseExpr->getExprLoc(), diag::note_lifetime_safety_used_here)
<< UseExpr->getSourceRange();
}
- void reportUseAfterInvalidation(const ParmVarDecl *PVD, const Expr *UseExpr,
- const Expr *InvalidationExpr) override {
+ void reportUseAfterInvalidation(
+ const ParmVarDecl *PVD, const Expr *UseExpr, const Expr *InvalidationExpr,
+ const internal::AccessPath &InvalidatedPath) override {
auto WarnDiag = isa<CXXDeleteExpr>(InvalidationExpr)
? diag::warn_lifetime_safety_use_after_free
: diag::warn_lifetime_safety_invalidation;
- auto UseDiag = isa<CXXDeleteExpr>(InvalidationExpr)
- ? diag::note_lifetime_safety_freed_here
- : diag::note_lifetime_safety_invalidated_here;
S.Diag(PVD->getSourceRange().getBegin(), WarnDiag)
<< getDiagSubjectDescription(PVD) << PVD->getSourceRange();
- S.Diag(InvalidationExpr->getExprLoc(), UseDiag)
- << InvalidationExpr->getSourceRange();
+ reportInvalidationNote(InvalidationExpr, InvalidatedPath);
S.Diag(UseExpr->getExprLoc(), diag::note_lifetime_safety_used_here)
<< UseExpr->getSourceRange();
}
- void reportInvalidatedField(const Expr *IssueExpr,
- const FieldDecl *DanglingField,
- const Expr *InvalidationExpr) override {
- auto InvalidationDiag = isa<CXXDeleteExpr>(InvalidationExpr)
- ? diag::note_lifetime_safety_freed_here
- : diag::note_lifetime_safety_invalidated_here;
+ void
+ reportInvalidatedField(const Expr *IssueExpr, const FieldDecl *DanglingField,
+ const Expr *InvalidationExpr,
+ const internal::AccessPath &InvalidatedPath) override {
S.Diag(IssueExpr->getExprLoc(),
diag::warn_lifetime_safety_invalidated_field)
<< getDiagSubjectDescription(IssueExpr)
<< getDiagSubjectDescription(DanglingField)
<< IssueExpr->getSourceRange();
- S.Diag(InvalidationExpr->getExprLoc(), InvalidationDiag)
- << InvalidationExpr->getSourceRange();
+ reportInvalidationNote(InvalidationExpr, InvalidatedPath);
S.Diag(DanglingField->getLocation(),
diag::note_lifetime_safety_dangling_field_here)
<< DanglingField->getEndLoc();
}
- void reportInvalidatedField(const ParmVarDecl *PVD,
- const FieldDecl *DanglingField,
- const Expr *InvalidationExpr) override {
- auto InvalidationDiag = isa<CXXDeleteExpr>(InvalidationExpr)
- ? diag::note_lifetime_safety_freed_here
- : diag::note_lifetime_safety_invalidated_here;
+ void
+ reportInvalidatedField(const ParmVarDecl *PVD, const FieldDecl *DanglingField,
+ const Expr *InvalidationExpr,
+ const internal::AccessPath &InvalidatedPath) override {
S.Diag(PVD->getSourceRange().getBegin(),
diag::warn_lifetime_safety_invalidated_field)
<< getDiagSubjectDescription(PVD)
<< getDiagSubjectDescription(DanglingField) << PVD->getSourceRange();
- S.Diag(InvalidationExpr->getExprLoc(), InvalidationDiag)
- << InvalidationExpr->getSourceRange();
+ reportInvalidationNote(InvalidationExpr, InvalidatedPath);
S.Diag(DanglingField->getLocation(),
diag::note_lifetime_safety_dangling_field_here)
<< DanglingField->getEndLoc();
}
- void reportInvalidatedGlobal(const Expr *IssueExpr,
- const VarDecl *DanglingGlobal,
- const Expr *InvalidationExpr) override {
- auto InvalidationDiag = isa<CXXDeleteExpr>(InvalidationExpr)
- ? diag::note_lifetime_safety_freed_here
- : diag::note_lifetime_safety_invalidated_here;
+ void reportInvalidatedGlobal(
+ const Expr *IssueExpr, const VarDecl *DanglingGlobal,
+ const Expr *InvalidationExpr,
+ const internal::AccessPath &InvalidatedPath) override {
S.Diag(IssueExpr->getExprLoc(),
diag::warn_lifetime_safety_invalidated_global)
<< getDiagSubjectDescription(IssueExpr)
<< getDiagSubjectDescription(DanglingGlobal)
<< IssueExpr->getSourceRange();
- S.Diag(InvalidationExpr->getExprLoc(), InvalidationDiag)
- << InvalidationExpr->getSourceRange();
+ reportInvalidationNote(InvalidationExpr, InvalidatedPath);
if (DanglingGlobal->isStaticLocal() || DanglingGlobal->isStaticDataMember())
S.Diag(DanglingGlobal->getLocation(),
diag::note_lifetime_safety_dangling_static_here)
@@ -252,18 +241,15 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper {
<< DanglingGlobal->getEndLoc();
}
- void reportInvalidatedGlobal(const ParmVarDecl *PVD,
- const VarDecl *DanglingGlobal,
- const Expr *InvalidationExpr) override {
- auto InvalidationDiag = isa<CXXDeleteExpr>(InvalidationExpr)
- ? diag::note_lifetime_safety_freed_here
- : diag::note_lifetime_safety_invalidated_here;
+ void reportInvalidatedGlobal(
+ const ParmVarDecl *PVD, const VarDecl *DanglingGlobal,
+ const Expr *InvalidationExpr,
+ const internal::AccessPath &InvalidatedPath) override {
S.Diag(PVD->getSourceRange().getBegin(),
diag::warn_lifetime_safety_invalidated_global)
<< getDiagSubjectDescription(PVD)
<< getDiagSubjectDescription(DanglingGlobal) << PVD->getSourceRange();
- S.Diag(InvalidationExpr->getExprLoc(), InvalidationDiag)
- << InvalidationExpr->getSourceRange();
+ reportInvalidationNote(InvalidationExpr, InvalidatedPath);
if (DanglingGlobal->isStaticLocal() || DanglingGlobal->isStaticDataMember())
S.Diag(DanglingGlobal->getLocation(),
diag::note_lifetime_safety_dangling_static_here)
@@ -441,6 +427,41 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper {
}
private:
+ std::string
+ getDiagStorageDescription(const internal::AccessPath &AccessPath) {
+ if (const auto *VD = AccessPath.getAsValueDecl()) {
+ std::string Res;
+ llvm::raw_string_ostream OS(Res);
+ OS << "'";
+ VD->getNameForDiagnostic(OS, S.getPrintingPolicy(), /*Qualified=*/false);
+ OS << "'";
+ return Res;
+ }
+ if (AccessPath.getAsMaterializeTemporaryExpr())
+ return "temporary object";
+ if (const auto *PVD = AccessPath.getAsPlaceholderParam())
+ return getDiagSubjectDescription(PVD);
+ if (AccessPath.getAsPlaceholderThis())
+ return "the object referenced by 'this'";
+ if (AccessPath.getAsNewAllocation())
+ return "allocated object";
+ return "object";
+ }
+
+ void reportInvalidationNote(const Expr *InvalidationExpr,
+ const internal::AccessPath &InvalidatedPath) {
+ if (isa<CXXDeleteExpr>(InvalidationExpr)) {
+ S.Diag(InvalidationExpr->getExprLoc(),
+ diag::note_lifetime_safety_freed_here)
+ << InvalidationExpr->getSourceRange();
+ return;
+ }
+ S.Diag(InvalidationExpr->getExprLoc(),
+ diag::note_lifetime_safety_invalidated_here)
+ << getDiagStorageDescription(InvalidatedPath)
+ << InvalidationExpr->getSourceRange();
+ }
+
std::pair<SourceLocation, StringRef>
getLifetimeBoundFixIt(const ParmVarDecl *Decl) {
SourceLocation InsertionPoint = Lexer::getLocForEndOfToken(
>From b88c9aa41c826f9a5c8859c550da491218342e17 Mon Sep 17 00:00:00 2001
From: iitianpushkar <pushkarsingh0587 at gmail.com>
Date: Sat, 20 Jun 2026 04:53:45 +0530
Subject: [PATCH 04/14] passed accesspath in semahelper's
afterScope/invalidated report methods
---
clang/lib/Analysis/LifetimeSafety/Checker.cpp | 20 ++++++++++++-------
1 file changed, 13 insertions(+), 7 deletions(-)
diff --git a/clang/lib/Analysis/LifetimeSafety/Checker.cpp b/clang/lib/Analysis/LifetimeSafety/Checker.cpp
index d41d6f43f837b..4c6542599ef31 100644
--- a/clang/lib/Analysis/LifetimeSafety/Checker.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/Checker.cpp
@@ -258,16 +258,18 @@ class LifetimeChecker {
if (IssueExpr)
// Use-after-invalidation of an object on stack.
SemaHelper->reportUseAfterInvalidation(IssueExpr, UF->getUseExpr(),
- Warning.InvalidatedByExpr);
+ Warning.InvalidatedByExpr,
+ L->getAccessPath());
else if (InvalidatedPVD)
// Use-after-invalidation of a parameter.
SemaHelper->reportUseAfterInvalidation(
- InvalidatedPVD, UF->getUseExpr(), Warning.InvalidatedByExpr);
-
+ InvalidatedPVD, UF->getUseExpr(), Warning.InvalidatedByExpr,
+ L->getAccessPath());
} else
// Scope-based expiry (use-after-scope).
SemaHelper->reportUseAfterScope(
IssueExpr, UF->getUseExpr(), MovedExpr, ExpiryLoc,
+ L->getAccessPath(),
getExprChain(LoanPropagation.buildOriginFlowChain(UF, LID)));
} else if (const auto *OEF =
@@ -279,12 +281,14 @@ class LifetimeChecker {
// Invalidated object on stack escapes to a field.
SemaHelper->reportInvalidatedField(IssueExpr,
FieldEscape->getFieldDecl(),
- Warning.InvalidatedByExpr);
+ Warning.InvalidatedByExpr,
+ L->getAccessPath());
else if (InvalidatedPVD)
// Invalidated parameter escapes to a field.
SemaHelper->reportInvalidatedField(InvalidatedPVD,
FieldEscape->getFieldDecl(),
- Warning.InvalidatedByExpr);
+ Warning.InvalidatedByExpr,
+ L->getAccessPath());
} else if (const auto *GlobalEscape =
dyn_cast<GlobalEscapeFact>(OEF)) {
// Invalidated object escapes to global or static storage.
@@ -293,12 +297,14 @@ class LifetimeChecker {
// storage.
SemaHelper->reportInvalidatedGlobal(IssueExpr,
GlobalEscape->getGlobal(),
- Warning.InvalidatedByExpr);
+ Warning.InvalidatedByExpr,
+ L->getAccessPath());
else if (InvalidatedPVD)
// Invalidated parameter escapes to global or static storage.
SemaHelper->reportInvalidatedGlobal(InvalidatedPVD,
GlobalEscape->getGlobal(),
- Warning.InvalidatedByExpr);
+ Warning.InvalidatedByExpr,
+ L->getAccessPath());
} else if (isa<ReturnEscapeFact>(OEF)) {
// FIXME: Diagnose invalidated return escapes separately.
} else
>From 577fdc8ee7658e1134cce3b6d93425521deadfab Mon Sep 17 00:00:00 2001
From: iitianpushkar <pushkarsingh0587 at gmail.com>
Date: Sat, 20 Jun 2026 05:12:11 +0530
Subject: [PATCH 05/14] tests passed for storage-aware
destruction/invalidations notes
---
clang/test/Sema/LifetimeSafety/invalidations.cpp | 2 +-
clang/test/Sema/LifetimeSafety/safety.cpp | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/clang/test/Sema/LifetimeSafety/invalidations.cpp b/clang/test/Sema/LifetimeSafety/invalidations.cpp
index 301822f066de8..b5eb886980ce0 100644
--- a/clang/test/Sema/LifetimeSafety/invalidations.cpp
+++ b/clang/test/Sema/LifetimeSafety/invalidations.cpp
@@ -8,7 +8,7 @@ namespace SimpleResize {
void IteratorInvalidAfterResize(int new_size) {
std::vector<int> v;
auto it = std::begin(v); // expected-warning {{local variable 'v' is later invalidated}}
- v.resize(new_size); // expected-note {{invalidated here}}
+ v.resize(new_size); // expected-note {{'v' is invalidated here}}
*it; // expected-note {{later used here}}
}
diff --git a/clang/test/Sema/LifetimeSafety/safety.cpp b/clang/test/Sema/LifetimeSafety/safety.cpp
index 7a2644e46a6e1..4d78276fa4f78 100644
--- a/clang/test/Sema/LifetimeSafety/safety.cpp
+++ b/clang/test/Sema/LifetimeSafety/safety.cpp
@@ -55,7 +55,7 @@ void simple_case() {
{
MyObj s;
p = &s; // expected-warning {{local variable 's' does not live long enough}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{'s' is destroyed here at the end of its scope}}
(void)*p; // expected-note {{later used here}}
}
@@ -1926,7 +1926,7 @@ const std::string& identity(const std::string& in [[clang::lifetimebound]]);
const S& identity(const S& in [[clang::lifetimebound]]);
void test_temporary() {
- const std::string& x = S().x(); // expected-warning {{temporary object does not live long enough}} expected-note {{destroyed here}} \
+ const std::string& x = S().x(); // expected-warning {{temporary object does not live long enough}} expected-note {{temporary object is destroyed here at the end of the full-expression}} \
// expected-note {{result of call to 'x' aliases the storage of temporary object}}
(void)x; // expected-note {{later used here}}
>From 8e0a03e31ff02523b0edeeae33f2db69daa4cc4a Mon Sep 17 00:00:00 2001
From: iitianpushkar <pushkarsingh0587 at gmail.com>
Date: Sat, 20 Jun 2026 06:41:11 +0530
Subject: [PATCH 06/14] Fixed clang-format CI failure
---
.../Analyses/LifetimeSafety/LifetimeSafety.h | 54 +++++++++----------
clang/lib/Analysis/LifetimeSafety/Checker.cpp | 28 +++++-----
2 files changed, 36 insertions(+), 46 deletions(-)
diff --git a/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h b/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h
index 3e03de134ea6b..4e2412b17ceaf 100644
--- a/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h
+++ b/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h
@@ -83,36 +83,30 @@ class LifetimeSafetySemaHelper {
// Reports when a reference/iterator is used after the container operation
// that invalidated it.
- virtual void reportUseAfterInvalidation(const Expr *IssueExpr,
- const Expr *UseExpr,
- const Expr *InvalidationExpr,
- const internal::AccessPath
- &InvalidatedPath) {}
- virtual void reportUseAfterInvalidation(const ParmVarDecl *PVD,
- const Expr *UseExpr,
- const Expr *InvalidationExpr,
- const internal::AccessPath
- &InvalidatedPath) {}
- virtual void reportInvalidatedField(const Expr *IssueExpr,
- const FieldDecl *Field,
- const Expr *InvalidationExpr,
- const internal::AccessPath
- &InvalidatedPath) {}
- virtual void reportInvalidatedField(const ParmVarDecl *PVD,
- const FieldDecl *Field,
- const Expr *InvalidationExpr,
- const internal::AccessPath
- &InvalidatedPath) {}
- virtual void reportInvalidatedGlobal(const Expr *IssueExpr,
- const VarDecl *Global,
- const Expr *InvalidationExpr,
- const internal::AccessPath
- &InvalidatedPath) {}
- virtual void reportInvalidatedGlobal(const ParmVarDecl *PVD,
- const VarDecl *Global,
- const Expr *InvalidationExpr,
- const internal::AccessPath
- &InvalidatedPath) {}
+ virtual void
+ reportUseAfterInvalidation(const Expr *IssueExpr, const Expr *UseExpr,
+ const Expr *InvalidationExpr,
+ const internal::AccessPath &InvalidatedPath) {}
+ virtual void
+ reportUseAfterInvalidation(const ParmVarDecl *PVD, const Expr *UseExpr,
+ const Expr *InvalidationExpr,
+ const internal::AccessPath &InvalidatedPath) {}
+ virtual void
+ reportInvalidatedField(const Expr *IssueExpr, const FieldDecl *Field,
+ const Expr *InvalidationExpr,
+ const internal::AccessPath &InvalidatedPath) {}
+ virtual void
+ reportInvalidatedField(const ParmVarDecl *PVD, const FieldDecl *Field,
+ const Expr *InvalidationExpr,
+ const internal::AccessPath &InvalidatedPath) {}
+ virtual void
+ reportInvalidatedGlobal(const Expr *IssueExpr, const VarDecl *Global,
+ const Expr *InvalidationExpr,
+ const internal::AccessPath &InvalidatedPath) {}
+ virtual void
+ reportInvalidatedGlobal(const ParmVarDecl *PVD, const VarDecl *Global,
+ const Expr *InvalidationExpr,
+ const internal::AccessPath &InvalidatedPath) {}
using EscapingTarget =
llvm::PointerUnion<const Expr *, const FieldDecl *, const VarDecl *>;
diff --git a/clang/lib/Analysis/LifetimeSafety/Checker.cpp b/clang/lib/Analysis/LifetimeSafety/Checker.cpp
index 4c6542599ef31..ac20e83c8473d 100644
--- a/clang/lib/Analysis/LifetimeSafety/Checker.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/Checker.cpp
@@ -279,32 +279,28 @@ class LifetimeChecker {
// Invalidated object escapes to a field.
if (IssueExpr)
// Invalidated object on stack escapes to a field.
- SemaHelper->reportInvalidatedField(IssueExpr,
- FieldEscape->getFieldDecl(),
- Warning.InvalidatedByExpr,
- L->getAccessPath());
+ SemaHelper->reportInvalidatedField(
+ IssueExpr, FieldEscape->getFieldDecl(),
+ Warning.InvalidatedByExpr, L->getAccessPath());
else if (InvalidatedPVD)
// Invalidated parameter escapes to a field.
- SemaHelper->reportInvalidatedField(InvalidatedPVD,
- FieldEscape->getFieldDecl(),
- Warning.InvalidatedByExpr,
- L->getAccessPath());
+ SemaHelper->reportInvalidatedField(
+ InvalidatedPVD, FieldEscape->getFieldDecl(),
+ Warning.InvalidatedByExpr, L->getAccessPath());
} else if (const auto *GlobalEscape =
dyn_cast<GlobalEscapeFact>(OEF)) {
// Invalidated object escapes to global or static storage.
if (IssueExpr)
// Invalidated object on stack escapes to global or static
// storage.
- SemaHelper->reportInvalidatedGlobal(IssueExpr,
- GlobalEscape->getGlobal(),
- Warning.InvalidatedByExpr,
- L->getAccessPath());
+ SemaHelper->reportInvalidatedGlobal(
+ IssueExpr, GlobalEscape->getGlobal(),
+ Warning.InvalidatedByExpr, L->getAccessPath());
else if (InvalidatedPVD)
// Invalidated parameter escapes to global or static storage.
- SemaHelper->reportInvalidatedGlobal(InvalidatedPVD,
- GlobalEscape->getGlobal(),
- Warning.InvalidatedByExpr,
- L->getAccessPath());
+ SemaHelper->reportInvalidatedGlobal(
+ InvalidatedPVD, GlobalEscape->getGlobal(),
+ Warning.InvalidatedByExpr, L->getAccessPath());
} else if (isa<ReturnEscapeFact>(OEF)) {
// FIXME: Diagnose invalidated return escapes separately.
} else
>From b037f53f47ff26185b3185aca07ed1c183598e7d Mon Sep 17 00:00:00 2001
From: iitianpushkar <pushkarsingh0587 at gmail.com>
Date: Sat, 20 Jun 2026 14:57:49 +0530
Subject: [PATCH 07/14] removed use of accesspath as extra parameter
---
.../Analyses/LifetimeSafety/LifetimeSafety.h | 43 +--
.../clang/Basic/DiagnosticSemaKinds.td | 4 +-
clang/lib/Analysis/LifetimeSafety/Checker.cpp | 31 +-
clang/lib/Sema/SemaLifetimeSafety.h | 109 +++---
.../LifetimeSafety/annotation-suggestions.cpp | 14 +-
.../Sema/LifetimeSafety/invalidations.cpp | 140 ++++----
clang/test/Sema/LifetimeSafety/safety-c.c | 18 +-
clang/test/Sema/LifetimeSafety/safety.cpp | 330 +++++++++---------
8 files changed, 325 insertions(+), 364 deletions(-)
diff --git a/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h b/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h
index 4e2412b17ceaf..28886b826f72f 100644
--- a/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h
+++ b/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h
@@ -64,7 +64,6 @@ class LifetimeSafetySemaHelper {
virtual void reportUseAfterScope(const Expr *IssueExpr, const Expr *UseExpr,
const Expr *MovedExpr,
SourceLocation FreeLoc,
- const internal::AccessPath &ExpiredPath,
llvm::ArrayRef<const Expr *> ExprChain) {}
virtual void reportUseAfterReturn(const Expr *IssueExpr,
@@ -83,30 +82,24 @@ class LifetimeSafetySemaHelper {
// Reports when a reference/iterator is used after the container operation
// that invalidated it.
- virtual void
- reportUseAfterInvalidation(const Expr *IssueExpr, const Expr *UseExpr,
- const Expr *InvalidationExpr,
- const internal::AccessPath &InvalidatedPath) {}
- virtual void
- reportUseAfterInvalidation(const ParmVarDecl *PVD, const Expr *UseExpr,
- const Expr *InvalidationExpr,
- const internal::AccessPath &InvalidatedPath) {}
- virtual void
- reportInvalidatedField(const Expr *IssueExpr, const FieldDecl *Field,
- const Expr *InvalidationExpr,
- const internal::AccessPath &InvalidatedPath) {}
- virtual void
- reportInvalidatedField(const ParmVarDecl *PVD, const FieldDecl *Field,
- const Expr *InvalidationExpr,
- const internal::AccessPath &InvalidatedPath) {}
- virtual void
- reportInvalidatedGlobal(const Expr *IssueExpr, const VarDecl *Global,
- const Expr *InvalidationExpr,
- const internal::AccessPath &InvalidatedPath) {}
- virtual void
- reportInvalidatedGlobal(const ParmVarDecl *PVD, const VarDecl *Global,
- const Expr *InvalidationExpr,
- const internal::AccessPath &InvalidatedPath) {}
+ virtual void reportUseAfterInvalidation(const Expr *IssueExpr,
+ const Expr *UseExpr,
+ const Expr *InvalidationExpr) {}
+ virtual void reportUseAfterInvalidation(const ParmVarDecl *PVD,
+ const Expr *UseExpr,
+ const Expr *InvalidationExpr) {}
+ virtual void reportInvalidatedField(const Expr *IssueExpr,
+ const FieldDecl *Field,
+ const Expr *InvalidationExpr) {}
+ virtual void reportInvalidatedField(const ParmVarDecl *PVD,
+ const FieldDecl *Field,
+ const Expr *InvalidationExpr) {}
+ virtual void reportInvalidatedGlobal(const Expr *IssueExpr,
+ const VarDecl *Global,
+ const Expr *InvalidationExpr) {}
+ virtual void reportInvalidatedGlobal(const ParmVarDecl *PVD,
+ const VarDecl *Global,
+ const Expr *InvalidationExpr) {}
using EscapingTarget =
llvm::PointerUnion<const Expr *, const FieldDecl *, const VarDecl *>;
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 92e80f299dbbb..fbb0ab4fbbf09 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -11053,9 +11053,7 @@ def warn_lifetime_safety_inapplicable_lifetimebound
def note_lifetime_safety_used_here : Note<"later used here">;
def note_lifetime_safety_invalidated_here : Note<"%0 is invalidated here">;
-def note_lifetime_safety_destroyed_here : Note<
- "%0 is destroyed here at the end of "
- "%select{its scope|the full-expression}1">;
+def note_lifetime_safety_destroyed_here : Note<"%0 is 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">;
diff --git a/clang/lib/Analysis/LifetimeSafety/Checker.cpp b/clang/lib/Analysis/LifetimeSafety/Checker.cpp
index ac20e83c8473d..323902da666bb 100644
--- a/clang/lib/Analysis/LifetimeSafety/Checker.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/Checker.cpp
@@ -258,18 +258,15 @@ class LifetimeChecker {
if (IssueExpr)
// Use-after-invalidation of an object on stack.
SemaHelper->reportUseAfterInvalidation(IssueExpr, UF->getUseExpr(),
- Warning.InvalidatedByExpr,
- L->getAccessPath());
+ Warning.InvalidatedByExpr);
else if (InvalidatedPVD)
// Use-after-invalidation of a parameter.
SemaHelper->reportUseAfterInvalidation(
- InvalidatedPVD, UF->getUseExpr(), Warning.InvalidatedByExpr,
- L->getAccessPath());
+ InvalidatedPVD, UF->getUseExpr(), Warning.InvalidatedByExpr);
} else
// Scope-based expiry (use-after-scope).
SemaHelper->reportUseAfterScope(
IssueExpr, UF->getUseExpr(), MovedExpr, ExpiryLoc,
- L->getAccessPath(),
getExprChain(LoanPropagation.buildOriginFlowChain(UF, LID)));
} else if (const auto *OEF =
@@ -279,28 +276,28 @@ class LifetimeChecker {
// Invalidated object escapes to a field.
if (IssueExpr)
// Invalidated object on stack escapes to a field.
- SemaHelper->reportInvalidatedField(
- IssueExpr, FieldEscape->getFieldDecl(),
- Warning.InvalidatedByExpr, L->getAccessPath());
+ SemaHelper->reportInvalidatedField(IssueExpr,
+ FieldEscape->getFieldDecl(),
+ Warning.InvalidatedByExpr);
else if (InvalidatedPVD)
// Invalidated parameter escapes to a field.
- SemaHelper->reportInvalidatedField(
- InvalidatedPVD, FieldEscape->getFieldDecl(),
- Warning.InvalidatedByExpr, L->getAccessPath());
+ SemaHelper->reportInvalidatedField(InvalidatedPVD,
+ FieldEscape->getFieldDecl(),
+ Warning.InvalidatedByExpr);
} else if (const auto *GlobalEscape =
dyn_cast<GlobalEscapeFact>(OEF)) {
// Invalidated object escapes to global or static storage.
if (IssueExpr)
// Invalidated object on stack escapes to global or static
// storage.
- SemaHelper->reportInvalidatedGlobal(
- IssueExpr, GlobalEscape->getGlobal(),
- Warning.InvalidatedByExpr, L->getAccessPath());
+ SemaHelper->reportInvalidatedGlobal(IssueExpr,
+ GlobalEscape->getGlobal(),
+ Warning.InvalidatedByExpr);
else if (InvalidatedPVD)
// Invalidated parameter escapes to global or static storage.
- SemaHelper->reportInvalidatedGlobal(
- InvalidatedPVD, GlobalEscape->getGlobal(),
- Warning.InvalidatedByExpr, L->getAccessPath());
+ SemaHelper->reportInvalidatedGlobal(InvalidatedPVD,
+ GlobalEscape->getGlobal(),
+ Warning.InvalidatedByExpr);
} else if (isa<ReturnEscapeFact>(OEF)) {
// FIXME: Diagnose invalidated return escapes separately.
} else
diff --git a/clang/lib/Sema/SemaLifetimeSafety.h b/clang/lib/Sema/SemaLifetimeSafety.h
index e67478afcf351..cf3138612cda6 100644
--- a/clang/lib/Sema/SemaLifetimeSafety.h
+++ b/clang/lib/Sema/SemaLifetimeSafety.h
@@ -82,21 +82,18 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper {
void reportUseAfterScope(const Expr *IssueExpr, const Expr *UseExpr,
const Expr *MovedExpr, SourceLocation FreeLoc,
- const internal::AccessPath &ExpiredPath,
llvm::ArrayRef<const Expr *> ExprChain) override {
unsigned DiagID = MovedExpr
? diag::warn_lifetime_safety_use_after_scope_moved
: diag::warn_lifetime_safety_use_after_scope;
+ std::string DiagSubject = getDiagSubjectDescription(IssueExpr);
S.Diag(IssueExpr->getExprLoc(), DiagID)
- << getDiagSubjectDescription(IssueExpr) << IssueExpr->getSourceRange();
+ << DiagSubject << IssueExpr->getSourceRange();
if (MovedExpr)
S.Diag(MovedExpr->getExprLoc(), diag::note_lifetime_safety_moved_here)
<< MovedExpr->getSourceRange();
- S.Diag(FreeLoc, diag::note_lifetime_safety_destroyed_here)
- << getDiagStorageDescription(ExpiredPath)
- << (ExpiredPath.getKind() ==
- internal::AccessPath::Kind::MaterializeTemporary);
+ S.Diag(FreeLoc, diag::note_lifetime_safety_destroyed_here) << DiagSubject;
reportAliasingChain(ExprChain);
@@ -165,72 +162,70 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper {
<< DanglingGlobal->getEndLoc();
}
- void reportUseAfterInvalidation(
- const Expr *IssueExpr, const Expr *UseExpr, const Expr *InvalidationExpr,
- const internal::AccessPath &InvalidatedPath) override {
+ void reportUseAfterInvalidation(const Expr *IssueExpr, const Expr *UseExpr,
+ const Expr *InvalidationExpr) override {
auto WarnDiag = isa<CXXDeleteExpr>(InvalidationExpr)
? diag::warn_lifetime_safety_use_after_free
: diag::warn_lifetime_safety_invalidation;
+ std::string DiagSubject = getDiagSubjectDescription(IssueExpr);
S.Diag(IssueExpr->getExprLoc(), WarnDiag)
- << getDiagSubjectDescription(IssueExpr) << IssueExpr->getSourceRange();
- reportInvalidationNote(InvalidationExpr, InvalidatedPath);
+ << DiagSubject << IssueExpr->getSourceRange();
+ reportInvalidationNote(InvalidationExpr, DiagSubject);
S.Diag(UseExpr->getExprLoc(), diag::note_lifetime_safety_used_here)
<< UseExpr->getSourceRange();
}
- void reportUseAfterInvalidation(
- const ParmVarDecl *PVD, const Expr *UseExpr, const Expr *InvalidationExpr,
- const internal::AccessPath &InvalidatedPath) override {
+ void reportUseAfterInvalidation(const ParmVarDecl *PVD, const Expr *UseExpr,
+ const Expr *InvalidationExpr) override {
auto WarnDiag = isa<CXXDeleteExpr>(InvalidationExpr)
? diag::warn_lifetime_safety_use_after_free
: diag::warn_lifetime_safety_invalidation;
+ std::string DiagSubject = getDiagSubjectDescription(PVD);
S.Diag(PVD->getSourceRange().getBegin(), WarnDiag)
- << getDiagSubjectDescription(PVD) << PVD->getSourceRange();
- reportInvalidationNote(InvalidationExpr, InvalidatedPath);
+ << DiagSubject << PVD->getSourceRange();
+ reportInvalidationNote(InvalidationExpr, DiagSubject);
S.Diag(UseExpr->getExprLoc(), diag::note_lifetime_safety_used_here)
<< UseExpr->getSourceRange();
}
- void
- reportInvalidatedField(const Expr *IssueExpr, const FieldDecl *DanglingField,
- const Expr *InvalidationExpr,
- const internal::AccessPath &InvalidatedPath) override {
+ void reportInvalidatedField(const Expr *IssueExpr,
+ const FieldDecl *DanglingField,
+ const Expr *InvalidationExpr) override {
+ std::string DiagSubject = getDiagSubjectDescription(IssueExpr);
S.Diag(IssueExpr->getExprLoc(),
diag::warn_lifetime_safety_invalidated_field)
- << getDiagSubjectDescription(IssueExpr)
- << getDiagSubjectDescription(DanglingField)
+ << DiagSubject << getDiagSubjectDescription(DanglingField)
<< IssueExpr->getSourceRange();
- reportInvalidationNote(InvalidationExpr, InvalidatedPath);
+ reportInvalidationNote(InvalidationExpr, DiagSubject);
S.Diag(DanglingField->getLocation(),
diag::note_lifetime_safety_dangling_field_here)
<< DanglingField->getEndLoc();
}
- void
- reportInvalidatedField(const ParmVarDecl *PVD, const FieldDecl *DanglingField,
- const Expr *InvalidationExpr,
- const internal::AccessPath &InvalidatedPath) override {
+ void reportInvalidatedField(const ParmVarDecl *PVD,
+ const FieldDecl *DanglingField,
+ const Expr *InvalidationExpr) override {
+ std::string DiagSubject = getDiagSubjectDescription(PVD);
S.Diag(PVD->getSourceRange().getBegin(),
diag::warn_lifetime_safety_invalidated_field)
- << getDiagSubjectDescription(PVD)
- << getDiagSubjectDescription(DanglingField) << PVD->getSourceRange();
- reportInvalidationNote(InvalidationExpr, InvalidatedPath);
+ << DiagSubject << getDiagSubjectDescription(DanglingField)
+ << PVD->getSourceRange();
+ reportInvalidationNote(InvalidationExpr, DiagSubject);
S.Diag(DanglingField->getLocation(),
diag::note_lifetime_safety_dangling_field_here)
<< DanglingField->getEndLoc();
}
- void reportInvalidatedGlobal(
- const Expr *IssueExpr, const VarDecl *DanglingGlobal,
- const Expr *InvalidationExpr,
- const internal::AccessPath &InvalidatedPath) override {
+ void reportInvalidatedGlobal(const Expr *IssueExpr,
+ const VarDecl *DanglingGlobal,
+ const Expr *InvalidationExpr) override {
+ std::string DiagSubject = getDiagSubjectDescription(IssueExpr);
S.Diag(IssueExpr->getExprLoc(),
diag::warn_lifetime_safety_invalidated_global)
- << getDiagSubjectDescription(IssueExpr)
- << getDiagSubjectDescription(DanglingGlobal)
+ << DiagSubject << getDiagSubjectDescription(DanglingGlobal)
<< IssueExpr->getSourceRange();
- reportInvalidationNote(InvalidationExpr, InvalidatedPath);
+ reportInvalidationNote(InvalidationExpr, DiagSubject);
if (DanglingGlobal->isStaticLocal() || DanglingGlobal->isStaticDataMember())
S.Diag(DanglingGlobal->getLocation(),
diag::note_lifetime_safety_dangling_static_here)
@@ -241,15 +236,15 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper {
<< DanglingGlobal->getEndLoc();
}
- void reportInvalidatedGlobal(
- const ParmVarDecl *PVD, const VarDecl *DanglingGlobal,
- const Expr *InvalidationExpr,
- const internal::AccessPath &InvalidatedPath) override {
+ void reportInvalidatedGlobal(const ParmVarDecl *PVD,
+ const VarDecl *DanglingGlobal,
+ const Expr *InvalidationExpr) override {
+ std::string DiagSubject = getDiagSubjectDescription(PVD);
S.Diag(PVD->getSourceRange().getBegin(),
diag::warn_lifetime_safety_invalidated_global)
- << getDiagSubjectDescription(PVD)
- << getDiagSubjectDescription(DanglingGlobal) << PVD->getSourceRange();
- reportInvalidationNote(InvalidationExpr, InvalidatedPath);
+ << DiagSubject << getDiagSubjectDescription(DanglingGlobal)
+ << PVD->getSourceRange();
+ reportInvalidationNote(InvalidationExpr, DiagSubject);
if (DanglingGlobal->isStaticLocal() || DanglingGlobal->isStaticDataMember())
S.Diag(DanglingGlobal->getLocation(),
diag::note_lifetime_safety_dangling_static_here)
@@ -427,29 +422,8 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper {
}
private:
- std::string
- getDiagStorageDescription(const internal::AccessPath &AccessPath) {
- if (const auto *VD = AccessPath.getAsValueDecl()) {
- std::string Res;
- llvm::raw_string_ostream OS(Res);
- OS << "'";
- VD->getNameForDiagnostic(OS, S.getPrintingPolicy(), /*Qualified=*/false);
- OS << "'";
- return Res;
- }
- if (AccessPath.getAsMaterializeTemporaryExpr())
- return "temporary object";
- if (const auto *PVD = AccessPath.getAsPlaceholderParam())
- return getDiagSubjectDescription(PVD);
- if (AccessPath.getAsPlaceholderThis())
- return "the object referenced by 'this'";
- if (AccessPath.getAsNewAllocation())
- return "allocated object";
- return "object";
- }
-
void reportInvalidationNote(const Expr *InvalidationExpr,
- const internal::AccessPath &InvalidatedPath) {
+ StringRef DiagSubject) {
if (isa<CXXDeleteExpr>(InvalidationExpr)) {
S.Diag(InvalidationExpr->getExprLoc(),
diag::note_lifetime_safety_freed_here)
@@ -458,8 +432,7 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper {
}
S.Diag(InvalidationExpr->getExprLoc(),
diag::note_lifetime_safety_invalidated_here)
- << getDiagStorageDescription(InvalidatedPath)
- << InvalidationExpr->getSourceRange();
+ << DiagSubject << InvalidationExpr->getSourceRange();
}
std::pair<SourceLocation, StringRef>
diff --git a/clang/test/Sema/LifetimeSafety/annotation-suggestions.cpp b/clang/test/Sema/LifetimeSafety/annotation-suggestions.cpp
index cef3397b57a6f..87bc2a24188bc 100644
--- a/clang/test/Sema/LifetimeSafety/annotation-suggestions.cpp
+++ b/clang/test/Sema/LifetimeSafety/annotation-suggestions.cpp
@@ -277,21 +277,21 @@ View return_view_field(const ViewProvider& v) { // expected-warning {{paramet
void test_get_on_temporary_pointer() {
const ReturnsSelf* s_ref = &ReturnsSelf().get(); // expected-warning {{temporary object does not live long enough}}.
- // expected-note at -1 {{destroyed here}}
+ // expected-note at -1 {{is destroyed here}}
// expected-note at -2 {{result of call to 'get' aliases the storage of temporary object}}
(void)s_ref; // expected-note {{later used here}}
}
void test_get_on_temporary_ref() {
const ReturnsSelf& s_ref = ReturnsSelf().get(); // expected-warning {{temporary object does not live long enough}}.
- // expected-note at -1 {{destroyed here}}
+ // expected-note at -1 {{is destroyed here}}
// expected-note at -2 {{result of call to 'get' aliases the storage of temporary object}}
(void)s_ref; // expected-note {{later used here}}
}
void test_getView_on_temporary() {
View sv = ViewProvider{1}.getView(); // expected-warning {{temporary object does not live long enough}}.
- // expected-note at -1 {{destroyed here}}
+ // expected-note at -1 {{is destroyed here}}
// expected-note at -2 {{result of call to 'getView' aliases the storage of temporary object}}
(void)sv; // expected-note {{later used here}}
}
@@ -604,7 +604,7 @@ void uaf_via_inferred_lifetimebound() {
int local;
f = return_lambda_capturing_param(local); // expected-warning {{local variable 'local' does not live long enough}} \
// expected-note {{result of call to 'return_lambda_capturing_param' aliases the storage of local variable 'local'}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)f; // expected-note {{later used here}}
}
@@ -628,7 +628,7 @@ void test_inference() {
MyObj obj;
ptr = create_target(obj); // expected-warning {{local variable 'obj' does not live long enough}} \
// expected-note {{result of call to 'create_target' aliases the storage of local variable 'obj'}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)ptr; // expected-note {{later used here}}
}
} // namespace make_unique_suggestion
@@ -636,12 +636,12 @@ void test_inference() {
namespace new_allocation_suggestion {
View* MakeView(const MyObj& in) { // expected-warning {{parameter in intra-TU function should be marked [[clang::lifetimebound]]}}
- return new View(in); // expected-note {{param returned here}} {{destroyed here}}
+ return new View(in); // expected-note {{param returned here}} {{is destroyed here}}
}
void test_new_allocation() {
View* v = MakeView(MyObj{}); // expected-warning {{temporary object does not live long enough}} \
- // expected-note {{destroyed here}} \
+ // expected-note {{is destroyed here}} \
// expected-note {{result of call to 'MakeView' aliases the storage of temporary object}}
(void)v; // expected-note {{later used here}}
}
diff --git a/clang/test/Sema/LifetimeSafety/invalidations.cpp b/clang/test/Sema/LifetimeSafety/invalidations.cpp
index b5eb886980ce0..5b612d2c4de5b 100644
--- a/clang/test/Sema/LifetimeSafety/invalidations.cpp
+++ b/clang/test/Sema/LifetimeSafety/invalidations.cpp
@@ -8,7 +8,7 @@ namespace SimpleResize {
void IteratorInvalidAfterResize(int new_size) {
std::vector<int> v;
auto it = std::begin(v); // expected-warning {{local variable 'v' is later invalidated}}
- v.resize(new_size); // expected-note {{'v' is invalidated here}}
+ v.resize(new_size); // expected-note {{local variable 'v' is invalidated here}}
*it; // expected-note {{later used here}}
}
@@ -53,7 +53,7 @@ void InvalidateBeforeSwapIterators(std::vector<int> v1, std::vector<int> v2) {
if (it1 == std::end(v1) || it2 == std::end(v2)) return;
*it1 = 0; // ok
*it2 = 0; // ok
- v1.clear(); // expected-note {{invalidated here}}
+ v1.clear(); // expected-note {{is invalidated here}}
*it1 = 0; // expected-note {{later used here}}
// FIXME: Handle invalidating functions like std::swap.
std::swap(it1, it2);
@@ -67,7 +67,7 @@ void InvalidateBeforeSwapContainers(std::vector<int> v1, std::vector<int> v2) {
if (it1 == std::end(v1) || it2 == std::end(v2)) return;
*it1 = 0; // ok
*it2 = 0; // ok
- v1.clear(); // expected-note {{invalidated here}}
+ v1.clear(); // expected-note {{is invalidated here}}
*it1 = 0; // expected-note {{later used here}}
}
} // namespace InvalidateBeforeSwap
@@ -81,7 +81,7 @@ void SameConditionInvalidatesThenValidatesIterator() {
if (it == container.end()) return;
const bool a = A();
if (a) {
- container.clear(); // expected-note {{invalidated here}}
+ container.clear(); // expected-note {{is invalidated here}}
}
if (a) {
it = container.begin();
@@ -112,7 +112,7 @@ void MergeWithDifferentContainerValuesInvalidated() {
} else {
it = std::find(v3.begin(), v3.end(), 10);
}
- v2.clear(); // expected-note {{invalidated here}}
+ v2.clear(); // expected-note {{is invalidated here}}
*it = 20; // expected-note {{later used here}}
}
} // namespace IteratorWithMultipleContainers
@@ -123,7 +123,7 @@ void IteratorInvalidationInAForLoop(std::vector<int> v) {
it != std::end(v);
++it) { // expected-note {{later used here}}
if (Bool()) {
- v.erase(it); // expected-note {{invalidated here}}
+ v.erase(it); // expected-note {{is invalidated here}}
}
}
}
@@ -132,7 +132,7 @@ void IteratorInvalidationInAWhileLoop(std::vector<int> v) {
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}}
+ v.erase(it); // expected-note {{is invalidated here}}
}
++it; // expected-note {{later used here}}
}
@@ -157,7 +157,7 @@ void IteratorInvalidationInAForeachLoop(std::vector<int> v) {
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}}
+ v.erase(std::find(v.begin(), v.end(), 1)); // expected-note {{is invalidated here}}
}
}
}
@@ -185,7 +185,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 {{parameter 'v' is later invalidated}}
if (it != std::end(v)) {
- v.erase(it); // expected-note {{invalidated here}}
+ v.erase(it); // expected-note {{is invalidated here}}
}
*it; // expected-note {{later used here}}
}
@@ -202,7 +202,7 @@ void UseReturnedIteratorAfterInsert(std::vector<int> v) {
void UseInvalidIteratorAfterInsert(std::vector<int> v) {
auto it = std::begin(v); // expected-warning {{parameter 'v' is later invalidated}}
- v.insert(it, 10); // expected-note {{invalidated here}}
+ v.insert(it, 10); // expected-note {{is invalidated here}}
if (it != std::end(v)) { // expected-note {{later used here}}
*it;
}
@@ -221,7 +221,7 @@ void IteratorValidAfterInsert(std::vector<int> v) {
void IteratorInvalidAfterInsert(std::vector<int> v, int value) {
auto it = std::begin(v); // expected-warning {{parameter 'v' is later invalidated}}
- v.insert(it, 0); // expected-note {{invalidated here}}
+ v.insert(it, 0); // expected-note {{is invalidated here}}
*it; // expected-note {{later used here}}
}
} // namespace SimpleStdInsert
@@ -231,7 +231,7 @@ void IteratorUsedAfterErase(std::vector<int> v) {
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}}
+ v.erase(it); // expected-note {{is invalidated here}}
}
}
}
@@ -239,7 +239,7 @@ void IteratorUsedAfterErase(std::vector<int> v) {
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}}
+ v.push_back(4); // expected-note {{is invalidated here}}
}
++it; // expected-note {{later used here}}
}
@@ -247,7 +247,7 @@ void IteratorUsedAfterPushBackParam(std::vector<int>& v) { // expected-warning {
void IteratorUsedAfterPushBack(std::vector<int> v) {
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}}
+ v.push_back(4); // expected-note {{is invalidated here}}
}
++it; // expected-note {{later used here}}
}
@@ -256,14 +256,14 @@ void IteratorUsedAfterPreIncrement() {
std::vector<int> v;
auto it = v.begin(); // expected-warning {{local variable 'v' is later invalidated}}
auto next = ++it;
- v.push_back(1); // expected-note {{invalidated here}}
+ v.push_back(1); // expected-note {{is invalidated here}}
(void)*next; // expected-note {{later used here}}
}
void IteratorUsedAfterPostDecrement(std::vector<int> v) {
auto it = v.rbegin(); // expected-warning {{parameter 'v' is later invalidated}}
auto prev = it--;
- v.push_back(1); // expected-note {{invalidated here}}
+ v.push_back(1); // expected-note {{is invalidated here}}
(void)*prev; // expected-note {{later used here}}
}
@@ -271,21 +271,21 @@ void IteratorUsedAfterAddition() {
std::vector<int> v;
auto it = v.cbegin(); // expected-warning {{local variable 'v' is later invalidated}}
auto next = it + 5;
- v.push_back(1); // expected-note {{invalidated here}}
+ v.push_back(1); // expected-note {{is invalidated here}}
(void)*next; // expected-note {{later used here}}
}
void IteratorUsedAfterReverseSubtraction(std::vector<int> v) {
auto it = v.crbegin(); // expected-warning {{parameter 'v' is later invalidated}}
auto prev = 5 - it;
- v.push_back(1); // expected-note {{invalidated here}}
+ v.push_back(1); // expected-note {{is invalidated here}}
(void)*prev; // expected-note {{later used here}}
}
void IteratorUsedAfterAddAdd(std::vector<int> v) {
auto it = v.cbegin(); // expected-warning {{parameter 'v' is later invalidated}}
auto next = (it + 5) + 5;
- v.push_back(1); // expected-note {{invalidated here}}
+ v.push_back(1); // expected-note {{is invalidated here}}
(void)*next; // expected-note {{later used here}}
}
@@ -293,21 +293,21 @@ void IteratorUsedAfterMixedAddition() {
std::vector<int> v;
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}}
+ v.push_back(1); // expected-note {{is invalidated here}}
(void)*next; // expected-note {{later used here}}
}
void IteratorUsedAfterPreIncrementAddAssign(std::vector<int> v) {
auto it = v.begin(); // expected-warning {{parameter 'v' is later invalidated}}
it = ++it + 1 + 2;
- v.push_back(1); // expected-note {{invalidated here}}
+ v.push_back(1); // expected-note {{is invalidated here}}
(void)*it; // expected-note {{later used here}}
}
void IteratorUsedAfterBeginAddAssign() {
std::vector<int> v;
auto it = v.begin() + 1; // expected-warning {{local variable 'v' is later invalidated}}
- v.push_back(1); // expected-note {{invalidated here}}
+ v.push_back(1); // expected-note {{is invalidated here}}
(void)*it; // expected-note {{later used here}}
}
@@ -315,7 +315,7 @@ void IteratorUsedAfterStdBeginAddAssign() {
std::vector<int> v;
std::vector<int>::iterator it;
it = std::begin(v) + 1; // expected-warning {{local variable 'v' is later invalidated}}
- v.push_back(1); // expected-note {{invalidated here}}
+ v.push_back(1); // expected-note {{is invalidated here}}
(void)*it; // expected-note {{later used here}}
}
} // namespace SimpleInvalidIterators
@@ -325,13 +325,13 @@ void IteratorInvalidatedThroughLocalReferenceAlias() {
std::vector<int> vv;
std::vector<int> &v = vv;
auto it = vv.begin(); // expected-warning {{local variable 'vv' is later invalidated}}
- v.push_back(42); // expected-note {{invalidated here}}
+ v.push_back(42); // expected-note {{is invalidated here}}
(void)it; // expected-note {{later used here}}
}
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}}
+ v->push_back(42); // expected-note {{is invalidated here}}
(void)it; // expected-note {{later used here}}
}
@@ -348,7 +348,7 @@ void ParenthesizedContainerInvalidatesIterator() {
namespace ContainerObjectAliases {
// FIXME: Distinguish owner-borrow from content-borrow.
void PointerParameterObjectUseIsOk(std::vector<int> *v) { // expected-warning {{parameter 'v' is later invalidated}}
- v->push_back(42); // expected-note {{invalidated here}}
+ v->push_back(42); // expected-note {{is invalidated here}}
(void)v; // expected-note {{later used here}}
}
@@ -356,7 +356,7 @@ void PointerParameterObjectUseIsOk(std::vector<int> *v) { // expected-warning {{
void LocalPointerAliasObjectUseIsOk() {
std::vector<int> vv;
std::vector<int> *v = &vv; // expected-warning {{local variable 'vv' is later invalidated}}
- v->push_back(42); // expected-note {{invalidated here}}
+ v->push_back(42); // expected-note {{is invalidated here}}
(void)*v; // expected-note {{later used here}}
}
@@ -364,7 +364,7 @@ void LocalPointerAliasObjectUseIsOk() {
void LocalReferenceAliasObjectUseIsOk() {
std::vector<int> vv;
std::vector<int> &v = vv; // expected-warning {{local variable 'vv' is later invalidated}}
- v.push_back(42); // expected-note {{invalidated here}}
+ v.push_back(42); // expected-note {{is invalidated here}}
(void)v; // expected-note {{later used here}}
}
} // namespace ContainerObjectAliases
@@ -375,7 +375,7 @@ namespace ElementReferences {
void ReferenceToVectorElement() {
std::vector<int> v = {1, 2, 3};
int& ref = v[0]; // expected-warning {{local variable 'v' is later invalidated}}
- v.push_back(4); // expected-note {{invalidated here}}
+ v.push_back(4); // expected-note {{is invalidated here}}
ref = 10; // expected-note {{later used here}}
(void)ref;
}
@@ -383,14 +383,14 @@ void ReferenceToVectorElement() {
void PointerRefToVectorElement() {
std::vector<int*> v = {nullptr, nullptr};
int*& ref = v[0]; // expected-warning {{local variable 'v' is later invalidated}}
- v.push_back(nullptr); // expected-note {{invalidated here}}
+ v.push_back(nullptr); // expected-note {{is invalidated here}}
ref = nullptr; // expected-note {{later used here}}
}
void PointerToVectorElement() {
std::vector<int> v = {1, 2, 3};
int* ptr = &v[0]; // expected-warning {{local variable 'v' is later invalidated}}
- v.resize(100); // expected-note {{invalidated here}}
+ v.resize(100); // expected-note {{is invalidated here}}
*ptr = 10; // expected-note {{later used here}}
}
@@ -403,7 +403,7 @@ void SelfInvalidatingMap() {
// On the other hand, std::flat_map (since C++23) does not provide pointer stability on
// insertion and following is unsafe for this container.
mp[1] = "42";
- mp[2] // expected-note {{invalidated here}}
+ mp[2] // expected-note {{is invalidated here}}
=
mp[1]; // expected-warning {{local variable 'mp' is later invalidated}} expected-note {{later used here}}
}
@@ -412,7 +412,7 @@ 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 {{local variable 'mp' is later invalidated}}
- mp.erase(mp.find(4)); // expected-note {{invalidated here}}
+ mp.erase(mp.find(4)); // expected-note {{is invalidated here}}
if (it != mp.end()) // expected-note {{later used here}}
*it;
}
@@ -422,12 +422,12 @@ namespace Strings {
void append(std::string str) {
std::string_view view = str; // expected-warning {{parameter 'str' is later invalidated}}
- str += "456"; // expected-note {{invalidated here}}
+ str += "456"; // expected-note {{is invalidated here}}
(void)view; // expected-note {{later used here}}
}
void reassign(std::string str, std::string str2) {
std::string_view view = str; // expected-warning {{parameter 'str' is later invalidated}}
- str = str2; // expected-note {{invalidated here}}
+ str = str2; // expected-note {{is invalidated here}}
(void)view; // expected-note {{later used here}}
}
} // namespace Strings
@@ -437,7 +437,7 @@ void ReassigningAfterMove(std::string str, std::string str2) {
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}}
+ str = str2; // expected-note {{is invalidated here}}
(void)view; // expected-note {{later used here}}
}
@@ -480,7 +480,7 @@ void Invalidate1Use2ViaRefIsOk() {
S s;
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}}
+ strings1.push_back("1"); // expected-note {{is invalidated here}}
*it; // expected-note {{later used here}}
}
void Invalidate1UseSIsOk() {
@@ -493,14 +493,14 @@ void Invalidate1UseSIsOk() {
void PointerToContainerIsOk() {
std::vector<std::string> s;
std::vector<std::string>* p = &s; // expected-warning {{local variable 's' is later invalidated}}
- p->push_back("1"); // expected-note {{invalidated here}}
+ p->push_back("1"); // expected-note {{is invalidated here}}
(void)*p; // expected-note {{later used here}}
}
void IteratorFromPointerToContainerIsInvalidated() {
std::vector<std::string> s;
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}}
+ p->push_back("1"); // expected-note {{is invalidated here}}
*it; // expected-note {{later used here}}
}
// FIXME: Distinguish invalidating an element's contents from invalidating
@@ -508,7 +508,7 @@ void IteratorFromPointerToContainerIsInvalidated() {
void ChangingRegionOwnedByContainerIsOk() {
std::vector<std::string> subdirs;
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}}
+ path = std::string(); // expected-note {{is invalidated here}}
}
} // namespace ContainersAsFields
@@ -522,7 +522,7 @@ struct SinkOwnerBorrow {
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}}
+ dest->clear(); // expected-note {{is invalidated here}}
}
};
@@ -531,7 +531,7 @@ struct SinkInteriorBorrow {
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}}
+ dest->clear(); // expected-note {{is invalidated here}}
}
};
@@ -548,28 +548,28 @@ struct S {
void InvalidatedFieldLocalVector() {
std::vector<std::string> strings;
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}}
+ strings.push_back("1"); // expected-note {{is invalidated here}}
}
void InvalidatedFieldByValueParamVector(std::vector<std::string> strings) {
FieldFromByValueParamVector = *strings.begin(); // expected-warning {{parameter 'strings' escapes to the field 'FieldFromByValueParamVector' and is later invalidated}}
- strings.push_back("1"); // expected-note {{invalidated here}}
+ strings.push_back("1"); // expected-note {{is invalidated here}}
}
void InvalidatedFieldLocalString() {
std::string s;
FieldFromLocalString = s; // expected-warning {{local variable 's' escapes to the field 'FieldFromLocalString' and is later invalidated}}
- s.clear(); // expected-note {{invalidated here}}
+ s.clear(); // expected-note {{is invalidated here}}
}
void InvalidatedFieldByValueParamString(std::string s) {
FieldFromByValueParamString = s; // expected-warning {{parameter 's' escapes to the field 'FieldFromByValueParamString' and is later invalidated}}
- s.clear(); // expected-note {{invalidated here}}
+ s.clear(); // expected-note {{is invalidated here}}
}
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}}
+ s.~basic_string(); // expected-note {{is invalidated here}}
}
void InvalidatedFieldDelete() {
@@ -608,17 +608,17 @@ struct S {
void InvalidatedGlobalLocalVector() {
std::vector<std::string> strings;
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}}
+ strings.push_back("1"); // expected-note {{is invalidated here}}
}
void InvalidatedGlobalByValueParamString(std::string s) {
GlobalFromByValueParamString = s; // expected-warning {{parameter 's' escapes to the global variable 'GlobalFromByValueParamString' and is later invalidated}}
- s.clear(); // expected-note {{invalidated here}}
+ s.clear(); // expected-note {{is invalidated here}}
}
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}}
+ s.~basic_string(); // expected-note {{is invalidated here}}
}
void InvalidatedGlobalDelete() {
@@ -636,13 +636,13 @@ void InvalidatedStaticLocalString() {
static std::string_view StaticFromLocalString; // expected-note {{this static storage dangles}}
std::string s;
StaticFromLocalString = s; // expected-warning {{local variable 's' escapes to the static variable 'StaticFromLocalString' and is later invalidated}}
- s.clear(); // expected-note {{invalidated here}}
+ s.clear(); // expected-note {{is invalidated here}}
}
void InvalidatedStaticMemberString() {
std::string s;
S::StaticMember = s; // expected-warning {{local variable 's' escapes to the static variable 'StaticMember' and is later invalidated}}
- s.clear(); // expected-note {{invalidated here}}
+ s.clear(); // expected-note {{is invalidated here}}
}
void GlobalReassignedBeforeInvalidation() {
@@ -715,14 +715,14 @@ void SetExtractDoesNotInvalidateOthers() {
void SetClearInvalidates() {
std::set<int> s;
auto it = s.begin(); // expected-warning {{local variable 's' is later invalidated}}
- s.clear(); // expected-note {{invalidated here}}
+ s.clear(); // expected-note {{is invalidated here}}
*it; // expected-note {{later used here}}
}
void MapClearInvalidates() {
std::map<int, int> m;
auto it = m.begin(); // expected-warning {{local variable 'm' is later invalidated}}
- m.clear(); // expected-note {{invalidated here}}
+ m.clear(); // expected-note {{is invalidated here}}
*it; // expected-note {{later used here}}
}
@@ -741,7 +741,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 {{parameter 'mp' is later invalidated}} \
- // expected-note {{invalidated here}} \
+ // expected-note {{is invalidated here}} \
// expected-note {{later used here}}
}
@@ -752,7 +752,7 @@ void captured_view_invalidated_by_owner() {
std::string s = "42";
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}}
+ s.push_back('c'); // expected-note {{is invalidated here}}
lambda(); // expected-note {{later used here}}
}
@@ -760,7 +760,7 @@ void multiple_captures_one_invalidated() {
std::string s1 = "a", s2 = "b";
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}}
+ s1.clear(); // expected-note {{is invalidated here}}
lambda(); // expected-note {{later used here}}
}
@@ -794,7 +794,7 @@ struct S {
void baz(){
std::vector<std::string> vec = {"42"};
v = vec[0]; // expected-warning {{local variable 'vec' is later invalidated}}
- vec.push_back("1"); // expected-note {{invalidated here}}
+ vec.push_back("1"); // expected-note {{is invalidated here}}
bar(); // expected-note {{later used here}}
v = nullptr;
}
@@ -807,7 +807,7 @@ void function_captured_ref_invalidated() {
std::vector<int> v;
v.push_back(1);
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}}
+ v.push_back(2); // expected-note {{is invalidated here}}
(void)f; // expected-note {{later used here}}
}
@@ -819,7 +819,7 @@ namespace explicit_destructor {
void explicit_destructor_invalidates_pointer() {
std::string s = "42";
const char *p = s.data(); // expected-warning {{local variable 's' is later invalidated}}
- s.~basic_string(); // expected-note {{invalidated here}}
+ s.~basic_string(); // expected-note {{is invalidated here}}
(void)*p; // expected-note {{later used here}}
}
@@ -827,7 +827,7 @@ void pointer_destructor_invalidates_pointer() {
char storage[sizeof(std::string)];
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}}
+ obj->~basic_string(); // expected-note {{is invalidated here}}
(void)*p; // expected-note {{later used here}}
}
@@ -835,7 +835,7 @@ void destroy_at_invalidates_pointer() {
char storage[sizeof(std::string)];
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}}
+ std::destroy_at(obj); // expected-note {{is invalidated here}}
(void)*p; // expected-note {{later used here}}
}
@@ -853,7 +853,7 @@ 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 {{local variable 'arr' is later invalidated}}
- std::destroy_at(&arr_ref); // expected-note {{invalidated here}}
+ std::destroy_at(&arr_ref); // expected-note {{is invalidated here}}
(void)*p; // expected-note {{later used here}}
}
@@ -861,7 +861,7 @@ void reference_destructor_invalidates_pointer() {
std::string s = "42";
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}}
+ std::destroy_at(&ref); // expected-note {{is invalidated here}}
(void)*p; // expected-note {{later used here}}
}
@@ -869,7 +869,7 @@ void destroy_at_ternary_operator(bool flag) {
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}}
+ std::destroy_at(flag ? str1 : str2); // expected-note {{is invalidated here}}
(void)*p; // expected-note {{later used here}}
}
@@ -881,7 +881,7 @@ struct StringOwner {
void member_destructor_invalidates_pointer() {
StringOwner owner = {"42", "43"};
const char *p = owner.s.data(); // expected-warning {{local variable 'owner' is later invalidated}}
- owner.t.~basic_string(); // expected-note {{invalidated here}}
+ owner.t.~basic_string(); // expected-note {{is invalidated here}}
(void)*p; // expected-note {{later used here}}
}
@@ -892,7 +892,7 @@ namespace unique_ptr_invalidation {
void invalid_after_reset() {
std::unique_ptr<int> up(new int);
int *p = up.get(); // expected-warning {{local variable 'up' is later invalidated}}
- up.reset(); // expected-note {{invalidated here}}
+ up.reset(); // expected-note {{is invalidated here}}
(void)*p; // expected-note {{later used here}}
}
@@ -900,14 +900,14 @@ 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 {{local variable 'up' is later invalidated}}
- up = std::move(other); // expected-note {{invalidated here}}
+ up = std::move(other); // expected-note {{is 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 {{local variable 'up' is later invalidated}}
- up = nullptr; // expected-note {{invalidated here}}
+ up = nullptr; // expected-note {{is invalidated here}}
(void)*p; // expected-note {{later used here}}
}
@@ -915,7 +915,7 @@ 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 {{local variable 'up' is later invalidated}}
- up.reset(); // expected-note {{invalidated here}}
+ up.reset(); // expected-note {{is invalidated here}}
(void)*p; // expected-note {{later used here}}
}
diff --git a/clang/test/Sema/LifetimeSafety/safety-c.c b/clang/test/Sema/LifetimeSafety/safety-c.c
index 95c8cf7bb00c7..dace935b26c5b 100644
--- a/clang/test/Sema/LifetimeSafety/safety-c.c
+++ b/clang/test/Sema/LifetimeSafety/safety-c.c
@@ -16,7 +16,7 @@ void simple_case(void) {
{
int i;
p = &i; // expected-warning {{local variable 'i' does not live long enough}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)*p; // expected-note {{later used here}}
}
@@ -25,7 +25,7 @@ void chained_assignment(void) {
{
int i;
p = q = r = &i; // expected-warning {{local variable 'i' does not live long enough}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)*p; // expected-note {{later used here}}
}
@@ -35,7 +35,7 @@ void conditional_branch(int cond) {
if (cond) {
int i;
p = &i; // expected-warning {{local variable 'i' does not live long enough}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)*p; // expected-note {{later used here}}
}
@@ -46,7 +46,7 @@ void loop_with_break(int cond) {
if (cond) {
int i;
p = &i; // expected-warning {{local variable 'i' does not live long enough}}
- break; // expected-note {{destroyed here}}
+ break; // expected-note {{is destroyed here}}
}
}
(void)*p; // expected-note {{later used here}}
@@ -64,7 +64,7 @@ void lifetimebound_call(void) {
int i;
p = identity(&i); // expected-warning {{local variable 'i' does not live long enough}} \
// expected-note {{result of call to 'identity' aliases the storage of local variable 'i'}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)*p; // expected-note {{later used here}}
}
@@ -85,7 +85,7 @@ void struct_address_of_field(void) {
{
struct IntField holder;
p = &holder.field; // expected-warning {{local variable 'holder' does not live long enough}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)*p; // expected-note {{later used here}}
}
@@ -95,7 +95,7 @@ void conditional_operator_lifetimebound(int cond) {
int a, b;
p = identity(cond ? &a // expected-warning {{local variable 'a' does not live long enough}}
: &b); // expected-warning {{local variable 'b' does not live long enough}}
- } // expected-note 2 {{destroyed here}}
+ } // expected-note 2 {{is destroyed here}}
(void)*p; // expected-note 2 {{later used here}}
}
@@ -109,7 +109,7 @@ void union_member(void) {
{
union IntOrPtr u;
p = &u.i; // expected-warning {{local variable 'u' does not live long enough}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)*p; // expected-note {{later used here}}
}
@@ -125,7 +125,7 @@ void anonymous_union_member(void) {
{
struct AnonymousUnion u;
p = &u.i; // expected-warning {{local variable 'u' does not live long enough}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed 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 4d78276fa4f78..3d07000938f9c 100644
--- a/clang/test/Sema/LifetimeSafety/safety.cpp
+++ b/clang/test/Sema/LifetimeSafety/safety.cpp
@@ -55,7 +55,7 @@ void simple_case() {
{
MyObj s;
p = &s; // expected-warning {{local variable 's' does not live long enough}}
- } // expected-note {{'s' is destroyed here at the end of its scope}}
+ } // expected-note {{local variable 's' is destroyed here}}
(void)*p; // expected-note {{later used here}}
}
@@ -64,7 +64,7 @@ void simple_case_gsl() {
{
MyObj s;
v = s; // expected-warning {{local variable 's' does not live long enough}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
v.use(); // expected-note {{later used here}}
}
@@ -93,7 +93,7 @@ void pointer_chain() {
MyObj s;
p = &s; // expected-warning {{does not live long enough}}
q = p; // expected-note {{local variable 'p' aliases the storage of local variable 's'}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)*q; // expected-note {{later used here}}
}
@@ -103,7 +103,7 @@ void propagation_gsl() {
MyObj s;
v1 = s; // expected-warning {{local variable 's' does not live long enough}}
v2 = v1; // expected-note {{local variable 'v1' aliases the storage of local variable 's'}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
v2.use(); // expected-note {{later used here}}
}
@@ -112,7 +112,7 @@ void multiple_uses_one_warning() {
{
MyObj s;
p = &s; // expected-warning {{does not live long enough}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)*p; // expected-note {{later used here}}
// No second warning for the same loan.
p->id = 1;
@@ -127,7 +127,7 @@ void multiple_pointers() {
p = &s; // expected-warning {{does not live long enough}}
q = &s; // expected-warning {{does not live long enough}}
r = &s; // expected-warning {{does not live long enough}}
- } // expected-note 3 {{destroyed here}}
+ } // expected-note 3 {{is destroyed here}}
(void)*p; // expected-note {{later used here}}
(void)*q; // expected-note {{later used here}}
(void)*r; // expected-note {{later used here}}
@@ -139,7 +139,7 @@ void multiple_pointers_chained() {
MyObj s;
MyObj* obj1, *obj2;
p = obj1 = obj2 = &s; // expected-warning {{does not live long enough}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)*p; // expected-note {{later used here}}
}
@@ -158,11 +158,11 @@ void single_pointer_multiple_loans(bool cond) {
if (cond){
MyObj s;
p = &s; // expected-warning {{does not live long enough}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
else {
MyObj t;
p = &t; // expected-warning {{does not live long enough}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)*p; // expected-note 2 {{later used here}}
}
@@ -171,11 +171,11 @@ void single_pointer_multiple_loans_gsl(bool cond) {
if (cond){
MyObj s;
v = s; // expected-warning {{local variable 's' does not live long enough}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
else {
MyObj t;
v = t; // expected-warning {{local variable 't' does not live long enough}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
v.use(); // expected-note 2 {{later used here}}
}
@@ -185,7 +185,7 @@ void if_branch(bool cond) {
if (cond) {
MyObj temp;
p = &temp; // expected-warning {{local variable 'temp' does not live long enough}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)*p; // expected-note {{later used here}}
}
@@ -195,7 +195,7 @@ void if_branch_potential(bool cond) {
if (cond) {
MyObj temp;
p = &temp; // expected-warning {{local variable 'temp' does not live long enough}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
if (!cond)
(void)*p; // expected-note {{later used here}}
else
@@ -208,7 +208,7 @@ void if_branch_gsl(bool cond) {
if (cond) {
MyObj temp;
v = temp; // expected-warning {{local variable 'temp' does not live long enough}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
v.use(); // expected-note {{later used here}}
}
@@ -223,7 +223,7 @@ void potential_together(bool cond) {
p_definite = &s; // expected-warning {{does not live long enough}}
if (cond)
p_maybe = &s; // expected-warning {{does not live long enough}}
- } // expected-note 2 {{destroyed here}}
+ } // expected-note 2 {{is destroyed here}}
(void)*p_definite; // expected-note {{later used here}}
if (!cond)
(void)*p_maybe; // expected-note {{later used here}}
@@ -237,7 +237,7 @@ void overrides_potential(bool cond) {
MyObj s;
q = &s; // expected-warning {{does not live long enough}}
p = q;
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
if (cond) {
// 'q' is conditionally "rescued". 'p' is not.
@@ -256,7 +256,7 @@ void due_to_conditional_killing(bool cond) {
{
MyObj s;
q = &s; // expected-warning {{does not live long enough}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
if (cond) {
// 'q' is conditionally "rescued". 'p' is not.
q = &safe;
@@ -269,7 +269,7 @@ void for_loop_use_after_loop_body(MyObj safe) {
for (int i = 0; i < 1; ++i) {
MyObj s;
p = &s; // expected-warning {{does not live long enough}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)*p; // expected-note {{later used here}}
}
@@ -289,7 +289,7 @@ void for_loop_gsl() {
for (int i = 0; i < 1; ++i) {
MyObj s;
v = s; // expected-warning {{local variable 's' does not live long enough}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
v.use(); // expected-note {{later used here}}
}
@@ -300,7 +300,7 @@ void for_loop_use_before_loop_body(MyObj safe) {
(void)*p; // expected-note {{later used here}}
MyObj s;
p = &s; // expected-warning {{does not live long enough}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)*p;
}
@@ -311,7 +311,7 @@ void loop_with_break(bool cond) {
if (cond) {
MyObj temp;
p = &temp; // expected-warning {{does not live long enough}}
- break; // expected-note {{destroyed here}}
+ break; // expected-note {{is destroyed here}}
}
}
(void)*p; // expected-note {{later used here}}
@@ -324,7 +324,7 @@ void loop_with_break_gsl(bool cond) {
if (cond) {
MyObj temp;
v = temp; // expected-warning {{local variable 'temp' does not live long enough}}
- break; // expected-note {{destroyed here}}
+ break; // expected-note {{is destroyed here}}
}
}
v.use(); // expected-note {{later used here}}
@@ -338,7 +338,7 @@ void multiple_expiry_of_same_loan(bool cond) {
MyObj unsafe;
if (cond) {
p = &unsafe; // expected-warning {{does not live long enough}}
- break; // expected-note {{destroyed here}}
+ break; // expected-note {{is destroyed here}}
}
}
(void)*p; // expected-note {{later used here}}
@@ -349,7 +349,7 @@ void multiple_expiry_of_same_loan(bool cond) {
if (cond) {
p = &unsafe; // expected-warning {{does not live long enough}}
if (cond)
- break; // expected-note {{destroyed here}}
+ break; // expected-note {{is destroyed here}}
}
}
(void)*p; // expected-note {{later used here}}
@@ -359,7 +359,7 @@ void multiple_expiry_of_same_loan(bool cond) {
if (cond) {
MyObj unsafe2;
p = &unsafe2; // expected-warning {{does not live long enough}}
- break; // expected-note {{destroyed here}}
+ break; // expected-note {{is destroyed here}}
}
}
(void)*p; // expected-note {{later used here}}
@@ -370,7 +370,7 @@ void multiple_expiry_of_same_loan(bool cond) {
if (cond)
p = &unsafe; // expected-warning {{does not live long enough}}
if (cond)
- break; // expected-note {{destroyed here}}
+ break; // expected-note {{is destroyed here}}
}
(void)*p; // expected-note {{later used here}}
}
@@ -382,7 +382,7 @@ void switch_potential(int mode) {
case 1: {
MyObj temp;
p = &temp; // expected-warning {{local variable 'temp' does not live long enough}}
- break; // expected-note {{destroyed here}}
+ break; // expected-note {{is destroyed here}}
}
case 2: {
p = &safe; // This path is okay.
@@ -401,17 +401,17 @@ void switch_uaf(int mode) {
case 1: {
MyObj temp1;
p = &temp1; // expected-warning {{does not live long enough}}
- break; // expected-note {{destroyed here}}
+ break; // expected-note {{is destroyed here}}
}
case 2: {
MyObj temp2;
p = &temp2; // expected-warning {{does not live long enough}}
- break; // expected-note {{destroyed here}}
+ break; // expected-note {{is destroyed here}}
}
default: {
MyObj temp2;
p = &temp2; // expected-warning {{does not live long enough}}
- break; // expected-note {{destroyed here}}
+ break; // expected-note {{is destroyed here}}
}
}
(void)*p; // expected-note 3 {{later used here}}
@@ -423,17 +423,17 @@ void switch_gsl(int mode) {
case 1: {
MyObj temp1;
v = temp1; // expected-warning {{local variable 'temp1' does not live long enough}}
- break; // expected-note {{destroyed here}}
+ break; // expected-note {{is destroyed here}}
}
case 2: {
MyObj temp2;
v = temp2; // expected-warning {{local variable 'temp2' does not live long enough}}
- break; // expected-note {{destroyed here}}
+ break; // expected-note {{is destroyed here}}
}
default: {
MyObj temp3;
v = temp3; // expected-warning {{local variable 'temp3' does not live long enough}}
- break; // expected-note {{destroyed here}}
+ break; // expected-note {{is destroyed here}}
}
}
v.use(); // expected-note 3 {{later used here}}
@@ -451,7 +451,7 @@ void loan_from_previous_iteration(MyObj safe, bool condition) {
q = p;
(void)*p;
(void)*q; // expected-note {{later used here}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
}
void trivial_int_uaf() {
@@ -459,7 +459,7 @@ void trivial_int_uaf() {
{
int b = 1;
a = &b; // expected-warning {{local variable 'b' does not live long enough}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)*a; // expected-note {{later used here}}
}
@@ -468,7 +468,7 @@ void trivial_class_uaf() {
{
TriviallyDestructedClass s;
ptr = &s; // expected-warning {{local variable 's' does not live long enough}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)ptr; // expected-note {{later used here}}
}
@@ -660,7 +660,7 @@ void test_view_pointer() {
{
View v;
vp = &v; // expected-warning {{local variable 'v' does not live long enough}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
vp->use(); // expected-note {{later used here}}
}
@@ -669,7 +669,7 @@ void test_view_double_pointer() {
{
View* vp = nullptr;
vpp = &vp; // expected-warning {{local variable 'vp' does not live long enough}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(**vpp).use(); // expected-note {{later used here}}
}
@@ -698,7 +698,7 @@ void test_lifetimebound_multi_level() {
int*** ppp = &pp; // expected-warning {{local variable 'pp' does not live long enough}}
result = return_inner_ptr_addr(ppp); // expected-note {{local variable 'ppp' aliases the storage of local variable 'pp'}} \
// expected-note {{result of call to 'return_inner_ptr_addr' aliases the storage of local variable 'pp'}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)**result; // expected-note {{used here}}
}
@@ -731,7 +731,7 @@ MyObj* uaf_before_uar() {
{
MyObj local_obj;
p = &local_obj; // expected-warning {{local variable 'local_obj' does not live long enough}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
return p; // expected-note {{later used here}}
}
@@ -822,7 +822,7 @@ void lifetimebound_simple_function() {
MyObj obj;
v = Identity(obj); // expected-warning {{local variable 'obj' does not live long enough}} \
// expected-note {{result of call to 'Identity' aliases the storage of local variable 'obj'}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
v.use(); // expected-note {{later used here}}
}
@@ -834,7 +834,7 @@ void lifetimebound_multiple_args_definite() {
// expected-note {{result of call to 'Choose' aliases the storage of local variable 'obj2'}}
obj1, // expected-warning {{local variable 'obj1' does not live long enough}}
obj2); // expected-warning {{local variable 'obj2' does not live long enough}}
- } // expected-note 2 {{destroyed here}}
+ } // expected-note 2 {{is destroyed here}}
v.use(); // expected-note 2 {{later used here}}
}
@@ -848,8 +848,8 @@ void lifetimebound_multiple_args_potential(bool cond) {
v = Choose(true,
obj1, // expected-warning {{local variable 'obj1' does not live long enough}}
obj2); // expected-warning {{local variable 'obj2' does not live long enough}}
- } // expected-note {{destroyed here}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
+ } // expected-note {{is destroyed here}}
v.use(); // expected-note 2 {{later used here}}
}
@@ -861,7 +861,7 @@ void lifetimebound_mixed_args() {
v = SelectFirst(obj1, // expected-warning {{local variable 'obj1' does not live long enough}} \
// expected-note {{result of call to 'SelectFirst' aliases the storage of local variable 'obj1'}}
obj2);
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
v.use(); // expected-note {{later used here}}
}
@@ -877,7 +877,7 @@ void lifetimebound_member_function() {
MyObj obj;
v = obj.getView(); // expected-warning {{local variable 'obj' does not live long enough}} \
// expected-note {{result of call to 'getView' aliases the storage of local variable 'obj'}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
v.use(); // expected-note {{later used here}}
}
@@ -892,7 +892,7 @@ void lifetimebound_conversion_operator() {
{
LifetimeBoundConversionView obj;
v = obj; // expected-warning {{local variable 'obj' does not live long enough}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
v.use(); // expected-note {{later used here}}
}
@@ -902,7 +902,7 @@ void lifetimebound_chained_calls() {
MyObj obj;
v = Identity(Identity(Identity(obj))); // expected-warning {{local variable 'obj' does not live long enough}} \
// expected-note 3 {{result of call to 'Identity' aliases the storage of local variable 'obj'}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
v.use(); // expected-note {{later used here}}
}
@@ -912,7 +912,7 @@ void lifetimebound_with_pointers() {
MyObj obj;
ptr = GetPointer(obj); // expected-warning {{local variable 'obj' does not live long enough}} \
// expected-note {{result of call to 'GetPointer' aliases the storage of local variable 'obj'}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)*ptr; // expected-note {{later used here}}
}
@@ -922,7 +922,7 @@ void chained_assignment_lifetimebound_call() {
MyObj s;
p = Identity(obj = &s); // expected-warning {{does not live long enough}} \
// expected-note {{result of call to 'Identity' aliases the storage of local variable 's'}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)*p; // expected-note {{later used here}}
}
@@ -942,7 +942,7 @@ void lifetimebound_partial_safety(bool cond) {
v = Choose(true,
safe_obj,
temp_obj); // expected-warning {{local variable 'temp_obj' does not live long enough}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
v.use(); // expected-note {{later used here}}
}
@@ -956,7 +956,7 @@ void lifetimebound_return_reference() {
const MyObj& ref = GetObject(temp_v); // expected-note {{local variable 'temp_v' aliases the storage of local variable 'obj'}} \
// expected-note {{result of call to 'GetObject' aliases the storage of local variable 'obj'}}
ptr = &ref;
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)*ptr; // expected-note {{later used here}}
}
@@ -973,7 +973,7 @@ void lifetimebound_ctor() {
{
MyObj obj;
v = obj; // expected-warning {{local variable 'obj' does not live long enough}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)v; // expected-note {{later used here}}
}
@@ -982,7 +982,7 @@ void lifetimebound_ctor_functional_cast() {
{
MyObj obj;
v = LifetimeBoundCtor(obj); // expected-warning {{local variable 'obj' does not live long enough}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)v; // expected-note {{later used here}}
}
@@ -991,7 +991,7 @@ void lifetimebound_ctor_c_style_cast() {
{
MyObj obj;
v = (LifetimeBoundCtor)(obj); // expected-warning {{local variable 'obj' does not live long enough}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)v; // expected-note {{later used here}}
}
@@ -1000,7 +1000,7 @@ void lifetimebound_ctor_static_cast() {
{
MyObj obj;
v = static_cast<LifetimeBoundCtor>(obj); // expected-warning {{local variable 'obj' does not live long enough}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)v; // expected-note {{later used here}}
}
@@ -1010,7 +1010,7 @@ void lifetimebound_make_unique() {
MyObj obj;
ptr = std::make_unique<LifetimeBoundCtor>(obj); // tu-warning {{local variable 'obj' does not live long enough}} \
// tu-note {{result of call to 'make_unique<LifetimeBoundCtor, MyObj &>' aliases the storage of local variable 'obj'}}
- } // tu-note {{destroyed here}}
+ } // tu-note {{is destroyed here}}
(void)ptr; // tu-note {{later used here}}
}
@@ -1026,7 +1026,7 @@ void non_lifetimebound_make_unique() {
void lifetimebound_make_unique_temp() {
std::unique_ptr<LifetimeBoundCtor> ptr = std::make_unique<LifetimeBoundCtor>(MyObj()); // tu-warning {{temporary object does not live long enough}} \
- // tu-note {{destroyed here}} \
+ // tu-note {{is destroyed here}} \
// tu-note {{result of call to 'make_unique<LifetimeBoundCtor, MyObj>' aliases the storage of temporary object}}
(void)ptr; // tu-note {{later used here}}
}
@@ -1066,7 +1066,7 @@ void lifetimebound_make_unique_multi_params() {
MyObj obj_short;
ptr = std::make_unique<MultiLifetimeBoundCtor>(obj_short, obj_long); // tu-warning {{local variable 'obj_short' does not live long enough}} \
// tu-note {{result of call to 'make_unique<MultiLifetimeBoundCtor, MyObj &, MyObj &>' aliases the storage of local variable 'obj_short'}}
- } // tu-note {{destroyed here}}
+ } // tu-note {{is destroyed here}}
(void)ptr; // tu-note {{later used here}}
}
@@ -1077,7 +1077,7 @@ void lifetimebound_make_unique_multi_params2() {
MyObj obj_short;
ptr = std::make_unique<MultiLifetimeBoundCtor>(obj_long, obj_short, 1); // tu-warning {{local variable 'obj_short' does not live long enough}} \
// tu-note {{result of call to 'make_unique<MultiLifetimeBoundCtor, MyObj &, MyObj &, int>' aliases the storage of local variable 'obj_short'}}
- } // tu-note {{destroyed here}}
+ } // tu-note {{is destroyed here}}
(void)ptr; // tu-note {{later used here}}
}
@@ -1098,7 +1098,7 @@ void lifetimebound_make_unique_multi_params3_1() {
MyObj obj_short;
ptr = std::make_unique<MultiLifetimeBoundCtor>(obj_short, obj_long, 1.0); // tu-warning {{local variable 'obj_short' does not live long enough}} \
// tu-note {{result of call to 'make_unique<MultiLifetimeBoundCtor, MyObj &, MyObj &, double>' aliases the storage of local variable 'obj_short'}}
- } // tu-note {{destroyed here}}
+ } // tu-note {{is destroyed here}}
(void)ptr; // tu-note {{later used here}}
}
@@ -1109,7 +1109,7 @@ void lifetimebound_make_unique_multi_params3_2() {
MyObj obj_short;
ptr = std::make_unique<MultiLifetimeBoundCtor>(obj_long, obj_short, 1.0); // tu-warning {{local variable 'obj_short' does not live long enough}} \
// tu-note {{result of call to 'make_unique<MultiLifetimeBoundCtor, MyObj &, MyObj &, double>' aliases the storage of local variable 'obj_short'}}
- } // tu-note {{destroyed here}}
+ } // tu-note {{is destroyed here}}
(void)ptr; // tu-note {{later used here}}
}
@@ -1186,7 +1186,7 @@ void conditional_operator_one_unsafe_branch(bool cond) {
MyObj temp;
p = cond ? &temp // expected-warning {{local variable 'temp' does not live long enough}}
: &safe;
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
// This is not a use-after-free for any value of `cond` but the analysis
// cannot reason this and marks the above as a false positive. This
@@ -1202,7 +1202,7 @@ void conditional_operator_two_unsafe_branches(bool cond) {
MyObj a, b;
p = cond ? &a // expected-warning {{local variable 'a' does not live long enough}}
: &b; // expected-warning {{local variable 'b' does not live long enough}}
- } // expected-note 2 {{destroyed here}}
+ } // expected-note 2 {{is destroyed here}}
(void)*p; // expected-note 2 {{later used here}}
}
@@ -1214,7 +1214,7 @@ void conditional_operator_nested(bool cond) {
: &b // expected-warning {{local variable 'b' does not live long enough}}.
: cond ? &c // expected-warning {{local variable 'c' does not live long enough}}.
: &d; // expected-warning {{local variable 'd' does not live long enough}}.
- } // expected-note 4 {{destroyed here}}
+ } // expected-note 4 {{is destroyed here}}
(void)*p; // expected-note 4 {{later used here}}
}
@@ -1224,7 +1224,7 @@ void conditional_operator_lifetimebound(bool cond) {
MyObj a, b;
p = Identity(cond ? &a // expected-warning {{local variable 'a' does not live long enough}}
: &b); // expected-warning {{local variable 'b' does not live long enough}}
- } // expected-note 2 {{destroyed here}}
+ } // expected-note 2 {{is destroyed here}}
(void)*p; // expected-note 2 {{later used here}}
}
@@ -1234,7 +1234,7 @@ void conditional_operator_lifetimebound_nested(bool cond) {
MyObj a, b;
p = Identity(cond ? Identity(&a) // expected-warning {{local variable 'a' does not live long enough}}
: Identity(&b)); // expected-warning {{local variable 'b' does not live long enough}}
- } // expected-note 2 {{destroyed here}}
+ } // expected-note 2 {{is destroyed here}}
(void)*p; // expected-note 2 {{later used here}}
}
@@ -1246,7 +1246,7 @@ void conditional_operator_lifetimebound_nested_deep(bool cond) {
: &b) // expected-warning {{local variable 'b' does not live long enough}}
: Identity(cond ? &c // expected-warning {{local variable 'c' does not live long enough}}
: &d)); // expected-warning {{local variable 'd' does not live long enough}}
- } // expected-note 4 {{destroyed here}}
+ } // expected-note 4 {{is destroyed here}}
(void)*p; // expected-note 4 {{later used here}}
}
@@ -1257,7 +1257,7 @@ void comma_use_after_scope() {
{
MyObj temp;
p = (side(), &temp); // expected-warning {{local variable 'temp' does not live long enough}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)*p; // expected-note {{later used here}}
}
@@ -1266,7 +1266,7 @@ void comma_nested() {
{
MyObj temp;
p = (side(), (side(), &temp)); // expected-warning {{local variable 'temp' does not live long enough}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)*p; // expected-note {{later used here}}
}
@@ -1277,7 +1277,7 @@ void comma_masked_by_conditional(bool cond) {
{
MyObj temp;
p = cond ? keep : (side(), &temp); // expected-warning {{local variable 'temp' does not live long enough}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)*p; // expected-note {{later used here}}
}
@@ -1293,7 +1293,7 @@ void binary_conditional_false_unsafe(MyObj* in) {
{
MyObj temp;
p = in ?: &temp; // expected-warning {{local variable 'temp' does not live long enough}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)*p; // expected-note {{later used here}}
}
@@ -1303,7 +1303,7 @@ void binary_conditional_common_unsafe(MyObj* fallback) {
MyObj temp;
MyObj* t = &temp; // expected-warning {{local variable 'temp' does not live long enough}}
p = t ?: fallback;
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)*p; // expected-note {{later used here}}
}
@@ -1318,7 +1318,7 @@ void binary_conditional_nested(MyObj* a, MyObj* b) {
{
MyObj temp;
p = a ?: b ?: &temp; // expected-warning {{local variable 'temp' does not live long enough}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)*p; // expected-note {{later used here}}
}
@@ -1329,7 +1329,7 @@ void binary_conditional_masked_by_conditional(bool cond, MyObj* in) {
{
MyObj temp;
p = cond ? keep : (in ?: &temp); // expected-warning {{local variable 'temp' does not live long enough}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)*p; // expected-note {{later used here}}
}
@@ -1377,7 +1377,7 @@ void simpleparen() {
MyObj a;
MyObj* b = &a; // expected-warning {{local variable 'a' does not live long enough}}
p = (((b)));
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)*p; // expected-note {{later used here}}
}
@@ -1386,14 +1386,14 @@ void parentheses(bool cond) {
{
MyObj a;
p = &((((a)))); // expected-warning {{local variable 'a' does not live long enough}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)*p; // expected-note {{later used here}}
{
MyObj a;
p = ((GetPointer((a)))); // expected-warning {{local variable 'a' does not live long enough}} \
// expected-note {{result of call to 'GetPointer' aliases the storage of local variable 'a'}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)*p; // expected-note {{later used here}}
{
@@ -1402,14 +1402,14 @@ void parentheses(bool cond) {
: b) // expected-warning {{local variable 'b' does not live long enough}}.
: (cond ? c // expected-warning {{local variable 'c' does not live long enough}}.
: d)); // expected-warning {{local variable 'd' does not live long enough}}.
- } // expected-note 4 {{destroyed here}}
+ } // expected-note 4 {{is destroyed here}}
(void)*p; // expected-note 4 {{later used here}}
{
MyObj a, b, c, d;
p = ((cond ? (((cond ? &a : &b))) // expected-warning {{local variable 'b' does not live long enough}} expected-warning {{local variable 'a' does not live long enough}}.
: &(((cond ? c : d))))); // expected-warning {{local variable 'd' does not live long enough}} expected-warning {{local variable 'c' does not live long enough}}.
- } // expected-note 4 {{destroyed here}}
+ } // expected-note 4 {{is destroyed here}}
(void)*p; // expected-note 4 {{later used here}}
}
@@ -1417,13 +1417,13 @@ void parentheses(bool cond) {
void use_temporary_after_destruction() {
View a;
a = non_trivially_destructed_temporary(); // expected-warning {{temporary object does not live long enough}} \
- expected-note {{destroyed here}}
+ expected-note {{is destroyed here}}
use(a); // expected-note {{later used here}}
}
void passing_temporary_to_lifetime_bound_function() {
View a = construct_view(non_trivially_destructed_temporary()); // expected-warning {{temporary object does not live long enough}} \
- expected-note {{destroyed here}} \
+ expected-note {{is destroyed here}} \
expected-note {{result of call to 'construct_view' aliases the storage of temporary object}}
use(a); // expected-note {{later used here}}
}
@@ -1431,7 +1431,7 @@ void passing_temporary_to_lifetime_bound_function() {
void use_trivial_temporary_after_destruction() {
View a;
a = trivially_destructed_temporary(); // expected-warning {{temporary object does not live long enough}} \
- expected-note {{destroyed here}}
+ expected-note {{is destroyed here}}
use(a); // expected-note {{later used here}}
}
@@ -1439,7 +1439,7 @@ namespace FullExprCleanupLoc {
void var_initializer() {
View v = non_trivially_destructed_temporary() // expected-warning {{temporary object does not live long enough}} \
// expected-note {{result of call to 'getView' aliases the storage of temporary object}}
- .getView(); // expected-note {{destroyed here}}
+ .getView(); // expected-note {{is destroyed here}}
v.use(); // expected-note {{later used here}}
}
@@ -1447,7 +1447,7 @@ void expr_statement() {
View v;
v = non_trivially_destructed_temporary() // expected-warning {{temporary object does not live long enough}} \
// expected-note {{result of call to 'getView' aliases the storage of temporary object}}
- .getView(); // expected-note {{destroyed here}}
+ .getView(); // expected-note {{is destroyed here}}
v.use(); // expected-note {{later used here}}
}
} // namespace FullExprCleanupLoc
@@ -1492,7 +1492,7 @@ void foobar() {
view = string_or. // expected-warning {{local variable 'string_or' does not live long enough}} \
// expected-note {{result of call to 'value' aliases the storage of local variable 'string_or'}}
value();
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)view; // expected-note {{later used here}}
}
} // namespace GH162834
@@ -1513,7 +1513,7 @@ void range_based_for_use_after_scope() {
for (const MyObj &o : s) { // expected-warning {{local variable 's' does not live long enough}}
v = o;
}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
v.use(); // expected-note {{later used here}}
}
@@ -1530,7 +1530,7 @@ void range_based_for_not_reference() {
View v;
{
MyObjStorage s;
- for (MyObj o : s) { // expected-note {{destroyed here}}
+ for (MyObj o : s) { // expected-note {{is destroyed here}}
v = o; // expected-warning {{local variable 'o' does not live long enough}}
}
}
@@ -1566,7 +1566,7 @@ void test_user_defined_deref_uaf() {
SmartPtr<MyObj> smart_ptr(&obj);
p = &(*smart_ptr); // expected-warning {{local variable 'smart_ptr' does not live long enough}} \
// expected-note {{expression aliases the storage of local variable 'smart_ptr'}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)*p; // expected-note {{later used here}}
}
@@ -1584,7 +1584,7 @@ void test_user_defined_deref_with_view() {
SmartPtr<MyObj> smart_ptr(&obj);
v = *smart_ptr; // expected-warning {{local variable 'smart_ptr' does not live long enough}} \
// expected-note {{expression aliases the storage of local variable 'smart_ptr'}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
v.use(); // expected-note {{later used here}}
}
@@ -1595,7 +1595,7 @@ void test_user_defined_deref_arrow() {
SmartPtr<MyObj> smart_ptr(&obj);
p = smart_ptr.operator->(); // expected-warning {{local variable 'smart_ptr' does not live long enough}} \
// expected-note {{expression aliases the storage of local variable 'smart_ptr'}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)*p; // expected-note {{later used here}}
}
@@ -1606,7 +1606,7 @@ void test_user_defined_deref_chained() {
SmartPtr<SmartPtr<MyObj>> double_ptr;
p = &(**double_ptr); // expected-warning {{local variable 'double_ptr' does not live long enough}} \
// expected-note 2 {{expression aliases the storage of local variable 'double_ptr'}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)*p; // expected-note {{later used here}}
}
@@ -1758,7 +1758,7 @@ void strict_warn_on_move() {
MyObj a;
v = a; // expected-warning {{local variable 'a' may not live long enough. This could be a false positive as the storage may have been moved later}}
b = std::move(a); // expected-note {{potentially moved here}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)v; // expected-note {{later used here}}
}
@@ -1771,7 +1771,7 @@ void flow_sensitive(bool c) {
return;
}
v = a; // expected-warning {{local variable 'a' does not live long enough}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)v; // expected-note {{later used here}}
}
@@ -1783,7 +1783,7 @@ void detect_conditional(bool cond) {
v = cond ? a : b; // expected-warning {{local variable 'a' may not live long enough. This could be a false positive as the storage may have been moved later}} \
// expected-warning {{local variable 'b' may not live long enough. This could be a false positive as the storage may have been moved later}}
take(std::move(cond ? a : b)); // expected-note 2 {{potentially moved here}}
- } // expected-note 2 {{destroyed here}}
+ } // expected-note 2 {{is destroyed here}}
(void)v; // expected-note 2 {{later used here}}
}
@@ -1793,7 +1793,7 @@ void wrong_use_of_move_is_permissive() {
MyObj a;
v = std::move(a); // expected-warning {{local variable 'a' does not live long enough}} \
// expected-note {{result of call to 'move<MyObj &>' aliases the storage of local variable 'a'}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)v; // expected-note {{later used here}}
const int* p;
{
@@ -1801,7 +1801,7 @@ void wrong_use_of_move_is_permissive() {
p = std::move(a).getData(); // expected-warning {{local variable 'a' does not live long enough}} \
// expected-note {{result of call to 'move<MyObj &>' aliases the storage of local variable 'a'}} \
// expected-note {{result of call to 'getData' aliases the storage of local variable 'a'}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)p; // expected-note {{later used here}}
}
@@ -1814,7 +1814,7 @@ void test_release_no_uaf() {
r = p.get(); // expected-warning {{local variable 'p' may not live long enough. This could be a false positive as the storage may have been moved later}} \
// expected-note {{result of call to 'get' aliases the storage of local variable 'p'}}
take(p.release()); // expected-note {{potentially moved here}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)*r; // expected-note {{later used here}}
}
} // namespace strict_warn_on_move
@@ -1837,10 +1837,10 @@ void bar() {
x = s.x(); // expected-warning {{local variable 's' does not live long enough}} \
// expected-note {{result of call to 'x' aliases the storage of local variable 's'}}
View y = S().x(); // expected-warning {{temporary object does not live long enough}} \
- expected-note {{destroyed here}} \
+ expected-note {{is destroyed here}} \
expected-note {{result of call to 'x' aliases the storage of temporary object}}
(void)y; // expected-note {{used here}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)x; // expected-note {{used here}}
}
}
@@ -1926,11 +1926,11 @@ const std::string& identity(const std::string& in [[clang::lifetimebound]]);
const S& identity(const S& in [[clang::lifetimebound]]);
void test_temporary() {
- const std::string& x = S().x(); // expected-warning {{temporary object does not live long enough}} expected-note {{temporary object is destroyed here at the end of the full-expression}} \
+ const std::string& x = S().x(); // expected-warning {{temporary object does not live long enough}} expected-note {{temporary object is destroyed here}} \
// expected-note {{result of call to 'x' aliases the storage of temporary object}}
(void)x; // expected-note {{later used here}}
- const std::string& y = identity(S().x()); // expected-warning {{temporary object does not live long enough}} expected-note {{destroyed here}} \
+ const std::string& y = identity(S().x()); // expected-warning {{temporary object does not live long enough}} expected-note {{is destroyed here}} \
// expected-note {{result of call to 'x' aliases the storage of temporary object}} \
// expected-note {{result of call to 'identity' aliases the storage of temporary object}}
(void)y; // expected-note {{later used here}}
@@ -1941,20 +1941,20 @@ void test_temporary() {
const std::string& zz = s.x(); // expected-warning {{local variable 's' does not live long enough}} \
// expected-note {{result of call to 'x' aliases the storage of local variable 's'}}
z = zz; // expected-note {{expression aliases the storage of local variable 's'}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)z; // expected-note {{later used here}}
}
void test_lifetime_extension_ok() {
const S& x = S();
(void)x;
- const S& y = identity(S()); // expected-warning {{temporary object does not live long enough}} expected-note {{destroyed here}} \
+ const S& y = identity(S()); // expected-warning {{temporary object does not live long enough}} expected-note {{is destroyed here}} \
// expected-note {{result of call to 'identity' aliases the storage of temporary object}}
(void)y; // expected-note {{later used here}}
}
const std::string& test_return() {
- const std::string& x = S().x(); // expected-warning {{temporary object does not live long enough}} expected-note {{destroyed here}} \
+ const std::string& x = S().x(); // expected-warning {{temporary object does not live long enough}} expected-note {{is destroyed here}} \
// expected-note {{result of call to 'x' aliases the storage of temporary object}}
return x; // expected-note {{later used here}}
}
@@ -1974,7 +1974,7 @@ void uaf() {
S* p = &str; // expected-warning {{local variable 'str' does not live long enough}}
view = p->s; // expected-note {{local variable 'p' aliases the storage of local variable 'str'}} \
// expected-note {{expression aliases the storage of local variable 'str'}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)view; // expected-note {{later used here}}
}
@@ -2001,7 +2001,7 @@ void uaf_union() {
U* up = &u; // expected-warning {{local variable 'u' does not live long enough}}
view = up->s; // expected-note {{local variable 'up' aliases the storage of local variable 'u'}} \
// expected-note {{expression aliases the storage of local variable 'u'}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)view; // expected-note {{later used here}}
}
@@ -2018,7 +2018,7 @@ void uaf_anonymous_union() {
AnonymousUnion au;
AnonymousUnion* up = &au; // expected-warning {{local variable 'au' does not live long enough}}
ip = &up->x; // expected-note {{local variable 'up' aliases the storage of local variable 'au'}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)ip; // expected-note {{later used here}}
}
@@ -2075,11 +2075,11 @@ const T* MemberFuncsTpl<T>::memberC(const T& x [[clang::lifetimebound]]) {
void test() {
MemberFuncsTpl<MyObj> mtf;
- const MyObj* pTMA = mtf.memberA(MyObj()); // expected-warning {{temporary object does not live long enough}} // expected-note {{destroyed here}} \
+ const MyObj* pTMA = mtf.memberA(MyObj()); // expected-warning {{temporary object does not live long enough}} // expected-note {{is destroyed here}} \
// expected-note {{result of call to 'memberA' aliases the storage of temporary object}}
- const MyObj* pTMB = mtf.memberB(MyObj()); // tu-warning {{temporary object does not live long enough}} // tu-note {{destroyed here}} \
+ const MyObj* pTMB = mtf.memberB(MyObj()); // tu-warning {{temporary object does not live long enough}} // tu-note {{is destroyed here}} \
// tu-note {{result of call to 'memberB' aliases the storage of temporary object}}
- const MyObj* pTMC = mtf.memberC(MyObj()); // expected-warning {{temporary object does not live long enough}} // expected-note {{destroyed here}} \
+ const MyObj* pTMC = mtf.memberC(MyObj()); // expected-warning {{temporary object does not live long enough}} // expected-note {{is destroyed here}} \
// expected-note {{result of call to 'memberC' aliases the storage of temporary object}}
(void)pTMA; // expected-note {{later used here}}
(void)pTMB; // tu-note {{later used here}}
@@ -2118,7 +2118,7 @@ void test_optional_arrow() {
p = opt->data(); // expected-warning {{local variable 'opt' does not live long enough}} \
// expected-note {{expression aliases the storage of local variable 'opt'}} \
// expected-note {{result of call to 'data' aliases the storage of local variable 'opt'}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)*p; // expected-note {{later used here}}
}
@@ -2129,7 +2129,7 @@ void test_optional_arrow_lifetimebound() {
v = opt->getView(); // expected-warning {{local variable 'opt' does not live long enough}} \
// expected-note {{expression aliases the storage of local variable 'opt'}} \
// expected-note {{result of call to 'getView' aliases the storage of local variable 'opt'}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
v.use(); // expected-note {{later used here}}
}
@@ -2140,7 +2140,7 @@ void test_unique_ptr_arrow() {
p = up->data(); // expected-warning {{local variable 'up' does not live long enough}} \
// expected-note {{expression aliases the storage of local variable 'up'}} \
// expected-note {{result of call to 'data' aliases the storage of local variable 'up'}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)*p; // expected-note {{later used here}}
}
@@ -2334,7 +2334,7 @@ void multi_level_pointer_in_loop() {
pp = &p;
}
(void)**pp; // expected-note {{later used here}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
}
void outer_pointer_outlives_inner_pointee() {
@@ -2343,7 +2343,7 @@ void outer_pointer_outlives_inner_pointee() {
for (int i = 0; i < 10; ++i) {
MyObj obj;
view = &obj; // expected-warning {{local variable 'obj' does not live long enough}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)*view; // expected-note {{later used here}}
}
@@ -2356,7 +2356,7 @@ void element_use_after_scope() {
{
int a[10]{};
p = &a[2]; // expected-warning {{local variable 'a' does not live long enough}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)*p; // expected-note {{later used here}}
}
@@ -2388,7 +2388,7 @@ void multidimensional_use_after_scope() {
{
int a[3][4]{};
p = &a[1][2]; // expected-warning {{local variable 'a' does not live long enough}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)*p; // expected-note {{later used here}}
}
@@ -2401,7 +2401,7 @@ void member_array_element_use_after_scope() {
{
S s;
p = &s.arr[0]; // expected-warning {{local variable 's' does not live long enough}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)*p; // expected-note {{later used here}}
}
@@ -2410,7 +2410,7 @@ void array_of_pointers_use_after_scope() {
{
int* a[10]{};
p = a; // expected-warning {{local variable 'a' does not live long enough}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)*p; // expected-note {{later used here}}
}
@@ -2419,7 +2419,7 @@ void reversed_subscript_use_after_scope() {
{
int a[10]{};
p = &(0[a]); // expected-warning {{local variable 'a' does not live long enough}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)*p; // expected-note {{later used here}}
}
@@ -2447,7 +2447,7 @@ void pointer_arithmetic_use_after_scope() {
p = a + 5; // expected-warning {{local variable 'a' does not live long enough}}
p2 = a - 5; // expected-warning {{local variable 'a' does not live long enough}}
p3 = 5 + a; // expected-warning {{local variable 'a' does not live long enough}}
- } // expected-note 3 {{destroyed here}}
+ } // expected-note 3 {{is destroyed here}}
(void)*p; // expected-note {{later used here}}
(void)*p2; // expected-note {{later used here}}
(void)*p3; // expected-note {{later used here}}
@@ -2493,7 +2493,7 @@ void indexing_with_static_operator() {
S()(1, 2);
S& x = S()("1", // expected-note 2 {{expression aliases the storage of temporary object}}
2, // expected-warning {{temporary object does not live long enough}}
- 3); // expected-warning {{temporary object does not live long enough}} expected-note 2 {{destroyed here}}
+ 3); // expected-warning {{temporary object does not live long enough}} expected-note 2 {{is destroyed here}}
(void)x; // expected-note 2 {{later used here}}
@@ -2516,14 +2516,14 @@ S getS(const std::string &s [[clang::lifetimebound]]);
void from_free_function() {
S s = getS(std::string("temp")); // expected-warning {{temporary object does not live long enough}} \
- // expected-note {{destroyed here}} \
+ // expected-note {{is destroyed here}} \
// expected-note {{result of call to 'getS' aliases the storage of temporary object}}
use(s); // expected-note {{later used here}}
}
void from_constructor() {
S s(std::string("temp")); // expected-warning {{temporary object does not live long enough}} \
- // expected-note {{destroyed here}}
+ // expected-note {{is destroyed here}}
use(s); // expected-note {{later used here}}
}
@@ -2536,14 +2536,14 @@ struct Factory {
void from_method() {
Factory f;
S s = f.make(std::string("temp")); // expected-warning {{temporary object does not live long enough}} \
- // expected-note {{destroyed here}} \
+ // expected-note {{is destroyed here}} \
// expected-note {{result of call to 'make' aliases the storage of temporary object}}
use(s); // expected-note {{later used here}}
}
void from_static_method() {
S s = Factory::create(std::string("temp")); // expected-warning {{temporary object does not live long enough}} \
- // expected-note {{destroyed here}} \
+ // expected-note {{is destroyed here}} \
// expected-note {{result of call to 'create' aliases the storage of temporary object}}
use(s); // expected-note {{later used here}}
}
@@ -2554,7 +2554,7 @@ void from_lifetimebound_this_method() {
Factory f;
value = f.makeThis(); // expected-warning {{local variable 'f' does not live long enough}} \
// expected-note {{result of call to 'makeThis' aliases the storage of local variable 'f'}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
use(value); // expected-note {{later used here}}
}
@@ -2564,7 +2564,7 @@ void across_scope() {
std::string str{"abc"};
s = getS(str); // expected-warning {{local variable 'str' does not live long enough}} \
// expected-note {{result of call to 'getS' aliases the storage of local variable 'str'}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
use(s); // expected-note {{later used here}}
}
@@ -2588,7 +2588,7 @@ void assignment_propagation() {
a = getS(str); // expected-warning {{local variable 'str' does not live long enough}} \
// expected-note {{result of call to 'getS' aliases the storage of local variable 'str'}}
b = a; // expected-note {{local variable 'a' aliases the storage of local variable 'str'}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
use(b); // expected-note {{later used here}}
}
@@ -2600,7 +2600,7 @@ void chained_defaulted_assignment_propagation() {
// expected-note {{result of call to 'getS' aliases the storage of local variable 'str'}}
c = b = a; // expected-note {{local variable 'a' aliases the storage of local variable 'str'}}\
// expected-note {{expression aliases the storage of local variable 'str'}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
use(c); // expected-note {{later used here}}
}
@@ -2613,7 +2613,7 @@ void no_annotation() {
void mix_annotated_and_not() {
S s1 = getS(std::string("temp")); // expected-warning {{temporary object does not live long enough}} \
- // expected-note {{destroyed here}} \
+ // expected-note {{is destroyed here}} \
// expected-note {{result of call to 'getS' aliases the storage of temporary object}}
S s2 = getSNoAnnotation(std::string("temp"));
use(s1); // expected-note {{later used here}}
@@ -2627,7 +2627,7 @@ S multiple_lifetimebound_params() {
S s = getS2(str, std::string("temp")); // expected-warning {{stack memory associated with local variable 'str' is returned}} \
// expected-warning {{temporary object does not live long enough}} \
// expected-note {{result of call to 'getS2' aliases the storage of temporary object}} \
- // expected-note {{destroyed here}}
+ // expected-note {{is destroyed here}}
return s; // expected-note {{returned here}} \
// expected-note {{later used here}}
}
@@ -2646,7 +2646,7 @@ T make(const std::string &s [[clang::lifetimebound]]);
void from_template_instantiation() {
S s = make<S>(std::string("temp")); // expected-warning {{temporary object does not live long enough}} \
- // expected-note {{destroyed here}} \
+ // expected-note {{is destroyed here}} \
// expected-note {{result of call to 'make<track_origins_for_lifetimebound_record_type::S>' aliases the storage of temporary object}}
use(s); // expected-note {{later used here}}
}
@@ -2710,7 +2710,7 @@ SAlias getSAlias(const std::string &s [[clang::lifetimebound]]);
void from_typedef_return() {
SAlias s = getSAlias(std::string("temp")); // expected-warning {{temporary object does not live long enough}} \
- // expected-note {{destroyed here}} \
+ // expected-note {{is destroyed here}} \
// expected-note {{result of call to 'getSAlias' aliases the storage of temporary object}}
use(s); // expected-note {{later used here}}
}
@@ -2785,7 +2785,7 @@ std::unique_ptr<S> getUniqueS(const std::string &s [[clang::lifetimebound]]);
void owner_return_unique_ptr_s() {
auto ptr = getUniqueS(std::string("temp")); // expected-warning {{temporary object does not live long enough}} \
- // expected-note {{destroyed here}} \
+ // expected-note {{is destroyed here}} \
// expected-note {{result of call to 'getUniqueS' aliases the storage of temporary object}}
(void)ptr; // expected-note {{later used here}}
}
@@ -2804,7 +2804,7 @@ void owner_outlives_lifetimebound_source() {
std::string local;
ups = getUniqueS(local); // expected-warning {{local variable 'local' does not live long enough}} \
// expected-note {{result of call to 'getUniqueS' aliases the storage of local variable 'local'}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)ups; // expected-note {{later used here}}
}
@@ -2827,7 +2827,7 @@ void local_pointer() {
{
int v;
p = Pointer(v); // expected-warning {{local variable 'v' does not live long enough}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
use(*p); // expected-note {{later used here}}
}
@@ -2840,7 +2840,7 @@ void nested_local_pointer() {
p = Pointer(v); // expected-warning {{local variable 'v' does not live long enough}}
pp = Pointer(p); // expected-note {{local variable 'p' aliases the storage of local variable 'v'}}
ppp = Pointer(pp); // expected-note {{local variable 'pp' aliases the storage of local variable 'v'}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
use(***ppp); // expected-note {{later used here}}
}
@@ -2937,7 +2937,7 @@ void new_view_from_dead_scope() {
{
MyObj obj;
p = new View(obj); // expected-warning {{local variable 'obj' does not live long enough}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
p->use(); // expected-note {{later used here}}
}
@@ -3001,7 +3001,7 @@ void new_pointer_from_pointer() {
MyObj obj;
MyObj *q = &obj; // expected-warning {{local variable 'obj' does not live long enough}}
p = new MyObj *(q); // expected-note {{local variable 'q' aliases the storage of local variable 'obj'}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)**p; // expected-note {{later used here}}
}
@@ -3010,7 +3010,7 @@ void new_pointer_from_dead_object() {
{
MyObj obj;
p = new MyObj *(&obj); // expected-warning {{local variable 'obj' does not live long enough}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)**p; // expected-note {{later used here}}
}
@@ -3024,7 +3024,7 @@ void new_multiview_from_mixed_scope() {
{
MyObj obj2;
p = new MultiView(obj1, obj2); // expected-warning {{local variable 'obj2' does not live long enough}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)p; // expected-note {{later used here}}
}
@@ -3187,7 +3187,7 @@ void placement_new_int_basic() {
{
int storage;
p = new (&storage) int; // expected-warning {{local variable 'storage' does not live long enough}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)*p; // expected-note {{later used here}}
}
@@ -3197,7 +3197,7 @@ void placement_new_view_from_dead_scope() {
{
MyObj obj;
p = new (&storage) View(obj); // expected-warning {{local variable 'obj' does not live long enough}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
p->use(); // expected-note {{later used here}}
}
@@ -3207,7 +3207,7 @@ void placement_new_pointer_from_dead_object() {
{
MyObj obj;
p = new (&slot) MyObj *(&obj); // expected-warning {{local variable 'obj' does not live long enough}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)**p; // expected-note {{later used here}}
}
@@ -3216,7 +3216,7 @@ void placement_new_array_basic() {
{
int storage[2];
p = new (&storage) int[2]; // expected-warning {{local variable 'storage' does not live long enough}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)p[0]; // expected-note {{later used here}}
}
@@ -3225,7 +3225,7 @@ void placement_new_array_braces() {
{
int storage[2];
p = new (&storage) int[2]{}; // expected-warning {{local variable 'storage' does not live long enough}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)p[0]; // expected-note {{later used here}}
}
@@ -3431,7 +3431,7 @@ struct S {
{
int num;
this->p_ = # // expected-warning {{local variable 'num' does not live long enough}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
bar(); // expected-note {{later used here}}
this->p_ = &GLOBAL_INT;
}
@@ -3449,7 +3449,7 @@ struct T {
std::string_view v;
void bar();
void foo() {
- v = std::string("tmp"); // expected-warning {{temporary object does not live long enough}} expected-note {{destroyed here}}
+ v = std::string("tmp"); // expected-warning {{temporary object does not live long enough}} expected-note {{is destroyed here}}
bar(); // expected-note {{later used here}}
}
};
@@ -3471,7 +3471,7 @@ struct S2 : S {
{
int num;
this->p_ = # // expected-warning {{local variable 'num' does not live long enough}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
bar(); // expected-note {{later used here}}
this->p_ = &GLOBAL_INT;
}
@@ -3479,7 +3479,7 @@ struct S2 : S {
{
int num;
this->p_ = # // expected-warning {{local variable 'num' does not live long enough}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
bar2(); // expected-note {{later used here}}
this->p_ = nullptr;
}
@@ -3597,7 +3597,7 @@ void uaf_via_lifetimebound() {
int local;
f = capture_lifetimebound_param(local); // expected-warning {{local variable 'local' does not live long enough}} \
// expected-note {{result of call to 'capture_lifetimebound_param' aliases the storage of local variable 'local'}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)f; // expected-note {{later used here}}
}
@@ -3616,7 +3616,7 @@ struct [[gsl::Pointer]] function_ref {
// avoid this warning for non-capturing lambdas.
void assign_non_capturing_to_function_ref(function_ref &r) {
r = []() {}; // expected-warning {{temporary object does not live long enough}} \
- // expected-note {{destroyed here}}
+ // expected-note {{is destroyed here}}
(void)r; // expected-note {{later used here}}
}
@@ -3661,7 +3661,7 @@ void deref_use_after_scope() {
optional<MyObj> opt;
p = &*opt; // expected-warning {{local variable 'opt' does not live long enough}} \
// expected-note {{expression aliases the storage of local variable 'opt'}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)p->id; // expected-note {{later used here}}
}
@@ -3713,7 +3713,7 @@ void use_after_free_capture_by() {
{
MyObj a;
setCaptureBy(res, a); // expected-warning {{local variable 'a' does not live long enough}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)res; // expected-note {{later used here}}
}
@@ -3731,7 +3731,7 @@ void transitive_capture() {
MyObj local;
setCaptureBy(v1, local); // expected-warning {{local variable 'local' does not live long enough}}
setCaptureBy(v2, v1); // expected-note {{local variable 'v1' aliases the storage of local variable 'local'}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)v2; // expected-note {{later used here}}
}
@@ -3742,7 +3742,7 @@ void test_reference_to_view() {
{
MyObj local;
set1(v, local); // expected-warning {{local variable 'local' does not live long enough}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)v; // expected-note {{later used here}}
}
@@ -3773,7 +3773,7 @@ void test_reference_to_pointer() {
{
MyObj local;
set3(ptr, local); // expected-warning {{local variable 'local' does not live long enough}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)ptr; // expected-note {{later used here}}
}
@@ -3787,7 +3787,7 @@ void member_capture() {
{
MyObj local;
c.set(local); // expected-warning {{local variable 'local' does not live long enough}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)c.stored; // expected-note {{later used here}}
}
@@ -3816,7 +3816,7 @@ void multiple_captures() {
{
MyObj val2;
captureTwo(res, val1, val2); // expected-warning {{local variable 'val2' does not live long enough}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)res; // expected-note {{later used here}}
}
@@ -3826,7 +3826,7 @@ void multiple_local_captures() {
MyObj val1;
MyObj val2;
captureTwo(res, val1, val2); // expected-warning {{local variable 'val1' does not live long enough}} // expected-warning {{local variable 'val2' does not live long enough}}
- } // expected-note 2 {{destroyed here}}
+ } // expected-note 2 {{is destroyed here}}
(void)res; // expected-note 2 {{later used here}}
}
@@ -3838,7 +3838,7 @@ void captured_by_multiple_params() {
{
MyObj local;
captureIntoTwo(v1, v2, local); // expected-warning {{local variable 'local' does not live long enough}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)v1; // expected-note {{later used here}}
}
@@ -3847,7 +3847,7 @@ void captured_by_multiple_params_2() {
{
MyObj local;
captureIntoTwo(v1, v2, local); // expected-warning {{local variable 'local' does not live long enough}}
- } // expected-note {{destroyed here}}
+ } // expected-note {{is destroyed here}}
(void)v2; // expected-note {{later used here}}
}
@@ -3858,7 +3858,7 @@ void capturing_multiple_locals() {
setCaptureBy(v, local1); // expected-warning{{local variable 'local1' does not live long enough}}
MyObj local2;
setCaptureBy(v, local2); // expected-warning{{local variable 'local2' does not live long enough}}
- } // expected-note 2 {{destroyed here}}
+ } // expected-note 2 {{is destroyed here}}
(void)v; // expected-note 2 {{later used here}}
}
>From 388acfdae810b5a27a2fade6cb16323e6f3d2fad Mon Sep 17 00:00:00 2001
From: iitianpushkar <pushkarsingh0587 at gmail.com>
Date: Sat, 20 Jun 2026 16:42:19 +0530
Subject: [PATCH 08/14] renamed diagSubject and resolved whitespace change in
checker
---
clang/lib/Analysis/LifetimeSafety/Checker.cpp | 1 +
clang/lib/Sema/SemaLifetimeSafety.h | 47 ++++++++++---------
2 files changed, 25 insertions(+), 23 deletions(-)
diff --git a/clang/lib/Analysis/LifetimeSafety/Checker.cpp b/clang/lib/Analysis/LifetimeSafety/Checker.cpp
index 323902da666bb..d41d6f43f837b 100644
--- a/clang/lib/Analysis/LifetimeSafety/Checker.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/Checker.cpp
@@ -263,6 +263,7 @@ class LifetimeChecker {
// Use-after-invalidation of a parameter.
SemaHelper->reportUseAfterInvalidation(
InvalidatedPVD, UF->getUseExpr(), Warning.InvalidatedByExpr);
+
} else
// Scope-based expiry (use-after-scope).
SemaHelper->reportUseAfterScope(
diff --git a/clang/lib/Sema/SemaLifetimeSafety.h b/clang/lib/Sema/SemaLifetimeSafety.h
index cf3138612cda6..f3680372b3e57 100644
--- a/clang/lib/Sema/SemaLifetimeSafety.h
+++ b/clang/lib/Sema/SemaLifetimeSafety.h
@@ -86,14 +86,15 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper {
unsigned DiagID = MovedExpr
? diag::warn_lifetime_safety_use_after_scope_moved
: diag::warn_lifetime_safety_use_after_scope;
- std::string DiagSubject = getDiagSubjectDescription(IssueExpr);
+ std::string DestroyedSubject = getDiagSubjectDescription(IssueExpr);
S.Diag(IssueExpr->getExprLoc(), DiagID)
- << DiagSubject << IssueExpr->getSourceRange();
+ << DestroyedSubject << IssueExpr->getSourceRange();
if (MovedExpr)
S.Diag(MovedExpr->getExprLoc(), diag::note_lifetime_safety_moved_here)
<< MovedExpr->getSourceRange();
- S.Diag(FreeLoc, diag::note_lifetime_safety_destroyed_here) << DiagSubject;
+ S.Diag(FreeLoc, diag::note_lifetime_safety_destroyed_here)
+ << DestroyedSubject;
reportAliasingChain(ExprChain);
@@ -167,10 +168,10 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper {
auto WarnDiag = isa<CXXDeleteExpr>(InvalidationExpr)
? diag::warn_lifetime_safety_use_after_free
: diag::warn_lifetime_safety_invalidation;
- std::string DiagSubject = getDiagSubjectDescription(IssueExpr);
+ std::string InvalidatedSubject = getDiagSubjectDescription(IssueExpr);
S.Diag(IssueExpr->getExprLoc(), WarnDiag)
- << DiagSubject << IssueExpr->getSourceRange();
- reportInvalidationNote(InvalidationExpr, DiagSubject);
+ << InvalidatedSubject << IssueExpr->getSourceRange();
+ reportInvalidationNote(InvalidationExpr, InvalidatedSubject);
S.Diag(UseExpr->getExprLoc(), diag::note_lifetime_safety_used_here)
<< UseExpr->getSourceRange();
}
@@ -180,11 +181,11 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper {
auto WarnDiag = isa<CXXDeleteExpr>(InvalidationExpr)
? diag::warn_lifetime_safety_use_after_free
: diag::warn_lifetime_safety_invalidation;
- std::string DiagSubject = getDiagSubjectDescription(PVD);
+ std::string InvalidatedSubject = getDiagSubjectDescription(PVD);
S.Diag(PVD->getSourceRange().getBegin(), WarnDiag)
- << DiagSubject << PVD->getSourceRange();
- reportInvalidationNote(InvalidationExpr, DiagSubject);
+ << InvalidatedSubject << PVD->getSourceRange();
+ reportInvalidationNote(InvalidationExpr, InvalidatedSubject);
S.Diag(UseExpr->getExprLoc(), diag::note_lifetime_safety_used_here)
<< UseExpr->getSourceRange();
}
@@ -192,12 +193,12 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper {
void reportInvalidatedField(const Expr *IssueExpr,
const FieldDecl *DanglingField,
const Expr *InvalidationExpr) override {
- std::string DiagSubject = getDiagSubjectDescription(IssueExpr);
+ std::string InvalidatedSubject = getDiagSubjectDescription(IssueExpr);
S.Diag(IssueExpr->getExprLoc(),
diag::warn_lifetime_safety_invalidated_field)
- << DiagSubject << getDiagSubjectDescription(DanglingField)
+ << InvalidatedSubject << getDiagSubjectDescription(DanglingField)
<< IssueExpr->getSourceRange();
- reportInvalidationNote(InvalidationExpr, DiagSubject);
+ reportInvalidationNote(InvalidationExpr, InvalidatedSubject);
S.Diag(DanglingField->getLocation(),
diag::note_lifetime_safety_dangling_field_here)
<< DanglingField->getEndLoc();
@@ -206,12 +207,12 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper {
void reportInvalidatedField(const ParmVarDecl *PVD,
const FieldDecl *DanglingField,
const Expr *InvalidationExpr) override {
- std::string DiagSubject = getDiagSubjectDescription(PVD);
+ std::string InvalidatedSubject = getDiagSubjectDescription(PVD);
S.Diag(PVD->getSourceRange().getBegin(),
diag::warn_lifetime_safety_invalidated_field)
- << DiagSubject << getDiagSubjectDescription(DanglingField)
+ << InvalidatedSubject << getDiagSubjectDescription(DanglingField)
<< PVD->getSourceRange();
- reportInvalidationNote(InvalidationExpr, DiagSubject);
+ reportInvalidationNote(InvalidationExpr, InvalidatedSubject);
S.Diag(DanglingField->getLocation(),
diag::note_lifetime_safety_dangling_field_here)
<< DanglingField->getEndLoc();
@@ -220,12 +221,12 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper {
void reportInvalidatedGlobal(const Expr *IssueExpr,
const VarDecl *DanglingGlobal,
const Expr *InvalidationExpr) override {
- std::string DiagSubject = getDiagSubjectDescription(IssueExpr);
+ std::string InvalidatedSubject = getDiagSubjectDescription(IssueExpr);
S.Diag(IssueExpr->getExprLoc(),
diag::warn_lifetime_safety_invalidated_global)
- << DiagSubject << getDiagSubjectDescription(DanglingGlobal)
+ << InvalidatedSubject << getDiagSubjectDescription(DanglingGlobal)
<< IssueExpr->getSourceRange();
- reportInvalidationNote(InvalidationExpr, DiagSubject);
+ reportInvalidationNote(InvalidationExpr, InvalidatedSubject);
if (DanglingGlobal->isStaticLocal() || DanglingGlobal->isStaticDataMember())
S.Diag(DanglingGlobal->getLocation(),
diag::note_lifetime_safety_dangling_static_here)
@@ -239,12 +240,12 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper {
void reportInvalidatedGlobal(const ParmVarDecl *PVD,
const VarDecl *DanglingGlobal,
const Expr *InvalidationExpr) override {
- std::string DiagSubject = getDiagSubjectDescription(PVD);
+ std::string InvalidatedSubject = getDiagSubjectDescription(PVD);
S.Diag(PVD->getSourceRange().getBegin(),
diag::warn_lifetime_safety_invalidated_global)
- << DiagSubject << getDiagSubjectDescription(DanglingGlobal)
+ << InvalidatedSubject << getDiagSubjectDescription(DanglingGlobal)
<< PVD->getSourceRange();
- reportInvalidationNote(InvalidationExpr, DiagSubject);
+ reportInvalidationNote(InvalidationExpr, InvalidatedSubject);
if (DanglingGlobal->isStaticLocal() || DanglingGlobal->isStaticDataMember())
S.Diag(DanglingGlobal->getLocation(),
diag::note_lifetime_safety_dangling_static_here)
@@ -423,7 +424,7 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper {
private:
void reportInvalidationNote(const Expr *InvalidationExpr,
- StringRef DiagSubject) {
+ StringRef InvalidatedSubject) {
if (isa<CXXDeleteExpr>(InvalidationExpr)) {
S.Diag(InvalidationExpr->getExprLoc(),
diag::note_lifetime_safety_freed_here)
@@ -432,7 +433,7 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper {
}
S.Diag(InvalidationExpr->getExprLoc(),
diag::note_lifetime_safety_invalidated_here)
- << DiagSubject << InvalidationExpr->getSourceRange();
+ << InvalidatedSubject << InvalidationExpr->getSourceRange();
}
std::pair<SourceLocation, StringRef>
>From 0e8aa55e8df7c590065961f7ddafbef94b25c156 Mon Sep 17 00:00:00 2001
From: iitianpushkar <pushkarsingh0587 at gmail.com>
Date: Sat, 20 Jun 2026 18:38:12 +0530
Subject: [PATCH 09/14] added full text diagnostic notes in all affected tests
---
.../LifetimeSafety/annotation-suggestions.cpp | 14 +-
.../Sema/LifetimeSafety/invalidations.cpp | 138 ++++----
clang/test/Sema/LifetimeSafety/safety-c.c | 19 +-
clang/test/Sema/LifetimeSafety/safety.cpp | 326 +++++++++---------
4 files changed, 249 insertions(+), 248 deletions(-)
diff --git a/clang/test/Sema/LifetimeSafety/annotation-suggestions.cpp b/clang/test/Sema/LifetimeSafety/annotation-suggestions.cpp
index 87bc2a24188bc..98c528516b8e7 100644
--- a/clang/test/Sema/LifetimeSafety/annotation-suggestions.cpp
+++ b/clang/test/Sema/LifetimeSafety/annotation-suggestions.cpp
@@ -277,21 +277,21 @@ View return_view_field(const ViewProvider& v) { // expected-warning {{paramet
void test_get_on_temporary_pointer() {
const ReturnsSelf* s_ref = &ReturnsSelf().get(); // expected-warning {{temporary object does not live long enough}}.
- // expected-note at -1 {{is destroyed here}}
+ // expected-note at -1 {{temporary object is destroyed here}}
// expected-note at -2 {{result of call to 'get' aliases the storage of temporary object}}
(void)s_ref; // expected-note {{later used here}}
}
void test_get_on_temporary_ref() {
const ReturnsSelf& s_ref = ReturnsSelf().get(); // expected-warning {{temporary object does not live long enough}}.
- // expected-note at -1 {{is destroyed here}}
+ // expected-note at -1 {{temporary object is destroyed here}}
// expected-note at -2 {{result of call to 'get' aliases the storage of temporary object}}
(void)s_ref; // expected-note {{later used here}}
}
void test_getView_on_temporary() {
View sv = ViewProvider{1}.getView(); // expected-warning {{temporary object does not live long enough}}.
- // expected-note at -1 {{is destroyed here}}
+ // expected-note at -1 {{temporary object is destroyed here}}
// expected-note at -2 {{result of call to 'getView' aliases the storage of temporary object}}
(void)sv; // expected-note {{later used here}}
}
@@ -604,7 +604,7 @@ void uaf_via_inferred_lifetimebound() {
int local;
f = return_lambda_capturing_param(local); // expected-warning {{local variable 'local' does not live long enough}} \
// expected-note {{result of call to 'return_lambda_capturing_param' aliases the storage of local variable 'local'}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'local' is destroyed here}}
(void)f; // expected-note {{later used here}}
}
@@ -628,7 +628,7 @@ void test_inference() {
MyObj obj;
ptr = create_target(obj); // expected-warning {{local variable 'obj' does not live long enough}} \
// expected-note {{result of call to 'create_target' aliases the storage of local variable 'obj'}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'obj' is destroyed here}}
(void)ptr; // expected-note {{later used here}}
}
} // namespace make_unique_suggestion
@@ -636,12 +636,12 @@ void test_inference() {
namespace new_allocation_suggestion {
View* MakeView(const MyObj& in) { // expected-warning {{parameter in intra-TU function should be marked [[clang::lifetimebound]]}}
- return new View(in); // expected-note {{param returned here}} {{is destroyed here}}
+ return new View(in); // expected-note {{param returned here}}
}
void test_new_allocation() {
View* v = MakeView(MyObj{}); // expected-warning {{temporary object does not live long enough}} \
- // expected-note {{is destroyed here}} \
+ // expected-note {{temporary object is destroyed here}} \
// expected-note {{result of call to 'MakeView' aliases the storage of temporary object}}
(void)v; // expected-note {{later used here}}
}
diff --git a/clang/test/Sema/LifetimeSafety/invalidations.cpp b/clang/test/Sema/LifetimeSafety/invalidations.cpp
index 5b612d2c4de5b..6d76940f48b64 100644
--- a/clang/test/Sema/LifetimeSafety/invalidations.cpp
+++ b/clang/test/Sema/LifetimeSafety/invalidations.cpp
@@ -53,7 +53,7 @@ void InvalidateBeforeSwapIterators(std::vector<int> v1, std::vector<int> v2) {
if (it1 == std::end(v1) || it2 == std::end(v2)) return;
*it1 = 0; // ok
*it2 = 0; // ok
- v1.clear(); // expected-note {{is invalidated here}}
+ v1.clear(); // expected-note {{parameter 'v1' is invalidated here}}
*it1 = 0; // expected-note {{later used here}}
// FIXME: Handle invalidating functions like std::swap.
std::swap(it1, it2);
@@ -67,7 +67,7 @@ void InvalidateBeforeSwapContainers(std::vector<int> v1, std::vector<int> v2) {
if (it1 == std::end(v1) || it2 == std::end(v2)) return;
*it1 = 0; // ok
*it2 = 0; // ok
- v1.clear(); // expected-note {{is invalidated here}}
+ v1.clear(); // expected-note {{parameter 'v1' is invalidated here}}
*it1 = 0; // expected-note {{later used here}}
}
} // namespace InvalidateBeforeSwap
@@ -81,7 +81,7 @@ void SameConditionInvalidatesThenValidatesIterator() {
if (it == container.end()) return;
const bool a = A();
if (a) {
- container.clear(); // expected-note {{is invalidated here}}
+ container.clear(); // expected-note {{local variable 'container' is invalidated here}}
}
if (a) {
it = container.begin();
@@ -112,7 +112,7 @@ void MergeWithDifferentContainerValuesInvalidated() {
} else {
it = std::find(v3.begin(), v3.end(), 10);
}
- v2.clear(); // expected-note {{is invalidated here}}
+ v2.clear(); // expected-note {{local variable 'v2' is invalidated here}}
*it = 20; // expected-note {{later used here}}
}
} // namespace IteratorWithMultipleContainers
@@ -123,7 +123,7 @@ void IteratorInvalidationInAForLoop(std::vector<int> v) {
it != std::end(v);
++it) { // expected-note {{later used here}}
if (Bool()) {
- v.erase(it); // expected-note {{is invalidated here}}
+ v.erase(it); // expected-note {{parameter 'v' is invalidated here}}
}
}
}
@@ -132,7 +132,7 @@ void IteratorInvalidationInAWhileLoop(std::vector<int> v) {
auto it = std::begin(v); // expected-warning {{parameter 'v' is later invalidated}}
while (it != std::end(v)) {
if (Bool()) {
- v.erase(it); // expected-note {{is invalidated here}}
+ v.erase(it); // expected-note {{parameter 'v' is invalidated here}}
}
++it; // expected-note {{later used here}}
}
@@ -157,7 +157,7 @@ void IteratorInvalidationInAForeachLoop(std::vector<int> v) {
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 {{is invalidated here}}
+ v.erase(std::find(v.begin(), v.end(), 1)); // expected-note {{parameter 'v' is invalidated here}}
}
}
}
@@ -185,7 +185,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 {{parameter 'v' is later invalidated}}
if (it != std::end(v)) {
- v.erase(it); // expected-note {{is invalidated here}}
+ v.erase(it); // expected-note {{parameter 'v' is invalidated here}}
}
*it; // expected-note {{later used here}}
}
@@ -202,7 +202,7 @@ void UseReturnedIteratorAfterInsert(std::vector<int> v) {
void UseInvalidIteratorAfterInsert(std::vector<int> v) {
auto it = std::begin(v); // expected-warning {{parameter 'v' is later invalidated}}
- v.insert(it, 10); // expected-note {{is invalidated here}}
+ v.insert(it, 10); // expected-note {{parameter 'v' is invalidated here}}
if (it != std::end(v)) { // expected-note {{later used here}}
*it;
}
@@ -221,7 +221,7 @@ void IteratorValidAfterInsert(std::vector<int> v) {
void IteratorInvalidAfterInsert(std::vector<int> v, int value) {
auto it = std::begin(v); // expected-warning {{parameter 'v' is later invalidated}}
- v.insert(it, 0); // expected-note {{is invalidated here}}
+ v.insert(it, 0); // expected-note {{parameter 'v' is invalidated here}}
*it; // expected-note {{later used here}}
}
} // namespace SimpleStdInsert
@@ -231,7 +231,7 @@ void IteratorUsedAfterErase(std::vector<int> v) {
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 {{is invalidated here}}
+ v.erase(it); // expected-note {{parameter 'v' is invalidated here}}
}
}
}
@@ -239,7 +239,7 @@ void IteratorUsedAfterErase(std::vector<int> v) {
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 {{is invalidated here}}
+ v.push_back(4); // expected-note {{parameter 'v' is invalidated here}}
}
++it; // expected-note {{later used here}}
}
@@ -247,7 +247,7 @@ void IteratorUsedAfterPushBackParam(std::vector<int>& v) { // expected-warning {
void IteratorUsedAfterPushBack(std::vector<int> v) {
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 {{is invalidated here}}
+ v.push_back(4); // expected-note {{parameter 'v' is invalidated here}}
}
++it; // expected-note {{later used here}}
}
@@ -256,14 +256,14 @@ void IteratorUsedAfterPreIncrement() {
std::vector<int> v;
auto it = v.begin(); // expected-warning {{local variable 'v' is later invalidated}}
auto next = ++it;
- v.push_back(1); // expected-note {{is invalidated here}}
+ v.push_back(1); // expected-note {{local variable 'v' is invalidated here}}
(void)*next; // expected-note {{later used here}}
}
void IteratorUsedAfterPostDecrement(std::vector<int> v) {
auto it = v.rbegin(); // expected-warning {{parameter 'v' is later invalidated}}
auto prev = it--;
- v.push_back(1); // expected-note {{is invalidated here}}
+ v.push_back(1); // expected-note {{parameter 'v' is invalidated here}}
(void)*prev; // expected-note {{later used here}}
}
@@ -271,21 +271,21 @@ void IteratorUsedAfterAddition() {
std::vector<int> v;
auto it = v.cbegin(); // expected-warning {{local variable 'v' is later invalidated}}
auto next = it + 5;
- v.push_back(1); // expected-note {{is invalidated here}}
+ v.push_back(1); // expected-note {{local variable 'v' is invalidated here}}
(void)*next; // expected-note {{later used here}}
}
void IteratorUsedAfterReverseSubtraction(std::vector<int> v) {
auto it = v.crbegin(); // expected-warning {{parameter 'v' is later invalidated}}
auto prev = 5 - it;
- v.push_back(1); // expected-note {{is invalidated here}}
+ v.push_back(1); // expected-note {{parameter 'v' is invalidated here}}
(void)*prev; // expected-note {{later used here}}
}
void IteratorUsedAfterAddAdd(std::vector<int> v) {
auto it = v.cbegin(); // expected-warning {{parameter 'v' is later invalidated}}
auto next = (it + 5) + 5;
- v.push_back(1); // expected-note {{is invalidated here}}
+ v.push_back(1); // expected-note {{parameter 'v' is invalidated here}}
(void)*next; // expected-note {{later used here}}
}
@@ -293,21 +293,21 @@ void IteratorUsedAfterMixedAddition() {
std::vector<int> v;
auto it = v.cbegin(); // expected-warning {{local variable 'v' is later invalidated}}
auto next = 1 + it + 2 + 3;
- v.push_back(1); // expected-note {{is invalidated here}}
+ v.push_back(1); // expected-note {{local variable 'v' is invalidated here}}
(void)*next; // expected-note {{later used here}}
}
void IteratorUsedAfterPreIncrementAddAssign(std::vector<int> v) {
auto it = v.begin(); // expected-warning {{parameter 'v' is later invalidated}}
it = ++it + 1 + 2;
- v.push_back(1); // expected-note {{is invalidated here}}
+ v.push_back(1); // expected-note {{parameter 'v' is invalidated here}}
(void)*it; // expected-note {{later used here}}
}
void IteratorUsedAfterBeginAddAssign() {
std::vector<int> v;
auto it = v.begin() + 1; // expected-warning {{local variable 'v' is later invalidated}}
- v.push_back(1); // expected-note {{is invalidated here}}
+ v.push_back(1); // expected-note {{local variable 'v' is invalidated here}}
(void)*it; // expected-note {{later used here}}
}
@@ -315,7 +315,7 @@ void IteratorUsedAfterStdBeginAddAssign() {
std::vector<int> v;
std::vector<int>::iterator it;
it = std::begin(v) + 1; // expected-warning {{local variable 'v' is later invalidated}}
- v.push_back(1); // expected-note {{is invalidated here}}
+ v.push_back(1); // expected-note {{local variable 'v' is invalidated here}}
(void)*it; // expected-note {{later used here}}
}
} // namespace SimpleInvalidIterators
@@ -325,13 +325,13 @@ void IteratorInvalidatedThroughLocalReferenceAlias() {
std::vector<int> vv;
std::vector<int> &v = vv;
auto it = vv.begin(); // expected-warning {{local variable 'vv' is later invalidated}}
- v.push_back(42); // expected-note {{is invalidated here}}
+ v.push_back(42); // expected-note {{local variable 'vv' is invalidated here}}
(void)it; // expected-note {{later used here}}
}
void IteratorInvalidatedThroughPointerParameter(std::vector<int> *v) { // expected-warning {{parameter 'v' is later invalidated}}
auto it = v->begin();
- v->push_back(42); // expected-note {{is invalidated here}}
+ v->push_back(42); // expected-note {{parameter 'v' is invalidated here}}
(void)it; // expected-note {{later used here}}
}
@@ -348,7 +348,7 @@ void ParenthesizedContainerInvalidatesIterator() {
namespace ContainerObjectAliases {
// FIXME: Distinguish owner-borrow from content-borrow.
void PointerParameterObjectUseIsOk(std::vector<int> *v) { // expected-warning {{parameter 'v' is later invalidated}}
- v->push_back(42); // expected-note {{is invalidated here}}
+ v->push_back(42); // expected-note {{parameter 'v' is invalidated here}}
(void)v; // expected-note {{later used here}}
}
@@ -356,7 +356,7 @@ void PointerParameterObjectUseIsOk(std::vector<int> *v) { // expected-warning {{
void LocalPointerAliasObjectUseIsOk() {
std::vector<int> vv;
std::vector<int> *v = &vv; // expected-warning {{local variable 'vv' is later invalidated}}
- v->push_back(42); // expected-note {{is invalidated here}}
+ v->push_back(42); // expected-note {{local variable 'vv' is invalidated here}}
(void)*v; // expected-note {{later used here}}
}
@@ -364,7 +364,7 @@ void LocalPointerAliasObjectUseIsOk() {
void LocalReferenceAliasObjectUseIsOk() {
std::vector<int> vv;
std::vector<int> &v = vv; // expected-warning {{local variable 'vv' is later invalidated}}
- v.push_back(42); // expected-note {{is invalidated here}}
+ v.push_back(42); // expected-note {{local variable 'vv' is invalidated here}}
(void)v; // expected-note {{later used here}}
}
} // namespace ContainerObjectAliases
@@ -375,7 +375,7 @@ namespace ElementReferences {
void ReferenceToVectorElement() {
std::vector<int> v = {1, 2, 3};
int& ref = v[0]; // expected-warning {{local variable 'v' is later invalidated}}
- v.push_back(4); // expected-note {{is invalidated here}}
+ v.push_back(4); // expected-note {{local variable 'v' is invalidated here}}
ref = 10; // expected-note {{later used here}}
(void)ref;
}
@@ -383,14 +383,14 @@ void ReferenceToVectorElement() {
void PointerRefToVectorElement() {
std::vector<int*> v = {nullptr, nullptr};
int*& ref = v[0]; // expected-warning {{local variable 'v' is later invalidated}}
- v.push_back(nullptr); // expected-note {{is invalidated here}}
+ v.push_back(nullptr); // expected-note {{local variable 'v' is invalidated here}}
ref = nullptr; // expected-note {{later used here}}
}
void PointerToVectorElement() {
std::vector<int> v = {1, 2, 3};
int* ptr = &v[0]; // expected-warning {{local variable 'v' is later invalidated}}
- v.resize(100); // expected-note {{is invalidated here}}
+ v.resize(100); // expected-note {{local variable 'v' is invalidated here}}
*ptr = 10; // expected-note {{later used here}}
}
@@ -403,7 +403,7 @@ void SelfInvalidatingMap() {
// On the other hand, std::flat_map (since C++23) does not provide pointer stability on
// insertion and following is unsafe for this container.
mp[1] = "42";
- mp[2] // expected-note {{is invalidated here}}
+ mp[2] // expected-note {{local variable 'mp' is invalidated here}}
=
mp[1]; // expected-warning {{local variable 'mp' is later invalidated}} expected-note {{later used here}}
}
@@ -412,7 +412,7 @@ 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 {{local variable 'mp' is later invalidated}}
- mp.erase(mp.find(4)); // expected-note {{is invalidated here}}
+ mp.erase(mp.find(4)); // expected-note {{local variable 'mp' is invalidated here}}
if (it != mp.end()) // expected-note {{later used here}}
*it;
}
@@ -422,12 +422,12 @@ namespace Strings {
void append(std::string str) {
std::string_view view = str; // expected-warning {{parameter 'str' is later invalidated}}
- str += "456"; // expected-note {{is invalidated here}}
+ str += "456"; // expected-note {{parameter 'str' is invalidated here}}
(void)view; // expected-note {{later used here}}
}
void reassign(std::string str, std::string str2) {
std::string_view view = str; // expected-warning {{parameter 'str' is later invalidated}}
- str = str2; // expected-note {{is invalidated here}}
+ str = str2; // expected-note {{parameter 'str' is invalidated here}}
(void)view; // expected-note {{later used here}}
}
} // namespace Strings
@@ -437,7 +437,7 @@ void ReassigningAfterMove(std::string str, std::string str2) {
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 {{is invalidated here}}
+ str = str2; // expected-note {{parameter 'str' is invalidated here}}
(void)view; // expected-note {{later used here}}
}
@@ -480,7 +480,7 @@ void Invalidate1Use2ViaRefIsOk() {
S s;
auto it = s.strings2.begin(); // expected-warning {{local variable 's' is later invalidated}}
auto& strings1 = s.strings1;
- strings1.push_back("1"); // expected-note {{is invalidated here}}
+ strings1.push_back("1"); // expected-note {{local variable 's' is invalidated here}}
*it; // expected-note {{later used here}}
}
void Invalidate1UseSIsOk() {
@@ -493,14 +493,14 @@ void Invalidate1UseSIsOk() {
void PointerToContainerIsOk() {
std::vector<std::string> s;
std::vector<std::string>* p = &s; // expected-warning {{local variable 's' is later invalidated}}
- p->push_back("1"); // expected-note {{is invalidated here}}
+ p->push_back("1"); // expected-note {{local variable 's' is invalidated here}}
(void)*p; // expected-note {{later used here}}
}
void IteratorFromPointerToContainerIsInvalidated() {
std::vector<std::string> s;
std::vector<std::string>* p = &s; // expected-warning {{local variable 's' is later invalidated}}
auto it = p->begin();
- p->push_back("1"); // expected-note {{is invalidated here}}
+ p->push_back("1"); // expected-note {{local variable 's' is invalidated here}}
*it; // expected-note {{later used here}}
}
// FIXME: Distinguish invalidating an element's contents from invalidating
@@ -508,7 +508,7 @@ void IteratorFromPointerToContainerIsInvalidated() {
void ChangingRegionOwnedByContainerIsOk() {
std::vector<std::string> subdirs;
for (std::string& path : subdirs) // expected-warning {{local variable 'subdirs' is later invalidated}} expected-note {{later used here}}
- path = std::string(); // expected-note {{is invalidated here}}
+ path = std::string(); // expected-note {{local variable 'subdirs' is invalidated here}}
}
} // namespace ContainersAsFields
@@ -522,7 +522,7 @@ struct SinkOwnerBorrow {
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 {{is invalidated here}}
+ dest->clear(); // expected-note {{parameter 'dest' is invalidated here}}
}
};
@@ -531,7 +531,7 @@ struct SinkInteriorBorrow {
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 {{is invalidated here}}
+ dest->clear(); // expected-note {{parameter 'dest' is invalidated here}}
}
};
@@ -548,28 +548,28 @@ struct S {
void InvalidatedFieldLocalVector() {
std::vector<std::string> strings;
FieldFromLocalVector = *strings.begin(); // expected-warning {{local variable 'strings' escapes to the field 'FieldFromLocalVector' and is later invalidated}}
- strings.push_back("1"); // expected-note {{is invalidated here}}
+ strings.push_back("1"); // expected-note {{local variable 'strings' is invalidated here}}
}
void InvalidatedFieldByValueParamVector(std::vector<std::string> strings) {
FieldFromByValueParamVector = *strings.begin(); // expected-warning {{parameter 'strings' escapes to the field 'FieldFromByValueParamVector' and is later invalidated}}
- strings.push_back("1"); // expected-note {{is invalidated here}}
+ strings.push_back("1"); // expected-note {{parameter 'strings' is invalidated here}}
}
void InvalidatedFieldLocalString() {
std::string s;
FieldFromLocalString = s; // expected-warning {{local variable 's' escapes to the field 'FieldFromLocalString' and is later invalidated}}
- s.clear(); // expected-note {{is invalidated here}}
+ s.clear(); // expected-note {{local variable 's' is invalidated here}}
}
void InvalidatedFieldByValueParamString(std::string s) {
FieldFromByValueParamString = s; // expected-warning {{parameter 's' escapes to the field 'FieldFromByValueParamString' and is later invalidated}}
- s.clear(); // expected-note {{is invalidated here}}
+ s.clear(); // expected-note {{parameter 's' is invalidated here}}
}
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 {{is invalidated here}}
+ s.~basic_string(); // expected-note {{parameter 's' is invalidated here}}
}
void InvalidatedFieldDelete() {
@@ -608,17 +608,17 @@ struct S {
void InvalidatedGlobalLocalVector() {
std::vector<std::string> strings;
GlobalFromLocalVector = *strings.begin(); // expected-warning {{local variable 'strings' escapes to the global variable 'GlobalFromLocalVector' and is later invalidated}}
- strings.push_back("1"); // expected-note {{is invalidated here}}
+ strings.push_back("1"); // expected-note {{local variable 'strings' is invalidated here}}
}
void InvalidatedGlobalByValueParamString(std::string s) {
GlobalFromByValueParamString = s; // expected-warning {{parameter 's' escapes to the global variable 'GlobalFromByValueParamString' and is later invalidated}}
- s.clear(); // expected-note {{is invalidated here}}
+ s.clear(); // expected-note {{parameter 's' is invalidated here}}
}
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 {{is invalidated here}}
+ s.~basic_string(); // expected-note {{parameter 's' is invalidated here}}
}
void InvalidatedGlobalDelete() {
@@ -636,13 +636,13 @@ void InvalidatedStaticLocalString() {
static std::string_view StaticFromLocalString; // expected-note {{this static storage dangles}}
std::string s;
StaticFromLocalString = s; // expected-warning {{local variable 's' escapes to the static variable 'StaticFromLocalString' and is later invalidated}}
- s.clear(); // expected-note {{is invalidated here}}
+ s.clear(); // expected-note {{local variable 's' is invalidated here}}
}
void InvalidatedStaticMemberString() {
std::string s;
S::StaticMember = s; // expected-warning {{local variable 's' escapes to the static variable 'StaticMember' and is later invalidated}}
- s.clear(); // expected-note {{is invalidated here}}
+ s.clear(); // expected-note {{local variable 's' is invalidated here}}
}
void GlobalReassignedBeforeInvalidation() {
@@ -715,14 +715,14 @@ void SetExtractDoesNotInvalidateOthers() {
void SetClearInvalidates() {
std::set<int> s;
auto it = s.begin(); // expected-warning {{local variable 's' is later invalidated}}
- s.clear(); // expected-note {{is invalidated here}}
+ s.clear(); // expected-note {{local variable 's' is invalidated here}}
*it; // expected-note {{later used here}}
}
void MapClearInvalidates() {
std::map<int, int> m;
auto it = m.begin(); // expected-warning {{local variable 'm' is later invalidated}}
- m.clear(); // expected-note {{is invalidated here}}
+ m.clear(); // expected-note {{local variable 'm' is invalidated here}}
*it; // expected-note {{later used here}}
}
@@ -741,7 +741,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 {{parameter 'mp' is later invalidated}} \
- // expected-note {{is invalidated here}} \
+ // expected-note {{parameter 'mp' is invalidated here}} \
// expected-note {{later used here}}
}
@@ -752,7 +752,7 @@ void captured_view_invalidated_by_owner() {
std::string s = "42";
std::string_view p = s; // expected-warning {{local variable 's' is later invalidated}}
auto lambda = [=]() { return p; };
- s.push_back('c'); // expected-note {{is invalidated here}}
+ s.push_back('c'); // expected-note {{local variable 's' is invalidated here}}
lambda(); // expected-note {{later used here}}
}
@@ -760,7 +760,7 @@ void multiple_captures_one_invalidated() {
std::string s1 = "a", s2 = "b";
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 {{is invalidated here}}
+ s1.clear(); // expected-note {{local variable 's1' is invalidated here}}
lambda(); // expected-note {{later used here}}
}
@@ -794,7 +794,7 @@ struct S {
void baz(){
std::vector<std::string> vec = {"42"};
v = vec[0]; // expected-warning {{local variable 'vec' is later invalidated}}
- vec.push_back("1"); // expected-note {{is invalidated here}}
+ vec.push_back("1"); // expected-note {{local variable 'vec' is invalidated here}}
bar(); // expected-note {{later used here}}
v = nullptr;
}
@@ -807,7 +807,7 @@ void function_captured_ref_invalidated() {
std::vector<int> v;
v.push_back(1);
std::function<void()> f = [&r = v[0]]() { (void)r; }; // expected-warning {{local variable 'v' is later invalidated}}
- v.push_back(2); // expected-note {{is invalidated here}}
+ v.push_back(2); // expected-note {{local variable 'v' is invalidated here}}
(void)f; // expected-note {{later used here}}
}
@@ -819,7 +819,7 @@ namespace explicit_destructor {
void explicit_destructor_invalidates_pointer() {
std::string s = "42";
const char *p = s.data(); // expected-warning {{local variable 's' is later invalidated}}
- s.~basic_string(); // expected-note {{is invalidated here}}
+ s.~basic_string(); // expected-note {{local variable 's' is invalidated here}}
(void)*p; // expected-note {{later used here}}
}
@@ -827,7 +827,7 @@ void pointer_destructor_invalidates_pointer() {
char storage[sizeof(std::string)];
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 {{is invalidated here}}
+ obj->~basic_string(); // expected-note {{local variable 'storage' is invalidated here}}
(void)*p; // expected-note {{later used here}}
}
@@ -835,7 +835,7 @@ void destroy_at_invalidates_pointer() {
char storage[sizeof(std::string)];
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 {{is invalidated here}}
+ std::destroy_at(obj); // expected-note {{local variable 'storage' is invalidated here}}
(void)*p; // expected-note {{later used here}}
}
@@ -853,7 +853,7 @@ 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 {{local variable 'arr' is later invalidated}}
- std::destroy_at(&arr_ref); // expected-note {{is invalidated here}}
+ std::destroy_at(&arr_ref); // expected-note {{local variable 'arr' is invalidated here}}
(void)*p; // expected-note {{later used here}}
}
@@ -861,7 +861,7 @@ void reference_destructor_invalidates_pointer() {
std::string s = "42";
std::string &ref = s; // expected-warning {{local variable 's' is later invalidated}}
const char *p = ref.data();
- std::destroy_at(&ref); // expected-note {{is invalidated here}}
+ std::destroy_at(&ref); // expected-note {{local variable 's' is invalidated here}}
(void)*p; // expected-note {{later used here}}
}
@@ -869,7 +869,7 @@ void destroy_at_ternary_operator(bool flag) {
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 {{is invalidated here}}
+ std::destroy_at(flag ? str1 : str2); // expected-note {{allocated object is invalidated here}}
(void)*p; // expected-note {{later used here}}
}
@@ -881,7 +881,7 @@ struct StringOwner {
void member_destructor_invalidates_pointer() {
StringOwner owner = {"42", "43"};
const char *p = owner.s.data(); // expected-warning {{local variable 'owner' is later invalidated}}
- owner.t.~basic_string(); // expected-note {{is invalidated here}}
+ owner.t.~basic_string(); // expected-note {{local variable 'owner' is invalidated here}}
(void)*p; // expected-note {{later used here}}
}
@@ -892,7 +892,7 @@ namespace unique_ptr_invalidation {
void invalid_after_reset() {
std::unique_ptr<int> up(new int);
int *p = up.get(); // expected-warning {{local variable 'up' is later invalidated}}
- up.reset(); // expected-note {{is invalidated here}}
+ up.reset(); // expected-note {{local variable 'up' is invalidated here}}
(void)*p; // expected-note {{later used here}}
}
@@ -900,14 +900,14 @@ 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 {{local variable 'up' is later invalidated}}
- up = std::move(other); // expected-note {{is invalidated here}}
+ up = std::move(other); // expected-note {{local variable 'up' is 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 {{local variable 'up' is later invalidated}}
- up = nullptr; // expected-note {{is invalidated here}}
+ up = nullptr; // expected-note {{local variable 'up' is invalidated here}}
(void)*p; // expected-note {{later used here}}
}
@@ -915,7 +915,7 @@ 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 {{local variable 'up' is later invalidated}}
- up.reset(); // expected-note {{is invalidated here}}
+ up.reset(); // expected-note {{local variable 'up' is invalidated here}}
(void)*p; // expected-note {{later used here}}
}
diff --git a/clang/test/Sema/LifetimeSafety/safety-c.c b/clang/test/Sema/LifetimeSafety/safety-c.c
index dace935b26c5b..81cc13569f09e 100644
--- a/clang/test/Sema/LifetimeSafety/safety-c.c
+++ b/clang/test/Sema/LifetimeSafety/safety-c.c
@@ -16,7 +16,7 @@ void simple_case(void) {
{
int i;
p = &i; // expected-warning {{local variable 'i' does not live long enough}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'i' is destroyed here}}
(void)*p; // expected-note {{later used here}}
}
@@ -25,7 +25,7 @@ void chained_assignment(void) {
{
int i;
p = q = r = &i; // expected-warning {{local variable 'i' does not live long enough}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'i' is destroyed here}}
(void)*p; // expected-note {{later used here}}
}
@@ -35,7 +35,7 @@ void conditional_branch(int cond) {
if (cond) {
int i;
p = &i; // expected-warning {{local variable 'i' does not live long enough}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'i' is destroyed here}}
(void)*p; // expected-note {{later used here}}
}
@@ -46,7 +46,7 @@ void loop_with_break(int cond) {
if (cond) {
int i;
p = &i; // expected-warning {{local variable 'i' does not live long enough}}
- break; // expected-note {{is destroyed here}}
+ break; // expected-note {{local variable 'i' is destroyed here}}
}
}
(void)*p; // expected-note {{later used here}}
@@ -64,7 +64,7 @@ void lifetimebound_call(void) {
int i;
p = identity(&i); // expected-warning {{local variable 'i' does not live long enough}} \
// expected-note {{result of call to 'identity' aliases the storage of local variable 'i'}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'i' is destroyed here}}
(void)*p; // expected-note {{later used here}}
}
@@ -85,7 +85,7 @@ void struct_address_of_field(void) {
{
struct IntField holder;
p = &holder.field; // expected-warning {{local variable 'holder' does not live long enough}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'holder' is destroyed here}}
(void)*p; // expected-note {{later used here}}
}
@@ -95,7 +95,8 @@ void conditional_operator_lifetimebound(int cond) {
int a, b;
p = identity(cond ? &a // expected-warning {{local variable 'a' does not live long enough}}
: &b); // expected-warning {{local variable 'b' does not live long enough}}
- } // expected-note 2 {{is destroyed here}}
+ } // expected-note {{local variable 'a' is destroyed here}}
+ // expected-note at -1 {{local variable 'b' is destroyed here}}
(void)*p; // expected-note 2 {{later used here}}
}
@@ -109,7 +110,7 @@ void union_member(void) {
{
union IntOrPtr u;
p = &u.i; // expected-warning {{local variable 'u' does not live long enough}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'u' is destroyed here}}
(void)*p; // expected-note {{later used here}}
}
@@ -125,7 +126,7 @@ void anonymous_union_member(void) {
{
struct AnonymousUnion u;
p = &u.i; // expected-warning {{local variable 'u' does not live long enough}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'u' is destroyed 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 3d07000938f9c..337a9a2648e6c 100644
--- a/clang/test/Sema/LifetimeSafety/safety.cpp
+++ b/clang/test/Sema/LifetimeSafety/safety.cpp
@@ -64,7 +64,7 @@ void simple_case_gsl() {
{
MyObj s;
v = s; // expected-warning {{local variable 's' does not live long enough}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 's' is destroyed here}}
v.use(); // expected-note {{later used here}}
}
@@ -93,7 +93,7 @@ void pointer_chain() {
MyObj s;
p = &s; // expected-warning {{does not live long enough}}
q = p; // expected-note {{local variable 'p' aliases the storage of local variable 's'}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 's' is destroyed here}}
(void)*q; // expected-note {{later used here}}
}
@@ -103,7 +103,7 @@ void propagation_gsl() {
MyObj s;
v1 = s; // expected-warning {{local variable 's' does not live long enough}}
v2 = v1; // expected-note {{local variable 'v1' aliases the storage of local variable 's'}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 's' is destroyed here}}
v2.use(); // expected-note {{later used here}}
}
@@ -112,7 +112,7 @@ void multiple_uses_one_warning() {
{
MyObj s;
p = &s; // expected-warning {{does not live long enough}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 's' is destroyed here}}
(void)*p; // expected-note {{later used here}}
// No second warning for the same loan.
p->id = 1;
@@ -127,7 +127,7 @@ void multiple_pointers() {
p = &s; // expected-warning {{does not live long enough}}
q = &s; // expected-warning {{does not live long enough}}
r = &s; // expected-warning {{does not live long enough}}
- } // expected-note 3 {{is destroyed here}}
+ } // expected-note 3 {{local variable 's' is destroyed here}}
(void)*p; // expected-note {{later used here}}
(void)*q; // expected-note {{later used here}}
(void)*r; // expected-note {{later used here}}
@@ -139,7 +139,7 @@ void multiple_pointers_chained() {
MyObj s;
MyObj* obj1, *obj2;
p = obj1 = obj2 = &s; // expected-warning {{does not live long enough}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 's' is destroyed here}}
(void)*p; // expected-note {{later used here}}
}
@@ -158,11 +158,11 @@ void single_pointer_multiple_loans(bool cond) {
if (cond){
MyObj s;
p = &s; // expected-warning {{does not live long enough}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 's' is destroyed here}}
else {
MyObj t;
p = &t; // expected-warning {{does not live long enough}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 't' is destroyed here}}
(void)*p; // expected-note 2 {{later used here}}
}
@@ -171,11 +171,11 @@ void single_pointer_multiple_loans_gsl(bool cond) {
if (cond){
MyObj s;
v = s; // expected-warning {{local variable 's' does not live long enough}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 's' is destroyed here}}
else {
MyObj t;
v = t; // expected-warning {{local variable 't' does not live long enough}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 't' is destroyed here}}
v.use(); // expected-note 2 {{later used here}}
}
@@ -185,7 +185,7 @@ void if_branch(bool cond) {
if (cond) {
MyObj temp;
p = &temp; // expected-warning {{local variable 'temp' does not live long enough}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'temp' is destroyed here}}
(void)*p; // expected-note {{later used here}}
}
@@ -195,7 +195,7 @@ void if_branch_potential(bool cond) {
if (cond) {
MyObj temp;
p = &temp; // expected-warning {{local variable 'temp' does not live long enough}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'temp' is destroyed here}}
if (!cond)
(void)*p; // expected-note {{later used here}}
else
@@ -208,7 +208,7 @@ void if_branch_gsl(bool cond) {
if (cond) {
MyObj temp;
v = temp; // expected-warning {{local variable 'temp' does not live long enough}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'temp' is destroyed here}}
v.use(); // expected-note {{later used here}}
}
@@ -223,7 +223,7 @@ void potential_together(bool cond) {
p_definite = &s; // expected-warning {{does not live long enough}}
if (cond)
p_maybe = &s; // expected-warning {{does not live long enough}}
- } // expected-note 2 {{is destroyed here}}
+ } // expected-note 2 {{local variable 's' is destroyed here}}
(void)*p_definite; // expected-note {{later used here}}
if (!cond)
(void)*p_maybe; // expected-note {{later used here}}
@@ -237,7 +237,7 @@ void overrides_potential(bool cond) {
MyObj s;
q = &s; // expected-warning {{does not live long enough}}
p = q;
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 's' is destroyed here}}
if (cond) {
// 'q' is conditionally "rescued". 'p' is not.
@@ -256,7 +256,7 @@ void due_to_conditional_killing(bool cond) {
{
MyObj s;
q = &s; // expected-warning {{does not live long enough}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 's' is destroyed here}}
if (cond) {
// 'q' is conditionally "rescued". 'p' is not.
q = &safe;
@@ -269,7 +269,7 @@ void for_loop_use_after_loop_body(MyObj safe) {
for (int i = 0; i < 1; ++i) {
MyObj s;
p = &s; // expected-warning {{does not live long enough}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 's' is destroyed here}}
(void)*p; // expected-note {{later used here}}
}
@@ -289,7 +289,7 @@ void for_loop_gsl() {
for (int i = 0; i < 1; ++i) {
MyObj s;
v = s; // expected-warning {{local variable 's' does not live long enough}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 's' is destroyed here}}
v.use(); // expected-note {{later used here}}
}
@@ -300,7 +300,7 @@ void for_loop_use_before_loop_body(MyObj safe) {
(void)*p; // expected-note {{later used here}}
MyObj s;
p = &s; // expected-warning {{does not live long enough}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 's' is destroyed here}}
(void)*p;
}
@@ -311,7 +311,7 @@ void loop_with_break(bool cond) {
if (cond) {
MyObj temp;
p = &temp; // expected-warning {{does not live long enough}}
- break; // expected-note {{is destroyed here}}
+ break; // expected-note {{local variable 'temp' is destroyed here}}
}
}
(void)*p; // expected-note {{later used here}}
@@ -324,7 +324,7 @@ void loop_with_break_gsl(bool cond) {
if (cond) {
MyObj temp;
v = temp; // expected-warning {{local variable 'temp' does not live long enough}}
- break; // expected-note {{is destroyed here}}
+ break; // expected-note {{local variable 'temp' is destroyed here}}
}
}
v.use(); // expected-note {{later used here}}
@@ -338,7 +338,7 @@ void multiple_expiry_of_same_loan(bool cond) {
MyObj unsafe;
if (cond) {
p = &unsafe; // expected-warning {{does not live long enough}}
- break; // expected-note {{is destroyed here}}
+ break; // expected-note {{local variable 'unsafe' is destroyed here}}
}
}
(void)*p; // expected-note {{later used here}}
@@ -349,7 +349,7 @@ void multiple_expiry_of_same_loan(bool cond) {
if (cond) {
p = &unsafe; // expected-warning {{does not live long enough}}
if (cond)
- break; // expected-note {{is destroyed here}}
+ break; // expected-note {{local variable 'unsafe' is destroyed here}}
}
}
(void)*p; // expected-note {{later used here}}
@@ -359,7 +359,7 @@ void multiple_expiry_of_same_loan(bool cond) {
if (cond) {
MyObj unsafe2;
p = &unsafe2; // expected-warning {{does not live long enough}}
- break; // expected-note {{is destroyed here}}
+ break; // expected-note {{local variable 'unsafe2' is destroyed here}}
}
}
(void)*p; // expected-note {{later used here}}
@@ -370,7 +370,7 @@ void multiple_expiry_of_same_loan(bool cond) {
if (cond)
p = &unsafe; // expected-warning {{does not live long enough}}
if (cond)
- break; // expected-note {{is destroyed here}}
+ break; // expected-note {{local variable 'unsafe' is destroyed here}}
}
(void)*p; // expected-note {{later used here}}
}
@@ -382,7 +382,7 @@ void switch_potential(int mode) {
case 1: {
MyObj temp;
p = &temp; // expected-warning {{local variable 'temp' does not live long enough}}
- break; // expected-note {{is destroyed here}}
+ break; // expected-note {{local variable 'temp' is destroyed here}}
}
case 2: {
p = &safe; // This path is okay.
@@ -401,17 +401,17 @@ void switch_uaf(int mode) {
case 1: {
MyObj temp1;
p = &temp1; // expected-warning {{does not live long enough}}
- break; // expected-note {{is destroyed here}}
+ break; // expected-note {{local variable 'temp1' is destroyed here}}
}
case 2: {
MyObj temp2;
p = &temp2; // expected-warning {{does not live long enough}}
- break; // expected-note {{is destroyed here}}
+ break; // expected-note {{local variable 'temp2' is destroyed here}}
}
default: {
MyObj temp2;
p = &temp2; // expected-warning {{does not live long enough}}
- break; // expected-note {{is destroyed here}}
+ break; // expected-note {{local variable 'temp2' is destroyed here}}
}
}
(void)*p; // expected-note 3 {{later used here}}
@@ -423,17 +423,17 @@ void switch_gsl(int mode) {
case 1: {
MyObj temp1;
v = temp1; // expected-warning {{local variable 'temp1' does not live long enough}}
- break; // expected-note {{is destroyed here}}
+ break; // expected-note {{local variable 'temp1' is destroyed here}}
}
case 2: {
MyObj temp2;
v = temp2; // expected-warning {{local variable 'temp2' does not live long enough}}
- break; // expected-note {{is destroyed here}}
+ break; // expected-note {{local variable 'temp2' is destroyed here}}
}
default: {
MyObj temp3;
v = temp3; // expected-warning {{local variable 'temp3' does not live long enough}}
- break; // expected-note {{is destroyed here}}
+ break; // expected-note {{local variable 'temp3' is destroyed here}}
}
}
v.use(); // expected-note 3 {{later used here}}
@@ -451,7 +451,7 @@ void loan_from_previous_iteration(MyObj safe, bool condition) {
q = p;
(void)*p;
(void)*q; // expected-note {{later used here}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'x' is destroyed here}}
}
void trivial_int_uaf() {
@@ -459,7 +459,7 @@ void trivial_int_uaf() {
{
int b = 1;
a = &b; // expected-warning {{local variable 'b' does not live long enough}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'b' is destroyed here}}
(void)*a; // expected-note {{later used here}}
}
@@ -468,7 +468,7 @@ void trivial_class_uaf() {
{
TriviallyDestructedClass s;
ptr = &s; // expected-warning {{local variable 's' does not live long enough}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 's' is destroyed here}}
(void)ptr; // expected-note {{later used here}}
}
@@ -660,7 +660,7 @@ void test_view_pointer() {
{
View v;
vp = &v; // expected-warning {{local variable 'v' does not live long enough}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'v' is destroyed here}}
vp->use(); // expected-note {{later used here}}
}
@@ -669,7 +669,7 @@ void test_view_double_pointer() {
{
View* vp = nullptr;
vpp = &vp; // expected-warning {{local variable 'vp' does not live long enough}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'vp' is destroyed here}}
(**vpp).use(); // expected-note {{later used here}}
}
@@ -698,7 +698,7 @@ void test_lifetimebound_multi_level() {
int*** ppp = &pp; // expected-warning {{local variable 'pp' does not live long enough}}
result = return_inner_ptr_addr(ppp); // expected-note {{local variable 'ppp' aliases the storage of local variable 'pp'}} \
// expected-note {{result of call to 'return_inner_ptr_addr' aliases the storage of local variable 'pp'}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'pp' is destroyed here}}
(void)**result; // expected-note {{used here}}
}
@@ -731,7 +731,7 @@ MyObj* uaf_before_uar() {
{
MyObj local_obj;
p = &local_obj; // expected-warning {{local variable 'local_obj' does not live long enough}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'local_obj' is destroyed here}}
return p; // expected-note {{later used here}}
}
@@ -822,7 +822,7 @@ void lifetimebound_simple_function() {
MyObj obj;
v = Identity(obj); // expected-warning {{local variable 'obj' does not live long enough}} \
// expected-note {{result of call to 'Identity' aliases the storage of local variable 'obj'}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'obj' is destroyed here}}
v.use(); // expected-note {{later used here}}
}
@@ -834,7 +834,7 @@ void lifetimebound_multiple_args_definite() {
// expected-note {{result of call to 'Choose' aliases the storage of local variable 'obj2'}}
obj1, // expected-warning {{local variable 'obj1' does not live long enough}}
obj2); // expected-warning {{local variable 'obj2' does not live long enough}}
- } // expected-note 2 {{is destroyed here}}
+ } // expected-note {{local variable 'obj1' is destroyed here}} expected-note {{local variable 'obj2' is destroyed here}}
v.use(); // expected-note 2 {{later used here}}
}
@@ -848,8 +848,8 @@ void lifetimebound_multiple_args_potential(bool cond) {
v = Choose(true,
obj1, // expected-warning {{local variable 'obj1' does not live long enough}}
obj2); // expected-warning {{local variable 'obj2' does not live long enough}}
- } // expected-note {{is destroyed here}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'obj2' is destroyed here}}
+ } // expected-note {{local variable 'obj1' is destroyed here}}
v.use(); // expected-note 2 {{later used here}}
}
@@ -861,7 +861,7 @@ void lifetimebound_mixed_args() {
v = SelectFirst(obj1, // expected-warning {{local variable 'obj1' does not live long enough}} \
// expected-note {{result of call to 'SelectFirst' aliases the storage of local variable 'obj1'}}
obj2);
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'obj1' is destroyed here}}
v.use(); // expected-note {{later used here}}
}
@@ -877,7 +877,7 @@ void lifetimebound_member_function() {
MyObj obj;
v = obj.getView(); // expected-warning {{local variable 'obj' does not live long enough}} \
// expected-note {{result of call to 'getView' aliases the storage of local variable 'obj'}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'obj' is destroyed here}}
v.use(); // expected-note {{later used here}}
}
@@ -892,7 +892,7 @@ void lifetimebound_conversion_operator() {
{
LifetimeBoundConversionView obj;
v = obj; // expected-warning {{local variable 'obj' does not live long enough}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'obj' is destroyed here}}
v.use(); // expected-note {{later used here}}
}
@@ -902,7 +902,7 @@ void lifetimebound_chained_calls() {
MyObj obj;
v = Identity(Identity(Identity(obj))); // expected-warning {{local variable 'obj' does not live long enough}} \
// expected-note 3 {{result of call to 'Identity' aliases the storage of local variable 'obj'}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'obj' is destroyed here}}
v.use(); // expected-note {{later used here}}
}
@@ -912,7 +912,7 @@ void lifetimebound_with_pointers() {
MyObj obj;
ptr = GetPointer(obj); // expected-warning {{local variable 'obj' does not live long enough}} \
// expected-note {{result of call to 'GetPointer' aliases the storage of local variable 'obj'}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'obj' is destroyed here}}
(void)*ptr; // expected-note {{later used here}}
}
@@ -922,7 +922,7 @@ void chained_assignment_lifetimebound_call() {
MyObj s;
p = Identity(obj = &s); // expected-warning {{does not live long enough}} \
// expected-note {{result of call to 'Identity' aliases the storage of local variable 's'}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 's' is destroyed here}}
(void)*p; // expected-note {{later used here}}
}
@@ -942,7 +942,7 @@ void lifetimebound_partial_safety(bool cond) {
v = Choose(true,
safe_obj,
temp_obj); // expected-warning {{local variable 'temp_obj' does not live long enough}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'temp_obj' is destroyed here}}
v.use(); // expected-note {{later used here}}
}
@@ -956,7 +956,7 @@ void lifetimebound_return_reference() {
const MyObj& ref = GetObject(temp_v); // expected-note {{local variable 'temp_v' aliases the storage of local variable 'obj'}} \
// expected-note {{result of call to 'GetObject' aliases the storage of local variable 'obj'}}
ptr = &ref;
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'obj' is destroyed here}}
(void)*ptr; // expected-note {{later used here}}
}
@@ -973,7 +973,7 @@ void lifetimebound_ctor() {
{
MyObj obj;
v = obj; // expected-warning {{local variable 'obj' does not live long enough}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'obj' is destroyed here}}
(void)v; // expected-note {{later used here}}
}
@@ -982,7 +982,7 @@ void lifetimebound_ctor_functional_cast() {
{
MyObj obj;
v = LifetimeBoundCtor(obj); // expected-warning {{local variable 'obj' does not live long enough}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'obj' is destroyed here}}
(void)v; // expected-note {{later used here}}
}
@@ -991,7 +991,7 @@ void lifetimebound_ctor_c_style_cast() {
{
MyObj obj;
v = (LifetimeBoundCtor)(obj); // expected-warning {{local variable 'obj' does not live long enough}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'obj' is destroyed here}}
(void)v; // expected-note {{later used here}}
}
@@ -1000,7 +1000,7 @@ void lifetimebound_ctor_static_cast() {
{
MyObj obj;
v = static_cast<LifetimeBoundCtor>(obj); // expected-warning {{local variable 'obj' does not live long enough}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'obj' is destroyed here}}
(void)v; // expected-note {{later used here}}
}
@@ -1010,7 +1010,7 @@ void lifetimebound_make_unique() {
MyObj obj;
ptr = std::make_unique<LifetimeBoundCtor>(obj); // tu-warning {{local variable 'obj' does not live long enough}} \
// tu-note {{result of call to 'make_unique<LifetimeBoundCtor, MyObj &>' aliases the storage of local variable 'obj'}}
- } // tu-note {{is destroyed here}}
+ } // tu-note {{local variable 'obj' is destroyed here}}
(void)ptr; // tu-note {{later used here}}
}
@@ -1026,7 +1026,7 @@ void non_lifetimebound_make_unique() {
void lifetimebound_make_unique_temp() {
std::unique_ptr<LifetimeBoundCtor> ptr = std::make_unique<LifetimeBoundCtor>(MyObj()); // tu-warning {{temporary object does not live long enough}} \
- // tu-note {{is destroyed here}} \
+ // tu-note {{temporary object is destroyed here}} \
// tu-note {{result of call to 'make_unique<LifetimeBoundCtor, MyObj>' aliases the storage of temporary object}}
(void)ptr; // tu-note {{later used here}}
}
@@ -1066,7 +1066,7 @@ void lifetimebound_make_unique_multi_params() {
MyObj obj_short;
ptr = std::make_unique<MultiLifetimeBoundCtor>(obj_short, obj_long); // tu-warning {{local variable 'obj_short' does not live long enough}} \
// tu-note {{result of call to 'make_unique<MultiLifetimeBoundCtor, MyObj &, MyObj &>' aliases the storage of local variable 'obj_short'}}
- } // tu-note {{is destroyed here}}
+ } // tu-note {{local variable 'obj_short' is destroyed here}}
(void)ptr; // tu-note {{later used here}}
}
@@ -1077,7 +1077,7 @@ void lifetimebound_make_unique_multi_params2() {
MyObj obj_short;
ptr = std::make_unique<MultiLifetimeBoundCtor>(obj_long, obj_short, 1); // tu-warning {{local variable 'obj_short' does not live long enough}} \
// tu-note {{result of call to 'make_unique<MultiLifetimeBoundCtor, MyObj &, MyObj &, int>' aliases the storage of local variable 'obj_short'}}
- } // tu-note {{is destroyed here}}
+ } // tu-note {{local variable 'obj_short' is destroyed here}}
(void)ptr; // tu-note {{later used here}}
}
@@ -1098,7 +1098,7 @@ void lifetimebound_make_unique_multi_params3_1() {
MyObj obj_short;
ptr = std::make_unique<MultiLifetimeBoundCtor>(obj_short, obj_long, 1.0); // tu-warning {{local variable 'obj_short' does not live long enough}} \
// tu-note {{result of call to 'make_unique<MultiLifetimeBoundCtor, MyObj &, MyObj &, double>' aliases the storage of local variable 'obj_short'}}
- } // tu-note {{is destroyed here}}
+ } // tu-note {{local variable 'obj_short' is destroyed here}}
(void)ptr; // tu-note {{later used here}}
}
@@ -1109,7 +1109,7 @@ void lifetimebound_make_unique_multi_params3_2() {
MyObj obj_short;
ptr = std::make_unique<MultiLifetimeBoundCtor>(obj_long, obj_short, 1.0); // tu-warning {{local variable 'obj_short' does not live long enough}} \
// tu-note {{result of call to 'make_unique<MultiLifetimeBoundCtor, MyObj &, MyObj &, double>' aliases the storage of local variable 'obj_short'}}
- } // tu-note {{is destroyed here}}
+ } // tu-note {{local variable 'obj_short' is destroyed here}}
(void)ptr; // tu-note {{later used here}}
}
@@ -1186,7 +1186,7 @@ void conditional_operator_one_unsafe_branch(bool cond) {
MyObj temp;
p = cond ? &temp // expected-warning {{local variable 'temp' does not live long enough}}
: &safe;
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'temp' is destroyed here}}
// This is not a use-after-free for any value of `cond` but the analysis
// cannot reason this and marks the above as a false positive. This
@@ -1202,7 +1202,7 @@ void conditional_operator_two_unsafe_branches(bool cond) {
MyObj a, b;
p = cond ? &a // expected-warning {{local variable 'a' does not live long enough}}
: &b; // expected-warning {{local variable 'b' does not live long enough}}
- } // expected-note 2 {{is destroyed here}}
+ } // expected-note {{local variable 'b' is destroyed here}} expected-note {{local variable 'a' is destroyed here}}
(void)*p; // expected-note 2 {{later used here}}
}
@@ -1214,7 +1214,7 @@ void conditional_operator_nested(bool cond) {
: &b // expected-warning {{local variable 'b' does not live long enough}}.
: cond ? &c // expected-warning {{local variable 'c' does not live long enough}}.
: &d; // expected-warning {{local variable 'd' does not live long enough}}.
- } // expected-note 4 {{is destroyed here}}
+ } // expected-note {{local variable 'a' is destroyed here}} expected-note {{local variable 'd' is destroyed here}} expected-note {{local variable 'b' is destroyed here}} expected-note {{local variable 'c' is destroyed here}}
(void)*p; // expected-note 4 {{later used here}}
}
@@ -1224,7 +1224,7 @@ void conditional_operator_lifetimebound(bool cond) {
MyObj a, b;
p = Identity(cond ? &a // expected-warning {{local variable 'a' does not live long enough}}
: &b); // expected-warning {{local variable 'b' does not live long enough}}
- } // expected-note 2 {{is destroyed here}}
+ } // expected-note {{local variable 'b' is destroyed here}} expected-note {{local variable 'a' is destroyed here}}
(void)*p; // expected-note 2 {{later used here}}
}
@@ -1234,7 +1234,7 @@ void conditional_operator_lifetimebound_nested(bool cond) {
MyObj a, b;
p = Identity(cond ? Identity(&a) // expected-warning {{local variable 'a' does not live long enough}}
: Identity(&b)); // expected-warning {{local variable 'b' does not live long enough}}
- } // expected-note 2 {{is destroyed here}}
+ } // expected-note {{local variable 'b' is destroyed here}} expected-note {{local variable 'a' is destroyed here}}
(void)*p; // expected-note 2 {{later used here}}
}
@@ -1246,7 +1246,7 @@ void conditional_operator_lifetimebound_nested_deep(bool cond) {
: &b) // expected-warning {{local variable 'b' does not live long enough}}
: Identity(cond ? &c // expected-warning {{local variable 'c' does not live long enough}}
: &d)); // expected-warning {{local variable 'd' does not live long enough}}
- } // expected-note 4 {{is destroyed here}}
+ } // expected-note {{local variable 'a' is destroyed here}} expected-note {{local variable 'd' is destroyed here}} expected-note {{local variable 'b' is destroyed here}} expected-note {{local variable 'c' is destroyed here}}
(void)*p; // expected-note 4 {{later used here}}
}
@@ -1257,7 +1257,7 @@ void comma_use_after_scope() {
{
MyObj temp;
p = (side(), &temp); // expected-warning {{local variable 'temp' does not live long enough}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'temp' is destroyed here}}
(void)*p; // expected-note {{later used here}}
}
@@ -1266,7 +1266,7 @@ void comma_nested() {
{
MyObj temp;
p = (side(), (side(), &temp)); // expected-warning {{local variable 'temp' does not live long enough}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'temp' is destroyed here}}
(void)*p; // expected-note {{later used here}}
}
@@ -1277,7 +1277,7 @@ void comma_masked_by_conditional(bool cond) {
{
MyObj temp;
p = cond ? keep : (side(), &temp); // expected-warning {{local variable 'temp' does not live long enough}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'temp' is destroyed here}}
(void)*p; // expected-note {{later used here}}
}
@@ -1293,7 +1293,7 @@ void binary_conditional_false_unsafe(MyObj* in) {
{
MyObj temp;
p = in ?: &temp; // expected-warning {{local variable 'temp' does not live long enough}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'temp' is destroyed here}}
(void)*p; // expected-note {{later used here}}
}
@@ -1303,7 +1303,7 @@ void binary_conditional_common_unsafe(MyObj* fallback) {
MyObj temp;
MyObj* t = &temp; // expected-warning {{local variable 'temp' does not live long enough}}
p = t ?: fallback;
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'temp' is destroyed here}}
(void)*p; // expected-note {{later used here}}
}
@@ -1318,7 +1318,7 @@ void binary_conditional_nested(MyObj* a, MyObj* b) {
{
MyObj temp;
p = a ?: b ?: &temp; // expected-warning {{local variable 'temp' does not live long enough}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'temp' is destroyed here}}
(void)*p; // expected-note {{later used here}}
}
@@ -1329,7 +1329,7 @@ void binary_conditional_masked_by_conditional(bool cond, MyObj* in) {
{
MyObj temp;
p = cond ? keep : (in ?: &temp); // expected-warning {{local variable 'temp' does not live long enough}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'temp' is destroyed here}}
(void)*p; // expected-note {{later used here}}
}
@@ -1377,7 +1377,7 @@ void simpleparen() {
MyObj a;
MyObj* b = &a; // expected-warning {{local variable 'a' does not live long enough}}
p = (((b)));
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'a' is destroyed here}}
(void)*p; // expected-note {{later used here}}
}
@@ -1386,14 +1386,14 @@ void parentheses(bool cond) {
{
MyObj a;
p = &((((a)))); // expected-warning {{local variable 'a' does not live long enough}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'a' is destroyed here}}
(void)*p; // expected-note {{later used here}}
{
MyObj a;
p = ((GetPointer((a)))); // expected-warning {{local variable 'a' does not live long enough}} \
// expected-note {{result of call to 'GetPointer' aliases the storage of local variable 'a'}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'a' is destroyed here}}
(void)*p; // expected-note {{later used here}}
{
@@ -1402,14 +1402,14 @@ void parentheses(bool cond) {
: b) // expected-warning {{local variable 'b' does not live long enough}}.
: (cond ? c // expected-warning {{local variable 'c' does not live long enough}}.
: d)); // expected-warning {{local variable 'd' does not live long enough}}.
- } // expected-note 4 {{is destroyed here}}
+ } // expected-note {{local variable 'b' is destroyed here}} expected-note {{local variable 'c' is destroyed here}} expected-note {{local variable 'a' is destroyed here}} expected-note {{local variable 'd' is destroyed here}}
(void)*p; // expected-note 4 {{later used here}}
{
MyObj a, b, c, d;
p = ((cond ? (((cond ? &a : &b))) // expected-warning {{local variable 'b' does not live long enough}} expected-warning {{local variable 'a' does not live long enough}}.
: &(((cond ? c : d))))); // expected-warning {{local variable 'd' does not live long enough}} expected-warning {{local variable 'c' does not live long enough}}.
- } // expected-note 4 {{is destroyed here}}
+ } // expected-note {{local variable 'd' is destroyed here}} expected-note {{local variable 'b' is destroyed here}} expected-note {{local variable 'c' is destroyed here}} expected-note {{local variable 'a' is destroyed here}}
(void)*p; // expected-note 4 {{later used here}}
}
@@ -1417,13 +1417,13 @@ void parentheses(bool cond) {
void use_temporary_after_destruction() {
View a;
a = non_trivially_destructed_temporary(); // expected-warning {{temporary object does not live long enough}} \
- expected-note {{is destroyed here}}
+ expected-note {{temporary object is destroyed here}}
use(a); // expected-note {{later used here}}
}
void passing_temporary_to_lifetime_bound_function() {
View a = construct_view(non_trivially_destructed_temporary()); // expected-warning {{temporary object does not live long enough}} \
- expected-note {{is destroyed here}} \
+ expected-note {{temporary object is destroyed here}} \
expected-note {{result of call to 'construct_view' aliases the storage of temporary object}}
use(a); // expected-note {{later used here}}
}
@@ -1431,7 +1431,7 @@ void passing_temporary_to_lifetime_bound_function() {
void use_trivial_temporary_after_destruction() {
View a;
a = trivially_destructed_temporary(); // expected-warning {{temporary object does not live long enough}} \
- expected-note {{is destroyed here}}
+ expected-note {{temporary object is destroyed here}}
use(a); // expected-note {{later used here}}
}
@@ -1439,7 +1439,7 @@ namespace FullExprCleanupLoc {
void var_initializer() {
View v = non_trivially_destructed_temporary() // expected-warning {{temporary object does not live long enough}} \
// expected-note {{result of call to 'getView' aliases the storage of temporary object}}
- .getView(); // expected-note {{is destroyed here}}
+ .getView(); // expected-note {{temporary object is destroyed here}}
v.use(); // expected-note {{later used here}}
}
@@ -1447,7 +1447,7 @@ void expr_statement() {
View v;
v = non_trivially_destructed_temporary() // expected-warning {{temporary object does not live long enough}} \
// expected-note {{result of call to 'getView' aliases the storage of temporary object}}
- .getView(); // expected-note {{is destroyed here}}
+ .getView(); // expected-note {{temporary object is destroyed here}}
v.use(); // expected-note {{later used here}}
}
} // namespace FullExprCleanupLoc
@@ -1492,7 +1492,7 @@ void foobar() {
view = string_or. // expected-warning {{local variable 'string_or' does not live long enough}} \
// expected-note {{result of call to 'value' aliases the storage of local variable 'string_or'}}
value();
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'string_or' is destroyed here}}
(void)view; // expected-note {{later used here}}
}
} // namespace GH162834
@@ -1513,7 +1513,7 @@ void range_based_for_use_after_scope() {
for (const MyObj &o : s) { // expected-warning {{local variable 's' does not live long enough}}
v = o;
}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 's' is destroyed here}}
v.use(); // expected-note {{later used here}}
}
@@ -1530,7 +1530,7 @@ void range_based_for_not_reference() {
View v;
{
MyObjStorage s;
- for (MyObj o : s) { // expected-note {{is destroyed here}}
+ for (MyObj o : s) { // expected-note {{local variable 'o' is destroyed here}}
v = o; // expected-warning {{local variable 'o' does not live long enough}}
}
}
@@ -1566,7 +1566,7 @@ void test_user_defined_deref_uaf() {
SmartPtr<MyObj> smart_ptr(&obj);
p = &(*smart_ptr); // expected-warning {{local variable 'smart_ptr' does not live long enough}} \
// expected-note {{expression aliases the storage of local variable 'smart_ptr'}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'smart_ptr' is destroyed here}}
(void)*p; // expected-note {{later used here}}
}
@@ -1584,7 +1584,7 @@ void test_user_defined_deref_with_view() {
SmartPtr<MyObj> smart_ptr(&obj);
v = *smart_ptr; // expected-warning {{local variable 'smart_ptr' does not live long enough}} \
// expected-note {{expression aliases the storage of local variable 'smart_ptr'}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'smart_ptr' is destroyed here}}
v.use(); // expected-note {{later used here}}
}
@@ -1595,7 +1595,7 @@ void test_user_defined_deref_arrow() {
SmartPtr<MyObj> smart_ptr(&obj);
p = smart_ptr.operator->(); // expected-warning {{local variable 'smart_ptr' does not live long enough}} \
// expected-note {{expression aliases the storage of local variable 'smart_ptr'}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'smart_ptr' is destroyed here}}
(void)*p; // expected-note {{later used here}}
}
@@ -1606,7 +1606,7 @@ void test_user_defined_deref_chained() {
SmartPtr<SmartPtr<MyObj>> double_ptr;
p = &(**double_ptr); // expected-warning {{local variable 'double_ptr' does not live long enough}} \
// expected-note 2 {{expression aliases the storage of local variable 'double_ptr'}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'double_ptr' is destroyed here}}
(void)*p; // expected-note {{later used here}}
}
@@ -1758,7 +1758,7 @@ void strict_warn_on_move() {
MyObj a;
v = a; // expected-warning {{local variable 'a' may not live long enough. This could be a false positive as the storage may have been moved later}}
b = std::move(a); // expected-note {{potentially moved here}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'a' is destroyed here}}
(void)v; // expected-note {{later used here}}
}
@@ -1771,7 +1771,7 @@ void flow_sensitive(bool c) {
return;
}
v = a; // expected-warning {{local variable 'a' does not live long enough}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'a' is destroyed here}}
(void)v; // expected-note {{later used here}}
}
@@ -1783,7 +1783,7 @@ void detect_conditional(bool cond) {
v = cond ? a : b; // expected-warning {{local variable 'a' may not live long enough. This could be a false positive as the storage may have been moved later}} \
// expected-warning {{local variable 'b' may not live long enough. This could be a false positive as the storage may have been moved later}}
take(std::move(cond ? a : b)); // expected-note 2 {{potentially moved here}}
- } // expected-note 2 {{is destroyed here}}
+ } // expected-note {{local variable 'b' is destroyed here}} expected-note {{local variable 'a' is destroyed here}}
(void)v; // expected-note 2 {{later used here}}
}
@@ -1793,7 +1793,7 @@ void wrong_use_of_move_is_permissive() {
MyObj a;
v = std::move(a); // expected-warning {{local variable 'a' does not live long enough}} \
// expected-note {{result of call to 'move<MyObj &>' aliases the storage of local variable 'a'}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'a' is destroyed here}}
(void)v; // expected-note {{later used here}}
const int* p;
{
@@ -1801,7 +1801,7 @@ void wrong_use_of_move_is_permissive() {
p = std::move(a).getData(); // expected-warning {{local variable 'a' does not live long enough}} \
// expected-note {{result of call to 'move<MyObj &>' aliases the storage of local variable 'a'}} \
// expected-note {{result of call to 'getData' aliases the storage of local variable 'a'}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'a' is destroyed here}}
(void)p; // expected-note {{later used here}}
}
@@ -1814,7 +1814,7 @@ void test_release_no_uaf() {
r = p.get(); // expected-warning {{local variable 'p' may not live long enough. This could be a false positive as the storage may have been moved later}} \
// expected-note {{result of call to 'get' aliases the storage of local variable 'p'}}
take(p.release()); // expected-note {{potentially moved here}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'p' is destroyed here}}
(void)*r; // expected-note {{later used here}}
}
} // namespace strict_warn_on_move
@@ -1837,10 +1837,10 @@ void bar() {
x = s.x(); // expected-warning {{local variable 's' does not live long enough}} \
// expected-note {{result of call to 'x' aliases the storage of local variable 's'}}
View y = S().x(); // expected-warning {{temporary object does not live long enough}} \
- expected-note {{is destroyed here}} \
+ expected-note {{temporary object is destroyed here}} \
expected-note {{result of call to 'x' aliases the storage of temporary object}}
(void)y; // expected-note {{used here}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 's' is destroyed here}}
(void)x; // expected-note {{used here}}
}
}
@@ -1930,7 +1930,7 @@ void test_temporary() {
// expected-note {{result of call to 'x' aliases the storage of temporary object}}
(void)x; // expected-note {{later used here}}
- const std::string& y = identity(S().x()); // expected-warning {{temporary object does not live long enough}} expected-note {{is destroyed here}} \
+ const std::string& y = identity(S().x()); // expected-warning {{temporary object does not live long enough}} expected-note {{temporary object is destroyed here}} \
// expected-note {{result of call to 'x' aliases the storage of temporary object}} \
// expected-note {{result of call to 'identity' aliases the storage of temporary object}}
(void)y; // expected-note {{later used here}}
@@ -1941,20 +1941,20 @@ void test_temporary() {
const std::string& zz = s.x(); // expected-warning {{local variable 's' does not live long enough}} \
// expected-note {{result of call to 'x' aliases the storage of local variable 's'}}
z = zz; // expected-note {{expression aliases the storage of local variable 's'}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 's' is destroyed here}}
(void)z; // expected-note {{later used here}}
}
void test_lifetime_extension_ok() {
const S& x = S();
(void)x;
- const S& y = identity(S()); // expected-warning {{temporary object does not live long enough}} expected-note {{is destroyed here}} \
+ const S& y = identity(S()); // expected-warning {{temporary object does not live long enough}} expected-note {{temporary object is destroyed here}} \
// expected-note {{result of call to 'identity' aliases the storage of temporary object}}
(void)y; // expected-note {{later used here}}
}
const std::string& test_return() {
- const std::string& x = S().x(); // expected-warning {{temporary object does not live long enough}} expected-note {{is destroyed here}} \
+ const std::string& x = S().x(); // expected-warning {{temporary object does not live long enough}} expected-note {{temporary object is destroyed here}} \
// expected-note {{result of call to 'x' aliases the storage of temporary object}}
return x; // expected-note {{later used here}}
}
@@ -1974,7 +1974,7 @@ void uaf() {
S* p = &str; // expected-warning {{local variable 'str' does not live long enough}}
view = p->s; // expected-note {{local variable 'p' aliases the storage of local variable 'str'}} \
// expected-note {{expression aliases the storage of local variable 'str'}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'str' is destroyed here}}
(void)view; // expected-note {{later used here}}
}
@@ -2001,7 +2001,7 @@ void uaf_union() {
U* up = &u; // expected-warning {{local variable 'u' does not live long enough}}
view = up->s; // expected-note {{local variable 'up' aliases the storage of local variable 'u'}} \
// expected-note {{expression aliases the storage of local variable 'u'}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'u' is destroyed here}}
(void)view; // expected-note {{later used here}}
}
@@ -2018,7 +2018,7 @@ void uaf_anonymous_union() {
AnonymousUnion au;
AnonymousUnion* up = &au; // expected-warning {{local variable 'au' does not live long enough}}
ip = &up->x; // expected-note {{local variable 'up' aliases the storage of local variable 'au'}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'au' is destroyed here}}
(void)ip; // expected-note {{later used here}}
}
@@ -2075,11 +2075,11 @@ const T* MemberFuncsTpl<T>::memberC(const T& x [[clang::lifetimebound]]) {
void test() {
MemberFuncsTpl<MyObj> mtf;
- const MyObj* pTMA = mtf.memberA(MyObj()); // expected-warning {{temporary object does not live long enough}} // expected-note {{is destroyed here}} \
+ const MyObj* pTMA = mtf.memberA(MyObj()); // expected-warning {{temporary object does not live long enough}} // expected-note {{temporary object is destroyed here}} \
// expected-note {{result of call to 'memberA' aliases the storage of temporary object}}
- const MyObj* pTMB = mtf.memberB(MyObj()); // tu-warning {{temporary object does not live long enough}} // tu-note {{is destroyed here}} \
+ const MyObj* pTMB = mtf.memberB(MyObj()); // tu-warning {{temporary object does not live long enough}} // tu-note {{temporary object is destroyed here}} \
// tu-note {{result of call to 'memberB' aliases the storage of temporary object}}
- const MyObj* pTMC = mtf.memberC(MyObj()); // expected-warning {{temporary object does not live long enough}} // expected-note {{is destroyed here}} \
+ const MyObj* pTMC = mtf.memberC(MyObj()); // expected-warning {{temporary object does not live long enough}} // expected-note {{temporary object is destroyed here}} \
// expected-note {{result of call to 'memberC' aliases the storage of temporary object}}
(void)pTMA; // expected-note {{later used here}}
(void)pTMB; // tu-note {{later used here}}
@@ -2118,7 +2118,7 @@ void test_optional_arrow() {
p = opt->data(); // expected-warning {{local variable 'opt' does not live long enough}} \
// expected-note {{expression aliases the storage of local variable 'opt'}} \
// expected-note {{result of call to 'data' aliases the storage of local variable 'opt'}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'opt' is destroyed here}}
(void)*p; // expected-note {{later used here}}
}
@@ -2129,7 +2129,7 @@ void test_optional_arrow_lifetimebound() {
v = opt->getView(); // expected-warning {{local variable 'opt' does not live long enough}} \
// expected-note {{expression aliases the storage of local variable 'opt'}} \
// expected-note {{result of call to 'getView' aliases the storage of local variable 'opt'}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'opt' is destroyed here}}
v.use(); // expected-note {{later used here}}
}
@@ -2140,7 +2140,7 @@ void test_unique_ptr_arrow() {
p = up->data(); // expected-warning {{local variable 'up' does not live long enough}} \
// expected-note {{expression aliases the storage of local variable 'up'}} \
// expected-note {{result of call to 'data' aliases the storage of local variable 'up'}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'up' is destroyed here}}
(void)*p; // expected-note {{later used here}}
}
@@ -2334,7 +2334,7 @@ void multi_level_pointer_in_loop() {
pp = &p;
}
(void)**pp; // expected-note {{later used here}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'obj' is destroyed here}}
}
void outer_pointer_outlives_inner_pointee() {
@@ -2343,7 +2343,7 @@ void outer_pointer_outlives_inner_pointee() {
for (int i = 0; i < 10; ++i) {
MyObj obj;
view = &obj; // expected-warning {{local variable 'obj' does not live long enough}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'obj' is destroyed here}}
(void)*view; // expected-note {{later used here}}
}
@@ -2356,7 +2356,7 @@ void element_use_after_scope() {
{
int a[10]{};
p = &a[2]; // expected-warning {{local variable 'a' does not live long enough}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'a' is destroyed here}}
(void)*p; // expected-note {{later used here}}
}
@@ -2388,7 +2388,7 @@ void multidimensional_use_after_scope() {
{
int a[3][4]{};
p = &a[1][2]; // expected-warning {{local variable 'a' does not live long enough}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'a' is destroyed here}}
(void)*p; // expected-note {{later used here}}
}
@@ -2401,7 +2401,7 @@ void member_array_element_use_after_scope() {
{
S s;
p = &s.arr[0]; // expected-warning {{local variable 's' does not live long enough}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 's' is destroyed here}}
(void)*p; // expected-note {{later used here}}
}
@@ -2410,7 +2410,7 @@ void array_of_pointers_use_after_scope() {
{
int* a[10]{};
p = a; // expected-warning {{local variable 'a' does not live long enough}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'a' is destroyed here}}
(void)*p; // expected-note {{later used here}}
}
@@ -2419,7 +2419,7 @@ void reversed_subscript_use_after_scope() {
{
int a[10]{};
p = &(0[a]); // expected-warning {{local variable 'a' does not live long enough}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'a' is destroyed here}}
(void)*p; // expected-note {{later used here}}
}
@@ -2447,7 +2447,7 @@ void pointer_arithmetic_use_after_scope() {
p = a + 5; // expected-warning {{local variable 'a' does not live long enough}}
p2 = a - 5; // expected-warning {{local variable 'a' does not live long enough}}
p3 = 5 + a; // expected-warning {{local variable 'a' does not live long enough}}
- } // expected-note 3 {{is destroyed here}}
+ } // expected-note 3 {{local variable 'a' is destroyed here}}
(void)*p; // expected-note {{later used here}}
(void)*p2; // expected-note {{later used here}}
(void)*p3; // expected-note {{later used here}}
@@ -2493,7 +2493,7 @@ void indexing_with_static_operator() {
S()(1, 2);
S& x = S()("1", // expected-note 2 {{expression aliases the storage of temporary object}}
2, // expected-warning {{temporary object does not live long enough}}
- 3); // expected-warning {{temporary object does not live long enough}} expected-note 2 {{is destroyed here}}
+ 3); // expected-warning {{temporary object does not live long enough}} expected-note 2 {{temporary object is destroyed here}}
(void)x; // expected-note 2 {{later used here}}
@@ -2516,14 +2516,14 @@ S getS(const std::string &s [[clang::lifetimebound]]);
void from_free_function() {
S s = getS(std::string("temp")); // expected-warning {{temporary object does not live long enough}} \
- // expected-note {{is destroyed here}} \
+ // expected-note {{temporary object is destroyed here}} \
// expected-note {{result of call to 'getS' aliases the storage of temporary object}}
use(s); // expected-note {{later used here}}
}
void from_constructor() {
S s(std::string("temp")); // expected-warning {{temporary object does not live long enough}} \
- // expected-note {{is destroyed here}}
+ // expected-note {{temporary object is destroyed here}}
use(s); // expected-note {{later used here}}
}
@@ -2536,14 +2536,14 @@ struct Factory {
void from_method() {
Factory f;
S s = f.make(std::string("temp")); // expected-warning {{temporary object does not live long enough}} \
- // expected-note {{is destroyed here}} \
+ // expected-note {{temporary object is destroyed here}} \
// expected-note {{result of call to 'make' aliases the storage of temporary object}}
use(s); // expected-note {{later used here}}
}
void from_static_method() {
S s = Factory::create(std::string("temp")); // expected-warning {{temporary object does not live long enough}} \
- // expected-note {{is destroyed here}} \
+ // expected-note {{temporary object is destroyed here}} \
// expected-note {{result of call to 'create' aliases the storage of temporary object}}
use(s); // expected-note {{later used here}}
}
@@ -2554,7 +2554,7 @@ void from_lifetimebound_this_method() {
Factory f;
value = f.makeThis(); // expected-warning {{local variable 'f' does not live long enough}} \
// expected-note {{result of call to 'makeThis' aliases the storage of local variable 'f'}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'f' is destroyed here}}
use(value); // expected-note {{later used here}}
}
@@ -2564,7 +2564,7 @@ void across_scope() {
std::string str{"abc"};
s = getS(str); // expected-warning {{local variable 'str' does not live long enough}} \
// expected-note {{result of call to 'getS' aliases the storage of local variable 'str'}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'str' is destroyed here}}
use(s); // expected-note {{later used here}}
}
@@ -2588,7 +2588,7 @@ void assignment_propagation() {
a = getS(str); // expected-warning {{local variable 'str' does not live long enough}} \
// expected-note {{result of call to 'getS' aliases the storage of local variable 'str'}}
b = a; // expected-note {{local variable 'a' aliases the storage of local variable 'str'}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'str' is destroyed here}}
use(b); // expected-note {{later used here}}
}
@@ -2600,7 +2600,7 @@ void chained_defaulted_assignment_propagation() {
// expected-note {{result of call to 'getS' aliases the storage of local variable 'str'}}
c = b = a; // expected-note {{local variable 'a' aliases the storage of local variable 'str'}}\
// expected-note {{expression aliases the storage of local variable 'str'}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'str' is destroyed here}}
use(c); // expected-note {{later used here}}
}
@@ -2613,7 +2613,7 @@ void no_annotation() {
void mix_annotated_and_not() {
S s1 = getS(std::string("temp")); // expected-warning {{temporary object does not live long enough}} \
- // expected-note {{is destroyed here}} \
+ // expected-note {{temporary object is destroyed here}} \
// expected-note {{result of call to 'getS' aliases the storage of temporary object}}
S s2 = getSNoAnnotation(std::string("temp"));
use(s1); // expected-note {{later used here}}
@@ -2627,7 +2627,7 @@ S multiple_lifetimebound_params() {
S s = getS2(str, std::string("temp")); // expected-warning {{stack memory associated with local variable 'str' is returned}} \
// expected-warning {{temporary object does not live long enough}} \
// expected-note {{result of call to 'getS2' aliases the storage of temporary object}} \
- // expected-note {{is destroyed here}}
+ // expected-note {{temporary object is destroyed here}}
return s; // expected-note {{returned here}} \
// expected-note {{later used here}}
}
@@ -2646,7 +2646,7 @@ T make(const std::string &s [[clang::lifetimebound]]);
void from_template_instantiation() {
S s = make<S>(std::string("temp")); // expected-warning {{temporary object does not live long enough}} \
- // expected-note {{is destroyed here}} \
+ // expected-note {{temporary object is destroyed here}} \
// expected-note {{result of call to 'make<track_origins_for_lifetimebound_record_type::S>' aliases the storage of temporary object}}
use(s); // expected-note {{later used here}}
}
@@ -2710,7 +2710,7 @@ SAlias getSAlias(const std::string &s [[clang::lifetimebound]]);
void from_typedef_return() {
SAlias s = getSAlias(std::string("temp")); // expected-warning {{temporary object does not live long enough}} \
- // expected-note {{is destroyed here}} \
+ // expected-note {{temporary object is destroyed here}} \
// expected-note {{result of call to 'getSAlias' aliases the storage of temporary object}}
use(s); // expected-note {{later used here}}
}
@@ -2785,7 +2785,7 @@ std::unique_ptr<S> getUniqueS(const std::string &s [[clang::lifetimebound]]);
void owner_return_unique_ptr_s() {
auto ptr = getUniqueS(std::string("temp")); // expected-warning {{temporary object does not live long enough}} \
- // expected-note {{is destroyed here}} \
+ // expected-note {{temporary object is destroyed here}} \
// expected-note {{result of call to 'getUniqueS' aliases the storage of temporary object}}
(void)ptr; // expected-note {{later used here}}
}
@@ -2804,7 +2804,7 @@ void owner_outlives_lifetimebound_source() {
std::string local;
ups = getUniqueS(local); // expected-warning {{local variable 'local' does not live long enough}} \
// expected-note {{result of call to 'getUniqueS' aliases the storage of local variable 'local'}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'local' is destroyed here}}
(void)ups; // expected-note {{later used here}}
}
@@ -2827,7 +2827,7 @@ void local_pointer() {
{
int v;
p = Pointer(v); // expected-warning {{local variable 'v' does not live long enough}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'v' is destroyed here}}
use(*p); // expected-note {{later used here}}
}
@@ -2840,7 +2840,7 @@ void nested_local_pointer() {
p = Pointer(v); // expected-warning {{local variable 'v' does not live long enough}}
pp = Pointer(p); // expected-note {{local variable 'p' aliases the storage of local variable 'v'}}
ppp = Pointer(pp); // expected-note {{local variable 'pp' aliases the storage of local variable 'v'}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'v' is destroyed here}}
use(***ppp); // expected-note {{later used here}}
}
@@ -2937,7 +2937,7 @@ void new_view_from_dead_scope() {
{
MyObj obj;
p = new View(obj); // expected-warning {{local variable 'obj' does not live long enough}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'obj' is destroyed here}}
p->use(); // expected-note {{later used here}}
}
@@ -3001,7 +3001,7 @@ void new_pointer_from_pointer() {
MyObj obj;
MyObj *q = &obj; // expected-warning {{local variable 'obj' does not live long enough}}
p = new MyObj *(q); // expected-note {{local variable 'q' aliases the storage of local variable 'obj'}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'obj' is destroyed here}}
(void)**p; // expected-note {{later used here}}
}
@@ -3010,7 +3010,7 @@ void new_pointer_from_dead_object() {
{
MyObj obj;
p = new MyObj *(&obj); // expected-warning {{local variable 'obj' does not live long enough}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'obj' is destroyed here}}
(void)**p; // expected-note {{later used here}}
}
@@ -3024,7 +3024,7 @@ void new_multiview_from_mixed_scope() {
{
MyObj obj2;
p = new MultiView(obj1, obj2); // expected-warning {{local variable 'obj2' does not live long enough}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'obj2' is destroyed here}}
(void)p; // expected-note {{later used here}}
}
@@ -3187,7 +3187,7 @@ void placement_new_int_basic() {
{
int storage;
p = new (&storage) int; // expected-warning {{local variable 'storage' does not live long enough}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'storage' is destroyed here}}
(void)*p; // expected-note {{later used here}}
}
@@ -3197,7 +3197,7 @@ void placement_new_view_from_dead_scope() {
{
MyObj obj;
p = new (&storage) View(obj); // expected-warning {{local variable 'obj' does not live long enough}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'obj' is destroyed here}}
p->use(); // expected-note {{later used here}}
}
@@ -3207,7 +3207,7 @@ void placement_new_pointer_from_dead_object() {
{
MyObj obj;
p = new (&slot) MyObj *(&obj); // expected-warning {{local variable 'obj' does not live long enough}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'obj' is destroyed here}}
(void)**p; // expected-note {{later used here}}
}
@@ -3216,7 +3216,7 @@ void placement_new_array_basic() {
{
int storage[2];
p = new (&storage) int[2]; // expected-warning {{local variable 'storage' does not live long enough}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'storage' is destroyed here}}
(void)p[0]; // expected-note {{later used here}}
}
@@ -3225,7 +3225,7 @@ void placement_new_array_braces() {
{
int storage[2];
p = new (&storage) int[2]{}; // expected-warning {{local variable 'storage' does not live long enough}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'storage' is destroyed here}}
(void)p[0]; // expected-note {{later used here}}
}
@@ -3431,7 +3431,7 @@ struct S {
{
int num;
this->p_ = # // expected-warning {{local variable 'num' does not live long enough}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'num' is destroyed here}}
bar(); // expected-note {{later used here}}
this->p_ = &GLOBAL_INT;
}
@@ -3449,7 +3449,7 @@ struct T {
std::string_view v;
void bar();
void foo() {
- v = std::string("tmp"); // expected-warning {{temporary object does not live long enough}} expected-note {{is destroyed here}}
+ v = std::string("tmp"); // expected-warning {{temporary object does not live long enough}} expected-note {{temporary object is destroyed here}}
bar(); // expected-note {{later used here}}
}
};
@@ -3471,7 +3471,7 @@ struct S2 : S {
{
int num;
this->p_ = # // expected-warning {{local variable 'num' does not live long enough}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'num' is destroyed here}}
bar(); // expected-note {{later used here}}
this->p_ = &GLOBAL_INT;
}
@@ -3479,7 +3479,7 @@ struct S2 : S {
{
int num;
this->p_ = # // expected-warning {{local variable 'num' does not live long enough}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'num' is destroyed here}}
bar2(); // expected-note {{later used here}}
this->p_ = nullptr;
}
@@ -3597,7 +3597,7 @@ void uaf_via_lifetimebound() {
int local;
f = capture_lifetimebound_param(local); // expected-warning {{local variable 'local' does not live long enough}} \
// expected-note {{result of call to 'capture_lifetimebound_param' aliases the storage of local variable 'local'}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'local' is destroyed here}}
(void)f; // expected-note {{later used here}}
}
@@ -3616,7 +3616,7 @@ struct [[gsl::Pointer]] function_ref {
// avoid this warning for non-capturing lambdas.
void assign_non_capturing_to_function_ref(function_ref &r) {
r = []() {}; // expected-warning {{temporary object does not live long enough}} \
- // expected-note {{is destroyed here}}
+ // expected-note {{temporary object is destroyed here}}
(void)r; // expected-note {{later used here}}
}
@@ -3661,7 +3661,7 @@ void deref_use_after_scope() {
optional<MyObj> opt;
p = &*opt; // expected-warning {{local variable 'opt' does not live long enough}} \
// expected-note {{expression aliases the storage of local variable 'opt'}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'opt' is destroyed here}}
(void)p->id; // expected-note {{later used here}}
}
@@ -3713,7 +3713,7 @@ void use_after_free_capture_by() {
{
MyObj a;
setCaptureBy(res, a); // expected-warning {{local variable 'a' does not live long enough}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'a' is destroyed here}}
(void)res; // expected-note {{later used here}}
}
@@ -3731,7 +3731,7 @@ void transitive_capture() {
MyObj local;
setCaptureBy(v1, local); // expected-warning {{local variable 'local' does not live long enough}}
setCaptureBy(v2, v1); // expected-note {{local variable 'v1' aliases the storage of local variable 'local'}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'local' is destroyed here}}
(void)v2; // expected-note {{later used here}}
}
@@ -3742,7 +3742,7 @@ void test_reference_to_view() {
{
MyObj local;
set1(v, local); // expected-warning {{local variable 'local' does not live long enough}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'local' is destroyed here}}
(void)v; // expected-note {{later used here}}
}
@@ -3773,7 +3773,7 @@ void test_reference_to_pointer() {
{
MyObj local;
set3(ptr, local); // expected-warning {{local variable 'local' does not live long enough}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'local' is destroyed here}}
(void)ptr; // expected-note {{later used here}}
}
@@ -3787,7 +3787,7 @@ void member_capture() {
{
MyObj local;
c.set(local); // expected-warning {{local variable 'local' does not live long enough}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'local' is destroyed here}}
(void)c.stored; // expected-note {{later used here}}
}
@@ -3816,7 +3816,7 @@ void multiple_captures() {
{
MyObj val2;
captureTwo(res, val1, val2); // expected-warning {{local variable 'val2' does not live long enough}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'val2' is destroyed here}}
(void)res; // expected-note {{later used here}}
}
@@ -3826,7 +3826,7 @@ void multiple_local_captures() {
MyObj val1;
MyObj val2;
captureTwo(res, val1, val2); // expected-warning {{local variable 'val1' does not live long enough}} // expected-warning {{local variable 'val2' does not live long enough}}
- } // expected-note 2 {{is destroyed here}}
+ } // expected-note {{local variable 'val2' is destroyed here}} expected-note {{local variable 'val1' is destroyed here}}
(void)res; // expected-note 2 {{later used here}}
}
@@ -3838,7 +3838,7 @@ void captured_by_multiple_params() {
{
MyObj local;
captureIntoTwo(v1, v2, local); // expected-warning {{local variable 'local' does not live long enough}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'local' is destroyed here}}
(void)v1; // expected-note {{later used here}}
}
@@ -3847,7 +3847,7 @@ void captured_by_multiple_params_2() {
{
MyObj local;
captureIntoTwo(v1, v2, local); // expected-warning {{local variable 'local' does not live long enough}}
- } // expected-note {{is destroyed here}}
+ } // expected-note {{local variable 'local' is destroyed here}}
(void)v2; // expected-note {{later used here}}
}
@@ -3858,7 +3858,7 @@ void capturing_multiple_locals() {
setCaptureBy(v, local1); // expected-warning{{local variable 'local1' does not live long enough}}
MyObj local2;
setCaptureBy(v, local2); // expected-warning{{local variable 'local2' does not live long enough}}
- } // expected-note 2 {{is destroyed here}}
+ } // expected-note {{local variable 'local1' is destroyed here}} expected-note {{local variable 'local2' is destroyed here}}
(void)v; // expected-note 2 {{later used here}}
}
>From 93038e73ccd2e42b8d54aa245b255dea08ca5825 Mon Sep 17 00:00:00 2001
From: iitianpushkar <pushkarsingh0587 at gmail.com>
Date: Sat, 20 Jun 2026 19:32:47 +0530
Subject: [PATCH 10/14] removes code duplication
---
clang/lib/Sema/SemaLifetimeSafety.h | 12 ++++--------
1 file changed, 4 insertions(+), 8 deletions(-)
diff --git a/clang/lib/Sema/SemaLifetimeSafety.h b/clang/lib/Sema/SemaLifetimeSafety.h
index f3680372b3e57..966dfdec934ed 100644
--- a/clang/lib/Sema/SemaLifetimeSafety.h
+++ b/clang/lib/Sema/SemaLifetimeSafety.h
@@ -425,14 +425,10 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper {
private:
void reportInvalidationNote(const Expr *InvalidationExpr,
StringRef InvalidatedSubject) {
- if (isa<CXXDeleteExpr>(InvalidationExpr)) {
- S.Diag(InvalidationExpr->getExprLoc(),
- diag::note_lifetime_safety_freed_here)
- << InvalidationExpr->getSourceRange();
- return;
- }
- S.Diag(InvalidationExpr->getExprLoc(),
- diag::note_lifetime_safety_invalidated_here)
+ auto Diag = isa<CXXDeleteExpr>(InvalidationExpr)
+ ? diag::note_lifetime_safety_freed_here
+ : diag::note_lifetime_safety_invalidated_here;
+ S.Diag(InvalidationExpr->getExprLoc(), Diag)
<< InvalidatedSubject << InvalidationExpr->getSourceRange();
}
>From df36100dfc15f7c3a37ad19058cc4ae388ddcfba Mon Sep 17 00:00:00 2001
From: iitianpushkar <pushkarsingh0587 at gmail.com>
Date: Sat, 20 Jun 2026 20:53:24 +0530
Subject: [PATCH 11/14] resolved build issue
---
clang/lib/Sema/SemaLifetimeSafety.h | 1 -
1 file changed, 1 deletion(-)
diff --git a/clang/lib/Sema/SemaLifetimeSafety.h b/clang/lib/Sema/SemaLifetimeSafety.h
index fbacbb6f90633..84190e70b136f 100644
--- a/clang/lib/Sema/SemaLifetimeSafety.h
+++ b/clang/lib/Sema/SemaLifetimeSafety.h
@@ -433,7 +433,6 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper {
<< InvalidatedSubject << InvalidationExpr->getSourceRange();
}
- std::pair<SourceLocation, StringRef>
std::string getLifetimeBoundFixItText(SourceLocation Loc, bool LeadingSpace,
bool AllowGNUAttrMacro = true) {
StringRef Spelling = S.getLangOpts().LifetimeSafetyLifetimeBoundMacro;
>From 3e0950c5f7e5a29a2f8211e9b888d9ebcd906191 Mon Sep 17 00:00:00 2001
From: iitianpushkar <pushkarsingh0587 at gmail.com>
Date: Sun, 21 Jun 2026 22:32:19 +0530
Subject: [PATCH 12/14] updated freed here diag notes to accept params
---
.../clang/Basic/DiagnosticSemaKinds.td | 2 +-
.../Sema/LifetimeSafety/invalidations.cpp | 8 ++--
clang/test/Sema/LifetimeSafety/safety.cpp | 46 +++++++++----------
3 files changed, 28 insertions(+), 28 deletions(-)
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 0b0a33c204c9c..8a461b8385013 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -11054,7 +11054,7 @@ def warn_lifetime_safety_inapplicable_lifetimebound
def note_lifetime_safety_used_here : Note<"later used here">;
def note_lifetime_safety_invalidated_here : Note<"%0 is invalidated here">;
def note_lifetime_safety_destroyed_here : Note<"%0 is destroyed here">;
-def note_lifetime_safety_freed_here : Note<"freed here">;
+def note_lifetime_safety_freed_here : Note<"%0 is 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">;
diff --git a/clang/test/Sema/LifetimeSafety/invalidations.cpp b/clang/test/Sema/LifetimeSafety/invalidations.cpp
index 6d76940f48b64..c2ac105855d07 100644
--- a/clang/test/Sema/LifetimeSafety/invalidations.cpp
+++ b/clang/test/Sema/LifetimeSafety/invalidations.cpp
@@ -575,12 +575,12 @@ struct S {
void InvalidatedFieldDelete() {
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}}
+ delete p; // expected-note {{allocated object is freed here}}
}
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}}
+ delete p; // expected-note {{parameter 'p' is freed here}}
}
void FieldReassignedBeforeInvalidation() {
@@ -624,12 +624,12 @@ void InvalidatedGlobalRefParamString(std::string &s) { // expected-warning {{par
void InvalidatedGlobalDelete() {
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}}
+ delete p; // expected-note {{allocated object is freed here}}
}
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}}
+ delete p; // expected-note {{parameter 'p' is freed here}}
}
void InvalidatedStaticLocalString() {
diff --git a/clang/test/Sema/LifetimeSafety/safety.cpp b/clang/test/Sema/LifetimeSafety/safety.cpp
index 972385551c2ea..5db966ab3c95c 100644
--- a/clang/test/Sema/LifetimeSafety/safety.cpp
+++ b/clang/test/Sema/LifetimeSafety/safety.cpp
@@ -1336,7 +1336,7 @@ void binary_conditional_masked_by_conditional(bool cond, MyObj* in) {
void binary_conditional_use_after_free(int* in) {
int* h = new int; // expected-warning {{allocated object does not live long enough}}
int* p = in ?: h;
- delete h; // expected-note {{freed here}}
+ delete h; // expected-note {{allocated object is freed here}}
(void)*p; // expected-note {{later used here}}
}
@@ -2971,44 +2971,44 @@ void new_view_from_dead_scope() {
void new_int_basic() {
int *p = new int; // expected-warning {{allocated object does not live long enough}}
- delete p; // expected-note {{freed here}}
+ delete p; // expected-note {{allocated object is freed here}}
(void)*p; // expected-note {{later used here}}
}
void new_int_parens() {
int *p = new int(); // expected-warning {{allocated object does not live long enough}}
- delete p; // expected-note {{freed here}}
+ delete p; // expected-note {{allocated object is freed here}}
(void)*p; // expected-note {{later used here}}
}
void new_int_braces() {
int *p = new int{}; // expected-warning {{allocated object does not live long enough}}
- delete p; // expected-note {{freed here}}
+ delete p; // expected-note {{allocated object is freed here}}
(void)*p; // expected-note {{later used here}}
}
void new_int_aligned() {
int *p = new (std::align_val_t(sizeof(int))) int{}; // expected-warning {{allocated object does not live long enough}}
- delete p; // expected-note {{freed here}}
+ delete p; // expected-note {{allocated object is freed here}}
(void)*p; // expected-note {{later used here}}
}
void new_int_nothrow() {
int *p = new (std::nothrow) int{}; // expected-warning {{allocated object does not live long enough}}
- delete p; // expected-note {{freed here}}
+ delete p; // expected-note {{allocated object is freed here}}
(void)*p; // expected-note {{later used here}}
}
void new_int_aligned_nothrow() {
int *p = new (std::align_val_t(sizeof(int)), std::nothrow) int{}; // expected-warning {{allocated object does not live long enough}}
- delete p; // expected-note {{freed here}}
+ delete p; // expected-note {{allocated object is freed here}}
(void)*p; // expected-note {{later used here}}
}
void conditional_delete(bool cond) {
int *p1 = new int; // expected-warning {{allocated object does not live long enough}}
int *p2 = new int; // expected-warning {{allocated object does not live long enough}}
- delete (cond ? p1 : p2); // expected-note 2 {{freed here}}
+ delete (cond ? p1 : p2); // expected-note 2 {{allocated object is freed here}}
(void)*p1; // expected-note {{later used here}}
(void)*p2; // expected-note {{later used here}}
}
@@ -3018,7 +3018,7 @@ int* foo(int* x [[clang::lifetimebound]], int* y [[clang::lifetimebound]]);
void delete_returned_from_call() {
int* x = new int(1); // expected-warning {{allocated object does not live long enough}}
int* y = new int(2); // expected-warning {{allocated object does not live long enough}}
- delete foo(x, y); // expected-note 2 {{freed here}}
+ delete foo(x, y); // expected-note 2 {{allocated object is freed here}}
(void)x; // expected-note {{later used here}}
(void)y; // expected-note {{later used here}}
}
@@ -3058,19 +3058,19 @@ void new_multiview_from_mixed_scope() {
void new_array_basic() {
int *p = new int[2]; // expected-warning {{allocated object does not live long enough}}
- delete[] p; // expected-note {{freed here}}
+ delete[] p; // expected-note {{allocated object is freed here}}
(void)p[0]; // expected-note {{later used here}}
}
void new_array_parens() {
int *p = new int[2](); // expected-warning {{allocated object does not live long enough}}
- delete[] p; // expected-note {{freed here}}
+ delete[] p; // expected-note {{allocated object is freed here}}
(void)p[0]; // expected-note {{later used here}}
}
void new_array_braces() {
int *p = new int[2]{}; // expected-warning {{allocated object does not live long enough}}
- delete[] p; // expected-note {{freed here}}
+ delete[] p; // expected-note {{allocated object is freed here}}
(void)p[0]; // expected-note {{later used here}}
}
@@ -3105,26 +3105,26 @@ void pointer_array_field_sensitivity() {
void delete_direct_use_after_free() {
MyObj *p = new MyObj; // expected-warning {{allocated object does not live long enough}}
- delete p; // expected-note {{freed here}}
+ delete p; // expected-note {{allocated object is freed here}}
(void)p->id; // expected-note {{later used here}}
}
void delete_alias_use_after_free() {
MyObj *p = new MyObj; // expected-warning {{allocated object does not live long enough}}
MyObj *q = p;
- delete p; // expected-note {{freed here}}
+ delete p; // expected-note {{allocated object is freed here}}
(void)q->id; // expected-note {{later used here}}
}
void delete_pointer_propagation_use_after_free() {
MyObj *p = new MyObj; // expected-warning {{allocated object does not live long enough}}
MyObj **pp = &p;
- delete p; // expected-note {{freed here}}
+ delete p; // expected-note {{allocated object is freed here}}
(void)(*pp)->id; // expected-note {{later used here}}
}
void delete_param_pointer(int* x) { // expected-warning {{parameter 'x' does not live long enough}}
- delete x; // expected-note {{freed here}}
+ delete x; // expected-note {{parameter 'x' is freed here}}
(void)x; // expected-note {{later used here}}
}
@@ -3139,7 +3139,7 @@ struct S {
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}}
+ delete obj; // expected-note {{parameter 'obj' is freed here}}
(void)*p; // expected-note {{later used here}}
}
@@ -3160,7 +3160,7 @@ struct ClassSpecificDelete {
void class_specific_operator_delete_use_after_free() {
ClassSpecificDelete *p = new ClassSpecificDelete; // expected-warning {{allocated object does not live long enough}}
- delete p; // expected-note {{freed here}}
+ delete p; // expected-note {{allocated object is freed here}}
(void)p->X; // expected-note {{later used here}}
}
@@ -3172,7 +3172,7 @@ struct ClassSpecificNew {
void class_specific_operator_new_use_after_free() {
ClassSpecificNew *p = new ClassSpecificNew; // expected-warning {{allocated object does not live long enough}}
- delete p; // expected-note {{freed here}}
+ delete p; // expected-note {{allocated object is freed here}}
(void)p->X; // expected-note {{later used here}}
}
@@ -3190,14 +3190,14 @@ void delete_through_pointer_field() {
void delete_stack_object() {
MyObj obj;
MyObj* p = &obj; // expected-warning {{local variable 'obj' does not live long enough}}
- delete &obj; // expected-note {{freed here}}
+ delete &obj; // expected-note {{local variable 'obj' is freed here}}
(void)p->id; // expected-note {{later used here}}
}
void delete_stack_object_int() {
int obj;
int* p = &obj; // expected-warning {{local variable 'obj' does not live long enough}}
- delete &obj; // expected-note {{freed here}}
+ delete &obj; // expected-note {{local variable 'obj' is freed here}}
(void)*p; // expected-note {{later used here}}
}
@@ -3260,7 +3260,7 @@ void placement_new_array_braces() {
void placement_new_heap_then_delete_use_after_free() {
int *storage = new int(7); // expected-warning {{allocated object does not live long enough}}
int *p = new (storage) int(42);
- delete storage; // expected-note {{freed here}}
+ delete storage; // expected-note {{allocated object is freed here}}
(void)*p; // expected-note {{later used here}}
}
@@ -3308,7 +3308,7 @@ void placement_new_delete_result_of_lifetimebound_call() {
int *y = new int(2); // expected-warning {{allocated object does not live long enough}}
int *slot = nullptr;
int **p = new (&slot) int *(foo(x, y));
- delete foo(x, y); // expected-note 2 {{freed here}}
+ delete foo(x, y); // expected-note 2 {{allocated object is freed here}}
(void)**p; // expected-note 2 {{later used here}}
}
>From 1d08f10fc950c3cc7aec5b1dc23b1b1d9bb0f95d Mon Sep 17 00:00:00 2001
From: iitianpushkar <pushkarsingh0587 at gmail.com>
Date: Mon, 22 Jun 2026 11:24:36 +0530
Subject: [PATCH 13/14] Renamed invalidation helper and improved test
readability
---
clang/lib/Sema/SemaLifetimeSafety.h | 2 +-
clang/test/Sema/LifetimeSafety/safety-c.c | 4 ++--
clang/test/Sema/LifetimeSafety/safety.cpp | 3 ++-
3 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/clang/lib/Sema/SemaLifetimeSafety.h b/clang/lib/Sema/SemaLifetimeSafety.h
index 84190e70b136f..e360af956353a 100644
--- a/clang/lib/Sema/SemaLifetimeSafety.h
+++ b/clang/lib/Sema/SemaLifetimeSafety.h
@@ -424,7 +424,7 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper {
}
private:
- void reportInvalidationNote(const Expr *InvalidationExpr,
+ void reportInvalidationSite(const Expr *InvalidationExpr,
StringRef InvalidatedSubject) {
auto Diag = isa<CXXDeleteExpr>(InvalidationExpr)
? diag::note_lifetime_safety_freed_here
diff --git a/clang/test/Sema/LifetimeSafety/safety-c.c b/clang/test/Sema/LifetimeSafety/safety-c.c
index ce415d1a015cf..e9443899c9935 100644
--- a/clang/test/Sema/LifetimeSafety/safety-c.c
+++ b/clang/test/Sema/LifetimeSafety/safety-c.c
@@ -95,8 +95,8 @@ void conditional_operator_lifetimebound(int cond) {
int a, b;
p = identity(cond ? &a // expected-warning {{local variable 'a' does not live long enough}}
: &b); // expected-warning {{local variable 'b' does not live long enough}}
- } // expected-note {{local variable 'a' is destroyed here}}
- // expected-note at -1 {{local variable 'b' is destroyed here}}
+ } // expected-note {{local variable 'a' is destroyed here}} \
+ // expected-note {{local variable 'b' is destroyed here}}
(void)*p; // expected-note 2 {{later used here}}
}
diff --git a/clang/test/Sema/LifetimeSafety/safety.cpp b/clang/test/Sema/LifetimeSafety/safety.cpp
index 5db966ab3c95c..abd3d9c61b784 100644
--- a/clang/test/Sema/LifetimeSafety/safety.cpp
+++ b/clang/test/Sema/LifetimeSafety/safety.cpp
@@ -834,7 +834,8 @@ void lifetimebound_multiple_args_definite() {
// expected-note {{result of call to 'Choose' aliases the storage of local variable 'obj2'}}
obj1, // expected-warning {{local variable 'obj1' does not live long enough}}
obj2); // expected-warning {{local variable 'obj2' does not live long enough}}
- } // expected-note {{local variable 'obj1' is destroyed here}} expected-note {{local variable 'obj2' is destroyed here}}
+ } // expected-note {{local variable 'obj1' is destroyed here}} \
+ // expected-note {{local variable 'obj2' is destroyed here}}
v.use(); // expected-note 2 {{later used here}}
}
>From a66a05a06f356cc137d6b2efe2e5f6cf4eae99c2 Mon Sep 17 00:00:00 2001
From: iitianpushkar <pushkarsingh0587 at gmail.com>
Date: Mon, 22 Jun 2026 11:46:09 +0530
Subject: [PATCH 14/14] resolved build issue
---
clang/lib/Sema/SemaLifetimeSafety.h | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/clang/lib/Sema/SemaLifetimeSafety.h b/clang/lib/Sema/SemaLifetimeSafety.h
index e360af956353a..1047aecf863fb 100644
--- a/clang/lib/Sema/SemaLifetimeSafety.h
+++ b/clang/lib/Sema/SemaLifetimeSafety.h
@@ -172,7 +172,7 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper {
std::string InvalidatedSubject = getDiagSubjectDescription(IssueExpr);
S.Diag(IssueExpr->getExprLoc(), WarnDiag)
<< InvalidatedSubject << IssueExpr->getSourceRange();
- reportInvalidationNote(InvalidationExpr, InvalidatedSubject);
+ reportInvalidationSite(InvalidationExpr, InvalidatedSubject);
S.Diag(UseExpr->getExprLoc(), diag::note_lifetime_safety_used_here)
<< UseExpr->getSourceRange();
}
@@ -186,7 +186,7 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper {
S.Diag(PVD->getSourceRange().getBegin(), WarnDiag)
<< InvalidatedSubject << PVD->getSourceRange();
- reportInvalidationNote(InvalidationExpr, InvalidatedSubject);
+ reportInvalidationSite(InvalidationExpr, InvalidatedSubject);
S.Diag(UseExpr->getExprLoc(), diag::note_lifetime_safety_used_here)
<< UseExpr->getSourceRange();
}
@@ -199,7 +199,7 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper {
diag::warn_lifetime_safety_invalidated_field)
<< InvalidatedSubject << getDiagSubjectDescription(DanglingField)
<< IssueExpr->getSourceRange();
- reportInvalidationNote(InvalidationExpr, InvalidatedSubject);
+ reportInvalidationSite(InvalidationExpr, InvalidatedSubject);
S.Diag(DanglingField->getLocation(),
diag::note_lifetime_safety_dangling_field_here)
<< DanglingField->getEndLoc();
@@ -213,7 +213,7 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper {
diag::warn_lifetime_safety_invalidated_field)
<< InvalidatedSubject << getDiagSubjectDescription(DanglingField)
<< PVD->getSourceRange();
- reportInvalidationNote(InvalidationExpr, InvalidatedSubject);
+ reportInvalidationSite(InvalidationExpr, InvalidatedSubject);
S.Diag(DanglingField->getLocation(),
diag::note_lifetime_safety_dangling_field_here)
<< DanglingField->getEndLoc();
@@ -227,7 +227,7 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper {
diag::warn_lifetime_safety_invalidated_global)
<< InvalidatedSubject << getDiagSubjectDescription(DanglingGlobal)
<< IssueExpr->getSourceRange();
- reportInvalidationNote(InvalidationExpr, InvalidatedSubject);
+ reportInvalidationSite(InvalidationExpr, InvalidatedSubject);
if (DanglingGlobal->isStaticLocal() || DanglingGlobal->isStaticDataMember())
S.Diag(DanglingGlobal->getLocation(),
diag::note_lifetime_safety_dangling_static_here)
@@ -246,7 +246,7 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper {
diag::warn_lifetime_safety_invalidated_global)
<< InvalidatedSubject << getDiagSubjectDescription(DanglingGlobal)
<< PVD->getSourceRange();
- reportInvalidationNote(InvalidationExpr, InvalidatedSubject);
+ reportInvalidationSite(InvalidationExpr, InvalidatedSubject);
if (DanglingGlobal->isStaticLocal() || DanglingGlobal->isStaticDataMember())
S.Diag(DanglingGlobal->getLocation(),
diag::note_lifetime_safety_dangling_static_here)
More information about the cfe-commits
mailing list