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