[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