BugReporter.cpp revision 048eeea6852043990c87e52938b53b5337bd098e
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 213d474da062565596015558856333423199aed5eb1Jordan Rose/// Returns true if the given decl has been implicitly given a body, either by 214d474da062565596015558856333423199aed5eb1Jordan Rose/// the analyzer or by the compiler proper. 215d474da062565596015558856333423199aed5eb1Jordan Rosestatic bool hasImplicitBody(const Decl *D) { 216d474da062565596015558856333423199aed5eb1Jordan Rose assert(D); 217d474da062565596015558856333423199aed5eb1Jordan Rose return D->isImplicit() || !D->hasBody(); 218d474da062565596015558856333423199aed5eb1Jordan Rose} 219d474da062565596015558856333423199aed5eb1Jordan Rose 220afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose/// Recursively scan through a path and make sure that all call pieces have 221afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose/// valid locations. Note that all other pieces with invalid locations should 222afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose/// have already been pruned out. 223afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rosestatic void adjustCallLocations(PathPieces &Pieces, 224afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose PathDiagnosticLocation *LastCallLocation = 0) { 225afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose for (PathPieces::iterator I = Pieces.begin(), E = Pieces.end(); I != E; ++I) { 226ed866e73bab7733f5226f84c52edefe23d694b2fTed Kremenek PathDiagnosticCallPiece *Call = dyn_cast<PathDiagnosticCallPiece>(*I); 227afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose 228afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose if (!Call) { 229ed866e73bab7733f5226f84c52edefe23d694b2fTed Kremenek assert((*I)->getLocation().asLocation().isValid()); 230afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose continue; 231afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose } 232afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose 233afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose if (LastCallLocation) { 234d474da062565596015558856333423199aed5eb1Jordan Rose bool CallerIsImplicit = hasImplicitBody(Call->getCaller()); 235d474da062565596015558856333423199aed5eb1Jordan Rose if (CallerIsImplicit || !Call->callEnter.asLocation().isValid()) 236afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose Call->callEnter = *LastCallLocation; 237d474da062565596015558856333423199aed5eb1Jordan Rose if (CallerIsImplicit || !Call->callReturn.asLocation().isValid()) 238afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose Call->callReturn = *LastCallLocation; 239afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose } 240afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose 241afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose // Recursively clean out the subclass. Keep this call around if 242afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose // it contains any informative diagnostics. 243afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose PathDiagnosticLocation *ThisCallLocation; 244187f8bd88bfc92cf3fea62b7d8db5f92edce410aJordan Rose if (Call->callEnterWithin.asLocation().isValid() && 245d474da062565596015558856333423199aed5eb1Jordan Rose !hasImplicitBody(Call->getCallee())) 246afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose ThisCallLocation = &Call->callEnterWithin; 247afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose else 248afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose ThisCallLocation = &Call->callEnter; 249afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose 250afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose assert(ThisCallLocation && "Outermost call has an invalid location"); 251afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose adjustCallLocations(Call->path, ThisCallLocation); 252afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose } 253afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose} 254afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose 255c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek//===----------------------------------------------------------------------===// 2563106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// PathDiagnosticBuilder and its associated routines and helper objects. 257b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek//===----------------------------------------------------------------------===// 258b479dadea93b93d3f0a335c3518b703f140b3f50Ted Kremenek 259babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremeneknamespace { 260ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass NodeMapClosure : public BugReport::NodeResolver { 261c9963132736782d0c9178c744b3e2307cfb98a08Jordan Rose InterExplodedGraphMap &M; 2627dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenekpublic: 263c9963132736782d0c9178c744b3e2307cfb98a08Jordan Rose NodeMapClosure(InterExplodedGraphMap &m) : M(m) {} 2641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2659c378f705405d37f49795d5e915989de774fe11fTed Kremenek const ExplodedNode *getOriginalNode(const ExplodedNode *N) { 266c9963132736782d0c9178c744b3e2307cfb98a08Jordan Rose return M.lookup(N); 2677dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek } 2687dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek}; 2691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 270ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass PathDiagnosticBuilder : public BugReporterContext { 2717dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek BugReport *R; 272ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie PathDiagnosticConsumer *PDC; 2737dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek NodeMapClosure NMC; 2741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumppublic: 27559950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek const LocationContext *LC; 27659950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek 2778966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek PathDiagnosticBuilder(GRBugReporter &br, 278c9963132736782d0c9178c744b3e2307cfb98a08Jordan Rose BugReport *r, InterExplodedGraphMap &Backmap, 279ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie PathDiagnosticConsumer *pdc) 2808966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek : BugReporterContext(br), 28159950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek R(r), PDC(pdc), NMC(Backmap), LC(r->getErrorNode()->getLocationContext()) 28259950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek {} 2831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2849c378f705405d37f49795d5e915989de774fe11fTed Kremenek PathDiagnosticLocation ExecutionContinues(const ExplodedNode *N); 2851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2869c378f705405d37f49795d5e915989de774fe11fTed Kremenek PathDiagnosticLocation ExecutionContinues(llvm::raw_string_ostream &os, 2879c378f705405d37f49795d5e915989de774fe11fTed Kremenek const ExplodedNode *N); 2881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2898e6431adab313e283a992698f6fc7afe62420999Anna Zaks BugReport *getBugReport() { return R; } 2908e6431adab313e283a992698f6fc7afe62420999Anna Zaks 291212f6d3b5fb3fa55ba1e40671cfc336430abc8ddTom Care Decl const &getCodeDecl() { return R->getErrorNode()->getCodeDecl(); } 29259950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek 29359950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek ParentMap& getParentMap() { return LC->getParentMap(); } 2941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 295c3f83ad7adaff2623986aa1c3e57833babd03d50Ted Kremenek const Stmt *getParent(const Stmt *S) { 296c3f83ad7adaff2623986aa1c3e57833babd03d50Ted Kremenek return getParentMap().getParent(S); 297c3f83ad7adaff2623986aa1c3e57833babd03d50Ted Kremenek } 2981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2998966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek virtual NodeMapClosure& getNodeResolver() { return NMC; } 3007297134f128423fce2e88f92421ed135bded7d4eDouglas Gregor 301d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek PathDiagnosticLocation getEnclosingStmtLocation(const Stmt *S); 3021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 303ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie PathDiagnosticConsumer::PathGenerationScheme getGenerationScheme() const { 304ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie return PDC ? PDC->getGenerationScheme() : PathDiagnosticConsumer::Extensive; 3057dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek } 3067dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek 307babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek bool supportsLogicalOpControlFlow() const { 308babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek return PDC ? PDC->supportsLogicalOpControlFlow() : true; 3091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 310babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek}; 311babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek} // end anonymous namespace 312babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek 31300605e0f011ed99225a22026344c5fc1b3212cd7Ted KremenekPathDiagnosticLocation 3149c378f705405d37f49795d5e915989de774fe11fTed KremenekPathDiagnosticBuilder::ExecutionContinues(const ExplodedNode *N) { 3150f8579274a010f360a371b53101859d9d6052314Anna Zaks if (const Stmt *S = PathDiagnosticLocation::getNextStmt(N)) 31659950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek return PathDiagnosticLocation(S, getSourceManager(), LC); 31700605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek 3180cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks return PathDiagnosticLocation::createDeclEnd(N->getLocationContext(), 3190cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks getSourceManager()); 320082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek} 3211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 32200605e0f011ed99225a22026344c5fc1b3212cd7Ted KremenekPathDiagnosticLocation 3239c378f705405d37f49795d5e915989de774fe11fTed KremenekPathDiagnosticBuilder::ExecutionContinues(llvm::raw_string_ostream &os, 3249c378f705405d37f49795d5e915989de774fe11fTed Kremenek const ExplodedNode *N) { 325babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek 326143ca222583a4a355fdc89af852deef287499300Ted Kremenek // Slow, but probably doesn't matter. 327b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek if (os.str().empty()) 328b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek os << ' '; 3291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 33000605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek const PathDiagnosticLocation &Loc = ExecutionContinues(N); 3311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 33200605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek if (Loc.asStmt()) 333b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek os << "Execution continues on line " 334642116259e8df6286063a17361c20e95b5017a0aChandler Carruth << getSourceManager().getExpansionLineNumber(Loc.asLocation()) 3358966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek << '.'; 3364f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek else { 3374f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek os << "Execution jumps to the end of the "; 3384f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek const Decl *D = N->getLocationContext()->getDecl(); 3394f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek if (isa<ObjCMethodDecl>(D)) 3404f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek os << "method"; 3414f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek else if (isa<FunctionDecl>(D)) 3424f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek os << "function"; 3434f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek else { 3444f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek assert(isa<BlockDecl>(D)); 3454f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek os << "anonymous block"; 3464f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek } 3474f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek os << '.'; 3484f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek } 3491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 350082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek return Loc; 351143ca222583a4a355fdc89af852deef287499300Ted Kremenek} 352143ca222583a4a355fdc89af852deef287499300Ted Kremenek 35396f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rosestatic const Stmt *getEnclosingParent(const Stmt *S, const ParentMap &PM) { 354ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek if (isa<Expr>(S) && PM.isConsumedExpr(cast<Expr>(S))) 35596f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose return PM.getParentIgnoreParens(S); 3561eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 357ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek const Stmt *Parent = PM.getParentIgnoreParens(S); 35896f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose if (!Parent) 35996f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose return 0; 3601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 36196f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose switch (Parent->getStmtClass()) { 36296f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose case Stmt::ForStmtClass: 36396f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose case Stmt::DoStmtClass: 36496f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose case Stmt::WhileStmtClass: 36596f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose case Stmt::ObjCForCollectionStmtClass: 36696f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose return Parent; 36796f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose default: 36896f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose break; 36996f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose } 3701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 37196f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose return 0; 372ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek} 373ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek 37496f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rosestatic PathDiagnosticLocation 37596f1061fbe59faff5b266a3a04061cefcfe03e2fJordan RosegetEnclosingStmtLocation(const Stmt *S, SourceManager &SMgr, const ParentMap &P, 3769d9b494aa36ceeb823c48acf04d2d7677174be88Jordan Rose const LocationContext *LC, bool allowNestedContexts) { 37796f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose if (!S) 37896f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose return PathDiagnosticLocation(); 3791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 38096f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose while (const Stmt *Parent = getEnclosingParent(S, P)) { 381af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek switch (Parent->getStmtClass()) { 3825fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek case Stmt::BinaryOperatorClass: { 3835fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek const BinaryOperator *B = cast<BinaryOperator>(Parent); 3845fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek if (B->isLogicalOp()) 3859d9b494aa36ceeb823c48acf04d2d7677174be88Jordan Rose return PathDiagnosticLocation(allowNestedContexts ? B : S, SMgr, LC); 3865fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek break; 3871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 388af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::CompoundStmtClass: 389af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::StmtExprClass: 390220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 3911d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek case Stmt::ChooseExprClass: 3921d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek // Similar to '?' if we are referring to condition, just have the edge 3931d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek // point to the entire choose expression. 3949d9b494aa36ceeb823c48acf04d2d7677174be88Jordan Rose if (allowNestedContexts || cast<ChooseExpr>(Parent)->getCond() == S) 395220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(Parent, SMgr, LC); 3961d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek else 397220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 39856ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall case Stmt::BinaryConditionalOperatorClass: 3991d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek case Stmt::ConditionalOperatorClass: 4001d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek // For '?', if we are referring to condition, just have the edge point 4011d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek // to the entire '?' expression. 4029d9b494aa36ceeb823c48acf04d2d7677174be88Jordan Rose if (allowNestedContexts || 4039d9b494aa36ceeb823c48acf04d2d7677174be88Jordan Rose cast<AbstractConditionalOperator>(Parent)->getCond() == S) 404220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(Parent, SMgr, LC); 4051d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek else 406220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 407af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::DoStmtClass: 408220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 409af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::ForStmtClass: 410af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek if (cast<ForStmt>(Parent)->getBody() == S) 411220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 4121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump break; 413af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::IfStmtClass: 414af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek if (cast<IfStmt>(Parent)->getCond() != S) 415220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 4168bd4d037d837e7922c3661d6158229da58a03887Ted Kremenek break; 417af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::ObjCForCollectionStmtClass: 418af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek if (cast<ObjCForCollectionStmt>(Parent)->getBody() == S) 419220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 420af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek break; 421af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::WhileStmtClass: 422af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek if (cast<WhileStmt>(Parent)->getCond() != S) 423220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 424af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek break; 425af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek default: 426af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek break; 427af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek } 428af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek 429d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek S = Parent; 430d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek } 4311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 432d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek assert(S && "Cannot have null Stmt for PathDiagnosticLocation"); 433e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek 434220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 435d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek} 436d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek 43796f1061fbe59faff5b266a3a04061cefcfe03e2fJordan RosePathDiagnosticLocation 43896f1061fbe59faff5b266a3a04061cefcfe03e2fJordan RosePathDiagnosticBuilder::getEnclosingStmtLocation(const Stmt *S) { 43996f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose assert(S && "Null Stmt passed to getEnclosingStmtLocation"); 4409d9b494aa36ceeb823c48acf04d2d7677174be88Jordan Rose return ::getEnclosingStmtLocation(S, getSourceManager(), getParentMap(), LC, 4419d9b494aa36ceeb823c48acf04d2d7677174be88Jordan Rose /*allowNestedContexts=*/false); 44296f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose} 44396f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose 444cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek//===----------------------------------------------------------------------===// 445d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose// "Visitors only" path diagnostic generation algorithm. 446d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose//===----------------------------------------------------------------------===// 447d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rosestatic bool GenerateVisitorsOnlyPathDiagnostic(PathDiagnostic &PD, 448d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose PathDiagnosticBuilder &PDB, 449d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose const ExplodedNode *N, 450d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose ArrayRef<BugReporterVisitor *> visitors) { 451d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose // All path generation skips the very first node (the error node). 452d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose // This is because there is special handling for the end-of-path note. 453d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose N = N->getFirstPred(); 454d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose if (!N) 455d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose return true; 456d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose 457d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose BugReport *R = PDB.getBugReport(); 458d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose while (const ExplodedNode *Pred = N->getFirstPred()) { 459d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose for (ArrayRef<BugReporterVisitor *>::iterator I = visitors.begin(), 460d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose E = visitors.end(); 461d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose I != E; ++I) { 462d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose // Visit all the node pairs, but throw the path pieces away. 463d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose PathDiagnosticPiece *Piece = (*I)->VisitNode(N, Pred, PDB, *R); 464d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose delete Piece; 465d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose } 466d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose 467d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose N = Pred; 468d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose } 469d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose 470d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose return R->isValid(); 471d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose} 472d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose 473d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose//===----------------------------------------------------------------------===// 4743106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// "Minimal" path diagnostic generation algorithm. 475cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek//===----------------------------------------------------------------------===// 47656a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zakstypedef std::pair<PathDiagnosticCallPiece*, const ExplodedNode*> StackDiagPair; 47756a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zakstypedef SmallVector<StackDiagPair, 6> StackDiagVector; 47856a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks 479368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaksstatic void updateStackPiecesWithMessage(PathDiagnosticPiece *P, 48056a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks StackDiagVector &CallStack) { 481368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks // If the piece contains a special message, add it to all the call 482368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks // pieces on the active stack. 483368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks if (PathDiagnosticEventPiece *ep = 484368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks dyn_cast<PathDiagnosticEventPiece>(P)) { 485368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks 48656a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks if (ep->hasCallStackHint()) 48756a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks for (StackDiagVector::iterator I = CallStack.begin(), 48856a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks E = CallStack.end(); I != E; ++I) { 48956a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks PathDiagnosticCallPiece *CP = I->first; 49056a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks const ExplodedNode *N = I->second; 4918fe4525680ce72e90cee3e58b5654e3ae955447fNAKAMURA Takumi std::string stackMsg = ep->getCallStackMessage(N); 49256a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks 493368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks // The last message on the path to final bug is the most important 494368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks // one. Since we traverse the path backwards, do not add the message 495368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks // if one has been previously added. 49656a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks if (!CP->hasCallStackMessage()) 49756a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks CP->setCallStackMessage(stackMsg); 49856a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks } 499368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks } 500368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks} 501cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek 50277d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenekstatic void CompactPathDiagnostic(PathPieces &path, const SourceManager& SM); 50314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 5048347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rosestatic bool GenerateMinimalPathDiagnostic(PathDiagnostic& PD, 5053106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PathDiagnosticBuilder &PDB, 5063bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose const ExplodedNode *N, 507d306a530fca74e40916121f5583e0545e470b3c4Ted Kremenek LocationContextMap &LCM, 5083bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose ArrayRef<BugReporterVisitor *> visitors) { 5098966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek 5103106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek SourceManager& SMgr = PDB.getSourceManager(); 51159950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek const LocationContext *LC = PDB.LC; 5129c378f705405d37f49795d5e915989de774fe11fTed Kremenek const ExplodedNode *NextNode = N->pred_empty() 5133106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek ? NULL : *(N->pred_begin()); 514368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks 51556a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks StackDiagVector CallStack; 516368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks 5173106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek while (NextNode) { 5181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump N = NextNode; 51959950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek PDB.LC = N->getLocationContext(); 5200f8579274a010f360a371b53101859d9d6052314Anna Zaks NextNode = N->getFirstPred(); 5211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 52261f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek ProgramPoint P = N->getLocation(); 52380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks 52480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks do { 5257a95de68c093991047ed8d339479ccad51b88663David Blaikie if (Optional<CallExitEnd> CE = P.getAs<CallExitEnd>()) { 52680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PathDiagnosticCallPiece *C = 52780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PathDiagnosticCallPiece::construct(N, *CE, SMgr); 528d306a530fca74e40916121f5583e0545e470b3c4Ted Kremenek // Record the mapping from call piece to LocationContext. 529bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek LCM[&C->path] = CE->getCalleeContext(); 53080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(C); 53180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.pushActivePath(&C->path); 53280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks CallStack.push_back(StackDiagPair(C, N)); 53380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks break; 5349373937945e1e075dfa08169eaccc1ad0b31f699Anna Zaks } 535183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose 5367a95de68c093991047ed8d339479ccad51b88663David Blaikie if (Optional<CallEnter> CE = P.getAs<CallEnter>()) { 53780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // Flush all locations, and pop the active path. 53880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks bool VisitedEntireCall = PD.isWithinCall(); 53980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.popActivePath(); 54080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks 54180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // Either we just added a bunch of stuff to the top-level path, or 54280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // we have a previous CallExitEnd. If the former, it means that the 54380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // path terminated within a function call. We must then take the 54480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // current contents of the active path and place it within 54580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // a new PathDiagnosticCallPiece. 54680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PathDiagnosticCallPiece *C; 54780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks if (VisitedEntireCall) { 54880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks C = cast<PathDiagnosticCallPiece>(PD.getActivePath().front()); 54980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks } else { 55080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks const Decl *Caller = CE->getLocationContext()->getDecl(); 55180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks C = PathDiagnosticCallPiece::construct(PD.getActivePath(), Caller); 552d306a530fca74e40916121f5583e0545e470b3c4Ted Kremenek // Record the mapping from call piece to LocationContext. 553bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek LCM[&C->path] = CE->getCalleeContext(); 55480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks } 55580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks 55680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks C->setCallee(*CE, SMgr); 55780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks if (!CallStack.empty()) { 55880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks assert(CallStack.back().first == C); 55980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks CallStack.pop_back(); 56080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks } 56180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks break; 562368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks } 5631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5647a95de68c093991047ed8d339479ccad51b88663David Blaikie if (Optional<BlockEdge> BE = P.getAs<BlockEdge>()) { 56580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks const CFGBlock *Src = BE->getSrc(); 56680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks const CFGBlock *Dst = BE->getDst(); 56780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks const Stmt *T = Src->getTerminator(); 5681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 56980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks if (!T) 57080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks break; 5711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 57280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PathDiagnosticLocation Start = 57380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PathDiagnosticLocation::createBegin(T, SMgr, 57480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks N->getLocationContext()); 5751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 57680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks switch (T->getStmtClass()) { 57761f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek default: 57861f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek break; 5791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 58061f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek case Stmt::GotoStmtClass: 5811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump case Stmt::IndirectGotoStmtClass: { 5820f8579274a010f360a371b53101859d9d6052314Anna Zaks const Stmt *S = PathDiagnosticLocation::getNextStmt(N); 5831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 58461f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek if (!S) 58580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks break; 5861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 587297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek std::string sbuf; 5881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump llvm::raw_string_ostream os(sbuf); 589d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek const PathDiagnosticLocation &End = PDB.getEnclosingStmtLocation(S); 5901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 59100605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek os << "Control jumps to line " 59280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks << End.asLocation().getExpansionLineNumber(); 59380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 59480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, os.str())); 59561f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek break; 59661f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek } 5971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump case Stmt::SwitchStmtClass: { 59961f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek // Figure out what case arm we took. 600297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek std::string sbuf; 601297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek llvm::raw_string_ostream os(sbuf); 6021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6039c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (const Stmt *S = Dst->getLabel()) { 604220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks PathDiagnosticLocation End(S, SMgr, LC); 6051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6065a429954aedd8a830a70fcea2cb51561673e4fc3Ted Kremenek switch (S->getStmtClass()) { 60780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks default: 60880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks os << "No cases match in the switch statement. " 60980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks "Control jumps to line " 61080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks << End.asLocation().getExpansionLineNumber(); 61180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks break; 61280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks case Stmt::DefaultStmtClass: 61380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks os << "Control jumps to the 'default' case at line " 61480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks << End.asLocation().getExpansionLineNumber(); 61580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks break; 61680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks 61780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks case Stmt::CaseStmtClass: { 61880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks os << "Control jumps to 'case "; 61980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks const CaseStmt *Case = cast<CaseStmt>(S); 62080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks const Expr *LHS = Case->getLHS()->IgnoreParenCasts(); 62180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks 62280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // Determine if it is an enum. 62380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks bool GetRawInt = true; 62480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks 62580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(LHS)) { 62680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // FIXME: Maybe this should be an assertion. Are there cases 62780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // were it is not an EnumConstantDecl? 62880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks const EnumConstantDecl *D = 62903509aea098772644bf4662dc1c88634818ceeccZhongxing Xu dyn_cast<EnumConstantDecl>(DR->getDecl()); 6301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 63180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks if (D) { 63280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks GetRawInt = false; 63380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks os << *D; 6345a429954aedd8a830a70fcea2cb51561673e4fc3Ted Kremenek } 63580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks } 6369ec64d6e2fe575b297e1eaa5051efc2983373e25Eli Friedman 63780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks if (GetRawInt) 63880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks os << LHS->EvaluateKnownConstInt(PDB.getASTContext()); 6399ec64d6e2fe575b297e1eaa5051efc2983373e25Eli Friedman 64080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks os << ":' at line " 64180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks << End.asLocation().getExpansionLineNumber(); 64280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks break; 64361f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek } 64480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks } 64580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 64680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, os.str())); 64761f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek } 648567839273dfc395a459cbe77d5f8d128b9ae85bfTed Kremenek else { 649c3517ebb48a51e146badc08bc3684520c41da6c8Ted Kremenek os << "'Default' branch taken. "; 6501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const PathDiagnosticLocation &End = PDB.ExecutionContinues(os, N); 65180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 65280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, os.str())); 653567839273dfc395a459cbe77d5f8d128b9ae85bfTed Kremenek } 6541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 65561f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek break; 65661f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek } 6571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6582673c9ff76ebdb72b7f846e2ff1e0f4256372e19Ted Kremenek case Stmt::BreakStmtClass: 6592673c9ff76ebdb72b7f846e2ff1e0f4256372e19Ted Kremenek case Stmt::ContinueStmtClass: { 660297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek std::string sbuf; 661297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek llvm::raw_string_ostream os(sbuf); 66200605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(os, N); 66380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 66480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, os.str())); 6652673c9ff76ebdb72b7f846e2ff1e0f4256372e19Ted Kremenek break; 6662673c9ff76ebdb72b7f846e2ff1e0f4256372e19Ted Kremenek } 6671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 66880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // Determine control-flow for ternary '?'. 66956ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall case Stmt::BinaryConditionalOperatorClass: 670706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek case Stmt::ConditionalOperatorClass: { 671297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek std::string sbuf; 672297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek llvm::raw_string_ostream os(sbuf); 6731d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek os << "'?' condition is "; 6741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 675706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek if (*(Src->succ_begin()+1) == Dst) 676082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek os << "false"; 677706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek else 678082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek os << "true"; 6791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 68000605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(N); 6811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6821d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek if (const Stmt *S = End.asStmt()) 6831d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek End = PDB.getEnclosingStmtLocation(S); 6841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 68580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 68680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, os.str())); 687babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek break; 688babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek } 6891eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 69080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // Determine control-flow for short-circuited '&&' and '||'. 691babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek case Stmt::BinaryOperatorClass: { 692babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek if (!PDB.supportsLogicalOpControlFlow()) 693babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek break; 6941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 69503509aea098772644bf4662dc1c88634818ceeccZhongxing Xu const BinaryOperator *B = cast<BinaryOperator>(T); 696babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek std::string sbuf; 697babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek llvm::raw_string_ostream os(sbuf); 698babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek os << "Left side of '"; 6991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7002de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall if (B->getOpcode() == BO_LAnd) { 701f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek os << "&&" << "' is "; 7021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 703f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek if (*(Src->succ_begin()+1) == Dst) { 704f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek os << "false"; 705220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks PathDiagnosticLocation End(B->getLHS(), SMgr, LC); 7060cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks PathDiagnosticLocation Start = 70780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PathDiagnosticLocation::createOperatorLoc(B, SMgr); 70880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 70980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, os.str())); 7101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 711f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek else { 712f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek os << "true"; 713220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks PathDiagnosticLocation Start(B->getLHS(), SMgr, LC); 714f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(N); 71580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 71680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, os.str())); 7171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 718babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek } 719babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek else { 7202de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall assert(B->getOpcode() == BO_LOr); 721f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek os << "||" << "' is "; 7221eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 723f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek if (*(Src->succ_begin()+1) == Dst) { 724f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek os << "false"; 725220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks PathDiagnosticLocation Start(B->getLHS(), SMgr, LC); 726f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(N); 72780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 72880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, os.str())); 729f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek } 730f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek else { 731f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek os << "true"; 732220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks PathDiagnosticLocation End(B->getLHS(), SMgr, LC); 7330cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks PathDiagnosticLocation Start = 73480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PathDiagnosticLocation::createOperatorLoc(B, SMgr); 73580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 73680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, os.str())); 737f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek } 738babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek } 7391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 740706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek break; 741706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek } 7421eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump case Stmt::DoStmtClass: { 744706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek if (*(Src->succ_begin()) == Dst) { 745297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek std::string sbuf; 746297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek llvm::raw_string_ostream os(sbuf); 7471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 748c3517ebb48a51e146badc08bc3684520c41da6c8Ted Kremenek os << "Loop condition is true. "; 749d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(os, N); 7501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 751d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek if (const Stmt *S = End.asStmt()) 752d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek End = PDB.getEnclosingStmtLocation(S); 7531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 75480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 75580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, os.str())); 756082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek } 757082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek else { 75800605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(N); 7591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 760d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek if (const Stmt *S = End.asStmt()) 761d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek End = PDB.getEnclosingStmtLocation(S); 7621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 76380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 76480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, "Loop condition is false. Exiting loop")); 7653106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 7661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7673106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 7683106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 7691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7703106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek case Stmt::WhileStmtClass: 7711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump case Stmt::ForStmtClass: { 7723106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (*(Src->succ_begin()+1) == Dst) { 7733106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek std::string sbuf; 7743106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek llvm::raw_string_ostream os(sbuf); 7751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7763106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek os << "Loop condition is false. "; 7773106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(os, N); 7783106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (const Stmt *S = End.asStmt()) 7793106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek End = PDB.getEnclosingStmtLocation(S); 7801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 78180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 78280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, os.str())); 7833106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 7843106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek else { 7853106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(N); 7863106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (const Stmt *S = End.asStmt()) 7873106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek End = PDB.getEnclosingStmtLocation(S); 7881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 78980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 79080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, "Loop condition is true. Entering loop body")); 7913106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 7921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7933106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 7943106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 7951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7963106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek case Stmt::IfStmtClass: { 7973106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(N); 7981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7993106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (const Stmt *S = End.asStmt()) 8003106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek End = PDB.getEnclosingStmtLocation(S); 8011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8023106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (*(Src->succ_begin()+1) == Dst) 80380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 80480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, "Taking false branch")); 8051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump else 80680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 80780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, "Taking true branch")); 8081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8093106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 8103106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 81180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks } 8123106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 81380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks } while(0); 8141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 815dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek if (NextNode) { 8168e6431adab313e283a992698f6fc7afe62420999Anna Zaks // Add diagnostic pieces from custom visitors. 8178e6431adab313e283a992698f6fc7afe62420999Anna Zaks BugReport *R = PDB.getBugReport(); 8183bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose for (ArrayRef<BugReporterVisitor *>::iterator I = visitors.begin(), 8193bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose E = visitors.end(); 8203bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose I != E; ++I) { 821368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks if (PathDiagnosticPiece *p = (*I)->VisitNode(N, NextNode, PDB, *R)) { 8222042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.getActivePath().push_front(p); 823368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks updateStackPiecesWithMessage(p, CallStack); 824368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks } 825dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek } 8268966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek } 8273106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 8281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8298347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose if (!PDB.getBugReport()->isValid()) 8308347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose return false; 8318347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose 83214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // After constructing the full PathDiagnostic, do a pass over it to compact 83314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // PathDiagnosticPieces that occur within a macro. 83477d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek CompactPathDiagnostic(PD.getMutablePieces(), PDB.getSourceManager()); 8358347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose return true; 8363106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 8373106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 8383106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 8395fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek// "Extensive" PathDiagnostic generation. 8405fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek//===----------------------------------------------------------------------===// 8415fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek 8425fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenekstatic bool IsControlFlowExpr(const Stmt *S) { 8435fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek const Expr *E = dyn_cast<Expr>(S); 8441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8455fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek if (!E) 8465fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek return false; 8471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump E = E->IgnoreParenCasts(); 8491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 85056ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall if (isa<AbstractConditionalOperator>(E)) 8515fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek return true; 8521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8535fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek if (const BinaryOperator *B = dyn_cast<BinaryOperator>(E)) 8545fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek if (B->isLogicalOp()) 8555fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek return true; 8561eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return false; 8585fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek} 8595fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek 86014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremeneknamespace { 861ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass ContextLocation : public PathDiagnosticLocation { 8628f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek bool IsDead; 8638f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenekpublic: 8648f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek ContextLocation(const PathDiagnosticLocation &L, bool isdead = false) 8658f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek : PathDiagnosticLocation(L), IsDead(isdead) {} 8661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump void markDead() { IsDead = true; } 8688f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek bool isDead() const { return IsDead; } 8698f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek}; 8701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 871e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenekstatic PathDiagnosticLocation cleanUpLocation(PathDiagnosticLocation L, 872e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek const LocationContext *LC, 873e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek bool firstCharOnly = false) { 874e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek if (const Stmt *S = L.asStmt()) { 875e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek const Stmt *Original = S; 876e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek while (1) { 877e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek // Adjust the location for some expressions that are best referenced 878e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek // by one of their subexpressions. 879e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek switch (S->getStmtClass()) { 880e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek default: 881e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek break; 882e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek case Stmt::ParenExprClass: 883e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek case Stmt::GenericSelectionExprClass: 884e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek S = cast<Expr>(S)->IgnoreParens(); 885e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek firstCharOnly = true; 886e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek continue; 887e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek case Stmt::BinaryConditionalOperatorClass: 888e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek case Stmt::ConditionalOperatorClass: 889e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek S = cast<AbstractConditionalOperator>(S)->getCond(); 890e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek firstCharOnly = true; 891e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek continue; 892e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek case Stmt::ChooseExprClass: 893e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek S = cast<ChooseExpr>(S)->getCond(); 894e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek firstCharOnly = true; 895e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek continue; 896e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek case Stmt::BinaryOperatorClass: 897e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek S = cast<BinaryOperator>(S)->getLHS(); 898e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek firstCharOnly = true; 899e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek continue; 900e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek } 901e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek 902e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek break; 903e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek } 904e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek 905e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek if (S != Original) 906e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek L = PathDiagnosticLocation(S, L.getManager(), LC); 907e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek } 908e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek 909e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek if (firstCharOnly) 910e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek L = PathDiagnosticLocation::createSingleLocation(L); 911e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek 912e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek return L; 913e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek} 914e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek 915ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass EdgeBuilder { 9168f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek std::vector<ContextLocation> CLocs; 9178f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek typedef std::vector<ContextLocation>::iterator iterator; 91814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek PathDiagnostic &PD; 91914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek PathDiagnosticBuilder &PDB; 92014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek PathDiagnosticLocation PrevLoc; 9211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9228f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek bool IsConsumedExpr(const PathDiagnosticLocation &L); 9231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 92414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek bool containsLocation(const PathDiagnosticLocation &Container, 92514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek const PathDiagnosticLocation &Containee); 9261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 92714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek PathDiagnosticLocation getContextLocation(const PathDiagnosticLocation &L); 9281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 93114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek void popLocation() { 9328f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek if (!CLocs.back().isDead() && CLocs.back().asLocation().isFileID()) { 9335c7168cbe8a0eabd05e0e12e469090d2cabd27c0Ted Kremenek // For contexts, we only one the first character as the range. 934e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek rawAddEdge(cleanUpLocation(CLocs.back(), PDB.LC, true)); 9355c7168cbe8a0eabd05e0e12e469090d2cabd27c0Ted Kremenek } 93614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek CLocs.pop_back(); 93714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 9381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 93914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekpublic: 94014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek EdgeBuilder(PathDiagnostic &pd, PathDiagnosticBuilder &pdb) 94114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek : PD(pd), PDB(pdb) { 9421eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 943a301a6773db085575ac51e3c966858180390c25bTed Kremenek // If the PathDiagnostic already has pieces, add the enclosing statement 944a301a6773db085575ac51e3c966858180390c25bTed Kremenek // of the first piece as a context as well. 945802e02463b880f53a6e645bde78cc412481ce9e0Ted Kremenek if (!PD.path.empty()) { 946ed866e73bab7733f5226f84c52edefe23d694b2fTed Kremenek PrevLoc = (*PD.path.begin())->getLocation(); 9471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 94814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (const Stmt *S = PrevLoc.asStmt()) 949e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek addExtendedContext(PDB.getEnclosingStmtLocation(S).asStmt()); 95014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 95114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 95214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 95314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek ~EdgeBuilder() { 95414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek while (!CLocs.empty()) popLocation(); 9550cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks 956a301a6773db085575ac51e3c966858180390c25bTed Kremenek // Finally, add an initial edge from the start location of the first 957a301a6773db085575ac51e3c966858180390c25bTed Kremenek // statement (if it doesn't already exist). 9580cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks PathDiagnosticLocation L = PathDiagnosticLocation::createDeclBegin( 95959950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek PDB.LC, 9600cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks PDB.getSourceManager()); 9610cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks if (L.isValid()) 9620cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks rawAddEdge(L); 96314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 96414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 9655de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek void flushLocations() { 9665de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek while (!CLocs.empty()) 9675de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek popLocation(); 9685de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek PrevLoc = PathDiagnosticLocation(); 9695de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek } 9705de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek 9713ea09a802f973c2726b2a489ae08a4bded93410bJordan Rose void addEdge(PathDiagnosticLocation NewLoc, bool alwaysAdd = false, 9723ea09a802f973c2726b2a489ae08a4bded93410bJordan Rose bool IsPostJump = false); 9731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9748bd4d037d837e7922c3661d6158229da58a03887Ted Kremenek void rawAddEdge(PathDiagnosticLocation NewLoc); 9751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 97614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek void addContext(const Stmt *S); 977183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose void addContext(const PathDiagnosticLocation &L); 978e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek void addExtendedContext(const Stmt *S); 9791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump}; 98014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} // end anonymous namespace 98114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 98214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 98314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted KremenekPathDiagnosticLocation 98414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted KremenekEdgeBuilder::getContextLocation(const PathDiagnosticLocation &L) { 98514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (const Stmt *S = L.asStmt()) { 98614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (IsControlFlowExpr(S)) 98714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return L; 9881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9891eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return PDB.getEnclosingStmtLocation(S); 99014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 9911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 99214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return L; 99314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} 99414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 99514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekbool EdgeBuilder::containsLocation(const PathDiagnosticLocation &Container, 99614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek const PathDiagnosticLocation &Containee) { 99714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 99814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (Container == Containee) 99914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return true; 10001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 100114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (Container.asDecl()) 100214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return true; 10031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 100414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (const Stmt *S = Containee.asStmt()) 100514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (const Stmt *ContainerS = Container.asStmt()) { 100614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek while (S) { 100714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (S == ContainerS) 100814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return true; 100914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek S = PDB.getParent(S); 101014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 101114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return false; 101214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 101314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 101414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // Less accurate: compare using source ranges. 101514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek SourceRange ContainerR = Container.asRange(); 101614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek SourceRange ContaineeR = Containee.asRange(); 10171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 101814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek SourceManager &SM = PDB.getSourceManager(); 1019402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth SourceLocation ContainerRBeg = SM.getExpansionLoc(ContainerR.getBegin()); 1020402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth SourceLocation ContainerREnd = SM.getExpansionLoc(ContainerR.getEnd()); 1021402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth SourceLocation ContaineeRBeg = SM.getExpansionLoc(ContaineeR.getBegin()); 1022402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth SourceLocation ContaineeREnd = SM.getExpansionLoc(ContaineeR.getEnd()); 10231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1024642116259e8df6286063a17361c20e95b5017a0aChandler Carruth unsigned ContainerBegLine = SM.getExpansionLineNumber(ContainerRBeg); 1025642116259e8df6286063a17361c20e95b5017a0aChandler Carruth unsigned ContainerEndLine = SM.getExpansionLineNumber(ContainerREnd); 1026642116259e8df6286063a17361c20e95b5017a0aChandler Carruth unsigned ContaineeBegLine = SM.getExpansionLineNumber(ContaineeRBeg); 1027642116259e8df6286063a17361c20e95b5017a0aChandler Carruth unsigned ContaineeEndLine = SM.getExpansionLineNumber(ContaineeREnd); 10281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 102914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek assert(ContainerBegLine <= ContainerEndLine); 10301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump assert(ContaineeBegLine <= ContaineeEndLine); 10311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 103214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return (ContainerBegLine <= ContaineeBegLine && 103314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek ContainerEndLine >= ContaineeEndLine && 103414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek (ContainerBegLine != ContaineeBegLine || 1035a77c031cb66f75d22672070052cc6e0205289ff8Chandler Carruth SM.getExpansionColumnNumber(ContainerRBeg) <= 1036a77c031cb66f75d22672070052cc6e0205289ff8Chandler Carruth SM.getExpansionColumnNumber(ContaineeRBeg)) && 103714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek (ContainerEndLine != ContaineeEndLine || 1038a77c031cb66f75d22672070052cc6e0205289ff8Chandler Carruth SM.getExpansionColumnNumber(ContainerREnd) >= 10396488dc31153be6f98b404c7860be6c66bb4ec917Ted Kremenek SM.getExpansionColumnNumber(ContaineeREnd))); 104014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} 104114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 104214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekvoid EdgeBuilder::rawAddEdge(PathDiagnosticLocation NewLoc) { 104314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (!PrevLoc.isValid()) { 104414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek PrevLoc = NewLoc; 104514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return; 104614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 10471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1048e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek const PathDiagnosticLocation &NewLocClean = cleanUpLocation(NewLoc, PDB.LC); 1049e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek const PathDiagnosticLocation &PrevLocClean = cleanUpLocation(PrevLoc, PDB.LC); 10501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1051a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek if (PrevLocClean.asLocation().isInvalid()) { 1052a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek PrevLoc = NewLoc; 1053a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek return; 1054a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek } 1055a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek 10568c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek if (NewLocClean.asLocation() == PrevLocClean.asLocation()) 105714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return; 10581eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 105914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // FIXME: Ignore intra-macro edges for now. 1060402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth if (NewLocClean.asLocation().getExpansionLoc() == 1061402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth PrevLocClean.asLocation().getExpansionLoc()) 106214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return; 106314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 10642042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(NewLocClean, PrevLocClean)); 10658c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek PrevLoc = NewLoc; 106614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} 106714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 10683ea09a802f973c2726b2a489ae08a4bded93410bJordan Rosevoid EdgeBuilder::addEdge(PathDiagnosticLocation NewLoc, bool alwaysAdd, 10693ea09a802f973c2726b2a489ae08a4bded93410bJordan Rose bool IsPostJump) { 10701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1071a301a6773db085575ac51e3c966858180390c25bTed Kremenek if (!alwaysAdd && NewLoc.asLocation().isMacroID()) 1072a301a6773db085575ac51e3c966858180390c25bTed Kremenek return; 10731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 107414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek const PathDiagnosticLocation &CLoc = getContextLocation(NewLoc); 107514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 107614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek while (!CLocs.empty()) { 10778f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek ContextLocation &TopContextLoc = CLocs.back(); 10781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 107914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // Is the top location context the same as the one for the new location? 108014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (TopContextLoc == CLoc) { 10818f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek if (alwaysAdd) { 10823ea09a802f973c2726b2a489ae08a4bded93410bJordan Rose if (IsConsumedExpr(TopContextLoc)) 10833ea09a802f973c2726b2a489ae08a4bded93410bJordan Rose TopContextLoc.markDead(); 10848f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek 108514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek rawAddEdge(NewLoc); 10868f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek } 108714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 10883ea09a802f973c2726b2a489ae08a4bded93410bJordan Rose if (IsPostJump) 10893ea09a802f973c2726b2a489ae08a4bded93410bJordan Rose TopContextLoc.markDead(); 109014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return; 109114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 109214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 109314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (containsLocation(TopContextLoc, CLoc)) { 10948f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek if (alwaysAdd) { 109514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek rawAddEdge(NewLoc); 10961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10973ea09a802f973c2726b2a489ae08a4bded93410bJordan Rose if (IsConsumedExpr(CLoc)) { 10983ea09a802f973c2726b2a489ae08a4bded93410bJordan Rose CLocs.push_back(ContextLocation(CLoc, /*IsDead=*/true)); 10998f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek return; 11008f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek } 11018f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek } 11021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11033ea09a802f973c2726b2a489ae08a4bded93410bJordan Rose CLocs.push_back(ContextLocation(CLoc, /*IsDead=*/IsPostJump)); 11041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return; 110514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 110614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 110714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // Context does not contain the location. Flush it. 110814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek popLocation(); 110914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 11101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11115c7168cbe8a0eabd05e0e12e469090d2cabd27c0Ted Kremenek // If we reach here, there is no enclosing context. Just add the edge. 11125c7168cbe8a0eabd05e0e12e469090d2cabd27c0Ted Kremenek rawAddEdge(NewLoc); 111314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} 111414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 11158f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenekbool EdgeBuilder::IsConsumedExpr(const PathDiagnosticLocation &L) { 11168f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek if (const Expr *X = dyn_cast_or_null<Expr>(L.asStmt())) 11178f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek return PDB.getParentMap().isConsumedExpr(X) && !IsControlFlowExpr(X); 11181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11198f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek return false; 11208f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek} 11211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1122e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenekvoid EdgeBuilder::addExtendedContext(const Stmt *S) { 1123e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek if (!S) 1124e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek return; 11251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const Stmt *Parent = PDB.getParent(S); 1127e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek while (Parent) { 1128e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek if (isa<CompoundStmt>(Parent)) 1129e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek Parent = PDB.getParent(Parent); 1130e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek else 1131e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek break; 1132e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek } 1133e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek 1134e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek if (Parent) { 1135e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek switch (Parent->getStmtClass()) { 1136e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek case Stmt::DoStmtClass: 1137e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek case Stmt::ObjCAtSynchronizedStmtClass: 1138e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek addContext(Parent); 1139e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek default: 1140e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek break; 1141e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek } 1142e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek } 11431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1144e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek addContext(S); 1145e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek} 11461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 114714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekvoid EdgeBuilder::addContext(const Stmt *S) { 114814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (!S) 114914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return; 115014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 115159950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek PathDiagnosticLocation L(S, PDB.getSourceManager(), PDB.LC); 1152183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose addContext(L); 1153183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose} 11541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1155183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rosevoid EdgeBuilder::addContext(const PathDiagnosticLocation &L) { 115614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek while (!CLocs.empty()) { 115714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek const PathDiagnosticLocation &TopContextLoc = CLocs.back(); 115814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 115914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // Is the top location context the same as the one for the new location? 116014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (TopContextLoc == L) 116114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return; 116214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 116314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (containsLocation(TopContextLoc, L)) { 116414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek CLocs.push_back(L); 11651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return; 116614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 116714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 116814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // Context does not contain the location. Flush it. 116914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek popLocation(); 117014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 117114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 117214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek CLocs.push_back(L); 117314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} 117414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 117511abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// Cone-of-influence: support the reverse propagation of "interesting" symbols 117611abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// and values by tracing interesting calculations backwards through evaluated 117711abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// expressions along a path. This is probably overly complicated, but the idea 117811abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// is that if an expression computed an "interesting" value, the child 117911abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// expressions are are also likely to be "interesting" as well (which then 118011abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// propagates to the values they in turn compute). This reverse propagation 118111abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// is needed to track interesting correlations across function call boundaries, 118211abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// where formal arguments bind to actual arguments, etc. This is also needed 118311abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// because the constraint solver sometimes simplifies certain symbolic values 118411abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// into constants when appropriate, and this complicates reasoning about 118511abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// interesting values. 118611abcecc8c919673237cf37384290a1ef1943976Ted Kremenektypedef llvm::DenseSet<const Expr *> InterestingExprs; 118711abcecc8c919673237cf37384290a1ef1943976Ted Kremenek 118811abcecc8c919673237cf37384290a1ef1943976Ted Kremenekstatic void reversePropagateIntererstingSymbols(BugReport &R, 118911abcecc8c919673237cf37384290a1ef1943976Ted Kremenek InterestingExprs &IE, 119011abcecc8c919673237cf37384290a1ef1943976Ted Kremenek const ProgramState *State, 119111abcecc8c919673237cf37384290a1ef1943976Ted Kremenek const Expr *Ex, 119211abcecc8c919673237cf37384290a1ef1943976Ted Kremenek const LocationContext *LCtx) { 119311abcecc8c919673237cf37384290a1ef1943976Ted Kremenek SVal V = State->getSVal(Ex, LCtx); 119411abcecc8c919673237cf37384290a1ef1943976Ted Kremenek if (!(R.isInteresting(V) || IE.count(Ex))) 119511abcecc8c919673237cf37384290a1ef1943976Ted Kremenek return; 119611abcecc8c919673237cf37384290a1ef1943976Ted Kremenek 119711abcecc8c919673237cf37384290a1ef1943976Ted Kremenek switch (Ex->getStmtClass()) { 119811abcecc8c919673237cf37384290a1ef1943976Ted Kremenek default: 119911abcecc8c919673237cf37384290a1ef1943976Ted Kremenek if (!isa<CastExpr>(Ex)) 120011abcecc8c919673237cf37384290a1ef1943976Ted Kremenek break; 120111abcecc8c919673237cf37384290a1ef1943976Ted Kremenek // Fall through. 120211abcecc8c919673237cf37384290a1ef1943976Ted Kremenek case Stmt::BinaryOperatorClass: 120311abcecc8c919673237cf37384290a1ef1943976Ted Kremenek case Stmt::UnaryOperatorClass: { 120411abcecc8c919673237cf37384290a1ef1943976Ted Kremenek for (Stmt::const_child_iterator CI = Ex->child_begin(), 120511abcecc8c919673237cf37384290a1ef1943976Ted Kremenek CE = Ex->child_end(); 120611abcecc8c919673237cf37384290a1ef1943976Ted Kremenek CI != CE; ++CI) { 120711abcecc8c919673237cf37384290a1ef1943976Ted Kremenek if (const Expr *child = dyn_cast_or_null<Expr>(*CI)) { 120811abcecc8c919673237cf37384290a1ef1943976Ted Kremenek IE.insert(child); 120911abcecc8c919673237cf37384290a1ef1943976Ted Kremenek SVal ChildV = State->getSVal(child, LCtx); 121011abcecc8c919673237cf37384290a1ef1943976Ted Kremenek R.markInteresting(ChildV); 121111abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 121211abcecc8c919673237cf37384290a1ef1943976Ted Kremenek break; 121311abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 121411abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 121511abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 121611abcecc8c919673237cf37384290a1ef1943976Ted Kremenek 121711abcecc8c919673237cf37384290a1ef1943976Ted Kremenek R.markInteresting(V); 121811abcecc8c919673237cf37384290a1ef1943976Ted Kremenek} 121911abcecc8c919673237cf37384290a1ef1943976Ted Kremenek 122011abcecc8c919673237cf37384290a1ef1943976Ted Kremenekstatic void reversePropagateInterestingSymbols(BugReport &R, 122111abcecc8c919673237cf37384290a1ef1943976Ted Kremenek InterestingExprs &IE, 122211abcecc8c919673237cf37384290a1ef1943976Ted Kremenek const ProgramState *State, 122311abcecc8c919673237cf37384290a1ef1943976Ted Kremenek const LocationContext *CalleeCtx, 122411abcecc8c919673237cf37384290a1ef1943976Ted Kremenek const LocationContext *CallerCtx) 122511abcecc8c919673237cf37384290a1ef1943976Ted Kremenek{ 1226852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose // FIXME: Handle non-CallExpr-based CallEvents. 122711abcecc8c919673237cf37384290a1ef1943976Ted Kremenek const StackFrameContext *Callee = CalleeCtx->getCurrentStackFrame(); 122811abcecc8c919673237cf37384290a1ef1943976Ted Kremenek const Stmt *CallSite = Callee->getCallSite(); 1229852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose if (const CallExpr *CE = dyn_cast_or_null<CallExpr>(CallSite)) { 123011abcecc8c919673237cf37384290a1ef1943976Ted Kremenek if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CalleeCtx->getDecl())) { 123111abcecc8c919673237cf37384290a1ef1943976Ted Kremenek FunctionDecl::param_const_iterator PI = FD->param_begin(), 123211abcecc8c919673237cf37384290a1ef1943976Ted Kremenek PE = FD->param_end(); 123311abcecc8c919673237cf37384290a1ef1943976Ted Kremenek CallExpr::const_arg_iterator AI = CE->arg_begin(), AE = CE->arg_end(); 123411abcecc8c919673237cf37384290a1ef1943976Ted Kremenek for (; AI != AE && PI != PE; ++AI, ++PI) { 123511abcecc8c919673237cf37384290a1ef1943976Ted Kremenek if (const Expr *ArgE = *AI) { 123611abcecc8c919673237cf37384290a1ef1943976Ted Kremenek if (const ParmVarDecl *PD = *PI) { 123711abcecc8c919673237cf37384290a1ef1943976Ted Kremenek Loc LV = State->getLValue(PD, CalleeCtx); 123811abcecc8c919673237cf37384290a1ef1943976Ted Kremenek if (R.isInteresting(LV) || R.isInteresting(State->getRawSVal(LV))) 123911abcecc8c919673237cf37384290a1ef1943976Ted Kremenek IE.insert(ArgE); 124011abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 124111abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 124211abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 124311abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 124411abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 124511abcecc8c919673237cf37384290a1ef1943976Ted Kremenek} 12468185674528423e2504a1fae35c28c24104846510Ted Kremenek 1247b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek//===----------------------------------------------------------------------===// 1248b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek// Functions for determining if a loop was executed 0 times. 1249b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek//===----------------------------------------------------------------------===// 1250b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek 1251b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenekstatic bool isLoop(const Stmt *Term) { 12528185674528423e2504a1fae35c28c24104846510Ted Kremenek switch (Term->getStmtClass()) { 12538185674528423e2504a1fae35c28c24104846510Ted Kremenek case Stmt::ForStmtClass: 12548185674528423e2504a1fae35c28c24104846510Ted Kremenek case Stmt::WhileStmtClass: 1255c5b9c8bc6d77175f6d41d898511b1e7b1e2f86f8Ted Kremenek case Stmt::ObjCForCollectionStmtClass: 1256b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek return true; 12578185674528423e2504a1fae35c28c24104846510Ted Kremenek default: 12588185674528423e2504a1fae35c28c24104846510Ted Kremenek // Note that we intentionally do not include do..while here. 12598185674528423e2504a1fae35c28c24104846510Ted Kremenek return false; 12608185674528423e2504a1fae35c28c24104846510Ted Kremenek } 1261b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek} 12628185674528423e2504a1fae35c28c24104846510Ted Kremenek 1263b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenekstatic bool isJumpToFalseBranch(const BlockEdge *BE) { 12648185674528423e2504a1fae35c28c24104846510Ted Kremenek const CFGBlock *Src = BE->getSrc(); 12658185674528423e2504a1fae35c28c24104846510Ted Kremenek assert(Src->succ_size() == 2); 12668185674528423e2504a1fae35c28c24104846510Ted Kremenek return (*(Src->succ_begin()+1) == BE->getDst()); 12678185674528423e2504a1fae35c28c24104846510Ted Kremenek} 12688185674528423e2504a1fae35c28c24104846510Ted Kremenek 1269b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek/// Return true if the terminator is a loop and the destination is the 1270b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek/// false branch. 1271b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenekstatic bool isLoopJumpPastBody(const Stmt *Term, const BlockEdge *BE) { 1272b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek if (!isLoop(Term)) 1273b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek return false; 1274b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek 1275b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek // Did we take the false branch? 1276b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek return isJumpToFalseBranch(BE); 1277b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek} 1278b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek 1279b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenekstatic bool isContainedByStmt(ParentMap &PM, const Stmt *S, const Stmt *SubS) { 1280b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek while (SubS) { 1281b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek if (SubS == S) 1282b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek return true; 1283b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek SubS = PM.getParent(SubS); 1284b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek } 1285b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek return false; 1286b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek} 1287b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek 1288b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenekstatic const Stmt *getStmtBeforeCond(ParentMap &PM, const Stmt *Term, 1289b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek const ExplodedNode *N) { 1290b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek while (N) { 1291b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek Optional<StmtPoint> SP = N->getLocation().getAs<StmtPoint>(); 1292b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek if (SP) { 1293b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek const Stmt *S = SP->getStmt(); 1294b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek if (!isContainedByStmt(PM, Term, S)) 1295b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek return S; 1296b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek } 12970f8579274a010f360a371b53101859d9d6052314Anna Zaks N = N->getFirstPred(); 1298b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek } 1299b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek return 0; 1300b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek} 1301b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek 1302b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenekstatic bool isInLoopBody(ParentMap &PM, const Stmt *S, const Stmt *Term) { 1303b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek const Stmt *LoopBody = 0; 1304b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek switch (Term->getStmtClass()) { 1305b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek case Stmt::ForStmtClass: { 1306b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek const ForStmt *FS = cast<ForStmt>(Term); 1307b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek if (isContainedByStmt(PM, FS->getInc(), S)) 1308b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek return true; 1309b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek LoopBody = FS->getBody(); 1310b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek break; 1311b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek } 1312c5b9c8bc6d77175f6d41d898511b1e7b1e2f86f8Ted Kremenek case Stmt::ObjCForCollectionStmtClass: { 1313c5b9c8bc6d77175f6d41d898511b1e7b1e2f86f8Ted Kremenek const ObjCForCollectionStmt *FC = cast<ObjCForCollectionStmt>(Term); 1314c5b9c8bc6d77175f6d41d898511b1e7b1e2f86f8Ted Kremenek LoopBody = FC->getBody(); 1315c5b9c8bc6d77175f6d41d898511b1e7b1e2f86f8Ted Kremenek break; 1316c5b9c8bc6d77175f6d41d898511b1e7b1e2f86f8Ted Kremenek } 1317b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek case Stmt::WhileStmtClass: 1318b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek LoopBody = cast<WhileStmt>(Term)->getBody(); 1319b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek break; 1320b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek default: 1321b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek return false; 1322b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek } 1323b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek return isContainedByStmt(PM, LoopBody, S); 1324b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek} 1325b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek 1326b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek//===----------------------------------------------------------------------===// 1327b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek// Top-level logic for generating extensive path diagnostics. 1328b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek//===----------------------------------------------------------------------===// 1329b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek 13308347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rosestatic bool GenerateExtensivePathDiagnostic(PathDiagnostic& PD, 133114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek PathDiagnosticBuilder &PDB, 13323bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose const ExplodedNode *N, 1333d306a530fca74e40916121f5583e0545e470b3c4Ted Kremenek LocationContextMap &LCM, 13343bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose ArrayRef<BugReporterVisitor *> visitors) { 133514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek EdgeBuilder EB(PD, PDB); 13360cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks const SourceManager& SM = PDB.getSourceManager(); 133756a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks StackDiagVector CallStack; 133811abcecc8c919673237cf37384290a1ef1943976Ted Kremenek InterestingExprs IE; 133914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 13409c378f705405d37f49795d5e915989de774fe11fTed Kremenek const ExplodedNode *NextNode = N->pred_empty() ? NULL : *(N->pred_begin()); 134114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek while (NextNode) { 134214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek N = NextNode; 13430f8579274a010f360a371b53101859d9d6052314Anna Zaks NextNode = N->getFirstPred(); 134414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek ProgramPoint P = N->getLocation(); 134514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 1346dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek do { 13477a95de68c093991047ed8d339479ccad51b88663David Blaikie if (Optional<PostStmt> PS = P.getAs<PostStmt>()) { 134811abcecc8c919673237cf37384290a1ef1943976Ted Kremenek if (const Expr *Ex = PS->getStmtAs<Expr>()) 134911abcecc8c919673237cf37384290a1ef1943976Ted Kremenek reversePropagateIntererstingSymbols(*PDB.getBugReport(), IE, 135011abcecc8c919673237cf37384290a1ef1943976Ted Kremenek N->getState().getPtr(), Ex, 135111abcecc8c919673237cf37384290a1ef1943976Ted Kremenek N->getLocationContext()); 135211abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 135311abcecc8c919673237cf37384290a1ef1943976Ted Kremenek 13547a95de68c093991047ed8d339479ccad51b88663David Blaikie if (Optional<CallExitEnd> CE = P.getAs<CallExitEnd>()) { 1355183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose const Stmt *S = CE->getCalleeContext()->getCallSite(); 1356183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose if (const Expr *Ex = dyn_cast_or_null<Expr>(S)) { 1357852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose reversePropagateIntererstingSymbols(*PDB.getBugReport(), IE, 1358852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose N->getState().getPtr(), Ex, 1359852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose N->getLocationContext()); 1360852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose } 1361183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose 1362183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose PathDiagnosticCallPiece *C = 1363183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose PathDiagnosticCallPiece::construct(N, *CE, SM); 1364bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek LCM[&C->path] = CE->getCalleeContext(); 1365183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose 13663ea09a802f973c2726b2a489ae08a4bded93410bJordan Rose EB.addEdge(C->callReturn, /*AlwaysAdd=*/true, /*IsPostJump=*/true); 1367183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose EB.flushLocations(); 1368183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose 1369183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose PD.getActivePath().push_front(C); 1370183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose PD.pushActivePath(&C->path); 1371183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose CallStack.push_back(StackDiagPair(C, N)); 13725de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek break; 13735de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek } 13744ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek 13752042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek // Pop the call hierarchy if we are done walking the contents 13762042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek // of a function call. 13777a95de68c093991047ed8d339479ccad51b88663David Blaikie if (Optional<CallEnter> CE = P.getAs<CallEnter>()) { 1378097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted Kremenek // Add an edge to the start of the function. 1379097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted Kremenek const Decl *D = CE->getCalleeContext()->getDecl(); 1380097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted Kremenek PathDiagnosticLocation pos = 1381097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted Kremenek PathDiagnosticLocation::createBegin(D, SM); 1382097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted Kremenek EB.addEdge(pos); 1383097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted Kremenek 1384097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted Kremenek // Flush all locations, and pop the active path. 1385183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose bool VisitedEntireCall = PD.isWithinCall(); 13864ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek EB.flushLocations(); 13872042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.popActivePath(); 13884ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek PDB.LC = N->getLocationContext(); 1389097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted Kremenek 1390183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose // Either we just added a bunch of stuff to the top-level path, or 1391183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose // we have a previous CallExitEnd. If the former, it means that the 13922042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek // path terminated within a function call. We must then take the 13932042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek // current contents of the active path and place it within 13942042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek // a new PathDiagnosticCallPiece. 1395183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose PathDiagnosticCallPiece *C; 1396183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose if (VisitedEntireCall) { 1397183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose C = cast<PathDiagnosticCallPiece>(PD.getActivePath().front()); 1398183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose } else { 1399183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose const Decl *Caller = CE->getLocationContext()->getDecl(); 14009373937945e1e075dfa08169eaccc1ad0b31f699Anna Zaks C = PathDiagnosticCallPiece::construct(PD.getActivePath(), Caller); 1401bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek LCM[&C->path] = CE->getCalleeContext(); 14029373937945e1e075dfa08169eaccc1ad0b31f699Anna Zaks } 1403852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose 1404183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose C->setCallee(*CE, SM); 1405183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose EB.addContext(C->getLocation()); 1406368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks 1407368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks if (!CallStack.empty()) { 140856a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks assert(CallStack.back().first == C); 1409368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks CallStack.pop_back(); 1410368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks } 14112042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek break; 14122042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek } 14134ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek 14144ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek // Note that is important that we update the LocationContext 14154ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek // after looking at CallExits. CallExit basically adds an 14164ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek // edge in the *caller*, so we don't want to update the LocationContext 14174ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek // too soon. 14184ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek PDB.LC = N->getLocationContext(); 14195de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek 1420dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek // Block edges. 14217a95de68c093991047ed8d339479ccad51b88663David Blaikie if (Optional<BlockEdge> BE = P.getAs<BlockEdge>()) { 142211abcecc8c919673237cf37384290a1ef1943976Ted Kremenek // Does this represent entering a call? If so, look at propagating 142311abcecc8c919673237cf37384290a1ef1943976Ted Kremenek // interesting symbols across call boundaries. 142411abcecc8c919673237cf37384290a1ef1943976Ted Kremenek if (NextNode) { 142511abcecc8c919673237cf37384290a1ef1943976Ted Kremenek const LocationContext *CallerCtx = NextNode->getLocationContext(); 142611abcecc8c919673237cf37384290a1ef1943976Ted Kremenek const LocationContext *CalleeCtx = PDB.LC; 142711abcecc8c919673237cf37384290a1ef1943976Ted Kremenek if (CallerCtx != CalleeCtx) { 142811abcecc8c919673237cf37384290a1ef1943976Ted Kremenek reversePropagateInterestingSymbols(*PDB.getBugReport(), IE, 142911abcecc8c919673237cf37384290a1ef1943976Ted Kremenek N->getState().getPtr(), 143011abcecc8c919673237cf37384290a1ef1943976Ted Kremenek CalleeCtx, CallerCtx); 143111abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 143211abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 143311abcecc8c919673237cf37384290a1ef1943976Ted Kremenek 1434dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek // Are we jumping to the head of a loop? Add a special diagnostic. 1435f57a2aa02c0578c5bd834fec0d44c16ad9908620Ted Kremenek if (const Stmt *Loop = BE->getSrc()->getLoopTarget()) { 143659950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek PathDiagnosticLocation L(Loop, SM, PDB.LC); 1437ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek const CompoundStmt *CS = NULL; 14381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1439f57a2aa02c0578c5bd834fec0d44c16ad9908620Ted Kremenek if (const ForStmt *FS = dyn_cast<ForStmt>(Loop)) 1440f57a2aa02c0578c5bd834fec0d44c16ad9908620Ted Kremenek CS = dyn_cast<CompoundStmt>(FS->getBody()); 1441f57a2aa02c0578c5bd834fec0d44c16ad9908620Ted Kremenek else if (const WhileStmt *WS = dyn_cast<WhileStmt>(Loop)) 1442f57a2aa02c0578c5bd834fec0d44c16ad9908620Ted Kremenek CS = dyn_cast<CompoundStmt>(WS->getBody()); 14431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1444dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek PathDiagnosticEventPiece *p = 1445dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek new PathDiagnosticEventPiece(L, 144607c015cbcee31f72e2d320ba2c713c046bed42faTed Kremenek "Looping back to the head of the loop"); 14472dd17abf11ae64339fa6bfaa57d76e13a5fbe5b8Ted Kremenek p->setPrunable(true); 14481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1449dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek EB.addEdge(p->getLocation(), true); 14502042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.getActivePath().push_front(p); 14511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1452ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek if (CS) { 14530cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks PathDiagnosticLocation BL = 14540cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks PathDiagnosticLocation::createEndBrace(CS, SM); 145507c015cbcee31f72e2d320ba2c713c046bed42faTed Kremenek EB.addEdge(BL); 1456dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek } 14578bd4d037d837e7922c3661d6158229da58a03887Ted Kremenek } 14588185674528423e2504a1fae35c28c24104846510Ted Kremenek 1459b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek const CFGBlock *BSrc = BE->getSrc(); 1460b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek ParentMap &PM = PDB.getParentMap(); 1461b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek 1462b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek if (const Stmt *Term = BSrc->getTerminator()) { 14638185674528423e2504a1fae35c28c24104846510Ted Kremenek // Are we jumping past the loop body without ever executing the 14648185674528423e2504a1fae35c28c24104846510Ted Kremenek // loop (because the condition was false)? 14657a95de68c093991047ed8d339479ccad51b88663David Blaikie if (isLoopJumpPastBody(Term, &*BE) && 1466b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek !isInLoopBody(PM, 1467b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek getStmtBeforeCond(PM, 1468b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek BSrc->getTerminatorCondition(), 1469b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek N), 1470b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek Term)) { 14718185674528423e2504a1fae35c28c24104846510Ted Kremenek PathDiagnosticLocation L(Term, SM, PDB.LC); 14728185674528423e2504a1fae35c28c24104846510Ted Kremenek PathDiagnosticEventPiece *PE = 1473b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek new PathDiagnosticEventPiece(L, "Loop body executed 0 times"); 14748185674528423e2504a1fae35c28c24104846510Ted Kremenek PE->setPrunable(true); 14758185674528423e2504a1fae35c28c24104846510Ted Kremenek 14768185674528423e2504a1fae35c28c24104846510Ted Kremenek EB.addEdge(PE->getLocation(), true); 14778185674528423e2504a1fae35c28c24104846510Ted Kremenek PD.getActivePath().push_front(PE); 14788185674528423e2504a1fae35c28c24104846510Ted Kremenek } 14798185674528423e2504a1fae35c28c24104846510Ted Kremenek 1480b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek // In any case, add the terminator as the current statement 1481b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek // context for control edges. 1482ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek EB.addContext(Term); 14838185674528423e2504a1fae35c28c24104846510Ted Kremenek } 14841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1485dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek break; 14868bd4d037d837e7922c3661d6158229da58a03887Ted Kremenek } 148714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 14887a95de68c093991047ed8d339479ccad51b88663David Blaikie if (Optional<BlockEntrance> BE = P.getAs<BlockEntrance>()) { 1489b07805485c603be3d8011f72611465324c9e664bDavid Blaikie Optional<CFGElement> First = BE->getFirstElement(); 1490b07805485c603be3d8011f72611465324c9e664bDavid Blaikie if (Optional<CFGStmt> S = First ? First->getAs<CFGStmt>() : None) { 1491b07805485c603be3d8011f72611465324c9e664bDavid Blaikie const Stmt *stmt = S->getStmt(); 14923c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek if (IsControlFlowExpr(stmt)) { 1493b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu // Add the proper context for '&&', '||', and '?'. 14943c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek EB.addContext(stmt); 1495b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu } 1496b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu else 14973c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek EB.addExtendedContext(PDB.getEnclosingStmtLocation(stmt).asStmt()); 1498dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek } 1499b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu 1500dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek break; 1501dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek } 15025de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek 15035de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek 1504dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek } while (0); 15051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1506dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek if (!NextNode) 150714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek continue; 15081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15098e6431adab313e283a992698f6fc7afe62420999Anna Zaks // Add pieces from custom visitors. 15108e6431adab313e283a992698f6fc7afe62420999Anna Zaks BugReport *R = PDB.getBugReport(); 15113bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose for (ArrayRef<BugReporterVisitor *>::iterator I = visitors.begin(), 15123bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose E = visitors.end(); 15133bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose I != E; ++I) { 15148e6431adab313e283a992698f6fc7afe62420999Anna Zaks if (PathDiagnosticPiece *p = (*I)->VisitNode(N, NextNode, PDB, *R)) { 15158966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek const PathDiagnosticLocation &Loc = p->getLocation(); 15168966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek EB.addEdge(Loc, true); 15172042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.getActivePath().push_front(p); 1518368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks updateStackPiecesWithMessage(p, CallStack); 1519368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks 15208966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek if (const Stmt *S = Loc.asStmt()) 15211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump EB.addExtendedContext(PDB.getEnclosingStmtLocation(S).asStmt()); 15228966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek } 15231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 152414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 15258347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose 15268347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose return PDB.getBugReport()->isValid(); 152714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} 152814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 1529af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek/// \brief Adds a sanitized control-flow diagnostic edge to a path. 1530af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenekstatic void addEdgeToPath(PathPieces &path, 1531af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek PathDiagnosticLocation &PrevLoc, 1532af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek PathDiagnosticLocation NewLoc, 1533af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek const LocationContext *LC) { 1534bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek if (!NewLoc.isValid()) 1535af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek return; 1536af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1537bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek SourceLocation NewLocL = NewLoc.asLocation(); 1538bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek if (NewLocL.isInvalid() || NewLocL.isMacroID()) 1539af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek return; 1540af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1541904fd08edbedeb18b16875dd54b3f1edb049e9b9Jordan Rose if (!PrevLoc.isValid() || !PrevLoc.asLocation().isValid()) { 1542af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek PrevLoc = NewLoc; 1543af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek return; 1544af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek } 1545af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1546af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek // FIXME: ignore intra-macro edges for now. 1547bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek if (NewLoc.asLocation().getExpansionLoc() == 1548bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek PrevLoc.asLocation().getExpansionLoc()) 1549af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek return; 1550af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1551bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek path.push_front(new PathDiagnosticControlFlowPiece(NewLoc, 1552bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek PrevLoc)); 1553af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek PrevLoc = NewLoc; 1554af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek} 1555af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1556e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek/// A customized wrapper for CFGBlock::getTerminatorCondition() 1557e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek/// which returns the element for ObjCForCollectionStmts. 1558e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenekstatic const Stmt *getTerminatorCondition(const CFGBlock *B) { 1559e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek const Stmt *S = B->getTerminatorCondition(); 1560e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek if (const ObjCForCollectionStmt *FS = 1561e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek dyn_cast_or_null<ObjCForCollectionStmt>(S)) 1562e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek return FS->getElement(); 1563e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek return S; 1564e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek} 1565e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek 1566f94cb007d03031bcf3d1b02f6a683a189e934953Ted Kremenekstatic const char *StrEnteringLoop = "Entering loop body"; 1567f94cb007d03031bcf3d1b02f6a683a189e934953Ted Kremenekstatic const char *StrLoopBodyZero = "Loop body executed 0 times"; 1568f94cb007d03031bcf3d1b02f6a683a189e934953Ted Kremenek 1569af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenekstatic bool 1570af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted KremenekGenerateAlternateExtensivePathDiagnostic(PathDiagnostic& PD, 1571af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek PathDiagnosticBuilder &PDB, 1572af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek const ExplodedNode *N, 1573af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek LocationContextMap &LCM, 1574af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek ArrayRef<BugReporterVisitor *> visitors) { 1575af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1576af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek BugReport *report = PDB.getBugReport(); 1577af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek const SourceManager& SM = PDB.getSourceManager(); 1578af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek StackDiagVector CallStack; 1579af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek InterestingExprs IE; 1580af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 15815a6fb20841220488f8be7254fbea8ba7233ebcd3Jordan Rose PathDiagnosticLocation PrevLoc = PD.getLocation(); 1582af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1583af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek const ExplodedNode *NextNode = N->getFirstPred(); 1584af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek while (NextNode) { 1585af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek N = NextNode; 1586af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek NextNode = N->getFirstPred(); 1587af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek ProgramPoint P = N->getLocation(); 1588af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1589af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek do { 1590be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek // Have we encountered an entrance to a call? It may be 1591be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek // the case that we have not encountered a matching 1592be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek // call exit before this point. This means that the path 1593be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek // terminated within the call itself. 1594be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek if (Optional<CallEnter> CE = P.getAs<CallEnter>()) { 1595904fd08edbedeb18b16875dd54b3f1edb049e9b9Jordan Rose // Add an edge to the start of the function. 1596904fd08edbedeb18b16875dd54b3f1edb049e9b9Jordan Rose const StackFrameContext *CalleeLC = CE->getCalleeContext(); 1597904fd08edbedeb18b16875dd54b3f1edb049e9b9Jordan Rose const Decl *D = CalleeLC->getDecl(); 1598904fd08edbedeb18b16875dd54b3f1edb049e9b9Jordan Rose addEdgeToPath(PD.getActivePath(), PrevLoc, 1599904fd08edbedeb18b16875dd54b3f1edb049e9b9Jordan Rose PathDiagnosticLocation::createBegin(D, SM), 1600904fd08edbedeb18b16875dd54b3f1edb049e9b9Jordan Rose CalleeLC); 1601904fd08edbedeb18b16875dd54b3f1edb049e9b9Jordan Rose 1602be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek // Did we visit an entire call? 1603be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek bool VisitedEntireCall = PD.isWithinCall(); 1604be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek PD.popActivePath(); 1605be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek 1606be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek PathDiagnosticCallPiece *C; 1607be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek if (VisitedEntireCall) { 1608be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek PathDiagnosticPiece *P = PD.getActivePath().front().getPtr(); 1609be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek C = cast<PathDiagnosticCallPiece>(P); 1610be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek } else { 1611be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek const Decl *Caller = CE->getLocationContext()->getDecl(); 1612be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek C = PathDiagnosticCallPiece::construct(PD.getActivePath(), Caller); 1613be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek 1614be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek // Since we just transferred the path over to the call piece, 1615be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek // reset the mapping from active to location context. 1616be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek assert(PD.getActivePath().size() == 1 && 1617be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek PD.getActivePath().front() == C); 1618be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek LCM[&PD.getActivePath()] = 0; 1619be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek 1620be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek // Record the location context mapping for the path within 1621be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek // the call. 1622be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek assert(LCM[&C->path] == 0 || 1623be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek LCM[&C->path] == CE->getCalleeContext()); 1624be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek LCM[&C->path] = CE->getCalleeContext(); 1625be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek 1626be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek // If this is the first item in the active path, record 1627be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek // the new mapping from active path to location context. 1628be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek const LocationContext *&NewLC = LCM[&PD.getActivePath()]; 16295a6fb20841220488f8be7254fbea8ba7233ebcd3Jordan Rose if (!NewLC) 1630be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek NewLC = N->getLocationContext(); 1631be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek 16325a6fb20841220488f8be7254fbea8ba7233ebcd3Jordan Rose PDB.LC = NewLC; 1633be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek } 1634be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek C->setCallee(*CE, SM); 1635be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek 16365a6fb20841220488f8be7254fbea8ba7233ebcd3Jordan Rose // Update the previous location in the active path. 16375a6fb20841220488f8be7254fbea8ba7233ebcd3Jordan Rose PrevLoc = C->getLocation(); 16385a6fb20841220488f8be7254fbea8ba7233ebcd3Jordan Rose 1639be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek if (!CallStack.empty()) { 1640be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek assert(CallStack.back().first == C); 1641be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek CallStack.pop_back(); 1642be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek } 1643af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek break; 1644af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek } 1645af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1646be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek // Query the location context here and the previous location 1647be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek // as processing CallEnter may change the active path. 1648be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek PDB.LC = N->getLocationContext(); 1649be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek 1650be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek // Record the mapping from the active path to the location 1651be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek // context. 1652be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek assert(!LCM[&PD.getActivePath()] || 1653be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek LCM[&PD.getActivePath()] == PDB.LC); 1654be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek LCM[&PD.getActivePath()] = PDB.LC; 1655be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek 1656af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek // Have we encountered an exit from a function call? 1657af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek if (Optional<CallExitEnd> CE = P.getAs<CallExitEnd>()) { 1658af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek const Stmt *S = CE->getCalleeContext()->getCallSite(); 1659af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek // Propagate the interesting symbols accordingly. 1660af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek if (const Expr *Ex = dyn_cast_or_null<Expr>(S)) { 1661af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek reversePropagateIntererstingSymbols(*PDB.getBugReport(), IE, 1662af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek N->getState().getPtr(), Ex, 1663af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek N->getLocationContext()); 1664af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek } 1665af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1666af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek // We are descending into a call (backwards). Construct 1667af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek // a new call piece to contain the path pieces for that call. 1668af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek PathDiagnosticCallPiece *C = 1669af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek PathDiagnosticCallPiece::construct(N, *CE, SM); 1670af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1671af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek // Record the location context for this call piece. 1672bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek LCM[&C->path] = CE->getCalleeContext(); 1673af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1674af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek // Add the edge to the return site. 1675be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek addEdgeToPath(PD.getActivePath(), PrevLoc, C->callReturn, PDB.LC); 1676be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek PD.getActivePath().push_front(C); 16775a6fb20841220488f8be7254fbea8ba7233ebcd3Jordan Rose PrevLoc.invalidate(); 1678af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1679af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek // Make the contents of the call the active path for now. 1680af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek PD.pushActivePath(&C->path); 1681af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek CallStack.push_back(StackDiagPair(C, N)); 1682af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek break; 1683af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek } 1684af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1685be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek if (Optional<PostStmt> PS = P.getAs<PostStmt>()) { 1686be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek // For expressions, make sure we propagate the 1687be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek // interesting symbols correctly. 1688be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek if (const Expr *Ex = PS->getStmtAs<Expr>()) 1689be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek reversePropagateIntererstingSymbols(*PDB.getBugReport(), IE, 1690be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek N->getState().getPtr(), Ex, 1691be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek N->getLocationContext()); 1692af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1693e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek // Add an edge. If this is an ObjCForCollectionStmt do 1694e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek // not add an edge here as it appears in the CFG both 1695e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek // as a terminator and as a terminator condition. 1696e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek if (!isa<ObjCForCollectionStmt>(PS->getStmt())) { 1697e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek PathDiagnosticLocation L = 1698e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek PathDiagnosticLocation(PS->getStmt(), SM, PDB.LC); 1699e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek addEdgeToPath(PD.getActivePath(), PrevLoc, L, PDB.LC); 1700e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek } 1701af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek break; 1702af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek } 1703af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1704af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek // Block edges. 1705af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek if (Optional<BlockEdge> BE = P.getAs<BlockEdge>()) { 1706af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek // Does this represent entering a call? If so, look at propagating 1707af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek // interesting symbols across call boundaries. 1708af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek if (NextNode) { 1709af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek const LocationContext *CallerCtx = NextNode->getLocationContext(); 1710af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek const LocationContext *CalleeCtx = PDB.LC; 1711af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek if (CallerCtx != CalleeCtx) { 1712af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek reversePropagateInterestingSymbols(*PDB.getBugReport(), IE, 1713af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek N->getState().getPtr(), 1714af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek CalleeCtx, CallerCtx); 1715af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek } 1716af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek } 1717af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1718af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek // Are we jumping to the head of a loop? Add a special diagnostic. 1719af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek if (const Stmt *Loop = BE->getSrc()->getLoopTarget()) { 1720af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek PathDiagnosticLocation L(Loop, SM, PDB.LC); 1721afde200cdae9731aa5826c6178eae9e7fef74475Ted Kremenek const CompoundStmt *CS = NULL; 1722afde200cdae9731aa5826c6178eae9e7fef74475Ted Kremenek 1723afde200cdae9731aa5826c6178eae9e7fef74475Ted Kremenek if (const ForStmt *FS = dyn_cast<ForStmt>(Loop)) 1724afde200cdae9731aa5826c6178eae9e7fef74475Ted Kremenek CS = dyn_cast<CompoundStmt>(FS->getBody()); 1725afde200cdae9731aa5826c6178eae9e7fef74475Ted Kremenek else if (const WhileStmt *WS = dyn_cast<WhileStmt>(Loop)) 1726afde200cdae9731aa5826c6178eae9e7fef74475Ted Kremenek CS = dyn_cast<CompoundStmt>(WS->getBody()); 1727e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek else if (const ObjCForCollectionStmt *OFS = 1728e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek dyn_cast<ObjCForCollectionStmt>(Loop)) { 1729e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek CS = dyn_cast<CompoundStmt>(OFS->getBody()); 1730e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek } 1731af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1732af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek PathDiagnosticEventPiece *p = 1733af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek new PathDiagnosticEventPiece(L, "Looping back to the head " 1734af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek "of the loop"); 1735af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek p->setPrunable(true); 1736af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1737be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek addEdgeToPath(PD.getActivePath(), PrevLoc, p->getLocation(), PDB.LC); 1738cd389d8cc9abeffb1416b70dd58148e66e5d822bTed Kremenek PD.getActivePath().push_front(p); 1739afde200cdae9731aa5826c6178eae9e7fef74475Ted Kremenek 1740afde200cdae9731aa5826c6178eae9e7fef74475Ted Kremenek if (CS) { 1741afde200cdae9731aa5826c6178eae9e7fef74475Ted Kremenek addEdgeToPath(PD.getActivePath(), PrevLoc, 1742afde200cdae9731aa5826c6178eae9e7fef74475Ted Kremenek PathDiagnosticLocation::createEndBrace(CS, SM), 1743afde200cdae9731aa5826c6178eae9e7fef74475Ted Kremenek PDB.LC); 1744afde200cdae9731aa5826c6178eae9e7fef74475Ted Kremenek } 1745af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek } 1746b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek 1747af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek const CFGBlock *BSrc = BE->getSrc(); 1748af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek ParentMap &PM = PDB.getParentMap(); 1749af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1750af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek if (const Stmt *Term = BSrc->getTerminator()) { 1751af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek // Are we jumping past the loop body without ever executing the 1752af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek // loop (because the condition was false)? 1753b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek if (isLoop(Term)) { 1754e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek const Stmt *TermCond = getTerminatorCondition(BSrc); 1755b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek bool IsInLoopBody = 1756b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek isInLoopBody(PM, getStmtBeforeCond(PM, TermCond, N), Term); 1757b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek 1758b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek const char *str = 0; 1759b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek 1760b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek if (isJumpToFalseBranch(&*BE)) { 1761b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek if (!IsInLoopBody) { 1762f94cb007d03031bcf3d1b02f6a683a189e934953Ted Kremenek str = StrLoopBodyZero; 1763b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek } 1764b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek } 1765b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek else { 1766f94cb007d03031bcf3d1b02f6a683a189e934953Ted Kremenek str = StrEnteringLoop; 1767b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek } 1768b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek 1769b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek if (str) { 17703e8a85fcfc3d264e4c5b21fbdd741bbc0c24a266Jordan Rose PathDiagnosticLocation L(TermCond ? TermCond : Term, SM, PDB.LC); 1771b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek PathDiagnosticEventPiece *PE = 1772b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek new PathDiagnosticEventPiece(L, str); 1773b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek PE->setPrunable(true); 1774b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek addEdgeToPath(PD.getActivePath(), PrevLoc, 1775be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek PE->getLocation(), PDB.LC); 1776b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek PD.getActivePath().push_front(PE); 1777b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek } 1778af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek } 1779bc0fd8129626ff4e485388311b081e76d0f96795Ted Kremenek else if (isa<BreakStmt>(Term) || isa<ContinueStmt>(Term) || 1780bc0fd8129626ff4e485388311b081e76d0f96795Ted Kremenek isa<GotoStmt>(Term)) { 1781bc0fd8129626ff4e485388311b081e76d0f96795Ted Kremenek PathDiagnosticLocation L(Term, SM, PDB.LC); 1782be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek addEdgeToPath(PD.getActivePath(), PrevLoc, L, PDB.LC); 1783bc0fd8129626ff4e485388311b081e76d0f96795Ted Kremenek } 1784af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek } 1785af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek break; 1786af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek } 1787af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek } while (0); 1788af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1789af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek if (!NextNode) 1790af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek continue; 1791af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1792af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek // Add pieces from custom visitors. 1793af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek for (ArrayRef<BugReporterVisitor *>::iterator I = visitors.begin(), 1794af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek E = visitors.end(); 1795af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek I != E; ++I) { 1796cd389d8cc9abeffb1416b70dd58148e66e5d822bTed Kremenek if (PathDiagnosticPiece *p = (*I)->VisitNode(N, NextNode, PDB, *report)) { 1797be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek addEdgeToPath(PD.getActivePath(), PrevLoc, p->getLocation(), PDB.LC); 1798cd389d8cc9abeffb1416b70dd58148e66e5d822bTed Kremenek PD.getActivePath().push_front(p); 1799af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek updateStackPiecesWithMessage(p, CallStack); 1800af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek } 1801af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek } 1802af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek } 1803af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 180401f1ff79f70b3e042995a43b29ccbf0fffc77d5fJordan Rose // Add an edge to the start of the function. 180501f1ff79f70b3e042995a43b29ccbf0fffc77d5fJordan Rose // We'll prune it out later, but it helps make diagnostics more uniform. 180601f1ff79f70b3e042995a43b29ccbf0fffc77d5fJordan Rose const StackFrameContext *CalleeLC = PDB.LC->getCurrentStackFrame(); 180701f1ff79f70b3e042995a43b29ccbf0fffc77d5fJordan Rose const Decl *D = CalleeLC->getDecl(); 180801f1ff79f70b3e042995a43b29ccbf0fffc77d5fJordan Rose addEdgeToPath(PD.getActivePath(), PrevLoc, 180901f1ff79f70b3e042995a43b29ccbf0fffc77d5fJordan Rose PathDiagnosticLocation::createBegin(D, SM), 181001f1ff79f70b3e042995a43b29ccbf0fffc77d5fJordan Rose CalleeLC); 181101f1ff79f70b3e042995a43b29ccbf0fffc77d5fJordan Rose 1812af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek return report->isValid(); 1813af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek} 1814af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1815b1a4d37c0549501fe12907bc6ffa81bc5d04b98aBenjamin Kramerstatic const Stmt *getLocStmt(PathDiagnosticLocation L) { 1816bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek if (!L.isValid()) 1817bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek return 0; 1818f468fa16e37fc8fa6a915fe36aee8f0434709789Ted Kremenek return L.asStmt(); 1819f468fa16e37fc8fa6a915fe36aee8f0434709789Ted Kremenek} 1820f468fa16e37fc8fa6a915fe36aee8f0434709789Ted Kremenek 182196f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rosestatic const Stmt *getStmtParent(const Stmt *S, const ParentMap &PM) { 1822bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek if (!S) 1823bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek return 0; 1824a40983460cc3f8f583cd968ac2e4647dc30c83f5Ted Kremenek 1825a40983460cc3f8f583cd968ac2e4647dc30c83f5Ted Kremenek while (true) { 1826a40983460cc3f8f583cd968ac2e4647dc30c83f5Ted Kremenek S = PM.getParentIgnoreParens(S); 1827a40983460cc3f8f583cd968ac2e4647dc30c83f5Ted Kremenek 1828a40983460cc3f8f583cd968ac2e4647dc30c83f5Ted Kremenek if (!S) 1829a40983460cc3f8f583cd968ac2e4647dc30c83f5Ted Kremenek break; 1830a40983460cc3f8f583cd968ac2e4647dc30c83f5Ted Kremenek 1831a327bb12b1cd0c142eb06e30b4f6018b96d5babfTed Kremenek if (isa<ExprWithCleanups>(S) || 1832a327bb12b1cd0c142eb06e30b4f6018b96d5babfTed Kremenek isa<CXXBindTemporaryExpr>(S) || 1833a327bb12b1cd0c142eb06e30b4f6018b96d5babfTed Kremenek isa<SubstNonTypeTemplateParmExpr>(S)) 1834a40983460cc3f8f583cd968ac2e4647dc30c83f5Ted Kremenek continue; 1835a40983460cc3f8f583cd968ac2e4647dc30c83f5Ted Kremenek 1836a40983460cc3f8f583cd968ac2e4647dc30c83f5Ted Kremenek break; 1837a40983460cc3f8f583cd968ac2e4647dc30c83f5Ted Kremenek } 1838a40983460cc3f8f583cd968ac2e4647dc30c83f5Ted Kremenek 1839a40983460cc3f8f583cd968ac2e4647dc30c83f5Ted Kremenek return S; 1840bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek} 1841bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek 184215676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenekstatic bool isConditionForTerminator(const Stmt *S, const Stmt *Cond) { 184315676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek switch (S->getStmtClass()) { 184403194fb1bbf2b2d17ff7e3d61ddb9d73e9297fdcTed Kremenek case Stmt::BinaryOperatorClass: { 184503194fb1bbf2b2d17ff7e3d61ddb9d73e9297fdcTed Kremenek const BinaryOperator *BO = cast<BinaryOperator>(S); 184603194fb1bbf2b2d17ff7e3d61ddb9d73e9297fdcTed Kremenek if (!BO->isLogicalOp()) 184703194fb1bbf2b2d17ff7e3d61ddb9d73e9297fdcTed Kremenek return false; 184803194fb1bbf2b2d17ff7e3d61ddb9d73e9297fdcTed Kremenek return BO->getLHS() == Cond || BO->getRHS() == Cond; 184903194fb1bbf2b2d17ff7e3d61ddb9d73e9297fdcTed Kremenek } 1850a399f776ee29e099da33eaf7f9d585b4edc4b61dTed Kremenek case Stmt::IfStmtClass: 1851a399f776ee29e099da33eaf7f9d585b4edc4b61dTed Kremenek return cast<IfStmt>(S)->getCond() == Cond; 185215676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek case Stmt::ForStmtClass: 185315676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek return cast<ForStmt>(S)->getCond() == Cond; 185415676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek case Stmt::WhileStmtClass: 185515676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek return cast<WhileStmt>(S)->getCond() == Cond; 185615676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek case Stmt::DoStmtClass: 185715676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek return cast<DoStmt>(S)->getCond() == Cond; 185815676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek case Stmt::ChooseExprClass: 185915676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek return cast<ChooseExpr>(S)->getCond() == Cond; 186015676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek case Stmt::IndirectGotoStmtClass: 186115676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek return cast<IndirectGotoStmt>(S)->getTarget() == Cond; 186215676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek case Stmt::SwitchStmtClass: 186315676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek return cast<SwitchStmt>(S)->getCond() == Cond; 186415676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek case Stmt::BinaryConditionalOperatorClass: 186515676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek return cast<BinaryConditionalOperator>(S)->getCond() == Cond; 18668484b37a2b7720c016d27a672343b1c67bd2e731Ted Kremenek case Stmt::ConditionalOperatorClass: { 18678484b37a2b7720c016d27a672343b1c67bd2e731Ted Kremenek const ConditionalOperator *CO = cast<ConditionalOperator>(S); 18688484b37a2b7720c016d27a672343b1c67bd2e731Ted Kremenek return CO->getCond() == Cond || 18698484b37a2b7720c016d27a672343b1c67bd2e731Ted Kremenek CO->getLHS() == Cond || 18708484b37a2b7720c016d27a672343b1c67bd2e731Ted Kremenek CO->getRHS() == Cond; 18718484b37a2b7720c016d27a672343b1c67bd2e731Ted Kremenek } 187215676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek case Stmt::ObjCForCollectionStmtClass: 187315676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek return cast<ObjCForCollectionStmt>(S)->getElement() == Cond; 187415676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek default: 187515676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek return false; 187615676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek } 187715676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek} 187815676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek 187996b8134337883908fcc45484486fe200d6b3e32fTed Kremenekstatic bool isIncrementOrInitInForLoop(const Stmt *S, const Stmt *FL) { 1880e2f7337958f21802e98777f441fe20ef7ba2adffTed Kremenek const ForStmt *FS = dyn_cast<ForStmt>(FL); 188196b8134337883908fcc45484486fe200d6b3e32fTed Kremenek if (!FS) 1882e2f7337958f21802e98777f441fe20ef7ba2adffTed Kremenek return false; 188396b8134337883908fcc45484486fe200d6b3e32fTed Kremenek return FS->getInc() == S || FS->getInit() == S; 1884e2f7337958f21802e98777f441fe20ef7ba2adffTed Kremenek} 1885e2f7337958f21802e98777f441fe20ef7ba2adffTed Kremenek 188615676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenektypedef llvm::DenseSet<const PathDiagnosticCallPiece *> 188715676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek OptimizedCallsSet; 188815676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek 1889d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rosevoid PathPieces::dump() const { 1890d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose unsigned index = 0; 1891d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose for (PathPieces::const_iterator I = begin(), E = end(); I != E; ++I ) { 1892d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose llvm::errs() << "[" << index++ << "]"; 1893d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose 1894d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose switch ((*I)->getKind()) { 1895d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose case PathDiagnosticPiece::Call: 1896d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose llvm::errs() << " CALL\n--------------\n"; 1897d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose 1898d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose if (const Stmt *SLoc = getLocStmt((*I)->getLocation())) { 1899d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose SLoc->dump(); 1900d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose } else { 1901d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose const PathDiagnosticCallPiece *Call = cast<PathDiagnosticCallPiece>(*I); 1902d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose if (const NamedDecl *ND = dyn_cast<NamedDecl>(Call->getCallee())) 1903d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose llvm::errs() << *ND << "\n"; 1904d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose } 1905d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose break; 1906d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose case PathDiagnosticPiece::Event: 1907d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose llvm::errs() << " EVENT\n--------------\n"; 1908d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose llvm::errs() << (*I)->getString() << "\n"; 1909d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose if (const Stmt *SLoc = getLocStmt((*I)->getLocation())) { 1910d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose llvm::errs() << " ---- at ----\n"; 1911d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose SLoc->dump(); 1912d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose } 1913d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose break; 1914d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose case PathDiagnosticPiece::Macro: 1915d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose llvm::errs() << " MACRO\n--------------\n"; 1916d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose // FIXME: print which macro is being invoked. 1917d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose break; 1918d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose case PathDiagnosticPiece::ControlFlow: { 1919d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose const PathDiagnosticControlFlowPiece *CP = 1920d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose cast<PathDiagnosticControlFlowPiece>(*I); 1921d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose llvm::errs() << " CONTROL\n--------------\n"; 1922d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose 1923d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose if (const Stmt *s1Start = getLocStmt(CP->getStartLocation())) 1924d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose s1Start->dump(); 1925d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose else 1926d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose llvm::errs() << "NULL\n"; 1927d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose 1928d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose llvm::errs() << " ---- to ----\n"; 1929d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose 1930d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose if (const Stmt *s1End = getLocStmt(CP->getEndLocation())) 1931d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose s1End->dump(); 1932d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose else 1933d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose llvm::errs() << "NULL\n"; 1934d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose 1935d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose break; 1936d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose } 1937d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose } 1938d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose 1939d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose llvm::errs() << "\n"; 1940d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose } 1941d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose} 1942d1913d89e2ff3b38bb6293833cfd9d8ead76348eJordan Rose 194396f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose/// Adds synthetic edges from top-level statements to their subexpressions. 194496f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose/// 194596f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose/// This avoids a "swoosh" effect, where an edge from a top-level statement A 194696f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose/// points to a sub-expression B.1 that's not at the start of B. In these cases, 194796f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose/// we'd like to see an edge from A to B, then another one from B to B.1. 194896f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rosestatic void addContextEdges(PathPieces &pieces, SourceManager &SM, 194996f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose const ParentMap &PM, const LocationContext *LCtx) { 195096f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose PathPieces::iterator Prev = pieces.end(); 195196f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose for (PathPieces::iterator I = pieces.begin(), E = Prev; I != E; 195296f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose Prev = I, ++I) { 195396f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose PathDiagnosticControlFlowPiece *Piece = 195496f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose dyn_cast<PathDiagnosticControlFlowPiece>(*I); 195596f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose 195696f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose if (!Piece) 195796f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose continue; 195896f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose 195996f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose PathDiagnosticLocation SrcLoc = Piece->getStartLocation(); 196096f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose const Stmt *Src = getLocStmt(SrcLoc); 19619d9b494aa36ceeb823c48acf04d2d7677174be88Jordan Rose SmallVector<PathDiagnosticLocation, 4> SrcContexts; 19629d9b494aa36ceeb823c48acf04d2d7677174be88Jordan Rose 19639d9b494aa36ceeb823c48acf04d2d7677174be88Jordan Rose PathDiagnosticLocation NextSrcContext = 19649d9b494aa36ceeb823c48acf04d2d7677174be88Jordan Rose getEnclosingStmtLocation(Src, SM, PM, LCtx, /*allowNested=*/true); 19659d9b494aa36ceeb823c48acf04d2d7677174be88Jordan Rose const Stmt *InnerStmt = Src; 19669d9b494aa36ceeb823c48acf04d2d7677174be88Jordan Rose while (NextSrcContext.isValid() && NextSrcContext.asStmt() != InnerStmt) { 19679d9b494aa36ceeb823c48acf04d2d7677174be88Jordan Rose SrcContexts.push_back(NextSrcContext); 19689d9b494aa36ceeb823c48acf04d2d7677174be88Jordan Rose InnerStmt = NextSrcContext.asStmt(); 19699d9b494aa36ceeb823c48acf04d2d7677174be88Jordan Rose NextSrcContext = getEnclosingStmtLocation(InnerStmt, SM, PM, LCtx, true); 19709d9b494aa36ceeb823c48acf04d2d7677174be88Jordan Rose } 197196f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose 197296f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose // Repeatedly split the edge as necessary. 197396f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose // This is important for nested logical expressions (||, &&, ?:) where we 197496f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose // want to show all the levels of context. 197596f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose while (true) { 197696f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose const Stmt *Dst = getLocStmt(Piece->getEndLocation()); 197796f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose 197896f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose // We are looking at an edge. Is the destination within a larger 197996f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose // expression? 198096f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose PathDiagnosticLocation DstContext = 19819d9b494aa36ceeb823c48acf04d2d7677174be88Jordan Rose getEnclosingStmtLocation(Dst, SM, PM, LCtx, /*allowNested=*/true); 198296f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose if (!DstContext.isValid() || DstContext.asStmt() == Dst) 198396f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose break; 198496f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose 198596f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose // If the source is in the same context, we're already good. 19869d9b494aa36ceeb823c48acf04d2d7677174be88Jordan Rose if (std::find(SrcContexts.begin(), SrcContexts.end(), DstContext) != 19879d9b494aa36ceeb823c48acf04d2d7677174be88Jordan Rose SrcContexts.end()) 198896f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose break; 198996f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose 199096f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose // Update the subexpression node to point to the context edge. 199196f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose Piece->setStartLocation(DstContext); 199296f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose 199396f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose // Try to extend the previous edge if it's at the same level as the source 199496f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose // context. 199596f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose if (Prev != E) { 199696f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose PathDiagnosticControlFlowPiece *PrevPiece = 199796f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose dyn_cast<PathDiagnosticControlFlowPiece>(*Prev); 199896f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose 199996f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose if (PrevPiece) { 200096f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose if (const Stmt *PrevSrc = getLocStmt(PrevPiece->getStartLocation())) { 200196f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose const Stmt *PrevSrcParent = getStmtParent(PrevSrc, PM); 200296f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose if (PrevSrcParent == getStmtParent(getLocStmt(DstContext), PM)) { 200396f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose PrevPiece->setEndLocation(DstContext); 200496f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose break; 200596f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose } 200696f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose } 200796f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose } 200896f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose } 200996f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose 201096f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose // Otherwise, split the current edge into a context edge and a 201196f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose // subexpression edge. Note that the context statement may itself have 201296f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose // context. 201396f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose Piece = new PathDiagnosticControlFlowPiece(SrcLoc, DstContext); 201496f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose I = pieces.insert(I, Piece); 201596f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose } 201696f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose } 201796f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose} 201896f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose 201996f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose/// \brief Move edges from a branch condition to a branch target 202096f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose/// when the condition is simple. 202196f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose/// 202296f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose/// This restructures some of the work of addContextEdges. That function 202396f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose/// creates edges this may destroy, but they work together to create a more 202496f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose/// aesthetically set of edges around branches. After the call to 202596f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose/// addContextEdges, we may have (1) an edge to the branch, (2) an edge from 202696f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose/// the branch to the branch condition, and (3) an edge from the branch 202796f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose/// condition to the branch target. We keep (1), but may wish to remove (2) 202896f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose/// and move the source of (3) to the branch if the branch condition is simple. 202996f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose/// 203096f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rosestatic void simplifySimpleBranches(PathPieces &pieces) { 203196f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose for (PathPieces::iterator I = pieces.begin(), E = pieces.end(); I != E; ++I) { 203296f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose 203396f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose PathDiagnosticControlFlowPiece *PieceI = 203496f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose dyn_cast<PathDiagnosticControlFlowPiece>(*I); 203596f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose 203696f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose if (!PieceI) 203796f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose continue; 203896f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose 203996f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose const Stmt *s1Start = getLocStmt(PieceI->getStartLocation()); 204096f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose const Stmt *s1End = getLocStmt(PieceI->getEndLocation()); 204196f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose 204296f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose if (!s1Start || !s1End) 204396f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose continue; 204496f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose 204596f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose PathPieces::iterator NextI = I; ++NextI; 204696f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose if (NextI == E) 204796f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose break; 204896f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose 204996f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose PathDiagnosticControlFlowPiece *PieceNextI = 0; 205096f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose 205196f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose while (true) { 205296f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose if (NextI == E) 205396f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose break; 205496f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose 205596f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose PathDiagnosticEventPiece *EV = dyn_cast<PathDiagnosticEventPiece>(*NextI); 205696f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose if (EV) { 205796f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose StringRef S = EV->getString(); 205896f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose if (S == StrEnteringLoop || S == StrLoopBodyZero) { 205996f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose ++NextI; 206096f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose continue; 206196f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose } 206296f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose break; 206396f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose } 206496f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose 206596f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose PieceNextI = dyn_cast<PathDiagnosticControlFlowPiece>(*NextI); 206696f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose break; 206796f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose } 206896f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose 206996f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose if (!PieceNextI) 207096f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose continue; 207196f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose 207296f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose const Stmt *s2Start = getLocStmt(PieceNextI->getStartLocation()); 207396f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose const Stmt *s2End = getLocStmt(PieceNextI->getEndLocation()); 207496f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose 207596f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose if (!s2Start || !s2End || s1End != s2Start) 207696f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose continue; 207796f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose 207896f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose // We only perform this transformation for specific branch kinds. 207996f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose // We don't want to do this for do..while, for example. 208096f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose if (!(isa<ForStmt>(s1Start) || isa<WhileStmt>(s1Start) || 208196f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose isa<IfStmt>(s1Start) || isa<ObjCForCollectionStmt>(s1Start))) 208296f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose continue; 208396f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose 208496f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose // Is s1End the branch condition? 208596f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose if (!isConditionForTerminator(s1Start, s1End)) 208696f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose continue; 208796f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose 208896f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose // Perform the hoisting by eliminating (2) and changing the start 208996f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose // location of (3). 209096f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose PieceNextI->setStartLocation(PieceI->getStartLocation()); 209196f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose I = pieces.erase(I); 209296f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose } 209396f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose} 209496f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose 2095e624524705ab660eb8d1feb9870ef2989fb2bdf4Jordan Rose/// Returns the number of bytes in the given (character-based) SourceRange. 209622b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose/// 209722b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose/// If the locations in the range are not on the same line, returns None. 209822b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose/// 209922b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose/// Note that this does not do a precise user-visible character or column count. 210022b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rosestatic Optional<size_t> getLengthOnSingleLine(SourceManager &SM, 210122b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose SourceRange Range) { 210222b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose SourceRange ExpansionRange(SM.getExpansionLoc(Range.getBegin()), 210322b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose SM.getExpansionRange(Range.getEnd()).second); 210422b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose 210522b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose FileID FID = SM.getFileID(ExpansionRange.getBegin()); 210622b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose if (FID != SM.getFileID(ExpansionRange.getEnd())) 210722b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose return None; 210822b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose 210922b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose bool Invalid; 211022b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose const llvm::MemoryBuffer *Buffer = SM.getBuffer(FID, &Invalid); 211122b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose if (Invalid) 211222b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose return None; 211322b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose 211422b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose unsigned BeginOffset = SM.getFileOffset(ExpansionRange.getBegin()); 211522b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose unsigned EndOffset = SM.getFileOffset(ExpansionRange.getEnd()); 211622b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose StringRef Snippet = Buffer->getBuffer().slice(BeginOffset, EndOffset); 211722b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose 211822b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose // We're searching the raw bytes of the buffer here, which might include 211922b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose // escaped newlines and such. That's okay; we're trying to decide whether the 212022b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose // SourceRange is covering a large or small amount of space in the user's 212122b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose // editor. 212222b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose if (Snippet.find_first_of("\r\n") != StringRef::npos) 212322b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose return None; 212422b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose 212522b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose // This isn't Unicode-aware, but it doesn't need to be. 212622b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose return Snippet.size(); 212722b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose} 212822b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose 212922b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose/// \sa getLengthOnSingleLine(SourceManager, SourceRange) 213022b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rosestatic Optional<size_t> getLengthOnSingleLine(SourceManager &SM, 213122b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose const Stmt *S) { 213222b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose return getLengthOnSingleLine(SM, S->getSourceRange()); 213322b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose} 213422b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose 213522b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose/// Eliminate two-edge cycles created by addContextEdges(). 213622b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose/// 213722b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose/// Once all the context edges are in place, there are plenty of cases where 213822b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose/// there's a single edge from a top-level statement to a subexpression, 213922b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose/// followed by a single path note, and then a reverse edge to get back out to 214022b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose/// the top level. If the statement is simple enough, the subexpression edges 214122b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose/// just add noise and make it harder to understand what's going on. 214222b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose/// 214322b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose/// This function only removes edges in pairs, because removing only one edge 214422b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose/// might leave other edges dangling. 214522b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose/// 214622b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose/// This will not remove edges in more complicated situations: 214722b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose/// - if there is more than one "hop" leading to or from a subexpression. 214822b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose/// - if there is an inlined call between the edges instead of a single event. 214922b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose/// - if the whole statement is large enough that having subexpression arrows 215022b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose/// might be helpful. 215122b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rosestatic void removeContextCycles(PathPieces &Path, SourceManager &SM, 215222b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose ParentMap &PM) { 21533b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose for (PathPieces::iterator I = Path.begin(), E = Path.end(); I != E; ) { 21543b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose // Pattern match the current piece and its successor. 21553b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose PathDiagnosticControlFlowPiece *PieceI = 21563b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose dyn_cast<PathDiagnosticControlFlowPiece>(*I); 21573b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose 21583b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose if (!PieceI) { 21593b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose ++I; 21603b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose continue; 21613b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose } 21623b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose 21633b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose const Stmt *s1Start = getLocStmt(PieceI->getStartLocation()); 21643b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose const Stmt *s1End = getLocStmt(PieceI->getEndLocation()); 21653b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose 21663b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose PathPieces::iterator NextI = I; ++NextI; 21673b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose if (NextI == E) 21683b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose break; 21693b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose 21703b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose PathDiagnosticControlFlowPiece *PieceNextI = 21713b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose dyn_cast<PathDiagnosticControlFlowPiece>(*NextI); 21723b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose 21733b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose if (!PieceNextI) { 21743b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose if (isa<PathDiagnosticEventPiece>(*NextI)) { 21753b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose ++NextI; 21763b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose if (NextI == E) 21773b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose break; 21783b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose PieceNextI = dyn_cast<PathDiagnosticControlFlowPiece>(*NextI); 21793b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose } 21803b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose 21813b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose if (!PieceNextI) { 21823b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose ++I; 21833b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose continue; 21843b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose } 21853b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose } 21863b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose 21873b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose const Stmt *s2Start = getLocStmt(PieceNextI->getStartLocation()); 21883b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose const Stmt *s2End = getLocStmt(PieceNextI->getEndLocation()); 21893b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose 21903b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose if (s1Start && s2Start && s1Start == s2End && s2Start == s1End) { 219122b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose const size_t MAX_SHORT_LINE_LENGTH = 80; 219222b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose Optional<size_t> s1Length = getLengthOnSingleLine(SM, s1Start); 219322b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose if (s1Length && *s1Length <= MAX_SHORT_LINE_LENGTH) { 219422b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose Optional<size_t> s2Length = getLengthOnSingleLine(SM, s2Start); 219522b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose if (s2Length && *s2Length <= MAX_SHORT_LINE_LENGTH) { 219622b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose Path.erase(I); 219722b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose I = Path.erase(NextI); 219822b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose continue; 219922b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose } 220022b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose } 22013b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose } 22023b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose 22033b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose ++I; 22043b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose } 22053b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose} 22063b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose 220752f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek/// \brief Return true if X is contained by Y. 220852f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenekstatic bool lexicalContains(ParentMap &PM, 220952f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek const Stmt *X, 221052f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek const Stmt *Y) { 221152f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek while (X) { 221252f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek if (X == Y) 221352f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek return true; 221452f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek X = PM.getParent(X); 221552f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek } 221652f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek return false; 221752f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek} 221852f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek 2219de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek// Remove short edges on the same line less than 3 columns in difference. 2220de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenekstatic void removePunyEdges(PathPieces &path, 2221de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek SourceManager &SM, 2222de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek ParentMap &PM) { 2223de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek 2224de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek bool erased = false; 2225de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek 2226de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek for (PathPieces::iterator I = path.begin(), E = path.end(); I != E; 2227de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek erased ? I : ++I) { 2228de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek 2229de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek erased = false; 2230de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek 2231de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek PathDiagnosticControlFlowPiece *PieceI = 2232de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek dyn_cast<PathDiagnosticControlFlowPiece>(*I); 2233de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek 2234de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek if (!PieceI) 2235de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek continue; 2236de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek 2237de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek const Stmt *start = getLocStmt(PieceI->getStartLocation()); 2238de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek const Stmt *end = getLocStmt(PieceI->getEndLocation()); 2239de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek 2240de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek if (!start || !end) 2241de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek continue; 2242de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek 2243de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek const Stmt *endParent = PM.getParent(end); 2244de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek if (!endParent) 2245de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek continue; 2246de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek 2247de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek if (isConditionForTerminator(end, endParent)) 2248de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek continue; 2249de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek 225022b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose SourceLocation FirstLoc = start->getLocStart(); 225122b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose SourceLocation SecondLoc = end->getLocStart(); 2252de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek 225322b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose if (!SM.isFromSameFile(FirstLoc, SecondLoc)) 2254de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek continue; 225522b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose if (SM.isBeforeInTranslationUnit(SecondLoc, FirstLoc)) 225622b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose std::swap(SecondLoc, FirstLoc); 2257de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek 225822b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose SourceRange EdgeRange(FirstLoc, SecondLoc); 225922b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose Optional<size_t> ByteWidth = getLengthOnSingleLine(SM, EdgeRange); 2260de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek 226122b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose // If the statements are on different lines, continue. 226222b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose if (!ByteWidth) 2263de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek continue; 2264de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek 226522b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose const size_t MAX_PUNY_EDGE_LENGTH = 2; 226622b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose if (*ByteWidth <= MAX_PUNY_EDGE_LENGTH) { 226722b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose // FIXME: There are enough /bytes/ between the endpoints of the edge, but 226822b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose // there might not be enough /columns/. A proper user-visible column count 226922b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose // is probably too expensive, though. 2270a705980a7c3315b7c72d99ce675342ad91b50642Ted Kremenek I = path.erase(I); 2271de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek erased = true; 2272de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek continue; 2273de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek } 2274de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek } 2275de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek} 2276de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek 22771d85a9e8fb4e6ac513467b5fa825bd53e6fcba56Ted Kremenekstatic void removeIdenticalEvents(PathPieces &path) { 22781d85a9e8fb4e6ac513467b5fa825bd53e6fcba56Ted Kremenek for (PathPieces::iterator I = path.begin(), E = path.end(); I != E; ++I) { 22791d85a9e8fb4e6ac513467b5fa825bd53e6fcba56Ted Kremenek PathDiagnosticEventPiece *PieceI = 22801d85a9e8fb4e6ac513467b5fa825bd53e6fcba56Ted Kremenek dyn_cast<PathDiagnosticEventPiece>(*I); 22811d85a9e8fb4e6ac513467b5fa825bd53e6fcba56Ted Kremenek 22821d85a9e8fb4e6ac513467b5fa825bd53e6fcba56Ted Kremenek if (!PieceI) 22831d85a9e8fb4e6ac513467b5fa825bd53e6fcba56Ted Kremenek continue; 22841d85a9e8fb4e6ac513467b5fa825bd53e6fcba56Ted Kremenek 22851d85a9e8fb4e6ac513467b5fa825bd53e6fcba56Ted Kremenek PathPieces::iterator NextI = I; ++NextI; 22861d85a9e8fb4e6ac513467b5fa825bd53e6fcba56Ted Kremenek if (NextI == E) 22871d85a9e8fb4e6ac513467b5fa825bd53e6fcba56Ted Kremenek return; 22881d85a9e8fb4e6ac513467b5fa825bd53e6fcba56Ted Kremenek 22891d85a9e8fb4e6ac513467b5fa825bd53e6fcba56Ted Kremenek PathDiagnosticEventPiece *PieceNextI = 22900fa3504acfc7c20a87973c58ad3474adc94dd97dTed Kremenek dyn_cast<PathDiagnosticEventPiece>(*NextI); 22911d85a9e8fb4e6ac513467b5fa825bd53e6fcba56Ted Kremenek 22921d85a9e8fb4e6ac513467b5fa825bd53e6fcba56Ted Kremenek if (!PieceNextI) 22931d85a9e8fb4e6ac513467b5fa825bd53e6fcba56Ted Kremenek continue; 22941d85a9e8fb4e6ac513467b5fa825bd53e6fcba56Ted Kremenek 22951d85a9e8fb4e6ac513467b5fa825bd53e6fcba56Ted Kremenek // Erase the second piece if it has the same exact message text. 22961d85a9e8fb4e6ac513467b5fa825bd53e6fcba56Ted Kremenek if (PieceI->getString() == PieceNextI->getString()) { 22971d85a9e8fb4e6ac513467b5fa825bd53e6fcba56Ted Kremenek path.erase(NextI); 22981d85a9e8fb4e6ac513467b5fa825bd53e6fcba56Ted Kremenek } 22991d85a9e8fb4e6ac513467b5fa825bd53e6fcba56Ted Kremenek } 23001d85a9e8fb4e6ac513467b5fa825bd53e6fcba56Ted Kremenek} 23011d85a9e8fb4e6ac513467b5fa825bd53e6fcba56Ted Kremenek 230215676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenekstatic bool optimizeEdges(PathPieces &path, SourceManager &SM, 230315676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek OptimizedCallsSet &OCS, 2304bb518991ce4298d8662235fc8cb13813f011c18dJordan Rose LocationContextMap &LCM) { 2305bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek bool hasChanges = false; 2306bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek const LocationContext *LC = LCM[&path]; 2307bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek assert(LC); 2308de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek ParentMap &PM = LC->getParentMap(); 2309bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek 2310481da5554d03271b0d87b695449963f7728c5895Ted Kremenek for (PathPieces::iterator I = path.begin(), E = path.end(); I != E; ) { 2311bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek // Optimize subpaths. 2312bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek if (PathDiagnosticCallPiece *CallI = dyn_cast<PathDiagnosticCallPiece>(*I)){ 2313481da5554d03271b0d87b695449963f7728c5895Ted Kremenek // Record the fact that a call has been optimized so we only do the 2314481da5554d03271b0d87b695449963f7728c5895Ted Kremenek // effort once. 231515676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek if (!OCS.count(CallI)) { 2316bb518991ce4298d8662235fc8cb13813f011c18dJordan Rose while (optimizeEdges(CallI->path, SM, OCS, LCM)) {} 231715676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek OCS.insert(CallI); 231815676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek } 2319481da5554d03271b0d87b695449963f7728c5895Ted Kremenek ++I; 2320bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek continue; 2321bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek } 2322bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek 2323bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek // Pattern match the current piece and its successor. 2324bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek PathDiagnosticControlFlowPiece *PieceI = 2325bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek dyn_cast<PathDiagnosticControlFlowPiece>(*I); 2326bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek 2327481da5554d03271b0d87b695449963f7728c5895Ted Kremenek if (!PieceI) { 2328481da5554d03271b0d87b695449963f7728c5895Ted Kremenek ++I; 2329bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek continue; 2330481da5554d03271b0d87b695449963f7728c5895Ted Kremenek } 2331bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek 2332f468fa16e37fc8fa6a915fe36aee8f0434709789Ted Kremenek const Stmt *s1Start = getLocStmt(PieceI->getStartLocation()); 2333f468fa16e37fc8fa6a915fe36aee8f0434709789Ted Kremenek const Stmt *s1End = getLocStmt(PieceI->getEndLocation()); 2334f468fa16e37fc8fa6a915fe36aee8f0434709789Ted Kremenek const Stmt *level1 = getStmtParent(s1Start, PM); 2335f468fa16e37fc8fa6a915fe36aee8f0434709789Ted Kremenek const Stmt *level2 = getStmtParent(s1End, PM); 2336f468fa16e37fc8fa6a915fe36aee8f0434709789Ted Kremenek 233715676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek PathPieces::iterator NextI = I; ++NextI; 233815676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek if (NextI == E) 233915676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek break; 234015676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek 2341bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek PathDiagnosticControlFlowPiece *PieceNextI = 2342bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek dyn_cast<PathDiagnosticControlFlowPiece>(*NextI); 2343bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek 2344481da5554d03271b0d87b695449963f7728c5895Ted Kremenek if (!PieceNextI) { 2345481da5554d03271b0d87b695449963f7728c5895Ted Kremenek ++I; 2346bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek continue; 2347481da5554d03271b0d87b695449963f7728c5895Ted Kremenek } 2348bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek 2349f468fa16e37fc8fa6a915fe36aee8f0434709789Ted Kremenek const Stmt *s2Start = getLocStmt(PieceNextI->getStartLocation()); 2350f468fa16e37fc8fa6a915fe36aee8f0434709789Ted Kremenek const Stmt *s2End = getLocStmt(PieceNextI->getEndLocation()); 2351f468fa16e37fc8fa6a915fe36aee8f0434709789Ted Kremenek const Stmt *level3 = getStmtParent(s2Start, PM); 2352f468fa16e37fc8fa6a915fe36aee8f0434709789Ted Kremenek const Stmt *level4 = getStmtParent(s2End, PM); 2353bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek 2354bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek // Rule I. 2355bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek // 2356bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek // If we have two consecutive control edges whose end/begin locations 2357481da5554d03271b0d87b695449963f7728c5895Ted Kremenek // are at the same level (e.g. statements or top-level expressions within 2358481da5554d03271b0d87b695449963f7728c5895Ted Kremenek // a compound statement, or siblings share a single ancestor expression), 2359481da5554d03271b0d87b695449963f7728c5895Ted Kremenek // then merge them if they have no interesting intermediate event. 2360bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek // 2361bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek // For example: 2362bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek // 2363bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek // (1.1 -> 1.2) -> (1.2 -> 1.3) becomes (1.1 -> 1.3) because the common 2364481da5554d03271b0d87b695449963f7728c5895Ted Kremenek // parent is '1'. Here 'x.y.z' represents the hierarchy of statements. 2365bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek // 2366bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek // NOTE: this will be limited later in cases where we add barriers 2367bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek // to prevent this optimization. 2368f468fa16e37fc8fa6a915fe36aee8f0434709789Ted Kremenek // 2369481da5554d03271b0d87b695449963f7728c5895Ted Kremenek if (level1 && level1 == level2 && level1 == level3 && level1 == level4) { 2370bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek PieceI->setEndLocation(PieceNextI->getEndLocation()); 2371bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek path.erase(NextI); 2372bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek hasChanges = true; 2373bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek continue; 2374bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek } 2375b9e13d555fc9f3e5515e2b1fa6f720e6f10bb076Ted Kremenek 2376b9e13d555fc9f3e5515e2b1fa6f720e6f10bb076Ted Kremenek // Rule II. 2377b9e13d555fc9f3e5515e2b1fa6f720e6f10bb076Ted Kremenek // 2378a399f776ee29e099da33eaf7f9d585b4edc4b61dTed Kremenek // Eliminate edges between subexpressions and parent expressions 2379a399f776ee29e099da33eaf7f9d585b4edc4b61dTed Kremenek // when the subexpression is consumed. 2380f468fa16e37fc8fa6a915fe36aee8f0434709789Ted Kremenek // 2381f468fa16e37fc8fa6a915fe36aee8f0434709789Ted Kremenek // NOTE: this will be limited later in cases where we add barriers 2382f468fa16e37fc8fa6a915fe36aee8f0434709789Ted Kremenek // to prevent this optimization. 2383f468fa16e37fc8fa6a915fe36aee8f0434709789Ted Kremenek // 238496b8134337883908fcc45484486fe200d6b3e32fTed Kremenek if (s1End && s1End == s2Start && level2) { 238552f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek bool removeEdge = false; 238652f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek // Remove edges into the increment or initialization of a 238752f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek // loop that have no interleaving event. This means that 238852f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek // they aren't interesting. 238952f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek if (isIncrementOrInitInForLoop(s1End, level2)) 239052f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek removeEdge = true; 239152f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek // Next only consider edges that are not anchored on 239252f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek // the condition of a terminator. This are intermediate edges 239352f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek // that we might want to trim. 239452f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek else if (!isConditionForTerminator(level2, s1End)) { 239552f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek // Trim edges on expressions that are consumed by 239652f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek // the parent expression. 239752f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek if (isa<Expr>(s1End) && PM.isConsumedExpr(cast<Expr>(s1End))) { 239852f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek removeEdge = true; 239952f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek } 240052f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek // Trim edges where a lexical containment doesn't exist. 240152f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek // For example: 240252f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek // 240352f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek // X -> Y -> Z 240452f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek // 240552f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek // If 'Z' lexically contains Y (it is an ancestor) and 240652f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek // 'X' does not lexically contain Y (it is a descendant OR 240752f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek // it has no lexical relationship at all) then trim. 240852f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek // 240952f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek // This can eliminate edges where we dive into a subexpression 241052f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek // and then pop back out, etc. 241152f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek else if (s1Start && s2End && 241252f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek lexicalContains(PM, s2Start, s2End) && 241352f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek !lexicalContains(PM, s1End, s1Start)) { 241452f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek removeEdge = true; 241552f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek } 2416e624524705ab660eb8d1feb9870ef2989fb2bdf4Jordan Rose // Trim edges from a subexpression back to the top level if the 2417e624524705ab660eb8d1feb9870ef2989fb2bdf4Jordan Rose // subexpression is on a different line. 2418e624524705ab660eb8d1feb9870ef2989fb2bdf4Jordan Rose // 2419e624524705ab660eb8d1feb9870ef2989fb2bdf4Jordan Rose // A.1 -> A -> B 2420e624524705ab660eb8d1feb9870ef2989fb2bdf4Jordan Rose // becomes 2421e624524705ab660eb8d1feb9870ef2989fb2bdf4Jordan Rose // A.1 -> B 2422e624524705ab660eb8d1feb9870ef2989fb2bdf4Jordan Rose // 2423e624524705ab660eb8d1feb9870ef2989fb2bdf4Jordan Rose // These edges just look ugly and don't usually add anything. 2424e624524705ab660eb8d1feb9870ef2989fb2bdf4Jordan Rose else if (s1Start && s2End && 2425e624524705ab660eb8d1feb9870ef2989fb2bdf4Jordan Rose lexicalContains(PM, s1Start, s1End)) { 2426e624524705ab660eb8d1feb9870ef2989fb2bdf4Jordan Rose SourceRange EdgeRange(PieceI->getEndLocation().asLocation(), 2427e624524705ab660eb8d1feb9870ef2989fb2bdf4Jordan Rose PieceI->getStartLocation().asLocation()); 2428e624524705ab660eb8d1feb9870ef2989fb2bdf4Jordan Rose if (!getLengthOnSingleLine(SM, EdgeRange).hasValue()) 2429e624524705ab660eb8d1feb9870ef2989fb2bdf4Jordan Rose removeEdge = true; 2430e624524705ab660eb8d1feb9870ef2989fb2bdf4Jordan Rose } 243152f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek } 243252f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek 243352f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek if (removeEdge) { 243496b8134337883908fcc45484486fe200d6b3e32fTed Kremenek PieceI->setEndLocation(PieceNextI->getEndLocation()); 243596b8134337883908fcc45484486fe200d6b3e32fTed Kremenek path.erase(NextI); 243696b8134337883908fcc45484486fe200d6b3e32fTed Kremenek hasChanges = true; 243796b8134337883908fcc45484486fe200d6b3e32fTed Kremenek continue; 243896b8134337883908fcc45484486fe200d6b3e32fTed Kremenek } 2439f468fa16e37fc8fa6a915fe36aee8f0434709789Ted Kremenek } 2440481da5554d03271b0d87b695449963f7728c5895Ted Kremenek 2441e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek // Optimize edges for ObjC fast-enumeration loops. 2442e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek // 2443e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek // (X -> collection) -> (collection -> element) 2444e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek // 2445e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek // becomes: 2446e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek // 2447e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek // (X -> element) 2448e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek if (s1End == s2Start) { 2449e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek const ObjCForCollectionStmt *FS = 2450e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek dyn_cast_or_null<ObjCForCollectionStmt>(level3); 2451e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek if (FS && FS->getCollection()->IgnoreParens() == s2Start && 2452e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek s2End == FS->getElement()) { 2453e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek PieceI->setEndLocation(PieceNextI->getEndLocation()); 2454e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek path.erase(NextI); 2455e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek hasChanges = true; 2456e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek continue; 2457e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek } 2458e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek } 2459e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek 2460481da5554d03271b0d87b695449963f7728c5895Ted Kremenek // No changes at this index? Move to the next one. 2461481da5554d03271b0d87b695449963f7728c5895Ted Kremenek ++I; 2462bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek } 2463bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek 2464de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek if (!hasChanges) { 246596f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose // Adjust edges into subexpressions to make them more uniform 246696f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose // and aesthetically pleasing. 246796f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose addContextEdges(path, SM, PM, LC); 24683b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose // Remove "cyclical" edges that include one or more context edges. 246922b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose removeContextCycles(path, SM, PM); 247096f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose // Hoist edges originating from branch conditions to branches 247196f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose // for simple branches. 247296f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose simplifySimpleBranches(path); 2473de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek // Remove any puny edges left over after primary optimization pass. 2474de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek removePunyEdges(path, SM, PM); 24751d85a9e8fb4e6ac513467b5fa825bd53e6fcba56Ted Kremenek // Remove identical events. 24761d85a9e8fb4e6ac513467b5fa825bd53e6fcba56Ted Kremenek removeIdenticalEvents(path); 2477de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek } 2478de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek 2479bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek return hasChanges; 2480bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek} 2481bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek 248201f1ff79f70b3e042995a43b29ccbf0fffc77d5fJordan Rose/// Drop the very first edge in a path, which should be a function entry edge. 248301f1ff79f70b3e042995a43b29ccbf0fffc77d5fJordan Rosestatic void dropFunctionEntryEdge(PathPieces &Path, 248401f1ff79f70b3e042995a43b29ccbf0fffc77d5fJordan Rose LocationContextMap &LCM, 248501f1ff79f70b3e042995a43b29ccbf0fffc77d5fJordan Rose SourceManager &SM) { 248601f1ff79f70b3e042995a43b29ccbf0fffc77d5fJordan Rose#ifndef NDEBUG 248701f1ff79f70b3e042995a43b29ccbf0fffc77d5fJordan Rose const Decl *D = LCM[&Path]->getDecl(); 248801f1ff79f70b3e042995a43b29ccbf0fffc77d5fJordan Rose PathDiagnosticLocation EntryLoc = 248901f1ff79f70b3e042995a43b29ccbf0fffc77d5fJordan Rose PathDiagnosticLocation::createBegin(D, SM); 249001f1ff79f70b3e042995a43b29ccbf0fffc77d5fJordan Rose const PathDiagnosticControlFlowPiece *FirstEdge = 249101f1ff79f70b3e042995a43b29ccbf0fffc77d5fJordan Rose cast<PathDiagnosticControlFlowPiece>(Path.front()); 249201f1ff79f70b3e042995a43b29ccbf0fffc77d5fJordan Rose assert(FirstEdge->getStartLocation() == EntryLoc && "not an entry edge"); 249301f1ff79f70b3e042995a43b29ccbf0fffc77d5fJordan Rose#endif 249401f1ff79f70b3e042995a43b29ccbf0fffc77d5fJordan Rose 249501f1ff79f70b3e042995a43b29ccbf0fffc77d5fJordan Rose Path.pop_front(); 249601f1ff79f70b3e042995a43b29ccbf0fffc77d5fJordan Rose} 249701f1ff79f70b3e042995a43b29ccbf0fffc77d5fJordan Rose 249801f1ff79f70b3e042995a43b29ccbf0fffc77d5fJordan Rose 24995fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek//===----------------------------------------------------------------------===// 25003106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// Methods for BugType and subclasses. 25013106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 2502404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios KyrtzidisBugType::~BugType() { } 2503404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis 25043106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenekvoid BugType::FlushReports(BugReporter &BR) {} 25053106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 250699ba9e3bd70671f3441fb974895f226a83ce0e66David Blaikievoid BuiltinBug::anchor() {} 250799ba9e3bd70671f3441fb974895f226a83ce0e66David Blaikie 25083106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 25093106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// Methods for BugReport and subclasses. 25103106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 2511e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks 251299ba9e3bd70671f3441fb974895f226a83ce0e66David Blaikievoid BugReport::NodeResolver::anchor() {} 251399ba9e3bd70671f3441fb974895f226a83ce0e66David Blaikie 25148e6431adab313e283a992698f6fc7afe62420999Anna Zaksvoid BugReport::addVisitor(BugReporterVisitor* visitor) { 25158e6431adab313e283a992698f6fc7afe62420999Anna Zaks if (!visitor) 25168e6431adab313e283a992698f6fc7afe62420999Anna Zaks return; 25178e6431adab313e283a992698f6fc7afe62420999Anna Zaks 25188e6431adab313e283a992698f6fc7afe62420999Anna Zaks llvm::FoldingSetNodeID ID; 25198e6431adab313e283a992698f6fc7afe62420999Anna Zaks visitor->Profile(ID); 25208e6431adab313e283a992698f6fc7afe62420999Anna Zaks void *InsertPos; 25218e6431adab313e283a992698f6fc7afe62420999Anna Zaks 25228e6431adab313e283a992698f6fc7afe62420999Anna Zaks if (CallbacksSet.FindNodeOrInsertPos(ID, InsertPos)) { 25238e6431adab313e283a992698f6fc7afe62420999Anna Zaks delete visitor; 25248e6431adab313e283a992698f6fc7afe62420999Anna Zaks return; 25258e6431adab313e283a992698f6fc7afe62420999Anna Zaks } 25268e6431adab313e283a992698f6fc7afe62420999Anna Zaks 25278e6431adab313e283a992698f6fc7afe62420999Anna Zaks CallbacksSet.InsertNode(visitor, InsertPos); 25283bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose Callbacks.push_back(visitor); 25293bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose ++ConfigurationChangeToken; 25308e6431adab313e283a992698f6fc7afe62420999Anna Zaks} 25318e6431adab313e283a992698f6fc7afe62420999Anna Zaks 25328e6431adab313e283a992698f6fc7afe62420999Anna ZaksBugReport::~BugReport() { 25338e6431adab313e283a992698f6fc7afe62420999Anna Zaks for (visitor_iterator I = visitor_begin(), E = visitor_end(); I != E; ++I) { 2534dc757b049796949e4b11646445a6598f0bdabd7aAnna Zaks delete *I; 25358e6431adab313e283a992698f6fc7afe62420999Anna Zaks } 2536c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek while (!interestingSymbols.empty()) { 2537c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek popInterestingSymbolsAndRegions(); 2538c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek } 25398e6431adab313e283a992698f6fc7afe62420999Anna Zaks} 2540e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks 254107189521a15d9c088216b943649cb9fe231cbb57Ted Kremenekconst Decl *BugReport::getDeclWithIssue() const { 254207189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek if (DeclWithIssue) 254307189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek return DeclWithIssue; 254407189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek 254507189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek const ExplodedNode *N = getErrorNode(); 254607189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek if (!N) 254707189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek return 0; 254807189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek 254907189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek const LocationContext *LC = N->getLocationContext(); 255007189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek return LC->getCurrentStackFrame()->getDecl(); 255107189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek} 255207189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek 2553e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaksvoid BugReport::Profile(llvm::FoldingSetNodeID& hash) const { 2554e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks hash.AddPointer(&BT); 2555e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks hash.AddString(Description); 255697bfb558f69c09b01a5c1510f08dc91eb62329a7Anna Zaks PathDiagnosticLocation UL = getUniqueingLocation(); 255797bfb558f69c09b01a5c1510f08dc91eb62329a7Anna Zaks if (UL.isValid()) { 255897bfb558f69c09b01a5c1510f08dc91eb62329a7Anna Zaks UL.Profile(hash); 2559ca8e36eb637e232475ef31c3f22d5da907390917Anna Zaks } else if (Location.isValid()) { 2560590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks Location.Profile(hash); 2561590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks } else { 2562590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks assert(ErrorNode); 2563590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks hash.AddPointer(GetCurrentOrPreviousStmt(ErrorNode)); 2564590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks } 2565e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks 2566e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks for (SmallVectorImpl<SourceRange>::const_iterator I = 2567e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks Ranges.begin(), E = Ranges.end(); I != E; ++I) { 2568e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks const SourceRange range = *I; 2569e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks if (!range.isValid()) 2570e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks continue; 2571e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks hash.AddInteger(range.getBegin().getRawEncoding()); 2572e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks hash.AddInteger(range.getEnd().getRawEncoding()); 2573e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks } 2574e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks} 25753106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 257676aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenekvoid BugReport::markInteresting(SymbolRef sym) { 257776aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek if (!sym) 257876aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek return; 25793bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose 25803bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose // If the symbol wasn't already in our set, note a configuration change. 2581c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek if (getInterestingSymbols().insert(sym).second) 25823bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose ++ConfigurationChangeToken; 25838ec588e2ac57311604cf80608c7d4b3fb3b022f7Jordy Rose 25848ec588e2ac57311604cf80608c7d4b3fb3b022f7Jordy Rose if (const SymbolMetadata *meta = dyn_cast<SymbolMetadata>(sym)) 2585c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek getInterestingRegions().insert(meta->getRegion()); 258676aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek} 258776aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek 258876aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenekvoid BugReport::markInteresting(const MemRegion *R) { 258976aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek if (!R) 259076aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek return; 25913bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose 25923bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose // If the base region wasn't already in our set, note a configuration change. 259376aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek R = R->getBaseRegion(); 2594c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek if (getInterestingRegions().insert(R).second) 25953bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose ++ConfigurationChangeToken; 25968ec588e2ac57311604cf80608c7d4b3fb3b022f7Jordy Rose 259776aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R)) 2598c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek getInterestingSymbols().insert(SR->getSymbol()); 259976aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek} 260076aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek 260176aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenekvoid BugReport::markInteresting(SVal V) { 260276aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek markInteresting(V.getAsRegion()); 260376aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek markInteresting(V.getAsSymbol()); 260476aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek} 260576aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek 260680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaksvoid BugReport::markInteresting(const LocationContext *LC) { 260780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks if (!LC) 260880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks return; 260980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks InterestingLocationContexts.insert(LC); 261080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks} 261180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks 2612c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenekbool BugReport::isInteresting(SVal V) { 261376aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek return isInteresting(V.getAsRegion()) || isInteresting(V.getAsSymbol()); 261476aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek} 261576aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek 2616c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenekbool BugReport::isInteresting(SymbolRef sym) { 261776aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek if (!sym) 261876aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek return false; 26198ec588e2ac57311604cf80608c7d4b3fb3b022f7Jordy Rose // We don't currently consider metadata symbols to be interesting 26208ec588e2ac57311604cf80608c7d4b3fb3b022f7Jordy Rose // even if we know their region is interesting. Is that correct behavior? 2621c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek return getInterestingSymbols().count(sym); 262276aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek} 262376aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek 2624c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenekbool BugReport::isInteresting(const MemRegion *R) { 262576aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek if (!R) 262676aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek return false; 262776aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek R = R->getBaseRegion(); 2628c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek bool b = getInterestingRegions().count(R); 262976aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek if (b) 263076aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek return true; 263176aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R)) 2632c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek return getInterestingSymbols().count(SR->getSymbol()); 263376aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek return false; 263476aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek} 2635c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek 263680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaksbool BugReport::isInteresting(const LocationContext *LC) { 263780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks if (!LC) 263880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks return false; 263980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks return InterestingLocationContexts.count(LC); 264080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks} 264180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks 2642c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenekvoid BugReport::lazyInitializeInterestingSets() { 2643c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek if (interestingSymbols.empty()) { 2644c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek interestingSymbols.push_back(new Symbols()); 2645c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek interestingRegions.push_back(new Regions()); 2646c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek } 2647c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek} 2648c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek 2649c4bac8e376b98d633bb00ee5f510d5e58449753cTed KremenekBugReport::Symbols &BugReport::getInterestingSymbols() { 2650c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek lazyInitializeInterestingSets(); 2651c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek return *interestingSymbols.back(); 2652c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek} 2653c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek 2654c4bac8e376b98d633bb00ee5f510d5e58449753cTed KremenekBugReport::Regions &BugReport::getInterestingRegions() { 2655c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek lazyInitializeInterestingSets(); 2656c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek return *interestingRegions.back(); 2657c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek} 2658c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek 2659c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenekvoid BugReport::pushInterestingSymbolsAndRegions() { 2660c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek interestingSymbols.push_back(new Symbols(getInterestingSymbols())); 2661c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek interestingRegions.push_back(new Regions(getInterestingRegions())); 2662c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek} 2663c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek 2664c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenekvoid BugReport::popInterestingSymbolsAndRegions() { 2665c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek delete interestingSymbols.back(); 2666c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek interestingSymbols.pop_back(); 2667c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek delete interestingRegions.back(); 2668c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek interestingRegions.pop_back(); 2669c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek} 267076aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek 26719c378f705405d37f49795d5e915989de774fe11fTed Kremenekconst Stmt *BugReport::getStmt() const { 2672e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks if (!ErrorNode) 2673e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks return 0; 2674e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks 2675212f6d3b5fb3fa55ba1e40671cfc336430abc8ddTom Care ProgramPoint ProgP = ErrorNode->getLocation(); 26765f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek const Stmt *S = NULL; 26771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 26787a95de68c093991047ed8d339479ccad51b88663David Blaikie if (Optional<BlockEntrance> BE = ProgP.getAs<BlockEntrance>()) { 2679fafd3834754d2093e0ad7a1c005860fd527ecb7fZhongxing Xu CFGBlock &Exit = ProgP.getLocationContext()->getCFG()->getExit(); 268050d5bc4e3b53eb8bb4ebf198f1213348a3fa0f38Zhongxing Xu if (BE->getBlock() == &Exit) 2681212f6d3b5fb3fa55ba1e40671cfc336430abc8ddTom Care S = GetPreviousStmt(ErrorNode); 26823106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 26835f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek if (!S) 26840f8579274a010f360a371b53101859d9d6052314Anna Zaks S = PathDiagnosticLocation::getStmt(ErrorNode); 26851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 26861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return S; 26873106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 26883106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 2689640ccf071076e684713cc3c3276bb51982bff607Argyrios Kyrtzidisstd::pair<BugReport::ranges_iterator, BugReport::ranges_iterator> 2690e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna ZaksBugReport::getRanges() { 2691e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks // If no custom ranges, add the range of the statement corresponding to 2692e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks // the error node. 2693e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks if (Ranges.empty()) { 2694e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks if (const Expr *E = dyn_cast_or_null<Expr>(getStmt())) 2695e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks addRange(E->getSourceRange()); 2696e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks else 2697e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks return std::make_pair(ranges_iterator(), ranges_iterator()); 2698e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks } 2699e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks 270014924267950e75c6c1f6fcea39fa507b7168bc39Anna Zaks // User-specified absence of range info. 270114924267950e75c6c1f6fcea39fa507b7168bc39Anna Zaks if (Ranges.size() == 1 && !Ranges.begin()->isValid()) 270214924267950e75c6c1f6fcea39fa507b7168bc39Anna Zaks return std::make_pair(ranges_iterator(), ranges_iterator()); 270314924267950e75c6c1f6fcea39fa507b7168bc39Anna Zaks 2704e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks return std::make_pair(Ranges.begin(), Ranges.end()); 27053106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 27063106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 2707590dd8e0959d8df5621827768987c4792b74fc06Anna ZaksPathDiagnosticLocation BugReport::getLocation(const SourceManager &SM) const { 2708b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks if (ErrorNode) { 2709590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks assert(!Location.isValid() && 2710b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks "Either Location or ErrorNode should be specified but not both."); 27110f8579274a010f360a371b53101859d9d6052314Anna Zaks return PathDiagnosticLocation::createEndOfPath(ErrorNode, SM); 2712b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks } else { 2713b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks assert(Location.isValid()); 2714b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks return Location; 2715b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks } 2716b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks 2717590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks return PathDiagnosticLocation(); 27183106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 27193106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 27203106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 27213106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// Methods for BugReporter and subclasses. 27223106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 27233106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 27244a5f724538cbc275370c9504e8169ce92503256cBenjamin KramerBugReportEquivClass::~BugReportEquivClass() { } 2725a2f4ec0df645fc249d2945beef9653f03b175417Zhongxing XuGRBugReporter::~GRBugReporter() { } 27263106198188ac6eb2753f1764d5c28376b0b76351Ted KremenekBugReporterData::~BugReporterData() {} 27273106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 272838b02b912e1a55c912f603c4369431264d36a381Zhongxing XuExplodedGraph &GRBugReporter::getGraph() { return Eng.getGraph(); } 27293106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 273018c66fdc3c4008d335885695fe36fb5353c5f672Ted KremenekProgramStateManager& 27313106198188ac6eb2753f1764d5c28376b0b76351Ted KremenekGRBugReporter::getStateManager() { return Eng.getStateManager(); } 27323106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 27333b030a28cda2b953758507769c1d436bec5ec45eAnna ZaksBugReporter::~BugReporter() { 27343b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks FlushReports(); 27353b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks 27363b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks // Free the bug reports we are tracking. 27373b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks typedef std::vector<BugReportEquivClass *> ContTy; 27383b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks for (ContTy::iterator I = EQClassesVector.begin(), E = EQClassesVector.end(); 27393b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks I != E; ++I) { 27403b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks delete *I; 27413b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks } 27423b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks} 27433106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 27443106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenekvoid BugReporter::FlushReports() { 27453106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (BugTypes.isEmpty()) 27463106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek return; 27473106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 27483106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // First flush the warnings for each BugType. This may end up creating new 2749404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // warnings and new BugTypes. 2750404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // FIXME: Only NSErrorChecker needs BugType's FlushReports. 2751404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // Turn NSErrorChecker into a proper checker and remove this. 27525f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<const BugType*, 16> bugTypes; 27533106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek for (BugTypesTy::iterator I=BugTypes.begin(), E=BugTypes.end(); I!=E; ++I) 2754404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis bugTypes.push_back(*I); 27555f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner for (SmallVector<const BugType*, 16>::iterator 2756404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis I = bugTypes.begin(), E = bugTypes.end(); I != E; ++I) 27573106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek const_cast<BugType*>(*I)->FlushReports(*this); 27583106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 2759d015f4febe85d3e3340172d70042840c51bbd836Anna Zaks // We need to flush reports in deterministic order to ensure the order 2760d015f4febe85d3e3340172d70042840c51bbd836Anna Zaks // of the reports is consistent between runs. 27610eb6c37dd4e4ad8fa2363003dea270f9fd6c2969Anna Zaks typedef std::vector<BugReportEquivClass *> ContVecTy; 27620eb6c37dd4e4ad8fa2363003dea270f9fd6c2969Anna Zaks for (ContVecTy::iterator EI=EQClassesVector.begin(), EE=EQClassesVector.end(); 27630eb6c37dd4e4ad8fa2363003dea270f9fd6c2969Anna Zaks EI != EE; ++EI){ 27640eb6c37dd4e4ad8fa2363003dea270f9fd6c2969Anna Zaks BugReportEquivClass& EQ = **EI; 2765404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis FlushReport(EQ); 27663106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 27673106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 2768404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // BugReporter owns and deletes only BugTypes created implicitly through 2769404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // EmitBasicReport. 2770404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // FIXME: There are leaks from checkers that assume that the BugTypes they 2771404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // create will be destroyed by the BugReporter. 2772404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis for (llvm::StringMap<BugType*>::iterator 2773404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis I = StrBugTypes.begin(), E = StrBugTypes.end(); I != E; ++I) 2774404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis delete I->second; 2775404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis 27763106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Remove all references to the BugType objects. 27773baf672378f105602d2b12f03f00277ae1936fe9Ted Kremenek BugTypes = F.getEmptySet(); 27783106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 27793106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 27803106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 27813106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// PathDiagnostics generation. 27823106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 27833106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 27841efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rosenamespace { 27851efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose/// A wrapper around a report graph, which contains only a single path, and its 27861efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose/// node maps. 27871efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Roseclass ReportGraph { 27881efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rosepublic: 27891efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose InterExplodedGraphMap BackMap; 2790228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose OwningPtr<ExplodedGraph> Graph; 2791228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose const ExplodedNode *ErrorNode; 27921efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose size_t Index; 27931efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose}; 27941efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose 27951efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose/// A wrapper around a trimmed graph and its node maps. 27961efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Roseclass TrimmedGraph { 27971efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose InterExplodedGraphMap InverseMap; 27982110350909701fcd6b55c636e24a675f0a905feaJordan Rose 27992110350909701fcd6b55c636e24a675f0a905feaJordan Rose typedef llvm::DenseMap<const ExplodedNode *, unsigned> PriorityMapTy; 28002110350909701fcd6b55c636e24a675f0a905feaJordan Rose PriorityMapTy PriorityMap; 28012110350909701fcd6b55c636e24a675f0a905feaJordan Rose 2802228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose typedef std::pair<const ExplodedNode *, size_t> NodeIndexPair; 2803228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose SmallVector<NodeIndexPair, 32> ReportNodes; 2804228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose 28051efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose OwningPtr<ExplodedGraph> G; 2806228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose 2807228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose /// A helper class for sorting ExplodedNodes by priority. 2808228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose template <bool Descending> 2809228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose class PriorityCompare { 2810228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose const PriorityMapTy &PriorityMap; 2811228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose 2812228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose public: 2813228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose PriorityCompare(const PriorityMapTy &M) : PriorityMap(M) {} 2814228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose 2815228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose bool operator()(const ExplodedNode *LHS, const ExplodedNode *RHS) const { 2816228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose PriorityMapTy::const_iterator LI = PriorityMap.find(LHS); 2817228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose PriorityMapTy::const_iterator RI = PriorityMap.find(RHS); 2818228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose PriorityMapTy::const_iterator E = PriorityMap.end(); 2819228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose 2820228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose if (LI == E) 2821228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose return Descending; 2822228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose if (RI == E) 2823228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose return !Descending; 2824228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose 2825228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose return Descending ? LI->second > RI->second 2826228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose : LI->second < RI->second; 2827228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose } 2828228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose 2829228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose bool operator()(const NodeIndexPair &LHS, const NodeIndexPair &RHS) const { 2830228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose return (*this)(LHS.first, RHS.first); 2831228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose } 2832228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose }; 2833228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose 28341efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rosepublic: 28351efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose TrimmedGraph(const ExplodedGraph *OriginalGraph, 28362110350909701fcd6b55c636e24a675f0a905feaJordan Rose ArrayRef<const ExplodedNode *> Nodes); 28371efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose 2838228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose bool popNextReportGraph(ReportGraph &GraphWrapper); 28391efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose}; 28401efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose} 28411efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose 28422110350909701fcd6b55c636e24a675f0a905feaJordan RoseTrimmedGraph::TrimmedGraph(const ExplodedGraph *OriginalGraph, 28432110350909701fcd6b55c636e24a675f0a905feaJordan Rose ArrayRef<const ExplodedNode *> Nodes) { 28442110350909701fcd6b55c636e24a675f0a905feaJordan Rose // The trimmed graph is created in the body of the constructor to ensure 28452110350909701fcd6b55c636e24a675f0a905feaJordan Rose // that the DenseMaps have been initialized already. 2846228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose InterExplodedGraphMap ForwardMap; 28470f3a34fb7fea37ebfbcba8b400ccb697b9559b49Jordan Rose G.reset(OriginalGraph->trim(Nodes, &ForwardMap, &InverseMap)); 28481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 28493106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Find the (first) error node in the trimmed graph. We just need to consult 28501efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose // the node map which maps from nodes in the original graph to nodes 28513106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // in the new graph. 2852228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose llvm::SmallPtrSet<const ExplodedNode *, 32> RemainingNodes; 28533106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 28541efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose for (unsigned i = 0, count = Nodes.size(); i < count; ++i) { 2855228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose if (const ExplodedNode *NewNode = ForwardMap.lookup(Nodes[i])) { 2856228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose ReportNodes.push_back(std::make_pair(NewNode, i)); 2857228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose RemainingNodes.insert(NewNode); 28583106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 285940406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek } 28601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2861228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose assert(!RemainingNodes.empty() && "No error node found in the trimmed graph"); 2862228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose 2863228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose // Perform a forward BFS to find all the shortest paths. 2864228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose std::queue<const ExplodedNode *> WS; 2865228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose 2866228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose assert(G->num_roots() == 1); 2867228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose WS.push(*G->roots_begin()); 2868228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose unsigned Priority = 0; 28693106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 28703106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek while (!WS.empty()) { 2871228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose const ExplodedNode *Node = WS.front(); 28723106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek WS.pop(); 28731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 28742110350909701fcd6b55c636e24a675f0a905feaJordan Rose PriorityMapTy::iterator PriorityEntry; 28752110350909701fcd6b55c636e24a675f0a905feaJordan Rose bool IsNew; 28762110350909701fcd6b55c636e24a675f0a905feaJordan Rose llvm::tie(PriorityEntry, IsNew) = 28772110350909701fcd6b55c636e24a675f0a905feaJordan Rose PriorityMap.insert(std::make_pair(Node, Priority)); 2878228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose ++Priority; 28791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 28802110350909701fcd6b55c636e24a675f0a905feaJordan Rose if (!IsNew) { 28812110350909701fcd6b55c636e24a675f0a905feaJordan Rose assert(PriorityEntry->second <= Priority); 28822110350909701fcd6b55c636e24a675f0a905feaJordan Rose continue; 28832110350909701fcd6b55c636e24a675f0a905feaJordan Rose } 28841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2885228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose if (RemainingNodes.erase(Node)) 2886228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose if (RemainingNodes.empty()) 2887228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose break; 2888a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose 2889228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose for (ExplodedNode::const_pred_iterator I = Node->succ_begin(), 2890228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose E = Node->succ_end(); 28912110350909701fcd6b55c636e24a675f0a905feaJordan Rose I != E; ++I) 2892228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose WS.push(*I); 2893239b6e47d282bd66c8b559ac47b8b42b34da619eJordan Rose } 28942110350909701fcd6b55c636e24a675f0a905feaJordan Rose 2895228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose // Sort the error paths from longest to shortest. 2896228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose std::sort(ReportNodes.begin(), ReportNodes.end(), 2897228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose PriorityCompare<true>(PriorityMap)); 2898228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose} 28992110350909701fcd6b55c636e24a675f0a905feaJordan Rose 2900228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rosebool TrimmedGraph::popNextReportGraph(ReportGraph &GraphWrapper) { 2901228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose if (ReportNodes.empty()) 2902228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose return false; 29032110350909701fcd6b55c636e24a675f0a905feaJordan Rose 2904228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose const ExplodedNode *OrigN; 2905228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose llvm::tie(OrigN, GraphWrapper.Index) = ReportNodes.pop_back_val(); 2906228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose assert(PriorityMap.find(OrigN) != PriorityMap.end() && 2907228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose "error node not accessible from root"); 29082110350909701fcd6b55c636e24a675f0a905feaJordan Rose 29092110350909701fcd6b55c636e24a675f0a905feaJordan Rose // Create a new graph with a single path. This is the graph 29102110350909701fcd6b55c636e24a675f0a905feaJordan Rose // that will be returned to the caller. 29112110350909701fcd6b55c636e24a675f0a905feaJordan Rose ExplodedGraph *GNew = new ExplodedGraph(); 29122110350909701fcd6b55c636e24a675f0a905feaJordan Rose GraphWrapper.Graph.reset(GNew); 2913228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose GraphWrapper.BackMap.clear(); 29141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2915228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose // Now walk from the error node up the BFS path, always taking the 2916228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose // predeccessor with the lowest number. 2917228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose ExplodedNode *Succ = 0; 2918228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose while (true) { 29193106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Create the equivalent node in the new graph with the same state 29203106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // and location. 29213e5ebf1a05603e08f2d0b2b2a5fa9406fe4cfb22Jordan Rose ExplodedNode *NewN = GNew->getNode(OrigN->getLocation(), OrigN->getState(), 29223e5ebf1a05603e08f2d0b2b2a5fa9406fe4cfb22Jordan Rose OrigN->isSink()); 29231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 29243106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Store the mapping to the original node. 2925228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose InterExplodedGraphMap::const_iterator IMitr = InverseMap.find(OrigN); 29263106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek assert(IMitr != InverseMap.end() && "No mapping to original node."); 29271efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose GraphWrapper.BackMap[NewN] = IMitr->second; 29281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 29293106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Link up the new node with the previous node. 2930228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose if (Succ) 2931228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose Succ->addPredecessor(NewN, *GNew); 2932228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose else 2933228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose GraphWrapper.ErrorNode = NewN; 29341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2935228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose Succ = NewN; 29361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 29373106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Are we at the final node? 2938228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose if (OrigN->pred_empty()) { 2939228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose GNew->addRoot(NewN); 29403106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 29413106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 29421eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2943228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose // Find the next predeccessor node. We choose the node that is marked 29442110350909701fcd6b55c636e24a675f0a905feaJordan Rose // with the lowest BFS number. 2945228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose OrigN = *std::min_element(OrigN->pred_begin(), OrigN->pred_end(), 2946228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose PriorityCompare<false>(PriorityMap)); 29472110350909701fcd6b55c636e24a675f0a905feaJordan Rose } 29482110350909701fcd6b55c636e24a675f0a905feaJordan Rose 2949228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose return true; 29502110350909701fcd6b55c636e24a675f0a905feaJordan Rose} 29512110350909701fcd6b55c636e24a675f0a905feaJordan Rose 29522110350909701fcd6b55c636e24a675f0a905feaJordan Rose 29533106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek/// CompactPathDiagnostic - This function postprocesses a PathDiagnostic object 29543106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek/// and collapses PathDiagosticPieces that are expanded by macros. 295577d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenekstatic void CompactPathDiagnostic(PathPieces &path, const SourceManager& SM) { 29562042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek typedef std::vector<std::pair<IntrusiveRefCntPtr<PathDiagnosticMacroPiece>, 29572042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek SourceLocation> > MacroStackTy; 29581eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2959c93dc7889644293e318e19d82830ea2acc45b678Dylan Noblesmith typedef std::vector<IntrusiveRefCntPtr<PathDiagnosticPiece> > 29603106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PiecesTy; 29611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 29623106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroStackTy MacroStack; 29633106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PiecesTy Pieces; 29641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2965ed866e73bab7733f5226f84c52edefe23d694b2fTed Kremenek for (PathPieces::const_iterator I = path.begin(), E = path.end(); 29662042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek I!=E; ++I) { 296777d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek 2968ed866e73bab7733f5226f84c52edefe23d694b2fTed Kremenek PathDiagnosticPiece *piece = I->getPtr(); 296977d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek 297077d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek // Recursively compact calls. 297177d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek if (PathDiagnosticCallPiece *call=dyn_cast<PathDiagnosticCallPiece>(piece)){ 297277d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek CompactPathDiagnostic(call->path, SM); 297377d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek } 297477d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek 29753106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Get the location of the PathDiagnosticPiece. 297677d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek const FullSourceLoc Loc = piece->getLocation().asLocation(); 29771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 29783106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Determine the instantiation location, which is the location we group 29793106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // related PathDiagnosticPieces. 29801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump SourceLocation InstantiationLoc = Loc.isMacroID() ? 2981402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth SM.getExpansionLoc(Loc) : 29823106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek SourceLocation(); 29831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 29843106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (Loc.isFileID()) { 29853106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroStack.clear(); 298677d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek Pieces.push_back(piece); 29873106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek continue; 29883106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 2989706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek 29903106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek assert(Loc.isMacroID()); 29911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 29923106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Is the PathDiagnosticPiece within the same macro group? 29933106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (!MacroStack.empty() && InstantiationLoc == MacroStack.back().second) { 299477d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek MacroStack.back().first->subPieces.push_back(piece); 29953106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek continue; 29963106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 2997d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek 29983106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // We aren't in the same group. Are we descending into a new macro 29993106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // or are part of an old one? 3000c93dc7889644293e318e19d82830ea2acc45b678Dylan Noblesmith IntrusiveRefCntPtr<PathDiagnosticMacroPiece> MacroGroup; 3001d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek 30023106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek SourceLocation ParentInstantiationLoc = InstantiationLoc.isMacroID() ? 3003402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth SM.getExpansionLoc(Loc) : 30043106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek SourceLocation(); 30051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 30063106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Walk the entire macro stack. 30073106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek while (!MacroStack.empty()) { 30083106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (InstantiationLoc == MacroStack.back().second) { 30093106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroGroup = MacroStack.back().first; 30103106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 30113106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 30121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 30133106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (ParentInstantiationLoc == MacroStack.back().second) { 30143106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroGroup = MacroStack.back().first; 30153106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 301661f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek } 30171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 30183106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroStack.pop_back(); 30196837faa083bebad39aa342f84c2b450fb6410eafTed Kremenek } 30201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 30213106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (!MacroGroup || ParentInstantiationLoc == MacroStack.back().second) { 30223106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Create a new macro group and add it to the stack. 3023590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks PathDiagnosticMacroPiece *NewGroup = 3024590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks new PathDiagnosticMacroPiece( 302577d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek PathDiagnosticLocation::createSingleLocation(piece->getLocation())); 30265a429954aedd8a830a70fcea2cb51561673e4fc3Ted Kremenek 30273106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (MacroGroup) 3028802e02463b880f53a6e645bde78cc412481ce9e0Ted Kremenek MacroGroup->subPieces.push_back(NewGroup); 30293106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek else { 30303106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek assert(InstantiationLoc.isFileID()); 30313106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek Pieces.push_back(NewGroup); 30323106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 30331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 30343106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroGroup = NewGroup; 30353106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroStack.push_back(std::make_pair(MacroGroup, InstantiationLoc)); 30367dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek } 30373106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 30383106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Finally, add the PathDiagnosticPiece to the group. 303977d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek MacroGroup->subPieces.push_back(piece); 30403106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 30411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 30423106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Now take the pieces and construct a new PathDiagnostic. 304377d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek path.clear(); 30441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 304577d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek for (PiecesTy::iterator I=Pieces.begin(), E=Pieces.end(); I!=E; ++I) 304677d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek path.push_back(*I); 304761f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek} 304861f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek 30498347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rosebool GRBugReporter::generatePathDiagnostic(PathDiagnostic& PD, 3050c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek PathDiagnosticConsumer &PC, 3051c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek ArrayRef<BugReport *> &bugReports) { 305240406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek assert(!bugReports.empty()); 30538347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose 30549a9fe4068eed2fc72ec985e5ae393fb79a8fb9adJordan Rose bool HasValid = false; 3055228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose bool HasInvalid = false; 30562f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose SmallVector<const ExplodedNode *, 32> errorNodes; 3057c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek for (ArrayRef<BugReport*>::iterator I = bugReports.begin(), 30589a9fe4068eed2fc72ec985e5ae393fb79a8fb9adJordan Rose E = bugReports.end(); I != E; ++I) { 30599a9fe4068eed2fc72ec985e5ae393fb79a8fb9adJordan Rose if ((*I)->isValid()) { 30609a9fe4068eed2fc72ec985e5ae393fb79a8fb9adJordan Rose HasValid = true; 30619a9fe4068eed2fc72ec985e5ae393fb79a8fb9adJordan Rose errorNodes.push_back((*I)->getErrorNode()); 30629a9fe4068eed2fc72ec985e5ae393fb79a8fb9adJordan Rose } else { 3063228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose // Keep the errorNodes list in sync with the bugReports list. 3064228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose HasInvalid = true; 30659a9fe4068eed2fc72ec985e5ae393fb79a8fb9adJordan Rose errorNodes.push_back(0); 30669a9fe4068eed2fc72ec985e5ae393fb79a8fb9adJordan Rose } 306740406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek } 30681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 30699a9fe4068eed2fc72ec985e5ae393fb79a8fb9adJordan Rose // If all the reports have been marked invalid by a previous path generation, 30709a9fe4068eed2fc72ec985e5ae393fb79a8fb9adJordan Rose // we're done. 30719a9fe4068eed2fc72ec985e5ae393fb79a8fb9adJordan Rose if (!HasValid) 30729a9fe4068eed2fc72ec985e5ae393fb79a8fb9adJordan Rose return false; 30739a9fe4068eed2fc72ec985e5ae393fb79a8fb9adJordan Rose 30742f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose typedef PathDiagnosticConsumer::PathGenerationScheme PathGenerationScheme; 30752f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose PathGenerationScheme ActiveScheme = PC.getGenerationScheme(); 30762f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose 3077af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek if (ActiveScheme == PathDiagnosticConsumer::Extensive) { 3078d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks AnalyzerOptions &options = getAnalyzerOptions(); 3079048eeea6852043990c87e52938b53b5337bd098eJordan Rose if (options.getBooleanOption("path-diagnostics-alternate", true)) { 3080af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek ActiveScheme = PathDiagnosticConsumer::AlternateExtensive; 3081af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek } 3082af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek } 3083af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 30841efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose TrimmedGraph TrimG(&getGraph(), errorNodes); 3085228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose ReportGraph ErrorGraph; 30861efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose 3087228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose while (TrimG.popNextReportGraph(ErrorGraph)) { 30882f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // Find the BugReport with the original location. 30891efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose assert(ErrorGraph.Index < bugReports.size()); 30901efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose BugReport *R = bugReports[ErrorGraph.Index]; 30912f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose assert(R && "No original report found for sliced graph."); 30922f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose assert(R->isValid() && "Report selected by trimmed graph marked invalid."); 30932f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose 30942f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // Start building the path diagnostic... 30951efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose PathDiagnosticBuilder PDB(*this, R, ErrorGraph.BackMap, &PC); 30961efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose const ExplodedNode *N = ErrorGraph.ErrorNode; 30972f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose 30982f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // Register additional node visitors. 30992f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose R->addVisitor(new NilReceiverBRVisitor()); 31002f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose R->addVisitor(new ConditionBRVisitor()); 31012f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose R->addVisitor(new LikelyFalsePositiveSuppressionBRVisitor()); 31022f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose 31032f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose BugReport::VisitorList visitors; 31042f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose unsigned origReportConfigToken, finalReportConfigToken; 3105d306a530fca74e40916121f5583e0545e470b3c4Ted Kremenek LocationContextMap LCM; 31062f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose 31072f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // While generating diagnostics, it's possible the visitors will decide 31082f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // new symbols and regions are interesting, or add other visitors based on 31092f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // the information they find. If they do, we need to regenerate the path 31102f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // based on our new report configuration. 31112f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose do { 31122f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // Get a clean copy of all the visitors. 31132f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose for (BugReport::visitor_iterator I = R->visitor_begin(), 31142f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose E = R->visitor_end(); I != E; ++I) 31152f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose visitors.push_back((*I)->clone()); 31162f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose 31172f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // Clear out the active path from any previous work. 31182f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose PD.resetPath(); 31192f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose origReportConfigToken = R->getConfigurationChangeToken(); 31202f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose 31212f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // Generate the very last diagnostic piece - the piece is visible before 31222f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // the trace is expanded. 31232f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose PathDiagnosticPiece *LastPiece = 0; 31242f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose for (BugReport::visitor_iterator I = visitors.begin(), E = visitors.end(); 31252f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose I != E; ++I) { 31262f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose if (PathDiagnosticPiece *Piece = (*I)->getEndPath(PDB, N, *R)) { 31272f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose assert (!LastPiece && 31282f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose "There can only be one final piece in a diagnostic."); 31292f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose LastPiece = Piece; 31302f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose } 31313bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose } 313286ff12c8a8a356ca284ca7687749216fbfd74519Anna Zaks 31332f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose if (ActiveScheme != PathDiagnosticConsumer::None) { 31342f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose if (!LastPiece) 31352f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose LastPiece = BugReporterVisitor::getDefaultEndPath(PDB, N, *R); 31362f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose assert(LastPiece); 3137d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose PD.setEndOfPath(LastPiece); 31388347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose } 31392f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose 3140d306a530fca74e40916121f5583e0545e470b3c4Ted Kremenek // Make sure we get a clean location context map so we don't 3141d306a530fca74e40916121f5583e0545e470b3c4Ted Kremenek // hold onto old mappings. 3142d306a530fca74e40916121f5583e0545e470b3c4Ted Kremenek LCM.clear(); 3143d306a530fca74e40916121f5583e0545e470b3c4Ted Kremenek 31442f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose switch (ActiveScheme) { 3145af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek case PathDiagnosticConsumer::AlternateExtensive: 3146af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek GenerateAlternateExtensivePathDiagnostic(PD, PDB, N, LCM, visitors); 3147af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek break; 31482f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose case PathDiagnosticConsumer::Extensive: 3149d306a530fca74e40916121f5583e0545e470b3c4Ted Kremenek GenerateExtensivePathDiagnostic(PD, PDB, N, LCM, visitors); 31502f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose break; 31512f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose case PathDiagnosticConsumer::Minimal: 3152d306a530fca74e40916121f5583e0545e470b3c4Ted Kremenek GenerateMinimalPathDiagnostic(PD, PDB, N, LCM, visitors); 31532f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose break; 31542f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose case PathDiagnosticConsumer::None: 31552f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose GenerateVisitorsOnlyPathDiagnostic(PD, PDB, N, visitors); 31562f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose break; 3157d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose } 31583bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose 31592f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // Clean up the visitors we used. 31602f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose llvm::DeleteContainerPointers(visitors); 31613bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose 31622f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // Did anything change while generating this path? 31632f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose finalReportConfigToken = R->getConfigurationChangeToken(); 31642f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose } while (finalReportConfigToken != origReportConfigToken); 31653bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose 3166228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose if (!R->isValid()) 31672f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose continue; 3168b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek 31692f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // Finally, prune the diagnostic path of uninteresting stuff. 31702f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose if (!PD.path.empty()) { 31712f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // Remove messages that are basically the same. 31722f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose removeRedundantMsgs(PD.getMutablePieces()); 31732f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose 3174d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks if (R->shouldPrunePath() && getAnalyzerOptions().shouldPrunePaths()) { 3175d306a530fca74e40916121f5583e0545e470b3c4Ted Kremenek bool stillHasNotes = removeUnneededCalls(PD.getMutablePieces(), R, LCM); 31762f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose assert(stillHasNotes); 31772f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose (void)stillHasNotes; 31782f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose } 31792f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose 31802f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose adjustCallLocations(PD.getMutablePieces()); 3181bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek 3182bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek if (ActiveScheme == PathDiagnosticConsumer::AlternateExtensive) { 3183aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek SourceManager &SM = getSourceManager(); 3184aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek 3185aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek // Reduce the number of edges from a very conservative set 3186aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek // to an aesthetically pleasing subset that conveys the 3187aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek // necessary information. 318815676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek OptimizedCallsSet OCS; 3189bb518991ce4298d8662235fc8cb13813f011c18dJordan Rose while (optimizeEdges(PD.getMutablePieces(), SM, OCS, LCM)) {} 3190aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek 319101f1ff79f70b3e042995a43b29ccbf0fffc77d5fJordan Rose // Drop the very first function-entry edge. It's not really necessary 319201f1ff79f70b3e042995a43b29ccbf0fffc77d5fJordan Rose // for top-level functions. 319301f1ff79f70b3e042995a43b29ccbf0fffc77d5fJordan Rose dropFunctionEntryEdge(PD.getMutablePieces(), LCM, SM); 3194bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek } 3195b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek } 3196afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose 31972f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // We found a report and didn't suppress it. 31982f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose return true; 3199ed7948b55fa4b2505f240cc5287137f451172b4cTed Kremenek } 32008347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose 32012f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // We suppressed all the reports in this equivalence class. 3202228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose assert(!HasInvalid && "Inconsistent suppression"); 3203228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose (void)HasInvalid; 32042f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose return false; 32053106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 32061aa44c7c9198796085b77c6bdd7c90030845a688Ted Kremenek 3207cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenekvoid BugReporter::Register(BugType *BT) { 32083baf672378f105602d2b12f03f00277ae1936fe9Ted Kremenek BugTypes = F.add(BugTypes, BT); 320976d90c8bf83d071fd1bdbffa6d9f2af87c6bb7b5Ted Kremenek} 321076d90c8bf83d071fd1bdbffa6d9f2af87c6bb7b5Ted Kremenek 3211785950e59424dca7ce0081bebf13c0acd2c4fff6Jordan Rosevoid BugReporter::emitReport(BugReport* R) { 3212cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek // Compute the bug report's hash to determine its equivalence class. 3213cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek llvm::FoldingSetNodeID ID; 3214cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek R->Profile(ID); 32151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 32161eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Lookup the equivance class. If there isn't one, create it. 3217cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek BugType& BT = R->getBugType(); 3218cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek Register(&BT); 3219cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek void *InsertPos; 3220404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis BugReportEquivClass* EQ = EQClasses.FindNodeOrInsertPos(ID, InsertPos); 32211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3222cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek if (!EQ) { 3223cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek EQ = new BugReportEquivClass(R); 3224404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis EQClasses.InsertNode(EQ, InsertPos); 32253b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks EQClassesVector.push_back(EQ); 3226cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek } 3227cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek else 3228cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek EQ->AddReport(R); 322961f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek} 323061f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek 323106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 323206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek//===----------------------------------------------------------------------===// 323306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek// Emitting reports in equivalence classes. 323406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek//===----------------------------------------------------------------------===// 323506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 323606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremeneknamespace { 3237ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamstruct FRIEC_WLItem { 323806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek const ExplodedNode *N; 323906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek ExplodedNode::const_succ_iterator I, E; 324006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 324106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek FRIEC_WLItem(const ExplodedNode *n) 324206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek : N(n), I(N->succ_begin()), E(N->succ_end()) {} 324306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek}; 324406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek} 324506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 324661f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenekstatic BugReport * 324761f52bd3c524268e25b48a1ed3730aedd6cc8374Ted KremenekFindReportInEquivalenceClass(BugReportEquivClass& EQ, 32485f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVectorImpl<BugReport*> &bugReports) { 324961f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek 325006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek BugReportEquivClass::iterator I = EQ.begin(), E = EQ.end(); 325106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek assert(I != E); 32524a5f724538cbc275370c9504e8169ce92503256cBenjamin Kramer BugType& BT = I->getBugType(); 325361f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek 325440406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek // If we don't need to suppress any of the nodes because they are 325540406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek // post-dominated by a sink, simply add all the nodes in the equivalence class 325640406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek // to 'Nodes'. Any of the reports will serve as a "representative" report. 325761f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek if (!BT.isSuppressOnSink()) { 32584a5f724538cbc275370c9504e8169ce92503256cBenjamin Kramer BugReport *R = I; 325961f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek for (BugReportEquivClass::iterator I=EQ.begin(), E=EQ.end(); I!=E; ++I) { 32609c378f705405d37f49795d5e915989de774fe11fTed Kremenek const ExplodedNode *N = I->getErrorNode(); 326161f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek if (N) { 32624a5f724538cbc275370c9504e8169ce92503256cBenjamin Kramer R = I; 326340406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek bugReports.push_back(R); 326461f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek } 326561f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek } 326606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek return R; 326761f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek } 326861f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek 326906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // For bug reports that should be suppressed when all paths are post-dominated 327006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // by a sink node, iterate through the reports in the equivalence class 327106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // until we find one that isn't post-dominated (if one exists). We use a 327206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // DFS traversal of the ExplodedGraph to find a non-sink node. We could write 327306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // this as a recursive function, but we don't want to risk blowing out the 327406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // stack for very long paths. 327540406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek BugReport *exampleReport = 0; 327661f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek 327706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek for (; I != E; ++I) { 32784a5f724538cbc275370c9504e8169ce92503256cBenjamin Kramer const ExplodedNode *errorNode = I->getErrorNode(); 327906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 328040406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek if (!errorNode) 328106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek continue; 328240406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek if (errorNode->isSink()) { 3283b219cfc4d75f0a03630b7c4509ef791b7e97b2c8David Blaikie llvm_unreachable( 328406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek "BugType::isSuppressSink() should not be 'true' for sink end nodes"); 328506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek } 328661f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek // No successors? By definition this nodes isn't post-dominated by a sink. 328740406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek if (errorNode->succ_empty()) { 32884a5f724538cbc275370c9504e8169ce92503256cBenjamin Kramer bugReports.push_back(I); 328940406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek if (!exampleReport) 32904a5f724538cbc275370c9504e8169ce92503256cBenjamin Kramer exampleReport = I; 329161f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek continue; 329261f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek } 329361f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek 329406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // At this point we know that 'N' is not a sink and it has at least one 329506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // successor. Use a DFS worklist to find a non-sink end-of-path node. 329606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek typedef FRIEC_WLItem WLItem; 32975f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner typedef SmallVector<WLItem, 10> DFSWorkList; 329806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek llvm::DenseMap<const ExplodedNode *, unsigned> Visited; 329906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 330006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek DFSWorkList WL; 330140406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek WL.push_back(errorNode); 330240406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek Visited[errorNode] = 1; 330306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 330406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek while (!WL.empty()) { 330506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek WLItem &WI = WL.back(); 330606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek assert(!WI.N->succ_empty()); 330706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 330806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek for (; WI.I != WI.E; ++WI.I) { 330906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek const ExplodedNode *Succ = *WI.I; 331006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // End-of-path node? 331106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek if (Succ->succ_empty()) { 331261f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek // If we found an end-of-path node that is not a sink. 331361f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek if (!Succ->isSink()) { 33144a5f724538cbc275370c9504e8169ce92503256cBenjamin Kramer bugReports.push_back(I); 331540406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek if (!exampleReport) 33164a5f724538cbc275370c9504e8169ce92503256cBenjamin Kramer exampleReport = I; 331761f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek WL.clear(); 331861f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek break; 331961f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek } 332006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // Found a sink? Continue on to the next successor. 332106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek continue; 332206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek } 332306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // Mark the successor as visited. If it hasn't been explored, 332406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // enqueue it to the DFS worklist. 332506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek unsigned &mark = Visited[Succ]; 332606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek if (!mark) { 332706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek mark = 1; 332806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek WL.push_back(Succ); 332906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek break; 333006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek } 333106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek } 333261f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek 333361f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek // The worklist may have been cleared at this point. First 333461f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek // check if it is empty before checking the last item. 333561f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek if (!WL.empty() && &WL.back() == &WI) 333606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek WL.pop_back(); 333706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek } 333806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek } 333906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 334061f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek // ExampleReport will be NULL if all the nodes in the equivalence class 334161f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek // were post-dominated by sinks. 334240406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek return exampleReport; 334361f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek} 3344e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek 3345cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenekvoid BugReporter::FlushReport(BugReportEquivClass& EQ) { 33465f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<BugReport*, 10> bugReports; 334740406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek BugReport *exampleReport = FindReportInEquivalenceClass(EQ, bugReports); 3348c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek if (exampleReport) { 3349c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek const PathDiagnosticConsumers &C = getPathDiagnosticConsumers(); 3350c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek for (PathDiagnosticConsumers::const_iterator I=C.begin(), 3351c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek E=C.end(); I != E; ++I) { 3352c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek FlushReport(exampleReport, **I, bugReports); 3353c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek } 3354c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek } 3355c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek} 3356c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek 3357c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenekvoid BugReporter::FlushReport(BugReport *exampleReport, 3358c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek PathDiagnosticConsumer &PD, 3359c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek ArrayRef<BugReport*> bugReports) { 33601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3361cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek // FIXME: Make sure we use the 'R' for the path that was actually used. 33621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Probably doesn't make a difference in practice. 336340406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek BugType& BT = exampleReport->getBugType(); 33641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 33656f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith OwningPtr<PathDiagnostic> 336607189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek D(new PathDiagnostic(exampleReport->getDeclWithIssue(), 336707189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek exampleReport->getBugType().getName(), 33683a46f5fd1709f6df03bbb8b0abf84052dc0f39ffJordan Rose exampleReport->getDescription(), 33693a46f5fd1709f6df03bbb8b0abf84052dc0f39ffJordan Rose exampleReport->getShortDescription(/*Fallback=*/false), 337097bfb558f69c09b01a5c1510f08dc91eb62329a7Anna Zaks BT.getCategory(), 337197bfb558f69c09b01a5c1510f08dc91eb62329a7Anna Zaks exampleReport->getUniqueingLocation(), 337297bfb558f69c09b01a5c1510f08dc91eb62329a7Anna Zaks exampleReport->getUniqueingDecl())); 3373d49967f8764135ae65658e354b6d38e3637c9de3Ted Kremenek 3374cc08ca9b3cd2b715a699bcc772ce2e83a502915aJordan Rose MaxBugClassSize = std::max(bugReports.size(), 3375cc08ca9b3cd2b715a699bcc772ce2e83a502915aJordan Rose static_cast<size_t>(MaxBugClassSize)); 3376cc08ca9b3cd2b715a699bcc772ce2e83a502915aJordan Rose 3377c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek // Generate the full path diagnostic, using the generation scheme 3378d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose // specified by the PathDiagnosticConsumer. Note that we have to generate 3379d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose // path diagnostics even for consumers which do not support paths, because 3380d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose // the BugReporterVisitors may mark this bug as a false positive. 3381d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose if (!bugReports.empty()) 3382d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose if (!generatePathDiagnostic(*D.get(), PD, bugReports)) 3383d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose return; 33843148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek 3385cc08ca9b3cd2b715a699bcc772ce2e83a502915aJordan Rose MaxValidBugClassSize = std::max(bugReports.size(), 3386cc08ca9b3cd2b715a699bcc772ce2e83a502915aJordan Rose static_cast<size_t>(MaxValidBugClassSize)); 3387cc08ca9b3cd2b715a699bcc772ce2e83a502915aJordan Rose 3388d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks // Examine the report and see if the last piece is in a header. Reset the 3389d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks // report location to the last piece in the main source file. 3390d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks AnalyzerOptions& Opts = getAnalyzerOptions(); 3391d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks if (Opts.shouldReportIssuesInMainSourceFile() && !Opts.AnalyzeAll) 3392d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks D->resetDiagnosticLocationToMainFile(); 3393d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks 3394c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek // If the path is empty, generate a single step path with the location 3395c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek // of the issue. 3396802e02463b880f53a6e645bde78cc412481ce9e0Ted Kremenek if (D->path.empty()) { 3397c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek PathDiagnosticLocation L = exampleReport->getLocation(getSourceManager()); 3398c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek PathDiagnosticPiece *piece = 3399c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek new PathDiagnosticEventPiece(L, exampleReport->getDescription()); 3400c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek BugReport::ranges_iterator Beg, End; 3401c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek llvm::tie(Beg, End) = exampleReport->getRanges(); 340207189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek for ( ; Beg != End; ++Beg) 340307189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek piece->addRange(*Beg); 34043a46f5fd1709f6df03bbb8b0abf84052dc0f39ffJordan Rose D->setEndOfPath(piece); 34053148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek } 34061eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3407c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek // Get the meta data. 3408c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek const BugReport::ExtraTextList &Meta = exampleReport->getExtraText(); 3409c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek for (BugReport::ExtraTextList::const_iterator i = Meta.begin(), 3410c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek e = Meta.end(); i != e; ++i) { 3411c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek D->addMeta(*i); 3412c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek } 3413c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek 3414c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek PD.HandlePathDiagnostic(D.take()); 341561f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek} 341657202071e477530e9348bc76671ee369b2399b92Ted Kremenek 341707189521a15d9c088216b943649cb9fe231cbb57Ted Kremenekvoid BugReporter::EmitBasicReport(const Decl *DeclWithIssue, 341807189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek StringRef name, 34195f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef category, 3420590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks StringRef str, PathDiagnosticLocation Loc, 34218c036c7f77d69f96df49219ed0bdbade200d52ebTed Kremenek SourceRange* RBeg, unsigned NumRanges) { 34221eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3423404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // 'BT' is owned by BugReporter. 3424404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis BugType *BT = getBugTypeForName(name, category); 3425590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks BugReport *R = new BugReport(*BT, str, Loc); 342607189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek R->setDeclWithIssue(DeclWithIssue); 3427cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek for ( ; NumRanges > 0 ; --NumRanges, ++RBeg) R->addRange(*RBeg); 3428785950e59424dca7ce0081bebf13c0acd2c4fff6Jordan Rose emitReport(R); 3429cabe66811fe43835b8c5a0854552768fc53261e3Ted Kremenek} 3430404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis 34315f9e272e632e951b1efe824cd16acb4d96077930Chris LattnerBugType *BugReporter::getBugTypeForName(StringRef name, 34325f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef category) { 3433f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith SmallString<136> fullDesc; 3434404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis llvm::raw_svector_ostream(fullDesc) << name << ":" << category; 3435404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis llvm::StringMapEntry<BugType *> & 3436404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis entry = StrBugTypes.GetOrCreateValue(fullDesc); 3437404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis BugType *BT = entry.getValue(); 3438404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis if (!BT) { 3439404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis BT = new BugType(name, category); 3440404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis entry.setValue(BT); 3441404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis } 3442404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis return BT; 3443404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis} 3444