[clang] LoanPropagation use pimpl style (PR #201071)

Utkarsh Saxena via cfe-commits cfe-commits at lists.llvm.org
Tue Jun 2 02:13:41 PDT 2026


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

LoanPropagation use pimpl style

update tests

>From e7556110c765675ba740faf522e983a186ddecf5 Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena <usx at google.com>
Date: Tue, 2 Jun 2026 09:10:23 +0000
Subject: [PATCH 1/2] LoanPropagation use pimpl style

---
 .../Analyses/LifetimeSafety/LoanPropagation.h |  4 +-
 .../LifetimeSafety/LoanPropagation.cpp        | 86 ++++++++++---------
 2 files changed, 48 insertions(+), 42 deletions(-)

diff --git a/clang/include/clang/Analysis/Analyses/LifetimeSafety/LoanPropagation.h b/clang/include/clang/Analysis/Analyses/LifetimeSafety/LoanPropagation.h
index 168223c42e2b2..e46912bedeb0f 100644
--- a/clang/include/clang/Analysis/Analyses/LifetimeSafety/LoanPropagation.h
+++ b/clang/include/clang/Analysis/Analyses/LifetimeSafety/LoanPropagation.h
@@ -45,8 +45,8 @@ class LoanPropagationAnalysis {
   /// sequence of origins through which the loan flowed, ending at the origin
   /// where the loan was originally issued.
   llvm::SmallVector<OriginID>
-  buildOriginFlowChain(const FactManager &FactMgr, ProgramPoint StartPoint,
-                       const OriginID StartOID, const LoanID TargetLoan) const;
+  buildOriginFlowChain(ProgramPoint StartPoint, const OriginID StartOID,
+                       const LoanID TargetLoan) const;
 
 private:
   class Impl;
diff --git a/clang/lib/Analysis/LifetimeSafety/LoanPropagation.cpp b/clang/lib/Analysis/LifetimeSafety/LoanPropagation.cpp
index cc24829281214..8c570cd29673b 100644
--- a/clang/lib/Analysis/LifetimeSafety/LoanPropagation.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/LoanPropagation.cpp
@@ -198,6 +198,47 @@ class AnalysisImpl
     return getLoans(getState(P), OID);
   }
 
+  llvm::SmallVector<OriginID>
+  buildOriginFlowChain(ProgramPoint StartPoint, const OriginID StartOID,
+                       const LoanID TargetLoan) const {
+    assert(getLoans(StartOID, StartPoint).contains(TargetLoan) &&
+           "TargetLoan must be present in the StartOID at the StartPoint");
+
+    OriginID CurrOID = StartOID;
+    llvm::SmallVector<OriginID> OriginFlowChain;
+    llvm::ArrayRef<const Fact *> Facts = FactMgr.getBlockContaining(StartPoint);
+    const auto *StartIt = llvm::find(Facts, StartPoint);
+    assert(StartIt != Facts.end());
+
+    for (const Fact *F :
+         llvm::reverse(llvm::make_range(Facts.begin(), StartIt))) {
+      if (const auto *IF = F->getAs<IssueFact>())
+        if (IF->getLoanID() == TargetLoan) {
+          assert(IF->getOriginID() == CurrOID);
+          return OriginFlowChain;
+        }
+
+      const auto *OFF = F->getAs<OriginFlowFact>();
+      if (!OFF)
+        continue;
+      if (OFF->getDestOriginID() != CurrOID)
+        continue;
+
+      const OriginID SrcOriginID = OFF->getSrcOriginID();
+      if (!getLoans(SrcOriginID, OFF).contains(TargetLoan))
+        continue;
+      OriginFlowChain.push_back(SrcOriginID);
+      CurrOID = SrcOriginID;
+    }
+
+    // FIXME: Ideally, this return is unreachable and should be an assert
+    // because we expect to always finish at an IssueFact. But since current
+    // traversal is limited to a single CFG block, multi-block OriginFlowChain
+    // construction might miss the IssueFact. We should add llvm_unreachable
+    // here once multi-block support is implemented.
+    return {};
+  }
+
 private:
   /// Returns true if the origin is persistent (referenced in multiple blocks).
   bool isPersistent(OriginID OID) const {
@@ -248,45 +289,10 @@ LoanSet LoanPropagationAnalysis::getLoans(OriginID OID, ProgramPoint P) const {
   return PImpl->getLoans(OID, P);
 }
 
-llvm::SmallVector<OriginID> LoanPropagationAnalysis::buildOriginFlowChain(
-    const FactManager &FactMgr, ProgramPoint StartPoint,
-    const OriginID StartOID, const LoanID TargetLoan) const {
-  assert(getLoans(StartOID, StartPoint).contains(TargetLoan) &&
-         "TargetLoan must be present in the StartOID at the StartPoint");
-
-  OriginID CurrOID = StartOID;
-  llvm::SmallVector<OriginID> OriginFlowChain;
-  llvm::ArrayRef<const Fact *> Facts = FactMgr.getBlockContaining(StartPoint);
-  const auto *StartIt = llvm::find(Facts, StartPoint);
-  assert(StartIt != Facts.end());
-
-  for (const Fact *F :
-       llvm::reverse(llvm::make_range(Facts.begin(), StartIt))) {
-    if (const auto *IF = F->getAs<IssueFact>())
-      if (IF->getLoanID() == TargetLoan) {
-        assert(IF->getOriginID() == CurrOID);
-        return OriginFlowChain;
-      }
-
-    const auto *OFF = F->getAs<OriginFlowFact>();
-    if (!OFF)
-      continue;
-    if (OFF->getDestOriginID() != CurrOID)
-      continue;
-
-    const OriginID SrcOriginID = OFF->getSrcOriginID();
-    if (!getLoans(SrcOriginID, OFF).contains(TargetLoan))
-      continue;
-    OriginFlowChain.push_back(SrcOriginID);
-    CurrOID = SrcOriginID;
-  }
-
-  // FIXME: Ideally, this return is unreachable and should be an assert because
-  // we expect to always finish at an IssueFact. But since current traversal is
-  // limited to a single CFG block, multi-block OriginFlowChain construction
-  // might miss the IssueFact.
-  // We should add llvm_unreachable here once multi-block support is
-  // implemented.
-  return {};
+llvm::SmallVector<OriginID>
+LoanPropagationAnalysis::buildOriginFlowChain(ProgramPoint StartPoint,
+                                              const OriginID StartOID,
+                                              const LoanID TargetLoan) const {
+  return PImpl->buildOriginFlowChain(StartPoint, StartOID, TargetLoan);
 }
 } // namespace clang::lifetimes::internal

>From 1812396fdc8011c1dc5c7e90944a1c597228dc91 Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena <usx at google.com>
Date: Tue, 2 Jun 2026 09:13:08 +0000
Subject: [PATCH 2/2] update tests

---
 clang/unittests/Analysis/LifetimeSafetyTest.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/clang/unittests/Analysis/LifetimeSafetyTest.cpp b/clang/unittests/Analysis/LifetimeSafetyTest.cpp
index 7105f3de2891e..febecb472455a 100644
--- a/clang/unittests/Analysis/LifetimeSafetyTest.cpp
+++ b/clang/unittests/Analysis/LifetimeSafetyTest.cpp
@@ -215,7 +215,6 @@ class LifetimeTestHelper {
     for (LoanID LID : EndLoanIDs) {
       const llvm::SmallVector<OriginID> OriginFlowChain =
           Runner.getAnalysis().getLoanPropagation().buildOriginFlowChain(
-              Runner.getAnalysis().getFactManager(),
               getProgramPoint(Annotation), *StartOriginID, LID);
       if (!OriginFlowChain.empty())
         return OriginFlowChain;



More information about the cfe-commits mailing list