BugReporter.cpp revision 7df1234c2e62b2a23dc4417e527f941c20ebe858
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() {}
361b431023814196f87515a540ebcb9e9f1a9176a1Ted Kremenek
37cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek//===----------------------------------------------------------------------===//
383106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// Helper routines for walking the ExplodedGraph and fetching statements.
39cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek//===----------------------------------------------------------------------===//
4061f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek
419c378f705405d37f49795d5e915989de774fe11fTed Kremenekstatic inline const Stmt *GetStmt(const ProgramPoint &P) {
42592362b46ad69db0db0988e7f9d8cbe647510bddTed Kremenek  if (const StmtPoint* SP = dyn_cast<StmtPoint>(&P))
43592362b46ad69db0db0988e7f9d8cbe647510bddTed Kremenek    return SP->getStmt();
449c378f705405d37f49795d5e915989de774fe11fTed Kremenek  else if (const BlockEdge *BE = dyn_cast<BlockEdge>(&P))
4561f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek    return BE->getSrc()->getTerminator();
461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
47b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek  return 0;
4861f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek}
4961f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek
50c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xustatic inline const ExplodedNode*
519c378f705405d37f49795d5e915989de774fe11fTed KremenekGetPredecessorNode(const ExplodedNode *N) {
52b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek  return N->pred_empty() ? NULL : *(N->pred_begin());
53706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek}
54706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek
55c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xustatic inline const ExplodedNode*
569c378f705405d37f49795d5e915989de774fe11fTed KremenekGetSuccessorNode(const ExplodedNode *N) {
57b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek  return N->succ_empty() ? NULL : *(N->succ_begin());
58bd7efa8ca27ed9676acf00abf31d5e1cd54651ccTed Kremenek}
592673c9ff76ebdb72b7f846e2ff1e0f4256372e19Ted Kremenek
609c378f705405d37f49795d5e915989de774fe11fTed Kremenekstatic const Stmt *GetPreviousStmt(const ExplodedNode *N) {
61b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek  for (N = GetPredecessorNode(N); N; N = GetPredecessorNode(N))
625f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek    if (const Stmt *S = GetStmt(N->getLocation()))
63b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek      return S;
641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
65b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek  return 0;
66b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek}
67b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek
689c378f705405d37f49795d5e915989de774fe11fTed Kremenekstatic const Stmt *GetNextStmt(const ExplodedNode *N) {
69b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek  for (N = GetSuccessorNode(N); N; N = GetSuccessorNode(N))
705f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek    if (const Stmt *S = GetStmt(N->getLocation())) {
71f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek      // Check if the statement is '?' or '&&'/'||'.  These are "merges",
72f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek      // not actual statement points.
73f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek      switch (S->getStmtClass()) {
74f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek        case Stmt::ChooseExprClass:
7556ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall        case Stmt::BinaryConditionalOperatorClass: continue;
76f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek        case Stmt::ConditionalOperatorClass: continue;
77f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek        case Stmt::BinaryOperatorClass: {
782de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall          BinaryOperatorKind Op = cast<BinaryOperator>(S)->getOpcode();
792de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall          if (Op == BO_LAnd || Op == BO_LOr)
80f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek            continue;
81f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek          break;
82f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek        }
83f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek        default:
84f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek          break;
85f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek      }
861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
87b7c515226e91848c7197fd0b9e198fce70ba5893Ted Kremenek      // Some expressions don't have locations.
88b7c515226e91848c7197fd0b9e198fce70ba5893Ted Kremenek      if (S->getLocStart().isInvalid())
89b7c515226e91848c7197fd0b9e198fce70ba5893Ted Kremenek        continue;
901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
91b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek      return S;
92f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek    }
931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
94b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek  return 0;
95bd7efa8ca27ed9676acf00abf31d5e1cd54651ccTed Kremenek}
96bd7efa8ca27ed9676acf00abf31d5e1cd54651ccTed Kremenek
975f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenekstatic inline const Stmt*
989c378f705405d37f49795d5e915989de774fe11fTed KremenekGetCurrentOrPreviousStmt(const ExplodedNode *N) {
995f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek  if (const Stmt *S = GetStmt(N->getLocation()))
100b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek    return S;
1011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
102b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek  return GetPreviousStmt(N);
103b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek}
1041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1055f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenekstatic inline const Stmt*
1069c378f705405d37f49795d5e915989de774fe11fTed KremenekGetCurrentOrNextStmt(const ExplodedNode *N) {
1075f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek  if (const Stmt *S = GetStmt(N->getLocation()))
108b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek    return S;
1091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
110b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek  return GetNextStmt(N);
1113148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek}
1123148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek
113b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek//===----------------------------------------------------------------------===//
1143106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// PathDiagnosticBuilder and its associated routines and helper objects.
115b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek//===----------------------------------------------------------------------===//
116b479dadea93b93d3f0a335c3518b703f140b3f50Ted Kremenek
117c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xutypedef llvm::DenseMap<const ExplodedNode*,
118c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xuconst ExplodedNode*> NodeBackMap;
1197dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek
120babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremeneknamespace {
121ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass NodeMapClosure : public BugReport::NodeResolver {
1227dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek  NodeBackMap& M;
1237dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenekpublic:
1247dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek  NodeMapClosure(NodeBackMap *m) : M(*m) {}
1257dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek  ~NodeMapClosure() {}
1261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1279c378f705405d37f49795d5e915989de774fe11fTed Kremenek  const ExplodedNode *getOriginalNode(const ExplodedNode *N) {
1287dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek    NodeBackMap::iterator I = M.find(N);
1297dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek    return I == M.end() ? 0 : I->second;
1307dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek  }
1317dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek};
1321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
133ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass PathDiagnosticBuilder : public BugReporterContext {
1347dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek  BugReport *R;
135babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek  PathDiagnosticClient *PDC;
13600605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek  llvm::OwningPtr<ParentMap> PM;
1377dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek  NodeMapClosure NMC;
1381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumppublic:
1398966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek  PathDiagnosticBuilder(GRBugReporter &br,
1401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump                        BugReport *r, NodeBackMap *Backmap,
1418966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek                        PathDiagnosticClient *pdc)
1428966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek    : BugReporterContext(br),
1438e6431adab313e283a992698f6fc7afe62420999Anna Zaks      R(r), PDC(pdc), NMC(Backmap) {}
1441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1459c378f705405d37f49795d5e915989de774fe11fTed Kremenek  PathDiagnosticLocation ExecutionContinues(const ExplodedNode *N);
1461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1479c378f705405d37f49795d5e915989de774fe11fTed Kremenek  PathDiagnosticLocation ExecutionContinues(llvm::raw_string_ostream &os,
1489c378f705405d37f49795d5e915989de774fe11fTed Kremenek                                            const ExplodedNode *N);
1491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1508e6431adab313e283a992698f6fc7afe62420999Anna Zaks  BugReport *getBugReport() { return R; }
1518e6431adab313e283a992698f6fc7afe62420999Anna Zaks
152212f6d3b5fb3fa55ba1e40671cfc336430abc8ddTom Care  Decl const &getCodeDecl() { return R->getErrorNode()->getCodeDecl(); }
153b317f8f5ca8737a5bbad97a3f7566a2dbd2ed61bZhongxing Xu
154212f6d3b5fb3fa55ba1e40671cfc336430abc8ddTom Care  ParentMap& getParentMap() { return R->getErrorNode()->getParentMap(); }
1551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
156c3f83ad7adaff2623986aa1c3e57833babd03d50Ted Kremenek  const Stmt *getParent(const Stmt *S) {
157c3f83ad7adaff2623986aa1c3e57833babd03d50Ted Kremenek    return getParentMap().getParent(S);
158c3f83ad7adaff2623986aa1c3e57833babd03d50Ted Kremenek  }
1591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1608966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek  virtual NodeMapClosure& getNodeResolver() { return NMC; }
1617297134f128423fce2e88f92421ed135bded7d4eDouglas Gregor
162d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek  PathDiagnosticLocation getEnclosingStmtLocation(const Stmt *S);
1631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1647dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek  PathDiagnosticClient::PathGenerationScheme getGenerationScheme() const {
1657dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek    return PDC ? PDC->getGenerationScheme() : PathDiagnosticClient::Extensive;
1667dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek  }
1677dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek
168babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek  bool supportsLogicalOpControlFlow() const {
169babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek    return PDC ? PDC->supportsLogicalOpControlFlow() : true;
1701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  }
171babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek};
172babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek} // end anonymous namespace
173babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek
17400605e0f011ed99225a22026344c5fc1b3212cd7Ted KremenekPathDiagnosticLocation
1759c378f705405d37f49795d5e915989de774fe11fTed KremenekPathDiagnosticBuilder::ExecutionContinues(const ExplodedNode *N) {
1765f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek  if (const Stmt *S = GetNextStmt(N))
1778966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek    return PathDiagnosticLocation(S, getSourceManager());
17800605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek
1791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  return FullSourceLoc(N->getLocationContext()->getDecl()->getBodyRBrace(),
180f7a50a4ee255b3a624ae64125537a7bdbd1da0efZhongxing Xu                       getSourceManager());
181082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek}
1821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
18300605e0f011ed99225a22026344c5fc1b3212cd7Ted KremenekPathDiagnosticLocation
1849c378f705405d37f49795d5e915989de774fe11fTed KremenekPathDiagnosticBuilder::ExecutionContinues(llvm::raw_string_ostream &os,
1859c378f705405d37f49795d5e915989de774fe11fTed Kremenek                                          const ExplodedNode *N) {
186babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek
187143ca222583a4a355fdc89af852deef287499300Ted Kremenek  // Slow, but probably doesn't matter.
188b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek  if (os.str().empty())
189b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek    os << ' ';
1901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
19100605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek  const PathDiagnosticLocation &Loc = ExecutionContinues(N);
1921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
19300605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek  if (Loc.asStmt())
194b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek    os << "Execution continues on line "
195642116259e8df6286063a17361c20e95b5017a0aChandler Carruth       << getSourceManager().getExpansionLineNumber(Loc.asLocation())
1968966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek       << '.';
1974f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek  else {
1984f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek    os << "Execution jumps to the end of the ";
1994f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek    const Decl *D = N->getLocationContext()->getDecl();
2004f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek    if (isa<ObjCMethodDecl>(D))
2014f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek      os << "method";
2024f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek    else if (isa<FunctionDecl>(D))
2034f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek      os << "function";
2044f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek    else {
2054f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek      assert(isa<BlockDecl>(D));
2064f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek      os << "anonymous block";
2074f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek    }
2084f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek    os << '.';
2094f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek  }
2101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
211082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek  return Loc;
212143ca222583a4a355fdc89af852deef287499300Ted Kremenek}
213143ca222583a4a355fdc89af852deef287499300Ted Kremenek
214ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenekstatic bool IsNested(const Stmt *S, ParentMap &PM) {
215ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek  if (isa<Expr>(S) && PM.isConsumedExpr(cast<Expr>(S)))
216ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek    return true;
2171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
218ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek  const Stmt *Parent = PM.getParentIgnoreParens(S);
2191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
220ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek  if (Parent)
221ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek    switch (Parent->getStmtClass()) {
222ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek      case Stmt::ForStmtClass:
223ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek      case Stmt::DoStmtClass:
224ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek      case Stmt::WhileStmtClass:
225ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek        return true;
226ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek      default:
227ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek        break;
228ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek    }
2291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  return false;
231ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek}
232ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek
233d8c938b0f6b7a7156181be575239e4c6e15a2adbTed KremenekPathDiagnosticLocation
234d8c938b0f6b7a7156181be575239e4c6e15a2adbTed KremenekPathDiagnosticBuilder::getEnclosingStmtLocation(const Stmt *S) {
2359c378f705405d37f49795d5e915989de774fe11fTed Kremenek  assert(S && "Null Stmt *passed to getEnclosingStmtLocation");
2361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  ParentMap &P = getParentMap();
2378966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek  SourceManager &SMgr = getSourceManager();
238e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek
239ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek  while (IsNested(S, P)) {
2408c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek    const Stmt *Parent = P.getParentIgnoreParens(S);
2411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
242af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek    if (!Parent)
243af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek      break;
2441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
245af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek    switch (Parent->getStmtClass()) {
2465fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek      case Stmt::BinaryOperatorClass: {
2475fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek        const BinaryOperator *B = cast<BinaryOperator>(Parent);
2485fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek        if (B->isLogicalOp())
2495fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek          return PathDiagnosticLocation(S, SMgr);
2505fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek        break;
2511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump      }
252af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek      case Stmt::CompoundStmtClass:
253af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek      case Stmt::StmtExprClass:
2541d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek        return PathDiagnosticLocation(S, SMgr);
2551d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek      case Stmt::ChooseExprClass:
2561d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek        // Similar to '?' if we are referring to condition, just have the edge
2571d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek        // point to the entire choose expression.
2581d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek        if (cast<ChooseExpr>(Parent)->getCond() == S)
2591d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek          return PathDiagnosticLocation(Parent, SMgr);
2601d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek        else
2611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump          return PathDiagnosticLocation(S, SMgr);
26256ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall      case Stmt::BinaryConditionalOperatorClass:
2631d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek      case Stmt::ConditionalOperatorClass:
2641d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek        // For '?', if we are referring to condition, just have the edge point
2651d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek        // to the entire '?' expression.
26656ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall        if (cast<AbstractConditionalOperator>(Parent)->getCond() == S)
2671d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek          return PathDiagnosticLocation(Parent, SMgr);
2681d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek        else
2691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump          return PathDiagnosticLocation(S, SMgr);
270af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek      case Stmt::DoStmtClass:
2711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump          return PathDiagnosticLocation(S, SMgr);
272af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek      case Stmt::ForStmtClass:
273af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek        if (cast<ForStmt>(Parent)->getBody() == S)
2741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump          return PathDiagnosticLocation(S, SMgr);
2751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump        break;
276af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek      case Stmt::IfStmtClass:
277af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek        if (cast<IfStmt>(Parent)->getCond() != S)
278af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek          return PathDiagnosticLocation(S, SMgr);
2798bd4d037d837e7922c3661d6158229da58a03887Ted Kremenek        break;
280af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek      case Stmt::ObjCForCollectionStmtClass:
281af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek        if (cast<ObjCForCollectionStmt>(Parent)->getBody() == S)
282af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek          return PathDiagnosticLocation(S, SMgr);
283af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek        break;
284af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek      case Stmt::WhileStmtClass:
285af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek        if (cast<WhileStmt>(Parent)->getCond() != S)
286af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek          return PathDiagnosticLocation(S, SMgr);
287af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek        break;
288af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek      default:
289af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek        break;
290af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek    }
291af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek
292d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek    S = Parent;
293d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek  }
2941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
295d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek  assert(S && "Cannot have null Stmt for PathDiagnosticLocation");
296e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek
297e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek  // Special case: DeclStmts can appear in for statement declarations, in which
298e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek  //  case the ForStmt is the context.
299e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek  if (isa<DeclStmt>(S)) {
300e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek    if (const Stmt *Parent = P.getParent(S)) {
301e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek      switch (Parent->getStmtClass()) {
302e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek        case Stmt::ForStmtClass:
303e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek        case Stmt::ObjCForCollectionStmtClass:
304e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek          return PathDiagnosticLocation(Parent, SMgr);
305e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek        default:
306e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek          break;
3071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump      }
3081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    }
309e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek  }
310e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek  else if (isa<BinaryOperator>(S)) {
311e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek    // Special case: the binary operator represents the initialization
312e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek    // code in a for statement (this can happen when the variable being
313e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek    // initialized is an old variable.
314e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek    if (const ForStmt *FS =
315e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek          dyn_cast_or_null<ForStmt>(P.getParentIgnoreParens(S))) {
316e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek      if (FS->getInit() == S)
317e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek        return PathDiagnosticLocation(FS, SMgr);
318e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek    }
319e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek  }
320e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek
321d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek  return PathDiagnosticLocation(S, SMgr);
322d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek}
323d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek
324cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek//===----------------------------------------------------------------------===//
3253106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// ScanNotableSymbols: closure-like callback for scanning Store bindings.
326cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek//===----------------------------------------------------------------------===//
327cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek
32818c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenekstatic const VarDecl* GetMostRecentVarDeclBinding(const ExplodedNode *N,
32918c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek                                                  ProgramStateManager& VMgr,
33018c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek                                                  SVal X) {
3311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3323106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  for ( ; N ; N = N->pred_empty() ? 0 : *N->pred_begin()) {
3331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3343106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    ProgramPoint P = N->getLocation();
3351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3363106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    if (!isa<PostStmt>(P))
3373106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      continue;
3381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3399c378f705405d37f49795d5e915989de774fe11fTed Kremenek    const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(cast<PostStmt>(P).getStmt());
3401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3413106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    if (!DR)
3423106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      continue;
3431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3441397663af9dbcc24dbf0e11de43931b3dc08fdbbTed Kremenek    SVal Y = N->getState()->getSVal(DR);
3451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3463106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    if (X != Y)
3473106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      continue;
3481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3499c378f705405d37f49795d5e915989de774fe11fTed Kremenek    const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl());
3501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3513106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    if (!VD)
3523106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      continue;
3531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3543106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    return VD;
355cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  }
3561eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3573106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  return 0;
358bb77e9b908658b354b058509d3801f3aed052becTed Kremenek}
359bb77e9b908658b354b058509d3801f3aed052becTed Kremenek
3603106198188ac6eb2753f1764d5c28376b0b76351Ted Kremeneknamespace {
361ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass NotableSymbolHandler
3623106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek: public StoreManager::BindingsHandler {
3631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3643106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  SymbolRef Sym;
36518c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek  const ProgramState *PrevSt;
3669c378f705405d37f49795d5e915989de774fe11fTed Kremenek  const Stmt *S;
36718c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek  ProgramStateManager& VMgr;
3689c378f705405d37f49795d5e915989de774fe11fTed Kremenek  const ExplodedNode *Pred;
3691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  PathDiagnostic& PD;
3703106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  BugReporter& BR;
3711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3723106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenekpublic:
3731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
37418c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek  NotableSymbolHandler(SymbolRef sym,
37518c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek                       const ProgramState *prevst,
37618c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek                       const Stmt *s,
37718c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek                       ProgramStateManager& vmgr,
37818c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek                       const ExplodedNode *pred,
37918c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek                       PathDiagnostic& pd,
38018c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek                       BugReporter& br)
38118c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek  : Sym(sym),
38218c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek    PrevSt(prevst),
38318c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek    S(s),
38418c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek    VMgr(vmgr),
38518c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek    Pred(pred),
38618c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek    PD(pd),
38718c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek    BR(br) {}
3881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3893106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  bool HandleBinding(StoreManager& SMgr, Store store, const MemRegion* R,
3903106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek                     SVal V) {
3911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3923106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    SymbolRef ScanSym = V.getAsSymbol();
3931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3943106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    if (ScanSym != Sym)
3953106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      return true;
3961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    // Check if the previous state has this binding.
3981397663af9dbcc24dbf0e11de43931b3dc08fdbbTed Kremenek    SVal X = PrevSt->getSVal(loc::MemRegionVal(R));
3991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4003106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    if (X == V) // Same binding?
4013106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      return true;
4021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4033106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // Different binding.  Only handle assignments for now.  We don't pull
4041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    // this check out of the loop because we will eventually handle other
4053106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // cases.
4061eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4073106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    VarDecl *VD = 0;
4081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4093106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    if (const BinaryOperator* B = dyn_cast<BinaryOperator>(S)) {
4103106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      if (!B->isAssignmentOp())
4113106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        return true;
4121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4133106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      // What variable did we assign to?
4149c378f705405d37f49795d5e915989de774fe11fTed Kremenek      DeclRefExpr *DR = dyn_cast<DeclRefExpr>(B->getLHS()->IgnoreParenCasts());
4151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4163106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      if (!DR)
4173106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        return true;
4181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4193106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      VD = dyn_cast<VarDecl>(DR->getDecl());
4203106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    }
4219c378f705405d37f49795d5e915989de774fe11fTed Kremenek    else if (const DeclStmt *DS = dyn_cast<DeclStmt>(S)) {
4223106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      // FIXME: Eventually CFGs won't have DeclStmts.  Right now we
4233106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      //  assume that each DeclStmt has a single Decl.  This invariant
424fc8f0e14ad142ed811e90fbd9a30e419e301c717Chris Lattner      //  holds by construction in the CFG.
4253106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      VD = dyn_cast<VarDecl>(*DS->decl_begin());
4263106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    }
4271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4283106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    if (!VD)
4293106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      return true;
4301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4313106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // What is the most recently referenced variable with this binding?
4329c378f705405d37f49795d5e915989de774fe11fTed Kremenek    const VarDecl *MostRecent = GetMostRecentVarDeclBinding(Pred, VMgr, V);
4331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4343106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    if (!MostRecent)
4353106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      return true;
4361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4373106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // Create the diagnostic.
4383106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    FullSourceLoc L(S->getLocStart(), BR.getSourceManager());
4391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4407dfc9420babe83e236a47e752f8723bd06070d9dZhanyong Wan    if (Loc::isLocType(VD->getType())) {
4417df1234c2e62b2a23dc4417e527f941c20ebe858Jordy Rose      llvm::SmallString<64> buf;
4427df1234c2e62b2a23dc4417e527f941c20ebe858Jordy Rose      llvm::raw_svector_ostream os(buf);
4437df1234c2e62b2a23dc4417e527f941c20ebe858Jordy Rose      os << '\'' << VD << "' now aliases '" << MostRecent << '\'';
4441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4457df1234c2e62b2a23dc4417e527f941c20ebe858Jordy Rose      PD.push_front(new PathDiagnosticEventPiece(L, os.str()));
4463106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    }
4471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4483106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    return true;
4491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  }
4503106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek};
4513106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek}
4523106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
4539c378f705405d37f49795d5e915989de774fe11fTed Kremenekstatic void HandleNotableSymbol(const ExplodedNode *N,
4549c378f705405d37f49795d5e915989de774fe11fTed Kremenek                                const Stmt *S,
4553106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek                                SymbolRef Sym, BugReporter& BR,
4563106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek                                PathDiagnostic& PD) {
4571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4589c378f705405d37f49795d5e915989de774fe11fTed Kremenek  const ExplodedNode *Pred = N->pred_empty() ? 0 : *N->pred_begin();
45918c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek  const ProgramState *PrevSt = Pred ? Pred->getState() : 0;
4601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4613106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  if (!PrevSt)
4623106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    return;
4631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4643106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // Look at the region bindings of the current state that map to the
4653106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // specified symbol.  Are any of them not in the previous state?
46618c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek  ProgramStateManager& VMgr = cast<GRBugReporter>(BR).getStateManager();
4673106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  NotableSymbolHandler H(Sym, PrevSt, S, VMgr, Pred, PD, BR);
4683106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  cast<GRBugReporter>(BR).getStateManager().iterBindings(N->getState(), H);
46961f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek}
47061f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek
4713106198188ac6eb2753f1764d5c28376b0b76351Ted Kremeneknamespace {
472ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass ScanNotableSymbols
4733106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek: public StoreManager::BindingsHandler {
4741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4753106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  llvm::SmallSet<SymbolRef, 10> AlreadyProcessed;
4769c378f705405d37f49795d5e915989de774fe11fTed Kremenek  const ExplodedNode *N;
4779c378f705405d37f49795d5e915989de774fe11fTed Kremenek  const Stmt *S;
4783106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  GRBugReporter& BR;
4793106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  PathDiagnostic& PD;
4801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4813106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenekpublic:
4829c378f705405d37f49795d5e915989de774fe11fTed Kremenek  ScanNotableSymbols(const ExplodedNode *n, const Stmt *s,
4835f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek                     GRBugReporter& br, PathDiagnostic& pd)
4843106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  : N(n), S(s), BR(br), PD(pd) {}
4851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4863106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  bool HandleBinding(StoreManager& SMgr, Store store,
4873106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek                     const MemRegion* R, SVal V) {
4881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4893106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    SymbolRef ScanSym = V.getAsSymbol();
4901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4913106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    if (!ScanSym)
4923106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      return true;
4931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4943106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    if (!BR.isNotable(ScanSym))
4953106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      return true;
4961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4973106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    if (AlreadyProcessed.count(ScanSym))
4983106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      return true;
4991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
5003106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    AlreadyProcessed.insert(ScanSym);
5011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
5023106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    HandleNotableSymbol(N, S, ScanSym, BR, PD);
5033106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    return true;
504bb77e9b908658b354b058509d3801f3aed052becTed Kremenek  }
5053106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek};
5063106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} // end anonymous namespace
50750a6d0ce344c02782e0207574005c3b2aaa5077cTed Kremenek
508cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek//===----------------------------------------------------------------------===//
5093106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// "Minimal" path diagnostic generation algorithm.
510cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek//===----------------------------------------------------------------------===//
511cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek
51214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekstatic void CompactPathDiagnostic(PathDiagnostic &PD, const SourceManager& SM);
51314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
5143106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenekstatic void GenerateMinimalPathDiagnostic(PathDiagnostic& PD,
5153106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek                                          PathDiagnosticBuilder &PDB,
516c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu                                          const ExplodedNode *N) {
5178966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek
5183106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  SourceManager& SMgr = PDB.getSourceManager();
5199c378f705405d37f49795d5e915989de774fe11fTed Kremenek  const ExplodedNode *NextNode = N->pred_empty()
5203106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek                                        ? NULL : *(N->pred_begin());
5213106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  while (NextNode) {
5221eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    N = NextNode;
5233106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    NextNode = GetPredecessorNode(N);
5241eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
52561f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek    ProgramPoint P = N->getLocation();
5261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
5279c378f705405d37f49795d5e915989de774fe11fTed Kremenek    if (const BlockEdge *BE = dyn_cast<BlockEdge>(&P)) {
5289c378f705405d37f49795d5e915989de774fe11fTed Kremenek      const CFGBlock *Src = BE->getSrc();
5299c378f705405d37f49795d5e915989de774fe11fTed Kremenek      const CFGBlock *Dst = BE->getDst();
5309c378f705405d37f49795d5e915989de774fe11fTed Kremenek      const Stmt *T = Src->getTerminator();
5311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
53261f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek      if (!T)
53361f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek        continue;
5341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
535082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek      FullSourceLoc Start(T->getLocStart(), SMgr);
5361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
53761f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek      switch (T->getStmtClass()) {
53861f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek        default:
53961f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek          break;
5401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
54161f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek        case Stmt::GotoStmtClass:
5421eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump        case Stmt::IndirectGotoStmtClass: {
5439c378f705405d37f49795d5e915989de774fe11fTed Kremenek          const Stmt *S = GetNextStmt(N);
5441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
54561f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek          if (!S)
54661f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek            continue;
5471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
548297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek          std::string sbuf;
5491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump          llvm::raw_string_ostream os(sbuf);
550d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek          const PathDiagnosticLocation &End = PDB.getEnclosingStmtLocation(S);
5511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
55200605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek          os << "Control jumps to line "
553642116259e8df6286063a17361c20e95b5017a0aChandler Carruth          << End.asLocation().getExpansionLineNumber();
554082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek          PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
555082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek                                                           os.str()));
55661f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek          break;
55761f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek        }
5581eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
5591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump        case Stmt::SwitchStmtClass: {
56061f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek          // Figure out what case arm we took.
561297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek          std::string sbuf;
562297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek          llvm::raw_string_ostream os(sbuf);
5631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
5649c378f705405d37f49795d5e915989de774fe11fTed Kremenek          if (const Stmt *S = Dst->getLabel()) {
56500605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek            PathDiagnosticLocation End(S, SMgr);
5661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
5675a429954aedd8a830a70fcea2cb51561673e4fc3Ted Kremenek            switch (S->getStmtClass()) {
568082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek              default:
569082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek                os << "No cases match in the switch statement. "
5703106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek                "Control jumps to line "
571642116259e8df6286063a17361c20e95b5017a0aChandler Carruth                << End.asLocation().getExpansionLineNumber();
572082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek                break;
573082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek              case Stmt::DefaultStmtClass:
574082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek                os << "Control jumps to the 'default' case at line "
575642116259e8df6286063a17361c20e95b5017a0aChandler Carruth                << End.asLocation().getExpansionLineNumber();
576082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek                break;
5771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
578082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek              case Stmt::CaseStmtClass: {
5791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump                os << "Control jumps to 'case ";
5809c378f705405d37f49795d5e915989de774fe11fTed Kremenek                const CaseStmt *Case = cast<CaseStmt>(S);
5819c378f705405d37f49795d5e915989de774fe11fTed Kremenek                const Expr *LHS = Case->getLHS()->IgnoreParenCasts();
5821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
5831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump                // Determine if it is an enum.
584082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek                bool GetRawInt = true;
5851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
5869c378f705405d37f49795d5e915989de774fe11fTed Kremenek                if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(LHS)) {
587082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek                  // FIXME: Maybe this should be an assertion.  Are there cases
588082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek                  // were it is not an EnumConstantDecl?
5899c378f705405d37f49795d5e915989de774fe11fTed Kremenek                  const EnumConstantDecl *D =
59003509aea098772644bf4662dc1c88634818ceeccZhongxing Xu                    dyn_cast<EnumConstantDecl>(DR->getDecl());
5911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
592082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek                  if (D) {
593082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek                    GetRawInt = false;
594900fc6388e803868a34b9483510c345e9b49d7ebBenjamin Kramer                    os << D;
595082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek                  }
5965a429954aedd8a830a70fcea2cb51561673e4fc3Ted Kremenek                }
5979ec64d6e2fe575b297e1eaa5051efc2983373e25Eli Friedman
5989ec64d6e2fe575b297e1eaa5051efc2983373e25Eli Friedman                if (GetRawInt)
5998966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek                  os << LHS->EvaluateAsInt(PDB.getASTContext());
6009ec64d6e2fe575b297e1eaa5051efc2983373e25Eli Friedman
60100605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek                os << ":'  at line "
602642116259e8df6286063a17361c20e95b5017a0aChandler Carruth                << End.asLocation().getExpansionLineNumber();
603082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek                break;
604082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek              }
60561f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek            }
60600605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek            PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
60700605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek                                                             os.str()));
60861f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek          }
609567839273dfc395a459cbe77d5f8d128b9ae85bfTed Kremenek          else {
610c3517ebb48a51e146badc08bc3684520c41da6c8Ted Kremenek            os << "'Default' branch taken. ";
6111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump            const PathDiagnosticLocation &End = PDB.ExecutionContinues(os, N);
61200605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek            PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
61300605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek                                                             os.str()));
614567839273dfc395a459cbe77d5f8d128b9ae85bfTed Kremenek          }
6151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
61661f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek          break;
61761f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek        }
6181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
6192673c9ff76ebdb72b7f846e2ff1e0f4256372e19Ted Kremenek        case Stmt::BreakStmtClass:
6202673c9ff76ebdb72b7f846e2ff1e0f4256372e19Ted Kremenek        case Stmt::ContinueStmtClass: {
621297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek          std::string sbuf;
622297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek          llvm::raw_string_ostream os(sbuf);
62300605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek          PathDiagnosticLocation End = PDB.ExecutionContinues(os, N);
624082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek          PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
625082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek                                                           os.str()));
6262673c9ff76ebdb72b7f846e2ff1e0f4256372e19Ted Kremenek          break;
6272673c9ff76ebdb72b7f846e2ff1e0f4256372e19Ted Kremenek        }
6281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
6293106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek          // Determine control-flow for ternary '?'.
63056ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall        case Stmt::BinaryConditionalOperatorClass:
631706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek        case Stmt::ConditionalOperatorClass: {
632297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek          std::string sbuf;
633297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek          llvm::raw_string_ostream os(sbuf);
6341d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek          os << "'?' condition is ";
6351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
636706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek          if (*(Src->succ_begin()+1) == Dst)
637082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek            os << "false";
638706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek          else
639082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek            os << "true";
6401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
64100605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek          PathDiagnosticLocation End = PDB.ExecutionContinues(N);
6421eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
6431d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek          if (const Stmt *S = End.asStmt())
6441d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek            End = PDB.getEnclosingStmtLocation(S);
6451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
646babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek          PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
647babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek                                                           os.str()));
648babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek          break;
649babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek        }
6501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
6513106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek          // Determine control-flow for short-circuited '&&' and '||'.
652babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek        case Stmt::BinaryOperatorClass: {
653babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek          if (!PDB.supportsLogicalOpControlFlow())
654babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek            break;
6551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
65603509aea098772644bf4662dc1c88634818ceeccZhongxing Xu          const BinaryOperator *B = cast<BinaryOperator>(T);
657babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek          std::string sbuf;
658babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek          llvm::raw_string_ostream os(sbuf);
659babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek          os << "Left side of '";
6601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
6612de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall          if (B->getOpcode() == BO_LAnd) {
662f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek            os << "&&" << "' is ";
6631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
664f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek            if (*(Src->succ_begin()+1) == Dst) {
665f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek              os << "false";
666f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek              PathDiagnosticLocation End(B->getLHS(), SMgr);
667f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek              PathDiagnosticLocation Start(B->getOperatorLoc(), SMgr);
668f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek              PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
669f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek                                                               os.str()));
6701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump            }
671f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek            else {
672f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek              os << "true";
673f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek              PathDiagnosticLocation Start(B->getLHS(), SMgr);
674f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek              PathDiagnosticLocation End = PDB.ExecutionContinues(N);
675f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek              PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
676f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek                                                               os.str()));
6771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump            }
678babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek          }
679babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek          else {
6802de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall            assert(B->getOpcode() == BO_LOr);
681f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek            os << "||" << "' is ";
6821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
683f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek            if (*(Src->succ_begin()+1) == Dst) {
684f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek              os << "false";
685f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek              PathDiagnosticLocation Start(B->getLHS(), SMgr);
686f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek              PathDiagnosticLocation End = PDB.ExecutionContinues(N);
687f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek              PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
6881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump                                                               os.str()));
689f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek            }
690f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek            else {
691f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek              os << "true";
692f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek              PathDiagnosticLocation End(B->getLHS(), SMgr);
693f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek              PathDiagnosticLocation Start(B->getOperatorLoc(), SMgr);
694f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek              PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
6951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump                                                               os.str()));
696f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek            }
697babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek          }
6981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
699706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek          break;
700706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek        }
7011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
7021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump        case Stmt::DoStmtClass:  {
703706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek          if (*(Src->succ_begin()) == Dst) {
704297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek            std::string sbuf;
705297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek            llvm::raw_string_ostream os(sbuf);
7061eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
707c3517ebb48a51e146badc08bc3684520c41da6c8Ted Kremenek            os << "Loop condition is true. ";
708d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek            PathDiagnosticLocation End = PDB.ExecutionContinues(os, N);
7091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
710d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek            if (const Stmt *S = End.asStmt())
711d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek              End = PDB.getEnclosingStmtLocation(S);
7121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
713082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek            PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
714082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek                                                             os.str()));
715082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek          }
716082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek          else {
71700605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek            PathDiagnosticLocation End = PDB.ExecutionContinues(N);
7181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
719d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek            if (const Stmt *S = End.asStmt())
720d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek              End = PDB.getEnclosingStmtLocation(S);
7211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
7223106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek            PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
7233106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek                              "Loop condition is false.  Exiting loop"));
7243106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek          }
7251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
7263106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek          break;
7273106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        }
7281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
7293106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        case Stmt::WhileStmtClass:
7301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump        case Stmt::ForStmtClass: {
7313106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek          if (*(Src->succ_begin()+1) == Dst) {
7323106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek            std::string sbuf;
7333106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek            llvm::raw_string_ostream os(sbuf);
7341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
7353106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek            os << "Loop condition is false. ";
7363106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek            PathDiagnosticLocation End = PDB.ExecutionContinues(os, N);
7373106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek            if (const Stmt *S = End.asStmt())
7383106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek              End = PDB.getEnclosingStmtLocation(S);
7391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
7403106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek            PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
7413106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek                                                             os.str()));
7423106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek          }
7433106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek          else {
7443106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek            PathDiagnosticLocation End = PDB.ExecutionContinues(N);
7453106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek            if (const Stmt *S = End.asStmt())
7463106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek              End = PDB.getEnclosingStmtLocation(S);
7471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
7483106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek            PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
7495fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek                            "Loop condition is true.  Entering loop body"));
7503106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek          }
7511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
7523106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek          break;
7533106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        }
7541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
7553106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        case Stmt::IfStmtClass: {
7563106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek          PathDiagnosticLocation End = PDB.ExecutionContinues(N);
7571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
7583106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek          if (const Stmt *S = End.asStmt())
7593106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek            End = PDB.getEnclosingStmtLocation(S);
7601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
7613106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek          if (*(Src->succ_begin()+1) == Dst)
7623106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek            PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
7635fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek                                                        "Taking false branch"));
7641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump          else
7653106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek            PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
7665fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek                                                         "Taking true branch"));
7671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
7683106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek          break;
7693106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        }
7703106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      }
7713106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    }
7721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
773dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek    if (NextNode) {
7748e6431adab313e283a992698f6fc7afe62420999Anna Zaks      // Add diagnostic pieces from custom visitors.
7758e6431adab313e283a992698f6fc7afe62420999Anna Zaks      BugReport *R = PDB.getBugReport();
7768e6431adab313e283a992698f6fc7afe62420999Anna Zaks      for (BugReport::visitor_iterator I = R->visitor_begin(),
7778e6431adab313e283a992698f6fc7afe62420999Anna Zaks           E = R->visitor_end(); I!=E; ++I) {
7788e6431adab313e283a992698f6fc7afe62420999Anna Zaks        if (PathDiagnosticPiece *p = (*I)->VisitNode(N, NextNode, PDB, *R))
779dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek          PD.push_front(p);
780dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek      }
7818966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek    }
7821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
7839c378f705405d37f49795d5e915989de774fe11fTed Kremenek    if (const PostStmt *PS = dyn_cast<PostStmt>(&P)) {
7843106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      // Scan the region bindings, and see if a "notable" symbol has a new
7853106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      // lval binding.
7863106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      ScanNotableSymbols SNS(N, PS->getStmt(), PDB.getBugReporter(), PD);
7873106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      PDB.getStateManager().iterBindings(N->getState(), SNS);
7883106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    }
7893106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  }
7901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
79114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  // After constructing the full PathDiagnostic, do a pass over it to compact
79214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  // PathDiagnosticPieces that occur within a macro.
79314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  CompactPathDiagnostic(PD, PDB.getSourceManager());
7943106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek}
7953106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
7963106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===//
7975fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek// "Extensive" PathDiagnostic generation.
7985fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek//===----------------------------------------------------------------------===//
7995fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek
8005fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenekstatic bool IsControlFlowExpr(const Stmt *S) {
8015fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek  const Expr *E = dyn_cast<Expr>(S);
8021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
8035fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek  if (!E)
8045fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek    return false;
8051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
8061eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  E = E->IgnoreParenCasts();
8071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
80856ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall  if (isa<AbstractConditionalOperator>(E))
8095fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek    return true;
8101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
8115fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek  if (const BinaryOperator *B = dyn_cast<BinaryOperator>(E))
8125fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek    if (B->isLogicalOp())
8135fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek      return true;
8141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
8151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  return false;
8165fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek}
8175fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek
81814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremeneknamespace {
819ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass ContextLocation : public PathDiagnosticLocation {
8208f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek  bool IsDead;
8218f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenekpublic:
8228f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek  ContextLocation(const PathDiagnosticLocation &L, bool isdead = false)
8238f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek    : PathDiagnosticLocation(L), IsDead(isdead) {}
8241eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
8251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  void markDead() { IsDead = true; }
8268f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek  bool isDead() const { return IsDead; }
8278f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek};
8281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
829ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass EdgeBuilder {
8308f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek  std::vector<ContextLocation> CLocs;
8318f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek  typedef std::vector<ContextLocation>::iterator iterator;
83214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  PathDiagnostic &PD;
83314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  PathDiagnosticBuilder &PDB;
83414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  PathDiagnosticLocation PrevLoc;
8351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
8368f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek  bool IsConsumedExpr(const PathDiagnosticLocation &L);
8371eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
83814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  bool containsLocation(const PathDiagnosticLocation &Container,
83914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek                        const PathDiagnosticLocation &Containee);
8401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
84114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  PathDiagnosticLocation getContextLocation(const PathDiagnosticLocation &L);
8421eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
8439650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek  PathDiagnosticLocation cleanUpLocation(PathDiagnosticLocation L,
8449650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek                                         bool firstCharOnly = false) {
8458c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek    if (const Stmt *S = L.asStmt()) {
8469650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek      const Stmt *Original = S;
8478c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek      while (1) {
8488c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek        // Adjust the location for some expressions that are best referenced
8498c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek        // by one of their subexpressions.
8509650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek        switch (S->getStmtClass()) {
8519650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek          default:
8529650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek            break;
8539650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek          case Stmt::ParenExprClass:
854f111d935722ed488144600cea5ed03a6b5069e8fPeter Collingbourne          case Stmt::GenericSelectionExprClass:
855f111d935722ed488144600cea5ed03a6b5069e8fPeter Collingbourne            S = cast<Expr>(S)->IgnoreParens();
8569650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek            firstCharOnly = true;
8579650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek            continue;
85856ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall          case Stmt::BinaryConditionalOperatorClass:
8599650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek          case Stmt::ConditionalOperatorClass:
86056ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall            S = cast<AbstractConditionalOperator>(S)->getCond();
8619650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek            firstCharOnly = true;
8629650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek            continue;
8639650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek          case Stmt::ChooseExprClass:
8649650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek            S = cast<ChooseExpr>(S)->getCond();
8659650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek            firstCharOnly = true;
8669650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek            continue;
8679650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek          case Stmt::BinaryOperatorClass:
8689650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek            S = cast<BinaryOperator>(S)->getLHS();
8699650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek            firstCharOnly = true;
8709650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek            continue;
8719650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek        }
8721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
8739650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek        break;
8748c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek      }
8751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
8769650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek      if (S != Original)
8779650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek        L = PathDiagnosticLocation(S, L.getManager());
8788c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek    }
8791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
8809650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek    if (firstCharOnly)
8819650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek      L = PathDiagnosticLocation(L.asLocation());
8829650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek
8838c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek    return L;
8848c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek  }
8851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
88614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  void popLocation() {
8878f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek    if (!CLocs.back().isDead() && CLocs.back().asLocation().isFileID()) {
8885c7168cbe8a0eabd05e0e12e469090d2cabd27c0Ted Kremenek      // For contexts, we only one the first character as the range.
88907c015cbcee31f72e2d320ba2c713c046bed42faTed Kremenek      rawAddEdge(cleanUpLocation(CLocs.back(), true));
8905c7168cbe8a0eabd05e0e12e469090d2cabd27c0Ted Kremenek    }
89114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    CLocs.pop_back();
89214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  }
8931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
89414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekpublic:
89514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  EdgeBuilder(PathDiagnostic &pd, PathDiagnosticBuilder &pdb)
89614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    : PD(pd), PDB(pdb) {
8971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
898a301a6773db085575ac51e3c966858180390c25bTed Kremenek      // If the PathDiagnostic already has pieces, add the enclosing statement
899a301a6773db085575ac51e3c966858180390c25bTed Kremenek      // of the first piece as a context as well.
90014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek      if (!PD.empty()) {
90114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek        PrevLoc = PD.begin()->getLocation();
9021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
90314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek        if (const Stmt *S = PrevLoc.asStmt())
904e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek          addExtendedContext(PDB.getEnclosingStmtLocation(S).asStmt());
90514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek      }
90614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  }
90714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
90814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  ~EdgeBuilder() {
90914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    while (!CLocs.empty()) popLocation();
9101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
911a301a6773db085575ac51e3c966858180390c25bTed Kremenek    // Finally, add an initial edge from the start location of the first
912a301a6773db085575ac51e3c966858180390c25bTed Kremenek    // statement (if it doesn't already exist).
913d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl    // FIXME: Should handle CXXTryStmt if analyser starts supporting C++.
914d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl    if (const CompoundStmt *CS =
9155f1bfc10a12d9759444eb433f52a85d2e0058967Argyrios Kyrtzidis          dyn_cast_or_null<CompoundStmt>(PDB.getCodeDecl().getBody()))
916a301a6773db085575ac51e3c966858180390c25bTed Kremenek      if (!CS->body_empty()) {
917a301a6773db085575ac51e3c966858180390c25bTed Kremenek        SourceLocation Loc = (*CS->body_begin())->getLocStart();
918a301a6773db085575ac51e3c966858180390c25bTed Kremenek        rawAddEdge(PathDiagnosticLocation(Loc, PDB.getSourceManager()));
919a301a6773db085575ac51e3c966858180390c25bTed Kremenek      }
9201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
92114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  }
92214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
92314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  void addEdge(PathDiagnosticLocation NewLoc, bool alwaysAdd = false);
9241eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
9258bd4d037d837e7922c3661d6158229da58a03887Ted Kremenek  void rawAddEdge(PathDiagnosticLocation NewLoc);
9261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
92714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  void addContext(const Stmt *S);
928e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek  void addExtendedContext(const Stmt *S);
9291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump};
93014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} // end anonymous namespace
93114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
93214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
93314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted KremenekPathDiagnosticLocation
93414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted KremenekEdgeBuilder::getContextLocation(const PathDiagnosticLocation &L) {
93514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  if (const Stmt *S = L.asStmt()) {
93614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    if (IsControlFlowExpr(S))
93714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek      return L;
9381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
9391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    return PDB.getEnclosingStmtLocation(S);
94014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  }
9411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
94214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  return L;
94314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek}
94414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
94514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekbool EdgeBuilder::containsLocation(const PathDiagnosticLocation &Container,
94614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek                                   const PathDiagnosticLocation &Containee) {
94714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
94814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  if (Container == Containee)
94914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    return true;
9501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
95114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  if (Container.asDecl())
95214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    return true;
9531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
95414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  if (const Stmt *S = Containee.asStmt())
95514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    if (const Stmt *ContainerS = Container.asStmt()) {
95614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek      while (S) {
95714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek        if (S == ContainerS)
95814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek          return true;
95914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek        S = PDB.getParent(S);
96014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek      }
96114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek      return false;
96214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    }
96314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
96414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  // Less accurate: compare using source ranges.
96514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  SourceRange ContainerR = Container.asRange();
96614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  SourceRange ContaineeR = Containee.asRange();
9671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
96814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  SourceManager &SM = PDB.getSourceManager();
969402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth  SourceLocation ContainerRBeg = SM.getExpansionLoc(ContainerR.getBegin());
970402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth  SourceLocation ContainerREnd = SM.getExpansionLoc(ContainerR.getEnd());
971402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth  SourceLocation ContaineeRBeg = SM.getExpansionLoc(ContaineeR.getBegin());
972402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth  SourceLocation ContaineeREnd = SM.getExpansionLoc(ContaineeR.getEnd());
9731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
974642116259e8df6286063a17361c20e95b5017a0aChandler Carruth  unsigned ContainerBegLine = SM.getExpansionLineNumber(ContainerRBeg);
975642116259e8df6286063a17361c20e95b5017a0aChandler Carruth  unsigned ContainerEndLine = SM.getExpansionLineNumber(ContainerREnd);
976642116259e8df6286063a17361c20e95b5017a0aChandler Carruth  unsigned ContaineeBegLine = SM.getExpansionLineNumber(ContaineeRBeg);
977642116259e8df6286063a17361c20e95b5017a0aChandler Carruth  unsigned ContaineeEndLine = SM.getExpansionLineNumber(ContaineeREnd);
9781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
97914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  assert(ContainerBegLine <= ContainerEndLine);
9801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  assert(ContaineeBegLine <= ContaineeEndLine);
9811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
98214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  return (ContainerBegLine <= ContaineeBegLine &&
98314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek          ContainerEndLine >= ContaineeEndLine &&
98414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek          (ContainerBegLine != ContaineeBegLine ||
985a77c031cb66f75d22672070052cc6e0205289ff8Chandler Carruth           SM.getExpansionColumnNumber(ContainerRBeg) <=
986a77c031cb66f75d22672070052cc6e0205289ff8Chandler Carruth           SM.getExpansionColumnNumber(ContaineeRBeg)) &&
98714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek          (ContainerEndLine != ContaineeEndLine ||
988a77c031cb66f75d22672070052cc6e0205289ff8Chandler Carruth           SM.getExpansionColumnNumber(ContainerREnd) >=
989a77c031cb66f75d22672070052cc6e0205289ff8Chandler Carruth           SM.getExpansionColumnNumber(ContainerREnd)));
99014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek}
99114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
99214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekvoid EdgeBuilder::rawAddEdge(PathDiagnosticLocation NewLoc) {
99314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  if (!PrevLoc.isValid()) {
99414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    PrevLoc = NewLoc;
99514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    return;
99614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  }
9971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
9988c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek  const PathDiagnosticLocation &NewLocClean = cleanUpLocation(NewLoc);
9998c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek  const PathDiagnosticLocation &PrevLocClean = cleanUpLocation(PrevLoc);
10001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
10018c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek  if (NewLocClean.asLocation() == PrevLocClean.asLocation())
100214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    return;
10031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
100414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  // FIXME: Ignore intra-macro edges for now.
1005402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth  if (NewLocClean.asLocation().getExpansionLoc() ==
1006402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth      PrevLocClean.asLocation().getExpansionLoc())
100714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    return;
100814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
10098c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek  PD.push_front(new PathDiagnosticControlFlowPiece(NewLocClean, PrevLocClean));
10108c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek  PrevLoc = NewLoc;
101114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek}
101214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
101314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekvoid EdgeBuilder::addEdge(PathDiagnosticLocation NewLoc, bool alwaysAdd) {
10141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1015a301a6773db085575ac51e3c966858180390c25bTed Kremenek  if (!alwaysAdd && NewLoc.asLocation().isMacroID())
1016a301a6773db085575ac51e3c966858180390c25bTed Kremenek    return;
10171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
101814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  const PathDiagnosticLocation &CLoc = getContextLocation(NewLoc);
101914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
102014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  while (!CLocs.empty()) {
10218f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek    ContextLocation &TopContextLoc = CLocs.back();
10221eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
102314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    // Is the top location context the same as the one for the new location?
102414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    if (TopContextLoc == CLoc) {
10258f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek      if (alwaysAdd) {
10264c6f8d38e2795c67048e16e737b8225eeb184262Ted Kremenek        if (IsConsumedExpr(TopContextLoc) &&
10274c6f8d38e2795c67048e16e737b8225eeb184262Ted Kremenek            !IsControlFlowExpr(TopContextLoc.asStmt()))
10288f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek            TopContextLoc.markDead();
10298f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek
103014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek        rawAddEdge(NewLoc);
10318f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek      }
103214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
103314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek      return;
103414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    }
103514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
103614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    if (containsLocation(TopContextLoc, CLoc)) {
10378f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek      if (alwaysAdd) {
103814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek        rawAddEdge(NewLoc);
10391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
10404c6f8d38e2795c67048e16e737b8225eeb184262Ted Kremenek        if (IsConsumedExpr(CLoc) && !IsControlFlowExpr(CLoc.asStmt())) {
10418f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek          CLocs.push_back(ContextLocation(CLoc, true));
10428f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek          return;
10438f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek        }
10448f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek      }
10451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
104614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek      CLocs.push_back(CLoc);
10471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump      return;
104814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    }
104914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
105014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    // Context does not contain the location.  Flush it.
105114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    popLocation();
105214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  }
10531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
10545c7168cbe8a0eabd05e0e12e469090d2cabd27c0Ted Kremenek  // If we reach here, there is no enclosing context.  Just add the edge.
10555c7168cbe8a0eabd05e0e12e469090d2cabd27c0Ted Kremenek  rawAddEdge(NewLoc);
105614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek}
105714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
10588f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenekbool EdgeBuilder::IsConsumedExpr(const PathDiagnosticLocation &L) {
10598f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek  if (const Expr *X = dyn_cast_or_null<Expr>(L.asStmt()))
10608f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek    return PDB.getParentMap().isConsumedExpr(X) && !IsControlFlowExpr(X);
10611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
10628f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek  return false;
10638f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek}
10641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1065e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenekvoid EdgeBuilder::addExtendedContext(const Stmt *S) {
1066e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek  if (!S)
1067e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek    return;
10681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
10691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  const Stmt *Parent = PDB.getParent(S);
1070e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek  while (Parent) {
1071e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek    if (isa<CompoundStmt>(Parent))
1072e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek      Parent = PDB.getParent(Parent);
1073e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek    else
1074e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek      break;
1075e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek  }
1076e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek
1077e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek  if (Parent) {
1078e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek    switch (Parent->getStmtClass()) {
1079e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek      case Stmt::DoStmtClass:
1080e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek      case Stmt::ObjCAtSynchronizedStmtClass:
1081e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek        addContext(Parent);
1082e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek      default:
1083e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek        break;
1084e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek    }
1085e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek  }
10861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1087e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek  addContext(S);
1088e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek}
10891eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
109014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekvoid EdgeBuilder::addContext(const Stmt *S) {
109114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  if (!S)
109214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    return;
109314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
109414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  PathDiagnosticLocation L(S, PDB.getSourceManager());
10951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
109614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  while (!CLocs.empty()) {
109714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    const PathDiagnosticLocation &TopContextLoc = CLocs.back();
109814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
109914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    // Is the top location context the same as the one for the new location?
110014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    if (TopContextLoc == L)
110114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek      return;
110214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
110314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    if (containsLocation(TopContextLoc, L)) {
110414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek      CLocs.push_back(L);
11051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump      return;
110614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    }
110714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
110814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    // Context does not contain the location.  Flush it.
110914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    popLocation();
111014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  }
111114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
111214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  CLocs.push_back(L);
111314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek}
111414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
111514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekstatic void GenerateExtensivePathDiagnostic(PathDiagnostic& PD,
111614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek                                            PathDiagnosticBuilder &PDB,
1117c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu                                            const ExplodedNode *N) {
111814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  EdgeBuilder EB(PD, PDB);
111914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
11209c378f705405d37f49795d5e915989de774fe11fTed Kremenek  const ExplodedNode *NextNode = N->pred_empty() ? NULL : *(N->pred_begin());
112114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  while (NextNode) {
112214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    N = NextNode;
112314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    NextNode = GetPredecessorNode(N);
112414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    ProgramPoint P = N->getLocation();
112514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
1126dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek    do {
1127dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek      // Block edges.
1128dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek      if (const BlockEdge *BE = dyn_cast<BlockEdge>(&P)) {
1129dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek        const CFGBlock &Blk = *BE->getSrc();
1130dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek        const Stmt *Term = Blk.getTerminator();
11311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1132dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek        // Are we jumping to the head of a loop?  Add a special diagnostic.
1133ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek        if (const Stmt *Loop = BE->getDst()->getLoopTarget()) {
1134dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek          PathDiagnosticLocation L(Loop, PDB.getSourceManager());
1135ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek          const CompoundStmt *CS = NULL;
11361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1137ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek          if (!Term) {
1138ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek            if (const ForStmt *FS = dyn_cast<ForStmt>(Loop))
1139ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek              CS = dyn_cast<CompoundStmt>(FS->getBody());
1140ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek            else if (const WhileStmt *WS = dyn_cast<WhileStmt>(Loop))
11411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump              CS = dyn_cast<CompoundStmt>(WS->getBody());
1142ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek          }
11431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1144dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek          PathDiagnosticEventPiece *p =
1145dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek            new PathDiagnosticEventPiece(L,
114607c015cbcee31f72e2d320ba2c713c046bed42faTed Kremenek                                        "Looping back to the head of the loop");
11471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1148dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek          EB.addEdge(p->getLocation(), true);
1149dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek          PD.push_front(p);
11501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1151ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek          if (CS) {
115207c015cbcee31f72e2d320ba2c713c046bed42faTed Kremenek            PathDiagnosticLocation BL(CS->getRBracLoc(),
115307c015cbcee31f72e2d320ba2c713c046bed42faTed Kremenek                                      PDB.getSourceManager());
115407c015cbcee31f72e2d320ba2c713c046bed42faTed Kremenek            BL = PathDiagnosticLocation(BL.asLocation());
115507c015cbcee31f72e2d320ba2c713c046bed42faTed Kremenek            EB.addEdge(BL);
1156dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek          }
11578bd4d037d837e7922c3661d6158229da58a03887Ted Kremenek        }
11581eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1159ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek        if (Term)
1160ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek          EB.addContext(Term);
11611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1162dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek        break;
11638bd4d037d837e7922c3661d6158229da58a03887Ted Kremenek      }
116414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
11651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump      if (const BlockEntrance *BE = dyn_cast<BlockEntrance>(&P)) {
11663c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek        if (const CFGStmt *S = BE->getFirstElement().getAs<CFGStmt>()) {
11673c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek          const Stmt *stmt = S->getStmt();
11683c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek          if (IsControlFlowExpr(stmt)) {
1169b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu            // Add the proper context for '&&', '||', and '?'.
11703c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek            EB.addContext(stmt);
1171b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu          }
1172b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu          else
11733c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek            EB.addExtendedContext(PDB.getEnclosingStmtLocation(stmt).asStmt());
1174dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek        }
1175b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu
1176dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek        break;
1177dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek      }
1178dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek    } while (0);
11791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1180dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek    if (!NextNode)
118114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek      continue;
11821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
11838e6431adab313e283a992698f6fc7afe62420999Anna Zaks    // Add pieces from custom visitors.
11848e6431adab313e283a992698f6fc7afe62420999Anna Zaks    BugReport *R = PDB.getBugReport();
11858e6431adab313e283a992698f6fc7afe62420999Anna Zaks    for (BugReport::visitor_iterator I = R->visitor_begin(),
11868e6431adab313e283a992698f6fc7afe62420999Anna Zaks                                     E = R->visitor_end(); I!=E; ++I) {
11878e6431adab313e283a992698f6fc7afe62420999Anna Zaks      if (PathDiagnosticPiece *p = (*I)->VisitNode(N, NextNode, PDB, *R)) {
11888966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek        const PathDiagnosticLocation &Loc = p->getLocation();
11898966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek        EB.addEdge(Loc, true);
11908966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek        PD.push_front(p);
11918966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek        if (const Stmt *S = Loc.asStmt())
11921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump          EB.addExtendedContext(PDB.getEnclosingStmtLocation(S).asStmt());
11938966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek      }
11941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    }
119514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  }
119614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek}
119714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
11985fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek//===----------------------------------------------------------------------===//
11993106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// Methods for BugType and subclasses.
12003106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===//
1201404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios KyrtzidisBugType::~BugType() { }
1202404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis
12033106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenekvoid BugType::FlushReports(BugReporter &BR) {}
12043106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
12053106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===//
12063106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// Methods for BugReport and subclasses.
12073106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===//
1208e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks
12098e6431adab313e283a992698f6fc7afe62420999Anna Zaksvoid BugReport::addVisitor(BugReporterVisitor* visitor) {
12108e6431adab313e283a992698f6fc7afe62420999Anna Zaks  if (!visitor)
12118e6431adab313e283a992698f6fc7afe62420999Anna Zaks    return;
12128e6431adab313e283a992698f6fc7afe62420999Anna Zaks
12138e6431adab313e283a992698f6fc7afe62420999Anna Zaks  llvm::FoldingSetNodeID ID;
12148e6431adab313e283a992698f6fc7afe62420999Anna Zaks  visitor->Profile(ID);
12158e6431adab313e283a992698f6fc7afe62420999Anna Zaks  void *InsertPos;
12168e6431adab313e283a992698f6fc7afe62420999Anna Zaks
12178e6431adab313e283a992698f6fc7afe62420999Anna Zaks  if (CallbacksSet.FindNodeOrInsertPos(ID, InsertPos)) {
12188e6431adab313e283a992698f6fc7afe62420999Anna Zaks    delete visitor;
12198e6431adab313e283a992698f6fc7afe62420999Anna Zaks    return;
12208e6431adab313e283a992698f6fc7afe62420999Anna Zaks  }
12218e6431adab313e283a992698f6fc7afe62420999Anna Zaks
12228e6431adab313e283a992698f6fc7afe62420999Anna Zaks  CallbacksSet.InsertNode(visitor, InsertPos);
12238e6431adab313e283a992698f6fc7afe62420999Anna Zaks  Callbacks = F.add(visitor, Callbacks);
12248e6431adab313e283a992698f6fc7afe62420999Anna Zaks}
12258e6431adab313e283a992698f6fc7afe62420999Anna Zaks
12268e6431adab313e283a992698f6fc7afe62420999Anna ZaksBugReport::~BugReport() {
12278e6431adab313e283a992698f6fc7afe62420999Anna Zaks  for (visitor_iterator I = visitor_begin(), E = visitor_end(); I != E; ++I) {
1228dc757b049796949e4b11646445a6598f0bdabd7aAnna Zaks    delete *I;
12298e6431adab313e283a992698f6fc7afe62420999Anna Zaks  }
12308e6431adab313e283a992698f6fc7afe62420999Anna Zaks}
1231e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks
1232e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaksvoid BugReport::Profile(llvm::FoldingSetNodeID& hash) const {
1233e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks  hash.AddPointer(&BT);
1234e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks  hash.AddInteger(getLocation().getRawEncoding());
1235e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks  hash.AddString(Description);
1236e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks
1237e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks  for (SmallVectorImpl<SourceRange>::const_iterator I =
1238e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks      Ranges.begin(), E = Ranges.end(); I != E; ++I) {
1239e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks    const SourceRange range = *I;
1240e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks    if (!range.isValid())
1241e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks      continue;
1242e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks    hash.AddInteger(range.getBegin().getRawEncoding());
1243e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks    hash.AddInteger(range.getEnd().getRawEncoding());
1244e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks  }
1245e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks}
12463106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
12479c378f705405d37f49795d5e915989de774fe11fTed Kremenekconst Stmt *BugReport::getStmt() const {
1248e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks  if (!ErrorNode)
1249e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks    return 0;
1250e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks
1251212f6d3b5fb3fa55ba1e40671cfc336430abc8ddTom Care  ProgramPoint ProgP = ErrorNode->getLocation();
12525f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek  const Stmt *S = NULL;
12531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
12549c378f705405d37f49795d5e915989de774fe11fTed Kremenek  if (BlockEntrance *BE = dyn_cast<BlockEntrance>(&ProgP)) {
1255fafd3834754d2093e0ad7a1c005860fd527ecb7fZhongxing Xu    CFGBlock &Exit = ProgP.getLocationContext()->getCFG()->getExit();
125650d5bc4e3b53eb8bb4ebf198f1213348a3fa0f38Zhongxing Xu    if (BE->getBlock() == &Exit)
1257212f6d3b5fb3fa55ba1e40671cfc336430abc8ddTom Care      S = GetPreviousStmt(ErrorNode);
12583106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  }
12595f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek  if (!S)
12601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    S = GetStmt(ProgP);
12611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
12621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  return S;
12633106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek}
12643106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
1265640ccf071076e684713cc3c3276bb51982bff607Argyrios Kyrtzidisstd::pair<BugReport::ranges_iterator, BugReport::ranges_iterator>
1266e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna ZaksBugReport::getRanges() {
1267e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks    // If no custom ranges, add the range of the statement corresponding to
1268e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks    // the error node.
1269e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks    if (Ranges.empty()) {
1270e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks      if (const Expr *E = dyn_cast_or_null<Expr>(getStmt()))
1271e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks        addRange(E->getSourceRange());
1272e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks      else
1273e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks        return std::make_pair(ranges_iterator(), ranges_iterator());
1274e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks    }
1275e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks
1276e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks    return std::make_pair(Ranges.begin(), Ranges.end());
12773106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek}
12783106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
12791eb4433ac451dc16f4133a88af2d002ac26c58efMike StumpSourceLocation BugReport::getLocation() const {
1280b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks  if (ErrorNode) {
1281b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks    (Location.isInvalid() &&
1282b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks     "Either Location or ErrorNode should be specified but not both.");
1283b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks
12849c378f705405d37f49795d5e915989de774fe11fTed Kremenek    if (const Stmt *S = GetCurrentOrPreviousStmt(ErrorNode)) {
12853106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      // For member expressions, return the location of the '.' or '->'.
12865b9bd2137ebef350af803c634e3fdf5d74678100Ted Kremenek      if (const MemberExpr *ME = dyn_cast<MemberExpr>(S))
12873106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        return ME->getMemberLoc();
12885b9bd2137ebef350af803c634e3fdf5d74678100Ted Kremenek      // For binary operators, return the location of the operator.
12895b9bd2137ebef350af803c634e3fdf5d74678100Ted Kremenek      if (const BinaryOperator *B = dyn_cast<BinaryOperator>(S))
12905b9bd2137ebef350af803c634e3fdf5d74678100Ted Kremenek        return B->getOperatorLoc();
12913106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
12923106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      return S->getLocStart();
12933106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    }
12943106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
1295b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks  } else {
1296b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks    assert(Location.isValid());
1297b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks    return Location;
1298b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks  }
1299b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks
13003106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  return FullSourceLoc();
13013106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek}
13023106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
13033106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===//
13043106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// Methods for BugReporter and subclasses.
13053106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===//
13063106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
13073106198188ac6eb2753f1764d5c28376b0b76351Ted KremenekBugReportEquivClass::~BugReportEquivClass() {
13088966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek  for (iterator I=begin(), E=end(); I!=E; ++I) delete *I;
13093106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek}
13103106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
1311a2f4ec0df645fc249d2945beef9653f03b175417Zhongxing XuGRBugReporter::~GRBugReporter() { }
13123106198188ac6eb2753f1764d5c28376b0b76351Ted KremenekBugReporterData::~BugReporterData() {}
13133106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
131438b02b912e1a55c912f603c4369431264d36a381Zhongxing XuExplodedGraph &GRBugReporter::getGraph() { return Eng.getGraph(); }
13153106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
131618c66fdc3c4008d335885695fe36fb5353c5f672Ted KremenekProgramStateManager&
13173106198188ac6eb2753f1764d5c28376b0b76351Ted KremenekGRBugReporter::getStateManager() { return Eng.getStateManager(); }
13183106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
13193b030a28cda2b953758507769c1d436bec5ec45eAnna ZaksBugReporter::~BugReporter() {
13203b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks  FlushReports();
13213b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks
13223b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks  // Free the bug reports we are tracking.
13233b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks  typedef std::vector<BugReportEquivClass *> ContTy;
13243b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks  for (ContTy::iterator I = EQClassesVector.begin(), E = EQClassesVector.end();
13253b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks       I != E; ++I) {
13263b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks    delete *I;
13273b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks  }
13283b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks}
13293106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
13303106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenekvoid BugReporter::FlushReports() {
13313106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  if (BugTypes.isEmpty())
13323106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    return;
13333106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
13343106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // First flush the warnings for each BugType.  This may end up creating new
1335404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis  // warnings and new BugTypes.
1336404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis  // FIXME: Only NSErrorChecker needs BugType's FlushReports.
1337404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis  // Turn NSErrorChecker into a proper checker and remove this.
13385f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  SmallVector<const BugType*, 16> bugTypes;
13393106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  for (BugTypesTy::iterator I=BugTypes.begin(), E=BugTypes.end(); I!=E; ++I)
1340404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis    bugTypes.push_back(*I);
13415f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  for (SmallVector<const BugType*, 16>::iterator
1342404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis         I = bugTypes.begin(), E = bugTypes.end(); I != E; ++I)
13433106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    const_cast<BugType*>(*I)->FlushReports(*this);
13443106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
1345404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis  typedef llvm::FoldingSet<BugReportEquivClass> SetTy;
1346404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis  for (SetTy::iterator EI=EQClasses.begin(), EE=EQClasses.end(); EI!=EE;++EI){
1347404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis    BugReportEquivClass& EQ = *EI;
1348404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis    FlushReport(EQ);
13493106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  }
13503106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
1351404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis  // BugReporter owns and deletes only BugTypes created implicitly through
1352404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis  // EmitBasicReport.
1353404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis  // FIXME: There are leaks from checkers that assume that the BugTypes they
1354404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis  // create will be destroyed by the BugReporter.
1355404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis  for (llvm::StringMap<BugType*>::iterator
1356404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis         I = StrBugTypes.begin(), E = StrBugTypes.end(); I != E; ++I)
1357404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis    delete I->second;
1358404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis
13593106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // Remove all references to the BugType objects.
13603baf672378f105602d2b12f03f00277ae1936fe9Ted Kremenek  BugTypes = F.getEmptySet();
13613106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek}
13623106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
13633106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===//
13643106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// PathDiagnostics generation.
13653106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===//
13663106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
136738b02b912e1a55c912f603c4369431264d36a381Zhongxing Xustatic std::pair<std::pair<ExplodedGraph*, NodeBackMap*>,
1368c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu                 std::pair<ExplodedNode*, unsigned> >
136938b02b912e1a55c912f603c4369431264d36a381Zhongxing XuMakeReportGraph(const ExplodedGraph* G,
13705f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner                SmallVectorImpl<const ExplodedNode*> &nodes) {
13711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
13723106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // Create the trimmed graph.  It will contain the shortest paths from the
13731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  // error nodes to the root.  In the new graph we should only have one
13743106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // error node unless there are two or more error nodes with the same minimum
13753106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // path length.
137638b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu  ExplodedGraph* GTrim;
1377c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu  InterExplodedGraphMap* NMap;
13783106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
13793106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  llvm::DenseMap<const void*, const void*> InverseMap;
138040406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  llvm::tie(GTrim, NMap) = G->Trim(nodes.data(), nodes.data() + nodes.size(),
138140406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek                                   &InverseMap);
13821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
13833106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // Create owning pointers for GTrim and NMap just to ensure that they are
13843106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // released when this function exists.
138538b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu  llvm::OwningPtr<ExplodedGraph> AutoReleaseGTrim(GTrim);
1386c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu  llvm::OwningPtr<InterExplodedGraphMap> AutoReleaseNMap(NMap);
13871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
13883106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // Find the (first) error node in the trimmed graph.  We just need to consult
13893106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // the node map (NMap) which maps from nodes in the original graph to nodes
13903106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // in the new graph.
1391938332c657390d1e782e0adc03b092993edae962Ted Kremenek
1392c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu  std::queue<const ExplodedNode*> WS;
139338b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu  typedef llvm::DenseMap<const ExplodedNode*, unsigned> IndexMapTy;
1394938332c657390d1e782e0adc03b092993edae962Ted Kremenek  IndexMapTy IndexMap;
13953106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
139640406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  for (unsigned nodeIndex = 0 ; nodeIndex < nodes.size(); ++nodeIndex) {
139740406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek    const ExplodedNode *originalNode = nodes[nodeIndex];
139840406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek    if (const ExplodedNode *N = NMap->getMappedNode(originalNode)) {
1399938332c657390d1e782e0adc03b092993edae962Ted Kremenek      WS.push(N);
140040406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek      IndexMap[originalNode] = nodeIndex;
14013106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    }
140240406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  }
14031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1404938332c657390d1e782e0adc03b092993edae962Ted Kremenek  assert(!WS.empty() && "No error node found in the trimmed graph.");
14053106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
14063106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // Create a new (third!) graph with a single path.  This is the graph
14073106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // that will be returned to the caller.
1408c77a55126fcad66fb086f8e100a494caa2496a2dZhongxing Xu  ExplodedGraph *GNew = new ExplodedGraph();
14091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
14103106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // Sometimes the trimmed graph can contain a cycle.  Perform a reverse BFS
14113106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // to the root node, and then construct a new graph that contains only
14123106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // a single path.
14133106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  llvm::DenseMap<const void*,unsigned> Visited;
14141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
14153106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  unsigned cnt = 0;
14169c378f705405d37f49795d5e915989de774fe11fTed Kremenek  const ExplodedNode *Root = 0;
14171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
14183106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  while (!WS.empty()) {
14199c378f705405d37f49795d5e915989de774fe11fTed Kremenek    const ExplodedNode *Node = WS.front();
14203106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    WS.pop();
14211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
14223106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    if (Visited.find(Node) != Visited.end())
14233106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      continue;
14241eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
14253106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    Visited[Node] = cnt++;
14261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
14273106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    if (Node->pred_empty()) {
14283106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      Root = Node;
14293106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      break;
14303106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    }
14311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1432c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu    for (ExplodedNode::const_pred_iterator I=Node->pred_begin(),
14333106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek         E=Node->pred_end(); I!=E; ++I)
14343106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      WS.push(*I);
14353106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  }
14361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1437938332c657390d1e782e0adc03b092993edae962Ted Kremenek  assert(Root);
14381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
14393106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // Now walk from the root down the BFS path, always taking the successor
14403106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // with the lowest number.
14411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  ExplodedNode *Last = 0, *First = 0;
14423106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  NodeBackMap *BM = new NodeBackMap();
1443938332c657390d1e782e0adc03b092993edae962Ted Kremenek  unsigned NodeIndex = 0;
14441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1445c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu  for ( const ExplodedNode *N = Root ;;) {
14463106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // Lookup the number associated with the current node.
14473106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    llvm::DenseMap<const void*,unsigned>::iterator I = Visited.find(N);
1448938332c657390d1e782e0adc03b092993edae962Ted Kremenek    assert(I != Visited.end());
14491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
14503106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // Create the equivalent node in the new graph with the same state
14513106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // and location.
14529c378f705405d37f49795d5e915989de774fe11fTed Kremenek    ExplodedNode *NewN = GNew->getNode(N->getLocation(), N->getState());
14531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
14543106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // Store the mapping to the original node.
14553106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    llvm::DenseMap<const void*, const void*>::iterator IMitr=InverseMap.find(N);
14563106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    assert(IMitr != InverseMap.end() && "No mapping to original node.");
1457c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu    (*BM)[NewN] = (const ExplodedNode*) IMitr->second;
14581eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
14593106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // Link up the new node with the previous node.
14603106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    if (Last)
14615fe4d9deb543a19f557e3d85c5f33867af97cd96Ted Kremenek      NewN->addPredecessor(Last, *GNew);
14621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
14633106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    Last = NewN;
14641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
14653106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // Are we at the final node?
1466938332c657390d1e782e0adc03b092993edae962Ted Kremenek    IndexMapTy::iterator IMI =
1467c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu      IndexMap.find((const ExplodedNode*)(IMitr->second));
1468938332c657390d1e782e0adc03b092993edae962Ted Kremenek    if (IMI != IndexMap.end()) {
14693106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      First = NewN;
1470938332c657390d1e782e0adc03b092993edae962Ted Kremenek      NodeIndex = IMI->second;
14713106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      break;
14723106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    }
14731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
14743106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // Find the next successor node.  We choose the node that is marked
14753106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // with the lowest DFS number.
1476c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu    ExplodedNode::const_succ_iterator SI = N->succ_begin();
1477c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu    ExplodedNode::const_succ_iterator SE = N->succ_end();
14783106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    N = 0;
14791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
14803106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    for (unsigned MinVal = 0; SI != SE; ++SI) {
14811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
14823106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      I = Visited.find(*SI);
14831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
14843106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      if (I == Visited.end())
14853106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        continue;
14861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
14873106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      if (!N || I->second < MinVal) {
14883106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        N = *SI;
14893106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        MinVal = I->second;
14903106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      }
14913106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    }
14921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1493938332c657390d1e782e0adc03b092993edae962Ted Kremenek    assert(N);
14943106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  }
14951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1496938332c657390d1e782e0adc03b092993edae962Ted Kremenek  assert(First);
1497938332c657390d1e782e0adc03b092993edae962Ted Kremenek
14983106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  return std::make_pair(std::make_pair(GNew, BM),
14993106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek                        std::make_pair(First, NodeIndex));
15003106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek}
1501d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek
15023106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek/// CompactPathDiagnostic - This function postprocesses a PathDiagnostic object
15033106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek///  and collapses PathDiagosticPieces that are expanded by macros.
15043106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenekstatic void CompactPathDiagnostic(PathDiagnostic &PD, const SourceManager& SM) {
15053106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  typedef std::vector<std::pair<PathDiagnosticMacroPiece*, SourceLocation> >
15063106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek          MacroStackTy;
15071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
15083106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  typedef std::vector<PathDiagnosticPiece*>
15093106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek          PiecesTy;
15101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
15113106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  MacroStackTy MacroStack;
15123106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  PiecesTy Pieces;
15131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
15143106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  for (PathDiagnostic::iterator I = PD.begin(), E = PD.end(); I!=E; ++I) {
15153106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // Get the location of the PathDiagnosticPiece.
15161eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    const FullSourceLoc Loc = I->getLocation().asLocation();
15171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
15183106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // Determine the instantiation location, which is the location we group
15193106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // related PathDiagnosticPieces.
15201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    SourceLocation InstantiationLoc = Loc.isMacroID() ?
1521402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth                                      SM.getExpansionLoc(Loc) :
15223106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek                                      SourceLocation();
15231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
15243106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    if (Loc.isFileID()) {
15253106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      MacroStack.clear();
15263106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      Pieces.push_back(&*I);
15273106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      continue;
15283106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    }
1529706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek
15303106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    assert(Loc.isMacroID());
15311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
15323106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // Is the PathDiagnosticPiece within the same macro group?
15333106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    if (!MacroStack.empty() && InstantiationLoc == MacroStack.back().second) {
15343106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      MacroStack.back().first->push_back(&*I);
15353106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      continue;
15363106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    }
1537d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek
15383106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // We aren't in the same group.  Are we descending into a new macro
15393106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // or are part of an old one?
15403106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    PathDiagnosticMacroPiece *MacroGroup = 0;
1541d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek
15423106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    SourceLocation ParentInstantiationLoc = InstantiationLoc.isMacroID() ?
1543402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth                                          SM.getExpansionLoc(Loc) :
15443106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek                                          SourceLocation();
15451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
15463106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // Walk the entire macro stack.
15473106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    while (!MacroStack.empty()) {
15483106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      if (InstantiationLoc == MacroStack.back().second) {
15493106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        MacroGroup = MacroStack.back().first;
15503106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        break;
15513106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      }
15521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
15533106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      if (ParentInstantiationLoc == MacroStack.back().second) {
15543106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        MacroGroup = MacroStack.back().first;
15553106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        break;
155661f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek      }
15571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
15583106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      MacroStack.pop_back();
15596837faa083bebad39aa342f84c2b450fb6410eafTed Kremenek    }
15601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
15613106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    if (!MacroGroup || ParentInstantiationLoc == MacroStack.back().second) {
15623106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      // Create a new macro group and add it to the stack.
15633106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      PathDiagnosticMacroPiece *NewGroup = new PathDiagnosticMacroPiece(Loc);
15645a429954aedd8a830a70fcea2cb51561673e4fc3Ted Kremenek
15653106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      if (MacroGroup)
15663106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        MacroGroup->push_back(NewGroup);
15673106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      else {
15683106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        assert(InstantiationLoc.isFileID());
15693106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        Pieces.push_back(NewGroup);
15703106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      }
15711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
15723106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      MacroGroup = NewGroup;
15733106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      MacroStack.push_back(std::make_pair(MacroGroup, InstantiationLoc));
15747dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek    }
15753106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
15763106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // Finally, add the PathDiagnosticPiece to the group.
15773106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    MacroGroup->push_back(&*I);
15783106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  }
15791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
15803106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // Now take the pieces and construct a new PathDiagnostic.
15813106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  PD.resetPath(false);
15821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
15833106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  for (PiecesTy::iterator I=Pieces.begin(), E=Pieces.end(); I!=E; ++I) {
15843106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    if (PathDiagnosticMacroPiece *MP=dyn_cast<PathDiagnosticMacroPiece>(*I))
15853106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      if (!MP->containsEvent()) {
15863106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        delete MP;
15873106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        continue;
15883106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      }
15891eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
15903106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    PD.push_back(*I);
159161f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek  }
159261f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek}
159361f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek
15943106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenekvoid GRBugReporter::GeneratePathDiagnostic(PathDiagnostic& PD,
15955f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner                        SmallVectorImpl<BugReport *> &bugReports) {
15961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
159740406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  assert(!bugReports.empty());
15985f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  SmallVector<const ExplodedNode *, 10> errorNodes;
15995f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  for (SmallVectorImpl<BugReport*>::iterator I = bugReports.begin(),
160040406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek    E = bugReports.end(); I != E; ++I) {
160140406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek      errorNodes.push_back((*I)->getErrorNode());
160240406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  }
16031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
16043106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // Construct a new graph that contains only a single path from the error
16051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  // node to a root.
160638b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu  const std::pair<std::pair<ExplodedGraph*, NodeBackMap*>,
1607c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu  std::pair<ExplodedNode*, unsigned> >&
160840406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek    GPair = MakeReportGraph(&getGraph(), errorNodes);
16091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
16103106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // Find the BugReport with the original location.
161140406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  assert(GPair.second.second < bugReports.size());
161240406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  BugReport *R = bugReports[GPair.second.second];
16133106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  assert(R && "No original report found for sliced graph.");
16141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
161538b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu  llvm::OwningPtr<ExplodedGraph> ReportGraph(GPair.first.first);
16163106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  llvm::OwningPtr<NodeBackMap> BackMap(GPair.first.second);
1617c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu  const ExplodedNode *N = GPair.second.first;
16181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
16191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  // Start building the path diagnostic...
16208966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek  PathDiagnosticBuilder PDB(*this, R, BackMap.get(), getPathDiagnosticClient());
16211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
16228e6431adab313e283a992698f6fc7afe62420999Anna Zaks  // Register additional node visitors.
162350bbc165b063155cc23c360deb7b865502e068e2Anna Zaks  R->addVisitor(new NilReceiverBRVisitor());
162450bbc165b063155cc23c360deb7b865502e068e2Anna Zaks  R->addVisitor(new ConditionBRVisitor());
16251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
162623f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks  // Generate the very last diagnostic piece - the piece is visible before
162723f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks  // the trace is expanded.
162823f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks  PathDiagnosticPiece *LastPiece = 0;
162923f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks  for (BugReport::visitor_iterator I = R->visitor_begin(),
163023f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks                                   E = R->visitor_end(); I!=E; ++I) {
163123f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks    if (PathDiagnosticPiece *Piece = (*I)->getEndPath(PDB, N, *R)) {
163223f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks      assert (!LastPiece &&
163323f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks              "There can only be one final piece in a diagnostic.");
163423f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks      LastPiece = Piece;
163523f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks    }
163623f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks  }
163723f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks  if (!LastPiece)
163823f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks    LastPiece = BugReporterVisitor::getDefaultEndPath(PDB, N, *R);
163923f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks  if (LastPiece)
164023f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks    PD.push_back(LastPiece);
164123f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks  else
164223f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks    return;
164323f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks
16443106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  switch (PDB.getGenerationScheme()) {
16453106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    case PathDiagnosticClient::Extensive:
16468966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek      GenerateExtensivePathDiagnostic(PD, PDB, N);
16475fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek      break;
16483106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    case PathDiagnosticClient::Minimal:
16493106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      GenerateMinimalPathDiagnostic(PD, PDB, N);
16503106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      break;
16513106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  }
16523106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek}
16531aa44c7c9198796085b77c6bdd7c90030845a688Ted Kremenek
1654cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenekvoid BugReporter::Register(BugType *BT) {
16553baf672378f105602d2b12f03f00277ae1936fe9Ted Kremenek  BugTypes = F.add(BugTypes, BT);
165676d90c8bf83d071fd1bdbffa6d9f2af87c6bb7b5Ted Kremenek}
165776d90c8bf83d071fd1bdbffa6d9f2af87c6bb7b5Ted Kremenek
16581eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpvoid BugReporter::EmitReport(BugReport* R) {
1659cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  // Compute the bug report's hash to determine its equivalence class.
1660cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  llvm::FoldingSetNodeID ID;
1661cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  R->Profile(ID);
16621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
16631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  // Lookup the equivance class.  If there isn't one, create it.
1664cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  BugType& BT = R->getBugType();
1665cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  Register(&BT);
1666cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  void *InsertPos;
1667404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis  BugReportEquivClass* EQ = EQClasses.FindNodeOrInsertPos(ID, InsertPos);
16681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1669cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  if (!EQ) {
1670cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek    EQ = new BugReportEquivClass(R);
1671404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis    EQClasses.InsertNode(EQ, InsertPos);
16723b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks    EQClassesVector.push_back(EQ);
1673cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  }
1674cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  else
1675cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek    EQ->AddReport(R);
167661f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek}
167761f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek
167806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek
167906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek//===----------------------------------------------------------------------===//
168006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek// Emitting reports in equivalence classes.
168106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek//===----------------------------------------------------------------------===//
168206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek
168306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremeneknamespace {
1684ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamstruct FRIEC_WLItem {
168506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek  const ExplodedNode *N;
168606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek  ExplodedNode::const_succ_iterator I, E;
168706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek
168806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek  FRIEC_WLItem(const ExplodedNode *n)
168906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek  : N(n), I(N->succ_begin()), E(N->succ_end()) {}
169006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek};
169106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek}
169206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek
169361f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenekstatic BugReport *
169461f52bd3c524268e25b48a1ed3730aedd6cc8374Ted KremenekFindReportInEquivalenceClass(BugReportEquivClass& EQ,
16955f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner                             SmallVectorImpl<BugReport*> &bugReports) {
169661f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek
169706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek  BugReportEquivClass::iterator I = EQ.begin(), E = EQ.end();
169806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek  assert(I != E);
169906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek  BugReport *R = *I;
170006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek  BugType& BT = R->getBugType();
170161f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek
170240406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  // If we don't need to suppress any of the nodes because they are
170340406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  // post-dominated by a sink, simply add all the nodes in the equivalence class
170440406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  // to 'Nodes'.  Any of the reports will serve as a "representative" report.
170561f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek  if (!BT.isSuppressOnSink()) {
170661f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek    for (BugReportEquivClass::iterator I=EQ.begin(), E=EQ.end(); I!=E; ++I) {
17079c378f705405d37f49795d5e915989de774fe11fTed Kremenek      const ExplodedNode *N = I->getErrorNode();
170861f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek      if (N) {
170961f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek        R = *I;
171040406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek        bugReports.push_back(R);
171161f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek      }
171261f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek    }
171306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek    return R;
171461f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek  }
171561f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek
171606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek  // For bug reports that should be suppressed when all paths are post-dominated
171706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek  // by a sink node, iterate through the reports in the equivalence class
171806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek  // until we find one that isn't post-dominated (if one exists).  We use a
171906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek  // DFS traversal of the ExplodedGraph to find a non-sink node.  We could write
172006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek  // this as a recursive function, but we don't want to risk blowing out the
172106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek  // stack for very long paths.
172240406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  BugReport *exampleReport = 0;
172361f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek
172406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek  for (; I != E; ++I) {
172506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek    R = *I;
172640406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek    const ExplodedNode *errorNode = R->getErrorNode();
172706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek
172840406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek    if (!errorNode)
172906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek      continue;
173040406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek    if (errorNode->isSink()) {
173106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek      assert(false &&
173206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek           "BugType::isSuppressSink() should not be 'true' for sink end nodes");
173361f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek      return 0;
173406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek    }
173561f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek    // No successors?  By definition this nodes isn't post-dominated by a sink.
173640406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek    if (errorNode->succ_empty()) {
173740406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek      bugReports.push_back(R);
173840406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek      if (!exampleReport)
173940406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek        exampleReport = R;
174061f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek      continue;
174161f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek    }
174261f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek
174306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek    // At this point we know that 'N' is not a sink and it has at least one
174406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek    // successor.  Use a DFS worklist to find a non-sink end-of-path node.
174506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek    typedef FRIEC_WLItem WLItem;
17465f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner    typedef SmallVector<WLItem, 10> DFSWorkList;
174706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek    llvm::DenseMap<const ExplodedNode *, unsigned> Visited;
174806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek
174906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek    DFSWorkList WL;
175040406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek    WL.push_back(errorNode);
175140406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek    Visited[errorNode] = 1;
175206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek
175306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek    while (!WL.empty()) {
175406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek      WLItem &WI = WL.back();
175506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek      assert(!WI.N->succ_empty());
175606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek
175706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek      for (; WI.I != WI.E; ++WI.I) {
175806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek        const ExplodedNode *Succ = *WI.I;
175906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek        // End-of-path node?
176006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek        if (Succ->succ_empty()) {
176161f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek          // If we found an end-of-path node that is not a sink.
176261f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek          if (!Succ->isSink()) {
176340406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek            bugReports.push_back(R);
176440406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek            if (!exampleReport)
176540406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek              exampleReport = R;
176661f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek            WL.clear();
176761f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek            break;
176861f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek          }
176906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek          // Found a sink?  Continue on to the next successor.
177006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek          continue;
177106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek        }
177206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek        // Mark the successor as visited.  If it hasn't been explored,
177306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek        // enqueue it to the DFS worklist.
177406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek        unsigned &mark = Visited[Succ];
177506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek        if (!mark) {
177606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek          mark = 1;
177706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek          WL.push_back(Succ);
177806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek          break;
177906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek        }
178006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek      }
178161f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek
178261f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek      // The worklist may have been cleared at this point.  First
178361f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek      // check if it is empty before checking the last item.
178461f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek      if (!WL.empty() && &WL.back() == &WI)
178506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek        WL.pop_back();
178606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek    }
178706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek  }
178806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek
178961f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek  // ExampleReport will be NULL if all the nodes in the equivalence class
179061f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek  // were post-dominated by sinks.
179140406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  return exampleReport;
179261f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek}
1793e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek
1794e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek//===----------------------------------------------------------------------===//
1795e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek// DiagnosticCache.  This is a hack to cache analyzer diagnostics.  It
1796e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek// uses global state, which eventually should go elsewhere.
1797e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek//===----------------------------------------------------------------------===//
1798e0a58073b76fc016325a35152533b8468df2bf4aTed Kremeneknamespace {
1799ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass DiagCacheItem : public llvm::FoldingSetNode {
1800e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek  llvm::FoldingSetNodeID ID;
1801e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenekpublic:
1802e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek  DiagCacheItem(BugReport *R, PathDiagnostic *PD) {
1803e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek    ID.AddString(R->getBugType().getName());
1804e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek    ID.AddString(R->getBugType().getCategory());
1805e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek    ID.AddString(R->getDescription());
1806e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek    ID.AddInteger(R->getLocation().getRawEncoding());
1807e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek    PD->Profile(ID);
1808e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek  }
1809e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek
1810e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek  void Profile(llvm::FoldingSetNodeID &id) {
1811e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek    id = ID;
1812e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek  }
1813e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek
1814e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek  llvm::FoldingSetNodeID &getID() { return ID; }
1815e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek};
1816e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek}
1817e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek
1818e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenekstatic bool IsCachedDiagnostic(BugReport *R, PathDiagnostic *PD) {
1819e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek  // FIXME: Eventually this diagnostic cache should reside in something
1820e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek  // like AnalysisManager instead of being a static variable.  This is
1821e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek  // really unsafe in the long term.
1822e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek  typedef llvm::FoldingSet<DiagCacheItem> DiagnosticCache;
1823e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek  static DiagnosticCache DC;
1824e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek
1825e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek  void *InsertPos;
1826e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek  DiagCacheItem *Item = new DiagCacheItem(R, PD);
1827e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek
1828e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek  if (DC.FindNodeOrInsertPos(Item->getID(), InsertPos)) {
1829e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek    delete Item;
1830e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek    return true;
1831e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek  }
1832e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek
1833e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek  DC.InsertNode(Item, InsertPos);
1834e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek  return false;
1835e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek}
1836e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek
1837cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenekvoid BugReporter::FlushReport(BugReportEquivClass& EQ) {
18385f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  SmallVector<BugReport*, 10> bugReports;
183940406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  BugReport *exampleReport = FindReportInEquivalenceClass(EQ, bugReports);
184040406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  if (!exampleReport)
184106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek    return;
184206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek
1843d49967f8764135ae65658e354b6d38e3637c9de3Ted Kremenek  PathDiagnosticClient* PD = getPathDiagnosticClient();
18441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1845cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  // FIXME: Make sure we use the 'R' for the path that was actually used.
18461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  // Probably doesn't make a difference in practice.
184740406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  BugType& BT = exampleReport->getBugType();
18481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1849d49967f8764135ae65658e354b6d38e3637c9de3Ted Kremenek  llvm::OwningPtr<PathDiagnostic>
185040406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek    D(new PathDiagnostic(exampleReport->getBugType().getName(),
1851da0e8429a3598acfdd0ecf15135d432e4dd3517cTed Kremenek                         !PD || PD->useVerboseDescription()
185240406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek                         ? exampleReport->getDescription()
185340406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek                         : exampleReport->getShortDescription(),
1854d49967f8764135ae65658e354b6d38e3637c9de3Ted Kremenek                         BT.getCategory()));
1855d49967f8764135ae65658e354b6d38e3637c9de3Ted Kremenek
185640406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  if (!bugReports.empty())
185740406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek    GeneratePathDiagnostic(*D.get(), bugReports);
18581eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
185940406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  if (IsCachedDiagnostic(exampleReport, D.get()))
1860e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek    return;
1861e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek
1862072192bcbb05a0fee7ec3061750b27e8d2004952Ted Kremenek  // Get the meta data.
186340406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  std::pair<const char**, const char**> Meta =
186440406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek    exampleReport->getExtraDescriptiveText();
186506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek  for (const char** s = Meta.first; s != Meta.second; ++s)
186606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek    D->addMeta(*s);
186775840e1501563fe7c3dcb5600b75965ba1fe1bc4Ted Kremenek
18683148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek  // Emit a summary diagnostic to the regular Diagnostics engine.
1869640ccf071076e684713cc3c3276bb51982bff607Argyrios Kyrtzidis  BugReport::ranges_iterator Beg, End;
1870640ccf071076e684713cc3c3276bb51982bff607Argyrios Kyrtzidis  llvm::tie(Beg, End) = exampleReport->getRanges();
187140406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  Diagnostic &Diag = getDiagnostic();
187240406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  FullSourceLoc L(exampleReport->getLocation(), getSourceManager());
1873c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek
1874c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek  // Search the description for '%', as that will be interpretted as a
1875c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek  // format character by FormatDiagnostics.
18765f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  StringRef desc = exampleReport->getShortDescription();
1877c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek  unsigned ErrorDiag;
1878c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek  {
1879c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek    llvm::SmallString<512> TmpStr;
1880c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek    llvm::raw_svector_ostream Out(TmpStr);
18815f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner    for (StringRef::iterator I=desc.begin(), E=desc.end(); I!=E; ++I)
1882c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek      if (*I == '%')
1883c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek        Out << "%%";
1884c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek      else
1885c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek        Out << *I;
1886c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek
1887c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek    Out.flush();
1888c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek    ErrorDiag = Diag.getCustomDiagID(Diagnostic::Warning, TmpStr);
1889c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek  }
18900a14eee528a901c16f0e288fbc10a3abc1660d87Chris Lattner
1891b6b7e7bff3101062521de6e79533a3c25e2195d9Argyrios Kyrtzidis  {
1892b6b7e7bff3101062521de6e79533a3c25e2195d9Argyrios Kyrtzidis    DiagnosticBuilder diagBuilder = Diag.Report(L, ErrorDiag);
1893640ccf071076e684713cc3c3276bb51982bff607Argyrios Kyrtzidis    for (BugReport::ranges_iterator I = Beg; I != End; ++I)
1894b6b7e7bff3101062521de6e79533a3c25e2195d9Argyrios Kyrtzidis      diagBuilder << *I;
18952f0e89ea96292d2974eb1a7dddc0e9870aa86bb7Ted Kremenek  }
18963148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek
18973148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek  // Emit a full diagnostic for the path if we have a PathDiagnosticClient.
18983148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek  if (!PD)
18993148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek    return;
19001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
19011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  if (D->empty()) {
19029c378f705405d37f49795d5e915989de774fe11fTed Kremenek    PathDiagnosticPiece *piece =
190340406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek      new PathDiagnosticEventPiece(L, exampleReport->getDescription());
19041fbfd5b9b8b82aea084773b76dd1ec6796a7000cTed Kremenek
19053148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek    for ( ; Beg != End; ++Beg) piece->addRange(*Beg);
19063148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek    D->push_back(piece);
19073148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek  }
19081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
19093148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek  PD->HandlePathDiagnostic(D.take());
191061f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek}
191157202071e477530e9348bc76671ee369b2399b92Ted Kremenek
19125f9e272e632e951b1efe824cd16acb4d96077930Chris Lattnervoid BugReporter::EmitBasicReport(StringRef name, StringRef str,
19138c036c7f77d69f96df49219ed0bdbade200d52ebTed Kremenek                                  SourceLocation Loc,
19148c036c7f77d69f96df49219ed0bdbade200d52ebTed Kremenek                                  SourceRange* RBeg, unsigned NumRanges) {
19158c036c7f77d69f96df49219ed0bdbade200d52ebTed Kremenek  EmitBasicReport(name, "", str, Loc, RBeg, NumRanges);
19168c036c7f77d69f96df49219ed0bdbade200d52ebTed Kremenek}
1917cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek
19185f9e272e632e951b1efe824cd16acb4d96077930Chris Lattnervoid BugReporter::EmitBasicReport(StringRef name,
19195f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner                                  StringRef category,
19205f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner                                  StringRef str, SourceLocation Loc,
19218c036c7f77d69f96df49219ed0bdbade200d52ebTed Kremenek                                  SourceRange* RBeg, unsigned NumRanges) {
19221eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1923404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis  // 'BT' is owned by BugReporter.
1924404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis  BugType *BT = getBugTypeForName(name, category);
19250a14eee528a901c16f0e288fbc10a3abc1660d87Chris Lattner  FullSourceLoc L = getContext().getFullLoc(Loc);
1926b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks  BugReport *R = new BugReport(*BT, str, L);
1927cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  for ( ; NumRanges > 0 ; --NumRanges, ++RBeg) R->addRange(*RBeg);
1928cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  EmitReport(R);
1929cabe66811fe43835b8c5a0854552768fc53261e3Ted Kremenek}
1930404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis
19315f9e272e632e951b1efe824cd16acb4d96077930Chris LattnerBugType *BugReporter::getBugTypeForName(StringRef name,
19325f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner                                        StringRef category) {
1933404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis  llvm::SmallString<136> fullDesc;
1934404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis  llvm::raw_svector_ostream(fullDesc) << name << ":" << category;
1935404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis  llvm::StringMapEntry<BugType *> &
1936404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis      entry = StrBugTypes.GetOrCreateValue(fullDesc);
1937404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis  BugType *BT = entry.getValue();
1938404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis  if (!BT) {
1939404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis    BT = new BugType(name, category);
1940404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis    entry.setValue(BT);
1941404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis  }
1942404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis  return BT;
1943404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis}
1944