1218887Sdim// BugReporter.cpp - Generate PathDiagnostics for Bugs ------------*- C++ -*--//
2218887Sdim//
3218887Sdim//                     The LLVM Compiler Infrastructure
4218887Sdim//
5218887Sdim// This file is distributed under the University of Illinois Open Source
6218887Sdim// License. See LICENSE.TXT for details.
7218887Sdim//
8218887Sdim//===----------------------------------------------------------------------===//
9218887Sdim//
10218887Sdim//  This file defines BugReporter, a utility class for generating
11218887Sdim//  PathDiagnostics.
12218887Sdim//
13218887Sdim//===----------------------------------------------------------------------===//
14218887Sdim
15249423Sdim#define DEBUG_TYPE "BugReporter"
16249423Sdim
17218887Sdim#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
18218887Sdim#include "clang/AST/ASTContext.h"
19234353Sdim#include "clang/AST/DeclObjC.h"
20218887Sdim#include "clang/AST/Expr.h"
21263508Sdim#include "clang/AST/ExprCXX.h"
22218887Sdim#include "clang/AST/ParentMap.h"
23218887Sdim#include "clang/AST/StmtObjC.h"
24263508Sdim#include "clang/AST/StmtCXX.h"
25249423Sdim#include "clang/Analysis/CFG.h"
26249423Sdim#include "clang/Analysis/ProgramPoint.h"
27218887Sdim#include "clang/Basic/SourceManager.h"
28249423Sdim#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
29218887Sdim#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
30249423Sdim#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
31218887Sdim#include "llvm/ADT/DenseMap.h"
32249423Sdim#include "llvm/ADT/IntrusiveRefCntPtr.h"
33249423Sdim#include "llvm/ADT/OwningPtr.h"
34249423Sdim#include "llvm/ADT/STLExtras.h"
35234353Sdim#include "llvm/ADT/SmallString.h"
36249423Sdim#include "llvm/ADT/Statistic.h"
37249423Sdim#include "llvm/Support/raw_ostream.h"
38218887Sdim#include <queue>
39218887Sdim
40218887Sdimusing namespace clang;
41218887Sdimusing namespace ento;
42218887Sdim
43249423SdimSTATISTIC(MaxBugClassSize,
44249423Sdim          "The maximum number of bug reports in the same equivalence class");
45249423SdimSTATISTIC(MaxValidBugClassSize,
46249423Sdim          "The maximum number of bug reports in the same equivalence class "
47249423Sdim          "where at least one report is valid (not suppressed)");
48249423Sdim
49218887SdimBugReporterVisitor::~BugReporterVisitor() {}
50218887Sdim
51234353Sdimvoid BugReporterContext::anchor() {}
52234353Sdim
53218887Sdim//===----------------------------------------------------------------------===//
54218887Sdim// Helper routines for walking the ExplodedGraph and fetching statements.
55218887Sdim//===----------------------------------------------------------------------===//
56218887Sdim
57226633Sdimstatic const Stmt *GetPreviousStmt(const ExplodedNode *N) {
58251662Sdim  for (N = N->getFirstPred(); N; N = N->getFirstPred())
59251662Sdim    if (const Stmt *S = PathDiagnosticLocation::getStmt(N))
60218887Sdim      return S;
61218887Sdim
62218887Sdim  return 0;
63218887Sdim}
64218887Sdim
65218887Sdimstatic inline const Stmt*
66226633SdimGetCurrentOrPreviousStmt(const ExplodedNode *N) {
67251662Sdim  if (const Stmt *S = PathDiagnosticLocation::getStmt(N))
68218887Sdim    return S;
69218887Sdim
70218887Sdim  return GetPreviousStmt(N);
71218887Sdim}
72218887Sdim
73218887Sdim//===----------------------------------------------------------------------===//
74234353Sdim// Diagnostic cleanup.
75234353Sdim//===----------------------------------------------------------------------===//
76234353Sdim
77243830Sdimstatic PathDiagnosticEventPiece *
78243830SdimeventsDescribeSameCondition(PathDiagnosticEventPiece *X,
79243830Sdim                            PathDiagnosticEventPiece *Y) {
80243830Sdim  // Prefer diagnostics that come from ConditionBRVisitor over
81243830Sdim  // those that came from TrackConstraintBRVisitor.
82243830Sdim  const void *tagPreferred = ConditionBRVisitor::getTag();
83243830Sdim  const void *tagLesser = TrackConstraintBRVisitor::getTag();
84243830Sdim
85243830Sdim  if (X->getLocation() != Y->getLocation())
86243830Sdim    return 0;
87243830Sdim
88243830Sdim  if (X->getTag() == tagPreferred && Y->getTag() == tagLesser)
89243830Sdim    return X;
90243830Sdim
91243830Sdim  if (Y->getTag() == tagPreferred && X->getTag() == tagLesser)
92243830Sdim    return Y;
93243830Sdim
94243830Sdim  return 0;
95243830Sdim}
96243830Sdim
97243830Sdim/// An optimization pass over PathPieces that removes redundant diagnostics
98243830Sdim/// generated by both ConditionBRVisitor and TrackConstraintBRVisitor.  Both
99243830Sdim/// BugReporterVisitors use different methods to generate diagnostics, with
100243830Sdim/// one capable of emitting diagnostics in some cases but not in others.  This
101243830Sdim/// can lead to redundant diagnostic pieces at the same point in a path.
102243830Sdimstatic void removeRedundantMsgs(PathPieces &path) {
103243830Sdim  unsigned N = path.size();
104243830Sdim  if (N < 2)
105243830Sdim    return;
106243830Sdim  // NOTE: this loop intentionally is not using an iterator.  Instead, we
107243830Sdim  // are streaming the path and modifying it in place.  This is done by
108243830Sdim  // grabbing the front, processing it, and if we decide to keep it append
109243830Sdim  // it to the end of the path.  The entire path is processed in this way.
110243830Sdim  for (unsigned i = 0; i < N; ++i) {
111243830Sdim    IntrusiveRefCntPtr<PathDiagnosticPiece> piece(path.front());
112243830Sdim    path.pop_front();
113243830Sdim
114243830Sdim    switch (piece->getKind()) {
115243830Sdim      case clang::ento::PathDiagnosticPiece::Call:
116243830Sdim        removeRedundantMsgs(cast<PathDiagnosticCallPiece>(piece)->path);
117243830Sdim        break;
118243830Sdim      case clang::ento::PathDiagnosticPiece::Macro:
119243830Sdim        removeRedundantMsgs(cast<PathDiagnosticMacroPiece>(piece)->subPieces);
120243830Sdim        break;
121243830Sdim      case clang::ento::PathDiagnosticPiece::ControlFlow:
122243830Sdim        break;
123243830Sdim      case clang::ento::PathDiagnosticPiece::Event: {
124243830Sdim        if (i == N-1)
125243830Sdim          break;
126243830Sdim
127243830Sdim        if (PathDiagnosticEventPiece *nextEvent =
128243830Sdim            dyn_cast<PathDiagnosticEventPiece>(path.front().getPtr())) {
129243830Sdim          PathDiagnosticEventPiece *event =
130243830Sdim            cast<PathDiagnosticEventPiece>(piece);
131243830Sdim          // Check to see if we should keep one of the two pieces.  If we
132243830Sdim          // come up with a preference, record which piece to keep, and consume
133243830Sdim          // another piece from the path.
134243830Sdim          if (PathDiagnosticEventPiece *pieceToKeep =
135243830Sdim              eventsDescribeSameCondition(event, nextEvent)) {
136243830Sdim            piece = pieceToKeep;
137243830Sdim            path.pop_front();
138243830Sdim            ++i;
139243830Sdim          }
140243830Sdim        }
141243830Sdim        break;
142243830Sdim      }
143243830Sdim    }
144243830Sdim    path.push_back(piece);
145243830Sdim  }
146243830Sdim}
147243830Sdim
148251662Sdim/// A map from PathDiagnosticPiece to the LocationContext of the inlined
149251662Sdim/// function call it represents.
150251662Sdimtypedef llvm::DenseMap<const PathPieces *, const LocationContext *>
151251662Sdim        LocationContextMap;
152251662Sdim
153234353Sdim/// Recursively scan through a path and prune out calls and macros pieces
154234353Sdim/// that aren't needed.  Return true if afterwards the path contains
155249423Sdim/// "interesting stuff" which means it shouldn't be pruned from the parent path.
156251662Sdimstatic bool removeUnneededCalls(PathPieces &pieces, BugReport *R,
157251662Sdim                                LocationContextMap &LCM) {
158234353Sdim  bool containsSomethingInteresting = false;
159234353Sdim  const unsigned N = pieces.size();
160234353Sdim
161234353Sdim  for (unsigned i = 0 ; i < N ; ++i) {
162234353Sdim    // Remove the front piece from the path.  If it is still something we
163234353Sdim    // want to keep once we are done, we will push it back on the end.
164234353Sdim    IntrusiveRefCntPtr<PathDiagnosticPiece> piece(pieces.front());
165234353Sdim    pieces.pop_front();
166234353Sdim
167234353Sdim    switch (piece->getKind()) {
168234353Sdim      case PathDiagnosticPiece::Call: {
169234353Sdim        PathDiagnosticCallPiece *call = cast<PathDiagnosticCallPiece>(piece);
170243830Sdim        // Check if the location context is interesting.
171251662Sdim        assert(LCM.count(&call->path));
172251662Sdim        if (R->isInteresting(LCM[&call->path])) {
173243830Sdim          containsSomethingInteresting = true;
174243830Sdim          break;
175243830Sdim        }
176249423Sdim
177251662Sdim        if (!removeUnneededCalls(call->path, R, LCM))
178234353Sdim          continue;
179243830Sdim
180234353Sdim        containsSomethingInteresting = true;
181234353Sdim        break;
182234353Sdim      }
183234353Sdim      case PathDiagnosticPiece::Macro: {
184234353Sdim        PathDiagnosticMacroPiece *macro = cast<PathDiagnosticMacroPiece>(piece);
185251662Sdim        if (!removeUnneededCalls(macro->subPieces, R, LCM))
186234353Sdim          continue;
187234353Sdim        containsSomethingInteresting = true;
188234353Sdim        break;
189234353Sdim      }
190234353Sdim      case PathDiagnosticPiece::Event: {
191234353Sdim        PathDiagnosticEventPiece *event = cast<PathDiagnosticEventPiece>(piece);
192243830Sdim
193234353Sdim        // We never throw away an event, but we do throw it away wholesale
194234353Sdim        // as part of a path if we throw the entire path away.
195243830Sdim        containsSomethingInteresting |= !event->isPrunable();
196234353Sdim        break;
197234353Sdim      }
198234353Sdim      case PathDiagnosticPiece::ControlFlow:
199234353Sdim        break;
200234353Sdim    }
201234353Sdim
202234353Sdim    pieces.push_back(piece);
203234353Sdim  }
204234353Sdim
205234353Sdim  return containsSomethingInteresting;
206234353Sdim}
207234353Sdim
208263508Sdim/// Returns true if the given decl has been implicitly given a body, either by
209263508Sdim/// the analyzer or by the compiler proper.
210263508Sdimstatic bool hasImplicitBody(const Decl *D) {
211263508Sdim  assert(D);
212263508Sdim  return D->isImplicit() || !D->hasBody();
213263508Sdim}
214263508Sdim
215249423Sdim/// Recursively scan through a path and make sure that all call pieces have
216263508Sdim/// valid locations.
217249423Sdimstatic void adjustCallLocations(PathPieces &Pieces,
218249423Sdim                                PathDiagnosticLocation *LastCallLocation = 0) {
219249423Sdim  for (PathPieces::iterator I = Pieces.begin(), E = Pieces.end(); I != E; ++I) {
220249423Sdim    PathDiagnosticCallPiece *Call = dyn_cast<PathDiagnosticCallPiece>(*I);
221249423Sdim
222249423Sdim    if (!Call) {
223249423Sdim      assert((*I)->getLocation().asLocation().isValid());
224249423Sdim      continue;
225249423Sdim    }
226249423Sdim
227249423Sdim    if (LastCallLocation) {
228263508Sdim      bool CallerIsImplicit = hasImplicitBody(Call->getCaller());
229263508Sdim      if (CallerIsImplicit || !Call->callEnter.asLocation().isValid())
230249423Sdim        Call->callEnter = *LastCallLocation;
231263508Sdim      if (CallerIsImplicit || !Call->callReturn.asLocation().isValid())
232249423Sdim        Call->callReturn = *LastCallLocation;
233249423Sdim    }
234249423Sdim
235249423Sdim    // Recursively clean out the subclass.  Keep this call around if
236249423Sdim    // it contains any informative diagnostics.
237249423Sdim    PathDiagnosticLocation *ThisCallLocation;
238249423Sdim    if (Call->callEnterWithin.asLocation().isValid() &&
239263508Sdim        !hasImplicitBody(Call->getCallee()))
240249423Sdim      ThisCallLocation = &Call->callEnterWithin;
241249423Sdim    else
242249423Sdim      ThisCallLocation = &Call->callEnter;
243249423Sdim
244249423Sdim    assert(ThisCallLocation && "Outermost call has an invalid location");
245249423Sdim    adjustCallLocations(Call->path, ThisCallLocation);
246249423Sdim  }
247249423Sdim}
248249423Sdim
249263508Sdim/// Remove edges in and out of C++ default initializer expressions. These are
250263508Sdim/// for fields that have in-class initializers, as opposed to being initialized
251263508Sdim/// explicitly in a constructor or braced list.
252263508Sdimstatic void removeEdgesToDefaultInitializers(PathPieces &Pieces) {
253263508Sdim  for (PathPieces::iterator I = Pieces.begin(), E = Pieces.end(); I != E;) {
254263508Sdim    if (PathDiagnosticCallPiece *C = dyn_cast<PathDiagnosticCallPiece>(*I))
255263508Sdim      removeEdgesToDefaultInitializers(C->path);
256263508Sdim
257263508Sdim    if (PathDiagnosticMacroPiece *M = dyn_cast<PathDiagnosticMacroPiece>(*I))
258263508Sdim      removeEdgesToDefaultInitializers(M->subPieces);
259263508Sdim
260263508Sdim    if (PathDiagnosticControlFlowPiece *CF =
261263508Sdim          dyn_cast<PathDiagnosticControlFlowPiece>(*I)) {
262263508Sdim      const Stmt *Start = CF->getStartLocation().asStmt();
263263508Sdim      const Stmt *End = CF->getEndLocation().asStmt();
264263508Sdim      if (Start && isa<CXXDefaultInitExpr>(Start)) {
265263508Sdim        I = Pieces.erase(I);
266263508Sdim        continue;
267263508Sdim      } else if (End && isa<CXXDefaultInitExpr>(End)) {
268263508Sdim        PathPieces::iterator Next = llvm::next(I);
269263508Sdim        if (Next != E) {
270263508Sdim          if (PathDiagnosticControlFlowPiece *NextCF =
271263508Sdim                dyn_cast<PathDiagnosticControlFlowPiece>(*Next)) {
272263508Sdim            NextCF->setStartLocation(CF->getStartLocation());
273263508Sdim          }
274263508Sdim        }
275263508Sdim        I = Pieces.erase(I);
276263508Sdim        continue;
277263508Sdim      }
278263508Sdim    }
279263508Sdim
280263508Sdim    I++;
281263508Sdim  }
282263508Sdim}
283263508Sdim
284263508Sdim/// Remove all pieces with invalid locations as these cannot be serialized.
285263508Sdim/// We might have pieces with invalid locations as a result of inlining Body
286263508Sdim/// Farm generated functions.
287263508Sdimstatic void removePiecesWithInvalidLocations(PathPieces &Pieces) {
288263508Sdim  for (PathPieces::iterator I = Pieces.begin(), E = Pieces.end(); I != E;) {
289263508Sdim    if (PathDiagnosticCallPiece *C = dyn_cast<PathDiagnosticCallPiece>(*I))
290263508Sdim      removePiecesWithInvalidLocations(C->path);
291263508Sdim
292263508Sdim    if (PathDiagnosticMacroPiece *M = dyn_cast<PathDiagnosticMacroPiece>(*I))
293263508Sdim      removePiecesWithInvalidLocations(M->subPieces);
294263508Sdim
295263508Sdim    if (!(*I)->getLocation().isValid() ||
296263508Sdim        !(*I)->getLocation().asLocation().isValid()) {
297263508Sdim      I = Pieces.erase(I);
298263508Sdim      continue;
299263508Sdim    }
300263508Sdim    I++;
301263508Sdim  }
302263508Sdim}
303263508Sdim
304234353Sdim//===----------------------------------------------------------------------===//
305218887Sdim// PathDiagnosticBuilder and its associated routines and helper objects.
306218887Sdim//===----------------------------------------------------------------------===//
307218887Sdim
308218887Sdimnamespace {
309218887Sdimclass NodeMapClosure : public BugReport::NodeResolver {
310249423Sdim  InterExplodedGraphMap &M;
311218887Sdimpublic:
312249423Sdim  NodeMapClosure(InterExplodedGraphMap &m) : M(m) {}
313218887Sdim
314226633Sdim  const ExplodedNode *getOriginalNode(const ExplodedNode *N) {
315249423Sdim    return M.lookup(N);
316218887Sdim  }
317218887Sdim};
318218887Sdim
319218887Sdimclass PathDiagnosticBuilder : public BugReporterContext {
320218887Sdim  BugReport *R;
321226633Sdim  PathDiagnosticConsumer *PDC;
322218887Sdim  NodeMapClosure NMC;
323218887Sdimpublic:
324234353Sdim  const LocationContext *LC;
325234353Sdim
326218887Sdim  PathDiagnosticBuilder(GRBugReporter &br,
327249423Sdim                        BugReport *r, InterExplodedGraphMap &Backmap,
328226633Sdim                        PathDiagnosticConsumer *pdc)
329218887Sdim    : BugReporterContext(br),
330234353Sdim      R(r), PDC(pdc), NMC(Backmap), LC(r->getErrorNode()->getLocationContext())
331234353Sdim  {}
332218887Sdim
333226633Sdim  PathDiagnosticLocation ExecutionContinues(const ExplodedNode *N);
334218887Sdim
335226633Sdim  PathDiagnosticLocation ExecutionContinues(llvm::raw_string_ostream &os,
336226633Sdim                                            const ExplodedNode *N);
337218887Sdim
338226633Sdim  BugReport *getBugReport() { return R; }
339226633Sdim
340218887Sdim  Decl const &getCodeDecl() { return R->getErrorNode()->getCodeDecl(); }
341234353Sdim
342234353Sdim  ParentMap& getParentMap() { return LC->getParentMap(); }
343218887Sdim
344218887Sdim  const Stmt *getParent(const Stmt *S) {
345218887Sdim    return getParentMap().getParent(S);
346218887Sdim  }
347218887Sdim
348218887Sdim  virtual NodeMapClosure& getNodeResolver() { return NMC; }
349218887Sdim
350218887Sdim  PathDiagnosticLocation getEnclosingStmtLocation(const Stmt *S);
351218887Sdim
352226633Sdim  PathDiagnosticConsumer::PathGenerationScheme getGenerationScheme() const {
353226633Sdim    return PDC ? PDC->getGenerationScheme() : PathDiagnosticConsumer::Extensive;
354218887Sdim  }
355218887Sdim
356218887Sdim  bool supportsLogicalOpControlFlow() const {
357218887Sdim    return PDC ? PDC->supportsLogicalOpControlFlow() : true;
358218887Sdim  }
359218887Sdim};
360218887Sdim} // end anonymous namespace
361218887Sdim
362218887SdimPathDiagnosticLocation
363226633SdimPathDiagnosticBuilder::ExecutionContinues(const ExplodedNode *N) {
364251662Sdim  if (const Stmt *S = PathDiagnosticLocation::getNextStmt(N))
365234353Sdim    return PathDiagnosticLocation(S, getSourceManager(), LC);
366218887Sdim
367226633Sdim  return PathDiagnosticLocation::createDeclEnd(N->getLocationContext(),
368226633Sdim                                               getSourceManager());
369218887Sdim}
370218887Sdim
371218887SdimPathDiagnosticLocation
372226633SdimPathDiagnosticBuilder::ExecutionContinues(llvm::raw_string_ostream &os,
373226633Sdim                                          const ExplodedNode *N) {
374218887Sdim
375218887Sdim  // Slow, but probably doesn't matter.
376218887Sdim  if (os.str().empty())
377218887Sdim    os << ' ';
378218887Sdim
379218887Sdim  const PathDiagnosticLocation &Loc = ExecutionContinues(N);
380218887Sdim
381218887Sdim  if (Loc.asStmt())
382218887Sdim    os << "Execution continues on line "
383226633Sdim       << getSourceManager().getExpansionLineNumber(Loc.asLocation())
384218887Sdim       << '.';
385218887Sdim  else {
386218887Sdim    os << "Execution jumps to the end of the ";
387218887Sdim    const Decl *D = N->getLocationContext()->getDecl();
388218887Sdim    if (isa<ObjCMethodDecl>(D))
389218887Sdim      os << "method";
390218887Sdim    else if (isa<FunctionDecl>(D))
391218887Sdim      os << "function";
392218887Sdim    else {
393218887Sdim      assert(isa<BlockDecl>(D));
394218887Sdim      os << "anonymous block";
395218887Sdim    }
396218887Sdim    os << '.';
397218887Sdim  }
398218887Sdim
399218887Sdim  return Loc;
400218887Sdim}
401218887Sdim
402263508Sdimstatic const Stmt *getEnclosingParent(const Stmt *S, const ParentMap &PM) {
403218887Sdim  if (isa<Expr>(S) && PM.isConsumedExpr(cast<Expr>(S)))
404263508Sdim    return PM.getParentIgnoreParens(S);
405218887Sdim
406218887Sdim  const Stmt *Parent = PM.getParentIgnoreParens(S);
407263508Sdim  if (!Parent)
408263508Sdim    return 0;
409218887Sdim
410263508Sdim  switch (Parent->getStmtClass()) {
411263508Sdim  case Stmt::ForStmtClass:
412263508Sdim  case Stmt::DoStmtClass:
413263508Sdim  case Stmt::WhileStmtClass:
414263508Sdim  case Stmt::ObjCForCollectionStmtClass:
415263508Sdim  case Stmt::CXXForRangeStmtClass:
416263508Sdim    return Parent;
417263508Sdim  default:
418263508Sdim    break;
419263508Sdim  }
420218887Sdim
421263508Sdim  return 0;
422218887Sdim}
423218887Sdim
424263508Sdimstatic PathDiagnosticLocation
425263508SdimgetEnclosingStmtLocation(const Stmt *S, SourceManager &SMgr, const ParentMap &P,
426263508Sdim                         const LocationContext *LC, bool allowNestedContexts) {
427263508Sdim  if (!S)
428263508Sdim    return PathDiagnosticLocation();
429218887Sdim
430263508Sdim  while (const Stmt *Parent = getEnclosingParent(S, P)) {
431218887Sdim    switch (Parent->getStmtClass()) {
432218887Sdim      case Stmt::BinaryOperatorClass: {
433218887Sdim        const BinaryOperator *B = cast<BinaryOperator>(Parent);
434218887Sdim        if (B->isLogicalOp())
435263508Sdim          return PathDiagnosticLocation(allowNestedContexts ? B : S, SMgr, LC);
436218887Sdim        break;
437218887Sdim      }
438218887Sdim      case Stmt::CompoundStmtClass:
439218887Sdim      case Stmt::StmtExprClass:
440226633Sdim        return PathDiagnosticLocation(S, SMgr, LC);
441218887Sdim      case Stmt::ChooseExprClass:
442218887Sdim        // Similar to '?' if we are referring to condition, just have the edge
443218887Sdim        // point to the entire choose expression.
444263508Sdim        if (allowNestedContexts || cast<ChooseExpr>(Parent)->getCond() == S)
445226633Sdim          return PathDiagnosticLocation(Parent, SMgr, LC);
446218887Sdim        else
447226633Sdim          return PathDiagnosticLocation(S, SMgr, LC);
448218887Sdim      case Stmt::BinaryConditionalOperatorClass:
449218887Sdim      case Stmt::ConditionalOperatorClass:
450218887Sdim        // For '?', if we are referring to condition, just have the edge point
451218887Sdim        // to the entire '?' expression.
452263508Sdim        if (allowNestedContexts ||
453263508Sdim            cast<AbstractConditionalOperator>(Parent)->getCond() == S)
454226633Sdim          return PathDiagnosticLocation(Parent, SMgr, LC);
455218887Sdim        else
456226633Sdim          return PathDiagnosticLocation(S, SMgr, LC);
457263508Sdim      case Stmt::CXXForRangeStmtClass:
458263508Sdim        if (cast<CXXForRangeStmt>(Parent)->getBody() == S)
459263508Sdim          return PathDiagnosticLocation(S, SMgr, LC);
460263508Sdim        break;
461218887Sdim      case Stmt::DoStmtClass:
462226633Sdim          return PathDiagnosticLocation(S, SMgr, LC);
463218887Sdim      case Stmt::ForStmtClass:
464218887Sdim        if (cast<ForStmt>(Parent)->getBody() == S)
465226633Sdim          return PathDiagnosticLocation(S, SMgr, LC);
466218887Sdim        break;
467218887Sdim      case Stmt::IfStmtClass:
468218887Sdim        if (cast<IfStmt>(Parent)->getCond() != S)
469226633Sdim          return PathDiagnosticLocation(S, SMgr, LC);
470218887Sdim        break;
471218887Sdim      case Stmt::ObjCForCollectionStmtClass:
472218887Sdim        if (cast<ObjCForCollectionStmt>(Parent)->getBody() == S)
473226633Sdim          return PathDiagnosticLocation(S, SMgr, LC);
474218887Sdim        break;
475218887Sdim      case Stmt::WhileStmtClass:
476218887Sdim        if (cast<WhileStmt>(Parent)->getCond() != S)
477226633Sdim          return PathDiagnosticLocation(S, SMgr, LC);
478218887Sdim        break;
479218887Sdim      default:
480218887Sdim        break;
481218887Sdim    }
482218887Sdim
483218887Sdim    S = Parent;
484218887Sdim  }
485218887Sdim
486218887Sdim  assert(S && "Cannot have null Stmt for PathDiagnosticLocation");
487218887Sdim
488226633Sdim  return PathDiagnosticLocation(S, SMgr, LC);
489218887Sdim}
490218887Sdim
491263508SdimPathDiagnosticLocation
492263508SdimPathDiagnosticBuilder::getEnclosingStmtLocation(const Stmt *S) {
493263508Sdim  assert(S && "Null Stmt passed to getEnclosingStmtLocation");
494263508Sdim  return ::getEnclosingStmtLocation(S, getSourceManager(), getParentMap(), LC,
495263508Sdim                                    /*allowNestedContexts=*/false);
496263508Sdim}
497263508Sdim
498218887Sdim//===----------------------------------------------------------------------===//
499243830Sdim// "Visitors only" path diagnostic generation algorithm.
500243830Sdim//===----------------------------------------------------------------------===//
501243830Sdimstatic bool GenerateVisitorsOnlyPathDiagnostic(PathDiagnostic &PD,
502243830Sdim                                               PathDiagnosticBuilder &PDB,
503243830Sdim                                               const ExplodedNode *N,
504243830Sdim                                      ArrayRef<BugReporterVisitor *> visitors) {
505243830Sdim  // All path generation skips the very first node (the error node).
506243830Sdim  // This is because there is special handling for the end-of-path note.
507243830Sdim  N = N->getFirstPred();
508243830Sdim  if (!N)
509243830Sdim    return true;
510243830Sdim
511243830Sdim  BugReport *R = PDB.getBugReport();
512243830Sdim  while (const ExplodedNode *Pred = N->getFirstPred()) {
513243830Sdim    for (ArrayRef<BugReporterVisitor *>::iterator I = visitors.begin(),
514243830Sdim                                                  E = visitors.end();
515243830Sdim         I != E; ++I) {
516243830Sdim      // Visit all the node pairs, but throw the path pieces away.
517243830Sdim      PathDiagnosticPiece *Piece = (*I)->VisitNode(N, Pred, PDB, *R);
518243830Sdim      delete Piece;
519243830Sdim    }
520243830Sdim
521243830Sdim    N = Pred;
522243830Sdim  }
523243830Sdim
524243830Sdim  return R->isValid();
525243830Sdim}
526243830Sdim
527243830Sdim//===----------------------------------------------------------------------===//
528234353Sdim// "Minimal" path diagnostic generation algorithm.
529218887Sdim//===----------------------------------------------------------------------===//
530234353Sdimtypedef std::pair<PathDiagnosticCallPiece*, const ExplodedNode*> StackDiagPair;
531234353Sdimtypedef SmallVector<StackDiagPair, 6> StackDiagVector;
532218887Sdim
533234353Sdimstatic void updateStackPiecesWithMessage(PathDiagnosticPiece *P,
534234353Sdim                                         StackDiagVector &CallStack) {
535234353Sdim  // If the piece contains a special message, add it to all the call
536234353Sdim  // pieces on the active stack.
537234353Sdim  if (PathDiagnosticEventPiece *ep =
538234353Sdim        dyn_cast<PathDiagnosticEventPiece>(P)) {
539218887Sdim
540234353Sdim    if (ep->hasCallStackHint())
541234353Sdim      for (StackDiagVector::iterator I = CallStack.begin(),
542234353Sdim                                     E = CallStack.end(); I != E; ++I) {
543234353Sdim        PathDiagnosticCallPiece *CP = I->first;
544234353Sdim        const ExplodedNode *N = I->second;
545234353Sdim        std::string stackMsg = ep->getCallStackMessage(N);
546218887Sdim
547234353Sdim        // The last message on the path to final bug is the most important
548234353Sdim        // one. Since we traverse the path backwards, do not add the message
549234353Sdim        // if one has been previously added.
550234353Sdim        if  (!CP->hasCallStackMessage())
551234353Sdim          CP->setCallStackMessage(stackMsg);
552234353Sdim      }
553218887Sdim  }
554218887Sdim}
555218887Sdim
556234353Sdimstatic void CompactPathDiagnostic(PathPieces &path, const SourceManager& SM);
557218887Sdim
558243830Sdimstatic bool GenerateMinimalPathDiagnostic(PathDiagnostic& PD,
559218887Sdim                                          PathDiagnosticBuilder &PDB,
560234353Sdim                                          const ExplodedNode *N,
561251662Sdim                                          LocationContextMap &LCM,
562234353Sdim                                      ArrayRef<BugReporterVisitor *> visitors) {
563218887Sdim
564218887Sdim  SourceManager& SMgr = PDB.getSourceManager();
565234353Sdim  const LocationContext *LC = PDB.LC;
566226633Sdim  const ExplodedNode *NextNode = N->pred_empty()
567218887Sdim                                        ? NULL : *(N->pred_begin());
568234353Sdim
569234353Sdim  StackDiagVector CallStack;
570234353Sdim
571218887Sdim  while (NextNode) {
572218887Sdim    N = NextNode;
573234353Sdim    PDB.LC = N->getLocationContext();
574251662Sdim    NextNode = N->getFirstPred();
575218887Sdim
576218887Sdim    ProgramPoint P = N->getLocation();
577239462Sdim
578243830Sdim    do {
579249423Sdim      if (Optional<CallExitEnd> CE = P.getAs<CallExitEnd>()) {
580243830Sdim        PathDiagnosticCallPiece *C =
581243830Sdim            PathDiagnosticCallPiece::construct(N, *CE, SMgr);
582251662Sdim        // Record the mapping from call piece to LocationContext.
583251662Sdim        LCM[&C->path] = CE->getCalleeContext();
584243830Sdim        PD.getActivePath().push_front(C);
585243830Sdim        PD.pushActivePath(&C->path);
586243830Sdim        CallStack.push_back(StackDiagPair(C, N));
587243830Sdim        break;
588234353Sdim      }
589239462Sdim
590249423Sdim      if (Optional<CallEnter> CE = P.getAs<CallEnter>()) {
591243830Sdim        // Flush all locations, and pop the active path.
592243830Sdim        bool VisitedEntireCall = PD.isWithinCall();
593243830Sdim        PD.popActivePath();
594243830Sdim
595243830Sdim        // Either we just added a bunch of stuff to the top-level path, or
596243830Sdim        // we have a previous CallExitEnd.  If the former, it means that the
597243830Sdim        // path terminated within a function call.  We must then take the
598243830Sdim        // current contents of the active path and place it within
599243830Sdim        // a new PathDiagnosticCallPiece.
600243830Sdim        PathDiagnosticCallPiece *C;
601243830Sdim        if (VisitedEntireCall) {
602243830Sdim          C = cast<PathDiagnosticCallPiece>(PD.getActivePath().front());
603243830Sdim        } else {
604243830Sdim          const Decl *Caller = CE->getLocationContext()->getDecl();
605243830Sdim          C = PathDiagnosticCallPiece::construct(PD.getActivePath(), Caller);
606251662Sdim          // Record the mapping from call piece to LocationContext.
607251662Sdim          LCM[&C->path] = CE->getCalleeContext();
608243830Sdim        }
609243830Sdim
610243830Sdim        C->setCallee(*CE, SMgr);
611243830Sdim        if (!CallStack.empty()) {
612243830Sdim          assert(CallStack.back().first == C);
613243830Sdim          CallStack.pop_back();
614243830Sdim        }
615243830Sdim        break;
616234353Sdim      }
617218887Sdim
618249423Sdim      if (Optional<BlockEdge> BE = P.getAs<BlockEdge>()) {
619243830Sdim        const CFGBlock *Src = BE->getSrc();
620243830Sdim        const CFGBlock *Dst = BE->getDst();
621243830Sdim        const Stmt *T = Src->getTerminator();
622218887Sdim
623243830Sdim        if (!T)
624243830Sdim          break;
625218887Sdim
626243830Sdim        PathDiagnosticLocation Start =
627243830Sdim            PathDiagnosticLocation::createBegin(T, SMgr,
628243830Sdim                N->getLocationContext());
629218887Sdim
630243830Sdim        switch (T->getStmtClass()) {
631218887Sdim        default:
632218887Sdim          break;
633218887Sdim
634218887Sdim        case Stmt::GotoStmtClass:
635218887Sdim        case Stmt::IndirectGotoStmtClass: {
636251662Sdim          const Stmt *S = PathDiagnosticLocation::getNextStmt(N);
637218887Sdim
638218887Sdim          if (!S)
639243830Sdim            break;
640218887Sdim
641218887Sdim          std::string sbuf;
642218887Sdim          llvm::raw_string_ostream os(sbuf);
643218887Sdim          const PathDiagnosticLocation &End = PDB.getEnclosingStmtLocation(S);
644218887Sdim
645218887Sdim          os << "Control jumps to line "
646243830Sdim              << End.asLocation().getExpansionLineNumber();
647243830Sdim          PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(
648243830Sdim              Start, End, os.str()));
649218887Sdim          break;
650218887Sdim        }
651218887Sdim
652218887Sdim        case Stmt::SwitchStmtClass: {
653218887Sdim          // Figure out what case arm we took.
654218887Sdim          std::string sbuf;
655218887Sdim          llvm::raw_string_ostream os(sbuf);
656218887Sdim
657226633Sdim          if (const Stmt *S = Dst->getLabel()) {
658226633Sdim            PathDiagnosticLocation End(S, SMgr, LC);
659218887Sdim
660218887Sdim            switch (S->getStmtClass()) {
661243830Sdim            default:
662243830Sdim              os << "No cases match in the switch statement. "
663243830Sdim              "Control jumps to line "
664243830Sdim              << End.asLocation().getExpansionLineNumber();
665243830Sdim              break;
666243830Sdim            case Stmt::DefaultStmtClass:
667243830Sdim              os << "Control jumps to the 'default' case at line "
668243830Sdim              << End.asLocation().getExpansionLineNumber();
669243830Sdim              break;
670218887Sdim
671243830Sdim            case Stmt::CaseStmtClass: {
672243830Sdim              os << "Control jumps to 'case ";
673243830Sdim              const CaseStmt *Case = cast<CaseStmt>(S);
674243830Sdim              const Expr *LHS = Case->getLHS()->IgnoreParenCasts();
675218887Sdim
676243830Sdim              // Determine if it is an enum.
677243830Sdim              bool GetRawInt = true;
678218887Sdim
679243830Sdim              if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(LHS)) {
680243830Sdim                // FIXME: Maybe this should be an assertion.  Are there cases
681243830Sdim                // were it is not an EnumConstantDecl?
682243830Sdim                const EnumConstantDecl *D =
683218887Sdim                    dyn_cast<EnumConstantDecl>(DR->getDecl());
684218887Sdim
685243830Sdim                if (D) {
686243830Sdim                  GetRawInt = false;
687243830Sdim                  os << *D;
688218887Sdim                }
689243830Sdim              }
690218887Sdim
691243830Sdim              if (GetRawInt)
692243830Sdim                os << LHS->EvaluateKnownConstInt(PDB.getASTContext());
693218887Sdim
694243830Sdim              os << ":'  at line "
695243830Sdim                  << End.asLocation().getExpansionLineNumber();
696243830Sdim              break;
697218887Sdim            }
698243830Sdim            }
699243830Sdim            PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(
700243830Sdim                Start, End, os.str()));
701218887Sdim          }
702218887Sdim          else {
703218887Sdim            os << "'Default' branch taken. ";
704218887Sdim            const PathDiagnosticLocation &End = PDB.ExecutionContinues(os, N);
705243830Sdim            PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(
706243830Sdim                Start, End, os.str()));
707218887Sdim          }
708218887Sdim
709218887Sdim          break;
710218887Sdim        }
711218887Sdim
712218887Sdim        case Stmt::BreakStmtClass:
713218887Sdim        case Stmt::ContinueStmtClass: {
714218887Sdim          std::string sbuf;
715218887Sdim          llvm::raw_string_ostream os(sbuf);
716218887Sdim          PathDiagnosticLocation End = PDB.ExecutionContinues(os, N);
717243830Sdim          PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(
718243830Sdim              Start, End, os.str()));
719218887Sdim          break;
720218887Sdim        }
721218887Sdim
722243830Sdim        // Determine control-flow for ternary '?'.
723218887Sdim        case Stmt::BinaryConditionalOperatorClass:
724218887Sdim        case Stmt::ConditionalOperatorClass: {
725218887Sdim          std::string sbuf;
726218887Sdim          llvm::raw_string_ostream os(sbuf);
727218887Sdim          os << "'?' condition is ";
728218887Sdim
729218887Sdim          if (*(Src->succ_begin()+1) == Dst)
730218887Sdim            os << "false";
731218887Sdim          else
732218887Sdim            os << "true";
733218887Sdim
734218887Sdim          PathDiagnosticLocation End = PDB.ExecutionContinues(N);
735218887Sdim
736218887Sdim          if (const Stmt *S = End.asStmt())
737218887Sdim            End = PDB.getEnclosingStmtLocation(S);
738218887Sdim
739243830Sdim          PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(
740243830Sdim              Start, End, os.str()));
741218887Sdim          break;
742218887Sdim        }
743218887Sdim
744243830Sdim        // Determine control-flow for short-circuited '&&' and '||'.
745218887Sdim        case Stmt::BinaryOperatorClass: {
746218887Sdim          if (!PDB.supportsLogicalOpControlFlow())
747218887Sdim            break;
748218887Sdim
749218887Sdim          const BinaryOperator *B = cast<BinaryOperator>(T);
750218887Sdim          std::string sbuf;
751218887Sdim          llvm::raw_string_ostream os(sbuf);
752218887Sdim          os << "Left side of '";
753218887Sdim
754218887Sdim          if (B->getOpcode() == BO_LAnd) {
755218887Sdim            os << "&&" << "' is ";
756218887Sdim
757218887Sdim            if (*(Src->succ_begin()+1) == Dst) {
758218887Sdim              os << "false";
759226633Sdim              PathDiagnosticLocation End(B->getLHS(), SMgr, LC);
760226633Sdim              PathDiagnosticLocation Start =
761243830Sdim                  PathDiagnosticLocation::createOperatorLoc(B, SMgr);
762243830Sdim              PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(
763243830Sdim                  Start, End, os.str()));
764218887Sdim            }
765218887Sdim            else {
766218887Sdim              os << "true";
767226633Sdim              PathDiagnosticLocation Start(B->getLHS(), SMgr, LC);
768218887Sdim              PathDiagnosticLocation End = PDB.ExecutionContinues(N);
769243830Sdim              PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(
770243830Sdim                  Start, End, os.str()));
771218887Sdim            }
772218887Sdim          }
773218887Sdim          else {
774218887Sdim            assert(B->getOpcode() == BO_LOr);
775218887Sdim            os << "||" << "' is ";
776218887Sdim
777218887Sdim            if (*(Src->succ_begin()+1) == Dst) {
778218887Sdim              os << "false";
779226633Sdim              PathDiagnosticLocation Start(B->getLHS(), SMgr, LC);
780218887Sdim              PathDiagnosticLocation End = PDB.ExecutionContinues(N);
781243830Sdim              PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(
782243830Sdim                  Start, End, os.str()));
783218887Sdim            }
784218887Sdim            else {
785218887Sdim              os << "true";
786226633Sdim              PathDiagnosticLocation End(B->getLHS(), SMgr, LC);
787226633Sdim              PathDiagnosticLocation Start =
788243830Sdim                  PathDiagnosticLocation::createOperatorLoc(B, SMgr);
789243830Sdim              PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(
790243830Sdim                  Start, End, os.str()));
791218887Sdim            }
792218887Sdim          }
793218887Sdim
794218887Sdim          break;
795218887Sdim        }
796218887Sdim
797218887Sdim        case Stmt::DoStmtClass:  {
798218887Sdim          if (*(Src->succ_begin()) == Dst) {
799218887Sdim            std::string sbuf;
800218887Sdim            llvm::raw_string_ostream os(sbuf);
801218887Sdim
802218887Sdim            os << "Loop condition is true. ";
803218887Sdim            PathDiagnosticLocation End = PDB.ExecutionContinues(os, N);
804218887Sdim
805218887Sdim            if (const Stmt *S = End.asStmt())
806218887Sdim              End = PDB.getEnclosingStmtLocation(S);
807218887Sdim
808243830Sdim            PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(
809243830Sdim                Start, End, os.str()));
810218887Sdim          }
811218887Sdim          else {
812218887Sdim            PathDiagnosticLocation End = PDB.ExecutionContinues(N);
813218887Sdim
814218887Sdim            if (const Stmt *S = End.asStmt())
815218887Sdim              End = PDB.getEnclosingStmtLocation(S);
816218887Sdim
817243830Sdim            PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(
818243830Sdim                Start, End, "Loop condition is false.  Exiting loop"));
819218887Sdim          }
820218887Sdim
821218887Sdim          break;
822218887Sdim        }
823218887Sdim
824218887Sdim        case Stmt::WhileStmtClass:
825218887Sdim        case Stmt::ForStmtClass: {
826218887Sdim          if (*(Src->succ_begin()+1) == Dst) {
827218887Sdim            std::string sbuf;
828218887Sdim            llvm::raw_string_ostream os(sbuf);
829218887Sdim
830218887Sdim            os << "Loop condition is false. ";
831218887Sdim            PathDiagnosticLocation End = PDB.ExecutionContinues(os, N);
832218887Sdim            if (const Stmt *S = End.asStmt())
833218887Sdim              End = PDB.getEnclosingStmtLocation(S);
834218887Sdim
835243830Sdim            PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(
836243830Sdim                Start, End, os.str()));
837218887Sdim          }
838218887Sdim          else {
839218887Sdim            PathDiagnosticLocation End = PDB.ExecutionContinues(N);
840218887Sdim            if (const Stmt *S = End.asStmt())
841218887Sdim              End = PDB.getEnclosingStmtLocation(S);
842218887Sdim
843243830Sdim            PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(
844243830Sdim                Start, End, "Loop condition is true.  Entering loop body"));
845218887Sdim          }
846218887Sdim
847218887Sdim          break;
848218887Sdim        }
849218887Sdim
850218887Sdim        case Stmt::IfStmtClass: {
851218887Sdim          PathDiagnosticLocation End = PDB.ExecutionContinues(N);
852218887Sdim
853218887Sdim          if (const Stmt *S = End.asStmt())
854218887Sdim            End = PDB.getEnclosingStmtLocation(S);
855218887Sdim
856218887Sdim          if (*(Src->succ_begin()+1) == Dst)
857243830Sdim            PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(
858243830Sdim                Start, End, "Taking false branch"));
859218887Sdim          else
860243830Sdim            PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(
861243830Sdim                Start, End, "Taking true branch"));
862218887Sdim
863218887Sdim          break;
864218887Sdim        }
865243830Sdim        }
866218887Sdim      }
867243830Sdim    } while(0);
868218887Sdim
869218887Sdim    if (NextNode) {
870226633Sdim      // Add diagnostic pieces from custom visitors.
871226633Sdim      BugReport *R = PDB.getBugReport();
872234353Sdim      for (ArrayRef<BugReporterVisitor *>::iterator I = visitors.begin(),
873234353Sdim                                                    E = visitors.end();
874234353Sdim           I != E; ++I) {
875234353Sdim        if (PathDiagnosticPiece *p = (*I)->VisitNode(N, NextNode, PDB, *R)) {
876234353Sdim          PD.getActivePath().push_front(p);
877234353Sdim          updateStackPiecesWithMessage(p, CallStack);
878234353Sdim        }
879218887Sdim      }
880218887Sdim    }
881218887Sdim  }
882218887Sdim
883243830Sdim  if (!PDB.getBugReport()->isValid())
884243830Sdim    return false;
885243830Sdim
886218887Sdim  // After constructing the full PathDiagnostic, do a pass over it to compact
887218887Sdim  // PathDiagnosticPieces that occur within a macro.
888234353Sdim  CompactPathDiagnostic(PD.getMutablePieces(), PDB.getSourceManager());
889243830Sdim  return true;
890218887Sdim}
891218887Sdim
892218887Sdim//===----------------------------------------------------------------------===//
893218887Sdim// "Extensive" PathDiagnostic generation.
894218887Sdim//===----------------------------------------------------------------------===//
895218887Sdim
896218887Sdimstatic bool IsControlFlowExpr(const Stmt *S) {
897218887Sdim  const Expr *E = dyn_cast<Expr>(S);
898218887Sdim
899218887Sdim  if (!E)
900218887Sdim    return false;
901218887Sdim
902218887Sdim  E = E->IgnoreParenCasts();
903218887Sdim
904218887Sdim  if (isa<AbstractConditionalOperator>(E))
905218887Sdim    return true;
906218887Sdim
907218887Sdim  if (const BinaryOperator *B = dyn_cast<BinaryOperator>(E))
908218887Sdim    if (B->isLogicalOp())
909218887Sdim      return true;
910218887Sdim
911218887Sdim  return false;
912218887Sdim}
913218887Sdim
914218887Sdimnamespace {
915218887Sdimclass ContextLocation : public PathDiagnosticLocation {
916218887Sdim  bool IsDead;
917218887Sdimpublic:
918218887Sdim  ContextLocation(const PathDiagnosticLocation &L, bool isdead = false)
919218887Sdim    : PathDiagnosticLocation(L), IsDead(isdead) {}
920218887Sdim
921218887Sdim  void markDead() { IsDead = true; }
922218887Sdim  bool isDead() const { return IsDead; }
923218887Sdim};
924218887Sdim
925251662Sdimstatic PathDiagnosticLocation cleanUpLocation(PathDiagnosticLocation L,
926251662Sdim                                              const LocationContext *LC,
927251662Sdim                                              bool firstCharOnly = false) {
928251662Sdim  if (const Stmt *S = L.asStmt()) {
929251662Sdim    const Stmt *Original = S;
930251662Sdim    while (1) {
931251662Sdim      // Adjust the location for some expressions that are best referenced
932251662Sdim      // by one of their subexpressions.
933251662Sdim      switch (S->getStmtClass()) {
934251662Sdim        default:
935251662Sdim          break;
936251662Sdim        case Stmt::ParenExprClass:
937251662Sdim        case Stmt::GenericSelectionExprClass:
938251662Sdim          S = cast<Expr>(S)->IgnoreParens();
939251662Sdim          firstCharOnly = true;
940251662Sdim          continue;
941251662Sdim        case Stmt::BinaryConditionalOperatorClass:
942251662Sdim        case Stmt::ConditionalOperatorClass:
943251662Sdim          S = cast<AbstractConditionalOperator>(S)->getCond();
944251662Sdim          firstCharOnly = true;
945251662Sdim          continue;
946251662Sdim        case Stmt::ChooseExprClass:
947251662Sdim          S = cast<ChooseExpr>(S)->getCond();
948251662Sdim          firstCharOnly = true;
949251662Sdim          continue;
950251662Sdim        case Stmt::BinaryOperatorClass:
951251662Sdim          S = cast<BinaryOperator>(S)->getLHS();
952251662Sdim          firstCharOnly = true;
953251662Sdim          continue;
954251662Sdim      }
955251662Sdim
956251662Sdim      break;
957251662Sdim    }
958251662Sdim
959251662Sdim    if (S != Original)
960251662Sdim      L = PathDiagnosticLocation(S, L.getManager(), LC);
961251662Sdim  }
962251662Sdim
963251662Sdim  if (firstCharOnly)
964251662Sdim    L  = PathDiagnosticLocation::createSingleLocation(L);
965251662Sdim
966251662Sdim  return L;
967251662Sdim}
968251662Sdim
969218887Sdimclass EdgeBuilder {
970218887Sdim  std::vector<ContextLocation> CLocs;
971218887Sdim  typedef std::vector<ContextLocation>::iterator iterator;
972218887Sdim  PathDiagnostic &PD;
973218887Sdim  PathDiagnosticBuilder &PDB;
974218887Sdim  PathDiagnosticLocation PrevLoc;
975218887Sdim
976218887Sdim  bool IsConsumedExpr(const PathDiagnosticLocation &L);
977218887Sdim
978218887Sdim  bool containsLocation(const PathDiagnosticLocation &Container,
979218887Sdim                        const PathDiagnosticLocation &Containee);
980218887Sdim
981218887Sdim  PathDiagnosticLocation getContextLocation(const PathDiagnosticLocation &L);
982218887Sdim
983218887Sdim
984218887Sdim
985218887Sdim  void popLocation() {
986218887Sdim    if (!CLocs.back().isDead() && CLocs.back().asLocation().isFileID()) {
987218887Sdim      // For contexts, we only one the first character as the range.
988251662Sdim      rawAddEdge(cleanUpLocation(CLocs.back(), PDB.LC, true));
989218887Sdim    }
990218887Sdim    CLocs.pop_back();
991218887Sdim  }
992218887Sdim
993218887Sdimpublic:
994218887Sdim  EdgeBuilder(PathDiagnostic &pd, PathDiagnosticBuilder &pdb)
995218887Sdim    : PD(pd), PDB(pdb) {
996218887Sdim
997218887Sdim      // If the PathDiagnostic already has pieces, add the enclosing statement
998218887Sdim      // of the first piece as a context as well.
999234353Sdim      if (!PD.path.empty()) {
1000234353Sdim        PrevLoc = (*PD.path.begin())->getLocation();
1001218887Sdim
1002218887Sdim        if (const Stmt *S = PrevLoc.asStmt())
1003218887Sdim          addExtendedContext(PDB.getEnclosingStmtLocation(S).asStmt());
1004218887Sdim      }
1005218887Sdim  }
1006218887Sdim
1007218887Sdim  ~EdgeBuilder() {
1008218887Sdim    while (!CLocs.empty()) popLocation();
1009226633Sdim
1010218887Sdim    // Finally, add an initial edge from the start location of the first
1011218887Sdim    // statement (if it doesn't already exist).
1012226633Sdim    PathDiagnosticLocation L = PathDiagnosticLocation::createDeclBegin(
1013234353Sdim                                                       PDB.LC,
1014226633Sdim                                                       PDB.getSourceManager());
1015226633Sdim    if (L.isValid())
1016226633Sdim      rawAddEdge(L);
1017218887Sdim  }
1018218887Sdim
1019234353Sdim  void flushLocations() {
1020234353Sdim    while (!CLocs.empty())
1021234353Sdim      popLocation();
1022234353Sdim    PrevLoc = PathDiagnosticLocation();
1023234353Sdim  }
1024234353Sdim
1025251662Sdim  void addEdge(PathDiagnosticLocation NewLoc, bool alwaysAdd = false,
1026251662Sdim               bool IsPostJump = false);
1027218887Sdim
1028218887Sdim  void rawAddEdge(PathDiagnosticLocation NewLoc);
1029218887Sdim
1030218887Sdim  void addContext(const Stmt *S);
1031239462Sdim  void addContext(const PathDiagnosticLocation &L);
1032218887Sdim  void addExtendedContext(const Stmt *S);
1033218887Sdim};
1034218887Sdim} // end anonymous namespace
1035218887Sdim
1036218887Sdim
1037218887SdimPathDiagnosticLocation
1038218887SdimEdgeBuilder::getContextLocation(const PathDiagnosticLocation &L) {
1039218887Sdim  if (const Stmt *S = L.asStmt()) {
1040218887Sdim    if (IsControlFlowExpr(S))
1041218887Sdim      return L;
1042218887Sdim
1043218887Sdim    return PDB.getEnclosingStmtLocation(S);
1044218887Sdim  }
1045218887Sdim
1046218887Sdim  return L;
1047218887Sdim}
1048218887Sdim
1049218887Sdimbool EdgeBuilder::containsLocation(const PathDiagnosticLocation &Container,
1050218887Sdim                                   const PathDiagnosticLocation &Containee) {
1051218887Sdim
1052218887Sdim  if (Container == Containee)
1053218887Sdim    return true;
1054218887Sdim
1055218887Sdim  if (Container.asDecl())
1056218887Sdim    return true;
1057218887Sdim
1058218887Sdim  if (const Stmt *S = Containee.asStmt())
1059218887Sdim    if (const Stmt *ContainerS = Container.asStmt()) {
1060218887Sdim      while (S) {
1061218887Sdim        if (S == ContainerS)
1062218887Sdim          return true;
1063218887Sdim        S = PDB.getParent(S);
1064218887Sdim      }
1065218887Sdim      return false;
1066218887Sdim    }
1067218887Sdim
1068218887Sdim  // Less accurate: compare using source ranges.
1069218887Sdim  SourceRange ContainerR = Container.asRange();
1070218887Sdim  SourceRange ContaineeR = Containee.asRange();
1071218887Sdim
1072218887Sdim  SourceManager &SM = PDB.getSourceManager();
1073226633Sdim  SourceLocation ContainerRBeg = SM.getExpansionLoc(ContainerR.getBegin());
1074226633Sdim  SourceLocation ContainerREnd = SM.getExpansionLoc(ContainerR.getEnd());
1075226633Sdim  SourceLocation ContaineeRBeg = SM.getExpansionLoc(ContaineeR.getBegin());
1076226633Sdim  SourceLocation ContaineeREnd = SM.getExpansionLoc(ContaineeR.getEnd());
1077218887Sdim
1078226633Sdim  unsigned ContainerBegLine = SM.getExpansionLineNumber(ContainerRBeg);
1079226633Sdim  unsigned ContainerEndLine = SM.getExpansionLineNumber(ContainerREnd);
1080226633Sdim  unsigned ContaineeBegLine = SM.getExpansionLineNumber(ContaineeRBeg);
1081226633Sdim  unsigned ContaineeEndLine = SM.getExpansionLineNumber(ContaineeREnd);
1082218887Sdim
1083218887Sdim  assert(ContainerBegLine <= ContainerEndLine);
1084218887Sdim  assert(ContaineeBegLine <= ContaineeEndLine);
1085218887Sdim
1086218887Sdim  return (ContainerBegLine <= ContaineeBegLine &&
1087218887Sdim          ContainerEndLine >= ContaineeEndLine &&
1088218887Sdim          (ContainerBegLine != ContaineeBegLine ||
1089226633Sdim           SM.getExpansionColumnNumber(ContainerRBeg) <=
1090226633Sdim           SM.getExpansionColumnNumber(ContaineeRBeg)) &&
1091218887Sdim          (ContainerEndLine != ContaineeEndLine ||
1092226633Sdim           SM.getExpansionColumnNumber(ContainerREnd) >=
1093234353Sdim           SM.getExpansionColumnNumber(ContaineeREnd)));
1094218887Sdim}
1095218887Sdim
1096218887Sdimvoid EdgeBuilder::rawAddEdge(PathDiagnosticLocation NewLoc) {
1097218887Sdim  if (!PrevLoc.isValid()) {
1098218887Sdim    PrevLoc = NewLoc;
1099218887Sdim    return;
1100218887Sdim  }
1101218887Sdim
1102251662Sdim  const PathDiagnosticLocation &NewLocClean = cleanUpLocation(NewLoc, PDB.LC);
1103251662Sdim  const PathDiagnosticLocation &PrevLocClean = cleanUpLocation(PrevLoc, PDB.LC);
1104218887Sdim
1105243830Sdim  if (PrevLocClean.asLocation().isInvalid()) {
1106243830Sdim    PrevLoc = NewLoc;
1107243830Sdim    return;
1108243830Sdim  }
1109243830Sdim
1110218887Sdim  if (NewLocClean.asLocation() == PrevLocClean.asLocation())
1111218887Sdim    return;
1112218887Sdim
1113218887Sdim  // FIXME: Ignore intra-macro edges for now.
1114226633Sdim  if (NewLocClean.asLocation().getExpansionLoc() ==
1115226633Sdim      PrevLocClean.asLocation().getExpansionLoc())
1116218887Sdim    return;
1117218887Sdim
1118234353Sdim  PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(NewLocClean, PrevLocClean));
1119218887Sdim  PrevLoc = NewLoc;
1120218887Sdim}
1121218887Sdim
1122251662Sdimvoid EdgeBuilder::addEdge(PathDiagnosticLocation NewLoc, bool alwaysAdd,
1123251662Sdim                          bool IsPostJump) {
1124218887Sdim
1125218887Sdim  if (!alwaysAdd && NewLoc.asLocation().isMacroID())
1126218887Sdim    return;
1127218887Sdim
1128218887Sdim  const PathDiagnosticLocation &CLoc = getContextLocation(NewLoc);
1129218887Sdim
1130218887Sdim  while (!CLocs.empty()) {
1131218887Sdim    ContextLocation &TopContextLoc = CLocs.back();
1132218887Sdim
1133218887Sdim    // Is the top location context the same as the one for the new location?
1134218887Sdim    if (TopContextLoc == CLoc) {
1135218887Sdim      if (alwaysAdd) {
1136251662Sdim        if (IsConsumedExpr(TopContextLoc))
1137251662Sdim          TopContextLoc.markDead();
1138218887Sdim
1139218887Sdim        rawAddEdge(NewLoc);
1140218887Sdim      }
1141218887Sdim
1142251662Sdim      if (IsPostJump)
1143251662Sdim        TopContextLoc.markDead();
1144218887Sdim      return;
1145218887Sdim    }
1146218887Sdim
1147218887Sdim    if (containsLocation(TopContextLoc, CLoc)) {
1148218887Sdim      if (alwaysAdd) {
1149218887Sdim        rawAddEdge(NewLoc);
1150218887Sdim
1151251662Sdim        if (IsConsumedExpr(CLoc)) {
1152251662Sdim          CLocs.push_back(ContextLocation(CLoc, /*IsDead=*/true));
1153218887Sdim          return;
1154218887Sdim        }
1155218887Sdim      }
1156218887Sdim
1157251662Sdim      CLocs.push_back(ContextLocation(CLoc, /*IsDead=*/IsPostJump));
1158218887Sdim      return;
1159218887Sdim    }
1160218887Sdim
1161218887Sdim    // Context does not contain the location.  Flush it.
1162218887Sdim    popLocation();
1163218887Sdim  }
1164218887Sdim
1165218887Sdim  // If we reach here, there is no enclosing context.  Just add the edge.
1166218887Sdim  rawAddEdge(NewLoc);
1167218887Sdim}
1168218887Sdim
1169218887Sdimbool EdgeBuilder::IsConsumedExpr(const PathDiagnosticLocation &L) {
1170218887Sdim  if (const Expr *X = dyn_cast_or_null<Expr>(L.asStmt()))
1171218887Sdim    return PDB.getParentMap().isConsumedExpr(X) && !IsControlFlowExpr(X);
1172218887Sdim
1173218887Sdim  return false;
1174218887Sdim}
1175218887Sdim
1176218887Sdimvoid EdgeBuilder::addExtendedContext(const Stmt *S) {
1177218887Sdim  if (!S)
1178218887Sdim    return;
1179218887Sdim
1180218887Sdim  const Stmt *Parent = PDB.getParent(S);
1181218887Sdim  while (Parent) {
1182218887Sdim    if (isa<CompoundStmt>(Parent))
1183218887Sdim      Parent = PDB.getParent(Parent);
1184218887Sdim    else
1185218887Sdim      break;
1186218887Sdim  }
1187218887Sdim
1188218887Sdim  if (Parent) {
1189218887Sdim    switch (Parent->getStmtClass()) {
1190218887Sdim      case Stmt::DoStmtClass:
1191218887Sdim      case Stmt::ObjCAtSynchronizedStmtClass:
1192218887Sdim        addContext(Parent);
1193218887Sdim      default:
1194218887Sdim        break;
1195218887Sdim    }
1196218887Sdim  }
1197218887Sdim
1198218887Sdim  addContext(S);
1199218887Sdim}
1200218887Sdim
1201218887Sdimvoid EdgeBuilder::addContext(const Stmt *S) {
1202218887Sdim  if (!S)
1203218887Sdim    return;
1204218887Sdim
1205234353Sdim  PathDiagnosticLocation L(S, PDB.getSourceManager(), PDB.LC);
1206239462Sdim  addContext(L);
1207239462Sdim}
1208218887Sdim
1209239462Sdimvoid EdgeBuilder::addContext(const PathDiagnosticLocation &L) {
1210218887Sdim  while (!CLocs.empty()) {
1211218887Sdim    const PathDiagnosticLocation &TopContextLoc = CLocs.back();
1212218887Sdim
1213218887Sdim    // Is the top location context the same as the one for the new location?
1214218887Sdim    if (TopContextLoc == L)
1215218887Sdim      return;
1216218887Sdim
1217218887Sdim    if (containsLocation(TopContextLoc, L)) {
1218218887Sdim      CLocs.push_back(L);
1219218887Sdim      return;
1220218887Sdim    }
1221218887Sdim
1222218887Sdim    // Context does not contain the location.  Flush it.
1223218887Sdim    popLocation();
1224218887Sdim  }
1225218887Sdim
1226218887Sdim  CLocs.push_back(L);
1227218887Sdim}
1228218887Sdim
1229239462Sdim// Cone-of-influence: support the reverse propagation of "interesting" symbols
1230239462Sdim// and values by tracing interesting calculations backwards through evaluated
1231239462Sdim// expressions along a path.  This is probably overly complicated, but the idea
1232239462Sdim// is that if an expression computed an "interesting" value, the child
1233239462Sdim// expressions are are also likely to be "interesting" as well (which then
1234239462Sdim// propagates to the values they in turn compute).  This reverse propagation
1235239462Sdim// is needed to track interesting correlations across function call boundaries,
1236239462Sdim// where formal arguments bind to actual arguments, etc.  This is also needed
1237239462Sdim// because the constraint solver sometimes simplifies certain symbolic values
1238239462Sdim// into constants when appropriate, and this complicates reasoning about
1239239462Sdim// interesting values.
1240239462Sdimtypedef llvm::DenseSet<const Expr *> InterestingExprs;
1241239462Sdim
1242239462Sdimstatic void reversePropagateIntererstingSymbols(BugReport &R,
1243239462Sdim                                                InterestingExprs &IE,
1244239462Sdim                                                const ProgramState *State,
1245239462Sdim                                                const Expr *Ex,
1246239462Sdim                                                const LocationContext *LCtx) {
1247239462Sdim  SVal V = State->getSVal(Ex, LCtx);
1248239462Sdim  if (!(R.isInteresting(V) || IE.count(Ex)))
1249239462Sdim    return;
1250239462Sdim
1251239462Sdim  switch (Ex->getStmtClass()) {
1252239462Sdim    default:
1253239462Sdim      if (!isa<CastExpr>(Ex))
1254239462Sdim        break;
1255239462Sdim      // Fall through.
1256239462Sdim    case Stmt::BinaryOperatorClass:
1257239462Sdim    case Stmt::UnaryOperatorClass: {
1258239462Sdim      for (Stmt::const_child_iterator CI = Ex->child_begin(),
1259239462Sdim            CE = Ex->child_end();
1260239462Sdim            CI != CE; ++CI) {
1261239462Sdim        if (const Expr *child = dyn_cast_or_null<Expr>(*CI)) {
1262239462Sdim          IE.insert(child);
1263239462Sdim          SVal ChildV = State->getSVal(child, LCtx);
1264239462Sdim          R.markInteresting(ChildV);
1265239462Sdim        }
1266239462Sdim        break;
1267239462Sdim      }
1268239462Sdim    }
1269239462Sdim  }
1270239462Sdim
1271239462Sdim  R.markInteresting(V);
1272239462Sdim}
1273239462Sdim
1274239462Sdimstatic void reversePropagateInterestingSymbols(BugReport &R,
1275239462Sdim                                               InterestingExprs &IE,
1276239462Sdim                                               const ProgramState *State,
1277239462Sdim                                               const LocationContext *CalleeCtx,
1278239462Sdim                                               const LocationContext *CallerCtx)
1279239462Sdim{
1280239462Sdim  // FIXME: Handle non-CallExpr-based CallEvents.
1281239462Sdim  const StackFrameContext *Callee = CalleeCtx->getCurrentStackFrame();
1282239462Sdim  const Stmt *CallSite = Callee->getCallSite();
1283239462Sdim  if (const CallExpr *CE = dyn_cast_or_null<CallExpr>(CallSite)) {
1284239462Sdim    if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CalleeCtx->getDecl())) {
1285239462Sdim      FunctionDecl::param_const_iterator PI = FD->param_begin(),
1286239462Sdim                                         PE = FD->param_end();
1287239462Sdim      CallExpr::const_arg_iterator AI = CE->arg_begin(), AE = CE->arg_end();
1288239462Sdim      for (; AI != AE && PI != PE; ++AI, ++PI) {
1289239462Sdim        if (const Expr *ArgE = *AI) {
1290239462Sdim          if (const ParmVarDecl *PD = *PI) {
1291239462Sdim            Loc LV = State->getLValue(PD, CalleeCtx);
1292239462Sdim            if (R.isInteresting(LV) || R.isInteresting(State->getRawSVal(LV)))
1293239462Sdim              IE.insert(ArgE);
1294239462Sdim          }
1295239462Sdim        }
1296239462Sdim      }
1297239462Sdim    }
1298239462Sdim  }
1299239462Sdim}
1300249423Sdim
1301249423Sdim//===----------------------------------------------------------------------===//
1302249423Sdim// Functions for determining if a loop was executed 0 times.
1303249423Sdim//===----------------------------------------------------------------------===//
1304249423Sdim
1305263508Sdimstatic bool isLoop(const Stmt *Term) {
1306249423Sdim  switch (Term->getStmtClass()) {
1307249423Sdim    case Stmt::ForStmtClass:
1308249423Sdim    case Stmt::WhileStmtClass:
1309249423Sdim    case Stmt::ObjCForCollectionStmtClass:
1310263508Sdim    case Stmt::CXXForRangeStmtClass:
1311263508Sdim      return true;
1312249423Sdim    default:
1313249423Sdim      // Note that we intentionally do not include do..while here.
1314249423Sdim      return false;
1315249423Sdim  }
1316263508Sdim}
1317249423Sdim
1318263508Sdimstatic bool isJumpToFalseBranch(const BlockEdge *BE) {
1319249423Sdim  const CFGBlock *Src = BE->getSrc();
1320249423Sdim  assert(Src->succ_size() == 2);
1321249423Sdim  return (*(Src->succ_begin()+1) == BE->getDst());
1322249423Sdim}
1323249423Sdim
1324263508Sdim/// Return true if the terminator is a loop and the destination is the
1325263508Sdim/// false branch.
1326263508Sdimstatic bool isLoopJumpPastBody(const Stmt *Term, const BlockEdge *BE) {
1327263508Sdim  if (!isLoop(Term))
1328263508Sdim    return false;
1329263508Sdim
1330263508Sdim  // Did we take the false branch?
1331263508Sdim  return isJumpToFalseBranch(BE);
1332263508Sdim}
1333263508Sdim
1334249423Sdimstatic bool isContainedByStmt(ParentMap &PM, const Stmt *S, const Stmt *SubS) {
1335249423Sdim  while (SubS) {
1336249423Sdim    if (SubS == S)
1337249423Sdim      return true;
1338249423Sdim    SubS = PM.getParent(SubS);
1339249423Sdim  }
1340249423Sdim  return false;
1341249423Sdim}
1342249423Sdim
1343249423Sdimstatic const Stmt *getStmtBeforeCond(ParentMap &PM, const Stmt *Term,
1344249423Sdim                                     const ExplodedNode *N) {
1345249423Sdim  while (N) {
1346249423Sdim    Optional<StmtPoint> SP = N->getLocation().getAs<StmtPoint>();
1347249423Sdim    if (SP) {
1348249423Sdim      const Stmt *S = SP->getStmt();
1349249423Sdim      if (!isContainedByStmt(PM, Term, S))
1350249423Sdim        return S;
1351249423Sdim    }
1352251662Sdim    N = N->getFirstPred();
1353249423Sdim  }
1354249423Sdim  return 0;
1355249423Sdim}
1356249423Sdim
1357249423Sdimstatic bool isInLoopBody(ParentMap &PM, const Stmt *S, const Stmt *Term) {
1358249423Sdim  const Stmt *LoopBody = 0;
1359249423Sdim  switch (Term->getStmtClass()) {
1360263508Sdim    case Stmt::CXXForRangeStmtClass: {
1361263508Sdim      const CXXForRangeStmt *FR = cast<CXXForRangeStmt>(Term);
1362263508Sdim      if (isContainedByStmt(PM, FR->getInc(), S))
1363263508Sdim        return true;
1364263508Sdim      if (isContainedByStmt(PM, FR->getLoopVarStmt(), S))
1365263508Sdim        return true;
1366263508Sdim      LoopBody = FR->getBody();
1367263508Sdim      break;
1368263508Sdim    }
1369249423Sdim    case Stmt::ForStmtClass: {
1370249423Sdim      const ForStmt *FS = cast<ForStmt>(Term);
1371249423Sdim      if (isContainedByStmt(PM, FS->getInc(), S))
1372249423Sdim        return true;
1373249423Sdim      LoopBody = FS->getBody();
1374249423Sdim      break;
1375249423Sdim    }
1376249423Sdim    case Stmt::ObjCForCollectionStmtClass: {
1377249423Sdim      const ObjCForCollectionStmt *FC = cast<ObjCForCollectionStmt>(Term);
1378249423Sdim      LoopBody = FC->getBody();
1379249423Sdim      break;
1380249423Sdim    }
1381249423Sdim    case Stmt::WhileStmtClass:
1382249423Sdim      LoopBody = cast<WhileStmt>(Term)->getBody();
1383249423Sdim      break;
1384249423Sdim    default:
1385249423Sdim      return false;
1386249423Sdim  }
1387249423Sdim  return isContainedByStmt(PM, LoopBody, S);
1388249423Sdim}
1389249423Sdim
1390249423Sdim//===----------------------------------------------------------------------===//
1391249423Sdim// Top-level logic for generating extensive path diagnostics.
1392249423Sdim//===----------------------------------------------------------------------===//
1393249423Sdim
1394243830Sdimstatic bool GenerateExtensivePathDiagnostic(PathDiagnostic& PD,
1395218887Sdim                                            PathDiagnosticBuilder &PDB,
1396234353Sdim                                            const ExplodedNode *N,
1397251662Sdim                                            LocationContextMap &LCM,
1398234353Sdim                                      ArrayRef<BugReporterVisitor *> visitors) {
1399218887Sdim  EdgeBuilder EB(PD, PDB);
1400226633Sdim  const SourceManager& SM = PDB.getSourceManager();
1401234353Sdim  StackDiagVector CallStack;
1402239462Sdim  InterestingExprs IE;
1403218887Sdim
1404226633Sdim  const ExplodedNode *NextNode = N->pred_empty() ? NULL : *(N->pred_begin());
1405218887Sdim  while (NextNode) {
1406218887Sdim    N = NextNode;
1407251662Sdim    NextNode = N->getFirstPred();
1408218887Sdim    ProgramPoint P = N->getLocation();
1409218887Sdim
1410218887Sdim    do {
1411249423Sdim      if (Optional<PostStmt> PS = P.getAs<PostStmt>()) {
1412239462Sdim        if (const Expr *Ex = PS->getStmtAs<Expr>())
1413239462Sdim          reversePropagateIntererstingSymbols(*PDB.getBugReport(), IE,
1414239462Sdim                                              N->getState().getPtr(), Ex,
1415239462Sdim                                              N->getLocationContext());
1416239462Sdim      }
1417239462Sdim
1418249423Sdim      if (Optional<CallExitEnd> CE = P.getAs<CallExitEnd>()) {
1419239462Sdim        const Stmt *S = CE->getCalleeContext()->getCallSite();
1420239462Sdim        if (const Expr *Ex = dyn_cast_or_null<Expr>(S)) {
1421239462Sdim            reversePropagateIntererstingSymbols(*PDB.getBugReport(), IE,
1422239462Sdim                                                N->getState().getPtr(), Ex,
1423239462Sdim                                                N->getLocationContext());
1424239462Sdim        }
1425239462Sdim
1426234353Sdim        PathDiagnosticCallPiece *C =
1427234353Sdim          PathDiagnosticCallPiece::construct(N, *CE, SM);
1428251662Sdim        LCM[&C->path] = CE->getCalleeContext();
1429239462Sdim
1430251662Sdim        EB.addEdge(C->callReturn, /*AlwaysAdd=*/true, /*IsPostJump=*/true);
1431239462Sdim        EB.flushLocations();
1432239462Sdim
1433234353Sdim        PD.getActivePath().push_front(C);
1434234353Sdim        PD.pushActivePath(&C->path);
1435234353Sdim        CallStack.push_back(StackDiagPair(C, N));
1436234353Sdim        break;
1437234353Sdim      }
1438234353Sdim
1439234353Sdim      // Pop the call hierarchy if we are done walking the contents
1440234353Sdim      // of a function call.
1441249423Sdim      if (Optional<CallEnter> CE = P.getAs<CallEnter>()) {
1442234353Sdim        // Add an edge to the start of the function.
1443234353Sdim        const Decl *D = CE->getCalleeContext()->getDecl();
1444234353Sdim        PathDiagnosticLocation pos =
1445234353Sdim          PathDiagnosticLocation::createBegin(D, SM);
1446234353Sdim        EB.addEdge(pos);
1447234353Sdim
1448234353Sdim        // Flush all locations, and pop the active path.
1449239462Sdim        bool VisitedEntireCall = PD.isWithinCall();
1450234353Sdim        EB.flushLocations();
1451234353Sdim        PD.popActivePath();
1452234353Sdim        PDB.LC = N->getLocationContext();
1453234353Sdim
1454239462Sdim        // Either we just added a bunch of stuff to the top-level path, or
1455239462Sdim        // we have a previous CallExitEnd.  If the former, it means that the
1456234353Sdim        // path terminated within a function call.  We must then take the
1457234353Sdim        // current contents of the active path and place it within
1458234353Sdim        // a new PathDiagnosticCallPiece.
1459239462Sdim        PathDiagnosticCallPiece *C;
1460239462Sdim        if (VisitedEntireCall) {
1461239462Sdim          C = cast<PathDiagnosticCallPiece>(PD.getActivePath().front());
1462239462Sdim        } else {
1463239462Sdim          const Decl *Caller = CE->getLocationContext()->getDecl();
1464234353Sdim          C = PathDiagnosticCallPiece::construct(PD.getActivePath(), Caller);
1465251662Sdim          LCM[&C->path] = CE->getCalleeContext();
1466234353Sdim        }
1467239462Sdim
1468234353Sdim        C->setCallee(*CE, SM);
1469239462Sdim        EB.addContext(C->getLocation());
1470234353Sdim
1471234353Sdim        if (!CallStack.empty()) {
1472234353Sdim          assert(CallStack.back().first == C);
1473234353Sdim          CallStack.pop_back();
1474234353Sdim        }
1475234353Sdim        break;
1476234353Sdim      }
1477234353Sdim
1478234353Sdim      // Note that is important that we update the LocationContext
1479234353Sdim      // after looking at CallExits.  CallExit basically adds an
1480234353Sdim      // edge in the *caller*, so we don't want to update the LocationContext
1481234353Sdim      // too soon.
1482234353Sdim      PDB.LC = N->getLocationContext();
1483234353Sdim
1484218887Sdim      // Block edges.
1485249423Sdim      if (Optional<BlockEdge> BE = P.getAs<BlockEdge>()) {
1486239462Sdim        // Does this represent entering a call?  If so, look at propagating
1487239462Sdim        // interesting symbols across call boundaries.
1488239462Sdim        if (NextNode) {
1489239462Sdim          const LocationContext *CallerCtx = NextNode->getLocationContext();
1490239462Sdim          const LocationContext *CalleeCtx = PDB.LC;
1491239462Sdim          if (CallerCtx != CalleeCtx) {
1492239462Sdim            reversePropagateInterestingSymbols(*PDB.getBugReport(), IE,
1493239462Sdim                                               N->getState().getPtr(),
1494239462Sdim                                               CalleeCtx, CallerCtx);
1495239462Sdim          }
1496239462Sdim        }
1497239462Sdim
1498218887Sdim        // Are we jumping to the head of a loop?  Add a special diagnostic.
1499243830Sdim        if (const Stmt *Loop = BE->getSrc()->getLoopTarget()) {
1500234353Sdim          PathDiagnosticLocation L(Loop, SM, PDB.LC);
1501218887Sdim          const CompoundStmt *CS = NULL;
1502218887Sdim
1503243830Sdim          if (const ForStmt *FS = dyn_cast<ForStmt>(Loop))
1504243830Sdim            CS = dyn_cast<CompoundStmt>(FS->getBody());
1505243830Sdim          else if (const WhileStmt *WS = dyn_cast<WhileStmt>(Loop))
1506243830Sdim            CS = dyn_cast<CompoundStmt>(WS->getBody());
1507218887Sdim
1508218887Sdim          PathDiagnosticEventPiece *p =
1509218887Sdim            new PathDiagnosticEventPiece(L,
1510218887Sdim                                        "Looping back to the head of the loop");
1511234353Sdim          p->setPrunable(true);
1512218887Sdim
1513218887Sdim          EB.addEdge(p->getLocation(), true);
1514234353Sdim          PD.getActivePath().push_front(p);
1515218887Sdim
1516218887Sdim          if (CS) {
1517226633Sdim            PathDiagnosticLocation BL =
1518226633Sdim              PathDiagnosticLocation::createEndBrace(CS, SM);
1519218887Sdim            EB.addEdge(BL);
1520218887Sdim          }
1521218887Sdim        }
1522249423Sdim
1523249423Sdim        const CFGBlock *BSrc = BE->getSrc();
1524249423Sdim        ParentMap &PM = PDB.getParentMap();
1525249423Sdim
1526249423Sdim        if (const Stmt *Term = BSrc->getTerminator()) {
1527249423Sdim          // Are we jumping past the loop body without ever executing the
1528249423Sdim          // loop (because the condition was false)?
1529249423Sdim          if (isLoopJumpPastBody(Term, &*BE) &&
1530249423Sdim              !isInLoopBody(PM,
1531249423Sdim                            getStmtBeforeCond(PM,
1532249423Sdim                                              BSrc->getTerminatorCondition(),
1533249423Sdim                                              N),
1534249423Sdim                            Term)) {
1535249423Sdim            PathDiagnosticLocation L(Term, SM, PDB.LC);
1536249423Sdim            PathDiagnosticEventPiece *PE =
1537249423Sdim                new PathDiagnosticEventPiece(L, "Loop body executed 0 times");
1538249423Sdim            PE->setPrunable(true);
1539249423Sdim
1540249423Sdim            EB.addEdge(PE->getLocation(), true);
1541249423Sdim            PD.getActivePath().push_front(PE);
1542249423Sdim          }
1543249423Sdim
1544249423Sdim          // In any case, add the terminator as the current statement
1545249423Sdim          // context for control edges.
1546218887Sdim          EB.addContext(Term);
1547249423Sdim        }
1548218887Sdim
1549218887Sdim        break;
1550218887Sdim      }
1551218887Sdim
1552249423Sdim      if (Optional<BlockEntrance> BE = P.getAs<BlockEntrance>()) {
1553249423Sdim        Optional<CFGElement> First = BE->getFirstElement();
1554249423Sdim        if (Optional<CFGStmt> S = First ? First->getAs<CFGStmt>() : None) {
1555221345Sdim          const Stmt *stmt = S->getStmt();
1556221345Sdim          if (IsControlFlowExpr(stmt)) {
1557218887Sdim            // Add the proper context for '&&', '||', and '?'.
1558221345Sdim            EB.addContext(stmt);
1559218887Sdim          }
1560218887Sdim          else
1561221345Sdim            EB.addExtendedContext(PDB.getEnclosingStmtLocation(stmt).asStmt());
1562218887Sdim        }
1563218887Sdim
1564218887Sdim        break;
1565218887Sdim      }
1566234353Sdim
1567234353Sdim
1568218887Sdim    } while (0);
1569218887Sdim
1570218887Sdim    if (!NextNode)
1571218887Sdim      continue;
1572218887Sdim
1573226633Sdim    // Add pieces from custom visitors.
1574226633Sdim    BugReport *R = PDB.getBugReport();
1575234353Sdim    for (ArrayRef<BugReporterVisitor *>::iterator I = visitors.begin(),
1576234353Sdim                                                  E = visitors.end();
1577234353Sdim         I != E; ++I) {
1578226633Sdim      if (PathDiagnosticPiece *p = (*I)->VisitNode(N, NextNode, PDB, *R)) {
1579218887Sdim        const PathDiagnosticLocation &Loc = p->getLocation();
1580218887Sdim        EB.addEdge(Loc, true);
1581234353Sdim        PD.getActivePath().push_front(p);
1582234353Sdim        updateStackPiecesWithMessage(p, CallStack);
1583234353Sdim
1584218887Sdim        if (const Stmt *S = Loc.asStmt())
1585218887Sdim          EB.addExtendedContext(PDB.getEnclosingStmtLocation(S).asStmt());
1586218887Sdim      }
1587218887Sdim    }
1588218887Sdim  }
1589243830Sdim
1590243830Sdim  return PDB.getBugReport()->isValid();
1591218887Sdim}
1592218887Sdim
1593251662Sdim/// \brief Adds a sanitized control-flow diagnostic edge to a path.
1594251662Sdimstatic void addEdgeToPath(PathPieces &path,
1595251662Sdim                          PathDiagnosticLocation &PrevLoc,
1596251662Sdim                          PathDiagnosticLocation NewLoc,
1597251662Sdim                          const LocationContext *LC) {
1598251662Sdim  if (!NewLoc.isValid())
1599251662Sdim    return;
1600251662Sdim
1601251662Sdim  SourceLocation NewLocL = NewLoc.asLocation();
1602263508Sdim  if (NewLocL.isInvalid())
1603251662Sdim    return;
1604251662Sdim
1605263508Sdim  if (!PrevLoc.isValid() || !PrevLoc.asLocation().isValid()) {
1606251662Sdim    PrevLoc = NewLoc;
1607251662Sdim    return;
1608251662Sdim  }
1609251662Sdim
1610263508Sdim  // Ignore self-edges, which occur when there are multiple nodes at the same
1611263508Sdim  // statement.
1612263508Sdim  if (NewLoc.asStmt() && NewLoc.asStmt() == PrevLoc.asStmt())
1613251662Sdim    return;
1614251662Sdim
1615251662Sdim  path.push_front(new PathDiagnosticControlFlowPiece(NewLoc,
1616251662Sdim                                                     PrevLoc));
1617251662Sdim  PrevLoc = NewLoc;
1618251662Sdim}
1619251662Sdim
1620263508Sdim/// A customized wrapper for CFGBlock::getTerminatorCondition()
1621263508Sdim/// which returns the element for ObjCForCollectionStmts.
1622263508Sdimstatic const Stmt *getTerminatorCondition(const CFGBlock *B) {
1623263508Sdim  const Stmt *S = B->getTerminatorCondition();
1624263508Sdim  if (const ObjCForCollectionStmt *FS =
1625263508Sdim      dyn_cast_or_null<ObjCForCollectionStmt>(S))
1626263508Sdim    return FS->getElement();
1627263508Sdim  return S;
1628263508Sdim}
1629263508Sdim
1630263508Sdimstatic const char StrEnteringLoop[] = "Entering loop body";
1631263508Sdimstatic const char StrLoopBodyZero[] = "Loop body executed 0 times";
1632263508Sdimstatic const char StrLoopRangeEmpty[] =
1633263508Sdim  "Loop body skipped when range is empty";
1634263508Sdimstatic const char StrLoopCollectionEmpty[] =
1635263508Sdim  "Loop body skipped when collection is empty";
1636263508Sdim
1637251662Sdimstatic bool
1638251662SdimGenerateAlternateExtensivePathDiagnostic(PathDiagnostic& PD,
1639251662Sdim                                         PathDiagnosticBuilder &PDB,
1640251662Sdim                                         const ExplodedNode *N,
1641251662Sdim                                         LocationContextMap &LCM,
1642251662Sdim                                      ArrayRef<BugReporterVisitor *> visitors) {
1643251662Sdim
1644251662Sdim  BugReport *report = PDB.getBugReport();
1645251662Sdim  const SourceManager& SM = PDB.getSourceManager();
1646251662Sdim  StackDiagVector CallStack;
1647251662Sdim  InterestingExprs IE;
1648251662Sdim
1649263508Sdim  PathDiagnosticLocation PrevLoc = PD.getLocation();
1650251662Sdim
1651251662Sdim  const ExplodedNode *NextNode = N->getFirstPred();
1652251662Sdim  while (NextNode) {
1653251662Sdim    N = NextNode;
1654251662Sdim    NextNode = N->getFirstPred();
1655251662Sdim    ProgramPoint P = N->getLocation();
1656251662Sdim
1657251662Sdim    do {
1658263508Sdim      // Have we encountered an entrance to a call?  It may be
1659263508Sdim      // the case that we have not encountered a matching
1660263508Sdim      // call exit before this point.  This means that the path
1661263508Sdim      // terminated within the call itself.
1662263508Sdim      if (Optional<CallEnter> CE = P.getAs<CallEnter>()) {
1663263508Sdim        // Add an edge to the start of the function.
1664263508Sdim        const StackFrameContext *CalleeLC = CE->getCalleeContext();
1665263508Sdim        const Decl *D = CalleeLC->getDecl();
1666263508Sdim        addEdgeToPath(PD.getActivePath(), PrevLoc,
1667263508Sdim                      PathDiagnosticLocation::createBegin(D, SM),
1668263508Sdim                      CalleeLC);
1669251662Sdim
1670263508Sdim        // Did we visit an entire call?
1671263508Sdim        bool VisitedEntireCall = PD.isWithinCall();
1672263508Sdim        PD.popActivePath();
1673263508Sdim
1674263508Sdim        PathDiagnosticCallPiece *C;
1675263508Sdim        if (VisitedEntireCall) {
1676263508Sdim          PathDiagnosticPiece *P = PD.getActivePath().front().getPtr();
1677263508Sdim          C = cast<PathDiagnosticCallPiece>(P);
1678263508Sdim        } else {
1679263508Sdim          const Decl *Caller = CE->getLocationContext()->getDecl();
1680263508Sdim          C = PathDiagnosticCallPiece::construct(PD.getActivePath(), Caller);
1681263508Sdim
1682263508Sdim          // Since we just transferred the path over to the call piece,
1683263508Sdim          // reset the mapping from active to location context.
1684263508Sdim          assert(PD.getActivePath().size() == 1 &&
1685263508Sdim                 PD.getActivePath().front() == C);
1686263508Sdim          LCM[&PD.getActivePath()] = 0;
1687263508Sdim
1688263508Sdim          // Record the location context mapping for the path within
1689263508Sdim          // the call.
1690263508Sdim          assert(LCM[&C->path] == 0 ||
1691263508Sdim                 LCM[&C->path] == CE->getCalleeContext());
1692263508Sdim          LCM[&C->path] = CE->getCalleeContext();
1693263508Sdim
1694263508Sdim          // If this is the first item in the active path, record
1695263508Sdim          // the new mapping from active path to location context.
1696263508Sdim          const LocationContext *&NewLC = LCM[&PD.getActivePath()];
1697263508Sdim          if (!NewLC)
1698263508Sdim            NewLC = N->getLocationContext();
1699263508Sdim
1700263508Sdim          PDB.LC = NewLC;
1701263508Sdim        }
1702263508Sdim        C->setCallee(*CE, SM);
1703263508Sdim
1704263508Sdim        // Update the previous location in the active path.
1705263508Sdim        PrevLoc = C->getLocation();
1706263508Sdim
1707263508Sdim        if (!CallStack.empty()) {
1708263508Sdim          assert(CallStack.back().first == C);
1709263508Sdim          CallStack.pop_back();
1710263508Sdim        }
1711251662Sdim        break;
1712251662Sdim      }
1713251662Sdim
1714263508Sdim      // Query the location context here and the previous location
1715263508Sdim      // as processing CallEnter may change the active path.
1716263508Sdim      PDB.LC = N->getLocationContext();
1717263508Sdim
1718263508Sdim      // Record the mapping from the active path to the location
1719263508Sdim      // context.
1720263508Sdim      assert(!LCM[&PD.getActivePath()] ||
1721263508Sdim             LCM[&PD.getActivePath()] == PDB.LC);
1722263508Sdim      LCM[&PD.getActivePath()] = PDB.LC;
1723263508Sdim
1724251662Sdim      // Have we encountered an exit from a function call?
1725251662Sdim      if (Optional<CallExitEnd> CE = P.getAs<CallExitEnd>()) {
1726251662Sdim        const Stmt *S = CE->getCalleeContext()->getCallSite();
1727251662Sdim        // Propagate the interesting symbols accordingly.
1728251662Sdim        if (const Expr *Ex = dyn_cast_or_null<Expr>(S)) {
1729251662Sdim          reversePropagateIntererstingSymbols(*PDB.getBugReport(), IE,
1730251662Sdim                                              N->getState().getPtr(), Ex,
1731251662Sdim                                              N->getLocationContext());
1732251662Sdim        }
1733251662Sdim
1734251662Sdim        // We are descending into a call (backwards).  Construct
1735251662Sdim        // a new call piece to contain the path pieces for that call.
1736251662Sdim        PathDiagnosticCallPiece *C =
1737251662Sdim          PathDiagnosticCallPiece::construct(N, *CE, SM);
1738251662Sdim
1739251662Sdim        // Record the location context for this call piece.
1740251662Sdim        LCM[&C->path] = CE->getCalleeContext();
1741251662Sdim
1742251662Sdim        // Add the edge to the return site.
1743263508Sdim        addEdgeToPath(PD.getActivePath(), PrevLoc, C->callReturn, PDB.LC);
1744263508Sdim        PD.getActivePath().push_front(C);
1745263508Sdim        PrevLoc.invalidate();
1746251662Sdim
1747251662Sdim        // Make the contents of the call the active path for now.
1748251662Sdim        PD.pushActivePath(&C->path);
1749251662Sdim        CallStack.push_back(StackDiagPair(C, N));
1750251662Sdim        break;
1751251662Sdim      }
1752251662Sdim
1753263508Sdim      if (Optional<PostStmt> PS = P.getAs<PostStmt>()) {
1754263508Sdim        // For expressions, make sure we propagate the
1755263508Sdim        // interesting symbols correctly.
1756263508Sdim        if (const Expr *Ex = PS->getStmtAs<Expr>())
1757263508Sdim          reversePropagateIntererstingSymbols(*PDB.getBugReport(), IE,
1758263508Sdim                                              N->getState().getPtr(), Ex,
1759263508Sdim                                              N->getLocationContext());
1760251662Sdim
1761263508Sdim        // Add an edge.  If this is an ObjCForCollectionStmt do
1762263508Sdim        // not add an edge here as it appears in the CFG both
1763263508Sdim        // as a terminator and as a terminator condition.
1764263508Sdim        if (!isa<ObjCForCollectionStmt>(PS->getStmt())) {
1765263508Sdim          PathDiagnosticLocation L =
1766263508Sdim            PathDiagnosticLocation(PS->getStmt(), SM, PDB.LC);
1767263508Sdim          addEdgeToPath(PD.getActivePath(), PrevLoc, L, PDB.LC);
1768251662Sdim        }
1769251662Sdim        break;
1770251662Sdim      }
1771251662Sdim
1772251662Sdim      // Block edges.
1773251662Sdim      if (Optional<BlockEdge> BE = P.getAs<BlockEdge>()) {
1774251662Sdim        // Does this represent entering a call?  If so, look at propagating
1775251662Sdim        // interesting symbols across call boundaries.
1776251662Sdim        if (NextNode) {
1777251662Sdim          const LocationContext *CallerCtx = NextNode->getLocationContext();
1778251662Sdim          const LocationContext *CalleeCtx = PDB.LC;
1779251662Sdim          if (CallerCtx != CalleeCtx) {
1780251662Sdim            reversePropagateInterestingSymbols(*PDB.getBugReport(), IE,
1781251662Sdim                                               N->getState().getPtr(),
1782251662Sdim                                               CalleeCtx, CallerCtx);
1783251662Sdim          }
1784251662Sdim        }
1785251662Sdim
1786251662Sdim        // Are we jumping to the head of a loop?  Add a special diagnostic.
1787251662Sdim        if (const Stmt *Loop = BE->getSrc()->getLoopTarget()) {
1788251662Sdim          PathDiagnosticLocation L(Loop, SM, PDB.LC);
1789263508Sdim          const Stmt *Body = NULL;
1790251662Sdim
1791251662Sdim          if (const ForStmt *FS = dyn_cast<ForStmt>(Loop))
1792263508Sdim            Body = FS->getBody();
1793251662Sdim          else if (const WhileStmt *WS = dyn_cast<WhileStmt>(Loop))
1794263508Sdim            Body = WS->getBody();
1795263508Sdim          else if (const ObjCForCollectionStmt *OFS =
1796263508Sdim                     dyn_cast<ObjCForCollectionStmt>(Loop)) {
1797263508Sdim            Body = OFS->getBody();
1798263508Sdim          } else if (const CXXForRangeStmt *FRS =
1799263508Sdim                       dyn_cast<CXXForRangeStmt>(Loop)) {
1800263508Sdim            Body = FRS->getBody();
1801263508Sdim          }
1802263508Sdim          // do-while statements are explicitly excluded here
1803251662Sdim
1804251662Sdim          PathDiagnosticEventPiece *p =
1805251662Sdim            new PathDiagnosticEventPiece(L, "Looping back to the head "
1806251662Sdim                                            "of the loop");
1807251662Sdim          p->setPrunable(true);
1808251662Sdim
1809263508Sdim          addEdgeToPath(PD.getActivePath(), PrevLoc, p->getLocation(), PDB.LC);
1810251662Sdim          PD.getActivePath().push_front(p);
1811251662Sdim
1812263508Sdim          if (const CompoundStmt *CS = dyn_cast_or_null<CompoundStmt>(Body)) {
1813251662Sdim            addEdgeToPath(PD.getActivePath(), PrevLoc,
1814263508Sdim                          PathDiagnosticLocation::createEndBrace(CS, SM),
1815263508Sdim                          PDB.LC);
1816251662Sdim          }
1817251662Sdim        }
1818263508Sdim
1819251662Sdim        const CFGBlock *BSrc = BE->getSrc();
1820251662Sdim        ParentMap &PM = PDB.getParentMap();
1821251662Sdim
1822251662Sdim        if (const Stmt *Term = BSrc->getTerminator()) {
1823251662Sdim          // Are we jumping past the loop body without ever executing the
1824251662Sdim          // loop (because the condition was false)?
1825263508Sdim          if (isLoop(Term)) {
1826263508Sdim            const Stmt *TermCond = getTerminatorCondition(BSrc);
1827263508Sdim            bool IsInLoopBody =
1828263508Sdim              isInLoopBody(PM, getStmtBeforeCond(PM, TermCond, N), Term);
1829263508Sdim
1830263508Sdim            const char *str = 0;
1831263508Sdim
1832263508Sdim            if (isJumpToFalseBranch(&*BE)) {
1833263508Sdim              if (!IsInLoopBody) {
1834263508Sdim                if (isa<ObjCForCollectionStmt>(Term)) {
1835263508Sdim                  str = StrLoopCollectionEmpty;
1836263508Sdim                } else if (isa<CXXForRangeStmt>(Term)) {
1837263508Sdim                  str = StrLoopRangeEmpty;
1838263508Sdim                } else {
1839263508Sdim                  str = StrLoopBodyZero;
1840263508Sdim                }
1841263508Sdim              }
1842263508Sdim            } else {
1843263508Sdim              str = StrEnteringLoop;
1844263508Sdim            }
1845263508Sdim
1846263508Sdim            if (str) {
1847263508Sdim              PathDiagnosticLocation L(TermCond ? TermCond : Term, SM, PDB.LC);
1848263508Sdim              PathDiagnosticEventPiece *PE =
1849263508Sdim                new PathDiagnosticEventPiece(L, str);
1850263508Sdim              PE->setPrunable(true);
1851263508Sdim              addEdgeToPath(PD.getActivePath(), PrevLoc,
1852263508Sdim                            PE->getLocation(), PDB.LC);
1853263508Sdim              PD.getActivePath().push_front(PE);
1854263508Sdim            }
1855263508Sdim          } else if (isa<BreakStmt>(Term) || isa<ContinueStmt>(Term) ||
1856263508Sdim                     isa<GotoStmt>(Term)) {
1857251662Sdim            PathDiagnosticLocation L(Term, SM, PDB.LC);
1858263508Sdim            addEdgeToPath(PD.getActivePath(), PrevLoc, L, PDB.LC);
1859251662Sdim          }
1860251662Sdim        }
1861251662Sdim        break;
1862251662Sdim      }
1863251662Sdim    } while (0);
1864251662Sdim
1865251662Sdim    if (!NextNode)
1866251662Sdim      continue;
1867251662Sdim
1868251662Sdim    // Add pieces from custom visitors.
1869251662Sdim    for (ArrayRef<BugReporterVisitor *>::iterator I = visitors.begin(),
1870251662Sdim         E = visitors.end();
1871251662Sdim         I != E; ++I) {
1872251662Sdim      if (PathDiagnosticPiece *p = (*I)->VisitNode(N, NextNode, PDB, *report)) {
1873263508Sdim        addEdgeToPath(PD.getActivePath(), PrevLoc, p->getLocation(), PDB.LC);
1874251662Sdim        PD.getActivePath().push_front(p);
1875251662Sdim        updateStackPiecesWithMessage(p, CallStack);
1876251662Sdim      }
1877251662Sdim    }
1878251662Sdim  }
1879251662Sdim
1880263508Sdim  // Add an edge to the start of the function.
1881263508Sdim  // We'll prune it out later, but it helps make diagnostics more uniform.
1882263508Sdim  const StackFrameContext *CalleeLC = PDB.LC->getCurrentStackFrame();
1883263508Sdim  const Decl *D = CalleeLC->getDecl();
1884263508Sdim  addEdgeToPath(PD.getActivePath(), PrevLoc,
1885263508Sdim                PathDiagnosticLocation::createBegin(D, SM),
1886263508Sdim                CalleeLC);
1887263508Sdim
1888251662Sdim  return report->isValid();
1889251662Sdim}
1890251662Sdim
1891263508Sdimstatic const Stmt *getLocStmt(PathDiagnosticLocation L) {
1892251662Sdim  if (!L.isValid())
1893251662Sdim    return 0;
1894251662Sdim  return L.asStmt();
1895251662Sdim}
1896251662Sdim
1897263508Sdimstatic const Stmt *getStmtParent(const Stmt *S, const ParentMap &PM) {
1898251662Sdim  if (!S)
1899251662Sdim    return 0;
1900263508Sdim
1901263508Sdim  while (true) {
1902263508Sdim    S = PM.getParentIgnoreParens(S);
1903263508Sdim
1904263508Sdim    if (!S)
1905263508Sdim      break;
1906263508Sdim
1907263508Sdim    if (isa<ExprWithCleanups>(S) ||
1908263508Sdim        isa<CXXBindTemporaryExpr>(S) ||
1909263508Sdim        isa<SubstNonTypeTemplateParmExpr>(S))
1910263508Sdim      continue;
1911263508Sdim
1912263508Sdim    break;
1913263508Sdim  }
1914263508Sdim
1915263508Sdim  return S;
1916251662Sdim}
1917251662Sdim
1918251662Sdimstatic bool isConditionForTerminator(const Stmt *S, const Stmt *Cond) {
1919251662Sdim  switch (S->getStmtClass()) {
1920263508Sdim    case Stmt::BinaryOperatorClass: {
1921263508Sdim      const BinaryOperator *BO = cast<BinaryOperator>(S);
1922263508Sdim      if (!BO->isLogicalOp())
1923263508Sdim        return false;
1924263508Sdim      return BO->getLHS() == Cond || BO->getRHS() == Cond;
1925263508Sdim    }
1926263508Sdim    case Stmt::IfStmtClass:
1927263508Sdim      return cast<IfStmt>(S)->getCond() == Cond;
1928251662Sdim    case Stmt::ForStmtClass:
1929251662Sdim      return cast<ForStmt>(S)->getCond() == Cond;
1930251662Sdim    case Stmt::WhileStmtClass:
1931251662Sdim      return cast<WhileStmt>(S)->getCond() == Cond;
1932251662Sdim    case Stmt::DoStmtClass:
1933251662Sdim      return cast<DoStmt>(S)->getCond() == Cond;
1934251662Sdim    case Stmt::ChooseExprClass:
1935251662Sdim      return cast<ChooseExpr>(S)->getCond() == Cond;
1936251662Sdim    case Stmt::IndirectGotoStmtClass:
1937251662Sdim      return cast<IndirectGotoStmt>(S)->getTarget() == Cond;
1938251662Sdim    case Stmt::SwitchStmtClass:
1939251662Sdim      return cast<SwitchStmt>(S)->getCond() == Cond;
1940251662Sdim    case Stmt::BinaryConditionalOperatorClass:
1941251662Sdim      return cast<BinaryConditionalOperator>(S)->getCond() == Cond;
1942263508Sdim    case Stmt::ConditionalOperatorClass: {
1943263508Sdim      const ConditionalOperator *CO = cast<ConditionalOperator>(S);
1944263508Sdim      return CO->getCond() == Cond ||
1945263508Sdim             CO->getLHS() == Cond ||
1946263508Sdim             CO->getRHS() == Cond;
1947263508Sdim    }
1948251662Sdim    case Stmt::ObjCForCollectionStmtClass:
1949251662Sdim      return cast<ObjCForCollectionStmt>(S)->getElement() == Cond;
1950263508Sdim    case Stmt::CXXForRangeStmtClass: {
1951263508Sdim      const CXXForRangeStmt *FRS = cast<CXXForRangeStmt>(S);
1952263508Sdim      return FRS->getCond() == Cond || FRS->getRangeInit() == Cond;
1953263508Sdim    }
1954251662Sdim    default:
1955251662Sdim      return false;
1956251662Sdim  }
1957251662Sdim}
1958251662Sdim
1959263508Sdimstatic bool isIncrementOrInitInForLoop(const Stmt *S, const Stmt *FL) {
1960263508Sdim  if (const ForStmt *FS = dyn_cast<ForStmt>(FL))
1961263508Sdim    return FS->getInc() == S || FS->getInit() == S;
1962263508Sdim  if (const CXXForRangeStmt *FRS = dyn_cast<CXXForRangeStmt>(FL))
1963263508Sdim    return FRS->getInc() == S || FRS->getRangeStmt() == S ||
1964263508Sdim           FRS->getLoopVarStmt() || FRS->getRangeInit() == S;
1965263508Sdim  return false;
1966263508Sdim}
1967251662Sdim
1968251662Sdimtypedef llvm::DenseSet<const PathDiagnosticCallPiece *>
1969251662Sdim        OptimizedCallsSet;
1970251662Sdim
1971263508Sdim/// Adds synthetic edges from top-level statements to their subexpressions.
1972263508Sdim///
1973263508Sdim/// This avoids a "swoosh" effect, where an edge from a top-level statement A
1974263508Sdim/// points to a sub-expression B.1 that's not at the start of B. In these cases,
1975263508Sdim/// we'd like to see an edge from A to B, then another one from B to B.1.
1976263508Sdimstatic void addContextEdges(PathPieces &pieces, SourceManager &SM,
1977263508Sdim                            const ParentMap &PM, const LocationContext *LCtx) {
1978263508Sdim  PathPieces::iterator Prev = pieces.end();
1979263508Sdim  for (PathPieces::iterator I = pieces.begin(), E = Prev; I != E;
1980263508Sdim       Prev = I, ++I) {
1981263508Sdim    PathDiagnosticControlFlowPiece *Piece =
1982263508Sdim      dyn_cast<PathDiagnosticControlFlowPiece>(*I);
1983263508Sdim
1984263508Sdim    if (!Piece)
1985263508Sdim      continue;
1986263508Sdim
1987263508Sdim    PathDiagnosticLocation SrcLoc = Piece->getStartLocation();
1988263508Sdim    SmallVector<PathDiagnosticLocation, 4> SrcContexts;
1989263508Sdim
1990263508Sdim    PathDiagnosticLocation NextSrcContext = SrcLoc;
1991263508Sdim    const Stmt *InnerStmt = 0;
1992263508Sdim    while (NextSrcContext.isValid() && NextSrcContext.asStmt() != InnerStmt) {
1993263508Sdim      SrcContexts.push_back(NextSrcContext);
1994263508Sdim      InnerStmt = NextSrcContext.asStmt();
1995263508Sdim      NextSrcContext = getEnclosingStmtLocation(InnerStmt, SM, PM, LCtx,
1996263508Sdim                                                /*allowNested=*/true);
1997263508Sdim    }
1998263508Sdim
1999263508Sdim    // Repeatedly split the edge as necessary.
2000263508Sdim    // This is important for nested logical expressions (||, &&, ?:) where we
2001263508Sdim    // want to show all the levels of context.
2002263508Sdim    while (true) {
2003263508Sdim      const Stmt *Dst = getLocStmt(Piece->getEndLocation());
2004263508Sdim
2005263508Sdim      // We are looking at an edge. Is the destination within a larger
2006263508Sdim      // expression?
2007263508Sdim      PathDiagnosticLocation DstContext =
2008263508Sdim        getEnclosingStmtLocation(Dst, SM, PM, LCtx, /*allowNested=*/true);
2009263508Sdim      if (!DstContext.isValid() || DstContext.asStmt() == Dst)
2010263508Sdim        break;
2011263508Sdim
2012263508Sdim      // If the source is in the same context, we're already good.
2013263508Sdim      if (std::find(SrcContexts.begin(), SrcContexts.end(), DstContext) !=
2014263508Sdim          SrcContexts.end())
2015263508Sdim        break;
2016263508Sdim
2017263508Sdim      // Update the subexpression node to point to the context edge.
2018263508Sdim      Piece->setStartLocation(DstContext);
2019263508Sdim
2020263508Sdim      // Try to extend the previous edge if it's at the same level as the source
2021263508Sdim      // context.
2022263508Sdim      if (Prev != E) {
2023263508Sdim        PathDiagnosticControlFlowPiece *PrevPiece =
2024263508Sdim          dyn_cast<PathDiagnosticControlFlowPiece>(*Prev);
2025263508Sdim
2026263508Sdim        if (PrevPiece) {
2027263508Sdim          if (const Stmt *PrevSrc = getLocStmt(PrevPiece->getStartLocation())) {
2028263508Sdim            const Stmt *PrevSrcParent = getStmtParent(PrevSrc, PM);
2029263508Sdim            if (PrevSrcParent == getStmtParent(getLocStmt(DstContext), PM)) {
2030263508Sdim              PrevPiece->setEndLocation(DstContext);
2031263508Sdim              break;
2032263508Sdim            }
2033263508Sdim          }
2034263508Sdim        }
2035263508Sdim      }
2036263508Sdim
2037263508Sdim      // Otherwise, split the current edge into a context edge and a
2038263508Sdim      // subexpression edge. Note that the context statement may itself have
2039263508Sdim      // context.
2040263508Sdim      Piece = new PathDiagnosticControlFlowPiece(SrcLoc, DstContext);
2041263508Sdim      I = pieces.insert(I, Piece);
2042263508Sdim    }
2043263508Sdim  }
2044251662Sdim}
2045251662Sdim
2046263508Sdim/// \brief Move edges from a branch condition to a branch target
2047263508Sdim///        when the condition is simple.
2048263508Sdim///
2049263508Sdim/// This restructures some of the work of addContextEdges.  That function
2050263508Sdim/// creates edges this may destroy, but they work together to create a more
2051263508Sdim/// aesthetically set of edges around branches.  After the call to
2052263508Sdim/// addContextEdges, we may have (1) an edge to the branch, (2) an edge from
2053263508Sdim/// the branch to the branch condition, and (3) an edge from the branch
2054263508Sdim/// condition to the branch target.  We keep (1), but may wish to remove (2)
2055263508Sdim/// and move the source of (3) to the branch if the branch condition is simple.
2056263508Sdim///
2057263508Sdimstatic void simplifySimpleBranches(PathPieces &pieces) {
2058263508Sdim  for (PathPieces::iterator I = pieces.begin(), E = pieces.end(); I != E; ++I) {
2059263508Sdim
2060263508Sdim    PathDiagnosticControlFlowPiece *PieceI =
2061263508Sdim      dyn_cast<PathDiagnosticControlFlowPiece>(*I);
2062263508Sdim
2063263508Sdim    if (!PieceI)
2064263508Sdim      continue;
2065263508Sdim
2066263508Sdim    const Stmt *s1Start = getLocStmt(PieceI->getStartLocation());
2067263508Sdim    const Stmt *s1End   = getLocStmt(PieceI->getEndLocation());
2068263508Sdim
2069263508Sdim    if (!s1Start || !s1End)
2070263508Sdim      continue;
2071263508Sdim
2072263508Sdim    PathPieces::iterator NextI = I; ++NextI;
2073263508Sdim    if (NextI == E)
2074263508Sdim      break;
2075263508Sdim
2076263508Sdim    PathDiagnosticControlFlowPiece *PieceNextI = 0;
2077263508Sdim
2078263508Sdim    while (true) {
2079263508Sdim      if (NextI == E)
2080263508Sdim        break;
2081263508Sdim
2082263508Sdim      PathDiagnosticEventPiece *EV = dyn_cast<PathDiagnosticEventPiece>(*NextI);
2083263508Sdim      if (EV) {
2084263508Sdim        StringRef S = EV->getString();
2085263508Sdim        if (S == StrEnteringLoop || S == StrLoopBodyZero ||
2086263508Sdim            S == StrLoopCollectionEmpty || S == StrLoopRangeEmpty) {
2087263508Sdim          ++NextI;
2088263508Sdim          continue;
2089263508Sdim        }
2090263508Sdim        break;
2091263508Sdim      }
2092263508Sdim
2093263508Sdim      PieceNextI = dyn_cast<PathDiagnosticControlFlowPiece>(*NextI);
2094263508Sdim      break;
2095263508Sdim    }
2096263508Sdim
2097263508Sdim    if (!PieceNextI)
2098263508Sdim      continue;
2099263508Sdim
2100263508Sdim    const Stmt *s2Start = getLocStmt(PieceNextI->getStartLocation());
2101263508Sdim    const Stmt *s2End   = getLocStmt(PieceNextI->getEndLocation());
2102263508Sdim
2103263508Sdim    if (!s2Start || !s2End || s1End != s2Start)
2104263508Sdim      continue;
2105263508Sdim
2106263508Sdim    // We only perform this transformation for specific branch kinds.
2107263508Sdim    // We don't want to do this for do..while, for example.
2108263508Sdim    if (!(isa<ForStmt>(s1Start) || isa<WhileStmt>(s1Start) ||
2109263508Sdim          isa<IfStmt>(s1Start) || isa<ObjCForCollectionStmt>(s1Start) ||
2110263508Sdim          isa<CXXForRangeStmt>(s1Start)))
2111263508Sdim      continue;
2112263508Sdim
2113263508Sdim    // Is s1End the branch condition?
2114263508Sdim    if (!isConditionForTerminator(s1Start, s1End))
2115263508Sdim      continue;
2116263508Sdim
2117263508Sdim    // Perform the hoisting by eliminating (2) and changing the start
2118263508Sdim    // location of (3).
2119263508Sdim    PieceNextI->setStartLocation(PieceI->getStartLocation());
2120263508Sdim    I = pieces.erase(I);
2121263508Sdim  }
2122263508Sdim}
2123263508Sdim
2124263508Sdim/// Returns the number of bytes in the given (character-based) SourceRange.
2125263508Sdim///
2126263508Sdim/// If the locations in the range are not on the same line, returns None.
2127263508Sdim///
2128263508Sdim/// Note that this does not do a precise user-visible character or column count.
2129263508Sdimstatic Optional<size_t> getLengthOnSingleLine(SourceManager &SM,
2130263508Sdim                                              SourceRange Range) {
2131263508Sdim  SourceRange ExpansionRange(SM.getExpansionLoc(Range.getBegin()),
2132263508Sdim                             SM.getExpansionRange(Range.getEnd()).second);
2133263508Sdim
2134263508Sdim  FileID FID = SM.getFileID(ExpansionRange.getBegin());
2135263508Sdim  if (FID != SM.getFileID(ExpansionRange.getEnd()))
2136263508Sdim    return None;
2137263508Sdim
2138263508Sdim  bool Invalid;
2139263508Sdim  const llvm::MemoryBuffer *Buffer = SM.getBuffer(FID, &Invalid);
2140263508Sdim  if (Invalid)
2141263508Sdim    return None;
2142263508Sdim
2143263508Sdim  unsigned BeginOffset = SM.getFileOffset(ExpansionRange.getBegin());
2144263508Sdim  unsigned EndOffset = SM.getFileOffset(ExpansionRange.getEnd());
2145263508Sdim  StringRef Snippet = Buffer->getBuffer().slice(BeginOffset, EndOffset);
2146263508Sdim
2147263508Sdim  // We're searching the raw bytes of the buffer here, which might include
2148263508Sdim  // escaped newlines and such. That's okay; we're trying to decide whether the
2149263508Sdim  // SourceRange is covering a large or small amount of space in the user's
2150263508Sdim  // editor.
2151263508Sdim  if (Snippet.find_first_of("\r\n") != StringRef::npos)
2152263508Sdim    return None;
2153263508Sdim
2154263508Sdim  // This isn't Unicode-aware, but it doesn't need to be.
2155263508Sdim  return Snippet.size();
2156263508Sdim}
2157263508Sdim
2158263508Sdim/// \sa getLengthOnSingleLine(SourceManager, SourceRange)
2159263508Sdimstatic Optional<size_t> getLengthOnSingleLine(SourceManager &SM,
2160263508Sdim                                              const Stmt *S) {
2161263508Sdim  return getLengthOnSingleLine(SM, S->getSourceRange());
2162263508Sdim}
2163263508Sdim
2164263508Sdim/// Eliminate two-edge cycles created by addContextEdges().
2165263508Sdim///
2166263508Sdim/// Once all the context edges are in place, there are plenty of cases where
2167263508Sdim/// there's a single edge from a top-level statement to a subexpression,
2168263508Sdim/// followed by a single path note, and then a reverse edge to get back out to
2169263508Sdim/// the top level. If the statement is simple enough, the subexpression edges
2170263508Sdim/// just add noise and make it harder to understand what's going on.
2171263508Sdim///
2172263508Sdim/// This function only removes edges in pairs, because removing only one edge
2173263508Sdim/// might leave other edges dangling.
2174263508Sdim///
2175263508Sdim/// This will not remove edges in more complicated situations:
2176263508Sdim/// - if there is more than one "hop" leading to or from a subexpression.
2177263508Sdim/// - if there is an inlined call between the edges instead of a single event.
2178263508Sdim/// - if the whole statement is large enough that having subexpression arrows
2179263508Sdim///   might be helpful.
2180263508Sdimstatic void removeContextCycles(PathPieces &Path, SourceManager &SM,
2181263508Sdim                                ParentMap &PM) {
2182263508Sdim  for (PathPieces::iterator I = Path.begin(), E = Path.end(); I != E; ) {
2183263508Sdim    // Pattern match the current piece and its successor.
2184263508Sdim    PathDiagnosticControlFlowPiece *PieceI =
2185263508Sdim      dyn_cast<PathDiagnosticControlFlowPiece>(*I);
2186263508Sdim
2187263508Sdim    if (!PieceI) {
2188263508Sdim      ++I;
2189263508Sdim      continue;
2190263508Sdim    }
2191263508Sdim
2192263508Sdim    const Stmt *s1Start = getLocStmt(PieceI->getStartLocation());
2193263508Sdim    const Stmt *s1End   = getLocStmt(PieceI->getEndLocation());
2194263508Sdim
2195263508Sdim    PathPieces::iterator NextI = I; ++NextI;
2196263508Sdim    if (NextI == E)
2197263508Sdim      break;
2198263508Sdim
2199263508Sdim    PathDiagnosticControlFlowPiece *PieceNextI =
2200263508Sdim      dyn_cast<PathDiagnosticControlFlowPiece>(*NextI);
2201263508Sdim
2202263508Sdim    if (!PieceNextI) {
2203263508Sdim      if (isa<PathDiagnosticEventPiece>(*NextI)) {
2204263508Sdim        ++NextI;
2205263508Sdim        if (NextI == E)
2206263508Sdim          break;
2207263508Sdim        PieceNextI = dyn_cast<PathDiagnosticControlFlowPiece>(*NextI);
2208263508Sdim      }
2209263508Sdim
2210263508Sdim      if (!PieceNextI) {
2211263508Sdim        ++I;
2212263508Sdim        continue;
2213263508Sdim      }
2214263508Sdim    }
2215263508Sdim
2216263508Sdim    const Stmt *s2Start = getLocStmt(PieceNextI->getStartLocation());
2217263508Sdim    const Stmt *s2End   = getLocStmt(PieceNextI->getEndLocation());
2218263508Sdim
2219263508Sdim    if (s1Start && s2Start && s1Start == s2End && s2Start == s1End) {
2220263508Sdim      const size_t MAX_SHORT_LINE_LENGTH = 80;
2221263508Sdim      Optional<size_t> s1Length = getLengthOnSingleLine(SM, s1Start);
2222263508Sdim      if (s1Length && *s1Length <= MAX_SHORT_LINE_LENGTH) {
2223263508Sdim        Optional<size_t> s2Length = getLengthOnSingleLine(SM, s2Start);
2224263508Sdim        if (s2Length && *s2Length <= MAX_SHORT_LINE_LENGTH) {
2225263508Sdim          Path.erase(I);
2226263508Sdim          I = Path.erase(NextI);
2227263508Sdim          continue;
2228263508Sdim        }
2229263508Sdim      }
2230263508Sdim    }
2231263508Sdim
2232263508Sdim    ++I;
2233263508Sdim  }
2234263508Sdim}
2235263508Sdim
2236263508Sdim/// \brief Return true if X is contained by Y.
2237263508Sdimstatic bool lexicalContains(ParentMap &PM,
2238263508Sdim                            const Stmt *X,
2239263508Sdim                            const Stmt *Y) {
2240263508Sdim  while (X) {
2241263508Sdim    if (X == Y)
2242263508Sdim      return true;
2243263508Sdim    X = PM.getParent(X);
2244263508Sdim  }
2245263508Sdim  return false;
2246263508Sdim}
2247263508Sdim
2248263508Sdim// Remove short edges on the same line less than 3 columns in difference.
2249263508Sdimstatic void removePunyEdges(PathPieces &path,
2250263508Sdim                            SourceManager &SM,
2251263508Sdim                            ParentMap &PM) {
2252263508Sdim
2253263508Sdim  bool erased = false;
2254263508Sdim
2255263508Sdim  for (PathPieces::iterator I = path.begin(), E = path.end(); I != E;
2256263508Sdim       erased ? I : ++I) {
2257263508Sdim
2258263508Sdim    erased = false;
2259263508Sdim
2260263508Sdim    PathDiagnosticControlFlowPiece *PieceI =
2261263508Sdim      dyn_cast<PathDiagnosticControlFlowPiece>(*I);
2262263508Sdim
2263263508Sdim    if (!PieceI)
2264263508Sdim      continue;
2265263508Sdim
2266263508Sdim    const Stmt *start = getLocStmt(PieceI->getStartLocation());
2267263508Sdim    const Stmt *end   = getLocStmt(PieceI->getEndLocation());
2268263508Sdim
2269263508Sdim    if (!start || !end)
2270263508Sdim      continue;
2271263508Sdim
2272263508Sdim    const Stmt *endParent = PM.getParent(end);
2273263508Sdim    if (!endParent)
2274263508Sdim      continue;
2275263508Sdim
2276263508Sdim    if (isConditionForTerminator(end, endParent))
2277263508Sdim      continue;
2278263508Sdim
2279263508Sdim    SourceLocation FirstLoc = start->getLocStart();
2280263508Sdim    SourceLocation SecondLoc = end->getLocStart();
2281263508Sdim
2282263508Sdim    if (!SM.isWrittenInSameFile(FirstLoc, SecondLoc))
2283263508Sdim      continue;
2284263508Sdim    if (SM.isBeforeInTranslationUnit(SecondLoc, FirstLoc))
2285263508Sdim      std::swap(SecondLoc, FirstLoc);
2286263508Sdim
2287263508Sdim    SourceRange EdgeRange(FirstLoc, SecondLoc);
2288263508Sdim    Optional<size_t> ByteWidth = getLengthOnSingleLine(SM, EdgeRange);
2289263508Sdim
2290263508Sdim    // If the statements are on different lines, continue.
2291263508Sdim    if (!ByteWidth)
2292263508Sdim      continue;
2293263508Sdim
2294263508Sdim    const size_t MAX_PUNY_EDGE_LENGTH = 2;
2295263508Sdim    if (*ByteWidth <= MAX_PUNY_EDGE_LENGTH) {
2296263508Sdim      // FIXME: There are enough /bytes/ between the endpoints of the edge, but
2297263508Sdim      // there might not be enough /columns/. A proper user-visible column count
2298263508Sdim      // is probably too expensive, though.
2299263508Sdim      I = path.erase(I);
2300263508Sdim      erased = true;
2301263508Sdim      continue;
2302263508Sdim    }
2303263508Sdim  }
2304263508Sdim}
2305263508Sdim
2306263508Sdimstatic void removeIdenticalEvents(PathPieces &path) {
2307263508Sdim  for (PathPieces::iterator I = path.begin(), E = path.end(); I != E; ++I) {
2308263508Sdim    PathDiagnosticEventPiece *PieceI =
2309263508Sdim      dyn_cast<PathDiagnosticEventPiece>(*I);
2310263508Sdim
2311263508Sdim    if (!PieceI)
2312263508Sdim      continue;
2313263508Sdim
2314263508Sdim    PathPieces::iterator NextI = I; ++NextI;
2315263508Sdim    if (NextI == E)
2316263508Sdim      return;
2317263508Sdim
2318263508Sdim    PathDiagnosticEventPiece *PieceNextI =
2319263508Sdim      dyn_cast<PathDiagnosticEventPiece>(*NextI);
2320263508Sdim
2321263508Sdim    if (!PieceNextI)
2322263508Sdim      continue;
2323263508Sdim
2324263508Sdim    // Erase the second piece if it has the same exact message text.
2325263508Sdim    if (PieceI->getString() == PieceNextI->getString()) {
2326263508Sdim      path.erase(NextI);
2327263508Sdim    }
2328263508Sdim  }
2329263508Sdim}
2330263508Sdim
2331251662Sdimstatic bool optimizeEdges(PathPieces &path, SourceManager &SM,
2332251662Sdim                          OptimizedCallsSet &OCS,
2333251662Sdim                          LocationContextMap &LCM) {
2334251662Sdim  bool hasChanges = false;
2335251662Sdim  const LocationContext *LC = LCM[&path];
2336251662Sdim  assert(LC);
2337263508Sdim  ParentMap &PM = LC->getParentMap();
2338251662Sdim
2339251662Sdim  for (PathPieces::iterator I = path.begin(), E = path.end(); I != E; ) {
2340251662Sdim    // Optimize subpaths.
2341251662Sdim    if (PathDiagnosticCallPiece *CallI = dyn_cast<PathDiagnosticCallPiece>(*I)){
2342251662Sdim      // Record the fact that a call has been optimized so we only do the
2343251662Sdim      // effort once.
2344251662Sdim      if (!OCS.count(CallI)) {
2345263508Sdim        while (optimizeEdges(CallI->path, SM, OCS, LCM)) {}
2346251662Sdim        OCS.insert(CallI);
2347251662Sdim      }
2348251662Sdim      ++I;
2349251662Sdim      continue;
2350251662Sdim    }
2351251662Sdim
2352251662Sdim    // Pattern match the current piece and its successor.
2353251662Sdim    PathDiagnosticControlFlowPiece *PieceI =
2354251662Sdim      dyn_cast<PathDiagnosticControlFlowPiece>(*I);
2355251662Sdim
2356251662Sdim    if (!PieceI) {
2357251662Sdim      ++I;
2358251662Sdim      continue;
2359251662Sdim    }
2360251662Sdim
2361251662Sdim    const Stmt *s1Start = getLocStmt(PieceI->getStartLocation());
2362251662Sdim    const Stmt *s1End   = getLocStmt(PieceI->getEndLocation());
2363251662Sdim    const Stmt *level1 = getStmtParent(s1Start, PM);
2364251662Sdim    const Stmt *level2 = getStmtParent(s1End, PM);
2365251662Sdim
2366251662Sdim    PathPieces::iterator NextI = I; ++NextI;
2367251662Sdim    if (NextI == E)
2368251662Sdim      break;
2369251662Sdim
2370251662Sdim    PathDiagnosticControlFlowPiece *PieceNextI =
2371251662Sdim      dyn_cast<PathDiagnosticControlFlowPiece>(*NextI);
2372251662Sdim
2373251662Sdim    if (!PieceNextI) {
2374251662Sdim      ++I;
2375251662Sdim      continue;
2376251662Sdim    }
2377251662Sdim
2378251662Sdim    const Stmt *s2Start = getLocStmt(PieceNextI->getStartLocation());
2379251662Sdim    const Stmt *s2End   = getLocStmt(PieceNextI->getEndLocation());
2380251662Sdim    const Stmt *level3 = getStmtParent(s2Start, PM);
2381251662Sdim    const Stmt *level4 = getStmtParent(s2End, PM);
2382251662Sdim
2383251662Sdim    // Rule I.
2384251662Sdim    //
2385251662Sdim    // If we have two consecutive control edges whose end/begin locations
2386251662Sdim    // are at the same level (e.g. statements or top-level expressions within
2387251662Sdim    // a compound statement, or siblings share a single ancestor expression),
2388251662Sdim    // then merge them if they have no interesting intermediate event.
2389251662Sdim    //
2390251662Sdim    // For example:
2391251662Sdim    //
2392251662Sdim    // (1.1 -> 1.2) -> (1.2 -> 1.3) becomes (1.1 -> 1.3) because the common
2393251662Sdim    // parent is '1'.  Here 'x.y.z' represents the hierarchy of statements.
2394251662Sdim    //
2395251662Sdim    // NOTE: this will be limited later in cases where we add barriers
2396251662Sdim    // to prevent this optimization.
2397251662Sdim    //
2398251662Sdim    if (level1 && level1 == level2 && level1 == level3 && level1 == level4) {
2399251662Sdim      PieceI->setEndLocation(PieceNextI->getEndLocation());
2400251662Sdim      path.erase(NextI);
2401251662Sdim      hasChanges = true;
2402251662Sdim      continue;
2403251662Sdim    }
2404251662Sdim
2405251662Sdim    // Rule II.
2406251662Sdim    //
2407263508Sdim    // Eliminate edges between subexpressions and parent expressions
2408263508Sdim    // when the subexpression is consumed.
2409251662Sdim    //
2410251662Sdim    // NOTE: this will be limited later in cases where we add barriers
2411251662Sdim    // to prevent this optimization.
2412251662Sdim    //
2413263508Sdim    if (s1End && s1End == s2Start && level2) {
2414263508Sdim      bool removeEdge = false;
2415263508Sdim      // Remove edges into the increment or initialization of a
2416263508Sdim      // loop that have no interleaving event.  This means that
2417263508Sdim      // they aren't interesting.
2418263508Sdim      if (isIncrementOrInitInForLoop(s1End, level2))
2419263508Sdim        removeEdge = true;
2420263508Sdim      // Next only consider edges that are not anchored on
2421263508Sdim      // the condition of a terminator.  This are intermediate edges
2422263508Sdim      // that we might want to trim.
2423263508Sdim      else if (!isConditionForTerminator(level2, s1End)) {
2424263508Sdim        // Trim edges on expressions that are consumed by
2425263508Sdim        // the parent expression.
2426263508Sdim        if (isa<Expr>(s1End) && PM.isConsumedExpr(cast<Expr>(s1End))) {
2427263508Sdim          removeEdge = true;
2428263508Sdim        }
2429263508Sdim        // Trim edges where a lexical containment doesn't exist.
2430263508Sdim        // For example:
2431263508Sdim        //
2432263508Sdim        //  X -> Y -> Z
2433263508Sdim        //
2434263508Sdim        // If 'Z' lexically contains Y (it is an ancestor) and
2435263508Sdim        // 'X' does not lexically contain Y (it is a descendant OR
2436263508Sdim        // it has no lexical relationship at all) then trim.
2437263508Sdim        //
2438263508Sdim        // This can eliminate edges where we dive into a subexpression
2439263508Sdim        // and then pop back out, etc.
2440263508Sdim        else if (s1Start && s2End &&
2441263508Sdim                 lexicalContains(PM, s2Start, s2End) &&
2442263508Sdim                 !lexicalContains(PM, s1End, s1Start)) {
2443263508Sdim          removeEdge = true;
2444263508Sdim        }
2445263508Sdim        // Trim edges from a subexpression back to the top level if the
2446263508Sdim        // subexpression is on a different line.
2447263508Sdim        //
2448263508Sdim        // A.1 -> A -> B
2449263508Sdim        // becomes
2450263508Sdim        // A.1 -> B
2451263508Sdim        //
2452263508Sdim        // These edges just look ugly and don't usually add anything.
2453263508Sdim        else if (s1Start && s2End &&
2454263508Sdim                 lexicalContains(PM, s1Start, s1End)) {
2455263508Sdim          SourceRange EdgeRange(PieceI->getEndLocation().asLocation(),
2456263508Sdim                                PieceI->getStartLocation().asLocation());
2457263508Sdim          if (!getLengthOnSingleLine(SM, EdgeRange).hasValue())
2458263508Sdim            removeEdge = true;
2459263508Sdim        }
2460263508Sdim      }
2461251662Sdim
2462263508Sdim      if (removeEdge) {
2463263508Sdim        PieceI->setEndLocation(PieceNextI->getEndLocation());
2464263508Sdim        path.erase(NextI);
2465263508Sdim        hasChanges = true;
2466263508Sdim        continue;
2467263508Sdim      }
2468251662Sdim    }
2469251662Sdim
2470263508Sdim    // Optimize edges for ObjC fast-enumeration loops.
2471251662Sdim    //
2472263508Sdim    // (X -> collection) -> (collection -> element)
2473251662Sdim    //
2474263508Sdim    // becomes:
2475251662Sdim    //
2476263508Sdim    // (X -> element)
2477263508Sdim    if (s1End == s2Start) {
2478263508Sdim      const ObjCForCollectionStmt *FS =
2479263508Sdim        dyn_cast_or_null<ObjCForCollectionStmt>(level3);
2480263508Sdim      if (FS && FS->getCollection()->IgnoreParens() == s2Start &&
2481263508Sdim          s2End == FS->getElement()) {
2482263508Sdim        PieceI->setEndLocation(PieceNextI->getEndLocation());
2483263508Sdim        path.erase(NextI);
2484251662Sdim        hasChanges = true;
2485251662Sdim        continue;
2486251662Sdim      }
2487251662Sdim    }
2488251662Sdim
2489251662Sdim    // No changes at this index?  Move to the next one.
2490251662Sdim    ++I;
2491251662Sdim  }
2492251662Sdim
2493263508Sdim  if (!hasChanges) {
2494263508Sdim    // Adjust edges into subexpressions to make them more uniform
2495263508Sdim    // and aesthetically pleasing.
2496263508Sdim    addContextEdges(path, SM, PM, LC);
2497263508Sdim    // Remove "cyclical" edges that include one or more context edges.
2498263508Sdim    removeContextCycles(path, SM, PM);
2499263508Sdim    // Hoist edges originating from branch conditions to branches
2500263508Sdim    // for simple branches.
2501263508Sdim    simplifySimpleBranches(path);
2502263508Sdim    // Remove any puny edges left over after primary optimization pass.
2503263508Sdim    removePunyEdges(path, SM, PM);
2504263508Sdim    // Remove identical events.
2505263508Sdim    removeIdenticalEvents(path);
2506263508Sdim  }
2507263508Sdim
2508251662Sdim  return hasChanges;
2509251662Sdim}
2510251662Sdim
2511263508Sdim/// Drop the very first edge in a path, which should be a function entry edge.
2512263508Sdim///
2513263508Sdim/// If the first edge is not a function entry edge (say, because the first
2514263508Sdim/// statement had an invalid source location), this function does nothing.
2515263508Sdim// FIXME: We should just generate invalid edges anyway and have the optimizer
2516263508Sdim// deal with them.
2517263508Sdimstatic void dropFunctionEntryEdge(PathPieces &Path,
2518263508Sdim                                  LocationContextMap &LCM,
2519263508Sdim                                  SourceManager &SM) {
2520263508Sdim  const PathDiagnosticControlFlowPiece *FirstEdge =
2521263508Sdim    dyn_cast<PathDiagnosticControlFlowPiece>(Path.front());
2522263508Sdim  if (!FirstEdge)
2523263508Sdim    return;
2524263508Sdim
2525263508Sdim  const Decl *D = LCM[&Path]->getDecl();
2526263508Sdim  PathDiagnosticLocation EntryLoc = PathDiagnosticLocation::createBegin(D, SM);
2527263508Sdim  if (FirstEdge->getStartLocation() != EntryLoc)
2528263508Sdim    return;
2529263508Sdim
2530263508Sdim  Path.pop_front();
2531263508Sdim}
2532263508Sdim
2533263508Sdim
2534218887Sdim//===----------------------------------------------------------------------===//
2535218887Sdim// Methods for BugType and subclasses.
2536218887Sdim//===----------------------------------------------------------------------===//
2537263508Sdimvoid BugType::anchor() { }
2538219077Sdim
2539218887Sdimvoid BugType::FlushReports(BugReporter &BR) {}
2540218887Sdim
2541234353Sdimvoid BuiltinBug::anchor() {}
2542234353Sdim
2543218887Sdim//===----------------------------------------------------------------------===//
2544218887Sdim// Methods for BugReport and subclasses.
2545218887Sdim//===----------------------------------------------------------------------===//
2546218887Sdim
2547234353Sdimvoid BugReport::NodeResolver::anchor() {}
2548234353Sdim
2549226633Sdimvoid BugReport::addVisitor(BugReporterVisitor* visitor) {
2550226633Sdim  if (!visitor)
2551226633Sdim    return;
2552226633Sdim
2553226633Sdim  llvm::FoldingSetNodeID ID;
2554226633Sdim  visitor->Profile(ID);
2555226633Sdim  void *InsertPos;
2556226633Sdim
2557226633Sdim  if (CallbacksSet.FindNodeOrInsertPos(ID, InsertPos)) {
2558226633Sdim    delete visitor;
2559226633Sdim    return;
2560226633Sdim  }
2561226633Sdim
2562226633Sdim  CallbacksSet.InsertNode(visitor, InsertPos);
2563234353Sdim  Callbacks.push_back(visitor);
2564234353Sdim  ++ConfigurationChangeToken;
2565226633Sdim}
2566226633Sdim
2567226633SdimBugReport::~BugReport() {
2568226633Sdim  for (visitor_iterator I = visitor_begin(), E = visitor_end(); I != E; ++I) {
2569226633Sdim    delete *I;
2570226633Sdim  }
2571239462Sdim  while (!interestingSymbols.empty()) {
2572239462Sdim    popInterestingSymbolsAndRegions();
2573239462Sdim  }
2574226633Sdim}
2575226633Sdim
2576234353Sdimconst Decl *BugReport::getDeclWithIssue() const {
2577234353Sdim  if (DeclWithIssue)
2578234353Sdim    return DeclWithIssue;
2579234353Sdim
2580234353Sdim  const ExplodedNode *N = getErrorNode();
2581234353Sdim  if (!N)
2582234353Sdim    return 0;
2583234353Sdim
2584234353Sdim  const LocationContext *LC = N->getLocationContext();
2585234353Sdim  return LC->getCurrentStackFrame()->getDecl();
2586234353Sdim}
2587234353Sdim
2588226633Sdimvoid BugReport::Profile(llvm::FoldingSetNodeID& hash) const {
2589226633Sdim  hash.AddPointer(&BT);
2590226633Sdim  hash.AddString(Description);
2591249423Sdim  PathDiagnosticLocation UL = getUniqueingLocation();
2592249423Sdim  if (UL.isValid()) {
2593249423Sdim    UL.Profile(hash);
2594234353Sdim  } else if (Location.isValid()) {
2595226633Sdim    Location.Profile(hash);
2596226633Sdim  } else {
2597226633Sdim    assert(ErrorNode);
2598226633Sdim    hash.AddPointer(GetCurrentOrPreviousStmt(ErrorNode));
2599226633Sdim  }
2600226633Sdim
2601226633Sdim  for (SmallVectorImpl<SourceRange>::const_iterator I =
2602226633Sdim      Ranges.begin(), E = Ranges.end(); I != E; ++I) {
2603226633Sdim    const SourceRange range = *I;
2604226633Sdim    if (!range.isValid())
2605226633Sdim      continue;
2606226633Sdim    hash.AddInteger(range.getBegin().getRawEncoding());
2607226633Sdim    hash.AddInteger(range.getEnd().getRawEncoding());
2608226633Sdim  }
2609226633Sdim}
2610226633Sdim
2611234353Sdimvoid BugReport::markInteresting(SymbolRef sym) {
2612234353Sdim  if (!sym)
2613234353Sdim    return;
2614234353Sdim
2615234353Sdim  // If the symbol wasn't already in our set, note a configuration change.
2616239462Sdim  if (getInterestingSymbols().insert(sym).second)
2617234353Sdim    ++ConfigurationChangeToken;
2618234353Sdim
2619234353Sdim  if (const SymbolMetadata *meta = dyn_cast<SymbolMetadata>(sym))
2620239462Sdim    getInterestingRegions().insert(meta->getRegion());
2621234353Sdim}
2622234353Sdim
2623234353Sdimvoid BugReport::markInteresting(const MemRegion *R) {
2624234353Sdim  if (!R)
2625234353Sdim    return;
2626234353Sdim
2627234353Sdim  // If the base region wasn't already in our set, note a configuration change.
2628234353Sdim  R = R->getBaseRegion();
2629239462Sdim  if (getInterestingRegions().insert(R).second)
2630234353Sdim    ++ConfigurationChangeToken;
2631234353Sdim
2632234353Sdim  if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R))
2633239462Sdim    getInterestingSymbols().insert(SR->getSymbol());
2634234353Sdim}
2635234353Sdim
2636234353Sdimvoid BugReport::markInteresting(SVal V) {
2637234353Sdim  markInteresting(V.getAsRegion());
2638234353Sdim  markInteresting(V.getAsSymbol());
2639234353Sdim}
2640234353Sdim
2641243830Sdimvoid BugReport::markInteresting(const LocationContext *LC) {
2642243830Sdim  if (!LC)
2643243830Sdim    return;
2644243830Sdim  InterestingLocationContexts.insert(LC);
2645243830Sdim}
2646243830Sdim
2647239462Sdimbool BugReport::isInteresting(SVal V) {
2648234353Sdim  return isInteresting(V.getAsRegion()) || isInteresting(V.getAsSymbol());
2649234353Sdim}
2650234353Sdim
2651239462Sdimbool BugReport::isInteresting(SymbolRef sym) {
2652234353Sdim  if (!sym)
2653234353Sdim    return false;
2654234353Sdim  // We don't currently consider metadata symbols to be interesting
2655234353Sdim  // even if we know their region is interesting. Is that correct behavior?
2656239462Sdim  return getInterestingSymbols().count(sym);
2657234353Sdim}
2658234353Sdim
2659239462Sdimbool BugReport::isInteresting(const MemRegion *R) {
2660234353Sdim  if (!R)
2661234353Sdim    return false;
2662234353Sdim  R = R->getBaseRegion();
2663239462Sdim  bool b = getInterestingRegions().count(R);
2664234353Sdim  if (b)
2665234353Sdim    return true;
2666234353Sdim  if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R))
2667239462Sdim    return getInterestingSymbols().count(SR->getSymbol());
2668234353Sdim  return false;
2669234353Sdim}
2670234353Sdim
2671243830Sdimbool BugReport::isInteresting(const LocationContext *LC) {
2672243830Sdim  if (!LC)
2673243830Sdim    return false;
2674243830Sdim  return InterestingLocationContexts.count(LC);
2675243830Sdim}
2676243830Sdim
2677239462Sdimvoid BugReport::lazyInitializeInterestingSets() {
2678239462Sdim  if (interestingSymbols.empty()) {
2679239462Sdim    interestingSymbols.push_back(new Symbols());
2680239462Sdim    interestingRegions.push_back(new Regions());
2681239462Sdim  }
2682239462Sdim}
2683239462Sdim
2684239462SdimBugReport::Symbols &BugReport::getInterestingSymbols() {
2685239462Sdim  lazyInitializeInterestingSets();
2686239462Sdim  return *interestingSymbols.back();
2687239462Sdim}
2688239462Sdim
2689239462SdimBugReport::Regions &BugReport::getInterestingRegions() {
2690239462Sdim  lazyInitializeInterestingSets();
2691239462Sdim  return *interestingRegions.back();
2692239462Sdim}
2693239462Sdim
2694239462Sdimvoid BugReport::pushInterestingSymbolsAndRegions() {
2695239462Sdim  interestingSymbols.push_back(new Symbols(getInterestingSymbols()));
2696239462Sdim  interestingRegions.push_back(new Regions(getInterestingRegions()));
2697239462Sdim}
2698239462Sdim
2699239462Sdimvoid BugReport::popInterestingSymbolsAndRegions() {
2700263508Sdim  delete interestingSymbols.pop_back_val();
2701263508Sdim  delete interestingRegions.pop_back_val();
2702239462Sdim}
2703239462Sdim
2704226633Sdimconst Stmt *BugReport::getStmt() const {
2705226633Sdim  if (!ErrorNode)
2706226633Sdim    return 0;
2707226633Sdim
2708218887Sdim  ProgramPoint ProgP = ErrorNode->getLocation();
2709218887Sdim  const Stmt *S = NULL;
2710218887Sdim
2711249423Sdim  if (Optional<BlockEntrance> BE = ProgP.getAs<BlockEntrance>()) {
2712218887Sdim    CFGBlock &Exit = ProgP.getLocationContext()->getCFG()->getExit();
2713218887Sdim    if (BE->getBlock() == &Exit)
2714218887Sdim      S = GetPreviousStmt(ErrorNode);
2715218887Sdim  }
2716218887Sdim  if (!S)
2717251662Sdim    S = PathDiagnosticLocation::getStmt(ErrorNode);
2718218887Sdim
2719218887Sdim  return S;
2720218887Sdim}
2721218887Sdim
2722226633Sdimstd::pair<BugReport::ranges_iterator, BugReport::ranges_iterator>
2723226633SdimBugReport::getRanges() {
2724226633Sdim    // If no custom ranges, add the range of the statement corresponding to
2725226633Sdim    // the error node.
2726226633Sdim    if (Ranges.empty()) {
2727226633Sdim      if (const Expr *E = dyn_cast_or_null<Expr>(getStmt()))
2728226633Sdim        addRange(E->getSourceRange());
2729226633Sdim      else
2730226633Sdim        return std::make_pair(ranges_iterator(), ranges_iterator());
2731226633Sdim    }
2732218887Sdim
2733226633Sdim    // User-specified absence of range info.
2734226633Sdim    if (Ranges.size() == 1 && !Ranges.begin()->isValid())
2735226633Sdim      return std::make_pair(ranges_iterator(), ranges_iterator());
2736218887Sdim
2737226633Sdim    return std::make_pair(Ranges.begin(), Ranges.end());
2738226633Sdim}
2739218887Sdim
2740226633SdimPathDiagnosticLocation BugReport::getLocation(const SourceManager &SM) const {
2741226633Sdim  if (ErrorNode) {
2742226633Sdim    assert(!Location.isValid() &&
2743226633Sdim     "Either Location or ErrorNode should be specified but not both.");
2744251662Sdim    return PathDiagnosticLocation::createEndOfPath(ErrorNode, SM);
2745226633Sdim  } else {
2746226633Sdim    assert(Location.isValid());
2747226633Sdim    return Location;
2748226633Sdim  }
2749218887Sdim
2750226633Sdim  return PathDiagnosticLocation();
2751218887Sdim}
2752218887Sdim
2753218887Sdim//===----------------------------------------------------------------------===//
2754218887Sdim// Methods for BugReporter and subclasses.
2755218887Sdim//===----------------------------------------------------------------------===//
2756218887Sdim
2757234353SdimBugReportEquivClass::~BugReportEquivClass() { }
2758218887SdimGRBugReporter::~GRBugReporter() { }
2759218887SdimBugReporterData::~BugReporterData() {}
2760218887Sdim
2761218887SdimExplodedGraph &GRBugReporter::getGraph() { return Eng.getGraph(); }
2762218887Sdim
2763226633SdimProgramStateManager&
2764218887SdimGRBugReporter::getStateManager() { return Eng.getStateManager(); }
2765218887Sdim
2766226633SdimBugReporter::~BugReporter() {
2767226633Sdim  FlushReports();
2768218887Sdim
2769226633Sdim  // Free the bug reports we are tracking.
2770226633Sdim  typedef std::vector<BugReportEquivClass *> ContTy;
2771226633Sdim  for (ContTy::iterator I = EQClassesVector.begin(), E = EQClassesVector.end();
2772226633Sdim       I != E; ++I) {
2773226633Sdim    delete *I;
2774226633Sdim  }
2775226633Sdim}
2776226633Sdim
2777218887Sdimvoid BugReporter::FlushReports() {
2778218887Sdim  if (BugTypes.isEmpty())
2779218887Sdim    return;
2780218887Sdim
2781218887Sdim  // First flush the warnings for each BugType.  This may end up creating new
2782219077Sdim  // warnings and new BugTypes.
2783219077Sdim  // FIXME: Only NSErrorChecker needs BugType's FlushReports.
2784219077Sdim  // Turn NSErrorChecker into a proper checker and remove this.
2785226633Sdim  SmallVector<const BugType*, 16> bugTypes;
2786218887Sdim  for (BugTypesTy::iterator I=BugTypes.begin(), E=BugTypes.end(); I!=E; ++I)
2787219077Sdim    bugTypes.push_back(*I);
2788263508Sdim  for (SmallVectorImpl<const BugType *>::iterator
2789219077Sdim         I = bugTypes.begin(), E = bugTypes.end(); I != E; ++I)
2790218887Sdim    const_cast<BugType*>(*I)->FlushReports(*this);
2791218887Sdim
2792239462Sdim  // We need to flush reports in deterministic order to ensure the order
2793239462Sdim  // of the reports is consistent between runs.
2794239462Sdim  typedef std::vector<BugReportEquivClass *> ContVecTy;
2795239462Sdim  for (ContVecTy::iterator EI=EQClassesVector.begin(), EE=EQClassesVector.end();
2796239462Sdim       EI != EE; ++EI){
2797239462Sdim    BugReportEquivClass& EQ = **EI;
2798219077Sdim    FlushReport(EQ);
2799219077Sdim  }
2800218887Sdim
2801219077Sdim  // BugReporter owns and deletes only BugTypes created implicitly through
2802219077Sdim  // EmitBasicReport.
2803219077Sdim  // FIXME: There are leaks from checkers that assume that the BugTypes they
2804219077Sdim  // create will be destroyed by the BugReporter.
2805219077Sdim  for (llvm::StringMap<BugType*>::iterator
2806219077Sdim         I = StrBugTypes.begin(), E = StrBugTypes.end(); I != E; ++I)
2807219077Sdim    delete I->second;
2808218887Sdim
2809218887Sdim  // Remove all references to the BugType objects.
2810218887Sdim  BugTypes = F.getEmptySet();
2811218887Sdim}
2812218887Sdim
2813218887Sdim//===----------------------------------------------------------------------===//
2814218887Sdim// PathDiagnostics generation.
2815218887Sdim//===----------------------------------------------------------------------===//
2816218887Sdim
2817249423Sdimnamespace {
2818249423Sdim/// A wrapper around a report graph, which contains only a single path, and its
2819249423Sdim/// node maps.
2820249423Sdimclass ReportGraph {
2821249423Sdimpublic:
2822249423Sdim  InterExplodedGraphMap BackMap;
2823249423Sdim  OwningPtr<ExplodedGraph> Graph;
2824249423Sdim  const ExplodedNode *ErrorNode;
2825249423Sdim  size_t Index;
2826249423Sdim};
2827218887Sdim
2828249423Sdim/// A wrapper around a trimmed graph and its node maps.
2829249423Sdimclass TrimmedGraph {
2830249423Sdim  InterExplodedGraphMap InverseMap;
2831218887Sdim
2832249423Sdim  typedef llvm::DenseMap<const ExplodedNode *, unsigned> PriorityMapTy;
2833249423Sdim  PriorityMapTy PriorityMap;
2834218887Sdim
2835249423Sdim  typedef std::pair<const ExplodedNode *, size_t> NodeIndexPair;
2836249423Sdim  SmallVector<NodeIndexPair, 32> ReportNodes;
2837218887Sdim
2838249423Sdim  OwningPtr<ExplodedGraph> G;
2839249423Sdim
2840249423Sdim  /// A helper class for sorting ExplodedNodes by priority.
2841249423Sdim  template <bool Descending>
2842249423Sdim  class PriorityCompare {
2843249423Sdim    const PriorityMapTy &PriorityMap;
2844249423Sdim
2845249423Sdim  public:
2846249423Sdim    PriorityCompare(const PriorityMapTy &M) : PriorityMap(M) {}
2847249423Sdim
2848249423Sdim    bool operator()(const ExplodedNode *LHS, const ExplodedNode *RHS) const {
2849249423Sdim      PriorityMapTy::const_iterator LI = PriorityMap.find(LHS);
2850249423Sdim      PriorityMapTy::const_iterator RI = PriorityMap.find(RHS);
2851249423Sdim      PriorityMapTy::const_iterator E = PriorityMap.end();
2852249423Sdim
2853249423Sdim      if (LI == E)
2854249423Sdim        return Descending;
2855249423Sdim      if (RI == E)
2856249423Sdim        return !Descending;
2857249423Sdim
2858249423Sdim      return Descending ? LI->second > RI->second
2859249423Sdim                        : LI->second < RI->second;
2860249423Sdim    }
2861249423Sdim
2862249423Sdim    bool operator()(const NodeIndexPair &LHS, const NodeIndexPair &RHS) const {
2863249423Sdim      return (*this)(LHS.first, RHS.first);
2864249423Sdim    }
2865249423Sdim  };
2866249423Sdim
2867249423Sdimpublic:
2868249423Sdim  TrimmedGraph(const ExplodedGraph *OriginalGraph,
2869249423Sdim               ArrayRef<const ExplodedNode *> Nodes);
2870249423Sdim
2871249423Sdim  bool popNextReportGraph(ReportGraph &GraphWrapper);
2872249423Sdim};
2873249423Sdim}
2874249423Sdim
2875249423SdimTrimmedGraph::TrimmedGraph(const ExplodedGraph *OriginalGraph,
2876249423Sdim                           ArrayRef<const ExplodedNode *> Nodes) {
2877249423Sdim  // The trimmed graph is created in the body of the constructor to ensure
2878249423Sdim  // that the DenseMaps have been initialized already.
2879249423Sdim  InterExplodedGraphMap ForwardMap;
2880249423Sdim  G.reset(OriginalGraph->trim(Nodes, &ForwardMap, &InverseMap));
2881249423Sdim
2882218887Sdim  // Find the (first) error node in the trimmed graph.  We just need to consult
2883249423Sdim  // the node map which maps from nodes in the original graph to nodes
2884218887Sdim  // in the new graph.
2885249423Sdim  llvm::SmallPtrSet<const ExplodedNode *, 32> RemainingNodes;
2886218887Sdim
2887249423Sdim  for (unsigned i = 0, count = Nodes.size(); i < count; ++i) {
2888249423Sdim    if (const ExplodedNode *NewNode = ForwardMap.lookup(Nodes[i])) {
2889249423Sdim      ReportNodes.push_back(std::make_pair(NewNode, i));
2890249423Sdim      RemainingNodes.insert(NewNode);
2891218887Sdim    }
2892218887Sdim  }
2893218887Sdim
2894249423Sdim  assert(!RemainingNodes.empty() && "No error node found in the trimmed graph");
2895218887Sdim
2896249423Sdim  // Perform a forward BFS to find all the shortest paths.
2897249423Sdim  std::queue<const ExplodedNode *> WS;
2898218887Sdim
2899249423Sdim  assert(G->num_roots() == 1);
2900249423Sdim  WS.push(*G->roots_begin());
2901249423Sdim  unsigned Priority = 0;
2902218887Sdim
2903218887Sdim  while (!WS.empty()) {
2904226633Sdim    const ExplodedNode *Node = WS.front();
2905218887Sdim    WS.pop();
2906218887Sdim
2907249423Sdim    PriorityMapTy::iterator PriorityEntry;
2908249423Sdim    bool IsNew;
2909249423Sdim    llvm::tie(PriorityEntry, IsNew) =
2910249423Sdim      PriorityMap.insert(std::make_pair(Node, Priority));
2911249423Sdim    ++Priority;
2912249423Sdim
2913249423Sdim    if (!IsNew) {
2914249423Sdim      assert(PriorityEntry->second <= Priority);
2915218887Sdim      continue;
2916249423Sdim    }
2917218887Sdim
2918249423Sdim    if (RemainingNodes.erase(Node))
2919249423Sdim      if (RemainingNodes.empty())
2920249423Sdim        break;
2921218887Sdim
2922249423Sdim    for (ExplodedNode::const_pred_iterator I = Node->succ_begin(),
2923249423Sdim                                           E = Node->succ_end();
2924249423Sdim         I != E; ++I)
2925218887Sdim      WS.push(*I);
2926218887Sdim  }
2927218887Sdim
2928249423Sdim  // Sort the error paths from longest to shortest.
2929249423Sdim  std::sort(ReportNodes.begin(), ReportNodes.end(),
2930249423Sdim            PriorityCompare<true>(PriorityMap));
2931249423Sdim}
2932218887Sdim
2933249423Sdimbool TrimmedGraph::popNextReportGraph(ReportGraph &GraphWrapper) {
2934249423Sdim  if (ReportNodes.empty())
2935249423Sdim    return false;
2936218887Sdim
2937249423Sdim  const ExplodedNode *OrigN;
2938249423Sdim  llvm::tie(OrigN, GraphWrapper.Index) = ReportNodes.pop_back_val();
2939249423Sdim  assert(PriorityMap.find(OrigN) != PriorityMap.end() &&
2940249423Sdim         "error node not accessible from root");
2941218887Sdim
2942249423Sdim  // Create a new graph with a single path.  This is the graph
2943249423Sdim  // that will be returned to the caller.
2944249423Sdim  ExplodedGraph *GNew = new ExplodedGraph();
2945249423Sdim  GraphWrapper.Graph.reset(GNew);
2946249423Sdim  GraphWrapper.BackMap.clear();
2947249423Sdim
2948249423Sdim  // Now walk from the error node up the BFS path, always taking the
2949249423Sdim  // predeccessor with the lowest number.
2950249423Sdim  ExplodedNode *Succ = 0;
2951249423Sdim  while (true) {
2952218887Sdim    // Create the equivalent node in the new graph with the same state
2953218887Sdim    // and location.
2954251662Sdim    ExplodedNode *NewN = GNew->getNode(OrigN->getLocation(), OrigN->getState(),
2955251662Sdim                                       OrigN->isSink());
2956218887Sdim
2957218887Sdim    // Store the mapping to the original node.
2958249423Sdim    InterExplodedGraphMap::const_iterator IMitr = InverseMap.find(OrigN);
2959218887Sdim    assert(IMitr != InverseMap.end() && "No mapping to original node.");
2960249423Sdim    GraphWrapper.BackMap[NewN] = IMitr->second;
2961218887Sdim
2962218887Sdim    // Link up the new node with the previous node.
2963249423Sdim    if (Succ)
2964249423Sdim      Succ->addPredecessor(NewN, *GNew);
2965249423Sdim    else
2966249423Sdim      GraphWrapper.ErrorNode = NewN;
2967218887Sdim
2968249423Sdim    Succ = NewN;
2969218887Sdim
2970218887Sdim    // Are we at the final node?
2971249423Sdim    if (OrigN->pred_empty()) {
2972249423Sdim      GNew->addRoot(NewN);
2973218887Sdim      break;
2974218887Sdim    }
2975218887Sdim
2976249423Sdim    // Find the next predeccessor node.  We choose the node that is marked
2977249423Sdim    // with the lowest BFS number.
2978249423Sdim    OrigN = *std::min_element(OrigN->pred_begin(), OrigN->pred_end(),
2979249423Sdim                          PriorityCompare<false>(PriorityMap));
2980218887Sdim  }
2981218887Sdim
2982249423Sdim  return true;
2983218887Sdim}
2984218887Sdim
2985249423Sdim
2986218887Sdim/// CompactPathDiagnostic - This function postprocesses a PathDiagnostic object
2987218887Sdim///  and collapses PathDiagosticPieces that are expanded by macros.
2988234353Sdimstatic void CompactPathDiagnostic(PathPieces &path, const SourceManager& SM) {
2989234353Sdim  typedef std::vector<std::pair<IntrusiveRefCntPtr<PathDiagnosticMacroPiece>,
2990234353Sdim                                SourceLocation> > MacroStackTy;
2991218887Sdim
2992234353Sdim  typedef std::vector<IntrusiveRefCntPtr<PathDiagnosticPiece> >
2993218887Sdim          PiecesTy;
2994218887Sdim
2995218887Sdim  MacroStackTy MacroStack;
2996218887Sdim  PiecesTy Pieces;
2997218887Sdim
2998234353Sdim  for (PathPieces::const_iterator I = path.begin(), E = path.end();
2999234353Sdim       I!=E; ++I) {
3000234353Sdim
3001234353Sdim    PathDiagnosticPiece *piece = I->getPtr();
3002234353Sdim
3003234353Sdim    // Recursively compact calls.
3004234353Sdim    if (PathDiagnosticCallPiece *call=dyn_cast<PathDiagnosticCallPiece>(piece)){
3005234353Sdim      CompactPathDiagnostic(call->path, SM);
3006234353Sdim    }
3007234353Sdim
3008218887Sdim    // Get the location of the PathDiagnosticPiece.
3009234353Sdim    const FullSourceLoc Loc = piece->getLocation().asLocation();
3010218887Sdim
3011218887Sdim    // Determine the instantiation location, which is the location we group
3012218887Sdim    // related PathDiagnosticPieces.
3013218887Sdim    SourceLocation InstantiationLoc = Loc.isMacroID() ?
3014226633Sdim                                      SM.getExpansionLoc(Loc) :
3015218887Sdim                                      SourceLocation();
3016218887Sdim
3017218887Sdim    if (Loc.isFileID()) {
3018218887Sdim      MacroStack.clear();
3019234353Sdim      Pieces.push_back(piece);
3020218887Sdim      continue;
3021218887Sdim    }
3022218887Sdim
3023218887Sdim    assert(Loc.isMacroID());
3024218887Sdim
3025218887Sdim    // Is the PathDiagnosticPiece within the same macro group?
3026218887Sdim    if (!MacroStack.empty() && InstantiationLoc == MacroStack.back().second) {
3027234353Sdim      MacroStack.back().first->subPieces.push_back(piece);
3028218887Sdim      continue;
3029218887Sdim    }
3030218887Sdim
3031218887Sdim    // We aren't in the same group.  Are we descending into a new macro
3032218887Sdim    // or are part of an old one?
3033234353Sdim    IntrusiveRefCntPtr<PathDiagnosticMacroPiece> MacroGroup;
3034218887Sdim
3035218887Sdim    SourceLocation ParentInstantiationLoc = InstantiationLoc.isMacroID() ?
3036226633Sdim                                          SM.getExpansionLoc(Loc) :
3037218887Sdim                                          SourceLocation();
3038218887Sdim
3039218887Sdim    // Walk the entire macro stack.
3040218887Sdim    while (!MacroStack.empty()) {
3041218887Sdim      if (InstantiationLoc == MacroStack.back().second) {
3042218887Sdim        MacroGroup = MacroStack.back().first;
3043218887Sdim        break;
3044218887Sdim      }
3045218887Sdim
3046218887Sdim      if (ParentInstantiationLoc == MacroStack.back().second) {
3047218887Sdim        MacroGroup = MacroStack.back().first;
3048218887Sdim        break;
3049218887Sdim      }
3050218887Sdim
3051218887Sdim      MacroStack.pop_back();
3052218887Sdim    }
3053218887Sdim
3054218887Sdim    if (!MacroGroup || ParentInstantiationLoc == MacroStack.back().second) {
3055218887Sdim      // Create a new macro group and add it to the stack.
3056226633Sdim      PathDiagnosticMacroPiece *NewGroup =
3057226633Sdim        new PathDiagnosticMacroPiece(
3058234353Sdim          PathDiagnosticLocation::createSingleLocation(piece->getLocation()));
3059218887Sdim
3060218887Sdim      if (MacroGroup)
3061234353Sdim        MacroGroup->subPieces.push_back(NewGroup);
3062218887Sdim      else {
3063218887Sdim        assert(InstantiationLoc.isFileID());
3064218887Sdim        Pieces.push_back(NewGroup);
3065218887Sdim      }
3066218887Sdim
3067218887Sdim      MacroGroup = NewGroup;
3068218887Sdim      MacroStack.push_back(std::make_pair(MacroGroup, InstantiationLoc));
3069218887Sdim    }
3070218887Sdim
3071218887Sdim    // Finally, add the PathDiagnosticPiece to the group.
3072234353Sdim    MacroGroup->subPieces.push_back(piece);
3073218887Sdim  }
3074218887Sdim
3075218887Sdim  // Now take the pieces and construct a new PathDiagnostic.
3076234353Sdim  path.clear();
3077218887Sdim
3078234353Sdim  for (PiecesTy::iterator I=Pieces.begin(), E=Pieces.end(); I!=E; ++I)
3079234353Sdim    path.push_back(*I);
3080218887Sdim}
3081218887Sdim
3082243830Sdimbool GRBugReporter::generatePathDiagnostic(PathDiagnostic& PD,
3083239462Sdim                                           PathDiagnosticConsumer &PC,
3084239462Sdim                                           ArrayRef<BugReport *> &bugReports) {
3085243830Sdim  assert(!bugReports.empty());
3086218887Sdim
3087243830Sdim  bool HasValid = false;
3088249423Sdim  bool HasInvalid = false;
3089249423Sdim  SmallVector<const ExplodedNode *, 32> errorNodes;
3090239462Sdim  for (ArrayRef<BugReport*>::iterator I = bugReports.begin(),
3091239462Sdim                                      E = bugReports.end(); I != E; ++I) {
3092243830Sdim    if ((*I)->isValid()) {
3093243830Sdim      HasValid = true;
3094218887Sdim      errorNodes.push_back((*I)->getErrorNode());
3095243830Sdim    } else {
3096249423Sdim      // Keep the errorNodes list in sync with the bugReports list.
3097249423Sdim      HasInvalid = true;
3098243830Sdim      errorNodes.push_back(0);
3099243830Sdim    }
3100218887Sdim  }
3101218887Sdim
3102249423Sdim  // If all the reports have been marked invalid by a previous path generation,
3103249423Sdim  // we're done.
3104243830Sdim  if (!HasValid)
3105243830Sdim    return false;
3106243830Sdim
3107249423Sdim  typedef PathDiagnosticConsumer::PathGenerationScheme PathGenerationScheme;
3108249423Sdim  PathGenerationScheme ActiveScheme = PC.getGenerationScheme();
3109218887Sdim
3110251662Sdim  if (ActiveScheme == PathDiagnosticConsumer::Extensive) {
3111263508Sdim    AnalyzerOptions &options = getAnalyzerOptions();
3112263508Sdim    if (options.getBooleanOption("path-diagnostics-alternate", true)) {
3113251662Sdim      ActiveScheme = PathDiagnosticConsumer::AlternateExtensive;
3114251662Sdim    }
3115251662Sdim  }
3116251662Sdim
3117249423Sdim  TrimmedGraph TrimG(&getGraph(), errorNodes);
3118249423Sdim  ReportGraph ErrorGraph;
3119218887Sdim
3120249423Sdim  while (TrimG.popNextReportGraph(ErrorGraph)) {
3121249423Sdim    // Find the BugReport with the original location.
3122249423Sdim    assert(ErrorGraph.Index < bugReports.size());
3123249423Sdim    BugReport *R = bugReports[ErrorGraph.Index];
3124249423Sdim    assert(R && "No original report found for sliced graph.");
3125249423Sdim    assert(R->isValid() && "Report selected by trimmed graph marked invalid.");
3126218887Sdim
3127249423Sdim    // Start building the path diagnostic...
3128249423Sdim    PathDiagnosticBuilder PDB(*this, R, ErrorGraph.BackMap, &PC);
3129249423Sdim    const ExplodedNode *N = ErrorGraph.ErrorNode;
3130218887Sdim
3131249423Sdim    // Register additional node visitors.
3132249423Sdim    R->addVisitor(new NilReceiverBRVisitor());
3133249423Sdim    R->addVisitor(new ConditionBRVisitor());
3134249423Sdim    R->addVisitor(new LikelyFalsePositiveSuppressionBRVisitor());
3135226633Sdim
3136249423Sdim    BugReport::VisitorList visitors;
3137249423Sdim    unsigned origReportConfigToken, finalReportConfigToken;
3138251662Sdim    LocationContextMap LCM;
3139234353Sdim
3140249423Sdim    // While generating diagnostics, it's possible the visitors will decide
3141249423Sdim    // new symbols and regions are interesting, or add other visitors based on
3142249423Sdim    // the information they find. If they do, we need to regenerate the path
3143249423Sdim    // based on our new report configuration.
3144249423Sdim    do {
3145249423Sdim      // Get a clean copy of all the visitors.
3146249423Sdim      for (BugReport::visitor_iterator I = R->visitor_begin(),
3147249423Sdim                                       E = R->visitor_end(); I != E; ++I)
3148249423Sdim        visitors.push_back((*I)->clone());
3149234353Sdim
3150249423Sdim      // Clear out the active path from any previous work.
3151249423Sdim      PD.resetPath();
3152249423Sdim      origReportConfigToken = R->getConfigurationChangeToken();
3153234353Sdim
3154249423Sdim      // Generate the very last diagnostic piece - the piece is visible before
3155249423Sdim      // the trace is expanded.
3156243830Sdim      PathDiagnosticPiece *LastPiece = 0;
3157243830Sdim      for (BugReport::visitor_iterator I = visitors.begin(), E = visitors.end();
3158249423Sdim          I != E; ++I) {
3159243830Sdim        if (PathDiagnosticPiece *Piece = (*I)->getEndPath(PDB, N, *R)) {
3160243830Sdim          assert (!LastPiece &&
3161249423Sdim              "There can only be one final piece in a diagnostic.");
3162243830Sdim          LastPiece = Piece;
3163243830Sdim        }
3164234353Sdim      }
3165249423Sdim
3166249423Sdim      if (ActiveScheme != PathDiagnosticConsumer::None) {
3167249423Sdim        if (!LastPiece)
3168249423Sdim          LastPiece = BugReporterVisitor::getDefaultEndPath(PDB, N, *R);
3169249423Sdim        assert(LastPiece);
3170243830Sdim        PD.setEndOfPath(LastPiece);
3171249423Sdim      }
3172218887Sdim
3173251662Sdim      // Make sure we get a clean location context map so we don't
3174251662Sdim      // hold onto old mappings.
3175251662Sdim      LCM.clear();
3176251662Sdim
3177249423Sdim      switch (ActiveScheme) {
3178251662Sdim      case PathDiagnosticConsumer::AlternateExtensive:
3179251662Sdim        GenerateAlternateExtensivePathDiagnostic(PD, PDB, N, LCM, visitors);
3180251662Sdim        break;
3181249423Sdim      case PathDiagnosticConsumer::Extensive:
3182251662Sdim        GenerateExtensivePathDiagnostic(PD, PDB, N, LCM, visitors);
3183249423Sdim        break;
3184249423Sdim      case PathDiagnosticConsumer::Minimal:
3185251662Sdim        GenerateMinimalPathDiagnostic(PD, PDB, N, LCM, visitors);
3186249423Sdim        break;
3187249423Sdim      case PathDiagnosticConsumer::None:
3188249423Sdim        GenerateVisitorsOnlyPathDiagnostic(PD, PDB, N, visitors);
3189249423Sdim        break;
3190243830Sdim      }
3191234353Sdim
3192249423Sdim      // Clean up the visitors we used.
3193249423Sdim      llvm::DeleteContainerPointers(visitors);
3194234353Sdim
3195249423Sdim      // Did anything change while generating this path?
3196249423Sdim      finalReportConfigToken = R->getConfigurationChangeToken();
3197249423Sdim    } while (finalReportConfigToken != origReportConfigToken);
3198234353Sdim
3199249423Sdim    if (!R->isValid())
3200249423Sdim      continue;
3201243830Sdim
3202249423Sdim    // Finally, prune the diagnostic path of uninteresting stuff.
3203249423Sdim    if (!PD.path.empty()) {
3204263508Sdim      if (R->shouldPrunePath() && getAnalyzerOptions().shouldPrunePaths()) {
3205251662Sdim        bool stillHasNotes = removeUnneededCalls(PD.getMutablePieces(), R, LCM);
3206249423Sdim        assert(stillHasNotes);
3207249423Sdim        (void)stillHasNotes;
3208249423Sdim      }
3209249423Sdim
3210263508Sdim      // Redirect all call pieces to have valid locations.
3211249423Sdim      adjustCallLocations(PD.getMutablePieces());
3212263508Sdim      removePiecesWithInvalidLocations(PD.getMutablePieces());
3213251662Sdim
3214251662Sdim      if (ActiveScheme == PathDiagnosticConsumer::AlternateExtensive) {
3215263508Sdim        SourceManager &SM = getSourceManager();
3216263508Sdim
3217263508Sdim        // Reduce the number of edges from a very conservative set
3218263508Sdim        // to an aesthetically pleasing subset that conveys the
3219263508Sdim        // necessary information.
3220251662Sdim        OptimizedCallsSet OCS;
3221263508Sdim        while (optimizeEdges(PD.getMutablePieces(), SM, OCS, LCM)) {}
3222263508Sdim
3223263508Sdim        // Drop the very first function-entry edge. It's not really necessary
3224263508Sdim        // for top-level functions.
3225263508Sdim        dropFunctionEntryEdge(PD.getMutablePieces(), LCM, SM);
3226251662Sdim      }
3227263508Sdim
3228263508Sdim      // Remove messages that are basically the same, and edges that may not
3229263508Sdim      // make sense.
3230263508Sdim      // We have to do this after edge optimization in the Extensive mode.
3231263508Sdim      removeRedundantMsgs(PD.getMutablePieces());
3232263508Sdim      removeEdgesToDefaultInitializers(PD.getMutablePieces());
3233243830Sdim    }
3234249423Sdim
3235249423Sdim    // We found a report and didn't suppress it.
3236249423Sdim    return true;
3237239462Sdim  }
3238243830Sdim
3239249423Sdim  // We suppressed all the reports in this equivalence class.
3240249423Sdim  assert(!HasInvalid && "Inconsistent suppression");
3241249423Sdim  (void)HasInvalid;
3242249423Sdim  return false;
3243218887Sdim}
3244218887Sdim
3245218887Sdimvoid BugReporter::Register(BugType *BT) {
3246218887Sdim  BugTypes = F.add(BugTypes, BT);
3247218887Sdim}
3248218887Sdim
3249243830Sdimvoid BugReporter::emitReport(BugReport* R) {
3250263508Sdim  // Defensive checking: throw the bug away if it comes from a BodyFarm-
3251263508Sdim  // generated body. We do this very early because report processing relies
3252263508Sdim  // on the report's location being valid.
3253263508Sdim  // FIXME: Valid bugs can occur in BodyFarm-generated bodies, so really we
3254263508Sdim  // need to just find a reasonable location like we do later on with the path
3255263508Sdim  // pieces.
3256263508Sdim  if (const ExplodedNode *E = R->getErrorNode()) {
3257263508Sdim    const LocationContext *LCtx = E->getLocationContext();
3258263508Sdim    if (LCtx->getAnalysisDeclContext()->isBodyAutosynthesized())
3259263508Sdim      return;
3260263508Sdim  }
3261263508Sdim
3262263508Sdim  bool ValidSourceLoc = R->getLocation(getSourceManager()).isValid();
3263263508Sdim  assert(ValidSourceLoc);
3264263508Sdim  // If we mess up in a release build, we'd still prefer to just drop the bug
3265263508Sdim  // instead of trying to go on.
3266263508Sdim  if (!ValidSourceLoc)
3267263508Sdim    return;
3268263508Sdim
3269218887Sdim  // Compute the bug report's hash to determine its equivalence class.
3270218887Sdim  llvm::FoldingSetNodeID ID;
3271218887Sdim  R->Profile(ID);
3272218887Sdim
3273218887Sdim  // Lookup the equivance class.  If there isn't one, create it.
3274218887Sdim  BugType& BT = R->getBugType();
3275218887Sdim  Register(&BT);
3276218887Sdim  void *InsertPos;
3277219077Sdim  BugReportEquivClass* EQ = EQClasses.FindNodeOrInsertPos(ID, InsertPos);
3278218887Sdim
3279218887Sdim  if (!EQ) {
3280218887Sdim    EQ = new BugReportEquivClass(R);
3281219077Sdim    EQClasses.InsertNode(EQ, InsertPos);
3282226633Sdim    EQClassesVector.push_back(EQ);
3283218887Sdim  }
3284218887Sdim  else
3285218887Sdim    EQ->AddReport(R);
3286218887Sdim}
3287218887Sdim
3288218887Sdim
3289218887Sdim//===----------------------------------------------------------------------===//
3290218887Sdim// Emitting reports in equivalence classes.
3291218887Sdim//===----------------------------------------------------------------------===//
3292218887Sdim
3293218887Sdimnamespace {
3294218887Sdimstruct FRIEC_WLItem {
3295218887Sdim  const ExplodedNode *N;
3296218887Sdim  ExplodedNode::const_succ_iterator I, E;
3297218887Sdim
3298218887Sdim  FRIEC_WLItem(const ExplodedNode *n)
3299218887Sdim  : N(n), I(N->succ_begin()), E(N->succ_end()) {}
3300218887Sdim};
3301218887Sdim}
3302218887Sdim
3303218887Sdimstatic BugReport *
3304218887SdimFindReportInEquivalenceClass(BugReportEquivClass& EQ,
3305226633Sdim                             SmallVectorImpl<BugReport*> &bugReports) {
3306218887Sdim
3307218887Sdim  BugReportEquivClass::iterator I = EQ.begin(), E = EQ.end();
3308218887Sdim  assert(I != E);
3309234353Sdim  BugType& BT = I->getBugType();
3310218887Sdim
3311218887Sdim  // If we don't need to suppress any of the nodes because they are
3312218887Sdim  // post-dominated by a sink, simply add all the nodes in the equivalence class
3313218887Sdim  // to 'Nodes'.  Any of the reports will serve as a "representative" report.
3314218887Sdim  if (!BT.isSuppressOnSink()) {
3315234353Sdim    BugReport *R = I;
3316218887Sdim    for (BugReportEquivClass::iterator I=EQ.begin(), E=EQ.end(); I!=E; ++I) {
3317226633Sdim      const ExplodedNode *N = I->getErrorNode();
3318218887Sdim      if (N) {
3319234353Sdim        R = I;
3320218887Sdim        bugReports.push_back(R);
3321218887Sdim      }
3322218887Sdim    }
3323218887Sdim    return R;
3324218887Sdim  }
3325218887Sdim
3326218887Sdim  // For bug reports that should be suppressed when all paths are post-dominated
3327218887Sdim  // by a sink node, iterate through the reports in the equivalence class
3328218887Sdim  // until we find one that isn't post-dominated (if one exists).  We use a
3329218887Sdim  // DFS traversal of the ExplodedGraph to find a non-sink node.  We could write
3330218887Sdim  // this as a recursive function, but we don't want to risk blowing out the
3331218887Sdim  // stack for very long paths.
3332218887Sdim  BugReport *exampleReport = 0;
3333218887Sdim
3334218887Sdim  for (; I != E; ++I) {
3335234353Sdim    const ExplodedNode *errorNode = I->getErrorNode();
3336218887Sdim
3337218887Sdim    if (!errorNode)
3338218887Sdim      continue;
3339218887Sdim    if (errorNode->isSink()) {
3340226633Sdim      llvm_unreachable(
3341218887Sdim           "BugType::isSuppressSink() should not be 'true' for sink end nodes");
3342218887Sdim    }
3343218887Sdim    // No successors?  By definition this nodes isn't post-dominated by a sink.
3344218887Sdim    if (errorNode->succ_empty()) {
3345234353Sdim      bugReports.push_back(I);
3346218887Sdim      if (!exampleReport)
3347234353Sdim        exampleReport = I;
3348218887Sdim      continue;
3349218887Sdim    }
3350218887Sdim
3351218887Sdim    // At this point we know that 'N' is not a sink and it has at least one
3352218887Sdim    // successor.  Use a DFS worklist to find a non-sink end-of-path node.
3353218887Sdim    typedef FRIEC_WLItem WLItem;
3354226633Sdim    typedef SmallVector<WLItem, 10> DFSWorkList;
3355218887Sdim    llvm::DenseMap<const ExplodedNode *, unsigned> Visited;
3356218887Sdim
3357218887Sdim    DFSWorkList WL;
3358218887Sdim    WL.push_back(errorNode);
3359218887Sdim    Visited[errorNode] = 1;
3360218887Sdim
3361218887Sdim    while (!WL.empty()) {
3362218887Sdim      WLItem &WI = WL.back();
3363218887Sdim      assert(!WI.N->succ_empty());
3364218887Sdim
3365218887Sdim      for (; WI.I != WI.E; ++WI.I) {
3366218887Sdim        const ExplodedNode *Succ = *WI.I;
3367218887Sdim        // End-of-path node?
3368218887Sdim        if (Succ->succ_empty()) {
3369218887Sdim          // If we found an end-of-path node that is not a sink.
3370218887Sdim          if (!Succ->isSink()) {
3371234353Sdim            bugReports.push_back(I);
3372218887Sdim            if (!exampleReport)
3373234353Sdim              exampleReport = I;
3374218887Sdim            WL.clear();
3375218887Sdim            break;
3376218887Sdim          }
3377218887Sdim          // Found a sink?  Continue on to the next successor.
3378218887Sdim          continue;
3379218887Sdim        }
3380218887Sdim        // Mark the successor as visited.  If it hasn't been explored,
3381218887Sdim        // enqueue it to the DFS worklist.
3382218887Sdim        unsigned &mark = Visited[Succ];
3383218887Sdim        if (!mark) {
3384218887Sdim          mark = 1;
3385218887Sdim          WL.push_back(Succ);
3386218887Sdim          break;
3387218887Sdim        }
3388218887Sdim      }
3389218887Sdim
3390218887Sdim      // The worklist may have been cleared at this point.  First
3391218887Sdim      // check if it is empty before checking the last item.
3392218887Sdim      if (!WL.empty() && &WL.back() == &WI)
3393218887Sdim        WL.pop_back();
3394218887Sdim    }
3395218887Sdim  }
3396218887Sdim
3397218887Sdim  // ExampleReport will be NULL if all the nodes in the equivalence class
3398218887Sdim  // were post-dominated by sinks.
3399218887Sdim  return exampleReport;
3400218887Sdim}
3401218887Sdim
3402239462Sdimvoid BugReporter::FlushReport(BugReportEquivClass& EQ) {
3403239462Sdim  SmallVector<BugReport*, 10> bugReports;
3404239462Sdim  BugReport *exampleReport = FindReportInEquivalenceClass(EQ, bugReports);
3405239462Sdim  if (exampleReport) {
3406239462Sdim    const PathDiagnosticConsumers &C = getPathDiagnosticConsumers();
3407239462Sdim    for (PathDiagnosticConsumers::const_iterator I=C.begin(),
3408239462Sdim                                                 E=C.end(); I != E; ++I) {
3409239462Sdim      FlushReport(exampleReport, **I, bugReports);
3410239462Sdim    }
3411218887Sdim  }
3412218887Sdim}
3413218887Sdim
3414239462Sdimvoid BugReporter::FlushReport(BugReport *exampleReport,
3415239462Sdim                              PathDiagnosticConsumer &PD,
3416239462Sdim                              ArrayRef<BugReport*> bugReports) {
3417218887Sdim
3418218887Sdim  // FIXME: Make sure we use the 'R' for the path that was actually used.
3419218887Sdim  // Probably doesn't make a difference in practice.
3420218887Sdim  BugType& BT = exampleReport->getBugType();
3421218887Sdim
3422234353Sdim  OwningPtr<PathDiagnostic>
3423234353Sdim    D(new PathDiagnostic(exampleReport->getDeclWithIssue(),
3424234353Sdim                         exampleReport->getBugType().getName(),
3425243830Sdim                         exampleReport->getDescription(),
3426243830Sdim                         exampleReport->getShortDescription(/*Fallback=*/false),
3427249423Sdim                         BT.getCategory(),
3428249423Sdim                         exampleReport->getUniqueingLocation(),
3429249423Sdim                         exampleReport->getUniqueingDecl()));
3430218887Sdim
3431249423Sdim  MaxBugClassSize = std::max(bugReports.size(),
3432249423Sdim                             static_cast<size_t>(MaxBugClassSize));
3433249423Sdim
3434239462Sdim  // Generate the full path diagnostic, using the generation scheme
3435243830Sdim  // specified by the PathDiagnosticConsumer. Note that we have to generate
3436243830Sdim  // path diagnostics even for consumers which do not support paths, because
3437243830Sdim  // the BugReporterVisitors may mark this bug as a false positive.
3438243830Sdim  if (!bugReports.empty())
3439243830Sdim    if (!generatePathDiagnostic(*D.get(), PD, bugReports))
3440243830Sdim      return;
3441218887Sdim
3442249423Sdim  MaxValidBugClassSize = std::max(bugReports.size(),
3443249423Sdim                                  static_cast<size_t>(MaxValidBugClassSize));
3444249423Sdim
3445263508Sdim  // Examine the report and see if the last piece is in a header. Reset the
3446263508Sdim  // report location to the last piece in the main source file.
3447263508Sdim  AnalyzerOptions& Opts = getAnalyzerOptions();
3448263508Sdim  if (Opts.shouldReportIssuesInMainSourceFile() && !Opts.AnalyzeAll)
3449263508Sdim    D->resetDiagnosticLocationToMainFile();
3450263508Sdim
3451239462Sdim  // If the path is empty, generate a single step path with the location
3452239462Sdim  // of the issue.
3453234353Sdim  if (D->path.empty()) {
3454239462Sdim    PathDiagnosticLocation L = exampleReport->getLocation(getSourceManager());
3455239462Sdim    PathDiagnosticPiece *piece =
3456239462Sdim      new PathDiagnosticEventPiece(L, exampleReport->getDescription());
3457239462Sdim    BugReport::ranges_iterator Beg, End;
3458239462Sdim    llvm::tie(Beg, End) = exampleReport->getRanges();
3459234353Sdim    for ( ; Beg != End; ++Beg)
3460234353Sdim      piece->addRange(*Beg);
3461243830Sdim    D->setEndOfPath(piece);
3462218887Sdim  }
3463218887Sdim
3464239462Sdim  // Get the meta data.
3465239462Sdim  const BugReport::ExtraTextList &Meta = exampleReport->getExtraText();
3466239462Sdim  for (BugReport::ExtraTextList::const_iterator i = Meta.begin(),
3467239462Sdim                                                e = Meta.end(); i != e; ++i) {
3468239462Sdim    D->addMeta(*i);
3469239462Sdim  }
3470239462Sdim
3471239462Sdim  PD.HandlePathDiagnostic(D.take());
3472218887Sdim}
3473218887Sdim
3474234353Sdimvoid BugReporter::EmitBasicReport(const Decl *DeclWithIssue,
3475234353Sdim                                  StringRef name,
3476226633Sdim                                  StringRef category,
3477226633Sdim                                  StringRef str, PathDiagnosticLocation Loc,
3478263508Sdim                                  ArrayRef<SourceRange> Ranges) {
3479218887Sdim
3480219077Sdim  // 'BT' is owned by BugReporter.
3481219077Sdim  BugType *BT = getBugTypeForName(name, category);
3482226633Sdim  BugReport *R = new BugReport(*BT, str, Loc);
3483234353Sdim  R->setDeclWithIssue(DeclWithIssue);
3484263508Sdim  for (ArrayRef<SourceRange>::iterator I = Ranges.begin(), E = Ranges.end();
3485263508Sdim       I != E; ++I)
3486263508Sdim    R->addRange(*I);
3487243830Sdim  emitReport(R);
3488218887Sdim}
3489219077Sdim
3490226633SdimBugType *BugReporter::getBugTypeForName(StringRef name,
3491226633Sdim                                        StringRef category) {
3492234353Sdim  SmallString<136> fullDesc;
3493219077Sdim  llvm::raw_svector_ostream(fullDesc) << name << ":" << category;
3494219077Sdim  llvm::StringMapEntry<BugType *> &
3495219077Sdim      entry = StrBugTypes.GetOrCreateValue(fullDesc);
3496219077Sdim  BugType *BT = entry.getValue();
3497219077Sdim  if (!BT) {
3498219077Sdim    BT = new BugType(name, category);
3499219077Sdim    entry.setValue(BT);
3500219077Sdim  }
3501219077Sdim  return BT;
3502219077Sdim}
3503263508Sdim
3504263508Sdim
3505263508Sdimvoid PathPieces::dump() const {
3506263508Sdim  unsigned index = 0;
3507263508Sdim  for (PathPieces::const_iterator I = begin(), E = end(); I != E; ++I) {
3508263508Sdim    llvm::errs() << "[" << index++ << "]  ";
3509263508Sdim    (*I)->dump();
3510263508Sdim    llvm::errs() << "\n";
3511263508Sdim  }
3512263508Sdim}
3513263508Sdim
3514263508Sdimvoid PathDiagnosticCallPiece::dump() const {
3515263508Sdim  llvm::errs() << "CALL\n--------------\n";
3516263508Sdim
3517263508Sdim  if (const Stmt *SLoc = getLocStmt(getLocation()))
3518263508Sdim    SLoc->dump();
3519263508Sdim  else if (const NamedDecl *ND = dyn_cast<NamedDecl>(getCallee()))
3520263508Sdim    llvm::errs() << *ND << "\n";
3521263508Sdim  else
3522263508Sdim    getLocation().dump();
3523263508Sdim}
3524263508Sdim
3525263508Sdimvoid PathDiagnosticEventPiece::dump() const {
3526263508Sdim  llvm::errs() << "EVENT\n--------------\n";
3527263508Sdim  llvm::errs() << getString() << "\n";
3528263508Sdim  llvm::errs() << " ---- at ----\n";
3529263508Sdim  getLocation().dump();
3530263508Sdim}
3531263508Sdim
3532263508Sdimvoid PathDiagnosticControlFlowPiece::dump() const {
3533263508Sdim  llvm::errs() << "CONTROL\n--------------\n";
3534263508Sdim  getStartLocation().dump();
3535263508Sdim  llvm::errs() << " ---- to ----\n";
3536263508Sdim  getEndLocation().dump();
3537263508Sdim}
3538263508Sdim
3539263508Sdimvoid PathDiagnosticMacroPiece::dump() const {
3540263508Sdim  llvm::errs() << "MACRO\n--------------\n";
3541263508Sdim  // FIXME: Print which macro is being invoked.
3542263508Sdim}
3543263508Sdim
3544263508Sdimvoid PathDiagnosticLocation::dump() const {
3545263508Sdim  if (!isValid()) {
3546263508Sdim    llvm::errs() << "<INVALID>\n";
3547263508Sdim    return;
3548263508Sdim  }
3549263508Sdim
3550263508Sdim  switch (K) {
3551263508Sdim  case RangeK:
3552263508Sdim    // FIXME: actually print the range.
3553263508Sdim    llvm::errs() << "<range>\n";
3554263508Sdim    break;
3555263508Sdim  case SingleLocK:
3556263508Sdim    asLocation().dump();
3557263508Sdim    llvm::errs() << "\n";
3558263508Sdim    break;
3559263508Sdim  case StmtK:
3560263508Sdim    if (S)
3561263508Sdim      S->dump();
3562263508Sdim    else
3563263508Sdim      llvm::errs() << "<NULL STMT>\n";
3564263508Sdim    break;
3565263508Sdim  case DeclK:
3566263508Sdim    if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(D))
3567263508Sdim      llvm::errs() << *ND << "\n";
3568263508Sdim    else if (isa<BlockDecl>(D))
3569263508Sdim      // FIXME: Make this nicer.
3570263508Sdim      llvm::errs() << "<block>\n";
3571263508Sdim    else if (D)
3572263508Sdim      llvm::errs() << "<unknown decl>\n";
3573263508Sdim    else
3574263508Sdim      llvm::errs() << "<NULL DECL>\n";
3575263508Sdim    break;
3576263508Sdim  }
3577263508Sdim}
3578