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