https://github.com/usx95 created 
https://github.com/llvm/llvm-project/pull/148222

None

>From 14a9c8b50df11ce48ce15d0fbe29568b3e23b5a6 Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena <u...@google.com>
Date: Fri, 11 Jul 2025 11:11:47 +0000
Subject: [PATCH] [LifetimeSafety] Add expired loans analysis

---
 clang/lib/Analysis/LifetimeSafety.cpp | 140 ++++++++++++++++++++++++++
 1 file changed, 140 insertions(+)

diff --git a/clang/lib/Analysis/LifetimeSafety.cpp 
b/clang/lib/Analysis/LifetimeSafety.cpp
index e72192aa92c1a..88ec70d000d2c 100644
--- a/clang/lib/Analysis/LifetimeSafety.cpp
+++ b/clang/lib/Analysis/LifetimeSafety.cpp
@@ -735,6 +735,142 @@ class LifetimeDataflow {
   }
 };
 
+// ========================================================================= //
+//                         Expired Loans Analysis
+// ========================================================================= //
+
+/// The lattice for tracking expired loans. It is a set of loan IDs.
+struct ExpiredLattice {
+  LoanSet Expired;
+
+  ExpiredLattice() = default;
+  explicit ExpiredLattice(LoanSet S) : Expired(S) {}
+
+  bool operator==(const ExpiredLattice &Other) const {
+    return Expired == Other.Expired;
+  }
+  bool operator!=(const ExpiredLattice &Other) const {
+    return !(*this == Other);
+  }
+
+  /// Computes the union of two lattices.
+  ExpiredLattice join(const ExpiredLattice &Other,
+                      LoanSet::Factory &Factory) const {
+    LoanSet JoinedSet = Expired;
+    for (LoanID LID : Other.Expired)
+      JoinedSet = Factory.add(JoinedSet, LID);
+    return ExpiredLattice(JoinedSet);
+  }
+
+  void dump(llvm::raw_ostream &OS) const {
+    OS << "ExpiredLattice State:\n";
+    if (Expired.isEmpty())
+      OS << "  <empty>\n";
+    for (const LoanID &LID : Expired)
+      OS << "  Loan " << LID << " is expired\n";
+  }
+};
+
+/// Transfer function for the expired loans analysis.
+class ExpiredLoansTransferer {
+  FactManager &AllFacts;
+  LoanSet::Factory &SetFactory;
+
+public:
+  explicit ExpiredLoansTransferer(FactManager &F, LoanSet::Factory &SF)
+      : AllFacts(F), SetFactory(SF) {}
+
+  /// Computes the exit state of a block by applying all its facts sequentially
+  /// to a given entry state.
+  ExpiredLattice transferBlock(const CFGBlock *Block,
+                                ExpiredLattice EntryState) {
+    ExpiredLattice BlockState = EntryState;
+    llvm::ArrayRef<const Fact *> Facts = AllFacts.getFacts(Block);
+
+    for (const Fact *F : Facts) {
+      BlockState = transferFact(BlockState, F);
+    }
+    return BlockState;
+  }
+
+private:
+  ExpiredLattice transferFact(ExpiredLattice In, const Fact *F) {
+    if (const auto *EF = F->getAs<ExpireFact>())
+      return ExpiredLattice(SetFactory.add(In.Expired, EF->getLoanID()));
+
+    if (const auto *IF = F->getAs<IssueFact>())
+      return ExpiredLattice(SetFactory.remove(In.Expired, IF->getLoanID()));
+
+    return In;
+  }
+};
+
+/// Dataflow analysis driver for tracking expired loans.
+class ExpiredLoansAnalysis {
+  const CFG &Cfg;
+  AnalysisDeclContext &AC;
+  LoanSet::Factory SetFactory;
+  ExpiredLoansTransferer Xfer;
+
+  llvm::DenseMap<const CFGBlock *, ExpiredLattice> BlockEntryStates;
+  llvm::DenseMap<const CFGBlock *, ExpiredLattice> BlockExitStates;
+
+public:
+  ExpiredLoansAnalysis(const CFG &C, FactManager &FS, AnalysisDeclContext &AC)
+      : Cfg(C), AC(AC), Xfer(FS, SetFactory) {}
+
+  void run() {
+    llvm::TimeTraceScope TimeProfile("Expired Loans Analysis");
+    ForwardDataflowWorklist Worklist(Cfg, AC);
+    const CFGBlock *Entry = &Cfg.getEntry();
+    BlockEntryStates[Entry] = ExpiredLattice(SetFactory.getEmptySet());
+    Worklist.enqueueBlock(Entry);
+    while (const CFGBlock *B = Worklist.dequeue()) {
+      ExpiredLattice EntryState = getEntryState(B);
+      ExpiredLattice ExitState = Xfer.transferBlock(B, EntryState);
+      BlockExitStates[B] = ExitState;
+
+      for (const CFGBlock *Successor : B->succs()) {
+        auto SuccIt = BlockEntryStates.find(Successor);
+        ExpiredLattice OldSuccEntryState = (SuccIt != BlockEntryStates.end())
+                                                ? SuccIt->second
+                                                : ExpiredLattice{};
+        ExpiredLattice NewSuccEntryState =
+            OldSuccEntryState.join(ExitState, SetFactory);
+        if (SuccIt == BlockEntryStates.end() ||
+            NewSuccEntryState != OldSuccEntryState) {
+          BlockEntryStates[Successor] = NewSuccEntryState;
+          Worklist.enqueueBlock(Successor);
+        }
+      }
+    }
+  }
+
+  void dump() const {
+    llvm::dbgs() << "==========================================\n";
+    llvm::dbgs() << "       Expired Loans Results:\n";
+    llvm::dbgs() << "==========================================\n";
+    const CFGBlock &B = Cfg.getExit();
+    getExitState(&B).dump(llvm::dbgs());
+  }
+
+  ExpiredLattice getEntryState(const CFGBlock *B) const {
+    auto It = BlockEntryStates.find(B);
+    if (It != BlockEntryStates.end()) {
+      return It->second;
+    }
+    return ExpiredLattice(SetFactory.getEmptySet());
+  }
+
+  ExpiredLattice getExitState(const CFGBlock *B) const {
+    auto It = BlockExitStates.find(B);
+    if (It != BlockExitStates.end()) {
+      return It->second;
+    }
+    return ExpiredLattice(SetFactory.getEmptySet());
+  }
+};
+
 // ========================================================================= //
 //  TODO: Analysing dataflow results and error reporting.
 // ========================================================================= //
@@ -762,5 +898,9 @@ void runLifetimeSafetyAnalysis(const DeclContext &DC, const 
CFG &Cfg,
   LifetimeDataflow Dataflow(Cfg, FactMgr, AC);
   Dataflow.run();
   DEBUG_WITH_TYPE("LifetimeDataflow", Dataflow.dump());
+
+  ExpiredLoansAnalysis ExpiredAnalysis(Cfg, FactMgr, AC);
+  ExpiredAnalysis.run();
+  DEBUG_WITH_TYPE("ExpiredLoans", ExpiredAnalysis.dump());
 }
 } // namespace clang

_______________________________________________
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits

Reply via email to