//===--- AnalysisConsumer.cpp - ASTConsumer for running Analyses ----------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// "Meta" ASTConsumer for running different source analyses.
//
//===----------------------------------------------------------------------===//

#include "clang/StaticAnalyzer/Frontend/AnalysisConsumer.h"
#include "ModelInjector.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Analysis/Analyses/LiveVariables.h"
#include "clang/Analysis/CFG.h"
#include "clang/Analysis/CallGraph.h"
#include "clang/Analysis/CodeInjector.h"
#include "clang/Analysis/MacroExpansionContext.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/Core/AnalyzerOptions.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
#include "llvm/ADT/PostOrderIterator.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Program.h"
#include "llvm/Support/Timer.h"
#include "llvm/Support/raw_ostream.h"
#include <memory>
#include <queue>
#include <utility>

using namespace clang;
using namespace ento;

#define DEBUG_TYPE "AnalysisConsumer"

STATISTIC(NumFunctionTopLevel, "The # of functions at top level.");
STATISTIC(NumFunctionsAnalyzed,
                      "The # of functions and blocks analyzed (as top level "
                      "with inlining turned on).");
STATISTIC(NumBlocksInAnalyzedFunctions,
                      "The # of basic blocks in the analyzed functions.");
STATISTIC(NumVisitedBlocksInAnalyzedFunctions,
          "The # of visited basic blocks in the analyzed functions.");
STATISTIC(PercentReachableBlocks, "The % of reachable basic blocks.");
STATISTIC(MaxCFGSize, "The maximum number of basic blocks in a function.");

//===----------------------------------------------------------------------===//
// AnalysisConsumer declaration.
//===----------------------------------------------------------------------===//

namespace {

class AnalysisConsumer : public AnalysisASTConsumer,
                         public RecursiveASTVisitor<AnalysisConsumer> {
  enum {
    AM_None = 0,
    AM_Syntax = 0x1,
    AM_Path = 0x2
  };
  typedef unsigned AnalysisMode;

  /// Mode of the analyzes while recursively visiting Decls.
  AnalysisMode RecVisitorMode;
  /// Bug Reporter to use while recursively visiting Decls.
  BugReporter *RecVisitorBR;

  std::vector<std::function<void(CheckerRegistry &)>> CheckerRegistrationFns;

public:
  ASTContext *Ctx;
  Preprocessor &PP;
  const std::string OutDir;
  AnalyzerOptionsRef Opts;
  ArrayRef<std::string> Plugins;
  CodeInjector *Injector;
  cross_tu::CrossTranslationUnitContext CTU;

  /// Stores the declarations from the local translation unit.
  /// Note, we pre-compute the local declarations at parse time as an
  /// optimization to make sure we do not deserialize everything from disk.
  /// The local declaration to all declarations ratio might be very small when
  /// working with a PCH file.
  SetOfDecls LocalTUDecls;

  MacroExpansionContext MacroExpansions;

  // Set of PathDiagnosticConsumers.  Owned by AnalysisManager.
  PathDiagnosticConsumers PathConsumers;

  StoreManagerCreator CreateStoreMgr;
  ConstraintManagerCreator CreateConstraintMgr;

  std::unique_ptr<CheckerManager> checkerMgr;
  std::unique_ptr<AnalysisManager> Mgr;

  /// Time the analyzes time of each translation unit.
  std::unique_ptr<llvm::TimerGroup> AnalyzerTimers;
  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.
  FunctionSummariesTy FunctionSummaries;

  AnalysisConsumer(CompilerInstance &CI, const std::string &outdir,
                   AnalyzerOptionsRef opts, ArrayRef<std::string> plugins,
                   CodeInjector *injector)
      : RecVisitorMode(0), RecVisitorBR(nullptr), Ctx(nullptr),
        PP(CI.getPreprocessor()), OutDir(outdir), Opts(std::move(opts)),
        Plugins(plugins), Injector(injector), CTU(CI),
        MacroExpansions(CI.getLangOpts()) {
    DigestAnalyzerOptions();
    if (Opts->AnalyzerDisplayProgress || Opts->PrintStats ||
        Opts->ShouldSerializeStats) {
      AnalyzerTimers = std::make_unique<llvm::TimerGroup>(
          "analyzer", "Analyzer timers");
      SyntaxCheckTimer = std::make_unique<llvm::Timer>(
          "syntaxchecks", "Syntax-based analysis time", *AnalyzerTimers);
      ExprEngineTimer = std::make_unique<llvm::Timer>(
          "exprengine", "Path exploration time", *AnalyzerTimers);
      BugReporterTimer = std::make_unique<llvm::Timer>(
          "bugreporter", "Path-sensitive report post-processing time",
          *AnalyzerTimers);
    }

    if (Opts->PrintStats || Opts->ShouldSerializeStats) {
      llvm::EnableStatistics(/* DoPrintOnExit= */ false);
    }

    if (Opts->ShouldDisplayMacroExpansions)
      MacroExpansions.registerForPreprocessor(PP);
  }

  ~AnalysisConsumer() override {
    if (Opts->PrintStats) {
      llvm::PrintStatistics();
    }
  }

  void DigestAnalyzerOptions() {
    switch (Opts->AnalysisDiagOpt) {
    case PD_NONE:
      break;
#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN)                    \
  case PD_##NAME:                                                              \
    CREATEFN(Opts->getDiagOpts(), PathConsumers, OutDir, PP, CTU,              \
             MacroExpansions);                                                 \
    break;
#include "clang/StaticAnalyzer/Core/Analyses.def"
    default:
      llvm_unreachable("Unknown analyzer output type!");
    }

    // Create the analyzer component creators.
    CreateStoreMgr = &CreateRegionStoreManager;

    switch (Opts->AnalysisConstraintsOpt) {
    default:
      llvm_unreachable("Unknown constraint manager.");
#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATEFN)     \
      case NAME##Model: CreateConstraintMgr = CREATEFN; break;
#include "clang/StaticAnalyzer/Core/Analyses.def"
    }
  }

  void DisplayTime(llvm::TimeRecord &Time) {
    if (!Opts->AnalyzerDisplayProgress) {
      return;
    }
    llvm::errs() << " : " << llvm::format("%1.1f", Time.getWallTime() * 1000)
                 << " ms\n";
  }

  void DisplayFunction(const Decl *D, AnalysisMode Mode,
                       ExprEngine::InliningModes IMode) {
    if (!Opts->AnalyzerDisplayProgress)
      return;

    SourceManager &SM = Mgr->getASTContext().getSourceManager();
    PresumedLoc Loc = SM.getPresumedLoc(D->getLocation());
    if (Loc.isValid()) {
      llvm::errs() << "ANALYZE";

      if (Mode == AM_Syntax)
        llvm::errs() << " (Syntax)";
      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;
        }
        llvm::errs() << ")";
      } else
        assert(Mode == (AM_Syntax | AM_Path) && "Unexpected mode!");

      llvm::errs() << ": " << Loc.getFilename() << ' '
                   << AnalysisDeclContext::getFunctionName(D);
    }
  }

  void Initialize(ASTContext &Context) override {
    Ctx = &Context;
    checkerMgr = std::make_unique<CheckerManager>(*Ctx, *Opts, PP, Plugins,
                                                  CheckerRegistrationFns);

    Mgr = std::make_unique<AnalysisManager>(*Ctx, PP, PathConsumers,
                                            CreateStoreMgr, CreateConstraintMgr,
                                            checkerMgr.get(), *Opts, Injector);
  }

  /// Store the top level decls in the set to be processed later on.
  /// (Doing this pre-processing avoids deserialization of data from PCH.)
  bool HandleTopLevelDecl(DeclGroupRef D) override;
  void HandleTopLevelDeclInObjCContainer(DeclGroupRef D) override;

  void HandleTranslationUnit(ASTContext &C) override;

  /// Determine which inlining mode should be used when this function is
  /// analyzed. This allows to redefine the default inlining policies when
  /// analyzing a given function.
  ExprEngine::InliningModes
    getInliningModeForFunction(const Decl *D, const SetOfConstDecls &Visited);

  /// Build the call graph for all the top level decls of this TU and
  /// use it to define the order in which the functions should be visited.
  void HandleDeclsCallGraph(const unsigned LocalTUDeclsSize);

  /// Run analyzes(syntax or path sensitive) on the given function.
  /// \param Mode - determines if we are requesting syntax only or path
  /// sensitive only analysis.
  /// \param VisitedCallees - The output parameter, which is populated with the
  /// set of functions which should be considered analyzed after analyzing the
  /// given root function.
  void HandleCode(Decl *D, AnalysisMode Mode,
                  ExprEngine::InliningModes IMode = ExprEngine::Inline_Minimal,
                  SetOfConstDecls *VisitedCallees = nullptr);

  void RunPathSensitiveChecks(Decl *D,
                              ExprEngine::InliningModes IMode,
                              SetOfConstDecls *VisitedCallees);

  /// Visitors for the RecursiveASTVisitor.
  bool shouldWalkTypesOfTypeLocs() const { return false; }

  /// Handle callbacks for arbitrary Decls.
  bool VisitDecl(Decl *D) {
    AnalysisMode Mode = getModeForDecl(D, RecVisitorMode);
    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::shouldImport(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;
  }

  bool VisitFunctionDecl(FunctionDecl *FD) {
    IdentifierInfo *II = FD->getIdentifier();
    if (II && II->getName().startswith("__inline"))
      return true;

    // We skip function template definitions, as their semantics is
    // only determined when they are instantiated.
    if (FD->isThisDeclarationADefinition() &&
        !FD->isDependentContext()) {
      assert(RecVisitorMode == AM_Syntax || Mgr->shouldInlineCall() == false);
      HandleCode(FD, RecVisitorMode);
    }
    return true;
  }

  bool VisitObjCMethodDecl(ObjCMethodDecl *MD) {
    if (MD->isThisDeclarationADefinition()) {
      assert(RecVisitorMode == AM_Syntax || Mgr->shouldInlineCall() == false);
      HandleCode(MD, RecVisitorMode);
    }
    return true;
  }

  bool VisitBlockDecl(BlockDecl *BD) {
    if (BD->hasBody()) {
      assert(RecVisitorMode == AM_Syntax || Mgr->shouldInlineCall() == false);
      // Since we skip function template definitions, we should skip blocks
      // declared in those functions as well.
      if (!BD->isDependentContext()) {
        HandleCode(BD, RecVisitorMode);
      }
    }
    return true;
  }

  void AddDiagnosticConsumer(PathDiagnosticConsumer *Consumer) override {
    PathConsumers.push_back(Consumer);
  }

  void AddCheckerRegistrationFn(std::function<void(CheckerRegistry&)> Fn) override {
    CheckerRegistrationFns.push_back(std::move(Fn));
  }

private:
  void storeTopLevelDecls(DeclGroupRef DG);

  /// Check if we should skip (not analyze) the given function.
  AnalysisMode getModeForDecl(Decl *D, AnalysisMode Mode);
  void runAnalysisOnTranslationUnit(ASTContext &C);

  /// Print \p S to stderr if \c Opts->AnalyzerDisplayProgress is set.
  void reportAnalyzerProgress(StringRef S);
}; // namespace
} // end anonymous namespace


//===----------------------------------------------------------------------===//
// AnalysisConsumer implementation.
//===----------------------------------------------------------------------===//
bool AnalysisConsumer::HandleTopLevelDecl(DeclGroupRef DG) {
  storeTopLevelDecls(DG);
  return true;
}

void AnalysisConsumer::HandleTopLevelDeclInObjCContainer(DeclGroupRef DG) {
  storeTopLevelDecls(DG);
}

void AnalysisConsumer::storeTopLevelDecls(DeclGroupRef DG) {
  for (auto &I : DG) {

    // Skip ObjCMethodDecl, wait for the objc container to avoid
    // analyzing twice.
    if (isa<ObjCMethodDecl>(I))
      continue;

    LocalTUDecls.push_back(I);
  }
}

static bool shouldSkipFunction(const Decl *D,
                               const SetOfConstDecls &Visited,
                               const SetOfConstDecls &VisitedAsTopLevel) {
  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
  //   'nil' and unless we analyze the 'init' functions as top level, we will
  //   not catch errors within defensive code.
  // - We want to reanalyze all ObjC methods as top level to report Retain
  //   Count naming convention errors more aggressively.
  if (isa<ObjCMethodDecl>(D))
    return false;
  // We also want to reanalyze all C++ copy and move assignment operators to
  // separately check the two cases where 'this' aliases with the parameter and
  // where it may not. (cplusplus.SelfAssignmentChecker)
  if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
    if (MD->isCopyAssignmentOperator() || MD->isMoveAssignmentOperator())
      return false;
  }

  // Otherwise, if we visited the function before, do not reanalyze it.
  return Visited.count(D);
}

ExprEngine::InliningModes
AnalysisConsumer::getInliningModeForFunction(const Decl *D,
                                             const SetOfConstDecls &Visited) {
  // We want to reanalyze all ObjC methods as top level to report Retain
  // Count naming convention errors more aggressively. But we should tune down
  // inlining when reanalyzing an already inlined function.
  if (Visited.count(D) && isa<ObjCMethodDecl>(D)) {
    const ObjCMethodDecl *ObjCM = cast<ObjCMethodDecl>(D);
    if (ObjCM->getMethodFamily() != OMF_init)
      return ExprEngine::Inline_Minimal;
  }

  return ExprEngine::Inline_Regular;
}

void AnalysisConsumer::HandleDeclsCallGraph(const unsigned LocalTUDeclsSize) {
  // Build the Call Graph by adding all the top level declarations to the graph.
  // Note: CallGraph can trigger deserialization of more items from a pch
  // (though HandleInterestingDecl); triggering additions to LocalTUDecls.
  // We rely on random access to add the initially processed Decls to CG.
  CallGraph CG;
  for (unsigned i = 0 ; i < LocalTUDeclsSize ; ++i) {
    CG.addToCallGraph(LocalTUDecls[i]);
  }

  // Walk over all of the call graph nodes in topological order, so that we
  // analyze parents before the children. Skip the functions inlined into
  // the previously processed functions. Use external Visited set to identify
  // inlined functions. The topological order allows the "do not reanalyze
  // previously inlined function" performance heuristic to be triggered more
  // often.
  SetOfConstDecls Visited;
  SetOfConstDecls VisitedAsTopLevel;
  llvm::ReversePostOrderTraversal<clang::CallGraph*> RPOT(&CG);
  for (auto &N : RPOT) {
    NumFunctionTopLevel++;

    Decl *D = N->getDecl();

    // Skip the abstract root node.
    if (!D)
      continue;

    // Skip the functions which have been processed already or previously
    // inlined.
    if (shouldSkipFunction(D, Visited, VisitedAsTopLevel))
      continue;

    // The CallGraph might have declarations as callees. However, during CTU
    // the declaration might form a declaration chain with the newly imported
    // definition from another TU. In this case we don't want to analyze the
    // function definition as toplevel.
    if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
      // Calling 'hasBody' replaces 'FD' in place with the FunctionDecl
      // that has the body.
      FD->hasBody(FD);
      if (CTU.isImportedAsNew(FD))
        continue;
    }

    // Analyze the function.
    SetOfConstDecls VisitedCallees;

    HandleCode(D, AM_Path, getInliningModeForFunction(D, Visited),
               (Mgr->options.InliningMode == All ? nullptr : &VisitedCallees));

    // Add the visited callees to the global visited set.
    for (const Decl *Callee : VisitedCallees)
      // Decls from CallGraph are already canonical. But Decls coming from
      // CallExprs may be not. We should canonicalize them manually.
      Visited.insert(isa<ObjCMethodDecl>(Callee) ? Callee
                                                 : Callee->getCanonicalDecl());
    VisitedAsTopLevel.insert(D);
  }
}

static bool fileContainsString(StringRef Substring, ASTContext &C) {
  const SourceManager &SM = C.getSourceManager();
  FileID FID = SM.getMainFileID();
  StringRef Buffer = SM.getBufferOrFake(FID).getBuffer();
  return Buffer.contains(Substring);
}

static void reportAnalyzerFunctionMisuse(const AnalyzerOptions &Opts,
                                         const ASTContext &Ctx) {
  llvm::errs() << "Every top-level function was skipped.\n";

  if (!Opts.AnalyzerDisplayProgress)
    llvm::errs() << "Pass the -analyzer-display-progress for tracking which "
                    "functions are analyzed.\n";

  bool HasBrackets =
      Opts.AnalyzeSpecificFunction.find("(") != std::string::npos;

  if (Ctx.getLangOpts().CPlusPlus && !HasBrackets) {
    llvm::errs()
        << "For analyzing C++ code you need to pass the function parameter "
           "list: -analyze-function=\"foobar(int, _Bool)\"\n";
  } else if (!Ctx.getLangOpts().CPlusPlus && HasBrackets) {
    llvm::errs() << "For analyzing C code you shouldn't pass the function "
                    "parameter list, only the name of the function: "
                    "-analyze-function=foobar\n";
  }
}

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
  // sensitive analyzes as well.
  RecVisitorMode = AM_Syntax;
  if (!Mgr->shouldInlineCall())
    RecVisitorMode |= AM_Path;
  RecVisitorBR = &BR;

  // Process all the top level declarations.
  //
  // Note: TraverseDecl may modify LocalTUDecls, but only by appending more
  // entries.  Thus we don't use an iterator, but rely on LocalTUDecls
  // random access.  By doing so, we automatically compensate for iterators
  // possibly being invalidated, although this is a bit slower.
  const unsigned LocalTUDeclsSize = LocalTUDecls.size();
  for (unsigned i = 0 ; i < LocalTUDeclsSize ; ++i) {
    TraverseDecl(LocalTUDecls[i]);
  }

  if (Mgr->shouldInlineCall())
    HandleDeclsCallGraph(LocalTUDeclsSize);

  // After all decls handled, run checkers on the entire TranslationUnit.
  checkerMgr->runCheckersOnEndOfTranslationUnit(TU, *Mgr, BR);

  BR.FlushReports();
  RecVisitorBR = nullptr;

  // 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)
    reportAnalyzerFunctionMisuse(*Opts, *Ctx);
}

void AnalysisConsumer::reportAnalyzerProgress(StringRef S) {
  if (Opts->AnalyzerDisplayProgress)
    llvm::errs() << S;
}

void AnalysisConsumer::HandleTranslationUnit(ASTContext &C) {
  // Don't run the actions if an error has occurred with parsing the file.
  DiagnosticsEngine &Diags = PP.getDiagnostics();
  if (Diags.hasErrorOccurred() || Diags.hasFatalErrorOccurred())
    return;

  // Explicitly destroy the PathDiagnosticConsumer.  This will flush its output.
  // FIXME: This should be replaced with something that doesn't rely on
  // side-effects in PathDiagnosticConsumer's destructor. This is required when
  // used with option -disable-free.
  const auto DiagFlusherScopeExit =
      llvm::make_scope_exit([this] { Mgr.reset(); });

  if (Opts->ShouldIgnoreBisonGeneratedFiles &&
      fileContainsString("/* A Bison parser, made by", C)) {
    reportAnalyzerProgress("Skipping bison-generated file\n");
    return;
  }

  if (Opts->ShouldIgnoreFlexGeneratedFiles &&
      fileContainsString("/* A lexical scanner generated by flex", C)) {
    reportAnalyzerProgress("Skipping flex-generated file\n");
    return;
  }

  // Don't analyze if the user explicitly asked for no checks to be performed
  // on this file.
  if (Opts->DisableAllCheckers) {
    reportAnalyzerProgress("All checks are disabled using a supplied option\n");
    return;
  }

  // Otherwise, just run the analysis.
  runAnalysisOnTranslationUnit(C);

  // Count how many basic blocks we have not covered.
  NumBlocksInAnalyzedFunctions = FunctionSummaries.getTotalNumBasicBlocks();
  NumVisitedBlocksInAnalyzedFunctions =
      FunctionSummaries.getTotalNumVisitedBasicBlocks();
  if (NumBlocksInAnalyzedFunctions > 0)
    PercentReachableBlocks =
        (FunctionSummaries.getTotalNumVisitedBasicBlocks() * 100) /
        NumBlocksInAnalyzedFunctions;
}

AnalysisConsumer::AnalysisMode
AnalysisConsumer::getModeForDecl(Decl *D, AnalysisMode Mode) {
  if (!Opts->AnalyzeSpecificFunction.empty() &&
      AnalysisDeclContext::getFunctionName(D) != Opts->AnalyzeSpecificFunction)
    return AM_None;

  // Unless -analyze-all is specified, treat decls differently depending on
  // where they came from:
  // - Main source file: run both path-sensitive and non-path-sensitive checks.
  // - Header files: run non-path-sensitive checks only.
  // - System headers: don't run any checks.
  if (Opts->AnalyzeAll)
    return Mode;

  const SourceManager &SM = Ctx->getSourceManager();

  const SourceLocation Loc = [&SM](Decl *D) -> SourceLocation {
    const Stmt *Body = D->getBody();
    SourceLocation SL = Body ? Body->getBeginLoc() : D->getLocation();
    return SM.getExpansionLoc(SL);
  }(D);

  // Ignore system headers.
  if (Loc.isInvalid() || SM.isInSystemHeader(Loc))
    return AM_None;

  // Disable path sensitive analysis in user-headers.
  if (!Mgr->isInCodeFile(Loc))
    return Mode & ~AM_Path;

  return Mode;
}

void AnalysisConsumer::HandleCode(Decl *D, AnalysisMode Mode,
                                  ExprEngine::InliningModes IMode,
                                  SetOfConstDecls *VisitedCallees) {
  if (!D->hasBody())
    return;
  Mode = getModeForDecl(D, Mode);
  if (Mode == AM_None)
    return;

  // Clear the AnalysisManager of old AnalysisDeclContexts.
  Mgr->ClearContexts();
  // Ignore autosynthesized code.
  if (Mgr->getAnalysisDeclContext(D)->isBodyAutosynthesized())
    return;

  CFG *DeclCFG = Mgr->getCFG(D);
  if (DeclCFG)
    MaxCFGSize.updateMax(DeclCFG->size());

  DisplayFunction(D, Mode, IMode);
  BugReporter BR(*Mgr);

  if (Mode & AM_Syntax) {
    llvm::TimeRecord CheckerStartTime;
    if (SyntaxCheckTimer) {
      CheckerStartTime = SyntaxCheckTimer->getTotalTime();
      SyntaxCheckTimer->startTimer();
    }
    checkerMgr->runCheckersOnASTBody(D, *Mgr, BR);
    if (SyntaxCheckTimer) {
      SyntaxCheckTimer->stopTimer();
      llvm::TimeRecord CheckerEndTime = SyntaxCheckTimer->getTotalTime();
      CheckerEndTime -= CheckerStartTime;
      DisplayTime(CheckerEndTime);
    }
  }

  BR.FlushReports();

  if ((Mode & AM_Path) && checkerMgr->hasPathSensitiveCheckers()) {
    RunPathSensitiveChecks(D, IMode, VisitedCallees);
    if (IMode != ExprEngine::Inline_Minimal)
      NumFunctionsAnalyzed++;
  }
}

//===----------------------------------------------------------------------===//
// Path-sensitive checking.
//===----------------------------------------------------------------------===//

void AnalysisConsumer::RunPathSensitiveChecks(Decl *D,
                                              ExprEngine::InliningModes IMode,
                                              SetOfConstDecls *VisitedCallees) {
  // Construct the analysis engine.  First check if the CFG is valid.
  // FIXME: Inter-procedural analysis will need to handle invalid CFGs.
  if (!Mgr->getCFG(D))
    return;

  // See if the LiveVariables analysis scales.
  if (!Mgr->getAnalysisDeclContext(D)->getAnalysis<RelaxedLiveVariables>())
    return;

  ExprEngine Eng(CTU, *Mgr, VisitedCallees, &FunctionSummaries, IMode);

  // Execute the worklist algorithm.
  llvm::TimeRecord ExprEngineStartTime;
  if (ExprEngineTimer) {
    ExprEngineStartTime = ExprEngineTimer->getTotalTime();
    ExprEngineTimer->startTimer();
  }
  Eng.ExecuteWorkList(Mgr->getAnalysisDeclContextManager().getStackFrame(D),
                      Mgr->options.MaxNodesPerTopLevelFunction);
  if (ExprEngineTimer) {
    ExprEngineTimer->stopTimer();
    llvm::TimeRecord ExprEngineEndTime = ExprEngineTimer->getTotalTime();
    ExprEngineEndTime -= ExprEngineStartTime;
    DisplayTime(ExprEngineEndTime);
  }

  if (!Mgr->options.DumpExplodedGraphTo.empty())
    Eng.DumpGraph(Mgr->options.TrimGraph, Mgr->options.DumpExplodedGraphTo);

  // Visualize the exploded graph.
  if (Mgr->options.visualizeExplodedGraphWithGraphViz)
    Eng.ViewGraph(Mgr->options.TrimGraph);

  // Display warnings.
  if (BugReporterTimer)
    BugReporterTimer->startTimer();
  Eng.getBugReporter().FlushReports();
  if (BugReporterTimer)
    BugReporterTimer->stopTimer();
}

//===----------------------------------------------------------------------===//
// AnalysisConsumer creation.
//===----------------------------------------------------------------------===//

std::unique_ptr<AnalysisASTConsumer>
ento::CreateAnalysisConsumer(CompilerInstance &CI) {
  // Disable the effects of '-Werror' when using the AnalysisConsumer.
  CI.getPreprocessor().getDiagnostics().setWarningsAsErrors(false);

  AnalyzerOptionsRef analyzerOpts = CI.getAnalyzerOpts();
  bool hasModelPath = analyzerOpts->Config.count("model-path") > 0;

  return std::make_unique<AnalysisConsumer>(
      CI, CI.getFrontendOpts().OutputFile, analyzerOpts,
      CI.getFrontendOpts().Plugins,
      hasModelPath ? new ModelInjector(CI) : nullptr);
}
