clang  5.0.0
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.
729  Eng.getBugReporter().FlushReports();
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, nullptr, 0, 0,
858  &ErrMsg)) {
859  llvm::errs() << "Error viewing graph: " << ErrMsg << "\n";
860  }
861 
862  // Delete the file.
863  llvm::sys::fs::remove(Filename);
864 }
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:1618
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.
A (possibly-)qualified type.
Definition: Type.h:616
unsigned getColumn() const
Return the presumed column number of this location.
bool isValid() const
IdentifierInfo * getIdentifier() const
getIdentifier - Get the identifier that names this declaration, if there is one.
Definition: Decl.h:232
Stmt - This represents one statement.
Definition: Stmt.h:60
STATISTIC(NumFunctionTopLevel,"The # of functions at top level.")
Defines the SourceManager interface.
Decl * getDecl() const
Definition: CallGraph.h:164
iterator end()
Definition: DeclGroup.h:108
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:81
PathPieces flatten(bool ShouldFlattenMacros) const
StringRef P
bool hasErrorOccurred() const
Definition: Diagnostic.h:660
bool isDependentContext() const
Determines whether this context is dependent on a template parameter.
Definition: DeclBase.cpp:1009
PathDiagnosticLocation getLocation() const
ObjCMethodDecl - Represents an instance or class method declaration.
Definition: DeclObjC.h:113
std::unique_ptr< ConstraintManager >(* ConstraintManagerCreator)(ProgramStateManager &, SubEngine *)
Definition: ProgramState.h:42
Describes how types, statements, expressions, and declarations should be printed. ...
Definition: PrettyPrinter.h:38
FullSourceLoc asLocation() const
PathDiagnostic - PathDiagnostic objects represent a single path-sensitive diagnostic.
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...
std::deque< Decl * > SetOfDecls
const LangOptions & getLangOpts() const
Definition: Preprocessor.h:725
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Definition: LangOptions.h:48
bool isThisDeclarationADefinition() const
Returns whether this specific method is a definition.
Definition: DeclObjC.h:497
FrontendOptions & getFrontendOpts()
ObjCMethodFamily getMethodFamily() const
Determines the family of this method.
Definition: DeclObjC.cpp:931
unsigned size() const
size - Return the total number of CFGBlocks within the CFG This is simply a renaming of the getNumBlo...
Definition: CFG.h:951
Concrete class used by the front-end to report problems and issues.
Definition: Diagnostic.h:147
iterator begin()
Definition: DeclGroup.h:102
void print(raw_ostream &OS, const PrintingPolicy &Policy, const Twine &PlaceHolder=Twine(), unsigned Indentation=0) const
Definition: Type.h:952
unsigned getLine() const
Return the presumed line number of this location.
A class that does preordor or postorder depth-first traversal on the entire Clang AST and visits each...
detail::InMemoryDirectory::const_iterator I
Preprocessor & getPreprocessor() const
Return the current preprocessor.
bool isInvalid() const
AnalyzerOptionsRef getAnalyzerOpts()
param_iterator param_begin()
Definition: Decl.h:2077
StringRef Filename
Definition: Format.cpp:1301
ASTContext * Context
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
BlockDecl - This represents a block literal declaration, which is like an unnamed FunctionDecl...
Definition: Decl.h:3557
std::vector< std::string > Plugins
The list of plugins to load.
StringRef getName() const
Return the actual identifier string.
bool hasFatalErrorOccurred() const
Definition: Diagnostic.h:667
CFG - Represents a source-level, intra-procedural CFG that represents the control-flow of a Stmt...
Definition: CFG.h:780
StringRef getShortDescription() const
TranslationUnitDecl * getTranslationUnitDecl() const
Definition: ASTContext.h:956
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.
bool isInSystemHeader(SourceLocation Loc) const
Returns if a SourceLocation is in a system header.
This file defines the clang::ento::ModelInjector class which implements the clang::CodeInjector inter...
Represents an unpacked "presumed" location which can be presented to the user.
const SourceManager & SM
Definition: Format.cpp:1293
BugReporter is a utility class for generating PathDiagnostics for analysis.
Definition: BugReporter.h:403
#define false
Definition: stdbool.h:33
const char * getFilename() const
Return the presumed filename of this location.
CompilerInstance - Helper class for managing a single instance of the Clang compiler.
Encodes a location in the source.
std::vector< PathDiagnosticConsumer * > PathDiagnosticConsumers
ArrayRef< ParmVarDecl * > parameters() const
Definition: Decl.h:2066
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:948
Do minimal inlining of callees.
Definition: ExprEngine.h:55
DiagnosticsEngine & getDiagnostics() const
Definition: Preprocessor.h:722
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition: DeclBase.h:1215
CodeInjector is an interface which is responsible for injecting AST of function definitions that may ...
Definition: CodeInjector.h:36
bool isThisDeclarationADefinition() const
Returns whether this specific declaration of the function is also a definition that does not contain ...
Definition: Decl.h:1874
detail::InMemoryDirectory::const_iterator E
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)
std::string getQualifiedNameAsString() const
Definition: Decl.cpp:1451
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate.h) and friends (in DeclFriend.h).
void addToCallGraph(Decl *D)
Populate the call graph with the functions in the given declaration.
Definition: CallGraph.h:54
TranslationUnitDecl - The top declaration context.
Definition: Decl.h:80
SourceLocation getLocation() const
Definition: DeclBase.h:407
SourceLocation getExpansionLoc(SourceLocation Loc) const
Given a SourceLocation object Loc, return the expansion location referenced by the ID...
SourceLocation getLocStart() const LLVM_READONLY
Definition: Stmt.cpp:257
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:954
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.
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
Definition: Preprocessor.h:98
std::unique_ptr< StoreManager >(* StoreManagerCreator)(ProgramStateManager &)
Definition: ProgramState.h:44
PresumedLoc getPresumedLoc(SourceLocation Loc, bool UseLineDirectives=true) const
Returns the "presumed" location of a SourceLocation specifies.