clang  6.0.0svn
AnalysisConsumer.cpp
Go to the documentation of this file.
1 //===--- AnalysisConsumer.cpp - ASTConsumer for running Analyses ----------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // "Meta" ASTConsumer for running different source analyses.
11 //
12 //===----------------------------------------------------------------------===//
13 
15 #include "ModelInjector.h"
16 #include "clang/AST/Decl.h"
17 #include "clang/AST/DeclCXX.h"
18 #include "clang/AST/DeclObjC.h"
21 #include "clang/Analysis/CFG.h"
26 #include "clang/Lex/Preprocessor.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 
47 using namespace clang;
48 using namespace ento;
49 
50 #define DEBUG_TYPE "AnalysisConsumer"
51 
52 static std::unique_ptr<ExplodedNode::Auditor> CreateUbiViz();
53 
54 STATISTIC(NumFunctionTopLevel, "The # of functions at top level.");
55 STATISTIC(NumFunctionsAnalyzed,
56  "The # of functions and blocks analyzed (as top level "
57  "with inlining turned on).");
58 STATISTIC(NumBlocksInAnalyzedFunctions,
59  "The # of basic blocks in the analyzed functions.");
60 STATISTIC(PercentReachableBlocks, "The % of reachable basic blocks.");
61 STATISTIC(MaxCFGSize, "The maximum number of basic blocks in a function.");
62 
63 //===----------------------------------------------------------------------===//
64 // Special PathDiagnosticConsumers.
65 //===----------------------------------------------------------------------===//
66 
67 void ento::createPlistHTMLDiagnosticConsumer(AnalyzerOptions &AnalyzerOpts,
69  const std::string &prefix,
70  const Preprocessor &PP) {
71  createHTMLDiagnosticConsumer(AnalyzerOpts, C,
72  llvm::sys::path::parent_path(prefix), PP);
73  createPlistDiagnosticConsumer(AnalyzerOpts, C, prefix, PP);
74 }
75 
76 void ento::createTextPathDiagnosticConsumer(AnalyzerOptions &AnalyzerOpts,
78  const std::string &Prefix,
79  const clang::Preprocessor &PP) {
80  llvm_unreachable("'text' consumer should be enabled on ClangDiags");
81 }
82 
83 namespace {
84 class ClangDiagPathDiagConsumer : public PathDiagnosticConsumer {
86  bool IncludePath;
87 public:
88  ClangDiagPathDiagConsumer(DiagnosticsEngine &Diag)
89  : Diag(Diag), IncludePath(false) {}
90  ~ClangDiagPathDiagConsumer() override {}
91  StringRef getName() const override { return "ClangDiags"; }
92 
93  bool supportsLogicalOpControlFlow() const override { return true; }
94  bool supportsCrossFileDiagnostics() const override { return true; }
95 
96  PathGenerationScheme getGenerationScheme() const override {
97  return IncludePath ? Minimal : None;
98  }
99 
100  void enablePaths() {
101  IncludePath = true;
102  }
103 
104  void FlushDiagnosticsImpl(std::vector<const PathDiagnostic *> &Diags,
105  FilesMade *filesMade) override {
106  unsigned WarnID = Diag.getCustomDiagID(DiagnosticsEngine::Warning, "%0");
107  unsigned NoteID = Diag.getCustomDiagID(DiagnosticsEngine::Note, "%0");
108 
109  for (std::vector<const PathDiagnostic*>::iterator I = Diags.begin(),
110  E = Diags.end(); I != E; ++I) {
111  const PathDiagnostic *PD = *I;
112  SourceLocation WarnLoc = PD->getLocation().asLocation();
113  Diag.Report(WarnLoc, WarnID) << PD->getShortDescription()
114  << PD->path.back()->getRanges();
115 
116  // First, add extra notes, even if paths should not be included.
117  for (const auto &Piece : PD->path) {
118  if (!isa<PathDiagnosticNotePiece>(Piece.get()))
119  continue;
120 
121  SourceLocation NoteLoc = Piece->getLocation().asLocation();
122  Diag.Report(NoteLoc, NoteID) << Piece->getString()
123  << Piece->getRanges();
124  }
125 
126  if (!IncludePath)
127  continue;
128 
129  // Then, add the path notes if necessary.
130  PathPieces FlatPath = PD->path.flatten(/*ShouldFlattenMacros=*/true);
131  for (const auto &Piece : FlatPath) {
132  if (isa<PathDiagnosticNotePiece>(Piece.get()))
133  continue;
134 
135  SourceLocation NoteLoc = Piece->getLocation().asLocation();
136  Diag.Report(NoteLoc, NoteID) << Piece->getString()
137  << Piece->getRanges();
138  }
139  }
140  }
141 };
142 } // end anonymous namespace
143 
144 //===----------------------------------------------------------------------===//
145 // AnalysisConsumer declaration.
146 //===----------------------------------------------------------------------===//
147 
148 namespace {
149 
150 class AnalysisConsumer : public AnalysisASTConsumer,
151  public RecursiveASTVisitor<AnalysisConsumer> {
152  enum {
153  AM_None = 0,
154  AM_Syntax = 0x1,
155  AM_Path = 0x2
156  };
157  typedef unsigned AnalysisMode;
158 
159  /// Mode of the analyzes while recursively visiting Decls.
160  AnalysisMode RecVisitorMode;
161  /// Bug Reporter to use while recursively visiting Decls.
162  BugReporter *RecVisitorBR;
163 
164 public:
165  ASTContext *Ctx;
166  const Preprocessor &PP;
167  const std::string OutDir;
168  AnalyzerOptionsRef Opts;
169  ArrayRef<std::string> Plugins;
170  CodeInjector *Injector;
171 
172  /// \brief Stores the declarations from the local translation unit.
173  /// Note, we pre-compute the local declarations at parse time as an
174  /// optimization to make sure we do not deserialize everything from disk.
175  /// The local declaration to all declarations ratio might be very small when
176  /// working with a PCH file.
177  SetOfDecls LocalTUDecls;
178 
179  // Set of PathDiagnosticConsumers. Owned by AnalysisManager.
180  PathDiagnosticConsumers PathConsumers;
181 
182  StoreManagerCreator CreateStoreMgr;
183  ConstraintManagerCreator CreateConstraintMgr;
184 
185  std::unique_ptr<CheckerManager> checkerMgr;
186  std::unique_ptr<AnalysisManager> Mgr;
187 
188  /// Time the analyzes time of each translation unit.
189  static llvm::Timer* TUTotalTimer;
190 
191  /// The information about analyzed functions shared throughout the
192  /// translation unit.
193  FunctionSummariesTy FunctionSummaries;
194 
195  AnalysisConsumer(const Preprocessor &pp, const std::string &outdir,
197  CodeInjector *injector)
198  : RecVisitorMode(0), RecVisitorBR(nullptr), Ctx(nullptr), PP(pp),
199  OutDir(outdir), Opts(std::move(opts)), Plugins(plugins),
200  Injector(injector) {
201  DigestAnalyzerOptions();
202  if (Opts->PrintStats) {
203  llvm::EnableStatistics(false);
204  TUTotalTimer = new llvm::Timer("time", "Analyzer Total Time");
205  }
206  }
207 
208  ~AnalysisConsumer() override {
209  if (Opts->PrintStats) {
210  delete TUTotalTimer;
211  llvm::PrintStatistics();
212  }
213  }
214 
215  void DigestAnalyzerOptions() {
216  if (Opts->AnalysisDiagOpt != PD_NONE) {
217  // Create the PathDiagnosticConsumer.
218  ClangDiagPathDiagConsumer *clangDiags =
219  new ClangDiagPathDiagConsumer(PP.getDiagnostics());
220  PathConsumers.push_back(clangDiags);
221 
222  if (Opts->AnalysisDiagOpt == PD_TEXT) {
223  clangDiags->enablePaths();
224 
225  } else if (!OutDir.empty()) {
226  switch (Opts->AnalysisDiagOpt) {
227  default:
228 #define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN) \
229  case PD_##NAME: \
230  CREATEFN(*Opts.get(), PathConsumers, OutDir, PP); \
231  break;
232 #include "clang/StaticAnalyzer/Core/Analyses.def"
233  }
234  }
235  }
236 
237  // Create the analyzer component creators.
238  switch (Opts->AnalysisStoreOpt) {
239  default:
240  llvm_unreachable("Unknown store manager.");
241 #define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATEFN) \
242  case NAME##Model: CreateStoreMgr = CREATEFN; break;
243 #include "clang/StaticAnalyzer/Core/Analyses.def"
244  }
245 
246  switch (Opts->AnalysisConstraintsOpt) {
247  default:
248  llvm_unreachable("Unknown constraint manager.");
249 #define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATEFN) \
250  case NAME##Model: CreateConstraintMgr = CREATEFN; break;
251 #include "clang/StaticAnalyzer/Core/Analyses.def"
252  }
253  }
254 
255  void DisplayFunction(const Decl *D, AnalysisMode Mode,
257  if (!Opts->AnalyzerDisplayProgress)
258  return;
259 
260  SourceManager &SM = Mgr->getASTContext().getSourceManager();
262  if (Loc.isValid()) {
263  llvm::errs() << "ANALYZE";
264 
265  if (Mode == AM_Syntax)
266  llvm::errs() << " (Syntax)";
267  else if (Mode == AM_Path) {
268  llvm::errs() << " (Path, ";
269  switch (IMode) {
271  llvm::errs() << " Inline_Minimal";
272  break;
274  llvm::errs() << " Inline_Regular";
275  break;
276  }
277  llvm::errs() << ")";
278  }
279  else
280  assert(Mode == (AM_Syntax | AM_Path) && "Unexpected mode!");
281 
282  llvm::errs() << ": " << Loc.getFilename() << ' '
283  << getFunctionName(D) << '\n';
284  }
285  }
286 
287  void Initialize(ASTContext &Context) override {
288  Ctx = &Context;
289  checkerMgr = createCheckerManager(*Opts, PP.getLangOpts(), Plugins,
290  PP.getDiagnostics());
291 
292  Mgr = llvm::make_unique<AnalysisManager>(
293  *Ctx, PP.getDiagnostics(), PP.getLangOpts(), PathConsumers,
294  CreateStoreMgr, CreateConstraintMgr, checkerMgr.get(), *Opts, Injector);
295  }
296 
297  /// \brief Store the top level decls in the set to be processed later on.
298  /// (Doing this pre-processing avoids deserialization of data from PCH.)
299  bool HandleTopLevelDecl(DeclGroupRef D) override;
300  void HandleTopLevelDeclInObjCContainer(DeclGroupRef D) override;
301 
302  void HandleTranslationUnit(ASTContext &C) override;
303 
304  /// \brief Determine which inlining mode should be used when this function is
305  /// analyzed. This allows to redefine the default inlining policies when
306  /// analyzing a given function.
308  getInliningModeForFunction(const Decl *D, const SetOfConstDecls &Visited);
309 
310  /// \brief Build the call graph for all the top level decls of this TU and
311  /// use it to define the order in which the functions should be visited.
312  void HandleDeclsCallGraph(const unsigned LocalTUDeclsSize);
313 
314  /// \brief Run analyzes(syntax or path sensitive) on the given function.
315  /// \param Mode - determines if we are requesting syntax only or path
316  /// sensitive only analysis.
317  /// \param VisitedCallees - The output parameter, which is populated with the
318  /// set of functions which should be considered analyzed after analyzing the
319  /// given root function.
320  void HandleCode(Decl *D, AnalysisMode Mode,
322  SetOfConstDecls *VisitedCallees = nullptr);
323 
324  void RunPathSensitiveChecks(Decl *D,
326  SetOfConstDecls *VisitedCallees);
327  void ActionExprEngine(Decl *D, bool ObjCGCEnabled,
329  SetOfConstDecls *VisitedCallees);
330 
331  /// Visitors for the RecursiveASTVisitor.
332  bool shouldWalkTypesOfTypeLocs() const { return false; }
333 
334  /// Handle callbacks for arbitrary Decls.
335  bool VisitDecl(Decl *D) {
336  AnalysisMode Mode = getModeForDecl(D, RecVisitorMode);
337  if (Mode & AM_Syntax)
338  checkerMgr->runCheckersOnASTDecl(D, *Mgr, *RecVisitorBR);
339  return true;
340  }
341 
342  bool VisitFunctionDecl(FunctionDecl *FD) {
343  IdentifierInfo *II = FD->getIdentifier();
344  if (II && II->getName().startswith("__inline"))
345  return true;
346 
347  // We skip function template definitions, as their semantics is
348  // only determined when they are instantiated.
349  if (FD->isThisDeclarationADefinition() &&
350  !FD->isDependentContext()) {
351  assert(RecVisitorMode == AM_Syntax || Mgr->shouldInlineCall() == false);
352  HandleCode(FD, RecVisitorMode);
353  }
354  return true;
355  }
356 
357  bool VisitObjCMethodDecl(ObjCMethodDecl *MD) {
358  if (MD->isThisDeclarationADefinition()) {
359  assert(RecVisitorMode == AM_Syntax || Mgr->shouldInlineCall() == false);
360  HandleCode(MD, RecVisitorMode);
361  }
362  return true;
363  }
364 
365  bool VisitBlockDecl(BlockDecl *BD) {
366  if (BD->hasBody()) {
367  assert(RecVisitorMode == AM_Syntax || Mgr->shouldInlineCall() == false);
368  // Since we skip function template definitions, we should skip blocks
369  // declared in those functions as well.
370  if (!BD->isDependentContext()) {
371  HandleCode(BD, RecVisitorMode);
372  }
373  }
374  return true;
375  }
376 
377  void AddDiagnosticConsumer(PathDiagnosticConsumer *Consumer) override {
378  PathConsumers.push_back(Consumer);
379  }
380 
381 private:
382  void storeTopLevelDecls(DeclGroupRef DG);
383  std::string getFunctionName(const Decl *D);
384 
385  /// \brief Check if we should skip (not analyze) the given function.
386  AnalysisMode getModeForDecl(Decl *D, AnalysisMode Mode);
387 
388 };
389 } // end anonymous namespace
390 
391 
392 //===----------------------------------------------------------------------===//
393 // AnalysisConsumer implementation.
394 //===----------------------------------------------------------------------===//
395 llvm::Timer* AnalysisConsumer::TUTotalTimer = nullptr;
396 
397 bool AnalysisConsumer::HandleTopLevelDecl(DeclGroupRef DG) {
398  storeTopLevelDecls(DG);
399  return true;
400 }
401 
402 void AnalysisConsumer::HandleTopLevelDeclInObjCContainer(DeclGroupRef DG) {
403  storeTopLevelDecls(DG);
404 }
405 
406 void AnalysisConsumer::storeTopLevelDecls(DeclGroupRef DG) {
407  for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) {
408 
409  // Skip ObjCMethodDecl, wait for the objc container to avoid
410  // analyzing twice.
411  if (isa<ObjCMethodDecl>(*I))
412  continue;
413 
414  LocalTUDecls.push_back(*I);
415  }
416 }
417 
418 static bool shouldSkipFunction(const Decl *D,
419  const SetOfConstDecls &Visited,
420  const SetOfConstDecls &VisitedAsTopLevel) {
421  if (VisitedAsTopLevel.count(D))
422  return true;
423 
424  // We want to re-analyse the functions as top level in the following cases:
425  // - The 'init' methods should be reanalyzed because
426  // ObjCNonNilReturnValueChecker assumes that '[super init]' never returns
427  // 'nil' and unless we analyze the 'init' functions as top level, we will
428  // not catch errors within defensive code.
429  // - We want to reanalyze all ObjC methods as top level to report Retain
430  // Count naming convention errors more aggressively.
431  if (isa<ObjCMethodDecl>(D))
432  return false;
433  // We also want to reanalyze all C++ copy and move assignment operators to
434  // separately check the two cases where 'this' aliases with the parameter and
435  // where it may not. (cplusplus.SelfAssignmentChecker)
436  if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
437  if (MD->isCopyAssignmentOperator() || MD->isMoveAssignmentOperator())
438  return false;
439  }
440 
441  // Otherwise, if we visited the function before, do not reanalyze it.
442  return Visited.count(D);
443 }
444 
446 AnalysisConsumer::getInliningModeForFunction(const Decl *D,
447  const SetOfConstDecls &Visited) {
448  // We want to reanalyze all ObjC methods as top level to report Retain
449  // Count naming convention errors more aggressively. But we should tune down
450  // inlining when reanalyzing an already inlined function.
451  if (Visited.count(D) && isa<ObjCMethodDecl>(D)) {
452  const ObjCMethodDecl *ObjCM = cast<ObjCMethodDecl>(D);
453  if (ObjCM->getMethodFamily() != OMF_init)
455  }
456 
458 }
459 
460 void AnalysisConsumer::HandleDeclsCallGraph(const unsigned LocalTUDeclsSize) {
461  // Build the Call Graph by adding all the top level declarations to the graph.
462  // Note: CallGraph can trigger deserialization of more items from a pch
463  // (though HandleInterestingDecl); triggering additions to LocalTUDecls.
464  // We rely on random access to add the initially processed Decls to CG.
465  CallGraph CG;
466  for (unsigned i = 0 ; i < LocalTUDeclsSize ; ++i) {
467  CG.addToCallGraph(LocalTUDecls[i]);
468  }
469 
470  // Walk over all of the call graph nodes in topological order, so that we
471  // analyze parents before the children. Skip the functions inlined into
472  // the previously processed functions. Use external Visited set to identify
473  // inlined functions. The topological order allows the "do not reanalyze
474  // previously inlined function" performance heuristic to be triggered more
475  // often.
476  SetOfConstDecls Visited;
477  SetOfConstDecls VisitedAsTopLevel;
478  llvm::ReversePostOrderTraversal<clang::CallGraph*> RPOT(&CG);
479  for (llvm::ReversePostOrderTraversal<clang::CallGraph*>::rpo_iterator
480  I = RPOT.begin(), E = RPOT.end(); I != E; ++I) {
481  NumFunctionTopLevel++;
482 
483  CallGraphNode *N = *I;
484  Decl *D = N->getDecl();
485 
486  // Skip the abstract root node.
487  if (!D)
488  continue;
489 
490  // Skip the functions which have been processed already or previously
491  // inlined.
492  if (shouldSkipFunction(D, Visited, VisitedAsTopLevel))
493  continue;
494 
495  // Analyze the function.
496  SetOfConstDecls VisitedCallees;
497 
498  HandleCode(D, AM_Path, getInliningModeForFunction(D, Visited),
499  (Mgr->options.InliningMode == All ? nullptr : &VisitedCallees));
500 
501  // Add the visited callees to the global visited set.
502  for (const Decl *Callee : VisitedCallees)
503  // Decls from CallGraph are already canonical. But Decls coming from
504  // CallExprs may be not. We should canonicalize them manually.
505  Visited.insert(isa<ObjCMethodDecl>(Callee) ? Callee
506  : Callee->getCanonicalDecl());
507  VisitedAsTopLevel.insert(D);
508  }
509 }
510 
511 void AnalysisConsumer::HandleTranslationUnit(ASTContext &C) {
512  // Don't run the actions if an error has occurred with parsing the file.
513  DiagnosticsEngine &Diags = PP.getDiagnostics();
514  if (Diags.hasErrorOccurred() || Diags.hasFatalErrorOccurred())
515  return;
516 
517  // Don't analyze if the user explicitly asked for no checks to be performed
518  // on this file.
519  if (Opts->DisableAllChecks)
520  return;
521 
522  {
523  if (TUTotalTimer) TUTotalTimer->startTimer();
524 
525  // Introduce a scope to destroy BR before Mgr.
526  BugReporter BR(*Mgr);
528  checkerMgr->runCheckersOnASTDecl(TU, *Mgr, BR);
529 
530  // Run the AST-only checks using the order in which functions are defined.
531  // If inlining is not turned on, use the simplest function order for path
532  // sensitive analyzes as well.
533  RecVisitorMode = AM_Syntax;
534  if (!Mgr->shouldInlineCall())
535  RecVisitorMode |= AM_Path;
536  RecVisitorBR = &BR;
537 
538  // Process all the top level declarations.
539  //
540  // Note: TraverseDecl may modify LocalTUDecls, but only by appending more
541  // entries. Thus we don't use an iterator, but rely on LocalTUDecls
542  // random access. By doing so, we automatically compensate for iterators
543  // possibly being invalidated, although this is a bit slower.
544  const unsigned LocalTUDeclsSize = LocalTUDecls.size();
545  for (unsigned i = 0 ; i < LocalTUDeclsSize ; ++i) {
546  TraverseDecl(LocalTUDecls[i]);
547  }
548 
549  if (Mgr->shouldInlineCall())
550  HandleDeclsCallGraph(LocalTUDeclsSize);
551 
552  // After all decls handled, run checkers on the entire TranslationUnit.
553  checkerMgr->runCheckersOnEndOfTranslationUnit(TU, *Mgr, BR);
554 
555  RecVisitorBR = nullptr;
556  }
557 
558  // Explicitly destroy the PathDiagnosticConsumer. This will flush its output.
559  // FIXME: This should be replaced with something that doesn't rely on
560  // side-effects in PathDiagnosticConsumer's destructor. This is required when
561  // used with option -disable-free.
562  Mgr.reset();
563 
564  if (TUTotalTimer) TUTotalTimer->stopTimer();
565 
566  // Count how many basic blocks we have not covered.
567  NumBlocksInAnalyzedFunctions = FunctionSummaries.getTotalNumBasicBlocks();
568  if (NumBlocksInAnalyzedFunctions > 0)
569  PercentReachableBlocks =
570  (FunctionSummaries.getTotalNumVisitedBasicBlocks() * 100) /
571  NumBlocksInAnalyzedFunctions;
572 
573 }
574 
575 std::string AnalysisConsumer::getFunctionName(const Decl *D) {
576  std::string Str;
577  llvm::raw_string_ostream OS(Str);
578 
579  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
580  OS << FD->getQualifiedNameAsString();
581 
582  // In C++, there are overloads.
583  if (Ctx->getLangOpts().CPlusPlus) {
584  OS << '(';
585  for (const auto &P : FD->parameters()) {
586  if (P != *FD->param_begin())
587  OS << ", ";
588  OS << P->getType().getAsString();
589  }
590  OS << ')';
591  }
592 
593  } else if (isa<BlockDecl>(D)) {
594  PresumedLoc Loc = Ctx->getSourceManager().getPresumedLoc(D->getLocation());
595 
596  if (Loc.isValid()) {
597  OS << "block (line: " << Loc.getLine() << ", col: " << Loc.getColumn()
598  << ')';
599  }
600 
601  } else if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D)) {
602 
603  // FIXME: copy-pasted from CGDebugInfo.cpp.
604  OS << (OMD->isInstanceMethod() ? '-' : '+') << '[';
605  const DeclContext *DC = OMD->getDeclContext();
606  if (const auto *OID = dyn_cast<ObjCImplementationDecl>(DC)) {
607  OS << OID->getName();
608  } else if (const auto *OID = dyn_cast<ObjCInterfaceDecl>(DC)) {
609  OS << OID->getName();
610  } else if (const auto *OC = dyn_cast<ObjCCategoryDecl>(DC)) {
611  if (OC->IsClassExtension()) {
612  OS << OC->getClassInterface()->getName();
613  } else {
614  OS << OC->getIdentifier()->getNameStart() << '('
615  << OC->getIdentifier()->getNameStart() << ')';
616  }
617  } else if (const auto *OCD = dyn_cast<ObjCCategoryImplDecl>(DC)) {
618  OS << OCD->getClassInterface()->getName() << '('
619  << OCD->getName() << ')';
620  } else if (isa<ObjCProtocolDecl>(DC)) {
621  // We can extract the type of the class from the self pointer.
622  if (ImplicitParamDecl *SelfDecl = OMD->getSelfDecl()) {
623  QualType ClassTy =
624  cast<ObjCObjectPointerType>(SelfDecl->getType())->getPointeeType();
625  ClassTy.print(OS, PrintingPolicy(LangOptions()));
626  }
627  }
628  OS << ' ' << OMD->getSelector().getAsString() << ']';
629 
630  }
631 
632  return OS.str();
633 }
634 
635 AnalysisConsumer::AnalysisMode
636 AnalysisConsumer::getModeForDecl(Decl *D, AnalysisMode Mode) {
637  if (!Opts->AnalyzeSpecificFunction.empty() &&
638  getFunctionName(D) != Opts->AnalyzeSpecificFunction)
639  return AM_None;
640 
641  // Unless -analyze-all is specified, treat decls differently depending on
642  // where they came from:
643  // - Main source file: run both path-sensitive and non-path-sensitive checks.
644  // - Header files: run non-path-sensitive checks only.
645  // - System headers: don't run any checks.
646  SourceManager &SM = Ctx->getSourceManager();
647  const Stmt *Body = D->getBody();
648  SourceLocation SL = Body ? Body->getLocStart() : D->getLocation();
649  SL = SM.getExpansionLoc(SL);
650 
651  if (!Opts->AnalyzeAll && !SM.isWrittenInMainFile(SL)) {
652  if (SL.isInvalid() || SM.isInSystemHeader(SL))
653  return AM_None;
654  return Mode & ~AM_Path;
655  }
656 
657  return Mode;
658 }
659 
660 void AnalysisConsumer::HandleCode(Decl *D, AnalysisMode Mode,
662  SetOfConstDecls *VisitedCallees) {
663  if (!D->hasBody())
664  return;
665  Mode = getModeForDecl(D, Mode);
666  if (Mode == AM_None)
667  return;
668 
669  // Clear the AnalysisManager of old AnalysisDeclContexts.
670  Mgr->ClearContexts();
671  // Ignore autosynthesized code.
672  if (Mgr->getAnalysisDeclContext(D)->isBodyAutosynthesized())
673  return;
674 
675  DisplayFunction(D, Mode, IMode);
676  CFG *DeclCFG = Mgr->getCFG(D);
677  if (DeclCFG)
678  MaxCFGSize.updateMax(DeclCFG->size());
679 
680  BugReporter BR(*Mgr);
681 
682  if (Mode & AM_Syntax)
683  checkerMgr->runCheckersOnASTBody(D, *Mgr, BR);
684  if ((Mode & AM_Path) && checkerMgr->hasPathSensitiveCheckers()) {
685  RunPathSensitiveChecks(D, IMode, VisitedCallees);
686  if (IMode != ExprEngine::Inline_Minimal)
687  NumFunctionsAnalyzed++;
688  }
689 }
690 
691 //===----------------------------------------------------------------------===//
692 // Path-sensitive checking.
693 //===----------------------------------------------------------------------===//
694 
695 void AnalysisConsumer::ActionExprEngine(Decl *D, bool ObjCGCEnabled,
697  SetOfConstDecls *VisitedCallees) {
698  // Construct the analysis engine. First check if the CFG is valid.
699  // FIXME: Inter-procedural analysis will need to handle invalid CFGs.
700  if (!Mgr->getCFG(D))
701  return;
702 
703  // See if the LiveVariables analysis scales.
704  if (!Mgr->getAnalysisDeclContext(D)->getAnalysis<RelaxedLiveVariables>())
705  return;
706 
707  ExprEngine Eng(*Mgr, ObjCGCEnabled, VisitedCallees, &FunctionSummaries,IMode);
708 
709  // Set the graph auditor.
710  std::unique_ptr<ExplodedNode::Auditor> Auditor;
711  if (Mgr->options.visualizeExplodedGraphWithUbiGraph) {
712  Auditor = CreateUbiViz();
713  ExplodedNode::SetAuditor(Auditor.get());
714  }
715 
716  // Execute the worklist algorithm.
717  Eng.ExecuteWorkList(Mgr->getAnalysisDeclContextManager().getStackFrame(D),
718  Mgr->options.getMaxNodesPerTopLevelFunction());
719 
720  // Release the auditor (if any) so that it doesn't monitor the graph
721  // created BugReporter.
722  ExplodedNode::SetAuditor(nullptr);
723 
724  // Visualize the exploded graph.
725  if (Mgr->options.visualizeExplodedGraphWithGraphViz)
726  Eng.ViewGraph(Mgr->options.TrimGraph);
727 
728  // Display warnings.
730 }
731 
732 void AnalysisConsumer::RunPathSensitiveChecks(Decl *D,
734  SetOfConstDecls *Visited) {
735 
736  switch (Mgr->getLangOpts().getGC()) {
737  case LangOptions::NonGC:
738  ActionExprEngine(D, false, IMode, Visited);
739  break;
740 
741  case LangOptions::GCOnly:
742  ActionExprEngine(D, true, IMode, Visited);
743  break;
744 
746  ActionExprEngine(D, false, IMode, Visited);
747  ActionExprEngine(D, true, IMode, Visited);
748  break;
749  }
750 }
751 
752 //===----------------------------------------------------------------------===//
753 // AnalysisConsumer creation.
754 //===----------------------------------------------------------------------===//
755 
756 std::unique_ptr<AnalysisASTConsumer>
758  // Disable the effects of '-Werror' when using the AnalysisConsumer.
760 
761  AnalyzerOptionsRef analyzerOpts = CI.getAnalyzerOpts();
762  bool hasModelPath = analyzerOpts->Config.count("model-path") > 0;
763 
764  return llvm::make_unique<AnalysisConsumer>(
765  CI.getPreprocessor(), CI.getFrontendOpts().OutputFile, analyzerOpts,
767  hasModelPath ? new ModelInjector(CI) : nullptr);
768 }
769 
770 //===----------------------------------------------------------------------===//
771 // Ubigraph Visualization. FIXME: Move to separate file.
772 //===----------------------------------------------------------------------===//
773 
774 namespace {
775 
776 class UbigraphViz : public ExplodedNode::Auditor {
777  std::unique_ptr<raw_ostream> Out;
778  std::string Filename;
779  unsigned Cntr;
780 
781  typedef llvm::DenseMap<void*,unsigned> VMap;
782  VMap M;
783 
784 public:
785  UbigraphViz(std::unique_ptr<raw_ostream> Out, StringRef Filename);
786 
787  ~UbigraphViz() override;
788 
789  void AddEdge(ExplodedNode *Src, ExplodedNode *Dst) override;
790 };
791 
792 } // end anonymous namespace
793 
794 static std::unique_ptr<ExplodedNode::Auditor> CreateUbiViz() {
796  int FD;
797  llvm::sys::fs::createTemporaryFile("llvm_ubi", "", FD, P);
798  llvm::errs() << "Writing '" << P << "'.\n";
799 
800  auto Stream = llvm::make_unique<llvm::raw_fd_ostream>(FD, true);
801 
802  return llvm::make_unique<UbigraphViz>(std::move(Stream), P);
803 }
804 
805 void UbigraphViz::AddEdge(ExplodedNode *Src, ExplodedNode *Dst) {
806 
807  assert (Src != Dst && "Self-edges are not allowed.");
808 
809  // Lookup the Src. If it is a new node, it's a root.
810  VMap::iterator SrcI= M.find(Src);
811  unsigned SrcID;
812 
813  if (SrcI == M.end()) {
814  M[Src] = SrcID = Cntr++;
815  *Out << "('vertex', " << SrcID << ", ('color','#00ff00'))\n";
816  }
817  else
818  SrcID = SrcI->second;
819 
820  // Lookup the Dst.
821  VMap::iterator DstI= M.find(Dst);
822  unsigned DstID;
823 
824  if (DstI == M.end()) {
825  M[Dst] = DstID = Cntr++;
826  *Out << "('vertex', " << DstID << ")\n";
827  }
828  else {
829  // We have hit DstID before. Change its style to reflect a cache hit.
830  DstID = DstI->second;
831  *Out << "('change_vertex_style', " << DstID << ", 1)\n";
832  }
833 
834  // Add the edge.
835  *Out << "('edge', " << SrcID << ", " << DstID
836  << ", ('arrow','true'), ('oriented', 'true'))\n";
837 }
838 
839 UbigraphViz::UbigraphViz(std::unique_ptr<raw_ostream> OutStream,
840  StringRef Filename)
841  : Out(std::move(OutStream)), Filename(Filename), Cntr(0) {
842 
843  *Out << "('vertex_style_attribute', 0, ('shape', 'icosahedron'))\n";
844  *Out << "('vertex_style', 1, 0, ('shape', 'sphere'), ('color', '#ffcc66'),"
845  " ('size', '1.5'))\n";
846 }
847 
848 UbigraphViz::~UbigraphViz() {
849  Out.reset();
850  llvm::errs() << "Running 'ubiviz' program... ";
851  std::string ErrMsg;
852  std::string Ubiviz;
853  if (auto Path = llvm::sys::findProgramByName("ubiviz"))
854  Ubiviz = *Path;
855  const char *args[] = {Ubiviz.c_str(), Filename.c_str(), nullptr};
856 
857  if (llvm::sys::ExecuteAndWait(Ubiviz, &args[0], nullptr, {}, 0, 0, &ErrMsg)) {
858  llvm::errs() << "Error viewing graph: " << ErrMsg << "\n";
859  }
860 
861  // Delete the file.
862  llvm::sys::fs::remove(Filename);
863 }
The AST-based call graph.
Definition: CallGraph.h:34
std::string OutputFile
The output file, if any.
FunctionDecl - An instance of this class is created to represent a function declaration or definition...
Definition: Decl.h:1631
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
bool isThisDeclarationADefinition() const
Returns whether this specific method is a definition.
Definition: DeclObjC.h:497
bool hasErrorOccurred() const
Definition: Diagnostic.h:660
A (possibly-)qualified type.
Definition: Type.h:614
void print(raw_ostream &OS, const PrintingPolicy &Policy, const Twine &PlaceHolder=Twine(), unsigned Indentation=0) const
Definition: Type.h:950
virtual Stmt * getBody() const
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
Definition: DeclBase.h:955
Stmt - This represents one statement.
Definition: Stmt.h:60
unsigned size() const
size - Return the total number of CFGBlocks within the CFG This is simply a renaming of the getNumBlo...
Definition: CFG.h:980
Defines the SourceManager interface.
iterator end()
Definition: DeclGroup.h:108
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:81
StringRef P
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
Definition: Diagnostic.h:1205
ObjCMethodDecl - Represents an instance or class method declaration.
Definition: DeclObjC.h:113
Describes how types, statements, expressions, and declarations should be printed. ...
Definition: PrettyPrinter.h:38
PathDiagnosticLocation getLocation() const
PathDiagnostic - PathDiagnostic objects represent a single path-sensitive diagnostic.
IdentifierInfo * getIdentifier() const
getIdentifier - Get the identifier that names this declaration, if there is one.
Definition: Decl.h:232
One of these records is kept for each identifier that is lexed.
Follow the default settings for inlining callees.
Definition: ExprEngine.h:53
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:128
Defines the clang::CodeInjector interface which is responsible for injecting AST of function definiti...
Definition: Format.h:1821
std::unique_ptr< StoreManager >(* StoreManagerCreator)(ProgramStateManager &)
Definition: ProgramState.h:44
std::deque< Decl * > SetOfDecls
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Definition: LangOptions.h:48
const LangOptions & getLangOpts() const
Definition: Preprocessor.h:728
ArrayRef< ParmVarDecl * > parameters() const
Definition: Decl.h:2090
ObjCMethodFamily getMethodFamily() const
Determines the family of this method.
Definition: DeclObjC.cpp:931
FrontendOptions & getFrontendOpts()
SourceLocation getExpansionLoc(SourceLocation Loc) const
Given a SourceLocation object Loc, return the expansion location referenced by the ID...
Concrete class used by the front-end to report problems and issues.
Definition: Diagnostic.h:147
iterator begin()
Definition: DeclGroup.h:102
A class that does preorder or postorder depth-first traversal on the entire Clang AST and visits each...
AnalyzerOptionsRef getAnalyzerOpts()
Decl * getDecl() const
Definition: CallGraph.h:164
param_iterator param_begin()
Definition: Decl.h:2101
std::unique_ptr< ConstraintManager >(* ConstraintManagerCreator)(ProgramStateManager &, SubEngine *)
Definition: ProgramState.h:42
StringRef Filename
Definition: Format.cpp:1316
static bool shouldSkipFunction(const Decl *D, const SetOfConstDecls &Visited, const SetOfConstDecls &VisitedAsTopLevel)
InliningModes
The modes of inlining, which override the default analysis-wide settings.
Definition: ExprEngine.h:51
bool isValid() const
BlockDecl - This represents a block literal declaration, which is like an unnamed FunctionDecl...
Definition: Decl.h:3595
std::vector< std::string > Plugins
The list of plugins to load.
CFG - Represents a source-level, intra-procedural CFG that represents the control-flow of a Stmt...
Definition: CFG.h:808
bool isInSystemHeader(SourceLocation Loc) const
Returns if a SourceLocation is in a system header.
unsigned getLine() const
Return the presumed line number of this location.
bool isThisDeclarationADefinition() const
Returns whether this specific declaration of the function is also a definition that does not contain ...
Definition: Decl.h:1895
Defines the clang::Preprocessor interface.
bool isWrittenInMainFile(SourceLocation Loc) const
Returns true if the spelling location for the given location is in the main file buffer.
This file defines the clang::ento::ModelInjector class which implements the clang::CodeInjector inter...
void FlushReports()
Generate and flush diagnostics for all bug reports.
Represents an unpacked "presumed" location which can be presented to the user.
bool isDependentContext() const
Determines whether this context is dependent on a template parameter.
Definition: DeclBase.cpp:1008
PathPieces flatten(bool ShouldFlattenMacros) const
const SourceManager & SM
Definition: Format.cpp:1308
virtual bool hasBody() const
Returns true if this Decl represents a declaration for a body of code, such as a function or method d...
Definition: DeclBase.h:961
const char * getFilename() const
Return the presumed filename of this location.
BugReporter is a utility class for generating PathDiagnostics for analysis.
Definition: BugReporter.h:403
#define false
Definition: stdbool.h:33
unsigned getColumn() const
Return the presumed column number of this location.
CompilerInstance - Helper class for managing a single instance of the Clang compiler.
Encodes a location in the source.
STATISTIC(NumFunctionTopLevel, "The # of functions at top level.")
std::vector< PathDiagnosticConsumer * > PathDiagnosticConsumers
BugReporter & getBugReporter()
Definition: ExprEngine.h:133
Do minimal inlining of callees.
Definition: ExprEngine.h:55
unsigned getCustomDiagID(Level L, const char(&FormatString)[N])
Return an ID for a diagnostic with the specified format string and level.
Definition: Diagnostic.h:689
StringRef getName() const
Return the actual identifier string.
bool ExecuteWorkList(const LocationContext *L, unsigned Steps=150000)
Returns true if there is still simulation state on the worklist.
Definition: ExprEngine.h:108
Dataflow Directional Tag Classes.
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition: DeclBase.h:1224
CodeInjector is an interface which is responsible for injecting AST of function definitions that may ...
Definition: CodeInjector.h:36
PresumedLoc getPresumedLoc(SourceLocation Loc, bool UseLineDirectives=true) const
Returns the "presumed" location of a SourceLocation specifies.
std::unique_ptr< AnalysisASTConsumer > CreateAnalysisConsumer(CompilerInstance &CI)
CreateAnalysisConsumer - Creates an ASTConsumer to run various code analysis passes.
void setWarningsAsErrors(bool Val)
When set to true, any warnings reported are issued as errors.
Definition: Diagnostic.h:522
static std::unique_ptr< ExplodedNode::Auditor > CreateUbiViz()
static void SetAuditor(Auditor *A)
bool hasFatalErrorOccurred() const
Definition: Diagnostic.h:667
Preprocessor & getPreprocessor() const
Return the current preprocessor.
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate.h) and friends (in DeclFriend.h).
TranslationUnitDecl * getTranslationUnitDecl() const
Definition: ASTContext.h:958
DiagnosticsEngine & getDiagnostics() const
Definition: Preprocessor.h:725
void addToCallGraph(Decl *D)
Populate the call graph with the functions in the given declaration.
Definition: CallGraph.h:54
std::string getQualifiedNameAsString() const
Definition: Decl.cpp:1436
TranslationUnitDecl - The top declaration context.
Definition: Decl.h:80
void ViewGraph(bool trim=false)
Visualize the ExplodedGraph created by executing the simulation.
SourceLocation getLocStart() const LLVM_READONLY
Definition: Stmt.cpp:257
std::unique_ptr< CheckerManager > createCheckerManager(AnalyzerOptions &opts, const LangOptions &langOpts, ArrayRef< std::string > plugins, DiagnosticsEngine &diags)
This class handles loading and caching of source files into memory.
SourceLocation getLocation() const
Definition: DeclBase.h:407
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
Definition: Preprocessor.h:98
StringRef getShortDescription() const