From 484bc33d1f8f6d9908d9d4211bd3035960342c77 Mon Sep 17 00:00:00 2001 From: Arseniy Zaostrovnykh Date: Tue, 14 Oct 2025 11:42:55 +0200 Subject: [PATCH] [clang][analyzer] Record entry-point CFG size in metrics 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 --- clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp | 10 ++++++++-- .../test/Analysis/analyzer-stats/entry-point-stats.cpp | 4 ++-- 2 files changed, 10 insertions(+), 4 deletions(-) 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()) 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]+}}",