diff options
Diffstat (limited to 'clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp')
| -rw-r--r-- | clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp | 175 | 
1 files changed, 29 insertions, 146 deletions
| diff --git a/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp index fea8100c3b3bc..392049e21c6e5 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 | 
