BugReporter.cpp revision e86ee1a213d244bb66b7eef3e9ab2266908cf4af
161f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek// BugReporter.cpp - Generate PathDiagnostics for Bugs ------------*- C++ -*--// 261f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek// 361f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek// The LLVM Compiler Infrastructure 461f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek// 561f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek// This file is distributed under the University of Illinois Open Source 661f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek// License. See LICENSE.TXT for details. 761f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek// 861f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek//===----------------------------------------------------------------------===// 961f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek// 1061f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek// This file defines BugReporter, a utility class for generating 116c07bdba93b095b66e2c8c82dd5ed458fa8285eaTed Kremenek// PathDiagnostics. 1261f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek// 1361f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek//===----------------------------------------------------------------------===// 1461f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek 15cc08ca9b3cd2b715a699bcc772ce2e83a502915aJordan Rose#define DEBUG_TYPE "BugReporter" 16cc08ca9b3cd2b715a699bcc772ce2e83a502915aJordan Rose 179b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" 1861f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek#include "clang/AST/ASTContext.h" 19c35fb7d67d515659ad2325b4f6ec97c9fe64fb63Benjamin Kramer#include "clang/AST/DeclObjC.h" 2061f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek#include "clang/AST/Expr.h" 2100605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek#include "clang/AST/ParentMap.h" 2216f0049415ec596504891259e2a83e19871c0d52Chris Lattner#include "clang/AST/StmtObjC.h" 2355fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Analysis/CFG.h" 2461f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek#include "clang/Analysis/ProgramPoint.h" 2555fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Basic/SourceManager.h" 2655fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" 279b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h" 2855fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" 29331b0ac44b9eb0ffcba66b4f3f3f9adb27c2434fTed Kremenek#include "llvm/ADT/DenseMap.h" 30802e02463b880f53a6e645bde78cc412481ce9e0Ted Kremenek#include "llvm/ADT/IntrusiveRefCntPtr.h" 3155fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "llvm/ADT/OwningPtr.h" 3255fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "llvm/ADT/STLExtras.h" 3355fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "llvm/ADT/SmallString.h" 34cc08ca9b3cd2b715a699bcc772ce2e83a502915aJordan Rose#include "llvm/ADT/Statistic.h" 3555fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "llvm/Support/raw_ostream.h" 3610aa55410bbecbb658ce14a5f801d50cf06d12dfTed Kremenek#include <queue> 3761f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek 3861f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenekusing namespace clang; 399ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremenekusing namespace ento; 4061f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek 41cc08ca9b3cd2b715a699bcc772ce2e83a502915aJordan RoseSTATISTIC(MaxBugClassSize, 42cc08ca9b3cd2b715a699bcc772ce2e83a502915aJordan Rose "The maximum number of bug reports in the same equivalence class"); 43cc08ca9b3cd2b715a699bcc772ce2e83a502915aJordan RoseSTATISTIC(MaxValidBugClassSize, 44cc08ca9b3cd2b715a699bcc772ce2e83a502915aJordan Rose "The maximum number of bug reports in the same equivalence class " 45cc08ca9b3cd2b715a699bcc772ce2e83a502915aJordan Rose "where at least one report is valid (not suppressed)"); 46cc08ca9b3cd2b715a699bcc772ce2e83a502915aJordan Rose 478966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed KremenekBugReporterVisitor::~BugReporterVisitor() {} 481b431023814196f87515a540ebcb9e9f1a9176a1Ted Kremenek 4999ba9e3bd70671f3441fb974895f226a83ce0e66David Blaikievoid BugReporterContext::anchor() {} 5099ba9e3bd70671f3441fb974895f226a83ce0e66David Blaikie 51cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek//===----------------------------------------------------------------------===// 523106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// Helper routines for walking the ExplodedGraph and fetching statements. 53cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek//===----------------------------------------------------------------------===// 5461f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek 559c378f705405d37f49795d5e915989de774fe11fTed Kremenekstatic const Stmt *GetPreviousStmt(const ExplodedNode *N) { 560f8579274a010f360a371b53101859d9d6052314Anna Zaks for (N = N->getFirstPred(); N; N = N->getFirstPred()) 570f8579274a010f360a371b53101859d9d6052314Anna Zaks if (const Stmt *S = PathDiagnosticLocation::getStmt(N)) 58b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek return S; 591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 60b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek return 0; 61b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek} 62b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek 635f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenekstatic inline const Stmt* 649c378f705405d37f49795d5e915989de774fe11fTed KremenekGetCurrentOrPreviousStmt(const ExplodedNode *N) { 650f8579274a010f360a371b53101859d9d6052314Anna Zaks if (const Stmt *S = PathDiagnosticLocation::getStmt(N)) 66b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek return S; 671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 68b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek return GetPreviousStmt(N); 69b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek} 701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 71b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek//===----------------------------------------------------------------------===// 72c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek// Diagnostic cleanup. 73c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek//===----------------------------------------------------------------------===// 74c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek 75b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenekstatic PathDiagnosticEventPiece * 76b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted KremenekeventsDescribeSameCondition(PathDiagnosticEventPiece *X, 77b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek PathDiagnosticEventPiece *Y) { 78b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek // Prefer diagnostics that come from ConditionBRVisitor over 79b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek // those that came from TrackConstraintBRVisitor. 80b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek const void *tagPreferred = ConditionBRVisitor::getTag(); 81b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek const void *tagLesser = TrackConstraintBRVisitor::getTag(); 82b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek 83b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek if (X->getLocation() != Y->getLocation()) 84b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek return 0; 85b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek 86b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek if (X->getTag() == tagPreferred && Y->getTag() == tagLesser) 87b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek return X; 88b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek 89b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek if (Y->getTag() == tagPreferred && X->getTag() == tagLesser) 90b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek return Y; 91b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek 92b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek return 0; 93b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek} 94b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek 953800165e56107df7430520aa98afdf7065db2dd2Ted Kremenek/// An optimization pass over PathPieces that removes redundant diagnostics 963800165e56107df7430520aa98afdf7065db2dd2Ted Kremenek/// generated by both ConditionBRVisitor and TrackConstraintBRVisitor. Both 973800165e56107df7430520aa98afdf7065db2dd2Ted Kremenek/// BugReporterVisitors use different methods to generate diagnostics, with 983800165e56107df7430520aa98afdf7065db2dd2Ted Kremenek/// one capable of emitting diagnostics in some cases but not in others. This 993800165e56107df7430520aa98afdf7065db2dd2Ted Kremenek/// can lead to redundant diagnostic pieces at the same point in a path. 1003800165e56107df7430520aa98afdf7065db2dd2Ted Kremenekstatic void removeRedundantMsgs(PathPieces &path) { 101b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek unsigned N = path.size(); 102b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek if (N < 2) 103b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek return; 1043800165e56107df7430520aa98afdf7065db2dd2Ted Kremenek // NOTE: this loop intentionally is not using an iterator. Instead, we 1053800165e56107df7430520aa98afdf7065db2dd2Ted Kremenek // are streaming the path and modifying it in place. This is done by 1063800165e56107df7430520aa98afdf7065db2dd2Ted Kremenek // grabbing the front, processing it, and if we decide to keep it append 1073800165e56107df7430520aa98afdf7065db2dd2Ted Kremenek // it to the end of the path. The entire path is processed in this way. 108b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek for (unsigned i = 0; i < N; ++i) { 109b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek IntrusiveRefCntPtr<PathDiagnosticPiece> piece(path.front()); 110b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek path.pop_front(); 111b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek 112b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek switch (piece->getKind()) { 113b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek case clang::ento::PathDiagnosticPiece::Call: 1143800165e56107df7430520aa98afdf7065db2dd2Ted Kremenek removeRedundantMsgs(cast<PathDiagnosticCallPiece>(piece)->path); 115b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek break; 116b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek case clang::ento::PathDiagnosticPiece::Macro: 1173800165e56107df7430520aa98afdf7065db2dd2Ted Kremenek removeRedundantMsgs(cast<PathDiagnosticMacroPiece>(piece)->subPieces); 118b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek break; 119b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek case clang::ento::PathDiagnosticPiece::ControlFlow: 120b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek break; 121b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek case clang::ento::PathDiagnosticPiece::Event: { 122b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek if (i == N-1) 123b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek break; 124b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek 125b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek if (PathDiagnosticEventPiece *nextEvent = 126ed866e73bab7733f5226f84c52edefe23d694b2fTed Kremenek dyn_cast<PathDiagnosticEventPiece>(path.front().getPtr())) { 127b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek PathDiagnosticEventPiece *event = 128b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek cast<PathDiagnosticEventPiece>(piece); 129b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek // Check to see if we should keep one of the two pieces. If we 130b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek // come up with a preference, record which piece to keep, and consume 131b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek // another piece from the path. 132b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek if (PathDiagnosticEventPiece *pieceToKeep = 133b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek eventsDescribeSameCondition(event, nextEvent)) { 134b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek piece = pieceToKeep; 135b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek path.pop_front(); 136b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek ++i; 137b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek } 138b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek } 139b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek break; 140b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek } 141b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek } 142b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek path.push_back(piece); 143b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek } 144b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek} 145b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek 146d306a530fca74e40916121f5583e0545e470b3c4Ted Kremenek/// A map from PathDiagnosticPiece to the LocationContext of the inlined 147d306a530fca74e40916121f5583e0545e470b3c4Ted Kremenek/// function call it represents. 148bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenektypedef llvm::DenseMap<const PathPieces *, const LocationContext *> 149d306a530fca74e40916121f5583e0545e470b3c4Ted Kremenek LocationContextMap; 150d306a530fca74e40916121f5583e0545e470b3c4Ted Kremenek 151c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek/// Recursively scan through a path and prune out calls and macros pieces 152c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek/// that aren't needed. Return true if afterwards the path contains 153afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose/// "interesting stuff" which means it shouldn't be pruned from the parent path. 154d306a530fca74e40916121f5583e0545e470b3c4Ted Kremenekstatic bool removeUnneededCalls(PathPieces &pieces, BugReport *R, 155d306a530fca74e40916121f5583e0545e470b3c4Ted Kremenek LocationContextMap &LCM) { 156c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek bool containsSomethingInteresting = false; 157c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek const unsigned N = pieces.size(); 158c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek 159c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek for (unsigned i = 0 ; i < N ; ++i) { 160c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek // Remove the front piece from the path. If it is still something we 161c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek // want to keep once we are done, we will push it back on the end. 162c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek IntrusiveRefCntPtr<PathDiagnosticPiece> piece(pieces.front()); 163c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek pieces.pop_front(); 164c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek 165afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose // Throw away pieces with invalid locations. Note that we can't throw away 166afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose // calls just yet because they might have something interesting inside them. 167afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose // If so, their locations will be adjusted as necessary later. 168a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek if (piece->getKind() != PathDiagnosticPiece::Call && 169a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek piece->getLocation().asLocation().isInvalid()) 170a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek continue; 171a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek 172725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek switch (piece->getKind()) { 173725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek case PathDiagnosticPiece::Call: { 174725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek PathDiagnosticCallPiece *call = cast<PathDiagnosticCallPiece>(piece); 17580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // Check if the location context is interesting. 176bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek assert(LCM.count(&call->path)); 177bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek if (R->isInteresting(LCM[&call->path])) { 17880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks containsSomethingInteresting = true; 17980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks break; 18080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks } 181368f3b070e8cb657a65bfa443d60256676d269e7Jordan Rose 182d306a530fca74e40916121f5583e0545e470b3c4Ted Kremenek if (!removeUnneededCalls(call->path, R, LCM)) 183368f3b070e8cb657a65bfa443d60256676d269e7Jordan Rose continue; 184a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek 185725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek containsSomethingInteresting = true; 186725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek break; 187725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek } 188725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek case PathDiagnosticPiece::Macro: { 189725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek PathDiagnosticMacroPiece *macro = cast<PathDiagnosticMacroPiece>(piece); 190d306a530fca74e40916121f5583e0545e470b3c4Ted Kremenek if (!removeUnneededCalls(macro->subPieces, R, LCM)) 191725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek continue; 192c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek containsSomethingInteresting = true; 193725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek break; 194725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek } 195725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek case PathDiagnosticPiece::Event: { 196725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek PathDiagnosticEventPiece *event = cast<PathDiagnosticEventPiece>(piece); 197a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek 198725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek // We never throw away an event, but we do throw it away wholesale 199725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek // as part of a path if we throw the entire path away. 20022505ef15e32db31a4f834a387cf73a913bc8f66Ted Kremenek containsSomethingInteresting |= !event->isPrunable(); 201725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek break; 202725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek } 203725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek case PathDiagnosticPiece::ControlFlow: 204725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek break; 205c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek } 206c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek 207c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek pieces.push_back(piece); 208c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek } 209c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek 210c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek return containsSomethingInteresting; 211c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek} 212c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek 213afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose/// Recursively scan through a path and make sure that all call pieces have 214afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose/// valid locations. Note that all other pieces with invalid locations should 215afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose/// have already been pruned out. 216afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rosestatic void adjustCallLocations(PathPieces &Pieces, 217afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose PathDiagnosticLocation *LastCallLocation = 0) { 218afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose for (PathPieces::iterator I = Pieces.begin(), E = Pieces.end(); I != E; ++I) { 219ed866e73bab7733f5226f84c52edefe23d694b2fTed Kremenek PathDiagnosticCallPiece *Call = dyn_cast<PathDiagnosticCallPiece>(*I); 220afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose 221afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose if (!Call) { 222ed866e73bab7733f5226f84c52edefe23d694b2fTed Kremenek assert((*I)->getLocation().asLocation().isValid()); 223afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose continue; 224afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose } 225afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose 226afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose if (LastCallLocation) { 227187f8bd88bfc92cf3fea62b7d8db5f92edce410aJordan Rose if (!Call->callEnter.asLocation().isValid() || 228187f8bd88bfc92cf3fea62b7d8db5f92edce410aJordan Rose Call->getCaller()->isImplicit()) 229afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose Call->callEnter = *LastCallLocation; 230187f8bd88bfc92cf3fea62b7d8db5f92edce410aJordan Rose if (!Call->callReturn.asLocation().isValid() || 231187f8bd88bfc92cf3fea62b7d8db5f92edce410aJordan Rose Call->getCaller()->isImplicit()) 232afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose Call->callReturn = *LastCallLocation; 233afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose } 234afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose 235afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose // Recursively clean out the subclass. Keep this call around if 236afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose // it contains any informative diagnostics. 237afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose PathDiagnosticLocation *ThisCallLocation; 238187f8bd88bfc92cf3fea62b7d8db5f92edce410aJordan Rose if (Call->callEnterWithin.asLocation().isValid() && 239187f8bd88bfc92cf3fea62b7d8db5f92edce410aJordan Rose !Call->getCallee()->isImplicit()) 240afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose ThisCallLocation = &Call->callEnterWithin; 241afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose else 242afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose ThisCallLocation = &Call->callEnter; 243afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose 244afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose assert(ThisCallLocation && "Outermost call has an invalid location"); 245afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose adjustCallLocations(Call->path, ThisCallLocation); 246afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose } 247afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose} 248afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose 249c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek//===----------------------------------------------------------------------===// 2503106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// PathDiagnosticBuilder and its associated routines and helper objects. 251b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek//===----------------------------------------------------------------------===// 252b479dadea93b93d3f0a335c3518b703f140b3f50Ted Kremenek 253babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremeneknamespace { 254ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass NodeMapClosure : public BugReport::NodeResolver { 255c9963132736782d0c9178c744b3e2307cfb98a08Jordan Rose InterExplodedGraphMap &M; 2567dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenekpublic: 257c9963132736782d0c9178c744b3e2307cfb98a08Jordan Rose NodeMapClosure(InterExplodedGraphMap &m) : M(m) {} 2581eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2599c378f705405d37f49795d5e915989de774fe11fTed Kremenek const ExplodedNode *getOriginalNode(const ExplodedNode *N) { 260c9963132736782d0c9178c744b3e2307cfb98a08Jordan Rose return M.lookup(N); 2617dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek } 2627dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek}; 2631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 264ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass PathDiagnosticBuilder : public BugReporterContext { 2657dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek BugReport *R; 266ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie PathDiagnosticConsumer *PDC; 2677dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek NodeMapClosure NMC; 2681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumppublic: 26959950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek const LocationContext *LC; 27059950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek 2718966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek PathDiagnosticBuilder(GRBugReporter &br, 272c9963132736782d0c9178c744b3e2307cfb98a08Jordan Rose BugReport *r, InterExplodedGraphMap &Backmap, 273ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie PathDiagnosticConsumer *pdc) 2748966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek : BugReporterContext(br), 27559950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek R(r), PDC(pdc), NMC(Backmap), LC(r->getErrorNode()->getLocationContext()) 27659950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek {} 2771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2789c378f705405d37f49795d5e915989de774fe11fTed Kremenek PathDiagnosticLocation ExecutionContinues(const ExplodedNode *N); 2791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2809c378f705405d37f49795d5e915989de774fe11fTed Kremenek PathDiagnosticLocation ExecutionContinues(llvm::raw_string_ostream &os, 2819c378f705405d37f49795d5e915989de774fe11fTed Kremenek const ExplodedNode *N); 2821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2838e6431adab313e283a992698f6fc7afe62420999Anna Zaks BugReport *getBugReport() { return R; } 2848e6431adab313e283a992698f6fc7afe62420999Anna Zaks 285212f6d3b5fb3fa55ba1e40671cfc336430abc8ddTom Care Decl const &getCodeDecl() { return R->getErrorNode()->getCodeDecl(); } 28659950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek 28759950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek ParentMap& getParentMap() { return LC->getParentMap(); } 2881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 289c3f83ad7adaff2623986aa1c3e57833babd03d50Ted Kremenek const Stmt *getParent(const Stmt *S) { 290c3f83ad7adaff2623986aa1c3e57833babd03d50Ted Kremenek return getParentMap().getParent(S); 291c3f83ad7adaff2623986aa1c3e57833babd03d50Ted Kremenek } 2921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2938966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek virtual NodeMapClosure& getNodeResolver() { return NMC; } 2947297134f128423fce2e88f92421ed135bded7d4eDouglas Gregor 295d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek PathDiagnosticLocation getEnclosingStmtLocation(const Stmt *S); 2961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 297ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie PathDiagnosticConsumer::PathGenerationScheme getGenerationScheme() const { 298ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie return PDC ? PDC->getGenerationScheme() : PathDiagnosticConsumer::Extensive; 2997dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek } 3007dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek 301babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek bool supportsLogicalOpControlFlow() const { 302babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek return PDC ? PDC->supportsLogicalOpControlFlow() : true; 3031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 304babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek}; 305babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek} // end anonymous namespace 306babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek 30700605e0f011ed99225a22026344c5fc1b3212cd7Ted KremenekPathDiagnosticLocation 3089c378f705405d37f49795d5e915989de774fe11fTed KremenekPathDiagnosticBuilder::ExecutionContinues(const ExplodedNode *N) { 3090f8579274a010f360a371b53101859d9d6052314Anna Zaks if (const Stmt *S = PathDiagnosticLocation::getNextStmt(N)) 31059950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek return PathDiagnosticLocation(S, getSourceManager(), LC); 31100605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek 3120cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks return PathDiagnosticLocation::createDeclEnd(N->getLocationContext(), 3130cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks getSourceManager()); 314082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek} 3151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 31600605e0f011ed99225a22026344c5fc1b3212cd7Ted KremenekPathDiagnosticLocation 3179c378f705405d37f49795d5e915989de774fe11fTed KremenekPathDiagnosticBuilder::ExecutionContinues(llvm::raw_string_ostream &os, 3189c378f705405d37f49795d5e915989de774fe11fTed Kremenek const ExplodedNode *N) { 319babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek 320143ca222583a4a355fdc89af852deef287499300Ted Kremenek // Slow, but probably doesn't matter. 321b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek if (os.str().empty()) 322b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek os << ' '; 3231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 32400605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek const PathDiagnosticLocation &Loc = ExecutionContinues(N); 3251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 32600605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek if (Loc.asStmt()) 327b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek os << "Execution continues on line " 328642116259e8df6286063a17361c20e95b5017a0aChandler Carruth << getSourceManager().getExpansionLineNumber(Loc.asLocation()) 3298966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek << '.'; 3304f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek else { 3314f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek os << "Execution jumps to the end of the "; 3324f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek const Decl *D = N->getLocationContext()->getDecl(); 3334f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek if (isa<ObjCMethodDecl>(D)) 3344f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek os << "method"; 3354f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek else if (isa<FunctionDecl>(D)) 3364f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek os << "function"; 3374f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek else { 3384f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek assert(isa<BlockDecl>(D)); 3394f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek os << "anonymous block"; 3404f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek } 3414f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek os << '.'; 3424f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek } 3431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 344082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek return Loc; 345143ca222583a4a355fdc89af852deef287499300Ted Kremenek} 346143ca222583a4a355fdc89af852deef287499300Ted Kremenek 347ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenekstatic bool IsNested(const Stmt *S, ParentMap &PM) { 348ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek if (isa<Expr>(S) && PM.isConsumedExpr(cast<Expr>(S))) 349ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek return true; 3501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 351ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek const Stmt *Parent = PM.getParentIgnoreParens(S); 3521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 353ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek if (Parent) 354ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek switch (Parent->getStmtClass()) { 355ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek case Stmt::ForStmtClass: 356ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek case Stmt::DoStmtClass: 357ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek case Stmt::WhileStmtClass: 358ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek return true; 359ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek default: 360ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek break; 361ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek } 3621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return false; 364ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek} 365ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek 366d8c938b0f6b7a7156181be575239e4c6e15a2adbTed KremenekPathDiagnosticLocation 367d8c938b0f6b7a7156181be575239e4c6e15a2adbTed KremenekPathDiagnosticBuilder::getEnclosingStmtLocation(const Stmt *S) { 3689c378f705405d37f49795d5e915989de774fe11fTed Kremenek assert(S && "Null Stmt *passed to getEnclosingStmtLocation"); 3691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump ParentMap &P = getParentMap(); 3708966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek SourceManager &SMgr = getSourceManager(); 371e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek 372ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek while (IsNested(S, P)) { 3738c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek const Stmt *Parent = P.getParentIgnoreParens(S); 3741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 375af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek if (!Parent) 376af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek break; 3771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 378af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek switch (Parent->getStmtClass()) { 3795fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek case Stmt::BinaryOperatorClass: { 3805fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek const BinaryOperator *B = cast<BinaryOperator>(Parent); 3815fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek if (B->isLogicalOp()) 382220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 3835fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek break; 3841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 385af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::CompoundStmtClass: 386af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::StmtExprClass: 387220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 3881d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek case Stmt::ChooseExprClass: 3891d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek // Similar to '?' if we are referring to condition, just have the edge 3901d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek // point to the entire choose expression. 3911d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek if (cast<ChooseExpr>(Parent)->getCond() == S) 392220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(Parent, SMgr, LC); 3931d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek else 394220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 39556ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall case Stmt::BinaryConditionalOperatorClass: 3961d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek case Stmt::ConditionalOperatorClass: 3971d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek // For '?', if we are referring to condition, just have the edge point 3981d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek // to the entire '?' expression. 39956ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall if (cast<AbstractConditionalOperator>(Parent)->getCond() == S) 400220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(Parent, SMgr, LC); 4011d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek else 402220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 403af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::DoStmtClass: 404220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 405af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::ForStmtClass: 406af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek if (cast<ForStmt>(Parent)->getBody() == S) 407220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 4081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump break; 409af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::IfStmtClass: 410af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek if (cast<IfStmt>(Parent)->getCond() != S) 411220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 4128bd4d037d837e7922c3661d6158229da58a03887Ted Kremenek break; 413af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::ObjCForCollectionStmtClass: 414af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek if (cast<ObjCForCollectionStmt>(Parent)->getBody() == S) 415220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 416af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek break; 417af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::WhileStmtClass: 418af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek if (cast<WhileStmt>(Parent)->getCond() != S) 419220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 420af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek break; 421af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek default: 422af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek break; 423af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek } 424af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek 425d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek S = Parent; 426d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek } 4271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 428d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek assert(S && "Cannot have null Stmt for PathDiagnosticLocation"); 429e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek 430e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek // Special case: DeclStmts can appear in for statement declarations, in which 431e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek // case the ForStmt is the context. 432e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek if (isa<DeclStmt>(S)) { 433e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek if (const Stmt *Parent = P.getParent(S)) { 434e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek switch (Parent->getStmtClass()) { 435e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek case Stmt::ForStmtClass: 436e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek case Stmt::ObjCForCollectionStmtClass: 437220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(Parent, SMgr, LC); 438e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek default: 439e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek break; 4401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 4411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 442e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek } 443e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek else if (isa<BinaryOperator>(S)) { 444e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek // Special case: the binary operator represents the initialization 445e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek // code in a for statement (this can happen when the variable being 446e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek // initialized is an old variable. 447e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek if (const ForStmt *FS = 448e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek dyn_cast_or_null<ForStmt>(P.getParentIgnoreParens(S))) { 449e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek if (FS->getInit() == S) 450220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(FS, SMgr, LC); 451e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek } 452e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek } 453e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek 454220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 455d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek} 456d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek 457cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek//===----------------------------------------------------------------------===// 458d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose// "Visitors only" path diagnostic generation algorithm. 459d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose//===----------------------------------------------------------------------===// 460d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rosestatic bool GenerateVisitorsOnlyPathDiagnostic(PathDiagnostic &PD, 461d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose PathDiagnosticBuilder &PDB, 462d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose const ExplodedNode *N, 463d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose ArrayRef<BugReporterVisitor *> visitors) { 464d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose // All path generation skips the very first node (the error node). 465d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose // This is because there is special handling for the end-of-path note. 466d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose N = N->getFirstPred(); 467d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose if (!N) 468d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose return true; 469d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose 470d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose BugReport *R = PDB.getBugReport(); 471d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose while (const ExplodedNode *Pred = N->getFirstPred()) { 472d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose for (ArrayRef<BugReporterVisitor *>::iterator I = visitors.begin(), 473d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose E = visitors.end(); 474d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose I != E; ++I) { 475d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose // Visit all the node pairs, but throw the path pieces away. 476d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose PathDiagnosticPiece *Piece = (*I)->VisitNode(N, Pred, PDB, *R); 477d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose delete Piece; 478d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose } 479d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose 480d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose N = Pred; 481d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose } 482d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose 483d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose return R->isValid(); 484d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose} 485d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose 486d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose//===----------------------------------------------------------------------===// 4873106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// "Minimal" path diagnostic generation algorithm. 488cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek//===----------------------------------------------------------------------===// 48956a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zakstypedef std::pair<PathDiagnosticCallPiece*, const ExplodedNode*> StackDiagPair; 49056a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zakstypedef SmallVector<StackDiagPair, 6> StackDiagVector; 49156a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks 492368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaksstatic void updateStackPiecesWithMessage(PathDiagnosticPiece *P, 49356a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks StackDiagVector &CallStack) { 494368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks // If the piece contains a special message, add it to all the call 495368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks // pieces on the active stack. 496368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks if (PathDiagnosticEventPiece *ep = 497368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks dyn_cast<PathDiagnosticEventPiece>(P)) { 498368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks 49956a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks if (ep->hasCallStackHint()) 50056a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks for (StackDiagVector::iterator I = CallStack.begin(), 50156a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks E = CallStack.end(); I != E; ++I) { 50256a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks PathDiagnosticCallPiece *CP = I->first; 50356a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks const ExplodedNode *N = I->second; 5048fe4525680ce72e90cee3e58b5654e3ae955447fNAKAMURA Takumi std::string stackMsg = ep->getCallStackMessage(N); 50556a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks 506368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks // The last message on the path to final bug is the most important 507368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks // one. Since we traverse the path backwards, do not add the message 508368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks // if one has been previously added. 50956a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks if (!CP->hasCallStackMessage()) 51056a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks CP->setCallStackMessage(stackMsg); 51156a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks } 512368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks } 513368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks} 514cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek 51577d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenekstatic void CompactPathDiagnostic(PathPieces &path, const SourceManager& SM); 51614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 5178347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rosestatic bool GenerateMinimalPathDiagnostic(PathDiagnostic& PD, 5183106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PathDiagnosticBuilder &PDB, 5193bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose const ExplodedNode *N, 520d306a530fca74e40916121f5583e0545e470b3c4Ted Kremenek LocationContextMap &LCM, 5213bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose ArrayRef<BugReporterVisitor *> visitors) { 5228966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek 5233106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek SourceManager& SMgr = PDB.getSourceManager(); 52459950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek const LocationContext *LC = PDB.LC; 5259c378f705405d37f49795d5e915989de774fe11fTed Kremenek const ExplodedNode *NextNode = N->pred_empty() 5263106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek ? NULL : *(N->pred_begin()); 527368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks 52856a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks StackDiagVector CallStack; 529368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks 5303106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek while (NextNode) { 5311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump N = NextNode; 53259950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek PDB.LC = N->getLocationContext(); 5330f8579274a010f360a371b53101859d9d6052314Anna Zaks NextNode = N->getFirstPred(); 5341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 53561f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek ProgramPoint P = N->getLocation(); 53680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks 53780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks do { 5387a95de68c093991047ed8d339479ccad51b88663David Blaikie if (Optional<CallExitEnd> CE = P.getAs<CallExitEnd>()) { 53980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PathDiagnosticCallPiece *C = 54080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PathDiagnosticCallPiece::construct(N, *CE, SMgr); 541d306a530fca74e40916121f5583e0545e470b3c4Ted Kremenek // Record the mapping from call piece to LocationContext. 542bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek LCM[&C->path] = CE->getCalleeContext(); 54380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(C); 54480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.pushActivePath(&C->path); 54580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks CallStack.push_back(StackDiagPair(C, N)); 54680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks break; 5479373937945e1e075dfa08169eaccc1ad0b31f699Anna Zaks } 548183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose 5497a95de68c093991047ed8d339479ccad51b88663David Blaikie if (Optional<CallEnter> CE = P.getAs<CallEnter>()) { 55080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // Flush all locations, and pop the active path. 55180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks bool VisitedEntireCall = PD.isWithinCall(); 55280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.popActivePath(); 55380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks 55480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // Either we just added a bunch of stuff to the top-level path, or 55580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // we have a previous CallExitEnd. If the former, it means that the 55680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // path terminated within a function call. We must then take the 55780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // current contents of the active path and place it within 55880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // a new PathDiagnosticCallPiece. 55980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PathDiagnosticCallPiece *C; 56080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks if (VisitedEntireCall) { 56180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks C = cast<PathDiagnosticCallPiece>(PD.getActivePath().front()); 56280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks } else { 56380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks const Decl *Caller = CE->getLocationContext()->getDecl(); 56480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks C = PathDiagnosticCallPiece::construct(PD.getActivePath(), Caller); 565d306a530fca74e40916121f5583e0545e470b3c4Ted Kremenek // Record the mapping from call piece to LocationContext. 566bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek LCM[&C->path] = CE->getCalleeContext(); 56780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks } 56880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks 56980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks C->setCallee(*CE, SMgr); 57080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks if (!CallStack.empty()) { 57180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks assert(CallStack.back().first == C); 57280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks CallStack.pop_back(); 57380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks } 57480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks break; 575368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks } 5761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5777a95de68c093991047ed8d339479ccad51b88663David Blaikie if (Optional<BlockEdge> BE = P.getAs<BlockEdge>()) { 57880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks const CFGBlock *Src = BE->getSrc(); 57980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks const CFGBlock *Dst = BE->getDst(); 58080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks const Stmt *T = Src->getTerminator(); 5811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 58280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks if (!T) 58380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks break; 5841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 58580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PathDiagnosticLocation Start = 58680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PathDiagnosticLocation::createBegin(T, SMgr, 58780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks N->getLocationContext()); 5881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 58980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks switch (T->getStmtClass()) { 59061f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek default: 59161f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek break; 5921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 59361f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek case Stmt::GotoStmtClass: 5941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump case Stmt::IndirectGotoStmtClass: { 5950f8579274a010f360a371b53101859d9d6052314Anna Zaks const Stmt *S = PathDiagnosticLocation::getNextStmt(N); 5961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 59761f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek if (!S) 59880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks break; 5991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 600297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek std::string sbuf; 6011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump llvm::raw_string_ostream os(sbuf); 602d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek const PathDiagnosticLocation &End = PDB.getEnclosingStmtLocation(S); 6031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 60400605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek os << "Control jumps to line " 60580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks << End.asLocation().getExpansionLineNumber(); 60680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 60780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, os.str())); 60861f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek break; 60961f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek } 6101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump case Stmt::SwitchStmtClass: { 61261f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek // Figure out what case arm we took. 613297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek std::string sbuf; 614297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek llvm::raw_string_ostream os(sbuf); 6151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6169c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (const Stmt *S = Dst->getLabel()) { 617220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks PathDiagnosticLocation End(S, SMgr, LC); 6181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6195a429954aedd8a830a70fcea2cb51561673e4fc3Ted Kremenek switch (S->getStmtClass()) { 62080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks default: 62180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks os << "No cases match in the switch statement. " 62280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks "Control jumps to line " 62380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks << End.asLocation().getExpansionLineNumber(); 62480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks break; 62580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks case Stmt::DefaultStmtClass: 62680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks os << "Control jumps to the 'default' case at line " 62780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks << End.asLocation().getExpansionLineNumber(); 62880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks break; 62980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks 63080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks case Stmt::CaseStmtClass: { 63180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks os << "Control jumps to 'case "; 63280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks const CaseStmt *Case = cast<CaseStmt>(S); 63380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks const Expr *LHS = Case->getLHS()->IgnoreParenCasts(); 63480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks 63580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // Determine if it is an enum. 63680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks bool GetRawInt = true; 63780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks 63880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(LHS)) { 63980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // FIXME: Maybe this should be an assertion. Are there cases 64080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // were it is not an EnumConstantDecl? 64180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks const EnumConstantDecl *D = 64203509aea098772644bf4662dc1c88634818ceeccZhongxing Xu dyn_cast<EnumConstantDecl>(DR->getDecl()); 6431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 64480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks if (D) { 64580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks GetRawInt = false; 64680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks os << *D; 6475a429954aedd8a830a70fcea2cb51561673e4fc3Ted Kremenek } 64880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks } 6499ec64d6e2fe575b297e1eaa5051efc2983373e25Eli Friedman 65080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks if (GetRawInt) 65180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks os << LHS->EvaluateKnownConstInt(PDB.getASTContext()); 6529ec64d6e2fe575b297e1eaa5051efc2983373e25Eli Friedman 65380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks os << ":' at line " 65480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks << End.asLocation().getExpansionLineNumber(); 65580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks break; 65661f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek } 65780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks } 65880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 65980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, os.str())); 66061f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek } 661567839273dfc395a459cbe77d5f8d128b9ae85bfTed Kremenek else { 662c3517ebb48a51e146badc08bc3684520c41da6c8Ted Kremenek os << "'Default' branch taken. "; 6631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const PathDiagnosticLocation &End = PDB.ExecutionContinues(os, N); 66480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 66580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, os.str())); 666567839273dfc395a459cbe77d5f8d128b9ae85bfTed Kremenek } 6671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 66861f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek break; 66961f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek } 6701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6712673c9ff76ebdb72b7f846e2ff1e0f4256372e19Ted Kremenek case Stmt::BreakStmtClass: 6722673c9ff76ebdb72b7f846e2ff1e0f4256372e19Ted Kremenek case Stmt::ContinueStmtClass: { 673297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek std::string sbuf; 674297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek llvm::raw_string_ostream os(sbuf); 67500605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(os, N); 67680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 67780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, os.str())); 6782673c9ff76ebdb72b7f846e2ff1e0f4256372e19Ted Kremenek break; 6792673c9ff76ebdb72b7f846e2ff1e0f4256372e19Ted Kremenek } 6801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 68180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // Determine control-flow for ternary '?'. 68256ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall case Stmt::BinaryConditionalOperatorClass: 683706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek case Stmt::ConditionalOperatorClass: { 684297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek std::string sbuf; 685297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek llvm::raw_string_ostream os(sbuf); 6861d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek os << "'?' condition is "; 6871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 688706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek if (*(Src->succ_begin()+1) == Dst) 689082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek os << "false"; 690706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek else 691082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek os << "true"; 6921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 69300605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(N); 6941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6951d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek if (const Stmt *S = End.asStmt()) 6961d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek End = PDB.getEnclosingStmtLocation(S); 6971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 69880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 69980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, os.str())); 700babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek break; 701babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek } 7021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 70380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // Determine control-flow for short-circuited '&&' and '||'. 704babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek case Stmt::BinaryOperatorClass: { 705babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek if (!PDB.supportsLogicalOpControlFlow()) 706babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek break; 7071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 70803509aea098772644bf4662dc1c88634818ceeccZhongxing Xu const BinaryOperator *B = cast<BinaryOperator>(T); 709babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek std::string sbuf; 710babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek llvm::raw_string_ostream os(sbuf); 711babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek os << "Left side of '"; 7121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7132de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall if (B->getOpcode() == BO_LAnd) { 714f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek os << "&&" << "' is "; 7151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 716f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek if (*(Src->succ_begin()+1) == Dst) { 717f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek os << "false"; 718220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks PathDiagnosticLocation End(B->getLHS(), SMgr, LC); 7190cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks PathDiagnosticLocation Start = 72080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PathDiagnosticLocation::createOperatorLoc(B, SMgr); 72180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 72280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, os.str())); 7231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 724f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek else { 725f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek os << "true"; 726220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks PathDiagnosticLocation Start(B->getLHS(), SMgr, LC); 727f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(N); 72880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 72980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, os.str())); 7301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 731babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek } 732babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek else { 7332de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall assert(B->getOpcode() == BO_LOr); 734f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek os << "||" << "' is "; 7351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 736f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek if (*(Src->succ_begin()+1) == Dst) { 737f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek os << "false"; 738220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks PathDiagnosticLocation Start(B->getLHS(), SMgr, LC); 739f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(N); 74080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 74180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, os.str())); 742f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek } 743f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek else { 744f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek os << "true"; 745220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks PathDiagnosticLocation End(B->getLHS(), SMgr, LC); 7460cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks PathDiagnosticLocation Start = 74780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PathDiagnosticLocation::createOperatorLoc(B, SMgr); 74880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 74980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, os.str())); 750f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek } 751babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek } 7521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 753706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek break; 754706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek } 7551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7561eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump case Stmt::DoStmtClass: { 757706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek if (*(Src->succ_begin()) == Dst) { 758297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek std::string sbuf; 759297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek llvm::raw_string_ostream os(sbuf); 7601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 761c3517ebb48a51e146badc08bc3684520c41da6c8Ted Kremenek os << "Loop condition is true. "; 762d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(os, N); 7631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 764d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek if (const Stmt *S = End.asStmt()) 765d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek End = PDB.getEnclosingStmtLocation(S); 7661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 76780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 76880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, os.str())); 769082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek } 770082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek else { 77100605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(N); 7721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 773d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek if (const Stmt *S = End.asStmt()) 774d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek End = PDB.getEnclosingStmtLocation(S); 7751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 77680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 77780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, "Loop condition is false. Exiting loop")); 7783106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 7791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7803106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 7813106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 7821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7833106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek case Stmt::WhileStmtClass: 7841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump case Stmt::ForStmtClass: { 7853106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (*(Src->succ_begin()+1) == Dst) { 7863106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek std::string sbuf; 7873106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek llvm::raw_string_ostream os(sbuf); 7881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7893106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek os << "Loop condition is false. "; 7903106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(os, N); 7913106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (const Stmt *S = End.asStmt()) 7923106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek End = PDB.getEnclosingStmtLocation(S); 7931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 79480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 79580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, os.str())); 7963106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 7973106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek else { 7983106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(N); 7993106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (const Stmt *S = End.asStmt()) 8003106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek End = PDB.getEnclosingStmtLocation(S); 8011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 80280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 80380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, "Loop condition is true. Entering loop body")); 8043106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 8051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8063106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 8073106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 8081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8093106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek case Stmt::IfStmtClass: { 8103106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(N); 8111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8123106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (const Stmt *S = End.asStmt()) 8133106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek End = PDB.getEnclosingStmtLocation(S); 8141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8153106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (*(Src->succ_begin()+1) == Dst) 81680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 81780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, "Taking false branch")); 8181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump else 81980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 82080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, "Taking true branch")); 8211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8223106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 8233106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 82480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks } 8253106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 82680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks } while(0); 8271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 828dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek if (NextNode) { 8298e6431adab313e283a992698f6fc7afe62420999Anna Zaks // Add diagnostic pieces from custom visitors. 8308e6431adab313e283a992698f6fc7afe62420999Anna Zaks BugReport *R = PDB.getBugReport(); 8313bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose for (ArrayRef<BugReporterVisitor *>::iterator I = visitors.begin(), 8323bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose E = visitors.end(); 8333bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose I != E; ++I) { 834368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks if (PathDiagnosticPiece *p = (*I)->VisitNode(N, NextNode, PDB, *R)) { 8352042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.getActivePath().push_front(p); 836368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks updateStackPiecesWithMessage(p, CallStack); 837368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks } 838dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek } 8398966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek } 8403106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 8411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8428347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose if (!PDB.getBugReport()->isValid()) 8438347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose return false; 8448347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose 84514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // After constructing the full PathDiagnostic, do a pass over it to compact 84614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // PathDiagnosticPieces that occur within a macro. 84777d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek CompactPathDiagnostic(PD.getMutablePieces(), PDB.getSourceManager()); 8488347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose return true; 8493106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 8503106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 8513106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 8525fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek// "Extensive" PathDiagnostic generation. 8535fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek//===----------------------------------------------------------------------===// 8545fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek 8555fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenekstatic bool IsControlFlowExpr(const Stmt *S) { 8565fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek const Expr *E = dyn_cast<Expr>(S); 8571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8585fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek if (!E) 8595fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek return false; 8601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump E = E->IgnoreParenCasts(); 8621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 86356ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall if (isa<AbstractConditionalOperator>(E)) 8645fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek return true; 8651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8665fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek if (const BinaryOperator *B = dyn_cast<BinaryOperator>(E)) 8675fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek if (B->isLogicalOp()) 8685fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek return true; 8691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return false; 8715fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek} 8725fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek 87314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremeneknamespace { 874ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass ContextLocation : public PathDiagnosticLocation { 8758f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek bool IsDead; 8768f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenekpublic: 8778f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek ContextLocation(const PathDiagnosticLocation &L, bool isdead = false) 8788f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek : PathDiagnosticLocation(L), IsDead(isdead) {} 8791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump void markDead() { IsDead = true; } 8818f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek bool isDead() const { return IsDead; } 8828f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek}; 8831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 884e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenekstatic PathDiagnosticLocation cleanUpLocation(PathDiagnosticLocation L, 885e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek const LocationContext *LC, 886e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek bool firstCharOnly = false) { 887e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek if (const Stmt *S = L.asStmt()) { 888e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek const Stmt *Original = S; 889e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek while (1) { 890e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek // Adjust the location for some expressions that are best referenced 891e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek // by one of their subexpressions. 892e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek switch (S->getStmtClass()) { 893e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek default: 894e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek break; 895e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek case Stmt::ParenExprClass: 896e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek case Stmt::GenericSelectionExprClass: 897e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek S = cast<Expr>(S)->IgnoreParens(); 898e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek firstCharOnly = true; 899e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek continue; 900e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek case Stmt::BinaryConditionalOperatorClass: 901e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek case Stmt::ConditionalOperatorClass: 902e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek S = cast<AbstractConditionalOperator>(S)->getCond(); 903e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek firstCharOnly = true; 904e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek continue; 905e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek case Stmt::ChooseExprClass: 906e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek S = cast<ChooseExpr>(S)->getCond(); 907e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek firstCharOnly = true; 908e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek continue; 909e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek case Stmt::BinaryOperatorClass: 910e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek S = cast<BinaryOperator>(S)->getLHS(); 911e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek firstCharOnly = true; 912e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek continue; 913e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek } 914e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek 915e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek break; 916e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek } 917e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek 918e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek if (S != Original) 919e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek L = PathDiagnosticLocation(S, L.getManager(), LC); 920e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek } 921e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek 922e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek if (firstCharOnly) 923e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek L = PathDiagnosticLocation::createSingleLocation(L); 924e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek 925e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek return L; 926e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek} 927e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek 928ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass EdgeBuilder { 9298f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek std::vector<ContextLocation> CLocs; 9308f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek typedef std::vector<ContextLocation>::iterator iterator; 93114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek PathDiagnostic &PD; 93214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek PathDiagnosticBuilder &PDB; 93314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek PathDiagnosticLocation PrevLoc; 9341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9358f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek bool IsConsumedExpr(const PathDiagnosticLocation &L); 9361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 93714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek bool containsLocation(const PathDiagnosticLocation &Container, 93814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek const PathDiagnosticLocation &Containee); 9391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 94014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek PathDiagnosticLocation getContextLocation(const PathDiagnosticLocation &L); 9411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9421eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 94414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek void popLocation() { 9458f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek if (!CLocs.back().isDead() && CLocs.back().asLocation().isFileID()) { 9465c7168cbe8a0eabd05e0e12e469090d2cabd27c0Ted Kremenek // For contexts, we only one the first character as the range. 947e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek rawAddEdge(cleanUpLocation(CLocs.back(), PDB.LC, true)); 9485c7168cbe8a0eabd05e0e12e469090d2cabd27c0Ted Kremenek } 94914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek CLocs.pop_back(); 95014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 9511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 95214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekpublic: 95314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek EdgeBuilder(PathDiagnostic &pd, PathDiagnosticBuilder &pdb) 95414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek : PD(pd), PDB(pdb) { 9551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 956a301a6773db085575ac51e3c966858180390c25bTed Kremenek // If the PathDiagnostic already has pieces, add the enclosing statement 957a301a6773db085575ac51e3c966858180390c25bTed Kremenek // of the first piece as a context as well. 958802e02463b880f53a6e645bde78cc412481ce9e0Ted Kremenek if (!PD.path.empty()) { 959ed866e73bab7733f5226f84c52edefe23d694b2fTed Kremenek PrevLoc = (*PD.path.begin())->getLocation(); 9601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 96114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (const Stmt *S = PrevLoc.asStmt()) 962e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek addExtendedContext(PDB.getEnclosingStmtLocation(S).asStmt()); 96314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 96414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 96514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 96614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek ~EdgeBuilder() { 96714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek while (!CLocs.empty()) popLocation(); 9680cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks 969a301a6773db085575ac51e3c966858180390c25bTed Kremenek // Finally, add an initial edge from the start location of the first 970a301a6773db085575ac51e3c966858180390c25bTed Kremenek // statement (if it doesn't already exist). 9710cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks PathDiagnosticLocation L = PathDiagnosticLocation::createDeclBegin( 97259950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek PDB.LC, 9730cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks PDB.getSourceManager()); 9740cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks if (L.isValid()) 9750cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks rawAddEdge(L); 97614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 97714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 9785de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek void flushLocations() { 9795de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek while (!CLocs.empty()) 9805de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek popLocation(); 9815de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek PrevLoc = PathDiagnosticLocation(); 9825de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek } 9835de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek 9843ea09a802f973c2726b2a489ae08a4bded93410bJordan Rose void addEdge(PathDiagnosticLocation NewLoc, bool alwaysAdd = false, 9853ea09a802f973c2726b2a489ae08a4bded93410bJordan Rose bool IsPostJump = false); 9861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9878bd4d037d837e7922c3661d6158229da58a03887Ted Kremenek void rawAddEdge(PathDiagnosticLocation NewLoc); 9881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 98914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek void addContext(const Stmt *S); 990183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose void addContext(const PathDiagnosticLocation &L); 991e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek void addExtendedContext(const Stmt *S); 9921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump}; 99314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} // end anonymous namespace 99414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 99514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 99614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted KremenekPathDiagnosticLocation 99714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted KremenekEdgeBuilder::getContextLocation(const PathDiagnosticLocation &L) { 99814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (const Stmt *S = L.asStmt()) { 99914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (IsControlFlowExpr(S)) 100014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return L; 10011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return PDB.getEnclosingStmtLocation(S); 100314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 10041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 100514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return L; 100614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} 100714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 100814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekbool EdgeBuilder::containsLocation(const PathDiagnosticLocation &Container, 100914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek const PathDiagnosticLocation &Containee) { 101014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 101114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (Container == Containee) 101214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return true; 10131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 101414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (Container.asDecl()) 101514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return true; 10161eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 101714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (const Stmt *S = Containee.asStmt()) 101814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (const Stmt *ContainerS = Container.asStmt()) { 101914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek while (S) { 102014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (S == ContainerS) 102114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return true; 102214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek S = PDB.getParent(S); 102314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 102414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return false; 102514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 102614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 102714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // Less accurate: compare using source ranges. 102814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek SourceRange ContainerR = Container.asRange(); 102914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek SourceRange ContaineeR = Containee.asRange(); 10301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 103114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek SourceManager &SM = PDB.getSourceManager(); 1032402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth SourceLocation ContainerRBeg = SM.getExpansionLoc(ContainerR.getBegin()); 1033402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth SourceLocation ContainerREnd = SM.getExpansionLoc(ContainerR.getEnd()); 1034402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth SourceLocation ContaineeRBeg = SM.getExpansionLoc(ContaineeR.getBegin()); 1035402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth SourceLocation ContaineeREnd = SM.getExpansionLoc(ContaineeR.getEnd()); 10361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1037642116259e8df6286063a17361c20e95b5017a0aChandler Carruth unsigned ContainerBegLine = SM.getExpansionLineNumber(ContainerRBeg); 1038642116259e8df6286063a17361c20e95b5017a0aChandler Carruth unsigned ContainerEndLine = SM.getExpansionLineNumber(ContainerREnd); 1039642116259e8df6286063a17361c20e95b5017a0aChandler Carruth unsigned ContaineeBegLine = SM.getExpansionLineNumber(ContaineeRBeg); 1040642116259e8df6286063a17361c20e95b5017a0aChandler Carruth unsigned ContaineeEndLine = SM.getExpansionLineNumber(ContaineeREnd); 10411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 104214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek assert(ContainerBegLine <= ContainerEndLine); 10431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump assert(ContaineeBegLine <= ContaineeEndLine); 10441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 104514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return (ContainerBegLine <= ContaineeBegLine && 104614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek ContainerEndLine >= ContaineeEndLine && 104714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek (ContainerBegLine != ContaineeBegLine || 1048a77c031cb66f75d22672070052cc6e0205289ff8Chandler Carruth SM.getExpansionColumnNumber(ContainerRBeg) <= 1049a77c031cb66f75d22672070052cc6e0205289ff8Chandler Carruth SM.getExpansionColumnNumber(ContaineeRBeg)) && 105014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek (ContainerEndLine != ContaineeEndLine || 1051a77c031cb66f75d22672070052cc6e0205289ff8Chandler Carruth SM.getExpansionColumnNumber(ContainerREnd) >= 10526488dc31153be6f98b404c7860be6c66bb4ec917Ted Kremenek SM.getExpansionColumnNumber(ContaineeREnd))); 105314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} 105414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 105514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekvoid EdgeBuilder::rawAddEdge(PathDiagnosticLocation NewLoc) { 105614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (!PrevLoc.isValid()) { 105714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek PrevLoc = NewLoc; 105814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return; 105914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 10601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1061e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek const PathDiagnosticLocation &NewLocClean = cleanUpLocation(NewLoc, PDB.LC); 1062e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek const PathDiagnosticLocation &PrevLocClean = cleanUpLocation(PrevLoc, PDB.LC); 10631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1064a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek if (PrevLocClean.asLocation().isInvalid()) { 1065a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek PrevLoc = NewLoc; 1066a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek return; 1067a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek } 1068a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek 10698c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek if (NewLocClean.asLocation() == PrevLocClean.asLocation()) 107014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return; 10711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 107214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // FIXME: Ignore intra-macro edges for now. 1073402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth if (NewLocClean.asLocation().getExpansionLoc() == 1074402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth PrevLocClean.asLocation().getExpansionLoc()) 107514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return; 107614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 10772042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(NewLocClean, PrevLocClean)); 10788c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek PrevLoc = NewLoc; 107914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} 108014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 10813ea09a802f973c2726b2a489ae08a4bded93410bJordan Rosevoid EdgeBuilder::addEdge(PathDiagnosticLocation NewLoc, bool alwaysAdd, 10823ea09a802f973c2726b2a489ae08a4bded93410bJordan Rose bool IsPostJump) { 10831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1084a301a6773db085575ac51e3c966858180390c25bTed Kremenek if (!alwaysAdd && NewLoc.asLocation().isMacroID()) 1085a301a6773db085575ac51e3c966858180390c25bTed Kremenek return; 10861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 108714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek const PathDiagnosticLocation &CLoc = getContextLocation(NewLoc); 108814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 108914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek while (!CLocs.empty()) { 10908f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek ContextLocation &TopContextLoc = CLocs.back(); 10911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 109214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // Is the top location context the same as the one for the new location? 109314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (TopContextLoc == CLoc) { 10948f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek if (alwaysAdd) { 10953ea09a802f973c2726b2a489ae08a4bded93410bJordan Rose if (IsConsumedExpr(TopContextLoc)) 10963ea09a802f973c2726b2a489ae08a4bded93410bJordan Rose TopContextLoc.markDead(); 10978f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek 109814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek rawAddEdge(NewLoc); 10998f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek } 110014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 11013ea09a802f973c2726b2a489ae08a4bded93410bJordan Rose if (IsPostJump) 11023ea09a802f973c2726b2a489ae08a4bded93410bJordan Rose TopContextLoc.markDead(); 110314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return; 110414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 110514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 110614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (containsLocation(TopContextLoc, CLoc)) { 11078f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek if (alwaysAdd) { 110814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek rawAddEdge(NewLoc); 11091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11103ea09a802f973c2726b2a489ae08a4bded93410bJordan Rose if (IsConsumedExpr(CLoc)) { 11113ea09a802f973c2726b2a489ae08a4bded93410bJordan Rose CLocs.push_back(ContextLocation(CLoc, /*IsDead=*/true)); 11128f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek return; 11138f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek } 11148f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek } 11151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11163ea09a802f973c2726b2a489ae08a4bded93410bJordan Rose CLocs.push_back(ContextLocation(CLoc, /*IsDead=*/IsPostJump)); 11171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return; 111814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 111914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 112014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // Context does not contain the location. Flush it. 112114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek popLocation(); 112214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 11231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11245c7168cbe8a0eabd05e0e12e469090d2cabd27c0Ted Kremenek // If we reach here, there is no enclosing context. Just add the edge. 11255c7168cbe8a0eabd05e0e12e469090d2cabd27c0Ted Kremenek rawAddEdge(NewLoc); 112614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} 112714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 11288f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenekbool EdgeBuilder::IsConsumedExpr(const PathDiagnosticLocation &L) { 11298f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek if (const Expr *X = dyn_cast_or_null<Expr>(L.asStmt())) 11308f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek return PDB.getParentMap().isConsumedExpr(X) && !IsControlFlowExpr(X); 11311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11328f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek return false; 11338f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek} 11341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1135e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenekvoid EdgeBuilder::addExtendedContext(const Stmt *S) { 1136e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek if (!S) 1137e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek return; 11381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const Stmt *Parent = PDB.getParent(S); 1140e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek while (Parent) { 1141e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek if (isa<CompoundStmt>(Parent)) 1142e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek Parent = PDB.getParent(Parent); 1143e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek else 1144e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek break; 1145e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek } 1146e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek 1147e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek if (Parent) { 1148e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek switch (Parent->getStmtClass()) { 1149e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek case Stmt::DoStmtClass: 1150e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek case Stmt::ObjCAtSynchronizedStmtClass: 1151e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek addContext(Parent); 1152e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek default: 1153e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek break; 1154e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek } 1155e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek } 11561eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1157e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek addContext(S); 1158e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek} 11591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 116014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekvoid EdgeBuilder::addContext(const Stmt *S) { 116114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (!S) 116214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return; 116314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 116459950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek PathDiagnosticLocation L(S, PDB.getSourceManager(), PDB.LC); 1165183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose addContext(L); 1166183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose} 11671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1168183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rosevoid EdgeBuilder::addContext(const PathDiagnosticLocation &L) { 116914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek while (!CLocs.empty()) { 117014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek const PathDiagnosticLocation &TopContextLoc = CLocs.back(); 117114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 117214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // Is the top location context the same as the one for the new location? 117314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (TopContextLoc == L) 117414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return; 117514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 117614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (containsLocation(TopContextLoc, L)) { 117714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek CLocs.push_back(L); 11781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return; 117914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 118014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 118114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // Context does not contain the location. Flush it. 118214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek popLocation(); 118314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 118414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 118514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek CLocs.push_back(L); 118614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} 118714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 118811abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// Cone-of-influence: support the reverse propagation of "interesting" symbols 118911abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// and values by tracing interesting calculations backwards through evaluated 119011abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// expressions along a path. This is probably overly complicated, but the idea 119111abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// is that if an expression computed an "interesting" value, the child 119211abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// expressions are are also likely to be "interesting" as well (which then 119311abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// propagates to the values they in turn compute). This reverse propagation 119411abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// is needed to track interesting correlations across function call boundaries, 119511abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// where formal arguments bind to actual arguments, etc. This is also needed 119611abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// because the constraint solver sometimes simplifies certain symbolic values 119711abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// into constants when appropriate, and this complicates reasoning about 119811abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// interesting values. 119911abcecc8c919673237cf37384290a1ef1943976Ted Kremenektypedef llvm::DenseSet<const Expr *> InterestingExprs; 120011abcecc8c919673237cf37384290a1ef1943976Ted Kremenek 120111abcecc8c919673237cf37384290a1ef1943976Ted Kremenekstatic void reversePropagateIntererstingSymbols(BugReport &R, 120211abcecc8c919673237cf37384290a1ef1943976Ted Kremenek InterestingExprs &IE, 120311abcecc8c919673237cf37384290a1ef1943976Ted Kremenek const ProgramState *State, 120411abcecc8c919673237cf37384290a1ef1943976Ted Kremenek const Expr *Ex, 120511abcecc8c919673237cf37384290a1ef1943976Ted Kremenek const LocationContext *LCtx) { 120611abcecc8c919673237cf37384290a1ef1943976Ted Kremenek SVal V = State->getSVal(Ex, LCtx); 120711abcecc8c919673237cf37384290a1ef1943976Ted Kremenek if (!(R.isInteresting(V) || IE.count(Ex))) 120811abcecc8c919673237cf37384290a1ef1943976Ted Kremenek return; 120911abcecc8c919673237cf37384290a1ef1943976Ted Kremenek 121011abcecc8c919673237cf37384290a1ef1943976Ted Kremenek switch (Ex->getStmtClass()) { 121111abcecc8c919673237cf37384290a1ef1943976Ted Kremenek default: 121211abcecc8c919673237cf37384290a1ef1943976Ted Kremenek if (!isa<CastExpr>(Ex)) 121311abcecc8c919673237cf37384290a1ef1943976Ted Kremenek break; 121411abcecc8c919673237cf37384290a1ef1943976Ted Kremenek // Fall through. 121511abcecc8c919673237cf37384290a1ef1943976Ted Kremenek case Stmt::BinaryOperatorClass: 121611abcecc8c919673237cf37384290a1ef1943976Ted Kremenek case Stmt::UnaryOperatorClass: { 121711abcecc8c919673237cf37384290a1ef1943976Ted Kremenek for (Stmt::const_child_iterator CI = Ex->child_begin(), 121811abcecc8c919673237cf37384290a1ef1943976Ted Kremenek CE = Ex->child_end(); 121911abcecc8c919673237cf37384290a1ef1943976Ted Kremenek CI != CE; ++CI) { 122011abcecc8c919673237cf37384290a1ef1943976Ted Kremenek if (const Expr *child = dyn_cast_or_null<Expr>(*CI)) { 122111abcecc8c919673237cf37384290a1ef1943976Ted Kremenek IE.insert(child); 122211abcecc8c919673237cf37384290a1ef1943976Ted Kremenek SVal ChildV = State->getSVal(child, LCtx); 122311abcecc8c919673237cf37384290a1ef1943976Ted Kremenek R.markInteresting(ChildV); 122411abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 122511abcecc8c919673237cf37384290a1ef1943976Ted Kremenek break; 122611abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 122711abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 122811abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 122911abcecc8c919673237cf37384290a1ef1943976Ted Kremenek 123011abcecc8c919673237cf37384290a1ef1943976Ted Kremenek R.markInteresting(V); 123111abcecc8c919673237cf37384290a1ef1943976Ted Kremenek} 123211abcecc8c919673237cf37384290a1ef1943976Ted Kremenek 123311abcecc8c919673237cf37384290a1ef1943976Ted Kremenekstatic void reversePropagateInterestingSymbols(BugReport &R, 123411abcecc8c919673237cf37384290a1ef1943976Ted Kremenek InterestingExprs &IE, 123511abcecc8c919673237cf37384290a1ef1943976Ted Kremenek const ProgramState *State, 123611abcecc8c919673237cf37384290a1ef1943976Ted Kremenek const LocationContext *CalleeCtx, 123711abcecc8c919673237cf37384290a1ef1943976Ted Kremenek const LocationContext *CallerCtx) 123811abcecc8c919673237cf37384290a1ef1943976Ted Kremenek{ 1239852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose // FIXME: Handle non-CallExpr-based CallEvents. 124011abcecc8c919673237cf37384290a1ef1943976Ted Kremenek const StackFrameContext *Callee = CalleeCtx->getCurrentStackFrame(); 124111abcecc8c919673237cf37384290a1ef1943976Ted Kremenek const Stmt *CallSite = Callee->getCallSite(); 1242852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose if (const CallExpr *CE = dyn_cast_or_null<CallExpr>(CallSite)) { 124311abcecc8c919673237cf37384290a1ef1943976Ted Kremenek if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CalleeCtx->getDecl())) { 124411abcecc8c919673237cf37384290a1ef1943976Ted Kremenek FunctionDecl::param_const_iterator PI = FD->param_begin(), 124511abcecc8c919673237cf37384290a1ef1943976Ted Kremenek PE = FD->param_end(); 124611abcecc8c919673237cf37384290a1ef1943976Ted Kremenek CallExpr::const_arg_iterator AI = CE->arg_begin(), AE = CE->arg_end(); 124711abcecc8c919673237cf37384290a1ef1943976Ted Kremenek for (; AI != AE && PI != PE; ++AI, ++PI) { 124811abcecc8c919673237cf37384290a1ef1943976Ted Kremenek if (const Expr *ArgE = *AI) { 124911abcecc8c919673237cf37384290a1ef1943976Ted Kremenek if (const ParmVarDecl *PD = *PI) { 125011abcecc8c919673237cf37384290a1ef1943976Ted Kremenek Loc LV = State->getLValue(PD, CalleeCtx); 125111abcecc8c919673237cf37384290a1ef1943976Ted Kremenek if (R.isInteresting(LV) || R.isInteresting(State->getRawSVal(LV))) 125211abcecc8c919673237cf37384290a1ef1943976Ted Kremenek IE.insert(ArgE); 125311abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 125411abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 125511abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 125611abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 125711abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 125811abcecc8c919673237cf37384290a1ef1943976Ted Kremenek} 12598185674528423e2504a1fae35c28c24104846510Ted Kremenek 1260b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek//===----------------------------------------------------------------------===// 1261b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek// Functions for determining if a loop was executed 0 times. 1262b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek//===----------------------------------------------------------------------===// 1263b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek 1264b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenekstatic bool isLoop(const Stmt *Term) { 12658185674528423e2504a1fae35c28c24104846510Ted Kremenek switch (Term->getStmtClass()) { 12668185674528423e2504a1fae35c28c24104846510Ted Kremenek case Stmt::ForStmtClass: 12678185674528423e2504a1fae35c28c24104846510Ted Kremenek case Stmt::WhileStmtClass: 1268c5b9c8bc6d77175f6d41d898511b1e7b1e2f86f8Ted Kremenek case Stmt::ObjCForCollectionStmtClass: 1269b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek return true; 12708185674528423e2504a1fae35c28c24104846510Ted Kremenek default: 12718185674528423e2504a1fae35c28c24104846510Ted Kremenek // Note that we intentionally do not include do..while here. 12728185674528423e2504a1fae35c28c24104846510Ted Kremenek return false; 12738185674528423e2504a1fae35c28c24104846510Ted Kremenek } 1274b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek} 12758185674528423e2504a1fae35c28c24104846510Ted Kremenek 1276b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenekstatic bool isJumpToFalseBranch(const BlockEdge *BE) { 12778185674528423e2504a1fae35c28c24104846510Ted Kremenek const CFGBlock *Src = BE->getSrc(); 12788185674528423e2504a1fae35c28c24104846510Ted Kremenek assert(Src->succ_size() == 2); 12798185674528423e2504a1fae35c28c24104846510Ted Kremenek return (*(Src->succ_begin()+1) == BE->getDst()); 12808185674528423e2504a1fae35c28c24104846510Ted Kremenek} 12818185674528423e2504a1fae35c28c24104846510Ted Kremenek 1282b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek/// Return true if the terminator is a loop and the destination is the 1283b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek/// false branch. 1284b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenekstatic bool isLoopJumpPastBody(const Stmt *Term, const BlockEdge *BE) { 1285b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek if (!isLoop(Term)) 1286b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek return false; 1287b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek 1288b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek // Did we take the false branch? 1289b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek return isJumpToFalseBranch(BE); 1290b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek} 1291b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek 1292b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenekstatic bool isContainedByStmt(ParentMap &PM, const Stmt *S, const Stmt *SubS) { 1293b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek while (SubS) { 1294b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek if (SubS == S) 1295b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek return true; 1296b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek SubS = PM.getParent(SubS); 1297b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek } 1298b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek return false; 1299b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek} 1300b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek 1301b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenekstatic const Stmt *getStmtBeforeCond(ParentMap &PM, const Stmt *Term, 1302b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek const ExplodedNode *N) { 1303b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek while (N) { 1304b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek Optional<StmtPoint> SP = N->getLocation().getAs<StmtPoint>(); 1305b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek if (SP) { 1306b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek const Stmt *S = SP->getStmt(); 1307b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek if (!isContainedByStmt(PM, Term, S)) 1308b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek return S; 1309b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek } 13100f8579274a010f360a371b53101859d9d6052314Anna Zaks N = N->getFirstPred(); 1311b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek } 1312b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek return 0; 1313b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek} 1314b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek 1315b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenekstatic bool isInLoopBody(ParentMap &PM, const Stmt *S, const Stmt *Term) { 1316b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek const Stmt *LoopBody = 0; 1317b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek switch (Term->getStmtClass()) { 1318b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek case Stmt::ForStmtClass: { 1319b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek const ForStmt *FS = cast<ForStmt>(Term); 1320b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek if (isContainedByStmt(PM, FS->getInc(), S)) 1321b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek return true; 1322b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek LoopBody = FS->getBody(); 1323b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek break; 1324b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek } 1325c5b9c8bc6d77175f6d41d898511b1e7b1e2f86f8Ted Kremenek case Stmt::ObjCForCollectionStmtClass: { 1326c5b9c8bc6d77175f6d41d898511b1e7b1e2f86f8Ted Kremenek const ObjCForCollectionStmt *FC = cast<ObjCForCollectionStmt>(Term); 1327c5b9c8bc6d77175f6d41d898511b1e7b1e2f86f8Ted Kremenek LoopBody = FC->getBody(); 1328c5b9c8bc6d77175f6d41d898511b1e7b1e2f86f8Ted Kremenek break; 1329c5b9c8bc6d77175f6d41d898511b1e7b1e2f86f8Ted Kremenek } 1330b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek case Stmt::WhileStmtClass: 1331b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek LoopBody = cast<WhileStmt>(Term)->getBody(); 1332b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek break; 1333b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek default: 1334b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek return false; 1335b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek } 1336b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek return isContainedByStmt(PM, LoopBody, S); 1337b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek} 1338b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek 1339b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek//===----------------------------------------------------------------------===// 1340b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek// Top-level logic for generating extensive path diagnostics. 1341b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek//===----------------------------------------------------------------------===// 1342b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek 13438347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rosestatic bool GenerateExtensivePathDiagnostic(PathDiagnostic& PD, 134414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek PathDiagnosticBuilder &PDB, 13453bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose const ExplodedNode *N, 1346d306a530fca74e40916121f5583e0545e470b3c4Ted Kremenek LocationContextMap &LCM, 13473bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose ArrayRef<BugReporterVisitor *> visitors) { 134814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek EdgeBuilder EB(PD, PDB); 13490cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks const SourceManager& SM = PDB.getSourceManager(); 135056a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks StackDiagVector CallStack; 135111abcecc8c919673237cf37384290a1ef1943976Ted Kremenek InterestingExprs IE; 135214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 13539c378f705405d37f49795d5e915989de774fe11fTed Kremenek const ExplodedNode *NextNode = N->pred_empty() ? NULL : *(N->pred_begin()); 135414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek while (NextNode) { 135514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek N = NextNode; 13560f8579274a010f360a371b53101859d9d6052314Anna Zaks NextNode = N->getFirstPred(); 135714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek ProgramPoint P = N->getLocation(); 135814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 1359dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek do { 13607a95de68c093991047ed8d339479ccad51b88663David Blaikie if (Optional<PostStmt> PS = P.getAs<PostStmt>()) { 136111abcecc8c919673237cf37384290a1ef1943976Ted Kremenek if (const Expr *Ex = PS->getStmtAs<Expr>()) 136211abcecc8c919673237cf37384290a1ef1943976Ted Kremenek reversePropagateIntererstingSymbols(*PDB.getBugReport(), IE, 136311abcecc8c919673237cf37384290a1ef1943976Ted Kremenek N->getState().getPtr(), Ex, 136411abcecc8c919673237cf37384290a1ef1943976Ted Kremenek N->getLocationContext()); 136511abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 136611abcecc8c919673237cf37384290a1ef1943976Ted Kremenek 13677a95de68c093991047ed8d339479ccad51b88663David Blaikie if (Optional<CallExitEnd> CE = P.getAs<CallExitEnd>()) { 1368183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose const Stmt *S = CE->getCalleeContext()->getCallSite(); 1369183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose if (const Expr *Ex = dyn_cast_or_null<Expr>(S)) { 1370852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose reversePropagateIntererstingSymbols(*PDB.getBugReport(), IE, 1371852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose N->getState().getPtr(), Ex, 1372852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose N->getLocationContext()); 1373852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose } 1374183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose 1375183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose PathDiagnosticCallPiece *C = 1376183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose PathDiagnosticCallPiece::construct(N, *CE, SM); 1377bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek LCM[&C->path] = CE->getCalleeContext(); 1378183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose 13793ea09a802f973c2726b2a489ae08a4bded93410bJordan Rose EB.addEdge(C->callReturn, /*AlwaysAdd=*/true, /*IsPostJump=*/true); 1380183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose EB.flushLocations(); 1381183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose 1382183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose PD.getActivePath().push_front(C); 1383183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose PD.pushActivePath(&C->path); 1384183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose CallStack.push_back(StackDiagPair(C, N)); 13855de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek break; 13865de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek } 13874ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek 13882042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek // Pop the call hierarchy if we are done walking the contents 13892042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek // of a function call. 13907a95de68c093991047ed8d339479ccad51b88663David Blaikie if (Optional<CallEnter> CE = P.getAs<CallEnter>()) { 1391097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted Kremenek // Add an edge to the start of the function. 1392097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted Kremenek const Decl *D = CE->getCalleeContext()->getDecl(); 1393097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted Kremenek PathDiagnosticLocation pos = 1394097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted Kremenek PathDiagnosticLocation::createBegin(D, SM); 1395097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted Kremenek EB.addEdge(pos); 1396097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted Kremenek 1397097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted Kremenek // Flush all locations, and pop the active path. 1398183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose bool VisitedEntireCall = PD.isWithinCall(); 13994ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek EB.flushLocations(); 14002042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.popActivePath(); 14014ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek PDB.LC = N->getLocationContext(); 1402097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted Kremenek 1403183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose // Either we just added a bunch of stuff to the top-level path, or 1404183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose // we have a previous CallExitEnd. If the former, it means that the 14052042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek // path terminated within a function call. We must then take the 14062042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek // current contents of the active path and place it within 14072042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek // a new PathDiagnosticCallPiece. 1408183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose PathDiagnosticCallPiece *C; 1409183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose if (VisitedEntireCall) { 1410183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose C = cast<PathDiagnosticCallPiece>(PD.getActivePath().front()); 1411183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose } else { 1412183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose const Decl *Caller = CE->getLocationContext()->getDecl(); 14139373937945e1e075dfa08169eaccc1ad0b31f699Anna Zaks C = PathDiagnosticCallPiece::construct(PD.getActivePath(), Caller); 1414bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek LCM[&C->path] = CE->getCalleeContext(); 14159373937945e1e075dfa08169eaccc1ad0b31f699Anna Zaks } 1416852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose 1417183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose C->setCallee(*CE, SM); 1418183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose EB.addContext(C->getLocation()); 1419368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks 1420368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks if (!CallStack.empty()) { 142156a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks assert(CallStack.back().first == C); 1422368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks CallStack.pop_back(); 1423368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks } 14242042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek break; 14252042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek } 14264ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek 14274ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek // Note that is important that we update the LocationContext 14284ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek // after looking at CallExits. CallExit basically adds an 14294ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek // edge in the *caller*, so we don't want to update the LocationContext 14304ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek // too soon. 14314ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek PDB.LC = N->getLocationContext(); 14325de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek 1433dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek // Block edges. 14347a95de68c093991047ed8d339479ccad51b88663David Blaikie if (Optional<BlockEdge> BE = P.getAs<BlockEdge>()) { 143511abcecc8c919673237cf37384290a1ef1943976Ted Kremenek // Does this represent entering a call? If so, look at propagating 143611abcecc8c919673237cf37384290a1ef1943976Ted Kremenek // interesting symbols across call boundaries. 143711abcecc8c919673237cf37384290a1ef1943976Ted Kremenek if (NextNode) { 143811abcecc8c919673237cf37384290a1ef1943976Ted Kremenek const LocationContext *CallerCtx = NextNode->getLocationContext(); 143911abcecc8c919673237cf37384290a1ef1943976Ted Kremenek const LocationContext *CalleeCtx = PDB.LC; 144011abcecc8c919673237cf37384290a1ef1943976Ted Kremenek if (CallerCtx != CalleeCtx) { 144111abcecc8c919673237cf37384290a1ef1943976Ted Kremenek reversePropagateInterestingSymbols(*PDB.getBugReport(), IE, 144211abcecc8c919673237cf37384290a1ef1943976Ted Kremenek N->getState().getPtr(), 144311abcecc8c919673237cf37384290a1ef1943976Ted Kremenek CalleeCtx, CallerCtx); 144411abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 144511abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 144611abcecc8c919673237cf37384290a1ef1943976Ted Kremenek 1447dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek // Are we jumping to the head of a loop? Add a special diagnostic. 1448f57a2aa02c0578c5bd834fec0d44c16ad9908620Ted Kremenek if (const Stmt *Loop = BE->getSrc()->getLoopTarget()) { 144959950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek PathDiagnosticLocation L(Loop, SM, PDB.LC); 1450ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek const CompoundStmt *CS = NULL; 14511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1452f57a2aa02c0578c5bd834fec0d44c16ad9908620Ted Kremenek if (const ForStmt *FS = dyn_cast<ForStmt>(Loop)) 1453f57a2aa02c0578c5bd834fec0d44c16ad9908620Ted Kremenek CS = dyn_cast<CompoundStmt>(FS->getBody()); 1454f57a2aa02c0578c5bd834fec0d44c16ad9908620Ted Kremenek else if (const WhileStmt *WS = dyn_cast<WhileStmt>(Loop)) 1455f57a2aa02c0578c5bd834fec0d44c16ad9908620Ted Kremenek CS = dyn_cast<CompoundStmt>(WS->getBody()); 14561eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1457dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek PathDiagnosticEventPiece *p = 1458dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek new PathDiagnosticEventPiece(L, 145907c015cbcee31f72e2d320ba2c713c046bed42faTed Kremenek "Looping back to the head of the loop"); 14602dd17abf11ae64339fa6bfaa57d76e13a5fbe5b8Ted Kremenek p->setPrunable(true); 14611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1462dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek EB.addEdge(p->getLocation(), true); 14632042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.getActivePath().push_front(p); 14641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1465ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek if (CS) { 14660cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks PathDiagnosticLocation BL = 14670cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks PathDiagnosticLocation::createEndBrace(CS, SM); 146807c015cbcee31f72e2d320ba2c713c046bed42faTed Kremenek EB.addEdge(BL); 1469dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek } 14708bd4d037d837e7922c3661d6158229da58a03887Ted Kremenek } 14718185674528423e2504a1fae35c28c24104846510Ted Kremenek 1472b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek const CFGBlock *BSrc = BE->getSrc(); 1473b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek ParentMap &PM = PDB.getParentMap(); 1474b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek 1475b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek if (const Stmt *Term = BSrc->getTerminator()) { 14768185674528423e2504a1fae35c28c24104846510Ted Kremenek // Are we jumping past the loop body without ever executing the 14778185674528423e2504a1fae35c28c24104846510Ted Kremenek // loop (because the condition was false)? 14787a95de68c093991047ed8d339479ccad51b88663David Blaikie if (isLoopJumpPastBody(Term, &*BE) && 1479b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek !isInLoopBody(PM, 1480b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek getStmtBeforeCond(PM, 1481b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek BSrc->getTerminatorCondition(), 1482b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek N), 1483b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek Term)) { 14848185674528423e2504a1fae35c28c24104846510Ted Kremenek PathDiagnosticLocation L(Term, SM, PDB.LC); 14858185674528423e2504a1fae35c28c24104846510Ted Kremenek PathDiagnosticEventPiece *PE = 1486b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek new PathDiagnosticEventPiece(L, "Loop body executed 0 times"); 14878185674528423e2504a1fae35c28c24104846510Ted Kremenek PE->setPrunable(true); 14888185674528423e2504a1fae35c28c24104846510Ted Kremenek 14898185674528423e2504a1fae35c28c24104846510Ted Kremenek EB.addEdge(PE->getLocation(), true); 14908185674528423e2504a1fae35c28c24104846510Ted Kremenek PD.getActivePath().push_front(PE); 14918185674528423e2504a1fae35c28c24104846510Ted Kremenek } 14928185674528423e2504a1fae35c28c24104846510Ted Kremenek 1493b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek // In any case, add the terminator as the current statement 1494b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek // context for control edges. 1495ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek EB.addContext(Term); 14968185674528423e2504a1fae35c28c24104846510Ted Kremenek } 14971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1498dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek break; 14998bd4d037d837e7922c3661d6158229da58a03887Ted Kremenek } 150014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 15017a95de68c093991047ed8d339479ccad51b88663David Blaikie if (Optional<BlockEntrance> BE = P.getAs<BlockEntrance>()) { 1502b07805485c603be3d8011f72611465324c9e664bDavid Blaikie Optional<CFGElement> First = BE->getFirstElement(); 1503b07805485c603be3d8011f72611465324c9e664bDavid Blaikie if (Optional<CFGStmt> S = First ? First->getAs<CFGStmt>() : None) { 1504b07805485c603be3d8011f72611465324c9e664bDavid Blaikie const Stmt *stmt = S->getStmt(); 15053c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek if (IsControlFlowExpr(stmt)) { 1506b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu // Add the proper context for '&&', '||', and '?'. 15073c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek EB.addContext(stmt); 1508b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu } 1509b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu else 15103c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek EB.addExtendedContext(PDB.getEnclosingStmtLocation(stmt).asStmt()); 1511dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek } 1512b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu 1513dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek break; 1514dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek } 15155de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek 15165de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek 1517dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek } while (0); 15181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1519dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek if (!NextNode) 152014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek continue; 15211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15228e6431adab313e283a992698f6fc7afe62420999Anna Zaks // Add pieces from custom visitors. 15238e6431adab313e283a992698f6fc7afe62420999Anna Zaks BugReport *R = PDB.getBugReport(); 15243bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose for (ArrayRef<BugReporterVisitor *>::iterator I = visitors.begin(), 15253bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose E = visitors.end(); 15263bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose I != E; ++I) { 15278e6431adab313e283a992698f6fc7afe62420999Anna Zaks if (PathDiagnosticPiece *p = (*I)->VisitNode(N, NextNode, PDB, *R)) { 15288966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek const PathDiagnosticLocation &Loc = p->getLocation(); 15298966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek EB.addEdge(Loc, true); 15302042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.getActivePath().push_front(p); 1531368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks updateStackPiecesWithMessage(p, CallStack); 1532368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks 15338966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek if (const Stmt *S = Loc.asStmt()) 15341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump EB.addExtendedContext(PDB.getEnclosingStmtLocation(S).asStmt()); 15358966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek } 15361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 153714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 15388347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose 15398347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose return PDB.getBugReport()->isValid(); 154014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} 154114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 1542af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek/// \brief Adds a sanitized control-flow diagnostic edge to a path. 1543af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenekstatic void addEdgeToPath(PathPieces &path, 1544af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek PathDiagnosticLocation &PrevLoc, 1545af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek PathDiagnosticLocation NewLoc, 1546af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek const LocationContext *LC) { 1547bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek if (!NewLoc.isValid()) 1548af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek return; 1549af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1550bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek SourceLocation NewLocL = NewLoc.asLocation(); 1551bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek if (NewLocL.isInvalid() || NewLocL.isMacroID()) 1552af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek return; 1553af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1554bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek if (!PrevLoc.isValid()) { 1555af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek PrevLoc = NewLoc; 1556af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek return; 1557af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek } 1558af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1559af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek // FIXME: ignore intra-macro edges for now. 1560bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek if (NewLoc.asLocation().getExpansionLoc() == 1561bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek PrevLoc.asLocation().getExpansionLoc()) 1562af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek return; 1563af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1564bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek path.push_front(new PathDiagnosticControlFlowPiece(NewLoc, 1565bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek PrevLoc)); 1566af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek PrevLoc = NewLoc; 1567af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek} 1568af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1569e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek/// A customized wrapper for CFGBlock::getTerminatorCondition() 1570e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek/// which returns the element for ObjCForCollectionStmts. 1571e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenekstatic const Stmt *getTerminatorCondition(const CFGBlock *B) { 1572e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek const Stmt *S = B->getTerminatorCondition(); 1573e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek if (const ObjCForCollectionStmt *FS = 1574e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek dyn_cast_or_null<ObjCForCollectionStmt>(S)) 1575e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek return FS->getElement(); 1576e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek return S; 1577e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek} 1578e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek 1579af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenekstatic bool 1580af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted KremenekGenerateAlternateExtensivePathDiagnostic(PathDiagnostic& PD, 1581af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek PathDiagnosticBuilder &PDB, 1582af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek const ExplodedNode *N, 1583af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek LocationContextMap &LCM, 1584af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek ArrayRef<BugReporterVisitor *> visitors) { 1585af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1586af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek BugReport *report = PDB.getBugReport(); 1587af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek const SourceManager& SM = PDB.getSourceManager(); 1588af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek StackDiagVector CallStack; 1589af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek InterestingExprs IE; 1590af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1591af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek // Record the last location for a given visited stack frame. 1592af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek llvm::DenseMap<const StackFrameContext *, PathDiagnosticLocation> 1593af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek PrevLocMap; 15946d0da608c144eb57b7dd22f71b363191a4a1b2c0Jordan Rose PrevLocMap[N->getLocationContext()->getCurrentStackFrame()] = 15956d0da608c144eb57b7dd22f71b363191a4a1b2c0Jordan Rose PD.getLocation(); 1596af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1597af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek const ExplodedNode *NextNode = N->getFirstPred(); 1598af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek while (NextNode) { 1599af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek N = NextNode; 1600af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek NextNode = N->getFirstPred(); 1601af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek ProgramPoint P = N->getLocation(); 1602af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1603af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek do { 1604be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek // Have we encountered an entrance to a call? It may be 1605be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek // the case that we have not encountered a matching 1606be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek // call exit before this point. This means that the path 1607be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek // terminated within the call itself. 1608be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek if (Optional<CallEnter> CE = P.getAs<CallEnter>()) { 1609be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek // Did we visit an entire call? 1610be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek bool VisitedEntireCall = PD.isWithinCall(); 1611be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek PD.popActivePath(); 1612be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek 1613be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek PathDiagnosticCallPiece *C; 1614be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek if (VisitedEntireCall) { 1615be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek PathDiagnosticPiece *P = PD.getActivePath().front().getPtr(); 1616be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek C = cast<PathDiagnosticCallPiece>(P); 1617be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek } else { 1618be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek const Decl *Caller = CE->getLocationContext()->getDecl(); 1619be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek C = PathDiagnosticCallPiece::construct(PD.getActivePath(), Caller); 1620be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek 1621be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek // Since we just transferred the path over to the call piece, 1622be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek // reset the mapping from active to location context. 1623be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek assert(PD.getActivePath().size() == 1 && 1624be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek PD.getActivePath().front() == C); 1625be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek LCM[&PD.getActivePath()] = 0; 1626be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek 1627be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek // Record the location context mapping for the path within 1628be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek // the call. 1629be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek assert(LCM[&C->path] == 0 || 1630be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek LCM[&C->path] == CE->getCalleeContext()); 1631be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek LCM[&C->path] = CE->getCalleeContext(); 1632be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek 1633be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek // If this is the first item in the active path, record 1634be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek // the new mapping from active path to location context. 1635be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek const LocationContext *&NewLC = LCM[&PD.getActivePath()]; 1636be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek if (!NewLC) { 1637be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek NewLC = N->getLocationContext(); 1638be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek } 1639be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek PDB.LC = NewLC; 1640be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek 1641be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek // Update the previous location in the active path 1642be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek // since we just created the call piece lazily. 1643be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek PrevLocMap[PDB.LC->getCurrentStackFrame()] = C->getLocation(); 1644be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek } 1645be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek C->setCallee(*CE, SM); 1646be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek 1647be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek if (!CallStack.empty()) { 1648be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek assert(CallStack.back().first == C); 1649be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek CallStack.pop_back(); 1650be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek } 1651af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek break; 1652af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek } 1653af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1654be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek // Query the location context here and the previous location 1655be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek // as processing CallEnter may change the active path. 1656be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek PDB.LC = N->getLocationContext(); 1657be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek 1658be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek // Get the previous location for the current active 1659be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek // location context. All edges will be based on this 1660be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek // location, and it will be updated in place. 1661be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek PathDiagnosticLocation &PrevLoc = 1662be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek PrevLocMap[PDB.LC->getCurrentStackFrame()]; 1663be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek 1664be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek // Record the mapping from the active path to the location 1665be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek // context. 1666be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek assert(!LCM[&PD.getActivePath()] || 1667be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek LCM[&PD.getActivePath()] == PDB.LC); 1668be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek LCM[&PD.getActivePath()] = PDB.LC; 1669be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek 1670af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek // Have we encountered an exit from a function call? 1671af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek if (Optional<CallExitEnd> CE = P.getAs<CallExitEnd>()) { 1672af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek const Stmt *S = CE->getCalleeContext()->getCallSite(); 1673af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek // Propagate the interesting symbols accordingly. 1674af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek if (const Expr *Ex = dyn_cast_or_null<Expr>(S)) { 1675af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek reversePropagateIntererstingSymbols(*PDB.getBugReport(), IE, 1676af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek N->getState().getPtr(), Ex, 1677af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek N->getLocationContext()); 1678af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek } 1679af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1680af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek // We are descending into a call (backwards). Construct 1681af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek // a new call piece to contain the path pieces for that call. 1682af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek PathDiagnosticCallPiece *C = 1683af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek PathDiagnosticCallPiece::construct(N, *CE, SM); 1684af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1685af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek // Record the location context for this call piece. 1686bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek LCM[&C->path] = CE->getCalleeContext(); 1687af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1688af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek // Add the edge to the return site. 1689be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek addEdgeToPath(PD.getActivePath(), PrevLoc, C->callReturn, PDB.LC); 1690be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek PD.getActivePath().push_front(C); 1691af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1692af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek // Make the contents of the call the active path for now. 1693af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek PD.pushActivePath(&C->path); 1694af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek CallStack.push_back(StackDiagPair(C, N)); 1695af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek break; 1696af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek } 1697af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1698be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek if (Optional<PostStmt> PS = P.getAs<PostStmt>()) { 1699be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek // For expressions, make sure we propagate the 1700be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek // interesting symbols correctly. 1701be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek if (const Expr *Ex = PS->getStmtAs<Expr>()) 1702be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek reversePropagateIntererstingSymbols(*PDB.getBugReport(), IE, 1703be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek N->getState().getPtr(), Ex, 1704be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek N->getLocationContext()); 1705af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1706e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek // Add an edge. If this is an ObjCForCollectionStmt do 1707e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek // not add an edge here as it appears in the CFG both 1708e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek // as a terminator and as a terminator condition. 1709e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek if (!isa<ObjCForCollectionStmt>(PS->getStmt())) { 1710e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek PathDiagnosticLocation L = 1711e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek PathDiagnosticLocation(PS->getStmt(), SM, PDB.LC); 1712e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek addEdgeToPath(PD.getActivePath(), PrevLoc, L, PDB.LC); 1713e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek } 1714af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek break; 1715af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek } 1716af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1717af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek // Block edges. 1718af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek if (Optional<BlockEdge> BE = P.getAs<BlockEdge>()) { 1719af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek // Does this represent entering a call? If so, look at propagating 1720af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek // interesting symbols across call boundaries. 1721af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek if (NextNode) { 1722af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek const LocationContext *CallerCtx = NextNode->getLocationContext(); 1723af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek const LocationContext *CalleeCtx = PDB.LC; 1724af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek if (CallerCtx != CalleeCtx) { 1725af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek reversePropagateInterestingSymbols(*PDB.getBugReport(), IE, 1726af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek N->getState().getPtr(), 1727af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek CalleeCtx, CallerCtx); 1728af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek } 1729af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek } 1730af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1731af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek // Are we jumping to the head of a loop? Add a special diagnostic. 1732af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek if (const Stmt *Loop = BE->getSrc()->getLoopTarget()) { 1733af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek PathDiagnosticLocation L(Loop, SM, PDB.LC); 1734afde200cdae9731aa5826c6178eae9e7fef74475Ted Kremenek const CompoundStmt *CS = NULL; 1735afde200cdae9731aa5826c6178eae9e7fef74475Ted Kremenek 1736afde200cdae9731aa5826c6178eae9e7fef74475Ted Kremenek if (const ForStmt *FS = dyn_cast<ForStmt>(Loop)) 1737afde200cdae9731aa5826c6178eae9e7fef74475Ted Kremenek CS = dyn_cast<CompoundStmt>(FS->getBody()); 1738afde200cdae9731aa5826c6178eae9e7fef74475Ted Kremenek else if (const WhileStmt *WS = dyn_cast<WhileStmt>(Loop)) 1739afde200cdae9731aa5826c6178eae9e7fef74475Ted Kremenek CS = dyn_cast<CompoundStmt>(WS->getBody()); 1740e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek else if (const ObjCForCollectionStmt *OFS = 1741e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek dyn_cast<ObjCForCollectionStmt>(Loop)) { 1742e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek CS = dyn_cast<CompoundStmt>(OFS->getBody()); 1743e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek } 1744af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1745af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek PathDiagnosticEventPiece *p = 1746af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek new PathDiagnosticEventPiece(L, "Looping back to the head " 1747af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek "of the loop"); 1748af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek p->setPrunable(true); 1749af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1750be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek addEdgeToPath(PD.getActivePath(), PrevLoc, p->getLocation(), PDB.LC); 1751cd389d8cc9abeffb1416b70dd58148e66e5d822bTed Kremenek PD.getActivePath().push_front(p); 1752afde200cdae9731aa5826c6178eae9e7fef74475Ted Kremenek 1753afde200cdae9731aa5826c6178eae9e7fef74475Ted Kremenek if (CS) { 1754afde200cdae9731aa5826c6178eae9e7fef74475Ted Kremenek addEdgeToPath(PD.getActivePath(), PrevLoc, 1755afde200cdae9731aa5826c6178eae9e7fef74475Ted Kremenek PathDiagnosticLocation::createEndBrace(CS, SM), 1756afde200cdae9731aa5826c6178eae9e7fef74475Ted Kremenek PDB.LC); 1757afde200cdae9731aa5826c6178eae9e7fef74475Ted Kremenek } 1758af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek } 1759b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek 1760af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek const CFGBlock *BSrc = BE->getSrc(); 1761af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek ParentMap &PM = PDB.getParentMap(); 1762af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1763af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek if (const Stmt *Term = BSrc->getTerminator()) { 1764af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek // Are we jumping past the loop body without ever executing the 1765af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek // loop (because the condition was false)? 1766b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek if (isLoop(Term)) { 1767e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek const Stmt *TermCond = getTerminatorCondition(BSrc); 1768b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek bool IsInLoopBody = 1769b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek isInLoopBody(PM, getStmtBeforeCond(PM, TermCond, N), Term); 1770b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek 1771b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek const char *str = 0; 1772b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek 1773b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek if (isJumpToFalseBranch(&*BE)) { 1774b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek if (!IsInLoopBody) { 1775b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek str = "Loop body executed 0 times"; 1776b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek } 1777b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek } 1778b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek else { 1779b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek str = "Entering loop body"; 1780b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek } 1781b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek 1782b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek if (str) { 1783d0f5faf319550b0504b2f8f822d06a6b0279285bTed Kremenek PathDiagnosticLocation L(TermCond, SM, PDB.LC); 1784b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek PathDiagnosticEventPiece *PE = 1785b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek new PathDiagnosticEventPiece(L, str); 1786b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek PE->setPrunable(true); 1787b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek addEdgeToPath(PD.getActivePath(), PrevLoc, 1788be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek PE->getLocation(), PDB.LC); 1789b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek PD.getActivePath().push_front(PE); 1790b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek } 1791af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek } 1792bc0fd8129626ff4e485388311b081e76d0f96795Ted Kremenek else if (isa<BreakStmt>(Term) || isa<ContinueStmt>(Term) || 1793bc0fd8129626ff4e485388311b081e76d0f96795Ted Kremenek isa<GotoStmt>(Term)) { 1794bc0fd8129626ff4e485388311b081e76d0f96795Ted Kremenek PathDiagnosticLocation L(Term, SM, PDB.LC); 1795be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek addEdgeToPath(PD.getActivePath(), PrevLoc, L, PDB.LC); 1796bc0fd8129626ff4e485388311b081e76d0f96795Ted Kremenek } 1797af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek } 1798af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek break; 1799af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek } 1800af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek } while (0); 1801af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1802af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek if (!NextNode) 1803af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek continue; 1804af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1805be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek // Since the active path may have been updated prior 1806be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek // to this point, query the active location context now. 1807be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek PathDiagnosticLocation &PrevLoc = 1808be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek PrevLocMap[PDB.LC->getCurrentStackFrame()]; 1809be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek 1810af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek // Add pieces from custom visitors. 1811af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek for (ArrayRef<BugReporterVisitor *>::iterator I = visitors.begin(), 1812af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek E = visitors.end(); 1813af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek I != E; ++I) { 1814cd389d8cc9abeffb1416b70dd58148e66e5d822bTed Kremenek if (PathDiagnosticPiece *p = (*I)->VisitNode(N, NextNode, PDB, *report)) { 1815be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek addEdgeToPath(PD.getActivePath(), PrevLoc, p->getLocation(), PDB.LC); 1816cd389d8cc9abeffb1416b70dd58148e66e5d822bTed Kremenek PD.getActivePath().push_front(p); 1817af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek updateStackPiecesWithMessage(p, CallStack); 1818af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek } 1819af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek } 1820af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek } 1821af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1822af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek return report->isValid(); 1823af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek} 1824af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1825f468fa16e37fc8fa6a915fe36aee8f0434709789Ted Kremenekconst Stmt *getLocStmt(PathDiagnosticLocation L) { 1826bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek if (!L.isValid()) 1827bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek return 0; 1828f468fa16e37fc8fa6a915fe36aee8f0434709789Ted Kremenek return L.asStmt(); 1829f468fa16e37fc8fa6a915fe36aee8f0434709789Ted Kremenek} 1830f468fa16e37fc8fa6a915fe36aee8f0434709789Ted Kremenek 1831f468fa16e37fc8fa6a915fe36aee8f0434709789Ted Kremenekconst Stmt *getStmtParent(const Stmt *S, ParentMap &PM) { 1832bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek if (!S) 1833bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek return 0; 1834a40983460cc3f8f583cd968ac2e4647dc30c83f5Ted Kremenek 1835a40983460cc3f8f583cd968ac2e4647dc30c83f5Ted Kremenek while (true) { 1836a40983460cc3f8f583cd968ac2e4647dc30c83f5Ted Kremenek S = PM.getParentIgnoreParens(S); 1837a40983460cc3f8f583cd968ac2e4647dc30c83f5Ted Kremenek 1838a40983460cc3f8f583cd968ac2e4647dc30c83f5Ted Kremenek if (!S) 1839a40983460cc3f8f583cd968ac2e4647dc30c83f5Ted Kremenek break; 1840a40983460cc3f8f583cd968ac2e4647dc30c83f5Ted Kremenek 1841a40983460cc3f8f583cd968ac2e4647dc30c83f5Ted Kremenek if (isa<ExprWithCleanups>(S)) 1842a40983460cc3f8f583cd968ac2e4647dc30c83f5Ted Kremenek continue; 1843a40983460cc3f8f583cd968ac2e4647dc30c83f5Ted Kremenek 1844a40983460cc3f8f583cd968ac2e4647dc30c83f5Ted Kremenek break; 1845a40983460cc3f8f583cd968ac2e4647dc30c83f5Ted Kremenek } 1846a40983460cc3f8f583cd968ac2e4647dc30c83f5Ted Kremenek 1847a40983460cc3f8f583cd968ac2e4647dc30c83f5Ted Kremenek return S; 1848bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek} 1849bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek 185015676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenekstatic bool isConditionForTerminator(const Stmt *S, const Stmt *Cond) { 185115676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek switch (S->getStmtClass()) { 185203194fb1bbf2b2d17ff7e3d61ddb9d73e9297fdcTed Kremenek case Stmt::BinaryOperatorClass: { 185303194fb1bbf2b2d17ff7e3d61ddb9d73e9297fdcTed Kremenek const BinaryOperator *BO = cast<BinaryOperator>(S); 185403194fb1bbf2b2d17ff7e3d61ddb9d73e9297fdcTed Kremenek if (!BO->isLogicalOp()) 185503194fb1bbf2b2d17ff7e3d61ddb9d73e9297fdcTed Kremenek return false; 185603194fb1bbf2b2d17ff7e3d61ddb9d73e9297fdcTed Kremenek return BO->getLHS() == Cond || BO->getRHS() == Cond; 185703194fb1bbf2b2d17ff7e3d61ddb9d73e9297fdcTed Kremenek } 1858a399f776ee29e099da33eaf7f9d585b4edc4b61dTed Kremenek case Stmt::IfStmtClass: 1859a399f776ee29e099da33eaf7f9d585b4edc4b61dTed Kremenek return cast<IfStmt>(S)->getCond() == Cond; 186015676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek case Stmt::ForStmtClass: 186115676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek return cast<ForStmt>(S)->getCond() == Cond; 186215676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek case Stmt::WhileStmtClass: 186315676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek return cast<WhileStmt>(S)->getCond() == Cond; 186415676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek case Stmt::DoStmtClass: 186515676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek return cast<DoStmt>(S)->getCond() == Cond; 186615676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek case Stmt::ChooseExprClass: 186715676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek return cast<ChooseExpr>(S)->getCond() == Cond; 186815676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek case Stmt::IndirectGotoStmtClass: 186915676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek return cast<IndirectGotoStmt>(S)->getTarget() == Cond; 187015676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek case Stmt::SwitchStmtClass: 187115676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek return cast<SwitchStmt>(S)->getCond() == Cond; 187215676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek case Stmt::BinaryConditionalOperatorClass: 187315676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek return cast<BinaryConditionalOperator>(S)->getCond() == Cond; 18748484b37a2b7720c016d27a672343b1c67bd2e731Ted Kremenek case Stmt::ConditionalOperatorClass: { 18758484b37a2b7720c016d27a672343b1c67bd2e731Ted Kremenek const ConditionalOperator *CO = cast<ConditionalOperator>(S); 18768484b37a2b7720c016d27a672343b1c67bd2e731Ted Kremenek return CO->getCond() == Cond || 18778484b37a2b7720c016d27a672343b1c67bd2e731Ted Kremenek CO->getLHS() == Cond || 18788484b37a2b7720c016d27a672343b1c67bd2e731Ted Kremenek CO->getRHS() == Cond; 18798484b37a2b7720c016d27a672343b1c67bd2e731Ted Kremenek } 188015676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek case Stmt::ObjCForCollectionStmtClass: 188115676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek return cast<ObjCForCollectionStmt>(S)->getElement() == Cond; 188215676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek default: 188315676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek return false; 188415676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek } 188515676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek} 188615676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek 188796b8134337883908fcc45484486fe200d6b3e32fTed Kremenekstatic bool isIncrementOrInitInForLoop(const Stmt *S, const Stmt *FL) { 1888e2f7337958f21802e98777f441fe20ef7ba2adffTed Kremenek const ForStmt *FS = dyn_cast<ForStmt>(FL); 188996b8134337883908fcc45484486fe200d6b3e32fTed Kremenek if (!FS) 1890e2f7337958f21802e98777f441fe20ef7ba2adffTed Kremenek return false; 189196b8134337883908fcc45484486fe200d6b3e32fTed Kremenek return FS->getInc() == S || FS->getInit() == S; 1892e2f7337958f21802e98777f441fe20ef7ba2adffTed Kremenek} 1893e2f7337958f21802e98777f441fe20ef7ba2adffTed Kremenek 189415676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenektypedef llvm::DenseSet<const PathDiagnosticCallPiece *> 189515676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek OptimizedCallsSet; 189615676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek 1897d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rosevoid PathPieces::dump() const { 1898d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose unsigned index = 0; 1899d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose for (PathPieces::const_iterator I = begin(), E = end(); I != E; ++I ) { 1900d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose llvm::errs() << "[" << index++ << "]"; 1901d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose 1902d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose switch ((*I)->getKind()) { 1903d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose case PathDiagnosticPiece::Call: 1904d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose llvm::errs() << " CALL\n--------------\n"; 1905d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose 1906d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose if (const Stmt *SLoc = getLocStmt((*I)->getLocation())) { 1907d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose SLoc->dump(); 1908d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose } else { 1909d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose const PathDiagnosticCallPiece *Call = cast<PathDiagnosticCallPiece>(*I); 1910d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose if (const NamedDecl *ND = dyn_cast<NamedDecl>(Call->getCallee())) 1911d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose llvm::errs() << *ND << "\n"; 1912d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose } 1913d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose break; 1914d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose case PathDiagnosticPiece::Event: 1915d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose llvm::errs() << " EVENT\n--------------\n"; 1916d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose llvm::errs() << (*I)->getString() << "\n"; 1917d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose if (const Stmt *SLoc = getLocStmt((*I)->getLocation())) { 1918d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose llvm::errs() << " ---- at ----\n"; 1919d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose SLoc->dump(); 1920d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose } 1921d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose break; 1922d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose case PathDiagnosticPiece::Macro: 1923d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose llvm::errs() << " MACRO\n--------------\n"; 1924d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose // FIXME: print which macro is being invoked. 1925d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose break; 1926d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose case PathDiagnosticPiece::ControlFlow: { 1927d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose const PathDiagnosticControlFlowPiece *CP = 1928d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose cast<PathDiagnosticControlFlowPiece>(*I); 1929d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose llvm::errs() << " CONTROL\n--------------\n"; 1930d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose 1931d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose if (const Stmt *s1Start = getLocStmt(CP->getStartLocation())) 1932d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose s1Start->dump(); 1933d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose else 1934d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose llvm::errs() << "NULL\n"; 1935d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose 1936d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose llvm::errs() << " ---- to ----\n"; 1937d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose 1938d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose if (const Stmt *s1End = getLocStmt(CP->getEndLocation())) 1939d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose s1End->dump(); 1940d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose else 1941d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose llvm::errs() << "NULL\n"; 1942d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose 1943d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose break; 1944d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose } 1945d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose } 1946d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose 1947d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose llvm::errs() << "\n"; 1948d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose } 1949d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose} 1950d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose 195115676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenekstatic bool optimizeEdges(PathPieces &path, SourceManager &SM, 195215676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek OptimizedCallsSet &OCS, 1953bb518991ce4298d8662235fc8cb13813f011c18dJordan Rose LocationContextMap &LCM) { 1954bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek bool hasChanges = false; 1955bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek const LocationContext *LC = LCM[&path]; 1956bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek assert(LC); 1957f468fa16e37fc8fa6a915fe36aee8f0434709789Ted Kremenek bool isFirst = true; 1958bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek 1959481da5554d03271b0d87b695449963f7728c5895Ted Kremenek for (PathPieces::iterator I = path.begin(), E = path.end(); I != E; ) { 196015676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek bool wasFirst = isFirst; 196115676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek isFirst = false; 1962bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek 1963bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek // Optimize subpaths. 1964bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek if (PathDiagnosticCallPiece *CallI = dyn_cast<PathDiagnosticCallPiece>(*I)){ 1965481da5554d03271b0d87b695449963f7728c5895Ted Kremenek // Record the fact that a call has been optimized so we only do the 1966481da5554d03271b0d87b695449963f7728c5895Ted Kremenek // effort once. 196715676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek if (!OCS.count(CallI)) { 1968bb518991ce4298d8662235fc8cb13813f011c18dJordan Rose while (optimizeEdges(CallI->path, SM, OCS, LCM)) {} 196915676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek OCS.insert(CallI); 197015676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek } 1971481da5554d03271b0d87b695449963f7728c5895Ted Kremenek ++I; 1972bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek continue; 1973bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek } 1974bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek 1975bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek // Pattern match the current piece and its successor. 1976bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek PathDiagnosticControlFlowPiece *PieceI = 1977bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek dyn_cast<PathDiagnosticControlFlowPiece>(*I); 1978bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek 1979481da5554d03271b0d87b695449963f7728c5895Ted Kremenek if (!PieceI) { 1980481da5554d03271b0d87b695449963f7728c5895Ted Kremenek ++I; 1981bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek continue; 1982481da5554d03271b0d87b695449963f7728c5895Ted Kremenek } 1983bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek 1984bb518991ce4298d8662235fc8cb13813f011c18dJordan Rose ParentMap &PM = LC->getParentMap(); 1985f468fa16e37fc8fa6a915fe36aee8f0434709789Ted Kremenek const Stmt *s1Start = getLocStmt(PieceI->getStartLocation()); 1986f468fa16e37fc8fa6a915fe36aee8f0434709789Ted Kremenek const Stmt *s1End = getLocStmt(PieceI->getEndLocation()); 1987f468fa16e37fc8fa6a915fe36aee8f0434709789Ted Kremenek const Stmt *level1 = getStmtParent(s1Start, PM); 1988f468fa16e37fc8fa6a915fe36aee8f0434709789Ted Kremenek const Stmt *level2 = getStmtParent(s1End, PM); 1989f468fa16e37fc8fa6a915fe36aee8f0434709789Ted Kremenek 199015676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek if (wasFirst) { 1991f4bbb1d8c2aa8b6630110827361ee0655e731548Ted Kremenek wasFirst = false; 1992f4bbb1d8c2aa8b6630110827361ee0655e731548Ted Kremenek 1993a399f776ee29e099da33eaf7f9d585b4edc4b61dTed Kremenek // If the first edge (in isolation) is just a transition from 1994a399f776ee29e099da33eaf7f9d585b4edc4b61dTed Kremenek // an expression to a parent expression then eliminate that edge. 1995a399f776ee29e099da33eaf7f9d585b4edc4b61dTed Kremenek if (level1 && level2 && level2 == PM.getParent(level1)) { 1996f468fa16e37fc8fa6a915fe36aee8f0434709789Ted Kremenek path.erase(I); 1997f468fa16e37fc8fa6a915fe36aee8f0434709789Ted Kremenek // Since we are erasing the current edge at the start of the 1998f468fa16e37fc8fa6a915fe36aee8f0434709789Ted Kremenek // path, just return now so we start analyzing the start of the path 1999f468fa16e37fc8fa6a915fe36aee8f0434709789Ted Kremenek // again. 2000f468fa16e37fc8fa6a915fe36aee8f0434709789Ted Kremenek return true; 2001f468fa16e37fc8fa6a915fe36aee8f0434709789Ted Kremenek } 200296b8134337883908fcc45484486fe200d6b3e32fTed Kremenek 200396b8134337883908fcc45484486fe200d6b3e32fTed Kremenek // If the first edge (in isolation) is a transition from the 200496b8134337883908fcc45484486fe200d6b3e32fTed Kremenek // initialization or increment in a for loop then remove it. 200596b8134337883908fcc45484486fe200d6b3e32fTed Kremenek if (level1 && isIncrementOrInitInForLoop(s1Start, level1)) { 200696b8134337883908fcc45484486fe200d6b3e32fTed Kremenek path.erase(I); 200796b8134337883908fcc45484486fe200d6b3e32fTed Kremenek return true; 200896b8134337883908fcc45484486fe200d6b3e32fTed Kremenek } 2009f468fa16e37fc8fa6a915fe36aee8f0434709789Ted Kremenek } 2010f468fa16e37fc8fa6a915fe36aee8f0434709789Ted Kremenek 201115676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek PathPieces::iterator NextI = I; ++NextI; 201215676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek if (NextI == E) 201315676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek break; 201415676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek 2015bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek PathDiagnosticControlFlowPiece *PieceNextI = 2016bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek dyn_cast<PathDiagnosticControlFlowPiece>(*NextI); 2017bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek 2018481da5554d03271b0d87b695449963f7728c5895Ted Kremenek if (!PieceNextI) { 2019481da5554d03271b0d87b695449963f7728c5895Ted Kremenek ++I; 2020bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek continue; 2021481da5554d03271b0d87b695449963f7728c5895Ted Kremenek } 2022bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek 2023f468fa16e37fc8fa6a915fe36aee8f0434709789Ted Kremenek const Stmt *s2Start = getLocStmt(PieceNextI->getStartLocation()); 2024f468fa16e37fc8fa6a915fe36aee8f0434709789Ted Kremenek const Stmt *s2End = getLocStmt(PieceNextI->getEndLocation()); 2025f468fa16e37fc8fa6a915fe36aee8f0434709789Ted Kremenek const Stmt *level3 = getStmtParent(s2Start, PM); 2026f468fa16e37fc8fa6a915fe36aee8f0434709789Ted Kremenek const Stmt *level4 = getStmtParent(s2End, PM); 2027bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek 2028bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek // Rule I. 2029bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek // 2030bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek // If we have two consecutive control edges whose end/begin locations 2031481da5554d03271b0d87b695449963f7728c5895Ted Kremenek // are at the same level (e.g. statements or top-level expressions within 2032481da5554d03271b0d87b695449963f7728c5895Ted Kremenek // a compound statement, or siblings share a single ancestor expression), 2033481da5554d03271b0d87b695449963f7728c5895Ted Kremenek // then merge them if they have no interesting intermediate event. 2034bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek // 2035bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek // For example: 2036bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek // 2037bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek // (1.1 -> 1.2) -> (1.2 -> 1.3) becomes (1.1 -> 1.3) because the common 2038481da5554d03271b0d87b695449963f7728c5895Ted Kremenek // parent is '1'. Here 'x.y.z' represents the hierarchy of statements. 2039bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek // 2040bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek // NOTE: this will be limited later in cases where we add barriers 2041bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek // to prevent this optimization. 2042f468fa16e37fc8fa6a915fe36aee8f0434709789Ted Kremenek // 2043481da5554d03271b0d87b695449963f7728c5895Ted Kremenek if (level1 && level1 == level2 && level1 == level3 && level1 == level4) { 2044bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek PieceI->setEndLocation(PieceNextI->getEndLocation()); 2045bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek path.erase(NextI); 2046bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek hasChanges = true; 2047bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek continue; 2048bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek } 2049b9e13d555fc9f3e5515e2b1fa6f720e6f10bb076Ted Kremenek 2050b9e13d555fc9f3e5515e2b1fa6f720e6f10bb076Ted Kremenek // Rule II. 2051b9e13d555fc9f3e5515e2b1fa6f720e6f10bb076Ted Kremenek // 2052a399f776ee29e099da33eaf7f9d585b4edc4b61dTed Kremenek // Eliminate edges between subexpressions and parent expressions 2053a399f776ee29e099da33eaf7f9d585b4edc4b61dTed Kremenek // when the subexpression is consumed. 2054f468fa16e37fc8fa6a915fe36aee8f0434709789Ted Kremenek // 2055f468fa16e37fc8fa6a915fe36aee8f0434709789Ted Kremenek // NOTE: this will be limited later in cases where we add barriers 2056f468fa16e37fc8fa6a915fe36aee8f0434709789Ted Kremenek // to prevent this optimization. 2057f468fa16e37fc8fa6a915fe36aee8f0434709789Ted Kremenek // 205896b8134337883908fcc45484486fe200d6b3e32fTed Kremenek if (s1End && s1End == s2Start && level2) { 205996b8134337883908fcc45484486fe200d6b3e32fTed Kremenek if (isIncrementOrInitInForLoop(s1End, level2) || 206096b8134337883908fcc45484486fe200d6b3e32fTed Kremenek (isa<Expr>(s1End) && PM.isConsumedExpr(cast<Expr>(s1End)) && 206196b8134337883908fcc45484486fe200d6b3e32fTed Kremenek !isConditionForTerminator(level2, s1End))) 206296b8134337883908fcc45484486fe200d6b3e32fTed Kremenek { 206396b8134337883908fcc45484486fe200d6b3e32fTed Kremenek PieceI->setEndLocation(PieceNextI->getEndLocation()); 206496b8134337883908fcc45484486fe200d6b3e32fTed Kremenek path.erase(NextI); 206596b8134337883908fcc45484486fe200d6b3e32fTed Kremenek hasChanges = true; 206696b8134337883908fcc45484486fe200d6b3e32fTed Kremenek continue; 206796b8134337883908fcc45484486fe200d6b3e32fTed Kremenek } 2068f468fa16e37fc8fa6a915fe36aee8f0434709789Ted Kremenek } 2069481da5554d03271b0d87b695449963f7728c5895Ted Kremenek 2070e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek // Optimize edges for ObjC fast-enumeration loops. 2071e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek // 2072e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek // (X -> collection) -> (collection -> element) 2073e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek // 2074e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek // becomes: 2075e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek // 2076e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek // (X -> element) 2077e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek if (s1End == s2Start) { 2078e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek const ObjCForCollectionStmt *FS = 2079e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek dyn_cast_or_null<ObjCForCollectionStmt>(level3); 2080e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek if (FS && FS->getCollection()->IgnoreParens() == s2Start && 2081e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek s2End == FS->getElement()) { 2082e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek PieceI->setEndLocation(PieceNextI->getEndLocation()); 2083e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek path.erase(NextI); 2084e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek hasChanges = true; 2085e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek continue; 2086e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek } 2087e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek } 2088e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek 2089481da5554d03271b0d87b695449963f7728c5895Ted Kremenek // No changes at this index? Move to the next one. 2090481da5554d03271b0d87b695449963f7728c5895Ted Kremenek ++I; 2091bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek } 2092bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek 2093bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek // No changes. 2094bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek return hasChanges; 2095bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek} 2096bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek 2097a40983460cc3f8f583cd968ac2e4647dc30c83f5Ted Kremenekstatic void adjustBranchEdges(PathPieces &pieces, LocationContextMap &LCM, 2098aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek SourceManager &SM) { 2099aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek // Retrieve the parent map for this path. 2100aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek const LocationContext *LC = LCM[&pieces]; 2101aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek ParentMap &PM = LC->getParentMap(); 2102aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek PathPieces::iterator Prev = pieces.end(); 2103aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek for (PathPieces::iterator I = pieces.begin(), E = pieces.end(); I != E; 2104aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek Prev = I, ++I) { 2105aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek // Adjust edges in subpaths. 2106aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek if (PathDiagnosticCallPiece *Call = dyn_cast<PathDiagnosticCallPiece>(*I)) { 2107a40983460cc3f8f583cd968ac2e4647dc30c83f5Ted Kremenek adjustBranchEdges(Call->path, LCM, SM); 2108aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek continue; 2109aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek } 2110aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek 2111aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek PathDiagnosticControlFlowPiece *PieceI = 2112aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek dyn_cast<PathDiagnosticControlFlowPiece>(*I); 2113aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek 2114aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek if (!PieceI) 2115aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek continue; 2116aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek 2117aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek // We are looking at two edges. Is the second one incident 2118a40983460cc3f8f583cd968ac2e4647dc30c83f5Ted Kremenek // on an expression (or subexpression) of a branch condition. 2119aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek const Stmt *Dst = getLocStmt(PieceI->getEndLocation()); 2120aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek const Stmt *Src = getLocStmt(PieceI->getStartLocation()); 2121aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek 2122aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek if (!Dst || !Src) 2123aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek continue; 2124aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek 2125a40983460cc3f8f583cd968ac2e4647dc30c83f5Ted Kremenek const Stmt *Branch = 0; 2126aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek const Stmt *S = Dst; 2127a40983460cc3f8f583cd968ac2e4647dc30c83f5Ted Kremenek while (const Stmt *Parent = getStmtParent(S, PM)) { 21288841c532f217d938f47f4feaa3707b929cd71181Ted Kremenek if (const ForStmt *FS = dyn_cast<ForStmt>(Parent)) { 21298841c532f217d938f47f4feaa3707b929cd71181Ted Kremenek if (FS->getCond()->IgnoreParens() == S) 2130a40983460cc3f8f583cd968ac2e4647dc30c83f5Ted Kremenek Branch = FS; 21318841c532f217d938f47f4feaa3707b929cd71181Ted Kremenek break; 21328841c532f217d938f47f4feaa3707b929cd71181Ted Kremenek } 21338841c532f217d938f47f4feaa3707b929cd71181Ted Kremenek if (const WhileStmt *WS = dyn_cast<WhileStmt>(Parent)) { 21348841c532f217d938f47f4feaa3707b929cd71181Ted Kremenek if (WS->getCond()->IgnoreParens() == S) 2135a40983460cc3f8f583cd968ac2e4647dc30c83f5Ted Kremenek Branch = WS; 2136a40983460cc3f8f583cd968ac2e4647dc30c83f5Ted Kremenek break; 2137a40983460cc3f8f583cd968ac2e4647dc30c83f5Ted Kremenek } 2138a40983460cc3f8f583cd968ac2e4647dc30c83f5Ted Kremenek if (const IfStmt *IS = dyn_cast<IfStmt>(Parent)) { 2139a40983460cc3f8f583cd968ac2e4647dc30c83f5Ted Kremenek if (IS->getCond()->IgnoreParens() == S) 2140a40983460cc3f8f583cd968ac2e4647dc30c83f5Ted Kremenek Branch = IS; 2141aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek break; 2142aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek } 2143e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek if (const ObjCForCollectionStmt *OFS = 2144e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek dyn_cast<ObjCForCollectionStmt>(Parent)) { 2145e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek if (OFS->getElement() == S) 2146e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek Branch = OFS; 2147e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek break; 2148e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek } 2149e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek 2150aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek S = Parent; 2151aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek } 2152aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek 2153a40983460cc3f8f583cd968ac2e4647dc30c83f5Ted Kremenek // If 'Branch' is non-null we have found a match where we have an edge 2154a40983460cc3f8f583cd968ac2e4647dc30c83f5Ted Kremenek // incident on the condition of a if/for/while statement. 2155a40983460cc3f8f583cd968ac2e4647dc30c83f5Ted Kremenek if (!Branch) 2156aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek continue; 2157aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek 2158a40983460cc3f8f583cd968ac2e4647dc30c83f5Ted Kremenek // If the current source of the edge is the if/for/while, then there is 21598841c532f217d938f47f4feaa3707b929cd71181Ted Kremenek // nothing left to be done. 2160a40983460cc3f8f583cd968ac2e4647dc30c83f5Ted Kremenek if (Src == Branch) 2161aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek continue; 2162aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek 2163aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek // Now look at the previous edge. We want to know if this was in the same 2164aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek // "level" as the for statement. 2165a40983460cc3f8f583cd968ac2e4647dc30c83f5Ted Kremenek const Stmt *SrcParent = getStmtParent(Src, PM); 2166a40983460cc3f8f583cd968ac2e4647dc30c83f5Ted Kremenek const Stmt *BranchParent = getStmtParent(Branch, PM); 2167a40983460cc3f8f583cd968ac2e4647dc30c83f5Ted Kremenek if (SrcParent && SrcParent == BranchParent) { 2168a40983460cc3f8f583cd968ac2e4647dc30c83f5Ted Kremenek PathDiagnosticLocation L(Branch, SM, LC); 2169aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek bool needsEdge = true; 2170aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek 2171aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek if (Prev != E) { 2172aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek if (PathDiagnosticControlFlowPiece *P = 2173aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek dyn_cast<PathDiagnosticControlFlowPiece>(*Prev)) { 2174aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek const Stmt *PrevSrc = getLocStmt(P->getStartLocation()); 2175aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek if (PrevSrc) { 2176a40983460cc3f8f583cd968ac2e4647dc30c83f5Ted Kremenek const Stmt *PrevSrcParent = getStmtParent(PrevSrc, PM); 2177a40983460cc3f8f583cd968ac2e4647dc30c83f5Ted Kremenek if (PrevSrcParent == BranchParent) { 2178aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek P->setEndLocation(L); 2179aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek needsEdge = false; 2180aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek } 2181aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek } 2182aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek } 2183aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek } 2184aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek 2185aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek if (needsEdge) { 2186aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek PathDiagnosticControlFlowPiece *P = 2187aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek new PathDiagnosticControlFlowPiece(PieceI->getStartLocation(), L); 2188aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek pieces.insert(I, P); 2189aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek } 2190aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek 2191aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek PieceI->setStartLocation(L); 2192aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek } 2193aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek } 2194aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek} 2195aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek 21965fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek//===----------------------------------------------------------------------===// 21973106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// Methods for BugType and subclasses. 21983106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 2199404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios KyrtzidisBugType::~BugType() { } 2200404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis 22013106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenekvoid BugType::FlushReports(BugReporter &BR) {} 22023106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 220399ba9e3bd70671f3441fb974895f226a83ce0e66David Blaikievoid BuiltinBug::anchor() {} 220499ba9e3bd70671f3441fb974895f226a83ce0e66David Blaikie 22053106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 22063106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// Methods for BugReport and subclasses. 22073106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 2208e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks 220999ba9e3bd70671f3441fb974895f226a83ce0e66David Blaikievoid BugReport::NodeResolver::anchor() {} 221099ba9e3bd70671f3441fb974895f226a83ce0e66David Blaikie 22118e6431adab313e283a992698f6fc7afe62420999Anna Zaksvoid BugReport::addVisitor(BugReporterVisitor* visitor) { 22128e6431adab313e283a992698f6fc7afe62420999Anna Zaks if (!visitor) 22138e6431adab313e283a992698f6fc7afe62420999Anna Zaks return; 22148e6431adab313e283a992698f6fc7afe62420999Anna Zaks 22158e6431adab313e283a992698f6fc7afe62420999Anna Zaks llvm::FoldingSetNodeID ID; 22168e6431adab313e283a992698f6fc7afe62420999Anna Zaks visitor->Profile(ID); 22178e6431adab313e283a992698f6fc7afe62420999Anna Zaks void *InsertPos; 22188e6431adab313e283a992698f6fc7afe62420999Anna Zaks 22198e6431adab313e283a992698f6fc7afe62420999Anna Zaks if (CallbacksSet.FindNodeOrInsertPos(ID, InsertPos)) { 22208e6431adab313e283a992698f6fc7afe62420999Anna Zaks delete visitor; 22218e6431adab313e283a992698f6fc7afe62420999Anna Zaks return; 22228e6431adab313e283a992698f6fc7afe62420999Anna Zaks } 22238e6431adab313e283a992698f6fc7afe62420999Anna Zaks 22248e6431adab313e283a992698f6fc7afe62420999Anna Zaks CallbacksSet.InsertNode(visitor, InsertPos); 22253bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose Callbacks.push_back(visitor); 22263bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose ++ConfigurationChangeToken; 22278e6431adab313e283a992698f6fc7afe62420999Anna Zaks} 22288e6431adab313e283a992698f6fc7afe62420999Anna Zaks 22298e6431adab313e283a992698f6fc7afe62420999Anna ZaksBugReport::~BugReport() { 22308e6431adab313e283a992698f6fc7afe62420999Anna Zaks for (visitor_iterator I = visitor_begin(), E = visitor_end(); I != E; ++I) { 2231dc757b049796949e4b11646445a6598f0bdabd7aAnna Zaks delete *I; 22328e6431adab313e283a992698f6fc7afe62420999Anna Zaks } 2233c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek while (!interestingSymbols.empty()) { 2234c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek popInterestingSymbolsAndRegions(); 2235c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek } 22368e6431adab313e283a992698f6fc7afe62420999Anna Zaks} 2237e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks 223807189521a15d9c088216b943649cb9fe231cbb57Ted Kremenekconst Decl *BugReport::getDeclWithIssue() const { 223907189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek if (DeclWithIssue) 224007189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek return DeclWithIssue; 224107189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek 224207189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek const ExplodedNode *N = getErrorNode(); 224307189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek if (!N) 224407189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek return 0; 224507189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek 224607189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek const LocationContext *LC = N->getLocationContext(); 224707189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek return LC->getCurrentStackFrame()->getDecl(); 224807189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek} 224907189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek 2250e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaksvoid BugReport::Profile(llvm::FoldingSetNodeID& hash) const { 2251e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks hash.AddPointer(&BT); 2252e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks hash.AddString(Description); 225397bfb558f69c09b01a5c1510f08dc91eb62329a7Anna Zaks PathDiagnosticLocation UL = getUniqueingLocation(); 225497bfb558f69c09b01a5c1510f08dc91eb62329a7Anna Zaks if (UL.isValid()) { 225597bfb558f69c09b01a5c1510f08dc91eb62329a7Anna Zaks UL.Profile(hash); 2256ca8e36eb637e232475ef31c3f22d5da907390917Anna Zaks } else if (Location.isValid()) { 2257590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks Location.Profile(hash); 2258590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks } else { 2259590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks assert(ErrorNode); 2260590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks hash.AddPointer(GetCurrentOrPreviousStmt(ErrorNode)); 2261590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks } 2262e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks 2263e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks for (SmallVectorImpl<SourceRange>::const_iterator I = 2264e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks Ranges.begin(), E = Ranges.end(); I != E; ++I) { 2265e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks const SourceRange range = *I; 2266e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks if (!range.isValid()) 2267e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks continue; 2268e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks hash.AddInteger(range.getBegin().getRawEncoding()); 2269e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks hash.AddInteger(range.getEnd().getRawEncoding()); 2270e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks } 2271e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks} 22723106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 227376aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenekvoid BugReport::markInteresting(SymbolRef sym) { 227476aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek if (!sym) 227576aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek return; 22763bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose 22773bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose // If the symbol wasn't already in our set, note a configuration change. 2278c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek if (getInterestingSymbols().insert(sym).second) 22793bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose ++ConfigurationChangeToken; 22808ec588e2ac57311604cf80608c7d4b3fb3b022f7Jordy Rose 22818ec588e2ac57311604cf80608c7d4b3fb3b022f7Jordy Rose if (const SymbolMetadata *meta = dyn_cast<SymbolMetadata>(sym)) 2282c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek getInterestingRegions().insert(meta->getRegion()); 228376aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek} 228476aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek 228576aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenekvoid BugReport::markInteresting(const MemRegion *R) { 228676aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek if (!R) 228776aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek return; 22883bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose 22893bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose // If the base region wasn't already in our set, note a configuration change. 229076aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek R = R->getBaseRegion(); 2291c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek if (getInterestingRegions().insert(R).second) 22923bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose ++ConfigurationChangeToken; 22938ec588e2ac57311604cf80608c7d4b3fb3b022f7Jordy Rose 229476aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R)) 2295c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek getInterestingSymbols().insert(SR->getSymbol()); 229676aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek} 229776aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek 229876aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenekvoid BugReport::markInteresting(SVal V) { 229976aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek markInteresting(V.getAsRegion()); 230076aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek markInteresting(V.getAsSymbol()); 230176aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek} 230276aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek 230380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaksvoid BugReport::markInteresting(const LocationContext *LC) { 230480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks if (!LC) 230580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks return; 230680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks InterestingLocationContexts.insert(LC); 230780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks} 230880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks 2309c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenekbool BugReport::isInteresting(SVal V) { 231076aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek return isInteresting(V.getAsRegion()) || isInteresting(V.getAsSymbol()); 231176aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek} 231276aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek 2313c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenekbool BugReport::isInteresting(SymbolRef sym) { 231476aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek if (!sym) 231576aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek return false; 23168ec588e2ac57311604cf80608c7d4b3fb3b022f7Jordy Rose // We don't currently consider metadata symbols to be interesting 23178ec588e2ac57311604cf80608c7d4b3fb3b022f7Jordy Rose // even if we know their region is interesting. Is that correct behavior? 2318c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek return getInterestingSymbols().count(sym); 231976aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek} 232076aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek 2321c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenekbool BugReport::isInteresting(const MemRegion *R) { 232276aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek if (!R) 232376aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek return false; 232476aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek R = R->getBaseRegion(); 2325c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek bool b = getInterestingRegions().count(R); 232676aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek if (b) 232776aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek return true; 232876aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R)) 2329c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek return getInterestingSymbols().count(SR->getSymbol()); 233076aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek return false; 233176aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek} 2332c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek 233380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaksbool BugReport::isInteresting(const LocationContext *LC) { 233480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks if (!LC) 233580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks return false; 233680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks return InterestingLocationContexts.count(LC); 233780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks} 233880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks 2339c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenekvoid BugReport::lazyInitializeInterestingSets() { 2340c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek if (interestingSymbols.empty()) { 2341c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek interestingSymbols.push_back(new Symbols()); 2342c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek interestingRegions.push_back(new Regions()); 2343c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek } 2344c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek} 2345c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek 2346c4bac8e376b98d633bb00ee5f510d5e58449753cTed KremenekBugReport::Symbols &BugReport::getInterestingSymbols() { 2347c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek lazyInitializeInterestingSets(); 2348c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek return *interestingSymbols.back(); 2349c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek} 2350c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek 2351c4bac8e376b98d633bb00ee5f510d5e58449753cTed KremenekBugReport::Regions &BugReport::getInterestingRegions() { 2352c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek lazyInitializeInterestingSets(); 2353c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek return *interestingRegions.back(); 2354c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek} 2355c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek 2356c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenekvoid BugReport::pushInterestingSymbolsAndRegions() { 2357c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek interestingSymbols.push_back(new Symbols(getInterestingSymbols())); 2358c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek interestingRegions.push_back(new Regions(getInterestingRegions())); 2359c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek} 2360c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek 2361c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenekvoid BugReport::popInterestingSymbolsAndRegions() { 2362c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek delete interestingSymbols.back(); 2363c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek interestingSymbols.pop_back(); 2364c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek delete interestingRegions.back(); 2365c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek interestingRegions.pop_back(); 2366c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek} 236776aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek 23689c378f705405d37f49795d5e915989de774fe11fTed Kremenekconst Stmt *BugReport::getStmt() const { 2369e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks if (!ErrorNode) 2370e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks return 0; 2371e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks 2372212f6d3b5fb3fa55ba1e40671cfc336430abc8ddTom Care ProgramPoint ProgP = ErrorNode->getLocation(); 23735f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek const Stmt *S = NULL; 23741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 23757a95de68c093991047ed8d339479ccad51b88663David Blaikie if (Optional<BlockEntrance> BE = ProgP.getAs<BlockEntrance>()) { 2376fafd3834754d2093e0ad7a1c005860fd527ecb7fZhongxing Xu CFGBlock &Exit = ProgP.getLocationContext()->getCFG()->getExit(); 237750d5bc4e3b53eb8bb4ebf198f1213348a3fa0f38Zhongxing Xu if (BE->getBlock() == &Exit) 2378212f6d3b5fb3fa55ba1e40671cfc336430abc8ddTom Care S = GetPreviousStmt(ErrorNode); 23793106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 23805f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek if (!S) 23810f8579274a010f360a371b53101859d9d6052314Anna Zaks S = PathDiagnosticLocation::getStmt(ErrorNode); 23821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 23831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return S; 23843106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 23853106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 2386640ccf071076e684713cc3c3276bb51982bff607Argyrios Kyrtzidisstd::pair<BugReport::ranges_iterator, BugReport::ranges_iterator> 2387e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna ZaksBugReport::getRanges() { 2388e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks // If no custom ranges, add the range of the statement corresponding to 2389e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks // the error node. 2390e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks if (Ranges.empty()) { 2391e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks if (const Expr *E = dyn_cast_or_null<Expr>(getStmt())) 2392e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks addRange(E->getSourceRange()); 2393e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks else 2394e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks return std::make_pair(ranges_iterator(), ranges_iterator()); 2395e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks } 2396e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks 239714924267950e75c6c1f6fcea39fa507b7168bc39Anna Zaks // User-specified absence of range info. 239814924267950e75c6c1f6fcea39fa507b7168bc39Anna Zaks if (Ranges.size() == 1 && !Ranges.begin()->isValid()) 239914924267950e75c6c1f6fcea39fa507b7168bc39Anna Zaks return std::make_pair(ranges_iterator(), ranges_iterator()); 240014924267950e75c6c1f6fcea39fa507b7168bc39Anna Zaks 2401e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks return std::make_pair(Ranges.begin(), Ranges.end()); 24023106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 24033106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 2404590dd8e0959d8df5621827768987c4792b74fc06Anna ZaksPathDiagnosticLocation BugReport::getLocation(const SourceManager &SM) const { 2405b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks if (ErrorNode) { 2406590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks assert(!Location.isValid() && 2407b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks "Either Location or ErrorNode should be specified but not both."); 24080f8579274a010f360a371b53101859d9d6052314Anna Zaks return PathDiagnosticLocation::createEndOfPath(ErrorNode, SM); 2409b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks } else { 2410b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks assert(Location.isValid()); 2411b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks return Location; 2412b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks } 2413b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks 2414590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks return PathDiagnosticLocation(); 24153106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 24163106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 24173106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 24183106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// Methods for BugReporter and subclasses. 24193106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 24203106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 24214a5f724538cbc275370c9504e8169ce92503256cBenjamin KramerBugReportEquivClass::~BugReportEquivClass() { } 2422a2f4ec0df645fc249d2945beef9653f03b175417Zhongxing XuGRBugReporter::~GRBugReporter() { } 24233106198188ac6eb2753f1764d5c28376b0b76351Ted KremenekBugReporterData::~BugReporterData() {} 24243106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 242538b02b912e1a55c912f603c4369431264d36a381Zhongxing XuExplodedGraph &GRBugReporter::getGraph() { return Eng.getGraph(); } 24263106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 242718c66fdc3c4008d335885695fe36fb5353c5f672Ted KremenekProgramStateManager& 24283106198188ac6eb2753f1764d5c28376b0b76351Ted KremenekGRBugReporter::getStateManager() { return Eng.getStateManager(); } 24293106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 24303b030a28cda2b953758507769c1d436bec5ec45eAnna ZaksBugReporter::~BugReporter() { 24313b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks FlushReports(); 24323b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks 24333b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks // Free the bug reports we are tracking. 24343b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks typedef std::vector<BugReportEquivClass *> ContTy; 24353b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks for (ContTy::iterator I = EQClassesVector.begin(), E = EQClassesVector.end(); 24363b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks I != E; ++I) { 24373b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks delete *I; 24383b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks } 24393b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks} 24403106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 24413106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenekvoid BugReporter::FlushReports() { 24423106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (BugTypes.isEmpty()) 24433106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek return; 24443106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 24453106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // First flush the warnings for each BugType. This may end up creating new 2446404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // warnings and new BugTypes. 2447404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // FIXME: Only NSErrorChecker needs BugType's FlushReports. 2448404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // Turn NSErrorChecker into a proper checker and remove this. 24495f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<const BugType*, 16> bugTypes; 24503106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek for (BugTypesTy::iterator I=BugTypes.begin(), E=BugTypes.end(); I!=E; ++I) 2451404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis bugTypes.push_back(*I); 24525f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner for (SmallVector<const BugType*, 16>::iterator 2453404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis I = bugTypes.begin(), E = bugTypes.end(); I != E; ++I) 24543106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek const_cast<BugType*>(*I)->FlushReports(*this); 24553106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 2456d015f4febe85d3e3340172d70042840c51bbd836Anna Zaks // We need to flush reports in deterministic order to ensure the order 2457d015f4febe85d3e3340172d70042840c51bbd836Anna Zaks // of the reports is consistent between runs. 24580eb6c37dd4e4ad8fa2363003dea270f9fd6c2969Anna Zaks typedef std::vector<BugReportEquivClass *> ContVecTy; 24590eb6c37dd4e4ad8fa2363003dea270f9fd6c2969Anna Zaks for (ContVecTy::iterator EI=EQClassesVector.begin(), EE=EQClassesVector.end(); 24600eb6c37dd4e4ad8fa2363003dea270f9fd6c2969Anna Zaks EI != EE; ++EI){ 24610eb6c37dd4e4ad8fa2363003dea270f9fd6c2969Anna Zaks BugReportEquivClass& EQ = **EI; 2462404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis FlushReport(EQ); 24633106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 24643106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 2465404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // BugReporter owns and deletes only BugTypes created implicitly through 2466404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // EmitBasicReport. 2467404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // FIXME: There are leaks from checkers that assume that the BugTypes they 2468404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // create will be destroyed by the BugReporter. 2469404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis for (llvm::StringMap<BugType*>::iterator 2470404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis I = StrBugTypes.begin(), E = StrBugTypes.end(); I != E; ++I) 2471404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis delete I->second; 2472404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis 24733106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Remove all references to the BugType objects. 24743baf672378f105602d2b12f03f00277ae1936fe9Ted Kremenek BugTypes = F.getEmptySet(); 24753106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 24763106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 24773106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 24783106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// PathDiagnostics generation. 24793106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 24803106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 24811efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rosenamespace { 24821efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose/// A wrapper around a report graph, which contains only a single path, and its 24831efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose/// node maps. 24841efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Roseclass ReportGraph { 24851efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rosepublic: 24861efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose InterExplodedGraphMap BackMap; 2487228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose OwningPtr<ExplodedGraph> Graph; 2488228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose const ExplodedNode *ErrorNode; 24891efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose size_t Index; 24901efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose}; 24911efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose 24921efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose/// A wrapper around a trimmed graph and its node maps. 24931efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Roseclass TrimmedGraph { 24941efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose InterExplodedGraphMap InverseMap; 24952110350909701fcd6b55c636e24a675f0a905feaJordan Rose 24962110350909701fcd6b55c636e24a675f0a905feaJordan Rose typedef llvm::DenseMap<const ExplodedNode *, unsigned> PriorityMapTy; 24972110350909701fcd6b55c636e24a675f0a905feaJordan Rose PriorityMapTy PriorityMap; 24982110350909701fcd6b55c636e24a675f0a905feaJordan Rose 2499228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose typedef std::pair<const ExplodedNode *, size_t> NodeIndexPair; 2500228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose SmallVector<NodeIndexPair, 32> ReportNodes; 2501228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose 25021efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose OwningPtr<ExplodedGraph> G; 2503228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose 2504228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose /// A helper class for sorting ExplodedNodes by priority. 2505228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose template <bool Descending> 2506228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose class PriorityCompare { 2507228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose const PriorityMapTy &PriorityMap; 2508228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose 2509228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose public: 2510228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose PriorityCompare(const PriorityMapTy &M) : PriorityMap(M) {} 2511228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose 2512228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose bool operator()(const ExplodedNode *LHS, const ExplodedNode *RHS) const { 2513228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose PriorityMapTy::const_iterator LI = PriorityMap.find(LHS); 2514228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose PriorityMapTy::const_iterator RI = PriorityMap.find(RHS); 2515228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose PriorityMapTy::const_iterator E = PriorityMap.end(); 2516228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose 2517228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose if (LI == E) 2518228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose return Descending; 2519228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose if (RI == E) 2520228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose return !Descending; 2521228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose 2522228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose return Descending ? LI->second > RI->second 2523228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose : LI->second < RI->second; 2524228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose } 2525228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose 2526228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose bool operator()(const NodeIndexPair &LHS, const NodeIndexPair &RHS) const { 2527228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose return (*this)(LHS.first, RHS.first); 2528228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose } 2529228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose }; 2530228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose 25311efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rosepublic: 25321efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose TrimmedGraph(const ExplodedGraph *OriginalGraph, 25332110350909701fcd6b55c636e24a675f0a905feaJordan Rose ArrayRef<const ExplodedNode *> Nodes); 25341efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose 2535228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose bool popNextReportGraph(ReportGraph &GraphWrapper); 25361efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose}; 25371efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose} 25381efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose 25392110350909701fcd6b55c636e24a675f0a905feaJordan RoseTrimmedGraph::TrimmedGraph(const ExplodedGraph *OriginalGraph, 25402110350909701fcd6b55c636e24a675f0a905feaJordan Rose ArrayRef<const ExplodedNode *> Nodes) { 25412110350909701fcd6b55c636e24a675f0a905feaJordan Rose // The trimmed graph is created in the body of the constructor to ensure 25422110350909701fcd6b55c636e24a675f0a905feaJordan Rose // that the DenseMaps have been initialized already. 2543228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose InterExplodedGraphMap ForwardMap; 25440f3a34fb7fea37ebfbcba8b400ccb697b9559b49Jordan Rose G.reset(OriginalGraph->trim(Nodes, &ForwardMap, &InverseMap)); 25451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 25463106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Find the (first) error node in the trimmed graph. We just need to consult 25471efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose // the node map which maps from nodes in the original graph to nodes 25483106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // in the new graph. 2549228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose llvm::SmallPtrSet<const ExplodedNode *, 32> RemainingNodes; 25503106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 25511efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose for (unsigned i = 0, count = Nodes.size(); i < count; ++i) { 2552228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose if (const ExplodedNode *NewNode = ForwardMap.lookup(Nodes[i])) { 2553228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose ReportNodes.push_back(std::make_pair(NewNode, i)); 2554228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose RemainingNodes.insert(NewNode); 25553106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 255640406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek } 25571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2558228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose assert(!RemainingNodes.empty() && "No error node found in the trimmed graph"); 2559228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose 2560228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose // Perform a forward BFS to find all the shortest paths. 2561228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose std::queue<const ExplodedNode *> WS; 2562228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose 2563228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose assert(G->num_roots() == 1); 2564228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose WS.push(*G->roots_begin()); 2565228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose unsigned Priority = 0; 25663106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 25673106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek while (!WS.empty()) { 2568228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose const ExplodedNode *Node = WS.front(); 25693106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek WS.pop(); 25701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 25712110350909701fcd6b55c636e24a675f0a905feaJordan Rose PriorityMapTy::iterator PriorityEntry; 25722110350909701fcd6b55c636e24a675f0a905feaJordan Rose bool IsNew; 25732110350909701fcd6b55c636e24a675f0a905feaJordan Rose llvm::tie(PriorityEntry, IsNew) = 25742110350909701fcd6b55c636e24a675f0a905feaJordan Rose PriorityMap.insert(std::make_pair(Node, Priority)); 2575228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose ++Priority; 25761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 25772110350909701fcd6b55c636e24a675f0a905feaJordan Rose if (!IsNew) { 25782110350909701fcd6b55c636e24a675f0a905feaJordan Rose assert(PriorityEntry->second <= Priority); 25792110350909701fcd6b55c636e24a675f0a905feaJordan Rose continue; 25802110350909701fcd6b55c636e24a675f0a905feaJordan Rose } 25811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2582228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose if (RemainingNodes.erase(Node)) 2583228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose if (RemainingNodes.empty()) 2584228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose break; 2585a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose 2586228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose for (ExplodedNode::const_pred_iterator I = Node->succ_begin(), 2587228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose E = Node->succ_end(); 25882110350909701fcd6b55c636e24a675f0a905feaJordan Rose I != E; ++I) 2589228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose WS.push(*I); 2590239b6e47d282bd66c8b559ac47b8b42b34da619eJordan Rose } 25912110350909701fcd6b55c636e24a675f0a905feaJordan Rose 2592228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose // Sort the error paths from longest to shortest. 2593228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose std::sort(ReportNodes.begin(), ReportNodes.end(), 2594228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose PriorityCompare<true>(PriorityMap)); 2595228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose} 25962110350909701fcd6b55c636e24a675f0a905feaJordan Rose 2597228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rosebool TrimmedGraph::popNextReportGraph(ReportGraph &GraphWrapper) { 2598228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose if (ReportNodes.empty()) 2599228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose return false; 26002110350909701fcd6b55c636e24a675f0a905feaJordan Rose 2601228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose const ExplodedNode *OrigN; 2602228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose llvm::tie(OrigN, GraphWrapper.Index) = ReportNodes.pop_back_val(); 2603228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose assert(PriorityMap.find(OrigN) != PriorityMap.end() && 2604228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose "error node not accessible from root"); 26052110350909701fcd6b55c636e24a675f0a905feaJordan Rose 26062110350909701fcd6b55c636e24a675f0a905feaJordan Rose // Create a new graph with a single path. This is the graph 26072110350909701fcd6b55c636e24a675f0a905feaJordan Rose // that will be returned to the caller. 26082110350909701fcd6b55c636e24a675f0a905feaJordan Rose ExplodedGraph *GNew = new ExplodedGraph(); 26092110350909701fcd6b55c636e24a675f0a905feaJordan Rose GraphWrapper.Graph.reset(GNew); 2610228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose GraphWrapper.BackMap.clear(); 26111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2612228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose // Now walk from the error node up the BFS path, always taking the 2613228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose // predeccessor with the lowest number. 2614228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose ExplodedNode *Succ = 0; 2615228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose while (true) { 26163106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Create the equivalent node in the new graph with the same state 26173106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // and location. 26183e5ebf1a05603e08f2d0b2b2a5fa9406fe4cfb22Jordan Rose ExplodedNode *NewN = GNew->getNode(OrigN->getLocation(), OrigN->getState(), 26193e5ebf1a05603e08f2d0b2b2a5fa9406fe4cfb22Jordan Rose OrigN->isSink()); 26201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 26213106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Store the mapping to the original node. 2622228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose InterExplodedGraphMap::const_iterator IMitr = InverseMap.find(OrigN); 26233106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek assert(IMitr != InverseMap.end() && "No mapping to original node."); 26241efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose GraphWrapper.BackMap[NewN] = IMitr->second; 26251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 26263106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Link up the new node with the previous node. 2627228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose if (Succ) 2628228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose Succ->addPredecessor(NewN, *GNew); 2629228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose else 2630228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose GraphWrapper.ErrorNode = NewN; 26311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2632228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose Succ = NewN; 26331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 26343106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Are we at the final node? 2635228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose if (OrigN->pred_empty()) { 2636228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose GNew->addRoot(NewN); 26373106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 26383106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 26391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2640228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose // Find the next predeccessor node. We choose the node that is marked 26412110350909701fcd6b55c636e24a675f0a905feaJordan Rose // with the lowest BFS number. 2642228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose OrigN = *std::min_element(OrigN->pred_begin(), OrigN->pred_end(), 2643228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose PriorityCompare<false>(PriorityMap)); 26442110350909701fcd6b55c636e24a675f0a905feaJordan Rose } 26452110350909701fcd6b55c636e24a675f0a905feaJordan Rose 2646228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose return true; 26472110350909701fcd6b55c636e24a675f0a905feaJordan Rose} 26482110350909701fcd6b55c636e24a675f0a905feaJordan Rose 26492110350909701fcd6b55c636e24a675f0a905feaJordan Rose 26503106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek/// CompactPathDiagnostic - This function postprocesses a PathDiagnostic object 26513106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek/// and collapses PathDiagosticPieces that are expanded by macros. 265277d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenekstatic void CompactPathDiagnostic(PathPieces &path, const SourceManager& SM) { 26532042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek typedef std::vector<std::pair<IntrusiveRefCntPtr<PathDiagnosticMacroPiece>, 26542042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek SourceLocation> > MacroStackTy; 26551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2656c93dc7889644293e318e19d82830ea2acc45b678Dylan Noblesmith typedef std::vector<IntrusiveRefCntPtr<PathDiagnosticPiece> > 26573106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PiecesTy; 26581eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 26593106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroStackTy MacroStack; 26603106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PiecesTy Pieces; 26611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2662ed866e73bab7733f5226f84c52edefe23d694b2fTed Kremenek for (PathPieces::const_iterator I = path.begin(), E = path.end(); 26632042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek I!=E; ++I) { 266477d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek 2665ed866e73bab7733f5226f84c52edefe23d694b2fTed Kremenek PathDiagnosticPiece *piece = I->getPtr(); 266677d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek 266777d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek // Recursively compact calls. 266877d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek if (PathDiagnosticCallPiece *call=dyn_cast<PathDiagnosticCallPiece>(piece)){ 266977d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek CompactPathDiagnostic(call->path, SM); 267077d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek } 267177d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek 26723106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Get the location of the PathDiagnosticPiece. 267377d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek const FullSourceLoc Loc = piece->getLocation().asLocation(); 26741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 26753106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Determine the instantiation location, which is the location we group 26763106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // related PathDiagnosticPieces. 26771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump SourceLocation InstantiationLoc = Loc.isMacroID() ? 2678402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth SM.getExpansionLoc(Loc) : 26793106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek SourceLocation(); 26801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 26813106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (Loc.isFileID()) { 26823106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroStack.clear(); 268377d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek Pieces.push_back(piece); 26843106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek continue; 26853106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 2686706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek 26873106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek assert(Loc.isMacroID()); 26881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 26893106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Is the PathDiagnosticPiece within the same macro group? 26903106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (!MacroStack.empty() && InstantiationLoc == MacroStack.back().second) { 269177d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek MacroStack.back().first->subPieces.push_back(piece); 26923106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek continue; 26933106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 2694d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek 26953106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // We aren't in the same group. Are we descending into a new macro 26963106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // or are part of an old one? 2697c93dc7889644293e318e19d82830ea2acc45b678Dylan Noblesmith IntrusiveRefCntPtr<PathDiagnosticMacroPiece> MacroGroup; 2698d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek 26993106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek SourceLocation ParentInstantiationLoc = InstantiationLoc.isMacroID() ? 2700402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth SM.getExpansionLoc(Loc) : 27013106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek SourceLocation(); 27021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 27033106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Walk the entire macro stack. 27043106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek while (!MacroStack.empty()) { 27053106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (InstantiationLoc == MacroStack.back().second) { 27063106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroGroup = MacroStack.back().first; 27073106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 27083106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 27091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 27103106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (ParentInstantiationLoc == MacroStack.back().second) { 27113106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroGroup = MacroStack.back().first; 27123106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 271361f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek } 27141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 27153106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroStack.pop_back(); 27166837faa083bebad39aa342f84c2b450fb6410eafTed Kremenek } 27171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 27183106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (!MacroGroup || ParentInstantiationLoc == MacroStack.back().second) { 27193106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Create a new macro group and add it to the stack. 2720590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks PathDiagnosticMacroPiece *NewGroup = 2721590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks new PathDiagnosticMacroPiece( 272277d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek PathDiagnosticLocation::createSingleLocation(piece->getLocation())); 27235a429954aedd8a830a70fcea2cb51561673e4fc3Ted Kremenek 27243106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (MacroGroup) 2725802e02463b880f53a6e645bde78cc412481ce9e0Ted Kremenek MacroGroup->subPieces.push_back(NewGroup); 27263106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek else { 27273106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek assert(InstantiationLoc.isFileID()); 27283106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek Pieces.push_back(NewGroup); 27293106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 27301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 27313106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroGroup = NewGroup; 27323106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroStack.push_back(std::make_pair(MacroGroup, InstantiationLoc)); 27337dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek } 27343106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 27353106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Finally, add the PathDiagnosticPiece to the group. 273677d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek MacroGroup->subPieces.push_back(piece); 27373106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 27381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 27393106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Now take the pieces and construct a new PathDiagnostic. 274077d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek path.clear(); 27411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 274277d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek for (PiecesTy::iterator I=Pieces.begin(), E=Pieces.end(); I!=E; ++I) 274377d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek path.push_back(*I); 274461f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek} 274561f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek 27468347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rosebool GRBugReporter::generatePathDiagnostic(PathDiagnostic& PD, 2747c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek PathDiagnosticConsumer &PC, 2748c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek ArrayRef<BugReport *> &bugReports) { 274940406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek assert(!bugReports.empty()); 27508347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose 27519a9fe4068eed2fc72ec985e5ae393fb79a8fb9adJordan Rose bool HasValid = false; 2752228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose bool HasInvalid = false; 27532f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose SmallVector<const ExplodedNode *, 32> errorNodes; 2754c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek for (ArrayRef<BugReport*>::iterator I = bugReports.begin(), 27559a9fe4068eed2fc72ec985e5ae393fb79a8fb9adJordan Rose E = bugReports.end(); I != E; ++I) { 27569a9fe4068eed2fc72ec985e5ae393fb79a8fb9adJordan Rose if ((*I)->isValid()) { 27579a9fe4068eed2fc72ec985e5ae393fb79a8fb9adJordan Rose HasValid = true; 27589a9fe4068eed2fc72ec985e5ae393fb79a8fb9adJordan Rose errorNodes.push_back((*I)->getErrorNode()); 27599a9fe4068eed2fc72ec985e5ae393fb79a8fb9adJordan Rose } else { 2760228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose // Keep the errorNodes list in sync with the bugReports list. 2761228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose HasInvalid = true; 27629a9fe4068eed2fc72ec985e5ae393fb79a8fb9adJordan Rose errorNodes.push_back(0); 27639a9fe4068eed2fc72ec985e5ae393fb79a8fb9adJordan Rose } 276440406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek } 27651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 27669a9fe4068eed2fc72ec985e5ae393fb79a8fb9adJordan Rose // If all the reports have been marked invalid by a previous path generation, 27679a9fe4068eed2fc72ec985e5ae393fb79a8fb9adJordan Rose // we're done. 27689a9fe4068eed2fc72ec985e5ae393fb79a8fb9adJordan Rose if (!HasValid) 27699a9fe4068eed2fc72ec985e5ae393fb79a8fb9adJordan Rose return false; 27709a9fe4068eed2fc72ec985e5ae393fb79a8fb9adJordan Rose 27712f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose typedef PathDiagnosticConsumer::PathGenerationScheme PathGenerationScheme; 27722f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose PathGenerationScheme ActiveScheme = PC.getGenerationScheme(); 27732f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose 2774af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek if (ActiveScheme == PathDiagnosticConsumer::Extensive) { 2775d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks AnalyzerOptions &options = getAnalyzerOptions(); 277615676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek if (options.getBooleanOption("path-diagnostics-alternate", false)) { 2777af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek ActiveScheme = PathDiagnosticConsumer::AlternateExtensive; 2778af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek } 2779af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek } 2780af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 27811efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose TrimmedGraph TrimG(&getGraph(), errorNodes); 2782228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose ReportGraph ErrorGraph; 27831efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose 2784228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose while (TrimG.popNextReportGraph(ErrorGraph)) { 27852f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // Find the BugReport with the original location. 27861efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose assert(ErrorGraph.Index < bugReports.size()); 27871efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose BugReport *R = bugReports[ErrorGraph.Index]; 27882f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose assert(R && "No original report found for sliced graph."); 27892f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose assert(R->isValid() && "Report selected by trimmed graph marked invalid."); 27902f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose 27912f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // Start building the path diagnostic... 27921efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose PathDiagnosticBuilder PDB(*this, R, ErrorGraph.BackMap, &PC); 27931efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose const ExplodedNode *N = ErrorGraph.ErrorNode; 27942f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose 27952f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // Register additional node visitors. 27962f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose R->addVisitor(new NilReceiverBRVisitor()); 27972f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose R->addVisitor(new ConditionBRVisitor()); 27982f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose R->addVisitor(new LikelyFalsePositiveSuppressionBRVisitor()); 27992f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose 28002f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose BugReport::VisitorList visitors; 28012f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose unsigned origReportConfigToken, finalReportConfigToken; 2802d306a530fca74e40916121f5583e0545e470b3c4Ted Kremenek LocationContextMap LCM; 28032f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose 28042f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // While generating diagnostics, it's possible the visitors will decide 28052f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // new symbols and regions are interesting, or add other visitors based on 28062f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // the information they find. If they do, we need to regenerate the path 28072f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // based on our new report configuration. 28082f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose do { 28092f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // Get a clean copy of all the visitors. 28102f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose for (BugReport::visitor_iterator I = R->visitor_begin(), 28112f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose E = R->visitor_end(); I != E; ++I) 28122f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose visitors.push_back((*I)->clone()); 28132f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose 28142f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // Clear out the active path from any previous work. 28152f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose PD.resetPath(); 28162f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose origReportConfigToken = R->getConfigurationChangeToken(); 28172f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose 28182f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // Generate the very last diagnostic piece - the piece is visible before 28192f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // the trace is expanded. 28202f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose PathDiagnosticPiece *LastPiece = 0; 28212f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose for (BugReport::visitor_iterator I = visitors.begin(), E = visitors.end(); 28222f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose I != E; ++I) { 28232f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose if (PathDiagnosticPiece *Piece = (*I)->getEndPath(PDB, N, *R)) { 28242f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose assert (!LastPiece && 28252f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose "There can only be one final piece in a diagnostic."); 28262f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose LastPiece = Piece; 28272f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose } 28283bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose } 282986ff12c8a8a356ca284ca7687749216fbfd74519Anna Zaks 28302f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose if (ActiveScheme != PathDiagnosticConsumer::None) { 28312f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose if (!LastPiece) 28322f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose LastPiece = BugReporterVisitor::getDefaultEndPath(PDB, N, *R); 28332f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose assert(LastPiece); 2834d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose PD.setEndOfPath(LastPiece); 28358347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose } 28362f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose 2837d306a530fca74e40916121f5583e0545e470b3c4Ted Kremenek // Make sure we get a clean location context map so we don't 2838d306a530fca74e40916121f5583e0545e470b3c4Ted Kremenek // hold onto old mappings. 2839d306a530fca74e40916121f5583e0545e470b3c4Ted Kremenek LCM.clear(); 2840d306a530fca74e40916121f5583e0545e470b3c4Ted Kremenek 28412f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose switch (ActiveScheme) { 2842af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek case PathDiagnosticConsumer::AlternateExtensive: 2843af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek GenerateAlternateExtensivePathDiagnostic(PD, PDB, N, LCM, visitors); 2844af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek break; 28452f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose case PathDiagnosticConsumer::Extensive: 2846d306a530fca74e40916121f5583e0545e470b3c4Ted Kremenek GenerateExtensivePathDiagnostic(PD, PDB, N, LCM, visitors); 28472f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose break; 28482f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose case PathDiagnosticConsumer::Minimal: 2849d306a530fca74e40916121f5583e0545e470b3c4Ted Kremenek GenerateMinimalPathDiagnostic(PD, PDB, N, LCM, visitors); 28502f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose break; 28512f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose case PathDiagnosticConsumer::None: 28522f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose GenerateVisitorsOnlyPathDiagnostic(PD, PDB, N, visitors); 28532f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose break; 2854d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose } 28553bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose 28562f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // Clean up the visitors we used. 28572f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose llvm::DeleteContainerPointers(visitors); 28583bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose 28592f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // Did anything change while generating this path? 28602f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose finalReportConfigToken = R->getConfigurationChangeToken(); 28612f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose } while (finalReportConfigToken != origReportConfigToken); 28623bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose 2863228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose if (!R->isValid()) 28642f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose continue; 2865b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek 28662f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // Finally, prune the diagnostic path of uninteresting stuff. 28672f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose if (!PD.path.empty()) { 28682f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // Remove messages that are basically the same. 28692f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose removeRedundantMsgs(PD.getMutablePieces()); 28702f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose 2871d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks if (R->shouldPrunePath() && getAnalyzerOptions().shouldPrunePaths()) { 2872d306a530fca74e40916121f5583e0545e470b3c4Ted Kremenek bool stillHasNotes = removeUnneededCalls(PD.getMutablePieces(), R, LCM); 28732f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose assert(stillHasNotes); 28742f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose (void)stillHasNotes; 28752f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose } 28762f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose 28772f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose adjustCallLocations(PD.getMutablePieces()); 2878bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek 2879bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek if (ActiveScheme == PathDiagnosticConsumer::AlternateExtensive) { 2880aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek SourceManager &SM = getSourceManager(); 2881aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek 2882aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek // Reduce the number of edges from a very conservative set 2883aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek // to an aesthetically pleasing subset that conveys the 2884aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek // necessary information. 288515676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek OptimizedCallsSet OCS; 2886bb518991ce4298d8662235fc8cb13813f011c18dJordan Rose while (optimizeEdges(PD.getMutablePieces(), SM, OCS, LCM)) {} 2887aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek 2888aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek // Adjust edges into loop conditions to make them more uniform 2889aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek // and aesthetically pleasing. 2890a40983460cc3f8f583cd968ac2e4647dc30c83f5Ted Kremenek adjustBranchEdges(PD.getMutablePieces(), LCM, SM); 2891bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek } 2892b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek } 2893afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose 28942f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // We found a report and didn't suppress it. 28952f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose return true; 2896ed7948b55fa4b2505f240cc5287137f451172b4cTed Kremenek } 28978347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose 28982f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // We suppressed all the reports in this equivalence class. 2899228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose assert(!HasInvalid && "Inconsistent suppression"); 2900228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose (void)HasInvalid; 29012f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose return false; 29023106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 29031aa44c7c9198796085b77c6bdd7c90030845a688Ted Kremenek 2904cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenekvoid BugReporter::Register(BugType *BT) { 29053baf672378f105602d2b12f03f00277ae1936fe9Ted Kremenek BugTypes = F.add(BugTypes, BT); 290676d90c8bf83d071fd1bdbffa6d9f2af87c6bb7b5Ted Kremenek} 290776d90c8bf83d071fd1bdbffa6d9f2af87c6bb7b5Ted Kremenek 2908785950e59424dca7ce0081bebf13c0acd2c4fff6Jordan Rosevoid BugReporter::emitReport(BugReport* R) { 2909cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek // Compute the bug report's hash to determine its equivalence class. 2910cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek llvm::FoldingSetNodeID ID; 2911cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek R->Profile(ID); 29121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 29131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Lookup the equivance class. If there isn't one, create it. 2914cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek BugType& BT = R->getBugType(); 2915cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek Register(&BT); 2916cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek void *InsertPos; 2917404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis BugReportEquivClass* EQ = EQClasses.FindNodeOrInsertPos(ID, InsertPos); 29181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2919cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek if (!EQ) { 2920cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek EQ = new BugReportEquivClass(R); 2921404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis EQClasses.InsertNode(EQ, InsertPos); 29223b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks EQClassesVector.push_back(EQ); 2923cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek } 2924cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek else 2925cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek EQ->AddReport(R); 292661f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek} 292761f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek 292806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 292906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek//===----------------------------------------------------------------------===// 293006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek// Emitting reports in equivalence classes. 293106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek//===----------------------------------------------------------------------===// 293206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 293306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremeneknamespace { 2934ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamstruct FRIEC_WLItem { 293506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek const ExplodedNode *N; 293606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek ExplodedNode::const_succ_iterator I, E; 293706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 293806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek FRIEC_WLItem(const ExplodedNode *n) 293906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek : N(n), I(N->succ_begin()), E(N->succ_end()) {} 294006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek}; 294106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek} 294206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 294361f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenekstatic BugReport * 294461f52bd3c524268e25b48a1ed3730aedd6cc8374Ted KremenekFindReportInEquivalenceClass(BugReportEquivClass& EQ, 29455f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVectorImpl<BugReport*> &bugReports) { 294661f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek 294706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek BugReportEquivClass::iterator I = EQ.begin(), E = EQ.end(); 294806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek assert(I != E); 29494a5f724538cbc275370c9504e8169ce92503256cBenjamin Kramer BugType& BT = I->getBugType(); 295061f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek 295140406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek // If we don't need to suppress any of the nodes because they are 295240406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek // post-dominated by a sink, simply add all the nodes in the equivalence class 295340406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek // to 'Nodes'. Any of the reports will serve as a "representative" report. 295461f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek if (!BT.isSuppressOnSink()) { 29554a5f724538cbc275370c9504e8169ce92503256cBenjamin Kramer BugReport *R = I; 295661f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek for (BugReportEquivClass::iterator I=EQ.begin(), E=EQ.end(); I!=E; ++I) { 29579c378f705405d37f49795d5e915989de774fe11fTed Kremenek const ExplodedNode *N = I->getErrorNode(); 295861f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek if (N) { 29594a5f724538cbc275370c9504e8169ce92503256cBenjamin Kramer R = I; 296040406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek bugReports.push_back(R); 296161f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek } 296261f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek } 296306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek return R; 296461f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek } 296561f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek 296606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // For bug reports that should be suppressed when all paths are post-dominated 296706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // by a sink node, iterate through the reports in the equivalence class 296806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // until we find one that isn't post-dominated (if one exists). We use a 296906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // DFS traversal of the ExplodedGraph to find a non-sink node. We could write 297006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // this as a recursive function, but we don't want to risk blowing out the 297106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // stack for very long paths. 297240406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek BugReport *exampleReport = 0; 297361f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek 297406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek for (; I != E; ++I) { 29754a5f724538cbc275370c9504e8169ce92503256cBenjamin Kramer const ExplodedNode *errorNode = I->getErrorNode(); 297606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 297740406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek if (!errorNode) 297806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek continue; 297940406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek if (errorNode->isSink()) { 2980b219cfc4d75f0a03630b7c4509ef791b7e97b2c8David Blaikie llvm_unreachable( 298106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek "BugType::isSuppressSink() should not be 'true' for sink end nodes"); 298206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek } 298361f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek // No successors? By definition this nodes isn't post-dominated by a sink. 298440406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek if (errorNode->succ_empty()) { 29854a5f724538cbc275370c9504e8169ce92503256cBenjamin Kramer bugReports.push_back(I); 298640406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek if (!exampleReport) 29874a5f724538cbc275370c9504e8169ce92503256cBenjamin Kramer exampleReport = I; 298861f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek continue; 298961f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek } 299061f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek 299106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // At this point we know that 'N' is not a sink and it has at least one 299206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // successor. Use a DFS worklist to find a non-sink end-of-path node. 299306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek typedef FRIEC_WLItem WLItem; 29945f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner typedef SmallVector<WLItem, 10> DFSWorkList; 299506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek llvm::DenseMap<const ExplodedNode *, unsigned> Visited; 299606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 299706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek DFSWorkList WL; 299840406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek WL.push_back(errorNode); 299940406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek Visited[errorNode] = 1; 300006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 300106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek while (!WL.empty()) { 300206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek WLItem &WI = WL.back(); 300306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek assert(!WI.N->succ_empty()); 300406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 300506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek for (; WI.I != WI.E; ++WI.I) { 300606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek const ExplodedNode *Succ = *WI.I; 300706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // End-of-path node? 300806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek if (Succ->succ_empty()) { 300961f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek // If we found an end-of-path node that is not a sink. 301061f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek if (!Succ->isSink()) { 30114a5f724538cbc275370c9504e8169ce92503256cBenjamin Kramer bugReports.push_back(I); 301240406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek if (!exampleReport) 30134a5f724538cbc275370c9504e8169ce92503256cBenjamin Kramer exampleReport = I; 301461f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek WL.clear(); 301561f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek break; 301661f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek } 301706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // Found a sink? Continue on to the next successor. 301806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek continue; 301906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek } 302006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // Mark the successor as visited. If it hasn't been explored, 302106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // enqueue it to the DFS worklist. 302206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek unsigned &mark = Visited[Succ]; 302306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek if (!mark) { 302406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek mark = 1; 302506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek WL.push_back(Succ); 302606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek break; 302706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek } 302806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek } 302961f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek 303061f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek // The worklist may have been cleared at this point. First 303161f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek // check if it is empty before checking the last item. 303261f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek if (!WL.empty() && &WL.back() == &WI) 303306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek WL.pop_back(); 303406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek } 303506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek } 303606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 303761f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek // ExampleReport will be NULL if all the nodes in the equivalence class 303861f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek // were post-dominated by sinks. 303940406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek return exampleReport; 304061f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek} 3041e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek 3042cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenekvoid BugReporter::FlushReport(BugReportEquivClass& EQ) { 30435f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<BugReport*, 10> bugReports; 304440406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek BugReport *exampleReport = FindReportInEquivalenceClass(EQ, bugReports); 3045c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek if (exampleReport) { 3046c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek const PathDiagnosticConsumers &C = getPathDiagnosticConsumers(); 3047c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek for (PathDiagnosticConsumers::const_iterator I=C.begin(), 3048c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek E=C.end(); I != E; ++I) { 3049c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek FlushReport(exampleReport, **I, bugReports); 3050c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek } 3051c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek } 3052c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek} 3053c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek 3054c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenekvoid BugReporter::FlushReport(BugReport *exampleReport, 3055c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek PathDiagnosticConsumer &PD, 3056c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek ArrayRef<BugReport*> bugReports) { 30571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3058cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek // FIXME: Make sure we use the 'R' for the path that was actually used. 30591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Probably doesn't make a difference in practice. 306040406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek BugType& BT = exampleReport->getBugType(); 30611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 30626f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith OwningPtr<PathDiagnostic> 306307189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek D(new PathDiagnostic(exampleReport->getDeclWithIssue(), 306407189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek exampleReport->getBugType().getName(), 30653a46f5fd1709f6df03bbb8b0abf84052dc0f39ffJordan Rose exampleReport->getDescription(), 30663a46f5fd1709f6df03bbb8b0abf84052dc0f39ffJordan Rose exampleReport->getShortDescription(/*Fallback=*/false), 306797bfb558f69c09b01a5c1510f08dc91eb62329a7Anna Zaks BT.getCategory(), 306897bfb558f69c09b01a5c1510f08dc91eb62329a7Anna Zaks exampleReport->getUniqueingLocation(), 306997bfb558f69c09b01a5c1510f08dc91eb62329a7Anna Zaks exampleReport->getUniqueingDecl())); 3070d49967f8764135ae65658e354b6d38e3637c9de3Ted Kremenek 3071cc08ca9b3cd2b715a699bcc772ce2e83a502915aJordan Rose MaxBugClassSize = std::max(bugReports.size(), 3072cc08ca9b3cd2b715a699bcc772ce2e83a502915aJordan Rose static_cast<size_t>(MaxBugClassSize)); 3073cc08ca9b3cd2b715a699bcc772ce2e83a502915aJordan Rose 3074c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek // Generate the full path diagnostic, using the generation scheme 3075d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose // specified by the PathDiagnosticConsumer. Note that we have to generate 3076d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose // path diagnostics even for consumers which do not support paths, because 3077d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose // the BugReporterVisitors may mark this bug as a false positive. 3078d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose if (!bugReports.empty()) 3079d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose if (!generatePathDiagnostic(*D.get(), PD, bugReports)) 3080d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose return; 30813148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek 3082cc08ca9b3cd2b715a699bcc772ce2e83a502915aJordan Rose MaxValidBugClassSize = std::max(bugReports.size(), 3083cc08ca9b3cd2b715a699bcc772ce2e83a502915aJordan Rose static_cast<size_t>(MaxValidBugClassSize)); 3084cc08ca9b3cd2b715a699bcc772ce2e83a502915aJordan Rose 3085d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks // Examine the report and see if the last piece is in a header. Reset the 3086d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks // report location to the last piece in the main source file. 3087d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks AnalyzerOptions& Opts = getAnalyzerOptions(); 3088d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks if (Opts.shouldReportIssuesInMainSourceFile() && !Opts.AnalyzeAll) 3089d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks D->resetDiagnosticLocationToMainFile(); 3090d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks 3091c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek // If the path is empty, generate a single step path with the location 3092c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek // of the issue. 3093802e02463b880f53a6e645bde78cc412481ce9e0Ted Kremenek if (D->path.empty()) { 3094c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek PathDiagnosticLocation L = exampleReport->getLocation(getSourceManager()); 3095c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek PathDiagnosticPiece *piece = 3096c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek new PathDiagnosticEventPiece(L, exampleReport->getDescription()); 3097c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek BugReport::ranges_iterator Beg, End; 3098c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek llvm::tie(Beg, End) = exampleReport->getRanges(); 309907189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek for ( ; Beg != End; ++Beg) 310007189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek piece->addRange(*Beg); 31013a46f5fd1709f6df03bbb8b0abf84052dc0f39ffJordan Rose D->setEndOfPath(piece); 31023148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek } 31031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3104c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek // Get the meta data. 3105c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek const BugReport::ExtraTextList &Meta = exampleReport->getExtraText(); 3106c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek for (BugReport::ExtraTextList::const_iterator i = Meta.begin(), 3107c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek e = Meta.end(); i != e; ++i) { 3108c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek D->addMeta(*i); 3109c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek } 3110c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek 3111c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek PD.HandlePathDiagnostic(D.take()); 311261f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek} 311357202071e477530e9348bc76671ee369b2399b92Ted Kremenek 311407189521a15d9c088216b943649cb9fe231cbb57Ted Kremenekvoid BugReporter::EmitBasicReport(const Decl *DeclWithIssue, 311507189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek StringRef name, 31165f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef category, 3117590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks StringRef str, PathDiagnosticLocation Loc, 31188c036c7f77d69f96df49219ed0bdbade200d52ebTed Kremenek SourceRange* RBeg, unsigned NumRanges) { 31191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3120404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // 'BT' is owned by BugReporter. 3121404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis BugType *BT = getBugTypeForName(name, category); 3122590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks BugReport *R = new BugReport(*BT, str, Loc); 312307189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek R->setDeclWithIssue(DeclWithIssue); 3124cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek for ( ; NumRanges > 0 ; --NumRanges, ++RBeg) R->addRange(*RBeg); 3125785950e59424dca7ce0081bebf13c0acd2c4fff6Jordan Rose emitReport(R); 3126cabe66811fe43835b8c5a0854552768fc53261e3Ted Kremenek} 3127404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis 31285f9e272e632e951b1efe824cd16acb4d96077930Chris LattnerBugType *BugReporter::getBugTypeForName(StringRef name, 31295f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef category) { 3130f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith SmallString<136> fullDesc; 3131404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis llvm::raw_svector_ostream(fullDesc) << name << ":" << category; 3132404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis llvm::StringMapEntry<BugType *> & 3133404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis entry = StrBugTypes.GetOrCreateValue(fullDesc); 3134404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis BugType *BT = entry.getValue(); 3135404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis if (!BT) { 3136404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis BT = new BugType(name, category); 3137404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis entry.setValue(BT); 3138404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis } 3139404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis return BT; 3140404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis} 3141