summaryrefslogtreecommitdiff
path: root/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2019-08-20 20:50:49 +0000
committerDimitry Andric <dim@FreeBSD.org>2019-08-20 20:50:49 +0000
commit2298981669bf3bd63335a4be179bc0f96823a8f4 (patch)
tree1cbe2eb27f030d2d70b80ee5ca3c86bee7326a9f /lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
parent9a83721404652cea39e9f02ae3e3b5c964602a5c (diff)
Notes
Diffstat (limited to 'lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp')
-rw-r--r--lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp94
1 files changed, 78 insertions, 16 deletions
diff --git a/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp b/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
index d87937d9b63d..454b61fd51a1 100644
--- a/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
+++ b/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
@@ -1,9 +1,8 @@
//===--- AnalysisConsumer.cpp - ASTConsumer for running Analyses ----------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -84,10 +83,11 @@ void ento::createTextPathDiagnosticConsumer(AnalyzerOptions &AnalyzerOpts,
namespace {
class ClangDiagPathDiagConsumer : public PathDiagnosticConsumer {
DiagnosticsEngine &Diag;
- bool IncludePath;
+ bool IncludePath, ShouldEmitAsError;
+
public:
ClangDiagPathDiagConsumer(DiagnosticsEngine &Diag)
- : Diag(Diag), IncludePath(false) {}
+ : Diag(Diag), IncludePath(false), ShouldEmitAsError(false) {}
~ClangDiagPathDiagConsumer() override {}
StringRef getName() const override { return "ClangDiags"; }
@@ -102,9 +102,14 @@ public:
IncludePath = true;
}
+ void enableWerror() { ShouldEmitAsError = true; }
+
void FlushDiagnosticsImpl(std::vector<const PathDiagnostic *> &Diags,
FilesMade *filesMade) override {
- unsigned WarnID = Diag.getCustomDiagID(DiagnosticsEngine::Warning, "%0");
+ unsigned WarnID =
+ ShouldEmitAsError
+ ? Diag.getCustomDiagID(DiagnosticsEngine::Error, "%0")
+ : Diag.getCustomDiagID(DiagnosticsEngine::Warning, "%0");
unsigned NoteID = Diag.getCustomDiagID(DiagnosticsEngine::Note, "%0");
for (std::vector<const PathDiagnostic*>::iterator I = Diags.begin(),
@@ -191,7 +196,9 @@ public:
/// Time the analyzes time of each translation unit.
std::unique_ptr<llvm::TimerGroup> AnalyzerTimers;
- std::unique_ptr<llvm::Timer> TUTotalTimer;
+ std::unique_ptr<llvm::Timer> SyntaxCheckTimer;
+ std::unique_ptr<llvm::Timer> ExprEngineTimer;
+ std::unique_ptr<llvm::Timer> BugReporterTimer;
/// The information about analyzed functions shared throughout the
/// translation unit.
@@ -207,8 +214,13 @@ public:
if (Opts->PrintStats || Opts->ShouldSerializeStats) {
AnalyzerTimers = llvm::make_unique<llvm::TimerGroup>(
"analyzer", "Analyzer timers");
- TUTotalTimer = llvm::make_unique<llvm::Timer>(
- "time", "Analyzer total time", *AnalyzerTimers);
+ SyntaxCheckTimer = llvm::make_unique<llvm::Timer>(
+ "syntaxchecks", "Syntax-based analysis time", *AnalyzerTimers);
+ ExprEngineTimer = llvm::make_unique<llvm::Timer>(
+ "exprengine", "Path exploration time", *AnalyzerTimers);
+ BugReporterTimer = llvm::make_unique<llvm::Timer>(
+ "bugreporter", "Path-sensitive report post-processing time",
+ *AnalyzerTimers);
llvm::EnableStatistics(/* PrintOnExit= */ false);
}
}
@@ -226,6 +238,9 @@ public:
new ClangDiagPathDiagConsumer(PP.getDiagnostics());
PathConsumers.push_back(clangDiags);
+ if (Opts->AnalyzerWerror)
+ clangDiags->enableWerror();
+
if (Opts->AnalysisDiagOpt == PD_TEXT) {
clangDiags->enablePaths();
@@ -338,8 +353,42 @@ public:
/// Handle callbacks for arbitrary Decls.
bool VisitDecl(Decl *D) {
AnalysisMode Mode = getModeForDecl(D, RecVisitorMode);
- if (Mode & AM_Syntax)
+ if (Mode & AM_Syntax) {
+ if (SyntaxCheckTimer)
+ SyntaxCheckTimer->startTimer();
checkerMgr->runCheckersOnASTDecl(D, *Mgr, *RecVisitorBR);
+ if (SyntaxCheckTimer)
+ SyntaxCheckTimer->stopTimer();
+ }
+ return true;
+ }
+
+ bool VisitVarDecl(VarDecl *VD) {
+ if (!Opts->IsNaiveCTUEnabled)
+ return true;
+
+ if (VD->hasExternalStorage() || VD->isStaticDataMember()) {
+ if (!cross_tu::containsConst(VD, *Ctx))
+ return true;
+ } else {
+ // Cannot be initialized in another TU.
+ return true;
+ }
+
+ if (VD->getAnyInitializer())
+ return true;
+
+ llvm::Expected<const VarDecl *> CTUDeclOrError =
+ CTU.getCrossTUDefinition(VD, Opts->CTUDir, Opts->CTUIndexName,
+ Opts->DisplayCTUProgress);
+
+ if (!CTUDeclOrError) {
+ handleAllErrors(CTUDeclOrError.takeError(),
+ [&](const cross_tu::IndexError &IE) {
+ CTU.emitCrossTUDiagnostics(IE);
+ });
+ }
+
return true;
}
@@ -529,7 +578,11 @@ static bool isBisonFile(ASTContext &C) {
void AnalysisConsumer::runAnalysisOnTranslationUnit(ASTContext &C) {
BugReporter BR(*Mgr);
TranslationUnitDecl *TU = C.getTranslationUnitDecl();
+ if (SyntaxCheckTimer)
+ SyntaxCheckTimer->startTimer();
checkerMgr->runCheckersOnASTDecl(TU, *Mgr, BR);
+ if (SyntaxCheckTimer)
+ SyntaxCheckTimer->stopTimer();
// Run the AST-only checks using the order in which functions are defined.
// If inlining is not turned on, use the simplest function order for path
@@ -571,8 +624,6 @@ void AnalysisConsumer::HandleTranslationUnit(ASTContext &C) {
if (Diags.hasErrorOccurred() || Diags.hasFatalErrorOccurred())
return;
- if (TUTotalTimer) TUTotalTimer->startTimer();
-
if (isBisonFile(C)) {
reportAnalyzerProgress("Skipping bison-generated file\n");
} else if (Opts->DisableAllChecks) {
@@ -585,8 +636,6 @@ void AnalysisConsumer::HandleTranslationUnit(ASTContext &C) {
runAnalysisOnTranslationUnit(C);
}
- if (TUTotalTimer) TUTotalTimer->stopTimer();
-
// Count how many basic blocks we have not covered.
NumBlocksInAnalyzedFunctions = FunctionSummaries.getTotalNumBasicBlocks();
NumVisitedBlocksInAnalyzedFunctions =
@@ -710,8 +759,13 @@ void AnalysisConsumer::HandleCode(Decl *D, AnalysisMode Mode,
BugReporter BR(*Mgr);
- if (Mode & AM_Syntax)
+ if (Mode & AM_Syntax) {
+ if (SyntaxCheckTimer)
+ SyntaxCheckTimer->startTimer();
checkerMgr->runCheckersOnASTBody(D, *Mgr, BR);
+ if (SyntaxCheckTimer)
+ SyntaxCheckTimer->stopTimer();
+ }
if ((Mode & AM_Path) && checkerMgr->hasPathSensitiveCheckers()) {
RunPathSensitiveChecks(D, IMode, VisitedCallees);
if (IMode != ExprEngine::Inline_Minimal)
@@ -738,8 +792,12 @@ void AnalysisConsumer::RunPathSensitiveChecks(Decl *D,
ExprEngine Eng(CTU, *Mgr, VisitedCallees, &FunctionSummaries, IMode);
// Execute the worklist algorithm.
+ if (ExprEngineTimer)
+ ExprEngineTimer->startTimer();
Eng.ExecuteWorkList(Mgr->getAnalysisDeclContextManager().getStackFrame(D),
Mgr->options.MaxNodesPerTopLevelFunction);
+ if (ExprEngineTimer)
+ ExprEngineTimer->stopTimer();
if (!Mgr->options.DumpExplodedGraphTo.empty())
Eng.DumpGraph(Mgr->options.TrimGraph, Mgr->options.DumpExplodedGraphTo);
@@ -749,7 +807,11 @@ void AnalysisConsumer::RunPathSensitiveChecks(Decl *D,
Eng.ViewGraph(Mgr->options.TrimGraph);
// Display warnings.
+ if (BugReporterTimer)
+ BugReporterTimer->startTimer();
Eng.getBugReporter().FlushReports();
+ if (BugReporterTimer)
+ BugReporterTimer->stopTimer();
}
//===----------------------------------------------------------------------===//