aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/StaticAnalyzer
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/StaticAnalyzer')
-rw-r--r--clang/lib/StaticAnalyzer/Core/CMakeLists.txt1
-rw-r--r--clang/lib/StaticAnalyzer/Core/EntryPointStats.cpp31
-rw-r--r--clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp27
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();