1//===--- AnalysisConsumer.cpp - ASTConsumer for running Analyses ----------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// "Meta" ASTConsumer for running different source analyses.
10//
11//===----------------------------------------------------------------------===//
12
13#include "clang/StaticAnalyzer/Frontend/AnalysisConsumer.h"
14#include "ModelInjector.h"
15#include "clang/AST/Decl.h"
16#include "clang/AST/DeclCXX.h"
17#include "clang/AST/DeclObjC.h"
18#include "clang/AST/RecursiveASTVisitor.h"
19#include "clang/Analysis/Analyses/LiveVariables.h"
20#include "clang/Analysis/CFG.h"
21#include "clang/Analysis/CallGraph.h"
22#include "clang/Analysis/CodeInjector.h"
23#include "clang/Analysis/PathDiagnostic.h"
24#include "clang/Basic/SourceManager.h"
25#include "clang/CrossTU/CrossTranslationUnit.h"
26#include "clang/Frontend/CompilerInstance.h"
27#include "clang/Lex/Preprocessor.h"
28#include "clang/Rewrite/Core/Rewriter.h"
29#include "clang/StaticAnalyzer/Checkers/LocalCheckers.h"
30#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
31#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
32#include "clang/StaticAnalyzer/Core/CheckerManager.h"
33#include "clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h"
34#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
35#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
36#include "llvm/ADT/PostOrderIterator.h"
37#include "llvm/ADT/Statistic.h"
38#include "llvm/Support/FileSystem.h"
39#include "llvm/Support/Path.h"
40#include "llvm/Support/Program.h"
41#include "llvm/Support/Timer.h"
42#include "llvm/Support/raw_ostream.h"
43#include <memory>
44#include <queue>
45#include <utility>
46
47using namespace clang;
48using namespace ento;
49
50#define DEBUG_TYPE "AnalysisConsumer"
51
52STATISTIC(NumFunctionTopLevel, "The # of functions at top level.");
53STATISTIC(NumFunctionsAnalyzed,
54                      "The # of functions and blocks analyzed (as top level "
55                      "with inlining turned on).");
56STATISTIC(NumBlocksInAnalyzedFunctions,
57                      "The # of basic blocks in the analyzed functions.");
58STATISTIC(NumVisitedBlocksInAnalyzedFunctions,
59          "The # of visited basic blocks in the analyzed functions.");
60STATISTIC(PercentReachableBlocks, "The % of reachable basic blocks.");
61STATISTIC(MaxCFGSize, "The maximum number of basic blocks in a function.");
62
63//===----------------------------------------------------------------------===//
64// AnalysisConsumer declaration.
65//===----------------------------------------------------------------------===//
66
67namespace {
68
69class AnalysisConsumer : public AnalysisASTConsumer,
70                         public RecursiveASTVisitor<AnalysisConsumer> {
71  enum {
72    AM_None = 0,
73    AM_Syntax = 0x1,
74    AM_Path = 0x2
75  };
76  typedef unsigned AnalysisMode;
77
78  /// Mode of the analyzes while recursively visiting Decls.
79  AnalysisMode RecVisitorMode;
80  /// Bug Reporter to use while recursively visiting Decls.
81  BugReporter *RecVisitorBR;
82
83  std::vector<std::function<void(CheckerRegistry &)>> CheckerRegistrationFns;
84
85public:
86  ASTContext *Ctx;
87  Preprocessor &PP;
88  const std::string OutDir;
89  AnalyzerOptionsRef Opts;
90  ArrayRef<std::string> Plugins;
91  CodeInjector *Injector;
92  cross_tu::CrossTranslationUnitContext CTU;
93
94  /// Stores the declarations from the local translation unit.
95  /// Note, we pre-compute the local declarations at parse time as an
96  /// optimization to make sure we do not deserialize everything from disk.
97  /// The local declaration to all declarations ratio might be very small when
98  /// working with a PCH file.
99  SetOfDecls LocalTUDecls;
100
101  // Set of PathDiagnosticConsumers.  Owned by AnalysisManager.
102  PathDiagnosticConsumers PathConsumers;
103
104  StoreManagerCreator CreateStoreMgr;
105  ConstraintManagerCreator CreateConstraintMgr;
106
107  std::unique_ptr<CheckerManager> checkerMgr;
108  std::unique_ptr<AnalysisManager> Mgr;
109
110  /// Time the analyzes time of each translation unit.
111  std::unique_ptr<llvm::TimerGroup> AnalyzerTimers;
112  std::unique_ptr<llvm::Timer> SyntaxCheckTimer;
113  std::unique_ptr<llvm::Timer> ExprEngineTimer;
114  std::unique_ptr<llvm::Timer> BugReporterTimer;
115
116  /// The information about analyzed functions shared throughout the
117  /// translation unit.
118  FunctionSummariesTy FunctionSummaries;
119
120  AnalysisConsumer(CompilerInstance &CI, const std::string &outdir,
121                   AnalyzerOptionsRef opts, ArrayRef<std::string> plugins,
122                   CodeInjector *injector)
123      : RecVisitorMode(0), RecVisitorBR(nullptr), Ctx(nullptr),
124        PP(CI.getPreprocessor()), OutDir(outdir), Opts(std::move(opts)),
125        Plugins(plugins), Injector(injector), CTU(CI) {
126    DigestAnalyzerOptions();
127    if (Opts->PrintStats || Opts->ShouldSerializeStats) {
128      AnalyzerTimers = std::make_unique<llvm::TimerGroup>(
129          "analyzer", "Analyzer timers");
130      SyntaxCheckTimer = std::make_unique<llvm::Timer>(
131          "syntaxchecks", "Syntax-based analysis time", *AnalyzerTimers);
132      ExprEngineTimer = std::make_unique<llvm::Timer>(
133          "exprengine", "Path exploration time", *AnalyzerTimers);
134      BugReporterTimer = std::make_unique<llvm::Timer>(
135          "bugreporter", "Path-sensitive report post-processing time",
136          *AnalyzerTimers);
137      llvm::EnableStatistics(/* PrintOnExit= */ false);
138    }
139  }
140
141  ~AnalysisConsumer() override {
142    if (Opts->PrintStats) {
143      llvm::PrintStatistics();
144    }
145  }
146
147  void DigestAnalyzerOptions() {
148    switch (Opts->AnalysisDiagOpt) {
149    case PD_NONE:
150      break;
151#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN)                    \
152  case PD_##NAME:                                                              \
153    CREATEFN(*Opts.get(), PathConsumers, OutDir, PP, CTU);                     \
154    break;
155#include "clang/StaticAnalyzer/Core/Analyses.def"
156    default:
157      llvm_unreachable("Unknown analyzer output type!");
158    }
159
160    // Create the analyzer component creators.
161    switch (Opts->AnalysisStoreOpt) {
162    default:
163      llvm_unreachable("Unknown store manager.");
164#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATEFN)           \
165      case NAME##Model: CreateStoreMgr = CREATEFN; break;
166#include "clang/StaticAnalyzer/Core/Analyses.def"
167    }
168
169    switch (Opts->AnalysisConstraintsOpt) {
170    default:
171      llvm_unreachable("Unknown constraint manager.");
172#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATEFN)     \
173      case NAME##Model: CreateConstraintMgr = CREATEFN; break;
174#include "clang/StaticAnalyzer/Core/Analyses.def"
175    }
176  }
177
178  void DisplayFunction(const Decl *D, AnalysisMode Mode,
179                       ExprEngine::InliningModes IMode) {
180    if (!Opts->AnalyzerDisplayProgress)
181      return;
182
183    SourceManager &SM = Mgr->getASTContext().getSourceManager();
184    PresumedLoc Loc = SM.getPresumedLoc(D->getLocation());
185    if (Loc.isValid()) {
186      llvm::errs() << "ANALYZE";
187
188      if (Mode == AM_Syntax)
189        llvm::errs() << " (Syntax)";
190      else if (Mode == AM_Path) {
191        llvm::errs() << " (Path, ";
192        switch (IMode) {
193        case ExprEngine::Inline_Minimal:
194          llvm::errs() << " Inline_Minimal";
195          break;
196        case ExprEngine::Inline_Regular:
197          llvm::errs() << " Inline_Regular";
198          break;
199        }
200        llvm::errs() << ")";
201      } else
202        assert(Mode == (AM_Syntax | AM_Path) && "Unexpected mode!");
203
204      llvm::errs() << ": " << Loc.getFilename() << ' ' << getFunctionName(D)
205                   << '\n';
206    }
207  }
208
209  void Initialize(ASTContext &Context) override {
210    Ctx = &Context;
211    checkerMgr = std::make_unique<CheckerManager>(*Ctx, *Opts, PP, Plugins,
212                                                  CheckerRegistrationFns);
213
214    Mgr = std::make_unique<AnalysisManager>(*Ctx, PP, PathConsumers,
215                                            CreateStoreMgr, CreateConstraintMgr,
216                                            checkerMgr.get(), *Opts, Injector);
217  }
218
219  /// Store the top level decls in the set to be processed later on.
220  /// (Doing this pre-processing avoids deserialization of data from PCH.)
221  bool HandleTopLevelDecl(DeclGroupRef D) override;
222  void HandleTopLevelDeclInObjCContainer(DeclGroupRef D) override;
223
224  void HandleTranslationUnit(ASTContext &C) override;
225
226  /// Determine which inlining mode should be used when this function is
227  /// analyzed. This allows to redefine the default inlining policies when
228  /// analyzing a given function.
229  ExprEngine::InliningModes
230    getInliningModeForFunction(const Decl *D, const SetOfConstDecls &Visited);
231
232  /// Build the call graph for all the top level decls of this TU and
233  /// use it to define the order in which the functions should be visited.
234  void HandleDeclsCallGraph(const unsigned LocalTUDeclsSize);
235
236  /// Run analyzes(syntax or path sensitive) on the given function.
237  /// \param Mode - determines if we are requesting syntax only or path
238  /// sensitive only analysis.
239  /// \param VisitedCallees - The output parameter, which is populated with the
240  /// set of functions which should be considered analyzed after analyzing the
241  /// given root function.
242  void HandleCode(Decl *D, AnalysisMode Mode,
243                  ExprEngine::InliningModes IMode = ExprEngine::Inline_Minimal,
244                  SetOfConstDecls *VisitedCallees = nullptr);
245
246  void RunPathSensitiveChecks(Decl *D,
247                              ExprEngine::InliningModes IMode,
248                              SetOfConstDecls *VisitedCallees);
249
250  /// Visitors for the RecursiveASTVisitor.
251  bool shouldWalkTypesOfTypeLocs() const { return false; }
252
253  /// Handle callbacks for arbitrary Decls.
254  bool VisitDecl(Decl *D) {
255    AnalysisMode Mode = getModeForDecl(D, RecVisitorMode);
256    if (Mode & AM_Syntax) {
257      if (SyntaxCheckTimer)
258        SyntaxCheckTimer->startTimer();
259      checkerMgr->runCheckersOnASTDecl(D, *Mgr, *RecVisitorBR);
260      if (SyntaxCheckTimer)
261        SyntaxCheckTimer->stopTimer();
262    }
263    return true;
264  }
265
266  bool VisitVarDecl(VarDecl *VD) {
267    if (!Opts->IsNaiveCTUEnabled)
268      return true;
269
270    if (VD->hasExternalStorage() || VD->isStaticDataMember()) {
271      if (!cross_tu::containsConst(VD, *Ctx))
272        return true;
273    } else {
274      // Cannot be initialized in another TU.
275      return true;
276    }
277
278    if (VD->getAnyInitializer())
279      return true;
280
281    llvm::Expected<const VarDecl *> CTUDeclOrError =
282      CTU.getCrossTUDefinition(VD, Opts->CTUDir, Opts->CTUIndexName,
283                               Opts->DisplayCTUProgress);
284
285    if (!CTUDeclOrError) {
286      handleAllErrors(CTUDeclOrError.takeError(),
287                      [&](const cross_tu::IndexError &IE) {
288                        CTU.emitCrossTUDiagnostics(IE);
289                      });
290    }
291
292    return true;
293  }
294
295  bool VisitFunctionDecl(FunctionDecl *FD) {
296    IdentifierInfo *II = FD->getIdentifier();
297    if (II && II->getName().startswith("__inline"))
298      return true;
299
300    // We skip function template definitions, as their semantics is
301    // only determined when they are instantiated.
302    if (FD->isThisDeclarationADefinition() &&
303        !FD->isDependentContext()) {
304      assert(RecVisitorMode == AM_Syntax || Mgr->shouldInlineCall() == false);
305      HandleCode(FD, RecVisitorMode);
306    }
307    return true;
308  }
309
310  bool VisitObjCMethodDecl(ObjCMethodDecl *MD) {
311    if (MD->isThisDeclarationADefinition()) {
312      assert(RecVisitorMode == AM_Syntax || Mgr->shouldInlineCall() == false);
313      HandleCode(MD, RecVisitorMode);
314    }
315    return true;
316  }
317
318  bool VisitBlockDecl(BlockDecl *BD) {
319    if (BD->hasBody()) {
320      assert(RecVisitorMode == AM_Syntax || Mgr->shouldInlineCall() == false);
321      // Since we skip function template definitions, we should skip blocks
322      // declared in those functions as well.
323      if (!BD->isDependentContext()) {
324        HandleCode(BD, RecVisitorMode);
325      }
326    }
327    return true;
328  }
329
330  void AddDiagnosticConsumer(PathDiagnosticConsumer *Consumer) override {
331    PathConsumers.push_back(Consumer);
332  }
333
334  void AddCheckerRegistrationFn(std::function<void(CheckerRegistry&)> Fn) override {
335    CheckerRegistrationFns.push_back(std::move(Fn));
336  }
337
338private:
339  void storeTopLevelDecls(DeclGroupRef DG);
340  std::string getFunctionName(const Decl *D);
341
342  /// Check if we should skip (not analyze) the given function.
343  AnalysisMode getModeForDecl(Decl *D, AnalysisMode Mode);
344  void runAnalysisOnTranslationUnit(ASTContext &C);
345
346  /// Print \p S to stderr if \c Opts->AnalyzerDisplayProgress is set.
347  void reportAnalyzerProgress(StringRef S);
348}; // namespace
349} // end anonymous namespace
350
351
352//===----------------------------------------------------------------------===//
353// AnalysisConsumer implementation.
354//===----------------------------------------------------------------------===//
355bool AnalysisConsumer::HandleTopLevelDecl(DeclGroupRef DG) {
356  storeTopLevelDecls(DG);
357  return true;
358}
359
360void AnalysisConsumer::HandleTopLevelDeclInObjCContainer(DeclGroupRef DG) {
361  storeTopLevelDecls(DG);
362}
363
364void AnalysisConsumer::storeTopLevelDecls(DeclGroupRef DG) {
365  for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) {
366
367    // Skip ObjCMethodDecl, wait for the objc container to avoid
368    // analyzing twice.
369    if (isa<ObjCMethodDecl>(*I))
370      continue;
371
372    LocalTUDecls.push_back(*I);
373  }
374}
375
376static bool shouldSkipFunction(const Decl *D,
377                               const SetOfConstDecls &Visited,
378                               const SetOfConstDecls &VisitedAsTopLevel) {
379  if (VisitedAsTopLevel.count(D))
380    return true;
381
382  // Skip analysis of inheriting constructors as top-level functions. These
383  // constructors don't even have a body written down in the code, so even if
384  // we find a bug, we won't be able to display it.
385  if (const auto *CD = dyn_cast<CXXConstructorDecl>(D))
386    if (CD->isInheritingConstructor())
387      return true;
388
389  // We want to re-analyse the functions as top level in the following cases:
390  // - The 'init' methods should be reanalyzed because
391  //   ObjCNonNilReturnValueChecker assumes that '[super init]' never returns
392  //   'nil' and unless we analyze the 'init' functions as top level, we will
393  //   not catch errors within defensive code.
394  // - We want to reanalyze all ObjC methods as top level to report Retain
395  //   Count naming convention errors more aggressively.
396  if (isa<ObjCMethodDecl>(D))
397    return false;
398  // We also want to reanalyze all C++ copy and move assignment operators to
399  // separately check the two cases where 'this' aliases with the parameter and
400  // where it may not. (cplusplus.SelfAssignmentChecker)
401  if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
402    if (MD->isCopyAssignmentOperator() || MD->isMoveAssignmentOperator())
403      return false;
404  }
405
406  // Otherwise, if we visited the function before, do not reanalyze it.
407  return Visited.count(D);
408}
409
410ExprEngine::InliningModes
411AnalysisConsumer::getInliningModeForFunction(const Decl *D,
412                                             const SetOfConstDecls &Visited) {
413  // We want to reanalyze all ObjC methods as top level to report Retain
414  // Count naming convention errors more aggressively. But we should tune down
415  // inlining when reanalyzing an already inlined function.
416  if (Visited.count(D) && isa<ObjCMethodDecl>(D)) {
417    const ObjCMethodDecl *ObjCM = cast<ObjCMethodDecl>(D);
418    if (ObjCM->getMethodFamily() != OMF_init)
419      return ExprEngine::Inline_Minimal;
420  }
421
422  return ExprEngine::Inline_Regular;
423}
424
425void AnalysisConsumer::HandleDeclsCallGraph(const unsigned LocalTUDeclsSize) {
426  // Build the Call Graph by adding all the top level declarations to the graph.
427  // Note: CallGraph can trigger deserialization of more items from a pch
428  // (though HandleInterestingDecl); triggering additions to LocalTUDecls.
429  // We rely on random access to add the initially processed Decls to CG.
430  CallGraph CG;
431  for (unsigned i = 0 ; i < LocalTUDeclsSize ; ++i) {
432    CG.addToCallGraph(LocalTUDecls[i]);
433  }
434
435  // Walk over all of the call graph nodes in topological order, so that we
436  // analyze parents before the children. Skip the functions inlined into
437  // the previously processed functions. Use external Visited set to identify
438  // inlined functions. The topological order allows the "do not reanalyze
439  // previously inlined function" performance heuristic to be triggered more
440  // often.
441  SetOfConstDecls Visited;
442  SetOfConstDecls VisitedAsTopLevel;
443  llvm::ReversePostOrderTraversal<clang::CallGraph*> RPOT(&CG);
444  for (llvm::ReversePostOrderTraversal<clang::CallGraph*>::rpo_iterator
445         I = RPOT.begin(), E = RPOT.end(); I != E; ++I) {
446    NumFunctionTopLevel++;
447
448    CallGraphNode *N = *I;
449    Decl *D = N->getDecl();
450
451    // Skip the abstract root node.
452    if (!D)
453      continue;
454
455    // Skip the functions which have been processed already or previously
456    // inlined.
457    if (shouldSkipFunction(D, Visited, VisitedAsTopLevel))
458      continue;
459
460    // Analyze the function.
461    SetOfConstDecls VisitedCallees;
462
463    HandleCode(D, AM_Path, getInliningModeForFunction(D, Visited),
464               (Mgr->options.InliningMode == All ? nullptr : &VisitedCallees));
465
466    // Add the visited callees to the global visited set.
467    for (const Decl *Callee : VisitedCallees)
468      // Decls from CallGraph are already canonical. But Decls coming from
469      // CallExprs may be not. We should canonicalize them manually.
470      Visited.insert(isa<ObjCMethodDecl>(Callee) ? Callee
471                                                 : Callee->getCanonicalDecl());
472    VisitedAsTopLevel.insert(D);
473  }
474}
475
476static bool isBisonFile(ASTContext &C) {
477  const SourceManager &SM = C.getSourceManager();
478  FileID FID = SM.getMainFileID();
479  StringRef Buffer = SM.getBuffer(FID)->getBuffer();
480  if (Buffer.startswith("/* A Bison parser, made by"))
481    return true;
482  return false;
483}
484
485void AnalysisConsumer::runAnalysisOnTranslationUnit(ASTContext &C) {
486  BugReporter BR(*Mgr);
487  TranslationUnitDecl *TU = C.getTranslationUnitDecl();
488  if (SyntaxCheckTimer)
489    SyntaxCheckTimer->startTimer();
490  checkerMgr->runCheckersOnASTDecl(TU, *Mgr, BR);
491  if (SyntaxCheckTimer)
492    SyntaxCheckTimer->stopTimer();
493
494  // Run the AST-only checks using the order in which functions are defined.
495  // If inlining is not turned on, use the simplest function order for path
496  // sensitive analyzes as well.
497  RecVisitorMode = AM_Syntax;
498  if (!Mgr->shouldInlineCall())
499    RecVisitorMode |= AM_Path;
500  RecVisitorBR = &BR;
501
502  // Process all the top level declarations.
503  //
504  // Note: TraverseDecl may modify LocalTUDecls, but only by appending more
505  // entries.  Thus we don't use an iterator, but rely on LocalTUDecls
506  // random access.  By doing so, we automatically compensate for iterators
507  // possibly being invalidated, although this is a bit slower.
508  const unsigned LocalTUDeclsSize = LocalTUDecls.size();
509  for (unsigned i = 0 ; i < LocalTUDeclsSize ; ++i) {
510    TraverseDecl(LocalTUDecls[i]);
511  }
512
513  if (Mgr->shouldInlineCall())
514    HandleDeclsCallGraph(LocalTUDeclsSize);
515
516  // After all decls handled, run checkers on the entire TranslationUnit.
517  checkerMgr->runCheckersOnEndOfTranslationUnit(TU, *Mgr, BR);
518
519  BR.FlushReports();
520  RecVisitorBR = nullptr;
521}
522
523void AnalysisConsumer::reportAnalyzerProgress(StringRef S) {
524  if (Opts->AnalyzerDisplayProgress)
525    llvm::errs() << S;
526}
527
528void AnalysisConsumer::HandleTranslationUnit(ASTContext &C) {
529
530  // Don't run the actions if an error has occurred with parsing the file.
531  DiagnosticsEngine &Diags = PP.getDiagnostics();
532  if (Diags.hasErrorOccurred() || Diags.hasFatalErrorOccurred())
533    return;
534
535  if (isBisonFile(C)) {
536    reportAnalyzerProgress("Skipping bison-generated file\n");
537  } else if (Opts->DisableAllCheckers) {
538
539    // Don't analyze if the user explicitly asked for no checks to be performed
540    // on this file.
541    reportAnalyzerProgress("All checks are disabled using a supplied option\n");
542  } else {
543    // Otherwise, just run the analysis.
544    runAnalysisOnTranslationUnit(C);
545  }
546
547  // Count how many basic blocks we have not covered.
548  NumBlocksInAnalyzedFunctions = FunctionSummaries.getTotalNumBasicBlocks();
549  NumVisitedBlocksInAnalyzedFunctions =
550      FunctionSummaries.getTotalNumVisitedBasicBlocks();
551  if (NumBlocksInAnalyzedFunctions > 0)
552    PercentReachableBlocks =
553      (FunctionSummaries.getTotalNumVisitedBasicBlocks() * 100) /
554        NumBlocksInAnalyzedFunctions;
555
556  // Explicitly destroy the PathDiagnosticConsumer.  This will flush its output.
557  // FIXME: This should be replaced with something that doesn't rely on
558  // side-effects in PathDiagnosticConsumer's destructor. This is required when
559  // used with option -disable-free.
560  Mgr.reset();
561}
562
563std::string AnalysisConsumer::getFunctionName(const Decl *D) {
564  std::string Str;
565  llvm::raw_string_ostream OS(Str);
566
567  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
568    OS << FD->getQualifiedNameAsString();
569
570    // In C++, there are overloads.
571    if (Ctx->getLangOpts().CPlusPlus) {
572      OS << '(';
573      for (const auto &P : FD->parameters()) {
574        if (P != *FD->param_begin())
575          OS << ", ";
576        OS << P->getType().getAsString();
577      }
578      OS << ')';
579    }
580
581  } else if (isa<BlockDecl>(D)) {
582    PresumedLoc Loc = Ctx->getSourceManager().getPresumedLoc(D->getLocation());
583
584    if (Loc.isValid()) {
585      OS << "block (line: " << Loc.getLine() << ", col: " << Loc.getColumn()
586         << ')';
587    }
588
589  } else if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D)) {
590
591    // FIXME: copy-pasted from CGDebugInfo.cpp.
592    OS << (OMD->isInstanceMethod() ? '-' : '+') << '[';
593    const DeclContext *DC = OMD->getDeclContext();
594    if (const auto *OID = dyn_cast<ObjCImplementationDecl>(DC)) {
595      OS << OID->getName();
596    } else if (const auto *OID = dyn_cast<ObjCInterfaceDecl>(DC)) {
597      OS << OID->getName();
598    } else if (const auto *OC = dyn_cast<ObjCCategoryDecl>(DC)) {
599      if (OC->IsClassExtension()) {
600        OS << OC->getClassInterface()->getName();
601      } else {
602        OS << OC->getIdentifier()->getNameStart() << '('
603           << OC->getIdentifier()->getNameStart() << ')';
604      }
605    } else if (const auto *OCD = dyn_cast<ObjCCategoryImplDecl>(DC)) {
606      OS << OCD->getClassInterface()->getName() << '('
607         << OCD->getName() << ')';
608    }
609    OS << ' ' << OMD->getSelector().getAsString() << ']';
610
611  }
612
613  return OS.str();
614}
615
616AnalysisConsumer::AnalysisMode
617AnalysisConsumer::getModeForDecl(Decl *D, AnalysisMode Mode) {
618  if (!Opts->AnalyzeSpecificFunction.empty() &&
619      getFunctionName(D) != Opts->AnalyzeSpecificFunction)
620    return AM_None;
621
622  // Unless -analyze-all is specified, treat decls differently depending on
623  // where they came from:
624  // - Main source file: run both path-sensitive and non-path-sensitive checks.
625  // - Header files: run non-path-sensitive checks only.
626  // - System headers: don't run any checks.
627  SourceManager &SM = Ctx->getSourceManager();
628  const Stmt *Body = D->getBody();
629  SourceLocation SL = Body ? Body->getBeginLoc() : D->getLocation();
630  SL = SM.getExpansionLoc(SL);
631
632  if (!Opts->AnalyzeAll && !Mgr->isInCodeFile(SL)) {
633    if (SL.isInvalid() || SM.isInSystemHeader(SL))
634      return AM_None;
635    return Mode & ~AM_Path;
636  }
637
638  return Mode;
639}
640
641void AnalysisConsumer::HandleCode(Decl *D, AnalysisMode Mode,
642                                  ExprEngine::InliningModes IMode,
643                                  SetOfConstDecls *VisitedCallees) {
644  if (!D->hasBody())
645    return;
646  Mode = getModeForDecl(D, Mode);
647  if (Mode == AM_None)
648    return;
649
650  // Clear the AnalysisManager of old AnalysisDeclContexts.
651  Mgr->ClearContexts();
652  // Ignore autosynthesized code.
653  if (Mgr->getAnalysisDeclContext(D)->isBodyAutosynthesized())
654    return;
655
656  DisplayFunction(D, Mode, IMode);
657  CFG *DeclCFG = Mgr->getCFG(D);
658  if (DeclCFG)
659    MaxCFGSize.updateMax(DeclCFG->size());
660
661  BugReporter BR(*Mgr);
662
663  if (Mode & AM_Syntax) {
664    if (SyntaxCheckTimer)
665      SyntaxCheckTimer->startTimer();
666    checkerMgr->runCheckersOnASTBody(D, *Mgr, BR);
667    if (SyntaxCheckTimer)
668      SyntaxCheckTimer->stopTimer();
669  }
670
671  BR.FlushReports();
672
673  if ((Mode & AM_Path) && checkerMgr->hasPathSensitiveCheckers()) {
674    RunPathSensitiveChecks(D, IMode, VisitedCallees);
675    if (IMode != ExprEngine::Inline_Minimal)
676      NumFunctionsAnalyzed++;
677  }
678}
679
680//===----------------------------------------------------------------------===//
681// Path-sensitive checking.
682//===----------------------------------------------------------------------===//
683
684void AnalysisConsumer::RunPathSensitiveChecks(Decl *D,
685                                              ExprEngine::InliningModes IMode,
686                                              SetOfConstDecls *VisitedCallees) {
687  // Construct the analysis engine.  First check if the CFG is valid.
688  // FIXME: Inter-procedural analysis will need to handle invalid CFGs.
689  if (!Mgr->getCFG(D))
690    return;
691
692  // See if the LiveVariables analysis scales.
693  if (!Mgr->getAnalysisDeclContext(D)->getAnalysis<RelaxedLiveVariables>())
694    return;
695
696  ExprEngine Eng(CTU, *Mgr, VisitedCallees, &FunctionSummaries, IMode);
697
698  // Execute the worklist algorithm.
699  if (ExprEngineTimer)
700    ExprEngineTimer->startTimer();
701  Eng.ExecuteWorkList(Mgr->getAnalysisDeclContextManager().getStackFrame(D),
702                      Mgr->options.MaxNodesPerTopLevelFunction);
703  if (ExprEngineTimer)
704    ExprEngineTimer->stopTimer();
705
706  if (!Mgr->options.DumpExplodedGraphTo.empty())
707    Eng.DumpGraph(Mgr->options.TrimGraph, Mgr->options.DumpExplodedGraphTo);
708
709  // Visualize the exploded graph.
710  if (Mgr->options.visualizeExplodedGraphWithGraphViz)
711    Eng.ViewGraph(Mgr->options.TrimGraph);
712
713  // Display warnings.
714  if (BugReporterTimer)
715    BugReporterTimer->startTimer();
716  Eng.getBugReporter().FlushReports();
717  if (BugReporterTimer)
718    BugReporterTimer->stopTimer();
719}
720
721//===----------------------------------------------------------------------===//
722// AnalysisConsumer creation.
723//===----------------------------------------------------------------------===//
724
725std::unique_ptr<AnalysisASTConsumer>
726ento::CreateAnalysisConsumer(CompilerInstance &CI) {
727  // Disable the effects of '-Werror' when using the AnalysisConsumer.
728  CI.getPreprocessor().getDiagnostics().setWarningsAsErrors(false);
729
730  AnalyzerOptionsRef analyzerOpts = CI.getAnalyzerOpts();
731  bool hasModelPath = analyzerOpts->Config.count("model-path") > 0;
732
733  return std::make_unique<AnalysisConsumer>(
734      CI, CI.getFrontendOpts().OutputFile, analyzerOpts,
735      CI.getFrontendOpts().Plugins,
736      hasModelPath ? new ModelInjector(CI) : nullptr);
737}
738