clang  3.7.0
BugReporter.cpp
Go to the documentation of this file.
1 // BugReporter.cpp - Generate PathDiagnostics for Bugs ------------*- C++ -*--//
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 // This file defines BugReporter, a utility class for generating
11 // PathDiagnostics.
12 //
13 //===----------------------------------------------------------------------===//
14 
16 #include "clang/AST/ASTContext.h"
17 #include "clang/AST/DeclObjC.h"
18 #include "clang/AST/Expr.h"
19 #include "clang/AST/ExprCXX.h"
20 #include "clang/AST/ParentMap.h"
21 #include "clang/AST/StmtCXX.h"
22 #include "clang/AST/StmtObjC.h"
23 #include "clang/Analysis/CFG.h"
29 #include "llvm/ADT/DenseMap.h"
30 #include "llvm/ADT/IntrusiveRefCntPtr.h"
31 #include "llvm/ADT/STLExtras.h"
32 #include "llvm/ADT/SmallString.h"
33 #include "llvm/ADT/Statistic.h"
34 #include "llvm/Support/raw_ostream.h"
35 #include <memory>
36 #include <queue>
37 
38 using namespace clang;
39 using namespace ento;
40 
41 #define DEBUG_TYPE "BugReporter"
42 
43 STATISTIC(MaxBugClassSize,
44  "The maximum number of bug reports in the same equivalence class");
45 STATISTIC(MaxValidBugClassSize,
46  "The maximum number of bug reports in the same equivalence class "
47  "where at least one report is valid (not suppressed)");
48 
50 
51 void BugReporterContext::anchor() {}
52 
53 //===----------------------------------------------------------------------===//
54 // Helper routines for walking the ExplodedGraph and fetching statements.
55 //===----------------------------------------------------------------------===//
56 
57 static const Stmt *GetPreviousStmt(const ExplodedNode *N) {
58  for (N = N->getFirstPred(); N; N = N->getFirstPred())
59  if (const Stmt *S = PathDiagnosticLocation::getStmt(N))
60  return S;
61 
62  return nullptr;
63 }
64 
65 static inline const Stmt*
67  if (const Stmt *S = PathDiagnosticLocation::getStmt(N))
68  return S;
69 
70  return GetPreviousStmt(N);
71 }
72 
73 //===----------------------------------------------------------------------===//
74 // Diagnostic cleanup.
75 //===----------------------------------------------------------------------===//
76 
80  // Prefer diagnostics that come from ConditionBRVisitor over
81  // those that came from TrackConstraintBRVisitor.
82  const void *tagPreferred = ConditionBRVisitor::getTag();
83  const void *tagLesser = TrackConstraintBRVisitor::getTag();
84 
85  if (X->getLocation() != Y->getLocation())
86  return nullptr;
87 
88  if (X->getTag() == tagPreferred && Y->getTag() == tagLesser)
89  return X;
90 
91  if (Y->getTag() == tagPreferred && X->getTag() == tagLesser)
92  return Y;
93 
94  return nullptr;
95 }
96 
97 /// An optimization pass over PathPieces that removes redundant diagnostics
98 /// generated by both ConditionBRVisitor and TrackConstraintBRVisitor. Both
99 /// BugReporterVisitors use different methods to generate diagnostics, with
100 /// one capable of emitting diagnostics in some cases but not in others. This
101 /// can lead to redundant diagnostic pieces at the same point in a path.
102 static void removeRedundantMsgs(PathPieces &path) {
103  unsigned N = path.size();
104  if (N < 2)
105  return;
106  // NOTE: this loop intentionally is not using an iterator. Instead, we
107  // are streaming the path and modifying it in place. This is done by
108  // grabbing the front, processing it, and if we decide to keep it append
109  // it to the end of the path. The entire path is processed in this way.
110  for (unsigned i = 0; i < N; ++i) {
111  IntrusiveRefCntPtr<PathDiagnosticPiece> piece(path.front());
112  path.pop_front();
113 
114  switch (piece->getKind()) {
116  removeRedundantMsgs(cast<PathDiagnosticCallPiece>(piece)->path);
117  break;
119  removeRedundantMsgs(cast<PathDiagnosticMacroPiece>(piece)->subPieces);
120  break;
122  break;
124  if (i == N-1)
125  break;
126 
127  if (PathDiagnosticEventPiece *nextEvent =
128  dyn_cast<PathDiagnosticEventPiece>(path.front().get())) {
129  PathDiagnosticEventPiece *event =
130  cast<PathDiagnosticEventPiece>(piece);
131  // Check to see if we should keep one of the two pieces. If we
132  // come up with a preference, record which piece to keep, and consume
133  // another piece from the path.
134  if (PathDiagnosticEventPiece *pieceToKeep =
135  eventsDescribeSameCondition(event, nextEvent)) {
136  piece = pieceToKeep;
137  path.pop_front();
138  ++i;
139  }
140  }
141  break;
142  }
143  }
144  path.push_back(piece);
145  }
146 }
147 
148 /// A map from PathDiagnosticPiece to the LocationContext of the inlined
149 /// function call it represents.
150 typedef llvm::DenseMap<const PathPieces *, const LocationContext *>
152 
153 /// Recursively scan through a path and prune out calls and macros pieces
154 /// that aren't needed. Return true if afterwards the path contains
155 /// "interesting stuff" which means it shouldn't be pruned from the parent path.
156 static bool removeUnneededCalls(PathPieces &pieces, BugReport *R,
157  LocationContextMap &LCM) {
158  bool containsSomethingInteresting = false;
159  const unsigned N = pieces.size();
160 
161  for (unsigned i = 0 ; i < N ; ++i) {
162  // Remove the front piece from the path. If it is still something we
163  // want to keep once we are done, we will push it back on the end.
164  IntrusiveRefCntPtr<PathDiagnosticPiece> piece(pieces.front());
165  pieces.pop_front();
166 
167  switch (piece->getKind()) {
169  PathDiagnosticCallPiece *call = cast<PathDiagnosticCallPiece>(piece);
170  // Check if the location context is interesting.
171  assert(LCM.count(&call->path));
172  if (R->isInteresting(LCM[&call->path])) {
173  containsSomethingInteresting = true;
174  break;
175  }
176 
177  if (!removeUnneededCalls(call->path, R, LCM))
178  continue;
179 
180  containsSomethingInteresting = true;
181  break;
182  }
184  PathDiagnosticMacroPiece *macro = cast<PathDiagnosticMacroPiece>(piece);
185  if (!removeUnneededCalls(macro->subPieces, R, LCM))
186  continue;
187  containsSomethingInteresting = true;
188  break;
189  }
191  PathDiagnosticEventPiece *event = cast<PathDiagnosticEventPiece>(piece);
192 
193  // We never throw away an event, but we do throw it away wholesale
194  // as part of a path if we throw the entire path away.
195  containsSomethingInteresting |= !event->isPrunable();
196  break;
197  }
199  break;
200  }
201 
202  pieces.push_back(piece);
203  }
204 
205  return containsSomethingInteresting;
206 }
207 
208 /// Returns true if the given decl has been implicitly given a body, either by
209 /// the analyzer or by the compiler proper.
210 static bool hasImplicitBody(const Decl *D) {
211  assert(D);
212  return D->isImplicit() || !D->hasBody();
213 }
214 
215 /// Recursively scan through a path and make sure that all call pieces have
216 /// valid locations.
217 static void
219  PathDiagnosticLocation *LastCallLocation = nullptr) {
220  for (PathPieces::iterator I = Pieces.begin(), E = Pieces.end(); I != E; ++I) {
221  PathDiagnosticCallPiece *Call = dyn_cast<PathDiagnosticCallPiece>(*I);
222 
223  if (!Call) {
224  assert((*I)->getLocation().asLocation().isValid());
225  continue;
226  }
227 
228  if (LastCallLocation) {
229  bool CallerIsImplicit = hasImplicitBody(Call->getCaller());
230  if (CallerIsImplicit || !Call->callEnter.asLocation().isValid())
231  Call->callEnter = *LastCallLocation;
232  if (CallerIsImplicit || !Call->callReturn.asLocation().isValid())
233  Call->callReturn = *LastCallLocation;
234  }
235 
236  // Recursively clean out the subclass. Keep this call around if
237  // it contains any informative diagnostics.
238  PathDiagnosticLocation *ThisCallLocation;
239  if (Call->callEnterWithin.asLocation().isValid() &&
240  !hasImplicitBody(Call->getCallee()))
241  ThisCallLocation = &Call->callEnterWithin;
242  else
243  ThisCallLocation = &Call->callEnter;
244 
245  assert(ThisCallLocation && "Outermost call has an invalid location");
246  adjustCallLocations(Call->path, ThisCallLocation);
247  }
248 }
249 
250 /// Remove edges in and out of C++ default initializer expressions. These are
251 /// for fields that have in-class initializers, as opposed to being initialized
252 /// explicitly in a constructor or braced list.
254  for (PathPieces::iterator I = Pieces.begin(), E = Pieces.end(); I != E;) {
255  if (PathDiagnosticCallPiece *C = dyn_cast<PathDiagnosticCallPiece>(*I))
257 
258  if (PathDiagnosticMacroPiece *M = dyn_cast<PathDiagnosticMacroPiece>(*I))
259  removeEdgesToDefaultInitializers(M->subPieces);
260 
262  dyn_cast<PathDiagnosticControlFlowPiece>(*I)) {
263  const Stmt *Start = CF->getStartLocation().asStmt();
264  const Stmt *End = CF->getEndLocation().asStmt();
265  if (Start && isa<CXXDefaultInitExpr>(Start)) {
266  I = Pieces.erase(I);
267  continue;
268  } else if (End && isa<CXXDefaultInitExpr>(End)) {
269  PathPieces::iterator Next = std::next(I);
270  if (Next != E) {
271  if (PathDiagnosticControlFlowPiece *NextCF =
272  dyn_cast<PathDiagnosticControlFlowPiece>(*Next)) {
273  NextCF->setStartLocation(CF->getStartLocation());
274  }
275  }
276  I = Pieces.erase(I);
277  continue;
278  }
279  }
280 
281  I++;
282  }
283 }
284 
285 /// Remove all pieces with invalid locations as these cannot be serialized.
286 /// We might have pieces with invalid locations as a result of inlining Body
287 /// Farm generated functions.
289  for (PathPieces::iterator I = Pieces.begin(), E = Pieces.end(); I != E;) {
290  if (PathDiagnosticCallPiece *C = dyn_cast<PathDiagnosticCallPiece>(*I))
292 
293  if (PathDiagnosticMacroPiece *M = dyn_cast<PathDiagnosticMacroPiece>(*I))
294  removePiecesWithInvalidLocations(M->subPieces);
295 
296  if (!(*I)->getLocation().isValid() ||
297  !(*I)->getLocation().asLocation().isValid()) {
298  I = Pieces.erase(I);
299  continue;
300  }
301  I++;
302  }
303 }
304 
305 //===----------------------------------------------------------------------===//
306 // PathDiagnosticBuilder and its associated routines and helper objects.
307 //===----------------------------------------------------------------------===//
308 
309 namespace {
310 class NodeMapClosure : public BugReport::NodeResolver {
312 public:
313  NodeMapClosure(InterExplodedGraphMap &m) : M(m) {}
314 
315  const ExplodedNode *getOriginalNode(const ExplodedNode *N) override {
316  return M.lookup(N);
317  }
318 };
319 
320 class PathDiagnosticBuilder : public BugReporterContext {
321  BugReport *R;
323  NodeMapClosure NMC;
324 public:
325  const LocationContext *LC;
326 
327  PathDiagnosticBuilder(GRBugReporter &br,
328  BugReport *r, InterExplodedGraphMap &Backmap,
330  : BugReporterContext(br),
331  R(r), PDC(pdc), NMC(Backmap), LC(r->getErrorNode()->getLocationContext())
332  {}
333 
334  PathDiagnosticLocation ExecutionContinues(const ExplodedNode *N);
335 
336  PathDiagnosticLocation ExecutionContinues(llvm::raw_string_ostream &os,
337  const ExplodedNode *N);
338 
339  BugReport *getBugReport() { return R; }
340 
341  Decl const &getCodeDecl() { return R->getErrorNode()->getCodeDecl(); }
342 
343  ParentMap& getParentMap() { return LC->getParentMap(); }
344 
345  const Stmt *getParent(const Stmt *S) {
346  return getParentMap().getParent(S);
347  }
348 
349  NodeMapClosure& getNodeResolver() override { return NMC; }
350 
352 
353  PathDiagnosticConsumer::PathGenerationScheme getGenerationScheme() const {
354  return PDC ? PDC->getGenerationScheme() : PathDiagnosticConsumer::Extensive;
355  }
356 
357  bool supportsLogicalOpControlFlow() const {
358  return PDC ? PDC->supportsLogicalOpControlFlow() : true;
359  }
360 };
361 } // end anonymous namespace
362 
364 PathDiagnosticBuilder::ExecutionContinues(const ExplodedNode *N) {
365  if (const Stmt *S = PathDiagnosticLocation::getNextStmt(N))
366  return PathDiagnosticLocation(S, getSourceManager(), LC);
367 
369  getSourceManager());
370 }
371 
373 PathDiagnosticBuilder::ExecutionContinues(llvm::raw_string_ostream &os,
374  const ExplodedNode *N) {
375 
376  // Slow, but probably doesn't matter.
377  if (os.str().empty())
378  os << ' ';
379 
380  const PathDiagnosticLocation &Loc = ExecutionContinues(N);
381 
382  if (Loc.asStmt())
383  os << "Execution continues on line "
384  << getSourceManager().getExpansionLineNumber(Loc.asLocation())
385  << '.';
386  else {
387  os << "Execution jumps to the end of the ";
388  const Decl *D = N->getLocationContext()->getDecl();
389  if (isa<ObjCMethodDecl>(D))
390  os << "method";
391  else if (isa<FunctionDecl>(D))
392  os << "function";
393  else {
394  assert(isa<BlockDecl>(D));
395  os << "anonymous block";
396  }
397  os << '.';
398  }
399 
400  return Loc;
401 }
402 
403 static const Stmt *getEnclosingParent(const Stmt *S, const ParentMap &PM) {
404  if (isa<Expr>(S) && PM.isConsumedExpr(cast<Expr>(S)))
405  return PM.getParentIgnoreParens(S);
406 
407  const Stmt *Parent = PM.getParentIgnoreParens(S);
408  if (!Parent)
409  return nullptr;
410 
411  switch (Parent->getStmtClass()) {
412  case Stmt::ForStmtClass:
413  case Stmt::DoStmtClass:
414  case Stmt::WhileStmtClass:
415  case Stmt::ObjCForCollectionStmtClass:
416  case Stmt::CXXForRangeStmtClass:
417  return Parent;
418  default:
419  break;
420  }
421 
422  return nullptr;
423 }
424 
427  const LocationContext *LC, bool allowNestedContexts) {
428  if (!S)
429  return PathDiagnosticLocation();
430 
431  while (const Stmt *Parent = getEnclosingParent(S, P)) {
432  switch (Parent->getStmtClass()) {
433  case Stmt::BinaryOperatorClass: {
434  const BinaryOperator *B = cast<BinaryOperator>(Parent);
435  if (B->isLogicalOp())
436  return PathDiagnosticLocation(allowNestedContexts ? B : S, SMgr, LC);
437  break;
438  }
439  case Stmt::CompoundStmtClass:
440  case Stmt::StmtExprClass:
441  return PathDiagnosticLocation(S, SMgr, LC);
442  case Stmt::ChooseExprClass:
443  // Similar to '?' if we are referring to condition, just have the edge
444  // point to the entire choose expression.
445  if (allowNestedContexts || cast<ChooseExpr>(Parent)->getCond() == S)
446  return PathDiagnosticLocation(Parent, SMgr, LC);
447  else
448  return PathDiagnosticLocation(S, SMgr, LC);
449  case Stmt::BinaryConditionalOperatorClass:
450  case Stmt::ConditionalOperatorClass:
451  // For '?', if we are referring to condition, just have the edge point
452  // to the entire '?' expression.
453  if (allowNestedContexts ||
454  cast<AbstractConditionalOperator>(Parent)->getCond() == S)
455  return PathDiagnosticLocation(Parent, SMgr, LC);
456  else
457  return PathDiagnosticLocation(S, SMgr, LC);
458  case Stmt::CXXForRangeStmtClass:
459  if (cast<CXXForRangeStmt>(Parent)->getBody() == S)
460  return PathDiagnosticLocation(S, SMgr, LC);
461  break;
462  case Stmt::DoStmtClass:
463  return PathDiagnosticLocation(S, SMgr, LC);
464  case Stmt::ForStmtClass:
465  if (cast<ForStmt>(Parent)->getBody() == S)
466  return PathDiagnosticLocation(S, SMgr, LC);
467  break;
468  case Stmt::IfStmtClass:
469  if (cast<IfStmt>(Parent)->getCond() != S)
470  return PathDiagnosticLocation(S, SMgr, LC);
471  break;
472  case Stmt::ObjCForCollectionStmtClass:
473  if (cast<ObjCForCollectionStmt>(Parent)->getBody() == S)
474  return PathDiagnosticLocation(S, SMgr, LC);
475  break;
476  case Stmt::WhileStmtClass:
477  if (cast<WhileStmt>(Parent)->getCond() != S)
478  return PathDiagnosticLocation(S, SMgr, LC);
479  break;
480  default:
481  break;
482  }
483 
484  S = Parent;
485  }
486 
487  assert(S && "Cannot have null Stmt for PathDiagnosticLocation");
488 
489  return PathDiagnosticLocation(S, SMgr, LC);
490 }
491 
494  assert(S && "Null Stmt passed to getEnclosingStmtLocation");
495  return ::getEnclosingStmtLocation(S, getSourceManager(), getParentMap(), LC,
496  /*allowNestedContexts=*/false);
497 }
498 
499 //===----------------------------------------------------------------------===//
500 // "Visitors only" path diagnostic generation algorithm.
501 //===----------------------------------------------------------------------===//
503  PathDiagnostic &PD, PathDiagnosticBuilder &PDB, const ExplodedNode *N,
504  ArrayRef<std::unique_ptr<BugReporterVisitor>> visitors) {
505  // All path generation skips the very first node (the error node).
506  // This is because there is special handling for the end-of-path note.
507  N = N->getFirstPred();
508  if (!N)
509  return true;
510 
511  BugReport *R = PDB.getBugReport();
512  while (const ExplodedNode *Pred = N->getFirstPred()) {
513  for (auto &V : visitors) {
514  // Visit all the node pairs, but throw the path pieces away.
515  PathDiagnosticPiece *Piece = V->VisitNode(N, Pred, PDB, *R);
516  delete Piece;
517  }
518 
519  N = Pred;
520  }
521 
522  return R->isValid();
523 }
524 
525 //===----------------------------------------------------------------------===//
526 // "Minimal" path diagnostic generation algorithm.
527 //===----------------------------------------------------------------------===//
528 typedef std::pair<PathDiagnosticCallPiece*, const ExplodedNode*> StackDiagPair;
530 
532  StackDiagVector &CallStack) {
533  // If the piece contains a special message, add it to all the call
534  // pieces on the active stack.
535  if (PathDiagnosticEventPiece *ep =
536  dyn_cast<PathDiagnosticEventPiece>(P)) {
537 
538  if (ep->hasCallStackHint())
539  for (StackDiagVector::iterator I = CallStack.begin(),
540  E = CallStack.end(); I != E; ++I) {
541  PathDiagnosticCallPiece *CP = I->first;
542  const ExplodedNode *N = I->second;
543  std::string stackMsg = ep->getCallStackMessage(N);
544 
545  // The last message on the path to final bug is the most important
546  // one. Since we traverse the path backwards, do not add the message
547  // if one has been previously added.
548  if (!CP->hasCallStackMessage())
549  CP->setCallStackMessage(stackMsg);
550  }
551  }
552 }
553 
554 static void CompactPathDiagnostic(PathPieces &path, const SourceManager& SM);
555 
557  PathDiagnostic &PD, PathDiagnosticBuilder &PDB, const ExplodedNode *N,
558  LocationContextMap &LCM,
559  ArrayRef<std::unique_ptr<BugReporterVisitor>> visitors) {
560 
561  SourceManager& SMgr = PDB.getSourceManager();
562  const LocationContext *LC = PDB.LC;
563  const ExplodedNode *NextNode = N->pred_empty()
564  ? nullptr : *(N->pred_begin());
565 
566  StackDiagVector CallStack;
567 
568  while (NextNode) {
569  N = NextNode;
570  PDB.LC = N->getLocationContext();
571  NextNode = N->getFirstPred();
572 
573  ProgramPoint P = N->getLocation();
574 
575  do {
576  if (Optional<CallExitEnd> CE = P.getAs<CallExitEnd>()) {
579  // Record the mapping from call piece to LocationContext.
580  LCM[&C->path] = CE->getCalleeContext();
581  PD.getActivePath().push_front(C);
582  PD.pushActivePath(&C->path);
583  CallStack.push_back(StackDiagPair(C, N));
584  break;
585  }
586 
587  if (Optional<CallEnter> CE = P.getAs<CallEnter>()) {
588  // Flush all locations, and pop the active path.
589  bool VisitedEntireCall = PD.isWithinCall();
590  PD.popActivePath();
591 
592  // Either we just added a bunch of stuff to the top-level path, or
593  // we have a previous CallExitEnd. If the former, it means that the
594  // path terminated within a function call. We must then take the
595  // current contents of the active path and place it within
596  // a new PathDiagnosticCallPiece.
598  if (VisitedEntireCall) {
599  C = cast<PathDiagnosticCallPiece>(PD.getActivePath().front());
600  } else {
601  const Decl *Caller = CE->getLocationContext()->getDecl();
603  // Record the mapping from call piece to LocationContext.
604  LCM[&C->path] = CE->getCalleeContext();
605  }
606 
607  C->setCallee(*CE, SMgr);
608  if (!CallStack.empty()) {
609  assert(CallStack.back().first == C);
610  CallStack.pop_back();
611  }
612  break;
613  }
614 
615  if (Optional<BlockEdge> BE = P.getAs<BlockEdge>()) {
616  const CFGBlock *Src = BE->getSrc();
617  const CFGBlock *Dst = BE->getDst();
618  const Stmt *T = Src->getTerminator();
619 
620  if (!T)
621  break;
622 
623  PathDiagnosticLocation Start =
625  N->getLocationContext());
626 
627  switch (T->getStmtClass()) {
628  default:
629  break;
630 
631  case Stmt::GotoStmtClass:
632  case Stmt::IndirectGotoStmtClass: {
634 
635  if (!S)
636  break;
637 
638  std::string sbuf;
639  llvm::raw_string_ostream os(sbuf);
640  const PathDiagnosticLocation &End = PDB.getEnclosingStmtLocation(S);
641 
642  os << "Control jumps to line "
644  PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(
645  Start, End, os.str()));
646  break;
647  }
648 
649  case Stmt::SwitchStmtClass: {
650  // Figure out what case arm we took.
651  std::string sbuf;
652  llvm::raw_string_ostream os(sbuf);
653 
654  if (const Stmt *S = Dst->getLabel()) {
655  PathDiagnosticLocation End(S, SMgr, LC);
656 
657  switch (S->getStmtClass()) {
658  default:
659  os << "No cases match in the switch statement. "
660  "Control jumps to line "
662  break;
663  case Stmt::DefaultStmtClass:
664  os << "Control jumps to the 'default' case at line "
666  break;
667 
668  case Stmt::CaseStmtClass: {
669  os << "Control jumps to 'case ";
670  const CaseStmt *Case = cast<CaseStmt>(S);
671  const Expr *LHS = Case->getLHS()->IgnoreParenCasts();
672 
673  // Determine if it is an enum.
674  bool GetRawInt = true;
675 
676  if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(LHS)) {
677  // FIXME: Maybe this should be an assertion. Are there cases
678  // were it is not an EnumConstantDecl?
679  const EnumConstantDecl *D =
680  dyn_cast<EnumConstantDecl>(DR->getDecl());
681 
682  if (D) {
683  GetRawInt = false;
684  os << *D;
685  }
686  }
687 
688  if (GetRawInt)
689  os << LHS->EvaluateKnownConstInt(PDB.getASTContext());
690 
691  os << ":' at line "
693  break;
694  }
695  }
696  PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(
697  Start, End, os.str()));
698  }
699  else {
700  os << "'Default' branch taken. ";
701  const PathDiagnosticLocation &End = PDB.ExecutionContinues(os, N);
702  PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(
703  Start, End, os.str()));
704  }
705 
706  break;
707  }
708 
709  case Stmt::BreakStmtClass:
710  case Stmt::ContinueStmtClass: {
711  std::string sbuf;
712  llvm::raw_string_ostream os(sbuf);
713  PathDiagnosticLocation End = PDB.ExecutionContinues(os, N);
714  PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(
715  Start, End, os.str()));
716  break;
717  }
718 
719  // Determine control-flow for ternary '?'.
720  case Stmt::BinaryConditionalOperatorClass:
721  case Stmt::ConditionalOperatorClass: {
722  std::string sbuf;
723  llvm::raw_string_ostream os(sbuf);
724  os << "'?' condition is ";
725 
726  if (*(Src->succ_begin()+1) == Dst)
727  os << "false";
728  else
729  os << "true";
730 
731  PathDiagnosticLocation End = PDB.ExecutionContinues(N);
732 
733  if (const Stmt *S = End.asStmt())
734  End = PDB.getEnclosingStmtLocation(S);
735 
736  PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(
737  Start, End, os.str()));
738  break;
739  }
740 
741  // Determine control-flow for short-circuited '&&' and '||'.
742  case Stmt::BinaryOperatorClass: {
743  if (!PDB.supportsLogicalOpControlFlow())
744  break;
745 
746  const BinaryOperator *B = cast<BinaryOperator>(T);
747  std::string sbuf;
748  llvm::raw_string_ostream os(sbuf);
749  os << "Left side of '";
750 
751  if (B->getOpcode() == BO_LAnd) {
752  os << "&&" << "' is ";
753 
754  if (*(Src->succ_begin()+1) == Dst) {
755  os << "false";
756  PathDiagnosticLocation End(B->getLHS(), SMgr, LC);
757  PathDiagnosticLocation Start =
759  PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(
760  Start, End, os.str()));
761  }
762  else {
763  os << "true";
764  PathDiagnosticLocation Start(B->getLHS(), SMgr, LC);
765  PathDiagnosticLocation End = PDB.ExecutionContinues(N);
766  PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(
767  Start, End, os.str()));
768  }
769  }
770  else {
771  assert(B->getOpcode() == BO_LOr);
772  os << "||" << "' is ";
773 
774  if (*(Src->succ_begin()+1) == Dst) {
775  os << "false";
776  PathDiagnosticLocation Start(B->getLHS(), SMgr, LC);
777  PathDiagnosticLocation End = PDB.ExecutionContinues(N);
778  PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(
779  Start, End, os.str()));
780  }
781  else {
782  os << "true";
783  PathDiagnosticLocation End(B->getLHS(), SMgr, LC);
784  PathDiagnosticLocation Start =
786  PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(
787  Start, End, os.str()));
788  }
789  }
790 
791  break;
792  }
793 
794  case Stmt::DoStmtClass: {
795  if (*(Src->succ_begin()) == Dst) {
796  std::string sbuf;
797  llvm::raw_string_ostream os(sbuf);
798 
799  os << "Loop condition is true. ";
800  PathDiagnosticLocation End = PDB.ExecutionContinues(os, N);
801 
802  if (const Stmt *S = End.asStmt())
803  End = PDB.getEnclosingStmtLocation(S);
804 
805  PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(
806  Start, End, os.str()));
807  }
808  else {
809  PathDiagnosticLocation End = PDB.ExecutionContinues(N);
810 
811  if (const Stmt *S = End.asStmt())
812  End = PDB.getEnclosingStmtLocation(S);
813 
814  PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(
815  Start, End, "Loop condition is false. Exiting loop"));
816  }
817 
818  break;
819  }
820 
821  case Stmt::WhileStmtClass:
822  case Stmt::ForStmtClass: {
823  if (*(Src->succ_begin()+1) == Dst) {
824  std::string sbuf;
825  llvm::raw_string_ostream os(sbuf);
826 
827  os << "Loop condition is false. ";
828  PathDiagnosticLocation End = PDB.ExecutionContinues(os, N);
829  if (const Stmt *S = End.asStmt())
830  End = PDB.getEnclosingStmtLocation(S);
831 
832  PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(
833  Start, End, os.str()));
834  }
835  else {
836  PathDiagnosticLocation End = PDB.ExecutionContinues(N);
837  if (const Stmt *S = End.asStmt())
838  End = PDB.getEnclosingStmtLocation(S);
839 
840  PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(
841  Start, End, "Loop condition is true. Entering loop body"));
842  }
843 
844  break;
845  }
846 
847  case Stmt::IfStmtClass: {
848  PathDiagnosticLocation End = PDB.ExecutionContinues(N);
849 
850  if (const Stmt *S = End.asStmt())
851  End = PDB.getEnclosingStmtLocation(S);
852 
853  if (*(Src->succ_begin()+1) == Dst)
854  PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(
855  Start, End, "Taking false branch"));
856  else
857  PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(
858  Start, End, "Taking true branch"));
859 
860  break;
861  }
862  }
863  }
864  } while(0);
865 
866  if (NextNode) {
867  // Add diagnostic pieces from custom visitors.
868  BugReport *R = PDB.getBugReport();
869  for (auto &V : visitors) {
870  if (PathDiagnosticPiece *p = V->VisitNode(N, NextNode, PDB, *R)) {
871  PD.getActivePath().push_front(p);
872  updateStackPiecesWithMessage(p, CallStack);
873  }
874  }
875  }
876  }
877 
878  if (!PDB.getBugReport()->isValid())
879  return false;
880 
881  // After constructing the full PathDiagnostic, do a pass over it to compact
882  // PathDiagnosticPieces that occur within a macro.
883  CompactPathDiagnostic(PD.getMutablePieces(), PDB.getSourceManager());
884  return true;
885 }
886 
887 //===----------------------------------------------------------------------===//
888 // "Extensive" PathDiagnostic generation.
889 //===----------------------------------------------------------------------===//
890 
891 static bool IsControlFlowExpr(const Stmt *S) {
892  const Expr *E = dyn_cast<Expr>(S);
893 
894  if (!E)
895  return false;
896 
897  E = E->IgnoreParenCasts();
898 
899  if (isa<AbstractConditionalOperator>(E))
900  return true;
901 
902  if (const BinaryOperator *B = dyn_cast<BinaryOperator>(E))
903  if (B->isLogicalOp())
904  return true;
905 
906  return false;
907 }
908 
909 namespace {
910 class ContextLocation : public PathDiagnosticLocation {
911  bool IsDead;
912 public:
913  ContextLocation(const PathDiagnosticLocation &L, bool isdead = false)
914  : PathDiagnosticLocation(L), IsDead(isdead) {}
915 
916  void markDead() { IsDead = true; }
917  bool isDead() const { return IsDead; }
918 };
919 
920 static PathDiagnosticLocation cleanUpLocation(PathDiagnosticLocation L,
921  const LocationContext *LC,
922  bool firstCharOnly = false) {
923  if (const Stmt *S = L.asStmt()) {
924  const Stmt *Original = S;
925  while (1) {
926  // Adjust the location for some expressions that are best referenced
927  // by one of their subexpressions.
928  switch (S->getStmtClass()) {
929  default:
930  break;
931  case Stmt::ParenExprClass:
932  case Stmt::GenericSelectionExprClass:
933  S = cast<Expr>(S)->IgnoreParens();
934  firstCharOnly = true;
935  continue;
936  case Stmt::BinaryConditionalOperatorClass:
937  case Stmt::ConditionalOperatorClass:
938  S = cast<AbstractConditionalOperator>(S)->getCond();
939  firstCharOnly = true;
940  continue;
941  case Stmt::ChooseExprClass:
942  S = cast<ChooseExpr>(S)->getCond();
943  firstCharOnly = true;
944  continue;
945  case Stmt::BinaryOperatorClass:
946  S = cast<BinaryOperator>(S)->getLHS();
947  firstCharOnly = true;
948  continue;
949  }
950 
951  break;
952  }
953 
954  if (S != Original)
955  L = PathDiagnosticLocation(S, L.getManager(), LC);
956  }
957 
958  if (firstCharOnly)
960 
961  return L;
962 }
963 
964 class EdgeBuilder {
965  std::vector<ContextLocation> CLocs;
966  typedef std::vector<ContextLocation>::iterator iterator;
967  PathDiagnostic &PD;
968  PathDiagnosticBuilder &PDB;
969  PathDiagnosticLocation PrevLoc;
970 
971  bool IsConsumedExpr(const PathDiagnosticLocation &L);
972 
973  bool containsLocation(const PathDiagnosticLocation &Container,
974  const PathDiagnosticLocation &Containee);
975 
976  PathDiagnosticLocation getContextLocation(const PathDiagnosticLocation &L);
977 
978 
979 
980  void popLocation() {
981  if (!CLocs.back().isDead() && CLocs.back().asLocation().isFileID()) {
982  // For contexts, we only one the first character as the range.
983  rawAddEdge(cleanUpLocation(CLocs.back(), PDB.LC, true));
984  }
985  CLocs.pop_back();
986  }
987 
988 public:
989  EdgeBuilder(PathDiagnostic &pd, PathDiagnosticBuilder &pdb)
990  : PD(pd), PDB(pdb) {
991 
992  // If the PathDiagnostic already has pieces, add the enclosing statement
993  // of the first piece as a context as well.
994  if (!PD.path.empty()) {
995  PrevLoc = (*PD.path.begin())->getLocation();
996 
997  if (const Stmt *S = PrevLoc.asStmt())
998  addExtendedContext(PDB.getEnclosingStmtLocation(S).asStmt());
999  }
1000  }
1001 
1002  ~EdgeBuilder() {
1003  while (!CLocs.empty()) popLocation();
1004 
1005  // Finally, add an initial edge from the start location of the first
1006  // statement (if it doesn't already exist).
1008  PDB.LC,
1009  PDB.getSourceManager());
1010  if (L.isValid())
1011  rawAddEdge(L);
1012  }
1013 
1014  void flushLocations() {
1015  while (!CLocs.empty())
1016  popLocation();
1017  PrevLoc = PathDiagnosticLocation();
1018  }
1019 
1020  void addEdge(PathDiagnosticLocation NewLoc, bool alwaysAdd = false,
1021  bool IsPostJump = false);
1022 
1023  void rawAddEdge(PathDiagnosticLocation NewLoc);
1024 
1025  void addContext(const Stmt *S);
1026  void addContext(const PathDiagnosticLocation &L);
1027  void addExtendedContext(const Stmt *S);
1028 };
1029 } // end anonymous namespace
1030 
1031 
1033 EdgeBuilder::getContextLocation(const PathDiagnosticLocation &L) {
1034  if (const Stmt *S = L.asStmt()) {
1035  if (IsControlFlowExpr(S))
1036  return L;
1037 
1038  return PDB.getEnclosingStmtLocation(S);
1039  }
1040 
1041  return L;
1042 }
1043 
1044 bool EdgeBuilder::containsLocation(const PathDiagnosticLocation &Container,
1045  const PathDiagnosticLocation &Containee) {
1046 
1047  if (Container == Containee)
1048  return true;
1049 
1050  if (Container.asDecl())
1051  return true;
1052 
1053  if (const Stmt *S = Containee.asStmt())
1054  if (const Stmt *ContainerS = Container.asStmt()) {
1055  while (S) {
1056  if (S == ContainerS)
1057  return true;
1058  S = PDB.getParent(S);
1059  }
1060  return false;
1061  }
1062 
1063  // Less accurate: compare using source ranges.
1064  SourceRange ContainerR = Container.asRange();
1065  SourceRange ContaineeR = Containee.asRange();
1066 
1067  SourceManager &SM = PDB.getSourceManager();
1068  SourceLocation ContainerRBeg = SM.getExpansionLoc(ContainerR.getBegin());
1069  SourceLocation ContainerREnd = SM.getExpansionLoc(ContainerR.getEnd());
1070  SourceLocation ContaineeRBeg = SM.getExpansionLoc(ContaineeR.getBegin());
1071  SourceLocation ContaineeREnd = SM.getExpansionLoc(ContaineeR.getEnd());
1072 
1073  unsigned ContainerBegLine = SM.getExpansionLineNumber(ContainerRBeg);
1074  unsigned ContainerEndLine = SM.getExpansionLineNumber(ContainerREnd);
1075  unsigned ContaineeBegLine = SM.getExpansionLineNumber(ContaineeRBeg);
1076  unsigned ContaineeEndLine = SM.getExpansionLineNumber(ContaineeREnd);
1077 
1078  assert(ContainerBegLine <= ContainerEndLine);
1079  assert(ContaineeBegLine <= ContaineeEndLine);
1080 
1081  return (ContainerBegLine <= ContaineeBegLine &&
1082  ContainerEndLine >= ContaineeEndLine &&
1083  (ContainerBegLine != ContaineeBegLine ||
1084  SM.getExpansionColumnNumber(ContainerRBeg) <=
1085  SM.getExpansionColumnNumber(ContaineeRBeg)) &&
1086  (ContainerEndLine != ContaineeEndLine ||
1087  SM.getExpansionColumnNumber(ContainerREnd) >=
1088  SM.getExpansionColumnNumber(ContaineeREnd)));
1089 }
1090 
1091 void EdgeBuilder::rawAddEdge(PathDiagnosticLocation NewLoc) {
1092  if (!PrevLoc.isValid()) {
1093  PrevLoc = NewLoc;
1094  return;
1095  }
1096 
1097  const PathDiagnosticLocation &NewLocClean = cleanUpLocation(NewLoc, PDB.LC);
1098  const PathDiagnosticLocation &PrevLocClean = cleanUpLocation(PrevLoc, PDB.LC);
1099 
1100  if (PrevLocClean.asLocation().isInvalid()) {
1101  PrevLoc = NewLoc;
1102  return;
1103  }
1104 
1105  if (NewLocClean.asLocation() == PrevLocClean.asLocation())
1106  return;
1107 
1108  // FIXME: Ignore intra-macro edges for now.
1109  if (NewLocClean.asLocation().getExpansionLoc() ==
1110  PrevLocClean.asLocation().getExpansionLoc())
1111  return;
1112 
1113  PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(NewLocClean, PrevLocClean));
1114  PrevLoc = NewLoc;
1115 }
1116 
1117 void EdgeBuilder::addEdge(PathDiagnosticLocation NewLoc, bool alwaysAdd,
1118  bool IsPostJump) {
1119 
1120  if (!alwaysAdd && NewLoc.asLocation().isMacroID())
1121  return;
1122 
1123  const PathDiagnosticLocation &CLoc = getContextLocation(NewLoc);
1124 
1125  while (!CLocs.empty()) {
1126  ContextLocation &TopContextLoc = CLocs.back();
1127 
1128  // Is the top location context the same as the one for the new location?
1129  if (TopContextLoc == CLoc) {
1130  if (alwaysAdd) {
1131  if (IsConsumedExpr(TopContextLoc))
1132  TopContextLoc.markDead();
1133 
1134  rawAddEdge(NewLoc);
1135  }
1136 
1137  if (IsPostJump)
1138  TopContextLoc.markDead();
1139  return;
1140  }
1141 
1142  if (containsLocation(TopContextLoc, CLoc)) {
1143  if (alwaysAdd) {
1144  rawAddEdge(NewLoc);
1145 
1146  if (IsConsumedExpr(CLoc)) {
1147  CLocs.push_back(ContextLocation(CLoc, /*IsDead=*/true));
1148  return;
1149  }
1150  }
1151 
1152  CLocs.push_back(ContextLocation(CLoc, /*IsDead=*/IsPostJump));
1153  return;
1154  }
1155 
1156  // Context does not contain the location. Flush it.
1157  popLocation();
1158  }
1159 
1160  // If we reach here, there is no enclosing context. Just add the edge.
1161  rawAddEdge(NewLoc);
1162 }
1163 
1164 bool EdgeBuilder::IsConsumedExpr(const PathDiagnosticLocation &L) {
1165  if (const Expr *X = dyn_cast_or_null<Expr>(L.asStmt()))
1166  return PDB.getParentMap().isConsumedExpr(X) && !IsControlFlowExpr(X);
1167 
1168  return false;
1169 }
1170 
1171 void EdgeBuilder::addExtendedContext(const Stmt *S) {
1172  if (!S)
1173  return;
1174 
1175  const Stmt *Parent = PDB.getParent(S);
1176  while (Parent) {
1177  if (isa<CompoundStmt>(Parent))
1178  Parent = PDB.getParent(Parent);
1179  else
1180  break;
1181  }
1182 
1183  if (Parent) {
1184  switch (Parent->getStmtClass()) {
1185  case Stmt::DoStmtClass:
1186  case Stmt::ObjCAtSynchronizedStmtClass:
1187  addContext(Parent);
1188  default:
1189  break;
1190  }
1191  }
1192 
1193  addContext(S);
1194 }
1195 
1196 void EdgeBuilder::addContext(const Stmt *S) {
1197  if (!S)
1198  return;
1199 
1200  PathDiagnosticLocation L(S, PDB.getSourceManager(), PDB.LC);
1201  addContext(L);
1202 }
1203 
1204 void EdgeBuilder::addContext(const PathDiagnosticLocation &L) {
1205  while (!CLocs.empty()) {
1206  const PathDiagnosticLocation &TopContextLoc = CLocs.back();
1207 
1208  // Is the top location context the same as the one for the new location?
1209  if (TopContextLoc == L)
1210  return;
1211 
1212  if (containsLocation(TopContextLoc, L)) {
1213  CLocs.push_back(L);
1214  return;
1215  }
1216 
1217  // Context does not contain the location. Flush it.
1218  popLocation();
1219  }
1220 
1221  CLocs.push_back(L);
1222 }
1223 
1224 // Cone-of-influence: support the reverse propagation of "interesting" symbols
1225 // and values by tracing interesting calculations backwards through evaluated
1226 // expressions along a path. This is probably overly complicated, but the idea
1227 // is that if an expression computed an "interesting" value, the child
1228 // expressions are are also likely to be "interesting" as well (which then
1229 // propagates to the values they in turn compute). This reverse propagation
1230 // is needed to track interesting correlations across function call boundaries,
1231 // where formal arguments bind to actual arguments, etc. This is also needed
1232 // because the constraint solver sometimes simplifies certain symbolic values
1233 // into constants when appropriate, and this complicates reasoning about
1234 // interesting values.
1236 
1238  InterestingExprs &IE,
1239  const ProgramState *State,
1240  const Expr *Ex,
1241  const LocationContext *LCtx) {
1242  SVal V = State->getSVal(Ex, LCtx);
1243  if (!(R.isInteresting(V) || IE.count(Ex)))
1244  return;
1245 
1246  switch (Ex->getStmtClass()) {
1247  default:
1248  if (!isa<CastExpr>(Ex))
1249  break;
1250  // Fall through.
1251  case Stmt::BinaryOperatorClass:
1252  case Stmt::UnaryOperatorClass: {
1253  for (const Stmt *SubStmt : Ex->children()) {
1254  if (const Expr *child = dyn_cast_or_null<Expr>(SubStmt)) {
1255  IE.insert(child);
1256  SVal ChildV = State->getSVal(child, LCtx);
1257  R.markInteresting(ChildV);
1258  }
1259  }
1260  break;
1261  }
1262  }
1263 
1264  R.markInteresting(V);
1265 }
1266 
1268  InterestingExprs &IE,
1269  const ProgramState *State,
1270  const LocationContext *CalleeCtx,
1271  const LocationContext *CallerCtx)
1272 {
1273  // FIXME: Handle non-CallExpr-based CallEvents.
1274  const StackFrameContext *Callee = CalleeCtx->getCurrentStackFrame();
1275  const Stmt *CallSite = Callee->getCallSite();
1276  if (const CallExpr *CE = dyn_cast_or_null<CallExpr>(CallSite)) {
1277  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CalleeCtx->getDecl())) {
1278  FunctionDecl::param_const_iterator PI = FD->param_begin(),
1279  PE = FD->param_end();
1280  CallExpr::const_arg_iterator AI = CE->arg_begin(), AE = CE->arg_end();
1281  for (; AI != AE && PI != PE; ++AI, ++PI) {
1282  if (const Expr *ArgE = *AI) {
1283  if (const ParmVarDecl *PD = *PI) {
1284  Loc LV = State->getLValue(PD, CalleeCtx);
1285  if (R.isInteresting(LV) || R.isInteresting(State->getRawSVal(LV)))
1286  IE.insert(ArgE);
1287  }
1288  }
1289  }
1290  }
1291  }
1292 }
1293 
1294 //===----------------------------------------------------------------------===//
1295 // Functions for determining if a loop was executed 0 times.
1296 //===----------------------------------------------------------------------===//
1297 
1298 static bool isLoop(const Stmt *Term) {
1299  switch (Term->getStmtClass()) {
1300  case Stmt::ForStmtClass:
1301  case Stmt::WhileStmtClass:
1302  case Stmt::ObjCForCollectionStmtClass:
1303  case Stmt::CXXForRangeStmtClass:
1304  return true;
1305  default:
1306  // Note that we intentionally do not include do..while here.
1307  return false;
1308  }
1309 }
1310 
1311 static bool isJumpToFalseBranch(const BlockEdge *BE) {
1312  const CFGBlock *Src = BE->getSrc();
1313  assert(Src->succ_size() == 2);
1314  return (*(Src->succ_begin()+1) == BE->getDst());
1315 }
1316 
1317 /// Return true if the terminator is a loop and the destination is the
1318 /// false branch.
1319 static bool isLoopJumpPastBody(const Stmt *Term, const BlockEdge *BE) {
1320  if (!isLoop(Term))
1321  return false;
1322 
1323  // Did we take the false branch?
1324  return isJumpToFalseBranch(BE);
1325 }
1326 
1327 static bool isContainedByStmt(ParentMap &PM, const Stmt *S, const Stmt *SubS) {
1328  while (SubS) {
1329  if (SubS == S)
1330  return true;
1331  SubS = PM.getParent(SubS);
1332  }
1333  return false;
1334 }
1335 
1336 static const Stmt *getStmtBeforeCond(ParentMap &PM, const Stmt *Term,
1337  const ExplodedNode *N) {
1338  while (N) {
1340  if (SP) {
1341  const Stmt *S = SP->getStmt();
1342  if (!isContainedByStmt(PM, Term, S))
1343  return S;
1344  }
1345  N = N->getFirstPred();
1346  }
1347  return nullptr;
1348 }
1349 
1350 static bool isInLoopBody(ParentMap &PM, const Stmt *S, const Stmt *Term) {
1351  const Stmt *LoopBody = nullptr;
1352  switch (Term->getStmtClass()) {
1353  case Stmt::CXXForRangeStmtClass: {
1354  const CXXForRangeStmt *FR = cast<CXXForRangeStmt>(Term);
1355  if (isContainedByStmt(PM, FR->getInc(), S))
1356  return true;
1357  if (isContainedByStmt(PM, FR->getLoopVarStmt(), S))
1358  return true;
1359  LoopBody = FR->getBody();
1360  break;
1361  }
1362  case Stmt::ForStmtClass: {
1363  const ForStmt *FS = cast<ForStmt>(Term);
1364  if (isContainedByStmt(PM, FS->getInc(), S))
1365  return true;
1366  LoopBody = FS->getBody();
1367  break;
1368  }
1369  case Stmt::ObjCForCollectionStmtClass: {
1370  const ObjCForCollectionStmt *FC = cast<ObjCForCollectionStmt>(Term);
1371  LoopBody = FC->getBody();
1372  break;
1373  }
1374  case Stmt::WhileStmtClass:
1375  LoopBody = cast<WhileStmt>(Term)->getBody();
1376  break;
1377  default:
1378  return false;
1379  }
1380  return isContainedByStmt(PM, LoopBody, S);
1381 }
1382 
1383 //===----------------------------------------------------------------------===//
1384 // Top-level logic for generating extensive path diagnostics.
1385 //===----------------------------------------------------------------------===//
1386 
1388  PathDiagnostic &PD, PathDiagnosticBuilder &PDB, const ExplodedNode *N,
1389  LocationContextMap &LCM,
1390  ArrayRef<std::unique_ptr<BugReporterVisitor>> visitors) {
1391  EdgeBuilder EB(PD, PDB);
1392  const SourceManager& SM = PDB.getSourceManager();
1393  StackDiagVector CallStack;
1394  InterestingExprs IE;
1395 
1396  const ExplodedNode *NextNode = N->pred_empty() ? nullptr : *(N->pred_begin());
1397  while (NextNode) {
1398  N = NextNode;
1399  NextNode = N->getFirstPred();
1400  ProgramPoint P = N->getLocation();
1401 
1402  do {
1403  if (Optional<PostStmt> PS = P.getAs<PostStmt>()) {
1404  if (const Expr *Ex = PS->getStmtAs<Expr>())
1405  reversePropagateIntererstingSymbols(*PDB.getBugReport(), IE,
1406  N->getState().get(), Ex,
1407  N->getLocationContext());
1408  }
1409 
1410  if (Optional<CallExitEnd> CE = P.getAs<CallExitEnd>()) {
1411  const Stmt *S = CE->getCalleeContext()->getCallSite();
1412  if (const Expr *Ex = dyn_cast_or_null<Expr>(S)) {
1413  reversePropagateIntererstingSymbols(*PDB.getBugReport(), IE,
1414  N->getState().get(), Ex,
1415  N->getLocationContext());
1416  }
1417 
1420  LCM[&C->path] = CE->getCalleeContext();
1421 
1422  EB.addEdge(C->callReturn, /*AlwaysAdd=*/true, /*IsPostJump=*/true);
1423  EB.flushLocations();
1424 
1425  PD.getActivePath().push_front(C);
1426  PD.pushActivePath(&C->path);
1427  CallStack.push_back(StackDiagPair(C, N));
1428  break;
1429  }
1430 
1431  // Pop the call hierarchy if we are done walking the contents
1432  // of a function call.
1433  if (Optional<CallEnter> CE = P.getAs<CallEnter>()) {
1434  // Add an edge to the start of the function.
1435  const Decl *D = CE->getCalleeContext()->getDecl();
1438  EB.addEdge(pos);
1439 
1440  // Flush all locations, and pop the active path.
1441  bool VisitedEntireCall = PD.isWithinCall();
1442  EB.flushLocations();
1443  PD.popActivePath();
1444  PDB.LC = N->getLocationContext();
1445 
1446  // Either we just added a bunch of stuff to the top-level path, or
1447  // we have a previous CallExitEnd. If the former, it means that the
1448  // path terminated within a function call. We must then take the
1449  // current contents of the active path and place it within
1450  // a new PathDiagnosticCallPiece.
1452  if (VisitedEntireCall) {
1453  C = cast<PathDiagnosticCallPiece>(PD.getActivePath().front());
1454  } else {
1455  const Decl *Caller = CE->getLocationContext()->getDecl();
1457  LCM[&C->path] = CE->getCalleeContext();
1458  }
1459 
1460  C->setCallee(*CE, SM);
1461  EB.addContext(C->getLocation());
1462 
1463  if (!CallStack.empty()) {
1464  assert(CallStack.back().first == C);
1465  CallStack.pop_back();
1466  }
1467  break;
1468  }
1469 
1470  // Note that is important that we update the LocationContext
1471  // after looking at CallExits. CallExit basically adds an
1472  // edge in the *caller*, so we don't want to update the LocationContext
1473  // too soon.
1474  PDB.LC = N->getLocationContext();
1475 
1476  // Block edges.
1477  if (Optional<BlockEdge> BE = P.getAs<BlockEdge>()) {
1478  // Does this represent entering a call? If so, look at propagating
1479  // interesting symbols across call boundaries.
1480  if (NextNode) {
1481  const LocationContext *CallerCtx = NextNode->getLocationContext();
1482  const LocationContext *CalleeCtx = PDB.LC;
1483  if (CallerCtx != CalleeCtx) {
1484  reversePropagateInterestingSymbols(*PDB.getBugReport(), IE,
1485  N->getState().get(),
1486  CalleeCtx, CallerCtx);
1487  }
1488  }
1489 
1490  // Are we jumping to the head of a loop? Add a special diagnostic.
1491  if (const Stmt *Loop = BE->getSrc()->getLoopTarget()) {
1492  PathDiagnosticLocation L(Loop, SM, PDB.LC);
1493  const CompoundStmt *CS = nullptr;
1494 
1495  if (const ForStmt *FS = dyn_cast<ForStmt>(Loop))
1496  CS = dyn_cast<CompoundStmt>(FS->getBody());
1497  else if (const WhileStmt *WS = dyn_cast<WhileStmt>(Loop))
1498  CS = dyn_cast<CompoundStmt>(WS->getBody());
1499 
1502  "Looping back to the head of the loop");
1503  p->setPrunable(true);
1504 
1505  EB.addEdge(p->getLocation(), true);
1506  PD.getActivePath().push_front(p);
1507 
1508  if (CS) {
1511  EB.addEdge(BL);
1512  }
1513  }
1514 
1515  const CFGBlock *BSrc = BE->getSrc();
1516  ParentMap &PM = PDB.getParentMap();
1517 
1518  if (const Stmt *Term = BSrc->getTerminator()) {
1519  // Are we jumping past the loop body without ever executing the
1520  // loop (because the condition was false)?
1521  if (isLoopJumpPastBody(Term, &*BE) &&
1522  !isInLoopBody(PM,
1523  getStmtBeforeCond(PM,
1524  BSrc->getTerminatorCondition(),
1525  N),
1526  Term)) {
1527  PathDiagnosticLocation L(Term, SM, PDB.LC);
1529  new PathDiagnosticEventPiece(L, "Loop body executed 0 times");
1530  PE->setPrunable(true);
1531 
1532  EB.addEdge(PE->getLocation(), true);
1533  PD.getActivePath().push_front(PE);
1534  }
1535 
1536  // In any case, add the terminator as the current statement
1537  // context for control edges.
1538  EB.addContext(Term);
1539  }
1540 
1541  break;
1542  }
1543 
1545  Optional<CFGElement> First = BE->getFirstElement();
1546  if (Optional<CFGStmt> S = First ? First->getAs<CFGStmt>() : None) {
1547  const Stmt *stmt = S->getStmt();
1548  if (IsControlFlowExpr(stmt)) {
1549  // Add the proper context for '&&', '||', and '?'.
1550  EB.addContext(stmt);
1551  }
1552  else
1553  EB.addExtendedContext(PDB.getEnclosingStmtLocation(stmt).asStmt());
1554  }
1555 
1556  break;
1557  }
1558 
1559 
1560  } while (0);
1561 
1562  if (!NextNode)
1563  continue;
1564 
1565  // Add pieces from custom visitors.
1566  BugReport *R = PDB.getBugReport();
1567  for (auto &V : visitors) {
1568  if (PathDiagnosticPiece *p = V->VisitNode(N, NextNode, PDB, *R)) {
1569  const PathDiagnosticLocation &Loc = p->getLocation();
1570  EB.addEdge(Loc, true);
1571  PD.getActivePath().push_front(p);
1572  updateStackPiecesWithMessage(p, CallStack);
1573 
1574  if (const Stmt *S = Loc.asStmt())
1575  EB.addExtendedContext(PDB.getEnclosingStmtLocation(S).asStmt());
1576  }
1577  }
1578  }
1579 
1580  return PDB.getBugReport()->isValid();
1581 }
1582 
1583 /// \brief Adds a sanitized control-flow diagnostic edge to a path.
1584 static void addEdgeToPath(PathPieces &path,
1585  PathDiagnosticLocation &PrevLoc,
1586  PathDiagnosticLocation NewLoc,
1587  const LocationContext *LC) {
1588  if (!NewLoc.isValid())
1589  return;
1590 
1591  SourceLocation NewLocL = NewLoc.asLocation();
1592  if (NewLocL.isInvalid())
1593  return;
1594 
1595  if (!PrevLoc.isValid() || !PrevLoc.asLocation().isValid()) {
1596  PrevLoc = NewLoc;
1597  return;
1598  }
1599 
1600  // Ignore self-edges, which occur when there are multiple nodes at the same
1601  // statement.
1602  if (NewLoc.asStmt() && NewLoc.asStmt() == PrevLoc.asStmt())
1603  return;
1604 
1605  path.push_front(new PathDiagnosticControlFlowPiece(NewLoc,
1606  PrevLoc));
1607  PrevLoc = NewLoc;
1608 }
1609 
1610 /// A customized wrapper for CFGBlock::getTerminatorCondition()
1611 /// which returns the element for ObjCForCollectionStmts.
1612 static const Stmt *getTerminatorCondition(const CFGBlock *B) {
1613  const Stmt *S = B->getTerminatorCondition();
1614  if (const ObjCForCollectionStmt *FS =
1615  dyn_cast_or_null<ObjCForCollectionStmt>(S))
1616  return FS->getElement();
1617  return S;
1618 }
1619 
1620 static const char StrEnteringLoop[] = "Entering loop body";
1621 static const char StrLoopBodyZero[] = "Loop body executed 0 times";
1622 static const char StrLoopRangeEmpty[] =
1623  "Loop body skipped when range is empty";
1624 static const char StrLoopCollectionEmpty[] =
1625  "Loop body skipped when collection is empty";
1626 
1628  PathDiagnostic &PD, PathDiagnosticBuilder &PDB, const ExplodedNode *N,
1629  LocationContextMap &LCM,
1630  ArrayRef<std::unique_ptr<BugReporterVisitor>> visitors) {
1631 
1632  BugReport *report = PDB.getBugReport();
1633  const SourceManager& SM = PDB.getSourceManager();
1634  StackDiagVector CallStack;
1635  InterestingExprs IE;
1636 
1637  PathDiagnosticLocation PrevLoc = PD.getLocation();
1638 
1639  const ExplodedNode *NextNode = N->getFirstPred();
1640  while (NextNode) {
1641  N = NextNode;
1642  NextNode = N->getFirstPred();
1643  ProgramPoint P = N->getLocation();
1644 
1645  do {
1646  // Have we encountered an entrance to a call? It may be
1647  // the case that we have not encountered a matching
1648  // call exit before this point. This means that the path
1649  // terminated within the call itself.
1650  if (Optional<CallEnter> CE = P.getAs<CallEnter>()) {
1651  // Add an edge to the start of the function.
1652  const StackFrameContext *CalleeLC = CE->getCalleeContext();
1653  const Decl *D = CalleeLC->getDecl();
1654  addEdgeToPath(PD.getActivePath(), PrevLoc,
1656  CalleeLC);
1657 
1658  // Did we visit an entire call?
1659  bool VisitedEntireCall = PD.isWithinCall();
1660  PD.popActivePath();
1661 
1663  if (VisitedEntireCall) {
1664  PathDiagnosticPiece *P = PD.getActivePath().front().get();
1665  C = cast<PathDiagnosticCallPiece>(P);
1666  } else {
1667  const Decl *Caller = CE->getLocationContext()->getDecl();
1669 
1670  // Since we just transferred the path over to the call piece,
1671  // reset the mapping from active to location context.
1672  assert(PD.getActivePath().size() == 1 &&
1673  PD.getActivePath().front() == C);
1674  LCM[&PD.getActivePath()] = nullptr;
1675 
1676  // Record the location context mapping for the path within
1677  // the call.
1678  assert(LCM[&C->path] == nullptr ||
1679  LCM[&C->path] == CE->getCalleeContext());
1680  LCM[&C->path] = CE->getCalleeContext();
1681 
1682  // If this is the first item in the active path, record
1683  // the new mapping from active path to location context.
1684  const LocationContext *&NewLC = LCM[&PD.getActivePath()];
1685  if (!NewLC)
1686  NewLC = N->getLocationContext();
1687 
1688  PDB.LC = NewLC;
1689  }
1690  C->setCallee(*CE, SM);
1691 
1692  // Update the previous location in the active path.
1693  PrevLoc = C->getLocation();
1694 
1695  if (!CallStack.empty()) {
1696  assert(CallStack.back().first == C);
1697  CallStack.pop_back();
1698  }
1699  break;
1700  }
1701 
1702  // Query the location context here and the previous location
1703  // as processing CallEnter may change the active path.
1704  PDB.LC = N->getLocationContext();
1705 
1706  // Record the mapping from the active path to the location
1707  // context.
1708  assert(!LCM[&PD.getActivePath()] ||
1709  LCM[&PD.getActivePath()] == PDB.LC);
1710  LCM[&PD.getActivePath()] = PDB.LC;
1711 
1712  // Have we encountered an exit from a function call?
1713  if (Optional<CallExitEnd> CE = P.getAs<CallExitEnd>()) {
1714  const Stmt *S = CE->getCalleeContext()->getCallSite();
1715  // Propagate the interesting symbols accordingly.
1716  if (const Expr *Ex = dyn_cast_or_null<Expr>(S)) {
1717  reversePropagateIntererstingSymbols(*PDB.getBugReport(), IE,
1718  N->getState().get(), Ex,
1719  N->getLocationContext());
1720  }
1721 
1722  // We are descending into a call (backwards). Construct
1723  // a new call piece to contain the path pieces for that call.
1726 
1727  // Record the location context for this call piece.
1728  LCM[&C->path] = CE->getCalleeContext();
1729 
1730  // Add the edge to the return site.
1731  addEdgeToPath(PD.getActivePath(), PrevLoc, C->callReturn, PDB.LC);
1732  PD.getActivePath().push_front(C);
1733  PrevLoc.invalidate();
1734 
1735  // Make the contents of the call the active path for now.
1736  PD.pushActivePath(&C->path);
1737  CallStack.push_back(StackDiagPair(C, N));
1738  break;
1739  }
1740 
1741  if (Optional<PostStmt> PS = P.getAs<PostStmt>()) {
1742  // For expressions, make sure we propagate the
1743  // interesting symbols correctly.
1744  if (const Expr *Ex = PS->getStmtAs<Expr>())
1745  reversePropagateIntererstingSymbols(*PDB.getBugReport(), IE,
1746  N->getState().get(), Ex,
1747  N->getLocationContext());
1748 
1749  // Add an edge. If this is an ObjCForCollectionStmt do
1750  // not add an edge here as it appears in the CFG both
1751  // as a terminator and as a terminator condition.
1752  if (!isa<ObjCForCollectionStmt>(PS->getStmt())) {
1754  PathDiagnosticLocation(PS->getStmt(), SM, PDB.LC);
1755  addEdgeToPath(PD.getActivePath(), PrevLoc, L, PDB.LC);
1756  }
1757  break;
1758  }
1759 
1760  // Block edges.
1761  if (Optional<BlockEdge> BE = P.getAs<BlockEdge>()) {
1762  // Does this represent entering a call? If so, look at propagating
1763  // interesting symbols across call boundaries.
1764  if (NextNode) {
1765  const LocationContext *CallerCtx = NextNode->getLocationContext();
1766  const LocationContext *CalleeCtx = PDB.LC;
1767  if (CallerCtx != CalleeCtx) {
1768  reversePropagateInterestingSymbols(*PDB.getBugReport(), IE,
1769  N->getState().get(),
1770  CalleeCtx, CallerCtx);
1771  }
1772  }
1773 
1774  // Are we jumping to the head of a loop? Add a special diagnostic.
1775  if (const Stmt *Loop = BE->getSrc()->getLoopTarget()) {
1776  PathDiagnosticLocation L(Loop, SM, PDB.LC);
1777  const Stmt *Body = nullptr;
1778 
1779  if (const ForStmt *FS = dyn_cast<ForStmt>(Loop))
1780  Body = FS->getBody();
1781  else if (const WhileStmt *WS = dyn_cast<WhileStmt>(Loop))
1782  Body = WS->getBody();
1783  else if (const ObjCForCollectionStmt *OFS =
1784  dyn_cast<ObjCForCollectionStmt>(Loop)) {
1785  Body = OFS->getBody();
1786  } else if (const CXXForRangeStmt *FRS =
1787  dyn_cast<CXXForRangeStmt>(Loop)) {
1788  Body = FRS->getBody();
1789  }
1790  // do-while statements are explicitly excluded here
1791 
1793  new PathDiagnosticEventPiece(L, "Looping back to the head "
1794  "of the loop");
1795  p->setPrunable(true);
1796 
1797  addEdgeToPath(PD.getActivePath(), PrevLoc, p->getLocation(), PDB.LC);
1798  PD.getActivePath().push_front(p);
1799 
1800  if (const CompoundStmt *CS = dyn_cast_or_null<CompoundStmt>(Body)) {
1801  addEdgeToPath(PD.getActivePath(), PrevLoc,
1803  PDB.LC);
1804  }
1805  }
1806 
1807  const CFGBlock *BSrc = BE->getSrc();
1808  ParentMap &PM = PDB.getParentMap();
1809 
1810  if (const Stmt *Term = BSrc->getTerminator()) {
1811  // Are we jumping past the loop body without ever executing the
1812  // loop (because the condition was false)?
1813  if (isLoop(Term)) {
1814  const Stmt *TermCond = getTerminatorCondition(BSrc);
1815  bool IsInLoopBody =
1816  isInLoopBody(PM, getStmtBeforeCond(PM, TermCond, N), Term);
1817 
1818  const char *str = nullptr;
1819 
1820  if (isJumpToFalseBranch(&*BE)) {
1821  if (!IsInLoopBody) {
1822  if (isa<ObjCForCollectionStmt>(Term)) {
1823  str = StrLoopCollectionEmpty;
1824  } else if (isa<CXXForRangeStmt>(Term)) {
1825  str = StrLoopRangeEmpty;
1826  } else {
1827  str = StrLoopBodyZero;
1828  }
1829  }
1830  } else {
1831  str = StrEnteringLoop;
1832  }
1833 
1834  if (str) {
1835  PathDiagnosticLocation L(TermCond ? TermCond : Term, SM, PDB.LC);
1837  new PathDiagnosticEventPiece(L, str);
1838  PE->setPrunable(true);
1839  addEdgeToPath(PD.getActivePath(), PrevLoc,
1840  PE->getLocation(), PDB.LC);
1841  PD.getActivePath().push_front(PE);
1842  }
1843  } else if (isa<BreakStmt>(Term) || isa<ContinueStmt>(Term) ||
1844  isa<GotoStmt>(Term)) {
1845  PathDiagnosticLocation L(Term, SM, PDB.LC);
1846  addEdgeToPath(PD.getActivePath(), PrevLoc, L, PDB.LC);
1847  }
1848  }
1849  break;
1850  }
1851  } while (0);
1852 
1853  if (!NextNode)
1854  continue;
1855 
1856  // Add pieces from custom visitors.
1857  for (auto &V : visitors) {
1858  if (PathDiagnosticPiece *p = V->VisitNode(N, NextNode, PDB, *report)) {
1859  addEdgeToPath(PD.getActivePath(), PrevLoc, p->getLocation(), PDB.LC);
1860  PD.getActivePath().push_front(p);
1861  updateStackPiecesWithMessage(p, CallStack);
1862  }
1863  }
1864  }
1865 
1866  // Add an edge to the start of the function.
1867  // We'll prune it out later, but it helps make diagnostics more uniform.
1868  const StackFrameContext *CalleeLC = PDB.LC->getCurrentStackFrame();
1869  const Decl *D = CalleeLC->getDecl();
1870  addEdgeToPath(PD.getActivePath(), PrevLoc,
1872  CalleeLC);
1873 
1874  return report->isValid();
1875 }
1876 
1878  if (!L.isValid())
1879  return nullptr;
1880  return L.asStmt();
1881 }
1882 
1883 static const Stmt *getStmtParent(const Stmt *S, const ParentMap &PM) {
1884  if (!S)
1885  return nullptr;
1886 
1887  while (true) {
1888  S = PM.getParentIgnoreParens(S);
1889 
1890  if (!S)
1891  break;
1892 
1893  if (isa<ExprWithCleanups>(S) ||
1894  isa<CXXBindTemporaryExpr>(S) ||
1895  isa<SubstNonTypeTemplateParmExpr>(S))
1896  continue;
1897 
1898  break;
1899  }
1900 
1901  return S;
1902 }
1903 
1904 static bool isConditionForTerminator(const Stmt *S, const Stmt *Cond) {
1905  switch (S->getStmtClass()) {
1906  case Stmt::BinaryOperatorClass: {
1907  const BinaryOperator *BO = cast<BinaryOperator>(S);
1908  if (!BO->isLogicalOp())
1909  return false;
1910  return BO->getLHS() == Cond || BO->getRHS() == Cond;
1911  }
1912  case Stmt::IfStmtClass:
1913  return cast<IfStmt>(S)->getCond() == Cond;
1914  case Stmt::ForStmtClass:
1915  return cast<ForStmt>(S)->getCond() == Cond;
1916  case Stmt::WhileStmtClass:
1917  return cast<WhileStmt>(S)->getCond() == Cond;
1918  case Stmt::DoStmtClass:
1919  return cast<DoStmt>(S)->getCond() == Cond;
1920  case Stmt::ChooseExprClass:
1921  return cast<ChooseExpr>(S)->getCond() == Cond;
1922  case Stmt::IndirectGotoStmtClass:
1923  return cast<IndirectGotoStmt>(S)->getTarget() == Cond;
1924  case Stmt::SwitchStmtClass:
1925  return cast<SwitchStmt>(S)->getCond() == Cond;
1926  case Stmt::BinaryConditionalOperatorClass:
1927  return cast<BinaryConditionalOperator>(S)->getCond() == Cond;
1928  case Stmt::ConditionalOperatorClass: {
1929  const ConditionalOperator *CO = cast<ConditionalOperator>(S);
1930  return CO->getCond() == Cond ||
1931  CO->getLHS() == Cond ||
1932  CO->getRHS() == Cond;
1933  }
1934  case Stmt::ObjCForCollectionStmtClass:
1935  return cast<ObjCForCollectionStmt>(S)->getElement() == Cond;
1936  case Stmt::CXXForRangeStmtClass: {
1937  const CXXForRangeStmt *FRS = cast<CXXForRangeStmt>(S);
1938  return FRS->getCond() == Cond || FRS->getRangeInit() == Cond;
1939  }
1940  default:
1941  return false;
1942  }
1943 }
1944 
1945 static bool isIncrementOrInitInForLoop(const Stmt *S, const Stmt *FL) {
1946  if (const ForStmt *FS = dyn_cast<ForStmt>(FL))
1947  return FS->getInc() == S || FS->getInit() == S;
1948  if (const CXXForRangeStmt *FRS = dyn_cast<CXXForRangeStmt>(FL))
1949  return FRS->getInc() == S || FRS->getRangeStmt() == S ||
1950  FRS->getLoopVarStmt() || FRS->getRangeInit() == S;
1951  return false;
1952 }
1953 
1956 
1957 /// Adds synthetic edges from top-level statements to their subexpressions.
1958 ///
1959 /// This avoids a "swoosh" effect, where an edge from a top-level statement A
1960 /// points to a sub-expression B.1 that's not at the start of B. In these cases,
1961 /// we'd like to see an edge from A to B, then another one from B to B.1.
1962 static void addContextEdges(PathPieces &pieces, SourceManager &SM,
1963  const ParentMap &PM, const LocationContext *LCtx) {
1964  PathPieces::iterator Prev = pieces.end();
1965  for (PathPieces::iterator I = pieces.begin(), E = Prev; I != E;
1966  Prev = I, ++I) {
1968  dyn_cast<PathDiagnosticControlFlowPiece>(*I);
1969 
1970  if (!Piece)
1971  continue;
1972 
1973  PathDiagnosticLocation SrcLoc = Piece->getStartLocation();
1975 
1976  PathDiagnosticLocation NextSrcContext = SrcLoc;
1977  const Stmt *InnerStmt = nullptr;
1978  while (NextSrcContext.isValid() && NextSrcContext.asStmt() != InnerStmt) {
1979  SrcContexts.push_back(NextSrcContext);
1980  InnerStmt = NextSrcContext.asStmt();
1981  NextSrcContext = getEnclosingStmtLocation(InnerStmt, SM, PM, LCtx,
1982  /*allowNested=*/true);
1983  }
1984 
1985  // Repeatedly split the edge as necessary.
1986  // This is important for nested logical expressions (||, &&, ?:) where we
1987  // want to show all the levels of context.
1988  while (true) {
1989  const Stmt *Dst = getLocStmt(Piece->getEndLocation());
1990 
1991  // We are looking at an edge. Is the destination within a larger
1992  // expression?
1993  PathDiagnosticLocation DstContext =
1994  getEnclosingStmtLocation(Dst, SM, PM, LCtx, /*allowNested=*/true);
1995  if (!DstContext.isValid() || DstContext.asStmt() == Dst)
1996  break;
1997 
1998  // If the source is in the same context, we're already good.
1999  if (std::find(SrcContexts.begin(), SrcContexts.end(), DstContext) !=
2000  SrcContexts.end())
2001  break;
2002 
2003  // Update the subexpression node to point to the context edge.
2004  Piece->setStartLocation(DstContext);
2005 
2006  // Try to extend the previous edge if it's at the same level as the source
2007  // context.
2008  if (Prev != E) {
2009  PathDiagnosticControlFlowPiece *PrevPiece =
2010  dyn_cast<PathDiagnosticControlFlowPiece>(*Prev);
2011 
2012  if (PrevPiece) {
2013  if (const Stmt *PrevSrc = getLocStmt(PrevPiece->getStartLocation())) {
2014  const Stmt *PrevSrcParent = getStmtParent(PrevSrc, PM);
2015  if (PrevSrcParent == getStmtParent(getLocStmt(DstContext), PM)) {
2016  PrevPiece->setEndLocation(DstContext);
2017  break;
2018  }
2019  }
2020  }
2021  }
2022 
2023  // Otherwise, split the current edge into a context edge and a
2024  // subexpression edge. Note that the context statement may itself have
2025  // context.
2026  Piece = new PathDiagnosticControlFlowPiece(SrcLoc, DstContext);
2027  I = pieces.insert(I, Piece);
2028  }
2029  }
2030 }
2031 
2032 /// \brief Move edges from a branch condition to a branch target
2033 /// when the condition is simple.
2034 ///
2035 /// This restructures some of the work of addContextEdges. That function
2036 /// creates edges this may destroy, but they work together to create a more
2037 /// aesthetically set of edges around branches. After the call to
2038 /// addContextEdges, we may have (1) an edge to the branch, (2) an edge from
2039 /// the branch to the branch condition, and (3) an edge from the branch
2040 /// condition to the branch target. We keep (1), but may wish to remove (2)
2041 /// and move the source of (3) to the branch if the branch condition is simple.
2042 ///
2043 static void simplifySimpleBranches(PathPieces &pieces) {
2044  for (PathPieces::iterator I = pieces.begin(), E = pieces.end(); I != E; ++I) {
2045 
2047  dyn_cast<PathDiagnosticControlFlowPiece>(*I);
2048 
2049  if (!PieceI)
2050  continue;
2051 
2052  const Stmt *s1Start = getLocStmt(PieceI->getStartLocation());
2053  const Stmt *s1End = getLocStmt(PieceI->getEndLocation());
2054 
2055  if (!s1Start || !s1End)
2056  continue;
2057 
2058  PathPieces::iterator NextI = I; ++NextI;
2059  if (NextI == E)
2060  break;
2061 
2062  PathDiagnosticControlFlowPiece *PieceNextI = nullptr;
2063 
2064  while (true) {
2065  if (NextI == E)
2066  break;
2067 
2068  PathDiagnosticEventPiece *EV = dyn_cast<PathDiagnosticEventPiece>(*NextI);
2069  if (EV) {
2070  StringRef S = EV->getString();
2071  if (S == StrEnteringLoop || S == StrLoopBodyZero ||
2073  ++NextI;
2074  continue;
2075  }
2076  break;
2077  }
2078 
2079  PieceNextI = dyn_cast<PathDiagnosticControlFlowPiece>(*NextI);
2080  break;
2081  }
2082 
2083  if (!PieceNextI)
2084  continue;
2085 
2086  const Stmt *s2Start = getLocStmt(PieceNextI->getStartLocation());
2087  const Stmt *s2End = getLocStmt(PieceNextI->getEndLocation());
2088 
2089  if (!s2Start || !s2End || s1End != s2Start)
2090  continue;
2091 
2092  // We only perform this transformation for specific branch kinds.
2093  // We don't want to do this for do..while, for example.
2094  if (!(isa<ForStmt>(s1Start) || isa<WhileStmt>(s1Start) ||
2095  isa<IfStmt>(s1Start) || isa<ObjCForCollectionStmt>(s1Start) ||
2096  isa<CXXForRangeStmt>(s1Start)))
2097  continue;
2098 
2099  // Is s1End the branch condition?
2100  if (!isConditionForTerminator(s1Start, s1End))
2101  continue;
2102 
2103  // Perform the hoisting by eliminating (2) and changing the start
2104  // location of (3).
2105  PieceNextI->setStartLocation(PieceI->getStartLocation());
2106  I = pieces.erase(I);
2107  }
2108 }
2109 
2110 /// Returns the number of bytes in the given (character-based) SourceRange.
2111 ///
2112 /// If the locations in the range are not on the same line, returns None.
2113 ///
2114 /// Note that this does not do a precise user-visible character or column count.
2116  SourceRange Range) {
2117  SourceRange ExpansionRange(SM.getExpansionLoc(Range.getBegin()),
2118  SM.getExpansionRange(Range.getEnd()).second);
2119 
2120  FileID FID = SM.getFileID(ExpansionRange.getBegin());
2121  if (FID != SM.getFileID(ExpansionRange.getEnd()))
2122  return None;
2123 
2124  bool Invalid;
2125  const llvm::MemoryBuffer *Buffer = SM.getBuffer(FID, &Invalid);
2126  if (Invalid)
2127  return None;
2128 
2129  unsigned BeginOffset = SM.getFileOffset(ExpansionRange.getBegin());
2130  unsigned EndOffset = SM.getFileOffset(ExpansionRange.getEnd());
2131  StringRef Snippet = Buffer->getBuffer().slice(BeginOffset, EndOffset);
2132 
2133  // We're searching the raw bytes of the buffer here, which might include
2134  // escaped newlines and such. That's okay; we're trying to decide whether the
2135  // SourceRange is covering a large or small amount of space in the user's
2136  // editor.
2137  if (Snippet.find_first_of("\r\n") != StringRef::npos)
2138  return None;
2139 
2140  // This isn't Unicode-aware, but it doesn't need to be.
2141  return Snippet.size();
2142 }
2143 
2144 /// \sa getLengthOnSingleLine(SourceManager, SourceRange)
2146  const Stmt *S) {
2147  return getLengthOnSingleLine(SM, S->getSourceRange());
2148 }
2149 
2150 /// Eliminate two-edge cycles created by addContextEdges().
2151 ///
2152 /// Once all the context edges are in place, there are plenty of cases where
2153 /// there's a single edge from a top-level statement to a subexpression,
2154 /// followed by a single path note, and then a reverse edge to get back out to
2155 /// the top level. If the statement is simple enough, the subexpression edges
2156 /// just add noise and make it harder to understand what's going on.
2157 ///
2158 /// This function only removes edges in pairs, because removing only one edge
2159 /// might leave other edges dangling.
2160 ///
2161 /// This will not remove edges in more complicated situations:
2162 /// - if there is more than one "hop" leading to or from a subexpression.
2163 /// - if there is an inlined call between the edges instead of a single event.
2164 /// - if the whole statement is large enough that having subexpression arrows
2165 /// might be helpful.
2167  ParentMap &PM) {
2168  for (PathPieces::iterator I = Path.begin(), E = Path.end(); I != E; ) {
2169  // Pattern match the current piece and its successor.
2171  dyn_cast<PathDiagnosticControlFlowPiece>(*I);
2172 
2173  if (!PieceI) {
2174  ++I;
2175  continue;
2176  }
2177 
2178  const Stmt *s1Start = getLocStmt(PieceI->getStartLocation());
2179  const Stmt *s1End = getLocStmt(PieceI->getEndLocation());
2180 
2181  PathPieces::iterator NextI = I; ++NextI;
2182  if (NextI == E)
2183  break;
2184 
2185  PathDiagnosticControlFlowPiece *PieceNextI =
2186  dyn_cast<PathDiagnosticControlFlowPiece>(*NextI);
2187 
2188  if (!PieceNextI) {
2189  if (isa<PathDiagnosticEventPiece>(*NextI)) {
2190  ++NextI;
2191  if (NextI == E)
2192  break;
2193  PieceNextI = dyn_cast<PathDiagnosticControlFlowPiece>(*NextI);
2194  }
2195 
2196  if (!PieceNextI) {
2197  ++I;
2198  continue;
2199  }
2200  }
2201 
2202  const Stmt *s2Start = getLocStmt(PieceNextI->getStartLocation());
2203  const Stmt *s2End = getLocStmt(PieceNextI->getEndLocation());
2204 
2205  if (s1Start && s2Start && s1Start == s2End && s2Start == s1End) {
2206  const size_t MAX_SHORT_LINE_LENGTH = 80;
2207  Optional<size_t> s1Length = getLengthOnSingleLine(SM, s1Start);
2208  if (s1Length && *s1Length <= MAX_SHORT_LINE_LENGTH) {
2209  Optional<size_t> s2Length = getLengthOnSingleLine(SM, s2Start);
2210  if (s2Length && *s2Length <= MAX_SHORT_LINE_LENGTH) {
2211  Path.erase(I);
2212  I = Path.erase(NextI);
2213  continue;
2214  }
2215  }
2216  }
2217 
2218  ++I;
2219  }
2220 }
2221 
2222 /// \brief Return true if X is contained by Y.
2223 static bool lexicalContains(ParentMap &PM,
2224  const Stmt *X,
2225  const Stmt *Y) {
2226  while (X) {
2227  if (X == Y)
2228  return true;
2229  X = PM.getParent(X);
2230  }
2231  return false;
2232 }
2233 
2234 // Remove short edges on the same line less than 3 columns in difference.
2235 static void removePunyEdges(PathPieces &path,
2236  SourceManager &SM,
2237  ParentMap &PM) {
2238 
2239  bool erased = false;
2240 
2241  for (PathPieces::iterator I = path.begin(), E = path.end(); I != E;
2242  erased ? I : ++I) {
2243 
2244  erased = false;
2245 
2247  dyn_cast<PathDiagnosticControlFlowPiece>(*I);
2248 
2249  if (!PieceI)
2250  continue;
2251 
2252  const Stmt *start = getLocStmt(PieceI->getStartLocation());
2253  const Stmt *end = getLocStmt(PieceI->getEndLocation());
2254 
2255  if (!start || !end)
2256  continue;
2257 
2258  const Stmt *endParent = PM.getParent(end);
2259  if (!endParent)
2260  continue;
2261 
2262  if (isConditionForTerminator(end, endParent))
2263  continue;
2264 
2265  SourceLocation FirstLoc = start->getLocStart();
2266  SourceLocation SecondLoc = end->getLocStart();
2267 
2268  if (!SM.isWrittenInSameFile(FirstLoc, SecondLoc))
2269  continue;
2270  if (SM.isBeforeInTranslationUnit(SecondLoc, FirstLoc))
2271  std::swap(SecondLoc, FirstLoc);
2272 
2273  SourceRange EdgeRange(FirstLoc, SecondLoc);
2274  Optional<size_t> ByteWidth = getLengthOnSingleLine(SM, EdgeRange);
2275 
2276  // If the statements are on different lines, continue.
2277  if (!ByteWidth)
2278  continue;
2279 
2280  const size_t MAX_PUNY_EDGE_LENGTH = 2;
2281  if (*ByteWidth <= MAX_PUNY_EDGE_LENGTH) {
2282  // FIXME: There are enough /bytes/ between the endpoints of the edge, but
2283  // there might not be enough /columns/. A proper user-visible column count
2284  // is probably too expensive, though.
2285  I = path.erase(I);
2286  erased = true;
2287  continue;
2288  }
2289  }
2290 }
2291 
2292 static void removeIdenticalEvents(PathPieces &path) {
2293  for (PathPieces::iterator I = path.begin(), E = path.end(); I != E; ++I) {
2294  PathDiagnosticEventPiece *PieceI =
2295  dyn_cast<PathDiagnosticEventPiece>(*I);
2296 
2297  if (!PieceI)
2298  continue;
2299 
2300  PathPieces::iterator NextI = I; ++NextI;
2301  if (NextI == E)
2302  return;
2303 
2304  PathDiagnosticEventPiece *PieceNextI =
2305  dyn_cast<PathDiagnosticEventPiece>(*NextI);
2306 
2307  if (!PieceNextI)
2308  continue;
2309 
2310  // Erase the second piece if it has the same exact message text.
2311  if (PieceI->getString() == PieceNextI->getString()) {
2312  path.erase(NextI);
2313  }
2314  }
2315 }
2316 
2317 static bool optimizeEdges(PathPieces &path, SourceManager &SM,
2318  OptimizedCallsSet &OCS,
2319  LocationContextMap &LCM) {
2320  bool hasChanges = false;
2321  const LocationContext *LC = LCM[&path];
2322  assert(LC);
2323  ParentMap &PM = LC->getParentMap();
2324 
2325  for (PathPieces::iterator I = path.begin(), E = path.end(); I != E; ) {
2326  // Optimize subpaths.
2327  if (PathDiagnosticCallPiece *CallI = dyn_cast<PathDiagnosticCallPiece>(*I)){
2328  // Record the fact that a call has been optimized so we only do the
2329  // effort once.
2330  if (!OCS.count(CallI)) {
2331  while (optimizeEdges(CallI->path, SM, OCS, LCM)) {}
2332  OCS.insert(CallI);
2333  }
2334  ++I;
2335  continue;
2336  }
2337 
2338  // Pattern match the current piece and its successor.
2340  dyn_cast<PathDiagnosticControlFlowPiece>(*I);
2341 
2342  if (!PieceI) {
2343  ++I;
2344  continue;
2345  }
2346 
2347  const Stmt *s1Start = getLocStmt(PieceI->getStartLocation());
2348  const Stmt *s1End = getLocStmt(PieceI->getEndLocation());
2349  const Stmt *level1 = getStmtParent(s1Start, PM);
2350  const Stmt *level2 = getStmtParent(s1End, PM);
2351 
2352  PathPieces::iterator NextI = I; ++NextI;
2353  if (NextI == E)
2354  break;
2355 
2356  PathDiagnosticControlFlowPiece *PieceNextI =
2357  dyn_cast<PathDiagnosticControlFlowPiece>(*NextI);
2358 
2359  if (!PieceNextI) {
2360  ++I;
2361  continue;
2362  }
2363 
2364  const Stmt *s2Start = getLocStmt(PieceNextI->getStartLocation());
2365  const Stmt *s2End = getLocStmt(PieceNextI->getEndLocation());
2366  const Stmt *level3 = getStmtParent(s2Start, PM);
2367  const Stmt *level4 = getStmtParent(s2End, PM);
2368 
2369  // Rule I.
2370  //
2371  // If we have two consecutive control edges whose end/begin locations
2372  // are at the same level (e.g. statements or top-level expressions within
2373  // a compound statement, or siblings share a single ancestor expression),
2374  // then merge them if they have no interesting intermediate event.
2375  //
2376  // For example:
2377  //
2378  // (1.1 -> 1.2) -> (1.2 -> 1.3) becomes (1.1 -> 1.3) because the common
2379  // parent is '1'. Here 'x.y.z' represents the hierarchy of statements.
2380  //
2381  // NOTE: this will be limited later in cases where we add barriers
2382  // to prevent this optimization.
2383  //
2384  if (level1 && level1 == level2 && level1 == level3 && level1 == level4) {
2385  PieceI->setEndLocation(PieceNextI->getEndLocation());
2386  path.erase(NextI);
2387  hasChanges = true;
2388  continue;
2389  }
2390 
2391  // Rule II.
2392  //
2393  // Eliminate edges between subexpressions and parent expressions
2394  // when the subexpression is consumed.
2395  //
2396  // NOTE: this will be limited later in cases where we add barriers
2397  // to prevent this optimization.
2398  //
2399  if (s1End && s1End == s2Start && level2) {
2400  bool removeEdge = false;
2401  // Remove edges into the increment or initialization of a
2402  // loop that have no interleaving event. This means that
2403  // they aren't interesting.
2404  if (isIncrementOrInitInForLoop(s1End, level2))
2405  removeEdge = true;
2406  // Next only consider edges that are not anchored on
2407  // the condition of a terminator. This are intermediate edges
2408  // that we might want to trim.
2409  else if (!isConditionForTerminator(level2, s1End)) {
2410  // Trim edges on expressions that are consumed by
2411  // the parent expression.
2412  if (isa<Expr>(s1End) && PM.isConsumedExpr(cast<Expr>(s1End))) {
2413  removeEdge = true;
2414  }
2415  // Trim edges where a lexical containment doesn't exist.
2416  // For example:
2417  //
2418  // X -> Y -> Z
2419  //
2420  // If 'Z' lexically contains Y (it is an ancestor) and
2421  // 'X' does not lexically contain Y (it is a descendant OR
2422  // it has no lexical relationship at all) then trim.
2423  //
2424  // This can eliminate edges where we dive into a subexpression
2425  // and then pop back out, etc.
2426  else if (s1Start && s2End &&
2427  lexicalContains(PM, s2Start, s2End) &&
2428  !lexicalContains(PM, s1End, s1Start)) {
2429  removeEdge = true;
2430  }
2431  // Trim edges from a subexpression back to the top level if the
2432  // subexpression is on a different line.
2433  //
2434  // A.1 -> A -> B
2435  // becomes
2436  // A.1 -> B
2437  //
2438  // These edges just look ugly and don't usually add anything.
2439  else if (s1Start && s2End &&
2440  lexicalContains(PM, s1Start, s1End)) {
2441  SourceRange EdgeRange(PieceI->getEndLocation().asLocation(),
2442  PieceI->getStartLocation().asLocation());
2443  if (!getLengthOnSingleLine(SM, EdgeRange).hasValue())
2444  removeEdge = true;
2445  }
2446  }
2447 
2448  if (removeEdge) {
2449  PieceI->setEndLocation(PieceNextI->getEndLocation());
2450  path.erase(NextI);
2451  hasChanges = true;
2452  continue;
2453  }
2454  }
2455 
2456  // Optimize edges for ObjC fast-enumeration loops.
2457  //
2458  // (X -> collection) -> (collection -> element)
2459  //
2460  // becomes:
2461  //
2462  // (X -> element)
2463  if (s1End == s2Start) {
2464  const ObjCForCollectionStmt *FS =
2465  dyn_cast_or_null<ObjCForCollectionStmt>(level3);
2466  if (FS && FS->getCollection()->IgnoreParens() == s2Start &&
2467  s2End == FS->getElement()) {
2468  PieceI->setEndLocation(PieceNextI->getEndLocation());
2469  path.erase(NextI);
2470  hasChanges = true;
2471  continue;
2472  }
2473  }
2474 
2475  // No changes at this index? Move to the next one.
2476  ++I;
2477  }
2478 
2479  if (!hasChanges) {
2480  // Adjust edges into subexpressions to make them more uniform
2481  // and aesthetically pleasing.
2482  addContextEdges(path, SM, PM, LC);
2483  // Remove "cyclical" edges that include one or more context edges.
2484  removeContextCycles(path, SM, PM);
2485  // Hoist edges originating from branch conditions to branches
2486  // for simple branches.
2487  simplifySimpleBranches(path);
2488  // Remove any puny edges left over after primary optimization pass.
2489  removePunyEdges(path, SM, PM);
2490  // Remove identical events.
2491  removeIdenticalEvents(path);
2492  }
2493 
2494  return hasChanges;
2495 }
2496 
2497 /// Drop the very first edge in a path, which should be a function entry edge.
2498 ///
2499 /// If the first edge is not a function entry edge (say, because the first
2500 /// statement had an invalid source location), this function does nothing.
2501 // FIXME: We should just generate invalid edges anyway and have the optimizer
2502 // deal with them.
2504  LocationContextMap &LCM,
2505  SourceManager &SM) {
2506  const PathDiagnosticControlFlowPiece *FirstEdge =
2507  dyn_cast<PathDiagnosticControlFlowPiece>(Path.front());
2508  if (!FirstEdge)
2509  return;
2510 
2511  const Decl *D = LCM[&Path]->getDecl();
2513  if (FirstEdge->getStartLocation() != EntryLoc)
2514  return;
2515 
2516  Path.pop_front();
2517 }
2518 
2519 
2520 //===----------------------------------------------------------------------===//
2521 // Methods for BugType and subclasses.
2522 //===----------------------------------------------------------------------===//
2523 void BugType::anchor() { }
2524 
2526 
2527 void BuiltinBug::anchor() {}
2528 
2529 //===----------------------------------------------------------------------===//
2530 // Methods for BugReport and subclasses.
2531 //===----------------------------------------------------------------------===//
2532 
2533 void BugReport::NodeResolver::anchor() {}
2534 
2535 void BugReport::addVisitor(std::unique_ptr<BugReporterVisitor> visitor) {
2536  if (!visitor)
2537  return;
2538 
2539  llvm::FoldingSetNodeID ID;
2540  visitor->Profile(ID);
2541  void *InsertPos;
2542 
2543  if (CallbacksSet.FindNodeOrInsertPos(ID, InsertPos))
2544  return;
2545 
2546  CallbacksSet.InsertNode(visitor.get(), InsertPos);
2547  Callbacks.push_back(std::move(visitor));
2549 }
2550 
2552  while (!interestingSymbols.empty()) {
2553  popInterestingSymbolsAndRegions();
2554  }
2555 }
2556 
2558  if (DeclWithIssue)
2559  return DeclWithIssue;
2560 
2561  const ExplodedNode *N = getErrorNode();
2562  if (!N)
2563  return nullptr;
2564 
2565  const LocationContext *LC = N->getLocationContext();
2566  return LC->getCurrentStackFrame()->getDecl();
2567 }
2568 
2569 void BugReport::Profile(llvm::FoldingSetNodeID& hash) const {
2570  hash.AddPointer(&BT);
2571  hash.AddString(Description);
2573  if (UL.isValid()) {
2574  UL.Profile(hash);
2575  } else if (Location.isValid()) {
2576  Location.Profile(hash);
2577  } else {
2578  assert(ErrorNode);
2579  hash.AddPointer(GetCurrentOrPreviousStmt(ErrorNode));
2580  }
2581 
2583  Ranges.begin(), E = Ranges.end(); I != E; ++I) {
2584  const SourceRange range = *I;
2585  if (!range.isValid())
2586  continue;
2587  hash.AddInteger(range.getBegin().getRawEncoding());
2588  hash.AddInteger(range.getEnd().getRawEncoding());
2589  }
2590 }
2591 
2593  if (!sym)
2594  return;
2595 
2596  // If the symbol wasn't already in our set, note a configuration change.
2597  if (getInterestingSymbols().insert(sym).second)
2599 
2600  if (const SymbolMetadata *meta = dyn_cast<SymbolMetadata>(sym))
2601  getInterestingRegions().insert(meta->getRegion());
2602 }
2603 
2605  if (!R)
2606  return;
2607 
2608  // If the base region wasn't already in our set, note a configuration change.
2609  R = R->getBaseRegion();
2610  if (getInterestingRegions().insert(R).second)
2612 
2613  if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R))
2614  getInterestingSymbols().insert(SR->getSymbol());
2615 }
2616 
2620 }
2621 
2623  if (!LC)
2624  return;
2625  InterestingLocationContexts.insert(LC);
2626 }
2627 
2629  return isInteresting(V.getAsRegion()) || isInteresting(V.getAsSymbol());
2630 }
2631 
2633  if (!sym)
2634  return false;
2635  // We don't currently consider metadata symbols to be interesting
2636  // even if we know their region is interesting. Is that correct behavior?
2637  return getInterestingSymbols().count(sym);
2638 }
2639 
2641  if (!R)
2642  return false;
2643  R = R->getBaseRegion();
2644  bool b = getInterestingRegions().count(R);
2645  if (b)
2646  return true;
2647  if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R))
2648  return getInterestingSymbols().count(SR->getSymbol());
2649  return false;
2650 }
2651 
2653  if (!LC)
2654  return false;
2655  return InterestingLocationContexts.count(LC);
2656 }
2657 
2658 void BugReport::lazyInitializeInterestingSets() {
2659  if (interestingSymbols.empty()) {
2660  interestingSymbols.push_back(new Symbols());
2661  interestingRegions.push_back(new Regions());
2662  }
2663 }
2664 
2665 BugReport::Symbols &BugReport::getInterestingSymbols() {
2666  lazyInitializeInterestingSets();
2667  return *interestingSymbols.back();
2668 }
2669 
2670 BugReport::Regions &BugReport::getInterestingRegions() {
2671  lazyInitializeInterestingSets();
2672  return *interestingRegions.back();
2673 }
2674 
2675 void BugReport::pushInterestingSymbolsAndRegions() {
2676  interestingSymbols.push_back(new Symbols(getInterestingSymbols()));
2677  interestingRegions.push_back(new Regions(getInterestingRegions()));
2678 }
2679 
2680 void BugReport::popInterestingSymbolsAndRegions() {
2681  delete interestingSymbols.pop_back_val();
2682  delete interestingRegions.pop_back_val();
2683 }
2684 
2685 const Stmt *BugReport::getStmt() const {
2686  if (!ErrorNode)
2687  return nullptr;
2688 
2689  ProgramPoint ProgP = ErrorNode->getLocation();
2690  const Stmt *S = nullptr;
2691 
2692  if (Optional<BlockEntrance> BE = ProgP.getAs<BlockEntrance>()) {
2693  CFGBlock &Exit = ProgP.getLocationContext()->getCFG()->getExit();
2694  if (BE->getBlock() == &Exit)
2696  }
2697  if (!S)
2699 
2700  return S;
2701 }
2702 
2703 llvm::iterator_range<BugReport::ranges_iterator> BugReport::getRanges() {
2704  // If no custom ranges, add the range of the statement corresponding to
2705  // the error node.
2706  if (Ranges.empty()) {
2707  if (const Expr *E = dyn_cast_or_null<Expr>(getStmt()))
2708  addRange(E->getSourceRange());
2709  else
2710  return llvm::make_range(ranges_iterator(), ranges_iterator());
2711  }
2712 
2713  // User-specified absence of range info.
2714  if (Ranges.size() == 1 && !Ranges.begin()->isValid())
2715  return llvm::make_range(ranges_iterator(), ranges_iterator());
2716 
2717  return llvm::iterator_range<BugReport::ranges_iterator>(Ranges.begin(),
2718  Ranges.end());
2719 }
2720 
2722  if (ErrorNode) {
2723  assert(!Location.isValid() &&
2724  "Either Location or ErrorNode should be specified but not both.");
2726  }
2727 
2728  assert(Location.isValid());
2729  return Location;
2730 }
2731 
2732 //===----------------------------------------------------------------------===//
2733 // Methods for BugReporter and subclasses.
2734 //===----------------------------------------------------------------------===//
2735 
2739 
2740 ExplodedGraph &GRBugReporter::getGraph() { return Eng.getGraph(); }
2741 
2743 GRBugReporter::getStateManager() { return Eng.getStateManager(); }
2744 
2746  FlushReports();
2747 
2748  // Free the bug reports we are tracking.
2749  typedef std::vector<BugReportEquivClass *> ContTy;
2750  for (ContTy::iterator I = EQClassesVector.begin(), E = EQClassesVector.end();
2751  I != E; ++I) {
2752  delete *I;
2753  }
2754 }
2755 
2757  if (BugTypes.isEmpty())
2758  return;
2759 
2760  // First flush the warnings for each BugType. This may end up creating new
2761  // warnings and new BugTypes.
2762  // FIXME: Only NSErrorChecker needs BugType's FlushReports.
2763  // Turn NSErrorChecker into a proper checker and remove this.
2764  SmallVector<const BugType *, 16> bugTypes(BugTypes.begin(), BugTypes.end());
2766  I = bugTypes.begin(), E = bugTypes.end(); I != E; ++I)
2767  const_cast<BugType*>(*I)->FlushReports(*this);
2768 
2769  // We need to flush reports in deterministic order to ensure the order
2770  // of the reports is consistent between runs.
2771  typedef std::vector<BugReportEquivClass *> ContVecTy;
2772  for (ContVecTy::iterator EI=EQClassesVector.begin(), EE=EQClassesVector.end();
2773  EI != EE; ++EI){
2774  BugReportEquivClass& EQ = **EI;
2775  FlushReport(EQ);
2776  }
2777 
2778  // BugReporter owns and deletes only BugTypes created implicitly through
2779  // EmitBasicReport.
2780  // FIXME: There are leaks from checkers that assume that the BugTypes they
2781  // create will be destroyed by the BugReporter.
2782  llvm::DeleteContainerSeconds(StrBugTypes);
2783 
2784  // Remove all references to the BugType objects.
2785  BugTypes = F.getEmptySet();
2786 }
2787 
2788 //===----------------------------------------------------------------------===//
2789 // PathDiagnostics generation.
2790 //===----------------------------------------------------------------------===//
2791 
2792 namespace {
2793 /// A wrapper around a report graph, which contains only a single path, and its
2794 /// node maps.
2795 class ReportGraph {
2796 public:
2797  InterExplodedGraphMap BackMap;
2798  std::unique_ptr<ExplodedGraph> Graph;
2799  const ExplodedNode *ErrorNode;
2800  size_t Index;
2801 };
2802 
2803 /// A wrapper around a trimmed graph and its node maps.
2804 class TrimmedGraph {
2805  InterExplodedGraphMap InverseMap;
2806 
2807  typedef llvm::DenseMap<const ExplodedNode *, unsigned> PriorityMapTy;
2808  PriorityMapTy PriorityMap;
2809 
2810  typedef std::pair<const ExplodedNode *, size_t> NodeIndexPair;
2811  SmallVector<NodeIndexPair, 32> ReportNodes;
2812 
2813  std::unique_ptr<ExplodedGraph> G;
2814 
2815  /// A helper class for sorting ExplodedNodes by priority.
2816  template <bool Descending>
2817  class PriorityCompare {
2818  const PriorityMapTy &PriorityMap;
2819 
2820  public:
2821  PriorityCompare(const PriorityMapTy &M) : PriorityMap(M) {}
2822 
2823  bool operator()(const ExplodedNode *LHS, const ExplodedNode *RHS) const {
2824  PriorityMapTy::const_iterator LI = PriorityMap.find(LHS);
2825  PriorityMapTy::const_iterator RI = PriorityMap.find(RHS);
2826  PriorityMapTy::const_iterator E = PriorityMap.end();
2827 
2828  if (LI == E)
2829  return Descending;
2830  if (RI == E)
2831  return !Descending;
2832 
2833  return Descending ? LI->second > RI->second
2834  : LI->second < RI->second;
2835  }
2836 
2837  bool operator()(const NodeIndexPair &LHS, const NodeIndexPair &RHS) const {
2838  return (*this)(LHS.first, RHS.first);
2839  }
2840  };
2841 
2842 public:
2843  TrimmedGraph(const ExplodedGraph *OriginalGraph,
2845 
2846  bool popNextReportGraph(ReportGraph &GraphWrapper);
2847 };
2848 }
2849 
2850 TrimmedGraph::TrimmedGraph(const ExplodedGraph *OriginalGraph,
2852  // The trimmed graph is created in the body of the constructor to ensure
2853  // that the DenseMaps have been initialized already.
2854  InterExplodedGraphMap ForwardMap;
2855  G = OriginalGraph->trim(Nodes, &ForwardMap, &InverseMap);
2856 
2857  // Find the (first) error node in the trimmed graph. We just need to consult
2858  // the node map which maps from nodes in the original graph to nodes
2859  // in the new graph.
2860  llvm::SmallPtrSet<const ExplodedNode *, 32> RemainingNodes;
2861 
2862  for (unsigned i = 0, count = Nodes.size(); i < count; ++i) {
2863  if (const ExplodedNode *NewNode = ForwardMap.lookup(Nodes[i])) {
2864  ReportNodes.push_back(std::make_pair(NewNode, i));
2865  RemainingNodes.insert(NewNode);
2866  }
2867  }
2868 
2869  assert(!RemainingNodes.empty() && "No error node found in the trimmed graph");
2870 
2871  // Perform a forward BFS to find all the shortest paths.
2872  std::queue<const ExplodedNode *> WS;
2873 
2874  assert(G->num_roots() == 1);
2875  WS.push(*G->roots_begin());
2876  unsigned Priority = 0;
2877 
2878  while (!WS.empty()) {
2879  const ExplodedNode *Node = WS.front();
2880  WS.pop();
2881 
2882  PriorityMapTy::iterator PriorityEntry;
2883  bool IsNew;
2884  std::tie(PriorityEntry, IsNew) =
2885  PriorityMap.insert(std::make_pair(Node, Priority));
2886  ++Priority;
2887 
2888  if (!IsNew) {
2889  assert(PriorityEntry->second <= Priority);
2890  continue;
2891  }
2892 
2893  if (RemainingNodes.erase(Node))
2894  if (RemainingNodes.empty())
2895  break;
2896 
2898  E = Node->succ_end();
2899  I != E; ++I)
2900  WS.push(*I);
2901  }
2902 
2903  // Sort the error paths from longest to shortest.
2904  std::sort(ReportNodes.begin(), ReportNodes.end(),
2905  PriorityCompare<true>(PriorityMap));
2906 }
2907 
2908 bool TrimmedGraph::popNextReportGraph(ReportGraph &GraphWrapper) {
2909  if (ReportNodes.empty())
2910  return false;
2911 
2912  const ExplodedNode *OrigN;
2913  std::tie(OrigN, GraphWrapper.Index) = ReportNodes.pop_back_val();
2914  assert(PriorityMap.find(OrigN) != PriorityMap.end() &&
2915  "error node not accessible from root");
2916 
2917  // Create a new graph with a single path. This is the graph
2918  // that will be returned to the caller.
2919  auto GNew = llvm::make_unique<ExplodedGraph>();
2920  GraphWrapper.BackMap.clear();
2921 
2922  // Now walk from the error node up the BFS path, always taking the
2923  // predeccessor with the lowest number.
2924  ExplodedNode *Succ = nullptr;
2925  while (true) {
2926  // Create the equivalent node in the new graph with the same state
2927  // and location.
2928  ExplodedNode *NewN = GNew->getNode(OrigN->getLocation(), OrigN->getState(),
2929  OrigN->isSink());
2930 
2931  // Store the mapping to the original node.
2932  InterExplodedGraphMap::const_iterator IMitr = InverseMap.find(OrigN);
2933  assert(IMitr != InverseMap.end() && "No mapping to original node.");
2934  GraphWrapper.BackMap[NewN] = IMitr->second;
2935 
2936  // Link up the new node with the previous node.
2937  if (Succ)
2938  Succ->addPredecessor(NewN, *GNew);
2939  else
2940  GraphWrapper.ErrorNode = NewN;
2941 
2942  Succ = NewN;
2943 
2944  // Are we at the final node?
2945  if (OrigN->pred_empty()) {
2946  GNew->addRoot(NewN);
2947  break;
2948  }
2949 
2950  // Find the next predeccessor node. We choose the node that is marked
2951  // with the lowest BFS number.
2952  OrigN = *std::min_element(OrigN->pred_begin(), OrigN->pred_end(),
2953  PriorityCompare<false>(PriorityMap));
2954  }
2955 
2956  GraphWrapper.Graph = std::move(GNew);
2957 
2958  return true;
2959 }
2960 
2961 
2962 /// CompactPathDiagnostic - This function postprocesses a PathDiagnostic object
2963 /// and collapses PathDiagosticPieces that are expanded by macros.
2964 static void CompactPathDiagnostic(PathPieces &path, const SourceManager& SM) {
2965  typedef std::vector<std::pair<IntrusiveRefCntPtr<PathDiagnosticMacroPiece>,
2966  SourceLocation> > MacroStackTy;
2967 
2968  typedef std::vector<IntrusiveRefCntPtr<PathDiagnosticPiece> >
2969  PiecesTy;
2970 
2971  MacroStackTy MacroStack;
2972  PiecesTy Pieces;
2973 
2974  for (PathPieces::const_iterator I = path.begin(), E = path.end();
2975  I!=E; ++I) {
2976 
2977  PathDiagnosticPiece *piece = I->get();
2978 
2979  // Recursively compact calls.
2980  if (PathDiagnosticCallPiece *call=dyn_cast<PathDiagnosticCallPiece>(piece)){
2981  CompactPathDiagnostic(call->path, SM);
2982  }
2983 
2984  // Get the location of the PathDiagnosticPiece.
2985  const FullSourceLoc Loc = piece->getLocation().asLocation();
2986 
2987  // Determine the instantiation location, which is the location we group
2988  // related PathDiagnosticPieces.
2989  SourceLocation InstantiationLoc = Loc.isMacroID() ?
2990  SM.getExpansionLoc(Loc) :
2991  SourceLocation();
2992 
2993  if (Loc.isFileID()) {
2994  MacroStack.clear();
2995  Pieces.push_back(piece);
2996  continue;
2997  }
2998 
2999  assert(Loc.isMacroID());
3000 
3001  // Is the PathDiagnosticPiece within the same macro group?
3002  if (!MacroStack.empty() && InstantiationLoc == MacroStack.back().second) {
3003  MacroStack.back().first->subPieces.push_back(piece);
3004  continue;
3005  }
3006 
3007  // We aren't in the same group. Are we descending into a new macro
3008  // or are part of an old one?
3010 
3011  SourceLocation ParentInstantiationLoc = InstantiationLoc.isMacroID() ?
3012  SM.getExpansionLoc(Loc) :
3013  SourceLocation();
3014 
3015  // Walk the entire macro stack.
3016  while (!MacroStack.empty()) {
3017  if (InstantiationLoc == MacroStack.back().second) {
3018  MacroGroup = MacroStack.back().first;
3019  break;
3020  }
3021 
3022  if (ParentInstantiationLoc == MacroStack.back().second) {
3023  MacroGroup = MacroStack.back().first;
3024  break;
3025  }
3026 
3027  MacroStack.pop_back();
3028  }
3029 
3030  if (!MacroGroup || ParentInstantiationLoc == MacroStack.back().second) {
3031  // Create a new macro group and add it to the stack.
3032  PathDiagnosticMacroPiece *NewGroup =
3035 
3036  if (MacroGroup)
3037  MacroGroup->subPieces.push_back(NewGroup);
3038  else {
3039  assert(InstantiationLoc.isFileID());
3040  Pieces.push_back(NewGroup);
3041  }
3042 
3043  MacroGroup = NewGroup;
3044  MacroStack.push_back(std::make_pair(MacroGroup, InstantiationLoc));
3045  }
3046 
3047  // Finally, add the PathDiagnosticPiece to the group.
3048  MacroGroup->subPieces.push_back(piece);
3049  }
3050 
3051  // Now take the pieces and construct a new PathDiagnostic.
3052  path.clear();
3053 
3054  path.insert(path.end(), Pieces.begin(), Pieces.end());
3055 }
3056 
3059  ArrayRef<BugReport *> &bugReports) {
3060  assert(!bugReports.empty());
3061 
3062  bool HasValid = false;
3063  bool HasInvalid = false;
3065  for (ArrayRef<BugReport*>::iterator I = bugReports.begin(),
3066  E = bugReports.end(); I != E; ++I) {
3067  if ((*I)->isValid()) {
3068  HasValid = true;
3069  errorNodes.push_back((*I)->getErrorNode());
3070  } else {
3071  // Keep the errorNodes list in sync with the bugReports list.
3072  HasInvalid = true;
3073  errorNodes.push_back(nullptr);
3074  }
3075  }
3076 
3077  // If all the reports have been marked invalid by a previous path generation,
3078  // we're done.
3079  if (!HasValid)
3080  return false;
3081 
3082  typedef PathDiagnosticConsumer::PathGenerationScheme PathGenerationScheme;
3083  PathGenerationScheme ActiveScheme = PC.getGenerationScheme();
3084 
3085  if (ActiveScheme == PathDiagnosticConsumer::Extensive) {
3086  AnalyzerOptions &options = getAnalyzerOptions();
3087  if (options.getBooleanOption("path-diagnostics-alternate", true)) {
3089  }
3090  }
3091 
3092  TrimmedGraph TrimG(&getGraph(), errorNodes);
3093  ReportGraph ErrorGraph;
3094 
3095  while (TrimG.popNextReportGraph(ErrorGraph)) {
3096  // Find the BugReport with the original location.
3097  assert(ErrorGraph.Index < bugReports.size());
3098  BugReport *R = bugReports[ErrorGraph.Index];
3099  assert(R && "No original report found for sliced graph.");
3100  assert(R->isValid() && "Report selected by trimmed graph marked invalid.");
3101 
3102  // Start building the path diagnostic...
3103  PathDiagnosticBuilder PDB(*this, R, ErrorGraph.BackMap, &PC);
3104  const ExplodedNode *N = ErrorGraph.ErrorNode;
3105 
3106  // Register additional node visitors.
3107  R->addVisitor(llvm::make_unique<NilReceiverBRVisitor>());
3108  R->addVisitor(llvm::make_unique<ConditionBRVisitor>());
3109  R->addVisitor(llvm::make_unique<LikelyFalsePositiveSuppressionBRVisitor>());
3110 
3111  BugReport::VisitorList visitors;
3112  unsigned origReportConfigToken, finalReportConfigToken;
3113  LocationContextMap LCM;
3114 
3115  // While generating diagnostics, it's possible the visitors will decide
3116  // new symbols and regions are interesting, or add other visitors based on
3117  // the information they find. If they do, we need to regenerate the path
3118  // based on our new report configuration.
3119  do {
3120  // Get a clean copy of all the visitors.
3121  for (BugReport::visitor_iterator I = R->visitor_begin(),
3122  E = R->visitor_end(); I != E; ++I)
3123  visitors.push_back((*I)->clone());
3124 
3125  // Clear out the active path from any previous work.
3126  PD.resetPath();
3127  origReportConfigToken = R->getConfigurationChangeToken();
3128 
3129  // Generate the very last diagnostic piece - the piece is visible before
3130  // the trace is expanded.
3131  std::unique_ptr<PathDiagnosticPiece> LastPiece;
3132  for (BugReport::visitor_iterator I = visitors.begin(), E = visitors.end();
3133  I != E; ++I) {
3134  if (std::unique_ptr<PathDiagnosticPiece> Piece =
3135  (*I)->getEndPath(PDB, N, *R)) {
3136  assert (!LastPiece &&
3137  "There can only be one final piece in a diagnostic.");
3138  LastPiece = std::move(Piece);
3139  }
3140  }
3141 
3142  if (ActiveScheme != PathDiagnosticConsumer::None) {
3143  if (!LastPiece)
3144  LastPiece = BugReporterVisitor::getDefaultEndPath(PDB, N, *R);
3145  assert(LastPiece);
3146  PD.setEndOfPath(std::move(LastPiece));
3147  }
3148 
3149  // Make sure we get a clean location context map so we don't
3150  // hold onto old mappings.
3151  LCM.clear();
3152 
3153  switch (ActiveScheme) {
3155  GenerateAlternateExtensivePathDiagnostic(PD, PDB, N, LCM, visitors);
3156  break;
3158  GenerateExtensivePathDiagnostic(PD, PDB, N, LCM, visitors);
3159  break;
3161  GenerateMinimalPathDiagnostic(PD, PDB, N, LCM, visitors);
3162  break;
3164  GenerateVisitorsOnlyPathDiagnostic(PD, PDB, N, visitors);
3165  break;
3166  }
3167 
3168  // Clean up the visitors we used.
3169  visitors.clear();
3170 
3171  // Did anything change while generating this path?
3172  finalReportConfigToken = R->getConfigurationChangeToken();
3173  } while (finalReportConfigToken != origReportConfigToken);
3174 
3175  if (!R->isValid())
3176  continue;
3177 
3178  // Finally, prune the diagnostic path of uninteresting stuff.
3179  if (!PD.path.empty()) {
3180  if (R->shouldPrunePath() && getAnalyzerOptions().shouldPrunePaths()) {
3181  bool stillHasNotes = removeUnneededCalls(PD.getMutablePieces(), R, LCM);
3182  assert(stillHasNotes);
3183  (void)stillHasNotes;
3184  }
3185 
3186  // Redirect all call pieces to have valid locations.
3189 
3190  if (ActiveScheme == PathDiagnosticConsumer::AlternateExtensive) {
3191  SourceManager &SM = getSourceManager();
3192 
3193  // Reduce the number of edges from a very conservative set
3194  // to an aesthetically pleasing subset that conveys the
3195  // necessary information.
3196  OptimizedCallsSet OCS;
3197  while (optimizeEdges(PD.getMutablePieces(), SM, OCS, LCM)) {}
3198 
3199  // Drop the very first function-entry edge. It's not really necessary
3200  // for top-level functions.
3202  }
3203 
3204  // Remove messages that are basically the same, and edges that may not
3205  // make sense.
3206  // We have to do this after edge optimization in the Extensive mode.
3209  }
3210 
3211  // We found a report and didn't suppress it.
3212  return true;
3213  }
3214 
3215  // We suppressed all the reports in this equivalence class.
3216  assert(!HasInvalid && "Inconsistent suppression");
3217  (void)HasInvalid;
3218  return false;
3219 }
3220 
3222  BugTypes = F.add(BugTypes, BT);
3223 }
3224 
3225 void BugReporter::emitReport(std::unique_ptr<BugReport> R) {
3226  if (const ExplodedNode *E = R->getErrorNode()) {
3227  const AnalysisDeclContext *DeclCtx =
3228  E->getLocationContext()->getAnalysisDeclContext();
3229  // The source of autosynthesized body can be handcrafted AST or a model
3230  // file. The locations from handcrafted ASTs have no valid source locations
3231  // and have to be discarded. Locations from model files should be preserved
3232  // for processing and reporting.
3233  if (DeclCtx->isBodyAutosynthesized() &&
3235  return;
3236  }
3237 
3238  bool ValidSourceLoc = R->getLocation(getSourceManager()).isValid();
3239  assert(ValidSourceLoc);
3240  // If we mess up in a release build, we'd still prefer to just drop the bug
3241  // instead of trying to go on.
3242  if (!ValidSourceLoc)
3243  return;
3244 
3245  // Compute the bug report's hash to determine its equivalence class.
3246  llvm::FoldingSetNodeID ID;
3247  R->Profile(ID);
3248 
3249  // Lookup the equivance class. If there isn't one, create it.
3250  BugType& BT = R->getBugType();
3251  Register(&BT);
3252  void *InsertPos;
3253  BugReportEquivClass* EQ = EQClasses.FindNodeOrInsertPos(ID, InsertPos);
3254 
3255  if (!EQ) {
3256  EQ = new BugReportEquivClass(std::move(R));
3257  EQClasses.InsertNode(EQ, InsertPos);
3258  EQClassesVector.push_back(EQ);
3259  } else
3260  EQ->AddReport(std::move(R));
3261 }
3262 
3263 
3264 //===----------------------------------------------------------------------===//
3265 // Emitting reports in equivalence classes.
3266 //===----------------------------------------------------------------------===//
3267 
3268 namespace {
3269 struct FRIEC_WLItem {
3270  const ExplodedNode *N;
3272 
3273  FRIEC_WLItem(const ExplodedNode *n)
3274  : N(n), I(N->succ_begin()), E(N->succ_end()) {}
3275 };
3276 }
3277 
3278 static BugReport *
3280  SmallVectorImpl<BugReport*> &bugReports) {
3281 
3282  BugReportEquivClass::iterator I = EQ.begin(), E = EQ.end();
3283  assert(I != E);
3284  BugType& BT = I->getBugType();
3285 
3286  // If we don't need to suppress any of the nodes because they are
3287  // post-dominated by a sink, simply add all the nodes in the equivalence class
3288  // to 'Nodes'. Any of the reports will serve as a "representative" report.
3289  if (!BT.isSuppressOnSink()) {
3290  BugReport *R = I;
3291  for (BugReportEquivClass::iterator I=EQ.begin(), E=EQ.end(); I!=E; ++I) {
3292  const ExplodedNode *N = I->getErrorNode();
3293  if (N) {
3294  R = I;
3295  bugReports.push_back(R);
3296  }
3297  }
3298  return R;
3299  }
3300 
3301  // For bug reports that should be suppressed when all paths are post-dominated
3302  // by a sink node, iterate through the reports in the equivalence class
3303  // until we find one that isn't post-dominated (if one exists). We use a
3304  // DFS traversal of the ExplodedGraph to find a non-sink node. We could write
3305  // this as a recursive function, but we don't want to risk blowing out the
3306  // stack for very long paths.
3307  BugReport *exampleReport = nullptr;
3308 
3309  for (; I != E; ++I) {
3310  const ExplodedNode *errorNode = I->getErrorNode();
3311 
3312  if (!errorNode)
3313  continue;
3314  if (errorNode->isSink()) {
3315  llvm_unreachable(
3316  "BugType::isSuppressSink() should not be 'true' for sink end nodes");
3317  }
3318  // No successors? By definition this nodes isn't post-dominated by a sink.
3319  if (errorNode->succ_empty()) {
3320  bugReports.push_back(I);
3321  if (!exampleReport)
3322  exampleReport = I;
3323  continue;
3324  }
3325 
3326  // At this point we know that 'N' is not a sink and it has at least one
3327  // successor. Use a DFS worklist to find a non-sink end-of-path node.
3328  typedef FRIEC_WLItem WLItem;
3329  typedef SmallVector<WLItem, 10> DFSWorkList;
3330  llvm::DenseMap<const ExplodedNode *, unsigned> Visited;
3331 
3332  DFSWorkList WL;
3333  WL.push_back(errorNode);
3334  Visited[errorNode] = 1;
3335 
3336  while (!WL.empty()) {
3337  WLItem &WI = WL.back();
3338  assert(!WI.N->succ_empty());
3339 
3340  for (; WI.I != WI.E; ++WI.I) {
3341  const ExplodedNode *Succ = *WI.I;
3342  // End-of-path node?
3343  if (Succ->succ_empty()) {
3344  // If we found an end-of-path node that is not a sink.
3345  if (!Succ->isSink()) {
3346  bugReports.push_back(I);
3347  if (!exampleReport)
3348  exampleReport = I;
3349  WL.clear();
3350  break;
3351  }
3352  // Found a sink? Continue on to the next successor.
3353  continue;
3354  }
3355  // Mark the successor as visited. If it hasn't been explored,
3356  // enqueue it to the DFS worklist.
3357  unsigned &mark = Visited[Succ];
3358  if (!mark) {
3359  mark = 1;
3360  WL.push_back(Succ);
3361  break;
3362  }
3363  }
3364 
3365  // The worklist may have been cleared at this point. First
3366  // check if it is empty before checking the last item.
3367  if (!WL.empty() && &WL.back() == &WI)
3368  WL.pop_back();
3369  }
3370  }
3371 
3372  // ExampleReport will be NULL if all the nodes in the equivalence class
3373  // were post-dominated by sinks.
3374  return exampleReport;
3375 }
3376 
3377 void BugReporter::FlushReport(BugReportEquivClass& EQ) {
3378  SmallVector<BugReport*, 10> bugReports;
3379  BugReport *exampleReport = FindReportInEquivalenceClass(EQ, bugReports);
3380  if (exampleReport) {
3381  for (PathDiagnosticConsumer *PDC : getPathDiagnosticConsumers()) {
3382  FlushReport(exampleReport, *PDC, bugReports);
3383  }
3384  }
3385 }
3386 
3387 void BugReporter::FlushReport(BugReport *exampleReport,
3389  ArrayRef<BugReport*> bugReports) {
3390 
3391  // FIXME: Make sure we use the 'R' for the path that was actually used.
3392  // Probably doesn't make a difference in practice.
3393  BugType& BT = exampleReport->getBugType();
3394 
3395  std::unique_ptr<PathDiagnostic> D(new PathDiagnostic(
3396  exampleReport->getBugType().getCheckName(),
3397  exampleReport->getDeclWithIssue(), exampleReport->getBugType().getName(),
3398  exampleReport->getDescription(),
3399  exampleReport->getShortDescription(/*Fallback=*/false), BT.getCategory(),
3400  exampleReport->getUniqueingLocation(),
3401  exampleReport->getUniqueingDecl()));
3402 
3403  MaxBugClassSize = std::max(bugReports.size(),
3404  static_cast<size_t>(MaxBugClassSize));
3405 
3406  // Generate the full path diagnostic, using the generation scheme
3407  // specified by the PathDiagnosticConsumer. Note that we have to generate
3408  // path diagnostics even for consumers which do not support paths, because
3409  // the BugReporterVisitors may mark this bug as a false positive.
3410  if (!bugReports.empty())
3411  if (!generatePathDiagnostic(*D.get(), PD, bugReports))
3412  return;
3413 
3414  MaxValidBugClassSize = std::max(bugReports.size(),
3415  static_cast<size_t>(MaxValidBugClassSize));
3416 
3417  // Examine the report and see if the last piece is in a header. Reset the
3418  // report location to the last piece in the main source file.
3419  AnalyzerOptions& Opts = getAnalyzerOptions();
3420  if (Opts.shouldReportIssuesInMainSourceFile() && !Opts.AnalyzeAll)
3421  D->resetDiagnosticLocationToMainFile();
3422 
3423  // If the path is empty, generate a single step path with the location
3424  // of the issue.
3425  if (D->path.empty()) {
3426  PathDiagnosticLocation L = exampleReport->getLocation(getSourceManager());
3427  auto piece = llvm::make_unique<PathDiagnosticEventPiece>(
3428  L, exampleReport->getDescription());
3429  for (const SourceRange &Range : exampleReport->getRanges())
3430  piece->addRange(Range);
3431  D->setEndOfPath(std::move(piece));
3432  }
3433 
3434  // Get the meta data.
3435  const BugReport::ExtraTextList &Meta = exampleReport->getExtraText();
3436  for (BugReport::ExtraTextList::const_iterator i = Meta.begin(),
3437  e = Meta.end(); i != e; ++i) {
3438  D->addMeta(*i);
3439  }
3440 
3441  PD.HandlePathDiagnostic(std::move(D));
3442 }
3443 
3445  const CheckerBase *Checker,
3446  StringRef Name, StringRef Category,
3447  StringRef Str, PathDiagnosticLocation Loc,
3449  EmitBasicReport(DeclWithIssue, Checker->getCheckName(), Name, Category, Str,
3450  Loc, Ranges);
3451 }
3454  StringRef name, StringRef category,
3455  StringRef str, PathDiagnosticLocation Loc,
3457 
3458  // 'BT' is owned by BugReporter.
3459  BugType *BT = getBugTypeForName(CheckName, name, category);
3460  auto R = llvm::make_unique<BugReport>(*BT, str, Loc);
3461  R->setDeclWithIssue(DeclWithIssue);
3462  for (ArrayRef<SourceRange>::iterator I = Ranges.begin(), E = Ranges.end();
3463  I != E; ++I)
3464  R->addRange(*I);
3465  emitReport(std::move(R));
3466 }
3467 
3468 BugType *BugReporter::getBugTypeForName(CheckName CheckName, StringRef name,
3469  StringRef category) {
3470  SmallString<136> fullDesc;
3471  llvm::raw_svector_ostream(fullDesc) << CheckName.getName() << ":" << name
3472  << ":" << category;
3473  BugType *&BT = StrBugTypes[fullDesc];
3474  if (!BT)
3475  BT = new BugType(CheckName, name, category);
3476  return BT;
3477 }
3478 
3479 LLVM_DUMP_METHOD void PathPieces::dump() const {
3480  unsigned index = 0;
3481  for (PathPieces::const_iterator I = begin(), E = end(); I != E; ++I) {
3482  llvm::errs() << "[" << index++ << "] ";
3483  (*I)->dump();
3484  llvm::errs() << "\n";
3485  }
3486 }
3487 
3489  llvm::errs() << "CALL\n--------------\n";
3490 
3491  if (const Stmt *SLoc = getLocStmt(getLocation()))
3492  SLoc->dump();
3493  else if (const NamedDecl *ND = dyn_cast<NamedDecl>(getCallee()))
3494  llvm::errs() << *ND << "\n";
3495  else
3496  getLocation().dump();
3497 }
3498 
3500  llvm::errs() << "EVENT\n--------------\n";
3501  llvm::errs() << getString() << "\n";
3502  llvm::errs() << " ---- at ----\n";
3503  getLocation().dump();
3504 }
3505 
3507  llvm::errs() << "CONTROL\n--------------\n";
3508  getStartLocation().dump();
3509  llvm::errs() << " ---- to ----\n";
3510  getEndLocation().dump();
3511 }
3512 
3514  llvm::errs() << "MACRO\n--------------\n";
3515  // FIXME: Print which macro is being invoked.
3516 }
3517 
3519  if (!isValid()) {
3520  llvm::errs() << "<INVALID>\n";
3521  return;
3522  }
3523 
3524  switch (K) {
3525  case RangeK:
3526  // FIXME: actually print the range.
3527  llvm::errs() << "<range>\n";
3528  break;
3529  case SingleLocK:
3530  asLocation().dump();
3531  llvm::errs() << "\n";
3532  break;
3533  case StmtK:
3534  if (S)
3535  S->dump();
3536  else
3537  llvm::errs() << "<NULL STMT>\n";
3538  break;
3539  case DeclK:
3540  if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(D))
3541  llvm::errs() << *ND << "\n";
3542  else if (isa<BlockDecl>(D))
3543  // FIXME: Make this nicer.
3544  llvm::errs() << "<block>\n";
3545  else if (D)
3546  llvm::errs() << "<unknown decl>\n";
3547  else
3548  llvm::errs() << "<NULL DECL>\n";
3549  break;
3550  }
3551 }
Expr * getInc()
Definition: Stmt.h:1178
VisitorList::iterator visitor_iterator
Definition: BugReporter.h:67
Defines the clang::ASTContext interface.
static void removeEdgesToDefaultInitializers(PathPieces &Pieces)
SourceLocation getEnd() const
static bool isLoopJumpPastBody(const Stmt *Term, const BlockEdge *BE)
static bool removeUnneededCalls(PathPieces &pieces, BugReport *R, LocationContextMap &LCM)
const Decl * getDeclWithIssue() const
static void removeRedundantMsgs(PathPieces &path)
ParmVarDecl *const * param_const_iterator
Definition: Decl.h:1943
static bool isContainedByStmt(ParentMap &PM, const Stmt *S, const Stmt *SubS)
static Optional< size_t > getLengthOnSingleLine(SourceManager &SM, SourceRange Range)
const SourceRange * ranges_iterator
Definition: BugReporter.h:65
MemRegion - The root abstract class for all memory regions.
Definition: MemRegion.h:77
bool isMacroID() const
StringRef getCategory() const
Definition: BugType.h:49
bool isInteresting(SymbolRef sym)
PathDiagnosticLocation getLocation() const override
llvm::DenseSet< SymbolRef > Symbols
Definition: BugReporter.h:86
succ_iterator succ_begin()
Definition: CFG.h:542
const ExplodedNode * getErrorNode() const
Definition: BugReporter.h:180
virtual PathDiagnosticLocation getLocation(const SourceManager &SM) const
Return the "definitive" location of the reported bug.
const internal::VariadicAllOfMatcher< Stmt > stmt
Matches statements.
Definition: ASTMatchers.h:826
SVal getRawSVal(Loc LV, QualType T=QualType()) const
Returns the "raw" SVal bound to LV before any value simplfication.
Definition: ProgramState.h:712
Defines the SourceManager interface.
ProgramPoint getLocation() const
getLocation - Returns the edge associated with the given node.
llvm::MemoryBuffer * getBuffer(FileID FID, SourceLocation Loc, bool *Invalid=nullptr) const
Return the buffer for the specified FileID.
SmallVector< StackDiagPair, 6 > StackDiagVector
static void adjustCallLocations(PathPieces &Pieces, PathDiagnosticLocation *LastCallLocation=nullptr)
StringRef getName() const
void setPrunable(bool isPrunable, bool override=false)
unsigned getRawEncoding() const
When a SourceLocation itself cannot be used, this returns an (opaque) 32-bit integer encoding for it...
static PathDiagnosticLocation createEndBrace(const CompoundStmt *CS, const SourceManager &SM)
static bool optimizeEdges(PathPieces &path, SourceManager &SM, OptimizedCallsSet &OCS, LocationContextMap &LCM)
PathDiagnosticLocation getLocation() const
unsigned succ_size() const
Definition: CFG.h:552
static const Stmt * GetCurrentOrPreviousStmt(const ExplodedNode *N)
Definition: BugReporter.cpp:66
SmallVector< SourceRange, 4 > Ranges
Definition: BugReporter.h:83
static bool isConditionForTerminator(const Stmt *S, const Stmt *Cond)
const MemRegion * getBaseRegion() const
Definition: MemRegion.cpp:1063
Defines the Objective-C statement AST node classes.
static PathDiagnosticLocation createDeclEnd(const LocationContext *LC, const SourceManager &SM)
ParmVarDecl - Represents a parameter to a function.
Definition: Decl.h:1334
Defines the clang::Expr interface and subclasses for C++ expressions.
static PathDiagnosticLocation createSingleLocation(const PathDiagnosticLocation &PDL)
Convert the given location into a single kind location.
static void removePiecesWithInvalidLocations(PathPieces &Pieces)
BoundNodesTreeBuilder Nodes
static void updateStackPiecesWithMessage(PathDiagnosticPiece *P, StackDiagVector &CallStack)
FullSourceLoc asLocation() const
Symbolic value. These values used to capture symbolic execution of the program.
Definition: SymbolManager.h:42
const Decl * getUniqueingDecl() const
Get the declaration containing the uniqueing location.
Definition: BugReporter.h:273
void setStartLocation(const PathDiagnosticLocation &L)
unsigned getExpansionLineNumber(bool *Invalid=nullptr) const
void addRange(SourceRange R)
Add a range to a bug report.
Definition: BugReporter.h:286
std::pair< SourceLocation, SourceLocation > getExpansionRange(SourceLocation Loc) const
Given a SourceLocation object, return the range of tokens covered by the expansion in the ultimate fi...
bool isBodyAutosynthesized() const
Checks if the body of the Decl is generated by the BodyFarm.
LineState State
friend class BugReportEquivClass
Definition: BugReporter.h:72
succ_iterator succ_begin()
static PathDiagnosticLocation getEnclosingStmtLocation(const Stmt *S, SourceManager &SMgr, const ParentMap &P, const LocationContext *LC, bool allowNestedContexts)
bool isFileID() const
static void removeIdenticalEvents(PathPieces &path)
static const char StrLoopBodyZero[]
const BugType & getBugType() const
Definition: BugReporter.h:177
void pushActivePath(PathPieces *p)
const Stmt * getStmt() const
void addPredecessor(ExplodedNode *V, ExplodedGraph &G)
SmallVector< Regions *, 2 > interestingRegions
Definition: BugReporter.h:101
PathPieces & getMutablePieces()
Return a mutable version of 'path'.
bool isPrunable() const
Return true if the diagnostic piece is prunable.
Expr * getLHS() const
Definition: Expr.h:2964
unsigned getExpansionColumnNumber(SourceLocation Loc, bool *Invalid=nullptr) const
virtual llvm::iterator_range< ranges_iterator > getRanges()
Get the SourceRanges associated with the report.
static bool IsControlFlowExpr(const Stmt *S)
llvm::FoldingSet< BugReporterVisitor > CallbacksSet
Used for ensuring the visitors are only added once.
Definition: BugReporter.h:112
virtual void FlushReports(BugReporter &BR)
llvm::SmallSet< const LocationContext *, 2 > InterestingLocationContexts
Definition: BugReporter.h:105
static void addEdgeToPath(PathPieces &path, PathDiagnosticLocation &PrevLoc, PathDiagnosticLocation NewLoc, const LocationContext *LC)
Adds a sanitized control-flow diagnostic edge to a path.
STATISTIC(MaxBugClassSize,"The maximum number of bug reports in the same equivalence class")
bool isImplicit() const
Definition: DeclBase.h:503
static bool isJumpToFalseBranch(const BlockEdge *BE)
Stmt * getBody()
Definition: Stmt.h:1179
A builtin binary operation expression such as "x + y" or "x <= y".
Definition: Expr.h:2918
const Stmt * getCallSite() const
Expr * IgnoreParenCasts() LLVM_READONLY
Definition: Expr.cpp:2439
static PathDiagnosticCallPiece * construct(const ExplodedNode *N, const CallExitEnd &CE, const SourceManager &SM)
Expr * getLHS() const
Definition: Expr.h:3233
const void * getTag() const
Return the opaque tag (if any) on the PathDiagnosticPiece.
static const Stmt * getStmtBeforeCond(ParentMap &PM, const Stmt *Term, const ExplodedNode *N)
StringRef getDescription() const
Definition: BugReporter.h:182
ExplodedNode * getFirstPred()
StringRef getShortDescription(bool UseFallback=true) const
Definition: BugReporter.h:184
static void reversePropagateIntererstingSymbols(BugReport &R, InterestingExprs &IE, const ProgramState *State, const Expr *Ex, const LocationContext *LCtx)
virtual PathDiagnosticLocation getLocation() const =0
void addVisitor(std::unique_ptr< BugReporterVisitor > visitor)
Add custom or predefined bug report visitors to this report.
bool isInvalid() const
llvm::DenseSet< const Expr * > InterestingExprs
bool isSuppressOnSink() const
Definition: BugType.h:55
const LocationContext * getLocationContext() const
Expr * getRHS() const
Definition: Expr.h:3234
AnnotatingParser & P
const CFGBlock * getSrc() const
Definition: ProgramPoint.h:456
StringRef getName() const
Definition: BugType.h:48
FileID getFileID(SourceLocation SpellingLoc) const
Return the FileID for a SourceLocation.
static BugReport * FindReportInEquivalenceClass(BugReportEquivClass &EQ, SmallVectorImpl< BugReport * > &bugReports)
llvm::DenseSet< const PathDiagnosticCallPiece * > OptimizedCallsSet
void HandlePathDiagnostic(std::unique_ptr< PathDiagnostic > D)
llvm::DenseMap< const ExplodedNode *, const ExplodedNode * > InterExplodedGraphMap
const SmallVectorImpl< AnnotatedLine * >::const_iterator End
Expr * getCond() const
Definition: Expr.h:3222
ID
Defines the set of possible language-specific address spaces.
Definition: AddressSpaces.h:27
SourceManager & SM
const CFGBlock * getDst() const
Definition: ProgramPoint.h:460
virtual const ExtraTextList & getExtraText()
Definition: BugReporter.h:256
bool isWrittenInSameFile(SourceLocation Loc1, SourceLocation Loc2) const
Returns true if the spelling locations for both SourceLocations are part of the same file buffer...
const ProgramStateRef & getState() const
Stmt * getTerminatorCondition(bool StripParens=true)
Definition: CFG.cpp:4470
pred_iterator pred_end()
bool isBeforeInTranslationUnit(SourceLocation LHS, SourceLocation RHS) const
Determines the order of 2 source locations in the translation unit.
const SourceManager & getManager() const
ParentMap & getParentMap() const
SVal getSVal(const Stmt *S, const LocationContext *LCtx) const
Returns the SVal bound to the statement 'S' in the state's environment.
Definition: ProgramState.h:693
static bool lexicalContains(ParentMap &PM, const Stmt *X, const Stmt *Y)
Return true if X is contained by Y.
static void reversePropagateInterestingSymbols(BugReport &R, InterestingExprs &IE, const ProgramState *State, const LocationContext *CalleeCtx, const LocationContext *CallerCtx)
PathDiagnosticLocation getEndLocation() const
unsigned getExpansionLineNumber(SourceLocation Loc, bool *Invalid=nullptr) const
void Register(BugType *BT)
static const Stmt * getNextStmt(const ExplodedNode *N)
Retrieve the statement corresponding to the successor node.
unsigned ConfigurationChangeToken
Definition: BugReporter.h:116
void FlushReports()
Generate and flush diagnostics for all bug reports.
static void dropFunctionEntryEdge(PathPieces &Path, LocationContextMap &LCM, SourceManager &SM)
void markInteresting(SymbolRef sym)
static const Stmt * GetPreviousStmt(const ExplodedNode *N)
Definition: BugReporter.cpp:57
bool getBooleanOption(StringRef Name, bool DefaultVal, const ento::CheckerBase *C=nullptr, bool SearchInParents=false)
PathDiagnosticLocation getStartLocation() const
CheckName getCheckName() const
Definition: Checker.cpp:24
static bool GenerateVisitorsOnlyPathDiagnostic(PathDiagnostic &PD, PathDiagnosticBuilder &PDB, const ExplodedNode *N, ArrayRef< std::unique_ptr< BugReporterVisitor >> visitors)
llvm::ilist< BugReport >::iterator iterator
Definition: BugReporter.h:361
static const Stmt * getStmt(const ExplodedNode *N)
Given an exploded node, retrieve the statement that should be used for the diagnostic location...
bool isConsumedExpr(Expr *E) const
Definition: ParentMap.cpp:157
static PathDiagnosticLocation createDeclBegin(const LocationContext *LC, const SourceManager &SM)
CFGTerminator getTerminator()
Definition: CFG.h:623
static PathDiagnosticLocation createBegin(const Decl *D, const SourceManager &SM)
Create a location for the beginning of the declaration.
static PathDiagnosticEventPiece * eventsDescribeSameCondition(PathDiagnosticEventPiece *X, PathDiagnosticEventPiece *Y)
Definition: BugReporter.cpp:78
llvm::DenseSet< const MemRegion * > Regions
Definition: BugReporter.h:87
static std::unique_ptr< PathDiagnosticPiece > getDefaultEndPath(BugReporterContext &BRC, const ExplodedNode *N, BugReport &BR)
Generates the default final diagnostic piece.
SmallVectorImpl< AnnotatedLine * >::const_iterator Next
Stmt * getParent(Stmt *) const
Definition: ParentMap.cpp:120
static void simplifySimpleBranches(PathPieces &pieces)
Move edges from a branch condition to a branch target when the condition is simple.
Encodes a location in the source. The SourceManager can decode this to get at the full include stack...
void EmitBasicReport(const Decl *DeclWithIssue, const CheckerBase *Checker, StringRef BugName, StringRef BugCategory, StringRef BugStr, PathDiagnosticLocation Loc, ArrayRef< SourceRange > Ranges=None)
Stmt * getLabel()
Definition: CFG.h:634
const ExplodedNode * ErrorNode
Definition: BugReporter.h:82
const StackFrameContext * getCurrentStackFrame() const
virtual PathGenerationScheme getGenerationScheme() const
Stmt * getParentIgnoreParens(Stmt *) const
Definition: ParentMap.cpp:126
StringRef getCheckName() const
Definition: BugType.h:50
const ExplodedNode *const * const_succ_iterator
bool isValid() const
Return true if this is a valid SourceLocation object.
Expr * getLHS()
Definition: Stmt.h:717
ExplodedGraph & getGraph()
void emitReport(std::unique_ptr< BugReport > R)
Add the given report to the set of reports tracked by BugReporter.
static bool isIncrementOrInitInForLoop(const Stmt *S, const Stmt *FL)
bool isValid() const
void Profile(llvm::FoldingSetNodeID &ID) const
void setCallee(const CallEnter &CE, const SourceManager &SM)
std::string Description
Definition: BugReporter.h:77
bool generatePathDiagnostic(PathDiagnostic &PD, PathDiagnosticConsumer &PC, ArrayRef< BugReport * > &bugReports) override
PathDiagnosticLocation Location
Definition: BugReporter.h:78
const Decl * getDecl() const
SourceLocation getBegin() const
Expr * getRangeInit()
Definition: Stmt.cpp:863
const Decl * DeclWithIssue
Definition: BugReporter.h:75
PathDiagnosticLocation getLocation() const override
static const Stmt * getEnclosingParent(const Stmt *S, const ParentMap &PM)
static bool isLogicalOp(Opcode Opc)
Definition: Expr.h:3037
static void removePunyEdges(PathPieces &path, SourceManager &SM, ParentMap &PM)
static bool hasImplicitBody(const Decl *D)
SmallVector< Symbols *, 2 > interestingSymbols
Definition: BugReporter.h:94
std::unique_ptr< ExplodedGraph > trim(ArrayRef< const NodeTy * > Nodes, InterExplodedGraphMap *ForwardMap=nullptr, InterExplodedGraphMap *InverseMap=nullptr) const
ast_type_traits::DynTypedNode Node
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
if(T->getSizeExpr()) TRY_TO(TraverseStmt(T-> getSizeExpr()))
virtual void Profile(llvm::FoldingSetNodeID &hash) const
static const char StrLoopCollectionEmpty[]
static const Stmt * getLocStmt(PathDiagnosticLocation L)
const LocationContext * getLocationContext() const
Definition: ProgramPoint.h:155
static __inline__ uint32_t volatile uint32_t * p
Definition: arm_acle.h:75
PathDiagnosticLocation getUniqueingLocation() const
Get the location on which the report should be uniqued.
Definition: BugReporter.h:268
static bool GenerateMinimalPathDiagnostic(PathDiagnostic &PD, PathDiagnosticBuilder &PDB, const ExplodedNode *N, LocationContextMap &LCM, ArrayRef< std::unique_ptr< BugReporterVisitor >> visitors)
const MemRegion * getAsRegion() const
Definition: SVals.cpp:135
static const Stmt * getTerminatorCondition(const CFGBlock *B)
bool isBodyAutosynthesizedFromModelFile() const
Checks if the body of the Decl is generated by the BodyFarm from a model file.
Optional< T > getAs() const
Convert to the specified ProgramPoint type, returning None if this ProgramPoint is not of the desired...
Definition: ProgramPoint.h:127
void setEndLocation(const PathDiagnosticLocation &L)
static bool isLoop(const Stmt *Term)
const ExplodedNode *const * const_pred_iterator
Represents Objective-C's collection statement.
Definition: StmtObjC.h:24
succ_iterator succ_end()
void setEndOfPath(std::unique_ptr< PathDiagnosticPiece > EndPiece)
static PathDiagnosticLocation createOperatorLoc(const BinaryOperator *BO, const SourceManager &SM)
X
Definition: SemaDecl.cpp:11429
PathDiagnosticRange asRange() const
ProgramStateManager & getStateManager()
static void CompactPathDiagnostic(PathPieces &path, const SourceManager &SM)
Opcode getOpcode() const
Definition: Expr.h:2961
pred_iterator pred_begin()
static const Stmt * getStmtParent(const Stmt *S, const ParentMap &PM)
static PathDiagnosticLocation createEndOfPath(const ExplodedNode *N, const SourceManager &SM)
llvm::DenseMap< const PathPieces *, const LocationContext * > LocationContextMap
static void removeContextCycles(PathPieces &Path, SourceManager &SM, ParentMap &PM)
SymbolRef getAsSymbol(bool IncludeBaseRegions=false) const
If this SVal wraps a symbol return that SymbolRef. Otherwise, return 0.
Definition: SVals.cpp:111
Loc getLValue(const VarDecl *D, const LocationContext *LC) const
Get the lvalue for a variable reference.
Definition: ProgramState.h:659
Expr * getRHS() const
Definition: Expr.h:2966
static bool GenerateAlternateExtensivePathDiagnostic(PathDiagnostic &PD, PathDiagnosticBuilder &PDB, const ExplodedNode *N, LocationContextMap &LCM, ArrayRef< std::unique_ptr< BugReporterVisitor >> visitors)
A SourceLocation and its associated SourceManager.
PathDiagnosticLocation callEnterWithin
A reference to a declared variable, function, enum, etc. [C99 6.5.1p2].
Definition: Expr.h:899
FullSourceLoc getExpansionLoc() const
static bool GenerateExtensivePathDiagnostic(PathDiagnostic &PD, PathDiagnosticBuilder &PDB, const ExplodedNode *N, LocationContextMap &LCM, ArrayRef< std::unique_ptr< BugReporterVisitor >> visitors)
unsigned getFileOffset(SourceLocation SpellingLoc) const
Returns the offset from the start of the file that the specified SourceLocation represents.
DeclStmt * getLoopVarStmt()
Definition: StmtCXX.h:156
A trivial tuple used to represent a source range.
static void addContextEdges(PathPieces &pieces, SourceManager &SM, const ParentMap &PM, const LocationContext *LCtx)
SourceLocation getExpansionLoc(SourceLocation Loc) const
Given a SourceLocation object Loc, return the expansion location referenced by the ID...
bool isValid() const
Definition: BugReporter.h:215
static const char StrEnteringLoop[]
std::pair< PathDiagnosticCallPiece *, const ExplodedNode * > StackDiagPair
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:846
static const char StrLoopRangeEmpty[]
This class handles loading and caching of source files into memory.
Expr * IgnoreParens() LLVM_READONLY
Definition: Expr.cpp:2408
CFGBlock & getExit()
Definition: CFG.h:865
static bool isInLoopBody(ParentMap &PM, const Stmt *S, const Stmt *Term)