[llvm-branch-commits] [clang] fa6b47c - Revert "[LifetimeSafety] Add support for `new`/`delete` (#192504)"
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Wed Apr 22 04:55:57 PDT 2026
Author: Martin Storsjö
Date: 2026-04-22T14:55:53+03:00
New Revision: fa6b47c6c167149fc75bb6dc84a14bde42c6e12e
URL: https://github.com/llvm/llvm-project/commit/fa6b47c6c167149fc75bb6dc84a14bde42c6e12e
DIFF: https://github.com/llvm/llvm-project/commit/fa6b47c6c167149fc75bb6dc84a14bde42c6e12e.diff
LOG: Revert "[LifetimeSafety] Add support for `new`/`delete` (#192504)"
This reverts commit b1175088531de1a3bae9942ef50d880fab6fe144.
Added:
Modified:
clang/include/clang/Analysis/Analyses/LifetimeSafety/Facts.h
clang/include/clang/Analysis/Analyses/LifetimeSafety/FactsGenerator.h
clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h
clang/include/clang/Analysis/Analyses/LifetimeSafety/Loans.h
clang/include/clang/Basic/DiagnosticGroups.td
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/lib/Analysis/LifetimeSafety/Checker.cpp
clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp
clang/lib/Analysis/LifetimeSafety/Loans.cpp
clang/lib/Sema/SemaLifetimeSafety.h
clang/test/Sema/Inputs/lifetime-analysis.h
clang/test/Sema/warn-lifetime-safety-suggestions.cpp
clang/test/Sema/warn-lifetime-safety.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/Analysis/Analyses/LifetimeSafety/Facts.h b/clang/include/clang/Analysis/Analyses/LifetimeSafety/Facts.h
index 88b509e1b94df..b70fecd5ab1d1 100644
--- a/clang/include/clang/Analysis/Analyses/LifetimeSafety/Facts.h
+++ b/clang/include/clang/Analysis/Analyses/LifetimeSafety/Facts.h
@@ -53,7 +53,7 @@ class Fact {
TestPoint,
/// An origin that escapes the function scope (e.g., via return).
OriginEscapes,
- /// An origin is invalidated (e.g. vector resized, `delete` called).
+ /// An origin is invalidated (e.g. vector resized).
InvalidateOrigin,
/// All loans of an origin are cleared.
KillOrigin,
diff --git a/clang/include/clang/Analysis/Analyses/LifetimeSafety/FactsGenerator.h b/clang/include/clang/Analysis/Analyses/LifetimeSafety/FactsGenerator.h
index 45b16cf1ec31d..a86f22a181a70 100644
--- a/clang/include/clang/Analysis/Analyses/LifetimeSafety/FactsGenerator.h
+++ b/clang/include/clang/Analysis/Analyses/LifetimeSafety/FactsGenerator.h
@@ -53,8 +53,6 @@ class FactsGenerator : public ConstStmtVisitor<FactsGenerator> {
void VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *MTE);
void VisitLambdaExpr(const LambdaExpr *LE);
void VisitArraySubscriptExpr(const ArraySubscriptExpr *ASE);
- void VisitCXXNewExpr(const CXXNewExpr *NE);
- void VisitCXXDeleteExpr(const CXXDeleteExpr *DE);
private:
OriginList *getOriginsList(const ValueDecl &D);
diff --git a/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h b/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h
index d20ac87a7c8d9..83c3c455c4c81 100644
--- a/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h
+++ b/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h
@@ -61,9 +61,9 @@ class LifetimeSafetySemaHelper {
LifetimeSafetySemaHelper() = default;
virtual ~LifetimeSafetySemaHelper() = default;
- virtual void reportUseAfterScope(const Expr *IssueExpr, const Expr *UseExpr,
- const Expr *MovedExpr,
- SourceLocation FreeLoc) {}
+ virtual void reportUseAfterFree(const Expr *IssueExpr, const Expr *UseExpr,
+ const Expr *MovedExpr,
+ SourceLocation FreeLoc) {}
virtual void reportUseAfterReturn(const Expr *IssueExpr,
const Expr *ReturnExpr,
diff --git a/clang/include/clang/Analysis/Analyses/LifetimeSafety/Loans.h b/clang/include/clang/Analysis/Analyses/LifetimeSafety/Loans.h
index d25c91333100c..aee6bf9eb69c9 100644
--- a/clang/include/clang/Analysis/Analyses/LifetimeSafety/Loans.h
+++ b/clang/include/clang/Analysis/Analyses/LifetimeSafety/Loans.h
@@ -35,35 +35,32 @@ inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, LoanID ID) {
/// - MaterializeTemporaryExpr: a temporary object
/// - ParmVarDecl: a function parameter (placeholder)
/// - CXXMethodDecl: the implicit 'this' object (placeholder)
-/// - CXXNewExpr: a heap allocation made by `new`
///
/// Placeholder paths never expire within the function scope, as they represent
/// storage from the caller's scope.
///
/// TODO: Model access paths of other types, e.g. field, array subscript, heap
-/// allocation not through `new`, and globals.
+/// and globals.
class AccessPath {
public:
enum class Kind : uint8_t {
ValueDecl,
MaterializeTemporary,
PlaceholderParam,
- PlaceholderThis,
- NewAllocation,
+ PlaceholderThis
};
private:
Kind K;
- const llvm::PointerUnion<
- const clang::ValueDecl *, const clang::MaterializeTemporaryExpr *,
- const ParmVarDecl *, const CXXMethodDecl *, const CXXNewExpr *>
+ const llvm::PointerUnion<const clang::ValueDecl *,
+ const clang::MaterializeTemporaryExpr *,
+ const ParmVarDecl *, const CXXMethodDecl *>
Root;
public:
AccessPath(const clang::ValueDecl *D) : K(Kind::ValueDecl), Root(D) {}
AccessPath(const clang::MaterializeTemporaryExpr *MTE)
: K(Kind::MaterializeTemporary), Root(MTE) {}
- AccessPath(const CXXNewExpr *New) : K(Kind::NewAllocation), Root(New) {}
static AccessPath Placeholder(const ParmVarDecl *PVD) {
return AccessPath(Kind::PlaceholderParam, PVD);
}
@@ -91,10 +88,6 @@ class AccessPath {
return K == Kind::PlaceholderThis ? Root.dyn_cast<const CXXMethodDecl *>()
: nullptr;
}
- const CXXNewExpr *getAsNewAllocation() const {
- return K == Kind::NewAllocation ? Root.dyn_cast<const CXXNewExpr *>()
- : nullptr;
- }
bool operator==(const AccessPath &RHS) const {
return K == RHS.K && Root == RHS.Root;
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td
index 74f9fab14d82c..3136d109e795b 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -586,12 +586,6 @@ This may contain false-positives, e.g. when the borrowed storage is potentially
}];
}
-def LifetimeSafetyUseAfterFree : DiagGroup<"lifetime-safety-use-after-free"> {
- code Documentation = [{
-Warning to detect use-after-free, introduced by freeing an object and later using it.
- }];
-}
-
// Dangling-Field (aka Escape-To-Field)
def LifetimeSafetyDanglingField : DiagGroup<"lifetime-safety-dangling-field"> {
code Documentation = [{
@@ -628,16 +622,14 @@ def LifetimeSafetyPermissive : DiagGroup<"lifetime-safety-permissive",
[LifetimeSafetyUseAfterScope,
LifetimeSafetyReturnStackAddr,
LifetimeSafetyDanglingField,
- LifetimeSafetyDanglingGlobal,
- LifetimeSafetyUseAfterFree]>;
+ LifetimeSafetyDanglingGlobal]>;
def LifetimeSafetyStrict : DiagGroup<"lifetime-safety-strict",
[LifetimeSafetyUseAfterScopeMoved,
LifetimeSafetyReturnStackAddrMoved,
LifetimeSafetyDanglingFieldMoved,
LifetimeSafetyDanglingGlobal,
- LifetimeSafetyInvalidation,
- LifetimeSafetyUseAfterFree]>;
+ LifetimeSafetyInvalidation]>;
def LifetimeSafety : DiagGroup<"lifetime-safety",
[LifetimeSafetyPermissive, LifetimeSafetyStrict]> {
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index dc86a0b58d8f9..cc82bb6a51e52 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -10962,10 +10962,6 @@ def warn_lifetime_safety_use_after_scope_moved : Warning<
"This could be false positive as the storage may have been moved later">,
InGroup<LifetimeSafetyUseAfterScopeMoved>, DefaultIgnore;
-def warn_lifetime_safety_use_after_free : Warning<
- "%select{allocated object|parameter}0 does not live long enough">,
- InGroup<LifetimeSafetyUseAfterFree>, DefaultIgnore;
-
def warn_lifetime_safety_return_stack_addr
: Warning<"address of stack memory is returned later">,
InGroup<LifetimeSafetyReturnStackAddr>,
@@ -11006,7 +11002,6 @@ def warn_lifetime_safety_dangling_global_moved
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_freed_here : Note<"freed here">;
def note_lifetime_safety_returned_here : Note<"returned here">;
def note_lifetime_safety_moved_here : Note<"potentially moved here">;
def note_lifetime_safety_dangling_field_here: Note<"this field dangles">;
diff --git a/clang/lib/Analysis/LifetimeSafety/Checker.cpp b/clang/lib/Analysis/LifetimeSafety/Checker.cpp
index 8164eb15cb6cb..fe103739dbcb0 100644
--- a/clang/lib/Analysis/LifetimeSafety/Checker.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/Checker.cpp
@@ -250,8 +250,8 @@ class LifetimeChecker {
} else
// Scope-based expiry (use-after-scope).
- SemaHelper->reportUseAfterScope(IssueExpr, UF->getUseExpr(),
- MovedExpr, ExpiryLoc);
+ SemaHelper->reportUseAfterFree(IssueExpr, UF->getUseExpr(), MovedExpr,
+ ExpiryLoc);
} else if (const auto *OEF =
CausingFact.dyn_cast<const OriginEscapesFact *>()) {
if (const auto *RetEscape = dyn_cast<ReturnEscapeFact>(OEF))
diff --git a/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp b/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp
index 33da608385dcd..23990435e24dc 100644
--- a/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp
@@ -94,14 +94,6 @@ static const Loan *createLoan(FactManager &FactMgr,
return FactMgr.getLoanMgr().createLoan(Path, MTE);
}
-/// Creates a loan for an allocation through 'new'
-/// \param NE The CXXNewExpr that represents the allocation
-/// \return The new Loan on success, nullptr otherwise
-static const Loan *createLoan(FactManager &FactMgr, const CXXNewExpr *NE) {
- AccessPath Path(NE);
- return FactMgr.getLoanMgr().createLoan(Path, NE);
-}
-
void FactsGenerator::run() {
llvm::TimeTraceScope TimeProfile("FactGenerator");
const CFG &Cfg = *AC.getCFG();
@@ -623,30 +615,6 @@ void FactsGenerator::VisitArraySubscriptExpr(const ArraySubscriptExpr *ASE) {
Dst->getOuterOriginID(), Src->getOuterOriginID(), /*Kill=*/true));
}
-void FactsGenerator::VisitCXXNewExpr(const CXXNewExpr *NE) {
- OriginList *NewList = getOriginsList(*NE);
-
- const Loan *L = createLoan(FactMgr, NE);
- CurrentBlockFacts.push_back(
- FactMgr.createFact<IssueFact>(L->getID(), NewList->getOuterOriginID()));
-
- NewList = NewList->peelOuterOrigin();
-
- if (!NewList)
- return;
-
- // FIXME: OriginList is null for `new[]` initializers. Remove this `Init`
- // check once array origins are supported.
- if (OriginList *Init = getOriginsList(*NE->getInitializer()); Init)
- flow(NewList, Init, true);
-}
-
-void FactsGenerator::VisitCXXDeleteExpr(const CXXDeleteExpr *DE) {
- OriginList *List = getOriginsList(*DE->getArgument());
- CurrentBlockFacts.push_back(
- FactMgr.createFact<InvalidateOriginFact>(List->getOuterOriginID(), DE));
-}
-
bool FactsGenerator::escapesViaReturn(OriginID OID) const {
return llvm::any_of(EscapesInCurrentBlock, [OID](const Fact *F) {
if (const auto *EF = F->getAs<ReturnEscapeFact>())
diff --git a/clang/lib/Analysis/LifetimeSafety/Loans.cpp b/clang/lib/Analysis/LifetimeSafety/Loans.cpp
index c0c8d0b283f8b..336331b8f5a27 100644
--- a/clang/lib/Analysis/LifetimeSafety/Loans.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/Loans.cpp
@@ -28,10 +28,6 @@ void AccessPath::dump(llvm::raw_ostream &OS) const {
case Kind::PlaceholderThis:
OS << "$this";
break;
- case Kind::NewAllocation:
- if (const auto *E = getAsNewAllocation())
- OS << "NewAllocation at " << E;
- break;
}
}
diff --git a/clang/lib/Sema/SemaLifetimeSafety.h b/clang/lib/Sema/SemaLifetimeSafety.h
index 92e7b5cf14ae5..c56a9692abe1a 100644
--- a/clang/lib/Sema/SemaLifetimeSafety.h
+++ b/clang/lib/Sema/SemaLifetimeSafety.h
@@ -43,9 +43,9 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper {
public:
LifetimeSafetySemaHelperImpl(Sema &S) : S(S) {}
- void reportUseAfterScope(const Expr *IssueExpr, const Expr *UseExpr,
- const Expr *MovedExpr,
- SourceLocation FreeLoc) override {
+ void reportUseAfterFree(const Expr *IssueExpr, const Expr *UseExpr,
+ const Expr *MovedExpr,
+ SourceLocation FreeLoc) override {
S.Diag(IssueExpr->getExprLoc(),
MovedExpr ? diag::warn_lifetime_safety_use_after_scope_moved
: diag::warn_lifetime_safety_use_after_scope)
@@ -111,32 +111,21 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper {
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;
- auto UseDiag = isa<CXXDeleteExpr>(InvalidationExpr)
- ? diag::note_lifetime_safety_freed_here
- : diag::note_lifetime_safety_invalidated_here;
- S.Diag(IssueExpr->getExprLoc(), WarnDiag)
+ S.Diag(IssueExpr->getExprLoc(), diag::warn_lifetime_safety_invalidation)
<< false << IssueExpr->getSourceRange();
- S.Diag(InvalidationExpr->getExprLoc(), UseDiag)
+ S.Diag(InvalidationExpr->getExprLoc(),
+ diag::note_lifetime_safety_invalidated_here)
<< InvalidationExpr->getSourceRange();
S.Diag(UseExpr->getExprLoc(), diag::note_lifetime_safety_used_here)
<< UseExpr->getSourceRange();
}
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;
- auto UseDiag = isa<CXXDeleteExpr>(InvalidationExpr)
- ? diag::note_lifetime_safety_freed_here
- : diag::note_lifetime_safety_invalidated_here;
-
- S.Diag(PVD->getSourceRange().getBegin(), WarnDiag)
+ S.Diag(PVD->getSourceRange().getBegin(),
+ diag::warn_lifetime_safety_invalidation)
<< true << PVD->getSourceRange();
- S.Diag(InvalidationExpr->getExprLoc(), UseDiag)
+ S.Diag(InvalidationExpr->getExprLoc(),
+ diag::note_lifetime_safety_invalidated_here)
<< InvalidationExpr->getSourceRange();
S.Diag(UseExpr->getExprLoc(), diag::note_lifetime_safety_used_here)
<< UseExpr->getSourceRange();
diff --git a/clang/test/Sema/Inputs/lifetime-analysis.h b/clang/test/Sema/Inputs/lifetime-analysis.h
index 2836ec00e97cb..9806cce15d8f5 100644
--- a/clang/test/Sema/Inputs/lifetime-analysis.h
+++ b/clang/test/Sema/Inputs/lifetime-analysis.h
@@ -289,6 +289,3 @@ class function<R(Args...)> {
};
}
-
-void *operator new(std::size_t, void *) noexcept;
-void *operator new[](std::size_t, void *) noexcept;
diff --git a/clang/test/Sema/warn-lifetime-safety-suggestions.cpp b/clang/test/Sema/warn-lifetime-safety-suggestions.cpp
index bdcfe728f6776..08405c4607f3c 100644
--- a/clang/test/Sema/warn-lifetime-safety-suggestions.cpp
+++ b/clang/test/Sema/warn-lifetime-safety-suggestions.cpp
@@ -570,53 +570,3 @@ void test_inference() {
(void)ptr; // expected-note {{later used here}}
}
} // namespace make_unique_suggestion
-
-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}}
-}
-
-void test_new_allocation() {
- View* v = MakeView(MyObj{}); // expected-warning {{object whose reference is captured does not live long enough}} \
- // expected-note {{destroyed here}}
- (void)v; // expected-note {{later used here}}
-}
-
-struct LifetimeBoundCtor {
- View v;
- LifetimeBoundCtor();
- LifetimeBoundCtor(const MyObj& obj [[clang::lifetimebound]]) : v(obj) {}
-};
-
-struct HasCtorField {
- LifetimeBoundCtor* field; // expected-note {{escapes to this field}}
- HasCtorField(const MyObj& obj) : field(new LifetimeBoundCtor(obj)) {} // expected-warning {{parameter in intra-TU function should be marked [[clang::lifetimebound]]}}
-};
-
-HasCtorField test_dangling_field_ctor() {
- MyObj obj;
- HasCtorField x(obj); // expected-warning {{address of stack memory is returned later}}
- return x; // expected-note {{returned here}}
-}
-
-struct HasSetterField {
- LifetimeBoundCtor* field; // expected-note {{this field dangles}}
- // FIXME: Does not currently suggest `lifetime_capture_by(this)` (even without `new`)
- void set(const MyObj& obj) {
- field = new LifetimeBoundCtor(obj);
- }
- void reset() {
- MyObj obj;
- field = new LifetimeBoundCtor(obj); // expected-warning {{address of stack memory escapes to a field}}
- }
-};
-
-HasSetterField test_dangling_field_member_fn() {
- MyObj obj;
- HasSetterField x;
- x.set(obj);
- return x;
-}
-
-} // namespace new_allocation_suggestion
diff --git a/clang/test/Sema/warn-lifetime-safety.cpp b/clang/test/Sema/warn-lifetime-safety.cpp
index bb87b13a71c49..fba5523931b44 100644
--- a/clang/test/Sema/warn-lifetime-safety.cpp
+++ b/clang/test/Sema/warn-lifetime-safety.cpp
@@ -2663,236 +2663,6 @@ int *noreturn_dead_nested(bool cond, bool cond2, int *num) {
} // namespace conditional_operator_control_flow
-namespace new_allocation {
-
-//===----------------------------------------------------------------------===//
-// new
-//===----------------------------------------------------------------------===//
-
-void new_view_from_dead_scope() {
- View *p;
- {
- MyObj obj;
- p = new View(obj); // expected-warning {{object whose reference is captured does not live long enough}}
- } // expected-note {{destroyed here}}
- p->use(); // expected-note {{later used here}}
-}
-
-void new_int_basic() {
- int *p = new int; // expected-warning {{allocated object does not live long enough}}
- delete p; // expected-note {{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}}
- (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}}
- (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}}
- (void)*p1; // expected-note {{later used here}}
- (void)*p2; // expected-note {{later used here}}
-}
-
-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}}
- (void)x; // expected-note {{later used here}}
- (void)y; // expected-note {{later used here}}
-}
-
-void new_pointer_from_pointer() {
- MyObj **p;
- {
- MyObj obj;
- MyObj *q = &obj; // expected-warning {{object whose reference is captured does not live long enough}}
- p = new MyObj *(q);
- } // expected-note {{destroyed here}}
- (void)**p; // expected-note {{later used here}}
-}
-
-void new_pointer_from_dead_object() {
- MyObj **p;
- {
- MyObj obj;
- p = new MyObj *(&obj); // expected-warning {{object whose reference is captured does not live long enough}}
- } // expected-note {{destroyed here}}
- (void)**p; // expected-note {{later used here}}
-}
-
-struct MultiView {
- MultiView(MyObj& a [[clang::lifetimebound]], MyObj& b [[clang::lifetimebound]]);
-};
-
-void new_multiview_from_mixed_scope() {
- MyObj obj1;
- MultiView *p;
- {
- MyObj obj2;
- p = new MultiView(obj1, obj2); // expected-warning {{object whose reference is captured does not live long enough}}
- } // expected-note {{destroyed here}}
- (void)p; // expected-note {{later used here}}
-}
-
-void new_array_basic() {
- int *p = new int[2]; // expected-warning {{allocated object does not live long enough}}
- delete[] p; // expected-note {{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}}
- (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}}
- (void)p[0]; // expected-note {{later used here}}
-}
-
-// FIXME: https://github.com/llvm/llvm-project/issues/187471
-void new_pointer_array_from_dead_objects() {
- MyObj **arr;
- {
- MyObj a, b;
- arr = new MyObj *[2]{&a, &b};
- }
- (void)arr[0]->id;
- (void)arr[1]->id;
-}
-
-struct PointerArrayFieldHolder {
- MyObj **Ptrs;
-};
-
-// FIXME: https://github.com/llvm/llvm-project/issues/187471
-void pointer_array_field_sensitivity() {
- PointerArrayFieldHolder h;
- {
- MyObj a, b;
- h.Ptrs = new MyObj *[2]{&a, &b};
- }
- (void)h.Ptrs[0]->id;
-}
-
-//===----------------------------------------------------------------------===//
-// delete
-//===----------------------------------------------------------------------===//
-
-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}}
- (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}}
- (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}}
- (void)(*pp)->id; // expected-note {{later used here}}
-}
-
-void delete_param_pointer(int* x) { // expected-warning {{parameter does not live long enough}}
- delete x; // expected-note {{freed here}}
- (void)x; // expected-note {{later used here}}
-}
-
-// FIXME: false-negative
-struct S {
- int *x;
- void foo() {
- delete x;
- (void)x;
- }
-};
-
-void use_inner_origin_after_delete(MyObj* obj) { // expected-warning {{parameter does not live long enough}}
- int* p = &obj->id;
- delete obj; // expected-note {{freed here}}
- (void)*p; // expected-note {{later used here}}
-}
-
-void delete_nullptr_no_warning() {
- int *p = nullptr;
- delete p;
-}
-
-void delete_array_nullptr_no_warning() {
- int *p = nullptr;
- delete[] p;
-}
-
-struct ClassSpecificDelete {
- int X;
- static void operator delete(void *);
-};
-
-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}}
- (void)p->X; // expected-note {{later used here}}
-}
-
-struct PointerFieldHolder {
- MyObj *Ptr;
-};
-
-// FIXME: https://github.com/llvm/llvm-project/issues/184344
-void placement_new_pointer_field_use_after_scope() {
- PointerFieldHolder h;
- PointerFieldHolder *p = &h;
- {
- MyObj obj;
- p = new (&h) PointerFieldHolder{&obj};
- }
- (void)p->Ptr->id;
-}
-
-// FIXME: https://github.com/llvm/llvm-project/issues/184344
-void delete_through_pointer_field() {
- PointerFieldHolder h{new MyObj};
- delete h.Ptr;
- (void)h.Ptr->id;
-}
-
-void delete_stack_object() {
- MyObj obj;
- MyObj* p = &obj; // expected-warning {{allocated object does not live long enough}}
- delete &obj; // expected-note {{freed here}}
- (void)p->id; // expected-note {{later used here}}
-}
-
-void delete_stack_object_int() {
- int obj;
- int* p = &obj; // expected-warning {{allocated object does not live long enough}}
- delete &obj; // expected-note {{freed here}}
- (void)*p; // expected-note {{later used here}}
-}
-
-} // namespace new_allocation
-
namespace method_call_uses_field_origins {
int GLOBAL_INT;
std::string GLOBAL_STRING{"123"};
More information about the llvm-branch-commits
mailing list