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