diff --git a/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp index 53466e7a75b0f..5906e876aa311 100644 --- a/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp +++ b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp @@ -51,6 +51,9 @@ STAT_COUNTER(NumFunctionTopLevel, "The # of functions at top level."); ALWAYS_ENABLED_STATISTIC(NumFunctionsAnalyzed, "The # of functions and blocks analyzed (as top level " "with inlining turned on)."); +ALWAYS_ENABLED_STATISTIC( + NumFunctionsAnalyzedSyntaxOnly, + "The # of functions analyzed by syntax checkers only."); ALWAYS_ENABLED_STATISTIC(NumBlocksInAnalyzedFunctions, "The # of basic blocks in the analyzed functions."); ALWAYS_ENABLED_STATISTIC( @@ -588,10 +591,10 @@ void AnalysisConsumer::runAnalysisOnTranslationUnit(ASTContext &C) { // If the user wanted to analyze a specific function and the number of basic // blocks analyzed is zero, than the user might not specified the function // name correctly. - // FIXME: The user might have analyzed the requested function in Syntax mode, - // but we are unaware of that. - if (!Opts.AnalyzeSpecificFunction.empty() && NumFunctionsAnalyzed == 0) + if (!Opts.AnalyzeSpecificFunction.empty() && NumFunctionsAnalyzed == 0 && + NumFunctionsAnalyzedSyntaxOnly == 0) { reportAnalyzerFunctionMisuse(Opts, *Ctx); + } } void AnalysisConsumer::reportAnalyzerProgress(StringRef S) { @@ -723,6 +726,7 @@ void AnalysisConsumer::HandleCode(Decl *D, AnalysisMode Mode, SyntaxCheckTimer->startTimer(); } checkerMgr->runCheckersOnASTBody(D, *Mgr, BR); + ++NumFunctionsAnalyzedSyntaxOnly; if (SyntaxCheckTimer) { SyntaxCheckTimer->stopTimer(); llvm::TimeRecord CheckerEndTime = SyntaxCheckTimer->getTotalTime(); diff --git a/clang/test/Analysis/analyze-function-guide.cpp b/clang/test/Analysis/analyze-function-guide.cpp index 96f1001057eb6..e260fc43a666a 100644 --- a/clang/test/Analysis/analyze-function-guide.cpp +++ b/clang/test/Analysis/analyze-function-guide.cpp @@ -46,14 +46,17 @@ int fizzbuzz(int x, bool y) { // CHECK-ADVOCATE-DISPLAY-PROGRESS-NEXT: Pass the -analyzer-display-progress for tracking which functions are analyzed. // CHECK-ADVOCATE-DISPLAY-PROGRESS-NOT: For analyzing -// Same as the previous but syntax mode only. -// FIXME: This should have empty standard output. +// The user only enables syntax-only analysis, like `debug.DumpDominators`. +// `-analyze-function` should only match the given function. // -// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-config ipa=none \ +// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.DumpDominators -analyzer-config ipa=none \ // RUN: -analyze-function='fizzbuzz(int, _Bool)' -x c++ \ // RUN: -triple x86_64-pc-linux-gnu 2>&1 %s \ -// RUN: | FileCheck %s -check-prefix=CHECK-EMPTY3 --allow-empty -// -// FIXME: This should have empty standard output. -// CHECK-EMPTY3: Every top-level function was skipped. -// CHECK-EMPTY3-NEXT: Pass the -analyzer-display-progress for tracking which functions are analyzed. +// RUN: | FileCheck %s -check-prefix=CHECK-SYNTAX-ONLY --allow-empty +// +// With syntax-only analysis, the function is found and analyzed, so no error message. +// CHECK-SYNTAX-ONLY: Immediate dominance tree (Node#,IDom#): +// CHECK-SYNTAX-ONLY-NEXT: (0,1) +// CHECK-SYNTAX-ONLY-NEXT: (1,2) +// CHECK-SYNTAX-ONLY-NEXT: (2,2) +// CHECK-SYNTAX-ONLY-NOT: Every top-level function was skipped.