BugReporter.cpp revision 56ca35d396d8692c384c785f9aeebcf22563fe1e
161f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek// BugReporter.cpp - Generate PathDiagnostics for Bugs ------------*- C++ -*--//
261f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek//
361f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek//                     The LLVM Compiler Infrastructure
461f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek//
561f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek// This file is distributed under the University of Illinois Open Source
661f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek// License. See LICENSE.TXT for details.
761f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek//
861f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek//===----------------------------------------------------------------------===//
961f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek//
1061f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek//  This file defines BugReporter, a utility class for generating
116c07bdba93b095b66e2c8c82dd5ed458fa8285eaTed Kremenek//  PathDiagnostics.
1261f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek//
1361f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek//===----------------------------------------------------------------------===//
1461f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek
159b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
169b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
179b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
1861f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek#include "clang/AST/ASTContext.h"
19e41611aa2237d06a0ef61db4528fb2883a8defcdTed Kremenek#include "clang/Analysis/CFG.h"
2061f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek#include "clang/AST/Expr.h"
2100605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek#include "clang/AST/ParentMap.h"
2216f0049415ec596504891259e2a83e19871c0d52Chris Lattner#include "clang/AST/StmtObjC.h"
2316f0049415ec596504891259e2a83e19871c0d52Chris Lattner#include "clang/Basic/SourceManager.h"
2461f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek#include "clang/Analysis/ProgramPoint.h"
259b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
26405674c26c52b05df0d833fae6bae818cd52bc32Chris Lattner#include "llvm/Support/raw_ostream.h"
27331b0ac44b9eb0ffcba66b4f3f3f9adb27c2434fTed Kremenek#include "llvm/ADT/DenseMap.h"
28cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek#include "llvm/ADT/STLExtras.h"
2900605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek#include "llvm/ADT/OwningPtr.h"
3010aa55410bbecbb658ce14a5f801d50cf06d12dfTed Kremenek#include <queue>
3161f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek
3261f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenekusing namespace clang;
339ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremenekusing namespace ento;
3461f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek
358966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed KremenekBugReporterVisitor::~BugReporterVisitor() {}
368966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed KremenekBugReporterContext::~BugReporterContext() {
378966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek  for (visitor_iterator I = visitor_begin(), E = visitor_end(); I != E; ++I)
388966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek    if ((*I)->isOwnedByReporterContext()) delete *I;
398966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek}
408966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek
411b431023814196f87515a540ebcb9e9f1a9176a1Ted Kremenekvoid BugReporterContext::addVisitor(BugReporterVisitor* visitor) {
421b431023814196f87515a540ebcb9e9f1a9176a1Ted Kremenek  if (!visitor)
431b431023814196f87515a540ebcb9e9f1a9176a1Ted Kremenek    return;
441b431023814196f87515a540ebcb9e9f1a9176a1Ted Kremenek
451b431023814196f87515a540ebcb9e9f1a9176a1Ted Kremenek  llvm::FoldingSetNodeID ID;
461b431023814196f87515a540ebcb9e9f1a9176a1Ted Kremenek  visitor->Profile(ID);
471b431023814196f87515a540ebcb9e9f1a9176a1Ted Kremenek  void *InsertPos;
481b431023814196f87515a540ebcb9e9f1a9176a1Ted Kremenek
493e0e41c9bba167437072c47a140d51509ebeb73cTed Kremenek  if (CallbacksSet.FindNodeOrInsertPos(ID, InsertPos)) {
503e0e41c9bba167437072c47a140d51509ebeb73cTed Kremenek    delete visitor;
511b431023814196f87515a540ebcb9e9f1a9176a1Ted Kremenek    return;
523e0e41c9bba167437072c47a140d51509ebeb73cTed Kremenek  }
531b431023814196f87515a540ebcb9e9f1a9176a1Ted Kremenek
541b431023814196f87515a540ebcb9e9f1a9176a1Ted Kremenek  CallbacksSet.InsertNode(visitor, InsertPos);
553baf672378f105602d2b12f03f00277ae1936fe9Ted Kremenek  Callbacks = F.add(visitor, Callbacks);
561b431023814196f87515a540ebcb9e9f1a9176a1Ted Kremenek}
571b431023814196f87515a540ebcb9e9f1a9176a1Ted Kremenek
58cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek//===----------------------------------------------------------------------===//
593106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// Helper routines for walking the ExplodedGraph and fetching statements.
60cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek//===----------------------------------------------------------------------===//
6161f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek
627f330856b8d5df764f1c91218471c47af9ae2aa5Zhongxing Xustatic inline const Stmt* GetStmt(const ProgramPoint &P) {
63592362b46ad69db0db0988e7f9d8cbe647510bddTed Kremenek  if (const StmtPoint* SP = dyn_cast<StmtPoint>(&P))
64592362b46ad69db0db0988e7f9d8cbe647510bddTed Kremenek    return SP->getStmt();
65b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek  else if (const BlockEdge* BE = dyn_cast<BlockEdge>(&P))
6661f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek    return BE->getSrc()->getTerminator();
671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
68b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek  return 0;
6961f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek}
7061f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek
71c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xustatic inline const ExplodedNode*
72c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing XuGetPredecessorNode(const ExplodedNode* N) {
73b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek  return N->pred_empty() ? NULL : *(N->pred_begin());
74706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek}
75706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek
76c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xustatic inline const ExplodedNode*
77c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing XuGetSuccessorNode(const ExplodedNode* N) {
78b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek  return N->succ_empty() ? NULL : *(N->succ_begin());
79bd7efa8ca27ed9676acf00abf31d5e1cd54651ccTed Kremenek}
802673c9ff76ebdb72b7f846e2ff1e0f4256372e19Ted Kremenek
81c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xustatic const Stmt* GetPreviousStmt(const ExplodedNode* N) {
82b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek  for (N = GetPredecessorNode(N); N; N = GetPredecessorNode(N))
835f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek    if (const Stmt *S = GetStmt(N->getLocation()))
84b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek      return S;
851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
86b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek  return 0;
87b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek}
88b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek
89c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xustatic const Stmt* GetNextStmt(const ExplodedNode* N) {
90b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek  for (N = GetSuccessorNode(N); N; N = GetSuccessorNode(N))
915f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek    if (const Stmt *S = GetStmt(N->getLocation())) {
92f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek      // Check if the statement is '?' or '&&'/'||'.  These are "merges",
93f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek      // not actual statement points.
94f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek      switch (S->getStmtClass()) {
95f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek        case Stmt::ChooseExprClass:
9656ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall        case Stmt::BinaryConditionalOperatorClass: continue;
97f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek        case Stmt::ConditionalOperatorClass: continue;
98f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek        case Stmt::BinaryOperatorClass: {
992de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall          BinaryOperatorKind Op = cast<BinaryOperator>(S)->getOpcode();
1002de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall          if (Op == BO_LAnd || Op == BO_LOr)
101f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek            continue;
102f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek          break;
103f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek        }
104f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek        default:
105f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek          break;
106f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek      }
1071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
108b7c515226e91848c7197fd0b9e198fce70ba5893Ted Kremenek      // Some expressions don't have locations.
109b7c515226e91848c7197fd0b9e198fce70ba5893Ted Kremenek      if (S->getLocStart().isInvalid())
110b7c515226e91848c7197fd0b9e198fce70ba5893Ted Kremenek        continue;
1111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
112b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek      return S;
113f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek    }
1141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
115b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek  return 0;
116bd7efa8ca27ed9676acf00abf31d5e1cd54651ccTed Kremenek}
117bd7efa8ca27ed9676acf00abf31d5e1cd54651ccTed Kremenek
1185f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenekstatic inline const Stmt*
1191eb4433ac451dc16f4133a88af2d002ac26c58efMike StumpGetCurrentOrPreviousStmt(const ExplodedNode* N) {
1205f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek  if (const Stmt *S = GetStmt(N->getLocation()))
121b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek    return S;
1221eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
123b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek  return GetPreviousStmt(N);
124b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek}
1251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1265f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenekstatic inline const Stmt*
1271eb4433ac451dc16f4133a88af2d002ac26c58efMike StumpGetCurrentOrNextStmt(const ExplodedNode* N) {
1285f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek  if (const Stmt *S = GetStmt(N->getLocation()))
129b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek    return S;
1301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
131b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek  return GetNextStmt(N);
1323148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek}
1333148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek
134b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek//===----------------------------------------------------------------------===//
1353106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// PathDiagnosticBuilder and its associated routines and helper objects.
136b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek//===----------------------------------------------------------------------===//
137b479dadea93b93d3f0a335c3518b703f140b3f50Ted Kremenek
138c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xutypedef llvm::DenseMap<const ExplodedNode*,
139c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xuconst ExplodedNode*> NodeBackMap;
1407dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek
141babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremeneknamespace {
142ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass NodeMapClosure : public BugReport::NodeResolver {
1437dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek  NodeBackMap& M;
1447dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenekpublic:
1457dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek  NodeMapClosure(NodeBackMap *m) : M(*m) {}
1467dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek  ~NodeMapClosure() {}
1471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
148c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu  const ExplodedNode* getOriginalNode(const ExplodedNode* N) {
1497dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek    NodeBackMap::iterator I = M.find(N);
1507dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek    return I == M.end() ? 0 : I->second;
1517dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek  }
1527dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek};
1531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
154ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass PathDiagnosticBuilder : public BugReporterContext {
1557dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek  BugReport *R;
156babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek  PathDiagnosticClient *PDC;
15700605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek  llvm::OwningPtr<ParentMap> PM;
1587dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek  NodeMapClosure NMC;
1591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumppublic:
1608966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek  PathDiagnosticBuilder(GRBugReporter &br,
1611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump                        BugReport *r, NodeBackMap *Backmap,
1628966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek                        PathDiagnosticClient *pdc)
1638966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek    : BugReporterContext(br),
1641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump      R(r), PDC(pdc), NMC(Backmap) {
1658966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek    addVisitor(R);
1668966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek  }
1671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
168c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu  PathDiagnosticLocation ExecutionContinues(const ExplodedNode* N);
1691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
17000605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek  PathDiagnosticLocation ExecutionContinues(llvm::raw_string_ostream& os,
171c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu                                            const ExplodedNode* N);
1721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
173212f6d3b5fb3fa55ba1e40671cfc336430abc8ddTom Care  Decl const &getCodeDecl() { return R->getErrorNode()->getCodeDecl(); }
174b317f8f5ca8737a5bbad97a3f7566a2dbd2ed61bZhongxing Xu
175212f6d3b5fb3fa55ba1e40671cfc336430abc8ddTom Care  ParentMap& getParentMap() { return R->getErrorNode()->getParentMap(); }
1761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
177c3f83ad7adaff2623986aa1c3e57833babd03d50Ted Kremenek  const Stmt *getParent(const Stmt *S) {
178c3f83ad7adaff2623986aa1c3e57833babd03d50Ted Kremenek    return getParentMap().getParent(S);
179c3f83ad7adaff2623986aa1c3e57833babd03d50Ted Kremenek  }
1801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1818966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek  virtual NodeMapClosure& getNodeResolver() { return NMC; }
1827297134f128423fce2e88f92421ed135bded7d4eDouglas Gregor
183d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek  PathDiagnosticLocation getEnclosingStmtLocation(const Stmt *S);
1841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1857dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek  PathDiagnosticClient::PathGenerationScheme getGenerationScheme() const {
1867dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek    return PDC ? PDC->getGenerationScheme() : PathDiagnosticClient::Extensive;
1877dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek  }
1887dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek
189babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek  bool supportsLogicalOpControlFlow() const {
190babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek    return PDC ? PDC->supportsLogicalOpControlFlow() : true;
1911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  }
192babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek};
193babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek} // end anonymous namespace
194babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek
19500605e0f011ed99225a22026344c5fc1b3212cd7Ted KremenekPathDiagnosticLocation
196c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing XuPathDiagnosticBuilder::ExecutionContinues(const ExplodedNode* N) {
1975f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek  if (const Stmt *S = GetNextStmt(N))
1988966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek    return PathDiagnosticLocation(S, getSourceManager());
19900605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek
2001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  return FullSourceLoc(N->getLocationContext()->getDecl()->getBodyRBrace(),
201f7a50a4ee255b3a624ae64125537a7bdbd1da0efZhongxing Xu                       getSourceManager());
202082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek}
2031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
20400605e0f011ed99225a22026344c5fc1b3212cd7Ted KremenekPathDiagnosticLocation
205babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed KremenekPathDiagnosticBuilder::ExecutionContinues(llvm::raw_string_ostream& os,
206c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu                                          const ExplodedNode* N) {
207babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek
208143ca222583a4a355fdc89af852deef287499300Ted Kremenek  // Slow, but probably doesn't matter.
209b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek  if (os.str().empty())
210b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek    os << ' ';
2111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
21200605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek  const PathDiagnosticLocation &Loc = ExecutionContinues(N);
2131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
21400605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek  if (Loc.asStmt())
215b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek    os << "Execution continues on line "
2168966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek       << getSourceManager().getInstantiationLineNumber(Loc.asLocation())
2178966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek       << '.';
2184f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek  else {
2194f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek    os << "Execution jumps to the end of the ";
2204f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek    const Decl *D = N->getLocationContext()->getDecl();
2214f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek    if (isa<ObjCMethodDecl>(D))
2224f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek      os << "method";
2234f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek    else if (isa<FunctionDecl>(D))
2244f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek      os << "function";
2254f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek    else {
2264f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek      assert(isa<BlockDecl>(D));
2274f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek      os << "anonymous block";
2284f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek    }
2294f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek    os << '.';
2304f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek  }
2311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
232082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek  return Loc;
233143ca222583a4a355fdc89af852deef287499300Ted Kremenek}
234143ca222583a4a355fdc89af852deef287499300Ted Kremenek
235ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenekstatic bool IsNested(const Stmt *S, ParentMap &PM) {
236ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek  if (isa<Expr>(S) && PM.isConsumedExpr(cast<Expr>(S)))
237ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek    return true;
2381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
239ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek  const Stmt *Parent = PM.getParentIgnoreParens(S);
2401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
241ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek  if (Parent)
242ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek    switch (Parent->getStmtClass()) {
243ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek      case Stmt::ForStmtClass:
244ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek      case Stmt::DoStmtClass:
245ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek      case Stmt::WhileStmtClass:
246ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek        return true;
247ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek      default:
248ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek        break;
249ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek    }
2501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  return false;
252ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek}
253ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek
254d8c938b0f6b7a7156181be575239e4c6e15a2adbTed KremenekPathDiagnosticLocation
255d8c938b0f6b7a7156181be575239e4c6e15a2adbTed KremenekPathDiagnosticBuilder::getEnclosingStmtLocation(const Stmt *S) {
256d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek  assert(S && "Null Stmt* passed to getEnclosingStmtLocation");
2571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  ParentMap &P = getParentMap();
2588966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek  SourceManager &SMgr = getSourceManager();
259e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek
260ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek  while (IsNested(S, P)) {
2618c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek    const Stmt *Parent = P.getParentIgnoreParens(S);
2621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
263af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek    if (!Parent)
264af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek      break;
2651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
266af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek    switch (Parent->getStmtClass()) {
2675fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek      case Stmt::BinaryOperatorClass: {
2685fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek        const BinaryOperator *B = cast<BinaryOperator>(Parent);
2695fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek        if (B->isLogicalOp())
2705fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek          return PathDiagnosticLocation(S, SMgr);
2715fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek        break;
2721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump      }
273af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek      case Stmt::CompoundStmtClass:
274af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek      case Stmt::StmtExprClass:
2751d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek        return PathDiagnosticLocation(S, SMgr);
2761d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek      case Stmt::ChooseExprClass:
2771d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek        // Similar to '?' if we are referring to condition, just have the edge
2781d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek        // point to the entire choose expression.
2791d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek        if (cast<ChooseExpr>(Parent)->getCond() == S)
2801d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek          return PathDiagnosticLocation(Parent, SMgr);
2811d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek        else
2821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump          return PathDiagnosticLocation(S, SMgr);
28356ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall      case Stmt::BinaryConditionalOperatorClass:
2841d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek      case Stmt::ConditionalOperatorClass:
2851d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek        // For '?', if we are referring to condition, just have the edge point
2861d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek        // to the entire '?' expression.
28756ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall        if (cast<AbstractConditionalOperator>(Parent)->getCond() == S)
2881d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek          return PathDiagnosticLocation(Parent, SMgr);
2891d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek        else
2901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump          return PathDiagnosticLocation(S, SMgr);
291af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek      case Stmt::DoStmtClass:
2921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump          return PathDiagnosticLocation(S, SMgr);
293af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek      case Stmt::ForStmtClass:
294af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek        if (cast<ForStmt>(Parent)->getBody() == S)
2951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump          return PathDiagnosticLocation(S, SMgr);
2961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump        break;
297af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek      case Stmt::IfStmtClass:
298af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek        if (cast<IfStmt>(Parent)->getCond() != S)
299af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek          return PathDiagnosticLocation(S, SMgr);
3008bd4d037d837e7922c3661d6158229da58a03887Ted Kremenek        break;
301af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek      case Stmt::ObjCForCollectionStmtClass:
302af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek        if (cast<ObjCForCollectionStmt>(Parent)->getBody() == S)
303af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek          return PathDiagnosticLocation(S, SMgr);
304af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek        break;
305af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek      case Stmt::WhileStmtClass:
306af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek        if (cast<WhileStmt>(Parent)->getCond() != S)
307af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek          return PathDiagnosticLocation(S, SMgr);
308af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek        break;
309af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek      default:
310af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek        break;
311af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek    }
312af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek
313d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek    S = Parent;
314d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek  }
3151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
316d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek  assert(S && "Cannot have null Stmt for PathDiagnosticLocation");
317e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek
318e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek  // Special case: DeclStmts can appear in for statement declarations, in which
319e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek  //  case the ForStmt is the context.
320e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek  if (isa<DeclStmt>(S)) {
321e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek    if (const Stmt *Parent = P.getParent(S)) {
322e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek      switch (Parent->getStmtClass()) {
323e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek        case Stmt::ForStmtClass:
324e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek        case Stmt::ObjCForCollectionStmtClass:
325e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek          return PathDiagnosticLocation(Parent, SMgr);
326e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek        default:
327e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek          break;
3281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump      }
3291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    }
330e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek  }
331e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek  else if (isa<BinaryOperator>(S)) {
332e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek    // Special case: the binary operator represents the initialization
333e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek    // code in a for statement (this can happen when the variable being
334e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek    // initialized is an old variable.
335e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek    if (const ForStmt *FS =
336e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek          dyn_cast_or_null<ForStmt>(P.getParentIgnoreParens(S))) {
337e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek      if (FS->getInit() == S)
338e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek        return PathDiagnosticLocation(FS, SMgr);
339e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek    }
340e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek  }
341e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek
342d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek  return PathDiagnosticLocation(S, SMgr);
343d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek}
344d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek
345cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek//===----------------------------------------------------------------------===//
3463106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// ScanNotableSymbols: closure-like callback for scanning Store bindings.
347cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek//===----------------------------------------------------------------------===//
348cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek
3493106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenekstatic const VarDecl*
350c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing XuGetMostRecentVarDeclBinding(const ExplodedNode* N,
3513106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek                            GRStateManager& VMgr, SVal X) {
3521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3533106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  for ( ; N ; N = N->pred_empty() ? 0 : *N->pred_begin()) {
3541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3553106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    ProgramPoint P = N->getLocation();
3561eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3573106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    if (!isa<PostStmt>(P))
3583106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      continue;
3591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3605f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek    const DeclRefExpr* DR = dyn_cast<DeclRefExpr>(cast<PostStmt>(P).getStmt());
3611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3623106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    if (!DR)
3633106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      continue;
3641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3651397663af9dbcc24dbf0e11de43931b3dc08fdbbTed Kremenek    SVal Y = N->getState()->getSVal(DR);
3661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3673106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    if (X != Y)
3683106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      continue;
3691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3705f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek    const VarDecl* VD = dyn_cast<VarDecl>(DR->getDecl());
3711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3723106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    if (!VD)
3733106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      continue;
3741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3753106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    return VD;
376cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  }
3771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3783106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  return 0;
379bb77e9b908658b354b058509d3801f3aed052becTed Kremenek}
380bb77e9b908658b354b058509d3801f3aed052becTed Kremenek
3813106198188ac6eb2753f1764d5c28376b0b76351Ted Kremeneknamespace {
382ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass NotableSymbolHandler
3833106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek: public StoreManager::BindingsHandler {
3841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3853106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  SymbolRef Sym;
3863106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  const GRState* PrevSt;
3873106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  const Stmt* S;
3883106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  GRStateManager& VMgr;
389c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu  const ExplodedNode* Pred;
3901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  PathDiagnostic& PD;
3913106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  BugReporter& BR;
3921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3933106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenekpublic:
3941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3953106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  NotableSymbolHandler(SymbolRef sym, const GRState* prevst, const Stmt* s,
396c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu                       GRStateManager& vmgr, const ExplodedNode* pred,
3973106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek                       PathDiagnostic& pd, BugReporter& br)
3983106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  : Sym(sym), PrevSt(prevst), S(s), VMgr(vmgr), Pred(pred), PD(pd), BR(br) {}
3991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4003106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  bool HandleBinding(StoreManager& SMgr, Store store, const MemRegion* R,
4013106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek                     SVal V) {
4021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4033106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    SymbolRef ScanSym = V.getAsSymbol();
4041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4053106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    if (ScanSym != Sym)
4063106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      return true;
4071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    // Check if the previous state has this binding.
4091397663af9dbcc24dbf0e11de43931b3dc08fdbbTed Kremenek    SVal X = PrevSt->getSVal(loc::MemRegionVal(R));
4101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4113106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    if (X == V) // Same binding?
4123106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      return true;
4131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4143106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // Different binding.  Only handle assignments for now.  We don't pull
4151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    // this check out of the loop because we will eventually handle other
4163106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // cases.
4171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4183106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    VarDecl *VD = 0;
4191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4203106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    if (const BinaryOperator* B = dyn_cast<BinaryOperator>(S)) {
4213106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      if (!B->isAssignmentOp())
4223106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        return true;
4231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4243106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      // What variable did we assign to?
4253106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      DeclRefExpr* DR = dyn_cast<DeclRefExpr>(B->getLHS()->IgnoreParenCasts());
4261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4273106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      if (!DR)
4283106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        return true;
4291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4303106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      VD = dyn_cast<VarDecl>(DR->getDecl());
4313106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    }
4323106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    else if (const DeclStmt* DS = dyn_cast<DeclStmt>(S)) {
4333106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      // FIXME: Eventually CFGs won't have DeclStmts.  Right now we
4343106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      //  assume that each DeclStmt has a single Decl.  This invariant
4353106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      //  holds by contruction in the CFG.
4363106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      VD = dyn_cast<VarDecl>(*DS->decl_begin());
4373106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    }
4381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4393106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    if (!VD)
4403106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      return true;
4411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4423106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // What is the most recently referenced variable with this binding?
4433106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    const VarDecl* MostRecent = GetMostRecentVarDeclBinding(Pred, VMgr, V);
4441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4453106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    if (!MostRecent)
4463106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      return true;
4471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4483106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // Create the diagnostic.
4493106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    FullSourceLoc L(S->getLocStart(), BR.getSourceManager());
4501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4517dfc9420babe83e236a47e752f8723bd06070d9dZhanyong Wan    if (Loc::isLocType(VD->getType())) {
4523106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      std::string msg = "'" + std::string(VD->getNameAsString()) +
4533106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      "' now aliases '" + MostRecent->getNameAsString() + "'";
4541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4553106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      PD.push_front(new PathDiagnosticEventPiece(L, msg));
4563106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    }
4571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4583106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    return true;
4591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  }
4603106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek};
4613106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek}
4623106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
463c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xustatic void HandleNotableSymbol(const ExplodedNode* N,
4643106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek                                const Stmt* S,
4653106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek                                SymbolRef Sym, BugReporter& BR,
4663106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek                                PathDiagnostic& PD) {
4671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
468c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu  const ExplodedNode* Pred = N->pred_empty() ? 0 : *N->pred_begin();
4693106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  const GRState* PrevSt = Pred ? Pred->getState() : 0;
4701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4713106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  if (!PrevSt)
4723106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    return;
4731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4743106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // Look at the region bindings of the current state that map to the
4753106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // specified symbol.  Are any of them not in the previous state?
4763106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  GRStateManager& VMgr = cast<GRBugReporter>(BR).getStateManager();
4773106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  NotableSymbolHandler H(Sym, PrevSt, S, VMgr, Pred, PD, BR);
4783106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  cast<GRBugReporter>(BR).getStateManager().iterBindings(N->getState(), H);
47961f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek}
48061f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek
4813106198188ac6eb2753f1764d5c28376b0b76351Ted Kremeneknamespace {
482ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass ScanNotableSymbols
4833106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek: public StoreManager::BindingsHandler {
4841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4853106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  llvm::SmallSet<SymbolRef, 10> AlreadyProcessed;
486c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu  const ExplodedNode* N;
4875f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek  const Stmt* S;
4883106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  GRBugReporter& BR;
4893106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  PathDiagnostic& PD;
4901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4913106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenekpublic:
492c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu  ScanNotableSymbols(const ExplodedNode* n, const Stmt* s,
4935f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek                     GRBugReporter& br, PathDiagnostic& pd)
4943106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  : N(n), S(s), BR(br), PD(pd) {}
4951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4963106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  bool HandleBinding(StoreManager& SMgr, Store store,
4973106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek                     const MemRegion* R, SVal V) {
4981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4993106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    SymbolRef ScanSym = V.getAsSymbol();
5001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
5013106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    if (!ScanSym)
5023106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      return true;
5031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
5043106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    if (!BR.isNotable(ScanSym))
5053106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      return true;
5061eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
5073106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    if (AlreadyProcessed.count(ScanSym))
5083106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      return true;
5091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
5103106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    AlreadyProcessed.insert(ScanSym);
5111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
5123106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    HandleNotableSymbol(N, S, ScanSym, BR, PD);
5133106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    return true;
514bb77e9b908658b354b058509d3801f3aed052becTed Kremenek  }
5153106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek};
5163106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} // end anonymous namespace
51750a6d0ce344c02782e0207574005c3b2aaa5077cTed Kremenek
518cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek//===----------------------------------------------------------------------===//
5193106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// "Minimal" path diagnostic generation algorithm.
520cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek//===----------------------------------------------------------------------===//
521cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek
52214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekstatic void CompactPathDiagnostic(PathDiagnostic &PD, const SourceManager& SM);
52314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
5243106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenekstatic void GenerateMinimalPathDiagnostic(PathDiagnostic& PD,
5253106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek                                          PathDiagnosticBuilder &PDB,
526c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu                                          const ExplodedNode *N) {
5278966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek
5283106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  SourceManager& SMgr = PDB.getSourceManager();
5291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  const ExplodedNode* NextNode = N->pred_empty()
5303106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek                                        ? NULL : *(N->pred_begin());
5313106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  while (NextNode) {
5321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    N = NextNode;
5333106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    NextNode = GetPredecessorNode(N);
5341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
53561f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek    ProgramPoint P = N->getLocation();
5361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
53761f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek    if (const BlockEdge* BE = dyn_cast<BlockEdge>(&P)) {
53803509aea098772644bf4662dc1c88634818ceeccZhongxing Xu      const CFGBlock* Src = BE->getSrc();
53903509aea098772644bf4662dc1c88634818ceeccZhongxing Xu      const CFGBlock* Dst = BE->getDst();
54003509aea098772644bf4662dc1c88634818ceeccZhongxing Xu      const Stmt* T = Src->getTerminator();
5411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
54261f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek      if (!T)
54361f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek        continue;
5441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
545082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek      FullSourceLoc Start(T->getLocStart(), SMgr);
5461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
54761f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek      switch (T->getStmtClass()) {
54861f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek        default:
54961f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek          break;
5501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
55161f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek        case Stmt::GotoStmtClass:
5521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump        case Stmt::IndirectGotoStmtClass: {
5535f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek          const Stmt* S = GetNextStmt(N);
5541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
55561f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek          if (!S)
55661f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek            continue;
5571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
558297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek          std::string sbuf;
5591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump          llvm::raw_string_ostream os(sbuf);
560d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek          const PathDiagnosticLocation &End = PDB.getEnclosingStmtLocation(S);
5611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
56200605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek          os << "Control jumps to line "
5633106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek          << End.asLocation().getInstantiationLineNumber();
564082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek          PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
565082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek                                                           os.str()));
56661f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek          break;
56761f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek        }
5681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
5691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump        case Stmt::SwitchStmtClass: {
57061f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek          // Figure out what case arm we took.
571297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek          std::string sbuf;
572297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek          llvm::raw_string_ostream os(sbuf);
5731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
57403509aea098772644bf4662dc1c88634818ceeccZhongxing Xu          if (const Stmt* S = Dst->getLabel()) {
57500605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek            PathDiagnosticLocation End(S, SMgr);
5761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
5775a429954aedd8a830a70fcea2cb51561673e4fc3Ted Kremenek            switch (S->getStmtClass()) {
578082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek              default:
579082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek                os << "No cases match in the switch statement. "
5803106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek                "Control jumps to line "
5813106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek                << End.asLocation().getInstantiationLineNumber();
582082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek                break;
583082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek              case Stmt::DefaultStmtClass:
584082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek                os << "Control jumps to the 'default' case at line "
5853106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek                << End.asLocation().getInstantiationLineNumber();
586082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek                break;
5871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
588082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek              case Stmt::CaseStmtClass: {
5891eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump                os << "Control jumps to 'case ";
59003509aea098772644bf4662dc1c88634818ceeccZhongxing Xu                const CaseStmt* Case = cast<CaseStmt>(S);
59103509aea098772644bf4662dc1c88634818ceeccZhongxing Xu                const Expr* LHS = Case->getLHS()->IgnoreParenCasts();
5921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
5931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump                // Determine if it is an enum.
594082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek                bool GetRawInt = true;
5951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
59603509aea098772644bf4662dc1c88634818ceeccZhongxing Xu                if (const DeclRefExpr* DR = dyn_cast<DeclRefExpr>(LHS)) {
597082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek                  // FIXME: Maybe this should be an assertion.  Are there cases
598082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek                  // were it is not an EnumConstantDecl?
59903509aea098772644bf4662dc1c88634818ceeccZhongxing Xu                  const EnumConstantDecl* D =
60003509aea098772644bf4662dc1c88634818ceeccZhongxing Xu                    dyn_cast<EnumConstantDecl>(DR->getDecl());
6011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
602082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek                  if (D) {
603082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek                    GetRawInt = false;
604900fc6388e803868a34b9483510c345e9b49d7ebBenjamin Kramer                    os << D;
605082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek                  }
6065a429954aedd8a830a70fcea2cb51561673e4fc3Ted Kremenek                }
6079ec64d6e2fe575b297e1eaa5051efc2983373e25Eli Friedman
6089ec64d6e2fe575b297e1eaa5051efc2983373e25Eli Friedman                if (GetRawInt)
6098966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek                  os << LHS->EvaluateAsInt(PDB.getASTContext());
6109ec64d6e2fe575b297e1eaa5051efc2983373e25Eli Friedman
61100605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek                os << ":'  at line "
6123106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek                << End.asLocation().getInstantiationLineNumber();
613082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek                break;
614082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek              }
61561f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek            }
61600605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek            PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
61700605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek                                                             os.str()));
61861f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek          }
619567839273dfc395a459cbe77d5f8d128b9ae85bfTed Kremenek          else {
620c3517ebb48a51e146badc08bc3684520c41da6c8Ted Kremenek            os << "'Default' branch taken. ";
6211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump            const PathDiagnosticLocation &End = PDB.ExecutionContinues(os, N);
62200605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek            PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
62300605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek                                                             os.str()));
624567839273dfc395a459cbe77d5f8d128b9ae85bfTed Kremenek          }
6251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
62661f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek          break;
62761f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek        }
6281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
6292673c9ff76ebdb72b7f846e2ff1e0f4256372e19Ted Kremenek        case Stmt::BreakStmtClass:
6302673c9ff76ebdb72b7f846e2ff1e0f4256372e19Ted Kremenek        case Stmt::ContinueStmtClass: {
631297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek          std::string sbuf;
632297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek          llvm::raw_string_ostream os(sbuf);
63300605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek          PathDiagnosticLocation End = PDB.ExecutionContinues(os, N);
634082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek          PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
635082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek                                                           os.str()));
6362673c9ff76ebdb72b7f846e2ff1e0f4256372e19Ted Kremenek          break;
6372673c9ff76ebdb72b7f846e2ff1e0f4256372e19Ted Kremenek        }
6381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
6393106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek          // Determine control-flow for ternary '?'.
64056ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall        case Stmt::BinaryConditionalOperatorClass:
641706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek        case Stmt::ConditionalOperatorClass: {
642297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek          std::string sbuf;
643297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek          llvm::raw_string_ostream os(sbuf);
6441d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek          os << "'?' condition is ";
6451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
646706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek          if (*(Src->succ_begin()+1) == Dst)
647082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek            os << "false";
648706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek          else
649082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek            os << "true";
6501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
65100605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek          PathDiagnosticLocation End = PDB.ExecutionContinues(N);
6521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
6531d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek          if (const Stmt *S = End.asStmt())
6541d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek            End = PDB.getEnclosingStmtLocation(S);
6551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
656babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek          PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
657babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek                                                           os.str()));
658babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek          break;
659babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek        }
6601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
6613106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek          // Determine control-flow for short-circuited '&&' and '||'.
662babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek        case Stmt::BinaryOperatorClass: {
663babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek          if (!PDB.supportsLogicalOpControlFlow())
664babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek            break;
6651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
66603509aea098772644bf4662dc1c88634818ceeccZhongxing Xu          const BinaryOperator *B = cast<BinaryOperator>(T);
667babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek          std::string sbuf;
668babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek          llvm::raw_string_ostream os(sbuf);
669babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek          os << "Left side of '";
6701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
6712de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall          if (B->getOpcode() == BO_LAnd) {
672f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek            os << "&&" << "' is ";
6731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
674f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek            if (*(Src->succ_begin()+1) == Dst) {
675f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek              os << "false";
676f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek              PathDiagnosticLocation End(B->getLHS(), SMgr);
677f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek              PathDiagnosticLocation Start(B->getOperatorLoc(), SMgr);
678f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek              PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
679f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek                                                               os.str()));
6801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump            }
681f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek            else {
682f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek              os << "true";
683f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek              PathDiagnosticLocation Start(B->getLHS(), SMgr);
684f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek              PathDiagnosticLocation End = PDB.ExecutionContinues(N);
685f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek              PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
686f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek                                                               os.str()));
6871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump            }
688babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek          }
689babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek          else {
6902de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall            assert(B->getOpcode() == BO_LOr);
691f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek            os << "||" << "' is ";
6921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
693f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek            if (*(Src->succ_begin()+1) == Dst) {
694f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek              os << "false";
695f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek              PathDiagnosticLocation Start(B->getLHS(), SMgr);
696f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek              PathDiagnosticLocation End = PDB.ExecutionContinues(N);
697f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek              PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
6981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump                                                               os.str()));
699f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek            }
700f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek            else {
701f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek              os << "true";
702f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek              PathDiagnosticLocation End(B->getLHS(), SMgr);
703f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek              PathDiagnosticLocation Start(B->getOperatorLoc(), SMgr);
704f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek              PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
7051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump                                                               os.str()));
706f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek            }
707babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek          }
7081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
709706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek          break;
710706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek        }
7111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
7121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump        case Stmt::DoStmtClass:  {
713706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek          if (*(Src->succ_begin()) == Dst) {
714297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek            std::string sbuf;
715297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek            llvm::raw_string_ostream os(sbuf);
7161eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
717c3517ebb48a51e146badc08bc3684520c41da6c8Ted Kremenek            os << "Loop condition is true. ";
718d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek            PathDiagnosticLocation End = PDB.ExecutionContinues(os, N);
7191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
720d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek            if (const Stmt *S = End.asStmt())
721d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek              End = PDB.getEnclosingStmtLocation(S);
7221eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
723082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek            PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
724082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek                                                             os.str()));
725082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek          }
726082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek          else {
72700605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek            PathDiagnosticLocation End = PDB.ExecutionContinues(N);
7281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
729d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek            if (const Stmt *S = End.asStmt())
730d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek              End = PDB.getEnclosingStmtLocation(S);
7311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
7323106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek            PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
7333106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek                              "Loop condition is false.  Exiting loop"));
7343106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek          }
7351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
7363106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek          break;
7373106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        }
7381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
7393106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        case Stmt::WhileStmtClass:
7401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump        case Stmt::ForStmtClass: {
7413106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek          if (*(Src->succ_begin()+1) == Dst) {
7423106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek            std::string sbuf;
7433106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek            llvm::raw_string_ostream os(sbuf);
7441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
7453106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek            os << "Loop condition is false. ";
7463106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek            PathDiagnosticLocation End = PDB.ExecutionContinues(os, N);
7473106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek            if (const Stmt *S = End.asStmt())
7483106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek              End = PDB.getEnclosingStmtLocation(S);
7491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
7503106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek            PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
7513106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek                                                             os.str()));
7523106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek          }
7533106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek          else {
7543106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek            PathDiagnosticLocation End = PDB.ExecutionContinues(N);
7553106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek            if (const Stmt *S = End.asStmt())
7563106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek              End = PDB.getEnclosingStmtLocation(S);
7571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
7583106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek            PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
7595fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek                            "Loop condition is true.  Entering loop body"));
7603106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek          }
7611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
7623106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek          break;
7633106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        }
7641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
7653106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        case Stmt::IfStmtClass: {
7663106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek          PathDiagnosticLocation End = PDB.ExecutionContinues(N);
7671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
7683106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek          if (const Stmt *S = End.asStmt())
7693106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek            End = PDB.getEnclosingStmtLocation(S);
7701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
7713106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek          if (*(Src->succ_begin()+1) == Dst)
7723106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek            PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
7735fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek                                                        "Taking false branch"));
7741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump          else
7753106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek            PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
7765fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek                                                         "Taking true branch"));
7771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
7783106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek          break;
7793106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        }
7803106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      }
7813106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    }
7821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
783dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek    if (NextNode) {
784dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek      for (BugReporterContext::visitor_iterator I = PDB.visitor_begin(),
785dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek           E = PDB.visitor_end(); I!=E; ++I) {
786dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek        if (PathDiagnosticPiece* p = (*I)->VisitNode(N, NextNode, PDB))
787dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek          PD.push_front(p);
788dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek      }
7898966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek    }
7901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
7911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    if (const PostStmt* PS = dyn_cast<PostStmt>(&P)) {
7923106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      // Scan the region bindings, and see if a "notable" symbol has a new
7933106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      // lval binding.
7943106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      ScanNotableSymbols SNS(N, PS->getStmt(), PDB.getBugReporter(), PD);
7953106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      PDB.getStateManager().iterBindings(N->getState(), SNS);
7963106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    }
7973106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  }
7981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
79914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  // After constructing the full PathDiagnostic, do a pass over it to compact
80014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  // PathDiagnosticPieces that occur within a macro.
80114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  CompactPathDiagnostic(PD, PDB.getSourceManager());
8023106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek}
8033106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
8043106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===//
8055fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek// "Extensive" PathDiagnostic generation.
8065fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek//===----------------------------------------------------------------------===//
8075fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek
8085fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenekstatic bool IsControlFlowExpr(const Stmt *S) {
8095fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek  const Expr *E = dyn_cast<Expr>(S);
8101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
8115fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek  if (!E)
8125fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek    return false;
8131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
8141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  E = E->IgnoreParenCasts();
8151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
81656ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall  if (isa<AbstractConditionalOperator>(E))
8175fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek    return true;
8181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
8195fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek  if (const BinaryOperator *B = dyn_cast<BinaryOperator>(E))
8205fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek    if (B->isLogicalOp())
8215fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek      return true;
8221eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
8231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  return false;
8245fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek}
8255fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek
82614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremeneknamespace {
827ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass ContextLocation : public PathDiagnosticLocation {
8288f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek  bool IsDead;
8298f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenekpublic:
8308f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek  ContextLocation(const PathDiagnosticLocation &L, bool isdead = false)
8318f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek    : PathDiagnosticLocation(L), IsDead(isdead) {}
8321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
8331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  void markDead() { IsDead = true; }
8348f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek  bool isDead() const { return IsDead; }
8358f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek};
8361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
837ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass EdgeBuilder {
8388f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek  std::vector<ContextLocation> CLocs;
8398f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek  typedef std::vector<ContextLocation>::iterator iterator;
84014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  PathDiagnostic &PD;
84114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  PathDiagnosticBuilder &PDB;
84214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  PathDiagnosticLocation PrevLoc;
8431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
8448f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek  bool IsConsumedExpr(const PathDiagnosticLocation &L);
8451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
84614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  bool containsLocation(const PathDiagnosticLocation &Container,
84714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek                        const PathDiagnosticLocation &Containee);
8481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
84914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  PathDiagnosticLocation getContextLocation(const PathDiagnosticLocation &L);
8501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
8519650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek  PathDiagnosticLocation cleanUpLocation(PathDiagnosticLocation L,
8529650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek                                         bool firstCharOnly = false) {
8538c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek    if (const Stmt *S = L.asStmt()) {
8549650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek      const Stmt *Original = S;
8558c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek      while (1) {
8568c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek        // Adjust the location for some expressions that are best referenced
8578c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek        // by one of their subexpressions.
8589650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek        switch (S->getStmtClass()) {
8599650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek          default:
8609650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek            break;
8619650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek          case Stmt::ParenExprClass:
8629650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek            S = cast<ParenExpr>(S)->IgnoreParens();
8639650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek            firstCharOnly = true;
8649650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek            continue;
86556ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall          case Stmt::BinaryConditionalOperatorClass:
8669650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek          case Stmt::ConditionalOperatorClass:
86756ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall            S = cast<AbstractConditionalOperator>(S)->getCond();
8689650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek            firstCharOnly = true;
8699650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek            continue;
8709650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek          case Stmt::ChooseExprClass:
8719650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek            S = cast<ChooseExpr>(S)->getCond();
8729650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek            firstCharOnly = true;
8739650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek            continue;
8749650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek          case Stmt::BinaryOperatorClass:
8759650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek            S = cast<BinaryOperator>(S)->getLHS();
8769650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek            firstCharOnly = true;
8779650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek            continue;
8789650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek        }
8791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
8809650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek        break;
8818c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek      }
8821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
8839650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek      if (S != Original)
8849650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek        L = PathDiagnosticLocation(S, L.getManager());
8858c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek    }
8861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
8879650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek    if (firstCharOnly)
8889650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek      L = PathDiagnosticLocation(L.asLocation());
8899650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek
8908c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek    return L;
8918c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek  }
8921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
89314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  void popLocation() {
8948f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek    if (!CLocs.back().isDead() && CLocs.back().asLocation().isFileID()) {
8955c7168cbe8a0eabd05e0e12e469090d2cabd27c0Ted Kremenek      // For contexts, we only one the first character as the range.
89607c015cbcee31f72e2d320ba2c713c046bed42faTed Kremenek      rawAddEdge(cleanUpLocation(CLocs.back(), true));
8975c7168cbe8a0eabd05e0e12e469090d2cabd27c0Ted Kremenek    }
89814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    CLocs.pop_back();
89914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  }
9001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
90114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekpublic:
90214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  EdgeBuilder(PathDiagnostic &pd, PathDiagnosticBuilder &pdb)
90314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    : PD(pd), PDB(pdb) {
9041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
905a301a6773db085575ac51e3c966858180390c25bTed Kremenek      // If the PathDiagnostic already has pieces, add the enclosing statement
906a301a6773db085575ac51e3c966858180390c25bTed Kremenek      // of the first piece as a context as well.
90714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek      if (!PD.empty()) {
90814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek        PrevLoc = PD.begin()->getLocation();
9091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
91014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek        if (const Stmt *S = PrevLoc.asStmt())
911e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek          addExtendedContext(PDB.getEnclosingStmtLocation(S).asStmt());
91214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek      }
91314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  }
91414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
91514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  ~EdgeBuilder() {
91614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    while (!CLocs.empty()) popLocation();
9171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
918a301a6773db085575ac51e3c966858180390c25bTed Kremenek    // Finally, add an initial edge from the start location of the first
919a301a6773db085575ac51e3c966858180390c25bTed Kremenek    // statement (if it doesn't already exist).
920d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl    // FIXME: Should handle CXXTryStmt if analyser starts supporting C++.
921d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl    if (const CompoundStmt *CS =
9225f1bfc10a12d9759444eb433f52a85d2e0058967Argyrios Kyrtzidis          dyn_cast_or_null<CompoundStmt>(PDB.getCodeDecl().getBody()))
923a301a6773db085575ac51e3c966858180390c25bTed Kremenek      if (!CS->body_empty()) {
924a301a6773db085575ac51e3c966858180390c25bTed Kremenek        SourceLocation Loc = (*CS->body_begin())->getLocStart();
925a301a6773db085575ac51e3c966858180390c25bTed Kremenek        rawAddEdge(PathDiagnosticLocation(Loc, PDB.getSourceManager()));
926a301a6773db085575ac51e3c966858180390c25bTed Kremenek      }
9271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
92814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  }
92914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
93014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  void addEdge(PathDiagnosticLocation NewLoc, bool alwaysAdd = false);
9311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
9328bd4d037d837e7922c3661d6158229da58a03887Ted Kremenek  void rawAddEdge(PathDiagnosticLocation NewLoc);
9331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
93414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  void addContext(const Stmt *S);
935e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek  void addExtendedContext(const Stmt *S);
9361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump};
93714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} // end anonymous namespace
93814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
93914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
94014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted KremenekPathDiagnosticLocation
94114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted KremenekEdgeBuilder::getContextLocation(const PathDiagnosticLocation &L) {
94214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  if (const Stmt *S = L.asStmt()) {
94314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    if (IsControlFlowExpr(S))
94414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek      return L;
9451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
9461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    return PDB.getEnclosingStmtLocation(S);
94714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  }
9481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
94914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  return L;
95014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek}
95114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
95214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekbool EdgeBuilder::containsLocation(const PathDiagnosticLocation &Container,
95314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek                                   const PathDiagnosticLocation &Containee) {
95414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
95514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  if (Container == Containee)
95614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    return true;
9571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
95814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  if (Container.asDecl())
95914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    return true;
9601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
96114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  if (const Stmt *S = Containee.asStmt())
96214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    if (const Stmt *ContainerS = Container.asStmt()) {
96314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek      while (S) {
96414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek        if (S == ContainerS)
96514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek          return true;
96614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek        S = PDB.getParent(S);
96714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek      }
96814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek      return false;
96914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    }
97014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
97114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  // Less accurate: compare using source ranges.
97214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  SourceRange ContainerR = Container.asRange();
97314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  SourceRange ContaineeR = Containee.asRange();
9741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
97514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  SourceManager &SM = PDB.getSourceManager();
97614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  SourceLocation ContainerRBeg = SM.getInstantiationLoc(ContainerR.getBegin());
97714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  SourceLocation ContainerREnd = SM.getInstantiationLoc(ContainerR.getEnd());
97814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  SourceLocation ContaineeRBeg = SM.getInstantiationLoc(ContaineeR.getBegin());
97914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  SourceLocation ContaineeREnd = SM.getInstantiationLoc(ContaineeR.getEnd());
9801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
98114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  unsigned ContainerBegLine = SM.getInstantiationLineNumber(ContainerRBeg);
98214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  unsigned ContainerEndLine = SM.getInstantiationLineNumber(ContainerREnd);
98314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  unsigned ContaineeBegLine = SM.getInstantiationLineNumber(ContaineeRBeg);
98414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  unsigned ContaineeEndLine = SM.getInstantiationLineNumber(ContaineeREnd);
9851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
98614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  assert(ContainerBegLine <= ContainerEndLine);
9871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  assert(ContaineeBegLine <= ContaineeEndLine);
9881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
98914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  return (ContainerBegLine <= ContaineeBegLine &&
99014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek          ContainerEndLine >= ContaineeEndLine &&
99114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek          (ContainerBegLine != ContaineeBegLine ||
9921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump           SM.getInstantiationColumnNumber(ContainerRBeg) <=
99314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek           SM.getInstantiationColumnNumber(ContaineeRBeg)) &&
99414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek          (ContainerEndLine != ContaineeEndLine ||
99514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek           SM.getInstantiationColumnNumber(ContainerREnd) >=
99614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek           SM.getInstantiationColumnNumber(ContainerREnd)));
99714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek}
99814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
99914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekvoid EdgeBuilder::rawAddEdge(PathDiagnosticLocation NewLoc) {
100014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  if (!PrevLoc.isValid()) {
100114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    PrevLoc = NewLoc;
100214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    return;
100314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  }
10041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
10058c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek  const PathDiagnosticLocation &NewLocClean = cleanUpLocation(NewLoc);
10068c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek  const PathDiagnosticLocation &PrevLocClean = cleanUpLocation(PrevLoc);
10071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
10088c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek  if (NewLocClean.asLocation() == PrevLocClean.asLocation())
100914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    return;
10101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
101114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  // FIXME: Ignore intra-macro edges for now.
10128c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek  if (NewLocClean.asLocation().getInstantiationLoc() ==
10138c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek      PrevLocClean.asLocation().getInstantiationLoc())
101414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    return;
101514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
10168c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek  PD.push_front(new PathDiagnosticControlFlowPiece(NewLocClean, PrevLocClean));
10178c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek  PrevLoc = NewLoc;
101814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek}
101914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
102014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekvoid EdgeBuilder::addEdge(PathDiagnosticLocation NewLoc, bool alwaysAdd) {
10211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1022a301a6773db085575ac51e3c966858180390c25bTed Kremenek  if (!alwaysAdd && NewLoc.asLocation().isMacroID())
1023a301a6773db085575ac51e3c966858180390c25bTed Kremenek    return;
10241eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
102514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  const PathDiagnosticLocation &CLoc = getContextLocation(NewLoc);
102614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
102714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  while (!CLocs.empty()) {
10288f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek    ContextLocation &TopContextLoc = CLocs.back();
10291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
103014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    // Is the top location context the same as the one for the new location?
103114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    if (TopContextLoc == CLoc) {
10328f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek      if (alwaysAdd) {
10334c6f8d38e2795c67048e16e737b8225eeb184262Ted Kremenek        if (IsConsumedExpr(TopContextLoc) &&
10344c6f8d38e2795c67048e16e737b8225eeb184262Ted Kremenek            !IsControlFlowExpr(TopContextLoc.asStmt()))
10358f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek            TopContextLoc.markDead();
10368f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek
103714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek        rawAddEdge(NewLoc);
10388f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek      }
103914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
104014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek      return;
104114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    }
104214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
104314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    if (containsLocation(TopContextLoc, CLoc)) {
10448f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek      if (alwaysAdd) {
104514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek        rawAddEdge(NewLoc);
10461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
10474c6f8d38e2795c67048e16e737b8225eeb184262Ted Kremenek        if (IsConsumedExpr(CLoc) && !IsControlFlowExpr(CLoc.asStmt())) {
10488f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek          CLocs.push_back(ContextLocation(CLoc, true));
10498f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek          return;
10508f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek        }
10518f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek      }
10521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
105314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek      CLocs.push_back(CLoc);
10541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump      return;
105514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    }
105614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
105714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    // Context does not contain the location.  Flush it.
105814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    popLocation();
105914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  }
10601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
10615c7168cbe8a0eabd05e0e12e469090d2cabd27c0Ted Kremenek  // If we reach here, there is no enclosing context.  Just add the edge.
10625c7168cbe8a0eabd05e0e12e469090d2cabd27c0Ted Kremenek  rawAddEdge(NewLoc);
106314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek}
106414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
10658f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenekbool EdgeBuilder::IsConsumedExpr(const PathDiagnosticLocation &L) {
10668f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek  if (const Expr *X = dyn_cast_or_null<Expr>(L.asStmt()))
10678f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek    return PDB.getParentMap().isConsumedExpr(X) && !IsControlFlowExpr(X);
10681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
10698f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek  return false;
10708f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek}
10711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1072e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenekvoid EdgeBuilder::addExtendedContext(const Stmt *S) {
1073e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek  if (!S)
1074e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek    return;
10751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
10761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  const Stmt *Parent = PDB.getParent(S);
1077e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek  while (Parent) {
1078e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek    if (isa<CompoundStmt>(Parent))
1079e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek      Parent = PDB.getParent(Parent);
1080e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek    else
1081e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek      break;
1082e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek  }
1083e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek
1084e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek  if (Parent) {
1085e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek    switch (Parent->getStmtClass()) {
1086e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek      case Stmt::DoStmtClass:
1087e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek      case Stmt::ObjCAtSynchronizedStmtClass:
1088e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek        addContext(Parent);
1089e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek      default:
1090e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek        break;
1091e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek    }
1092e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek  }
10931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1094e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek  addContext(S);
1095e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek}
10961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
109714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekvoid EdgeBuilder::addContext(const Stmt *S) {
109814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  if (!S)
109914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    return;
110014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
110114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  PathDiagnosticLocation L(S, PDB.getSourceManager());
11021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
110314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  while (!CLocs.empty()) {
110414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    const PathDiagnosticLocation &TopContextLoc = CLocs.back();
110514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
110614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    // Is the top location context the same as the one for the new location?
110714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    if (TopContextLoc == L)
110814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek      return;
110914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
111014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    if (containsLocation(TopContextLoc, L)) {
111114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek      CLocs.push_back(L);
11121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump      return;
111314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    }
111414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
111514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    // Context does not contain the location.  Flush it.
111614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    popLocation();
111714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  }
111814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
111914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  CLocs.push_back(L);
112014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek}
112114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
112214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekstatic void GenerateExtensivePathDiagnostic(PathDiagnostic& PD,
112314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek                                            PathDiagnosticBuilder &PDB,
1124c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu                                            const ExplodedNode *N) {
112514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  EdgeBuilder EB(PD, PDB);
112614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
112741ca1347c4b5bfea012f08d7eff8636d355762eaZhongxing Xu  const ExplodedNode* NextNode = N->pred_empty() ? NULL : *(N->pred_begin());
112814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  while (NextNode) {
112914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    N = NextNode;
113014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    NextNode = GetPredecessorNode(N);
113114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    ProgramPoint P = N->getLocation();
113214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
1133dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek    do {
1134dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek      // Block edges.
1135dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek      if (const BlockEdge *BE = dyn_cast<BlockEdge>(&P)) {
1136dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek        const CFGBlock &Blk = *BE->getSrc();
1137dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek        const Stmt *Term = Blk.getTerminator();
11381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1139dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek        // Are we jumping to the head of a loop?  Add a special diagnostic.
1140ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek        if (const Stmt *Loop = BE->getDst()->getLoopTarget()) {
1141dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek          PathDiagnosticLocation L(Loop, PDB.getSourceManager());
1142ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek          const CompoundStmt *CS = NULL;
11431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1144ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek          if (!Term) {
1145ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek            if (const ForStmt *FS = dyn_cast<ForStmt>(Loop))
1146ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek              CS = dyn_cast<CompoundStmt>(FS->getBody());
1147ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek            else if (const WhileStmt *WS = dyn_cast<WhileStmt>(Loop))
11481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump              CS = dyn_cast<CompoundStmt>(WS->getBody());
1149ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek          }
11501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1151dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek          PathDiagnosticEventPiece *p =
1152dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek            new PathDiagnosticEventPiece(L,
115307c015cbcee31f72e2d320ba2c713c046bed42faTed Kremenek                                        "Looping back to the head of the loop");
11541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1155dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek          EB.addEdge(p->getLocation(), true);
1156dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek          PD.push_front(p);
11571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1158ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek          if (CS) {
115907c015cbcee31f72e2d320ba2c713c046bed42faTed Kremenek            PathDiagnosticLocation BL(CS->getRBracLoc(),
116007c015cbcee31f72e2d320ba2c713c046bed42faTed Kremenek                                      PDB.getSourceManager());
116107c015cbcee31f72e2d320ba2c713c046bed42faTed Kremenek            BL = PathDiagnosticLocation(BL.asLocation());
116207c015cbcee31f72e2d320ba2c713c046bed42faTed Kremenek            EB.addEdge(BL);
1163dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek          }
11648bd4d037d837e7922c3661d6158229da58a03887Ted Kremenek        }
11651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1166ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek        if (Term)
1167ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek          EB.addContext(Term);
11681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1169dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek        break;
11708bd4d037d837e7922c3661d6158229da58a03887Ted Kremenek      }
117114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
11721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump      if (const BlockEntrance *BE = dyn_cast<BlockEntrance>(&P)) {
1173b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu        if (CFGStmt S = BE->getFirstElement().getAs<CFGStmt>()) {
1174b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu          if (IsControlFlowExpr(S)) {
1175b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu            // Add the proper context for '&&', '||', and '?'.
1176b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu            EB.addContext(S);
1177b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu          }
1178b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu          else
1179b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu            EB.addExtendedContext(PDB.getEnclosingStmtLocation(S).asStmt());
1180dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek        }
1181b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu
1182dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek        break;
1183dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek      }
1184dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek    } while (0);
11851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1186dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek    if (!NextNode)
118714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek      continue;
11881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
11898966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek    for (BugReporterContext::visitor_iterator I = PDB.visitor_begin(),
11908966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek         E = PDB.visitor_end(); I!=E; ++I) {
11918966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek      if (PathDiagnosticPiece* p = (*I)->VisitNode(N, NextNode, PDB)) {
11928966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek        const PathDiagnosticLocation &Loc = p->getLocation();
11938966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek        EB.addEdge(Loc, true);
11948966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek        PD.push_front(p);
11958966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek        if (const Stmt *S = Loc.asStmt())
11961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump          EB.addExtendedContext(PDB.getEnclosingStmtLocation(S).asStmt());
11978966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek      }
11981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    }
119914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  }
120014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek}
120114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
12025fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek//===----------------------------------------------------------------------===//
12033106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// Methods for BugType and subclasses.
12043106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===//
120590b6acf414327f953aa696cd64a449a4bd4fbb0dTed KremenekBugType::~BugType() {
120690b6acf414327f953aa696cd64a449a4bd4fbb0dTed Kremenek  // Free up the equivalence class objects.  Observe that we get a pointer to
120790b6acf414327f953aa696cd64a449a4bd4fbb0dTed Kremenek  // the object first before incrementing the iterator, as destroying the
120890b6acf414327f953aa696cd64a449a4bd4fbb0dTed Kremenek  // node before doing so means we will read from freed memory.
120990b6acf414327f953aa696cd64a449a4bd4fbb0dTed Kremenek  for (iterator I = begin(), E = end(); I !=E; ) {
121090b6acf414327f953aa696cd64a449a4bd4fbb0dTed Kremenek    BugReportEquivClass *EQ = &*I;
121190b6acf414327f953aa696cd64a449a4bd4fbb0dTed Kremenek    ++I;
121290b6acf414327f953aa696cd64a449a4bd4fbb0dTed Kremenek    delete EQ;
121390b6acf414327f953aa696cd64a449a4bd4fbb0dTed Kremenek  }
121490b6acf414327f953aa696cd64a449a4bd4fbb0dTed Kremenek}
12153106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenekvoid BugType::FlushReports(BugReporter &BR) {}
12163106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
12173106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===//
12183106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// Methods for BugReport and subclasses.
12193106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===//
12203106198188ac6eb2753f1764d5c28376b0b76351Ted KremenekBugReport::~BugReport() {}
12213106198188ac6eb2753f1764d5c28376b0b76351Ted KremenekRangedBugReport::~RangedBugReport() {}
12223106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
12231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpconst Stmt* BugReport::getStmt() const {
1224212f6d3b5fb3fa55ba1e40671cfc336430abc8ddTom Care  ProgramPoint ProgP = ErrorNode->getLocation();
12255f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek  const Stmt *S = NULL;
12261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
12273106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  if (BlockEntrance* BE = dyn_cast<BlockEntrance>(&ProgP)) {
1228fafd3834754d2093e0ad7a1c005860fd527ecb7fZhongxing Xu    CFGBlock &Exit = ProgP.getLocationContext()->getCFG()->getExit();
122950d5bc4e3b53eb8bb4ebf198f1213348a3fa0f38Zhongxing Xu    if (BE->getBlock() == &Exit)
1230212f6d3b5fb3fa55ba1e40671cfc336430abc8ddTom Care      S = GetPreviousStmt(ErrorNode);
12313106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  }
12325f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek  if (!S)
12331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    S = GetStmt(ProgP);
12341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
12351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  return S;
12363106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek}
12373106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
12383106198188ac6eb2753f1764d5c28376b0b76351Ted KremenekPathDiagnosticPiece*
12398966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed KremenekBugReport::getEndPath(BugReporterContext& BRC,
1240c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu                      const ExplodedNode* EndPathNode) {
12411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
124250d5bc4e3b53eb8bb4ebf198f1213348a3fa0f38Zhongxing Xu  const Stmt* S = getStmt();
12431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
12443106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  if (!S)
12453106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    return NULL;
12463ef538dd1bb1001fa1a1d50594d13f480a8dfa21Ted Kremenek
1247640ccf071076e684713cc3c3276bb51982bff607Argyrios Kyrtzidis  BugReport::ranges_iterator Beg, End;
1248640ccf071076e684713cc3c3276bb51982bff607Argyrios Kyrtzidis  llvm::tie(Beg, End) = getRanges();
12493ef538dd1bb1001fa1a1d50594d13f480a8dfa21Ted Kremenek  PathDiagnosticLocation L(S, BRC.getSourceManager());
12501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
12513ef538dd1bb1001fa1a1d50594d13f480a8dfa21Ted Kremenek  // Only add the statement itself as a range if we didn't specify any
12523ef538dd1bb1001fa1a1d50594d13f480a8dfa21Ted Kremenek  // special ranges for this report.
12533ef538dd1bb1001fa1a1d50594d13f480a8dfa21Ted Kremenek  PathDiagnosticPiece* P = new PathDiagnosticEventPiece(L, getDescription(),
12543ef538dd1bb1001fa1a1d50594d13f480a8dfa21Ted Kremenek                                                        Beg == End);
12551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
12563106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  for (; Beg != End; ++Beg)
12573106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    P->addRange(*Beg);
12581eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
12593106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  return P;
12603106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek}
12613106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
1262640ccf071076e684713cc3c3276bb51982bff607Argyrios Kyrtzidisstd::pair<BugReport::ranges_iterator, BugReport::ranges_iterator>
1263640ccf071076e684713cc3c3276bb51982bff607Argyrios KyrtzidisBugReport::getRanges() const {
126450d5bc4e3b53eb8bb4ebf198f1213348a3fa0f38Zhongxing Xu  if (const Expr* E = dyn_cast_or_null<Expr>(getStmt())) {
12653106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    R = E->getSourceRange();
12663106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    assert(R.isValid());
1267640ccf071076e684713cc3c3276bb51982bff607Argyrios Kyrtzidis    return std::make_pair(&R, &R+1);
12683106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  }
12693106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  else
1270640ccf071076e684713cc3c3276bb51982bff607Argyrios Kyrtzidis    return std::make_pair(ranges_iterator(), ranges_iterator());
12713106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek}
12723106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
12731eb4433ac451dc16f4133a88af2d002ac26c58efMike StumpSourceLocation BugReport::getLocation() const {
1274212f6d3b5fb3fa55ba1e40671cfc336430abc8ddTom Care  if (ErrorNode)
1275212f6d3b5fb3fa55ba1e40671cfc336430abc8ddTom Care    if (const Stmt* S = GetCurrentOrPreviousStmt(ErrorNode)) {
12763106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      // For member expressions, return the location of the '.' or '->'.
12775b9bd2137ebef350af803c634e3fdf5d74678100Ted Kremenek      if (const MemberExpr *ME = dyn_cast<MemberExpr>(S))
12783106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        return ME->getMemberLoc();
12795b9bd2137ebef350af803c634e3fdf5d74678100Ted Kremenek      // For binary operators, return the location of the operator.
12805b9bd2137ebef350af803c634e3fdf5d74678100Ted Kremenek      if (const BinaryOperator *B = dyn_cast<BinaryOperator>(S))
12815b9bd2137ebef350af803c634e3fdf5d74678100Ted Kremenek        return B->getOperatorLoc();
12823106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
12833106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      return S->getLocStart();
12843106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    }
12853106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
12863106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  return FullSourceLoc();
12873106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek}
12883106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
1289c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing XuPathDiagnosticPiece* BugReport::VisitNode(const ExplodedNode* N,
1290c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu                                          const ExplodedNode* PrevN,
12918966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek                                          BugReporterContext &BRC) {
12923106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  return NULL;
12933106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek}
12943106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
12953106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===//
12963106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// Methods for BugReporter and subclasses.
12973106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===//
12983106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
12993106198188ac6eb2753f1764d5c28376b0b76351Ted KremenekBugReportEquivClass::~BugReportEquivClass() {
13008966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek  for (iterator I=begin(), E=end(); I!=E; ++I) delete *I;
13013106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek}
13023106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
1303a2f4ec0df645fc249d2945beef9653f03b175417Zhongxing XuGRBugReporter::~GRBugReporter() { }
13043106198188ac6eb2753f1764d5c28376b0b76351Ted KremenekBugReporterData::~BugReporterData() {}
13053106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
130638b02b912e1a55c912f603c4369431264d36a381Zhongxing XuExplodedGraph &GRBugReporter::getGraph() { return Eng.getGraph(); }
13073106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
13083106198188ac6eb2753f1764d5c28376b0b76351Ted KremenekGRStateManager&
13093106198188ac6eb2753f1764d5c28376b0b76351Ted KremenekGRBugReporter::getStateManager() { return Eng.getStateManager(); }
13103106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
13113106198188ac6eb2753f1764d5c28376b0b76351Ted KremenekBugReporter::~BugReporter() { FlushReports(); }
13123106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
13133106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenekvoid BugReporter::FlushReports() {
13143106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  if (BugTypes.isEmpty())
13153106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    return;
13163106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
13173106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // First flush the warnings for each BugType.  This may end up creating new
13183106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // warnings and new BugTypes.  Because ImmutableSet is a functional data
13193106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // structure, we do not need to worry about the iterators being invalidated.
13203106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  for (BugTypesTy::iterator I=BugTypes.begin(), E=BugTypes.end(); I!=E; ++I)
13213106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    const_cast<BugType*>(*I)->FlushReports(*this);
13223106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
13233106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // Iterate through BugTypes a second time.  BugTypes may have been updated
13243106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // with new BugType objects and new warnings.
13253106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  for (BugTypesTy::iterator I=BugTypes.begin(), E=BugTypes.end(); I!=E; ++I) {
13263106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    BugType *BT = const_cast<BugType*>(*I);
13273106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
13283106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    typedef llvm::FoldingSet<BugReportEquivClass> SetTy;
13293106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    SetTy& EQClasses = BT->EQClasses;
13303106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
13313106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    for (SetTy::iterator EI=EQClasses.begin(), EE=EQClasses.end(); EI!=EE;++EI){
13323106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      BugReportEquivClass& EQ = *EI;
13333106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      FlushReport(EQ);
13343106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    }
13351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
13361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    // Delete the BugType object.
13373106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    delete BT;
13383106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  }
13393106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
13403106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // Remove all references to the BugType objects.
13413baf672378f105602d2b12f03f00277ae1936fe9Ted Kremenek  BugTypes = F.getEmptySet();
13423106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek}
13433106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
13443106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===//
13453106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// PathDiagnostics generation.
13463106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===//
13473106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
134838b02b912e1a55c912f603c4369431264d36a381Zhongxing Xustatic std::pair<std::pair<ExplodedGraph*, NodeBackMap*>,
1349c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu                 std::pair<ExplodedNode*, unsigned> >
135038b02b912e1a55c912f603c4369431264d36a381Zhongxing XuMakeReportGraph(const ExplodedGraph* G,
135140406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek                llvm::SmallVectorImpl<const ExplodedNode*> &nodes) {
13521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
13533106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // Create the trimmed graph.  It will contain the shortest paths from the
13541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  // error nodes to the root.  In the new graph we should only have one
13553106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // error node unless there are two or more error nodes with the same minimum
13563106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // path length.
135738b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu  ExplodedGraph* GTrim;
1358c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu  InterExplodedGraphMap* NMap;
13593106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
13603106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  llvm::DenseMap<const void*, const void*> InverseMap;
136140406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  llvm::tie(GTrim, NMap) = G->Trim(nodes.data(), nodes.data() + nodes.size(),
136240406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek                                   &InverseMap);
13631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
13643106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // Create owning pointers for GTrim and NMap just to ensure that they are
13653106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // released when this function exists.
136638b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu  llvm::OwningPtr<ExplodedGraph> AutoReleaseGTrim(GTrim);
1367c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu  llvm::OwningPtr<InterExplodedGraphMap> AutoReleaseNMap(NMap);
13681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
13693106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // Find the (first) error node in the trimmed graph.  We just need to consult
13703106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // the node map (NMap) which maps from nodes in the original graph to nodes
13713106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // in the new graph.
1372938332c657390d1e782e0adc03b092993edae962Ted Kremenek
1373c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu  std::queue<const ExplodedNode*> WS;
137438b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu  typedef llvm::DenseMap<const ExplodedNode*, unsigned> IndexMapTy;
1375938332c657390d1e782e0adc03b092993edae962Ted Kremenek  IndexMapTy IndexMap;
13763106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
137740406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  for (unsigned nodeIndex = 0 ; nodeIndex < nodes.size(); ++nodeIndex) {
137840406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek    const ExplodedNode *originalNode = nodes[nodeIndex];
137940406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek    if (const ExplodedNode *N = NMap->getMappedNode(originalNode)) {
1380938332c657390d1e782e0adc03b092993edae962Ted Kremenek      WS.push(N);
138140406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek      IndexMap[originalNode] = nodeIndex;
13823106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    }
138340406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  }
13841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1385938332c657390d1e782e0adc03b092993edae962Ted Kremenek  assert(!WS.empty() && "No error node found in the trimmed graph.");
13863106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
13873106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // Create a new (third!) graph with a single path.  This is the graph
13883106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // that will be returned to the caller.
1389c77a55126fcad66fb086f8e100a494caa2496a2dZhongxing Xu  ExplodedGraph *GNew = new ExplodedGraph();
13901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
13913106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // Sometimes the trimmed graph can contain a cycle.  Perform a reverse BFS
13923106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // to the root node, and then construct a new graph that contains only
13933106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // a single path.
13943106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  llvm::DenseMap<const void*,unsigned> Visited;
13951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
13963106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  unsigned cnt = 0;
1397c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu  const ExplodedNode* Root = 0;
13981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
13993106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  while (!WS.empty()) {
1400c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu    const ExplodedNode* Node = WS.front();
14013106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    WS.pop();
14021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
14033106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    if (Visited.find(Node) != Visited.end())
14043106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      continue;
14051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
14063106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    Visited[Node] = cnt++;
14071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
14083106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    if (Node->pred_empty()) {
14093106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      Root = Node;
14103106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      break;
14113106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    }
14121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1413c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu    for (ExplodedNode::const_pred_iterator I=Node->pred_begin(),
14143106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek         E=Node->pred_end(); I!=E; ++I)
14153106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      WS.push(*I);
14163106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  }
14171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1418938332c657390d1e782e0adc03b092993edae962Ted Kremenek  assert(Root);
14191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
14203106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // Now walk from the root down the BFS path, always taking the successor
14213106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // with the lowest number.
14221eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  ExplodedNode *Last = 0, *First = 0;
14233106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  NodeBackMap *BM = new NodeBackMap();
1424938332c657390d1e782e0adc03b092993edae962Ted Kremenek  unsigned NodeIndex = 0;
14251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1426c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu  for ( const ExplodedNode *N = Root ;;) {
14273106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // Lookup the number associated with the current node.
14283106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    llvm::DenseMap<const void*,unsigned>::iterator I = Visited.find(N);
1429938332c657390d1e782e0adc03b092993edae962Ted Kremenek    assert(I != Visited.end());
14301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
14313106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // Create the equivalent node in the new graph with the same state
14323106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // and location.
143338b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu    ExplodedNode* NewN = GNew->getNode(N->getLocation(), N->getState());
14341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
14353106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // Store the mapping to the original node.
14363106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    llvm::DenseMap<const void*, const void*>::iterator IMitr=InverseMap.find(N);
14373106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    assert(IMitr != InverseMap.end() && "No mapping to original node.");
1438c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu    (*BM)[NewN] = (const ExplodedNode*) IMitr->second;
14391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
14403106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // Link up the new node with the previous node.
14413106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    if (Last)
14425fe4d9deb543a19f557e3d85c5f33867af97cd96Ted Kremenek      NewN->addPredecessor(Last, *GNew);
14431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
14443106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    Last = NewN;
14451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
14463106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // Are we at the final node?
1447938332c657390d1e782e0adc03b092993edae962Ted Kremenek    IndexMapTy::iterator IMI =
1448c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu      IndexMap.find((const ExplodedNode*)(IMitr->second));
1449938332c657390d1e782e0adc03b092993edae962Ted Kremenek    if (IMI != IndexMap.end()) {
14503106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      First = NewN;
1451938332c657390d1e782e0adc03b092993edae962Ted Kremenek      NodeIndex = IMI->second;
14523106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      break;
14533106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    }
14541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
14553106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // Find the next successor node.  We choose the node that is marked
14563106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // with the lowest DFS number.
1457c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu    ExplodedNode::const_succ_iterator SI = N->succ_begin();
1458c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu    ExplodedNode::const_succ_iterator SE = N->succ_end();
14593106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    N = 0;
14601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
14613106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    for (unsigned MinVal = 0; SI != SE; ++SI) {
14621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
14633106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      I = Visited.find(*SI);
14641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
14653106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      if (I == Visited.end())
14663106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        continue;
14671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
14683106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      if (!N || I->second < MinVal) {
14693106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        N = *SI;
14703106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        MinVal = I->second;
14713106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      }
14723106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    }
14731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1474938332c657390d1e782e0adc03b092993edae962Ted Kremenek    assert(N);
14753106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  }
14761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1477938332c657390d1e782e0adc03b092993edae962Ted Kremenek  assert(First);
1478938332c657390d1e782e0adc03b092993edae962Ted Kremenek
14793106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  return std::make_pair(std::make_pair(GNew, BM),
14803106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek                        std::make_pair(First, NodeIndex));
14813106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek}
1482d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek
14833106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek/// CompactPathDiagnostic - This function postprocesses a PathDiagnostic object
14843106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek///  and collapses PathDiagosticPieces that are expanded by macros.
14853106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenekstatic void CompactPathDiagnostic(PathDiagnostic &PD, const SourceManager& SM) {
14863106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  typedef std::vector<std::pair<PathDiagnosticMacroPiece*, SourceLocation> >
14873106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek          MacroStackTy;
14881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
14893106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  typedef std::vector<PathDiagnosticPiece*>
14903106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek          PiecesTy;
14911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
14923106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  MacroStackTy MacroStack;
14933106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  PiecesTy Pieces;
14941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
14953106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  for (PathDiagnostic::iterator I = PD.begin(), E = PD.end(); I!=E; ++I) {
14963106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // Get the location of the PathDiagnosticPiece.
14971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    const FullSourceLoc Loc = I->getLocation().asLocation();
14981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
14993106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // Determine the instantiation location, which is the location we group
15003106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // related PathDiagnosticPieces.
15011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    SourceLocation InstantiationLoc = Loc.isMacroID() ?
15023106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek                                      SM.getInstantiationLoc(Loc) :
15033106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek                                      SourceLocation();
15041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
15053106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    if (Loc.isFileID()) {
15063106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      MacroStack.clear();
15073106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      Pieces.push_back(&*I);
15083106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      continue;
15093106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    }
1510706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek
15113106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    assert(Loc.isMacroID());
15121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
15133106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // Is the PathDiagnosticPiece within the same macro group?
15143106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    if (!MacroStack.empty() && InstantiationLoc == MacroStack.back().second) {
15153106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      MacroStack.back().first->push_back(&*I);
15163106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      continue;
15173106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    }
1518d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek
15193106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // We aren't in the same group.  Are we descending into a new macro
15203106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // or are part of an old one?
15213106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    PathDiagnosticMacroPiece *MacroGroup = 0;
1522d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek
15233106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    SourceLocation ParentInstantiationLoc = InstantiationLoc.isMacroID() ?
15243106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek                                          SM.getInstantiationLoc(Loc) :
15253106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek                                          SourceLocation();
15261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
15273106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // Walk the entire macro stack.
15283106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    while (!MacroStack.empty()) {
15293106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      if (InstantiationLoc == MacroStack.back().second) {
15303106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        MacroGroup = MacroStack.back().first;
15313106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        break;
15323106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      }
15331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
15343106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      if (ParentInstantiationLoc == MacroStack.back().second) {
15353106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        MacroGroup = MacroStack.back().first;
15363106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        break;
153761f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek      }
15381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
15393106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      MacroStack.pop_back();
15406837faa083bebad39aa342f84c2b450fb6410eafTed Kremenek    }
15411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
15423106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    if (!MacroGroup || ParentInstantiationLoc == MacroStack.back().second) {
15433106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      // Create a new macro group and add it to the stack.
15443106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      PathDiagnosticMacroPiece *NewGroup = new PathDiagnosticMacroPiece(Loc);
15455a429954aedd8a830a70fcea2cb51561673e4fc3Ted Kremenek
15463106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      if (MacroGroup)
15473106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        MacroGroup->push_back(NewGroup);
15483106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      else {
15493106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        assert(InstantiationLoc.isFileID());
15503106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        Pieces.push_back(NewGroup);
15513106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      }
15521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
15533106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      MacroGroup = NewGroup;
15543106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      MacroStack.push_back(std::make_pair(MacroGroup, InstantiationLoc));
15557dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek    }
15563106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
15573106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // Finally, add the PathDiagnosticPiece to the group.
15583106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    MacroGroup->push_back(&*I);
15593106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  }
15601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
15613106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // Now take the pieces and construct a new PathDiagnostic.
15623106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  PD.resetPath(false);
15631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
15643106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  for (PiecesTy::iterator I=Pieces.begin(), E=Pieces.end(); I!=E; ++I) {
15653106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    if (PathDiagnosticMacroPiece *MP=dyn_cast<PathDiagnosticMacroPiece>(*I))
15663106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      if (!MP->containsEvent()) {
15673106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        delete MP;
15683106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        continue;
15693106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      }
15701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
15713106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    PD.push_back(*I);
157261f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek  }
157361f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek}
157461f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek
15753106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenekvoid GRBugReporter::GeneratePathDiagnostic(PathDiagnostic& PD,
157640406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek                        llvm::SmallVectorImpl<BugReport *> &bugReports) {
15771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
157840406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  assert(!bugReports.empty());
157940406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  llvm::SmallVector<const ExplodedNode *, 10> errorNodes;
158040406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  for (llvm::SmallVectorImpl<BugReport*>::iterator I = bugReports.begin(),
158140406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek    E = bugReports.end(); I != E; ++I) {
158240406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek      errorNodes.push_back((*I)->getErrorNode());
158340406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  }
15841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
15853106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // Construct a new graph that contains only a single path from the error
15861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  // node to a root.
158738b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu  const std::pair<std::pair<ExplodedGraph*, NodeBackMap*>,
1588c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu  std::pair<ExplodedNode*, unsigned> >&
158940406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek    GPair = MakeReportGraph(&getGraph(), errorNodes);
15901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
15913106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // Find the BugReport with the original location.
159240406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  assert(GPair.second.second < bugReports.size());
159340406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  BugReport *R = bugReports[GPair.second.second];
15943106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  assert(R && "No original report found for sliced graph.");
15951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
159638b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu  llvm::OwningPtr<ExplodedGraph> ReportGraph(GPair.first.first);
15973106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  llvm::OwningPtr<NodeBackMap> BackMap(GPair.first.second);
1598c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu  const ExplodedNode *N = GPair.second.first;
15991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
16001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  // Start building the path diagnostic...
16018966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek  PathDiagnosticBuilder PDB(*this, R, BackMap.get(), getPathDiagnosticClient());
16021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
16038966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek  if (PathDiagnosticPiece* Piece = R->getEndPath(PDB, N))
16043106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    PD.push_back(Piece);
16053106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  else
16063106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    return;
16071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1608ff7f736211070be873df0a345295fd1453ee7c50Ted Kremenek  // Register node visitors.
1609dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek  R->registerInitialVisitors(PDB, N);
1610ff7f736211070be873df0a345295fd1453ee7c50Ted Kremenek  bugreporter::registerNilReceiverVisitor(PDB);
16111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
16123106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  switch (PDB.getGenerationScheme()) {
16133106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    case PathDiagnosticClient::Extensive:
16148966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek      GenerateExtensivePathDiagnostic(PD, PDB, N);
16155fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek      break;
16163106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    case PathDiagnosticClient::Minimal:
16173106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      GenerateMinimalPathDiagnostic(PD, PDB, N);
16183106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      break;
16193106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  }
16203106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek}
16211aa44c7c9198796085b77c6bdd7c90030845a688Ted Kremenek
1622cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenekvoid BugReporter::Register(BugType *BT) {
16233baf672378f105602d2b12f03f00277ae1936fe9Ted Kremenek  BugTypes = F.add(BugTypes, BT);
162476d90c8bf83d071fd1bdbffa6d9f2af87c6bb7b5Ted Kremenek}
162576d90c8bf83d071fd1bdbffa6d9f2af87c6bb7b5Ted Kremenek
16261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpvoid BugReporter::EmitReport(BugReport* R) {
1627cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  // Compute the bug report's hash to determine its equivalence class.
1628cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  llvm::FoldingSetNodeID ID;
1629cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  R->Profile(ID);
16301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
16311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  // Lookup the equivance class.  If there isn't one, create it.
1632cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  BugType& BT = R->getBugType();
1633cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  Register(&BT);
1634cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  void *InsertPos;
16351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  BugReportEquivClass* EQ = BT.EQClasses.FindNodeOrInsertPos(ID, InsertPos);
16361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1637cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  if (!EQ) {
1638cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek    EQ = new BugReportEquivClass(R);
1639cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek    BT.EQClasses.InsertNode(EQ, InsertPos);
1640cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  }
1641cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  else
1642cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek    EQ->AddReport(R);
164361f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek}
164461f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek
164506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek
164606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek//===----------------------------------------------------------------------===//
164706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek// Emitting reports in equivalence classes.
164806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek//===----------------------------------------------------------------------===//
164906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek
165006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremeneknamespace {
1651ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamstruct FRIEC_WLItem {
165206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek  const ExplodedNode *N;
165306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek  ExplodedNode::const_succ_iterator I, E;
165406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek
165506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek  FRIEC_WLItem(const ExplodedNode *n)
165606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek  : N(n), I(N->succ_begin()), E(N->succ_end()) {}
165706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek};
165806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek}
165906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek
166061f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenekstatic BugReport *
166161f52bd3c524268e25b48a1ed3730aedd6cc8374Ted KremenekFindReportInEquivalenceClass(BugReportEquivClass& EQ,
166240406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek                             llvm::SmallVectorImpl<BugReport*> &bugReports) {
166361f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek
166406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek  BugReportEquivClass::iterator I = EQ.begin(), E = EQ.end();
166506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek  assert(I != E);
166606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek  BugReport *R = *I;
166706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek  BugType& BT = R->getBugType();
166861f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek
166940406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  // If we don't need to suppress any of the nodes because they are
167040406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  // post-dominated by a sink, simply add all the nodes in the equivalence class
167140406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  // to 'Nodes'.  Any of the reports will serve as a "representative" report.
167261f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek  if (!BT.isSuppressOnSink()) {
167361f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek    for (BugReportEquivClass::iterator I=EQ.begin(), E=EQ.end(); I!=E; ++I) {
1674212f6d3b5fb3fa55ba1e40671cfc336430abc8ddTom Care      const ExplodedNode* N = I->getErrorNode();
167561f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek      if (N) {
167661f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek        R = *I;
167740406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek        bugReports.push_back(R);
167861f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek      }
167961f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek    }
168006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek    return R;
168161f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek  }
168261f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek
168306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek  // For bug reports that should be suppressed when all paths are post-dominated
168406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek  // by a sink node, iterate through the reports in the equivalence class
168506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek  // until we find one that isn't post-dominated (if one exists).  We use a
168606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek  // DFS traversal of the ExplodedGraph to find a non-sink node.  We could write
168706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek  // this as a recursive function, but we don't want to risk blowing out the
168806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek  // stack for very long paths.
168940406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  BugReport *exampleReport = 0;
169061f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek
169106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek  for (; I != E; ++I) {
169206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek    R = *I;
169340406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek    const ExplodedNode *errorNode = R->getErrorNode();
169406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek
169540406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek    if (!errorNode)
169606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek      continue;
169740406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek    if (errorNode->isSink()) {
169806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek      assert(false &&
169906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek           "BugType::isSuppressSink() should not be 'true' for sink end nodes");
170061f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek      return 0;
170106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek    }
170261f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek    // No successors?  By definition this nodes isn't post-dominated by a sink.
170340406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek    if (errorNode->succ_empty()) {
170440406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek      bugReports.push_back(R);
170540406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek      if (!exampleReport)
170640406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek        exampleReport = R;
170761f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek      continue;
170861f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek    }
170961f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek
171006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek    // At this point we know that 'N' is not a sink and it has at least one
171106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek    // successor.  Use a DFS worklist to find a non-sink end-of-path node.
171206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek    typedef FRIEC_WLItem WLItem;
171306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek    typedef llvm::SmallVector<WLItem, 10> DFSWorkList;
171406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek    llvm::DenseMap<const ExplodedNode *, unsigned> Visited;
171506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek
171606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek    DFSWorkList WL;
171740406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek    WL.push_back(errorNode);
171840406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek    Visited[errorNode] = 1;
171906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek
172006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek    while (!WL.empty()) {
172106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek      WLItem &WI = WL.back();
172206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek      assert(!WI.N->succ_empty());
172306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek
172406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek      for (; WI.I != WI.E; ++WI.I) {
172506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek        const ExplodedNode *Succ = *WI.I;
172606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek        // End-of-path node?
172706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek        if (Succ->succ_empty()) {
172861f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek          // If we found an end-of-path node that is not a sink.
172961f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek          if (!Succ->isSink()) {
173040406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek            bugReports.push_back(R);
173140406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek            if (!exampleReport)
173240406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek              exampleReport = R;
173361f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek            WL.clear();
173461f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek            break;
173561f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek          }
173606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek          // Found a sink?  Continue on to the next successor.
173706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek          continue;
173806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek        }
173906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek        // Mark the successor as visited.  If it hasn't been explored,
174006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek        // enqueue it to the DFS worklist.
174106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek        unsigned &mark = Visited[Succ];
174206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek        if (!mark) {
174306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek          mark = 1;
174406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek          WL.push_back(Succ);
174506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek          break;
174606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek        }
174706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek      }
174861f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek
174961f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek      // The worklist may have been cleared at this point.  First
175061f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek      // check if it is empty before checking the last item.
175161f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek      if (!WL.empty() && &WL.back() == &WI)
175206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek        WL.pop_back();
175306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek    }
175406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek  }
175506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek
175661f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek  // ExampleReport will be NULL if all the nodes in the equivalence class
175761f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek  // were post-dominated by sinks.
175840406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  return exampleReport;
175961f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek}
1760e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek
1761e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek//===----------------------------------------------------------------------===//
1762e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek// DiagnosticCache.  This is a hack to cache analyzer diagnostics.  It
1763e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek// uses global state, which eventually should go elsewhere.
1764e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek//===----------------------------------------------------------------------===//
1765e0a58073b76fc016325a35152533b8468df2bf4aTed Kremeneknamespace {
1766ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass DiagCacheItem : public llvm::FoldingSetNode {
1767e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek  llvm::FoldingSetNodeID ID;
1768e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenekpublic:
1769e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek  DiagCacheItem(BugReport *R, PathDiagnostic *PD) {
1770e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek    ID.AddString(R->getBugType().getName());
1771e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek    ID.AddString(R->getBugType().getCategory());
1772e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek    ID.AddString(R->getDescription());
1773e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek    ID.AddInteger(R->getLocation().getRawEncoding());
1774e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek    PD->Profile(ID);
1775e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek  }
1776e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek
1777e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek  void Profile(llvm::FoldingSetNodeID &id) {
1778e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek    id = ID;
1779e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek  }
1780e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek
1781e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek  llvm::FoldingSetNodeID &getID() { return ID; }
1782e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek};
1783e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek}
1784e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek
1785e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenekstatic bool IsCachedDiagnostic(BugReport *R, PathDiagnostic *PD) {
1786e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek  // FIXME: Eventually this diagnostic cache should reside in something
1787e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek  // like AnalysisManager instead of being a static variable.  This is
1788e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek  // really unsafe in the long term.
1789e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek  typedef llvm::FoldingSet<DiagCacheItem> DiagnosticCache;
1790e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek  static DiagnosticCache DC;
1791e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek
1792e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek  void *InsertPos;
1793e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek  DiagCacheItem *Item = new DiagCacheItem(R, PD);
1794e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek
1795e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek  if (DC.FindNodeOrInsertPos(Item->getID(), InsertPos)) {
1796e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek    delete Item;
1797e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek    return true;
1798e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek  }
1799e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek
1800e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek  DC.InsertNode(Item, InsertPos);
1801e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek  return false;
1802e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek}
1803e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek
1804cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenekvoid BugReporter::FlushReport(BugReportEquivClass& EQ) {
180540406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  llvm::SmallVector<BugReport*, 10> bugReports;
180640406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  BugReport *exampleReport = FindReportInEquivalenceClass(EQ, bugReports);
180740406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  if (!exampleReport)
180806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek    return;
180906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek
1810d49967f8764135ae65658e354b6d38e3637c9de3Ted Kremenek  PathDiagnosticClient* PD = getPathDiagnosticClient();
18111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1812cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  // FIXME: Make sure we use the 'R' for the path that was actually used.
18131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  // Probably doesn't make a difference in practice.
181440406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  BugType& BT = exampleReport->getBugType();
18151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1816d49967f8764135ae65658e354b6d38e3637c9de3Ted Kremenek  llvm::OwningPtr<PathDiagnostic>
181740406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek    D(new PathDiagnostic(exampleReport->getBugType().getName(),
1818da0e8429a3598acfdd0ecf15135d432e4dd3517cTed Kremenek                         !PD || PD->useVerboseDescription()
181940406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek                         ? exampleReport->getDescription()
182040406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek                         : exampleReport->getShortDescription(),
1821d49967f8764135ae65658e354b6d38e3637c9de3Ted Kremenek                         BT.getCategory()));
1822d49967f8764135ae65658e354b6d38e3637c9de3Ted Kremenek
182340406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  if (!bugReports.empty())
182440406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek    GeneratePathDiagnostic(*D.get(), bugReports);
18251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
182640406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  if (IsCachedDiagnostic(exampleReport, D.get()))
1827e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek    return;
1828e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek
1829072192bcbb05a0fee7ec3061750b27e8d2004952Ted Kremenek  // Get the meta data.
183040406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  std::pair<const char**, const char**> Meta =
183140406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek    exampleReport->getExtraDescriptiveText();
183206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek  for (const char** s = Meta.first; s != Meta.second; ++s)
183306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek    D->addMeta(*s);
183475840e1501563fe7c3dcb5600b75965ba1fe1bc4Ted Kremenek
18353148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek  // Emit a summary diagnostic to the regular Diagnostics engine.
1836640ccf071076e684713cc3c3276bb51982bff607Argyrios Kyrtzidis  BugReport::ranges_iterator Beg, End;
1837640ccf071076e684713cc3c3276bb51982bff607Argyrios Kyrtzidis  llvm::tie(Beg, End) = exampleReport->getRanges();
183840406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  Diagnostic &Diag = getDiagnostic();
183940406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  FullSourceLoc L(exampleReport->getLocation(), getSourceManager());
1840c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek
1841c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek  // Search the description for '%', as that will be interpretted as a
1842c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek  // format character by FormatDiagnostics.
184340406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  llvm::StringRef desc = exampleReport->getShortDescription();
1844c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek  unsigned ErrorDiag;
1845c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek  {
1846c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek    llvm::SmallString<512> TmpStr;
1847c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek    llvm::raw_svector_ostream Out(TmpStr);
1848c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek    for (llvm::StringRef::iterator I=desc.begin(), E=desc.end(); I!=E; ++I)
1849c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek      if (*I == '%')
1850c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek        Out << "%%";
1851c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek      else
1852c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek        Out << *I;
1853c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek
1854c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek    Out.flush();
1855c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek    ErrorDiag = Diag.getCustomDiagID(Diagnostic::Warning, TmpStr);
1856c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek  }
18570a14eee528a901c16f0e288fbc10a3abc1660d87Chris Lattner
1858b6b7e7bff3101062521de6e79533a3c25e2195d9Argyrios Kyrtzidis  {
1859b6b7e7bff3101062521de6e79533a3c25e2195d9Argyrios Kyrtzidis    DiagnosticBuilder diagBuilder = Diag.Report(L, ErrorDiag);
1860640ccf071076e684713cc3c3276bb51982bff607Argyrios Kyrtzidis    for (BugReport::ranges_iterator I = Beg; I != End; ++I)
1861b6b7e7bff3101062521de6e79533a3c25e2195d9Argyrios Kyrtzidis      diagBuilder << *I;
18622f0e89ea96292d2974eb1a7dddc0e9870aa86bb7Ted Kremenek  }
18633148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek
18643148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek  // Emit a full diagnostic for the path if we have a PathDiagnosticClient.
18653148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek  if (!PD)
18663148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek    return;
18671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
18681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  if (D->empty()) {
18691fbfd5b9b8b82aea084773b76dd1ec6796a7000cTed Kremenek    PathDiagnosticPiece* piece =
187040406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek      new PathDiagnosticEventPiece(L, exampleReport->getDescription());
18711fbfd5b9b8b82aea084773b76dd1ec6796a7000cTed Kremenek
18723148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek    for ( ; Beg != End; ++Beg) piece->addRange(*Beg);
18733148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek    D->push_back(piece);
18743148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek  }
18751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
18763148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek  PD->HandlePathDiagnostic(D.take());
187761f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek}
187857202071e477530e9348bc76671ee369b2399b92Ted Kremenek
1879f0171732efb4647772ad2a45c0f31978b0e34f71Benjamin Kramervoid BugReporter::EmitBasicReport(llvm::StringRef name, llvm::StringRef str,
18808c036c7f77d69f96df49219ed0bdbade200d52ebTed Kremenek                                  SourceLocation Loc,
18818c036c7f77d69f96df49219ed0bdbade200d52ebTed Kremenek                                  SourceRange* RBeg, unsigned NumRanges) {
18828c036c7f77d69f96df49219ed0bdbade200d52ebTed Kremenek  EmitBasicReport(name, "", str, Loc, RBeg, NumRanges);
18838c036c7f77d69f96df49219ed0bdbade200d52ebTed Kremenek}
1884cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek
1885f0171732efb4647772ad2a45c0f31978b0e34f71Benjamin Kramervoid BugReporter::EmitBasicReport(llvm::StringRef name,
1886f0171732efb4647772ad2a45c0f31978b0e34f71Benjamin Kramer                                  llvm::StringRef category,
1887f0171732efb4647772ad2a45c0f31978b0e34f71Benjamin Kramer                                  llvm::StringRef str, SourceLocation Loc,
18888c036c7f77d69f96df49219ed0bdbade200d52ebTed Kremenek                                  SourceRange* RBeg, unsigned NumRanges) {
18891eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1890cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  // 'BT' will be owned by BugReporter as soon as we call 'EmitReport'.
1891cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  BugType *BT = new BugType(name, category);
18920a14eee528a901c16f0e288fbc10a3abc1660d87Chris Lattner  FullSourceLoc L = getContext().getFullLoc(Loc);
1893cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  RangedBugReport *R = new DiagBugReport(*BT, str, L);
1894cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  for ( ; NumRanges > 0 ; --NumRanges, ++RBeg) R->addRange(*RBeg);
1895cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  EmitReport(R);
1896cabe66811fe43835b8c5a0854552768fc53261e3Ted Kremenek}
1897