https://github.com/DEBADRIBASAK updated 
https://github.com/llvm/llvm-project/pull/170444

>From a7f5c0cc51ee72bfdd150eb6e4b7aa2b20e24373 Mon Sep 17 00:00:00 2001
From: Debadri Basak <[email protected]>
Date: Wed, 3 Dec 2025 09:11:15 +0000
Subject: [PATCH 1/8] Adding an integer flag for setting a threhsold for
 skipping large CFGs and a debug-only flag for printing CFG size stats.

In this context, CFG size refers to the number of facts generated by the fact 
generator. This is a change to effectively control bail-out strategies.
---
 .../Analyses/LifetimeSafety/Checker.h         |  3 ++-
 .../Analysis/Analyses/LifetimeSafety/Facts.h  |  7 +++++++
 .../Analyses/LifetimeSafety/LifetimeSafety.h  |  7 +++++--
 clang/include/clang/Basic/LangOptions.def     |  3 +++
 clang/include/clang/Options/Options.td        |  4 ++++
 clang/lib/Analysis/LifetimeSafety/Checker.cpp | 16 ++++++++++----
 clang/lib/Analysis/LifetimeSafety/Facts.cpp   | 21 +++++++++++++++++++
 .../LifetimeSafety/LifetimeSafety.cpp         | 15 ++++++++-----
 clang/lib/Sema/AnalysisBasedWarnings.cpp      |  2 +-
 9 files changed, 65 insertions(+), 13 deletions(-)

diff --git a/clang/include/clang/Analysis/Analyses/LifetimeSafety/Checker.h 
b/clang/include/clang/Analysis/Analyses/LifetimeSafety/Checker.h
index 03636be7d00c3..c609543575e0f 100644
--- a/clang/include/clang/Analysis/Analyses/LifetimeSafety/Checker.h
+++ b/clang/include/clang/Analysis/Analyses/LifetimeSafety/Checker.h
@@ -28,7 +28,8 @@ namespace clang::lifetimes::internal {
 void runLifetimeChecker(const LoanPropagationAnalysis &LoanPropagation,
                         const LiveOriginsAnalysis &LiveOrigins,
                         const FactManager &FactMgr, AnalysisDeclContext &ADC,
-                        LifetimeSafetyReporter *Reporter);
+                        LifetimeSafetyReporter *Reporter,
+                    uint32_t BlockFactNumThreshold);
 
 } // namespace clang::lifetimes::internal
 
diff --git a/clang/include/clang/Analysis/Analyses/LifetimeSafety/Facts.h 
b/clang/include/clang/Analysis/Analyses/LifetimeSafety/Facts.h
index b5f7f8746186a..5e7e93118bf10 100644
--- a/clang/include/clang/Analysis/Analyses/LifetimeSafety/Facts.h
+++ b/clang/include/clang/Analysis/Analyses/LifetimeSafety/Facts.h
@@ -218,6 +218,9 @@ class FactManager {
 
   void dump(const CFG &Cfg, AnalysisDeclContext &AC) const;
 
+  // A utility function to print the size of the CFG blocks in the analysis 
context.
+  void dumpBlockSizes(const CFG &Cfg, AnalysisDeclContext &AC) const;
+
   /// Retrieves program points that were specially marked in the source code
   /// for testing.
   ///
@@ -238,6 +241,9 @@ class FactManager {
   const LoanManager &getLoanMgr() const { return LoanMgr; }
   OriginManager &getOriginMgr() { return OriginMgr; }
   const OriginManager &getOriginMgr() const { return OriginMgr; }
+  void setBlockFactNumThreshold(uint32_t Threshold) {
+    BlockFactNumThreshold = Threshold;
+  }
 
 private:
   FactID NextFactID{0};
@@ -246,6 +252,7 @@ class FactManager {
   /// Facts for each CFG block, indexed by block ID.
   llvm::SmallVector<llvm::SmallVector<const Fact *>> BlockToFacts;
   llvm::BumpPtrAllocator FactAllocator;
+  uint32_t BlockFactNumThreshold = 0;
 };
 } // namespace clang::lifetimes::internal
 
diff --git 
a/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h 
b/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h
index b34a7f18b5809..29078756b3e15 100644
--- a/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h
+++ b/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h
@@ -51,7 +51,8 @@ class LifetimeSafetyReporter {
 
 /// The main entry point for the analysis.
 void runLifetimeSafetyAnalysis(AnalysisDeclContext &AC,
-                               LifetimeSafetyReporter *Reporter);
+                               LifetimeSafetyReporter *Reporter,
+                              uint32_t BlockFactNumThreshold);
 
 namespace internal {
 /// An object to hold the factories for immutable collections, ensuring
@@ -67,7 +68,8 @@ struct LifetimeFactory {
 class LifetimeSafetyAnalysis {
 public:
   LifetimeSafetyAnalysis(AnalysisDeclContext &AC,
-                         LifetimeSafetyReporter *Reporter);
+                         LifetimeSafetyReporter *Reporter,
+                        uint32_t BlockFactNumThreshold);
 
   void run();
 
@@ -79,6 +81,7 @@ class LifetimeSafetyAnalysis {
   FactManager &getFactManager() { return FactMgr; }
 
 private:
+  uint32_t BlockFactNumThreshold;
   AnalysisDeclContext &AC;
   LifetimeSafetyReporter *Reporter;
   LifetimeFactory Factory;
diff --git a/clang/include/clang/Basic/LangOptions.def 
b/clang/include/clang/Basic/LangOptions.def
index 40fc66ea12e34..9b6e36f0ace3a 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -501,6 +501,9 @@ LANGOPT(EnableLifetimeSafety, 1, 0, NotCompatible, 
"Experimental lifetime safety
 
 LANGOPT(PreserveVec3Type, 1, 0, NotCompatible, "Preserve 3-component vector 
type")
 
+LANGOPT(BlockFactNumThreshold, 32, 0, NotCompatible, "Experimental CFG bailout 
size threshold for C++")
+
+
 #undef LANGOPT
 #undef ENUM_LANGOPT
 #undef VALUE_LANGOPT
diff --git a/clang/include/clang/Options/Options.td 
b/clang/include/clang/Options/Options.td
index 756d6deed7130..7d227b3d5e194 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -5166,6 +5166,10 @@ def ffuchsia_api_level_EQ : Joined<["-"], 
"ffuchsia-api-level=">,
   Group<m_Group>, Visibility<[ClangOption, CC1Option]>,
   HelpText<"Set Fuchsia API level">,
   MarshallingInfoInt<LangOpts<"FuchsiaAPILevel">>;
+def fblock_size_threshold : Joined<["-"], "fblock-size-threshold=">,
+  Group<m_Group>, Visibility<[ClangOption, CC1Option]>,
+  HelpText<"Set Threshold for block size above which lifetime analysis will be 
skipped">,
+  MarshallingInfoInt<LangOpts<"BlockFactNumThreshold">>;
 def mmacos_version_min_EQ : Joined<["-"], "mmacos-version-min=">,
   Visibility<[ClangOption, CC1Option, FlangOption]>,
   Group<m_Group>, HelpText<"Set macOS deployment target">;
diff --git a/clang/lib/Analysis/LifetimeSafety/Checker.cpp 
b/clang/lib/Analysis/LifetimeSafety/Checker.cpp
index 1f7c282dadac2..ec5377bf8168e 100644
--- a/clang/lib/Analysis/LifetimeSafety/Checker.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/Checker.cpp
@@ -58,13 +58,20 @@ class LifetimeChecker {
 public:
   LifetimeChecker(const LoanPropagationAnalysis &LoanPropagation,
                   const LiveOriginsAnalysis &LiveOrigins, const FactManager 
&FM,
-                  AnalysisDeclContext &ADC, LifetimeSafetyReporter *Reporter)
+                  AnalysisDeclContext &ADC, LifetimeSafetyReporter *Reporter, 
uint32_t BlockFactNumThreshold)
       : LoanPropagation(LoanPropagation), LiveOrigins(LiveOrigins), 
FactMgr(FM),
         Reporter(Reporter) {
-    for (const CFGBlock *B : *ADC.getAnalysis<PostOrderCFGView>())
+    if (BlockFactNumThreshold <= 0) {
+      llvm::errs() << "Warning: BlockFactNumThreshold should be positive.\n";
+    }
+    for (const CFGBlock *B : *ADC.getAnalysis<PostOrderCFGView>()) {
+      const auto& BlockFacts = FactMgr.getFacts(B);
+      if (BlockFactNumThreshold > 0 && BlockFacts.size() > 
BlockFactNumThreshold)
+        continue;
       for (const Fact *F : FactMgr.getFacts(B))
         if (const auto *EF = F->getAs<ExpireFact>())
           checkExpiry(EF);
+    }
     issuePendingWarnings();
   }
 
@@ -138,9 +145,10 @@ class LifetimeChecker {
 void runLifetimeChecker(const LoanPropagationAnalysis &LP,
                         const LiveOriginsAnalysis &LO,
                         const FactManager &FactMgr, AnalysisDeclContext &ADC,
-                        LifetimeSafetyReporter *Reporter) {
+                        LifetimeSafetyReporter *Reporter,
+                      uint32_t BlockFactNumThreshold) {
   llvm::TimeTraceScope TimeProfile("LifetimeChecker");
-  LifetimeChecker Checker(LP, LO, FactMgr, ADC, Reporter);
+  LifetimeChecker Checker(LP, LO, FactMgr, ADC, Reporter, 
BlockFactNumThreshold);
 }
 
 } // namespace clang::lifetimes::internal
diff --git a/clang/lib/Analysis/LifetimeSafety/Facts.cpp 
b/clang/lib/Analysis/LifetimeSafety/Facts.cpp
index 0ae7111c489e8..845c7f18df608 100644
--- a/clang/lib/Analysis/LifetimeSafety/Facts.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/Facts.cpp
@@ -95,6 +95,27 @@ void FactManager::dump(const CFG &Cfg, AnalysisDeclContext 
&AC) const {
   }
 }
 
+void FactManager::dumpBlockSizes(const CFG &Cfg,
+                                 AnalysisDeclContext &AC) const {
+  llvm::dbgs() << "==========================================\n";
+  llvm::dbgs() << "       Lifetime Analysis CFG Block Sizes:\n";
+  llvm::dbgs() << "==========================================\n";
+  if (const Decl *D = AC.getDecl())
+    if (const auto *ND = dyn_cast<NamedDecl>(D))
+      llvm::dbgs() << "Function: " << ND->getQualifiedNameAsString() << "\n";
+  // Print blocks in the order as they appear in code for a stable ordering.
+  for (const CFGBlock *B : *AC.getAnalysis<PostOrderCFGView>()) {
+    if (getFacts(B).size() > BlockFactNumThreshold)
+      continue;
+    if (B->getLabel()) {
+      llvm::dbgs() << "  Block: " << B->getLabel()->getStmtClassName();
+    } else {
+      llvm::dbgs() << "  Block B" << B->getBlockID();
+    }
+    llvm::dbgs() << ": Number of facts = " << getFacts(B).size() << "\n";
+  }
+}
+
 llvm::ArrayRef<const Fact *>
 FactManager::getBlockContaining(ProgramPoint P) const {
   for (const auto &BlockToFactsVec : BlockToFacts) {
diff --git a/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp 
b/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp
index a51ba4280f284..d057e9fa08c73 100644
--- a/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp
@@ -32,8 +32,11 @@ namespace clang::lifetimes {
 namespace internal {
 
 LifetimeSafetyAnalysis::LifetimeSafetyAnalysis(AnalysisDeclContext &AC,
-                                               LifetimeSafetyReporter 
*Reporter)
-    : AC(AC), Reporter(Reporter) {}
+                                               LifetimeSafetyReporter 
*Reporter,
+                                              uint32_t BlockFactNumThreshold)
+    : BlockFactNumThreshold(BlockFactNumThreshold), AC(AC), Reporter(Reporter) 
{
+  FactMgr.setBlockFactNumThreshold(BlockFactNumThreshold);
+    }
 
 void LifetimeSafetyAnalysis::run() {
   llvm::TimeTraceScope TimeProfile("LifetimeSafetyAnalysis");
@@ -46,6 +49,7 @@ void LifetimeSafetyAnalysis::run() {
   FactsGenerator FactGen(FactMgr, AC);
   FactGen.run();
   DEBUG_WITH_TYPE("LifetimeFacts", FactMgr.dump(Cfg, AC));
+  DEBUG_WITH_TYPE("LifetimeCFGSizes", FactMgr.dumpBlockSizes(Cfg, AC));
 
   /// TODO(opt): Consider optimizing individual blocks before running the
   /// dataflow analysis.
@@ -66,13 +70,14 @@ void LifetimeSafetyAnalysis::run() {
   DEBUG_WITH_TYPE("LiveOrigins",
                   LiveOrigins->dump(llvm::dbgs(), FactMgr.getTestPoints()));
 
-  runLifetimeChecker(*LoanPropagation, *LiveOrigins, FactMgr, AC, Reporter);
+  runLifetimeChecker(*LoanPropagation, *LiveOrigins, FactMgr, AC, Reporter, 
BlockFactNumThreshold);
 }
 } // namespace internal
 
 void runLifetimeSafetyAnalysis(AnalysisDeclContext &AC,
-                               LifetimeSafetyReporter *Reporter) {
-  internal::LifetimeSafetyAnalysis Analysis(AC, Reporter);
+                               LifetimeSafetyReporter *Reporter,
+                              uint32_t BlockFactNumThreshold) {
+  internal::LifetimeSafetyAnalysis Analysis(AC, Reporter, 
BlockFactNumThreshold);
   Analysis.run();
 }
 } // namespace clang::lifetimes
diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp 
b/clang/lib/Sema/AnalysisBasedWarnings.cpp
index 43d2b9a829545..b379279115784 100644
--- a/clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -3107,7 +3107,7 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings(
   if (EnableLifetimeSafetyAnalysis && S.getLangOpts().CPlusPlus) {
     if (AC.getCFG()) {
       lifetimes::LifetimeSafetyReporterImpl LifetimeSafetyReporter(S);
-      lifetimes::runLifetimeSafetyAnalysis(AC, &LifetimeSafetyReporter);
+      lifetimes::runLifetimeSafetyAnalysis(AC, &LifetimeSafetyReporter, 
S.getLangOpts().BlockFactNumThreshold);
     }
   }
   // Check for violations of "called once" parameter properties.

>From 1f989f9103e73c439d3c63e1e74d7797a7339a0b Mon Sep 17 00:00:00 2001
From: Debadri Basak <[email protected]>
Date: Wed, 3 Dec 2025 09:13:39 +0000
Subject: [PATCH 2/8] Formatting changes

---
 .../Analysis/Analyses/LifetimeSafety/Checker.h      |  2 +-
 .../clang/Analysis/Analyses/LifetimeSafety/Facts.h  |  3 ++-
 .../Analyses/LifetimeSafety/LifetimeSafety.h        |  4 ++--
 clang/include/clang/Options/Options.td              | 11 +++++++----
 clang/lib/Analysis/LifetimeSafety/Checker.cpp       | 13 ++++++++-----
 .../lib/Analysis/LifetimeSafety/LifetimeSafety.cpp  | 12 +++++++-----
 clang/lib/Sema/AnalysisBasedWarnings.cpp            |  3 ++-
 7 files changed, 29 insertions(+), 19 deletions(-)

diff --git a/clang/include/clang/Analysis/Analyses/LifetimeSafety/Checker.h 
b/clang/include/clang/Analysis/Analyses/LifetimeSafety/Checker.h
index c609543575e0f..be10f298ab2ff 100644
--- a/clang/include/clang/Analysis/Analyses/LifetimeSafety/Checker.h
+++ b/clang/include/clang/Analysis/Analyses/LifetimeSafety/Checker.h
@@ -29,7 +29,7 @@ void runLifetimeChecker(const LoanPropagationAnalysis 
&LoanPropagation,
                         const LiveOriginsAnalysis &LiveOrigins,
                         const FactManager &FactMgr, AnalysisDeclContext &ADC,
                         LifetimeSafetyReporter *Reporter,
-                    uint32_t BlockFactNumThreshold);
+                        uint32_t BlockFactNumThreshold);
 
 } // namespace clang::lifetimes::internal
 
diff --git a/clang/include/clang/Analysis/Analyses/LifetimeSafety/Facts.h 
b/clang/include/clang/Analysis/Analyses/LifetimeSafety/Facts.h
index 5e7e93118bf10..c6680d234ddba 100644
--- a/clang/include/clang/Analysis/Analyses/LifetimeSafety/Facts.h
+++ b/clang/include/clang/Analysis/Analyses/LifetimeSafety/Facts.h
@@ -218,7 +218,8 @@ class FactManager {
 
   void dump(const CFG &Cfg, AnalysisDeclContext &AC) const;
 
-  // A utility function to print the size of the CFG blocks in the analysis 
context.
+  // A utility function to print the size of the CFG blocks in the analysis
+  // context.
   void dumpBlockSizes(const CFG &Cfg, AnalysisDeclContext &AC) const;
 
   /// Retrieves program points that were specially marked in the source code
diff --git 
a/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h 
b/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h
index 29078756b3e15..95b0ed71af3e0 100644
--- a/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h
+++ b/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h
@@ -52,7 +52,7 @@ class LifetimeSafetyReporter {
 /// The main entry point for the analysis.
 void runLifetimeSafetyAnalysis(AnalysisDeclContext &AC,
                                LifetimeSafetyReporter *Reporter,
-                              uint32_t BlockFactNumThreshold);
+                               uint32_t BlockFactNumThreshold);
 
 namespace internal {
 /// An object to hold the factories for immutable collections, ensuring
@@ -69,7 +69,7 @@ class LifetimeSafetyAnalysis {
 public:
   LifetimeSafetyAnalysis(AnalysisDeclContext &AC,
                          LifetimeSafetyReporter *Reporter,
-                        uint32_t BlockFactNumThreshold);
+                         uint32_t BlockFactNumThreshold);
 
   void run();
 
diff --git a/clang/include/clang/Options/Options.td 
b/clang/include/clang/Options/Options.td
index 7d227b3d5e194..dd367e4555228 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -5166,10 +5166,13 @@ def ffuchsia_api_level_EQ : Joined<["-"], 
"ffuchsia-api-level=">,
   Group<m_Group>, Visibility<[ClangOption, CC1Option]>,
   HelpText<"Set Fuchsia API level">,
   MarshallingInfoInt<LangOpts<"FuchsiaAPILevel">>;
-def fblock_size_threshold : Joined<["-"], "fblock-size-threshold=">,
-  Group<m_Group>, Visibility<[ClangOption, CC1Option]>,
-  HelpText<"Set Threshold for block size above which lifetime analysis will be 
skipped">,
-  MarshallingInfoInt<LangOpts<"BlockFactNumThreshold">>;
+def fblock_size_threshold
+    : Joined<["-"], "fblock-size-threshold=">,
+      Group<m_Group>,
+      Visibility<[ClangOption, CC1Option]>,
+      HelpText<"Set Threshold for block size above which lifetime analysis "
+               "will be skipped">,
+      MarshallingInfoInt<LangOpts<"BlockFactNumThreshold">>;
 def mmacos_version_min_EQ : Joined<["-"], "mmacos-version-min=">,
   Visibility<[ClangOption, CC1Option, FlangOption]>,
   Group<m_Group>, HelpText<"Set macOS deployment target">;
diff --git a/clang/lib/Analysis/LifetimeSafety/Checker.cpp 
b/clang/lib/Analysis/LifetimeSafety/Checker.cpp
index ec5377bf8168e..89415d1f0bf02 100644
--- a/clang/lib/Analysis/LifetimeSafety/Checker.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/Checker.cpp
@@ -58,15 +58,17 @@ class LifetimeChecker {
 public:
   LifetimeChecker(const LoanPropagationAnalysis &LoanPropagation,
                   const LiveOriginsAnalysis &LiveOrigins, const FactManager 
&FM,
-                  AnalysisDeclContext &ADC, LifetimeSafetyReporter *Reporter, 
uint32_t BlockFactNumThreshold)
+                  AnalysisDeclContext &ADC, LifetimeSafetyReporter *Reporter,
+                  uint32_t BlockFactNumThreshold)
       : LoanPropagation(LoanPropagation), LiveOrigins(LiveOrigins), 
FactMgr(FM),
         Reporter(Reporter) {
     if (BlockFactNumThreshold <= 0) {
       llvm::errs() << "Warning: BlockFactNumThreshold should be positive.\n";
     }
     for (const CFGBlock *B : *ADC.getAnalysis<PostOrderCFGView>()) {
-      const auto& BlockFacts = FactMgr.getFacts(B);
-      if (BlockFactNumThreshold > 0 && BlockFacts.size() > 
BlockFactNumThreshold)
+      const auto &BlockFacts = FactMgr.getFacts(B);
+      if (BlockFactNumThreshold > 0 &&
+          BlockFacts.size() > BlockFactNumThreshold)
         continue;
       for (const Fact *F : FactMgr.getFacts(B))
         if (const auto *EF = F->getAs<ExpireFact>())
@@ -146,9 +148,10 @@ void runLifetimeChecker(const LoanPropagationAnalysis &LP,
                         const LiveOriginsAnalysis &LO,
                         const FactManager &FactMgr, AnalysisDeclContext &ADC,
                         LifetimeSafetyReporter *Reporter,
-                      uint32_t BlockFactNumThreshold) {
+                        uint32_t BlockFactNumThreshold) {
   llvm::TimeTraceScope TimeProfile("LifetimeChecker");
-  LifetimeChecker Checker(LP, LO, FactMgr, ADC, Reporter, 
BlockFactNumThreshold);
+  LifetimeChecker Checker(LP, LO, FactMgr, ADC, Reporter,
+                          BlockFactNumThreshold);
 }
 
 } // namespace clang::lifetimes::internal
diff --git a/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp 
b/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp
index d057e9fa08c73..36f48ae83dfc8 100644
--- a/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp
@@ -33,10 +33,10 @@ namespace internal {
 
 LifetimeSafetyAnalysis::LifetimeSafetyAnalysis(AnalysisDeclContext &AC,
                                                LifetimeSafetyReporter 
*Reporter,
-                                              uint32_t BlockFactNumThreshold)
+                                               uint32_t BlockFactNumThreshold)
     : BlockFactNumThreshold(BlockFactNumThreshold), AC(AC), Reporter(Reporter) 
{
   FactMgr.setBlockFactNumThreshold(BlockFactNumThreshold);
-    }
+}
 
 void LifetimeSafetyAnalysis::run() {
   llvm::TimeTraceScope TimeProfile("LifetimeSafetyAnalysis");
@@ -70,14 +70,16 @@ void LifetimeSafetyAnalysis::run() {
   DEBUG_WITH_TYPE("LiveOrigins",
                   LiveOrigins->dump(llvm::dbgs(), FactMgr.getTestPoints()));
 
-  runLifetimeChecker(*LoanPropagation, *LiveOrigins, FactMgr, AC, Reporter, 
BlockFactNumThreshold);
+  runLifetimeChecker(*LoanPropagation, *LiveOrigins, FactMgr, AC, Reporter,
+                     BlockFactNumThreshold);
 }
 } // namespace internal
 
 void runLifetimeSafetyAnalysis(AnalysisDeclContext &AC,
                                LifetimeSafetyReporter *Reporter,
-                              uint32_t BlockFactNumThreshold) {
-  internal::LifetimeSafetyAnalysis Analysis(AC, Reporter, 
BlockFactNumThreshold);
+                               uint32_t BlockFactNumThreshold) {
+  internal::LifetimeSafetyAnalysis Analysis(AC, Reporter,
+                                            BlockFactNumThreshold);
   Analysis.run();
 }
 } // namespace clang::lifetimes
diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp 
b/clang/lib/Sema/AnalysisBasedWarnings.cpp
index b379279115784..c32e3c007e13c 100644
--- a/clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -3107,7 +3107,8 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings(
   if (EnableLifetimeSafetyAnalysis && S.getLangOpts().CPlusPlus) {
     if (AC.getCFG()) {
       lifetimes::LifetimeSafetyReporterImpl LifetimeSafetyReporter(S);
-      lifetimes::runLifetimeSafetyAnalysis(AC, &LifetimeSafetyReporter, 
S.getLangOpts().BlockFactNumThreshold);
+      lifetimes::runLifetimeSafetyAnalysis(
+          AC, &LifetimeSafetyReporter, S.getLangOpts().BlockFactNumThreshold);
     }
   }
   // Check for violations of "called once" parameter properties.

>From 8294f3f7b95a01f230aa754af7c6703c4cb36177 Mon Sep 17 00:00:00 2001
From: Debadri Basak <[email protected]>
Date: Wed, 3 Dec 2025 09:28:23 +0000
Subject: [PATCH 3/8] Correcting the implementation of block size printing
 function

---
 clang/lib/Analysis/LifetimeSafety/Checker.cpp | 3 ---
 clang/lib/Analysis/LifetimeSafety/Facts.cpp   | 2 +-
 2 files changed, 1 insertion(+), 4 deletions(-)

diff --git a/clang/lib/Analysis/LifetimeSafety/Checker.cpp 
b/clang/lib/Analysis/LifetimeSafety/Checker.cpp
index 89415d1f0bf02..6622600b1ec30 100644
--- a/clang/lib/Analysis/LifetimeSafety/Checker.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/Checker.cpp
@@ -62,9 +62,6 @@ class LifetimeChecker {
                   uint32_t BlockFactNumThreshold)
       : LoanPropagation(LoanPropagation), LiveOrigins(LiveOrigins), 
FactMgr(FM),
         Reporter(Reporter) {
-    if (BlockFactNumThreshold <= 0) {
-      llvm::errs() << "Warning: BlockFactNumThreshold should be positive.\n";
-    }
     for (const CFGBlock *B : *ADC.getAnalysis<PostOrderCFGView>()) {
       const auto &BlockFacts = FactMgr.getFacts(B);
       if (BlockFactNumThreshold > 0 &&
diff --git a/clang/lib/Analysis/LifetimeSafety/Facts.cpp 
b/clang/lib/Analysis/LifetimeSafety/Facts.cpp
index 845c7f18df608..98f6de28154d2 100644
--- a/clang/lib/Analysis/LifetimeSafety/Facts.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/Facts.cpp
@@ -105,7 +105,7 @@ void FactManager::dumpBlockSizes(const CFG &Cfg,
       llvm::dbgs() << "Function: " << ND->getQualifiedNameAsString() << "\n";
   // Print blocks in the order as they appear in code for a stable ordering.
   for (const CFGBlock *B : *AC.getAnalysis<PostOrderCFGView>()) {
-    if (getFacts(B).size() > BlockFactNumThreshold)
+    if (BlockFactNumThreshold > 0 && getFacts(B).size() > 
BlockFactNumThreshold)
       continue;
     if (B->getLabel()) {
       llvm::dbgs() << "  Block: " << B->getLabel()->getStmtClassName();

>From 5f0dff2dbf1d4345dab8121406f99e58d250b20c Mon Sep 17 00:00:00 2001
From: Debadri Basak <[email protected]>
Date: Mon, 8 Dec 2025 04:06:29 +0000
Subject: [PATCH 4/8] Adding two flags for origin count based and block count
 based bail-out

---
 .../Analyses/LifetimeSafety/LifetimeSafety.h  | 12 ++++--
 clang/include/clang/Basic/LangOptions.def     |  2 +-
 clang/include/clang/Options/Options.td        | 17 +++++---
 clang/lib/Analysis/LifetimeSafety/Checker.cpp | 13 ++----
 .../LifetimeSafety/LifetimeSafety.cpp         | 42 +++++++++++++++----
 clang/lib/Sema/AnalysisBasedWarnings.cpp      |  2 +-
 .../unittests/Analysis/LifetimeSafetyTest.cpp |  2 +-
 7 files changed, 62 insertions(+), 28 deletions(-)

diff --git 
a/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h 
b/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h
index 95b0ed71af3e0..6b5b71686a758 100644
--- a/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h
+++ b/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h
@@ -24,6 +24,7 @@
 #include "clang/Analysis/Analyses/LifetimeSafety/LiveOrigins.h"
 #include "clang/Analysis/Analyses/LifetimeSafety/LoanPropagation.h"
 #include "clang/Analysis/AnalysisDeclContext.h"
+#include <cstdint>
 
 namespace clang::lifetimes {
 
@@ -52,7 +53,8 @@ class LifetimeSafetyReporter {
 /// The main entry point for the analysis.
 void runLifetimeSafetyAnalysis(AnalysisDeclContext &AC,
                                LifetimeSafetyReporter *Reporter,
-                               uint32_t BlockFactNumThreshold);
+                               uint32_t CfgBlocknumThreshold,
+                                              uint32_t 
CfgOriginCountThreshold);
 
 namespace internal {
 /// An object to hold the factories for immutable collections, ensuring
@@ -69,7 +71,8 @@ class LifetimeSafetyAnalysis {
 public:
   LifetimeSafetyAnalysis(AnalysisDeclContext &AC,
                          LifetimeSafetyReporter *Reporter,
-                         uint32_t BlockFactNumThreshold);
+                         uint32_t CfgBlocknumThreshold,
+                                              uint32_t 
CfgOriginCountThreshold);
 
   void run();
 
@@ -81,7 +84,10 @@ class LifetimeSafetyAnalysis {
   FactManager &getFactManager() { return FactMgr; }
 
 private:
-  uint32_t BlockFactNumThreshold;
+  bool shouldBailOutCFGPreFactGeneration(const CFG& Cfg) const;
+  bool shouldBailOutCFGPostFactGeneration(const CFG& Cfg) const;
+  uint32_t CfgBlocknumThreshold;
+  uint32_t CfgOriginCountThreshold;
   AnalysisDeclContext &AC;
   LifetimeSafetyReporter *Reporter;
   LifetimeFactory Factory;
diff --git a/clang/include/clang/Basic/LangOptions.def 
b/clang/include/clang/Basic/LangOptions.def
index 9b6e36f0ace3a..05830caea2830 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -501,7 +501,7 @@ LANGOPT(EnableLifetimeSafety, 1, 0, NotCompatible, 
"Experimental lifetime safety
 
 LANGOPT(PreserveVec3Type, 1, 0, NotCompatible, "Preserve 3-component vector 
type")
 
-LANGOPT(BlockFactNumThreshold, 32, 0, NotCompatible, "Experimental CFG bailout 
size threshold for C++")
+LANGOPT(CfgBlocknumThreshold, 32, 0, NotCompatible, "Experimental CFG bailout 
size threshold for C++")
 
 
 #undef LANGOPT
diff --git a/clang/include/clang/Options/Options.td 
b/clang/include/clang/Options/Options.td
index dd367e4555228..abe984b440e77 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -5166,13 +5166,20 @@ def ffuchsia_api_level_EQ : Joined<["-"], 
"ffuchsia-api-level=">,
   Group<m_Group>, Visibility<[ClangOption, CC1Option]>,
   HelpText<"Set Fuchsia API level">,
   MarshallingInfoInt<LangOpts<"FuchsiaAPILevel">>;
-def fblock_size_threshold
-    : Joined<["-"], "fblock-size-threshold=">,
+def fcfg_block_num_threshold
+    : Joined<["-"], "fcfg-block-num-threshold=">,
       Group<m_Group>,
       Visibility<[ClangOption, CC1Option]>,
-      HelpText<"Set Threshold for block size above which lifetime analysis "
-               "will be skipped">,
-      MarshallingInfoInt<LangOpts<"BlockFactNumThreshold">>;
+      HelpText<"Set Threshold for number of blocks above which lifetime 
analysis "
+               "will be skipped for a CFG">,
+      MarshallingInfoInt<LangOpts<"CfgBlocknumThreshold">>;
+def fcfg_origin_count_threshold
+    : Joined<["-"], "fcfg-origin-count-threshold=">,
+      Group<m_Group>,
+      Visibility<[ClangOption, CC1Option]>,
+      HelpText<"Set Threshold for number of origins after fact generation 
after which lifetime analysis "
+               "will be skipped for a CFG">,
+      MarshallingInfoInt<LangOpts<"CfgOriginCountThreshold">>;
 def mmacos_version_min_EQ : Joined<["-"], "mmacos-version-min=">,
   Visibility<[ClangOption, CC1Option, FlangOption]>,
   Group<m_Group>, HelpText<"Set macOS deployment target">;
diff --git a/clang/lib/Analysis/LifetimeSafety/Checker.cpp 
b/clang/lib/Analysis/LifetimeSafety/Checker.cpp
index 6622600b1ec30..0ced00f5fadda 100644
--- a/clang/lib/Analysis/LifetimeSafety/Checker.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/Checker.cpp
@@ -58,15 +58,10 @@ class LifetimeChecker {
 public:
   LifetimeChecker(const LoanPropagationAnalysis &LoanPropagation,
                   const LiveOriginsAnalysis &LiveOrigins, const FactManager 
&FM,
-                  AnalysisDeclContext &ADC, LifetimeSafetyReporter *Reporter,
-                  uint32_t BlockFactNumThreshold)
+                  AnalysisDeclContext &ADC, LifetimeSafetyReporter *Reporter)
       : LoanPropagation(LoanPropagation), LiveOrigins(LiveOrigins), 
FactMgr(FM),
         Reporter(Reporter) {
     for (const CFGBlock *B : *ADC.getAnalysis<PostOrderCFGView>()) {
-      const auto &BlockFacts = FactMgr.getFacts(B);
-      if (BlockFactNumThreshold > 0 &&
-          BlockFacts.size() > BlockFactNumThreshold)
-        continue;
       for (const Fact *F : FactMgr.getFacts(B))
         if (const auto *EF = F->getAs<ExpireFact>())
           checkExpiry(EF);
@@ -144,11 +139,9 @@ class LifetimeChecker {
 void runLifetimeChecker(const LoanPropagationAnalysis &LP,
                         const LiveOriginsAnalysis &LO,
                         const FactManager &FactMgr, AnalysisDeclContext &ADC,
-                        LifetimeSafetyReporter *Reporter,
-                        uint32_t BlockFactNumThreshold) {
+                        LifetimeSafetyReporter *Reporter) {
   llvm::TimeTraceScope TimeProfile("LifetimeChecker");
-  LifetimeChecker Checker(LP, LO, FactMgr, ADC, Reporter,
-                          BlockFactNumThreshold);
+  LifetimeChecker Checker(LP, LO, FactMgr, ADC, Reporter);
 }
 
 } // namespace clang::lifetimes::internal
diff --git a/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp 
b/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp
index 36f48ae83dfc8..0865d54261ce7 100644
--- a/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp
@@ -33,21 +33,48 @@ namespace internal {
 
 LifetimeSafetyAnalysis::LifetimeSafetyAnalysis(AnalysisDeclContext &AC,
                                                LifetimeSafetyReporter 
*Reporter,
-                                               uint32_t BlockFactNumThreshold)
-    : BlockFactNumThreshold(BlockFactNumThreshold), AC(AC), Reporter(Reporter) 
{
-  FactMgr.setBlockFactNumThreshold(BlockFactNumThreshold);
+                                               uint32_t CfgBlocknumThreshold,
+                                              uint32_t CfgOriginCountThreshold)
+    : CfgBlocknumThreshold(CfgBlocknumThreshold), 
CfgOriginCountThreshold(CfgOriginCountThreshold), AC(AC), Reporter(Reporter) {
+  FactMgr.setBlockFactNumThreshold(CfgBlocknumThreshold);
+}
+
+bool LifetimeSafetyAnalysis::shouldBailOutCFGPreFactGeneration(const CFG& Cfg) 
const {
+  if (Cfg.getNumBlockIDs() > CfgBlocknumThreshold) {
+    LLVM_DEBUG(llvm::dbgs()
+               << "Lifetime Safety Analysis aborted: CFG too large before fact 
generation ("
+               << Cfg.getNumBlockIDs() << " blocks).\n");
+    return true;
+  }
+  return false;
+}
+
+bool LifetimeSafetyAnalysis::shouldBailOutCFGPostFactGeneration(const CFG& 
Cfg) const {
+  if (FactMgr.getOriginMgr().getNumOrigins() > CfgOriginCountThreshold) {
+    LLVM_DEBUG(llvm::dbgs()
+               << "Lifetime Safety Analysis aborted: Too many origins after 
fact generation ("
+               << FactMgr.getOriginMgr().getNumOrigins() << " origins).\n");
+    return true;
+  }
+  return false;
 }
 
 void LifetimeSafetyAnalysis::run() {
   llvm::TimeTraceScope TimeProfile("LifetimeSafetyAnalysis");
 
   const CFG &Cfg = *AC.getCFG();
+  if (shouldBailOutCFGPreFactGeneration(Cfg)) {
+    return;
+  }
   DEBUG_WITH_TYPE("PrintCFG", Cfg.dump(AC.getASTContext().getLangOpts(),
                                        /*ShowColors=*/true));
   FactMgr.init(Cfg);
 
   FactsGenerator FactGen(FactMgr, AC);
   FactGen.run();
+  if (shouldBailOutCFGPostFactGeneration(Cfg)) {
+    return;
+  }
   DEBUG_WITH_TYPE("LifetimeFacts", FactMgr.dump(Cfg, AC));
   DEBUG_WITH_TYPE("LifetimeCFGSizes", FactMgr.dumpBlockSizes(Cfg, AC));
 
@@ -70,16 +97,17 @@ void LifetimeSafetyAnalysis::run() {
   DEBUG_WITH_TYPE("LiveOrigins",
                   LiveOrigins->dump(llvm::dbgs(), FactMgr.getTestPoints()));
 
-  runLifetimeChecker(*LoanPropagation, *LiveOrigins, FactMgr, AC, Reporter,
-                     BlockFactNumThreshold);
+  runLifetimeChecker(*LoanPropagation, *LiveOrigins, FactMgr, AC, Reporter);
 }
 } // namespace internal
 
 void runLifetimeSafetyAnalysis(AnalysisDeclContext &AC,
                                LifetimeSafetyReporter *Reporter,
-                               uint32_t BlockFactNumThreshold) {
+                               uint32_t CfgBlocknumThreshold,
+                                              uint32_t 
CfgOriginCountThreshold) {
   internal::LifetimeSafetyAnalysis Analysis(AC, Reporter,
-                                            BlockFactNumThreshold);
+                                            CfgBlocknumThreshold,
+                                          CfgOriginCountThreshold);
   Analysis.run();
 }
 } // namespace clang::lifetimes
diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp 
b/clang/lib/Sema/AnalysisBasedWarnings.cpp
index c32e3c007e13c..ba396191bfa5f 100644
--- a/clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -3108,7 +3108,7 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings(
     if (AC.getCFG()) {
       lifetimes::LifetimeSafetyReporterImpl LifetimeSafetyReporter(S);
       lifetimes::runLifetimeSafetyAnalysis(
-          AC, &LifetimeSafetyReporter, S.getLangOpts().BlockFactNumThreshold);
+          AC, &LifetimeSafetyReporter, S.getLangOpts().CfgBlocknumThreshold, 
S.getLangOpts().CfgOriginCountThreshold);
     }
   }
   // Check for violations of "called once" parameter properties.
diff --git a/clang/unittests/Analysis/LifetimeSafetyTest.cpp 
b/clang/unittests/Analysis/LifetimeSafetyTest.cpp
index a895475013c98..157b77841f533 100644
--- a/clang/unittests/Analysis/LifetimeSafetyTest.cpp
+++ b/clang/unittests/Analysis/LifetimeSafetyTest.cpp
@@ -62,7 +62,7 @@ class LifetimeTestRunner {
     BuildOptions.AddLifetime = true;
 
     // Run the main analysis.
-    Analysis = std::make_unique<LifetimeSafetyAnalysis>(*AnalysisCtx, nullptr);
+    Analysis = std::make_unique<LifetimeSafetyAnalysis>(*AnalysisCtx, nullptr, 
0, 0);
     Analysis->run();
 
     AnnotationToPointMap = Analysis->getFactManager().getTestPoints();

>From 58db8bfca9fe6c8371b143d90f397be247e129a4 Mon Sep 17 00:00:00 2001
From: Debadri Basak <[email protected]>
Date: Thu, 11 Dec 2025 07:14:43 +0000
Subject: [PATCH 5/8] Adding block number based bailout logic

---
 .../Analyses/LifetimeSafety/Checker.h         |  3 +-
 .../Analysis/Analyses/LifetimeSafety/Facts.h  |  6 +--
 .../Analyses/LifetimeSafety/LifetimeSafety.h  | 10 ++---
 clang/include/clang/Options/Options.td        | 12 ++----
 clang/lib/Analysis/LifetimeSafety/Facts.cpp   | 15 +++++---
 .../LifetimeSafety/LifetimeSafety.cpp         | 38 +++++++------------
 clang/lib/Sema/AnalysisBasedWarnings.cpp      |  2 +-
 .../unittests/Analysis/LifetimeSafetyTest.cpp |  3 +-
 8 files changed, 35 insertions(+), 54 deletions(-)

diff --git a/clang/include/clang/Analysis/Analyses/LifetimeSafety/Checker.h 
b/clang/include/clang/Analysis/Analyses/LifetimeSafety/Checker.h
index be10f298ab2ff..03636be7d00c3 100644
--- a/clang/include/clang/Analysis/Analyses/LifetimeSafety/Checker.h
+++ b/clang/include/clang/Analysis/Analyses/LifetimeSafety/Checker.h
@@ -28,8 +28,7 @@ namespace clang::lifetimes::internal {
 void runLifetimeChecker(const LoanPropagationAnalysis &LoanPropagation,
                         const LiveOriginsAnalysis &LiveOrigins,
                         const FactManager &FactMgr, AnalysisDeclContext &ADC,
-                        LifetimeSafetyReporter *Reporter,
-                        uint32_t BlockFactNumThreshold);
+                        LifetimeSafetyReporter *Reporter);
 
 } // namespace clang::lifetimes::internal
 
diff --git a/clang/include/clang/Analysis/Analyses/LifetimeSafety/Facts.h 
b/clang/include/clang/Analysis/Analyses/LifetimeSafety/Facts.h
index c6680d234ddba..b10b0a95a82fa 100644
--- a/clang/include/clang/Analysis/Analyses/LifetimeSafety/Facts.h
+++ b/clang/include/clang/Analysis/Analyses/LifetimeSafety/Facts.h
@@ -242,8 +242,8 @@ class FactManager {
   const LoanManager &getLoanMgr() const { return LoanMgr; }
   OriginManager &getOriginMgr() { return OriginMgr; }
   const OriginManager &getOriginMgr() const { return OriginMgr; }
-  void setBlockFactNumThreshold(uint32_t Threshold) {
-    BlockFactNumThreshold = Threshold;
+  void setBlockNumThreshold(uint32_t Threshold) {
+    BlockNumThreshold = Threshold;
   }
 
 private:
@@ -253,7 +253,7 @@ class FactManager {
   /// Facts for each CFG block, indexed by block ID.
   llvm::SmallVector<llvm::SmallVector<const Fact *>> BlockToFacts;
   llvm::BumpPtrAllocator FactAllocator;
-  uint32_t BlockFactNumThreshold = 0;
+  uint32_t BlockNumThreshold = 0;
 };
 } // namespace clang::lifetimes::internal
 
diff --git 
a/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h 
b/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h
index 6b5b71686a758..e32e91befca8f 100644
--- a/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h
+++ b/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h
@@ -53,8 +53,7 @@ class LifetimeSafetyReporter {
 /// The main entry point for the analysis.
 void runLifetimeSafetyAnalysis(AnalysisDeclContext &AC,
                                LifetimeSafetyReporter *Reporter,
-                               uint32_t CfgBlocknumThreshold,
-                                              uint32_t 
CfgOriginCountThreshold);
+                               uint32_t CfgBlocknumThreshold);
 
 namespace internal {
 /// An object to hold the factories for immutable collections, ensuring
@@ -71,8 +70,7 @@ class LifetimeSafetyAnalysis {
 public:
   LifetimeSafetyAnalysis(AnalysisDeclContext &AC,
                          LifetimeSafetyReporter *Reporter,
-                         uint32_t CfgBlocknumThreshold,
-                                              uint32_t 
CfgOriginCountThreshold);
+                         uint32_t CfgBlocknumThreshold);
 
   void run();
 
@@ -84,10 +82,8 @@ class LifetimeSafetyAnalysis {
   FactManager &getFactManager() { return FactMgr; }
 
 private:
-  bool shouldBailOutCFGPreFactGeneration(const CFG& Cfg) const;
-  bool shouldBailOutCFGPostFactGeneration(const CFG& Cfg) const;
+  bool shouldBailOutCFGPreFactGeneration(const CFG &Cfg) const;
   uint32_t CfgBlocknumThreshold;
-  uint32_t CfgOriginCountThreshold;
   AnalysisDeclContext &AC;
   LifetimeSafetyReporter *Reporter;
   LifetimeFactory Factory;
diff --git a/clang/include/clang/Options/Options.td 
b/clang/include/clang/Options/Options.td
index abe984b440e77..975d7bf0341a9 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -5170,16 +5170,10 @@ def fcfg_block_num_threshold
     : Joined<["-"], "fcfg-block-num-threshold=">,
       Group<m_Group>,
       Visibility<[ClangOption, CC1Option]>,
-      HelpText<"Set Threshold for number of blocks above which lifetime 
analysis "
-               "will be skipped for a CFG">,
+      HelpText<
+          "Set Threshold for number of blocks above which lifetime analysis "
+          "will be skipped for a CFG">,
       MarshallingInfoInt<LangOpts<"CfgBlocknumThreshold">>;
-def fcfg_origin_count_threshold
-    : Joined<["-"], "fcfg-origin-count-threshold=">,
-      Group<m_Group>,
-      Visibility<[ClangOption, CC1Option]>,
-      HelpText<"Set Threshold for number of origins after fact generation 
after which lifetime analysis "
-               "will be skipped for a CFG">,
-      MarshallingInfoInt<LangOpts<"CfgOriginCountThreshold">>;
 def mmacos_version_min_EQ : Joined<["-"], "mmacos-version-min=">,
   Visibility<[ClangOption, CC1Option, FlangOption]>,
   Group<m_Group>, HelpText<"Set macOS deployment target">;
diff --git a/clang/lib/Analysis/LifetimeSafety/Facts.cpp 
b/clang/lib/Analysis/LifetimeSafety/Facts.cpp
index 98f6de28154d2..9cdde1b4d77d9 100644
--- a/clang/lib/Analysis/LifetimeSafety/Facts.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/Facts.cpp
@@ -103,16 +103,19 @@ void FactManager::dumpBlockSizes(const CFG &Cfg,
   if (const Decl *D = AC.getDecl())
     if (const auto *ND = dyn_cast<NamedDecl>(D))
       llvm::dbgs() << "Function: " << ND->getQualifiedNameAsString() << "\n";
+  llvm::dbgs() << "Number of CFG Blocks: " << Cfg.getNumBlockIDs() << "\n";
+  if (BlockNumThreshold > 0 && Cfg.getNumBlockIDs() > BlockNumThreshold) {
+    llvm::dbgs() << "CFG Block Number Threshold: " << BlockNumThreshold << 
"\n";
+    llvm::dbgs() << "Bailed out before generating facts.\n";
+    return;
+  }
   // Print blocks in the order as they appear in code for a stable ordering.
   for (const CFGBlock *B : *AC.getAnalysis<PostOrderCFGView>()) {
-    if (BlockFactNumThreshold > 0 && getFacts(B).size() > 
BlockFactNumThreshold)
-      continue;
-    if (B->getLabel()) {
+    if (B->getLabel())
       llvm::dbgs() << "  Block: " << B->getLabel()->getStmtClassName();
-    } else {
+    else
       llvm::dbgs() << "  Block B" << B->getBlockID();
-    }
-    llvm::dbgs() << ": Number of facts = " << getFacts(B).size() << "\n";
+    llvm::dbgs() << ": Number of elements = " << B->size() << "\n";
   }
 }
 
diff --git a/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp 
b/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp
index 0865d54261ce7..af3b3cc87f872 100644
--- a/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp
@@ -28,32 +28,26 @@
 #include "llvm/Support/TimeProfiler.h"
 #include <memory>
 
+#undef DEBUG_TYPE
+#define DEBUG_TYPE "lifetime-safety"
+
 namespace clang::lifetimes {
 namespace internal {
 
 LifetimeSafetyAnalysis::LifetimeSafetyAnalysis(AnalysisDeclContext &AC,
                                                LifetimeSafetyReporter 
*Reporter,
-                                               uint32_t CfgBlocknumThreshold,
-                                              uint32_t CfgOriginCountThreshold)
-    : CfgBlocknumThreshold(CfgBlocknumThreshold), 
CfgOriginCountThreshold(CfgOriginCountThreshold), AC(AC), Reporter(Reporter) {
-  FactMgr.setBlockFactNumThreshold(CfgBlocknumThreshold);
+                                               uint32_t CfgBlocknumThreshold)
+    : CfgBlocknumThreshold(CfgBlocknumThreshold), AC(AC), Reporter(Reporter) {
+  FactMgr.setBlockNumThreshold(CfgBlocknumThreshold);
 }
 
 bool LifetimeSafetyAnalysis::shouldBailOutCFGPreFactGeneration(const CFG& Cfg) 
const {
-  if (Cfg.getNumBlockIDs() > CfgBlocknumThreshold) {
+  if ((CfgBlocknumThreshold > 0) &&
+      (Cfg.getNumBlockIDs() > CfgBlocknumThreshold)) {
     LLVM_DEBUG(llvm::dbgs()
-               << "Lifetime Safety Analysis aborted: CFG too large before fact 
generation ("
-               << Cfg.getNumBlockIDs() << " blocks).\n");
-    return true;
-  }
-  return false;
-}
-
-bool LifetimeSafetyAnalysis::shouldBailOutCFGPostFactGeneration(const CFG& 
Cfg) const {
-  if (FactMgr.getOriginMgr().getNumOrigins() > CfgOriginCountThreshold) {
-    LLVM_DEBUG(llvm::dbgs()
-               << "Lifetime Safety Analysis aborted: Too many origins after 
fact generation ("
-               << FactMgr.getOriginMgr().getNumOrigins() << " origins).\n");
+               << "Aborting Lifetime Safety analysis for current CFG as it has 
"
+                  "blocks exceeding the thresold. Number of blocks: "
+               << Cfg.getNumBlockIDs() << "\n");
     return true;
   }
   return false;
@@ -72,9 +66,6 @@ void LifetimeSafetyAnalysis::run() {
 
   FactsGenerator FactGen(FactMgr, AC);
   FactGen.run();
-  if (shouldBailOutCFGPostFactGeneration(Cfg)) {
-    return;
-  }
   DEBUG_WITH_TYPE("LifetimeFacts", FactMgr.dump(Cfg, AC));
   DEBUG_WITH_TYPE("LifetimeCFGSizes", FactMgr.dumpBlockSizes(Cfg, AC));
 
@@ -103,11 +94,8 @@ void LifetimeSafetyAnalysis::run() {
 
 void runLifetimeSafetyAnalysis(AnalysisDeclContext &AC,
                                LifetimeSafetyReporter *Reporter,
-                               uint32_t CfgBlocknumThreshold,
-                                              uint32_t 
CfgOriginCountThreshold) {
-  internal::LifetimeSafetyAnalysis Analysis(AC, Reporter,
-                                            CfgBlocknumThreshold,
-                                          CfgOriginCountThreshold);
+                               uint32_t CfgBlocknumThreshold) {
+  internal::LifetimeSafetyAnalysis Analysis(AC, Reporter, 
CfgBlocknumThreshold);
   Analysis.run();
 }
 } // namespace clang::lifetimes
diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp 
b/clang/lib/Sema/AnalysisBasedWarnings.cpp
index ba396191bfa5f..00d8e52bcbbea 100644
--- a/clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -3108,7 +3108,7 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings(
     if (AC.getCFG()) {
       lifetimes::LifetimeSafetyReporterImpl LifetimeSafetyReporter(S);
       lifetimes::runLifetimeSafetyAnalysis(
-          AC, &LifetimeSafetyReporter, S.getLangOpts().CfgBlocknumThreshold, 
S.getLangOpts().CfgOriginCountThreshold);
+          AC, &LifetimeSafetyReporter, S.getLangOpts().CfgBlocknumThreshold);
     }
   }
   // Check for violations of "called once" parameter properties.
diff --git a/clang/unittests/Analysis/LifetimeSafetyTest.cpp 
b/clang/unittests/Analysis/LifetimeSafetyTest.cpp
index 157b77841f533..1f27df26d30f6 100644
--- a/clang/unittests/Analysis/LifetimeSafetyTest.cpp
+++ b/clang/unittests/Analysis/LifetimeSafetyTest.cpp
@@ -62,7 +62,8 @@ class LifetimeTestRunner {
     BuildOptions.AddLifetime = true;
 
     // Run the main analysis.
-    Analysis = std::make_unique<LifetimeSafetyAnalysis>(*AnalysisCtx, nullptr, 
0, 0);
+    Analysis =
+        std::make_unique<LifetimeSafetyAnalysis>(*AnalysisCtx, nullptr, 0);
     Analysis->run();
 
     AnnotationToPointMap = Analysis->getFactManager().getTestPoints();

>From 3cb5ad3c341f2fa65bb74e50becb5d7e04b074c8 Mon Sep 17 00:00:00 2001
From: Debadri Basak <[email protected]>
Date: Fri, 12 Dec 2025 09:11:33 +0000
Subject: [PATCH 6/8] Changing the flag name and removing unused dumpCFGStats
 function

---
 .../Analysis/Analyses/LifetimeSafety/Facts.h  | 10 +----
 .../Analyses/LifetimeSafety/LifetimeSafety.h  |  9 ++---
 clang/include/clang/Basic/LangOptions.def     |  5 +--
 clang/include/clang/Options/Options.td        | 23 ++++++-----
 clang/lib/Analysis/LifetimeSafety/Checker.cpp |  3 +-
 clang/lib/Analysis/LifetimeSafety/Facts.cpp   | 24 -----------
 .../LifetimeSafety/LifetimeSafety.cpp         | 40 ++++++++-----------
 clang/lib/Sema/AnalysisBasedWarnings.cpp      |  3 +-
 8 files changed, 38 insertions(+), 79 deletions(-)

diff --git a/clang/include/clang/Analysis/Analyses/LifetimeSafety/Facts.h 
b/clang/include/clang/Analysis/Analyses/LifetimeSafety/Facts.h
index b10b0a95a82fa..82e14832208b3 100644
--- a/clang/include/clang/Analysis/Analyses/LifetimeSafety/Facts.h
+++ b/clang/include/clang/Analysis/Analyses/LifetimeSafety/Facts.h
@@ -218,10 +218,6 @@ class FactManager {
 
   void dump(const CFG &Cfg, AnalysisDeclContext &AC) const;
 
-  // A utility function to print the size of the CFG blocks in the analysis
-  // context.
-  void dumpBlockSizes(const CFG &Cfg, AnalysisDeclContext &AC) const;
-
   /// Retrieves program points that were specially marked in the source code
   /// for testing.
   ///
@@ -242,9 +238,7 @@ class FactManager {
   const LoanManager &getLoanMgr() const { return LoanMgr; }
   OriginManager &getOriginMgr() { return OriginMgr; }
   const OriginManager &getOriginMgr() const { return OriginMgr; }
-  void setBlockNumThreshold(uint32_t Threshold) {
-    BlockNumThreshold = Threshold;
-  }
+  void setMaxCFGBlocksThreshold(size_t Threshold) { MaxCFGBlocks = Threshold; }
 
 private:
   FactID NextFactID{0};
@@ -253,7 +247,7 @@ class FactManager {
   /// Facts for each CFG block, indexed by block ID.
   llvm::SmallVector<llvm::SmallVector<const Fact *>> BlockToFacts;
   llvm::BumpPtrAllocator FactAllocator;
-  uint32_t BlockNumThreshold = 0;
+  size_t MaxCFGBlocks = 0;
 };
 } // namespace clang::lifetimes::internal
 
diff --git 
a/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h 
b/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h
index e32e91befca8f..0173c872cbee6 100644
--- a/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h
+++ b/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h
@@ -52,8 +52,7 @@ class LifetimeSafetyReporter {
 
 /// The main entry point for the analysis.
 void runLifetimeSafetyAnalysis(AnalysisDeclContext &AC,
-                               LifetimeSafetyReporter *Reporter,
-                               uint32_t CfgBlocknumThreshold);
+                               LifetimeSafetyReporter *Reporter);
 
 namespace internal {
 /// An object to hold the factories for immutable collections, ensuring
@@ -69,8 +68,7 @@ struct LifetimeFactory {
 class LifetimeSafetyAnalysis {
 public:
   LifetimeSafetyAnalysis(AnalysisDeclContext &AC,
-                         LifetimeSafetyReporter *Reporter,
-                         uint32_t CfgBlocknumThreshold);
+                         LifetimeSafetyReporter *Reporter, size_t 
MaxCFGBlocks);
 
   void run();
 
@@ -82,8 +80,7 @@ class LifetimeSafetyAnalysis {
   FactManager &getFactManager() { return FactMgr; }
 
 private:
-  bool shouldBailOutCFGPreFactGeneration(const CFG &Cfg) const;
-  uint32_t CfgBlocknumThreshold;
+  size_t MaxCFGBlocks;
   AnalysisDeclContext &AC;
   LifetimeSafetyReporter *Reporter;
   LifetimeFactory Factory;
diff --git a/clang/include/clang/Basic/LangOptions.def 
b/clang/include/clang/Basic/LangOptions.def
index 05830caea2830..d8de6e3e8826c 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -499,10 +499,9 @@ LANGOPT(BoundsSafety, 1, 0, NotCompatible, "Bounds safety 
extension for C")
 
 LANGOPT(EnableLifetimeSafety, 1, 0, NotCompatible, "Experimental lifetime 
safety analysis for C++")
 
-LANGOPT(PreserveVec3Type, 1, 0, NotCompatible, "Preserve 3-component vector 
type")
-
-LANGOPT(CfgBlocknumThreshold, 32, 0, NotCompatible, "Experimental CFG bailout 
size threshold for C++")
+LANGOPT(LifetimeSafetyMaxCFGBlocks, 32, 0, NotCompatible, "Skip LifetimeSafety 
analysis for functions with CFG block count exceeding this threshold. Specify 0 
for no limit")
 
+LANGOPT(PreserveVec3Type, 1, 0, NotCompatible, "Preserve 3-component vector 
type")
 
 #undef LANGOPT
 #undef ENUM_LANGOPT
diff --git a/clang/include/clang/Options/Options.td 
b/clang/include/clang/Options/Options.td
index 975d7bf0341a9..c208179925b87 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -1955,6 +1955,14 @@ defm lifetime_safety : BoolFOption<
   BothFlags<[], [CC1Option],
           " experimental lifetime safety for C++">>;
 
+def fexperimental_lifetime_safety_max_cfg_blocks
+    : Joined<["-"], "fexperimental-lifetime-safety-max-cfg-blocks=">,
+      Group<m_Group>,
+      Visibility<[ClangOption, CC1Option]>,
+      HelpText<"Skip LifetimeSafety analysis for functions with CFG block "
+               "count exceeding this threshold. Specify 0 for no limit.">,
+      MarshallingInfoInt<LangOpts<"LifetimeSafetyMaxCFGBlocks">>;
+
 defm addrsig : BoolFOption<"addrsig",
   CodeGenOpts<"Addrsig">, DefaultFalse,
   PosFlag<SetTrue, [], [ClangOption, CC1Option], "Emit">,
@@ -5163,17 +5171,10 @@ def mmlir : Separate<["-"], "mmlir">,
   HelpText<"Additional arguments to forward to MLIR's option processing">,
   MarshallingInfoStringVector<FrontendOpts<"MLIRArgs">>;
 def ffuchsia_api_level_EQ : Joined<["-"], "ffuchsia-api-level=">,
-  Group<m_Group>, Visibility<[ClangOption, CC1Option]>,
-  HelpText<"Set Fuchsia API level">,
-  MarshallingInfoInt<LangOpts<"FuchsiaAPILevel">>;
-def fcfg_block_num_threshold
-    : Joined<["-"], "fcfg-block-num-threshold=">,
-      Group<m_Group>,
-      Visibility<[ClangOption, CC1Option]>,
-      HelpText<
-          "Set Threshold for number of blocks above which lifetime analysis "
-          "will be skipped for a CFG">,
-      MarshallingInfoInt<LangOpts<"CfgBlocknumThreshold">>;
+                            Group<m_Group>,
+                            Visibility<[ClangOption, CC1Option]>,
+                            HelpText<"Set Fuchsia API level">,
+                            MarshallingInfoInt<LangOpts<"FuchsiaAPILevel">>;
 def mmacos_version_min_EQ : Joined<["-"], "mmacos-version-min=">,
   Visibility<[ClangOption, CC1Option, FlangOption]>,
   Group<m_Group>, HelpText<"Set macOS deployment target">;
diff --git a/clang/lib/Analysis/LifetimeSafety/Checker.cpp 
b/clang/lib/Analysis/LifetimeSafety/Checker.cpp
index 0ced00f5fadda..1f7c282dadac2 100644
--- a/clang/lib/Analysis/LifetimeSafety/Checker.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/Checker.cpp
@@ -61,11 +61,10 @@ class LifetimeChecker {
                   AnalysisDeclContext &ADC, LifetimeSafetyReporter *Reporter)
       : LoanPropagation(LoanPropagation), LiveOrigins(LiveOrigins), 
FactMgr(FM),
         Reporter(Reporter) {
-    for (const CFGBlock *B : *ADC.getAnalysis<PostOrderCFGView>()) {
+    for (const CFGBlock *B : *ADC.getAnalysis<PostOrderCFGView>())
       for (const Fact *F : FactMgr.getFacts(B))
         if (const auto *EF = F->getAs<ExpireFact>())
           checkExpiry(EF);
-    }
     issuePendingWarnings();
   }
 
diff --git a/clang/lib/Analysis/LifetimeSafety/Facts.cpp 
b/clang/lib/Analysis/LifetimeSafety/Facts.cpp
index 9cdde1b4d77d9..0ae7111c489e8 100644
--- a/clang/lib/Analysis/LifetimeSafety/Facts.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/Facts.cpp
@@ -95,30 +95,6 @@ void FactManager::dump(const CFG &Cfg, AnalysisDeclContext 
&AC) const {
   }
 }
 
-void FactManager::dumpBlockSizes(const CFG &Cfg,
-                                 AnalysisDeclContext &AC) const {
-  llvm::dbgs() << "==========================================\n";
-  llvm::dbgs() << "       Lifetime Analysis CFG Block Sizes:\n";
-  llvm::dbgs() << "==========================================\n";
-  if (const Decl *D = AC.getDecl())
-    if (const auto *ND = dyn_cast<NamedDecl>(D))
-      llvm::dbgs() << "Function: " << ND->getQualifiedNameAsString() << "\n";
-  llvm::dbgs() << "Number of CFG Blocks: " << Cfg.getNumBlockIDs() << "\n";
-  if (BlockNumThreshold > 0 && Cfg.getNumBlockIDs() > BlockNumThreshold) {
-    llvm::dbgs() << "CFG Block Number Threshold: " << BlockNumThreshold << 
"\n";
-    llvm::dbgs() << "Bailed out before generating facts.\n";
-    return;
-  }
-  // Print blocks in the order as they appear in code for a stable ordering.
-  for (const CFGBlock *B : *AC.getAnalysis<PostOrderCFGView>()) {
-    if (B->getLabel())
-      llvm::dbgs() << "  Block: " << B->getLabel()->getStmtClassName();
-    else
-      llvm::dbgs() << "  Block B" << B->getBlockID();
-    llvm::dbgs() << ": Number of elements = " << B->size() << "\n";
-  }
-}
-
 llvm::ArrayRef<const Fact *>
 FactManager::getBlockContaining(ProgramPoint P) const {
   for (const auto &BlockToFactsVec : BlockToFacts) {
diff --git a/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp 
b/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp
index af3b3cc87f872..b74b2feb3174b 100644
--- a/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp
@@ -28,36 +28,30 @@
 #include "llvm/Support/TimeProfiler.h"
 #include <memory>
 
-#undef DEBUG_TYPE
-#define DEBUG_TYPE "lifetime-safety"
-
 namespace clang::lifetimes {
 namespace internal {
 
 LifetimeSafetyAnalysis::LifetimeSafetyAnalysis(AnalysisDeclContext &AC,
                                                LifetimeSafetyReporter 
*Reporter,
-                                               uint32_t CfgBlocknumThreshold)
-    : CfgBlocknumThreshold(CfgBlocknumThreshold), AC(AC), Reporter(Reporter) {
-  FactMgr.setBlockNumThreshold(CfgBlocknumThreshold);
-}
-
-bool LifetimeSafetyAnalysis::shouldBailOutCFGPreFactGeneration(const CFG& Cfg) 
const {
-  if ((CfgBlocknumThreshold > 0) &&
-      (Cfg.getNumBlockIDs() > CfgBlocknumThreshold)) {
-    LLVM_DEBUG(llvm::dbgs()
-               << "Aborting Lifetime Safety analysis for current CFG as it has 
"
-                  "blocks exceeding the thresold. Number of blocks: "
-               << Cfg.getNumBlockIDs() << "\n");
-    return true;
-  }
-  return false;
+                                               size_t MaxCFGBlocks)
+    : MaxCFGBlocks(MaxCFGBlocks), AC(AC), Reporter(Reporter) {
+  FactMgr.setMaxCFGBlocksThreshold(MaxCFGBlocks);
 }
 
 void LifetimeSafetyAnalysis::run() {
   llvm::TimeTraceScope TimeProfile("LifetimeSafetyAnalysis");
 
   const CFG &Cfg = *AC.getCFG();
-  if (shouldBailOutCFGPreFactGeneration(Cfg)) {
+  if (MaxCFGBlocks > 0 && Cfg.getNumBlockIDs() > MaxCFGBlocks) {
+    std::string FuncName = "<unknown>";
+    if (const Decl *D = AC.getDecl())
+      if (const auto *ND = dyn_cast<NamedDecl>(D))
+        FuncName = ND->getQualifiedNameAsString();
+    DEBUG_WITH_TYPE("LifetimeSafety",
+                    llvm::dbgs()
+                        << "LifetimeSafety: Skipping function " << FuncName
+                        << "due to large CFG: <count> blocks (threshold: "
+                        << MaxCFGBlocks << ")\n");
     return;
   }
   DEBUG_WITH_TYPE("PrintCFG", Cfg.dump(AC.getASTContext().getLangOpts(),
@@ -67,7 +61,6 @@ void LifetimeSafetyAnalysis::run() {
   FactsGenerator FactGen(FactMgr, AC);
   FactGen.run();
   DEBUG_WITH_TYPE("LifetimeFacts", FactMgr.dump(Cfg, AC));
-  DEBUG_WITH_TYPE("LifetimeCFGSizes", FactMgr.dumpBlockSizes(Cfg, AC));
 
   /// TODO(opt): Consider optimizing individual blocks before running the
   /// dataflow analysis.
@@ -93,9 +86,10 @@ void LifetimeSafetyAnalysis::run() {
 } // namespace internal
 
 void runLifetimeSafetyAnalysis(AnalysisDeclContext &AC,
-                               LifetimeSafetyReporter *Reporter,
-                               uint32_t CfgBlocknumThreshold) {
-  internal::LifetimeSafetyAnalysis Analysis(AC, Reporter, 
CfgBlocknumThreshold);
+                               LifetimeSafetyReporter *Reporter) {
+  internal::LifetimeSafetyAnalysis Analysis(
+      AC, Reporter,
+      AC.getASTContext().getLangOpts().LifetimeSafetyMaxCFGBlocks);
   Analysis.run();
 }
 } // namespace clang::lifetimes
diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp 
b/clang/lib/Sema/AnalysisBasedWarnings.cpp
index 00d8e52bcbbea..43d2b9a829545 100644
--- a/clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -3107,8 +3107,7 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings(
   if (EnableLifetimeSafetyAnalysis && S.getLangOpts().CPlusPlus) {
     if (AC.getCFG()) {
       lifetimes::LifetimeSafetyReporterImpl LifetimeSafetyReporter(S);
-      lifetimes::runLifetimeSafetyAnalysis(
-          AC, &LifetimeSafetyReporter, S.getLangOpts().CfgBlocknumThreshold);
+      lifetimes::runLifetimeSafetyAnalysis(AC, &LifetimeSafetyReporter);
     }
   }
   // Check for violations of "called once" parameter properties.

>From c1d711228db59ab3ff065ad8eb404f5dd1006cbf Mon Sep 17 00:00:00 2001
From: Debadri Basak <[email protected]>
Date: Mon, 15 Dec 2025 09:26:34 +0000
Subject: [PATCH 7/8] Adding LifetimeSafetyOpts struct to track different
 options for bailout

---
 .../Analyses/LifetimeSafety/LifetimeSafety.h  | 11 +++++--
 clang/include/clang/Options/Options.td        |  7 ++--
 .../LifetimeSafety/LifetimeSafety.cpp         | 32 +++++++++----------
 .../unittests/Analysis/LifetimeSafetyTest.cpp |  4 ++-
 4 files changed, 30 insertions(+), 24 deletions(-)

diff --git 
a/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h 
b/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h
index 0173c872cbee6..f07867f311990 100644
--- a/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h
+++ b/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h
@@ -35,6 +35,12 @@ enum class Confidence : uint8_t {
   Definite // Reported as a definite error (-Wlifetime-safety-permissive)
 };
 
+struct LifetimeSafetyOpts {
+  /// Maximum number of CFG blocks to analyze. Functions with larger CFGs will
+  /// be skipped.
+  size_t MaxCFGBlocks;
+};
+
 class LifetimeSafetyReporter {
 public:
   LifetimeSafetyReporter() = default;
@@ -68,7 +74,8 @@ struct LifetimeFactory {
 class LifetimeSafetyAnalysis {
 public:
   LifetimeSafetyAnalysis(AnalysisDeclContext &AC,
-                         LifetimeSafetyReporter *Reporter, size_t 
MaxCFGBlocks);
+                         LifetimeSafetyReporter *Reporter,
+                         const LifetimeSafetyOpts &LSOpts);
 
   void run();
 
@@ -80,7 +87,7 @@ class LifetimeSafetyAnalysis {
   FactManager &getFactManager() { return FactMgr; }
 
 private:
-  size_t MaxCFGBlocks;
+  const LifetimeSafetyOpts &LSOpts;
   AnalysisDeclContext &AC;
   LifetimeSafetyReporter *Reporter;
   LifetimeFactory Factory;
diff --git a/clang/include/clang/Options/Options.td 
b/clang/include/clang/Options/Options.td
index c208179925b87..e7b1ba2cf9ac8 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -5171,10 +5171,9 @@ def mmlir : Separate<["-"], "mmlir">,
   HelpText<"Additional arguments to forward to MLIR's option processing">,
   MarshallingInfoStringVector<FrontendOpts<"MLIRArgs">>;
 def ffuchsia_api_level_EQ : Joined<["-"], "ffuchsia-api-level=">,
-                            Group<m_Group>,
-                            Visibility<[ClangOption, CC1Option]>,
-                            HelpText<"Set Fuchsia API level">,
-                            MarshallingInfoInt<LangOpts<"FuchsiaAPILevel">>;
+  Group<m_Group>, Visibility<[ClangOption, CC1Option]>,
+  HelpText<"Set Fuchsia API level">,
+  MarshallingInfoInt<LangOpts<"FuchsiaAPILevel">>;
 def mmacos_version_min_EQ : Joined<["-"], "mmacos-version-min=">,
   Visibility<[ClangOption, CC1Option, FlangOption]>,
   Group<m_Group>, HelpText<"Set macOS deployment target">;
diff --git a/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp 
b/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp
index b74b2feb3174b..1c662cd87f607 100644
--- a/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp
@@ -33,25 +33,22 @@ namespace internal {
 
 LifetimeSafetyAnalysis::LifetimeSafetyAnalysis(AnalysisDeclContext &AC,
                                                LifetimeSafetyReporter 
*Reporter,
-                                               size_t MaxCFGBlocks)
-    : MaxCFGBlocks(MaxCFGBlocks), AC(AC), Reporter(Reporter) {
-  FactMgr.setMaxCFGBlocksThreshold(MaxCFGBlocks);
-}
+                                               const LifetimeSafetyOpts 
&LSOpts)
+    : LSOpts(LSOpts), AC(AC), Reporter(Reporter) {}
 
 void LifetimeSafetyAnalysis::run() {
   llvm::TimeTraceScope TimeProfile("LifetimeSafetyAnalysis");
 
   const CFG &Cfg = *AC.getCFG();
-  if (MaxCFGBlocks > 0 && Cfg.getNumBlockIDs() > MaxCFGBlocks) {
-    std::string FuncName = "<unknown>";
-    if (const Decl *D = AC.getDecl())
-      if (const auto *ND = dyn_cast<NamedDecl>(D))
-        FuncName = ND->getQualifiedNameAsString();
-    DEBUG_WITH_TYPE("LifetimeSafety",
-                    llvm::dbgs()
-                        << "LifetimeSafety: Skipping function " << FuncName
-                        << "due to large CFG: <count> blocks (threshold: "
-                        << MaxCFGBlocks << ")\n");
+  if (LSOpts.MaxCFGBlocks > 0 && Cfg.getNumBlockIDs() > LSOpts.MaxCFGBlocks) {
+    DEBUG_WITH_TYPE(
+        "LifetimeSafety", std::string FuncName = "<unknown>";
+        if (const Decl *D = AC.getDecl()) if (const auto *ND =
+                                                  dyn_cast<NamedDecl>(D))
+            FuncName = ND->getQualifiedNameAsString();
+        llvm::dbgs() << "LifetimeSafety: Skipping function " << FuncName
+                     << "due to large CFG: <count> blocks (threshold: "
+                     << LSOpts.MaxCFGBlocks << ")\n");
     return;
   }
   DEBUG_WITH_TYPE("PrintCFG", Cfg.dump(AC.getASTContext().getLangOpts(),
@@ -87,9 +84,10 @@ void LifetimeSafetyAnalysis::run() {
 
 void runLifetimeSafetyAnalysis(AnalysisDeclContext &AC,
                                LifetimeSafetyReporter *Reporter) {
-  internal::LifetimeSafetyAnalysis Analysis(
-      AC, Reporter,
-      AC.getASTContext().getLangOpts().LifetimeSafetyMaxCFGBlocks);
+  LifetimeSafetyOpts LSOpts;
+  LSOpts.MaxCFGBlocks =
+      AC.getASTContext().getLangOpts().LifetimeSafetyMaxCFGBlocks;
+  internal::LifetimeSafetyAnalysis Analysis(AC, Reporter, LSOpts);
   Analysis.run();
 }
 } // namespace clang::lifetimes
diff --git a/clang/unittests/Analysis/LifetimeSafetyTest.cpp 
b/clang/unittests/Analysis/LifetimeSafetyTest.cpp
index 1f27df26d30f6..20afe0d93a2d7 100644
--- a/clang/unittests/Analysis/LifetimeSafetyTest.cpp
+++ b/clang/unittests/Analysis/LifetimeSafetyTest.cpp
@@ -62,8 +62,10 @@ class LifetimeTestRunner {
     BuildOptions.AddLifetime = true;
 
     // Run the main analysis.
+    LifetimeSafetyOpts LSOpts;
+    LSOpts.MaxCFGBlocks = 0;
     Analysis =
-        std::make_unique<LifetimeSafetyAnalysis>(*AnalysisCtx, nullptr, 0);
+        std::make_unique<LifetimeSafetyAnalysis>(*AnalysisCtx, nullptr, 
LSOpts);
     Analysis->run();
 
     AnnotationToPointMap = Analysis->getFactManager().getTestPoints();

>From b83eb55a25fe19a2ccac6075b3f0df7f1018f4b6 Mon Sep 17 00:00:00 2001
From: Debadri Basak <[email protected]>
Date: Mon, 15 Dec 2025 09:29:29 +0000
Subject: [PATCH 8/8] Remvoing unused members and functions from Fact class

---
 clang/include/clang/Analysis/Analyses/LifetimeSafety/Facts.h | 2 --
 1 file changed, 2 deletions(-)

diff --git a/clang/include/clang/Analysis/Analyses/LifetimeSafety/Facts.h 
b/clang/include/clang/Analysis/Analyses/LifetimeSafety/Facts.h
index 82e14832208b3..b5f7f8746186a 100644
--- a/clang/include/clang/Analysis/Analyses/LifetimeSafety/Facts.h
+++ b/clang/include/clang/Analysis/Analyses/LifetimeSafety/Facts.h
@@ -238,7 +238,6 @@ class FactManager {
   const LoanManager &getLoanMgr() const { return LoanMgr; }
   OriginManager &getOriginMgr() { return OriginMgr; }
   const OriginManager &getOriginMgr() const { return OriginMgr; }
-  void setMaxCFGBlocksThreshold(size_t Threshold) { MaxCFGBlocks = Threshold; }
 
 private:
   FactID NextFactID{0};
@@ -247,7 +246,6 @@ class FactManager {
   /// Facts for each CFG block, indexed by block ID.
   llvm::SmallVector<llvm::SmallVector<const Fact *>> BlockToFacts;
   llvm::BumpPtrAllocator FactAllocator;
-  size_t MaxCFGBlocks = 0;
 };
 } // namespace clang::lifetimes::internal
 

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to