Skip to content

Conversation

@necto
Copy link
Contributor

@necto necto commented Oct 14, 2025

MaxCFGSize does not make sense in the context of per-entry-point metric. Moreover, it gets polluted by the syntax-only checks that run before path-sensitive analysis: the first entry point analized by path-sensitive analysis will have MaxCFGSize set to the max CFG across all syntax-only-analyzed entry points, which has little meaning.

This change unbundles the per-TU statistic MaxCFGSize and per-EP statistic CFGSize.

--

CPP-7099

MaxCFGSize does not make sense in the context of per-entry-point metric. Moreover, it gets polluted by the syntax-only checks that run before path-sensitive analysis: the first entry point analized by path-sensitive analysis will have MaxCFGSize set to the max CFG across all syntax-only-analyzed entry points, which has little meaning. This change unbundles the per-TU statistic MaxCFGSize and per-EP statistic CFGSize. -- CPP-7099
@necto necto requested review from NagyDonat and steakhal October 14, 2025 09:48
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:static analyzer labels Oct 14, 2025
@llvmbot
Copy link
Member

llvmbot commented Oct 14, 2025

@llvm/pr-subscribers-clang-static-analyzer-1

Author: Arseniy Zaostrovnykh (necto)

Changes

MaxCFGSize does not make sense in the context of per-entry-point metric. Moreover, it gets polluted by the syntax-only checks that run before path-sensitive analysis: the first entry point analized by path-sensitive analysis will have MaxCFGSize set to the max CFG across all syntax-only-analyzed entry points, which has little meaning.

This change unbundles the per-TU statistic MaxCFGSize and per-EP statistic CFGSize.

--

CPP-7099


Full diff: https://github.com/llvm/llvm-project/pull/163351.diff

2 Files Affected:

  • (modified) clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp (+8-2)
  • (modified) clang/test/Analysis/analyzer-stats/entry-point-stats.cpp (+2-2)
diff --git a/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp index 4efde59aab763..f6a3e7996cd61 100644 --- a/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp +++ b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp @@ -62,7 +62,9 @@ ALWAYS_ENABLED_STATISTIC( "The # of visited basic blocks in the analyzed functions."); ALWAYS_ENABLED_STATISTIC(PercentReachableBlocks, "The % of reachable basic blocks."); -STAT_MAX(MaxCFGSize, "The maximum number of basic blocks in a function."); +ALWAYS_ENABLED_STATISTIC(MaxCFGSize, + "The maximum number of basic blocks in a function."); +static UnsignedEPStat CFGSize("CFGSize"); //===----------------------------------------------------------------------===// // AnalysisConsumer declaration. //===----------------------------------------------------------------------===// @@ -783,15 +785,19 @@ void AnalysisConsumer::HandleCode(Decl *D, AnalysisMode Mode, void AnalysisConsumer::RunPathSensitiveChecks(Decl *D, ExprEngine::InliningModes IMode, SetOfConstDecls *VisitedCallees) { + auto *CFG = Mgr->getCFG(D); + // Construct the analysis engine. First check if the CFG is valid. // FIXME: Inter-procedural analysis will need to handle invalid CFGs. - if (!Mgr->getCFG(D)) + if (!CFG) return; // See if the LiveVariables analysis scales. if (!Mgr->getAnalysisDeclContext(D)->getAnalysis<RelaxedLiveVariables>()) return; + CFGSize.set(CFG->size()); + ExprEngine Eng(CTU, *Mgr, VisitedCallees, &FunctionSummaries, IMode); // Execute the worklist algorithm. diff --git a/clang/test/Analysis/analyzer-stats/entry-point-stats.cpp b/clang/test/Analysis/analyzer-stats/entry-point-stats.cpp index 2a0caad5950ec..ebbc01574db8d 100644 --- a/clang/test/Analysis/analyzer-stats/entry-point-stats.cpp +++ b/clang/test/Analysis/analyzer-stats/entry-point-stats.cpp @@ -8,9 +8,9 @@ // CHECK-NEXT: "c:@F@fib#i#": { // CHECK-NEXT: "File": "{{.*}}entry-point-stats.cpp", // CHECK-NEXT: "DebugName": "fib(unsigned int)", +// CHECK-NEXT: "CFGSize": "5", // CHECK-NEXT: "PathRunningTime": "{{[0-9]+}}", // CHECK-NEXT: "MaxBugClassSize": "{{[0-9]+}}", -// CHECK-NEXT: "MaxCFGSize": "{{[0-9]+}}", // CHECK-NEXT: "MaxQueueSize": "{{[0-9]+}}", // CHECK-NEXT: "MaxReachableSize": "{{[0-9]+}}", // CHECK-NEXT: "MaxTimeSpentSolvingZ3Queries": "{{[0-9]+}}", @@ -45,9 +45,9 @@ // CHECK-NEXT: "c:@F@main#I#**C#": { // CHECK-NEXT: "File": "{{.*}}entry-point-stats.cpp", // CHECK-NEXT: "DebugName": "main(int, char **)", +// CHECK-NEXT: "CFGSize": "3", // CHECK-NEXT: "PathRunningTime": "{{[0-9]+}}", // CHECK-NEXT: "MaxBugClassSize": "{{[0-9]+}}", -// CHECK-NEXT: "MaxCFGSize": "{{[0-9]+}}", // CHECK-NEXT: "MaxQueueSize": "{{[0-9]+}}", // CHECK-NEXT: "MaxReachableSize": "{{[0-9]+}}", // CHECK-NEXT: "MaxTimeSpentSolvingZ3Queries": "{{[0-9]+}}", 
@llvmbot
Copy link
Member

llvmbot commented Oct 14, 2025

@llvm/pr-subscribers-clang

Author: Arseniy Zaostrovnykh (necto)

Changes

MaxCFGSize does not make sense in the context of per-entry-point metric. Moreover, it gets polluted by the syntax-only checks that run before path-sensitive analysis: the first entry point analized by path-sensitive analysis will have MaxCFGSize set to the max CFG across all syntax-only-analyzed entry points, which has little meaning.

This change unbundles the per-TU statistic MaxCFGSize and per-EP statistic CFGSize.

--

CPP-7099


Full diff: https://github.com/llvm/llvm-project/pull/163351.diff

2 Files Affected:

  • (modified) clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp (+8-2)
  • (modified) clang/test/Analysis/analyzer-stats/entry-point-stats.cpp (+2-2)
diff --git a/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp index 4efde59aab763..f6a3e7996cd61 100644 --- a/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp +++ b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp @@ -62,7 +62,9 @@ ALWAYS_ENABLED_STATISTIC( "The # of visited basic blocks in the analyzed functions."); ALWAYS_ENABLED_STATISTIC(PercentReachableBlocks, "The % of reachable basic blocks."); -STAT_MAX(MaxCFGSize, "The maximum number of basic blocks in a function."); +ALWAYS_ENABLED_STATISTIC(MaxCFGSize, + "The maximum number of basic blocks in a function."); +static UnsignedEPStat CFGSize("CFGSize"); //===----------------------------------------------------------------------===// // AnalysisConsumer declaration. //===----------------------------------------------------------------------===// @@ -783,15 +785,19 @@ void AnalysisConsumer::HandleCode(Decl *D, AnalysisMode Mode, void AnalysisConsumer::RunPathSensitiveChecks(Decl *D, ExprEngine::InliningModes IMode, SetOfConstDecls *VisitedCallees) { + auto *CFG = Mgr->getCFG(D); + // Construct the analysis engine. First check if the CFG is valid. // FIXME: Inter-procedural analysis will need to handle invalid CFGs. - if (!Mgr->getCFG(D)) + if (!CFG) return; // See if the LiveVariables analysis scales. if (!Mgr->getAnalysisDeclContext(D)->getAnalysis<RelaxedLiveVariables>()) return; + CFGSize.set(CFG->size()); + ExprEngine Eng(CTU, *Mgr, VisitedCallees, &FunctionSummaries, IMode); // Execute the worklist algorithm. diff --git a/clang/test/Analysis/analyzer-stats/entry-point-stats.cpp b/clang/test/Analysis/analyzer-stats/entry-point-stats.cpp index 2a0caad5950ec..ebbc01574db8d 100644 --- a/clang/test/Analysis/analyzer-stats/entry-point-stats.cpp +++ b/clang/test/Analysis/analyzer-stats/entry-point-stats.cpp @@ -8,9 +8,9 @@ // CHECK-NEXT: "c:@F@fib#i#": { // CHECK-NEXT: "File": "{{.*}}entry-point-stats.cpp", // CHECK-NEXT: "DebugName": "fib(unsigned int)", +// CHECK-NEXT: "CFGSize": "5", // CHECK-NEXT: "PathRunningTime": "{{[0-9]+}}", // CHECK-NEXT: "MaxBugClassSize": "{{[0-9]+}}", -// CHECK-NEXT: "MaxCFGSize": "{{[0-9]+}}", // CHECK-NEXT: "MaxQueueSize": "{{[0-9]+}}", // CHECK-NEXT: "MaxReachableSize": "{{[0-9]+}}", // CHECK-NEXT: "MaxTimeSpentSolvingZ3Queries": "{{[0-9]+}}", @@ -45,9 +45,9 @@ // CHECK-NEXT: "c:@F@main#I#**C#": { // CHECK-NEXT: "File": "{{.*}}entry-point-stats.cpp", // CHECK-NEXT: "DebugName": "main(int, char **)", +// CHECK-NEXT: "CFGSize": "3", // CHECK-NEXT: "PathRunningTime": "{{[0-9]+}}", // CHECK-NEXT: "MaxBugClassSize": "{{[0-9]+}}", -// CHECK-NEXT: "MaxCFGSize": "{{[0-9]+}}", // CHECK-NEXT: "MaxQueueSize": "{{[0-9]+}}", // CHECK-NEXT: "MaxReachableSize": "{{[0-9]+}}", // CHECK-NEXT: "MaxTimeSpentSolvingZ3Queries": "{{[0-9]+}}", 
Copy link
Contributor

@steakhal steakhal left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@necto necto merged commit a08b094 into llvm:main Oct 17, 2025
13 checks passed
@necto necto deleted the az/cfg-size branch October 17, 2025 08:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

clang:static analyzer clang Clang issues not falling into any other category

3 participants