BugReporter.cpp revision ef3643fbbbf66247c5e205497fae0f46e240c143
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      }
86b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek      return S;
87f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek    }
881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
89b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek  return 0;
90bd7efa8ca27ed9676acf00abf31d5e1cd54651ccTed Kremenek}
91bd7efa8ca27ed9676acf00abf31d5e1cd54651ccTed Kremenek
925f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenekstatic inline const Stmt*
939c378f705405d37f49795d5e915989de774fe11fTed KremenekGetCurrentOrPreviousStmt(const ExplodedNode *N) {
945f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek  if (const Stmt *S = GetStmt(N->getLocation()))
95b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek    return S;
961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
97b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek  return GetPreviousStmt(N);
98b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek}
991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1005f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenekstatic inline const Stmt*
1019c378f705405d37f49795d5e915989de774fe11fTed KremenekGetCurrentOrNextStmt(const ExplodedNode *N) {
1025f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek  if (const Stmt *S = GetStmt(N->getLocation()))
103b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek    return S;
1041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
105b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek  return GetNextStmt(N);
1063148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek}
1073148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek
108b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek//===----------------------------------------------------------------------===//
1093106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// PathDiagnosticBuilder and its associated routines and helper objects.
110b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek//===----------------------------------------------------------------------===//
111b479dadea93b93d3f0a335c3518b703f140b3f50Ted Kremenek
112c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xutypedef llvm::DenseMap<const ExplodedNode*,
113c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xuconst ExplodedNode*> NodeBackMap;
1147dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek
115babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremeneknamespace {
116ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass NodeMapClosure : public BugReport::NodeResolver {
1177dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek  NodeBackMap& M;
1187dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenekpublic:
1197dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek  NodeMapClosure(NodeBackMap *m) : M(*m) {}
1207dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek  ~NodeMapClosure() {}
1211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1229c378f705405d37f49795d5e915989de774fe11fTed Kremenek  const ExplodedNode *getOriginalNode(const ExplodedNode *N) {
1237dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek    NodeBackMap::iterator I = M.find(N);
1247dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek    return I == M.end() ? 0 : I->second;
1257dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek  }
1267dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek};
1271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
128ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass PathDiagnosticBuilder : public BugReporterContext {
1297dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek  BugReport *R;
130ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie  PathDiagnosticConsumer *PDC;
13100605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek  llvm::OwningPtr<ParentMap> PM;
1327dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek  NodeMapClosure NMC;
1331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumppublic:
1348966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek  PathDiagnosticBuilder(GRBugReporter &br,
1351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump                        BugReport *r, NodeBackMap *Backmap,
136ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie                        PathDiagnosticConsumer *pdc)
1378966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek    : BugReporterContext(br),
1388e6431adab313e283a992698f6fc7afe62420999Anna Zaks      R(r), PDC(pdc), NMC(Backmap) {}
1391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1409c378f705405d37f49795d5e915989de774fe11fTed Kremenek  PathDiagnosticLocation ExecutionContinues(const ExplodedNode *N);
1411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1429c378f705405d37f49795d5e915989de774fe11fTed Kremenek  PathDiagnosticLocation ExecutionContinues(llvm::raw_string_ostream &os,
1439c378f705405d37f49795d5e915989de774fe11fTed Kremenek                                            const ExplodedNode *N);
1441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1458e6431adab313e283a992698f6fc7afe62420999Anna Zaks  BugReport *getBugReport() { return R; }
1468e6431adab313e283a992698f6fc7afe62420999Anna Zaks
147212f6d3b5fb3fa55ba1e40671cfc336430abc8ddTom Care  Decl const &getCodeDecl() { return R->getErrorNode()->getCodeDecl(); }
148b317f8f5ca8737a5bbad97a3f7566a2dbd2ed61bZhongxing Xu
149220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks  const LocationContext* getLocationContext() {
150220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks    return R->getErrorNode()->getLocationContext();
151220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks  }
152220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks
153212f6d3b5fb3fa55ba1e40671cfc336430abc8ddTom Care  ParentMap& getParentMap() { return R->getErrorNode()->getParentMap(); }
1541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
155c3f83ad7adaff2623986aa1c3e57833babd03d50Ted Kremenek  const Stmt *getParent(const Stmt *S) {
156c3f83ad7adaff2623986aa1c3e57833babd03d50Ted Kremenek    return getParentMap().getParent(S);
157c3f83ad7adaff2623986aa1c3e57833babd03d50Ted Kremenek  }
1581eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1598966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek  virtual NodeMapClosure& getNodeResolver() { return NMC; }
1607297134f128423fce2e88f92421ed135bded7d4eDouglas Gregor
161d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek  PathDiagnosticLocation getEnclosingStmtLocation(const Stmt *S);
1621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
163ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie  PathDiagnosticConsumer::PathGenerationScheme getGenerationScheme() const {
164ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie    return PDC ? PDC->getGenerationScheme() : PathDiagnosticConsumer::Extensive;
1657dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek  }
1667dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek
167babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek  bool supportsLogicalOpControlFlow() const {
168babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek    return PDC ? PDC->supportsLogicalOpControlFlow() : true;
1691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  }
170babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek};
171babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek} // end anonymous namespace
172babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek
17300605e0f011ed99225a22026344c5fc1b3212cd7Ted KremenekPathDiagnosticLocation
1749c378f705405d37f49795d5e915989de774fe11fTed KremenekPathDiagnosticBuilder::ExecutionContinues(const ExplodedNode *N) {
1755f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek  if (const Stmt *S = GetNextStmt(N))
176220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks    return PathDiagnosticLocation(S, getSourceManager(), getLocationContext());
17700605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek
1780cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks  return PathDiagnosticLocation::createDeclEnd(N->getLocationContext(),
1790cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks                                               getSourceManager());
180082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek}
1811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
18200605e0f011ed99225a22026344c5fc1b3212cd7Ted KremenekPathDiagnosticLocation
1839c378f705405d37f49795d5e915989de774fe11fTed KremenekPathDiagnosticBuilder::ExecutionContinues(llvm::raw_string_ostream &os,
1849c378f705405d37f49795d5e915989de774fe11fTed Kremenek                                          const ExplodedNode *N) {
185babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek
186143ca222583a4a355fdc89af852deef287499300Ted Kremenek  // Slow, but probably doesn't matter.
187b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek  if (os.str().empty())
188b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek    os << ' ';
1891eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
19000605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek  const PathDiagnosticLocation &Loc = ExecutionContinues(N);
1911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
19200605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek  if (Loc.asStmt())
193b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek    os << "Execution continues on line "
194642116259e8df6286063a17361c20e95b5017a0aChandler Carruth       << getSourceManager().getExpansionLineNumber(Loc.asLocation())
1958966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek       << '.';
1964f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek  else {
1974f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek    os << "Execution jumps to the end of the ";
1984f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek    const Decl *D = N->getLocationContext()->getDecl();
1994f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek    if (isa<ObjCMethodDecl>(D))
2004f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek      os << "method";
2014f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek    else if (isa<FunctionDecl>(D))
2024f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek      os << "function";
2034f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek    else {
2044f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek      assert(isa<BlockDecl>(D));
2054f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek      os << "anonymous block";
2064f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek    }
2074f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek    os << '.';
2084f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek  }
2091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
210082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek  return Loc;
211143ca222583a4a355fdc89af852deef287499300Ted Kremenek}
212143ca222583a4a355fdc89af852deef287499300Ted Kremenek
213ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenekstatic bool IsNested(const Stmt *S, ParentMap &PM) {
214ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek  if (isa<Expr>(S) && PM.isConsumedExpr(cast<Expr>(S)))
215ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek    return true;
2161eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
217ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek  const Stmt *Parent = PM.getParentIgnoreParens(S);
2181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
219ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek  if (Parent)
220ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek    switch (Parent->getStmtClass()) {
221ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek      case Stmt::ForStmtClass:
222ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek      case Stmt::DoStmtClass:
223ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek      case Stmt::WhileStmtClass:
224ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek        return true;
225ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek      default:
226ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek        break;
227ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek    }
2281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  return false;
230ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek}
231ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek
232d8c938b0f6b7a7156181be575239e4c6e15a2adbTed KremenekPathDiagnosticLocation
233d8c938b0f6b7a7156181be575239e4c6e15a2adbTed KremenekPathDiagnosticBuilder::getEnclosingStmtLocation(const Stmt *S) {
2349c378f705405d37f49795d5e915989de774fe11fTed Kremenek  assert(S && "Null Stmt *passed to getEnclosingStmtLocation");
2351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  ParentMap &P = getParentMap();
2368966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek  SourceManager &SMgr = getSourceManager();
237220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks  const LocationContext *LC = getLocationContext();
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())
249220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks          return PathDiagnosticLocation(S, SMgr, LC);
2505fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek        break;
2511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump      }
252af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek      case Stmt::CompoundStmtClass:
253af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek      case Stmt::StmtExprClass:
254220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks        return PathDiagnosticLocation(S, SMgr, LC);
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)
259220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks          return PathDiagnosticLocation(Parent, SMgr, LC);
2601d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek        else
261220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks          return PathDiagnosticLocation(S, SMgr, LC);
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)
267220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks          return PathDiagnosticLocation(Parent, SMgr, LC);
2681d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek        else
269220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks          return PathDiagnosticLocation(S, SMgr, LC);
270af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek      case Stmt::DoStmtClass:
271220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks          return PathDiagnosticLocation(S, SMgr, LC);
272af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek      case Stmt::ForStmtClass:
273af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek        if (cast<ForStmt>(Parent)->getBody() == S)
274220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks          return PathDiagnosticLocation(S, SMgr, LC);
2751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump        break;
276af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek      case Stmt::IfStmtClass:
277af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek        if (cast<IfStmt>(Parent)->getCond() != S)
278220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks          return PathDiagnosticLocation(S, SMgr, LC);
2798bd4d037d837e7922c3661d6158229da58a03887Ted Kremenek        break;
280af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek      case Stmt::ObjCForCollectionStmtClass:
281af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek        if (cast<ObjCForCollectionStmt>(Parent)->getBody() == S)
282220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks          return PathDiagnosticLocation(S, SMgr, LC);
283af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek        break;
284af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek      case Stmt::WhileStmtClass:
285af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek        if (cast<WhileStmt>(Parent)->getCond() != S)
286220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks          return PathDiagnosticLocation(S, SMgr, LC);
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:
304220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks          return PathDiagnosticLocation(Parent, SMgr, LC);
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)
317220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks        return PathDiagnosticLocation(FS, SMgr, LC);
318e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek    }
319e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek  }
320e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek
321220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks  return PathDiagnosticLocation(S, SMgr, LC);
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.
4387dfc9420babe83e236a47e752f8723bd06070d9dZhanyong Wan    if (Loc::isLocType(VD->getType())) {
4397df1234c2e62b2a23dc4417e527f941c20ebe858Jordy Rose      llvm::SmallString<64> buf;
4407df1234c2e62b2a23dc4417e527f941c20ebe858Jordy Rose      llvm::raw_svector_ostream os(buf);
4417df1234c2e62b2a23dc4417e527f941c20ebe858Jordy Rose      os << '\'' << VD << "' now aliases '" << MostRecent << '\'';
442590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks      PathDiagnosticLocation L =
443590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks        PathDiagnosticLocation::createBegin(S, BR.getSourceManager(),
444590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks                                                   Pred->getLocationContext());
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();
519220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks  const LocationContext *LC = PDB.getLocationContext();
5209c378f705405d37f49795d5e915989de774fe11fTed Kremenek  const ExplodedNode *NextNode = N->pred_empty()
5213106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek                                        ? NULL : *(N->pred_begin());
5223106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  while (NextNode) {
5231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    N = NextNode;
5243106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    NextNode = GetPredecessorNode(N);
5251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
52661f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek    ProgramPoint P = N->getLocation();
5271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
5289c378f705405d37f49795d5e915989de774fe11fTed Kremenek    if (const BlockEdge *BE = dyn_cast<BlockEdge>(&P)) {
5299c378f705405d37f49795d5e915989de774fe11fTed Kremenek      const CFGBlock *Src = BE->getSrc();
5309c378f705405d37f49795d5e915989de774fe11fTed Kremenek      const CFGBlock *Dst = BE->getDst();
5319c378f705405d37f49795d5e915989de774fe11fTed Kremenek      const Stmt *T = Src->getTerminator();
5321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
53361f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek      if (!T)
53461f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek        continue;
5351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
536590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks      PathDiagnosticLocation Start =
537590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks        PathDiagnosticLocation::createBegin(T, SMgr,
538590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks                                                N->getLocationContext());
5391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
54061f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek      switch (T->getStmtClass()) {
54161f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek        default:
54261f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek          break;
5431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
54461f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek        case Stmt::GotoStmtClass:
5451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump        case Stmt::IndirectGotoStmtClass: {
5469c378f705405d37f49795d5e915989de774fe11fTed Kremenek          const Stmt *S = GetNextStmt(N);
5471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
54861f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek          if (!S)
54961f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek            continue;
5501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
551297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek          std::string sbuf;
5521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump          llvm::raw_string_ostream os(sbuf);
553d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek          const PathDiagnosticLocation &End = PDB.getEnclosingStmtLocation(S);
5541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
55500605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek          os << "Control jumps to line "
556642116259e8df6286063a17361c20e95b5017a0aChandler Carruth          << End.asLocation().getExpansionLineNumber();
557082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek          PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
558082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek                                                           os.str()));
55961f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek          break;
56061f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek        }
5611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
5621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump        case Stmt::SwitchStmtClass: {
56361f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek          // Figure out what case arm we took.
564297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek          std::string sbuf;
565297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek          llvm::raw_string_ostream os(sbuf);
5661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
5679c378f705405d37f49795d5e915989de774fe11fTed Kremenek          if (const Stmt *S = Dst->getLabel()) {
568220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks            PathDiagnosticLocation End(S, SMgr, LC);
5691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
5705a429954aedd8a830a70fcea2cb51561673e4fc3Ted Kremenek            switch (S->getStmtClass()) {
571082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek              default:
572082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek                os << "No cases match in the switch statement. "
5733106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek                "Control jumps to line "
574642116259e8df6286063a17361c20e95b5017a0aChandler Carruth                << End.asLocation().getExpansionLineNumber();
575082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek                break;
576082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek              case Stmt::DefaultStmtClass:
577082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek                os << "Control jumps to the 'default' case at line "
578642116259e8df6286063a17361c20e95b5017a0aChandler Carruth                << End.asLocation().getExpansionLineNumber();
579082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek                break;
5801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
581082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek              case Stmt::CaseStmtClass: {
5821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump                os << "Control jumps to 'case ";
5839c378f705405d37f49795d5e915989de774fe11fTed Kremenek                const CaseStmt *Case = cast<CaseStmt>(S);
5849c378f705405d37f49795d5e915989de774fe11fTed Kremenek                const Expr *LHS = Case->getLHS()->IgnoreParenCasts();
5851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
5861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump                // Determine if it is an enum.
587082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek                bool GetRawInt = true;
5881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
5899c378f705405d37f49795d5e915989de774fe11fTed Kremenek                if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(LHS)) {
590082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek                  // FIXME: Maybe this should be an assertion.  Are there cases
591082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek                  // were it is not an EnumConstantDecl?
5929c378f705405d37f49795d5e915989de774fe11fTed Kremenek                  const EnumConstantDecl *D =
59303509aea098772644bf4662dc1c88634818ceeccZhongxing Xu                    dyn_cast<EnumConstantDecl>(DR->getDecl());
5941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
595082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek                  if (D) {
596082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek                    GetRawInt = false;
597900fc6388e803868a34b9483510c345e9b49d7ebBenjamin Kramer                    os << D;
598082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek                  }
5995a429954aedd8a830a70fcea2cb51561673e4fc3Ted Kremenek                }
6009ec64d6e2fe575b297e1eaa5051efc2983373e25Eli Friedman
6019ec64d6e2fe575b297e1eaa5051efc2983373e25Eli Friedman                if (GetRawInt)
6028966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek                  os << LHS->EvaluateAsInt(PDB.getASTContext());
6039ec64d6e2fe575b297e1eaa5051efc2983373e25Eli Friedman
60400605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek                os << ":'  at line "
605642116259e8df6286063a17361c20e95b5017a0aChandler Carruth                << End.asLocation().getExpansionLineNumber();
606082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek                break;
607082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek              }
60861f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek            }
60900605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek            PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
61000605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek                                                             os.str()));
61161f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek          }
612567839273dfc395a459cbe77d5f8d128b9ae85bfTed Kremenek          else {
613c3517ebb48a51e146badc08bc3684520c41da6c8Ted Kremenek            os << "'Default' branch taken. ";
6141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump            const PathDiagnosticLocation &End = PDB.ExecutionContinues(os, N);
61500605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek            PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
61600605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek                                                             os.str()));
617567839273dfc395a459cbe77d5f8d128b9ae85bfTed Kremenek          }
6181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
61961f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek          break;
62061f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek        }
6211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
6222673c9ff76ebdb72b7f846e2ff1e0f4256372e19Ted Kremenek        case Stmt::BreakStmtClass:
6232673c9ff76ebdb72b7f846e2ff1e0f4256372e19Ted Kremenek        case Stmt::ContinueStmtClass: {
624297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek          std::string sbuf;
625297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek          llvm::raw_string_ostream os(sbuf);
62600605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek          PathDiagnosticLocation End = PDB.ExecutionContinues(os, N);
627082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek          PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
628082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek                                                           os.str()));
6292673c9ff76ebdb72b7f846e2ff1e0f4256372e19Ted Kremenek          break;
6302673c9ff76ebdb72b7f846e2ff1e0f4256372e19Ted Kremenek        }
6311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
6323106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek          // Determine control-flow for ternary '?'.
63356ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall        case Stmt::BinaryConditionalOperatorClass:
634706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek        case Stmt::ConditionalOperatorClass: {
635297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek          std::string sbuf;
636297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek          llvm::raw_string_ostream os(sbuf);
6371d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek          os << "'?' condition is ";
6381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
639706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek          if (*(Src->succ_begin()+1) == Dst)
640082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek            os << "false";
641706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek          else
642082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek            os << "true";
6431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
64400605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek          PathDiagnosticLocation End = PDB.ExecutionContinues(N);
6451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
6461d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek          if (const Stmt *S = End.asStmt())
6471d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek            End = PDB.getEnclosingStmtLocation(S);
6481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
649babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek          PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
650babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek                                                           os.str()));
651babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek          break;
652babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek        }
6531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
6543106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek          // Determine control-flow for short-circuited '&&' and '||'.
655babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek        case Stmt::BinaryOperatorClass: {
656babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek          if (!PDB.supportsLogicalOpControlFlow())
657babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek            break;
6581eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
65903509aea098772644bf4662dc1c88634818ceeccZhongxing Xu          const BinaryOperator *B = cast<BinaryOperator>(T);
660babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek          std::string sbuf;
661babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek          llvm::raw_string_ostream os(sbuf);
662babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek          os << "Left side of '";
6631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
6642de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall          if (B->getOpcode() == BO_LAnd) {
665f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek            os << "&&" << "' is ";
6661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
667f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek            if (*(Src->succ_begin()+1) == Dst) {
668f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek              os << "false";
669220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks              PathDiagnosticLocation End(B->getLHS(), SMgr, LC);
6700cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks              PathDiagnosticLocation Start =
6710cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks                PathDiagnosticLocation::createOperatorLoc(B, SMgr);
672f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek              PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
673f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek                                                               os.str()));
6741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump            }
675f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek            else {
676f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek              os << "true";
677220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks              PathDiagnosticLocation Start(B->getLHS(), SMgr, LC);
678f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek              PathDiagnosticLocation End = PDB.ExecutionContinues(N);
679f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek              PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
680f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek                                                               os.str()));
6811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump            }
682babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek          }
683babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek          else {
6842de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall            assert(B->getOpcode() == BO_LOr);
685f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek            os << "||" << "' is ";
6861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
687f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek            if (*(Src->succ_begin()+1) == Dst) {
688f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek              os << "false";
689220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks              PathDiagnosticLocation Start(B->getLHS(), SMgr, LC);
690f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek              PathDiagnosticLocation End = PDB.ExecutionContinues(N);
691f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek              PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
6921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump                                                               os.str()));
693f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek            }
694f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek            else {
695f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek              os << "true";
696220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks              PathDiagnosticLocation End(B->getLHS(), SMgr, LC);
6970cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks              PathDiagnosticLocation Start =
6980cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks                PathDiagnosticLocation::createOperatorLoc(B, SMgr);
699f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek              PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
7001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump                                                               os.str()));
701f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek            }
702babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek          }
7031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
704706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek          break;
705706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek        }
7061eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
7071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump        case Stmt::DoStmtClass:  {
708706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek          if (*(Src->succ_begin()) == Dst) {
709297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek            std::string sbuf;
710297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek            llvm::raw_string_ostream os(sbuf);
7111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
712c3517ebb48a51e146badc08bc3684520c41da6c8Ted Kremenek            os << "Loop condition is true. ";
713d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek            PathDiagnosticLocation End = PDB.ExecutionContinues(os, N);
7141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
715d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek            if (const Stmt *S = End.asStmt())
716d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek              End = PDB.getEnclosingStmtLocation(S);
7171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
718082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek            PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
719082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek                                                             os.str()));
720082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek          }
721082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek          else {
72200605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek            PathDiagnosticLocation End = PDB.ExecutionContinues(N);
7231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
724d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek            if (const Stmt *S = End.asStmt())
725d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek              End = PDB.getEnclosingStmtLocation(S);
7261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
7273106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek            PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
7283106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek                              "Loop condition is false.  Exiting loop"));
7293106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek          }
7301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
7313106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek          break;
7323106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        }
7331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
7343106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        case Stmt::WhileStmtClass:
7351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump        case Stmt::ForStmtClass: {
7363106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek          if (*(Src->succ_begin()+1) == Dst) {
7373106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek            std::string sbuf;
7383106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek            llvm::raw_string_ostream os(sbuf);
7391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
7403106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek            os << "Loop condition is false. ";
7413106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek            PathDiagnosticLocation End = PDB.ExecutionContinues(os, N);
7423106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek            if (const Stmt *S = End.asStmt())
7433106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek              End = PDB.getEnclosingStmtLocation(S);
7441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
7453106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek            PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
7463106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek                                                             os.str()));
7473106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek          }
7483106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek          else {
7493106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek            PathDiagnosticLocation End = PDB.ExecutionContinues(N);
7503106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek            if (const Stmt *S = End.asStmt())
7513106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek              End = PDB.getEnclosingStmtLocation(S);
7521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
7533106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek            PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
7545fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek                            "Loop condition is true.  Entering loop body"));
7553106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek          }
7561eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
7573106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek          break;
7583106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        }
7591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
7603106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        case Stmt::IfStmtClass: {
7613106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek          PathDiagnosticLocation End = PDB.ExecutionContinues(N);
7621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
7633106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek          if (const Stmt *S = End.asStmt())
7643106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek            End = PDB.getEnclosingStmtLocation(S);
7651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
7663106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek          if (*(Src->succ_begin()+1) == Dst)
7673106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek            PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
7685fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek                                                        "Taking false branch"));
7691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump          else
7703106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek            PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
7715fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek                                                         "Taking true branch"));
7721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
7733106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek          break;
7743106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        }
7753106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      }
7763106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    }
7771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
778dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek    if (NextNode) {
7798e6431adab313e283a992698f6fc7afe62420999Anna Zaks      // Add diagnostic pieces from custom visitors.
7808e6431adab313e283a992698f6fc7afe62420999Anna Zaks      BugReport *R = PDB.getBugReport();
7818e6431adab313e283a992698f6fc7afe62420999Anna Zaks      for (BugReport::visitor_iterator I = R->visitor_begin(),
7828e6431adab313e283a992698f6fc7afe62420999Anna Zaks           E = R->visitor_end(); I!=E; ++I) {
7838e6431adab313e283a992698f6fc7afe62420999Anna Zaks        if (PathDiagnosticPiece *p = (*I)->VisitNode(N, NextNode, PDB, *R))
784dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek          PD.push_front(p);
785dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek      }
7868966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek    }
7871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
7889c378f705405d37f49795d5e915989de774fe11fTed Kremenek    if (const PostStmt *PS = dyn_cast<PostStmt>(&P)) {
7893106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      // Scan the region bindings, and see if a "notable" symbol has a new
7903106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      // lval binding.
7913106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      ScanNotableSymbols SNS(N, PS->getStmt(), PDB.getBugReporter(), PD);
7923106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      PDB.getStateManager().iterBindings(N->getState(), SNS);
7933106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    }
7943106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  }
7951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
79614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  // After constructing the full PathDiagnostic, do a pass over it to compact
79714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  // PathDiagnosticPieces that occur within a macro.
79814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  CompactPathDiagnostic(PD, PDB.getSourceManager());
7993106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek}
8003106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
8013106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===//
8025fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek// "Extensive" PathDiagnostic generation.
8035fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek//===----------------------------------------------------------------------===//
8045fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek
8055fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenekstatic bool IsControlFlowExpr(const Stmt *S) {
8065fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek  const Expr *E = dyn_cast<Expr>(S);
8071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
8085fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek  if (!E)
8095fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek    return false;
8101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
8111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  E = E->IgnoreParenCasts();
8121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
81356ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall  if (isa<AbstractConditionalOperator>(E))
8145fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek    return true;
8151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
8165fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek  if (const BinaryOperator *B = dyn_cast<BinaryOperator>(E))
8175fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek    if (B->isLogicalOp())
8185fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek      return true;
8191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
8201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  return false;
8215fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek}
8225fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek
82314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremeneknamespace {
824ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass ContextLocation : public PathDiagnosticLocation {
8258f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek  bool IsDead;
8268f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenekpublic:
8278f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek  ContextLocation(const PathDiagnosticLocation &L, bool isdead = false)
8288f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek    : PathDiagnosticLocation(L), IsDead(isdead) {}
8291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
8301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  void markDead() { IsDead = true; }
8318f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek  bool isDead() const { return IsDead; }
8328f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek};
8331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
834ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass EdgeBuilder {
8358f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek  std::vector<ContextLocation> CLocs;
8368f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek  typedef std::vector<ContextLocation>::iterator iterator;
83714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  PathDiagnostic &PD;
83814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  PathDiagnosticBuilder &PDB;
83914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  PathDiagnosticLocation PrevLoc;
8401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
8418f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek  bool IsConsumedExpr(const PathDiagnosticLocation &L);
8421eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
84314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  bool containsLocation(const PathDiagnosticLocation &Container,
84414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek                        const PathDiagnosticLocation &Containee);
8451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
84614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  PathDiagnosticLocation getContextLocation(const PathDiagnosticLocation &L);
8471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
8489650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek  PathDiagnosticLocation cleanUpLocation(PathDiagnosticLocation L,
8499650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek                                         bool firstCharOnly = false) {
8508c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek    if (const Stmt *S = L.asStmt()) {
8519650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek      const Stmt *Original = S;
8528c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek      while (1) {
8538c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek        // Adjust the location for some expressions that are best referenced
8548c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek        // by one of their subexpressions.
8559650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek        switch (S->getStmtClass()) {
8569650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek          default:
8579650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek            break;
8589650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek          case Stmt::ParenExprClass:
859f111d935722ed488144600cea5ed03a6b5069e8fPeter Collingbourne          case Stmt::GenericSelectionExprClass:
860f111d935722ed488144600cea5ed03a6b5069e8fPeter Collingbourne            S = cast<Expr>(S)->IgnoreParens();
8619650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek            firstCharOnly = true;
8629650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek            continue;
86356ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall          case Stmt::BinaryConditionalOperatorClass:
8649650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek          case Stmt::ConditionalOperatorClass:
86556ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall            S = cast<AbstractConditionalOperator>(S)->getCond();
8669650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek            firstCharOnly = true;
8679650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek            continue;
8689650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek          case Stmt::ChooseExprClass:
8699650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek            S = cast<ChooseExpr>(S)->getCond();
8709650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek            firstCharOnly = true;
8719650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek            continue;
8729650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek          case Stmt::BinaryOperatorClass:
8739650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek            S = cast<BinaryOperator>(S)->getLHS();
8749650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek            firstCharOnly = true;
8759650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek            continue;
8769650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek        }
8771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
8789650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek        break;
8798c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek      }
8801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
8819650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek      if (S != Original)
88223803374d8db054192ea6fcb766b87e04f26c8fbAnna Zaks        L = PathDiagnosticLocation(S, L.getManager(), PDB.getLocationContext());
8838c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek    }
8841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
8859650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek    if (firstCharOnly)
8861531bb0c69d9afff6a6434e4cadf345eb628b287Anna Zaks      L  = PathDiagnosticLocation::createSingleLocation(L);
8879650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek
8888c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek    return L;
8898c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek  }
8901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
89114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  void popLocation() {
8928f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek    if (!CLocs.back().isDead() && CLocs.back().asLocation().isFileID()) {
8935c7168cbe8a0eabd05e0e12e469090d2cabd27c0Ted Kremenek      // For contexts, we only one the first character as the range.
89407c015cbcee31f72e2d320ba2c713c046bed42faTed Kremenek      rawAddEdge(cleanUpLocation(CLocs.back(), true));
8955c7168cbe8a0eabd05e0e12e469090d2cabd27c0Ted Kremenek    }
89614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    CLocs.pop_back();
89714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  }
8981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
89914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekpublic:
90014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  EdgeBuilder(PathDiagnostic &pd, PathDiagnosticBuilder &pdb)
90114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    : PD(pd), PDB(pdb) {
9021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
903a301a6773db085575ac51e3c966858180390c25bTed Kremenek      // If the PathDiagnostic already has pieces, add the enclosing statement
904a301a6773db085575ac51e3c966858180390c25bTed Kremenek      // of the first piece as a context as well.
90514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek      if (!PD.empty()) {
90614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek        PrevLoc = PD.begin()->getLocation();
9071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
90814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek        if (const Stmt *S = PrevLoc.asStmt())
909e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek          addExtendedContext(PDB.getEnclosingStmtLocation(S).asStmt());
91014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek      }
91114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  }
91214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
91314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  ~EdgeBuilder() {
91414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    while (!CLocs.empty()) popLocation();
9150cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks
916a301a6773db085575ac51e3c966858180390c25bTed Kremenek    // Finally, add an initial edge from the start location of the first
917a301a6773db085575ac51e3c966858180390c25bTed Kremenek    // statement (if it doesn't already exist).
9180cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks    PathDiagnosticLocation L = PathDiagnosticLocation::createDeclBegin(
9190cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks                                                       PDB.getLocationContext(),
9200cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks                                                       PDB.getSourceManager());
9210cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks    if (L.isValid())
9220cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks      rawAddEdge(L);
92314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  }
92414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
92514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  void addEdge(PathDiagnosticLocation NewLoc, bool alwaysAdd = false);
9261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
9278bd4d037d837e7922c3661d6158229da58a03887Ted Kremenek  void rawAddEdge(PathDiagnosticLocation NewLoc);
9281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
92914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  void addContext(const Stmt *S);
930e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek  void addExtendedContext(const Stmt *S);
9311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump};
93214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} // end anonymous namespace
93314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
93414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
93514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted KremenekPathDiagnosticLocation
93614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted KremenekEdgeBuilder::getContextLocation(const PathDiagnosticLocation &L) {
93714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  if (const Stmt *S = L.asStmt()) {
93814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    if (IsControlFlowExpr(S))
93914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek      return L;
9401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
9411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    return PDB.getEnclosingStmtLocation(S);
94214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  }
9431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
94414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  return L;
94514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek}
94614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
94714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekbool EdgeBuilder::containsLocation(const PathDiagnosticLocation &Container,
94814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek                                   const PathDiagnosticLocation &Containee) {
94914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
95014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  if (Container == Containee)
95114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    return true;
9521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
95314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  if (Container.asDecl())
95414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    return true;
9551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
95614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  if (const Stmt *S = Containee.asStmt())
95714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    if (const Stmt *ContainerS = Container.asStmt()) {
95814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek      while (S) {
95914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek        if (S == ContainerS)
96014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek          return true;
96114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek        S = PDB.getParent(S);
96214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek      }
96314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek      return false;
96414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    }
96514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
96614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  // Less accurate: compare using source ranges.
96714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  SourceRange ContainerR = Container.asRange();
96814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  SourceRange ContaineeR = Containee.asRange();
9691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
97014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  SourceManager &SM = PDB.getSourceManager();
971402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth  SourceLocation ContainerRBeg = SM.getExpansionLoc(ContainerR.getBegin());
972402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth  SourceLocation ContainerREnd = SM.getExpansionLoc(ContainerR.getEnd());
973402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth  SourceLocation ContaineeRBeg = SM.getExpansionLoc(ContaineeR.getBegin());
974402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth  SourceLocation ContaineeREnd = SM.getExpansionLoc(ContaineeR.getEnd());
9751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
976642116259e8df6286063a17361c20e95b5017a0aChandler Carruth  unsigned ContainerBegLine = SM.getExpansionLineNumber(ContainerRBeg);
977642116259e8df6286063a17361c20e95b5017a0aChandler Carruth  unsigned ContainerEndLine = SM.getExpansionLineNumber(ContainerREnd);
978642116259e8df6286063a17361c20e95b5017a0aChandler Carruth  unsigned ContaineeBegLine = SM.getExpansionLineNumber(ContaineeRBeg);
979642116259e8df6286063a17361c20e95b5017a0aChandler Carruth  unsigned ContaineeEndLine = SM.getExpansionLineNumber(ContaineeREnd);
9801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
98114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  assert(ContainerBegLine <= ContainerEndLine);
9821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  assert(ContaineeBegLine <= ContaineeEndLine);
9831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
98414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  return (ContainerBegLine <= ContaineeBegLine &&
98514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek          ContainerEndLine >= ContaineeEndLine &&
98614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek          (ContainerBegLine != ContaineeBegLine ||
987a77c031cb66f75d22672070052cc6e0205289ff8Chandler Carruth           SM.getExpansionColumnNumber(ContainerRBeg) <=
988a77c031cb66f75d22672070052cc6e0205289ff8Chandler Carruth           SM.getExpansionColumnNumber(ContaineeRBeg)) &&
98914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek          (ContainerEndLine != ContaineeEndLine ||
990a77c031cb66f75d22672070052cc6e0205289ff8Chandler Carruth           SM.getExpansionColumnNumber(ContainerREnd) >=
991a77c031cb66f75d22672070052cc6e0205289ff8Chandler Carruth           SM.getExpansionColumnNumber(ContainerREnd)));
99214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek}
99314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
99414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekvoid EdgeBuilder::rawAddEdge(PathDiagnosticLocation NewLoc) {
99514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  if (!PrevLoc.isValid()) {
99614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    PrevLoc = NewLoc;
99714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    return;
99814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  }
9991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
10008c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek  const PathDiagnosticLocation &NewLocClean = cleanUpLocation(NewLoc);
10018c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek  const PathDiagnosticLocation &PrevLocClean = cleanUpLocation(PrevLoc);
10021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
10038c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek  if (NewLocClean.asLocation() == PrevLocClean.asLocation())
100414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    return;
10051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
100614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  // FIXME: Ignore intra-macro edges for now.
1007402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth  if (NewLocClean.asLocation().getExpansionLoc() ==
1008402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth      PrevLocClean.asLocation().getExpansionLoc())
100914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    return;
101014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
10118c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek  PD.push_front(new PathDiagnosticControlFlowPiece(NewLocClean, PrevLocClean));
10128c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek  PrevLoc = NewLoc;
101314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek}
101414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
101514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekvoid EdgeBuilder::addEdge(PathDiagnosticLocation NewLoc, bool alwaysAdd) {
10161eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1017a301a6773db085575ac51e3c966858180390c25bTed Kremenek  if (!alwaysAdd && NewLoc.asLocation().isMacroID())
1018a301a6773db085575ac51e3c966858180390c25bTed Kremenek    return;
10191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
102014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  const PathDiagnosticLocation &CLoc = getContextLocation(NewLoc);
102114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
102214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  while (!CLocs.empty()) {
10238f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek    ContextLocation &TopContextLoc = CLocs.back();
10241eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
102514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    // Is the top location context the same as the one for the new location?
102614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    if (TopContextLoc == CLoc) {
10278f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek      if (alwaysAdd) {
10284c6f8d38e2795c67048e16e737b8225eeb184262Ted Kremenek        if (IsConsumedExpr(TopContextLoc) &&
10294c6f8d38e2795c67048e16e737b8225eeb184262Ted Kremenek            !IsControlFlowExpr(TopContextLoc.asStmt()))
10308f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek            TopContextLoc.markDead();
10318f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek
103214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek        rawAddEdge(NewLoc);
10338f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek      }
103414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
103514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek      return;
103614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    }
103714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
103814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    if (containsLocation(TopContextLoc, CLoc)) {
10398f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek      if (alwaysAdd) {
104014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek        rawAddEdge(NewLoc);
10411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
10424c6f8d38e2795c67048e16e737b8225eeb184262Ted Kremenek        if (IsConsumedExpr(CLoc) && !IsControlFlowExpr(CLoc.asStmt())) {
10438f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek          CLocs.push_back(ContextLocation(CLoc, true));
10448f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek          return;
10458f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek        }
10468f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek      }
10471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
104814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek      CLocs.push_back(CLoc);
10491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump      return;
105014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    }
105114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
105214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    // Context does not contain the location.  Flush it.
105314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    popLocation();
105414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  }
10551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
10565c7168cbe8a0eabd05e0e12e469090d2cabd27c0Ted Kremenek  // If we reach here, there is no enclosing context.  Just add the edge.
10575c7168cbe8a0eabd05e0e12e469090d2cabd27c0Ted Kremenek  rawAddEdge(NewLoc);
105814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek}
105914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
10608f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenekbool EdgeBuilder::IsConsumedExpr(const PathDiagnosticLocation &L) {
10618f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek  if (const Expr *X = dyn_cast_or_null<Expr>(L.asStmt()))
10628f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek    return PDB.getParentMap().isConsumedExpr(X) && !IsControlFlowExpr(X);
10631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
10648f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek  return false;
10658f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek}
10661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1067e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenekvoid EdgeBuilder::addExtendedContext(const Stmt *S) {
1068e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek  if (!S)
1069e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek    return;
10701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
10711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  const Stmt *Parent = PDB.getParent(S);
1072e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek  while (Parent) {
1073e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek    if (isa<CompoundStmt>(Parent))
1074e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek      Parent = PDB.getParent(Parent);
1075e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek    else
1076e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek      break;
1077e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek  }
1078e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek
1079e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek  if (Parent) {
1080e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek    switch (Parent->getStmtClass()) {
1081e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek      case Stmt::DoStmtClass:
1082e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek      case Stmt::ObjCAtSynchronizedStmtClass:
1083e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek        addContext(Parent);
1084e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek      default:
1085e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek        break;
1086e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek    }
1087e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek  }
10881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1089e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek  addContext(S);
1090e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek}
10911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
109214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekvoid EdgeBuilder::addContext(const Stmt *S) {
109314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  if (!S)
109414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    return;
109514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
1096220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks  PathDiagnosticLocation L(S, PDB.getSourceManager(), PDB.getLocationContext());
10971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
109814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  while (!CLocs.empty()) {
109914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    const PathDiagnosticLocation &TopContextLoc = CLocs.back();
110014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
110114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    // Is the top location context the same as the one for the new location?
110214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    if (TopContextLoc == L)
110314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek      return;
110414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
110514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    if (containsLocation(TopContextLoc, L)) {
110614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek      CLocs.push_back(L);
11071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump      return;
110814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    }
110914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
111014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    // Context does not contain the location.  Flush it.
111114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    popLocation();
111214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  }
111314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
111414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  CLocs.push_back(L);
111514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek}
111614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
111714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekstatic void GenerateExtensivePathDiagnostic(PathDiagnostic& PD,
111814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek                                            PathDiagnosticBuilder &PDB,
1119c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu                                            const ExplodedNode *N) {
112014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  EdgeBuilder EB(PD, PDB);
11210cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks  const SourceManager& SM = PDB.getSourceManager();
112214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
11239c378f705405d37f49795d5e915989de774fe11fTed Kremenek  const ExplodedNode *NextNode = N->pred_empty() ? NULL : *(N->pred_begin());
112414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  while (NextNode) {
112514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    N = NextNode;
112614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    NextNode = GetPredecessorNode(N);
112714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    ProgramPoint P = N->getLocation();
112814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
1129dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek    do {
1130dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek      // Block edges.
1131dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek      if (const BlockEdge *BE = dyn_cast<BlockEdge>(&P)) {
1132dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek        const CFGBlock &Blk = *BE->getSrc();
1133dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek        const Stmt *Term = Blk.getTerminator();
11341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1135dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek        // Are we jumping to the head of a loop?  Add a special diagnostic.
1136ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek        if (const Stmt *Loop = BE->getDst()->getLoopTarget()) {
11370cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks          PathDiagnosticLocation L(Loop, SM, PDB.getLocationContext());
1138ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek          const CompoundStmt *CS = NULL;
11391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1140ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek          if (!Term) {
1141ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek            if (const ForStmt *FS = dyn_cast<ForStmt>(Loop))
1142ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek              CS = dyn_cast<CompoundStmt>(FS->getBody());
1143ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek            else if (const WhileStmt *WS = dyn_cast<WhileStmt>(Loop))
11441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump              CS = dyn_cast<CompoundStmt>(WS->getBody());
1145ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek          }
11461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1147dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek          PathDiagnosticEventPiece *p =
1148dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek            new PathDiagnosticEventPiece(L,
114907c015cbcee31f72e2d320ba2c713c046bed42faTed Kremenek                                        "Looping back to the head of the loop");
11501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1151dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek          EB.addEdge(p->getLocation(), true);
1152dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek          PD.push_front(p);
11531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1154ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek          if (CS) {
11550cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks            PathDiagnosticLocation BL =
11560cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks              PathDiagnosticLocation::createEndBrace(CS, SM);
115707c015cbcee31f72e2d320ba2c713c046bed42faTed Kremenek            EB.addEdge(BL);
1158dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek          }
11598bd4d037d837e7922c3661d6158229da58a03887Ted Kremenek        }
11601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1161ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek        if (Term)
1162ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek          EB.addContext(Term);
11631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1164dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek        break;
11658bd4d037d837e7922c3661d6158229da58a03887Ted Kremenek      }
116614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
11671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump      if (const BlockEntrance *BE = dyn_cast<BlockEntrance>(&P)) {
11683c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek        if (const CFGStmt *S = BE->getFirstElement().getAs<CFGStmt>()) {
11693c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek          const Stmt *stmt = S->getStmt();
11703c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek          if (IsControlFlowExpr(stmt)) {
1171b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu            // Add the proper context for '&&', '||', and '?'.
11723c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek            EB.addContext(stmt);
1173b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu          }
1174b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu          else
11753c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek            EB.addExtendedContext(PDB.getEnclosingStmtLocation(stmt).asStmt());
1176dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek        }
1177b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu
1178dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek        break;
1179dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek      }
1180dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek    } while (0);
11811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1182dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek    if (!NextNode)
118314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek      continue;
11841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
11858e6431adab313e283a992698f6fc7afe62420999Anna Zaks    // Add pieces from custom visitors.
11868e6431adab313e283a992698f6fc7afe62420999Anna Zaks    BugReport *R = PDB.getBugReport();
11878e6431adab313e283a992698f6fc7afe62420999Anna Zaks    for (BugReport::visitor_iterator I = R->visitor_begin(),
11888e6431adab313e283a992698f6fc7afe62420999Anna Zaks                                     E = R->visitor_end(); I!=E; ++I) {
11898e6431adab313e283a992698f6fc7afe62420999Anna Zaks      if (PathDiagnosticPiece *p = (*I)->VisitNode(N, NextNode, PDB, *R)) {
11908966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek        const PathDiagnosticLocation &Loc = p->getLocation();
11918966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek        EB.addEdge(Loc, true);
11928966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek        PD.push_front(p);
11938966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek        if (const Stmt *S = Loc.asStmt())
11941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump          EB.addExtendedContext(PDB.getEnclosingStmtLocation(S).asStmt());
11958966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek      }
11961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    }
119714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  }
119814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek}
119914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
12005fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek//===----------------------------------------------------------------------===//
12013106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// Methods for BugType and subclasses.
12023106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===//
1203404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios KyrtzidisBugType::~BugType() { }
1204404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis
12053106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenekvoid BugType::FlushReports(BugReporter &BR) {}
12063106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
12073106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===//
12083106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// Methods for BugReport and subclasses.
12093106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===//
1210e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks
12118e6431adab313e283a992698f6fc7afe62420999Anna Zaksvoid BugReport::addVisitor(BugReporterVisitor* visitor) {
12128e6431adab313e283a992698f6fc7afe62420999Anna Zaks  if (!visitor)
12138e6431adab313e283a992698f6fc7afe62420999Anna Zaks    return;
12148e6431adab313e283a992698f6fc7afe62420999Anna Zaks
12158e6431adab313e283a992698f6fc7afe62420999Anna Zaks  llvm::FoldingSetNodeID ID;
12168e6431adab313e283a992698f6fc7afe62420999Anna Zaks  visitor->Profile(ID);
12178e6431adab313e283a992698f6fc7afe62420999Anna Zaks  void *InsertPos;
12188e6431adab313e283a992698f6fc7afe62420999Anna Zaks
12198e6431adab313e283a992698f6fc7afe62420999Anna Zaks  if (CallbacksSet.FindNodeOrInsertPos(ID, InsertPos)) {
12208e6431adab313e283a992698f6fc7afe62420999Anna Zaks    delete visitor;
12218e6431adab313e283a992698f6fc7afe62420999Anna Zaks    return;
12228e6431adab313e283a992698f6fc7afe62420999Anna Zaks  }
12238e6431adab313e283a992698f6fc7afe62420999Anna Zaks
12248e6431adab313e283a992698f6fc7afe62420999Anna Zaks  CallbacksSet.InsertNode(visitor, InsertPos);
12258e6431adab313e283a992698f6fc7afe62420999Anna Zaks  Callbacks = F.add(visitor, Callbacks);
12268e6431adab313e283a992698f6fc7afe62420999Anna Zaks}
12278e6431adab313e283a992698f6fc7afe62420999Anna Zaks
12288e6431adab313e283a992698f6fc7afe62420999Anna ZaksBugReport::~BugReport() {
12298e6431adab313e283a992698f6fc7afe62420999Anna Zaks  for (visitor_iterator I = visitor_begin(), E = visitor_end(); I != E; ++I) {
1230dc757b049796949e4b11646445a6598f0bdabd7aAnna Zaks    delete *I;
12318e6431adab313e283a992698f6fc7afe62420999Anna Zaks  }
12328e6431adab313e283a992698f6fc7afe62420999Anna Zaks}
1233e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks
1234e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaksvoid BugReport::Profile(llvm::FoldingSetNodeID& hash) const {
1235e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks  hash.AddPointer(&BT);
1236e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks  hash.AddString(Description);
1237590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks  if (Location.isValid()) {
1238590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks    Location.Profile(hash);
1239590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks  } else {
1240590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks    assert(ErrorNode);
1241590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks    hash.AddPointer(GetCurrentOrPreviousStmt(ErrorNode));
1242590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks  }
1243e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks
1244e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks  for (SmallVectorImpl<SourceRange>::const_iterator I =
1245e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks      Ranges.begin(), E = Ranges.end(); I != E; ++I) {
1246e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks    const SourceRange range = *I;
1247e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks    if (!range.isValid())
1248e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks      continue;
1249e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks    hash.AddInteger(range.getBegin().getRawEncoding());
1250e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks    hash.AddInteger(range.getEnd().getRawEncoding());
1251e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks  }
1252e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks}
12533106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
12549c378f705405d37f49795d5e915989de774fe11fTed Kremenekconst Stmt *BugReport::getStmt() const {
1255e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks  if (!ErrorNode)
1256e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks    return 0;
1257e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks
1258212f6d3b5fb3fa55ba1e40671cfc336430abc8ddTom Care  ProgramPoint ProgP = ErrorNode->getLocation();
12595f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek  const Stmt *S = NULL;
12601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
12619c378f705405d37f49795d5e915989de774fe11fTed Kremenek  if (BlockEntrance *BE = dyn_cast<BlockEntrance>(&ProgP)) {
1262fafd3834754d2093e0ad7a1c005860fd527ecb7fZhongxing Xu    CFGBlock &Exit = ProgP.getLocationContext()->getCFG()->getExit();
126350d5bc4e3b53eb8bb4ebf198f1213348a3fa0f38Zhongxing Xu    if (BE->getBlock() == &Exit)
1264212f6d3b5fb3fa55ba1e40671cfc336430abc8ddTom Care      S = GetPreviousStmt(ErrorNode);
12653106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  }
12665f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek  if (!S)
12671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    S = GetStmt(ProgP);
12681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
12691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  return S;
12703106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek}
12713106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
1272640ccf071076e684713cc3c3276bb51982bff607Argyrios Kyrtzidisstd::pair<BugReport::ranges_iterator, BugReport::ranges_iterator>
1273e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna ZaksBugReport::getRanges() {
1274e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks    // If no custom ranges, add the range of the statement corresponding to
1275e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks    // the error node.
1276e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks    if (Ranges.empty()) {
1277e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks      if (const Expr *E = dyn_cast_or_null<Expr>(getStmt()))
1278e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks        addRange(E->getSourceRange());
1279e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks      else
1280e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks        return std::make_pair(ranges_iterator(), ranges_iterator());
1281e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks    }
1282e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks
128314924267950e75c6c1f6fcea39fa507b7168bc39Anna Zaks    // User-specified absence of range info.
128414924267950e75c6c1f6fcea39fa507b7168bc39Anna Zaks    if (Ranges.size() == 1 && !Ranges.begin()->isValid())
128514924267950e75c6c1f6fcea39fa507b7168bc39Anna Zaks      return std::make_pair(ranges_iterator(), ranges_iterator());
128614924267950e75c6c1f6fcea39fa507b7168bc39Anna Zaks
1287e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks    return std::make_pair(Ranges.begin(), Ranges.end());
12883106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek}
12893106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
1290590dd8e0959d8df5621827768987c4792b74fc06Anna ZaksPathDiagnosticLocation BugReport::getLocation(const SourceManager &SM) const {
1291b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks  if (ErrorNode) {
1292590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks    assert(!Location.isValid() &&
1293b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks     "Either Location or ErrorNode should be specified but not both.");
1294b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks
12959c378f705405d37f49795d5e915989de774fe11fTed Kremenek    if (const Stmt *S = GetCurrentOrPreviousStmt(ErrorNode)) {
1296590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks      const LocationContext *LC = ErrorNode->getLocationContext();
1297590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks
12983106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      // For member expressions, return the location of the '.' or '->'.
12995b9bd2137ebef350af803c634e3fdf5d74678100Ted Kremenek      if (const MemberExpr *ME = dyn_cast<MemberExpr>(S))
1300590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks        return PathDiagnosticLocation::createMemberLoc(ME, SM);
13015b9bd2137ebef350af803c634e3fdf5d74678100Ted Kremenek      // For binary operators, return the location of the operator.
13025b9bd2137ebef350af803c634e3fdf5d74678100Ted Kremenek      if (const BinaryOperator *B = dyn_cast<BinaryOperator>(S))
1303590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks        return PathDiagnosticLocation::createOperatorLoc(B, SM);
13043106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
1305590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks      return PathDiagnosticLocation::createBegin(S, SM, LC);
13063106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    }
1307b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks  } else {
1308b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks    assert(Location.isValid());
1309b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks    return Location;
1310b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks  }
1311b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks
1312590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks  return PathDiagnosticLocation();
13133106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek}
13143106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
13153106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===//
13163106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// Methods for BugReporter and subclasses.
13173106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===//
13183106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
13193106198188ac6eb2753f1764d5c28376b0b76351Ted KremenekBugReportEquivClass::~BugReportEquivClass() {
13208966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek  for (iterator I=begin(), E=end(); I!=E; ++I) delete *I;
13213106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek}
13223106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
1323a2f4ec0df645fc249d2945beef9653f03b175417Zhongxing XuGRBugReporter::~GRBugReporter() { }
13243106198188ac6eb2753f1764d5c28376b0b76351Ted KremenekBugReporterData::~BugReporterData() {}
13253106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
132638b02b912e1a55c912f603c4369431264d36a381Zhongxing XuExplodedGraph &GRBugReporter::getGraph() { return Eng.getGraph(); }
13273106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
132818c66fdc3c4008d335885695fe36fb5353c5f672Ted KremenekProgramStateManager&
13293106198188ac6eb2753f1764d5c28376b0b76351Ted KremenekGRBugReporter::getStateManager() { return Eng.getStateManager(); }
13303106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
13313b030a28cda2b953758507769c1d436bec5ec45eAnna ZaksBugReporter::~BugReporter() {
13323b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks  FlushReports();
13333b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks
13343b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks  // Free the bug reports we are tracking.
13353b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks  typedef std::vector<BugReportEquivClass *> ContTy;
13363b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks  for (ContTy::iterator I = EQClassesVector.begin(), E = EQClassesVector.end();
13373b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks       I != E; ++I) {
13383b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks    delete *I;
13393b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks  }
13403b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks}
13413106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
13423106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenekvoid BugReporter::FlushReports() {
13433106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  if (BugTypes.isEmpty())
13443106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    return;
13453106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
13463106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // First flush the warnings for each BugType.  This may end up creating new
1347404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis  // warnings and new BugTypes.
1348404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis  // FIXME: Only NSErrorChecker needs BugType's FlushReports.
1349404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis  // Turn NSErrorChecker into a proper checker and remove this.
13505f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  SmallVector<const BugType*, 16> bugTypes;
13513106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  for (BugTypesTy::iterator I=BugTypes.begin(), E=BugTypes.end(); I!=E; ++I)
1352404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis    bugTypes.push_back(*I);
13535f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  for (SmallVector<const BugType*, 16>::iterator
1354404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis         I = bugTypes.begin(), E = bugTypes.end(); I != E; ++I)
13553106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    const_cast<BugType*>(*I)->FlushReports(*this);
13563106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
1357404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis  typedef llvm::FoldingSet<BugReportEquivClass> SetTy;
1358404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis  for (SetTy::iterator EI=EQClasses.begin(), EE=EQClasses.end(); EI!=EE;++EI){
1359404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis    BugReportEquivClass& EQ = *EI;
1360404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis    FlushReport(EQ);
13613106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  }
13623106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
1363404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis  // BugReporter owns and deletes only BugTypes created implicitly through
1364404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis  // EmitBasicReport.
1365404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis  // FIXME: There are leaks from checkers that assume that the BugTypes they
1366404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis  // create will be destroyed by the BugReporter.
1367404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis  for (llvm::StringMap<BugType*>::iterator
1368404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis         I = StrBugTypes.begin(), E = StrBugTypes.end(); I != E; ++I)
1369404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis    delete I->second;
1370404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis
13713106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // Remove all references to the BugType objects.
13723baf672378f105602d2b12f03f00277ae1936fe9Ted Kremenek  BugTypes = F.getEmptySet();
13733106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek}
13743106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
13753106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===//
13763106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// PathDiagnostics generation.
13773106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===//
13783106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
137938b02b912e1a55c912f603c4369431264d36a381Zhongxing Xustatic std::pair<std::pair<ExplodedGraph*, NodeBackMap*>,
1380c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu                 std::pair<ExplodedNode*, unsigned> >
138138b02b912e1a55c912f603c4369431264d36a381Zhongxing XuMakeReportGraph(const ExplodedGraph* G,
13825f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner                SmallVectorImpl<const ExplodedNode*> &nodes) {
13831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
13843106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // Create the trimmed graph.  It will contain the shortest paths from the
13851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  // error nodes to the root.  In the new graph we should only have one
13863106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // error node unless there are two or more error nodes with the same minimum
13873106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // path length.
138838b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu  ExplodedGraph* GTrim;
1389c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu  InterExplodedGraphMap* NMap;
13903106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
13913106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  llvm::DenseMap<const void*, const void*> InverseMap;
139240406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  llvm::tie(GTrim, NMap) = G->Trim(nodes.data(), nodes.data() + nodes.size(),
139340406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek                                   &InverseMap);
13941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
13953106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // Create owning pointers for GTrim and NMap just to ensure that they are
13963106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // released when this function exists.
139738b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu  llvm::OwningPtr<ExplodedGraph> AutoReleaseGTrim(GTrim);
1398c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu  llvm::OwningPtr<InterExplodedGraphMap> AutoReleaseNMap(NMap);
13991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
14003106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // Find the (first) error node in the trimmed graph.  We just need to consult
14013106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // the node map (NMap) which maps from nodes in the original graph to nodes
14023106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // in the new graph.
1403938332c657390d1e782e0adc03b092993edae962Ted Kremenek
1404c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu  std::queue<const ExplodedNode*> WS;
140538b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu  typedef llvm::DenseMap<const ExplodedNode*, unsigned> IndexMapTy;
1406938332c657390d1e782e0adc03b092993edae962Ted Kremenek  IndexMapTy IndexMap;
14073106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
140840406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  for (unsigned nodeIndex = 0 ; nodeIndex < nodes.size(); ++nodeIndex) {
140940406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek    const ExplodedNode *originalNode = nodes[nodeIndex];
141040406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek    if (const ExplodedNode *N = NMap->getMappedNode(originalNode)) {
1411938332c657390d1e782e0adc03b092993edae962Ted Kremenek      WS.push(N);
141240406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek      IndexMap[originalNode] = nodeIndex;
14133106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    }
141440406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  }
14151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1416938332c657390d1e782e0adc03b092993edae962Ted Kremenek  assert(!WS.empty() && "No error node found in the trimmed graph.");
14173106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
14183106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // Create a new (third!) graph with a single path.  This is the graph
14193106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // that will be returned to the caller.
1420c77a55126fcad66fb086f8e100a494caa2496a2dZhongxing Xu  ExplodedGraph *GNew = new ExplodedGraph();
14211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
14223106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // Sometimes the trimmed graph can contain a cycle.  Perform a reverse BFS
14233106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // to the root node, and then construct a new graph that contains only
14243106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // a single path.
14253106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  llvm::DenseMap<const void*,unsigned> Visited;
14261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
14273106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  unsigned cnt = 0;
14289c378f705405d37f49795d5e915989de774fe11fTed Kremenek  const ExplodedNode *Root = 0;
14291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
14303106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  while (!WS.empty()) {
14319c378f705405d37f49795d5e915989de774fe11fTed Kremenek    const ExplodedNode *Node = WS.front();
14323106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    WS.pop();
14331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
14343106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    if (Visited.find(Node) != Visited.end())
14353106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      continue;
14361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
14373106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    Visited[Node] = cnt++;
14381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
14393106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    if (Node->pred_empty()) {
14403106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      Root = Node;
14413106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      break;
14423106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    }
14431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1444c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu    for (ExplodedNode::const_pred_iterator I=Node->pred_begin(),
14453106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek         E=Node->pred_end(); I!=E; ++I)
14463106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      WS.push(*I);
14473106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  }
14481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1449938332c657390d1e782e0adc03b092993edae962Ted Kremenek  assert(Root);
14501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
14513106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // Now walk from the root down the BFS path, always taking the successor
14523106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // with the lowest number.
14531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  ExplodedNode *Last = 0, *First = 0;
14543106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  NodeBackMap *BM = new NodeBackMap();
1455938332c657390d1e782e0adc03b092993edae962Ted Kremenek  unsigned NodeIndex = 0;
14561eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1457c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu  for ( const ExplodedNode *N = Root ;;) {
14583106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // Lookup the number associated with the current node.
14593106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    llvm::DenseMap<const void*,unsigned>::iterator I = Visited.find(N);
1460938332c657390d1e782e0adc03b092993edae962Ted Kremenek    assert(I != Visited.end());
14611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
14623106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // Create the equivalent node in the new graph with the same state
14633106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // and location.
14649c378f705405d37f49795d5e915989de774fe11fTed Kremenek    ExplodedNode *NewN = GNew->getNode(N->getLocation(), N->getState());
14651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
14663106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // Store the mapping to the original node.
14673106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    llvm::DenseMap<const void*, const void*>::iterator IMitr=InverseMap.find(N);
14683106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    assert(IMitr != InverseMap.end() && "No mapping to original node.");
1469c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu    (*BM)[NewN] = (const ExplodedNode*) IMitr->second;
14701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
14713106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // Link up the new node with the previous node.
14723106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    if (Last)
14735fe4d9deb543a19f557e3d85c5f33867af97cd96Ted Kremenek      NewN->addPredecessor(Last, *GNew);
14741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
14753106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    Last = NewN;
14761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
14773106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // Are we at the final node?
1478938332c657390d1e782e0adc03b092993edae962Ted Kremenek    IndexMapTy::iterator IMI =
1479c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu      IndexMap.find((const ExplodedNode*)(IMitr->second));
1480938332c657390d1e782e0adc03b092993edae962Ted Kremenek    if (IMI != IndexMap.end()) {
14813106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      First = NewN;
1482938332c657390d1e782e0adc03b092993edae962Ted Kremenek      NodeIndex = IMI->second;
14833106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      break;
14843106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    }
14851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
14863106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // Find the next successor node.  We choose the node that is marked
14873106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // with the lowest DFS number.
1488c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu    ExplodedNode::const_succ_iterator SI = N->succ_begin();
1489c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu    ExplodedNode::const_succ_iterator SE = N->succ_end();
14903106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    N = 0;
14911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
14923106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    for (unsigned MinVal = 0; SI != SE; ++SI) {
14931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
14943106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      I = Visited.find(*SI);
14951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
14963106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      if (I == Visited.end())
14973106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        continue;
14981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
14993106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      if (!N || I->second < MinVal) {
15003106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        N = *SI;
15013106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        MinVal = I->second;
15023106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      }
15033106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    }
15041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1505938332c657390d1e782e0adc03b092993edae962Ted Kremenek    assert(N);
15063106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  }
15071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1508938332c657390d1e782e0adc03b092993edae962Ted Kremenek  assert(First);
1509938332c657390d1e782e0adc03b092993edae962Ted Kremenek
15103106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  return std::make_pair(std::make_pair(GNew, BM),
15113106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek                        std::make_pair(First, NodeIndex));
15123106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek}
1513d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek
15143106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek/// CompactPathDiagnostic - This function postprocesses a PathDiagnostic object
15153106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek///  and collapses PathDiagosticPieces that are expanded by macros.
15163106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenekstatic void CompactPathDiagnostic(PathDiagnostic &PD, const SourceManager& SM) {
15173106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  typedef std::vector<std::pair<PathDiagnosticMacroPiece*, SourceLocation> >
15183106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek          MacroStackTy;
15191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
15203106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  typedef std::vector<PathDiagnosticPiece*>
15213106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek          PiecesTy;
15221eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
15233106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  MacroStackTy MacroStack;
15243106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  PiecesTy Pieces;
15251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
15263106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  for (PathDiagnostic::iterator I = PD.begin(), E = PD.end(); I!=E; ++I) {
15273106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // Get the location of the PathDiagnosticPiece.
15281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    const FullSourceLoc Loc = I->getLocation().asLocation();
15291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
15303106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // Determine the instantiation location, which is the location we group
15313106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // related PathDiagnosticPieces.
15321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    SourceLocation InstantiationLoc = Loc.isMacroID() ?
1533402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth                                      SM.getExpansionLoc(Loc) :
15343106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek                                      SourceLocation();
15351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
15363106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    if (Loc.isFileID()) {
15373106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      MacroStack.clear();
15383106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      Pieces.push_back(&*I);
15393106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      continue;
15403106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    }
1541706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek
15423106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    assert(Loc.isMacroID());
15431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
15443106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // Is the PathDiagnosticPiece within the same macro group?
15453106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    if (!MacroStack.empty() && InstantiationLoc == MacroStack.back().second) {
15463106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      MacroStack.back().first->push_back(&*I);
15473106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      continue;
15483106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    }
1549d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek
15503106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // We aren't in the same group.  Are we descending into a new macro
15513106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // or are part of an old one?
15523106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    PathDiagnosticMacroPiece *MacroGroup = 0;
1553d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek
15543106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    SourceLocation ParentInstantiationLoc = InstantiationLoc.isMacroID() ?
1555402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth                                          SM.getExpansionLoc(Loc) :
15563106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek                                          SourceLocation();
15571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
15583106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // Walk the entire macro stack.
15593106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    while (!MacroStack.empty()) {
15603106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      if (InstantiationLoc == MacroStack.back().second) {
15613106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        MacroGroup = MacroStack.back().first;
15623106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        break;
15633106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      }
15641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
15653106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      if (ParentInstantiationLoc == MacroStack.back().second) {
15663106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        MacroGroup = MacroStack.back().first;
15673106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        break;
156861f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek      }
15691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
15703106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      MacroStack.pop_back();
15716837faa083bebad39aa342f84c2b450fb6410eafTed Kremenek    }
15721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
15733106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    if (!MacroGroup || ParentInstantiationLoc == MacroStack.back().second) {
15743106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      // Create a new macro group and add it to the stack.
1575590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks      PathDiagnosticMacroPiece *NewGroup =
1576590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks        new PathDiagnosticMacroPiece(
1577590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks          PathDiagnosticLocation::createSingleLocation(I->getLocation()));
15785a429954aedd8a830a70fcea2cb51561673e4fc3Ted Kremenek
15793106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      if (MacroGroup)
15803106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        MacroGroup->push_back(NewGroup);
15813106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      else {
15823106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        assert(InstantiationLoc.isFileID());
15833106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        Pieces.push_back(NewGroup);
15843106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      }
15851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
15863106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      MacroGroup = NewGroup;
15873106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      MacroStack.push_back(std::make_pair(MacroGroup, InstantiationLoc));
15887dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek    }
15893106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
15903106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // Finally, add the PathDiagnosticPiece to the group.
15913106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    MacroGroup->push_back(&*I);
15923106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  }
15931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
15943106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // Now take the pieces and construct a new PathDiagnostic.
15953106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  PD.resetPath(false);
15961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
15973106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  for (PiecesTy::iterator I=Pieces.begin(), E=Pieces.end(); I!=E; ++I) {
15983106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    if (PathDiagnosticMacroPiece *MP=dyn_cast<PathDiagnosticMacroPiece>(*I))
15993106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      if (!MP->containsEvent()) {
16003106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        delete MP;
16013106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        continue;
16023106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      }
16031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
16043106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    PD.push_back(*I);
160561f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek  }
160661f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek}
160761f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek
16083106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenekvoid GRBugReporter::GeneratePathDiagnostic(PathDiagnostic& PD,
16095f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner                        SmallVectorImpl<BugReport *> &bugReports) {
16101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
161140406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  assert(!bugReports.empty());
16125f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  SmallVector<const ExplodedNode *, 10> errorNodes;
16135f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  for (SmallVectorImpl<BugReport*>::iterator I = bugReports.begin(),
161440406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek    E = bugReports.end(); I != E; ++I) {
161540406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek      errorNodes.push_back((*I)->getErrorNode());
161640406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  }
16171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
16183106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // Construct a new graph that contains only a single path from the error
16191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  // node to a root.
162038b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu  const std::pair<std::pair<ExplodedGraph*, NodeBackMap*>,
1621c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu  std::pair<ExplodedNode*, unsigned> >&
162240406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek    GPair = MakeReportGraph(&getGraph(), errorNodes);
16231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
16243106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // Find the BugReport with the original location.
162540406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  assert(GPair.second.second < bugReports.size());
162640406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  BugReport *R = bugReports[GPair.second.second];
16273106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  assert(R && "No original report found for sliced graph.");
16281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
162938b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu  llvm::OwningPtr<ExplodedGraph> ReportGraph(GPair.first.first);
16303106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  llvm::OwningPtr<NodeBackMap> BackMap(GPair.first.second);
1631c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu  const ExplodedNode *N = GPair.second.first;
16321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
16331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  // Start building the path diagnostic...
1634ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie  PathDiagnosticBuilder PDB(*this, R, BackMap.get(),
1635ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie                            getPathDiagnosticConsumer());
16361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
16378e6431adab313e283a992698f6fc7afe62420999Anna Zaks  // Register additional node visitors.
163850bbc165b063155cc23c360deb7b865502e068e2Anna Zaks  R->addVisitor(new NilReceiverBRVisitor());
163950bbc165b063155cc23c360deb7b865502e068e2Anna Zaks  R->addVisitor(new ConditionBRVisitor());
16401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
164123f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks  // Generate the very last diagnostic piece - the piece is visible before
164223f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks  // the trace is expanded.
164323f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks  PathDiagnosticPiece *LastPiece = 0;
164423f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks  for (BugReport::visitor_iterator I = R->visitor_begin(),
164523f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks                                   E = R->visitor_end(); I!=E; ++I) {
164623f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks    if (PathDiagnosticPiece *Piece = (*I)->getEndPath(PDB, N, *R)) {
164723f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks      assert (!LastPiece &&
164823f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks              "There can only be one final piece in a diagnostic.");
164923f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks      LastPiece = Piece;
165023f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks    }
165123f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks  }
165223f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks  if (!LastPiece)
165323f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks    LastPiece = BugReporterVisitor::getDefaultEndPath(PDB, N, *R);
165423f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks  if (LastPiece)
165523f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks    PD.push_back(LastPiece);
165623f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks  else
165723f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks    return;
165823f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks
16593106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  switch (PDB.getGenerationScheme()) {
1660ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie    case PathDiagnosticConsumer::Extensive:
16618966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek      GenerateExtensivePathDiagnostic(PD, PDB, N);
16625fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek      break;
1663ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie    case PathDiagnosticConsumer::Minimal:
16643106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      GenerateMinimalPathDiagnostic(PD, PDB, N);
16653106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      break;
16663106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  }
16673106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek}
16681aa44c7c9198796085b77c6bdd7c90030845a688Ted Kremenek
1669cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenekvoid BugReporter::Register(BugType *BT) {
16703baf672378f105602d2b12f03f00277ae1936fe9Ted Kremenek  BugTypes = F.add(BugTypes, BT);
167176d90c8bf83d071fd1bdbffa6d9f2af87c6bb7b5Ted Kremenek}
167276d90c8bf83d071fd1bdbffa6d9f2af87c6bb7b5Ted Kremenek
16731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpvoid BugReporter::EmitReport(BugReport* R) {
1674cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  // Compute the bug report's hash to determine its equivalence class.
1675cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  llvm::FoldingSetNodeID ID;
1676cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  R->Profile(ID);
16771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
16781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  // Lookup the equivance class.  If there isn't one, create it.
1679cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  BugType& BT = R->getBugType();
1680cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  Register(&BT);
1681cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  void *InsertPos;
1682404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis  BugReportEquivClass* EQ = EQClasses.FindNodeOrInsertPos(ID, InsertPos);
16831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1684cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  if (!EQ) {
1685cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek    EQ = new BugReportEquivClass(R);
1686404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis    EQClasses.InsertNode(EQ, InsertPos);
16873b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks    EQClassesVector.push_back(EQ);
1688cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  }
1689cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  else
1690cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek    EQ->AddReport(R);
169161f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek}
169261f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek
169306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek
169406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek//===----------------------------------------------------------------------===//
169506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek// Emitting reports in equivalence classes.
169606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek//===----------------------------------------------------------------------===//
169706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek
169806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremeneknamespace {
1699ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamstruct FRIEC_WLItem {
170006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek  const ExplodedNode *N;
170106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek  ExplodedNode::const_succ_iterator I, E;
170206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek
170306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek  FRIEC_WLItem(const ExplodedNode *n)
170406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek  : N(n), I(N->succ_begin()), E(N->succ_end()) {}
170506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek};
170606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek}
170706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek
170861f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenekstatic BugReport *
170961f52bd3c524268e25b48a1ed3730aedd6cc8374Ted KremenekFindReportInEquivalenceClass(BugReportEquivClass& EQ,
17105f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner                             SmallVectorImpl<BugReport*> &bugReports) {
171161f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek
171206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek  BugReportEquivClass::iterator I = EQ.begin(), E = EQ.end();
171306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek  assert(I != E);
171406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek  BugReport *R = *I;
171506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek  BugType& BT = R->getBugType();
171661f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek
171740406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  // If we don't need to suppress any of the nodes because they are
171840406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  // post-dominated by a sink, simply add all the nodes in the equivalence class
171940406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  // to 'Nodes'.  Any of the reports will serve as a "representative" report.
172061f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek  if (!BT.isSuppressOnSink()) {
172161f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek    for (BugReportEquivClass::iterator I=EQ.begin(), E=EQ.end(); I!=E; ++I) {
17229c378f705405d37f49795d5e915989de774fe11fTed Kremenek      const ExplodedNode *N = I->getErrorNode();
172361f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek      if (N) {
172461f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek        R = *I;
172540406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek        bugReports.push_back(R);
172661f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek      }
172761f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek    }
172806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek    return R;
172961f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek  }
173061f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek
173106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek  // For bug reports that should be suppressed when all paths are post-dominated
173206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek  // by a sink node, iterate through the reports in the equivalence class
173306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek  // until we find one that isn't post-dominated (if one exists).  We use a
173406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek  // DFS traversal of the ExplodedGraph to find a non-sink node.  We could write
173506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek  // this as a recursive function, but we don't want to risk blowing out the
173606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek  // stack for very long paths.
173740406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  BugReport *exampleReport = 0;
173861f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek
173906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek  for (; I != E; ++I) {
174006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek    R = *I;
174140406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek    const ExplodedNode *errorNode = R->getErrorNode();
174206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek
174340406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek    if (!errorNode)
174406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek      continue;
174540406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek    if (errorNode->isSink()) {
1746b219cfc4d75f0a03630b7c4509ef791b7e97b2c8David Blaikie      llvm_unreachable(
174706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek           "BugType::isSuppressSink() should not be 'true' for sink end nodes");
174806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek    }
174961f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek    // No successors?  By definition this nodes isn't post-dominated by a sink.
175040406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek    if (errorNode->succ_empty()) {
175140406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek      bugReports.push_back(R);
175240406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek      if (!exampleReport)
175340406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek        exampleReport = R;
175461f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek      continue;
175561f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek    }
175661f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek
175706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek    // At this point we know that 'N' is not a sink and it has at least one
175806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek    // successor.  Use a DFS worklist to find a non-sink end-of-path node.
175906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek    typedef FRIEC_WLItem WLItem;
17605f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner    typedef SmallVector<WLItem, 10> DFSWorkList;
176106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek    llvm::DenseMap<const ExplodedNode *, unsigned> Visited;
176206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek
176306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek    DFSWorkList WL;
176440406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek    WL.push_back(errorNode);
176540406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek    Visited[errorNode] = 1;
176606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek
176706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek    while (!WL.empty()) {
176806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek      WLItem &WI = WL.back();
176906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek      assert(!WI.N->succ_empty());
177006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek
177106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek      for (; WI.I != WI.E; ++WI.I) {
177206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek        const ExplodedNode *Succ = *WI.I;
177306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek        // End-of-path node?
177406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek        if (Succ->succ_empty()) {
177561f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek          // If we found an end-of-path node that is not a sink.
177661f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek          if (!Succ->isSink()) {
177740406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek            bugReports.push_back(R);
177840406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek            if (!exampleReport)
177940406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek              exampleReport = R;
178061f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek            WL.clear();
178161f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek            break;
178261f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek          }
178306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek          // Found a sink?  Continue on to the next successor.
178406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek          continue;
178506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek        }
178606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek        // Mark the successor as visited.  If it hasn't been explored,
178706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek        // enqueue it to the DFS worklist.
178806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek        unsigned &mark = Visited[Succ];
178906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek        if (!mark) {
179006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek          mark = 1;
179106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek          WL.push_back(Succ);
179206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek          break;
179306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek        }
179406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek      }
179561f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek
179661f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek      // The worklist may have been cleared at this point.  First
179761f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek      // check if it is empty before checking the last item.
179861f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek      if (!WL.empty() && &WL.back() == &WI)
179906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek        WL.pop_back();
180006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek    }
180106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek  }
180206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek
180361f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek  // ExampleReport will be NULL if all the nodes in the equivalence class
180461f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek  // were post-dominated by sinks.
180540406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  return exampleReport;
180661f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek}
1807e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek
1808e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek//===----------------------------------------------------------------------===//
1809e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek// DiagnosticCache.  This is a hack to cache analyzer diagnostics.  It
1810e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek// uses global state, which eventually should go elsewhere.
1811e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek//===----------------------------------------------------------------------===//
1812e0a58073b76fc016325a35152533b8468df2bf4aTed Kremeneknamespace {
1813ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass DiagCacheItem : public llvm::FoldingSetNode {
1814e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek  llvm::FoldingSetNodeID ID;
1815e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenekpublic:
1816e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek  DiagCacheItem(BugReport *R, PathDiagnostic *PD) {
18174522e2a9e7fa0313e8e5a388d8f0ab66feccc6afAnna Zaks    R->Profile(ID);
18184522e2a9e7fa0313e8e5a388d8f0ab66feccc6afAnna Zaks    PD->Profile(ID);
1819e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek  }
1820e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek
1821e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek  void Profile(llvm::FoldingSetNodeID &id) {
1822e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek    id = ID;
1823e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek  }
1824e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek
1825e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek  llvm::FoldingSetNodeID &getID() { return ID; }
1826e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek};
1827e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek}
1828e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek
1829e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenekstatic bool IsCachedDiagnostic(BugReport *R, PathDiagnostic *PD) {
1830e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek  // FIXME: Eventually this diagnostic cache should reside in something
1831e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek  // like AnalysisManager instead of being a static variable.  This is
1832e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek  // really unsafe in the long term.
1833e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek  typedef llvm::FoldingSet<DiagCacheItem> DiagnosticCache;
1834e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek  static DiagnosticCache DC;
1835e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek
1836e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek  void *InsertPos;
1837e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek  DiagCacheItem *Item = new DiagCacheItem(R, PD);
1838e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek
1839e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek  if (DC.FindNodeOrInsertPos(Item->getID(), InsertPos)) {
1840e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek    delete Item;
1841e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek    return true;
1842e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek  }
1843e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek
1844e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek  DC.InsertNode(Item, InsertPos);
1845e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek  return false;
1846e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek}
1847e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek
1848cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenekvoid BugReporter::FlushReport(BugReportEquivClass& EQ) {
18495f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  SmallVector<BugReport*, 10> bugReports;
185040406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  BugReport *exampleReport = FindReportInEquivalenceClass(EQ, bugReports);
185140406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  if (!exampleReport)
185206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek    return;
185306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek
1854ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie  PathDiagnosticConsumer* PD = getPathDiagnosticConsumer();
18551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1856cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  // FIXME: Make sure we use the 'R' for the path that was actually used.
18571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  // Probably doesn't make a difference in practice.
185840406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  BugType& BT = exampleReport->getBugType();
18591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1860d49967f8764135ae65658e354b6d38e3637c9de3Ted Kremenek  llvm::OwningPtr<PathDiagnostic>
186140406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek    D(new PathDiagnostic(exampleReport->getBugType().getName(),
1862da0e8429a3598acfdd0ecf15135d432e4dd3517cTed Kremenek                         !PD || PD->useVerboseDescription()
186340406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek                         ? exampleReport->getDescription()
186440406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek                         : exampleReport->getShortDescription(),
1865d49967f8764135ae65658e354b6d38e3637c9de3Ted Kremenek                         BT.getCategory()));
1866d49967f8764135ae65658e354b6d38e3637c9de3Ted Kremenek
186740406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  if (!bugReports.empty())
186840406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek    GeneratePathDiagnostic(*D.get(), bugReports);
18691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
187040406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  if (IsCachedDiagnostic(exampleReport, D.get()))
1871e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek    return;
1872e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek
1873072192bcbb05a0fee7ec3061750b27e8d2004952Ted Kremenek  // Get the meta data.
18747f2531cb41448852ec78de90fc1d3c0149c95d7dAnna Zaks  const BugReport::ExtraTextList &Meta =
18757f2531cb41448852ec78de90fc1d3c0149c95d7dAnna Zaks                                  exampleReport->getExtraText();
18767f2531cb41448852ec78de90fc1d3c0149c95d7dAnna Zaks  for (BugReport::ExtraTextList::const_iterator i = Meta.begin(),
18777f2531cb41448852ec78de90fc1d3c0149c95d7dAnna Zaks                                                e = Meta.end(); i != e; ++i) {
18787f2531cb41448852ec78de90fc1d3c0149c95d7dAnna Zaks    D->addMeta(*i);
18797f2531cb41448852ec78de90fc1d3c0149c95d7dAnna Zaks  }
188075840e1501563fe7c3dcb5600b75965ba1fe1bc4Ted Kremenek
18813148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek  // Emit a summary diagnostic to the regular Diagnostics engine.
1882640ccf071076e684713cc3c3276bb51982bff607Argyrios Kyrtzidis  BugReport::ranges_iterator Beg, End;
1883640ccf071076e684713cc3c3276bb51982bff607Argyrios Kyrtzidis  llvm::tie(Beg, End) = exampleReport->getRanges();
1884d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie  DiagnosticsEngine &Diag = getDiagnostic();
1885c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek
1886c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek  // Search the description for '%', as that will be interpretted as a
1887c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek  // format character by FormatDiagnostics.
18885f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  StringRef desc = exampleReport->getShortDescription();
1889c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek  unsigned ErrorDiag;
1890c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek  {
1891c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek    llvm::SmallString<512> TmpStr;
1892c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek    llvm::raw_svector_ostream Out(TmpStr);
18935f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner    for (StringRef::iterator I=desc.begin(), E=desc.end(); I!=E; ++I)
1894c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek      if (*I == '%')
1895c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek        Out << "%%";
1896c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek      else
1897c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek        Out << *I;
1898c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek
1899c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek    Out.flush();
1900d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie    ErrorDiag = Diag.getCustomDiagID(DiagnosticsEngine::Warning, TmpStr);
1901c213b48206c55ca0eb1387cfa1651de504f147d1Ted Kremenek  }
19020a14eee528a901c16f0e288fbc10a3abc1660d87Chris Lattner
1903b6b7e7bff3101062521de6e79533a3c25e2195d9Argyrios Kyrtzidis  {
1904590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks    DiagnosticBuilder diagBuilder = Diag.Report(
1905590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks      exampleReport->getLocation(getSourceManager()).asLocation(), ErrorDiag);
1906640ccf071076e684713cc3c3276bb51982bff607Argyrios Kyrtzidis    for (BugReport::ranges_iterator I = Beg; I != End; ++I)
1907b6b7e7bff3101062521de6e79533a3c25e2195d9Argyrios Kyrtzidis      diagBuilder << *I;
19082f0e89ea96292d2974eb1a7dddc0e9870aa86bb7Ted Kremenek  }
19093148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek
1910ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie  // Emit a full diagnostic for the path if we have a PathDiagnosticConsumer.
19113148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek  if (!PD)
19123148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek    return;
19131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
19141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  if (D->empty()) {
1915590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks    PathDiagnosticPiece *piece = new PathDiagnosticEventPiece(
1916590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks                                 exampleReport->getLocation(getSourceManager()),
1917590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks                                 exampleReport->getDescription());
19181fbfd5b9b8b82aea084773b76dd1ec6796a7000cTed Kremenek
19193148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek    for ( ; Beg != End; ++Beg) piece->addRange(*Beg);
19203148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek    D->push_back(piece);
19213148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek  }
19221eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
19233148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek  PD->HandlePathDiagnostic(D.take());
192461f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek}
192557202071e477530e9348bc76671ee369b2399b92Ted Kremenek
19265f9e272e632e951b1efe824cd16acb4d96077930Chris Lattnervoid BugReporter::EmitBasicReport(StringRef name, StringRef str,
1927590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks                                  PathDiagnosticLocation Loc,
19288c036c7f77d69f96df49219ed0bdbade200d52ebTed Kremenek                                  SourceRange* RBeg, unsigned NumRanges) {
19298c036c7f77d69f96df49219ed0bdbade200d52ebTed Kremenek  EmitBasicReport(name, "", str, Loc, RBeg, NumRanges);
19308c036c7f77d69f96df49219ed0bdbade200d52ebTed Kremenek}
1931cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek
19325f9e272e632e951b1efe824cd16acb4d96077930Chris Lattnervoid BugReporter::EmitBasicReport(StringRef name,
19335f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner                                  StringRef category,
1934590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks                                  StringRef str, PathDiagnosticLocation Loc,
19358c036c7f77d69f96df49219ed0bdbade200d52ebTed Kremenek                                  SourceRange* RBeg, unsigned NumRanges) {
19361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1937404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis  // 'BT' is owned by BugReporter.
1938404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis  BugType *BT = getBugTypeForName(name, category);
1939590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks  BugReport *R = new BugReport(*BT, str, Loc);
1940cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  for ( ; NumRanges > 0 ; --NumRanges, ++RBeg) R->addRange(*RBeg);
1941cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  EmitReport(R);
1942cabe66811fe43835b8c5a0854552768fc53261e3Ted Kremenek}
1943404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis
19445f9e272e632e951b1efe824cd16acb4d96077930Chris LattnerBugType *BugReporter::getBugTypeForName(StringRef name,
19455f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner                                        StringRef category) {
1946404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis  llvm::SmallString<136> fullDesc;
1947404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis  llvm::raw_svector_ostream(fullDesc) << name << ":" << category;
1948404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis  llvm::StringMapEntry<BugType *> &
1949404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis      entry = StrBugTypes.GetOrCreateValue(fullDesc);
1950404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis  BugType *BT = entry.getValue();
1951404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis  if (!BT) {
1952404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis    BT = new BugType(name, category);
1953404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis    entry.setValue(BT);
1954404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis  }
1955404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis  return BT;
1956404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis}
1957