aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp')
-rw-r--r--clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp175
1 files changed, 29 insertions, 146 deletions
diff --git a/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
index fea8100c3b3b..392049e21c6e 100644
--- a/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
+++ b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
@@ -12,7 +12,6 @@
#include "clang/StaticAnalyzer/Frontend/AnalysisConsumer.h"
#include "ModelInjector.h"
-#include "clang/Analysis/PathDiagnostic.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
@@ -21,10 +20,12 @@
#include "clang/Analysis/CFG.h"
#include "clang/Analysis/CallGraph.h"
#include "clang/Analysis/CodeInjector.h"
+#include "clang/Analysis/PathDiagnostic.h"
#include "clang/Basic/SourceManager.h"
#include "clang/CrossTU/CrossTranslationUnit.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Lex/Preprocessor.h"
+#include "clang/Rewrite/Core/Rewriter.h"
#include "clang/StaticAnalyzer/Checkers/LocalCheckers.h"
#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
@@ -32,7 +33,6 @@
#include "clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
-#include "clang/StaticAnalyzer/Frontend/CheckerRegistration.h"
#include "llvm/ADT/PostOrderIterator.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/FileSystem.h"
@@ -61,114 +61,6 @@ STATISTIC(PercentReachableBlocks, "The % of reachable basic blocks.");
STATISTIC(MaxCFGSize, "The maximum number of basic blocks in a function.");
//===----------------------------------------------------------------------===//
-// Special PathDiagnosticConsumers.
-//===----------------------------------------------------------------------===//
-
-void ento::createPlistHTMLDiagnosticConsumer(
- AnalyzerOptions &AnalyzerOpts, PathDiagnosticConsumers &C,
- const std::string &prefix, const Preprocessor &PP,
- const cross_tu::CrossTranslationUnitContext &CTU) {
- createHTMLDiagnosticConsumer(AnalyzerOpts, C,
- llvm::sys::path::parent_path(prefix), PP, CTU);
- createPlistMultiFileDiagnosticConsumer(AnalyzerOpts, C, prefix, PP, CTU);
-}
-
-void ento::createTextPathDiagnosticConsumer(
- AnalyzerOptions &AnalyzerOpts, PathDiagnosticConsumers &C,
- const std::string &Prefix, const clang::Preprocessor &PP,
- const cross_tu::CrossTranslationUnitContext &CTU) {
- llvm_unreachable("'text' consumer should be enabled on ClangDiags");
-}
-
-namespace {
-class ClangDiagPathDiagConsumer : public PathDiagnosticConsumer {
- DiagnosticsEngine &Diag;
- bool IncludePath = false, ShouldEmitAsError = false, FixitsAsRemarks = false;
-
-public:
- ClangDiagPathDiagConsumer(DiagnosticsEngine &Diag)
- : Diag(Diag) {}
- ~ClangDiagPathDiagConsumer() override {}
- StringRef getName() const override { return "ClangDiags"; }
-
- bool supportsLogicalOpControlFlow() const override { return true; }
- bool supportsCrossFileDiagnostics() const override { return true; }
-
- PathGenerationScheme getGenerationScheme() const override {
- return IncludePath ? Minimal : None;
- }
-
- void enablePaths() { IncludePath = true; }
- void enableWerror() { ShouldEmitAsError = true; }
- void enableFixitsAsRemarks() { FixitsAsRemarks = true; }
-
- void FlushDiagnosticsImpl(std::vector<const PathDiagnostic *> &Diags,
- FilesMade *filesMade) override {
- unsigned WarnID =
- ShouldEmitAsError
- ? Diag.getCustomDiagID(DiagnosticsEngine::Error, "%0")
- : Diag.getCustomDiagID(DiagnosticsEngine::Warning, "%0");
- unsigned NoteID = Diag.getCustomDiagID(DiagnosticsEngine::Note, "%0");
- unsigned RemarkID = Diag.getCustomDiagID(DiagnosticsEngine::Remark, "%0");
-
- auto reportPiece =
- [&](unsigned ID, SourceLocation Loc, StringRef String,
- ArrayRef<SourceRange> Ranges, ArrayRef<FixItHint> Fixits) {
- if (!FixitsAsRemarks) {
- Diag.Report(Loc, ID) << String << Ranges << Fixits;
- } else {
- Diag.Report(Loc, ID) << String << Ranges;
- for (const FixItHint &Hint : Fixits) {
- SourceManager &SM = Diag.getSourceManager();
- llvm::SmallString<128> Str;
- llvm::raw_svector_ostream OS(Str);
- // FIXME: Add support for InsertFromRange and
- // BeforePreviousInsertion.
- assert(!Hint.InsertFromRange.isValid() && "Not implemented yet!");
- assert(!Hint.BeforePreviousInsertions && "Not implemented yet!");
- OS << SM.getSpellingColumnNumber(Hint.RemoveRange.getBegin())
- << "-" << SM.getSpellingColumnNumber(Hint.RemoveRange.getEnd())
- << ": '" << Hint.CodeToInsert << "'";
- Diag.Report(Loc, RemarkID) << OS.str();
- }
- }
- };
-
- for (std::vector<const PathDiagnostic *>::iterator I = Diags.begin(),
- E = Diags.end();
- I != E; ++I) {
- const PathDiagnostic *PD = *I;
- reportPiece(WarnID, PD->getLocation().asLocation(),
- PD->getShortDescription(), PD->path.back()->getRanges(),
- PD->path.back()->getFixits());
-
- // First, add extra notes, even if paths should not be included.
- for (const auto &Piece : PD->path) {
- if (!isa<PathDiagnosticNotePiece>(Piece.get()))
- continue;
-
- reportPiece(NoteID, Piece->getLocation().asLocation(),
- Piece->getString(), Piece->getRanges(), Piece->getFixits());
- }
-
- if (!IncludePath)
- continue;
-
- // Then, add the path notes if necessary.
- PathPieces FlatPath = PD->path.flatten(/*ShouldFlattenMacros=*/true);
- for (const auto &Piece : FlatPath) {
- if (isa<PathDiagnosticNotePiece>(Piece.get()))
- continue;
-
- reportPiece(NoteID, Piece->getLocation().asLocation(),
- Piece->getString(), Piece->getRanges(), Piece->getFixits());
- }
- }
- }
-};
-} // end anonymous namespace
-
-//===----------------------------------------------------------------------===//
// AnalysisConsumer declaration.
//===----------------------------------------------------------------------===//
@@ -192,7 +84,7 @@ class AnalysisConsumer : public AnalysisASTConsumer,
public:
ASTContext *Ctx;
- const Preprocessor &PP;
+ Preprocessor &PP;
const std::string OutDir;
AnalyzerOptionsRef Opts;
ArrayRef<std::string> Plugins;
@@ -253,31 +145,16 @@ public:
}
void DigestAnalyzerOptions() {
- if (Opts->AnalysisDiagOpt != PD_NONE) {
- // Create the PathDiagnosticConsumer.
- ClangDiagPathDiagConsumer *clangDiags =
- new ClangDiagPathDiagConsumer(PP.getDiagnostics());
- PathConsumers.push_back(clangDiags);
-
- if (Opts->AnalyzerWerror)
- clangDiags->enableWerror();
-
- if (Opts->ShouldEmitFixItHintsAsRemarks)
- clangDiags->enableFixitsAsRemarks();
-
- if (Opts->AnalysisDiagOpt == PD_TEXT) {
- clangDiags->enablePaths();
-
- } else if (!OutDir.empty()) {
- switch (Opts->AnalysisDiagOpt) {
- default:
+ switch (Opts->AnalysisDiagOpt) {
+ case PD_NONE:
+ break;
#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN) \
case PD_##NAME: \
CREATEFN(*Opts.get(), PathConsumers, OutDir, PP, CTU); \
break;
#include "clang/StaticAnalyzer/Core/Analyses.def"
- }
- }
+ default:
+ llvm_unreachable("Unknown analyzer output type!");
}
// Create the analyzer component creators.
@@ -313,30 +190,29 @@ public:
else if (Mode == AM_Path) {
llvm::errs() << " (Path, ";
switch (IMode) {
- case ExprEngine::Inline_Minimal:
- llvm::errs() << " Inline_Minimal";
- break;
- case ExprEngine::Inline_Regular:
- llvm::errs() << " Inline_Regular";
- break;
+ case ExprEngine::Inline_Minimal:
+ llvm::errs() << " Inline_Minimal";
+ break;
+ case ExprEngine::Inline_Regular:
+ llvm::errs() << " Inline_Regular";
+ break;
}
llvm::errs() << ")";
- }
- else
+ } else
assert(Mode == (AM_Syntax | AM_Path) && "Unexpected mode!");
- llvm::errs() << ": " << Loc.getFilename() << ' '
- << getFunctionName(D) << '\n';
+ llvm::errs() << ": " << Loc.getFilename() << ' ' << getFunctionName(D)
+ << '\n';
}
}
void Initialize(ASTContext &Context) override {
Ctx = &Context;
- checkerMgr = createCheckerManager(
- *Ctx, *Opts, Plugins, CheckerRegistrationFns, PP.getDiagnostics());
+ checkerMgr = std::make_unique<CheckerManager>(*Ctx, *Opts, PP, Plugins,
+ CheckerRegistrationFns);
- Mgr = std::make_unique<AnalysisManager>(*Ctx, PathConsumers, CreateStoreMgr,
- CreateConstraintMgr,
+ Mgr = std::make_unique<AnalysisManager>(*Ctx, PP, PathConsumers,
+ CreateStoreMgr, CreateConstraintMgr,
checkerMgr.get(), *Opts, Injector);
}
@@ -469,7 +345,7 @@ private:
/// Print \p S to stderr if \c Opts->AnalyzerDisplayProgress is set.
void reportAnalyzerProgress(StringRef S);
-};
+}; // namespace
} // end anonymous namespace
@@ -503,6 +379,13 @@ static bool shouldSkipFunction(const Decl *D,
if (VisitedAsTopLevel.count(D))
return true;
+ // Skip analysis of inheriting constructors as top-level functions. These
+ // constructors don't even have a body written down in the code, so even if
+ // we find a bug, we won't be able to display it.
+ if (const auto *CD = dyn_cast<CXXConstructorDecl>(D))
+ if (CD->isInheritingConstructor())
+ return true;
+
// We want to re-analyse the functions as top level in the following cases:
// - The 'init' methods should be reanalyzed because
// ObjCNonNilReturnValueChecker assumes that '[super init]' never returns