BugReporter.cpp revision b04a2387ac23adfa063de03844cb16c0d77fb405
1ea91cc579ade536e3a08498a8157921dd4f533d1ager@chromium.org// BugReporter.cpp - Generate PathDiagnostics for Bugs ------------*- C++ -*--// 23484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// 33484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// The LLVM Compiler Infrastructure 443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// 543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// This file is distributed under the University of Illinois Open Source 643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// License. See LICENSE.TXT for details. 7196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org// 8196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org//===----------------------------------------------------------------------===// 9196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org// 10196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org// This file defines BugReporter, a utility class for generating 11196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org// PathDiagnostics. 12196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org// 13196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org//===----------------------------------------------------------------------===// 14196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org 15196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" 16196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "clang/AST/ASTContext.h" 17196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "clang/AST/DeclObjC.h" 18196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "clang/AST/Expr.h" 19196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "clang/AST/ParentMap.h" 20196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "clang/AST/StmtObjC.h" 21196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "clang/Analysis/CFG.h" 2243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#include "clang/Analysis/ProgramPoint.h" 2371affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org#include "clang/Basic/SourceManager.h" 2471affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" 2543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h" 2610480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" 27ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org#include "llvm/ADT/DenseMap.h" 28ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org#include "llvm/ADT/IntrusiveRefCntPtr.h" 29ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org#include "llvm/ADT/OwningPtr.h" 30ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org#include "llvm/ADT/STLExtras.h" 31ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org#include "llvm/ADT/SmallString.h" 32ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org#include "llvm/Support/raw_ostream.h" 33ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org#include <queue> 34d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org 35d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.orgusing namespace clang; 36d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.orgusing namespace ento; 37d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org 38d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.orgBugReporterVisitor::~BugReporterVisitor() {} 39c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org 40c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.orgvoid BugReporterContext::anchor() {} 41c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org 42c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org//===----------------------------------------------------------------------===// 43c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org// Helper routines for walking the ExplodedGraph and fetching statements. 44c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org//===----------------------------------------------------------------------===// 45c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org 46c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.orgstatic inline const Stmt *GetStmt(const ProgramPoint &P) { 47ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org if (Optional<StmtPoint> SP = P.getAs<StmtPoint>()) 48ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org return SP->getStmt(); 49ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org if (Optional<BlockEdge> BE = P.getAs<BlockEdge>()) 50ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org return BE->getSrc()->getTerminator(); 51ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org if (Optional<CallEnter> CE = P.getAs<CallEnter>()) 52ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org return CE->getCallExpr(); 53ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org if (Optional<CallExitEnd> CEE = P.getAs<CallExitEnd>()) 54ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org return CEE->getCalleeContext()->getCallSite(); 55ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org 56ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org return 0; 57d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org} 58ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org 59d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.orgstatic inline const ExplodedNode* 607ca89addc38b7479d2d7526d2043283ab7480ffcdanno@chromium.orgGetPredecessorNode(const ExplodedNode *N) { 61d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org return N->pred_empty() ? NULL : *(N->pred_begin()); 62d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org} 63d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org 64ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.orgstatic inline const ExplodedNode* 65d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.orgGetSuccessorNode(const ExplodedNode *N) { 66d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org return N->succ_empty() ? NULL : *(N->succ_begin()); 67d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org} 68d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org 69d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.orgstatic const Stmt *GetPreviousStmt(const ExplodedNode *N) { 70d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org for (N = GetPredecessorNode(N); N; N = GetPredecessorNode(N)) 71d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org if (const Stmt *S = GetStmt(N->getLocation())) 72d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org return S; 73d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org 74d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org return 0; 75d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org} 76d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org 77d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.orgstatic const Stmt *GetNextStmt(const ExplodedNode *N) { 78d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org for (N = GetSuccessorNode(N); N; N = GetSuccessorNode(N)) 79d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org if (const Stmt *S = GetStmt(N->getLocation())) { 80d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org // Check if the statement is '?' or '&&'/'||'. These are "merges", 81ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org // not actual statement points. 82d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org switch (S->getStmtClass()) { 83d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org case Stmt::ChooseExprClass: 84d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org case Stmt::BinaryConditionalOperatorClass: continue; 85ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org case Stmt::ConditionalOperatorClass: continue; 86d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org case Stmt::BinaryOperatorClass: { 87ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org BinaryOperatorKind Op = cast<BinaryOperator>(S)->getOpcode(); 88d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org if (Op == BO_LAnd || Op == BO_LOr) 89d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org continue; 90d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org break; 91d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org } 92d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org default: 93d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org break; 94d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org } 95d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org return S; 96d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org } 97d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org 98d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org return 0; 99d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org} 100d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org 101d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.orgstatic inline const Stmt* 102c22f2d813ad21e25e8df5d4a371fd63f582e4262danno@chromium.orgGetCurrentOrPreviousStmt(const ExplodedNode *N) { 103d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org if (const Stmt *S = GetStmt(N->getLocation())) 104c22f2d813ad21e25e8df5d4a371fd63f582e4262danno@chromium.org return S; 105d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org 106ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org return GetPreviousStmt(N); 107d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org} 108d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org 109d06b9264b1c886fc80a100e9915cf8ae07fdb4e5machenbach@chromium.orgstatic inline const Stmt* 110d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.orgGetCurrentOrNextStmt(const ExplodedNode *N) { 111d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org if (const Stmt *S = GetStmt(N->getLocation())) 112ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org return S; 113d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org 114d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org return GetNextStmt(N); 115d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org} 116ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org 117d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org//===----------------------------------------------------------------------===// 118d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org// Diagnostic cleanup. 119d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org//===----------------------------------------------------------------------===// 120d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org 121ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.orgstatic PathDiagnosticEventPiece * 122d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.orgeventsDescribeSameCondition(PathDiagnosticEventPiece *X, 123d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org PathDiagnosticEventPiece *Y) { 124d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org // Prefer diagnostics that come from ConditionBRVisitor over 12570ec1a2160dd946b9578d04d97d631a6d4ab4f8cbmeurer@chromium.org // those that came from TrackConstraintBRVisitor. 126d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org const void *tagPreferred = ConditionBRVisitor::getTag(); 127d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org const void *tagLesser = TrackConstraintBRVisitor::getTag(); 128ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org 129d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org if (X->getLocation() != Y->getLocation()) 130ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org return 0; 131d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org 132d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org if (X->getTag() == tagPreferred && Y->getTag() == tagLesser) 133d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org return X; 13470ec1a2160dd946b9578d04d97d631a6d4ab4f8cbmeurer@chromium.org 135d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org if (Y->getTag() == tagPreferred && X->getTag() == tagLesser) 136d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org return Y; 137c22f2d813ad21e25e8df5d4a371fd63f582e4262danno@chromium.org 138d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org return 0; 139ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org} 140d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org 141d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org/// An optimization pass over PathPieces that removes redundant diagnostics 142ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org/// generated by both ConditionBRVisitor and TrackConstraintBRVisitor. Both 143c22f2d813ad21e25e8df5d4a371fd63f582e4262danno@chromium.org/// BugReporterVisitors use different methods to generate diagnostics, with 144d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org/// one capable of emitting diagnostics in some cases but not in others. This 145d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org/// can lead to redundant diagnostic pieces at the same point in a path. 1467ca89addc38b7479d2d7526d2043283ab7480ffcdanno@chromium.orgstatic void removeRedundantMsgs(PathPieces &path) { 147d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org unsigned N = path.size(); 148d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org if (N < 2) 149d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org return; 150c22f2d813ad21e25e8df5d4a371fd63f582e4262danno@chromium.org // NOTE: this loop intentionally is not using an iterator. Instead, we 1517ca89addc38b7479d2d7526d2043283ab7480ffcdanno@chromium.org // are streaming the path and modifying it in place. This is done by 1527ca89addc38b7479d2d7526d2043283ab7480ffcdanno@chromium.org // grabbing the front, processing it, and if we decide to keep it append 153d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org // it to the end of the path. The entire path is processed in this way. 154d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org for (unsigned i = 0; i < N; ++i) { 155d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org IntrusiveRefCntPtr<PathDiagnosticPiece> piece(path.front()); 156d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org path.pop_front(); 157d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org 158ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org switch (piece->getKind()) { 159ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org case clang::ento::PathDiagnosticPiece::Call: 160ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org removeRedundantMsgs(cast<PathDiagnosticCallPiece>(piece)->path); 161d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org break; 162d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org case clang::ento::PathDiagnosticPiece::Macro: 163d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org removeRedundantMsgs(cast<PathDiagnosticMacroPiece>(piece)->subPieces); 164ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org break; 165ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org case clang::ento::PathDiagnosticPiece::ControlFlow: 166ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org break; 167ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org case clang::ento::PathDiagnosticPiece::Event: { 168ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org if (i == N-1) 169ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org break; 170d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org 171d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org if (PathDiagnosticEventPiece *nextEvent = 172d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org dyn_cast<PathDiagnosticEventPiece>(path.front().getPtr())) { 173ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org PathDiagnosticEventPiece *event = 174ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org cast<PathDiagnosticEventPiece>(piece); 175ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org // Check to see if we should keep one of the two pieces. If we 176ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org // come up with a preference, record which piece to keep, and consume 177d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org // another piece from the path. 178d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org if (PathDiagnosticEventPiece *pieceToKeep = 179d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org eventsDescribeSameCondition(event, nextEvent)) { 180d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org piece = pieceToKeep; 181d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org path.pop_front(); 182d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org ++i; 183d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org } 184d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org } 185ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org break; 186ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org } 187ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org } 188ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org path.push_back(piece); 189d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org } 190d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org} 191d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org 192dd6d9eedcac6e3b5adfb7702649ac32def9c3585mvstanton@chromium.org/// Recursively scan through a path and prune out calls and macros pieces 193d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org/// that aren't needed. Return true if afterwards the path contains 194d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org/// "interesting stuff" which means it shouldn't be pruned from the parent path. 195d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.orgbool BugReporter::RemoveUnneededCalls(PathPieces &pieces, BugReport *R) { 196d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org bool containsSomethingInteresting = false; 197ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org const unsigned N = pieces.size(); 198d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org 199ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org for (unsigned i = 0 ; i < N ; ++i) { 200d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org // Remove the front piece from the path. If it is still something we 201d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org // want to keep once we are done, we will push it back on the end. 202d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org IntrusiveRefCntPtr<PathDiagnosticPiece> piece(pieces.front()); 203ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org pieces.pop_front(); 204d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org 205d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org // Throw away pieces with invalid locations. Note that we can't throw away 206d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org // calls just yet because they might have something interesting inside them. 207ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org // If so, their locations will be adjusted as necessary later. 208ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org if (piece->getKind() != PathDiagnosticPiece::Call && 209ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org piece->getLocation().asLocation().isInvalid()) 210ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org continue; 211ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org 212ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org switch (piece->getKind()) { 213d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org case PathDiagnosticPiece::Call: { 214d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org PathDiagnosticCallPiece *call = cast<PathDiagnosticCallPiece>(piece); 215d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org // Check if the location context is interesting. 216ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org assert(LocationContextMap.count(call)); 217ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org if (R->isInteresting(LocationContextMap[call])) { 218ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org containsSomethingInteresting = true; 219ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org break; 220d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org } 221d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org 222d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org if (!RemoveUnneededCalls(call->path, R)) 223ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org continue; 224ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org 225ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org containsSomethingInteresting = true; 226f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org break; 227f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org } 228f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org case PathDiagnosticPiece::Macro: { 229f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org PathDiagnosticMacroPiece *macro = cast<PathDiagnosticMacroPiece>(piece); 230f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org if (!RemoveUnneededCalls(macro->subPieces, R)) 231f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org continue; 232f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org containsSomethingInteresting = true; 233fb547e07aef43e02715c5d6c1530e84bb3cbba02machenbach@chromium.org break; 234f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org } 235f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org case PathDiagnosticPiece::Event: { 236f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org PathDiagnosticEventPiece *event = cast<PathDiagnosticEventPiece>(piece); 237f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org 238f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org // We never throw away an event, but we do throw it away wholesale 239f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org // as part of a path if we throw the entire path away. 240f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org containsSomethingInteresting |= !event->isPrunable(); 241f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org break; 242f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org } 243f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org case PathDiagnosticPiece::ControlFlow: 244f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org break; 245f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org } 246f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org 247f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org pieces.push_back(piece); 248f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org } 249f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org 250f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org return containsSomethingInteresting; 251f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org} 252f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org 253f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org/// Recursively scan through a path and make sure that all call pieces have 254f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org/// valid locations. Note that all other pieces with invalid locations should 255f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org/// have already been pruned out. 256f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.orgstatic void adjustCallLocations(PathPieces &Pieces, 257f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org PathDiagnosticLocation *LastCallLocation = 0) { 258f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org for (PathPieces::iterator I = Pieces.begin(), E = Pieces.end(); I != E; ++I) { 259f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org PathDiagnosticCallPiece *Call = dyn_cast<PathDiagnosticCallPiece>(*I); 260f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org 261f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org if (!Call) { 26270ec1a2160dd946b9578d04d97d631a6d4ab4f8cbmeurer@chromium.org assert((*I)->getLocation().asLocation().isValid()); 263f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org continue; 264f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org } 265f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org 266f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org if (LastCallLocation) { 267f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org if (!Call->callEnter.asLocation().isValid() || 268f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org Call->getCaller()->isImplicit()) 269f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org Call->callEnter = *LastCallLocation; 270f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org if (!Call->callReturn.asLocation().isValid() || 271f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org Call->getCaller()->isImplicit()) 272f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org Call->callReturn = *LastCallLocation; 273f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org } 274f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org 275f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org // Recursively clean out the subclass. Keep this call around if 276f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org // it contains any informative diagnostics. 277f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org PathDiagnosticLocation *ThisCallLocation; 278f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org if (Call->callEnterWithin.asLocation().isValid() && 279f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org !Call->getCallee()->isImplicit()) 280f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org ThisCallLocation = &Call->callEnterWithin; 281f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org else 282f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org ThisCallLocation = &Call->callEnter; 283f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org 284f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org assert(ThisCallLocation && "Outermost call has an invalid location"); 285f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org adjustCallLocations(Call->path, ThisCallLocation); 286f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org } 287f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org} 288f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org 289f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org//===----------------------------------------------------------------------===// 290f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org// PathDiagnosticBuilder and its associated routines and helper objects. 291f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org//===----------------------------------------------------------------------===// 292f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org 293f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.orgtypedef llvm::DenseMap<const ExplodedNode*, 294f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.orgconst ExplodedNode*> NodeBackMap; 295f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org 296f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.orgnamespace { 297f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.orgclass NodeMapClosure : public BugReport::NodeResolver { 298f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org NodeBackMap& M; 299fb547e07aef43e02715c5d6c1530e84bb3cbba02machenbach@chromium.orgpublic: 300f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org NodeMapClosure(NodeBackMap *m) : M(*m) {} 301f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org ~NodeMapClosure() {} 302f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org 303f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org const ExplodedNode *getOriginalNode(const ExplodedNode *N) { 304f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org NodeBackMap::iterator I = M.find(N); 305f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org return I == M.end() ? 0 : I->second; 306f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org } 307f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org}; 308f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org 309f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.orgclass PathDiagnosticBuilder : public BugReporterContext { 310f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org BugReport *R; 311f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org PathDiagnosticConsumer *PDC; 312f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org NodeMapClosure NMC; 313f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.orgpublic: 314f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org const LocationContext *LC; 315f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org 316f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org PathDiagnosticBuilder(GRBugReporter &br, 317f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org BugReport *r, NodeBackMap *Backmap, 318f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org PathDiagnosticConsumer *pdc) 319f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org : BugReporterContext(br), 320f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org R(r), PDC(pdc), NMC(Backmap), LC(r->getErrorNode()->getLocationContext()) 321f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org {} 322f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org 323f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org PathDiagnosticLocation ExecutionContinues(const ExplodedNode *N); 324f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org 325864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org PathDiagnosticLocation ExecutionContinues(llvm::raw_string_ostream &os, 326f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org const ExplodedNode *N); 327f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org 328f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org BugReport *getBugReport() { return R; } 329f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org 330f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org Decl const &getCodeDecl() { return R->getErrorNode()->getCodeDecl(); } 331f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org 332f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org ParentMap& getParentMap() { return LC->getParentMap(); } 333f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org 334f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org const Stmt *getParent(const Stmt *S) { 335f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org return getParentMap().getParent(S); 336f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org } 337f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org 338f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org virtual NodeMapClosure& getNodeResolver() { return NMC; } 339f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org 340f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org PathDiagnosticLocation getEnclosingStmtLocation(const Stmt *S); 341f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org 342f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org PathDiagnosticConsumer::PathGenerationScheme getGenerationScheme() const { 343f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org return PDC ? PDC->getGenerationScheme() : PathDiagnosticConsumer::Extensive; 344f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org } 345f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org 346f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org bool supportsLogicalOpControlFlow() const { 347f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org return PDC ? PDC->supportsLogicalOpControlFlow() : true; 348f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org } 349f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org}; 350f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org} // end anonymous namespace 351f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org 352f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.orgPathDiagnosticLocation 353f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.orgPathDiagnosticBuilder::ExecutionContinues(const ExplodedNode *N) { 354f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org if (const Stmt *S = GetNextStmt(N)) 355f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org return PathDiagnosticLocation(S, getSourceManager(), LC); 356f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org 357f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org return PathDiagnosticLocation::createDeclEnd(N->getLocationContext(), 358f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org getSourceManager()); 359f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org} 360f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org 361f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.orgPathDiagnosticLocation 362f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.orgPathDiagnosticBuilder::ExecutionContinues(llvm::raw_string_ostream &os, 363f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org const ExplodedNode *N) { 364f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org 365864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org // Slow, but probably doesn't matter. 366864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org if (os.str().empty()) 367f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org os << ' '; 368f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org 369f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org const PathDiagnosticLocation &Loc = ExecutionContinues(N); 370f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org 371f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org if (Loc.asStmt()) 372f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org os << "Execution continues on line " 373f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org << getSourceManager().getExpansionLineNumber(Loc.asLocation()) 374f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org << '.'; 375f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org else { 376f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org os << "Execution jumps to the end of the "; 377f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org const Decl *D = N->getLocationContext()->getDecl(); 378f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org if (isa<ObjCMethodDecl>(D)) 379f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org os << "method"; 380f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org else if (isa<FunctionDecl>(D)) 381f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org os << "function"; 382f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org else { 383f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org assert(isa<BlockDecl>(D)); 384f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org os << "anonymous block"; 385f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org } 38670ec1a2160dd946b9578d04d97d631a6d4ab4f8cbmeurer@chromium.org os << '.'; 387f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org } 388f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org 389f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org return Loc; 390f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org} 391f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org 392f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.orgstatic bool IsNested(const Stmt *S, ParentMap &PM) { 393f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org if (isa<Expr>(S) && PM.isConsumedExpr(cast<Expr>(S))) 394f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org return true; 395f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org 396f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org const Stmt *Parent = PM.getParentIgnoreParens(S); 397f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org 398f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org if (Parent) 399f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org switch (Parent->getStmtClass()) { 400f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org case Stmt::ForStmtClass: 401f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org case Stmt::DoStmtClass: 402f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org case Stmt::WhileStmtClass: 403f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org return true; 404f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org default: 405f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org break; 406f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org } 407f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org 408f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org return false; 409f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org} 410f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org 411f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.orgPathDiagnosticLocation 412f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.orgPathDiagnosticBuilder::getEnclosingStmtLocation(const Stmt *S) { 413f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org assert(S && "Null Stmt *passed to getEnclosingStmtLocation"); 414f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org ParentMap &P = getParentMap(); 415f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org SourceManager &SMgr = getSourceManager(); 416f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org 417f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org while (IsNested(S, P)) { 418f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org const Stmt *Parent = P.getParentIgnoreParens(S); 419f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org 420f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org if (!Parent) 421f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org break; 422f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org 423f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org switch (Parent->getStmtClass()) { 424f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org case Stmt::BinaryOperatorClass: { 425f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org const BinaryOperator *B = cast<BinaryOperator>(Parent); 426f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org if (B->isLogicalOp()) 427f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org return PathDiagnosticLocation(S, SMgr, LC); 428f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org break; 429f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org } 430f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org case Stmt::CompoundStmtClass: 431f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org case Stmt::StmtExprClass: 432f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org return PathDiagnosticLocation(S, SMgr, LC); 433f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org case Stmt::ChooseExprClass: 434f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org // Similar to '?' if we are referring to condition, just have the edge 435f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org // point to the entire choose expression. 436f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org if (cast<ChooseExpr>(Parent)->getCond() == S) 437f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org return PathDiagnosticLocation(Parent, SMgr, LC); 438f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org else 439f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org return PathDiagnosticLocation(S, SMgr, LC); 440f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org case Stmt::BinaryConditionalOperatorClass: 441f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org case Stmt::ConditionalOperatorClass: 442f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org // For '?', if we are referring to condition, just have the edge point 443f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org // to the entire '?' expression. 444f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org if (cast<AbstractConditionalOperator>(Parent)->getCond() == S) 445f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org return PathDiagnosticLocation(Parent, SMgr, LC); 446f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org else 447f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org return PathDiagnosticLocation(S, SMgr, LC); 448f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org case Stmt::DoStmtClass: 449f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org return PathDiagnosticLocation(S, SMgr, LC); 450f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org case Stmt::ForStmtClass: 451f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org if (cast<ForStmt>(Parent)->getBody() == S) 452f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org return PathDiagnosticLocation(S, SMgr, LC); 453f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org break; 454f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org case Stmt::IfStmtClass: 455f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org if (cast<IfStmt>(Parent)->getCond() != S) 45610480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org return PathDiagnosticLocation(S, SMgr, LC); 457d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org break; 458d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org case Stmt::ObjCForCollectionStmtClass: 459ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org if (cast<ObjCForCollectionStmt>(Parent)->getBody() == S) 46010480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org return PathDiagnosticLocation(S, SMgr, LC); 46110480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org break; 462ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org case Stmt::WhileStmtClass: 46310480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org if (cast<WhileStmt>(Parent)->getCond() != S) 464d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org return PathDiagnosticLocation(S, SMgr, LC); 465fb547e07aef43e02715c5d6c1530e84bb3cbba02machenbach@chromium.org break; 466d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org default: 467d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org break; 468d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org } 46910480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org 47010480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org S = Parent; 471ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org } 472ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org 473d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org assert(S && "Cannot have null Stmt for PathDiagnosticLocation"); 474d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org 47510480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org // Special case: DeclStmts can appear in for statement declarations, in which 476ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org // case the ForStmt is the context. 47710480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org if (isa<DeclStmt>(S)) { 47810480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org if (const Stmt *Parent = P.getParent(S)) { 47910480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org switch (Parent->getStmtClass()) { 48010480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org case Stmt::ForStmtClass: 48110480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org case Stmt::ObjCForCollectionStmtClass: 48210480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org return PathDiagnosticLocation(Parent, SMgr, LC); 48310480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org default: 48410480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org break; 48510480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org } 48610480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org } 48710480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org } 48810480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org else if (isa<BinaryOperator>(S)) { 48910480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org // Special case: the binary operator represents the initialization 49010480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org // code in a for statement (this can happen when the variable being 49110480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org // initialized is an old variable. 49210480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org if (const ForStmt *FS = 49310480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org dyn_cast_or_null<ForStmt>(P.getParentIgnoreParens(S))) { 49410480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org if (FS->getInit() == S) 49510480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org return PathDiagnosticLocation(FS, SMgr, LC); 49610480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org } 49710480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org } 49810480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org 49910480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org return PathDiagnosticLocation(S, SMgr, LC); 50010480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org} 50110480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org 50210480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org//===----------------------------------------------------------------------===// 50310480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org// "Visitors only" path diagnostic generation algorithm. 50410480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org//===----------------------------------------------------------------------===// 50510480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.orgstatic bool GenerateVisitorsOnlyPathDiagnostic(PathDiagnostic &PD, 50610480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org PathDiagnosticBuilder &PDB, 50710480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org const ExplodedNode *N, 50810480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org ArrayRef<BugReporterVisitor *> visitors) { 50910480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org // All path generation skips the very first node (the error node). 51010480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org // This is because there is special handling for the end-of-path note. 51110480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org N = N->getFirstPred(); 51210480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org if (!N) 51310480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org return true; 51410480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org 51510480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org BugReport *R = PDB.getBugReport(); 51610480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org while (const ExplodedNode *Pred = N->getFirstPred()) { 51710480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org for (ArrayRef<BugReporterVisitor *>::iterator I = visitors.begin(), 51810480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org E = visitors.end(); 51910480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org I != E; ++I) { 52010480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org // Visit all the node pairs, but throw the path pieces away. 52110480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org PathDiagnosticPiece *Piece = (*I)->VisitNode(N, Pred, PDB, *R); 52210480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org delete Piece; 52310480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org } 52410480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org 52510480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org N = Pred; 52610480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org } 52710480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org 52810480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org return R->isValid(); 52910480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org} 53010480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org 53110480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org//===----------------------------------------------------------------------===// 53210480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org// "Minimal" path diagnostic generation algorithm. 53310480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org//===----------------------------------------------------------------------===// 534ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.orgtypedef std::pair<PathDiagnosticCallPiece*, const ExplodedNode*> StackDiagPair; 535ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.orgtypedef SmallVector<StackDiagPair, 6> StackDiagVector; 536ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org 537ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.orgstatic void updateStackPiecesWithMessage(PathDiagnosticPiece *P, 538ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org StackDiagVector &CallStack) { 539d06b9264b1c886fc80a100e9915cf8ae07fdb4e5machenbach@chromium.org // If the piece contains a special message, add it to all the call 540d06b9264b1c886fc80a100e9915cf8ae07fdb4e5machenbach@chromium.org // pieces on the active stack. 541ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org if (PathDiagnosticEventPiece *ep = 542ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org dyn_cast<PathDiagnosticEventPiece>(P)) { 543ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org 544ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org if (ep->hasCallStackHint()) 545ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org for (StackDiagVector::iterator I = CallStack.begin(), 546ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org E = CallStack.end(); I != E; ++I) { 547ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org PathDiagnosticCallPiece *CP = I->first; 548ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org const ExplodedNode *N = I->second; 549ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org std::string stackMsg = ep->getCallStackMessage(N); 550ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org 551ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org // The last message on the path to final bug is the most important 552ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org // one. Since we traverse the path backwards, do not add the message 553ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org // if one has been previously added. 554ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org if (!CP->hasCallStackMessage()) 555ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org CP->setCallStackMessage(stackMsg); 556ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org } 557ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org } 558ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org} 559ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org 560ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.orgstatic void CompactPathDiagnostic(PathPieces &path, const SourceManager& SM); 561ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org 562ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.orgstatic bool GenerateMinimalPathDiagnostic(PathDiagnostic& PD, 563864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org PathDiagnosticBuilder &PDB, 564864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org const ExplodedNode *N, 565ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org ArrayRef<BugReporterVisitor *> visitors) { 566ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org 567ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org SourceManager& SMgr = PDB.getSourceManager(); 568ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org const LocationContext *LC = PDB.LC; 569ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org const ExplodedNode *NextNode = N->pred_empty() 570ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org ? NULL : *(N->pred_begin()); 571ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org 572ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org StackDiagVector CallStack; 573ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org 574d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org while (NextNode) { 575d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org N = NextNode; 576ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org PDB.LC = N->getLocationContext(); 577d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org NextNode = GetPredecessorNode(N); 578ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org 579ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org ProgramPoint P = N->getLocation(); 580ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org 581ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org do { 582d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org if (Optional<CallExitEnd> CE = P.getAs<CallExitEnd>()) { 583ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org PathDiagnosticCallPiece *C = 584ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org PathDiagnosticCallPiece::construct(N, *CE, SMgr); 585ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org GRBugReporter& BR = PDB.getBugReporter(); 586ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org BR.addCallPieceLocationContextPair(C, CE->getCalleeContext()); 587ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org PD.getActivePath().push_front(C); 588ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org PD.pushActivePath(&C->path); 589ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org CallStack.push_back(StackDiagPair(C, N)); 590ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org break; 591ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org } 592ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org 593ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org if (Optional<CallEnter> CE = P.getAs<CallEnter>()) { 594ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org // Flush all locations, and pop the active path. 595ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org bool VisitedEntireCall = PD.isWithinCall(); 596ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org PD.popActivePath(); 597ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org 598ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org // Either we just added a bunch of stuff to the top-level path, or 599ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org // we have a previous CallExitEnd. If the former, it means that the 600ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org // path terminated within a function call. We must then take the 601ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org // current contents of the active path and place it within 602ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org // a new PathDiagnosticCallPiece. 603ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org PathDiagnosticCallPiece *C; 604ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org if (VisitedEntireCall) { 605ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org C = cast<PathDiagnosticCallPiece>(PD.getActivePath().front()); 606ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org } else { 607ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org const Decl *Caller = CE->getLocationContext()->getDecl(); 608ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org C = PathDiagnosticCallPiece::construct(PD.getActivePath(), Caller); 609ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org GRBugReporter& BR = PDB.getBugReporter(); 610ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org BR.addCallPieceLocationContextPair(C, CE->getCalleeContext()); 611ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org } 612ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org 613ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org C->setCallee(*CE, SMgr); 614ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org if (!CallStack.empty()) { 615ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org assert(CallStack.back().first == C); 616ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org CallStack.pop_back(); 617ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org } 618ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org break; 619ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org } 620ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org 621ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org if (Optional<BlockEdge> BE = P.getAs<BlockEdge>()) { 622ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org const CFGBlock *Src = BE->getSrc(); 623ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org const CFGBlock *Dst = BE->getDst(); 624ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org const Stmt *T = Src->getTerminator(); 625ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org 626d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org if (!T) 627ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org break; 628ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org 629ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org PathDiagnosticLocation Start = 630ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org PathDiagnosticLocation::createBegin(T, SMgr, 631ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org N->getLocationContext()); 632ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org 633d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org switch (T->getStmtClass()) { 634fb547e07aef43e02715c5d6c1530e84bb3cbba02machenbach@chromium.org default: 635d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org break; 636d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org 637ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org case Stmt::GotoStmtClass: 638ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org case Stmt::IndirectGotoStmtClass: { 639ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org const Stmt *S = GetNextStmt(N); 640ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org 641d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org if (!S) 642ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org break; 643ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org 644ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org std::string sbuf; 645ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org llvm::raw_string_ostream os(sbuf); 646ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org const PathDiagnosticLocation &End = PDB.getEnclosingStmtLocation(S); 647ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org 648d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org os << "Control jumps to line " 649d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org << End.asLocation().getExpansionLineNumber(); 650ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 651ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org Start, End, os.str())); 652ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org break; 653ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org } 654ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org 655ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org case Stmt::SwitchStmtClass: { 656ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org // Figure out what case arm we took. 657ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org std::string sbuf; 658ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org llvm::raw_string_ostream os(sbuf); 659ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org 660ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org if (const Stmt *S = Dst->getLabel()) { 661ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org PathDiagnosticLocation End(S, SMgr, LC); 662d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org 663d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org switch (S->getStmtClass()) { 664ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org default: 665ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org os << "No cases match in the switch statement. " 666ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org "Control jumps to line " 667ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org << End.asLocation().getExpansionLineNumber(); 668ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org break; 669ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org case Stmt::DefaultStmtClass: 670ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org os << "Control jumps to the 'default' case at line " 671ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org << End.asLocation().getExpansionLineNumber(); 672ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org break; 673ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org 674d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org case Stmt::CaseStmtClass: { 675d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org os << "Control jumps to 'case "; 676ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org const CaseStmt *Case = cast<CaseStmt>(S); 677ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org const Expr *LHS = Case->getLHS()->IgnoreParenCasts(); 678ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org 679ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org // Determine if it is an enum. 680c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org bool GetRawInt = true; 681ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org 682ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(LHS)) { 683ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org // FIXME: Maybe this should be an assertion. Are there cases 684ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org // were it is not an EnumConstantDecl? 685ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org const EnumConstantDecl *D = 686ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org dyn_cast<EnumConstantDecl>(DR->getDecl()); 687ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org 688ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org if (D) { 689ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org GetRawInt = false; 690ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org os << *D; 691ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org } 692ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org } 693ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org 694ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org if (GetRawInt) 695ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org os << LHS->EvaluateKnownConstInt(PDB.getASTContext()); 696ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org 697ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org os << ":' at line " 698ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org << End.asLocation().getExpansionLineNumber(); 699ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org break; 700ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org } 701ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org } 702ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 703ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org Start, End, os.str())); 704ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org } 705ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org else { 706ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org os << "'Default' branch taken. "; 707ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org const PathDiagnosticLocation &End = PDB.ExecutionContinues(os, N); 708ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 709ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org Start, End, os.str())); 710ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org } 711ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org 712ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org break; 713ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org } 714ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org 715ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org case Stmt::BreakStmtClass: 716ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org case Stmt::ContinueStmtClass: { 717ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org std::string sbuf; 718ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org llvm::raw_string_ostream os(sbuf); 719ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org PathDiagnosticLocation End = PDB.ExecutionContinues(os, N); 720ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 721ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org Start, End, os.str())); 722ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org break; 723ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org } 724ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org 725ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org // Determine control-flow for ternary '?'. 726ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org case Stmt::BinaryConditionalOperatorClass: 727ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org case Stmt::ConditionalOperatorClass: { 728ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org std::string sbuf; 729ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org llvm::raw_string_ostream os(sbuf); 730ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org os << "'?' condition is "; 731ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org 732ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org if (*(Src->succ_begin()+1) == Dst) 733ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org os << "false"; 734ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org else 735ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org os << "true"; 736ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org 737ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org PathDiagnosticLocation End = PDB.ExecutionContinues(N); 738ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org 739ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org if (const Stmt *S = End.asStmt()) 740ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org End = PDB.getEnclosingStmtLocation(S); 741ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org 742ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 743ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org Start, End, os.str())); 744ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org break; 745ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org } 746ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org 747ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org // Determine control-flow for short-circuited '&&' and '||'. 748ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org case Stmt::BinaryOperatorClass: { 74943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen if (!PDB.supportsLogicalOpControlFlow()) 75043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen break; 75143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 75243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen const BinaryOperator *B = cast<BinaryOperator>(T); 75343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen std::string sbuf; 75443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen llvm::raw_string_ostream os(sbuf); 75543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen os << "Left side of '"; 756ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org 75743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen if (B->getOpcode() == BO_LAnd) { 75843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen os << "&&" << "' is "; 75943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 76043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen if (*(Src->succ_begin()+1) == Dst) { 76143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen os << "false"; 762245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org PathDiagnosticLocation End(B->getLHS(), SMgr, LC); 763245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org PathDiagnosticLocation Start = 764245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org PathDiagnosticLocation::createOperatorLoc(B, SMgr); 76543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 76643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen Start, End, os.str())); 76743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen } 76843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen else { 76943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen os << "true"; 770e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org PathDiagnosticLocation Start(B->getLHS(), SMgr, LC); 77143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen PathDiagnosticLocation End = PDB.ExecutionContinues(N); 77243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 77343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen Start, End, os.str())); 7741e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org } 7751e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org } 7761e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org else { 7771e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org assert(B->getOpcode() == BO_LOr); 7781e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org os << "||" << "' is "; 7791e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org 7801e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org if (*(Src->succ_begin()+1) == Dst) { 78143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen os << "false"; 78243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen PathDiagnosticLocation Start(B->getLHS(), SMgr, LC); 783e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org PathDiagnosticLocation End = PDB.ExecutionContinues(N); 78443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 78543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen Start, End, os.str())); 78643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen } 78743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen else { 78843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen os << "true"; 78943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen PathDiagnosticLocation End(B->getLHS(), SMgr, LC); 79043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen PathDiagnosticLocation Start = 79143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen PathDiagnosticLocation::createOperatorLoc(B, SMgr); 79243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 79343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen Start, End, os.str())); 7946d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org } 79543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen } 79643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 79743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen break; 79843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen } 79943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 80043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen case Stmt::DoStmtClass: { 80143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen if (*(Src->succ_begin()) == Dst) { 8021e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org std::string sbuf; 803e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org llvm::raw_string_ostream os(sbuf); 80443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 8053811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org os << "Loop condition is true. "; 8063811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org PathDiagnosticLocation End = PDB.ExecutionContinues(os, N); 8073811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org 80843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen if (const Stmt *S = End.asStmt()) 80943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen End = PDB.getEnclosingStmtLocation(S); 810245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org 811245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 812ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org Start, End, os.str())); 81343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen } 81443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen else { 81543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen PathDiagnosticLocation End = PDB.ExecutionContinues(N); 81643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 81743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen if (const Stmt *S = End.asStmt()) 81843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen End = PDB.getEnclosingStmtLocation(S); 81943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 8209a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 82143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen Start, End, "Loop condition is false. Exiting loop")); 82274f333bce721daf6b1f9d7d3d3faa623f77658d7vegorov@chromium.org } 823ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org 824a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org break; 82543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen } 82643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 82743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen case Stmt::WhileStmtClass: 8284a5224e84636d192e82f288bfab0d308bdae5c37whesse@chromium.org case Stmt::ForStmtClass: { 82943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen if (*(Src->succ_begin()+1) == Dst) { 83043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen std::string sbuf; 83143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen llvm::raw_string_ostream os(sbuf); 83243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 833a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org os << "Loop condition is false. "; 83443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen PathDiagnosticLocation End = PDB.ExecutionContinues(os, N); 835a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org if (const Stmt *S = End.asStmt()) 836dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org End = PDB.getEnclosingStmtLocation(S); 83743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 83843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 83943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen Start, End, os.str())); 84043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen } 8415323a9c29497eb5a52821d396990c6d75a37baf7jkummerow@chromium.org else { 842dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org PathDiagnosticLocation End = PDB.ExecutionContinues(N); 84343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen if (const Stmt *S = End.asStmt()) 84443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen End = PDB.getEnclosingStmtLocation(S); 84543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 84643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 84743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen Start, End, "Loop condition is true. Entering loop body")); 84843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen } 84943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 85043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen break; 85143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen } 85243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 853ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org case Stmt::IfStmtClass: { 8546d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org PathDiagnosticLocation End = PDB.ExecutionContinues(N); 8556d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org 8565d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org if (const Stmt *S = End.asStmt()) 8573811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org End = PDB.getEnclosingStmtLocation(S); 8583811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org 859e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org if (*(Src->succ_begin()+1) == Dst) 8603811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 861ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org Start, End, "Taking false branch")); 862ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org else 86343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 86443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen Start, End, "Taking true branch")); 86543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 86643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen break; 8673811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org } 8683811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org } 8693811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org } 8701845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org } while(0); 8711845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org 8721845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org if (NextNode) { 8731845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org // Add diagnostic pieces from custom visitors. 8741845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org BugReport *R = PDB.getBugReport(); 8751845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org for (ArrayRef<BugReporterVisitor *>::iterator I = visitors.begin(), 87643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen E = visitors.end(); 87743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen I != E; ++I) { 87843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen if (PathDiagnosticPiece *p = (*I)->VisitNode(N, NextNode, PDB, *R)) { 87943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen PD.getActivePath().push_front(p); 88043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen updateStackPiecesWithMessage(p, CallStack); 88143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen } 882e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org } 883e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org } 88443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen } 885e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org 88643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen if (!PDB.getBugReport()->isValid()) 88743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen return false; 88843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 88943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen // After constructing the full PathDiagnostic, do a pass over it to compact 8903811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org // PathDiagnosticPieces that occur within a macro. 8913811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org CompactPathDiagnostic(PD.getMutablePieces(), PDB.getSourceManager()); 89243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen return true; 893e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org} 89443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 89543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen//===----------------------------------------------------------------------===// 89643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// "Extensive" PathDiagnostic generation. 89743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen//===----------------------------------------------------------------------===// 89843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 89943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenstatic bool IsControlFlowExpr(const Stmt *S) { 90071affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org const Expr *E = dyn_cast<Expr>(S); 90171affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org 90243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen if (!E) 90343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen return false; 90443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 905c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org E = E->IgnoreParenCasts(); 90643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 90743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen if (isa<AbstractConditionalOperator>(E)) 90843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen return true; 90943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 91043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen if (const BinaryOperator *B = dyn_cast<BinaryOperator>(E)) 911ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org if (B->isLogicalOp()) 912ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org return true; 913ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org 914ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org return false; 915750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org} 916ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org 917750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.orgnamespace { 9188e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.orgclass ContextLocation : public PathDiagnosticLocation { 919ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org bool IsDead; 920ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.orgpublic: 921ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org ContextLocation(const PathDiagnosticLocation &L, bool isdead = false) 9228e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org : PathDiagnosticLocation(L), IsDead(isdead) {} 923c03a1924dcc113678c0ebe58aa7d3c855a657719yangguo@chromium.org 924c03a1924dcc113678c0ebe58aa7d3c855a657719yangguo@chromium.org void markDead() { IsDead = true; } 925c03a1924dcc113678c0ebe58aa7d3c855a657719yangguo@chromium.org bool isDead() const { return IsDead; } 926ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org}; 927ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org 928dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.orgclass EdgeBuilder { 929ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org std::vector<ContextLocation> CLocs; 930f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org typedef std::vector<ContextLocation>::iterator iterator; 931f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org PathDiagnostic &PD; 93210480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org PathDiagnosticBuilder &PDB; 933ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org PathDiagnosticLocation PrevLoc; 934d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org 935dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org bool IsConsumedExpr(const PathDiagnosticLocation &L); 936ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org 937ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org bool containsLocation(const PathDiagnosticLocation &Container, 9388e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org const PathDiagnosticLocation &Containee); 939ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org 940ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org PathDiagnosticLocation getContextLocation(const PathDiagnosticLocation &L); 941ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org 942eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org PathDiagnosticLocation cleanUpLocation(PathDiagnosticLocation L, 9438e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org bool firstCharOnly = false) { 944d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org if (const Stmt *S = L.asStmt()) { 945d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org const Stmt *Original = S; 946d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org while (1) { 947d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org // Adjust the location for some expressions that are best referenced 948d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org // by one of their subexpressions. 949d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org switch (S->getStmtClass()) { 950d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org default: 951d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org break; 952d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org case Stmt::ParenExprClass: 953d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org case Stmt::GenericSelectionExprClass: 954d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org S = cast<Expr>(S)->IgnoreParens(); 955d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org firstCharOnly = true; 956d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org continue; 957d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org case Stmt::BinaryConditionalOperatorClass: 958d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org case Stmt::ConditionalOperatorClass: 959d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org S = cast<AbstractConditionalOperator>(S)->getCond(); 960d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org firstCharOnly = true; 961755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org continue; 962ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org case Stmt::ChooseExprClass: 963ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org S = cast<ChooseExpr>(S)->getCond(); 964755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org firstCharOnly = true; 965755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org continue; 966755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org case Stmt::BinaryOperatorClass: 967755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org S = cast<BinaryOperator>(S)->getLHS(); 968381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.org firstCharOnly = true; 96943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen continue; 9706f10e41fef1524c70846d970268de222e41c594cager@chromium.org } 9716f10e41fef1524c70846d970268de222e41c594cager@chromium.org 9726f10e41fef1524c70846d970268de222e41c594cager@chromium.org break; 9736f10e41fef1524c70846d970268de222e41c594cager@chromium.org } 9746f10e41fef1524c70846d970268de222e41c594cager@chromium.org 975ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org if (S != Original) 976ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org L = PathDiagnosticLocation(S, L.getManager(), PDB.LC); 977381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.org } 978381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.org 97943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen if (firstCharOnly) 98043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen L = PathDiagnosticLocation::createSingleLocation(L); 98143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 98243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen return L; 983ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org } 984ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org 985ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org void popLocation() { 986ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org if (!CLocs.back().isDead() && CLocs.back().asLocation().isFileID()) { 987f05f2913e034b9332e55c02c9395e701725c02c1kmillikin@chromium.org // For contexts, we only one the first character as the range. 988f05f2913e034b9332e55c02c9395e701725c02c1kmillikin@chromium.org rawAddEdge(cleanUpLocation(CLocs.back(), true)); 989f05f2913e034b9332e55c02c9395e701725c02c1kmillikin@chromium.org } 990f05f2913e034b9332e55c02c9395e701725c02c1kmillikin@chromium.org CLocs.pop_back(); 991f05f2913e034b9332e55c02c9395e701725c02c1kmillikin@chromium.org } 992ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org 993ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.orgpublic: 994ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org EdgeBuilder(PathDiagnostic &pd, PathDiagnosticBuilder &pdb) 995381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.org : PD(pd), PDB(pdb) { 996381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.org 99743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen // If the PathDiagnostic already has pieces, add the enclosing statement 99843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen // of the first piece as a context as well. 99943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen if (!PD.path.empty()) { 1000f05f2913e034b9332e55c02c9395e701725c02c1kmillikin@chromium.org PrevLoc = (*PD.path.begin())->getLocation(); 1001ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org 1002ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org if (const Stmt *S = PrevLoc.asStmt()) 1003f05f2913e034b9332e55c02c9395e701725c02c1kmillikin@chromium.org addExtendedContext(PDB.getEnclosingStmtLocation(S).asStmt()); 1004f05f2913e034b9332e55c02c9395e701725c02c1kmillikin@chromium.org } 1005f05f2913e034b9332e55c02c9395e701725c02c1kmillikin@chromium.org } 1006f05f2913e034b9332e55c02c9395e701725c02c1kmillikin@chromium.org 1007f05f2913e034b9332e55c02c9395e701725c02c1kmillikin@chromium.org ~EdgeBuilder() { 100843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen while (!CLocs.empty()) popLocation(); 1009ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org 1010ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org // Finally, add an initial edge from the start location of the first 1011b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org // statement (if it doesn't already exist). 1012381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.org PathDiagnosticLocation L = PathDiagnosticLocation::createDeclBegin( 101343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen PDB.LC, 101443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen PDB.getSourceManager()); 101543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen if (L.isValid()) 101643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen rawAddEdge(L); 10179085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org } 101843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 101943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen void flushLocations() { 1020ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org while (!CLocs.empty()) 1021ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org popLocation(); 102243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen PrevLoc = PathDiagnosticLocation(); 102343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen } 1024eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org 1025381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.org void addEdge(PathDiagnosticLocation NewLoc, bool alwaysAdd = false); 1026381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.org 102743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen void rawAddEdge(PathDiagnosticLocation NewLoc); 102843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 102943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen void addContext(const Stmt *S); 103043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen void addContext(const PathDiagnosticLocation &L); 1031ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org void addExtendedContext(const Stmt *S); 103243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}; 103383e168294456ca2f02db421a635f7d5f5d023966kmillikin@chromium.org} // end anonymous namespace 103443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 1035afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org 1036750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.orgPathDiagnosticLocation 1037f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.orgEdgeBuilder::getContextLocation(const PathDiagnosticLocation &L) { 1038f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org if (const Stmt *S = L.asStmt()) { 1039f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org if (IsControlFlowExpr(S)) 1040f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org return L; 1041f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org 1042f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org return PDB.getEnclosingStmtLocation(S); 1043f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org } 1044f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org 1045afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org return L; 1046f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org} 1047f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org 104843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenbool EdgeBuilder::containsLocation(const PathDiagnosticLocation &Container, 104943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen const PathDiagnosticLocation &Containee) { 105043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 105143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen if (Container == Containee) 105243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen return true; 105343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 105443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen if (Container.asDecl()) 105543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen return true; 10561845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org 10575aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org if (const Stmt *S = Containee.asStmt()) 10585aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org if (const Stmt *ContainerS = Container.asStmt()) { 1059ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org while (S) { 1060ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org if (S == ContainerS) 10615aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org return true; 10621845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org S = PDB.getParent(S); 10635aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org } 10645aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org return false; 1065381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.org } 106643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 106743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen // Less accurate: compare using source ranges. 1068b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org SourceRange ContainerR = Container.asRange(); 1069c1789eecd43bf9c5497636592bf14fa754d04c89machenbach@chromium.org SourceRange ContaineeR = Containee.asRange(); 1070c1789eecd43bf9c5497636592bf14fa754d04c89machenbach@chromium.org 1071c1789eecd43bf9c5497636592bf14fa754d04c89machenbach@chromium.org SourceManager &SM = PDB.getSourceManager(); 1072ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org SourceLocation ContainerRBeg = SM.getExpansionLoc(ContainerR.getBegin()); 1073dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org SourceLocation ContainerREnd = SM.getExpansionLoc(ContainerR.getEnd()); 1074c1789eecd43bf9c5497636592bf14fa754d04c89machenbach@chromium.org SourceLocation ContaineeRBeg = SM.getExpansionLoc(ContaineeR.getBegin()); 1075c1789eecd43bf9c5497636592bf14fa754d04c89machenbach@chromium.org SourceLocation ContaineeREnd = SM.getExpansionLoc(ContaineeR.getEnd()); 1076c1789eecd43bf9c5497636592bf14fa754d04c89machenbach@chromium.org 1077c1789eecd43bf9c5497636592bf14fa754d04c89machenbach@chromium.org unsigned ContainerBegLine = SM.getExpansionLineNumber(ContainerRBeg); 1078c1789eecd43bf9c5497636592bf14fa754d04c89machenbach@chromium.org unsigned ContainerEndLine = SM.getExpansionLineNumber(ContainerREnd); 107970d11c79c7833b9ab1ee185625fcf707b9480a40machenbach@chromium.org unsigned ContaineeBegLine = SM.getExpansionLineNumber(ContaineeRBeg); 108070d11c79c7833b9ab1ee185625fcf707b9480a40machenbach@chromium.org unsigned ContaineeEndLine = SM.getExpansionLineNumber(ContaineeREnd); 108170d11c79c7833b9ab1ee185625fcf707b9480a40machenbach@chromium.org 108270d11c79c7833b9ab1ee185625fcf707b9480a40machenbach@chromium.org assert(ContainerBegLine <= ContainerEndLine); 108370d11c79c7833b9ab1ee185625fcf707b9480a40machenbach@chromium.org assert(ContaineeBegLine <= ContaineeEndLine); 108470d11c79c7833b9ab1ee185625fcf707b9480a40machenbach@chromium.org 108570d11c79c7833b9ab1ee185625fcf707b9480a40machenbach@chromium.org return (ContainerBegLine <= ContaineeBegLine && 108670d11c79c7833b9ab1ee185625fcf707b9480a40machenbach@chromium.org ContainerEndLine >= ContaineeEndLine && 108770d11c79c7833b9ab1ee185625fcf707b9480a40machenbach@chromium.org (ContainerBegLine != ContaineeBegLine || 108870d11c79c7833b9ab1ee185625fcf707b9480a40machenbach@chromium.org SM.getExpansionColumnNumber(ContainerRBeg) <= 1089068ea0a6ea115c058d1d9798029bd7fa1eaaa955mstarzinger@chromium.org SM.getExpansionColumnNumber(ContaineeRBeg)) && 10901f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org (ContainerEndLine != ContaineeEndLine || 109132280cf2786219b2d9a668f7f00778fb59ac40b3mstarzinger@chromium.org SM.getExpansionColumnNumber(ContainerREnd) >= 1092ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org SM.getExpansionColumnNumber(ContaineeREnd))); 1093dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org} 1094068ea0a6ea115c058d1d9798029bd7fa1eaaa955mstarzinger@chromium.org 1095068ea0a6ea115c058d1d9798029bd7fa1eaaa955mstarzinger@chromium.orgvoid EdgeBuilder::rawAddEdge(PathDiagnosticLocation NewLoc) { 1096068ea0a6ea115c058d1d9798029bd7fa1eaaa955mstarzinger@chromium.org if (!PrevLoc.isValid()) { 10978e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org PrevLoc = NewLoc; 10988e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org return; 10998e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org } 11008e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org 1101ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org const PathDiagnosticLocation &NewLocClean = cleanUpLocation(NewLoc); 1102ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org const PathDiagnosticLocation &PrevLocClean = cleanUpLocation(PrevLoc); 1103ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org 1104ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org if (PrevLocClean.asLocation().isInvalid()) { 110583130cfc204d3ffed6832a7ef149b19328a58b33svenpanne@chromium.org PrevLoc = NewLoc; 110683130cfc204d3ffed6832a7ef149b19328a58b33svenpanne@chromium.org return; 110783130cfc204d3ffed6832a7ef149b19328a58b33svenpanne@chromium.org } 1108ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org 1109ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org if (NewLocClean.asLocation() == PrevLocClean.asLocation()) 1110ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org return; 1111ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org 111283130cfc204d3ffed6832a7ef149b19328a58b33svenpanne@chromium.org // FIXME: Ignore intra-macro edges for now. 111383130cfc204d3ffed6832a7ef149b19328a58b33svenpanne@chromium.org if (NewLocClean.asLocation().getExpansionLoc() == 111483130cfc204d3ffed6832a7ef149b19328a58b33svenpanne@chromium.org PrevLocClean.asLocation().getExpansionLoc()) 1115ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org return; 1116ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org 1117ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(NewLocClean, PrevLocClean)); 1118ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org PrevLoc = NewLoc; 1119ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org} 1120ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org 1121068ea0a6ea115c058d1d9798029bd7fa1eaaa955mstarzinger@chromium.orgvoid EdgeBuilder::addEdge(PathDiagnosticLocation NewLoc, bool alwaysAdd) { 1122ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org 11231f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org if (!alwaysAdd && NewLoc.asLocation().isMacroID()) 11241f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org return; 11251f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org 11268e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org const PathDiagnosticLocation &CLoc = getContextLocation(NewLoc); 11278e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org 11289259716434187c932704601f700375e53d865de8rossberg@chromium.org while (!CLocs.empty()) { 11299259716434187c932704601f700375e53d865de8rossberg@chromium.org ContextLocation &TopContextLoc = CLocs.back(); 11308e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org 11318e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org // Is the top location context the same as the one for the new location? 11328e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org if (TopContextLoc == CLoc) { 1133068ea0a6ea115c058d1d9798029bd7fa1eaaa955mstarzinger@chromium.org if (alwaysAdd) { 1134e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org if (IsConsumedExpr(TopContextLoc) && 11358e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org !IsControlFlowExpr(TopContextLoc.asStmt())) 11368e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org TopContextLoc.markDead(); 1137236ad9617a7359a463144a6ebeb5431a70f769cfager@chromium.org 1138b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org rawAddEdge(NewLoc); 1139b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org } 1140ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org 1141b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org return; 11429fa619507474a4c1c21c6935b3209070bc13a218machenbach@chromium.org } 11439fa619507474a4c1c21c6935b3209070bc13a218machenbach@chromium.org 1144b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org if (containsLocation(TopContextLoc, CLoc)) { 1145381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.org if (alwaysAdd) { 1146b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org rawAddEdge(NewLoc); 1147b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org 1148b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org if (IsConsumedExpr(CLoc) && !IsControlFlowExpr(CLoc.asStmt())) { 11499fe21c6d4c657d15af27c8751257d3e2bf113e45kasperl@chromium.org CLocs.push_back(ContextLocation(CLoc, true)); 115041044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org return; 1151381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.org } 115241044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org } 115341044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org 115441044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org CLocs.push_back(CLoc); 115541044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org return; 1156381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.org } 1157381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.org 1158381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.org // Context does not contain the location. Flush it. 1159b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org popLocation(); 1160b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org } 11619fa619507474a4c1c21c6935b3209070bc13a218machenbach@chromium.org 11629fa619507474a4c1c21c6935b3209070bc13a218machenbach@chromium.org // If we reach here, there is no enclosing context. Just add the edge. 1163b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org rawAddEdge(NewLoc); 1164381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.org} 1165b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org 1166b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.orgbool EdgeBuilder::IsConsumedExpr(const PathDiagnosticLocation &L) { 11679fa619507474a4c1c21c6935b3209070bc13a218machenbach@chromium.org if (const Expr *X = dyn_cast_or_null<Expr>(L.asStmt())) 11689fa619507474a4c1c21c6935b3209070bc13a218machenbach@chromium.org return PDB.getParentMap().isConsumedExpr(X) && !IsControlFlowExpr(X); 1169b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org 1170381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.org return false; 1171b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org} 1172b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org 11739fa619507474a4c1c21c6935b3209070bc13a218machenbach@chromium.orgvoid EdgeBuilder::addExtendedContext(const Stmt *S) { 11749fa619507474a4c1c21c6935b3209070bc13a218machenbach@chromium.org if (!S) 1175b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org return; 1176381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.org 1177b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org const Stmt *Parent = PDB.getParent(S); 1178381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.org while (Parent) { 1179381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.org if (isa<CompoundStmt>(Parent)) 1180b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org Parent = PDB.getParent(Parent); 1181b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org else 1182b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org break; 11839fe21c6d4c657d15af27c8751257d3e2bf113e45kasperl@chromium.org } 1184ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org 1185ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org if (Parent) { 1186381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.org switch (Parent->getStmtClass()) { 1187b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org case Stmt::DoStmtClass: 1188381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.org case Stmt::ObjCAtSynchronizedStmtClass: 1189381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.org addContext(Parent); 1190b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org default: 1191b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org break; 1192b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org } 119343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen } 1194ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org 119543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen addContext(S); 119643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen} 119743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 119843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenvoid EdgeBuilder::addContext(const Stmt *S) { 119943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen if (!S) 120043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen return; 120143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 1202750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org PathDiagnosticLocation L(S, PDB.getSourceManager(), PDB.LC); 1203ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org addContext(L); 120443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen} 120583e168294456ca2f02db421a635f7d5f5d023966kmillikin@chromium.org 120643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenvoid EdgeBuilder::addContext(const PathDiagnosticLocation &L) { 1207750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org while (!CLocs.empty()) { 1208750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org const PathDiagnosticLocation &TopContextLoc = CLocs.back(); 1209750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org 1210afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org // Is the top location context the same as the one for the new location? 1211afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org if (TopContextLoc == L) 1212750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org return; 1213f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org 1214f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org if (containsLocation(TopContextLoc, L)) { 1215f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org CLocs.push_back(L); 1216afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org return; 1217f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org } 1218f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org 1219f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org // Context does not contain the location. Flush it. 1220f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org popLocation(); 1221afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org } 1222f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org 1223750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org CLocs.push_back(L); 122443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen} 122543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 122643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// Cone-of-influence: support the reverse propagation of "interesting" symbols 122743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// and values by tracing interesting calculations backwards through evaluated 122843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// expressions along a path. This is probably overly complicated, but the idea 1229ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// is that if an expression computed an "interesting" value, the child 123043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// expressions are are also likely to be "interesting" as well (which then 123183e168294456ca2f02db421a635f7d5f5d023966kmillikin@chromium.org// propagates to the values they in turn compute). This reverse propagation 123243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// is needed to track interesting correlations across function call boundaries, 1233afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org// where formal arguments bind to actual arguments, etc. This is also needed 123443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// because the constraint solver sometimes simplifies certain symbolic values 123543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// into constants when appropriate, and this complicates reasoning about 1236e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org// interesting values. 123743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansentypedef llvm::DenseSet<const Expr *> InterestingExprs; 1238ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org 123943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenstatic void reversePropagateIntererstingSymbols(BugReport &R, 124083e168294456ca2f02db421a635f7d5f5d023966kmillikin@chromium.org InterestingExprs &IE, 124143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen const ProgramState *State, 1242afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org const Expr *Ex, 124343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen const LocationContext *LCtx) { 124443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen SVal V = State->getSVal(Ex, LCtx); 124543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen if (!(R.isInteresting(V) || IE.count(Ex))) 124643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen return; 1247ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org 12487979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org switch (Ex->getStmtClass()) { 124943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen default: 125043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen if (!isa<CastExpr>(Ex)) 125143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen break; 125243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen // Fall through. 1253ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org case Stmt::BinaryOperatorClass: 1254ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org case Stmt::UnaryOperatorClass: { 1255b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org for (Stmt::const_child_iterator CI = Ex->child_begin(), 1256381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.org CE = Ex->child_end(); 1257381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.org CI != CE; ++CI) { 125843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen if (const Expr *child = dyn_cast_or_null<Expr>(*CI)) { 125943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen IE.insert(child); 126043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen SVal ChildV = State->getSVal(child, LCtx); 126143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen R.markInteresting(ChildV); 1262ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org } 1263ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org break; 1264b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org } 1265381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.org } 126643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen } 126743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 126843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen R.markInteresting(V); 1269ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org} 1270e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org 1271ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.orgstatic void reversePropagateInterestingSymbols(BugReport &R, 1272ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org InterestingExprs &IE, 1273ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org const ProgramState *State, 1274ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org const LocationContext *CalleeCtx, 1275e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org const LocationContext *CallerCtx) 1276ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org{ 1277ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org // FIXME: Handle non-CallExpr-based CallEvents. 1278ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org const StackFrameContext *Callee = CalleeCtx->getCurrentStackFrame(); 1279750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org const Stmt *CallSite = Callee->getCallSite(); 1280ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org if (const CallExpr *CE = dyn_cast_or_null<CallExpr>(CallSite)) { 1281c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CalleeCtx->getDecl())) { 1282ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org FunctionDecl::param_const_iterator PI = FD->param_begin(), 12831510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org PE = FD->param_end(); 12845f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org CallExpr::const_arg_iterator AI = CE->arg_begin(), AE = CE->arg_end(); 12855f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org for (; AI != AE && PI != PE; ++AI, ++PI) { 128601beca7f8d9f549e04ec575a0bca96d859ab55a5ager@chromium.org if (const Expr *ArgE = *AI) { 1287750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org if (const ParmVarDecl *PD = *PI) { 1288750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org Loc LV = State->getLValue(PD, CalleeCtx); 1289750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org if (R.isInteresting(LV) || R.isInteresting(State->getRawSVal(LV))) 1290afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org IE.insert(ArgE); 1291750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org } 1292f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org } 1293f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org } 1294f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org } 1295f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org } 1296f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org} 1297f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org 1298afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org//===----------------------------------------------------------------------===// 1299afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org// Functions for determining if a loop was executed 0 times. 1300f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org//===----------------------------------------------------------------------===// 1301750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org 130201beca7f8d9f549e04ec575a0bca96d859ab55a5ager@chromium.org/// Return true if the terminator is a loop and the destination is the 130301beca7f8d9f549e04ec575a0bca96d859ab55a5ager@chromium.org/// false branch. 1304ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.orgstatic bool isLoopJumpPastBody(const Stmt *Term, const BlockEdge *BE) { 1305ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org switch (Term->getStmtClass()) { 1306ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org case Stmt::ForStmtClass: 1307750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org case Stmt::WhileStmtClass: 1308c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org break; 1309750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org default: 1310ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org // Note that we intentionally do not include do..while here. 1311ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org return false; 1312ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org } 1313750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org 1314c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org // Did we take the false branch? 1315750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org const CFGBlock *Src = BE->getSrc(); 1316ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org assert(Src->succ_size() == 2); 1317ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org return (*(Src->succ_begin()+1) == BE->getDst()); 1318ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org} 1319750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org 1320c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.orgstatic bool isContainedByStmt(ParentMap &PM, const Stmt *S, const Stmt *SubS) { 1321750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org while (SubS) { 132201beca7f8d9f549e04ec575a0bca96d859ab55a5ager@chromium.org if (SubS == S) 132301beca7f8d9f549e04ec575a0bca96d859ab55a5ager@chromium.org return true; 132401beca7f8d9f549e04ec575a0bca96d859ab55a5ager@chromium.org SubS = PM.getParent(SubS); 1325ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org } 1326ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org return false; 1327ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org} 13281510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org 13291510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.orgstatic const Stmt *getStmtBeforeCond(ParentMap &PM, const Stmt *Term, 1330ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org const ExplodedNode *N) { 13311510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org while (N) { 13321510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org Optional<StmtPoint> SP = N->getLocation().getAs<StmtPoint>(); 13331510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org if (SP) { 13341510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org const Stmt *S = SP->getStmt(); 13351510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org if (!isContainedByStmt(PM, Term, S)) 13361510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org return S; 13371510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org } 13381510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org N = GetPredecessorNode(N); 13391510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org } 13401510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org return 0; 1341c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org} 1342ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org 1343c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.orgstatic bool isInLoopBody(ParentMap &PM, const Stmt *S, const Stmt *Term) { 1344d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org const Stmt *LoopBody = 0; 13451510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org switch (Term->getStmtClass()) { 13461510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org case Stmt::ForStmtClass: { 1347ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org const ForStmt *FS = cast<ForStmt>(Term); 13481510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org if (isContainedByStmt(PM, FS->getInc(), S)) 13491510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org return true; 1350381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.org LoopBody = FS->getBody(); 1351381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.org break; 135243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen } 135343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen case Stmt::WhileStmtClass: 135443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen LoopBody = cast<WhileStmt>(Term)->getBody(); 13553a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org break; 13563a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org default: 1357750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org return false; 1358c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org } 1359ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org return isContainedByStmt(PM, LoopBody, S); 1360c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org} 1361d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org 13621510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org//===----------------------------------------------------------------------===// 13631510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org// Top-level logic for generating extensive path diagnostics. 1364ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org//===----------------------------------------------------------------------===// 13651510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org 1366750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.orgstatic bool GenerateExtensivePathDiagnostic(PathDiagnostic& PD, 1367750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org PathDiagnosticBuilder &PDB, 1368750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org const ExplodedNode *N, 1369750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org ArrayRef<BugReporterVisitor *> visitors) { 1370750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org EdgeBuilder EB(PD, PDB); 1371ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org const SourceManager& SM = PDB.getSourceManager(); 1372750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org StackDiagVector CallStack; 13738e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org InterestingExprs IE; 13748e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org 13753a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org const ExplodedNode *NextNode = N->pred_empty() ? NULL : *(N->pred_begin()); 13763a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org while (NextNode) { 13773a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org N = NextNode; 13783a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org NextNode = GetPredecessorNode(N); 13793a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org ProgramPoint P = N->getLocation(); 13803a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org 13814e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org do { 1382750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org if (Optional<PostStmt> PS = P.getAs<PostStmt>()) { 1383c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org if (const Expr *Ex = PS->getStmtAs<Expr>()) 1384ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org reversePropagateIntererstingSymbols(*PDB.getBugReport(), IE, 1385c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org N->getState().getPtr(), Ex, 1386d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org N->getLocationContext()); 13871510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org } 13881510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org 13894954674151afa960af66efb4831df06bde727333yangguo@chromium.org if (Optional<CallExitEnd> CE = P.getAs<CallExitEnd>()) { 1390ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org const Stmt *S = CE->getCalleeContext()->getCallSite(); 1391ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org if (const Expr *Ex = dyn_cast_or_null<Expr>(S)) { 1392ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org reversePropagateIntererstingSymbols(*PDB.getBugReport(), IE, 13931510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org N->getState().getPtr(), Ex, 1394750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org N->getLocationContext()); 1395750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org } 1396750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org 1397afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org PathDiagnosticCallPiece *C = 1398750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org PathDiagnosticCallPiece::construct(N, *CE, SM); 1399ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org GRBugReporter& BR = PDB.getBugReporter(); 1400750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org BR.addCallPieceLocationContextPair(C, CE->getCalleeContext()); 1401750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org 14023a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org EB.addEdge(C->callReturn, true); 14033a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org EB.flushLocations(); 14045aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org 1405381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.org PD.getActivePath().push_front(C); 140643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen PD.pushActivePath(&C->path); 140743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen CallStack.push_back(StackDiagPair(C, N)); 140843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen break; 14093a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org } 14103a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org 14113a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org // Pop the call hierarchy if we are done walking the contents 1412eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org // of a function call. 14133a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org if (Optional<CallEnter> CE = P.getAs<CallEnter>()) { 14143a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org // Add an edge to the start of the function. 14154e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org const Decl *D = CE->getCalleeContext()->getDecl(); 14161e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org PathDiagnosticLocation pos = 1417dd6d9eedcac6e3b5adfb7702649ac32def9c3585mvstanton@chromium.org PathDiagnosticLocation::createBegin(D, SM); 1418ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org EB.addEdge(pos); 1419c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org 1420dd6d9eedcac6e3b5adfb7702649ac32def9c3585mvstanton@chromium.org // Flush all locations, and pop the active path. 1421dd6d9eedcac6e3b5adfb7702649ac32def9c3585mvstanton@chromium.org bool VisitedEntireCall = PD.isWithinCall(); 14221510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org EB.flushLocations(); 14231510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org PD.popActivePath(); 1424ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org PDB.LC = N->getLocationContext(); 14251510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org 142683e168294456ca2f02db421a635f7d5f5d023966kmillikin@chromium.org // Either we just added a bunch of stuff to the top-level path, or 14273a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org // we have a previous CallExitEnd. If the former, it means that the 1428afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org // path terminated within a function call. We must then take the 1429750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org // current contents of the active path and place it within 1430750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org // a new PathDiagnosticCallPiece. 1431750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org PathDiagnosticCallPiece *C; 1432afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org if (VisitedEntireCall) { 1433750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org C = cast<PathDiagnosticCallPiece>(PD.getActivePath().front()); 1434ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org } else { 1435750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org const Decl *Caller = CE->getLocationContext()->getDecl(); 14361e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org C = PathDiagnosticCallPiece::construct(PD.getActivePath(), Caller); 14373a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org GRBugReporter& BR = PDB.getBugReporter(); 14383a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org BR.addCallPieceLocationContextPair(C, CE->getCalleeContext()); 14395aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org } 1440381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.org 1441245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org C->setCallee(*CE, SM); 1442245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org EB.addContext(C->getLocation()); 1443245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org 1444ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org if (!CallStack.empty()) { 1445ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org assert(CallStack.back().first == C); 1446ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org CallStack.pop_back(); 1447c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org } 1448ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org break; 1449c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org } 1450d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org 14511510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org // Note that is important that we update the LocationContext 14521510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org // after looking at CallExits. CallExit basically adds an 1453ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org // edge in the *caller*, so we don't want to update the LocationContext 14541510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org // too soon. 14551510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org PDB.LC = N->getLocationContext(); 14565aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org 1457381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.org // Block edges. 145843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen if (Optional<BlockEdge> BE = P.getAs<BlockEdge>()) { 145943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen // Does this represent entering a call? If so, look at propagating 146043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen // interesting symbols across call boundaries. 1461fb547e07aef43e02715c5d6c1530e84bb3cbba02machenbach@chromium.org if (NextNode) { 1462fb547e07aef43e02715c5d6c1530e84bb3cbba02machenbach@chromium.org const LocationContext *CallerCtx = NextNode->getLocationContext(); 1463fb547e07aef43e02715c5d6c1530e84bb3cbba02machenbach@chromium.org const LocationContext *CalleeCtx = PDB.LC; 1464fb547e07aef43e02715c5d6c1530e84bb3cbba02machenbach@chromium.org if (CallerCtx != CalleeCtx) { 1465fb547e07aef43e02715c5d6c1530e84bb3cbba02machenbach@chromium.org reversePropagateInterestingSymbols(*PDB.getBugReport(), IE, 1466fb547e07aef43e02715c5d6c1530e84bb3cbba02machenbach@chromium.org N->getState().getPtr(), 1467fb547e07aef43e02715c5d6c1530e84bb3cbba02machenbach@chromium.org CalleeCtx, CallerCtx); 1468fb547e07aef43e02715c5d6c1530e84bb3cbba02machenbach@chromium.org } 1469fb547e07aef43e02715c5d6c1530e84bb3cbba02machenbach@chromium.org } 1470fb547e07aef43e02715c5d6c1530e84bb3cbba02machenbach@chromium.org 1471fb547e07aef43e02715c5d6c1530e84bb3cbba02machenbach@chromium.org // Are we jumping to the head of a loop? Add a special diagnostic. 1472fb547e07aef43e02715c5d6c1530e84bb3cbba02machenbach@chromium.org if (const Stmt *Loop = BE->getSrc()->getLoopTarget()) { 1473fb547e07aef43e02715c5d6c1530e84bb3cbba02machenbach@chromium.org PathDiagnosticLocation L(Loop, SM, PDB.LC); 1474fb547e07aef43e02715c5d6c1530e84bb3cbba02machenbach@chromium.org const CompoundStmt *CS = NULL; 1475fb547e07aef43e02715c5d6c1530e84bb3cbba02machenbach@chromium.org 1476fb547e07aef43e02715c5d6c1530e84bb3cbba02machenbach@chromium.org if (const ForStmt *FS = dyn_cast<ForStmt>(Loop)) 1477fb547e07aef43e02715c5d6c1530e84bb3cbba02machenbach@chromium.org CS = dyn_cast<CompoundStmt>(FS->getBody()); 1478fb547e07aef43e02715c5d6c1530e84bb3cbba02machenbach@chromium.org else if (const WhileStmt *WS = dyn_cast<WhileStmt>(Loop)) 14794a5224e84636d192e82f288bfab0d308bdae5c37whesse@chromium.org CS = dyn_cast<CompoundStmt>(WS->getBody()); 1480c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org 1481c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org PathDiagnosticEventPiece *p = 1482c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org new PathDiagnosticEventPiece(L, 14838e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org "Looping back to the head of the loop"); 1484d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org p->setPrunable(true); 14854a5224e84636d192e82f288bfab0d308bdae5c37whesse@chromium.org 14864a5224e84636d192e82f288bfab0d308bdae5c37whesse@chromium.org EB.addEdge(p->getLocation(), true); 14874a5224e84636d192e82f288bfab0d308bdae5c37whesse@chromium.org PD.getActivePath().push_front(p); 14884a5224e84636d192e82f288bfab0d308bdae5c37whesse@chromium.org 148971daaf639544be2a6638e3566f78e0b14f05cd7bager@chromium.org if (CS) { 1490c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org PathDiagnosticLocation BL = 1491ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org PathDiagnosticLocation::createEndBrace(CS, SM); 1492c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org EB.addEdge(BL); 1493d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org } 14941510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org } 14951510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org 1496ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org const CFGBlock *BSrc = BE->getSrc(); 14971510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org ParentMap &PM = PDB.getParentMap(); 14981510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org 149971daaf639544be2a6638e3566f78e0b14f05cd7bager@chromium.org if (const Stmt *Term = BSrc->getTerminator()) { 15001510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org // Are we jumping past the loop body without ever executing the 15015aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org // loop (because the condition was false)? 150271daaf639544be2a6638e3566f78e0b14f05cd7bager@chromium.org if (isLoopJumpPastBody(Term, &*BE) && 150371daaf639544be2a6638e3566f78e0b14f05cd7bager@chromium.org !isInLoopBody(PM, 150471daaf639544be2a6638e3566f78e0b14f05cd7bager@chromium.org getStmtBeforeCond(PM, 150571daaf639544be2a6638e3566f78e0b14f05cd7bager@chromium.org BSrc->getTerminatorCondition(), 150643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen N), 1507c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org Term)) { 1508c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org PathDiagnosticLocation L(Term, SM, PDB.LC); 1509c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org PathDiagnosticEventPiece *PE = 1510d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org new PathDiagnosticEventPiece(L, "Loop body executed 0 times"); 1511b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org PE->setPrunable(true); 1512b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org 1513b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org EB.addEdge(PE->getLocation(), true); 1514b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org PD.getActivePath().push_front(PE); 1515b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org } 1516c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org 1517c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org // In any case, add the terminator as the current statement 1518c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org // context for control edges. 1519d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org EB.addContext(Term); 1520ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org } 1521c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org 1522ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org break; 1523ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org } 1524ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org 1525ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org if (Optional<BlockEntrance> BE = P.getAs<BlockEntrance>()) { 1526ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org CFGElement First = BE->getFirstElement(); 1527b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org if (CFGStmt S = First.getAs<CFGStmt>()) { 1528b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org const Stmt *stmt = S.getStmt(); 1529ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org if (IsControlFlowExpr(stmt)) { 1530c03a1924dcc113678c0ebe58aa7d3c855a657719yangguo@chromium.org // Add the proper context for '&&', '||', and '?'. 1531c03a1924dcc113678c0ebe58aa7d3c855a657719yangguo@chromium.org EB.addContext(stmt); 1532c03a1924dcc113678c0ebe58aa7d3c855a657719yangguo@chromium.org } 1533ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org else 1534ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org EB.addExtendedContext(PDB.getEnclosingStmtLocation(stmt).asStmt()); 1535ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org } 1536ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org 1537c03a1924dcc113678c0ebe58aa7d3c855a657719yangguo@chromium.org break; 1538c03a1924dcc113678c0ebe58aa7d3c855a657719yangguo@chromium.org } 1539ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org 1540c03a1924dcc113678c0ebe58aa7d3c855a657719yangguo@chromium.org 1541c03a1924dcc113678c0ebe58aa7d3c855a657719yangguo@chromium.org } while (0); 1542c03a1924dcc113678c0ebe58aa7d3c855a657719yangguo@chromium.org 1543ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org if (!NextNode) 1544ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org continue; 1545ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org 1546ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org // Add pieces from custom visitors. 1547c03a1924dcc113678c0ebe58aa7d3c855a657719yangguo@chromium.org BugReport *R = PDB.getBugReport(); 1548c03a1924dcc113678c0ebe58aa7d3c855a657719yangguo@chromium.org for (ArrayRef<BugReporterVisitor *>::iterator I = visitors.begin(), 1549e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org E = visitors.end(); 1550c03a1924dcc113678c0ebe58aa7d3c855a657719yangguo@chromium.org I != E; ++I) { 1551ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org if (PathDiagnosticPiece *p = (*I)->VisitNode(N, NextNode, PDB, *R)) { 1552ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org const PathDiagnosticLocation &Loc = p->getLocation(); 1553c03a1924dcc113678c0ebe58aa7d3c855a657719yangguo@chromium.org EB.addEdge(Loc, true); 1554c03a1924dcc113678c0ebe58aa7d3c855a657719yangguo@chromium.org PD.getActivePath().push_front(p); 1555c03a1924dcc113678c0ebe58aa7d3c855a657719yangguo@chromium.org updateStackPiecesWithMessage(p, CallStack); 1556ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org 1557c03a1924dcc113678c0ebe58aa7d3c855a657719yangguo@chromium.org if (const Stmt *S = Loc.asStmt()) 1558c03a1924dcc113678c0ebe58aa7d3c855a657719yangguo@chromium.org EB.addExtendedContext(PDB.getEnclosingStmtLocation(S).asStmt()); 1559ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org } 1560c03a1924dcc113678c0ebe58aa7d3c855a657719yangguo@chromium.org } 1561b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org } 1562e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org 1563d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org return PDB.getBugReport()->isValid(); 1564d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org} 1565d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org 1566d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org//===----------------------------------------------------------------------===// 1567d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org// Methods for BugType and subclasses. 1568d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org//===----------------------------------------------------------------------===// 1569d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.orgBugType::~BugType() { } 1570d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org 1571d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.orgvoid BugType::FlushReports(BugReporter &BR) {} 1572d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org 1573b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.orgvoid BuiltinBug::anchor() {} 15748e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org 157510480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org//===----------------------------------------------------------------------===// 15768e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org// Methods for BugReport and subclasses. 1577ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org//===----------------------------------------------------------------------===// 15785f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org 1579b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.orgvoid BugReport::NodeResolver::anchor() {} 1580b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org 1581b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.orgvoid BugReport::addVisitor(BugReporterVisitor* visitor) { 1582b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org if (!visitor) 1583b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org return; 1584b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org 1585b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org llvm::FoldingSetNodeID ID; 1586b08986cb66c3f6687247cb6da186c1e73057e399whesse@chromium.org visitor->Profile(ID); 1587c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org void *InsertPos; 1588c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org 1589c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org if (CallbacksSet.FindNodeOrInsertPos(ID, InsertPos)) { 1590b08986cb66c3f6687247cb6da186c1e73057e399whesse@chromium.org delete visitor; 1591b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org return; 1592b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org } 1593b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org 1594b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org CallbacksSet.InsertNode(visitor, InsertPos); 1595b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org Callbacks.push_back(visitor); 1596b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org ++ConfigurationChangeToken; 1597c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org} 1598ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org 15995f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.orgBugReport::~BugReport() { 1600eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org for (visitor_iterator I = visitor_begin(), E = visitor_end(); I != E; ++I) { 1601eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org delete *I; 16025f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org } 1603eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org while (!interestingSymbols.empty()) { 1604381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.org popInterestingSymbolsAndRegions(); 160543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen } 160643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen} 160743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 160843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenconst Decl *BugReport::getDeclWithIssue() const { 1609ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org if (DeclWithIssue) 1610ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org return DeclWithIssue; 1611381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.org 161243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen const ExplodedNode *N = getErrorNode(); 161343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen if (!N) 161443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen return 0; 1615381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.org 161643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen const LocationContext *LC = N->getLocationContext(); 1617381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.org return LC->getCurrentStackFrame()->getDecl(); 161843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen} 1619381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.org 1620381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.orgvoid BugReport::Profile(llvm::FoldingSetNodeID& hash) const { 162143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen hash.AddPointer(&BT); 162243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen hash.AddString(Description); 162343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen PathDiagnosticLocation UL = getUniqueingLocation(); 1624750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org if (UL.isValid()) { 1625ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org UL.Profile(hash); 1626ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org } else if (Location.isValid()) { 16278bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org Location.Profile(hash); 16288bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org } else { 1629c03a1924dcc113678c0ebe58aa7d3c855a657719yangguo@chromium.org assert(ErrorNode); 1630381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.org hash.AddPointer(GetCurrentOrPreviousStmt(ErrorNode)); 1631381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.org } 1632381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.org 1633750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org for (SmallVectorImpl<SourceRange>::const_iterator I = 1634750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org Ranges.begin(), E = Ranges.end(); I != E; ++I) { 1635750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org const SourceRange range = *I; 1636750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org if (!range.isValid()) 1637750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org continue; 1638ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org hash.AddInteger(range.getBegin().getRawEncoding()); 1639750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org hash.AddInteger(range.getEnd().getRawEncoding()); 1640381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.org } 1641381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.org} 164243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 164343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenvoid BugReport::markInteresting(SymbolRef sym) { 164443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen if (!sym) 164543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen return; 1646ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org 1647ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org // If the symbol wasn't already in our set, note a configuration change. 1648e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org if (getInterestingSymbols().insert(sym).second) 1649e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org ++ConfigurationChangeToken; 1650e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org 1651e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org if (const SymbolMetadata *meta = dyn_cast<SymbolMetadata>(sym)) 1652e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org getInterestingRegions().insert(meta->getRegion()); 1653e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org} 1654e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org 1655e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.orgvoid BugReport::markInteresting(const MemRegion *R) { 165643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen if (!R) 1657ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org return; 1658ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org 1659381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.org // If the base region wasn't already in our set, note a configuration change. 1660381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.org R = R->getBaseRegion(); 166143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen if (getInterestingRegions().insert(R).second) 166243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen ++ConfigurationChangeToken; 166343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 166443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R)) 1665ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org getInterestingSymbols().insert(SR->getSymbol()); 1666ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org} 1667381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.org 1668381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.orgvoid BugReport::markInteresting(SVal V) { 166943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen markInteresting(V.getAsRegion()); 167043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen markInteresting(V.getAsSymbol()); 167143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen} 1672769cc962a043dd8d92cc010dd2c50bc26f652c94mads.s.ager@gmail.com 1673ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.orgvoid BugReport::markInteresting(const LocationContext *LC) { 1674ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org if (!LC) 1675381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.org return; 1676381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.org InterestingLocationContexts.insert(LC); 1677769cc962a043dd8d92cc010dd2c50bc26f652c94mads.s.ager@gmail.com} 1678769cc962a043dd8d92cc010dd2c50bc26f652c94mads.s.ager@gmail.com 1679769cc962a043dd8d92cc010dd2c50bc26f652c94mads.s.ager@gmail.combool BugReport::isInteresting(SVal V) { 1680769cc962a043dd8d92cc010dd2c50bc26f652c94mads.s.ager@gmail.com return isInteresting(V.getAsRegion()) || isInteresting(V.getAsSymbol()); 1681ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org} 1682769cc962a043dd8d92cc010dd2c50bc26f652c94mads.s.ager@gmail.com 1683769cc962a043dd8d92cc010dd2c50bc26f652c94mads.s.ager@gmail.combool BugReport::isInteresting(SymbolRef sym) { 1684769cc962a043dd8d92cc010dd2c50bc26f652c94mads.s.ager@gmail.com if (!sym) 1685769cc962a043dd8d92cc010dd2c50bc26f652c94mads.s.ager@gmail.com return false; 1686769cc962a043dd8d92cc010dd2c50bc26f652c94mads.s.ager@gmail.com // We don't currently consider metadata symbols to be interesting 1687ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org // even if we know their region is interesting. Is that correct behavior? 1688381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.org return getInterestingSymbols().count(sym); 1689381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.org} 1690381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.org 1691381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.orgbool BugReport::isInteresting(const MemRegion *R) { 1692769cc962a043dd8d92cc010dd2c50bc26f652c94mads.s.ager@gmail.com if (!R) 1693381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.org return false; 1694769cc962a043dd8d92cc010dd2c50bc26f652c94mads.s.ager@gmail.com R = R->getBaseRegion(); 1695769cc962a043dd8d92cc010dd2c50bc26f652c94mads.s.ager@gmail.com bool b = getInterestingRegions().count(R); 1696769cc962a043dd8d92cc010dd2c50bc26f652c94mads.s.ager@gmail.com if (b) 169743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen return true; 1698ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R)) 1699ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org return getInterestingSymbols().count(SR->getSymbol()); 17005f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org return false; 17015f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org} 1702dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org 170377ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.orgbool BugReport::isInteresting(const LocationContext *LC) { 170477ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org if (!LC) 170577ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org return false; 170677ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org return InterestingLocationContexts.count(LC); 170777ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org} 170877ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org 170977ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.orgvoid BugReport::lazyInitializeInterestingSets() { 1710eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org if (interestingSymbols.empty()) { 1711381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.org interestingSymbols.push_back(new Symbols()); 1712381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.org interestingRegions.push_back(new Regions()); 1713381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.org } 17147be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org} 1715eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org 17165f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.orgBugReport::Symbols &BugReport::getInterestingSymbols() { 1717381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.org lazyInitializeInterestingSets(); 1718381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.org return *interestingSymbols.back(); 1719381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.org} 172043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 1721245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.orgBugReport::Regions &BugReport::getInterestingRegions() { 1722245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org lazyInitializeInterestingSets(); 1723dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org return *interestingRegions.back(); 1724ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org} 17254f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org 1726dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.orgvoid BugReport::pushInterestingSymbolsAndRegions() { 1727dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org interestingSymbols.push_back(new Symbols(getInterestingSymbols())); 1728755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org interestingRegions.push_back(new Regions(getInterestingRegions())); 1729245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org} 17309085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 17319085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.orgvoid BugReport::popInterestingSymbolsAndRegions() { 1732755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org delete interestingSymbols.back(); 1733755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org interestingSymbols.pop_back(); 1734ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org delete interestingRegions.back(); 1735dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org interestingRegions.pop_back(); 1736755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org} 1737755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org 1738755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.orgconst Stmt *BugReport::getStmt() const { 1739a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org if (!ErrorNode) 1740a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org return 0; 1741a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 1742a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org ProgramPoint ProgP = ErrorNode->getLocation(); 1743a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org const Stmt *S = NULL; 1744a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 1745a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org if (Optional<BlockEntrance> BE = ProgP.getAs<BlockEntrance>()) { 1746a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org CFGBlock &Exit = ProgP.getLocationContext()->getCFG()->getExit(); 1747a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org if (BE->getBlock() == &Exit) 1748a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org S = GetPreviousStmt(ErrorNode); 1749a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org } 17507b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org if (!S) 17517b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org S = GetStmt(ProgP); 17527b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org 17537b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org return S; 1754a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org} 17557b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org 1756a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgstd::pair<BugReport::ranges_iterator, BugReport::ranges_iterator> 1757a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgBugReport::getRanges() { 1758a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org // If no custom ranges, add the range of the statement corresponding to 1759a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org // the error node. 1760a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org if (Ranges.empty()) { 1761a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org if (const Expr *E = dyn_cast_or_null<Expr>(getStmt())) 1762a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org addRange(E->getSourceRange()); 1763a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org else 1764a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org return std::make_pair(ranges_iterator(), ranges_iterator()); 1765a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org } 1766a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 1767a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org // User-specified absence of range info. 1768a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org if (Ranges.size() == 1 && !Ranges.begin()->isValid()) 1769a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org return std::make_pair(ranges_iterator(), ranges_iterator()); 1770a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 17717c3372bc426136cb79479c1b59d1770f5528882ahpayer@chromium.org return std::make_pair(Ranges.begin(), Ranges.end()); 17727c3372bc426136cb79479c1b59d1770f5528882ahpayer@chromium.org} 1773a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 17747c3372bc426136cb79479c1b59d1770f5528882ahpayer@chromium.orgPathDiagnosticLocation BugReport::getLocation(const SourceManager &SM) const { 177579e7902fa5f94747b5383dd40f3002dd8b62303arossberg@chromium.org if (ErrorNode) { 177671affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org assert(!Location.isValid() && 1777a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org "Either Location or ErrorNode should be specified but not both."); 1778a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 1779a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org if (const Stmt *S = GetCurrentOrPreviousStmt(ErrorNode)) { 1780b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org const LocationContext *LC = ErrorNode->getLocationContext(); 1781152a0b013d7d17f4fe9d04cdce58ec3d6fab2aa5sgjesse@chromium.org 1782152a0b013d7d17f4fe9d04cdce58ec3d6fab2aa5sgjesse@chromium.org // For member expressions, return the location of the '.' or '->'. 1783152a0b013d7d17f4fe9d04cdce58ec3d6fab2aa5sgjesse@chromium.org if (const MemberExpr *ME = dyn_cast<MemberExpr>(S)) 1784152a0b013d7d17f4fe9d04cdce58ec3d6fab2aa5sgjesse@chromium.org return PathDiagnosticLocation::createMemberLoc(ME, SM); 1785152a0b013d7d17f4fe9d04cdce58ec3d6fab2aa5sgjesse@chromium.org // For binary operators, return the location of the operator. 1786a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org if (const BinaryOperator *B = dyn_cast<BinaryOperator>(S)) 1787152a0b013d7d17f4fe9d04cdce58ec3d6fab2aa5sgjesse@chromium.org return PathDiagnosticLocation::createOperatorLoc(B, SM); 1788a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 1789a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org if (ErrorNode->getLocation().getAs<PostStmtPurgeDeadSymbols>()) 1790a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org return PathDiagnosticLocation::createEnd(S, SM, LC); 1791a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 1792152a0b013d7d17f4fe9d04cdce58ec3d6fab2aa5sgjesse@chromium.org return PathDiagnosticLocation::createBegin(S, SM, LC); 179371affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org } 1794152a0b013d7d17f4fe9d04cdce58ec3d6fab2aa5sgjesse@chromium.org } else { 1795a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org assert(Location.isValid()); 1796a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org return Location; 1797a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org } 1798a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 1799a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org return PathDiagnosticLocation(); 1800876cca833d7212e476250d102cad185cdcfa9dfesvenpanne@chromium.org} 1801a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 1802152a0b013d7d17f4fe9d04cdce58ec3d6fab2aa5sgjesse@chromium.org//===----------------------------------------------------------------------===// 1803152a0b013d7d17f4fe9d04cdce58ec3d6fab2aa5sgjesse@chromium.org// Methods for BugReporter and subclasses. 180471affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org//===----------------------------------------------------------------------===// 180571affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org 1806c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.orgBugReportEquivClass::~BugReportEquivClass() { } 180779e7902fa5f94747b5383dd40f3002dd8b62303arossberg@chromium.orgGRBugReporter::~GRBugReporter() { } 180879e7902fa5f94747b5383dd40f3002dd8b62303arossberg@chromium.orgBugReporterData::~BugReporterData() {} 180979e7902fa5f94747b5383dd40f3002dd8b62303arossberg@chromium.org 181079e7902fa5f94747b5383dd40f3002dd8b62303arossberg@chromium.orgExplodedGraph &GRBugReporter::getGraph() { return Eng.getGraph(); } 181179e7902fa5f94747b5383dd40f3002dd8b62303arossberg@chromium.org 181279e7902fa5f94747b5383dd40f3002dd8b62303arossberg@chromium.orgProgramStateManager& 181379e7902fa5f94747b5383dd40f3002dd8b62303arossberg@chromium.orgGRBugReporter::getStateManager() { return Eng.getStateManager(); } 1814ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org 181579e7902fa5f94747b5383dd40f3002dd8b62303arossberg@chromium.orgBugReporter::~BugReporter() { 181679e7902fa5f94747b5383dd40f3002dd8b62303arossberg@chromium.org FlushReports(); 181779e7902fa5f94747b5383dd40f3002dd8b62303arossberg@chromium.org 181879e7902fa5f94747b5383dd40f3002dd8b62303arossberg@chromium.org // Free the bug reports we are tracking. 181979e7902fa5f94747b5383dd40f3002dd8b62303arossberg@chromium.org typedef std::vector<BugReportEquivClass *> ContTy; 182079e7902fa5f94747b5383dd40f3002dd8b62303arossberg@chromium.org for (ContTy::iterator I = EQClassesVector.begin(), E = EQClassesVector.end(); 182179e7902fa5f94747b5383dd40f3002dd8b62303arossberg@chromium.org I != E; ++I) { 182279e7902fa5f94747b5383dd40f3002dd8b62303arossberg@chromium.org delete *I; 182379e7902fa5f94747b5383dd40f3002dd8b62303arossberg@chromium.org } 182479e7902fa5f94747b5383dd40f3002dd8b62303arossberg@chromium.org} 18251510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org 18261510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.orgvoid BugReporter::FlushReports() { 18271510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org if (BugTypes.isEmpty()) 18281510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org return; 182979e7902fa5f94747b5383dd40f3002dd8b62303arossberg@chromium.org 183079e7902fa5f94747b5383dd40f3002dd8b62303arossberg@chromium.org // First flush the warnings for each BugType. This may end up creating new 183179e7902fa5f94747b5383dd40f3002dd8b62303arossberg@chromium.org // warnings and new BugTypes. 183279e7902fa5f94747b5383dd40f3002dd8b62303arossberg@chromium.org // FIXME: Only NSErrorChecker needs BugType's FlushReports. 183332aa03c4b5fe6e129df7529ecdaaeefce3ecee29jkummerow@chromium.org // Turn NSErrorChecker into a proper checker and remove this. 183432aa03c4b5fe6e129df7529ecdaaeefce3ecee29jkummerow@chromium.org SmallVector<const BugType*, 16> bugTypes; 183532aa03c4b5fe6e129df7529ecdaaeefce3ecee29jkummerow@chromium.org for (BugTypesTy::iterator I=BugTypes.begin(), E=BugTypes.end(); I!=E; ++I) 183632aa03c4b5fe6e129df7529ecdaaeefce3ecee29jkummerow@chromium.org bugTypes.push_back(*I); 183779e7902fa5f94747b5383dd40f3002dd8b62303arossberg@chromium.org for (SmallVector<const BugType*, 16>::iterator 183879e7902fa5f94747b5383dd40f3002dd8b62303arossberg@chromium.org I = bugTypes.begin(), E = bugTypes.end(); I != E; ++I) 183979e7902fa5f94747b5383dd40f3002dd8b62303arossberg@chromium.org const_cast<BugType*>(*I)->FlushReports(*this); 184079e7902fa5f94747b5383dd40f3002dd8b62303arossberg@chromium.org 184179e7902fa5f94747b5383dd40f3002dd8b62303arossberg@chromium.org // We need to flush reports in deterministic order to ensure the order 184279e7902fa5f94747b5383dd40f3002dd8b62303arossberg@chromium.org // of the reports is consistent between runs. 184379e7902fa5f94747b5383dd40f3002dd8b62303arossberg@chromium.org typedef std::vector<BugReportEquivClass *> ContVecTy; 184479e7902fa5f94747b5383dd40f3002dd8b62303arossberg@chromium.org for (ContVecTy::iterator EI=EQClassesVector.begin(), EE=EQClassesVector.end(); 1845a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org EI != EE; ++EI){ 1846a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org BugReportEquivClass& EQ = **EI; 1847a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org FlushReport(EQ); 1848a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org } 184979e7902fa5f94747b5383dd40f3002dd8b62303arossberg@chromium.org 185079e7902fa5f94747b5383dd40f3002dd8b62303arossberg@chromium.org // BugReporter owns and deletes only BugTypes created implicitly through 185179e7902fa5f94747b5383dd40f3002dd8b62303arossberg@chromium.org // EmitBasicReport. 185279e7902fa5f94747b5383dd40f3002dd8b62303arossberg@chromium.org // FIXME: There are leaks from checkers that assume that the BugTypes they 185379e7902fa5f94747b5383dd40f3002dd8b62303arossberg@chromium.org // create will be destroyed by the BugReporter. 185479e7902fa5f94747b5383dd40f3002dd8b62303arossberg@chromium.org for (llvm::StringMap<BugType*>::iterator 185579e7902fa5f94747b5383dd40f3002dd8b62303arossberg@chromium.org I = StrBugTypes.begin(), E = StrBugTypes.end(); I != E; ++I) 185679e7902fa5f94747b5383dd40f3002dd8b62303arossberg@chromium.org delete I->second; 18571510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org 18581510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org // Remove all references to the BugType objects. 1859c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org BugTypes = F.getEmptySet(); 186079e7902fa5f94747b5383dd40f3002dd8b62303arossberg@chromium.org} 1861c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org 1862c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org//===----------------------------------------------------------------------===// 1863c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org// PathDiagnostics generation. 18645c838251403b0be9a882540f1922577abba4c872ager@chromium.org//===----------------------------------------------------------------------===// 1865c03a1924dcc113678c0ebe58aa7d3c855a657719yangguo@chromium.org 18667c3372bc426136cb79479c1b59d1770f5528882ahpayer@chromium.orgstatic std::pair<std::pair<ExplodedGraph*, NodeBackMap*>, 1867994edf6a113fb3651536b60073df05a72a95f77erossberg@chromium.org std::pair<ExplodedNode*, unsigned> > 18687c3372bc426136cb79479c1b59d1770f5528882ahpayer@chromium.orgMakeReportGraph(const ExplodedGraph* G, 186979e7902fa5f94747b5383dd40f3002dd8b62303arossberg@chromium.org SmallVectorImpl<const ExplodedNode*> &nodes) { 18705c838251403b0be9a882540f1922577abba4c872ager@chromium.org 18715c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Create the trimmed graph. It will contain the shortest paths from the 18725c838251403b0be9a882540f1922577abba4c872ager@chromium.org // error nodes to the root. In the new graph we should only have one 18735c838251403b0be9a882540f1922577abba4c872ager@chromium.org // error node unless there are two or more error nodes with the same minimum 18745c838251403b0be9a882540f1922577abba4c872ager@chromium.org // path length. 18755c838251403b0be9a882540f1922577abba4c872ager@chromium.org ExplodedGraph* GTrim; 187634e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org InterExplodedGraphMap* NMap; 187734e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org 187834e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org llvm::DenseMap<const void*, const void*> InverseMap; 187934e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org llvm::tie(GTrim, NMap) = G->Trim(nodes.data(), nodes.data() + nodes.size(), 188034e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org &InverseMap); 18819fa619507474a4c1c21c6935b3209070bc13a218machenbach@chromium.org 18821e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org // Create owning pointers for GTrim and NMap just to ensure that they are 18839fa619507474a4c1c21c6935b3209070bc13a218machenbach@chromium.org // released when this function exists. 188434e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org OwningPtr<ExplodedGraph> AutoReleaseGTrim(GTrim); 1885f95d4b920abb640ab0986d138ad559a7d3b91d04danno@chromium.org OwningPtr<InterExplodedGraphMap> AutoReleaseNMap(NMap); 1886f95d4b920abb640ab0986d138ad559a7d3b91d04danno@chromium.org 1887f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org // Find the (first) error node in the trimmed graph. We just need to consult 188834e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org // the node map (NMap) which maps from nodes in the original graph to nodes 188934e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org // in the new graph. 18904e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org 18911e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org std::queue<const ExplodedNode*> WS; 189234e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org typedef llvm::DenseMap<const ExplodedNode*, unsigned> IndexMapTy; 189334e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org IndexMapTy IndexMap; 1894f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org 189534e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org for (unsigned nodeIndex = 0 ; nodeIndex < nodes.size(); ++nodeIndex) { 189634e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org const ExplodedNode *originalNode = nodes[nodeIndex]; 18974e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org if (const ExplodedNode *N = NMap->getMappedNode(originalNode)) { 189834e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org WS.push(N); 189934e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org IndexMap[originalNode] = nodeIndex; 1900f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org } 190134e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org } 190234e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org 1903e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org assert(!WS.empty() && "No error node found in the trimmed graph."); 19041e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org 190534e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org // Create a new (third!) graph with a single path. This is the graph 190634e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org // that will be returned to the caller. 190734e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org ExplodedGraph *GNew = new ExplodedGraph(); 190834e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org 190934e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org // Sometimes the trimmed graph can contain a cycle. Perform a reverse BFS 191034e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org // to the root node, and then construct a new graph that contains only 191134e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org // a single path. 191234e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org llvm::DenseMap<const void*,unsigned> Visited; 191334e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org 1914f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org unsigned cnt = 0; 191534e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org const ExplodedNode *Root = 0; 191634e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org 1917f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org while (!WS.empty()) { 191834e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org const ExplodedNode *Node = WS.front(); 19194e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org WS.pop(); 192034e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org 192134e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org if (Visited.find(Node) != Visited.end()) 192234e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org continue; 192334e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org 1924152a0b013d7d17f4fe9d04cdce58ec3d6fab2aa5sgjesse@chromium.org Visited[Node] = cnt++; 1925c03a1924dcc113678c0ebe58aa7d3c855a657719yangguo@chromium.org 19267c3372bc426136cb79479c1b59d1770f5528882ahpayer@chromium.org if (Node->pred_empty()) { 1927994edf6a113fb3651536b60073df05a72a95f77erossberg@chromium.org Root = Node; 1928c03a1924dcc113678c0ebe58aa7d3c855a657719yangguo@chromium.org break; 19297c3372bc426136cb79479c1b59d1770f5528882ahpayer@chromium.org } 1930720dc0bc17114e33b9b2177fcb6726bda9cabd62sgjesse@chromium.org 1931a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org for (ExplodedNode::const_pred_iterator I=Node->pred_begin(), 19327c3372bc426136cb79479c1b59d1770f5528882ahpayer@chromium.org E=Node->pred_end(); I!=E; ++I) 193371affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org WS.push(*I); 193471affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org } 193571affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org 193671affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org assert(Root); 19374954674151afa960af66efb4831df06bde727333yangguo@chromium.org 19384954674151afa960af66efb4831df06bde727333yangguo@chromium.org // Now walk from the root down the BFS path, always taking the successor 1939ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org // with the lowest number. 194034e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org ExplodedNode *Last = 0, *First = 0; 194171affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org NodeBackMap *BM = new NodeBackMap(); 194271affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org unsigned NodeIndex = 0; 194371affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org 1944ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org for ( const ExplodedNode *N = Root ;;) { 1945ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org // Lookup the number associated with the current node. 1946c03a1924dcc113678c0ebe58aa7d3c855a657719yangguo@chromium.org llvm::DenseMap<const void*,unsigned>::iterator I = Visited.find(N); 19477c3372bc426136cb79479c1b59d1770f5528882ahpayer@chromium.org assert(I != Visited.end()); 1948994edf6a113fb3651536b60073df05a72a95f77erossberg@chromium.org 19497c3372bc426136cb79479c1b59d1770f5528882ahpayer@chromium.org // Create the equivalent node in the new graph with the same state 195079e7902fa5f94747b5383dd40f3002dd8b62303arossberg@chromium.org // and location. 1951b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org ExplodedNode *NewN = GNew->getNode(N->getLocation(), N->getState()); 19527c3372bc426136cb79479c1b59d1770f5528882ahpayer@chromium.org 19537c3372bc426136cb79479c1b59d1770f5528882ahpayer@chromium.org // Store the mapping to the original node. 1954750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org llvm::DenseMap<const void*, const void*>::iterator IMitr=InverseMap.find(N); 1955ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org assert(IMitr != InverseMap.end() && "No mapping to original node."); 1956750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org (*BM)[NewN] = (const ExplodedNode*) IMitr->second; 1957ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org 1958f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org // Link up the new node with the previous node. 1959ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org if (Last) 1960ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org NewN->addPredecessor(Last, *GNew); 1961ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org 1962f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org Last = NewN; 1963ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org 1964ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org // Are we at the final node? 1965ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org IndexMapTy::iterator IMI = 1966ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org IndexMap.find((const ExplodedNode*)(IMitr->second)); 196743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen if (IMI != IndexMap.end()) { 19683d00d0a753cf5e5091f883517e6612ece769f999jkummerow@chromium.org First = NewN; 19693c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org NodeIndex = IMI->second; 197010480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org break; 197110480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org } 197210480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org 19733d00d0a753cf5e5091f883517e6612ece769f999jkummerow@chromium.org // Find the next successor node. We choose the node that is marked 19743d00d0a753cf5e5091f883517e6612ece769f999jkummerow@chromium.org // with the lowest DFS number. 19753c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org ExplodedNode::const_succ_iterator SI = N->succ_begin(); 19763c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org ExplodedNode::const_succ_iterator SE = N->succ_end(); 19773c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org N = 0; 19783c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org 19793c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org for (unsigned MinVal = 0; SI != SE; ++SI) { 19803c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org 19813c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org I = Visited.find(*SI); 19823c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org 19833c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org if (I == Visited.end()) 19843c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org continue; 19853c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org 19863c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org if (!N || I->second < MinVal) { 19873c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org N = *SI; 19883c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org MinVal = I->second; 19893c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org } 19903c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org } 19913c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org 19923c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org assert(N); 19933c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org } 19943c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org 199510480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org assert(First); 19963c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org 19973c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org return std::make_pair(std::make_pair(GNew, BM), 19983c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org std::make_pair(First, NodeIndex)); 19993c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org} 20003c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org 20013c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org/// CompactPathDiagnostic - This function postprocesses a PathDiagnostic object 20023c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org/// and collapses PathDiagosticPieces that are expanded by macros. 20033c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.orgstatic void CompactPathDiagnostic(PathPieces &path, const SourceManager& SM) { 20043c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org typedef std::vector<std::pair<IntrusiveRefCntPtr<PathDiagnosticMacroPiece>, 200510480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org SourceLocation> > MacroStackTy; 20063c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org 20073c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org typedef std::vector<IntrusiveRefCntPtr<PathDiagnosticPiece> > 200810480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org PiecesTy; 200910480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org 20103c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org MacroStackTy MacroStack; 201110480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org PiecesTy Pieces; 201210480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org 201310480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org for (PathPieces::const_iterator I = path.begin(), E = path.end(); 2014ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org I!=E; ++I) { 2015ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org 2016ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org PathDiagnosticPiece *piece = I->getPtr(); 2017ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org 201843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen // Recursively compact calls. 20194a5224e84636d192e82f288bfab0d308bdae5c37whesse@chromium.org if (PathDiagnosticCallPiece *call=dyn_cast<PathDiagnosticCallPiece>(piece)){ 20204a5224e84636d192e82f288bfab0d308bdae5c37whesse@chromium.org CompactPathDiagnostic(call->path, SM); 20214a5224e84636d192e82f288bfab0d308bdae5c37whesse@chromium.org } 20224a5224e84636d192e82f288bfab0d308bdae5c37whesse@chromium.org 20234a5224e84636d192e82f288bfab0d308bdae5c37whesse@chromium.org // Get the location of the PathDiagnosticPiece. 202410480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org const FullSourceLoc Loc = piece->getLocation().asLocation(); 20253d00d0a753cf5e5091f883517e6612ece769f999jkummerow@chromium.org 2026afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org // Determine the instantiation location, which is the location we group 202743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen // related PathDiagnosticPieces. 2028f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org SourceLocation InstantiationLoc = Loc.isMacroID() ? 2029f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org SM.getExpansionLoc(Loc) : 2030f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org SourceLocation(); 2031f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org 2032f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org if (Loc.isFileID()) { 2033f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org MacroStack.clear(); 2034f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org Pieces.push_back(piece); 2035f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org continue; 2036f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org } 2037f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org 2038f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org assert(Loc.isMacroID()); 203910480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org 2040afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org // Is the PathDiagnosticPiece within the same macro group? 2041d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org if (!MacroStack.empty() && InstantiationLoc == MacroStack.back().second) { 204210480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org MacroStack.back().first->subPieces.push_back(piece); 20434a5224e84636d192e82f288bfab0d308bdae5c37whesse@chromium.org continue; 20446d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org } 20456d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org 2046ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org // We aren't in the same group. Are we descending into a new macro 2047dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org // or are part of an old one? 2048ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org IntrusiveRefCntPtr<PathDiagnosticMacroPiece> MacroGroup; 20493e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org 205043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen SourceLocation ParentInstantiationLoc = InstantiationLoc.isMacroID() ? 20517979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org SM.getExpansionLoc(Loc) : 2052dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org SourceLocation(); 2053dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org 205443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen // Walk the entire macro stack. 205543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen while (!MacroStack.empty()) { 2056dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org if (InstantiationLoc == MacroStack.back().second) { 20578e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org MacroGroup = MacroStack.back().first; 205843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen break; 205943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen } 206043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 206143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen if (ParentInstantiationLoc == MacroStack.back().second) { 2062355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org MacroGroup = MacroStack.back().first; 2063355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org break; 2064ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org } 2065d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org 2066ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org MacroStack.pop_back(); 2067ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org } 2068ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org 2069355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org if (!MacroGroup || ParentInstantiationLoc == MacroStack.back().second) { 2070ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org // Create a new macro group and add it to the stack. 2071ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org PathDiagnosticMacroPiece *NewGroup = 2072d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org new PathDiagnosticMacroPiece( 2073d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org PathDiagnosticLocation::createSingleLocation(piece->getLocation())); 2074d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org 2075d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org if (MacroGroup) 2076d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org MacroGroup->subPieces.push_back(NewGroup); 2077d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org else { 2078355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org assert(InstantiationLoc.isFileID()); 2079355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org Pieces.push_back(NewGroup); 2080355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org } 2081355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org 2082ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org MacroGroup = NewGroup; 2083ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org MacroStack.push_back(std::make_pair(MacroGroup, InstantiationLoc)); 2084ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org } 2085ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org 2086ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org // Finally, add the PathDiagnosticPiece to the group. 2087030d38ee536bc25856546e75fdac60d1a0c42bddwhesse@chromium.org MacroGroup->subPieces.push_back(piece); 2088030d38ee536bc25856546e75fdac60d1a0c42bddwhesse@chromium.org } 2089ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org 2090755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org // Now take the pieces and construct a new PathDiagnostic. 209143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen path.clear(); 209243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 209343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen for (PiecesTy::iterator I=Pieces.begin(), E=Pieces.end(); I!=E; ++I) 209443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen path.push_back(*I); 209543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen} 209643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 209743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenbool GRBugReporter::generatePathDiagnostic(PathDiagnostic& PD, 209843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen PathDiagnosticConsumer &PC, 209971affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org ArrayRef<BugReport *> &bugReports) { 210043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen assert(!bugReports.empty()); 2101f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org 2102f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org bool HasValid = false; 2103f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org SmallVector<const ExplodedNode *, 10> errorNodes; 2104f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org for (ArrayRef<BugReport*>::iterator I = bugReports.begin(), 2105f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org E = bugReports.end(); I != E; ++I) { 2106f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org if ((*I)->isValid()) { 2107f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org HasValid = true; 2108f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org errorNodes.push_back((*I)->getErrorNode()); 2109f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org } else { 2110f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org errorNodes.push_back(0); 2111f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org } 2112f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org } 211310480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org 2114d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org // If all the reports have been marked invalid, we're done. 211510480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org if (!HasValid) 211610480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org return false; 211710480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org 211810480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.org // Construct a new graph that contains only a single path from the error 2119ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org // node to a root. 2120d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org const std::pair<std::pair<ExplodedGraph*, NodeBackMap*>, 2121ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org std::pair<ExplodedNode*, unsigned> >& 2122ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org GPair = MakeReportGraph(&getGraph(), errorNodes); 2123ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org 2124ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org // Find the BugReport with the original location. 2125030d38ee536bc25856546e75fdac60d1a0c42bddwhesse@chromium.org assert(GPair.second.second < bugReports.size()); 212643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen BugReport *R = bugReports[GPair.second.second]; 212743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen assert(R && "No original report found for sliced graph."); 212843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen assert(R->isValid() && "Report selected from trimmed graph marked invalid."); 2129 2130 OwningPtr<ExplodedGraph> ReportGraph(GPair.first.first); 2131 OwningPtr<NodeBackMap> BackMap(GPair.first.second); 2132 const ExplodedNode *N = GPair.second.first; 2133 2134 // Start building the path diagnostic... 2135 PathDiagnosticBuilder PDB(*this, R, BackMap.get(), &PC); 2136 2137 // Register additional node visitors. 2138 R->addVisitor(new NilReceiverBRVisitor()); 2139 R->addVisitor(new ConditionBRVisitor()); 2140 R->addVisitor(new LikelyFalsePositiveSuppressionBRVisitor()); 2141 2142 BugReport::VisitorList visitors; 2143 unsigned originalReportConfigToken, finalReportConfigToken; 2144 2145 // While generating diagnostics, it's possible the visitors will decide 2146 // new symbols and regions are interesting, or add other visitors based on 2147 // the information they find. If they do, we need to regenerate the path 2148 // based on our new report configuration. 2149 do { 2150 // Get a clean copy of all the visitors. 2151 for (BugReport::visitor_iterator I = R->visitor_begin(), 2152 E = R->visitor_end(); I != E; ++I) 2153 visitors.push_back((*I)->clone()); 2154 2155 // Clear out the active path from any previous work. 2156 PD.resetPath(); 2157 originalReportConfigToken = R->getConfigurationChangeToken(); 2158 2159 // Generate the very last diagnostic piece - the piece is visible before 2160 // the trace is expanded. 2161 PathDiagnosticPiece *LastPiece = 0; 2162 for (BugReport::visitor_iterator I = visitors.begin(), E = visitors.end(); 2163 I != E; ++I) { 2164 if (PathDiagnosticPiece *Piece = (*I)->getEndPath(PDB, N, *R)) { 2165 assert (!LastPiece && 2166 "There can only be one final piece in a diagnostic."); 2167 LastPiece = Piece; 2168 } 2169 } 2170 2171 if (PDB.getGenerationScheme() != PathDiagnosticConsumer::None) { 2172 if (!LastPiece) 2173 LastPiece = BugReporterVisitor::getDefaultEndPath(PDB, N, *R); 2174 if (LastPiece) 2175 PD.setEndOfPath(LastPiece); 2176 else 2177 return false; 2178 } 2179 2180 switch (PDB.getGenerationScheme()) { 2181 case PathDiagnosticConsumer::Extensive: 2182 if (!GenerateExtensivePathDiagnostic(PD, PDB, N, visitors)) { 2183 assert(!R->isValid() && "Failed on valid report"); 2184 // Try again. We'll filter out the bad report when we trim the graph. 2185 // FIXME: It would be more efficient to use the same intermediate 2186 // trimmed graph, and just repeat the shortest-path search. 2187 return generatePathDiagnostic(PD, PC, bugReports); 2188 } 2189 break; 2190 case PathDiagnosticConsumer::Minimal: 2191 if (!GenerateMinimalPathDiagnostic(PD, PDB, N, visitors)) { 2192 assert(!R->isValid() && "Failed on valid report"); 2193 // Try again. We'll filter out the bad report when we trim the graph. 2194 return generatePathDiagnostic(PD, PC, bugReports); 2195 } 2196 break; 2197 case PathDiagnosticConsumer::None: 2198 if (!GenerateVisitorsOnlyPathDiagnostic(PD, PDB, N, visitors)) { 2199 assert(!R->isValid() && "Failed on valid report"); 2200 // Try again. We'll filter out the bad report when we trim the graph. 2201 return generatePathDiagnostic(PD, PC, bugReports); 2202 } 2203 break; 2204 } 2205 2206 // Clean up the visitors we used. 2207 llvm::DeleteContainerPointers(visitors); 2208 2209 // Did anything change while generating this path? 2210 finalReportConfigToken = R->getConfigurationChangeToken(); 2211 } while(finalReportConfigToken != originalReportConfigToken); 2212 2213 // Finally, prune the diagnostic path of uninteresting stuff. 2214 if (!PD.path.empty()) { 2215 // Remove messages that are basically the same. 2216 removeRedundantMsgs(PD.getMutablePieces()); 2217 2218 if (R->shouldPrunePath() && 2219 getEngine().getAnalysisManager().options.shouldPrunePaths()) { 2220 bool hasSomethingInteresting = RemoveUnneededCalls(PD.getMutablePieces(), 2221 R); 2222 assert(hasSomethingInteresting); 2223 (void) hasSomethingInteresting; 2224 } 2225 2226 adjustCallLocations(PD.getMutablePieces()); 2227 } 2228 2229 return true; 2230} 2231 2232void BugReporter::Register(BugType *BT) { 2233 BugTypes = F.add(BugTypes, BT); 2234} 2235 2236void BugReporter::emitReport(BugReport* R) { 2237 // Compute the bug report's hash to determine its equivalence class. 2238 llvm::FoldingSetNodeID ID; 2239 R->Profile(ID); 2240 2241 // Lookup the equivance class. If there isn't one, create it. 2242 BugType& BT = R->getBugType(); 2243 Register(&BT); 2244 void *InsertPos; 2245 BugReportEquivClass* EQ = EQClasses.FindNodeOrInsertPos(ID, InsertPos); 2246 2247 if (!EQ) { 2248 EQ = new BugReportEquivClass(R); 2249 EQClasses.InsertNode(EQ, InsertPos); 2250 EQClassesVector.push_back(EQ); 2251 } 2252 else 2253 EQ->AddReport(R); 2254} 2255 2256 2257//===----------------------------------------------------------------------===// 2258// Emitting reports in equivalence classes. 2259//===----------------------------------------------------------------------===// 2260 2261namespace { 2262struct FRIEC_WLItem { 2263 const ExplodedNode *N; 2264 ExplodedNode::const_succ_iterator I, E; 2265 2266 FRIEC_WLItem(const ExplodedNode *n) 2267 : N(n), I(N->succ_begin()), E(N->succ_end()) {} 2268}; 2269} 2270 2271static BugReport * 2272FindReportInEquivalenceClass(BugReportEquivClass& EQ, 2273 SmallVectorImpl<BugReport*> &bugReports) { 2274 2275 BugReportEquivClass::iterator I = EQ.begin(), E = EQ.end(); 2276 assert(I != E); 2277 BugType& BT = I->getBugType(); 2278 2279 // If we don't need to suppress any of the nodes because they are 2280 // post-dominated by a sink, simply add all the nodes in the equivalence class 2281 // to 'Nodes'. Any of the reports will serve as a "representative" report. 2282 if (!BT.isSuppressOnSink()) { 2283 BugReport *R = I; 2284 for (BugReportEquivClass::iterator I=EQ.begin(), E=EQ.end(); I!=E; ++I) { 2285 const ExplodedNode *N = I->getErrorNode(); 2286 if (N) { 2287 R = I; 2288 bugReports.push_back(R); 2289 } 2290 } 2291 return R; 2292 } 2293 2294 // For bug reports that should be suppressed when all paths are post-dominated 2295 // by a sink node, iterate through the reports in the equivalence class 2296 // until we find one that isn't post-dominated (if one exists). We use a 2297 // DFS traversal of the ExplodedGraph to find a non-sink node. We could write 2298 // this as a recursive function, but we don't want to risk blowing out the 2299 // stack for very long paths. 2300 BugReport *exampleReport = 0; 2301 2302 for (; I != E; ++I) { 2303 const ExplodedNode *errorNode = I->getErrorNode(); 2304 2305 if (!errorNode) 2306 continue; 2307 if (errorNode->isSink()) { 2308 llvm_unreachable( 2309 "BugType::isSuppressSink() should not be 'true' for sink end nodes"); 2310 } 2311 // No successors? By definition this nodes isn't post-dominated by a sink. 2312 if (errorNode->succ_empty()) { 2313 bugReports.push_back(I); 2314 if (!exampleReport) 2315 exampleReport = I; 2316 continue; 2317 } 2318 2319 // At this point we know that 'N' is not a sink and it has at least one 2320 // successor. Use a DFS worklist to find a non-sink end-of-path node. 2321 typedef FRIEC_WLItem WLItem; 2322 typedef SmallVector<WLItem, 10> DFSWorkList; 2323 llvm::DenseMap<const ExplodedNode *, unsigned> Visited; 2324 2325 DFSWorkList WL; 2326 WL.push_back(errorNode); 2327 Visited[errorNode] = 1; 2328 2329 while (!WL.empty()) { 2330 WLItem &WI = WL.back(); 2331 assert(!WI.N->succ_empty()); 2332 2333 for (; WI.I != WI.E; ++WI.I) { 2334 const ExplodedNode *Succ = *WI.I; 2335 // End-of-path node? 2336 if (Succ->succ_empty()) { 2337 // If we found an end-of-path node that is not a sink. 2338 if (!Succ->isSink()) { 2339 bugReports.push_back(I); 2340 if (!exampleReport) 2341 exampleReport = I; 2342 WL.clear(); 2343 break; 2344 } 2345 // Found a sink? Continue on to the next successor. 2346 continue; 2347 } 2348 // Mark the successor as visited. If it hasn't been explored, 2349 // enqueue it to the DFS worklist. 2350 unsigned &mark = Visited[Succ]; 2351 if (!mark) { 2352 mark = 1; 2353 WL.push_back(Succ); 2354 break; 2355 } 2356 } 2357 2358 // The worklist may have been cleared at this point. First 2359 // check if it is empty before checking the last item. 2360 if (!WL.empty() && &WL.back() == &WI) 2361 WL.pop_back(); 2362 } 2363 } 2364 2365 // ExampleReport will be NULL if all the nodes in the equivalence class 2366 // were post-dominated by sinks. 2367 return exampleReport; 2368} 2369 2370void BugReporter::FlushReport(BugReportEquivClass& EQ) { 2371 SmallVector<BugReport*, 10> bugReports; 2372 BugReport *exampleReport = FindReportInEquivalenceClass(EQ, bugReports); 2373 if (exampleReport) { 2374 const PathDiagnosticConsumers &C = getPathDiagnosticConsumers(); 2375 for (PathDiagnosticConsumers::const_iterator I=C.begin(), 2376 E=C.end(); I != E; ++I) { 2377 FlushReport(exampleReport, **I, bugReports); 2378 } 2379 } 2380} 2381 2382void BugReporter::FlushReport(BugReport *exampleReport, 2383 PathDiagnosticConsumer &PD, 2384 ArrayRef<BugReport*> bugReports) { 2385 2386 // FIXME: Make sure we use the 'R' for the path that was actually used. 2387 // Probably doesn't make a difference in practice. 2388 BugType& BT = exampleReport->getBugType(); 2389 2390 OwningPtr<PathDiagnostic> 2391 D(new PathDiagnostic(exampleReport->getDeclWithIssue(), 2392 exampleReport->getBugType().getName(), 2393 exampleReport->getDescription(), 2394 exampleReport->getShortDescription(/*Fallback=*/false), 2395 BT.getCategory(), 2396 exampleReport->getUniqueingLocation(), 2397 exampleReport->getUniqueingDecl())); 2398 2399 // Generate the full path diagnostic, using the generation scheme 2400 // specified by the PathDiagnosticConsumer. Note that we have to generate 2401 // path diagnostics even for consumers which do not support paths, because 2402 // the BugReporterVisitors may mark this bug as a false positive. 2403 if (!bugReports.empty()) 2404 if (!generatePathDiagnostic(*D.get(), PD, bugReports)) 2405 return; 2406 2407 // If the path is empty, generate a single step path with the location 2408 // of the issue. 2409 if (D->path.empty()) { 2410 PathDiagnosticLocation L = exampleReport->getLocation(getSourceManager()); 2411 PathDiagnosticPiece *piece = 2412 new PathDiagnosticEventPiece(L, exampleReport->getDescription()); 2413 BugReport::ranges_iterator Beg, End; 2414 llvm::tie(Beg, End) = exampleReport->getRanges(); 2415 for ( ; Beg != End; ++Beg) 2416 piece->addRange(*Beg); 2417 D->setEndOfPath(piece); 2418 } 2419 2420 // Get the meta data. 2421 const BugReport::ExtraTextList &Meta = exampleReport->getExtraText(); 2422 for (BugReport::ExtraTextList::const_iterator i = Meta.begin(), 2423 e = Meta.end(); i != e; ++i) { 2424 D->addMeta(*i); 2425 } 2426 2427 PD.HandlePathDiagnostic(D.take()); 2428} 2429 2430void BugReporter::EmitBasicReport(const Decl *DeclWithIssue, 2431 StringRef name, 2432 StringRef category, 2433 StringRef str, PathDiagnosticLocation Loc, 2434 SourceRange* RBeg, unsigned NumRanges) { 2435 2436 // 'BT' is owned by BugReporter. 2437 BugType *BT = getBugTypeForName(name, category); 2438 BugReport *R = new BugReport(*BT, str, Loc); 2439 R->setDeclWithIssue(DeclWithIssue); 2440 for ( ; NumRanges > 0 ; --NumRanges, ++RBeg) R->addRange(*RBeg); 2441 emitReport(R); 2442} 2443 2444BugType *BugReporter::getBugTypeForName(StringRef name, 2445 StringRef category) { 2446 SmallString<136> fullDesc; 2447 llvm::raw_svector_ostream(fullDesc) << name << ":" << category; 2448 llvm::StringMapEntry<BugType *> & 2449 entry = StrBugTypes.GetOrCreateValue(fullDesc); 2450 BugType *BT = entry.getValue(); 2451 if (!BT) { 2452 BT = new BugType(name, category); 2453 entry.setValue(BT); 2454 } 2455 return BT; 2456} 2457