diff options
Diffstat (limited to 'clang/lib/StaticAnalyzer')
-rw-r--r-- | clang/lib/StaticAnalyzer/Core/CMakeLists.txt | 1 | ||||
-rw-r--r-- | clang/lib/StaticAnalyzer/Core/EntryPointStats.cpp | 31 | ||||
-rw-r--r-- | clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp | 27 |
3 files changed, 47 insertions, 12 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/CMakeLists.txt b/clang/lib/StaticAnalyzer/Core/CMakeLists.txt index d0a9b20..b8095a5 100644 --- a/clang/lib/StaticAnalyzer/Core/CMakeLists.txt +++ b/clang/lib/StaticAnalyzer/Core/CMakeLists.txt @@ -61,6 +61,7 @@ add_clang_library(clangStaticAnalyzerCore clangBasic clangCrossTU clangFrontend + clangIndex clangLex clangRewrite clangToolingCore diff --git a/clang/lib/StaticAnalyzer/Core/EntryPointStats.cpp b/clang/lib/StaticAnalyzer/Core/EntryPointStats.cpp index b7f9044..62ae62f2f 100644 --- a/clang/lib/StaticAnalyzer/Core/EntryPointStats.cpp +++ b/clang/lib/StaticAnalyzer/Core/EntryPointStats.cpp @@ -9,7 +9,9 @@ #include "clang/StaticAnalyzer/Core/PathSensitive/EntryPointStats.h" #include "clang/AST/DeclBase.h" #include "clang/Analysis/AnalysisDeclContext.h" +#include "clang/Index/USRGeneration.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/FileSystem.h" @@ -38,6 +40,7 @@ struct Registry { }; std::vector<Snapshot> Snapshots; + std::string EscapedCPPFileName; }; } // namespace @@ -69,7 +72,7 @@ static void checkStatName(const EntryPointStat *M) { } } -void EntryPointStat::lockRegistry() { +void EntryPointStat::lockRegistry(llvm::StringRef CPPFileName) { auto CmpByNames = [](const EntryPointStat *L, const EntryPointStat *R) { return L->name() < R->name(); }; @@ -78,6 +81,8 @@ void EntryPointStat::lockRegistry() { enumerateStatVectors( [](const auto &Stats) { llvm::for_each(Stats, checkStatName); }); StatsRegistry->IsLocked = true; + llvm::raw_string_ostream OS(StatsRegistry->EscapedCPPFileName); + llvm::printEscapedString(CPPFileName, OS); } [[maybe_unused]] static bool isRegistered(llvm::StringLiteral Name) { @@ -144,15 +149,27 @@ static std::vector<llvm::StringLiteral> getStatNames() { return Ret; } +static std::string getUSR(const Decl *D) { + llvm::SmallVector<char> Buf; + if (index::generateUSRForDecl(D, Buf)) { + assert(false && "This should never fail"); + return AnalysisDeclContext::getFunctionName(D); + } + return llvm::toStringRef(Buf).str(); +} + void Registry::Snapshot::dumpAsCSV(llvm::raw_ostream &OS) const { OS << '"'; + llvm::printEscapedString(getUSR(EntryPoint), OS); + OS << "\",\""; + OS << StatsRegistry->EscapedCPPFileName << "\",\""; llvm::printEscapedString( clang::AnalysisDeclContext::getFunctionName(EntryPoint), OS); - OS << "\", "; + OS << "\","; auto PrintAsBool = [&OS](bool B) { OS << (B ? "true" : "false"); }; - llvm::interleaveComma(BoolStatValues, OS, PrintAsBool); - OS << ((BoolStatValues.empty() || UnsignedStatValues.empty()) ? "" : ", "); - llvm::interleaveComma(UnsignedStatValues, OS); + llvm::interleave(BoolStatValues, OS, PrintAsBool, ","); + OS << ((BoolStatValues.empty() || UnsignedStatValues.empty()) ? "" : ","); + llvm::interleave(UnsignedStatValues, OS, [&OS](unsigned U) { OS << U; }, ","); } static std::vector<bool> consumeBoolStats() { @@ -181,8 +198,8 @@ void EntryPointStat::dumpStatsAsCSV(llvm::StringRef FileName) { } void EntryPointStat::dumpStatsAsCSV(llvm::raw_ostream &OS) { - OS << "EntryPoint, "; - llvm::interleaveComma(getStatNames(), OS); + OS << "USR,File,DebugName,"; + llvm::interleave(getStatNames(), OS, [&OS](const auto &a) { OS << a; }, ","); OS << "\n"; std::vector<std::string> Rows; diff --git a/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp index 53466e7..cf01e2f 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( @@ -65,6 +68,15 @@ STAT_MAX(MaxCFGSize, "The maximum number of basic blocks in a function."); namespace { +StringRef getMainFileName(const CompilerInvocation &Invocation) { + if (!Invocation.getFrontendOpts().Inputs.empty()) { + const FrontendInputFile &Input = Invocation.getFrontendOpts().Inputs[0]; + return Input.isFile() ? Input.getFile() + : Input.getBuffer().getBufferIdentifier(); + } + return "<no input>"; +} + class AnalysisConsumer : public AnalysisASTConsumer, public DynamicRecursiveASTVisitor { enum { @@ -125,7 +137,8 @@ public: PP(CI.getPreprocessor()), OutDir(outdir), Opts(opts), Plugins(plugins), Injector(std::move(injector)), CTU(CI), MacroExpansions(CI.getLangOpts()) { - EntryPointStat::lockRegistry(); + + EntryPointStat::lockRegistry(getMainFileName(CI.getInvocation())); DigestAnalyzerOptions(); if (Opts.AnalyzerDisplayProgress || Opts.PrintStats || @@ -588,10 +601,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) { @@ -659,8 +672,11 @@ void AnalysisConsumer::HandleTranslationUnit(ASTContext &C) { AnalysisConsumer::AnalysisMode AnalysisConsumer::getModeForDecl(Decl *D, AnalysisMode Mode) { if (!Opts.AnalyzeSpecificFunction.empty() && - AnalysisDeclContext::getFunctionName(D) != Opts.AnalyzeSpecificFunction) + AnalysisDeclContext::getFunctionName(D) != Opts.AnalyzeSpecificFunction && + cross_tu::CrossTranslationUnitContext::getLookupName(D).value_or("") != + Opts.AnalyzeSpecificFunction) { return AM_None; + } // Unless -analyze-all is specified, treat decls differently depending on // where they came from: @@ -723,6 +739,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(); |