BugReporter.cpp revision a5f80b2ea6d30c5055c067530d63bb0dcaf937d0
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
15cc08ca9b3cd2b715a699bcc772ce2e83a502915aJordan Rose#define DEBUG_TYPE "BugReporter"
16cc08ca9b3cd2b715a699bcc772ce2e83a502915aJordan Rose
179b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
1861f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek#include "clang/AST/ASTContext.h"
19c35fb7d67d515659ad2325b4f6ec97c9fe64fb63Benjamin Kramer#include "clang/AST/DeclObjC.h"
2061f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek#include "clang/AST/Expr.h"
2100605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek#include "clang/AST/ParentMap.h"
2216f0049415ec596504891259e2a83e19871c0d52Chris Lattner#include "clang/AST/StmtObjC.h"
2355fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Analysis/CFG.h"
2461f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek#include "clang/Analysis/ProgramPoint.h"
2555fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Basic/SourceManager.h"
2655fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
279b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
2855fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
29331b0ac44b9eb0ffcba66b4f3f3f9adb27c2434fTed Kremenek#include "llvm/ADT/DenseMap.h"
30802e02463b880f53a6e645bde78cc412481ce9e0Ted Kremenek#include "llvm/ADT/IntrusiveRefCntPtr.h"
3155fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "llvm/ADT/OwningPtr.h"
3255fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "llvm/ADT/STLExtras.h"
3355fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "llvm/ADT/SmallString.h"
34cc08ca9b3cd2b715a699bcc772ce2e83a502915aJordan Rose#include "llvm/ADT/Statistic.h"
3555fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "llvm/Support/raw_ostream.h"
3610aa55410bbecbb658ce14a5f801d50cf06d12dfTed Kremenek#include <queue>
3761f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek
3861f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenekusing namespace clang;
399ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremenekusing namespace ento;
4061f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek
41cc08ca9b3cd2b715a699bcc772ce2e83a502915aJordan RoseSTATISTIC(MaxBugClassSize,
42cc08ca9b3cd2b715a699bcc772ce2e83a502915aJordan Rose          "The maximum number of bug reports in the same equivalence class");
43cc08ca9b3cd2b715a699bcc772ce2e83a502915aJordan RoseSTATISTIC(MaxValidBugClassSize,
44cc08ca9b3cd2b715a699bcc772ce2e83a502915aJordan Rose          "The maximum number of bug reports in the same equivalence class "
45cc08ca9b3cd2b715a699bcc772ce2e83a502915aJordan Rose          "where at least one report is valid (not suppressed)");
46cc08ca9b3cd2b715a699bcc772ce2e83a502915aJordan Rose
478966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed KremenekBugReporterVisitor::~BugReporterVisitor() {}
481b431023814196f87515a540ebcb9e9f1a9176a1Ted Kremenek
4999ba9e3bd70671f3441fb974895f226a83ce0e66David Blaikievoid BugReporterContext::anchor() {}
5099ba9e3bd70671f3441fb974895f226a83ce0e66David Blaikie
51cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek//===----------------------------------------------------------------------===//
523106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// Helper routines for walking the ExplodedGraph and fetching statements.
53cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek//===----------------------------------------------------------------------===//
5461f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek
559c378f705405d37f49795d5e915989de774fe11fTed Kremenekstatic inline const Stmt *GetStmt(const ProgramPoint &P) {
567a95de68c093991047ed8d339479ccad51b88663David Blaikie  if (Optional<StmtPoint> SP = P.getAs<StmtPoint>())
57592362b46ad69db0db0988e7f9d8cbe647510bddTed Kremenek    return SP->getStmt();
587a95de68c093991047ed8d339479ccad51b88663David Blaikie  if (Optional<BlockEdge> BE = P.getAs<BlockEdge>())
5961f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek    return BE->getSrc()->getTerminator();
607a95de68c093991047ed8d339479ccad51b88663David Blaikie  if (Optional<CallEnter> CE = P.getAs<CallEnter>())
61852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose    return CE->getCallExpr();
627a95de68c093991047ed8d339479ccad51b88663David Blaikie  if (Optional<CallExitEnd> CEE = P.getAs<CallExitEnd>())
63852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose    return CEE->getCalleeContext()->getCallSite();
641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
65b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek  return 0;
6661f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek}
6761f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek
68c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xustatic inline const ExplodedNode*
699c378f705405d37f49795d5e915989de774fe11fTed KremenekGetPredecessorNode(const ExplodedNode *N) {
70b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek  return N->pred_empty() ? NULL : *(N->pred_begin());
71706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek}
72706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek
73c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xustatic inline const ExplodedNode*
749c378f705405d37f49795d5e915989de774fe11fTed KremenekGetSuccessorNode(const ExplodedNode *N) {
75b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek  return N->succ_empty() ? NULL : *(N->succ_begin());
76bd7efa8ca27ed9676acf00abf31d5e1cd54651ccTed Kremenek}
772673c9ff76ebdb72b7f846e2ff1e0f4256372e19Ted Kremenek
789c378f705405d37f49795d5e915989de774fe11fTed Kremenekstatic const Stmt *GetPreviousStmt(const ExplodedNode *N) {
79b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek  for (N = GetPredecessorNode(N); N; N = GetPredecessorNode(N))
805f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek    if (const Stmt *S = GetStmt(N->getLocation()))
81b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek      return S;
821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
83b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek  return 0;
84b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek}
85b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek
869c378f705405d37f49795d5e915989de774fe11fTed Kremenekstatic const Stmt *GetNextStmt(const ExplodedNode *N) {
87b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek  for (N = GetSuccessorNode(N); N; N = GetSuccessorNode(N))
885f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek    if (const Stmt *S = GetStmt(N->getLocation())) {
89f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek      // Check if the statement is '?' or '&&'/'||'.  These are "merges",
90f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek      // not actual statement points.
91f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek      switch (S->getStmtClass()) {
92f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek        case Stmt::ChooseExprClass:
9356ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall        case Stmt::BinaryConditionalOperatorClass: continue;
94f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek        case Stmt::ConditionalOperatorClass: continue;
95f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek        case Stmt::BinaryOperatorClass: {
962de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall          BinaryOperatorKind Op = cast<BinaryOperator>(S)->getOpcode();
972de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall          if (Op == BO_LAnd || Op == BO_LOr)
98f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek            continue;
99f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek          break;
100f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek        }
101f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek        default:
102f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek          break;
103f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek      }
104b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek      return S;
105f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek    }
1061eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
107b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek  return 0;
108bd7efa8ca27ed9676acf00abf31d5e1cd54651ccTed Kremenek}
109bd7efa8ca27ed9676acf00abf31d5e1cd54651ccTed Kremenek
1105f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenekstatic inline const Stmt*
1119c378f705405d37f49795d5e915989de774fe11fTed KremenekGetCurrentOrPreviousStmt(const ExplodedNode *N) {
1125f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek  if (const Stmt *S = GetStmt(N->getLocation()))
113b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek    return S;
1141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
115b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek  return GetPreviousStmt(N);
116b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek}
1171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1185f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenekstatic inline const Stmt*
1199c378f705405d37f49795d5e915989de774fe11fTed KremenekGetCurrentOrNextStmt(const ExplodedNode *N) {
1205f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek  if (const Stmt *S = GetStmt(N->getLocation()))
121b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek    return S;
1221eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
123b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek  return GetNextStmt(N);
1243148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek}
1253148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek
126b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek//===----------------------------------------------------------------------===//
127c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek// Diagnostic cleanup.
128c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek//===----------------------------------------------------------------------===//
129c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek
130b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenekstatic PathDiagnosticEventPiece *
131b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted KremenekeventsDescribeSameCondition(PathDiagnosticEventPiece *X,
132b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek                            PathDiagnosticEventPiece *Y) {
133b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek  // Prefer diagnostics that come from ConditionBRVisitor over
134b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek  // those that came from TrackConstraintBRVisitor.
135b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek  const void *tagPreferred = ConditionBRVisitor::getTag();
136b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek  const void *tagLesser = TrackConstraintBRVisitor::getTag();
137b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek
138b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek  if (X->getLocation() != Y->getLocation())
139b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek    return 0;
140b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek
141b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek  if (X->getTag() == tagPreferred && Y->getTag() == tagLesser)
142b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek    return X;
143b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek
144b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek  if (Y->getTag() == tagPreferred && X->getTag() == tagLesser)
145b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek    return Y;
146b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek
147b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek  return 0;
148b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek}
149b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek
1503800165e56107df7430520aa98afdf7065db2dd2Ted Kremenek/// An optimization pass over PathPieces that removes redundant diagnostics
1513800165e56107df7430520aa98afdf7065db2dd2Ted Kremenek/// generated by both ConditionBRVisitor and TrackConstraintBRVisitor.  Both
1523800165e56107df7430520aa98afdf7065db2dd2Ted Kremenek/// BugReporterVisitors use different methods to generate diagnostics, with
1533800165e56107df7430520aa98afdf7065db2dd2Ted Kremenek/// one capable of emitting diagnostics in some cases but not in others.  This
1543800165e56107df7430520aa98afdf7065db2dd2Ted Kremenek/// can lead to redundant diagnostic pieces at the same point in a path.
1553800165e56107df7430520aa98afdf7065db2dd2Ted Kremenekstatic void removeRedundantMsgs(PathPieces &path) {
156b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek  unsigned N = path.size();
157b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek  if (N < 2)
158b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek    return;
1593800165e56107df7430520aa98afdf7065db2dd2Ted Kremenek  // NOTE: this loop intentionally is not using an iterator.  Instead, we
1603800165e56107df7430520aa98afdf7065db2dd2Ted Kremenek  // are streaming the path and modifying it in place.  This is done by
1613800165e56107df7430520aa98afdf7065db2dd2Ted Kremenek  // grabbing the front, processing it, and if we decide to keep it append
1623800165e56107df7430520aa98afdf7065db2dd2Ted Kremenek  // it to the end of the path.  The entire path is processed in this way.
163b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek  for (unsigned i = 0; i < N; ++i) {
164b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek    IntrusiveRefCntPtr<PathDiagnosticPiece> piece(path.front());
165b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek    path.pop_front();
166b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek
167b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek    switch (piece->getKind()) {
168b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek      case clang::ento::PathDiagnosticPiece::Call:
1693800165e56107df7430520aa98afdf7065db2dd2Ted Kremenek        removeRedundantMsgs(cast<PathDiagnosticCallPiece>(piece)->path);
170b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek        break;
171b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek      case clang::ento::PathDiagnosticPiece::Macro:
1723800165e56107df7430520aa98afdf7065db2dd2Ted Kremenek        removeRedundantMsgs(cast<PathDiagnosticMacroPiece>(piece)->subPieces);
173b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek        break;
174b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek      case clang::ento::PathDiagnosticPiece::ControlFlow:
175b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek        break;
176b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek      case clang::ento::PathDiagnosticPiece::Event: {
177b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek        if (i == N-1)
178b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek          break;
179b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek
180b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek        if (PathDiagnosticEventPiece *nextEvent =
181b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek            dyn_cast<PathDiagnosticEventPiece>(path.front().getPtr())) {
182b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek          PathDiagnosticEventPiece *event =
183b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek            cast<PathDiagnosticEventPiece>(piece);
184b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek          // Check to see if we should keep one of the two pieces.  If we
185b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek          // come up with a preference, record which piece to keep, and consume
186b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek          // another piece from the path.
187b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek          if (PathDiagnosticEventPiece *pieceToKeep =
188b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek              eventsDescribeSameCondition(event, nextEvent)) {
189b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek            piece = pieceToKeep;
190b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek            path.pop_front();
191b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek            ++i;
192b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek          }
193b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek        }
194b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek        break;
195b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek      }
196b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek    }
197b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek    path.push_back(piece);
198b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek  }
199b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek}
200b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek
201c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek/// Recursively scan through a path and prune out calls and macros pieces
202c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek/// that aren't needed.  Return true if afterwards the path contains
203afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose/// "interesting stuff" which means it shouldn't be pruned from the parent path.
204afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rosebool BugReporter::RemoveUnneededCalls(PathPieces &pieces, BugReport *R) {
205c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek  bool containsSomethingInteresting = false;
206c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek  const unsigned N = pieces.size();
207c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek
208c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek  for (unsigned i = 0 ; i < N ; ++i) {
209c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek    // Remove the front piece from the path.  If it is still something we
210c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek    // want to keep once we are done, we will push it back on the end.
211c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek    IntrusiveRefCntPtr<PathDiagnosticPiece> piece(pieces.front());
212c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek    pieces.pop_front();
213c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek
214afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose    // Throw away pieces with invalid locations. Note that we can't throw away
215afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose    // calls just yet because they might have something interesting inside them.
216afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose    // If so, their locations will be adjusted as necessary later.
217a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek    if (piece->getKind() != PathDiagnosticPiece::Call &&
218a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek        piece->getLocation().asLocation().isInvalid())
219a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek      continue;
220a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek
221725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek    switch (piece->getKind()) {
222725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek      case PathDiagnosticPiece::Call: {
223725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek        PathDiagnosticCallPiece *call = cast<PathDiagnosticCallPiece>(piece);
22480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks        // Check if the location context is interesting.
22580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks        assert(LocationContextMap.count(call));
22680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks        if (R->isInteresting(LocationContextMap[call])) {
22780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks          containsSomethingInteresting = true;
22880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks          break;
22980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks        }
230368f3b070e8cb657a65bfa443d60256676d269e7Jordan Rose
231afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose        if (!RemoveUnneededCalls(call->path, R))
232368f3b070e8cb657a65bfa443d60256676d269e7Jordan Rose          continue;
233a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek
234725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek        containsSomethingInteresting = true;
235725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek        break;
236725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek      }
237725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek      case PathDiagnosticPiece::Macro: {
238725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek        PathDiagnosticMacroPiece *macro = cast<PathDiagnosticMacroPiece>(piece);
239afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose        if (!RemoveUnneededCalls(macro->subPieces, R))
240725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek          continue;
241c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek        containsSomethingInteresting = true;
242725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek        break;
243725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek      }
244725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek      case PathDiagnosticPiece::Event: {
245725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek        PathDiagnosticEventPiece *event = cast<PathDiagnosticEventPiece>(piece);
246a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek
247725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek        // We never throw away an event, but we do throw it away wholesale
248725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek        // as part of a path if we throw the entire path away.
24922505ef15e32db31a4f834a387cf73a913bc8f66Ted Kremenek        containsSomethingInteresting |= !event->isPrunable();
250725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek        break;
251725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek      }
252725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek      case PathDiagnosticPiece::ControlFlow:
253725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek        break;
254c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek    }
255c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek
256c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek    pieces.push_back(piece);
257c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek  }
258c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek
259c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek  return containsSomethingInteresting;
260c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek}
261c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek
262afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose/// Recursively scan through a path and make sure that all call pieces have
263afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose/// valid locations. Note that all other pieces with invalid locations should
264afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose/// have already been pruned out.
265afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rosestatic void adjustCallLocations(PathPieces &Pieces,
266afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose                                PathDiagnosticLocation *LastCallLocation = 0) {
267afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose  for (PathPieces::iterator I = Pieces.begin(), E = Pieces.end(); I != E; ++I) {
268afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose    PathDiagnosticCallPiece *Call = dyn_cast<PathDiagnosticCallPiece>(*I);
269afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose
270afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose    if (!Call) {
271afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose      assert((*I)->getLocation().asLocation().isValid());
272afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose      continue;
273afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose    }
274afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose
275afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose    if (LastCallLocation) {
276187f8bd88bfc92cf3fea62b7d8db5f92edce410aJordan Rose      if (!Call->callEnter.asLocation().isValid() ||
277187f8bd88bfc92cf3fea62b7d8db5f92edce410aJordan Rose          Call->getCaller()->isImplicit())
278afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose        Call->callEnter = *LastCallLocation;
279187f8bd88bfc92cf3fea62b7d8db5f92edce410aJordan Rose      if (!Call->callReturn.asLocation().isValid() ||
280187f8bd88bfc92cf3fea62b7d8db5f92edce410aJordan Rose          Call->getCaller()->isImplicit())
281afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose        Call->callReturn = *LastCallLocation;
282afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose    }
283afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose
284afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose    // Recursively clean out the subclass.  Keep this call around if
285afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose    // it contains any informative diagnostics.
286afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose    PathDiagnosticLocation *ThisCallLocation;
287187f8bd88bfc92cf3fea62b7d8db5f92edce410aJordan Rose    if (Call->callEnterWithin.asLocation().isValid() &&
288187f8bd88bfc92cf3fea62b7d8db5f92edce410aJordan Rose        !Call->getCallee()->isImplicit())
289afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose      ThisCallLocation = &Call->callEnterWithin;
290afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose    else
291afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose      ThisCallLocation = &Call->callEnter;
292afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose
293afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose    assert(ThisCallLocation && "Outermost call has an invalid location");
294afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose    adjustCallLocations(Call->path, ThisCallLocation);
295afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose  }
296afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose}
297afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose
298c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek//===----------------------------------------------------------------------===//
2993106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// PathDiagnosticBuilder and its associated routines and helper objects.
300b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek//===----------------------------------------------------------------------===//
301b479dadea93b93d3f0a335c3518b703f140b3f50Ted Kremenek
302babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremeneknamespace {
303ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass NodeMapClosure : public BugReport::NodeResolver {
304c9963132736782d0c9178c744b3e2307cfb98a08Jordan Rose  InterExplodedGraphMap &M;
3057dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenekpublic:
306c9963132736782d0c9178c744b3e2307cfb98a08Jordan Rose  NodeMapClosure(InterExplodedGraphMap &m) : M(m) {}
3071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3089c378f705405d37f49795d5e915989de774fe11fTed Kremenek  const ExplodedNode *getOriginalNode(const ExplodedNode *N) {
309c9963132736782d0c9178c744b3e2307cfb98a08Jordan Rose    return M.lookup(N);
3107dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek  }
3117dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek};
3121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
313ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass PathDiagnosticBuilder : public BugReporterContext {
3147dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek  BugReport *R;
315ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie  PathDiagnosticConsumer *PDC;
3167dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek  NodeMapClosure NMC;
3171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumppublic:
31859950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek  const LocationContext *LC;
31959950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek
3208966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek  PathDiagnosticBuilder(GRBugReporter &br,
321c9963132736782d0c9178c744b3e2307cfb98a08Jordan Rose                        BugReport *r, InterExplodedGraphMap &Backmap,
322ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie                        PathDiagnosticConsumer *pdc)
3238966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek    : BugReporterContext(br),
32459950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek      R(r), PDC(pdc), NMC(Backmap), LC(r->getErrorNode()->getLocationContext())
32559950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek  {}
3261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3279c378f705405d37f49795d5e915989de774fe11fTed Kremenek  PathDiagnosticLocation ExecutionContinues(const ExplodedNode *N);
3281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3299c378f705405d37f49795d5e915989de774fe11fTed Kremenek  PathDiagnosticLocation ExecutionContinues(llvm::raw_string_ostream &os,
3309c378f705405d37f49795d5e915989de774fe11fTed Kremenek                                            const ExplodedNode *N);
3311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3328e6431adab313e283a992698f6fc7afe62420999Anna Zaks  BugReport *getBugReport() { return R; }
3338e6431adab313e283a992698f6fc7afe62420999Anna Zaks
334212f6d3b5fb3fa55ba1e40671cfc336430abc8ddTom Care  Decl const &getCodeDecl() { return R->getErrorNode()->getCodeDecl(); }
33559950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek
33659950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek  ParentMap& getParentMap() { return LC->getParentMap(); }
3371eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
338c3f83ad7adaff2623986aa1c3e57833babd03d50Ted Kremenek  const Stmt *getParent(const Stmt *S) {
339c3f83ad7adaff2623986aa1c3e57833babd03d50Ted Kremenek    return getParentMap().getParent(S);
340c3f83ad7adaff2623986aa1c3e57833babd03d50Ted Kremenek  }
3411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3428966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek  virtual NodeMapClosure& getNodeResolver() { return NMC; }
3437297134f128423fce2e88f92421ed135bded7d4eDouglas Gregor
344d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek  PathDiagnosticLocation getEnclosingStmtLocation(const Stmt *S);
3451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
346ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie  PathDiagnosticConsumer::PathGenerationScheme getGenerationScheme() const {
347ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie    return PDC ? PDC->getGenerationScheme() : PathDiagnosticConsumer::Extensive;
3487dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek  }
3497dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek
350babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek  bool supportsLogicalOpControlFlow() const {
351babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek    return PDC ? PDC->supportsLogicalOpControlFlow() : true;
3521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  }
353babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek};
354babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek} // end anonymous namespace
355babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek
35600605e0f011ed99225a22026344c5fc1b3212cd7Ted KremenekPathDiagnosticLocation
3579c378f705405d37f49795d5e915989de774fe11fTed KremenekPathDiagnosticBuilder::ExecutionContinues(const ExplodedNode *N) {
3585f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek  if (const Stmt *S = GetNextStmt(N))
35959950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek    return PathDiagnosticLocation(S, getSourceManager(), LC);
36000605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek
3610cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks  return PathDiagnosticLocation::createDeclEnd(N->getLocationContext(),
3620cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks                                               getSourceManager());
363082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek}
3641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
36500605e0f011ed99225a22026344c5fc1b3212cd7Ted KremenekPathDiagnosticLocation
3669c378f705405d37f49795d5e915989de774fe11fTed KremenekPathDiagnosticBuilder::ExecutionContinues(llvm::raw_string_ostream &os,
3679c378f705405d37f49795d5e915989de774fe11fTed Kremenek                                          const ExplodedNode *N) {
368babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek
369143ca222583a4a355fdc89af852deef287499300Ted Kremenek  // Slow, but probably doesn't matter.
370b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek  if (os.str().empty())
371b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek    os << ' ';
3721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
37300605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek  const PathDiagnosticLocation &Loc = ExecutionContinues(N);
3741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
37500605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek  if (Loc.asStmt())
376b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek    os << "Execution continues on line "
377642116259e8df6286063a17361c20e95b5017a0aChandler Carruth       << getSourceManager().getExpansionLineNumber(Loc.asLocation())
3788966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek       << '.';
3794f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek  else {
3804f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek    os << "Execution jumps to the end of the ";
3814f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek    const Decl *D = N->getLocationContext()->getDecl();
3824f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek    if (isa<ObjCMethodDecl>(D))
3834f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek      os << "method";
3844f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek    else if (isa<FunctionDecl>(D))
3854f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek      os << "function";
3864f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek    else {
3874f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek      assert(isa<BlockDecl>(D));
3884f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek      os << "anonymous block";
3894f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek    }
3904f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek    os << '.';
3914f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek  }
3921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
393082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek  return Loc;
394143ca222583a4a355fdc89af852deef287499300Ted Kremenek}
395143ca222583a4a355fdc89af852deef287499300Ted Kremenek
396ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenekstatic bool IsNested(const Stmt *S, ParentMap &PM) {
397ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek  if (isa<Expr>(S) && PM.isConsumedExpr(cast<Expr>(S)))
398ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek    return true;
3991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
400ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek  const Stmt *Parent = PM.getParentIgnoreParens(S);
4011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
402ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek  if (Parent)
403ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek    switch (Parent->getStmtClass()) {
404ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek      case Stmt::ForStmtClass:
405ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek      case Stmt::DoStmtClass:
406ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek      case Stmt::WhileStmtClass:
407ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek        return true;
408ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek      default:
409ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek        break;
410ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek    }
4111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  return false;
413ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek}
414ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek
415d8c938b0f6b7a7156181be575239e4c6e15a2adbTed KremenekPathDiagnosticLocation
416d8c938b0f6b7a7156181be575239e4c6e15a2adbTed KremenekPathDiagnosticBuilder::getEnclosingStmtLocation(const Stmt *S) {
4179c378f705405d37f49795d5e915989de774fe11fTed Kremenek  assert(S && "Null Stmt *passed to getEnclosingStmtLocation");
4181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  ParentMap &P = getParentMap();
4198966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek  SourceManager &SMgr = getSourceManager();
420e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek
421ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek  while (IsNested(S, P)) {
4228c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek    const Stmt *Parent = P.getParentIgnoreParens(S);
4231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
424af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek    if (!Parent)
425af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek      break;
4261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
427af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek    switch (Parent->getStmtClass()) {
4285fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek      case Stmt::BinaryOperatorClass: {
4295fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek        const BinaryOperator *B = cast<BinaryOperator>(Parent);
4305fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek        if (B->isLogicalOp())
431220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks          return PathDiagnosticLocation(S, SMgr, LC);
4325fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek        break;
4331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump      }
434af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek      case Stmt::CompoundStmtClass:
435af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek      case Stmt::StmtExprClass:
436220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks        return PathDiagnosticLocation(S, SMgr, LC);
4371d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek      case Stmt::ChooseExprClass:
4381d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek        // Similar to '?' if we are referring to condition, just have the edge
4391d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek        // point to the entire choose expression.
4401d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek        if (cast<ChooseExpr>(Parent)->getCond() == S)
441220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks          return PathDiagnosticLocation(Parent, SMgr, LC);
4421d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek        else
443220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks          return PathDiagnosticLocation(S, SMgr, LC);
44456ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall      case Stmt::BinaryConditionalOperatorClass:
4451d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek      case Stmt::ConditionalOperatorClass:
4461d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek        // For '?', if we are referring to condition, just have the edge point
4471d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek        // to the entire '?' expression.
44856ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall        if (cast<AbstractConditionalOperator>(Parent)->getCond() == S)
449220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks          return PathDiagnosticLocation(Parent, SMgr, LC);
4501d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek        else
451220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks          return PathDiagnosticLocation(S, SMgr, LC);
452af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek      case Stmt::DoStmtClass:
453220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks          return PathDiagnosticLocation(S, SMgr, LC);
454af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek      case Stmt::ForStmtClass:
455af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek        if (cast<ForStmt>(Parent)->getBody() == S)
456220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks          return PathDiagnosticLocation(S, SMgr, LC);
4571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump        break;
458af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek      case Stmt::IfStmtClass:
459af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek        if (cast<IfStmt>(Parent)->getCond() != S)
460220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks          return PathDiagnosticLocation(S, SMgr, LC);
4618bd4d037d837e7922c3661d6158229da58a03887Ted Kremenek        break;
462af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek      case Stmt::ObjCForCollectionStmtClass:
463af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek        if (cast<ObjCForCollectionStmt>(Parent)->getBody() == S)
464220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks          return PathDiagnosticLocation(S, SMgr, LC);
465af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek        break;
466af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek      case Stmt::WhileStmtClass:
467af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek        if (cast<WhileStmt>(Parent)->getCond() != S)
468220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks          return PathDiagnosticLocation(S, SMgr, LC);
469af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek        break;
470af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek      default:
471af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek        break;
472af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek    }
473af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek
474d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek    S = Parent;
475d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek  }
4761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
477d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek  assert(S && "Cannot have null Stmt for PathDiagnosticLocation");
478e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek
479e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek  // Special case: DeclStmts can appear in for statement declarations, in which
480e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek  //  case the ForStmt is the context.
481e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek  if (isa<DeclStmt>(S)) {
482e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek    if (const Stmt *Parent = P.getParent(S)) {
483e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek      switch (Parent->getStmtClass()) {
484e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek        case Stmt::ForStmtClass:
485e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek        case Stmt::ObjCForCollectionStmtClass:
486220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks          return PathDiagnosticLocation(Parent, SMgr, LC);
487e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek        default:
488e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek          break;
4891eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump      }
4901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    }
491e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek  }
492e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek  else if (isa<BinaryOperator>(S)) {
493e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek    // Special case: the binary operator represents the initialization
494e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek    // code in a for statement (this can happen when the variable being
495e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek    // initialized is an old variable.
496e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek    if (const ForStmt *FS =
497e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek          dyn_cast_or_null<ForStmt>(P.getParentIgnoreParens(S))) {
498e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek      if (FS->getInit() == S)
499220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks        return PathDiagnosticLocation(FS, SMgr, LC);
500e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek    }
501e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek  }
502e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek
503220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks  return PathDiagnosticLocation(S, SMgr, LC);
504d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek}
505d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek
506cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek//===----------------------------------------------------------------------===//
507d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose// "Visitors only" path diagnostic generation algorithm.
508d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose//===----------------------------------------------------------------------===//
509d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rosestatic bool GenerateVisitorsOnlyPathDiagnostic(PathDiagnostic &PD,
510d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose                                               PathDiagnosticBuilder &PDB,
511d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose                                               const ExplodedNode *N,
512d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose                                      ArrayRef<BugReporterVisitor *> visitors) {
513d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose  // All path generation skips the very first node (the error node).
514d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose  // This is because there is special handling for the end-of-path note.
515d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose  N = N->getFirstPred();
516d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose  if (!N)
517d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose    return true;
518d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose
519d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose  BugReport *R = PDB.getBugReport();
520d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose  while (const ExplodedNode *Pred = N->getFirstPred()) {
521d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose    for (ArrayRef<BugReporterVisitor *>::iterator I = visitors.begin(),
522d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose                                                  E = visitors.end();
523d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose         I != E; ++I) {
524d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose      // Visit all the node pairs, but throw the path pieces away.
525d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose      PathDiagnosticPiece *Piece = (*I)->VisitNode(N, Pred, PDB, *R);
526d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose      delete Piece;
527d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose    }
528d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose
529d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose    N = Pred;
530d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose  }
531d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose
532d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose  return R->isValid();
533d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose}
534d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose
535d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose//===----------------------------------------------------------------------===//
5363106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// "Minimal" path diagnostic generation algorithm.
537cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek//===----------------------------------------------------------------------===//
53856a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zakstypedef std::pair<PathDiagnosticCallPiece*, const ExplodedNode*> StackDiagPair;
53956a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zakstypedef SmallVector<StackDiagPair, 6> StackDiagVector;
54056a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks
541368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaksstatic void updateStackPiecesWithMessage(PathDiagnosticPiece *P,
54256a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks                                         StackDiagVector &CallStack) {
543368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks  // If the piece contains a special message, add it to all the call
544368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks  // pieces on the active stack.
545368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks  if (PathDiagnosticEventPiece *ep =
546368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks        dyn_cast<PathDiagnosticEventPiece>(P)) {
547368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks
54856a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks    if (ep->hasCallStackHint())
54956a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks      for (StackDiagVector::iterator I = CallStack.begin(),
55056a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks                                     E = CallStack.end(); I != E; ++I) {
55156a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks        PathDiagnosticCallPiece *CP = I->first;
55256a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks        const ExplodedNode *N = I->second;
5538fe4525680ce72e90cee3e58b5654e3ae955447fNAKAMURA Takumi        std::string stackMsg = ep->getCallStackMessage(N);
55456a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks
555368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks        // The last message on the path to final bug is the most important
556368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks        // one. Since we traverse the path backwards, do not add the message
557368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks        // if one has been previously added.
55856a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks        if  (!CP->hasCallStackMessage())
55956a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks          CP->setCallStackMessage(stackMsg);
56056a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks      }
561368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks  }
562368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks}
563cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek
56477d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenekstatic void CompactPathDiagnostic(PathPieces &path, const SourceManager& SM);
56514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
5668347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rosestatic bool GenerateMinimalPathDiagnostic(PathDiagnostic& PD,
5673106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek                                          PathDiagnosticBuilder &PDB,
5683bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose                                          const ExplodedNode *N,
5693bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose                                      ArrayRef<BugReporterVisitor *> visitors) {
5708966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek
5713106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  SourceManager& SMgr = PDB.getSourceManager();
57259950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek  const LocationContext *LC = PDB.LC;
5739c378f705405d37f49795d5e915989de774fe11fTed Kremenek  const ExplodedNode *NextNode = N->pred_empty()
5743106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek                                        ? NULL : *(N->pred_begin());
575368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks
57656a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks  StackDiagVector CallStack;
577368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks
5783106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  while (NextNode) {
5791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    N = NextNode;
58059950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek    PDB.LC = N->getLocationContext();
5813106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    NextNode = GetPredecessorNode(N);
5821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
58361f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek    ProgramPoint P = N->getLocation();
58480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks
58580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks    do {
5867a95de68c093991047ed8d339479ccad51b88663David Blaikie      if (Optional<CallExitEnd> CE = P.getAs<CallExitEnd>()) {
58780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks        PathDiagnosticCallPiece *C =
58880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks            PathDiagnosticCallPiece::construct(N, *CE, SMgr);
58980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks        GRBugReporter& BR = PDB.getBugReporter();
59080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks        BR.addCallPieceLocationContextPair(C, CE->getCalleeContext());
59180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks        PD.getActivePath().push_front(C);
59280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks        PD.pushActivePath(&C->path);
59380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks        CallStack.push_back(StackDiagPair(C, N));
59480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks        break;
5959373937945e1e075dfa08169eaccc1ad0b31f699Anna Zaks      }
596183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose
5977a95de68c093991047ed8d339479ccad51b88663David Blaikie      if (Optional<CallEnter> CE = P.getAs<CallEnter>()) {
59880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks        // Flush all locations, and pop the active path.
59980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks        bool VisitedEntireCall = PD.isWithinCall();
60080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks        PD.popActivePath();
60180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks
60280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks        // Either we just added a bunch of stuff to the top-level path, or
60380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks        // we have a previous CallExitEnd.  If the former, it means that the
60480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks        // path terminated within a function call.  We must then take the
60580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks        // current contents of the active path and place it within
60680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks        // a new PathDiagnosticCallPiece.
60780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks        PathDiagnosticCallPiece *C;
60880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks        if (VisitedEntireCall) {
60980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks          C = cast<PathDiagnosticCallPiece>(PD.getActivePath().front());
61080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks        } else {
61180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks          const Decl *Caller = CE->getLocationContext()->getDecl();
61280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks          C = PathDiagnosticCallPiece::construct(PD.getActivePath(), Caller);
61380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks          GRBugReporter& BR = PDB.getBugReporter();
61480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks          BR.addCallPieceLocationContextPair(C, CE->getCalleeContext());
61580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks        }
61680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks
61780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks        C->setCallee(*CE, SMgr);
61880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks        if (!CallStack.empty()) {
61980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks          assert(CallStack.back().first == C);
62080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks          CallStack.pop_back();
62180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks        }
62280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks        break;
623368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks      }
6241eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
6257a95de68c093991047ed8d339479ccad51b88663David Blaikie      if (Optional<BlockEdge> BE = P.getAs<BlockEdge>()) {
62680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks        const CFGBlock *Src = BE->getSrc();
62780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks        const CFGBlock *Dst = BE->getDst();
62880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks        const Stmt *T = Src->getTerminator();
6291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
63080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks        if (!T)
63180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks          break;
6321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
63380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks        PathDiagnosticLocation Start =
63480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks            PathDiagnosticLocation::createBegin(T, SMgr,
63580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks                N->getLocationContext());
6361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
63780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks        switch (T->getStmtClass()) {
63861f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek        default:
63961f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek          break;
6401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
64161f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek        case Stmt::GotoStmtClass:
6421eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump        case Stmt::IndirectGotoStmtClass: {
6439c378f705405d37f49795d5e915989de774fe11fTed Kremenek          const Stmt *S = GetNextStmt(N);
6441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
64561f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek          if (!S)
64680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks            break;
6471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
648297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek          std::string sbuf;
6491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump          llvm::raw_string_ostream os(sbuf);
650d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek          const PathDiagnosticLocation &End = PDB.getEnclosingStmtLocation(S);
6511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
65200605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek          os << "Control jumps to line "
65380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks              << End.asLocation().getExpansionLineNumber();
65480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks          PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(
65580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks              Start, End, os.str()));
65661f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek          break;
65761f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek        }
6581eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
6591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump        case Stmt::SwitchStmtClass: {
66061f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek          // Figure out what case arm we took.
661297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek          std::string sbuf;
662297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek          llvm::raw_string_ostream os(sbuf);
6631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
6649c378f705405d37f49795d5e915989de774fe11fTed Kremenek          if (const Stmt *S = Dst->getLabel()) {
665220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks            PathDiagnosticLocation End(S, SMgr, LC);
6661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
6675a429954aedd8a830a70fcea2cb51561673e4fc3Ted Kremenek            switch (S->getStmtClass()) {
66880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks            default:
66980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks              os << "No cases match in the switch statement. "
67080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks              "Control jumps to line "
67180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks              << End.asLocation().getExpansionLineNumber();
67280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks              break;
67380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks            case Stmt::DefaultStmtClass:
67480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks              os << "Control jumps to the 'default' case at line "
67580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks              << End.asLocation().getExpansionLineNumber();
67680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks              break;
67780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks
67880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks            case Stmt::CaseStmtClass: {
67980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks              os << "Control jumps to 'case ";
68080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks              const CaseStmt *Case = cast<CaseStmt>(S);
68180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks              const Expr *LHS = Case->getLHS()->IgnoreParenCasts();
68280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks
68380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks              // Determine if it is an enum.
68480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks              bool GetRawInt = true;
68580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks
68680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks              if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(LHS)) {
68780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks                // FIXME: Maybe this should be an assertion.  Are there cases
68880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks                // were it is not an EnumConstantDecl?
68980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks                const EnumConstantDecl *D =
69003509aea098772644bf4662dc1c88634818ceeccZhongxing Xu                    dyn_cast<EnumConstantDecl>(DR->getDecl());
6911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
69280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks                if (D) {
69380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks                  GetRawInt = false;
69480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks                  os << *D;
6955a429954aedd8a830a70fcea2cb51561673e4fc3Ted Kremenek                }
69680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks              }
6979ec64d6e2fe575b297e1eaa5051efc2983373e25Eli Friedman
69880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks              if (GetRawInt)
69980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks                os << LHS->EvaluateKnownConstInt(PDB.getASTContext());
7009ec64d6e2fe575b297e1eaa5051efc2983373e25Eli Friedman
70180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks              os << ":'  at line "
70280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks                  << End.asLocation().getExpansionLineNumber();
70380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks              break;
70461f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek            }
70580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks            }
70680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks            PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(
70780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks                Start, End, os.str()));
70861f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek          }
709567839273dfc395a459cbe77d5f8d128b9ae85bfTed Kremenek          else {
710c3517ebb48a51e146badc08bc3684520c41da6c8Ted Kremenek            os << "'Default' branch taken. ";
7111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump            const PathDiagnosticLocation &End = PDB.ExecutionContinues(os, N);
71280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks            PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(
71380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks                Start, End, os.str()));
714567839273dfc395a459cbe77d5f8d128b9ae85bfTed Kremenek          }
7151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
71661f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek          break;
71761f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek        }
7181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
7192673c9ff76ebdb72b7f846e2ff1e0f4256372e19Ted Kremenek        case Stmt::BreakStmtClass:
7202673c9ff76ebdb72b7f846e2ff1e0f4256372e19Ted Kremenek        case Stmt::ContinueStmtClass: {
721297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek          std::string sbuf;
722297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek          llvm::raw_string_ostream os(sbuf);
72300605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek          PathDiagnosticLocation End = PDB.ExecutionContinues(os, N);
72480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks          PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(
72580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks              Start, End, os.str()));
7262673c9ff76ebdb72b7f846e2ff1e0f4256372e19Ted Kremenek          break;
7272673c9ff76ebdb72b7f846e2ff1e0f4256372e19Ted Kremenek        }
7281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
72980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks        // Determine control-flow for ternary '?'.
73056ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall        case Stmt::BinaryConditionalOperatorClass:
731706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek        case Stmt::ConditionalOperatorClass: {
732297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek          std::string sbuf;
733297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek          llvm::raw_string_ostream os(sbuf);
7341d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek          os << "'?' condition is ";
7351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
736706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek          if (*(Src->succ_begin()+1) == Dst)
737082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek            os << "false";
738706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek          else
739082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek            os << "true";
7401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
74100605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek          PathDiagnosticLocation End = PDB.ExecutionContinues(N);
7421eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
7431d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek          if (const Stmt *S = End.asStmt())
7441d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek            End = PDB.getEnclosingStmtLocation(S);
7451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
74680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks          PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(
74780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks              Start, End, os.str()));
748babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek          break;
749babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek        }
7501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
75180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks        // Determine control-flow for short-circuited '&&' and '||'.
752babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek        case Stmt::BinaryOperatorClass: {
753babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek          if (!PDB.supportsLogicalOpControlFlow())
754babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek            break;
7551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
75603509aea098772644bf4662dc1c88634818ceeccZhongxing Xu          const BinaryOperator *B = cast<BinaryOperator>(T);
757babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek          std::string sbuf;
758babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek          llvm::raw_string_ostream os(sbuf);
759babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek          os << "Left side of '";
7601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
7612de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall          if (B->getOpcode() == BO_LAnd) {
762f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek            os << "&&" << "' is ";
7631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
764f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek            if (*(Src->succ_begin()+1) == Dst) {
765f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek              os << "false";
766220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks              PathDiagnosticLocation End(B->getLHS(), SMgr, LC);
7670cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks              PathDiagnosticLocation Start =
76880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks                  PathDiagnosticLocation::createOperatorLoc(B, SMgr);
76980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks              PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(
77080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks                  Start, End, os.str()));
7711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump            }
772f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek            else {
773f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek              os << "true";
774220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks              PathDiagnosticLocation Start(B->getLHS(), SMgr, LC);
775f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek              PathDiagnosticLocation End = PDB.ExecutionContinues(N);
77680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks              PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(
77780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks                  Start, End, os.str()));
7781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump            }
779babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek          }
780babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek          else {
7812de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall            assert(B->getOpcode() == BO_LOr);
782f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek            os << "||" << "' is ";
7831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
784f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek            if (*(Src->succ_begin()+1) == Dst) {
785f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek              os << "false";
786220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks              PathDiagnosticLocation Start(B->getLHS(), SMgr, LC);
787f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek              PathDiagnosticLocation End = PDB.ExecutionContinues(N);
78880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks              PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(
78980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks                  Start, End, os.str()));
790f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek            }
791f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek            else {
792f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek              os << "true";
793220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks              PathDiagnosticLocation End(B->getLHS(), SMgr, LC);
7940cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks              PathDiagnosticLocation Start =
79580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks                  PathDiagnosticLocation::createOperatorLoc(B, SMgr);
79680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks              PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(
79780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks                  Start, End, os.str()));
798f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek            }
799babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek          }
8001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
801706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek          break;
802706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek        }
8031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
8041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump        case Stmt::DoStmtClass:  {
805706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek          if (*(Src->succ_begin()) == Dst) {
806297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek            std::string sbuf;
807297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek            llvm::raw_string_ostream os(sbuf);
8081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
809c3517ebb48a51e146badc08bc3684520c41da6c8Ted Kremenek            os << "Loop condition is true. ";
810d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek            PathDiagnosticLocation End = PDB.ExecutionContinues(os, N);
8111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
812d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek            if (const Stmt *S = End.asStmt())
813d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek              End = PDB.getEnclosingStmtLocation(S);
8141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
81580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks            PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(
81680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks                Start, End, os.str()));
817082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek          }
818082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek          else {
81900605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek            PathDiagnosticLocation End = PDB.ExecutionContinues(N);
8201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
821d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek            if (const Stmt *S = End.asStmt())
822d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek              End = PDB.getEnclosingStmtLocation(S);
8231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
82480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks            PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(
82580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks                Start, End, "Loop condition is false.  Exiting loop"));
8263106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek          }
8271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
8283106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek          break;
8293106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        }
8301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
8313106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        case Stmt::WhileStmtClass:
8321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump        case Stmt::ForStmtClass: {
8333106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek          if (*(Src->succ_begin()+1) == Dst) {
8343106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek            std::string sbuf;
8353106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek            llvm::raw_string_ostream os(sbuf);
8361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
8373106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek            os << "Loop condition is false. ";
8383106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek            PathDiagnosticLocation End = PDB.ExecutionContinues(os, N);
8393106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek            if (const Stmt *S = End.asStmt())
8403106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek              End = PDB.getEnclosingStmtLocation(S);
8411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
84280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks            PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(
84380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks                Start, End, os.str()));
8443106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek          }
8453106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek          else {
8463106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek            PathDiagnosticLocation End = PDB.ExecutionContinues(N);
8473106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek            if (const Stmt *S = End.asStmt())
8483106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek              End = PDB.getEnclosingStmtLocation(S);
8491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
85080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks            PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(
85180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks                Start, End, "Loop condition is true.  Entering loop body"));
8523106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek          }
8531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
8543106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek          break;
8553106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        }
8561eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
8573106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        case Stmt::IfStmtClass: {
8583106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek          PathDiagnosticLocation End = PDB.ExecutionContinues(N);
8591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
8603106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek          if (const Stmt *S = End.asStmt())
8613106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek            End = PDB.getEnclosingStmtLocation(S);
8621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
8633106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek          if (*(Src->succ_begin()+1) == Dst)
86480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks            PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(
86580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks                Start, End, "Taking false branch"));
8661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump          else
86780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks            PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(
86880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks                Start, End, "Taking true branch"));
8691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
8703106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek          break;
8713106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        }
87280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks        }
8733106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      }
87480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks    } while(0);
8751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
876dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek    if (NextNode) {
8778e6431adab313e283a992698f6fc7afe62420999Anna Zaks      // Add diagnostic pieces from custom visitors.
8788e6431adab313e283a992698f6fc7afe62420999Anna Zaks      BugReport *R = PDB.getBugReport();
8793bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose      for (ArrayRef<BugReporterVisitor *>::iterator I = visitors.begin(),
8803bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose                                                    E = visitors.end();
8813bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose           I != E; ++I) {
882368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks        if (PathDiagnosticPiece *p = (*I)->VisitNode(N, NextNode, PDB, *R)) {
8832042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek          PD.getActivePath().push_front(p);
884368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks          updateStackPiecesWithMessage(p, CallStack);
885368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks        }
886dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek      }
8878966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek    }
8883106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  }
8891eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
8908347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose  if (!PDB.getBugReport()->isValid())
8918347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose    return false;
8928347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose
89314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  // After constructing the full PathDiagnostic, do a pass over it to compact
89414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  // PathDiagnosticPieces that occur within a macro.
89577d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek  CompactPathDiagnostic(PD.getMutablePieces(), PDB.getSourceManager());
8968347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose  return true;
8973106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek}
8983106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
8993106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===//
9005fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek// "Extensive" PathDiagnostic generation.
9015fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek//===----------------------------------------------------------------------===//
9025fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek
9035fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenekstatic bool IsControlFlowExpr(const Stmt *S) {
9045fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek  const Expr *E = dyn_cast<Expr>(S);
9051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
9065fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek  if (!E)
9075fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek    return false;
9081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
9091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  E = E->IgnoreParenCasts();
9101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
91156ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall  if (isa<AbstractConditionalOperator>(E))
9125fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek    return true;
9131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
9145fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek  if (const BinaryOperator *B = dyn_cast<BinaryOperator>(E))
9155fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek    if (B->isLogicalOp())
9165fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek      return true;
9171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
9181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  return false;
9195fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek}
9205fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek
92114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremeneknamespace {
922ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass ContextLocation : public PathDiagnosticLocation {
9238f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek  bool IsDead;
9248f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenekpublic:
9258f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek  ContextLocation(const PathDiagnosticLocation &L, bool isdead = false)
9268f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek    : PathDiagnosticLocation(L), IsDead(isdead) {}
9271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
9281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  void markDead() { IsDead = true; }
9298f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek  bool isDead() const { return IsDead; }
9308f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek};
9311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
932ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass EdgeBuilder {
9338f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek  std::vector<ContextLocation> CLocs;
9348f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek  typedef std::vector<ContextLocation>::iterator iterator;
93514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  PathDiagnostic &PD;
93614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  PathDiagnosticBuilder &PDB;
93714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  PathDiagnosticLocation PrevLoc;
9381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
9398f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek  bool IsConsumedExpr(const PathDiagnosticLocation &L);
9401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
94114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  bool containsLocation(const PathDiagnosticLocation &Container,
94214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek                        const PathDiagnosticLocation &Containee);
9431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
94414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  PathDiagnosticLocation getContextLocation(const PathDiagnosticLocation &L);
9451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
9469650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek  PathDiagnosticLocation cleanUpLocation(PathDiagnosticLocation L,
9479650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek                                         bool firstCharOnly = false) {
9488c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek    if (const Stmt *S = L.asStmt()) {
9499650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek      const Stmt *Original = S;
9508c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek      while (1) {
9518c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek        // Adjust the location for some expressions that are best referenced
9528c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek        // by one of their subexpressions.
9539650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek        switch (S->getStmtClass()) {
9549650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek          default:
9559650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek            break;
9569650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek          case Stmt::ParenExprClass:
957f111d935722ed488144600cea5ed03a6b5069e8fPeter Collingbourne          case Stmt::GenericSelectionExprClass:
958f111d935722ed488144600cea5ed03a6b5069e8fPeter Collingbourne            S = cast<Expr>(S)->IgnoreParens();
9599650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek            firstCharOnly = true;
9609650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek            continue;
96156ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall          case Stmt::BinaryConditionalOperatorClass:
9629650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek          case Stmt::ConditionalOperatorClass:
96356ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall            S = cast<AbstractConditionalOperator>(S)->getCond();
9649650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek            firstCharOnly = true;
9659650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek            continue;
9669650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek          case Stmt::ChooseExprClass:
9679650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek            S = cast<ChooseExpr>(S)->getCond();
9689650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek            firstCharOnly = true;
9699650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek            continue;
9709650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek          case Stmt::BinaryOperatorClass:
9719650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek            S = cast<BinaryOperator>(S)->getLHS();
9729650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek            firstCharOnly = true;
9739650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek            continue;
9749650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek        }
9751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
9769650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek        break;
9778c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek      }
9781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
9799650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek      if (S != Original)
98059950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek        L = PathDiagnosticLocation(S, L.getManager(), PDB.LC);
9818c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek    }
9821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
9839650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek    if (firstCharOnly)
9841531bb0c69d9afff6a6434e4cadf345eb628b287Anna Zaks      L  = PathDiagnosticLocation::createSingleLocation(L);
9859650cf3b08fcd66caae39bd5a1915c3eac735095Ted Kremenek
9868c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek    return L;
9878c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek  }
9881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
98914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  void popLocation() {
9908f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek    if (!CLocs.back().isDead() && CLocs.back().asLocation().isFileID()) {
9915c7168cbe8a0eabd05e0e12e469090d2cabd27c0Ted Kremenek      // For contexts, we only one the first character as the range.
99207c015cbcee31f72e2d320ba2c713c046bed42faTed Kremenek      rawAddEdge(cleanUpLocation(CLocs.back(), true));
9935c7168cbe8a0eabd05e0e12e469090d2cabd27c0Ted Kremenek    }
99414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    CLocs.pop_back();
99514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  }
9961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
99714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekpublic:
99814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  EdgeBuilder(PathDiagnostic &pd, PathDiagnosticBuilder &pdb)
99914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    : PD(pd), PDB(pdb) {
10001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1001a301a6773db085575ac51e3c966858180390c25bTed Kremenek      // If the PathDiagnostic already has pieces, add the enclosing statement
1002a301a6773db085575ac51e3c966858180390c25bTed Kremenek      // of the first piece as a context as well.
1003802e02463b880f53a6e645bde78cc412481ce9e0Ted Kremenek      if (!PD.path.empty()) {
1004802e02463b880f53a6e645bde78cc412481ce9e0Ted Kremenek        PrevLoc = (*PD.path.begin())->getLocation();
10051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
100614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek        if (const Stmt *S = PrevLoc.asStmt())
1007e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek          addExtendedContext(PDB.getEnclosingStmtLocation(S).asStmt());
100814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek      }
100914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  }
101014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
101114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  ~EdgeBuilder() {
101214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    while (!CLocs.empty()) popLocation();
10130cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks
1014a301a6773db085575ac51e3c966858180390c25bTed Kremenek    // Finally, add an initial edge from the start location of the first
1015a301a6773db085575ac51e3c966858180390c25bTed Kremenek    // statement (if it doesn't already exist).
10160cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks    PathDiagnosticLocation L = PathDiagnosticLocation::createDeclBegin(
101759950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek                                                       PDB.LC,
10180cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks                                                       PDB.getSourceManager());
10190cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks    if (L.isValid())
10200cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks      rawAddEdge(L);
102114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  }
102214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
10235de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek  void flushLocations() {
10245de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek    while (!CLocs.empty())
10255de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek      popLocation();
10265de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek    PrevLoc = PathDiagnosticLocation();
10275de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek  }
10285de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek
102914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  void addEdge(PathDiagnosticLocation NewLoc, bool alwaysAdd = false);
10301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
10318bd4d037d837e7922c3661d6158229da58a03887Ted Kremenek  void rawAddEdge(PathDiagnosticLocation NewLoc);
10321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
103314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  void addContext(const Stmt *S);
1034183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose  void addContext(const PathDiagnosticLocation &L);
1035e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek  void addExtendedContext(const Stmt *S);
10361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump};
103714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} // end anonymous namespace
103814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
103914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
104014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted KremenekPathDiagnosticLocation
104114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted KremenekEdgeBuilder::getContextLocation(const PathDiagnosticLocation &L) {
104214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  if (const Stmt *S = L.asStmt()) {
104314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    if (IsControlFlowExpr(S))
104414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek      return L;
10451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
10461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    return PDB.getEnclosingStmtLocation(S);
104714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  }
10481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
104914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  return L;
105014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek}
105114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
105214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekbool EdgeBuilder::containsLocation(const PathDiagnosticLocation &Container,
105314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek                                   const PathDiagnosticLocation &Containee) {
105414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
105514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  if (Container == Containee)
105614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    return true;
10571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
105814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  if (Container.asDecl())
105914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    return true;
10601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
106114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  if (const Stmt *S = Containee.asStmt())
106214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    if (const Stmt *ContainerS = Container.asStmt()) {
106314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek      while (S) {
106414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek        if (S == ContainerS)
106514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek          return true;
106614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek        S = PDB.getParent(S);
106714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek      }
106814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek      return false;
106914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    }
107014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
107114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  // Less accurate: compare using source ranges.
107214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  SourceRange ContainerR = Container.asRange();
107314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  SourceRange ContaineeR = Containee.asRange();
10741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
107514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  SourceManager &SM = PDB.getSourceManager();
1076402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth  SourceLocation ContainerRBeg = SM.getExpansionLoc(ContainerR.getBegin());
1077402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth  SourceLocation ContainerREnd = SM.getExpansionLoc(ContainerR.getEnd());
1078402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth  SourceLocation ContaineeRBeg = SM.getExpansionLoc(ContaineeR.getBegin());
1079402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth  SourceLocation ContaineeREnd = SM.getExpansionLoc(ContaineeR.getEnd());
10801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1081642116259e8df6286063a17361c20e95b5017a0aChandler Carruth  unsigned ContainerBegLine = SM.getExpansionLineNumber(ContainerRBeg);
1082642116259e8df6286063a17361c20e95b5017a0aChandler Carruth  unsigned ContainerEndLine = SM.getExpansionLineNumber(ContainerREnd);
1083642116259e8df6286063a17361c20e95b5017a0aChandler Carruth  unsigned ContaineeBegLine = SM.getExpansionLineNumber(ContaineeRBeg);
1084642116259e8df6286063a17361c20e95b5017a0aChandler Carruth  unsigned ContaineeEndLine = SM.getExpansionLineNumber(ContaineeREnd);
10851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
108614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  assert(ContainerBegLine <= ContainerEndLine);
10871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  assert(ContaineeBegLine <= ContaineeEndLine);
10881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
108914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  return (ContainerBegLine <= ContaineeBegLine &&
109014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek          ContainerEndLine >= ContaineeEndLine &&
109114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek          (ContainerBegLine != ContaineeBegLine ||
1092a77c031cb66f75d22672070052cc6e0205289ff8Chandler Carruth           SM.getExpansionColumnNumber(ContainerRBeg) <=
1093a77c031cb66f75d22672070052cc6e0205289ff8Chandler Carruth           SM.getExpansionColumnNumber(ContaineeRBeg)) &&
109414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek          (ContainerEndLine != ContaineeEndLine ||
1095a77c031cb66f75d22672070052cc6e0205289ff8Chandler Carruth           SM.getExpansionColumnNumber(ContainerREnd) >=
10966488dc31153be6f98b404c7860be6c66bb4ec917Ted Kremenek           SM.getExpansionColumnNumber(ContaineeREnd)));
109714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek}
109814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
109914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekvoid EdgeBuilder::rawAddEdge(PathDiagnosticLocation NewLoc) {
110014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  if (!PrevLoc.isValid()) {
110114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    PrevLoc = NewLoc;
110214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    return;
110314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  }
11041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
11058c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek  const PathDiagnosticLocation &NewLocClean = cleanUpLocation(NewLoc);
11068c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek  const PathDiagnosticLocation &PrevLocClean = cleanUpLocation(PrevLoc);
11071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1108a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek  if (PrevLocClean.asLocation().isInvalid()) {
1109a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek    PrevLoc = NewLoc;
1110a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek    return;
1111a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek  }
1112a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek
11138c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek  if (NewLocClean.asLocation() == PrevLocClean.asLocation())
111414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    return;
11151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
111614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  // FIXME: Ignore intra-macro edges for now.
1117402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth  if (NewLocClean.asLocation().getExpansionLoc() ==
1118402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth      PrevLocClean.asLocation().getExpansionLoc())
111914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    return;
112014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
11212042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek  PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(NewLocClean, PrevLocClean));
11228c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek  PrevLoc = NewLoc;
112314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek}
112414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
112514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekvoid EdgeBuilder::addEdge(PathDiagnosticLocation NewLoc, bool alwaysAdd) {
11261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1127a301a6773db085575ac51e3c966858180390c25bTed Kremenek  if (!alwaysAdd && NewLoc.asLocation().isMacroID())
1128a301a6773db085575ac51e3c966858180390c25bTed Kremenek    return;
11291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
113014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  const PathDiagnosticLocation &CLoc = getContextLocation(NewLoc);
113114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
113214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  while (!CLocs.empty()) {
11338f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek    ContextLocation &TopContextLoc = CLocs.back();
11341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
113514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    // Is the top location context the same as the one for the new location?
113614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    if (TopContextLoc == CLoc) {
11378f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek      if (alwaysAdd) {
11384c6f8d38e2795c67048e16e737b8225eeb184262Ted Kremenek        if (IsConsumedExpr(TopContextLoc) &&
11394c6f8d38e2795c67048e16e737b8225eeb184262Ted Kremenek            !IsControlFlowExpr(TopContextLoc.asStmt()))
11408f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek            TopContextLoc.markDead();
11418f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek
114214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek        rawAddEdge(NewLoc);
11438f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek      }
114414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
114514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek      return;
114614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    }
114714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
114814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    if (containsLocation(TopContextLoc, CLoc)) {
11498f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek      if (alwaysAdd) {
115014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek        rawAddEdge(NewLoc);
11511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
11524c6f8d38e2795c67048e16e737b8225eeb184262Ted Kremenek        if (IsConsumedExpr(CLoc) && !IsControlFlowExpr(CLoc.asStmt())) {
11538f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek          CLocs.push_back(ContextLocation(CLoc, true));
11548f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek          return;
11558f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek        }
11568f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek      }
11571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
115814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek      CLocs.push_back(CLoc);
11591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump      return;
116014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    }
116114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
116214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    // Context does not contain the location.  Flush it.
116314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    popLocation();
116414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  }
11651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
11665c7168cbe8a0eabd05e0e12e469090d2cabd27c0Ted Kremenek  // If we reach here, there is no enclosing context.  Just add the edge.
11675c7168cbe8a0eabd05e0e12e469090d2cabd27c0Ted Kremenek  rawAddEdge(NewLoc);
116814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek}
116914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
11708f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenekbool EdgeBuilder::IsConsumedExpr(const PathDiagnosticLocation &L) {
11718f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek  if (const Expr *X = dyn_cast_or_null<Expr>(L.asStmt()))
11728f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek    return PDB.getParentMap().isConsumedExpr(X) && !IsControlFlowExpr(X);
11731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
11748f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek  return false;
11758f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek}
11761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1177e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenekvoid EdgeBuilder::addExtendedContext(const Stmt *S) {
1178e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek  if (!S)
1179e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek    return;
11801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
11811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  const Stmt *Parent = PDB.getParent(S);
1182e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek  while (Parent) {
1183e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek    if (isa<CompoundStmt>(Parent))
1184e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek      Parent = PDB.getParent(Parent);
1185e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek    else
1186e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek      break;
1187e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek  }
1188e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek
1189e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek  if (Parent) {
1190e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek    switch (Parent->getStmtClass()) {
1191e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek      case Stmt::DoStmtClass:
1192e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek      case Stmt::ObjCAtSynchronizedStmtClass:
1193e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek        addContext(Parent);
1194e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek      default:
1195e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek        break;
1196e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek    }
1197e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek  }
11981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1199e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek  addContext(S);
1200e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek}
12011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
120214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekvoid EdgeBuilder::addContext(const Stmt *S) {
120314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  if (!S)
120414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    return;
120514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
120659950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek  PathDiagnosticLocation L(S, PDB.getSourceManager(), PDB.LC);
1207183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose  addContext(L);
1208183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose}
12091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1210183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rosevoid EdgeBuilder::addContext(const PathDiagnosticLocation &L) {
121114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  while (!CLocs.empty()) {
121214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    const PathDiagnosticLocation &TopContextLoc = CLocs.back();
121314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
121414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    // Is the top location context the same as the one for the new location?
121514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    if (TopContextLoc == L)
121614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek      return;
121714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
121814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    if (containsLocation(TopContextLoc, L)) {
121914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek      CLocs.push_back(L);
12201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump      return;
122114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    }
122214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
122314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    // Context does not contain the location.  Flush it.
122414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    popLocation();
122514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  }
122614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
122714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  CLocs.push_back(L);
122814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek}
122914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
123011abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// Cone-of-influence: support the reverse propagation of "interesting" symbols
123111abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// and values by tracing interesting calculations backwards through evaluated
123211abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// expressions along a path.  This is probably overly complicated, but the idea
123311abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// is that if an expression computed an "interesting" value, the child
123411abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// expressions are are also likely to be "interesting" as well (which then
123511abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// propagates to the values they in turn compute).  This reverse propagation
123611abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// is needed to track interesting correlations across function call boundaries,
123711abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// where formal arguments bind to actual arguments, etc.  This is also needed
123811abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// because the constraint solver sometimes simplifies certain symbolic values
123911abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// into constants when appropriate, and this complicates reasoning about
124011abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// interesting values.
124111abcecc8c919673237cf37384290a1ef1943976Ted Kremenektypedef llvm::DenseSet<const Expr *> InterestingExprs;
124211abcecc8c919673237cf37384290a1ef1943976Ted Kremenek
124311abcecc8c919673237cf37384290a1ef1943976Ted Kremenekstatic void reversePropagateIntererstingSymbols(BugReport &R,
124411abcecc8c919673237cf37384290a1ef1943976Ted Kremenek                                                InterestingExprs &IE,
124511abcecc8c919673237cf37384290a1ef1943976Ted Kremenek                                                const ProgramState *State,
124611abcecc8c919673237cf37384290a1ef1943976Ted Kremenek                                                const Expr *Ex,
124711abcecc8c919673237cf37384290a1ef1943976Ted Kremenek                                                const LocationContext *LCtx) {
124811abcecc8c919673237cf37384290a1ef1943976Ted Kremenek  SVal V = State->getSVal(Ex, LCtx);
124911abcecc8c919673237cf37384290a1ef1943976Ted Kremenek  if (!(R.isInteresting(V) || IE.count(Ex)))
125011abcecc8c919673237cf37384290a1ef1943976Ted Kremenek    return;
125111abcecc8c919673237cf37384290a1ef1943976Ted Kremenek
125211abcecc8c919673237cf37384290a1ef1943976Ted Kremenek  switch (Ex->getStmtClass()) {
125311abcecc8c919673237cf37384290a1ef1943976Ted Kremenek    default:
125411abcecc8c919673237cf37384290a1ef1943976Ted Kremenek      if (!isa<CastExpr>(Ex))
125511abcecc8c919673237cf37384290a1ef1943976Ted Kremenek        break;
125611abcecc8c919673237cf37384290a1ef1943976Ted Kremenek      // Fall through.
125711abcecc8c919673237cf37384290a1ef1943976Ted Kremenek    case Stmt::BinaryOperatorClass:
125811abcecc8c919673237cf37384290a1ef1943976Ted Kremenek    case Stmt::UnaryOperatorClass: {
125911abcecc8c919673237cf37384290a1ef1943976Ted Kremenek      for (Stmt::const_child_iterator CI = Ex->child_begin(),
126011abcecc8c919673237cf37384290a1ef1943976Ted Kremenek            CE = Ex->child_end();
126111abcecc8c919673237cf37384290a1ef1943976Ted Kremenek            CI != CE; ++CI) {
126211abcecc8c919673237cf37384290a1ef1943976Ted Kremenek        if (const Expr *child = dyn_cast_or_null<Expr>(*CI)) {
126311abcecc8c919673237cf37384290a1ef1943976Ted Kremenek          IE.insert(child);
126411abcecc8c919673237cf37384290a1ef1943976Ted Kremenek          SVal ChildV = State->getSVal(child, LCtx);
126511abcecc8c919673237cf37384290a1ef1943976Ted Kremenek          R.markInteresting(ChildV);
126611abcecc8c919673237cf37384290a1ef1943976Ted Kremenek        }
126711abcecc8c919673237cf37384290a1ef1943976Ted Kremenek        break;
126811abcecc8c919673237cf37384290a1ef1943976Ted Kremenek      }
126911abcecc8c919673237cf37384290a1ef1943976Ted Kremenek    }
127011abcecc8c919673237cf37384290a1ef1943976Ted Kremenek  }
127111abcecc8c919673237cf37384290a1ef1943976Ted Kremenek
127211abcecc8c919673237cf37384290a1ef1943976Ted Kremenek  R.markInteresting(V);
127311abcecc8c919673237cf37384290a1ef1943976Ted Kremenek}
127411abcecc8c919673237cf37384290a1ef1943976Ted Kremenek
127511abcecc8c919673237cf37384290a1ef1943976Ted Kremenekstatic void reversePropagateInterestingSymbols(BugReport &R,
127611abcecc8c919673237cf37384290a1ef1943976Ted Kremenek                                               InterestingExprs &IE,
127711abcecc8c919673237cf37384290a1ef1943976Ted Kremenek                                               const ProgramState *State,
127811abcecc8c919673237cf37384290a1ef1943976Ted Kremenek                                               const LocationContext *CalleeCtx,
127911abcecc8c919673237cf37384290a1ef1943976Ted Kremenek                                               const LocationContext *CallerCtx)
128011abcecc8c919673237cf37384290a1ef1943976Ted Kremenek{
1281852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose  // FIXME: Handle non-CallExpr-based CallEvents.
128211abcecc8c919673237cf37384290a1ef1943976Ted Kremenek  const StackFrameContext *Callee = CalleeCtx->getCurrentStackFrame();
128311abcecc8c919673237cf37384290a1ef1943976Ted Kremenek  const Stmt *CallSite = Callee->getCallSite();
1284852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose  if (const CallExpr *CE = dyn_cast_or_null<CallExpr>(CallSite)) {
128511abcecc8c919673237cf37384290a1ef1943976Ted Kremenek    if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CalleeCtx->getDecl())) {
128611abcecc8c919673237cf37384290a1ef1943976Ted Kremenek      FunctionDecl::param_const_iterator PI = FD->param_begin(),
128711abcecc8c919673237cf37384290a1ef1943976Ted Kremenek                                         PE = FD->param_end();
128811abcecc8c919673237cf37384290a1ef1943976Ted Kremenek      CallExpr::const_arg_iterator AI = CE->arg_begin(), AE = CE->arg_end();
128911abcecc8c919673237cf37384290a1ef1943976Ted Kremenek      for (; AI != AE && PI != PE; ++AI, ++PI) {
129011abcecc8c919673237cf37384290a1ef1943976Ted Kremenek        if (const Expr *ArgE = *AI) {
129111abcecc8c919673237cf37384290a1ef1943976Ted Kremenek          if (const ParmVarDecl *PD = *PI) {
129211abcecc8c919673237cf37384290a1ef1943976Ted Kremenek            Loc LV = State->getLValue(PD, CalleeCtx);
129311abcecc8c919673237cf37384290a1ef1943976Ted Kremenek            if (R.isInteresting(LV) || R.isInteresting(State->getRawSVal(LV)))
129411abcecc8c919673237cf37384290a1ef1943976Ted Kremenek              IE.insert(ArgE);
129511abcecc8c919673237cf37384290a1ef1943976Ted Kremenek          }
129611abcecc8c919673237cf37384290a1ef1943976Ted Kremenek        }
129711abcecc8c919673237cf37384290a1ef1943976Ted Kremenek      }
129811abcecc8c919673237cf37384290a1ef1943976Ted Kremenek    }
129911abcecc8c919673237cf37384290a1ef1943976Ted Kremenek  }
130011abcecc8c919673237cf37384290a1ef1943976Ted Kremenek}
13018185674528423e2504a1fae35c28c24104846510Ted Kremenek
1302b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek//===----------------------------------------------------------------------===//
1303b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek// Functions for determining if a loop was executed 0 times.
1304b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek//===----------------------------------------------------------------------===//
1305b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek
13068185674528423e2504a1fae35c28c24104846510Ted Kremenek/// Return true if the terminator is a loop and the destination is the
13078185674528423e2504a1fae35c28c24104846510Ted Kremenek/// false branch.
13088185674528423e2504a1fae35c28c24104846510Ted Kremenekstatic bool isLoopJumpPastBody(const Stmt *Term, const BlockEdge *BE) {
13098185674528423e2504a1fae35c28c24104846510Ted Kremenek  switch (Term->getStmtClass()) {
13108185674528423e2504a1fae35c28c24104846510Ted Kremenek    case Stmt::ForStmtClass:
13118185674528423e2504a1fae35c28c24104846510Ted Kremenek    case Stmt::WhileStmtClass:
1312c5b9c8bc6d77175f6d41d898511b1e7b1e2f86f8Ted Kremenek    case Stmt::ObjCForCollectionStmtClass:
13138185674528423e2504a1fae35c28c24104846510Ted Kremenek      break;
13148185674528423e2504a1fae35c28c24104846510Ted Kremenek    default:
13158185674528423e2504a1fae35c28c24104846510Ted Kremenek      // Note that we intentionally do not include do..while here.
13168185674528423e2504a1fae35c28c24104846510Ted Kremenek      return false;
13178185674528423e2504a1fae35c28c24104846510Ted Kremenek  }
13188185674528423e2504a1fae35c28c24104846510Ted Kremenek
13198185674528423e2504a1fae35c28c24104846510Ted Kremenek  // Did we take the false branch?
13208185674528423e2504a1fae35c28c24104846510Ted Kremenek  const CFGBlock *Src = BE->getSrc();
13218185674528423e2504a1fae35c28c24104846510Ted Kremenek  assert(Src->succ_size() == 2);
13228185674528423e2504a1fae35c28c24104846510Ted Kremenek  return (*(Src->succ_begin()+1) == BE->getDst());
13238185674528423e2504a1fae35c28c24104846510Ted Kremenek}
13248185674528423e2504a1fae35c28c24104846510Ted Kremenek
1325b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenekstatic bool isContainedByStmt(ParentMap &PM, const Stmt *S, const Stmt *SubS) {
1326b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek  while (SubS) {
1327b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek    if (SubS == S)
1328b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek      return true;
1329b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek    SubS = PM.getParent(SubS);
1330b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek  }
1331b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek  return false;
1332b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek}
1333b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek
1334b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenekstatic const Stmt *getStmtBeforeCond(ParentMap &PM, const Stmt *Term,
1335b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek                                     const ExplodedNode *N) {
1336b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek  while (N) {
1337b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek    Optional<StmtPoint> SP = N->getLocation().getAs<StmtPoint>();
1338b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek    if (SP) {
1339b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek      const Stmt *S = SP->getStmt();
1340b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek      if (!isContainedByStmt(PM, Term, S))
1341b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek        return S;
1342b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek    }
1343b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek    N = GetPredecessorNode(N);
1344b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek  }
1345b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek  return 0;
1346b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek}
1347b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek
1348b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenekstatic bool isInLoopBody(ParentMap &PM, const Stmt *S, const Stmt *Term) {
1349b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek  const Stmt *LoopBody = 0;
1350b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek  switch (Term->getStmtClass()) {
1351b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek    case Stmt::ForStmtClass: {
1352b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek      const ForStmt *FS = cast<ForStmt>(Term);
1353b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek      if (isContainedByStmt(PM, FS->getInc(), S))
1354b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek        return true;
1355b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek      LoopBody = FS->getBody();
1356b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek      break;
1357b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek    }
1358c5b9c8bc6d77175f6d41d898511b1e7b1e2f86f8Ted Kremenek    case Stmt::ObjCForCollectionStmtClass: {
1359c5b9c8bc6d77175f6d41d898511b1e7b1e2f86f8Ted Kremenek      const ObjCForCollectionStmt *FC = cast<ObjCForCollectionStmt>(Term);
1360c5b9c8bc6d77175f6d41d898511b1e7b1e2f86f8Ted Kremenek      LoopBody = FC->getBody();
1361c5b9c8bc6d77175f6d41d898511b1e7b1e2f86f8Ted Kremenek      break;
1362c5b9c8bc6d77175f6d41d898511b1e7b1e2f86f8Ted Kremenek    }
1363b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek    case Stmt::WhileStmtClass:
1364b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek      LoopBody = cast<WhileStmt>(Term)->getBody();
1365b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek      break;
1366b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek    default:
1367b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek      return false;
1368b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek  }
1369b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek  return isContainedByStmt(PM, LoopBody, S);
1370b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek}
1371b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek
1372b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek//===----------------------------------------------------------------------===//
1373b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek// Top-level logic for generating extensive path diagnostics.
1374b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek//===----------------------------------------------------------------------===//
1375b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek
13768347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rosestatic bool GenerateExtensivePathDiagnostic(PathDiagnostic& PD,
137714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek                                            PathDiagnosticBuilder &PDB,
13783bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose                                            const ExplodedNode *N,
13793bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose                                      ArrayRef<BugReporterVisitor *> visitors) {
138014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  EdgeBuilder EB(PD, PDB);
13810cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks  const SourceManager& SM = PDB.getSourceManager();
138256a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks  StackDiagVector CallStack;
138311abcecc8c919673237cf37384290a1ef1943976Ted Kremenek  InterestingExprs IE;
138414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
13859c378f705405d37f49795d5e915989de774fe11fTed Kremenek  const ExplodedNode *NextNode = N->pred_empty() ? NULL : *(N->pred_begin());
138614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  while (NextNode) {
138714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    N = NextNode;
138814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    NextNode = GetPredecessorNode(N);
138914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek    ProgramPoint P = N->getLocation();
139014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
1391dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek    do {
13927a95de68c093991047ed8d339479ccad51b88663David Blaikie      if (Optional<PostStmt> PS = P.getAs<PostStmt>()) {
139311abcecc8c919673237cf37384290a1ef1943976Ted Kremenek        if (const Expr *Ex = PS->getStmtAs<Expr>())
139411abcecc8c919673237cf37384290a1ef1943976Ted Kremenek          reversePropagateIntererstingSymbols(*PDB.getBugReport(), IE,
139511abcecc8c919673237cf37384290a1ef1943976Ted Kremenek                                              N->getState().getPtr(), Ex,
139611abcecc8c919673237cf37384290a1ef1943976Ted Kremenek                                              N->getLocationContext());
139711abcecc8c919673237cf37384290a1ef1943976Ted Kremenek      }
139811abcecc8c919673237cf37384290a1ef1943976Ted Kremenek
13997a95de68c093991047ed8d339479ccad51b88663David Blaikie      if (Optional<CallExitEnd> CE = P.getAs<CallExitEnd>()) {
1400183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose        const Stmt *S = CE->getCalleeContext()->getCallSite();
1401183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose        if (const Expr *Ex = dyn_cast_or_null<Expr>(S)) {
1402852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose            reversePropagateIntererstingSymbols(*PDB.getBugReport(), IE,
1403852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose                                                N->getState().getPtr(), Ex,
1404852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose                                                N->getLocationContext());
1405852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose        }
1406183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose
1407183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose        PathDiagnosticCallPiece *C =
1408183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose          PathDiagnosticCallPiece::construct(N, *CE, SM);
140980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks        GRBugReporter& BR = PDB.getBugReporter();
141080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks        BR.addCallPieceLocationContextPair(C, CE->getCalleeContext());
1411183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose
1412183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose        EB.addEdge(C->callReturn, true);
1413183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose        EB.flushLocations();
1414183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose
1415183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose        PD.getActivePath().push_front(C);
1416183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose        PD.pushActivePath(&C->path);
1417183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose        CallStack.push_back(StackDiagPair(C, N));
14185de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek        break;
14195de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek      }
14204ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek
14212042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek      // Pop the call hierarchy if we are done walking the contents
14222042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek      // of a function call.
14237a95de68c093991047ed8d339479ccad51b88663David Blaikie      if (Optional<CallEnter> CE = P.getAs<CallEnter>()) {
1424097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted Kremenek        // Add an edge to the start of the function.
1425097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted Kremenek        const Decl *D = CE->getCalleeContext()->getDecl();
1426097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted Kremenek        PathDiagnosticLocation pos =
1427097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted Kremenek          PathDiagnosticLocation::createBegin(D, SM);
1428097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted Kremenek        EB.addEdge(pos);
1429097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted Kremenek
1430097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted Kremenek        // Flush all locations, and pop the active path.
1431183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose        bool VisitedEntireCall = PD.isWithinCall();
14324ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek        EB.flushLocations();
14332042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek        PD.popActivePath();
14344ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek        PDB.LC = N->getLocationContext();
1435097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted Kremenek
1436183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose        // Either we just added a bunch of stuff to the top-level path, or
1437183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose        // we have a previous CallExitEnd.  If the former, it means that the
14382042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek        // path terminated within a function call.  We must then take the
14392042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek        // current contents of the active path and place it within
14402042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek        // a new PathDiagnosticCallPiece.
1441183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose        PathDiagnosticCallPiece *C;
1442183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose        if (VisitedEntireCall) {
1443183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose          C = cast<PathDiagnosticCallPiece>(PD.getActivePath().front());
1444183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose        } else {
1445183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose          const Decl *Caller = CE->getLocationContext()->getDecl();
14469373937945e1e075dfa08169eaccc1ad0b31f699Anna Zaks          C = PathDiagnosticCallPiece::construct(PD.getActivePath(), Caller);
144780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks          GRBugReporter& BR = PDB.getBugReporter();
144880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks          BR.addCallPieceLocationContextPair(C, CE->getCalleeContext());
14499373937945e1e075dfa08169eaccc1ad0b31f699Anna Zaks        }
1450852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose
1451183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose        C->setCallee(*CE, SM);
1452183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose        EB.addContext(C->getLocation());
1453368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks
1454368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks        if (!CallStack.empty()) {
145556a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks          assert(CallStack.back().first == C);
1456368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks          CallStack.pop_back();
1457368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks        }
14582042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek        break;
14592042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek      }
14604ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek
14614ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek      // Note that is important that we update the LocationContext
14624ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek      // after looking at CallExits.  CallExit basically adds an
14634ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek      // edge in the *caller*, so we don't want to update the LocationContext
14644ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek      // too soon.
14654ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek      PDB.LC = N->getLocationContext();
14665de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek
1467dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek      // Block edges.
14687a95de68c093991047ed8d339479ccad51b88663David Blaikie      if (Optional<BlockEdge> BE = P.getAs<BlockEdge>()) {
146911abcecc8c919673237cf37384290a1ef1943976Ted Kremenek        // Does this represent entering a call?  If so, look at propagating
147011abcecc8c919673237cf37384290a1ef1943976Ted Kremenek        // interesting symbols across call boundaries.
147111abcecc8c919673237cf37384290a1ef1943976Ted Kremenek        if (NextNode) {
147211abcecc8c919673237cf37384290a1ef1943976Ted Kremenek          const LocationContext *CallerCtx = NextNode->getLocationContext();
147311abcecc8c919673237cf37384290a1ef1943976Ted Kremenek          const LocationContext *CalleeCtx = PDB.LC;
147411abcecc8c919673237cf37384290a1ef1943976Ted Kremenek          if (CallerCtx != CalleeCtx) {
147511abcecc8c919673237cf37384290a1ef1943976Ted Kremenek            reversePropagateInterestingSymbols(*PDB.getBugReport(), IE,
147611abcecc8c919673237cf37384290a1ef1943976Ted Kremenek                                               N->getState().getPtr(),
147711abcecc8c919673237cf37384290a1ef1943976Ted Kremenek                                               CalleeCtx, CallerCtx);
147811abcecc8c919673237cf37384290a1ef1943976Ted Kremenek          }
147911abcecc8c919673237cf37384290a1ef1943976Ted Kremenek        }
148011abcecc8c919673237cf37384290a1ef1943976Ted Kremenek
1481dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek        // Are we jumping to the head of a loop?  Add a special diagnostic.
1482f57a2aa02c0578c5bd834fec0d44c16ad9908620Ted Kremenek        if (const Stmt *Loop = BE->getSrc()->getLoopTarget()) {
148359950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek          PathDiagnosticLocation L(Loop, SM, PDB.LC);
1484ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek          const CompoundStmt *CS = NULL;
14851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1486f57a2aa02c0578c5bd834fec0d44c16ad9908620Ted Kremenek          if (const ForStmt *FS = dyn_cast<ForStmt>(Loop))
1487f57a2aa02c0578c5bd834fec0d44c16ad9908620Ted Kremenek            CS = dyn_cast<CompoundStmt>(FS->getBody());
1488f57a2aa02c0578c5bd834fec0d44c16ad9908620Ted Kremenek          else if (const WhileStmt *WS = dyn_cast<WhileStmt>(Loop))
1489f57a2aa02c0578c5bd834fec0d44c16ad9908620Ted Kremenek            CS = dyn_cast<CompoundStmt>(WS->getBody());
14901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1491dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek          PathDiagnosticEventPiece *p =
1492dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek            new PathDiagnosticEventPiece(L,
149307c015cbcee31f72e2d320ba2c713c046bed42faTed Kremenek                                        "Looping back to the head of the loop");
14942dd17abf11ae64339fa6bfaa57d76e13a5fbe5b8Ted Kremenek          p->setPrunable(true);
14951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1496dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek          EB.addEdge(p->getLocation(), true);
14972042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek          PD.getActivePath().push_front(p);
14981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1499ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek          if (CS) {
15000cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks            PathDiagnosticLocation BL =
15010cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks              PathDiagnosticLocation::createEndBrace(CS, SM);
150207c015cbcee31f72e2d320ba2c713c046bed42faTed Kremenek            EB.addEdge(BL);
1503dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek          }
15048bd4d037d837e7922c3661d6158229da58a03887Ted Kremenek        }
15058185674528423e2504a1fae35c28c24104846510Ted Kremenek
1506b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek        const CFGBlock *BSrc = BE->getSrc();
1507b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek        ParentMap &PM = PDB.getParentMap();
1508b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek
1509b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek        if (const Stmt *Term = BSrc->getTerminator()) {
15108185674528423e2504a1fae35c28c24104846510Ted Kremenek          // Are we jumping past the loop body without ever executing the
15118185674528423e2504a1fae35c28c24104846510Ted Kremenek          // loop (because the condition was false)?
15127a95de68c093991047ed8d339479ccad51b88663David Blaikie          if (isLoopJumpPastBody(Term, &*BE) &&
1513b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek              !isInLoopBody(PM,
1514b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek                            getStmtBeforeCond(PM,
1515b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek                                              BSrc->getTerminatorCondition(),
1516b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek                                              N),
1517b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek                            Term)) {
15188185674528423e2504a1fae35c28c24104846510Ted Kremenek            PathDiagnosticLocation L(Term, SM, PDB.LC);
15198185674528423e2504a1fae35c28c24104846510Ted Kremenek            PathDiagnosticEventPiece *PE =
1520b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek                new PathDiagnosticEventPiece(L, "Loop body executed 0 times");
15218185674528423e2504a1fae35c28c24104846510Ted Kremenek            PE->setPrunable(true);
15228185674528423e2504a1fae35c28c24104846510Ted Kremenek
15238185674528423e2504a1fae35c28c24104846510Ted Kremenek            EB.addEdge(PE->getLocation(), true);
15248185674528423e2504a1fae35c28c24104846510Ted Kremenek            PD.getActivePath().push_front(PE);
15258185674528423e2504a1fae35c28c24104846510Ted Kremenek          }
15268185674528423e2504a1fae35c28c24104846510Ted Kremenek
1527b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek          // In any case, add the terminator as the current statement
1528b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek          // context for control edges.
1529ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek          EB.addContext(Term);
15308185674528423e2504a1fae35c28c24104846510Ted Kremenek        }
15311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1532dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek        break;
15338bd4d037d837e7922c3661d6158229da58a03887Ted Kremenek      }
153414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
15357a95de68c093991047ed8d339479ccad51b88663David Blaikie      if (Optional<BlockEntrance> BE = P.getAs<BlockEntrance>()) {
1536b07805485c603be3d8011f72611465324c9e664bDavid Blaikie        Optional<CFGElement> First = BE->getFirstElement();
1537b07805485c603be3d8011f72611465324c9e664bDavid Blaikie        if (Optional<CFGStmt> S = First ? First->getAs<CFGStmt>() : None) {
1538b07805485c603be3d8011f72611465324c9e664bDavid Blaikie          const Stmt *stmt = S->getStmt();
15393c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek          if (IsControlFlowExpr(stmt)) {
1540b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu            // Add the proper context for '&&', '||', and '?'.
15413c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek            EB.addContext(stmt);
1542b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu          }
1543b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu          else
15443c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek            EB.addExtendedContext(PDB.getEnclosingStmtLocation(stmt).asStmt());
1545dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek        }
1546b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu
1547dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek        break;
1548dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek      }
15495de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek
15505de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek
1551dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek    } while (0);
15521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1553dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek    if (!NextNode)
155414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek      continue;
15551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
15568e6431adab313e283a992698f6fc7afe62420999Anna Zaks    // Add pieces from custom visitors.
15578e6431adab313e283a992698f6fc7afe62420999Anna Zaks    BugReport *R = PDB.getBugReport();
15583bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose    for (ArrayRef<BugReporterVisitor *>::iterator I = visitors.begin(),
15593bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose                                                  E = visitors.end();
15603bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose         I != E; ++I) {
15618e6431adab313e283a992698f6fc7afe62420999Anna Zaks      if (PathDiagnosticPiece *p = (*I)->VisitNode(N, NextNode, PDB, *R)) {
15628966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek        const PathDiagnosticLocation &Loc = p->getLocation();
15638966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek        EB.addEdge(Loc, true);
15642042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek        PD.getActivePath().push_front(p);
1565368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks        updateStackPiecesWithMessage(p, CallStack);
1566368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks
15678966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek        if (const Stmt *S = Loc.asStmt())
15681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump          EB.addExtendedContext(PDB.getEnclosingStmtLocation(S).asStmt());
15698966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek      }
15701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    }
157114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek  }
15728347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose
15738347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose  return PDB.getBugReport()->isValid();
157414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek}
157514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek
15765fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek//===----------------------------------------------------------------------===//
15773106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// Methods for BugType and subclasses.
15783106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===//
1579404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios KyrtzidisBugType::~BugType() { }
1580404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis
15813106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenekvoid BugType::FlushReports(BugReporter &BR) {}
15823106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
158399ba9e3bd70671f3441fb974895f226a83ce0e66David Blaikievoid BuiltinBug::anchor() {}
158499ba9e3bd70671f3441fb974895f226a83ce0e66David Blaikie
15853106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===//
15863106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// Methods for BugReport and subclasses.
15873106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===//
1588e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks
158999ba9e3bd70671f3441fb974895f226a83ce0e66David Blaikievoid BugReport::NodeResolver::anchor() {}
159099ba9e3bd70671f3441fb974895f226a83ce0e66David Blaikie
15918e6431adab313e283a992698f6fc7afe62420999Anna Zaksvoid BugReport::addVisitor(BugReporterVisitor* visitor) {
15928e6431adab313e283a992698f6fc7afe62420999Anna Zaks  if (!visitor)
15938e6431adab313e283a992698f6fc7afe62420999Anna Zaks    return;
15948e6431adab313e283a992698f6fc7afe62420999Anna Zaks
15958e6431adab313e283a992698f6fc7afe62420999Anna Zaks  llvm::FoldingSetNodeID ID;
15968e6431adab313e283a992698f6fc7afe62420999Anna Zaks  visitor->Profile(ID);
15978e6431adab313e283a992698f6fc7afe62420999Anna Zaks  void *InsertPos;
15988e6431adab313e283a992698f6fc7afe62420999Anna Zaks
15998e6431adab313e283a992698f6fc7afe62420999Anna Zaks  if (CallbacksSet.FindNodeOrInsertPos(ID, InsertPos)) {
16008e6431adab313e283a992698f6fc7afe62420999Anna Zaks    delete visitor;
16018e6431adab313e283a992698f6fc7afe62420999Anna Zaks    return;
16028e6431adab313e283a992698f6fc7afe62420999Anna Zaks  }
16038e6431adab313e283a992698f6fc7afe62420999Anna Zaks
16048e6431adab313e283a992698f6fc7afe62420999Anna Zaks  CallbacksSet.InsertNode(visitor, InsertPos);
16053bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose  Callbacks.push_back(visitor);
16063bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose  ++ConfigurationChangeToken;
16078e6431adab313e283a992698f6fc7afe62420999Anna Zaks}
16088e6431adab313e283a992698f6fc7afe62420999Anna Zaks
16098e6431adab313e283a992698f6fc7afe62420999Anna ZaksBugReport::~BugReport() {
16108e6431adab313e283a992698f6fc7afe62420999Anna Zaks  for (visitor_iterator I = visitor_begin(), E = visitor_end(); I != E; ++I) {
1611dc757b049796949e4b11646445a6598f0bdabd7aAnna Zaks    delete *I;
16128e6431adab313e283a992698f6fc7afe62420999Anna Zaks  }
1613c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek  while (!interestingSymbols.empty()) {
1614c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek    popInterestingSymbolsAndRegions();
1615c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek  }
16168e6431adab313e283a992698f6fc7afe62420999Anna Zaks}
1617e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks
161807189521a15d9c088216b943649cb9fe231cbb57Ted Kremenekconst Decl *BugReport::getDeclWithIssue() const {
161907189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek  if (DeclWithIssue)
162007189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek    return DeclWithIssue;
162107189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek
162207189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek  const ExplodedNode *N = getErrorNode();
162307189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek  if (!N)
162407189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek    return 0;
162507189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek
162607189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek  const LocationContext *LC = N->getLocationContext();
162707189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek  return LC->getCurrentStackFrame()->getDecl();
162807189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek}
162907189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek
1630e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaksvoid BugReport::Profile(llvm::FoldingSetNodeID& hash) const {
1631e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks  hash.AddPointer(&BT);
1632e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks  hash.AddString(Description);
163397bfb558f69c09b01a5c1510f08dc91eb62329a7Anna Zaks  PathDiagnosticLocation UL = getUniqueingLocation();
163497bfb558f69c09b01a5c1510f08dc91eb62329a7Anna Zaks  if (UL.isValid()) {
163597bfb558f69c09b01a5c1510f08dc91eb62329a7Anna Zaks    UL.Profile(hash);
1636ca8e36eb637e232475ef31c3f22d5da907390917Anna Zaks  } else if (Location.isValid()) {
1637590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks    Location.Profile(hash);
1638590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks  } else {
1639590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks    assert(ErrorNode);
1640590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks    hash.AddPointer(GetCurrentOrPreviousStmt(ErrorNode));
1641590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks  }
1642e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks
1643e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks  for (SmallVectorImpl<SourceRange>::const_iterator I =
1644e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks      Ranges.begin(), E = Ranges.end(); I != E; ++I) {
1645e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks    const SourceRange range = *I;
1646e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks    if (!range.isValid())
1647e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks      continue;
1648e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks    hash.AddInteger(range.getBegin().getRawEncoding());
1649e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks    hash.AddInteger(range.getEnd().getRawEncoding());
1650e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks  }
1651e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks}
16523106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
165376aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenekvoid BugReport::markInteresting(SymbolRef sym) {
165476aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek  if (!sym)
165576aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek    return;
16563bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose
16573bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose  // If the symbol wasn't already in our set, note a configuration change.
1658c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek  if (getInterestingSymbols().insert(sym).second)
16593bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose    ++ConfigurationChangeToken;
16608ec588e2ac57311604cf80608c7d4b3fb3b022f7Jordy Rose
16618ec588e2ac57311604cf80608c7d4b3fb3b022f7Jordy Rose  if (const SymbolMetadata *meta = dyn_cast<SymbolMetadata>(sym))
1662c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek    getInterestingRegions().insert(meta->getRegion());
166376aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek}
166476aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek
166576aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenekvoid BugReport::markInteresting(const MemRegion *R) {
166676aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek  if (!R)
166776aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek    return;
16683bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose
16693bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose  // If the base region wasn't already in our set, note a configuration change.
167076aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek  R = R->getBaseRegion();
1671c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek  if (getInterestingRegions().insert(R).second)
16723bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose    ++ConfigurationChangeToken;
16738ec588e2ac57311604cf80608c7d4b3fb3b022f7Jordy Rose
167476aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek  if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R))
1675c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek    getInterestingSymbols().insert(SR->getSymbol());
167676aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek}
167776aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek
167876aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenekvoid BugReport::markInteresting(SVal V) {
167976aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek  markInteresting(V.getAsRegion());
168076aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek  markInteresting(V.getAsSymbol());
168176aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek}
168276aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek
168380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaksvoid BugReport::markInteresting(const LocationContext *LC) {
168480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks  if (!LC)
168580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks    return;
168680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks  InterestingLocationContexts.insert(LC);
168780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks}
168880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks
1689c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenekbool BugReport::isInteresting(SVal V) {
169076aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek  return isInteresting(V.getAsRegion()) || isInteresting(V.getAsSymbol());
169176aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek}
169276aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek
1693c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenekbool BugReport::isInteresting(SymbolRef sym) {
169476aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek  if (!sym)
169576aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek    return false;
16968ec588e2ac57311604cf80608c7d4b3fb3b022f7Jordy Rose  // We don't currently consider metadata symbols to be interesting
16978ec588e2ac57311604cf80608c7d4b3fb3b022f7Jordy Rose  // even if we know their region is interesting. Is that correct behavior?
1698c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek  return getInterestingSymbols().count(sym);
169976aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek}
170076aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek
1701c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenekbool BugReport::isInteresting(const MemRegion *R) {
170276aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek  if (!R)
170376aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek    return false;
170476aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek  R = R->getBaseRegion();
1705c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek  bool b = getInterestingRegions().count(R);
170676aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek  if (b)
170776aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek    return true;
170876aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek  if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R))
1709c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek    return getInterestingSymbols().count(SR->getSymbol());
171076aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek  return false;
171176aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek}
1712c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek
171380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaksbool BugReport::isInteresting(const LocationContext *LC) {
171480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks  if (!LC)
171580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks    return false;
171680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks  return InterestingLocationContexts.count(LC);
171780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks}
171880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks
1719c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenekvoid BugReport::lazyInitializeInterestingSets() {
1720c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek  if (interestingSymbols.empty()) {
1721c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek    interestingSymbols.push_back(new Symbols());
1722c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek    interestingRegions.push_back(new Regions());
1723c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek  }
1724c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek}
1725c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek
1726c4bac8e376b98d633bb00ee5f510d5e58449753cTed KremenekBugReport::Symbols &BugReport::getInterestingSymbols() {
1727c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek  lazyInitializeInterestingSets();
1728c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek  return *interestingSymbols.back();
1729c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek}
1730c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek
1731c4bac8e376b98d633bb00ee5f510d5e58449753cTed KremenekBugReport::Regions &BugReport::getInterestingRegions() {
1732c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek  lazyInitializeInterestingSets();
1733c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek  return *interestingRegions.back();
1734c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek}
1735c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek
1736c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenekvoid BugReport::pushInterestingSymbolsAndRegions() {
1737c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek  interestingSymbols.push_back(new Symbols(getInterestingSymbols()));
1738c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek  interestingRegions.push_back(new Regions(getInterestingRegions()));
1739c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek}
1740c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek
1741c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenekvoid BugReport::popInterestingSymbolsAndRegions() {
1742c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek  delete interestingSymbols.back();
1743c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek  interestingSymbols.pop_back();
1744c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek  delete interestingRegions.back();
1745c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek  interestingRegions.pop_back();
1746c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek}
174776aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek
17489c378f705405d37f49795d5e915989de774fe11fTed Kremenekconst Stmt *BugReport::getStmt() const {
1749e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks  if (!ErrorNode)
1750e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks    return 0;
1751e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks
1752212f6d3b5fb3fa55ba1e40671cfc336430abc8ddTom Care  ProgramPoint ProgP = ErrorNode->getLocation();
17535f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek  const Stmt *S = NULL;
17541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
17557a95de68c093991047ed8d339479ccad51b88663David Blaikie  if (Optional<BlockEntrance> BE = ProgP.getAs<BlockEntrance>()) {
1756fafd3834754d2093e0ad7a1c005860fd527ecb7fZhongxing Xu    CFGBlock &Exit = ProgP.getLocationContext()->getCFG()->getExit();
175750d5bc4e3b53eb8bb4ebf198f1213348a3fa0f38Zhongxing Xu    if (BE->getBlock() == &Exit)
1758212f6d3b5fb3fa55ba1e40671cfc336430abc8ddTom Care      S = GetPreviousStmt(ErrorNode);
17593106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  }
17605f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek  if (!S)
17611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    S = GetStmt(ProgP);
17621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
17631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  return S;
17643106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek}
17653106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
1766640ccf071076e684713cc3c3276bb51982bff607Argyrios Kyrtzidisstd::pair<BugReport::ranges_iterator, BugReport::ranges_iterator>
1767e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna ZaksBugReport::getRanges() {
1768e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks    // If no custom ranges, add the range of the statement corresponding to
1769e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks    // the error node.
1770e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks    if (Ranges.empty()) {
1771e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks      if (const Expr *E = dyn_cast_or_null<Expr>(getStmt()))
1772e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks        addRange(E->getSourceRange());
1773e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks      else
1774e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks        return std::make_pair(ranges_iterator(), ranges_iterator());
1775e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks    }
1776e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks
177714924267950e75c6c1f6fcea39fa507b7168bc39Anna Zaks    // User-specified absence of range info.
177814924267950e75c6c1f6fcea39fa507b7168bc39Anna Zaks    if (Ranges.size() == 1 && !Ranges.begin()->isValid())
177914924267950e75c6c1f6fcea39fa507b7168bc39Anna Zaks      return std::make_pair(ranges_iterator(), ranges_iterator());
178014924267950e75c6c1f6fcea39fa507b7168bc39Anna Zaks
1781e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks    return std::make_pair(Ranges.begin(), Ranges.end());
17823106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek}
17833106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
1784590dd8e0959d8df5621827768987c4792b74fc06Anna ZaksPathDiagnosticLocation BugReport::getLocation(const SourceManager &SM) const {
1785b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks  if (ErrorNode) {
1786590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks    assert(!Location.isValid() &&
1787b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks     "Either Location or ErrorNode should be specified but not both.");
1788b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks
17899c378f705405d37f49795d5e915989de774fe11fTed Kremenek    if (const Stmt *S = GetCurrentOrPreviousStmt(ErrorNode)) {
1790590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks      const LocationContext *LC = ErrorNode->getLocationContext();
1791590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks
17923106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      // For member expressions, return the location of the '.' or '->'.
17935b9bd2137ebef350af803c634e3fdf5d74678100Ted Kremenek      if (const MemberExpr *ME = dyn_cast<MemberExpr>(S))
1794590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks        return PathDiagnosticLocation::createMemberLoc(ME, SM);
17955b9bd2137ebef350af803c634e3fdf5d74678100Ted Kremenek      // For binary operators, return the location of the operator.
17965b9bd2137ebef350af803c634e3fdf5d74678100Ted Kremenek      if (const BinaryOperator *B = dyn_cast<BinaryOperator>(S))
1797590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks        return PathDiagnosticLocation::createOperatorLoc(B, SM);
17983106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
17997a95de68c093991047ed8d339479ccad51b88663David Blaikie      if (ErrorNode->getLocation().getAs<PostStmtPurgeDeadSymbols>())
180063bc186d6ac0b44ba4ec6fccb5f471b05c79b666Jordan Rose        return PathDiagnosticLocation::createEnd(S, SM, LC);
180163bc186d6ac0b44ba4ec6fccb5f471b05c79b666Jordan Rose
1802590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks      return PathDiagnosticLocation::createBegin(S, SM, LC);
18033106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    }
1804b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks  } else {
1805b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks    assert(Location.isValid());
1806b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks    return Location;
1807b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks  }
1808b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks
1809590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks  return PathDiagnosticLocation();
18103106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek}
18113106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
18123106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===//
18133106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// Methods for BugReporter and subclasses.
18143106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===//
18153106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
18164a5f724538cbc275370c9504e8169ce92503256cBenjamin KramerBugReportEquivClass::~BugReportEquivClass() { }
1817a2f4ec0df645fc249d2945beef9653f03b175417Zhongxing XuGRBugReporter::~GRBugReporter() { }
18183106198188ac6eb2753f1764d5c28376b0b76351Ted KremenekBugReporterData::~BugReporterData() {}
18193106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
182038b02b912e1a55c912f603c4369431264d36a381Zhongxing XuExplodedGraph &GRBugReporter::getGraph() { return Eng.getGraph(); }
18213106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
182218c66fdc3c4008d335885695fe36fb5353c5f672Ted KremenekProgramStateManager&
18233106198188ac6eb2753f1764d5c28376b0b76351Ted KremenekGRBugReporter::getStateManager() { return Eng.getStateManager(); }
18243106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
18253b030a28cda2b953758507769c1d436bec5ec45eAnna ZaksBugReporter::~BugReporter() {
18263b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks  FlushReports();
18273b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks
18283b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks  // Free the bug reports we are tracking.
18293b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks  typedef std::vector<BugReportEquivClass *> ContTy;
18303b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks  for (ContTy::iterator I = EQClassesVector.begin(), E = EQClassesVector.end();
18313b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks       I != E; ++I) {
18323b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks    delete *I;
18333b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks  }
18343b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks}
18353106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
18363106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenekvoid BugReporter::FlushReports() {
18373106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  if (BugTypes.isEmpty())
18383106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    return;
18393106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
18403106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // First flush the warnings for each BugType.  This may end up creating new
1841404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis  // warnings and new BugTypes.
1842404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis  // FIXME: Only NSErrorChecker needs BugType's FlushReports.
1843404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis  // Turn NSErrorChecker into a proper checker and remove this.
18445f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  SmallVector<const BugType*, 16> bugTypes;
18453106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  for (BugTypesTy::iterator I=BugTypes.begin(), E=BugTypes.end(); I!=E; ++I)
1846404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis    bugTypes.push_back(*I);
18475f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  for (SmallVector<const BugType*, 16>::iterator
1848404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis         I = bugTypes.begin(), E = bugTypes.end(); I != E; ++I)
18493106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    const_cast<BugType*>(*I)->FlushReports(*this);
18503106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
1851d015f4febe85d3e3340172d70042840c51bbd836Anna Zaks  // We need to flush reports in deterministic order to ensure the order
1852d015f4febe85d3e3340172d70042840c51bbd836Anna Zaks  // of the reports is consistent between runs.
18530eb6c37dd4e4ad8fa2363003dea270f9fd6c2969Anna Zaks  typedef std::vector<BugReportEquivClass *> ContVecTy;
18540eb6c37dd4e4ad8fa2363003dea270f9fd6c2969Anna Zaks  for (ContVecTy::iterator EI=EQClassesVector.begin(), EE=EQClassesVector.end();
18550eb6c37dd4e4ad8fa2363003dea270f9fd6c2969Anna Zaks       EI != EE; ++EI){
18560eb6c37dd4e4ad8fa2363003dea270f9fd6c2969Anna Zaks    BugReportEquivClass& EQ = **EI;
1857404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis    FlushReport(EQ);
18583106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  }
18593106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
1860404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis  // BugReporter owns and deletes only BugTypes created implicitly through
1861404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis  // EmitBasicReport.
1862404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis  // FIXME: There are leaks from checkers that assume that the BugTypes they
1863404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis  // create will be destroyed by the BugReporter.
1864404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis  for (llvm::StringMap<BugType*>::iterator
1865404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis         I = StrBugTypes.begin(), E = StrBugTypes.end(); I != E; ++I)
1866404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis    delete I->second;
1867404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis
18683106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // Remove all references to the BugType objects.
18693baf672378f105602d2b12f03f00277ae1936fe9Ted Kremenek  BugTypes = F.getEmptySet();
18703106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek}
18713106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
18723106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===//
18733106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// PathDiagnostics generation.
18743106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===//
18753106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
18761efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rosenamespace {
18771efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose/// A wrapper around a report graph, which contains only a single path, and its
18781efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose/// node maps.
18791efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Roseclass ReportGraph {
18801efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rosepublic:
18811efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose  OwningPtr<ExplodedGraph> Graph;
18821efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose  InterExplodedGraphMap BackMap;
18831efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose  ExplodedNode *ErrorNode;
18841efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose  size_t Index;
18851efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose};
18861efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose
18871efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose/// A wrapper around a trimmed graph and its node maps.
18881efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Roseclass TrimmedGraph {
18891efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose  InterExplodedGraphMap ForwardMap;
18901efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose  InterExplodedGraphMap InverseMap;
1891a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose
1892a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose  typedef llvm::DenseMap<const ExplodedNode *, unsigned> PriorityMapTy;
1893a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose  PriorityMapTy PriorityMap;
1894a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose
18951efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose  OwningPtr<ExplodedGraph> G;
1896a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose  const ExplodedNode *Root;
18971efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rosepublic:
18981efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose  TrimmedGraph(const ExplodedGraph *OriginalGraph,
1899a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose               ArrayRef<const ExplodedNode *> Nodes);
19001efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose
19011efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose  void createBestReportGraph(ArrayRef<const ExplodedNode *> Nodes,
19021efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose                             ReportGraph &GraphWrapper) const;
1903a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose
1904a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose  void removeErrorNode(const ExplodedNode *Node);
19051efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose};
19061efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose
19071efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose}
19081efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose
1909a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan RoseTrimmedGraph::TrimmedGraph(const ExplodedGraph *OriginalGraph,
1910a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose                           ArrayRef<const ExplodedNode *> Nodes) {
1911a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose  // The trimmed graph is created in the body of the constructor to ensure
1912a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose  // that the DenseMaps have been initialized already.
1913a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose  G.reset(OriginalGraph->trim(Nodes, &ForwardMap, &InverseMap));
19141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
19153106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // Find the (first) error node in the trimmed graph.  We just need to consult
19161efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose  // the node map which maps from nodes in the original graph to nodes
19173106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // in the new graph.
1918a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose  std::queue<std::pair<const ExplodedNode *, unsigned> > WS;
19191efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose  typedef llvm::SmallDenseMap<const ExplodedNode *, size_t, 32> IndexMapTy;
1920a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose  IndexMapTy IndexMap(llvm::NextPowerOf2(Nodes.size() + 1));
19213106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
19221efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose  for (unsigned i = 0, count = Nodes.size(); i < count; ++i) {
19231efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose    const ExplodedNode *OriginalNode = Nodes[i];
19241efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose    if (const ExplodedNode *N = ForwardMap.lookup(OriginalNode)) {
1925a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose      WS.push(std::make_pair(N, 0));
19261efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose      IndexMap[OriginalNode] = i;
19273106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    }
192840406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  }
19291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1930938332c657390d1e782e0adc03b092993edae962Ted Kremenek  assert(!WS.empty() && "No error node found in the trimmed graph.");
19313106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
1932a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose  // Perform a reverse BFS to find all the shortest paths.
1933a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose  Root = 0;
19343106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  while (!WS.empty()) {
1935a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose    const ExplodedNode *Node;
1936a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose    unsigned Priority;
1937a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose    llvm::tie(Node, Priority) = WS.front();
19383106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    WS.pop();
19391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1940a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose    PriorityMapTy::iterator I = PriorityMap.find(Node);
1941a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose    if (I != PriorityMap.end()) {
1942a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose      assert(I->second <= Priority);
19433106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      continue;
1944a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose    }
19451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1946a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose    PriorityMap[Node] = Priority;
19471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1948a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose    if (Node->pred_empty())
19493106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      Root = Node;
19501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1951a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose    for (ExplodedNode::const_pred_iterator I = Node->pred_begin(),
1952a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose                                           E = Node->pred_end();
1953a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose         I != E; ++I)
1954a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose      WS.push(std::make_pair(*I, Priority + 1));
19553106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  }
1956a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose
1957938332c657390d1e782e0adc03b092993edae962Ted Kremenek  assert(Root);
1958a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose}
1959a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose
1960a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rosevoid TrimmedGraph::createBestReportGraph(ArrayRef<const ExplodedNode *> Nodes,
1961a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose                                         ReportGraph &GraphWrapper) const {
1962a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose  assert(!GraphWrapper.Graph && "ReportGraph is already in use");
1963a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose  assert(GraphWrapper.BackMap.empty() && "ReportGraph is already in use");
1964a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose
1965a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose  // Find the (first) error node in the trimmed graph.  We just need to consult
1966a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose  // the node map which maps from nodes in the original graph to nodes
1967a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose  // in the new graph.
1968a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose  std::queue<std::pair<const ExplodedNode *, unsigned> > WS;
1969a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose  typedef llvm::SmallDenseMap<const ExplodedNode *, size_t, 32> IndexMapTy;
1970a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose  IndexMapTy IndexMap(llvm::NextPowerOf2(Nodes.size() + 1));
1971a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose
1972a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose  for (unsigned i = 0, count = Nodes.size(); i < count; ++i) {
1973a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose    const ExplodedNode *OriginalNode = Nodes[i];
1974a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose    if (const ExplodedNode *N = ForwardMap.lookup(OriginalNode)) {
1975a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose      WS.push(std::make_pair(N, 0));
1976a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose      IndexMap[OriginalNode] = i;
1977a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose    }
1978a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose  }
1979a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose
1980a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose  assert(!WS.empty() && "No error node found in the trimmed graph.");
1981a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose
1982a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose  // Create a new graph with a single path.  This is the graph
1983a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose  // that will be returned to the caller.
1984a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose  ExplodedGraph *GNew = new ExplodedGraph();
1985a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose  GraphWrapper.Graph.reset(GNew);
19861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
19873106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // Now walk from the root down the BFS path, always taking the successor
19883106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // with the lowest number.
19891efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose  ExplodedNode *Last = 0;
1990c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu  for ( const ExplodedNode *N = Root ;;) {
19913106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // Lookup the number associated with the current node.
1992a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose    PriorityMapTy::const_iterator I = PriorityMap.find(N);
1993a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose    assert(I != PriorityMap.end());
19941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
19953106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // Create the equivalent node in the new graph with the same state
19963106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // and location.
19979c378f705405d37f49795d5e915989de774fe11fTed Kremenek    ExplodedNode *NewN = GNew->getNode(N->getLocation(), N->getState());
19981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
19993106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // Store the mapping to the original node.
20001efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose    InterExplodedGraphMap::const_iterator IMitr = InverseMap.find(N);
20013106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    assert(IMitr != InverseMap.end() && "No mapping to original node.");
20021efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose    GraphWrapper.BackMap[NewN] = IMitr->second;
20031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
20043106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // Link up the new node with the previous node.
20053106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    if (Last)
20065fe4d9deb543a19f557e3d85c5f33867af97cd96Ted Kremenek      NewN->addPredecessor(Last, *GNew);
20071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
20083106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    Last = NewN;
20091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
20103106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // Are we at the final node?
20111efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose    IndexMapTy::iterator IMI = IndexMap.find(IMitr->second);
2012938332c657390d1e782e0adc03b092993edae962Ted Kremenek    if (IMI != IndexMap.end()) {
20131efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose      GraphWrapper.ErrorNode = NewN;
20141efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose      GraphWrapper.Index = IMI->second;
20153106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      break;
20163106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    }
20171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
20183106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // Find the next successor node.  We choose the node that is marked
20193106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // with the lowest DFS number.
20201efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose    unsigned MinVal = -1U;
20211efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose    for (ExplodedNode::const_succ_iterator SI = N->succ_begin(),
20221efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose                                           SE = N->succ_end();
20231efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose         SI != SE; ++SI) {
2024a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose      I = PriorityMap.find(*SI);
20251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2026a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose      if (I == PriorityMap.end())
20273106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        continue;
20281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
20291efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose      if (I->second < MinVal) {
20303106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        N = *SI;
20313106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        MinVal = I->second;
20323106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      }
20333106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    }
20341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
20351efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose    assert(MinVal != -1U);
20363106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  }
20373106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek}
2038d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek
2039a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rosevoid TrimmedGraph::removeErrorNode(const ExplodedNode *ErrorNode) {
2040a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose  ErrorNode = ForwardMap[ErrorNode];
2041a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose  assert(ErrorNode && "not an error node");
2042a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose
2043a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose  PriorityMapTy::iterator PriorityEntry = PriorityMap.find(ErrorNode);
2044a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose  assert(PriorityEntry != PriorityMap.end() && "error node already removed");
2045a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose  PriorityMap.erase(PriorityEntry);
2046a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose
2047a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose  std::queue<const ExplodedNode *> WS;
2048a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose  for (ExplodedNode::const_pred_iterator PI = ErrorNode->pred_begin(),
2049a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose                                         PE = ErrorNode->pred_end();
2050a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose       PI != PE; ++PI) {
2051a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose    assert(PriorityMap.find(*PI) != PriorityMap.end());
2052a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose    WS.push(*PI);
2053a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose  }
2054a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose
2055a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose  // Update all nodes possibly affected by this change.
2056a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose  while (!WS.empty()) {
2057a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose    const ExplodedNode *N = WS.front();
2058a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose    WS.pop();
2059a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose
2060a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose    unsigned MinPriority = -1U;
2061a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose    for (ExplodedNode::const_succ_iterator SI = N->succ_begin(),
2062a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose                                           SE = N->succ_end();
2063a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose         SI != SE; ++SI) {
2064a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose      PriorityMapTy::iterator SuccEntry = PriorityMap.find(*SI);
2065a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose      if (SuccEntry == PriorityMap.end())
2066a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose        continue;
2067a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose      MinPriority = std::min(SuccEntry->second, MinPriority);
2068a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose    }
2069a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose
2070a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose    if (MinPriority == -1U)
2071a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose      PriorityMap.erase(N);
2072a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose    else if (PriorityMap[N] == MinPriority + 1)
2073a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose      continue;
2074a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose    else
2075a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose      PriorityMap[N] = MinPriority + 1;
2076a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose
2077a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose    for (ExplodedNode::const_pred_iterator PI = N->pred_begin(),
2078a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose                                           PE = N->pred_end();
2079a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose         PI != PE; ++PI) {
2080a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose      assert(PriorityMap.find(*PI) != PriorityMap.end());
2081a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose      WS.push(*PI);
2082a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose    }
2083a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose  }
2084a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose}
2085a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose
2086a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose
20873106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek/// CompactPathDiagnostic - This function postprocesses a PathDiagnostic object
20883106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek///  and collapses PathDiagosticPieces that are expanded by macros.
208977d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenekstatic void CompactPathDiagnostic(PathPieces &path, const SourceManager& SM) {
20902042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek  typedef std::vector<std::pair<IntrusiveRefCntPtr<PathDiagnosticMacroPiece>,
20912042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek                                SourceLocation> > MacroStackTy;
20921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2093c93dc7889644293e318e19d82830ea2acc45b678Dylan Noblesmith  typedef std::vector<IntrusiveRefCntPtr<PathDiagnosticPiece> >
20943106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek          PiecesTy;
20951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
20963106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  MacroStackTy MacroStack;
20973106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  PiecesTy Pieces;
20981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
209977d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek  for (PathPieces::const_iterator I = path.begin(), E = path.end();
21002042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek       I!=E; ++I) {
210177d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek
210277d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek    PathDiagnosticPiece *piece = I->getPtr();
210377d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek
210477d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek    // Recursively compact calls.
210577d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek    if (PathDiagnosticCallPiece *call=dyn_cast<PathDiagnosticCallPiece>(piece)){
210677d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek      CompactPathDiagnostic(call->path, SM);
210777d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek    }
210877d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek
21093106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // Get the location of the PathDiagnosticPiece.
211077d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek    const FullSourceLoc Loc = piece->getLocation().asLocation();
21111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
21123106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // Determine the instantiation location, which is the location we group
21133106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // related PathDiagnosticPieces.
21141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    SourceLocation InstantiationLoc = Loc.isMacroID() ?
2115402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth                                      SM.getExpansionLoc(Loc) :
21163106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek                                      SourceLocation();
21171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
21183106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    if (Loc.isFileID()) {
21193106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      MacroStack.clear();
212077d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek      Pieces.push_back(piece);
21213106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      continue;
21223106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    }
2123706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek
21243106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    assert(Loc.isMacroID());
21251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
21263106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // Is the PathDiagnosticPiece within the same macro group?
21273106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    if (!MacroStack.empty() && InstantiationLoc == MacroStack.back().second) {
212877d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek      MacroStack.back().first->subPieces.push_back(piece);
21293106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      continue;
21303106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    }
2131d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek
21323106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // We aren't in the same group.  Are we descending into a new macro
21333106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // or are part of an old one?
2134c93dc7889644293e318e19d82830ea2acc45b678Dylan Noblesmith    IntrusiveRefCntPtr<PathDiagnosticMacroPiece> MacroGroup;
2135d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek
21363106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    SourceLocation ParentInstantiationLoc = InstantiationLoc.isMacroID() ?
2137402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth                                          SM.getExpansionLoc(Loc) :
21383106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek                                          SourceLocation();
21391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
21403106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // Walk the entire macro stack.
21413106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    while (!MacroStack.empty()) {
21423106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      if (InstantiationLoc == MacroStack.back().second) {
21433106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        MacroGroup = MacroStack.back().first;
21443106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        break;
21453106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      }
21461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
21473106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      if (ParentInstantiationLoc == MacroStack.back().second) {
21483106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        MacroGroup = MacroStack.back().first;
21493106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        break;
215061f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek      }
21511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
21523106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      MacroStack.pop_back();
21536837faa083bebad39aa342f84c2b450fb6410eafTed Kremenek    }
21541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
21553106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    if (!MacroGroup || ParentInstantiationLoc == MacroStack.back().second) {
21563106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      // Create a new macro group and add it to the stack.
2157590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks      PathDiagnosticMacroPiece *NewGroup =
2158590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks        new PathDiagnosticMacroPiece(
215977d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek          PathDiagnosticLocation::createSingleLocation(piece->getLocation()));
21605a429954aedd8a830a70fcea2cb51561673e4fc3Ted Kremenek
21613106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      if (MacroGroup)
2162802e02463b880f53a6e645bde78cc412481ce9e0Ted Kremenek        MacroGroup->subPieces.push_back(NewGroup);
21633106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      else {
21643106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        assert(InstantiationLoc.isFileID());
21653106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek        Pieces.push_back(NewGroup);
21663106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      }
21671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
21683106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      MacroGroup = NewGroup;
21693106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek      MacroStack.push_back(std::make_pair(MacroGroup, InstantiationLoc));
21707dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek    }
21713106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek
21723106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek    // Finally, add the PathDiagnosticPiece to the group.
217377d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek    MacroGroup->subPieces.push_back(piece);
21743106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  }
21751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
21763106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek  // Now take the pieces and construct a new PathDiagnostic.
217777d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek  path.clear();
21781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
217977d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek  for (PiecesTy::iterator I=Pieces.begin(), E=Pieces.end(); I!=E; ++I)
218077d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek    path.push_back(*I);
218161f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek}
218261f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek
21838347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rosebool GRBugReporter::generatePathDiagnostic(PathDiagnostic& PD,
2184c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek                                           PathDiagnosticConsumer &PC,
2185c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek                                           ArrayRef<BugReport *> &bugReports) {
218640406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  assert(!bugReports.empty());
21878347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose
21889a9fe4068eed2fc72ec985e5ae393fb79a8fb9adJordan Rose  bool HasValid = false;
21892f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose  SmallVector<const ExplodedNode *, 32> errorNodes;
2190c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek  for (ArrayRef<BugReport*>::iterator I = bugReports.begin(),
21919a9fe4068eed2fc72ec985e5ae393fb79a8fb9adJordan Rose                                      E = bugReports.end(); I != E; ++I) {
21929a9fe4068eed2fc72ec985e5ae393fb79a8fb9adJordan Rose    if ((*I)->isValid()) {
21939a9fe4068eed2fc72ec985e5ae393fb79a8fb9adJordan Rose      HasValid = true;
21949a9fe4068eed2fc72ec985e5ae393fb79a8fb9adJordan Rose      errorNodes.push_back((*I)->getErrorNode());
21959a9fe4068eed2fc72ec985e5ae393fb79a8fb9adJordan Rose    } else {
21969a9fe4068eed2fc72ec985e5ae393fb79a8fb9adJordan Rose      errorNodes.push_back(0);
21979a9fe4068eed2fc72ec985e5ae393fb79a8fb9adJordan Rose    }
219840406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  }
21991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
22009a9fe4068eed2fc72ec985e5ae393fb79a8fb9adJordan Rose  // If all the reports have been marked invalid by a previous path generation,
22019a9fe4068eed2fc72ec985e5ae393fb79a8fb9adJordan Rose  // we're done.
22029a9fe4068eed2fc72ec985e5ae393fb79a8fb9adJordan Rose  if (!HasValid)
22039a9fe4068eed2fc72ec985e5ae393fb79a8fb9adJordan Rose    return false;
22049a9fe4068eed2fc72ec985e5ae393fb79a8fb9adJordan Rose
22052f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose  typedef PathDiagnosticConsumer::PathGenerationScheme PathGenerationScheme;
22062f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose  PathGenerationScheme ActiveScheme = PC.getGenerationScheme();
22072f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose
22081efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose  TrimmedGraph TrimG(&getGraph(), errorNodes);
22091efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose
22102f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose  for (size_t Remaining = bugReports.size(); Remaining > 0; --Remaining) {
22112f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose    // Construct a new graph that contains only a single path from the error
22122f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose    // node to a root.
22131efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose    ReportGraph ErrorGraph;
22141efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose    TrimG.createBestReportGraph(errorNodes, ErrorGraph);
22152f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose
22162f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose    // Find the BugReport with the original location.
22171efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose    assert(ErrorGraph.Index < bugReports.size());
22181efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose    BugReport *R = bugReports[ErrorGraph.Index];
22192f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose    assert(R && "No original report found for sliced graph.");
22202f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose    assert(R->isValid() && "Report selected by trimmed graph marked invalid.");
22212f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose
22222f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose    // Don't try to reuse this report if it ends up being suppressed.
22231efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose    errorNodes[ErrorGraph.Index] = 0;
22242f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose
22252f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose    // Start building the path diagnostic...
22261efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose    PathDiagnosticBuilder PDB(*this, R, ErrorGraph.BackMap, &PC);
22271efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose    const ExplodedNode *N = ErrorGraph.ErrorNode;
22282f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose
22292f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose    // Register additional node visitors.
22302f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose    R->addVisitor(new NilReceiverBRVisitor());
22312f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose    R->addVisitor(new ConditionBRVisitor());
22322f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose    R->addVisitor(new LikelyFalsePositiveSuppressionBRVisitor());
22332f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose
22342f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose    BugReport::VisitorList visitors;
22352f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose    unsigned origReportConfigToken, finalReportConfigToken;
22362f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose
22372f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose    // While generating diagnostics, it's possible the visitors will decide
22382f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose    // new symbols and regions are interesting, or add other visitors based on
22392f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose    // the information they find. If they do, we need to regenerate the path
22402f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose    // based on our new report configuration.
22412f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose    do {
22422f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose      // Get a clean copy of all the visitors.
22432f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose      for (BugReport::visitor_iterator I = R->visitor_begin(),
22442f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose                                       E = R->visitor_end(); I != E; ++I)
22452f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose        visitors.push_back((*I)->clone());
22462f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose
22472f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose      // Clear out the active path from any previous work.
22482f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose      PD.resetPath();
22492f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose      origReportConfigToken = R->getConfigurationChangeToken();
22502f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose
22512f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose      // Generate the very last diagnostic piece - the piece is visible before
22522f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose      // the trace is expanded.
22532f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose      PathDiagnosticPiece *LastPiece = 0;
22542f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose      for (BugReport::visitor_iterator I = visitors.begin(), E = visitors.end();
22552f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose          I != E; ++I) {
22562f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose        if (PathDiagnosticPiece *Piece = (*I)->getEndPath(PDB, N, *R)) {
22572f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose          assert (!LastPiece &&
22582f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose              "There can only be one final piece in a diagnostic.");
22592f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose          LastPiece = Piece;
22602f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose        }
22613bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose      }
226286ff12c8a8a356ca284ca7687749216fbfd74519Anna Zaks
22632f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose      if (ActiveScheme != PathDiagnosticConsumer::None) {
22642f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose        if (!LastPiece)
22652f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose          LastPiece = BugReporterVisitor::getDefaultEndPath(PDB, N, *R);
22662f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose        assert(LastPiece);
2267d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose        PD.setEndOfPath(LastPiece);
22688347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose      }
22692f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose
22702f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose      switch (ActiveScheme) {
22712f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose      case PathDiagnosticConsumer::Extensive:
22722f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose        GenerateExtensivePathDiagnostic(PD, PDB, N, visitors);
22732f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose        break;
22742f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose      case PathDiagnosticConsumer::Minimal:
22752f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose        GenerateMinimalPathDiagnostic(PD, PDB, N, visitors);
22762f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose        break;
22772f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose      case PathDiagnosticConsumer::None:
22782f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose        GenerateVisitorsOnlyPathDiagnostic(PD, PDB, N, visitors);
22792f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose        break;
2280d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose      }
22813bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose
22822f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose      // Clean up the visitors we used.
22832f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose      llvm::DeleteContainerPointers(visitors);
22843bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose
22852f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose      // Did anything change while generating this path?
22862f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose      finalReportConfigToken = R->getConfigurationChangeToken();
22872f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose    } while (finalReportConfigToken != origReportConfigToken);
22883bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose
2289a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose    if (!R->isValid()) {
2290a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose      TrimG.removeErrorNode(R->getErrorNode());
22912f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose      continue;
2292a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose    }
2293b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek
22942f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose    // Finally, prune the diagnostic path of uninteresting stuff.
22952f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose    if (!PD.path.empty()) {
22962f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose      // Remove messages that are basically the same.
22972f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose      removeRedundantMsgs(PD.getMutablePieces());
22982f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose
22992f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose      if (R->shouldPrunePath() &&
23002f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose          getEngine().getAnalysisManager().options.shouldPrunePaths()) {
23012f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose        bool stillHasNotes = RemoveUnneededCalls(PD.getMutablePieces(), R);
23022f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose        assert(stillHasNotes);
23032f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose        (void)stillHasNotes;
23042f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose      }
23052f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose
23062f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose      adjustCallLocations(PD.getMutablePieces());
2307b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek    }
2308afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose
23092f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose    // We found a report and didn't suppress it.
23102f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose    return true;
2311ed7948b55fa4b2505f240cc5287137f451172b4cTed Kremenek  }
23128347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose
23132f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose  // We suppressed all the reports in this equivalence class.
23142f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose  return false;
23153106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek}
23161aa44c7c9198796085b77c6bdd7c90030845a688Ted Kremenek
2317cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenekvoid BugReporter::Register(BugType *BT) {
23183baf672378f105602d2b12f03f00277ae1936fe9Ted Kremenek  BugTypes = F.add(BugTypes, BT);
231976d90c8bf83d071fd1bdbffa6d9f2af87c6bb7b5Ted Kremenek}
232076d90c8bf83d071fd1bdbffa6d9f2af87c6bb7b5Ted Kremenek
2321785950e59424dca7ce0081bebf13c0acd2c4fff6Jordan Rosevoid BugReporter::emitReport(BugReport* R) {
2322cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  // Compute the bug report's hash to determine its equivalence class.
2323cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  llvm::FoldingSetNodeID ID;
2324cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  R->Profile(ID);
23251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
23261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  // Lookup the equivance class.  If there isn't one, create it.
2327cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  BugType& BT = R->getBugType();
2328cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  Register(&BT);
2329cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  void *InsertPos;
2330404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis  BugReportEquivClass* EQ = EQClasses.FindNodeOrInsertPos(ID, InsertPos);
23311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2332cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  if (!EQ) {
2333cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek    EQ = new BugReportEquivClass(R);
2334404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis    EQClasses.InsertNode(EQ, InsertPos);
23353b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks    EQClassesVector.push_back(EQ);
2336cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  }
2337cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  else
2338cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek    EQ->AddReport(R);
233961f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek}
234061f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek
234106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek
234206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek//===----------------------------------------------------------------------===//
234306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek// Emitting reports in equivalence classes.
234406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek//===----------------------------------------------------------------------===//
234506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek
234606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremeneknamespace {
2347ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamstruct FRIEC_WLItem {
234806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek  const ExplodedNode *N;
234906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek  ExplodedNode::const_succ_iterator I, E;
235006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek
235106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek  FRIEC_WLItem(const ExplodedNode *n)
235206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek  : N(n), I(N->succ_begin()), E(N->succ_end()) {}
235306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek};
235406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek}
235506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek
235661f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenekstatic BugReport *
235761f52bd3c524268e25b48a1ed3730aedd6cc8374Ted KremenekFindReportInEquivalenceClass(BugReportEquivClass& EQ,
23585f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner                             SmallVectorImpl<BugReport*> &bugReports) {
235961f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek
236006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek  BugReportEquivClass::iterator I = EQ.begin(), E = EQ.end();
236106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek  assert(I != E);
23624a5f724538cbc275370c9504e8169ce92503256cBenjamin Kramer  BugType& BT = I->getBugType();
236361f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek
236440406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  // If we don't need to suppress any of the nodes because they are
236540406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  // post-dominated by a sink, simply add all the nodes in the equivalence class
236640406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  // to 'Nodes'.  Any of the reports will serve as a "representative" report.
236761f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek  if (!BT.isSuppressOnSink()) {
23684a5f724538cbc275370c9504e8169ce92503256cBenjamin Kramer    BugReport *R = I;
236961f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek    for (BugReportEquivClass::iterator I=EQ.begin(), E=EQ.end(); I!=E; ++I) {
23709c378f705405d37f49795d5e915989de774fe11fTed Kremenek      const ExplodedNode *N = I->getErrorNode();
237161f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek      if (N) {
23724a5f724538cbc275370c9504e8169ce92503256cBenjamin Kramer        R = I;
237340406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek        bugReports.push_back(R);
237461f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek      }
237561f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek    }
237606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek    return R;
237761f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek  }
237861f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek
237906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek  // For bug reports that should be suppressed when all paths are post-dominated
238006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek  // by a sink node, iterate through the reports in the equivalence class
238106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek  // until we find one that isn't post-dominated (if one exists).  We use a
238206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek  // DFS traversal of the ExplodedGraph to find a non-sink node.  We could write
238306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek  // this as a recursive function, but we don't want to risk blowing out the
238406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek  // stack for very long paths.
238540406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  BugReport *exampleReport = 0;
238661f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek
238706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek  for (; I != E; ++I) {
23884a5f724538cbc275370c9504e8169ce92503256cBenjamin Kramer    const ExplodedNode *errorNode = I->getErrorNode();
238906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek
239040406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek    if (!errorNode)
239106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek      continue;
239240406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek    if (errorNode->isSink()) {
2393b219cfc4d75f0a03630b7c4509ef791b7e97b2c8David Blaikie      llvm_unreachable(
239406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek           "BugType::isSuppressSink() should not be 'true' for sink end nodes");
239506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek    }
239661f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek    // No successors?  By definition this nodes isn't post-dominated by a sink.
239740406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek    if (errorNode->succ_empty()) {
23984a5f724538cbc275370c9504e8169ce92503256cBenjamin Kramer      bugReports.push_back(I);
239940406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek      if (!exampleReport)
24004a5f724538cbc275370c9504e8169ce92503256cBenjamin Kramer        exampleReport = I;
240161f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek      continue;
240261f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek    }
240361f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek
240406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek    // At this point we know that 'N' is not a sink and it has at least one
240506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek    // successor.  Use a DFS worklist to find a non-sink end-of-path node.
240606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek    typedef FRIEC_WLItem WLItem;
24075f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner    typedef SmallVector<WLItem, 10> DFSWorkList;
240806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek    llvm::DenseMap<const ExplodedNode *, unsigned> Visited;
240906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek
241006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek    DFSWorkList WL;
241140406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek    WL.push_back(errorNode);
241240406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek    Visited[errorNode] = 1;
241306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek
241406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek    while (!WL.empty()) {
241506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek      WLItem &WI = WL.back();
241606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek      assert(!WI.N->succ_empty());
241706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek
241806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek      for (; WI.I != WI.E; ++WI.I) {
241906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek        const ExplodedNode *Succ = *WI.I;
242006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek        // End-of-path node?
242106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek        if (Succ->succ_empty()) {
242261f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek          // If we found an end-of-path node that is not a sink.
242361f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek          if (!Succ->isSink()) {
24244a5f724538cbc275370c9504e8169ce92503256cBenjamin Kramer            bugReports.push_back(I);
242540406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek            if (!exampleReport)
24264a5f724538cbc275370c9504e8169ce92503256cBenjamin Kramer              exampleReport = I;
242761f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek            WL.clear();
242861f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek            break;
242961f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek          }
243006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek          // Found a sink?  Continue on to the next successor.
243106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek          continue;
243206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek        }
243306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek        // Mark the successor as visited.  If it hasn't been explored,
243406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek        // enqueue it to the DFS worklist.
243506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek        unsigned &mark = Visited[Succ];
243606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek        if (!mark) {
243706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek          mark = 1;
243806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek          WL.push_back(Succ);
243906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek          break;
244006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek        }
244106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek      }
244261f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek
244361f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek      // The worklist may have been cleared at this point.  First
244461f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek      // check if it is empty before checking the last item.
244561f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek      if (!WL.empty() && &WL.back() == &WI)
244606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek        WL.pop_back();
244706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek    }
244806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek  }
244906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek
245061f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek  // ExampleReport will be NULL if all the nodes in the equivalence class
245161f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek  // were post-dominated by sinks.
245240406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  return exampleReport;
245361f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek}
2454e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek
2455cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenekvoid BugReporter::FlushReport(BugReportEquivClass& EQ) {
24565f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  SmallVector<BugReport*, 10> bugReports;
245740406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  BugReport *exampleReport = FindReportInEquivalenceClass(EQ, bugReports);
2458c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek  if (exampleReport) {
2459c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek    const PathDiagnosticConsumers &C = getPathDiagnosticConsumers();
2460c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek    for (PathDiagnosticConsumers::const_iterator I=C.begin(),
2461c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek                                                 E=C.end(); I != E; ++I) {
2462c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek      FlushReport(exampleReport, **I, bugReports);
2463c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek    }
2464c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek  }
2465c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek}
2466c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek
2467c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenekvoid BugReporter::FlushReport(BugReport *exampleReport,
2468c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek                              PathDiagnosticConsumer &PD,
2469c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek                              ArrayRef<BugReport*> bugReports) {
24701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2471cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  // FIXME: Make sure we use the 'R' for the path that was actually used.
24721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  // Probably doesn't make a difference in practice.
247340406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek  BugType& BT = exampleReport->getBugType();
24741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
24756f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith  OwningPtr<PathDiagnostic>
247607189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek    D(new PathDiagnostic(exampleReport->getDeclWithIssue(),
247707189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek                         exampleReport->getBugType().getName(),
24783a46f5fd1709f6df03bbb8b0abf84052dc0f39ffJordan Rose                         exampleReport->getDescription(),
24793a46f5fd1709f6df03bbb8b0abf84052dc0f39ffJordan Rose                         exampleReport->getShortDescription(/*Fallback=*/false),
248097bfb558f69c09b01a5c1510f08dc91eb62329a7Anna Zaks                         BT.getCategory(),
248197bfb558f69c09b01a5c1510f08dc91eb62329a7Anna Zaks                         exampleReport->getUniqueingLocation(),
248297bfb558f69c09b01a5c1510f08dc91eb62329a7Anna Zaks                         exampleReport->getUniqueingDecl()));
2483d49967f8764135ae65658e354b6d38e3637c9de3Ted Kremenek
2484cc08ca9b3cd2b715a699bcc772ce2e83a502915aJordan Rose  MaxBugClassSize = std::max(bugReports.size(),
2485cc08ca9b3cd2b715a699bcc772ce2e83a502915aJordan Rose                             static_cast<size_t>(MaxBugClassSize));
2486cc08ca9b3cd2b715a699bcc772ce2e83a502915aJordan Rose
2487c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek  // Generate the full path diagnostic, using the generation scheme
2488d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose  // specified by the PathDiagnosticConsumer. Note that we have to generate
2489d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose  // path diagnostics even for consumers which do not support paths, because
2490d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose  // the BugReporterVisitors may mark this bug as a false positive.
2491d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose  if (!bugReports.empty())
2492d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose    if (!generatePathDiagnostic(*D.get(), PD, bugReports))
2493d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose      return;
24943148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek
2495cc08ca9b3cd2b715a699bcc772ce2e83a502915aJordan Rose  MaxValidBugClassSize = std::max(bugReports.size(),
2496cc08ca9b3cd2b715a699bcc772ce2e83a502915aJordan Rose                                  static_cast<size_t>(MaxValidBugClassSize));
2497cc08ca9b3cd2b715a699bcc772ce2e83a502915aJordan Rose
2498c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek  // If the path is empty, generate a single step path with the location
2499c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek  // of the issue.
2500802e02463b880f53a6e645bde78cc412481ce9e0Ted Kremenek  if (D->path.empty()) {
2501c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek    PathDiagnosticLocation L = exampleReport->getLocation(getSourceManager());
2502c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek    PathDiagnosticPiece *piece =
2503c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek      new PathDiagnosticEventPiece(L, exampleReport->getDescription());
2504c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek    BugReport::ranges_iterator Beg, End;
2505c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek    llvm::tie(Beg, End) = exampleReport->getRanges();
250607189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek    for ( ; Beg != End; ++Beg)
250707189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek      piece->addRange(*Beg);
25083a46f5fd1709f6df03bbb8b0abf84052dc0f39ffJordan Rose    D->setEndOfPath(piece);
25093148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek  }
25101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2511c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek  // Get the meta data.
2512c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek  const BugReport::ExtraTextList &Meta = exampleReport->getExtraText();
2513c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek  for (BugReport::ExtraTextList::const_iterator i = Meta.begin(),
2514c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek                                                e = Meta.end(); i != e; ++i) {
2515c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek    D->addMeta(*i);
2516c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek  }
2517c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek
2518c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek  PD.HandlePathDiagnostic(D.take());
251961f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek}
252057202071e477530e9348bc76671ee369b2399b92Ted Kremenek
252107189521a15d9c088216b943649cb9fe231cbb57Ted Kremenekvoid BugReporter::EmitBasicReport(const Decl *DeclWithIssue,
252207189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek                                  StringRef name,
25235f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner                                  StringRef category,
2524590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks                                  StringRef str, PathDiagnosticLocation Loc,
25258c036c7f77d69f96df49219ed0bdbade200d52ebTed Kremenek                                  SourceRange* RBeg, unsigned NumRanges) {
25261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2527404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis  // 'BT' is owned by BugReporter.
2528404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis  BugType *BT = getBugTypeForName(name, category);
2529590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks  BugReport *R = new BugReport(*BT, str, Loc);
253007189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek  R->setDeclWithIssue(DeclWithIssue);
2531cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  for ( ; NumRanges > 0 ; --NumRanges, ++RBeg) R->addRange(*RBeg);
2532785950e59424dca7ce0081bebf13c0acd2c4fff6Jordan Rose  emitReport(R);
2533cabe66811fe43835b8c5a0854552768fc53261e3Ted Kremenek}
2534404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis
25355f9e272e632e951b1efe824cd16acb4d96077930Chris LattnerBugType *BugReporter::getBugTypeForName(StringRef name,
25365f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner                                        StringRef category) {
2537f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith  SmallString<136> fullDesc;
2538404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis  llvm::raw_svector_ostream(fullDesc) << name << ":" << category;
2539404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis  llvm::StringMapEntry<BugType *> &
2540404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis      entry = StrBugTypes.GetOrCreateValue(fullDesc);
2541404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis  BugType *BT = entry.getValue();
2542404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis  if (!BT) {
2543404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis    BT = new BugType(name, category);
2544404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis    entry.setValue(BT);
2545404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis  }
2546404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis  return BT;
2547404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis}
2548