[clang] [LifetimeSafety] Add bailout for large CFGs (PR #170444)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Dec 10 23:15:05 PST 2025
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 <debadri1010 at gmail.com>
Date: Wed, 3 Dec 2025 09:11:15 +0000
Subject: [PATCH 1/5] 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 <debadri1010 at gmail.com>
Date: Wed, 3 Dec 2025 09:13:39 +0000
Subject: [PATCH 2/5] 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 <debadri1010 at gmail.com>
Date: Wed, 3 Dec 2025 09:28:23 +0000
Subject: [PATCH 3/5] 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 <debadri1010 at gmail.com>
Date: Mon, 8 Dec 2025 04:06:29 +0000
Subject: [PATCH 4/5] 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 <debadri1010 at gmail.com>
Date: Thu, 11 Dec 2025 07:14:43 +0000
Subject: [PATCH 5/5] 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();
More information about the cfe-commits
mailing list