161f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek// BugReporter.cpp - Generate PathDiagnostics for Bugs ------------*- C++ -*--// 261f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek// 361f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek// The LLVM Compiler Infrastructure 461f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek// 561f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek// This file is distributed under the University of Illinois Open Source 661f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek// License. See LICENSE.TXT for details. 761f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek// 861f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek//===----------------------------------------------------------------------===// 961f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek// 1061f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek// This file defines BugReporter, a utility class for generating 116c07bdba93b095b66e2c8c82dd5ed458fa8285eaTed Kremenek// PathDiagnostics. 1261f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek// 1361f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek//===----------------------------------------------------------------------===// 1461f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek 159b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" 1661f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek#include "clang/AST/ASTContext.h" 17c35fb7d67d515659ad2325b4f6ec97c9fe64fb63Benjamin Kramer#include "clang/AST/DeclObjC.h" 1861f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek#include "clang/AST/Expr.h" 19cff15128c6c089bd6fae841b80680e6f5afbf0bfReid Kleckner#include "clang/AST/ExprCXX.h" 2000605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek#include "clang/AST/ParentMap.h" 21cff15128c6c089bd6fae841b80680e6f5afbf0bfReid Kleckner#include "clang/AST/StmtCXX.h" 22651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#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/STLExtras.h" 3255fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "llvm/ADT/SmallString.h" 33cc08ca9b3cd2b715a699bcc772ce2e83a502915aJordan Rose#include "llvm/ADT/Statistic.h" 3455fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "llvm/Support/raw_ostream.h" 35651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include <memory> 3610aa55410bbecbb658ce14a5f801d50cf06d12dfTed Kremenek#include <queue> 3761f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek 3861f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenekusing namespace clang; 399ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremenekusing namespace ento; 4061f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek 416bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines#define DEBUG_TYPE "BugReporter" 426bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 43cc08ca9b3cd2b715a699bcc772ce2e83a502915aJordan RoseSTATISTIC(MaxBugClassSize, 44cc08ca9b3cd2b715a699bcc772ce2e83a502915aJordan Rose "The maximum number of bug reports in the same equivalence class"); 45cc08ca9b3cd2b715a699bcc772ce2e83a502915aJordan RoseSTATISTIC(MaxValidBugClassSize, 46cc08ca9b3cd2b715a699bcc772ce2e83a502915aJordan Rose "The maximum number of bug reports in the same equivalence class " 47cc08ca9b3cd2b715a699bcc772ce2e83a502915aJordan Rose "where at least one report is valid (not suppressed)"); 48cc08ca9b3cd2b715a699bcc772ce2e83a502915aJordan Rose 498966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed KremenekBugReporterVisitor::~BugReporterVisitor() {} 501b431023814196f87515a540ebcb9e9f1a9176a1Ted Kremenek 5199ba9e3bd70671f3441fb974895f226a83ce0e66David Blaikievoid BugReporterContext::anchor() {} 5299ba9e3bd70671f3441fb974895f226a83ce0e66David Blaikie 53cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek//===----------------------------------------------------------------------===// 543106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// Helper routines for walking the ExplodedGraph and fetching statements. 55cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek//===----------------------------------------------------------------------===// 5661f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek 579c378f705405d37f49795d5e915989de774fe11fTed Kremenekstatic const Stmt *GetPreviousStmt(const ExplodedNode *N) { 580f8579274a010f360a371b53101859d9d6052314Anna Zaks for (N = N->getFirstPred(); N; N = N->getFirstPred()) 590f8579274a010f360a371b53101859d9d6052314Anna Zaks if (const Stmt *S = PathDiagnosticLocation::getStmt(N)) 60b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek return S; 611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 626bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 63b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek} 64b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek 655f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenekstatic inline const Stmt* 669c378f705405d37f49795d5e915989de774fe11fTed KremenekGetCurrentOrPreviousStmt(const ExplodedNode *N) { 670f8579274a010f360a371b53101859d9d6052314Anna Zaks if (const Stmt *S = PathDiagnosticLocation::getStmt(N)) 68b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek return S; 691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 70b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek return GetPreviousStmt(N); 71b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek} 721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 73b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek//===----------------------------------------------------------------------===// 74c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek// Diagnostic cleanup. 75c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek//===----------------------------------------------------------------------===// 76c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek 77b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenekstatic PathDiagnosticEventPiece * 78b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted KremenekeventsDescribeSameCondition(PathDiagnosticEventPiece *X, 79b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek PathDiagnosticEventPiece *Y) { 80b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek // Prefer diagnostics that come from ConditionBRVisitor over 81b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek // those that came from TrackConstraintBRVisitor. 82b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek const void *tagPreferred = ConditionBRVisitor::getTag(); 83b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek const void *tagLesser = TrackConstraintBRVisitor::getTag(); 84b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek 85b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek if (X->getLocation() != Y->getLocation()) 866bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 876bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 88b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek if (X->getTag() == tagPreferred && Y->getTag() == tagLesser) 89b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek return X; 90b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek 91b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek if (Y->getTag() == tagPreferred && X->getTag() == tagLesser) 92b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek return Y; 936bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 946bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 95b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek} 96b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek 973800165e56107df7430520aa98afdf7065db2dd2Ted Kremenek/// An optimization pass over PathPieces that removes redundant diagnostics 983800165e56107df7430520aa98afdf7065db2dd2Ted Kremenek/// generated by both ConditionBRVisitor and TrackConstraintBRVisitor. Both 993800165e56107df7430520aa98afdf7065db2dd2Ted Kremenek/// BugReporterVisitors use different methods to generate diagnostics, with 1003800165e56107df7430520aa98afdf7065db2dd2Ted Kremenek/// one capable of emitting diagnostics in some cases but not in others. This 1013800165e56107df7430520aa98afdf7065db2dd2Ted Kremenek/// can lead to redundant diagnostic pieces at the same point in a path. 1023800165e56107df7430520aa98afdf7065db2dd2Ted Kremenekstatic void removeRedundantMsgs(PathPieces &path) { 103b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek unsigned N = path.size(); 104b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek if (N < 2) 105b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek return; 1063800165e56107df7430520aa98afdf7065db2dd2Ted Kremenek // NOTE: this loop intentionally is not using an iterator. Instead, we 1073800165e56107df7430520aa98afdf7065db2dd2Ted Kremenek // are streaming the path and modifying it in place. This is done by 1083800165e56107df7430520aa98afdf7065db2dd2Ted Kremenek // grabbing the front, processing it, and if we decide to keep it append 1093800165e56107df7430520aa98afdf7065db2dd2Ted Kremenek // it to the end of the path. The entire path is processed in this way. 110b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek for (unsigned i = 0; i < N; ++i) { 111b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek IntrusiveRefCntPtr<PathDiagnosticPiece> piece(path.front()); 112b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek path.pop_front(); 113b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek 114b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek switch (piece->getKind()) { 115b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek case clang::ento::PathDiagnosticPiece::Call: 1163800165e56107df7430520aa98afdf7065db2dd2Ted Kremenek removeRedundantMsgs(cast<PathDiagnosticCallPiece>(piece)->path); 117b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek break; 118b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek case clang::ento::PathDiagnosticPiece::Macro: 1193800165e56107df7430520aa98afdf7065db2dd2Ted Kremenek removeRedundantMsgs(cast<PathDiagnosticMacroPiece>(piece)->subPieces); 120b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek break; 121b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek case clang::ento::PathDiagnosticPiece::ControlFlow: 122b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek break; 123b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek case clang::ento::PathDiagnosticPiece::Event: { 124b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek if (i == N-1) 125b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek break; 126b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek 127b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek if (PathDiagnosticEventPiece *nextEvent = 128ef8225444452a1486bd721f3285301fe84643b00Stephen Hines dyn_cast<PathDiagnosticEventPiece>(path.front().get())) { 129b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek PathDiagnosticEventPiece *event = 130b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek cast<PathDiagnosticEventPiece>(piece); 131b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek // Check to see if we should keep one of the two pieces. If we 132b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek // come up with a preference, record which piece to keep, and consume 133b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek // another piece from the path. 134b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek if (PathDiagnosticEventPiece *pieceToKeep = 135b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek eventsDescribeSameCondition(event, nextEvent)) { 136b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek piece = pieceToKeep; 137b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek path.pop_front(); 138b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek ++i; 139b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek } 140b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek } 141b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek break; 142b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek } 143b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek } 144b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek path.push_back(piece); 145b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek } 146b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek} 147b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek 148d306a530fca74e40916121f5583e0545e470b3c4Ted Kremenek/// A map from PathDiagnosticPiece to the LocationContext of the inlined 149d306a530fca74e40916121f5583e0545e470b3c4Ted Kremenek/// function call it represents. 150bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenektypedef llvm::DenseMap<const PathPieces *, const LocationContext *> 151d306a530fca74e40916121f5583e0545e470b3c4Ted Kremenek LocationContextMap; 152d306a530fca74e40916121f5583e0545e470b3c4Ted Kremenek 153c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek/// Recursively scan through a path and prune out calls and macros pieces 154c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek/// that aren't needed. Return true if afterwards the path contains 155afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose/// "interesting stuff" which means it shouldn't be pruned from the parent path. 156d306a530fca74e40916121f5583e0545e470b3c4Ted Kremenekstatic bool removeUnneededCalls(PathPieces &pieces, BugReport *R, 157d306a530fca74e40916121f5583e0545e470b3c4Ted Kremenek LocationContextMap &LCM) { 158c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek bool containsSomethingInteresting = false; 159c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek const unsigned N = pieces.size(); 160c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek 161c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek for (unsigned i = 0 ; i < N ; ++i) { 162c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek // Remove the front piece from the path. If it is still something we 163c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek // want to keep once we are done, we will push it back on the end. 164c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek IntrusiveRefCntPtr<PathDiagnosticPiece> piece(pieces.front()); 165c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek pieces.pop_front(); 166c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek 167725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek switch (piece->getKind()) { 168725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek case PathDiagnosticPiece::Call: { 169725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek PathDiagnosticCallPiece *call = cast<PathDiagnosticCallPiece>(piece); 17080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // Check if the location context is interesting. 171bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek assert(LCM.count(&call->path)); 172bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek if (R->isInteresting(LCM[&call->path])) { 17380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks containsSomethingInteresting = true; 17480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks break; 17580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks } 176368f3b070e8cb657a65bfa443d60256676d269e7Jordan Rose 177d306a530fca74e40916121f5583e0545e470b3c4Ted Kremenek if (!removeUnneededCalls(call->path, R, LCM)) 178368f3b070e8cb657a65bfa443d60256676d269e7Jordan Rose continue; 179a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek 180725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek containsSomethingInteresting = true; 181725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek break; 182725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek } 183725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek case PathDiagnosticPiece::Macro: { 184725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek PathDiagnosticMacroPiece *macro = cast<PathDiagnosticMacroPiece>(piece); 185d306a530fca74e40916121f5583e0545e470b3c4Ted Kremenek if (!removeUnneededCalls(macro->subPieces, R, LCM)) 186725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek continue; 187c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek containsSomethingInteresting = true; 188725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek break; 189725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek } 190725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek case PathDiagnosticPiece::Event: { 191725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek PathDiagnosticEventPiece *event = cast<PathDiagnosticEventPiece>(piece); 192a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek 193725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek // We never throw away an event, but we do throw it away wholesale 194725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek // as part of a path if we throw the entire path away. 19522505ef15e32db31a4f834a387cf73a913bc8f66Ted Kremenek containsSomethingInteresting |= !event->isPrunable(); 196725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek break; 197725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek } 198725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek case PathDiagnosticPiece::ControlFlow: 199725167443808efdc39a99f4eb132a0ae64ac5118Ted Kremenek break; 200c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek } 201c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek 202c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek pieces.push_back(piece); 203c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek } 204c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek 205c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek return containsSomethingInteresting; 206c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek} 207c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek 208d474da062565596015558856333423199aed5eb1Jordan Rose/// Returns true if the given decl has been implicitly given a body, either by 209d474da062565596015558856333423199aed5eb1Jordan Rose/// the analyzer or by the compiler proper. 210d474da062565596015558856333423199aed5eb1Jordan Rosestatic bool hasImplicitBody(const Decl *D) { 211d474da062565596015558856333423199aed5eb1Jordan Rose assert(D); 212d474da062565596015558856333423199aed5eb1Jordan Rose return D->isImplicit() || !D->hasBody(); 213d474da062565596015558856333423199aed5eb1Jordan Rose} 214d474da062565596015558856333423199aed5eb1Jordan Rose 215afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose/// Recursively scan through a path and make sure that all call pieces have 2166838710779a23ea5dfdb5764ad7b7a7451b00bf8Anna Zaks/// valid locations. 2176bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesstatic void 2186bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen HinesadjustCallLocations(PathPieces &Pieces, 2196bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines PathDiagnosticLocation *LastCallLocation = nullptr) { 220afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose for (PathPieces::iterator I = Pieces.begin(), E = Pieces.end(); I != E; ++I) { 221ed866e73bab7733f5226f84c52edefe23d694b2fTed Kremenek PathDiagnosticCallPiece *Call = dyn_cast<PathDiagnosticCallPiece>(*I); 222afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose 223afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose if (!Call) { 224ed866e73bab7733f5226f84c52edefe23d694b2fTed Kremenek assert((*I)->getLocation().asLocation().isValid()); 225afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose continue; 226afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose } 227afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose 228afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose if (LastCallLocation) { 229d474da062565596015558856333423199aed5eb1Jordan Rose bool CallerIsImplicit = hasImplicitBody(Call->getCaller()); 230d474da062565596015558856333423199aed5eb1Jordan Rose if (CallerIsImplicit || !Call->callEnter.asLocation().isValid()) 231afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose Call->callEnter = *LastCallLocation; 232d474da062565596015558856333423199aed5eb1Jordan Rose if (CallerIsImplicit || !Call->callReturn.asLocation().isValid()) 233afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose Call->callReturn = *LastCallLocation; 234afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose } 235afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose 236afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose // Recursively clean out the subclass. Keep this call around if 237afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose // it contains any informative diagnostics. 238afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose PathDiagnosticLocation *ThisCallLocation; 239187f8bd88bfc92cf3fea62b7d8db5f92edce410aJordan Rose if (Call->callEnterWithin.asLocation().isValid() && 240d474da062565596015558856333423199aed5eb1Jordan Rose !hasImplicitBody(Call->getCallee())) 241afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose ThisCallLocation = &Call->callEnterWithin; 242afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose else 243afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose ThisCallLocation = &Call->callEnter; 244afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose 245afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose assert(ThisCallLocation && "Outermost call has an invalid location"); 246afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose adjustCallLocations(Call->path, ThisCallLocation); 247afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose } 248afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose} 249afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose 250d3d0dcfbf784c828c2f07384fd6a3401b0cd4e9eJordan Rose/// Remove edges in and out of C++ default initializer expressions. These are 251d3d0dcfbf784c828c2f07384fd6a3401b0cd4e9eJordan Rose/// for fields that have in-class initializers, as opposed to being initialized 252d3d0dcfbf784c828c2f07384fd6a3401b0cd4e9eJordan Rose/// explicitly in a constructor or braced list. 253d3d0dcfbf784c828c2f07384fd6a3401b0cd4e9eJordan Rosestatic void removeEdgesToDefaultInitializers(PathPieces &Pieces) { 254d3d0dcfbf784c828c2f07384fd6a3401b0cd4e9eJordan Rose for (PathPieces::iterator I = Pieces.begin(), E = Pieces.end(); I != E;) { 255d3d0dcfbf784c828c2f07384fd6a3401b0cd4e9eJordan Rose if (PathDiagnosticCallPiece *C = dyn_cast<PathDiagnosticCallPiece>(*I)) 256d3d0dcfbf784c828c2f07384fd6a3401b0cd4e9eJordan Rose removeEdgesToDefaultInitializers(C->path); 257d3d0dcfbf784c828c2f07384fd6a3401b0cd4e9eJordan Rose 258d3d0dcfbf784c828c2f07384fd6a3401b0cd4e9eJordan Rose if (PathDiagnosticMacroPiece *M = dyn_cast<PathDiagnosticMacroPiece>(*I)) 259d3d0dcfbf784c828c2f07384fd6a3401b0cd4e9eJordan Rose removeEdgesToDefaultInitializers(M->subPieces); 260d3d0dcfbf784c828c2f07384fd6a3401b0cd4e9eJordan Rose 261d3d0dcfbf784c828c2f07384fd6a3401b0cd4e9eJordan Rose if (PathDiagnosticControlFlowPiece *CF = 262d3d0dcfbf784c828c2f07384fd6a3401b0cd4e9eJordan Rose dyn_cast<PathDiagnosticControlFlowPiece>(*I)) { 263d3d0dcfbf784c828c2f07384fd6a3401b0cd4e9eJordan Rose const Stmt *Start = CF->getStartLocation().asStmt(); 264d3d0dcfbf784c828c2f07384fd6a3401b0cd4e9eJordan Rose const Stmt *End = CF->getEndLocation().asStmt(); 265d3d0dcfbf784c828c2f07384fd6a3401b0cd4e9eJordan Rose if (Start && isa<CXXDefaultInitExpr>(Start)) { 266d3d0dcfbf784c828c2f07384fd6a3401b0cd4e9eJordan Rose I = Pieces.erase(I); 267d3d0dcfbf784c828c2f07384fd6a3401b0cd4e9eJordan Rose continue; 268d3d0dcfbf784c828c2f07384fd6a3401b0cd4e9eJordan Rose } else if (End && isa<CXXDefaultInitExpr>(End)) { 269651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines PathPieces::iterator Next = std::next(I); 270d3d0dcfbf784c828c2f07384fd6a3401b0cd4e9eJordan Rose if (Next != E) { 271d3d0dcfbf784c828c2f07384fd6a3401b0cd4e9eJordan Rose if (PathDiagnosticControlFlowPiece *NextCF = 272d3d0dcfbf784c828c2f07384fd6a3401b0cd4e9eJordan Rose dyn_cast<PathDiagnosticControlFlowPiece>(*Next)) { 273d3d0dcfbf784c828c2f07384fd6a3401b0cd4e9eJordan Rose NextCF->setStartLocation(CF->getStartLocation()); 274d3d0dcfbf784c828c2f07384fd6a3401b0cd4e9eJordan Rose } 275d3d0dcfbf784c828c2f07384fd6a3401b0cd4e9eJordan Rose } 276d3d0dcfbf784c828c2f07384fd6a3401b0cd4e9eJordan Rose I = Pieces.erase(I); 277d3d0dcfbf784c828c2f07384fd6a3401b0cd4e9eJordan Rose continue; 278d3d0dcfbf784c828c2f07384fd6a3401b0cd4e9eJordan Rose } 279d3d0dcfbf784c828c2f07384fd6a3401b0cd4e9eJordan Rose } 280d3d0dcfbf784c828c2f07384fd6a3401b0cd4e9eJordan Rose 281d3d0dcfbf784c828c2f07384fd6a3401b0cd4e9eJordan Rose I++; 282d3d0dcfbf784c828c2f07384fd6a3401b0cd4e9eJordan Rose } 283d3d0dcfbf784c828c2f07384fd6a3401b0cd4e9eJordan Rose} 284d3d0dcfbf784c828c2f07384fd6a3401b0cd4e9eJordan Rose 2856838710779a23ea5dfdb5764ad7b7a7451b00bf8Anna Zaks/// Remove all pieces with invalid locations as these cannot be serialized. 2866838710779a23ea5dfdb5764ad7b7a7451b00bf8Anna Zaks/// We might have pieces with invalid locations as a result of inlining Body 2876838710779a23ea5dfdb5764ad7b7a7451b00bf8Anna Zaks/// Farm generated functions. 2886838710779a23ea5dfdb5764ad7b7a7451b00bf8Anna Zaksstatic void removePiecesWithInvalidLocations(PathPieces &Pieces) { 28957c8736e7dce5e63b4e1665d2c4fcf6e6ef959d0Anna Zaks for (PathPieces::iterator I = Pieces.begin(), E = Pieces.end(); I != E;) { 2906838710779a23ea5dfdb5764ad7b7a7451b00bf8Anna Zaks if (PathDiagnosticCallPiece *C = dyn_cast<PathDiagnosticCallPiece>(*I)) 2916838710779a23ea5dfdb5764ad7b7a7451b00bf8Anna Zaks removePiecesWithInvalidLocations(C->path); 2926838710779a23ea5dfdb5764ad7b7a7451b00bf8Anna Zaks 2936838710779a23ea5dfdb5764ad7b7a7451b00bf8Anna Zaks if (PathDiagnosticMacroPiece *M = dyn_cast<PathDiagnosticMacroPiece>(*I)) 2946838710779a23ea5dfdb5764ad7b7a7451b00bf8Anna Zaks removePiecesWithInvalidLocations(M->subPieces); 2956838710779a23ea5dfdb5764ad7b7a7451b00bf8Anna Zaks 2966838710779a23ea5dfdb5764ad7b7a7451b00bf8Anna Zaks if (!(*I)->getLocation().isValid() || 2976838710779a23ea5dfdb5764ad7b7a7451b00bf8Anna Zaks !(*I)->getLocation().asLocation().isValid()) { 29857c8736e7dce5e63b4e1665d2c4fcf6e6ef959d0Anna Zaks I = Pieces.erase(I); 2996838710779a23ea5dfdb5764ad7b7a7451b00bf8Anna Zaks continue; 3006838710779a23ea5dfdb5764ad7b7a7451b00bf8Anna Zaks } 30157c8736e7dce5e63b4e1665d2c4fcf6e6ef959d0Anna Zaks I++; 3026838710779a23ea5dfdb5764ad7b7a7451b00bf8Anna Zaks } 3036838710779a23ea5dfdb5764ad7b7a7451b00bf8Anna Zaks} 3046838710779a23ea5dfdb5764ad7b7a7451b00bf8Anna Zaks 305c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek//===----------------------------------------------------------------------===// 3063106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// PathDiagnosticBuilder and its associated routines and helper objects. 307b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek//===----------------------------------------------------------------------===// 308b479dadea93b93d3f0a335c3518b703f140b3f50Ted Kremenek 309babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremeneknamespace { 310ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass NodeMapClosure : public BugReport::NodeResolver { 311c9963132736782d0c9178c744b3e2307cfb98a08Jordan Rose InterExplodedGraphMap &M; 3127dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenekpublic: 313c9963132736782d0c9178c744b3e2307cfb98a08Jordan Rose NodeMapClosure(InterExplodedGraphMap &m) : M(m) {} 3141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 315651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const ExplodedNode *getOriginalNode(const ExplodedNode *N) override { 316c9963132736782d0c9178c744b3e2307cfb98a08Jordan Rose return M.lookup(N); 3177dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek } 3187dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek}; 3191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 320ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass PathDiagnosticBuilder : public BugReporterContext { 3217dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek BugReport *R; 322ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie PathDiagnosticConsumer *PDC; 3237dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek NodeMapClosure NMC; 3241eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumppublic: 32559950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek const LocationContext *LC; 32659950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek 3278966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek PathDiagnosticBuilder(GRBugReporter &br, 328c9963132736782d0c9178c744b3e2307cfb98a08Jordan Rose BugReport *r, InterExplodedGraphMap &Backmap, 329ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie PathDiagnosticConsumer *pdc) 3308966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek : BugReporterContext(br), 33159950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek R(r), PDC(pdc), NMC(Backmap), LC(r->getErrorNode()->getLocationContext()) 33259950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek {} 3331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3349c378f705405d37f49795d5e915989de774fe11fTed Kremenek PathDiagnosticLocation ExecutionContinues(const ExplodedNode *N); 3351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3369c378f705405d37f49795d5e915989de774fe11fTed Kremenek PathDiagnosticLocation ExecutionContinues(llvm::raw_string_ostream &os, 3379c378f705405d37f49795d5e915989de774fe11fTed Kremenek const ExplodedNode *N); 3381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3398e6431adab313e283a992698f6fc7afe62420999Anna Zaks BugReport *getBugReport() { return R; } 3408e6431adab313e283a992698f6fc7afe62420999Anna Zaks 341212f6d3b5fb3fa55ba1e40671cfc336430abc8ddTom Care Decl const &getCodeDecl() { return R->getErrorNode()->getCodeDecl(); } 34259950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek 34359950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek ParentMap& getParentMap() { return LC->getParentMap(); } 3441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 345c3f83ad7adaff2623986aa1c3e57833babd03d50Ted Kremenek const Stmt *getParent(const Stmt *S) { 346c3f83ad7adaff2623986aa1c3e57833babd03d50Ted Kremenek return getParentMap().getParent(S); 347c3f83ad7adaff2623986aa1c3e57833babd03d50Ted Kremenek } 3481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 349651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines NodeMapClosure& getNodeResolver() override { return NMC; } 3507297134f128423fce2e88f92421ed135bded7d4eDouglas Gregor 351d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek PathDiagnosticLocation getEnclosingStmtLocation(const Stmt *S); 3521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 353ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie PathDiagnosticConsumer::PathGenerationScheme getGenerationScheme() const { 354ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie return PDC ? PDC->getGenerationScheme() : PathDiagnosticConsumer::Extensive; 3557dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek } 3567dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek 357babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek bool supportsLogicalOpControlFlow() const { 358babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek return PDC ? PDC->supportsLogicalOpControlFlow() : true; 3591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 360babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek}; 361babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek} // end anonymous namespace 362babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek 36300605e0f011ed99225a22026344c5fc1b3212cd7Ted KremenekPathDiagnosticLocation 3649c378f705405d37f49795d5e915989de774fe11fTed KremenekPathDiagnosticBuilder::ExecutionContinues(const ExplodedNode *N) { 3650f8579274a010f360a371b53101859d9d6052314Anna Zaks if (const Stmt *S = PathDiagnosticLocation::getNextStmt(N)) 36659950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek return PathDiagnosticLocation(S, getSourceManager(), LC); 36700605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek 3680cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks return PathDiagnosticLocation::createDeclEnd(N->getLocationContext(), 3690cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks getSourceManager()); 370082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek} 3711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 37200605e0f011ed99225a22026344c5fc1b3212cd7Ted KremenekPathDiagnosticLocation 3739c378f705405d37f49795d5e915989de774fe11fTed KremenekPathDiagnosticBuilder::ExecutionContinues(llvm::raw_string_ostream &os, 3749c378f705405d37f49795d5e915989de774fe11fTed Kremenek const ExplodedNode *N) { 375babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek 376143ca222583a4a355fdc89af852deef287499300Ted Kremenek // Slow, but probably doesn't matter. 377b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek if (os.str().empty()) 378b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek os << ' '; 3791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 38000605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek const PathDiagnosticLocation &Loc = ExecutionContinues(N); 3811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 38200605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek if (Loc.asStmt()) 383b697b100f2354ac84b7a0785cab9481e8bfdcf23Ted Kremenek os << "Execution continues on line " 384642116259e8df6286063a17361c20e95b5017a0aChandler Carruth << getSourceManager().getExpansionLineNumber(Loc.asLocation()) 3858966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek << '.'; 3864f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek else { 3874f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek os << "Execution jumps to the end of the "; 3884f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek const Decl *D = N->getLocationContext()->getDecl(); 3894f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek if (isa<ObjCMethodDecl>(D)) 3904f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek os << "method"; 3914f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek else if (isa<FunctionDecl>(D)) 3924f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek os << "function"; 3934f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek else { 3944f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek assert(isa<BlockDecl>(D)); 3954f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek os << "anonymous block"; 3964f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek } 3974f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek os << '.'; 3984f1db537722e8d46146cd95f5962a6dcf6e44e54Ted Kremenek } 3991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 400082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek return Loc; 401143ca222583a4a355fdc89af852deef287499300Ted Kremenek} 402143ca222583a4a355fdc89af852deef287499300Ted Kremenek 40396f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rosestatic const Stmt *getEnclosingParent(const Stmt *S, const ParentMap &PM) { 404ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek if (isa<Expr>(S) && PM.isConsumedExpr(cast<Expr>(S))) 40596f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose return PM.getParentIgnoreParens(S); 4061eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 407ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek const Stmt *Parent = PM.getParentIgnoreParens(S); 40896f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose if (!Parent) 4096bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 4101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 41196f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose switch (Parent->getStmtClass()) { 41296f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose case Stmt::ForStmtClass: 41396f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose case Stmt::DoStmtClass: 41496f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose case Stmt::WhileStmtClass: 41596f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose case Stmt::ObjCForCollectionStmtClass: 41649a246f4fad959888bb0164c624c3c2b03078e91Jordan Rose case Stmt::CXXForRangeStmtClass: 41796f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose return Parent; 41896f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose default: 41996f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose break; 42096f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose } 4211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4226bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 423ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek} 424ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek 42596f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rosestatic PathDiagnosticLocation 42696f1061fbe59faff5b266a3a04061cefcfe03e2fJordan RosegetEnclosingStmtLocation(const Stmt *S, SourceManager &SMgr, const ParentMap &P, 4279d9b494aa36ceeb823c48acf04d2d7677174be88Jordan Rose const LocationContext *LC, bool allowNestedContexts) { 42896f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose if (!S) 42996f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose return PathDiagnosticLocation(); 4301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 43196f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose while (const Stmt *Parent = getEnclosingParent(S, P)) { 432af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek switch (Parent->getStmtClass()) { 4335fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek case Stmt::BinaryOperatorClass: { 4345fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek const BinaryOperator *B = cast<BinaryOperator>(Parent); 4355fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek if (B->isLogicalOp()) 4369d9b494aa36ceeb823c48acf04d2d7677174be88Jordan Rose return PathDiagnosticLocation(allowNestedContexts ? B : S, SMgr, LC); 4375fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek break; 4381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 439af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::CompoundStmtClass: 440af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::StmtExprClass: 441220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 4421d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek case Stmt::ChooseExprClass: 4431d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek // Similar to '?' if we are referring to condition, just have the edge 4441d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek // point to the entire choose expression. 4459d9b494aa36ceeb823c48acf04d2d7677174be88Jordan Rose if (allowNestedContexts || cast<ChooseExpr>(Parent)->getCond() == S) 446220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(Parent, SMgr, LC); 4471d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek else 448220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 44956ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall case Stmt::BinaryConditionalOperatorClass: 4501d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek case Stmt::ConditionalOperatorClass: 4511d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek // For '?', if we are referring to condition, just have the edge point 4521d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek // to the entire '?' expression. 4539d9b494aa36ceeb823c48acf04d2d7677174be88Jordan Rose if (allowNestedContexts || 4549d9b494aa36ceeb823c48acf04d2d7677174be88Jordan Rose cast<AbstractConditionalOperator>(Parent)->getCond() == S) 455220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(Parent, SMgr, LC); 4561d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek else 457220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 45849a246f4fad959888bb0164c624c3c2b03078e91Jordan Rose case Stmt::CXXForRangeStmtClass: 45949a246f4fad959888bb0164c624c3c2b03078e91Jordan Rose if (cast<CXXForRangeStmt>(Parent)->getBody() == S) 46049a246f4fad959888bb0164c624c3c2b03078e91Jordan Rose return PathDiagnosticLocation(S, SMgr, LC); 46149a246f4fad959888bb0164c624c3c2b03078e91Jordan Rose break; 462af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::DoStmtClass: 463220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 464af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::ForStmtClass: 465af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek if (cast<ForStmt>(Parent)->getBody() == S) 466220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 4671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump break; 468af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::IfStmtClass: 469af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek if (cast<IfStmt>(Parent)->getCond() != S) 470220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 4718bd4d037d837e7922c3661d6158229da58a03887Ted Kremenek break; 472af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::ObjCForCollectionStmtClass: 473af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek if (cast<ObjCForCollectionStmt>(Parent)->getBody() == S) 474220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 475af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek break; 476af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek case Stmt::WhileStmtClass: 477af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek if (cast<WhileStmt>(Parent)->getCond() != S) 478220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 479af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek break; 480af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek default: 481af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek break; 482af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek } 483af3e3d54e990b385e5a653d2994d7d41427a13b8Ted Kremenek 484d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek S = Parent; 485d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek } 4861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 487d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek assert(S && "Cannot have null Stmt for PathDiagnosticLocation"); 488e88a170da9219ef6a62d2182560c4de2ebffbd59Ted Kremenek 489220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return PathDiagnosticLocation(S, SMgr, LC); 490d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek} 491d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek 49296f1061fbe59faff5b266a3a04061cefcfe03e2fJordan RosePathDiagnosticLocation 49396f1061fbe59faff5b266a3a04061cefcfe03e2fJordan RosePathDiagnosticBuilder::getEnclosingStmtLocation(const Stmt *S) { 49496f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose assert(S && "Null Stmt passed to getEnclosingStmtLocation"); 4959d9b494aa36ceeb823c48acf04d2d7677174be88Jordan Rose return ::getEnclosingStmtLocation(S, getSourceManager(), getParentMap(), LC, 4969d9b494aa36ceeb823c48acf04d2d7677174be88Jordan Rose /*allowNestedContexts=*/false); 49796f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose} 49896f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose 499cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek//===----------------------------------------------------------------------===// 500d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose// "Visitors only" path diagnostic generation algorithm. 501d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose//===----------------------------------------------------------------------===// 502d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rosestatic bool GenerateVisitorsOnlyPathDiagnostic(PathDiagnostic &PD, 503d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose PathDiagnosticBuilder &PDB, 504d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose const ExplodedNode *N, 505d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose ArrayRef<BugReporterVisitor *> visitors) { 506d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose // All path generation skips the very first node (the error node). 507d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose // This is because there is special handling for the end-of-path note. 508d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose N = N->getFirstPred(); 509d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose if (!N) 510d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose return true; 511d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose 512d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose BugReport *R = PDB.getBugReport(); 513d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose while (const ExplodedNode *Pred = N->getFirstPred()) { 514d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose for (ArrayRef<BugReporterVisitor *>::iterator I = visitors.begin(), 515d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose E = visitors.end(); 516d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose I != E; ++I) { 517d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose // Visit all the node pairs, but throw the path pieces away. 518d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose PathDiagnosticPiece *Piece = (*I)->VisitNode(N, Pred, PDB, *R); 519d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose delete Piece; 520d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose } 521d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose 522d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose N = Pred; 523d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose } 524d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose 525d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose return R->isValid(); 526d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose} 527d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose 528d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose//===----------------------------------------------------------------------===// 5293106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// "Minimal" path diagnostic generation algorithm. 530cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek//===----------------------------------------------------------------------===// 53156a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zakstypedef std::pair<PathDiagnosticCallPiece*, const ExplodedNode*> StackDiagPair; 53256a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zakstypedef SmallVector<StackDiagPair, 6> StackDiagVector; 53356a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks 534368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaksstatic void updateStackPiecesWithMessage(PathDiagnosticPiece *P, 53556a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks StackDiagVector &CallStack) { 536368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks // If the piece contains a special message, add it to all the call 537368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks // pieces on the active stack. 538368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks if (PathDiagnosticEventPiece *ep = 539368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks dyn_cast<PathDiagnosticEventPiece>(P)) { 540368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks 54156a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks if (ep->hasCallStackHint()) 54256a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks for (StackDiagVector::iterator I = CallStack.begin(), 54356a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks E = CallStack.end(); I != E; ++I) { 54456a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks PathDiagnosticCallPiece *CP = I->first; 54556a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks const ExplodedNode *N = I->second; 5468fe4525680ce72e90cee3e58b5654e3ae955447fNAKAMURA Takumi std::string stackMsg = ep->getCallStackMessage(N); 54756a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks 548368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks // The last message on the path to final bug is the most important 549368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks // one. Since we traverse the path backwards, do not add the message 550368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks // if one has been previously added. 55156a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks if (!CP->hasCallStackMessage()) 55256a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks CP->setCallStackMessage(stackMsg); 55356a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks } 554368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks } 555368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks} 556cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek 55777d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenekstatic void CompactPathDiagnostic(PathPieces &path, const SourceManager& SM); 55814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 5598347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rosestatic bool GenerateMinimalPathDiagnostic(PathDiagnostic& PD, 5603106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PathDiagnosticBuilder &PDB, 5613bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose const ExplodedNode *N, 562d306a530fca74e40916121f5583e0545e470b3c4Ted Kremenek LocationContextMap &LCM, 5633bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose ArrayRef<BugReporterVisitor *> visitors) { 5648966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek 5653106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek SourceManager& SMgr = PDB.getSourceManager(); 56659950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek const LocationContext *LC = PDB.LC; 5679c378f705405d37f49795d5e915989de774fe11fTed Kremenek const ExplodedNode *NextNode = N->pred_empty() 5686bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines ? nullptr : *(N->pred_begin()); 569368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks 57056a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks StackDiagVector CallStack; 571368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks 5723106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek while (NextNode) { 5731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump N = NextNode; 57459950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek PDB.LC = N->getLocationContext(); 5750f8579274a010f360a371b53101859d9d6052314Anna Zaks NextNode = N->getFirstPred(); 5761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 57761f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek ProgramPoint P = N->getLocation(); 57880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks 57980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks do { 5807a95de68c093991047ed8d339479ccad51b88663David Blaikie if (Optional<CallExitEnd> CE = P.getAs<CallExitEnd>()) { 58180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PathDiagnosticCallPiece *C = 58280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PathDiagnosticCallPiece::construct(N, *CE, SMgr); 583d306a530fca74e40916121f5583e0545e470b3c4Ted Kremenek // Record the mapping from call piece to LocationContext. 584bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek LCM[&C->path] = CE->getCalleeContext(); 58580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(C); 58680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.pushActivePath(&C->path); 58780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks CallStack.push_back(StackDiagPair(C, N)); 58880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks break; 5899373937945e1e075dfa08169eaccc1ad0b31f699Anna Zaks } 590183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose 5917a95de68c093991047ed8d339479ccad51b88663David Blaikie if (Optional<CallEnter> CE = P.getAs<CallEnter>()) { 59280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // Flush all locations, and pop the active path. 59380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks bool VisitedEntireCall = PD.isWithinCall(); 59480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.popActivePath(); 59580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks 59680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // Either we just added a bunch of stuff to the top-level path, or 59780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // we have a previous CallExitEnd. If the former, it means that the 59880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // path terminated within a function call. We must then take the 59980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // current contents of the active path and place it within 60080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // a new PathDiagnosticCallPiece. 60180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PathDiagnosticCallPiece *C; 60280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks if (VisitedEntireCall) { 60380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks C = cast<PathDiagnosticCallPiece>(PD.getActivePath().front()); 60480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks } else { 60580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks const Decl *Caller = CE->getLocationContext()->getDecl(); 60680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks C = PathDiagnosticCallPiece::construct(PD.getActivePath(), Caller); 607d306a530fca74e40916121f5583e0545e470b3c4Ted Kremenek // Record the mapping from call piece to LocationContext. 608bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek LCM[&C->path] = CE->getCalleeContext(); 60980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks } 61080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks 61180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks C->setCallee(*CE, SMgr); 61280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks if (!CallStack.empty()) { 61380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks assert(CallStack.back().first == C); 61480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks CallStack.pop_back(); 61580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks } 61680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks break; 617368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks } 6181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6197a95de68c093991047ed8d339479ccad51b88663David Blaikie if (Optional<BlockEdge> BE = P.getAs<BlockEdge>()) { 62080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks const CFGBlock *Src = BE->getSrc(); 62180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks const CFGBlock *Dst = BE->getDst(); 62280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks const Stmt *T = Src->getTerminator(); 6231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 62480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks if (!T) 62580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks break; 6261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 62780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PathDiagnosticLocation Start = 62880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PathDiagnosticLocation::createBegin(T, SMgr, 62980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks N->getLocationContext()); 6301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 63180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks switch (T->getStmtClass()) { 63261f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek default: 63361f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek break; 6341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 63561f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek case Stmt::GotoStmtClass: 6361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump case Stmt::IndirectGotoStmtClass: { 6370f8579274a010f360a371b53101859d9d6052314Anna Zaks const Stmt *S = PathDiagnosticLocation::getNextStmt(N); 6381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 63961f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek if (!S) 64080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks break; 6411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 642297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek std::string sbuf; 6431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump llvm::raw_string_ostream os(sbuf); 644d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek const PathDiagnosticLocation &End = PDB.getEnclosingStmtLocation(S); 6451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 64600605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek os << "Control jumps to line " 64780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks << End.asLocation().getExpansionLineNumber(); 64880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 64980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, os.str())); 65061f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek break; 65161f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek } 6521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump case Stmt::SwitchStmtClass: { 65461f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek // Figure out what case arm we took. 655297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek std::string sbuf; 656297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek llvm::raw_string_ostream os(sbuf); 6571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6589c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (const Stmt *S = Dst->getLabel()) { 659220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks PathDiagnosticLocation End(S, SMgr, LC); 6601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6615a429954aedd8a830a70fcea2cb51561673e4fc3Ted Kremenek switch (S->getStmtClass()) { 66280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks default: 66380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks os << "No cases match in the switch statement. " 66480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks "Control jumps to line " 66580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks << End.asLocation().getExpansionLineNumber(); 66680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks break; 66780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks case Stmt::DefaultStmtClass: 66880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks os << "Control jumps to the 'default' case at line " 66980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks << End.asLocation().getExpansionLineNumber(); 67080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks break; 67180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks 67280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks case Stmt::CaseStmtClass: { 67380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks os << "Control jumps to 'case "; 67480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks const CaseStmt *Case = cast<CaseStmt>(S); 67580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks const Expr *LHS = Case->getLHS()->IgnoreParenCasts(); 67680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks 67780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // Determine if it is an enum. 67880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks bool GetRawInt = true; 67980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks 68080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(LHS)) { 68180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // FIXME: Maybe this should be an assertion. Are there cases 68280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // were it is not an EnumConstantDecl? 68380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks const EnumConstantDecl *D = 68403509aea098772644bf4662dc1c88634818ceeccZhongxing Xu dyn_cast<EnumConstantDecl>(DR->getDecl()); 6851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 68680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks if (D) { 68780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks GetRawInt = false; 68880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks os << *D; 6895a429954aedd8a830a70fcea2cb51561673e4fc3Ted Kremenek } 69080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks } 6919ec64d6e2fe575b297e1eaa5051efc2983373e25Eli Friedman 69280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks if (GetRawInt) 69380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks os << LHS->EvaluateKnownConstInt(PDB.getASTContext()); 6949ec64d6e2fe575b297e1eaa5051efc2983373e25Eli Friedman 69580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks os << ":' at line " 69680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks << End.asLocation().getExpansionLineNumber(); 69780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks break; 69861f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek } 69980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks } 70080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 70180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, os.str())); 70261f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek } 703567839273dfc395a459cbe77d5f8d128b9ae85bfTed Kremenek else { 704c3517ebb48a51e146badc08bc3684520c41da6c8Ted Kremenek os << "'Default' branch taken. "; 7051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const PathDiagnosticLocation &End = PDB.ExecutionContinues(os, N); 70680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 70780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, os.str())); 708567839273dfc395a459cbe77d5f8d128b9ae85bfTed Kremenek } 7091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 71061f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek break; 71161f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek } 7121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7132673c9ff76ebdb72b7f846e2ff1e0f4256372e19Ted Kremenek case Stmt::BreakStmtClass: 7142673c9ff76ebdb72b7f846e2ff1e0f4256372e19Ted Kremenek case Stmt::ContinueStmtClass: { 715297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek std::string sbuf; 716297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek llvm::raw_string_ostream os(sbuf); 71700605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(os, N); 71880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 71980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, os.str())); 7202673c9ff76ebdb72b7f846e2ff1e0f4256372e19Ted Kremenek break; 7212673c9ff76ebdb72b7f846e2ff1e0f4256372e19Ted Kremenek } 7221eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 72380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // Determine control-flow for ternary '?'. 72456ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall case Stmt::BinaryConditionalOperatorClass: 725706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek case Stmt::ConditionalOperatorClass: { 726297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek std::string sbuf; 727297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek llvm::raw_string_ostream os(sbuf); 7281d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek os << "'?' condition is "; 7291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 730706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek if (*(Src->succ_begin()+1) == Dst) 731082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek os << "false"; 732706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek else 733082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek os << "true"; 7341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 73500605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(N); 7361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7371d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek if (const Stmt *S = End.asStmt()) 7381d9a23ac34fee297e28361653a72c519cb04a854Ted Kremenek End = PDB.getEnclosingStmtLocation(S); 7391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 74080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 74180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, os.str())); 742babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek break; 743babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek } 7441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 74580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // Determine control-flow for short-circuited '&&' and '||'. 746babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek case Stmt::BinaryOperatorClass: { 747babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek if (!PDB.supportsLogicalOpControlFlow()) 748babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek break; 7491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 75003509aea098772644bf4662dc1c88634818ceeccZhongxing Xu const BinaryOperator *B = cast<BinaryOperator>(T); 751babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek std::string sbuf; 752babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek llvm::raw_string_ostream os(sbuf); 753babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek os << "Left side of '"; 7541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7552de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall if (B->getOpcode() == BO_LAnd) { 756f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek os << "&&" << "' is "; 7571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 758f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek if (*(Src->succ_begin()+1) == Dst) { 759f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek os << "false"; 760220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks PathDiagnosticLocation End(B->getLHS(), SMgr, LC); 7610cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks PathDiagnosticLocation Start = 76280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PathDiagnosticLocation::createOperatorLoc(B, SMgr); 76380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 76480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, os.str())); 7651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 766f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek else { 767f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek os << "true"; 768220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks PathDiagnosticLocation Start(B->getLHS(), SMgr, LC); 769f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(N); 77080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 77180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, os.str())); 7721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 773babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek } 774babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek else { 7752de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall assert(B->getOpcode() == BO_LOr); 776f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek os << "||" << "' is "; 7771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 778f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek if (*(Src->succ_begin()+1) == Dst) { 779f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek os << "false"; 780220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks PathDiagnosticLocation Start(B->getLHS(), SMgr, LC); 781f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(N); 78280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 78380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, os.str())); 784f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek } 785f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek else { 786f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek os << "true"; 787220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks PathDiagnosticLocation End(B->getLHS(), SMgr, LC); 7880cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks PathDiagnosticLocation Start = 78980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PathDiagnosticLocation::createOperatorLoc(B, SMgr); 79080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 79180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, os.str())); 792f5ab8e6eb4b1c14cb3a0f69aad526192794c95ceTed Kremenek } 793babdd7b56d02e2b6924a2c93b061d6a48bb5f0caTed Kremenek } 7941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 795706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek break; 796706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek } 7971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump case Stmt::DoStmtClass: { 799706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek if (*(Src->succ_begin()) == Dst) { 800297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek std::string sbuf; 801297308eda369de400e6ea7057dffeadd9f92e385Ted Kremenek llvm::raw_string_ostream os(sbuf); 8021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 803c3517ebb48a51e146badc08bc3684520c41da6c8Ted Kremenek os << "Loop condition is true. "; 804d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(os, N); 8051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 806d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek if (const Stmt *S = End.asStmt()) 807d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek End = PDB.getEnclosingStmtLocation(S); 8081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 80980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 81080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, os.str())); 811082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek } 812082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek else { 81300605e0f011ed99225a22026344c5fc1b3212cd7Ted Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(N); 8141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 815d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek if (const Stmt *S = End.asStmt()) 816d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek End = PDB.getEnclosingStmtLocation(S); 8171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 81880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 81980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, "Loop condition is false. Exiting loop")); 8203106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 8211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8223106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 8233106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 8241eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8253106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek case Stmt::WhileStmtClass: 8261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump case Stmt::ForStmtClass: { 8273106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (*(Src->succ_begin()+1) == Dst) { 8283106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek std::string sbuf; 8293106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek llvm::raw_string_ostream os(sbuf); 8301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8313106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek os << "Loop condition is false. "; 8323106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(os, N); 8333106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (const Stmt *S = End.asStmt()) 8343106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek End = PDB.getEnclosingStmtLocation(S); 8351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 83680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 83780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, os.str())); 8383106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 8393106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek else { 8403106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(N); 8413106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (const Stmt *S = End.asStmt()) 8423106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek End = PDB.getEnclosingStmtLocation(S); 8431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 84480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 84580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, "Loop condition is true. Entering loop body")); 8463106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 8471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8483106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 8493106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 8501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8513106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek case Stmt::IfStmtClass: { 8523106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PathDiagnosticLocation End = PDB.ExecutionContinues(N); 8531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8543106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (const Stmt *S = End.asStmt()) 8553106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek End = PDB.getEnclosingStmtLocation(S); 8561eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8573106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (*(Src->succ_begin()+1) == Dst) 85880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 85980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, "Taking false branch")); 8601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump else 86180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece( 86280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks Start, End, "Taking true branch")); 8631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8643106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 8653106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 86680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks } 8673106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 86880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks } while(0); 8691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 870dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek if (NextNode) { 8718e6431adab313e283a992698f6fc7afe62420999Anna Zaks // Add diagnostic pieces from custom visitors. 8728e6431adab313e283a992698f6fc7afe62420999Anna Zaks BugReport *R = PDB.getBugReport(); 8733bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose for (ArrayRef<BugReporterVisitor *>::iterator I = visitors.begin(), 8743bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose E = visitors.end(); 8753bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose I != E; ++I) { 876368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks if (PathDiagnosticPiece *p = (*I)->VisitNode(N, NextNode, PDB, *R)) { 8772042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.getActivePath().push_front(p); 878368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks updateStackPiecesWithMessage(p, CallStack); 879368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks } 880dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek } 8818966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek } 8823106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 8831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8848347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose if (!PDB.getBugReport()->isValid()) 8858347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose return false; 8868347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose 88714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // After constructing the full PathDiagnostic, do a pass over it to compact 88814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // PathDiagnosticPieces that occur within a macro. 88977d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek CompactPathDiagnostic(PD.getMutablePieces(), PDB.getSourceManager()); 8908347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose return true; 8913106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 8923106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 8933106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 8945fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek// "Extensive" PathDiagnostic generation. 8955fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek//===----------------------------------------------------------------------===// 8965fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek 8975fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenekstatic bool IsControlFlowExpr(const Stmt *S) { 8985fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek const Expr *E = dyn_cast<Expr>(S); 8991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9005fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek if (!E) 9015fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek return false; 9021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump E = E->IgnoreParenCasts(); 9041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 90556ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall if (isa<AbstractConditionalOperator>(E)) 9065fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek return true; 9071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9085fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek if (const BinaryOperator *B = dyn_cast<BinaryOperator>(E)) 9095fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek if (B->isLogicalOp()) 9105fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek return true; 9111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return false; 9135fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek} 9145fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek 91514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremeneknamespace { 916ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass ContextLocation : public PathDiagnosticLocation { 9178f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek bool IsDead; 9188f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenekpublic: 9198f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek ContextLocation(const PathDiagnosticLocation &L, bool isdead = false) 9208f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek : PathDiagnosticLocation(L), IsDead(isdead) {} 9211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9221eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump void markDead() { IsDead = true; } 9238f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek bool isDead() const { return IsDead; } 9248f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek}; 9251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 926e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenekstatic PathDiagnosticLocation cleanUpLocation(PathDiagnosticLocation L, 927e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek const LocationContext *LC, 928e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek bool firstCharOnly = false) { 929e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek if (const Stmt *S = L.asStmt()) { 930e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek const Stmt *Original = S; 931e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek while (1) { 932e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek // Adjust the location for some expressions that are best referenced 933e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek // by one of their subexpressions. 934e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek switch (S->getStmtClass()) { 935e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek default: 936e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek break; 937e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek case Stmt::ParenExprClass: 938e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek case Stmt::GenericSelectionExprClass: 939e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek S = cast<Expr>(S)->IgnoreParens(); 940e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek firstCharOnly = true; 941e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek continue; 942e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek case Stmt::BinaryConditionalOperatorClass: 943e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek case Stmt::ConditionalOperatorClass: 944e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek S = cast<AbstractConditionalOperator>(S)->getCond(); 945e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek firstCharOnly = true; 946e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek continue; 947e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek case Stmt::ChooseExprClass: 948e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek S = cast<ChooseExpr>(S)->getCond(); 949e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek firstCharOnly = true; 950e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek continue; 951e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek case Stmt::BinaryOperatorClass: 952e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek S = cast<BinaryOperator>(S)->getLHS(); 953e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek firstCharOnly = true; 954e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek continue; 955e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek } 956e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek 957e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek break; 958e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek } 959e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek 960e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek if (S != Original) 961e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek L = PathDiagnosticLocation(S, L.getManager(), LC); 962e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek } 963e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek 964e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek if (firstCharOnly) 965e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek L = PathDiagnosticLocation::createSingleLocation(L); 966e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek 967e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek return L; 968e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek} 969e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek 970ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass EdgeBuilder { 9718f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek std::vector<ContextLocation> CLocs; 9728f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek typedef std::vector<ContextLocation>::iterator iterator; 97314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek PathDiagnostic &PD; 97414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek PathDiagnosticBuilder &PDB; 97514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek PathDiagnosticLocation PrevLoc; 9761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9778f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek bool IsConsumedExpr(const PathDiagnosticLocation &L); 9781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 97914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek bool containsLocation(const PathDiagnosticLocation &Container, 98014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek const PathDiagnosticLocation &Containee); 9811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 98214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek PathDiagnosticLocation getContextLocation(const PathDiagnosticLocation &L); 9831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 98614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek void popLocation() { 9878f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek if (!CLocs.back().isDead() && CLocs.back().asLocation().isFileID()) { 9885c7168cbe8a0eabd05e0e12e469090d2cabd27c0Ted Kremenek // For contexts, we only one the first character as the range. 989e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek rawAddEdge(cleanUpLocation(CLocs.back(), PDB.LC, true)); 9905c7168cbe8a0eabd05e0e12e469090d2cabd27c0Ted Kremenek } 99114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek CLocs.pop_back(); 99214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 9931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 99414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekpublic: 99514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek EdgeBuilder(PathDiagnostic &pd, PathDiagnosticBuilder &pdb) 99614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek : PD(pd), PDB(pdb) { 9971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 998a301a6773db085575ac51e3c966858180390c25bTed Kremenek // If the PathDiagnostic already has pieces, add the enclosing statement 999a301a6773db085575ac51e3c966858180390c25bTed Kremenek // of the first piece as a context as well. 1000802e02463b880f53a6e645bde78cc412481ce9e0Ted Kremenek if (!PD.path.empty()) { 1001ed866e73bab7733f5226f84c52edefe23d694b2fTed Kremenek PrevLoc = (*PD.path.begin())->getLocation(); 10021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 100314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (const Stmt *S = PrevLoc.asStmt()) 1004e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek addExtendedContext(PDB.getEnclosingStmtLocation(S).asStmt()); 100514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 100614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 100714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 100814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek ~EdgeBuilder() { 100914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek while (!CLocs.empty()) popLocation(); 10100cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks 1011a301a6773db085575ac51e3c966858180390c25bTed Kremenek // Finally, add an initial edge from the start location of the first 1012a301a6773db085575ac51e3c966858180390c25bTed Kremenek // statement (if it doesn't already exist). 10130cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks PathDiagnosticLocation L = PathDiagnosticLocation::createDeclBegin( 101459950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek PDB.LC, 10150cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks PDB.getSourceManager()); 10160cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks if (L.isValid()) 10170cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks rawAddEdge(L); 101814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 101914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 10205de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek void flushLocations() { 10215de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek while (!CLocs.empty()) 10225de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek popLocation(); 10235de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek PrevLoc = PathDiagnosticLocation(); 10245de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek } 10255de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek 10263ea09a802f973c2726b2a489ae08a4bded93410bJordan Rose void addEdge(PathDiagnosticLocation NewLoc, bool alwaysAdd = false, 10273ea09a802f973c2726b2a489ae08a4bded93410bJordan Rose bool IsPostJump = false); 10281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10298bd4d037d837e7922c3661d6158229da58a03887Ted Kremenek void rawAddEdge(PathDiagnosticLocation NewLoc); 10301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 103114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek void addContext(const Stmt *S); 1032183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose void addContext(const PathDiagnosticLocation &L); 1033e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek void addExtendedContext(const Stmt *S); 10341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump}; 103514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} // end anonymous namespace 103614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 103714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 103814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted KremenekPathDiagnosticLocation 103914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted KremenekEdgeBuilder::getContextLocation(const PathDiagnosticLocation &L) { 104014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (const Stmt *S = L.asStmt()) { 104114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (IsControlFlowExpr(S)) 104214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return L; 10431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return PDB.getEnclosingStmtLocation(S); 104514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 10461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 104714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return L; 104814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} 104914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 105014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekbool EdgeBuilder::containsLocation(const PathDiagnosticLocation &Container, 105114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek const PathDiagnosticLocation &Containee) { 105214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 105314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (Container == Containee) 105414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return true; 10551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 105614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (Container.asDecl()) 105714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return true; 10581eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 105914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (const Stmt *S = Containee.asStmt()) 106014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (const Stmt *ContainerS = Container.asStmt()) { 106114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek while (S) { 106214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (S == ContainerS) 106314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return true; 106414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek S = PDB.getParent(S); 106514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 106614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return false; 106714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 106814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 106914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // Less accurate: compare using source ranges. 107014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek SourceRange ContainerR = Container.asRange(); 107114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek SourceRange ContaineeR = Containee.asRange(); 10721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 107314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek SourceManager &SM = PDB.getSourceManager(); 1074402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth SourceLocation ContainerRBeg = SM.getExpansionLoc(ContainerR.getBegin()); 1075402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth SourceLocation ContainerREnd = SM.getExpansionLoc(ContainerR.getEnd()); 1076402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth SourceLocation ContaineeRBeg = SM.getExpansionLoc(ContaineeR.getBegin()); 1077402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth SourceLocation ContaineeREnd = SM.getExpansionLoc(ContaineeR.getEnd()); 10781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1079642116259e8df6286063a17361c20e95b5017a0aChandler Carruth unsigned ContainerBegLine = SM.getExpansionLineNumber(ContainerRBeg); 1080642116259e8df6286063a17361c20e95b5017a0aChandler Carruth unsigned ContainerEndLine = SM.getExpansionLineNumber(ContainerREnd); 1081642116259e8df6286063a17361c20e95b5017a0aChandler Carruth unsigned ContaineeBegLine = SM.getExpansionLineNumber(ContaineeRBeg); 1082642116259e8df6286063a17361c20e95b5017a0aChandler Carruth unsigned ContaineeEndLine = SM.getExpansionLineNumber(ContaineeREnd); 10831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 108414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek assert(ContainerBegLine <= ContainerEndLine); 10851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump assert(ContaineeBegLine <= ContaineeEndLine); 10861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 108714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return (ContainerBegLine <= ContaineeBegLine && 108814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek ContainerEndLine >= ContaineeEndLine && 108914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek (ContainerBegLine != ContaineeBegLine || 1090a77c031cb66f75d22672070052cc6e0205289ff8Chandler Carruth SM.getExpansionColumnNumber(ContainerRBeg) <= 1091a77c031cb66f75d22672070052cc6e0205289ff8Chandler Carruth SM.getExpansionColumnNumber(ContaineeRBeg)) && 109214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek (ContainerEndLine != ContaineeEndLine || 1093a77c031cb66f75d22672070052cc6e0205289ff8Chandler Carruth SM.getExpansionColumnNumber(ContainerREnd) >= 10946488dc31153be6f98b404c7860be6c66bb4ec917Ted Kremenek SM.getExpansionColumnNumber(ContaineeREnd))); 109514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} 109614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 109714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekvoid EdgeBuilder::rawAddEdge(PathDiagnosticLocation NewLoc) { 109814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (!PrevLoc.isValid()) { 109914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek PrevLoc = NewLoc; 110014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return; 110114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 11021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1103e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek const PathDiagnosticLocation &NewLocClean = cleanUpLocation(NewLoc, PDB.LC); 1104e19229be18725bd856410b478c0e63d81ab8e4f5Ted Kremenek const PathDiagnosticLocation &PrevLocClean = cleanUpLocation(PrevLoc, PDB.LC); 11051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1106a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek if (PrevLocClean.asLocation().isInvalid()) { 1107a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek PrevLoc = NewLoc; 1108a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek return; 1109a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek } 1110a43df9539644bf1c258e12710cd69d79b0b078cdTed Kremenek 11118c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek if (NewLocClean.asLocation() == PrevLocClean.asLocation()) 111214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return; 11131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 111414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // FIXME: Ignore intra-macro edges for now. 1115402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth if (NewLocClean.asLocation().getExpansionLoc() == 1116402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth PrevLocClean.asLocation().getExpansionLoc()) 111714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return; 111814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 11192042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.getActivePath().push_front(new PathDiagnosticControlFlowPiece(NewLocClean, PrevLocClean)); 11208c8b0ad9601d6ccf3d7b2a3f77a896ef4fb4e6e9Ted Kremenek PrevLoc = NewLoc; 112114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} 112214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 11233ea09a802f973c2726b2a489ae08a4bded93410bJordan Rosevoid EdgeBuilder::addEdge(PathDiagnosticLocation NewLoc, bool alwaysAdd, 11243ea09a802f973c2726b2a489ae08a4bded93410bJordan Rose bool IsPostJump) { 11251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1126a301a6773db085575ac51e3c966858180390c25bTed Kremenek if (!alwaysAdd && NewLoc.asLocation().isMacroID()) 1127a301a6773db085575ac51e3c966858180390c25bTed Kremenek return; 11281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 112914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek const PathDiagnosticLocation &CLoc = getContextLocation(NewLoc); 113014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 113114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek while (!CLocs.empty()) { 11328f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek ContextLocation &TopContextLoc = CLocs.back(); 11331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 113414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // Is the top location context the same as the one for the new location? 113514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (TopContextLoc == CLoc) { 11368f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek if (alwaysAdd) { 11373ea09a802f973c2726b2a489ae08a4bded93410bJordan Rose if (IsConsumedExpr(TopContextLoc)) 11383ea09a802f973c2726b2a489ae08a4bded93410bJordan Rose TopContextLoc.markDead(); 11398f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek 114014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek rawAddEdge(NewLoc); 11418f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek } 114214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 11433ea09a802f973c2726b2a489ae08a4bded93410bJordan Rose if (IsPostJump) 11443ea09a802f973c2726b2a489ae08a4bded93410bJordan Rose TopContextLoc.markDead(); 114514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return; 114614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 114714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 114814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (containsLocation(TopContextLoc, CLoc)) { 11498f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek if (alwaysAdd) { 115014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek rawAddEdge(NewLoc); 11511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11523ea09a802f973c2726b2a489ae08a4bded93410bJordan Rose if (IsConsumedExpr(CLoc)) { 11533ea09a802f973c2726b2a489ae08a4bded93410bJordan Rose CLocs.push_back(ContextLocation(CLoc, /*IsDead=*/true)); 11548f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek return; 11558f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek } 11568f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek } 11571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11583ea09a802f973c2726b2a489ae08a4bded93410bJordan Rose CLocs.push_back(ContextLocation(CLoc, /*IsDead=*/IsPostJump)); 11591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return; 116014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 116114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 116214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // Context does not contain the location. Flush it. 116314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek popLocation(); 116414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 11651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11665c7168cbe8a0eabd05e0e12e469090d2cabd27c0Ted Kremenek // If we reach here, there is no enclosing context. Just add the edge. 11675c7168cbe8a0eabd05e0e12e469090d2cabd27c0Ted Kremenek rawAddEdge(NewLoc); 116814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} 116914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 11708f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenekbool EdgeBuilder::IsConsumedExpr(const PathDiagnosticLocation &L) { 11718f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek if (const Expr *X = dyn_cast_or_null<Expr>(L.asStmt())) 11728f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek return PDB.getParentMap().isConsumedExpr(X) && !IsControlFlowExpr(X); 11731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11748f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek return false; 11758f9b1b3865cd5814a8c4c768a34d56df6d6c93beTed Kremenek} 11761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1177e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenekvoid EdgeBuilder::addExtendedContext(const Stmt *S) { 1178e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek if (!S) 1179e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek return; 11801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const Stmt *Parent = PDB.getParent(S); 1182e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek while (Parent) { 1183e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek if (isa<CompoundStmt>(Parent)) 1184e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek Parent = PDB.getParent(Parent); 1185e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek else 1186e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek break; 1187e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek } 1188e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek 1189e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek if (Parent) { 1190e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek switch (Parent->getStmtClass()) { 1191e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek case Stmt::DoStmtClass: 1192e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek case Stmt::ObjCAtSynchronizedStmtClass: 1193e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek addContext(Parent); 1194e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek default: 1195e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek break; 1196e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek } 1197e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek } 11981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1199e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek addContext(S); 1200e1baed38437e08fee7ab372ba2579ce22da354c2Ted Kremenek} 12011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 120214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenekvoid EdgeBuilder::addContext(const Stmt *S) { 120314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (!S) 120414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return; 120514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 120659950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek PathDiagnosticLocation L(S, PDB.getSourceManager(), PDB.LC); 1207183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose addContext(L); 1208183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose} 12091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1210183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rosevoid EdgeBuilder::addContext(const PathDiagnosticLocation &L) { 121114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek while (!CLocs.empty()) { 121214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek const PathDiagnosticLocation &TopContextLoc = CLocs.back(); 121314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 121414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // Is the top location context the same as the one for the new location? 121514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (TopContextLoc == L) 121614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek return; 121714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 121814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek if (containsLocation(TopContextLoc, L)) { 121914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek CLocs.push_back(L); 12201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return; 122114856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 122214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 122314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek // Context does not contain the location. Flush it. 122414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek popLocation(); 122514856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 122614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 122714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek CLocs.push_back(L); 122814856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} 122914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 123011abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// Cone-of-influence: support the reverse propagation of "interesting" symbols 123111abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// and values by tracing interesting calculations backwards through evaluated 123211abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// expressions along a path. This is probably overly complicated, but the idea 123311abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// is that if an expression computed an "interesting" value, the child 123411abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// expressions are are also likely to be "interesting" as well (which then 123511abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// propagates to the values they in turn compute). This reverse propagation 123611abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// is needed to track interesting correlations across function call boundaries, 123711abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// where formal arguments bind to actual arguments, etc. This is also needed 123811abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// because the constraint solver sometimes simplifies certain symbolic values 123911abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// into constants when appropriate, and this complicates reasoning about 124011abcecc8c919673237cf37384290a1ef1943976Ted Kremenek// interesting values. 124111abcecc8c919673237cf37384290a1ef1943976Ted Kremenektypedef llvm::DenseSet<const Expr *> InterestingExprs; 124211abcecc8c919673237cf37384290a1ef1943976Ted Kremenek 124311abcecc8c919673237cf37384290a1ef1943976Ted Kremenekstatic void reversePropagateIntererstingSymbols(BugReport &R, 124411abcecc8c919673237cf37384290a1ef1943976Ted Kremenek InterestingExprs &IE, 124511abcecc8c919673237cf37384290a1ef1943976Ted Kremenek const ProgramState *State, 124611abcecc8c919673237cf37384290a1ef1943976Ted Kremenek const Expr *Ex, 124711abcecc8c919673237cf37384290a1ef1943976Ted Kremenek const LocationContext *LCtx) { 124811abcecc8c919673237cf37384290a1ef1943976Ted Kremenek SVal V = State->getSVal(Ex, LCtx); 124911abcecc8c919673237cf37384290a1ef1943976Ted Kremenek if (!(R.isInteresting(V) || IE.count(Ex))) 125011abcecc8c919673237cf37384290a1ef1943976Ted Kremenek return; 125111abcecc8c919673237cf37384290a1ef1943976Ted Kremenek 125211abcecc8c919673237cf37384290a1ef1943976Ted Kremenek switch (Ex->getStmtClass()) { 125311abcecc8c919673237cf37384290a1ef1943976Ted Kremenek default: 125411abcecc8c919673237cf37384290a1ef1943976Ted Kremenek if (!isa<CastExpr>(Ex)) 125511abcecc8c919673237cf37384290a1ef1943976Ted Kremenek break; 125611abcecc8c919673237cf37384290a1ef1943976Ted Kremenek // Fall through. 125711abcecc8c919673237cf37384290a1ef1943976Ted Kremenek case Stmt::BinaryOperatorClass: 125811abcecc8c919673237cf37384290a1ef1943976Ted Kremenek case Stmt::UnaryOperatorClass: { 125911abcecc8c919673237cf37384290a1ef1943976Ted Kremenek for (Stmt::const_child_iterator CI = Ex->child_begin(), 126011abcecc8c919673237cf37384290a1ef1943976Ted Kremenek CE = Ex->child_end(); 126111abcecc8c919673237cf37384290a1ef1943976Ted Kremenek CI != CE; ++CI) { 126211abcecc8c919673237cf37384290a1ef1943976Ted Kremenek if (const Expr *child = dyn_cast_or_null<Expr>(*CI)) { 126311abcecc8c919673237cf37384290a1ef1943976Ted Kremenek IE.insert(child); 126411abcecc8c919673237cf37384290a1ef1943976Ted Kremenek SVal ChildV = State->getSVal(child, LCtx); 126511abcecc8c919673237cf37384290a1ef1943976Ted Kremenek R.markInteresting(ChildV); 126611abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 126711abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 1268651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines break; 126911abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 127011abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 127111abcecc8c919673237cf37384290a1ef1943976Ted Kremenek 127211abcecc8c919673237cf37384290a1ef1943976Ted Kremenek R.markInteresting(V); 127311abcecc8c919673237cf37384290a1ef1943976Ted Kremenek} 127411abcecc8c919673237cf37384290a1ef1943976Ted Kremenek 127511abcecc8c919673237cf37384290a1ef1943976Ted Kremenekstatic void reversePropagateInterestingSymbols(BugReport &R, 127611abcecc8c919673237cf37384290a1ef1943976Ted Kremenek InterestingExprs &IE, 127711abcecc8c919673237cf37384290a1ef1943976Ted Kremenek const ProgramState *State, 127811abcecc8c919673237cf37384290a1ef1943976Ted Kremenek const LocationContext *CalleeCtx, 127911abcecc8c919673237cf37384290a1ef1943976Ted Kremenek const LocationContext *CallerCtx) 128011abcecc8c919673237cf37384290a1ef1943976Ted Kremenek{ 1281852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose // FIXME: Handle non-CallExpr-based CallEvents. 128211abcecc8c919673237cf37384290a1ef1943976Ted Kremenek const StackFrameContext *Callee = CalleeCtx->getCurrentStackFrame(); 128311abcecc8c919673237cf37384290a1ef1943976Ted Kremenek const Stmt *CallSite = Callee->getCallSite(); 1284852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose if (const CallExpr *CE = dyn_cast_or_null<CallExpr>(CallSite)) { 128511abcecc8c919673237cf37384290a1ef1943976Ted Kremenek if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CalleeCtx->getDecl())) { 128611abcecc8c919673237cf37384290a1ef1943976Ted Kremenek FunctionDecl::param_const_iterator PI = FD->param_begin(), 128711abcecc8c919673237cf37384290a1ef1943976Ted Kremenek PE = FD->param_end(); 128811abcecc8c919673237cf37384290a1ef1943976Ted Kremenek CallExpr::const_arg_iterator AI = CE->arg_begin(), AE = CE->arg_end(); 128911abcecc8c919673237cf37384290a1ef1943976Ted Kremenek for (; AI != AE && PI != PE; ++AI, ++PI) { 129011abcecc8c919673237cf37384290a1ef1943976Ted Kremenek if (const Expr *ArgE = *AI) { 129111abcecc8c919673237cf37384290a1ef1943976Ted Kremenek if (const ParmVarDecl *PD = *PI) { 129211abcecc8c919673237cf37384290a1ef1943976Ted Kremenek Loc LV = State->getLValue(PD, CalleeCtx); 129311abcecc8c919673237cf37384290a1ef1943976Ted Kremenek if (R.isInteresting(LV) || R.isInteresting(State->getRawSVal(LV))) 129411abcecc8c919673237cf37384290a1ef1943976Ted Kremenek IE.insert(ArgE); 129511abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 129611abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 129711abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 129811abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 129911abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 130011abcecc8c919673237cf37384290a1ef1943976Ted Kremenek} 13018185674528423e2504a1fae35c28c24104846510Ted Kremenek 1302b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek//===----------------------------------------------------------------------===// 1303b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek// Functions for determining if a loop was executed 0 times. 1304b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek//===----------------------------------------------------------------------===// 1305b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek 1306b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenekstatic bool isLoop(const Stmt *Term) { 13078185674528423e2504a1fae35c28c24104846510Ted Kremenek switch (Term->getStmtClass()) { 13088185674528423e2504a1fae35c28c24104846510Ted Kremenek case Stmt::ForStmtClass: 13098185674528423e2504a1fae35c28c24104846510Ted Kremenek case Stmt::WhileStmtClass: 1310c5b9c8bc6d77175f6d41d898511b1e7b1e2f86f8Ted Kremenek case Stmt::ObjCForCollectionStmtClass: 131149a246f4fad959888bb0164c624c3c2b03078e91Jordan Rose case Stmt::CXXForRangeStmtClass: 1312b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek return true; 13138185674528423e2504a1fae35c28c24104846510Ted Kremenek default: 13148185674528423e2504a1fae35c28c24104846510Ted Kremenek // Note that we intentionally do not include do..while here. 13158185674528423e2504a1fae35c28c24104846510Ted Kremenek return false; 13168185674528423e2504a1fae35c28c24104846510Ted Kremenek } 1317b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek} 13188185674528423e2504a1fae35c28c24104846510Ted Kremenek 1319b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenekstatic bool isJumpToFalseBranch(const BlockEdge *BE) { 13208185674528423e2504a1fae35c28c24104846510Ted Kremenek const CFGBlock *Src = BE->getSrc(); 13218185674528423e2504a1fae35c28c24104846510Ted Kremenek assert(Src->succ_size() == 2); 13228185674528423e2504a1fae35c28c24104846510Ted Kremenek return (*(Src->succ_begin()+1) == BE->getDst()); 13238185674528423e2504a1fae35c28c24104846510Ted Kremenek} 13248185674528423e2504a1fae35c28c24104846510Ted Kremenek 1325b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek/// Return true if the terminator is a loop and the destination is the 1326b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek/// false branch. 1327b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenekstatic bool isLoopJumpPastBody(const Stmt *Term, const BlockEdge *BE) { 1328b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek if (!isLoop(Term)) 1329b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek return false; 1330b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek 1331b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek // Did we take the false branch? 1332b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek return isJumpToFalseBranch(BE); 1333b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek} 1334b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek 1335b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenekstatic bool isContainedByStmt(ParentMap &PM, const Stmt *S, const Stmt *SubS) { 1336b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek while (SubS) { 1337b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek if (SubS == S) 1338b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek return true; 1339b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek SubS = PM.getParent(SubS); 1340b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek } 1341b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek return false; 1342b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek} 1343b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek 1344b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenekstatic const Stmt *getStmtBeforeCond(ParentMap &PM, const Stmt *Term, 1345b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek const ExplodedNode *N) { 1346b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek while (N) { 1347b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek Optional<StmtPoint> SP = N->getLocation().getAs<StmtPoint>(); 1348b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek if (SP) { 1349b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek const Stmt *S = SP->getStmt(); 1350b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek if (!isContainedByStmt(PM, Term, S)) 1351b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek return S; 1352b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek } 13530f8579274a010f360a371b53101859d9d6052314Anna Zaks N = N->getFirstPred(); 1354b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek } 13556bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 1356b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek} 1357b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek 1358b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenekstatic bool isInLoopBody(ParentMap &PM, const Stmt *S, const Stmt *Term) { 13596bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines const Stmt *LoopBody = nullptr; 1360b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek switch (Term->getStmtClass()) { 136149a246f4fad959888bb0164c624c3c2b03078e91Jordan Rose case Stmt::CXXForRangeStmtClass: { 136249a246f4fad959888bb0164c624c3c2b03078e91Jordan Rose const CXXForRangeStmt *FR = cast<CXXForRangeStmt>(Term); 136349a246f4fad959888bb0164c624c3c2b03078e91Jordan Rose if (isContainedByStmt(PM, FR->getInc(), S)) 136449a246f4fad959888bb0164c624c3c2b03078e91Jordan Rose return true; 136549a246f4fad959888bb0164c624c3c2b03078e91Jordan Rose if (isContainedByStmt(PM, FR->getLoopVarStmt(), S)) 136649a246f4fad959888bb0164c624c3c2b03078e91Jordan Rose return true; 136749a246f4fad959888bb0164c624c3c2b03078e91Jordan Rose LoopBody = FR->getBody(); 136849a246f4fad959888bb0164c624c3c2b03078e91Jordan Rose break; 136949a246f4fad959888bb0164c624c3c2b03078e91Jordan Rose } 1370b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek case Stmt::ForStmtClass: { 1371b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek const ForStmt *FS = cast<ForStmt>(Term); 1372b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek if (isContainedByStmt(PM, FS->getInc(), S)) 1373b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek return true; 1374b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek LoopBody = FS->getBody(); 1375b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek break; 1376b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek } 1377c5b9c8bc6d77175f6d41d898511b1e7b1e2f86f8Ted Kremenek case Stmt::ObjCForCollectionStmtClass: { 1378c5b9c8bc6d77175f6d41d898511b1e7b1e2f86f8Ted Kremenek const ObjCForCollectionStmt *FC = cast<ObjCForCollectionStmt>(Term); 1379c5b9c8bc6d77175f6d41d898511b1e7b1e2f86f8Ted Kremenek LoopBody = FC->getBody(); 1380c5b9c8bc6d77175f6d41d898511b1e7b1e2f86f8Ted Kremenek break; 1381c5b9c8bc6d77175f6d41d898511b1e7b1e2f86f8Ted Kremenek } 1382b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek case Stmt::WhileStmtClass: 1383b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek LoopBody = cast<WhileStmt>(Term)->getBody(); 1384b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek break; 1385b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek default: 1386b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek return false; 1387b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek } 1388b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek return isContainedByStmt(PM, LoopBody, S); 1389b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek} 1390b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek 1391b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek//===----------------------------------------------------------------------===// 1392b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek// Top-level logic for generating extensive path diagnostics. 1393b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek//===----------------------------------------------------------------------===// 1394b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek 13958347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rosestatic bool GenerateExtensivePathDiagnostic(PathDiagnostic& PD, 139614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek PathDiagnosticBuilder &PDB, 13973bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose const ExplodedNode *N, 1398d306a530fca74e40916121f5583e0545e470b3c4Ted Kremenek LocationContextMap &LCM, 13993bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose ArrayRef<BugReporterVisitor *> visitors) { 140014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek EdgeBuilder EB(PD, PDB); 14010cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks const SourceManager& SM = PDB.getSourceManager(); 140256a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks StackDiagVector CallStack; 140311abcecc8c919673237cf37384290a1ef1943976Ted Kremenek InterestingExprs IE; 140414856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 14056bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines const ExplodedNode *NextNode = N->pred_empty() ? nullptr : *(N->pred_begin()); 140614856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek while (NextNode) { 140714856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek N = NextNode; 14080f8579274a010f360a371b53101859d9d6052314Anna Zaks NextNode = N->getFirstPred(); 140914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek ProgramPoint P = N->getLocation(); 141014856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 1411dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek do { 14127a95de68c093991047ed8d339479ccad51b88663David Blaikie if (Optional<PostStmt> PS = P.getAs<PostStmt>()) { 141311abcecc8c919673237cf37384290a1ef1943976Ted Kremenek if (const Expr *Ex = PS->getStmtAs<Expr>()) 141411abcecc8c919673237cf37384290a1ef1943976Ted Kremenek reversePropagateIntererstingSymbols(*PDB.getBugReport(), IE, 1415ef8225444452a1486bd721f3285301fe84643b00Stephen Hines N->getState().get(), Ex, 141611abcecc8c919673237cf37384290a1ef1943976Ted Kremenek N->getLocationContext()); 141711abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 141811abcecc8c919673237cf37384290a1ef1943976Ted Kremenek 14197a95de68c093991047ed8d339479ccad51b88663David Blaikie if (Optional<CallExitEnd> CE = P.getAs<CallExitEnd>()) { 1420183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose const Stmt *S = CE->getCalleeContext()->getCallSite(); 1421183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose if (const Expr *Ex = dyn_cast_or_null<Expr>(S)) { 1422852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose reversePropagateIntererstingSymbols(*PDB.getBugReport(), IE, 1423ef8225444452a1486bd721f3285301fe84643b00Stephen Hines N->getState().get(), Ex, 1424852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose N->getLocationContext()); 1425852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose } 1426183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose 1427183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose PathDiagnosticCallPiece *C = 1428183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose PathDiagnosticCallPiece::construct(N, *CE, SM); 1429bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek LCM[&C->path] = CE->getCalleeContext(); 1430183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose 14313ea09a802f973c2726b2a489ae08a4bded93410bJordan Rose EB.addEdge(C->callReturn, /*AlwaysAdd=*/true, /*IsPostJump=*/true); 1432183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose EB.flushLocations(); 1433183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose 1434183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose PD.getActivePath().push_front(C); 1435183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose PD.pushActivePath(&C->path); 1436183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose CallStack.push_back(StackDiagPair(C, N)); 14375de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek break; 14385de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek } 14394ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek 14402042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek // Pop the call hierarchy if we are done walking the contents 14412042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek // of a function call. 14427a95de68c093991047ed8d339479ccad51b88663David Blaikie if (Optional<CallEnter> CE = P.getAs<CallEnter>()) { 1443097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted Kremenek // Add an edge to the start of the function. 1444097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted Kremenek const Decl *D = CE->getCalleeContext()->getDecl(); 1445097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted Kremenek PathDiagnosticLocation pos = 1446097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted Kremenek PathDiagnosticLocation::createBegin(D, SM); 1447097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted Kremenek EB.addEdge(pos); 1448097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted Kremenek 1449097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted Kremenek // Flush all locations, and pop the active path. 1450183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose bool VisitedEntireCall = PD.isWithinCall(); 14514ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek EB.flushLocations(); 14522042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.popActivePath(); 14534ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek PDB.LC = N->getLocationContext(); 1454097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted Kremenek 1455183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose // Either we just added a bunch of stuff to the top-level path, or 1456183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose // we have a previous CallExitEnd. If the former, it means that the 14572042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek // path terminated within a function call. We must then take the 14582042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek // current contents of the active path and place it within 14592042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek // a new PathDiagnosticCallPiece. 1460183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose PathDiagnosticCallPiece *C; 1461183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose if (VisitedEntireCall) { 1462183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose C = cast<PathDiagnosticCallPiece>(PD.getActivePath().front()); 1463183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose } else { 1464183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose const Decl *Caller = CE->getLocationContext()->getDecl(); 14659373937945e1e075dfa08169eaccc1ad0b31f699Anna Zaks C = PathDiagnosticCallPiece::construct(PD.getActivePath(), Caller); 1466bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek LCM[&C->path] = CE->getCalleeContext(); 14679373937945e1e075dfa08169eaccc1ad0b31f699Anna Zaks } 1468852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose 1469183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose C->setCallee(*CE, SM); 1470183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose EB.addContext(C->getLocation()); 1471368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks 1472368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks if (!CallStack.empty()) { 147356a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks assert(CallStack.back().first == C); 1474368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks CallStack.pop_back(); 1475368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks } 14762042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek break; 14772042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek } 14784ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek 14794ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek // Note that is important that we update the LocationContext 14804ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek // after looking at CallExits. CallExit basically adds an 14814ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek // edge in the *caller*, so we don't want to update the LocationContext 14824ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek // too soon. 14834ba86bc53bb280ba46a08459eda7d283d513b61fTed Kremenek PDB.LC = N->getLocationContext(); 14845de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek 1485dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek // Block edges. 14867a95de68c093991047ed8d339479ccad51b88663David Blaikie if (Optional<BlockEdge> BE = P.getAs<BlockEdge>()) { 148711abcecc8c919673237cf37384290a1ef1943976Ted Kremenek // Does this represent entering a call? If so, look at propagating 148811abcecc8c919673237cf37384290a1ef1943976Ted Kremenek // interesting symbols across call boundaries. 148911abcecc8c919673237cf37384290a1ef1943976Ted Kremenek if (NextNode) { 149011abcecc8c919673237cf37384290a1ef1943976Ted Kremenek const LocationContext *CallerCtx = NextNode->getLocationContext(); 149111abcecc8c919673237cf37384290a1ef1943976Ted Kremenek const LocationContext *CalleeCtx = PDB.LC; 149211abcecc8c919673237cf37384290a1ef1943976Ted Kremenek if (CallerCtx != CalleeCtx) { 149311abcecc8c919673237cf37384290a1ef1943976Ted Kremenek reversePropagateInterestingSymbols(*PDB.getBugReport(), IE, 1494ef8225444452a1486bd721f3285301fe84643b00Stephen Hines N->getState().get(), 149511abcecc8c919673237cf37384290a1ef1943976Ted Kremenek CalleeCtx, CallerCtx); 149611abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 149711abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 149811abcecc8c919673237cf37384290a1ef1943976Ted Kremenek 1499dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek // Are we jumping to the head of a loop? Add a special diagnostic. 1500f57a2aa02c0578c5bd834fec0d44c16ad9908620Ted Kremenek if (const Stmt *Loop = BE->getSrc()->getLoopTarget()) { 150159950d3aa54ca5066b1fb08a8c79ebfe10e0919bTed Kremenek PathDiagnosticLocation L(Loop, SM, PDB.LC); 15026bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines const CompoundStmt *CS = nullptr; 15031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1504f57a2aa02c0578c5bd834fec0d44c16ad9908620Ted Kremenek if (const ForStmt *FS = dyn_cast<ForStmt>(Loop)) 1505f57a2aa02c0578c5bd834fec0d44c16ad9908620Ted Kremenek CS = dyn_cast<CompoundStmt>(FS->getBody()); 1506f57a2aa02c0578c5bd834fec0d44c16ad9908620Ted Kremenek else if (const WhileStmt *WS = dyn_cast<WhileStmt>(Loop)) 1507f57a2aa02c0578c5bd834fec0d44c16ad9908620Ted Kremenek CS = dyn_cast<CompoundStmt>(WS->getBody()); 15081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1509dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek PathDiagnosticEventPiece *p = 1510dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek new PathDiagnosticEventPiece(L, 151107c015cbcee31f72e2d320ba2c713c046bed42faTed Kremenek "Looping back to the head of the loop"); 15122dd17abf11ae64339fa6bfaa57d76e13a5fbe5b8Ted Kremenek p->setPrunable(true); 15131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1514dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek EB.addEdge(p->getLocation(), true); 15152042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.getActivePath().push_front(p); 15161eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1517ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek if (CS) { 15180cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks PathDiagnosticLocation BL = 15190cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks PathDiagnosticLocation::createEndBrace(CS, SM); 152007c015cbcee31f72e2d320ba2c713c046bed42faTed Kremenek EB.addEdge(BL); 1521dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek } 15228bd4d037d837e7922c3661d6158229da58a03887Ted Kremenek } 15238185674528423e2504a1fae35c28c24104846510Ted Kremenek 1524b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek const CFGBlock *BSrc = BE->getSrc(); 1525b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek ParentMap &PM = PDB.getParentMap(); 1526b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek 1527b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek if (const Stmt *Term = BSrc->getTerminator()) { 15288185674528423e2504a1fae35c28c24104846510Ted Kremenek // Are we jumping past the loop body without ever executing the 15298185674528423e2504a1fae35c28c24104846510Ted Kremenek // loop (because the condition was false)? 15307a95de68c093991047ed8d339479ccad51b88663David Blaikie if (isLoopJumpPastBody(Term, &*BE) && 1531b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek !isInLoopBody(PM, 1532b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek getStmtBeforeCond(PM, 1533b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek BSrc->getTerminatorCondition(), 1534b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek N), 1535b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek Term)) { 15368185674528423e2504a1fae35c28c24104846510Ted Kremenek PathDiagnosticLocation L(Term, SM, PDB.LC); 15378185674528423e2504a1fae35c28c24104846510Ted Kremenek PathDiagnosticEventPiece *PE = 1538b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek new PathDiagnosticEventPiece(L, "Loop body executed 0 times"); 15398185674528423e2504a1fae35c28c24104846510Ted Kremenek PE->setPrunable(true); 15408185674528423e2504a1fae35c28c24104846510Ted Kremenek 15418185674528423e2504a1fae35c28c24104846510Ted Kremenek EB.addEdge(PE->getLocation(), true); 15428185674528423e2504a1fae35c28c24104846510Ted Kremenek PD.getActivePath().push_front(PE); 15438185674528423e2504a1fae35c28c24104846510Ted Kremenek } 15448185674528423e2504a1fae35c28c24104846510Ted Kremenek 1545b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek // In any case, add the terminator as the current statement 1546b04a2387ac23adfa063de03844cb16c0d77fb405Ted Kremenek // context for control edges. 1547ddb7babf448822e0f8da07fdf9446cf515d04ad5Ted Kremenek EB.addContext(Term); 15488185674528423e2504a1fae35c28c24104846510Ted Kremenek } 15491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1550dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek break; 15518bd4d037d837e7922c3661d6158229da58a03887Ted Kremenek } 155214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 15537a95de68c093991047ed8d339479ccad51b88663David Blaikie if (Optional<BlockEntrance> BE = P.getAs<BlockEntrance>()) { 1554b07805485c603be3d8011f72611465324c9e664bDavid Blaikie Optional<CFGElement> First = BE->getFirstElement(); 1555b07805485c603be3d8011f72611465324c9e664bDavid Blaikie if (Optional<CFGStmt> S = First ? First->getAs<CFGStmt>() : None) { 1556b07805485c603be3d8011f72611465324c9e664bDavid Blaikie const Stmt *stmt = S->getStmt(); 15573c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek if (IsControlFlowExpr(stmt)) { 1558b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu // Add the proper context for '&&', '||', and '?'. 15593c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek EB.addContext(stmt); 1560b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu } 1561b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu else 15623c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek EB.addExtendedContext(PDB.getEnclosingStmtLocation(stmt).asStmt()); 1563dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek } 1564b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu 1565dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek break; 1566dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek } 15675de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek 15685de4fdb8de700f95b0b863a9e5a4a508de17a034Ted Kremenek 1569dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek } while (0); 15701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1571dd986cc9989f665370cef0917ba8ba3b4871e3e6Ted Kremenek if (!NextNode) 157214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek continue; 15731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15748e6431adab313e283a992698f6fc7afe62420999Anna Zaks // Add pieces from custom visitors. 15758e6431adab313e283a992698f6fc7afe62420999Anna Zaks BugReport *R = PDB.getBugReport(); 15763bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose for (ArrayRef<BugReporterVisitor *>::iterator I = visitors.begin(), 15773bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose E = visitors.end(); 15783bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose I != E; ++I) { 15798e6431adab313e283a992698f6fc7afe62420999Anna Zaks if (PathDiagnosticPiece *p = (*I)->VisitNode(N, NextNode, PDB, *R)) { 15808966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek const PathDiagnosticLocation &Loc = p->getLocation(); 15818966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek EB.addEdge(Loc, true); 15822042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PD.getActivePath().push_front(p); 1583368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks updateStackPiecesWithMessage(p, CallStack); 1584368a0d565f078666ca5bfb7fe08d04648688e4bcAnna Zaks 15858966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek if (const Stmt *S = Loc.asStmt()) 15861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump EB.addExtendedContext(PDB.getEnclosingStmtLocation(S).asStmt()); 15878966bc1c8ce271c09936c0eaf6c841aef4a0af1bTed Kremenek } 15881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 158914856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek } 15908347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose 15918347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose return PDB.getBugReport()->isValid(); 159214856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek} 159314856d7b7a2be05ae9a0fd5b2073631994c2ba43Ted Kremenek 1594af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek/// \brief Adds a sanitized control-flow diagnostic edge to a path. 1595af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenekstatic void addEdgeToPath(PathPieces &path, 1596af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek PathDiagnosticLocation &PrevLoc, 1597af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek PathDiagnosticLocation NewLoc, 1598af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek const LocationContext *LC) { 1599bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek if (!NewLoc.isValid()) 1600af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek return; 1601af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1602bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek SourceLocation NewLocL = NewLoc.asLocation(); 1603a3f5a5afefca7653349a88472d5ce01ba7226e27Anna Zaks if (NewLocL.isInvalid()) 1604af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek return; 1605af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1606904fd08edbedeb18b16875dd54b3f1edb049e9b9Jordan Rose if (!PrevLoc.isValid() || !PrevLoc.asLocation().isValid()) { 1607af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek PrevLoc = NewLoc; 1608af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek return; 1609af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek } 1610af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1611574c7cf6d0c8e8f8ecda360ae271d5391c404534Jordan Rose // Ignore self-edges, which occur when there are multiple nodes at the same 1612574c7cf6d0c8e8f8ecda360ae271d5391c404534Jordan Rose // statement. 1613574c7cf6d0c8e8f8ecda360ae271d5391c404534Jordan Rose if (NewLoc.asStmt() && NewLoc.asStmt() == PrevLoc.asStmt()) 1614af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek return; 1615af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1616bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek path.push_front(new PathDiagnosticControlFlowPiece(NewLoc, 1617bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek PrevLoc)); 1618af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek PrevLoc = NewLoc; 1619af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek} 1620af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1621e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek/// A customized wrapper for CFGBlock::getTerminatorCondition() 1622e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek/// which returns the element for ObjCForCollectionStmts. 1623e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenekstatic const Stmt *getTerminatorCondition(const CFGBlock *B) { 1624e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek const Stmt *S = B->getTerminatorCondition(); 1625e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek if (const ObjCForCollectionStmt *FS = 1626e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek dyn_cast_or_null<ObjCForCollectionStmt>(S)) 1627e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek return FS->getElement(); 1628e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek return S; 1629e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek} 1630e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek 16310a9350f2411926f4faaeb2ce7d7a9bc1f27751e9Craig Topperstatic const char StrEnteringLoop[] = "Entering loop body"; 16320a9350f2411926f4faaeb2ce7d7a9bc1f27751e9Craig Topperstatic const char StrLoopBodyZero[] = "Loop body executed 0 times"; 163364cc0c37f78719f905029a9099445c214cb40ce3Jordan Rosestatic const char StrLoopRangeEmpty[] = 163464cc0c37f78719f905029a9099445c214cb40ce3Jordan Rose "Loop body skipped when range is empty"; 163564cc0c37f78719f905029a9099445c214cb40ce3Jordan Rosestatic const char StrLoopCollectionEmpty[] = 163664cc0c37f78719f905029a9099445c214cb40ce3Jordan Rose "Loop body skipped when collection is empty"; 1637f94cb007d03031bcf3d1b02f6a683a189e934953Ted Kremenek 1638af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenekstatic bool 1639af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted KremenekGenerateAlternateExtensivePathDiagnostic(PathDiagnostic& PD, 1640af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek PathDiagnosticBuilder &PDB, 1641af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek const ExplodedNode *N, 1642af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek LocationContextMap &LCM, 1643af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek ArrayRef<BugReporterVisitor *> visitors) { 1644af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1645af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek BugReport *report = PDB.getBugReport(); 1646af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek const SourceManager& SM = PDB.getSourceManager(); 1647af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek StackDiagVector CallStack; 1648af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek InterestingExprs IE; 1649af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 16505a6fb20841220488f8be7254fbea8ba7233ebcd3Jordan Rose PathDiagnosticLocation PrevLoc = PD.getLocation(); 1651af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1652af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek const ExplodedNode *NextNode = N->getFirstPred(); 1653af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek while (NextNode) { 1654af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek N = NextNode; 1655af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek NextNode = N->getFirstPred(); 1656af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek ProgramPoint P = N->getLocation(); 1657af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1658af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek do { 1659be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek // Have we encountered an entrance to a call? It may be 1660be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek // the case that we have not encountered a matching 1661be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek // call exit before this point. This means that the path 1662be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek // terminated within the call itself. 1663be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek if (Optional<CallEnter> CE = P.getAs<CallEnter>()) { 1664904fd08edbedeb18b16875dd54b3f1edb049e9b9Jordan Rose // Add an edge to the start of the function. 1665904fd08edbedeb18b16875dd54b3f1edb049e9b9Jordan Rose const StackFrameContext *CalleeLC = CE->getCalleeContext(); 1666904fd08edbedeb18b16875dd54b3f1edb049e9b9Jordan Rose const Decl *D = CalleeLC->getDecl(); 1667904fd08edbedeb18b16875dd54b3f1edb049e9b9Jordan Rose addEdgeToPath(PD.getActivePath(), PrevLoc, 1668904fd08edbedeb18b16875dd54b3f1edb049e9b9Jordan Rose PathDiagnosticLocation::createBegin(D, SM), 1669904fd08edbedeb18b16875dd54b3f1edb049e9b9Jordan Rose CalleeLC); 1670904fd08edbedeb18b16875dd54b3f1edb049e9b9Jordan Rose 1671be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek // Did we visit an entire call? 1672be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek bool VisitedEntireCall = PD.isWithinCall(); 1673be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek PD.popActivePath(); 1674be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek 1675be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek PathDiagnosticCallPiece *C; 1676be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek if (VisitedEntireCall) { 1677ef8225444452a1486bd721f3285301fe84643b00Stephen Hines PathDiagnosticPiece *P = PD.getActivePath().front().get(); 1678be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek C = cast<PathDiagnosticCallPiece>(P); 1679be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek } else { 1680be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek const Decl *Caller = CE->getLocationContext()->getDecl(); 1681be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek C = PathDiagnosticCallPiece::construct(PD.getActivePath(), Caller); 1682be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek 1683be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek // Since we just transferred the path over to the call piece, 1684be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek // reset the mapping from active to location context. 1685be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek assert(PD.getActivePath().size() == 1 && 1686be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek PD.getActivePath().front() == C); 16876bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines LCM[&PD.getActivePath()] = nullptr; 1688be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek 1689be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek // Record the location context mapping for the path within 1690be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek // the call. 16916bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines assert(LCM[&C->path] == nullptr || 1692be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek LCM[&C->path] == CE->getCalleeContext()); 1693be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek LCM[&C->path] = CE->getCalleeContext(); 1694be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek 1695be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek // If this is the first item in the active path, record 1696be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek // the new mapping from active path to location context. 1697be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek const LocationContext *&NewLC = LCM[&PD.getActivePath()]; 16985a6fb20841220488f8be7254fbea8ba7233ebcd3Jordan Rose if (!NewLC) 1699be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek NewLC = N->getLocationContext(); 1700be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek 17015a6fb20841220488f8be7254fbea8ba7233ebcd3Jordan Rose PDB.LC = NewLC; 1702be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek } 1703be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek C->setCallee(*CE, SM); 1704be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek 17055a6fb20841220488f8be7254fbea8ba7233ebcd3Jordan Rose // Update the previous location in the active path. 17065a6fb20841220488f8be7254fbea8ba7233ebcd3Jordan Rose PrevLoc = C->getLocation(); 17075a6fb20841220488f8be7254fbea8ba7233ebcd3Jordan Rose 1708be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek if (!CallStack.empty()) { 1709be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek assert(CallStack.back().first == C); 1710be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek CallStack.pop_back(); 1711be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek } 1712af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek break; 1713af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek } 1714af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1715be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek // Query the location context here and the previous location 1716be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek // as processing CallEnter may change the active path. 1717be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek PDB.LC = N->getLocationContext(); 1718be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek 1719be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek // Record the mapping from the active path to the location 1720be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek // context. 1721be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek assert(!LCM[&PD.getActivePath()] || 1722be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek LCM[&PD.getActivePath()] == PDB.LC); 1723be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek LCM[&PD.getActivePath()] = PDB.LC; 1724be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek 1725af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek // Have we encountered an exit from a function call? 1726af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek if (Optional<CallExitEnd> CE = P.getAs<CallExitEnd>()) { 1727af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek const Stmt *S = CE->getCalleeContext()->getCallSite(); 1728af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek // Propagate the interesting symbols accordingly. 1729af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek if (const Expr *Ex = dyn_cast_or_null<Expr>(S)) { 1730af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek reversePropagateIntererstingSymbols(*PDB.getBugReport(), IE, 1731ef8225444452a1486bd721f3285301fe84643b00Stephen Hines N->getState().get(), Ex, 1732af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek N->getLocationContext()); 1733af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek } 1734af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1735af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek // We are descending into a call (backwards). Construct 1736af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek // a new call piece to contain the path pieces for that call. 1737af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek PathDiagnosticCallPiece *C = 1738af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek PathDiagnosticCallPiece::construct(N, *CE, SM); 1739af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1740af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek // Record the location context for this call piece. 1741bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek LCM[&C->path] = CE->getCalleeContext(); 1742af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1743af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek // Add the edge to the return site. 1744be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek addEdgeToPath(PD.getActivePath(), PrevLoc, C->callReturn, PDB.LC); 1745be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek PD.getActivePath().push_front(C); 17465a6fb20841220488f8be7254fbea8ba7233ebcd3Jordan Rose PrevLoc.invalidate(); 1747af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1748af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek // Make the contents of the call the active path for now. 1749af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek PD.pushActivePath(&C->path); 1750af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek CallStack.push_back(StackDiagPair(C, N)); 1751af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek break; 1752af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek } 1753af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1754be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek if (Optional<PostStmt> PS = P.getAs<PostStmt>()) { 1755be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek // For expressions, make sure we propagate the 1756be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek // interesting symbols correctly. 1757be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek if (const Expr *Ex = PS->getStmtAs<Expr>()) 1758be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek reversePropagateIntererstingSymbols(*PDB.getBugReport(), IE, 1759ef8225444452a1486bd721f3285301fe84643b00Stephen Hines N->getState().get(), Ex, 1760be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek N->getLocationContext()); 1761af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1762e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek // Add an edge. If this is an ObjCForCollectionStmt do 1763e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek // not add an edge here as it appears in the CFG both 1764e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek // as a terminator and as a terminator condition. 1765e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek if (!isa<ObjCForCollectionStmt>(PS->getStmt())) { 1766e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek PathDiagnosticLocation L = 1767e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek PathDiagnosticLocation(PS->getStmt(), SM, PDB.LC); 1768e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek addEdgeToPath(PD.getActivePath(), PrevLoc, L, PDB.LC); 1769e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek } 1770af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek break; 1771af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek } 1772af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1773af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek // Block edges. 1774af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek if (Optional<BlockEdge> BE = P.getAs<BlockEdge>()) { 1775af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek // Does this represent entering a call? If so, look at propagating 1776af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek // interesting symbols across call boundaries. 1777af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek if (NextNode) { 1778af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek const LocationContext *CallerCtx = NextNode->getLocationContext(); 1779af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek const LocationContext *CalleeCtx = PDB.LC; 1780af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek if (CallerCtx != CalleeCtx) { 1781af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek reversePropagateInterestingSymbols(*PDB.getBugReport(), IE, 1782ef8225444452a1486bd721f3285301fe84643b00Stephen Hines N->getState().get(), 1783af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek CalleeCtx, CallerCtx); 1784af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek } 1785af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek } 1786af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1787af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek // Are we jumping to the head of a loop? Add a special diagnostic. 1788af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek if (const Stmt *Loop = BE->getSrc()->getLoopTarget()) { 1789af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek PathDiagnosticLocation L(Loop, SM, PDB.LC); 17906bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines const Stmt *Body = nullptr; 1791afde200cdae9731aa5826c6178eae9e7fef74475Ted Kremenek 1792afde200cdae9731aa5826c6178eae9e7fef74475Ted Kremenek if (const ForStmt *FS = dyn_cast<ForStmt>(Loop)) 179349a246f4fad959888bb0164c624c3c2b03078e91Jordan Rose Body = FS->getBody(); 1794afde200cdae9731aa5826c6178eae9e7fef74475Ted Kremenek else if (const WhileStmt *WS = dyn_cast<WhileStmt>(Loop)) 179549a246f4fad959888bb0164c624c3c2b03078e91Jordan Rose Body = WS->getBody(); 1796e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek else if (const ObjCForCollectionStmt *OFS = 179749a246f4fad959888bb0164c624c3c2b03078e91Jordan Rose dyn_cast<ObjCForCollectionStmt>(Loop)) { 179849a246f4fad959888bb0164c624c3c2b03078e91Jordan Rose Body = OFS->getBody(); 179949a246f4fad959888bb0164c624c3c2b03078e91Jordan Rose } else if (const CXXForRangeStmt *FRS = 180049a246f4fad959888bb0164c624c3c2b03078e91Jordan Rose dyn_cast<CXXForRangeStmt>(Loop)) { 180149a246f4fad959888bb0164c624c3c2b03078e91Jordan Rose Body = FRS->getBody(); 1802e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek } 180349a246f4fad959888bb0164c624c3c2b03078e91Jordan Rose // do-while statements are explicitly excluded here 1804af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1805af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek PathDiagnosticEventPiece *p = 1806af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek new PathDiagnosticEventPiece(L, "Looping back to the head " 1807af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek "of the loop"); 1808af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek p->setPrunable(true); 1809af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1810be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek addEdgeToPath(PD.getActivePath(), PrevLoc, p->getLocation(), PDB.LC); 1811cd389d8cc9abeffb1416b70dd58148e66e5d822bTed Kremenek PD.getActivePath().push_front(p); 1812afde200cdae9731aa5826c6178eae9e7fef74475Ted Kremenek 181349a246f4fad959888bb0164c624c3c2b03078e91Jordan Rose if (const CompoundStmt *CS = dyn_cast_or_null<CompoundStmt>(Body)) { 1814afde200cdae9731aa5826c6178eae9e7fef74475Ted Kremenek addEdgeToPath(PD.getActivePath(), PrevLoc, 1815afde200cdae9731aa5826c6178eae9e7fef74475Ted Kremenek PathDiagnosticLocation::createEndBrace(CS, SM), 1816afde200cdae9731aa5826c6178eae9e7fef74475Ted Kremenek PDB.LC); 1817afde200cdae9731aa5826c6178eae9e7fef74475Ted Kremenek } 1818af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek } 1819b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek 1820af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek const CFGBlock *BSrc = BE->getSrc(); 1821af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek ParentMap &PM = PDB.getParentMap(); 1822af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1823af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek if (const Stmt *Term = BSrc->getTerminator()) { 1824af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek // Are we jumping past the loop body without ever executing the 1825af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek // loop (because the condition was false)? 1826b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek if (isLoop(Term)) { 1827e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek const Stmt *TermCond = getTerminatorCondition(BSrc); 1828b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek bool IsInLoopBody = 1829b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek isInLoopBody(PM, getStmtBeforeCond(PM, TermCond, N), Term); 1830b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek 18316bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines const char *str = nullptr; 1832b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek 1833b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek if (isJumpToFalseBranch(&*BE)) { 1834b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek if (!IsInLoopBody) { 183564cc0c37f78719f905029a9099445c214cb40ce3Jordan Rose if (isa<ObjCForCollectionStmt>(Term)) { 183664cc0c37f78719f905029a9099445c214cb40ce3Jordan Rose str = StrLoopCollectionEmpty; 183764cc0c37f78719f905029a9099445c214cb40ce3Jordan Rose } else if (isa<CXXForRangeStmt>(Term)) { 183864cc0c37f78719f905029a9099445c214cb40ce3Jordan Rose str = StrLoopRangeEmpty; 183964cc0c37f78719f905029a9099445c214cb40ce3Jordan Rose } else { 184064cc0c37f78719f905029a9099445c214cb40ce3Jordan Rose str = StrLoopBodyZero; 184164cc0c37f78719f905029a9099445c214cb40ce3Jordan Rose } 1842b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek } 18430a9350f2411926f4faaeb2ce7d7a9bc1f27751e9Craig Topper } else { 1844f94cb007d03031bcf3d1b02f6a683a189e934953Ted Kremenek str = StrEnteringLoop; 1845b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek } 1846b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek 1847b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek if (str) { 18483e8a85fcfc3d264e4c5b21fbdd741bbc0c24a266Jordan Rose PathDiagnosticLocation L(TermCond ? TermCond : Term, SM, PDB.LC); 1849b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek PathDiagnosticEventPiece *PE = 1850b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek new PathDiagnosticEventPiece(L, str); 1851b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek PE->setPrunable(true); 1852b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek addEdgeToPath(PD.getActivePath(), PrevLoc, 1853be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek PE->getLocation(), PDB.LC); 1854b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek PD.getActivePath().push_front(PE); 1855b097a57f58672a825c99fdfb668b04e921e363b9Ted Kremenek } 18560a9350f2411926f4faaeb2ce7d7a9bc1f27751e9Craig Topper } else if (isa<BreakStmt>(Term) || isa<ContinueStmt>(Term) || 18570a9350f2411926f4faaeb2ce7d7a9bc1f27751e9Craig Topper isa<GotoStmt>(Term)) { 1858bc0fd8129626ff4e485388311b081e76d0f96795Ted Kremenek PathDiagnosticLocation L(Term, SM, PDB.LC); 1859be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek addEdgeToPath(PD.getActivePath(), PrevLoc, L, PDB.LC); 1860bc0fd8129626ff4e485388311b081e76d0f96795Ted Kremenek } 1861af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek } 1862af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek break; 1863af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek } 1864af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek } while (0); 1865af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1866af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek if (!NextNode) 1867af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek continue; 1868af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1869af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek // Add pieces from custom visitors. 1870af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek for (ArrayRef<BugReporterVisitor *>::iterator I = visitors.begin(), 1871af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek E = visitors.end(); 1872af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek I != E; ++I) { 1873cd389d8cc9abeffb1416b70dd58148e66e5d822bTed Kremenek if (PathDiagnosticPiece *p = (*I)->VisitNode(N, NextNode, PDB, *report)) { 1874be0b207c4916f823497d31cbf5083efb4e374163Ted Kremenek addEdgeToPath(PD.getActivePath(), PrevLoc, p->getLocation(), PDB.LC); 1875cd389d8cc9abeffb1416b70dd58148e66e5d822bTed Kremenek PD.getActivePath().push_front(p); 1876af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek updateStackPiecesWithMessage(p, CallStack); 1877af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek } 1878af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek } 1879af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek } 1880af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 188101f1ff79f70b3e042995a43b29ccbf0fffc77d5fJordan Rose // Add an edge to the start of the function. 188201f1ff79f70b3e042995a43b29ccbf0fffc77d5fJordan Rose // We'll prune it out later, but it helps make diagnostics more uniform. 188301f1ff79f70b3e042995a43b29ccbf0fffc77d5fJordan Rose const StackFrameContext *CalleeLC = PDB.LC->getCurrentStackFrame(); 188401f1ff79f70b3e042995a43b29ccbf0fffc77d5fJordan Rose const Decl *D = CalleeLC->getDecl(); 188501f1ff79f70b3e042995a43b29ccbf0fffc77d5fJordan Rose addEdgeToPath(PD.getActivePath(), PrevLoc, 188601f1ff79f70b3e042995a43b29ccbf0fffc77d5fJordan Rose PathDiagnosticLocation::createBegin(D, SM), 188701f1ff79f70b3e042995a43b29ccbf0fffc77d5fJordan Rose CalleeLC); 188801f1ff79f70b3e042995a43b29ccbf0fffc77d5fJordan Rose 1889af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek return report->isValid(); 1890af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek} 1891af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 1892b1a4d37c0549501fe12907bc6ffa81bc5d04b98aBenjamin Kramerstatic const Stmt *getLocStmt(PathDiagnosticLocation L) { 1893bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek if (!L.isValid()) 18946bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 1895f468fa16e37fc8fa6a915fe36aee8f0434709789Ted Kremenek return L.asStmt(); 1896f468fa16e37fc8fa6a915fe36aee8f0434709789Ted Kremenek} 1897f468fa16e37fc8fa6a915fe36aee8f0434709789Ted Kremenek 189896f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rosestatic const Stmt *getStmtParent(const Stmt *S, const ParentMap &PM) { 1899bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek if (!S) 19006bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 1901a40983460cc3f8f583cd968ac2e4647dc30c83f5Ted Kremenek 1902a40983460cc3f8f583cd968ac2e4647dc30c83f5Ted Kremenek while (true) { 1903a40983460cc3f8f583cd968ac2e4647dc30c83f5Ted Kremenek S = PM.getParentIgnoreParens(S); 1904a40983460cc3f8f583cd968ac2e4647dc30c83f5Ted Kremenek 1905a40983460cc3f8f583cd968ac2e4647dc30c83f5Ted Kremenek if (!S) 1906a40983460cc3f8f583cd968ac2e4647dc30c83f5Ted Kremenek break; 1907a40983460cc3f8f583cd968ac2e4647dc30c83f5Ted Kremenek 1908a327bb12b1cd0c142eb06e30b4f6018b96d5babfTed Kremenek if (isa<ExprWithCleanups>(S) || 1909a327bb12b1cd0c142eb06e30b4f6018b96d5babfTed Kremenek isa<CXXBindTemporaryExpr>(S) || 1910a327bb12b1cd0c142eb06e30b4f6018b96d5babfTed Kremenek isa<SubstNonTypeTemplateParmExpr>(S)) 1911a40983460cc3f8f583cd968ac2e4647dc30c83f5Ted Kremenek continue; 1912a40983460cc3f8f583cd968ac2e4647dc30c83f5Ted Kremenek 1913a40983460cc3f8f583cd968ac2e4647dc30c83f5Ted Kremenek break; 1914a40983460cc3f8f583cd968ac2e4647dc30c83f5Ted Kremenek } 1915a40983460cc3f8f583cd968ac2e4647dc30c83f5Ted Kremenek 1916a40983460cc3f8f583cd968ac2e4647dc30c83f5Ted Kremenek return S; 1917bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek} 1918bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek 191915676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenekstatic bool isConditionForTerminator(const Stmt *S, const Stmt *Cond) { 192015676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek switch (S->getStmtClass()) { 192103194fb1bbf2b2d17ff7e3d61ddb9d73e9297fdcTed Kremenek case Stmt::BinaryOperatorClass: { 192203194fb1bbf2b2d17ff7e3d61ddb9d73e9297fdcTed Kremenek const BinaryOperator *BO = cast<BinaryOperator>(S); 192303194fb1bbf2b2d17ff7e3d61ddb9d73e9297fdcTed Kremenek if (!BO->isLogicalOp()) 192403194fb1bbf2b2d17ff7e3d61ddb9d73e9297fdcTed Kremenek return false; 192503194fb1bbf2b2d17ff7e3d61ddb9d73e9297fdcTed Kremenek return BO->getLHS() == Cond || BO->getRHS() == Cond; 192603194fb1bbf2b2d17ff7e3d61ddb9d73e9297fdcTed Kremenek } 1927a399f776ee29e099da33eaf7f9d585b4edc4b61dTed Kremenek case Stmt::IfStmtClass: 1928a399f776ee29e099da33eaf7f9d585b4edc4b61dTed Kremenek return cast<IfStmt>(S)->getCond() == Cond; 192915676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek case Stmt::ForStmtClass: 193015676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek return cast<ForStmt>(S)->getCond() == Cond; 193115676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek case Stmt::WhileStmtClass: 193215676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek return cast<WhileStmt>(S)->getCond() == Cond; 193315676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek case Stmt::DoStmtClass: 193415676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek return cast<DoStmt>(S)->getCond() == Cond; 193515676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek case Stmt::ChooseExprClass: 193615676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek return cast<ChooseExpr>(S)->getCond() == Cond; 193715676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek case Stmt::IndirectGotoStmtClass: 193815676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek return cast<IndirectGotoStmt>(S)->getTarget() == Cond; 193915676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek case Stmt::SwitchStmtClass: 194015676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek return cast<SwitchStmt>(S)->getCond() == Cond; 194115676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek case Stmt::BinaryConditionalOperatorClass: 194215676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek return cast<BinaryConditionalOperator>(S)->getCond() == Cond; 19438484b37a2b7720c016d27a672343b1c67bd2e731Ted Kremenek case Stmt::ConditionalOperatorClass: { 19448484b37a2b7720c016d27a672343b1c67bd2e731Ted Kremenek const ConditionalOperator *CO = cast<ConditionalOperator>(S); 19458484b37a2b7720c016d27a672343b1c67bd2e731Ted Kremenek return CO->getCond() == Cond || 19468484b37a2b7720c016d27a672343b1c67bd2e731Ted Kremenek CO->getLHS() == Cond || 19478484b37a2b7720c016d27a672343b1c67bd2e731Ted Kremenek CO->getRHS() == Cond; 19488484b37a2b7720c016d27a672343b1c67bd2e731Ted Kremenek } 194915676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek case Stmt::ObjCForCollectionStmtClass: 195015676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek return cast<ObjCForCollectionStmt>(S)->getElement() == Cond; 195149a246f4fad959888bb0164c624c3c2b03078e91Jordan Rose case Stmt::CXXForRangeStmtClass: { 195249a246f4fad959888bb0164c624c3c2b03078e91Jordan Rose const CXXForRangeStmt *FRS = cast<CXXForRangeStmt>(S); 195349a246f4fad959888bb0164c624c3c2b03078e91Jordan Rose return FRS->getCond() == Cond || FRS->getRangeInit() == Cond; 195449a246f4fad959888bb0164c624c3c2b03078e91Jordan Rose } 195515676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek default: 195615676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek return false; 195715676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek } 195815676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek} 195915676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek 196096b8134337883908fcc45484486fe200d6b3e32fTed Kremenekstatic bool isIncrementOrInitInForLoop(const Stmt *S, const Stmt *FL) { 196149a246f4fad959888bb0164c624c3c2b03078e91Jordan Rose if (const ForStmt *FS = dyn_cast<ForStmt>(FL)) 196249a246f4fad959888bb0164c624c3c2b03078e91Jordan Rose return FS->getInc() == S || FS->getInit() == S; 196349a246f4fad959888bb0164c624c3c2b03078e91Jordan Rose if (const CXXForRangeStmt *FRS = dyn_cast<CXXForRangeStmt>(FL)) 196449a246f4fad959888bb0164c624c3c2b03078e91Jordan Rose return FRS->getInc() == S || FRS->getRangeStmt() == S || 196549a246f4fad959888bb0164c624c3c2b03078e91Jordan Rose FRS->getLoopVarStmt() || FRS->getRangeInit() == S; 196649a246f4fad959888bb0164c624c3c2b03078e91Jordan Rose return false; 1967e2f7337958f21802e98777f441fe20ef7ba2adffTed Kremenek} 1968e2f7337958f21802e98777f441fe20ef7ba2adffTed Kremenek 196915676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenektypedef llvm::DenseSet<const PathDiagnosticCallPiece *> 197015676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek OptimizedCallsSet; 197115676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek 197296f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose/// Adds synthetic edges from top-level statements to their subexpressions. 197396f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose/// 197496f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose/// This avoids a "swoosh" effect, where an edge from a top-level statement A 197596f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose/// points to a sub-expression B.1 that's not at the start of B. In these cases, 197696f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose/// we'd like to see an edge from A to B, then another one from B to B.1. 197796f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rosestatic void addContextEdges(PathPieces &pieces, SourceManager &SM, 197896f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose const ParentMap &PM, const LocationContext *LCtx) { 197996f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose PathPieces::iterator Prev = pieces.end(); 198096f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose for (PathPieces::iterator I = pieces.begin(), E = Prev; I != E; 198196f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose Prev = I, ++I) { 198296f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose PathDiagnosticControlFlowPiece *Piece = 198396f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose dyn_cast<PathDiagnosticControlFlowPiece>(*I); 198496f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose 198596f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose if (!Piece) 198696f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose continue; 198796f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose 198896f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose PathDiagnosticLocation SrcLoc = Piece->getStartLocation(); 19899d9b494aa36ceeb823c48acf04d2d7677174be88Jordan Rose SmallVector<PathDiagnosticLocation, 4> SrcContexts; 19909d9b494aa36ceeb823c48acf04d2d7677174be88Jordan Rose 199149a246f4fad959888bb0164c624c3c2b03078e91Jordan Rose PathDiagnosticLocation NextSrcContext = SrcLoc; 19926bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines const Stmt *InnerStmt = nullptr; 19939d9b494aa36ceeb823c48acf04d2d7677174be88Jordan Rose while (NextSrcContext.isValid() && NextSrcContext.asStmt() != InnerStmt) { 19949d9b494aa36ceeb823c48acf04d2d7677174be88Jordan Rose SrcContexts.push_back(NextSrcContext); 19959d9b494aa36ceeb823c48acf04d2d7677174be88Jordan Rose InnerStmt = NextSrcContext.asStmt(); 199649a246f4fad959888bb0164c624c3c2b03078e91Jordan Rose NextSrcContext = getEnclosingStmtLocation(InnerStmt, SM, PM, LCtx, 199749a246f4fad959888bb0164c624c3c2b03078e91Jordan Rose /*allowNested=*/true); 19989d9b494aa36ceeb823c48acf04d2d7677174be88Jordan Rose } 199996f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose 200096f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose // Repeatedly split the edge as necessary. 200196f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose // This is important for nested logical expressions (||, &&, ?:) where we 200296f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose // want to show all the levels of context. 200396f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose while (true) { 200496f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose const Stmt *Dst = getLocStmt(Piece->getEndLocation()); 200596f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose 200696f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose // We are looking at an edge. Is the destination within a larger 200796f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose // expression? 200896f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose PathDiagnosticLocation DstContext = 20099d9b494aa36ceeb823c48acf04d2d7677174be88Jordan Rose getEnclosingStmtLocation(Dst, SM, PM, LCtx, /*allowNested=*/true); 201096f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose if (!DstContext.isValid() || DstContext.asStmt() == Dst) 201196f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose break; 201296f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose 201396f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose // If the source is in the same context, we're already good. 20149d9b494aa36ceeb823c48acf04d2d7677174be88Jordan Rose if (std::find(SrcContexts.begin(), SrcContexts.end(), DstContext) != 20159d9b494aa36ceeb823c48acf04d2d7677174be88Jordan Rose SrcContexts.end()) 201696f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose break; 201796f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose 201896f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose // Update the subexpression node to point to the context edge. 201996f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose Piece->setStartLocation(DstContext); 202096f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose 202196f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose // Try to extend the previous edge if it's at the same level as the source 202296f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose // context. 202396f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose if (Prev != E) { 202496f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose PathDiagnosticControlFlowPiece *PrevPiece = 202596f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose dyn_cast<PathDiagnosticControlFlowPiece>(*Prev); 202696f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose 202796f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose if (PrevPiece) { 202896f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose if (const Stmt *PrevSrc = getLocStmt(PrevPiece->getStartLocation())) { 202996f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose const Stmt *PrevSrcParent = getStmtParent(PrevSrc, PM); 203096f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose if (PrevSrcParent == getStmtParent(getLocStmt(DstContext), PM)) { 203196f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose PrevPiece->setEndLocation(DstContext); 203296f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose break; 203396f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose } 203496f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose } 203596f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose } 203696f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose } 203796f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose 203896f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose // Otherwise, split the current edge into a context edge and a 203996f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose // subexpression edge. Note that the context statement may itself have 204096f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose // context. 204196f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose Piece = new PathDiagnosticControlFlowPiece(SrcLoc, DstContext); 204296f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose I = pieces.insert(I, Piece); 204396f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose } 204496f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose } 204596f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose} 204696f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose 204796f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose/// \brief Move edges from a branch condition to a branch target 204896f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose/// when the condition is simple. 204996f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose/// 205096f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose/// This restructures some of the work of addContextEdges. That function 205196f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose/// creates edges this may destroy, but they work together to create a more 205296f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose/// aesthetically set of edges around branches. After the call to 205396f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose/// addContextEdges, we may have (1) an edge to the branch, (2) an edge from 205496f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose/// the branch to the branch condition, and (3) an edge from the branch 205596f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose/// condition to the branch target. We keep (1), but may wish to remove (2) 205696f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose/// and move the source of (3) to the branch if the branch condition is simple. 205796f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose/// 205896f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rosestatic void simplifySimpleBranches(PathPieces &pieces) { 205996f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose for (PathPieces::iterator I = pieces.begin(), E = pieces.end(); I != E; ++I) { 206096f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose 206196f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose PathDiagnosticControlFlowPiece *PieceI = 206296f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose dyn_cast<PathDiagnosticControlFlowPiece>(*I); 206396f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose 206496f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose if (!PieceI) 206596f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose continue; 206696f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose 206796f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose const Stmt *s1Start = getLocStmt(PieceI->getStartLocation()); 206896f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose const Stmt *s1End = getLocStmt(PieceI->getEndLocation()); 206996f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose 207096f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose if (!s1Start || !s1End) 207196f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose continue; 207296f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose 207396f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose PathPieces::iterator NextI = I; ++NextI; 207496f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose if (NextI == E) 207596f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose break; 207696f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose 20776bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines PathDiagnosticControlFlowPiece *PieceNextI = nullptr; 207896f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose 207996f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose while (true) { 208096f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose if (NextI == E) 208196f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose break; 208296f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose 208396f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose PathDiagnosticEventPiece *EV = dyn_cast<PathDiagnosticEventPiece>(*NextI); 208496f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose if (EV) { 208596f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose StringRef S = EV->getString(); 208664cc0c37f78719f905029a9099445c214cb40ce3Jordan Rose if (S == StrEnteringLoop || S == StrLoopBodyZero || 208764cc0c37f78719f905029a9099445c214cb40ce3Jordan Rose S == StrLoopCollectionEmpty || S == StrLoopRangeEmpty) { 208896f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose ++NextI; 208996f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose continue; 209096f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose } 209196f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose break; 209296f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose } 209396f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose 209496f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose PieceNextI = dyn_cast<PathDiagnosticControlFlowPiece>(*NextI); 209596f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose break; 209696f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose } 209796f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose 209896f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose if (!PieceNextI) 209996f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose continue; 210096f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose 210196f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose const Stmt *s2Start = getLocStmt(PieceNextI->getStartLocation()); 210296f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose const Stmt *s2End = getLocStmt(PieceNextI->getEndLocation()); 210396f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose 210496f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose if (!s2Start || !s2End || s1End != s2Start) 210596f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose continue; 210696f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose 210796f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose // We only perform this transformation for specific branch kinds. 210896f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose // We don't want to do this for do..while, for example. 210996f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose if (!(isa<ForStmt>(s1Start) || isa<WhileStmt>(s1Start) || 211049a246f4fad959888bb0164c624c3c2b03078e91Jordan Rose isa<IfStmt>(s1Start) || isa<ObjCForCollectionStmt>(s1Start) || 211149a246f4fad959888bb0164c624c3c2b03078e91Jordan Rose isa<CXXForRangeStmt>(s1Start))) 211296f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose continue; 211396f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose 211496f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose // Is s1End the branch condition? 211596f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose if (!isConditionForTerminator(s1Start, s1End)) 211696f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose continue; 211796f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose 211896f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose // Perform the hoisting by eliminating (2) and changing the start 211996f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose // location of (3). 212096f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose PieceNextI->setStartLocation(PieceI->getStartLocation()); 212196f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose I = pieces.erase(I); 212296f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose } 212396f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose} 212496f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose 2125e624524705ab660eb8d1feb9870ef2989fb2bdf4Jordan Rose/// Returns the number of bytes in the given (character-based) SourceRange. 212622b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose/// 212722b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose/// If the locations in the range are not on the same line, returns None. 212822b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose/// 212922b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose/// Note that this does not do a precise user-visible character or column count. 213022b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rosestatic Optional<size_t> getLengthOnSingleLine(SourceManager &SM, 213122b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose SourceRange Range) { 213222b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose SourceRange ExpansionRange(SM.getExpansionLoc(Range.getBegin()), 213322b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose SM.getExpansionRange(Range.getEnd()).second); 213422b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose 213522b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose FileID FID = SM.getFileID(ExpansionRange.getBegin()); 213622b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose if (FID != SM.getFileID(ExpansionRange.getEnd())) 213722b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose return None; 213822b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose 213922b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose bool Invalid; 214022b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose const llvm::MemoryBuffer *Buffer = SM.getBuffer(FID, &Invalid); 214122b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose if (Invalid) 214222b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose return None; 214322b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose 214422b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose unsigned BeginOffset = SM.getFileOffset(ExpansionRange.getBegin()); 214522b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose unsigned EndOffset = SM.getFileOffset(ExpansionRange.getEnd()); 214622b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose StringRef Snippet = Buffer->getBuffer().slice(BeginOffset, EndOffset); 214722b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose 214822b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose // We're searching the raw bytes of the buffer here, which might include 214922b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose // escaped newlines and such. That's okay; we're trying to decide whether the 215022b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose // SourceRange is covering a large or small amount of space in the user's 215122b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose // editor. 215222b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose if (Snippet.find_first_of("\r\n") != StringRef::npos) 215322b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose return None; 215422b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose 215522b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose // This isn't Unicode-aware, but it doesn't need to be. 215622b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose return Snippet.size(); 215722b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose} 215822b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose 215922b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose/// \sa getLengthOnSingleLine(SourceManager, SourceRange) 216022b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rosestatic Optional<size_t> getLengthOnSingleLine(SourceManager &SM, 216122b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose const Stmt *S) { 216222b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose return getLengthOnSingleLine(SM, S->getSourceRange()); 216322b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose} 216422b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose 216522b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose/// Eliminate two-edge cycles created by addContextEdges(). 216622b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose/// 216722b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose/// Once all the context edges are in place, there are plenty of cases where 216822b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose/// there's a single edge from a top-level statement to a subexpression, 216922b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose/// followed by a single path note, and then a reverse edge to get back out to 217022b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose/// the top level. If the statement is simple enough, the subexpression edges 217122b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose/// just add noise and make it harder to understand what's going on. 217222b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose/// 217322b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose/// This function only removes edges in pairs, because removing only one edge 217422b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose/// might leave other edges dangling. 217522b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose/// 217622b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose/// This will not remove edges in more complicated situations: 217722b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose/// - if there is more than one "hop" leading to or from a subexpression. 217822b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose/// - if there is an inlined call between the edges instead of a single event. 217922b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose/// - if the whole statement is large enough that having subexpression arrows 218022b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose/// might be helpful. 218122b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rosestatic void removeContextCycles(PathPieces &Path, SourceManager &SM, 218222b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose ParentMap &PM) { 21833b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose for (PathPieces::iterator I = Path.begin(), E = Path.end(); I != E; ) { 21843b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose // Pattern match the current piece and its successor. 21853b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose PathDiagnosticControlFlowPiece *PieceI = 21863b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose dyn_cast<PathDiagnosticControlFlowPiece>(*I); 21873b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose 21883b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose if (!PieceI) { 21893b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose ++I; 21903b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose continue; 21913b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose } 21923b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose 21933b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose const Stmt *s1Start = getLocStmt(PieceI->getStartLocation()); 21943b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose const Stmt *s1End = getLocStmt(PieceI->getEndLocation()); 21953b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose 21963b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose PathPieces::iterator NextI = I; ++NextI; 21973b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose if (NextI == E) 21983b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose break; 21993b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose 22003b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose PathDiagnosticControlFlowPiece *PieceNextI = 22013b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose dyn_cast<PathDiagnosticControlFlowPiece>(*NextI); 22023b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose 22033b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose if (!PieceNextI) { 22043b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose if (isa<PathDiagnosticEventPiece>(*NextI)) { 22053b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose ++NextI; 22063b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose if (NextI == E) 22073b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose break; 22083b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose PieceNextI = dyn_cast<PathDiagnosticControlFlowPiece>(*NextI); 22093b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose } 22103b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose 22113b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose if (!PieceNextI) { 22123b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose ++I; 22133b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose continue; 22143b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose } 22153b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose } 22163b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose 22173b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose const Stmt *s2Start = getLocStmt(PieceNextI->getStartLocation()); 22183b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose const Stmt *s2End = getLocStmt(PieceNextI->getEndLocation()); 22193b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose 22203b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose if (s1Start && s2Start && s1Start == s2End && s2Start == s1End) { 222122b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose const size_t MAX_SHORT_LINE_LENGTH = 80; 222222b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose Optional<size_t> s1Length = getLengthOnSingleLine(SM, s1Start); 222322b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose if (s1Length && *s1Length <= MAX_SHORT_LINE_LENGTH) { 222422b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose Optional<size_t> s2Length = getLengthOnSingleLine(SM, s2Start); 222522b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose if (s2Length && *s2Length <= MAX_SHORT_LINE_LENGTH) { 222622b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose Path.erase(I); 222722b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose I = Path.erase(NextI); 222822b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose continue; 222922b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose } 223022b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose } 22313b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose } 22323b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose 22333b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose ++I; 22343b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose } 22353b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose} 22363b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose 223752f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek/// \brief Return true if X is contained by Y. 223852f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenekstatic bool lexicalContains(ParentMap &PM, 223952f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek const Stmt *X, 224052f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek const Stmt *Y) { 224152f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek while (X) { 224252f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek if (X == Y) 224352f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek return true; 224452f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek X = PM.getParent(X); 224552f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek } 224652f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek return false; 224752f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek} 224852f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek 2249de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek// Remove short edges on the same line less than 3 columns in difference. 2250de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenekstatic void removePunyEdges(PathPieces &path, 2251de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek SourceManager &SM, 2252de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek ParentMap &PM) { 2253de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek 2254de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek bool erased = false; 2255de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek 2256de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek for (PathPieces::iterator I = path.begin(), E = path.end(); I != E; 2257de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek erased ? I : ++I) { 2258de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek 2259de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek erased = false; 2260de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek 2261de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek PathDiagnosticControlFlowPiece *PieceI = 2262de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek dyn_cast<PathDiagnosticControlFlowPiece>(*I); 2263de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek 2264de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek if (!PieceI) 2265de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek continue; 2266de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek 2267de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek const Stmt *start = getLocStmt(PieceI->getStartLocation()); 2268de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek const Stmt *end = getLocStmt(PieceI->getEndLocation()); 2269de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek 2270de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek if (!start || !end) 2271de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek continue; 2272de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek 2273de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek const Stmt *endParent = PM.getParent(end); 2274de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek if (!endParent) 2275de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek continue; 2276de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek 2277de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek if (isConditionForTerminator(end, endParent)) 2278de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek continue; 2279de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek 228022b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose SourceLocation FirstLoc = start->getLocStart(); 228122b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose SourceLocation SecondLoc = end->getLocStart(); 2282de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek 228324146975f1af8c1b4b14e8545f218129d0e7dfebEli Friedman if (!SM.isWrittenInSameFile(FirstLoc, SecondLoc)) 2284de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek continue; 228522b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose if (SM.isBeforeInTranslationUnit(SecondLoc, FirstLoc)) 228622b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose std::swap(SecondLoc, FirstLoc); 2287de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek 228822b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose SourceRange EdgeRange(FirstLoc, SecondLoc); 228922b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose Optional<size_t> ByteWidth = getLengthOnSingleLine(SM, EdgeRange); 2290de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek 229122b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose // If the statements are on different lines, continue. 229222b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose if (!ByteWidth) 2293de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek continue; 2294de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek 229522b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose const size_t MAX_PUNY_EDGE_LENGTH = 2; 229622b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose if (*ByteWidth <= MAX_PUNY_EDGE_LENGTH) { 229722b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose // FIXME: There are enough /bytes/ between the endpoints of the edge, but 229822b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose // there might not be enough /columns/. A proper user-visible column count 229922b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose // is probably too expensive, though. 2300a705980a7c3315b7c72d99ce675342ad91b50642Ted Kremenek I = path.erase(I); 2301de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek erased = true; 2302de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek continue; 2303de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek } 2304de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek } 2305de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek} 2306de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek 23071d85a9e8fb4e6ac513467b5fa825bd53e6fcba56Ted Kremenekstatic void removeIdenticalEvents(PathPieces &path) { 23081d85a9e8fb4e6ac513467b5fa825bd53e6fcba56Ted Kremenek for (PathPieces::iterator I = path.begin(), E = path.end(); I != E; ++I) { 23091d85a9e8fb4e6ac513467b5fa825bd53e6fcba56Ted Kremenek PathDiagnosticEventPiece *PieceI = 23101d85a9e8fb4e6ac513467b5fa825bd53e6fcba56Ted Kremenek dyn_cast<PathDiagnosticEventPiece>(*I); 23111d85a9e8fb4e6ac513467b5fa825bd53e6fcba56Ted Kremenek 23121d85a9e8fb4e6ac513467b5fa825bd53e6fcba56Ted Kremenek if (!PieceI) 23131d85a9e8fb4e6ac513467b5fa825bd53e6fcba56Ted Kremenek continue; 23141d85a9e8fb4e6ac513467b5fa825bd53e6fcba56Ted Kremenek 23151d85a9e8fb4e6ac513467b5fa825bd53e6fcba56Ted Kremenek PathPieces::iterator NextI = I; ++NextI; 23161d85a9e8fb4e6ac513467b5fa825bd53e6fcba56Ted Kremenek if (NextI == E) 23171d85a9e8fb4e6ac513467b5fa825bd53e6fcba56Ted Kremenek return; 23181d85a9e8fb4e6ac513467b5fa825bd53e6fcba56Ted Kremenek 23191d85a9e8fb4e6ac513467b5fa825bd53e6fcba56Ted Kremenek PathDiagnosticEventPiece *PieceNextI = 23200fa3504acfc7c20a87973c58ad3474adc94dd97dTed Kremenek dyn_cast<PathDiagnosticEventPiece>(*NextI); 23211d85a9e8fb4e6ac513467b5fa825bd53e6fcba56Ted Kremenek 23221d85a9e8fb4e6ac513467b5fa825bd53e6fcba56Ted Kremenek if (!PieceNextI) 23231d85a9e8fb4e6ac513467b5fa825bd53e6fcba56Ted Kremenek continue; 23241d85a9e8fb4e6ac513467b5fa825bd53e6fcba56Ted Kremenek 23251d85a9e8fb4e6ac513467b5fa825bd53e6fcba56Ted Kremenek // Erase the second piece if it has the same exact message text. 23261d85a9e8fb4e6ac513467b5fa825bd53e6fcba56Ted Kremenek if (PieceI->getString() == PieceNextI->getString()) { 23271d85a9e8fb4e6ac513467b5fa825bd53e6fcba56Ted Kremenek path.erase(NextI); 23281d85a9e8fb4e6ac513467b5fa825bd53e6fcba56Ted Kremenek } 23291d85a9e8fb4e6ac513467b5fa825bd53e6fcba56Ted Kremenek } 23301d85a9e8fb4e6ac513467b5fa825bd53e6fcba56Ted Kremenek} 23311d85a9e8fb4e6ac513467b5fa825bd53e6fcba56Ted Kremenek 233215676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenekstatic bool optimizeEdges(PathPieces &path, SourceManager &SM, 233315676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek OptimizedCallsSet &OCS, 2334bb518991ce4298d8662235fc8cb13813f011c18dJordan Rose LocationContextMap &LCM) { 2335bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek bool hasChanges = false; 2336bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek const LocationContext *LC = LCM[&path]; 2337bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek assert(LC); 2338de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek ParentMap &PM = LC->getParentMap(); 2339bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek 2340481da5554d03271b0d87b695449963f7728c5895Ted Kremenek for (PathPieces::iterator I = path.begin(), E = path.end(); I != E; ) { 2341bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek // Optimize subpaths. 2342bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek if (PathDiagnosticCallPiece *CallI = dyn_cast<PathDiagnosticCallPiece>(*I)){ 2343481da5554d03271b0d87b695449963f7728c5895Ted Kremenek // Record the fact that a call has been optimized so we only do the 2344481da5554d03271b0d87b695449963f7728c5895Ted Kremenek // effort once. 234515676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek if (!OCS.count(CallI)) { 2346bb518991ce4298d8662235fc8cb13813f011c18dJordan Rose while (optimizeEdges(CallI->path, SM, OCS, LCM)) {} 234715676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek OCS.insert(CallI); 234815676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek } 2349481da5554d03271b0d87b695449963f7728c5895Ted Kremenek ++I; 2350bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek continue; 2351bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek } 2352bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek 2353bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek // Pattern match the current piece and its successor. 2354bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek PathDiagnosticControlFlowPiece *PieceI = 2355bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek dyn_cast<PathDiagnosticControlFlowPiece>(*I); 2356bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek 2357481da5554d03271b0d87b695449963f7728c5895Ted Kremenek if (!PieceI) { 2358481da5554d03271b0d87b695449963f7728c5895Ted Kremenek ++I; 2359bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek continue; 2360481da5554d03271b0d87b695449963f7728c5895Ted Kremenek } 2361bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek 2362f468fa16e37fc8fa6a915fe36aee8f0434709789Ted Kremenek const Stmt *s1Start = getLocStmt(PieceI->getStartLocation()); 2363f468fa16e37fc8fa6a915fe36aee8f0434709789Ted Kremenek const Stmt *s1End = getLocStmt(PieceI->getEndLocation()); 2364f468fa16e37fc8fa6a915fe36aee8f0434709789Ted Kremenek const Stmt *level1 = getStmtParent(s1Start, PM); 2365f468fa16e37fc8fa6a915fe36aee8f0434709789Ted Kremenek const Stmt *level2 = getStmtParent(s1End, PM); 2366f468fa16e37fc8fa6a915fe36aee8f0434709789Ted Kremenek 236715676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek PathPieces::iterator NextI = I; ++NextI; 236815676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek if (NextI == E) 236915676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek break; 237015676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek 2371bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek PathDiagnosticControlFlowPiece *PieceNextI = 2372bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek dyn_cast<PathDiagnosticControlFlowPiece>(*NextI); 2373bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek 2374481da5554d03271b0d87b695449963f7728c5895Ted Kremenek if (!PieceNextI) { 2375481da5554d03271b0d87b695449963f7728c5895Ted Kremenek ++I; 2376bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek continue; 2377481da5554d03271b0d87b695449963f7728c5895Ted Kremenek } 2378bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek 2379f468fa16e37fc8fa6a915fe36aee8f0434709789Ted Kremenek const Stmt *s2Start = getLocStmt(PieceNextI->getStartLocation()); 2380f468fa16e37fc8fa6a915fe36aee8f0434709789Ted Kremenek const Stmt *s2End = getLocStmt(PieceNextI->getEndLocation()); 2381f468fa16e37fc8fa6a915fe36aee8f0434709789Ted Kremenek const Stmt *level3 = getStmtParent(s2Start, PM); 2382f468fa16e37fc8fa6a915fe36aee8f0434709789Ted Kremenek const Stmt *level4 = getStmtParent(s2End, PM); 2383bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek 2384bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek // Rule I. 2385bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek // 2386bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek // If we have two consecutive control edges whose end/begin locations 2387481da5554d03271b0d87b695449963f7728c5895Ted Kremenek // are at the same level (e.g. statements or top-level expressions within 2388481da5554d03271b0d87b695449963f7728c5895Ted Kremenek // a compound statement, or siblings share a single ancestor expression), 2389481da5554d03271b0d87b695449963f7728c5895Ted Kremenek // then merge them if they have no interesting intermediate event. 2390bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek // 2391bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek // For example: 2392bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek // 2393bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek // (1.1 -> 1.2) -> (1.2 -> 1.3) becomes (1.1 -> 1.3) because the common 2394481da5554d03271b0d87b695449963f7728c5895Ted Kremenek // parent is '1'. Here 'x.y.z' represents the hierarchy of statements. 2395bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek // 2396bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek // NOTE: this will be limited later in cases where we add barriers 2397bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek // to prevent this optimization. 2398f468fa16e37fc8fa6a915fe36aee8f0434709789Ted Kremenek // 2399481da5554d03271b0d87b695449963f7728c5895Ted Kremenek if (level1 && level1 == level2 && level1 == level3 && level1 == level4) { 2400bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek PieceI->setEndLocation(PieceNextI->getEndLocation()); 2401bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek path.erase(NextI); 2402bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek hasChanges = true; 2403bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek continue; 2404bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek } 2405b9e13d555fc9f3e5515e2b1fa6f720e6f10bb076Ted Kremenek 2406b9e13d555fc9f3e5515e2b1fa6f720e6f10bb076Ted Kremenek // Rule II. 2407b9e13d555fc9f3e5515e2b1fa6f720e6f10bb076Ted Kremenek // 2408a399f776ee29e099da33eaf7f9d585b4edc4b61dTed Kremenek // Eliminate edges between subexpressions and parent expressions 2409a399f776ee29e099da33eaf7f9d585b4edc4b61dTed Kremenek // when the subexpression is consumed. 2410f468fa16e37fc8fa6a915fe36aee8f0434709789Ted Kremenek // 2411f468fa16e37fc8fa6a915fe36aee8f0434709789Ted Kremenek // NOTE: this will be limited later in cases where we add barriers 2412f468fa16e37fc8fa6a915fe36aee8f0434709789Ted Kremenek // to prevent this optimization. 2413f468fa16e37fc8fa6a915fe36aee8f0434709789Ted Kremenek // 241496b8134337883908fcc45484486fe200d6b3e32fTed Kremenek if (s1End && s1End == s2Start && level2) { 241552f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek bool removeEdge = false; 241652f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek // Remove edges into the increment or initialization of a 241752f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek // loop that have no interleaving event. This means that 241852f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek // they aren't interesting. 241952f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek if (isIncrementOrInitInForLoop(s1End, level2)) 242052f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek removeEdge = true; 242152f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek // Next only consider edges that are not anchored on 242252f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek // the condition of a terminator. This are intermediate edges 242352f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek // that we might want to trim. 242452f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek else if (!isConditionForTerminator(level2, s1End)) { 242552f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek // Trim edges on expressions that are consumed by 242652f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek // the parent expression. 242752f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek if (isa<Expr>(s1End) && PM.isConsumedExpr(cast<Expr>(s1End))) { 242852f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek removeEdge = true; 242952f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek } 243052f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek // Trim edges where a lexical containment doesn't exist. 243152f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek // For example: 243252f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek // 243352f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek // X -> Y -> Z 243452f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek // 243552f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek // If 'Z' lexically contains Y (it is an ancestor) and 243652f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek // 'X' does not lexically contain Y (it is a descendant OR 243752f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek // it has no lexical relationship at all) then trim. 243852f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek // 243952f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek // This can eliminate edges where we dive into a subexpression 244052f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek // and then pop back out, etc. 244152f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek else if (s1Start && s2End && 244252f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek lexicalContains(PM, s2Start, s2End) && 244352f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek !lexicalContains(PM, s1End, s1Start)) { 244452f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek removeEdge = true; 244552f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek } 2446e624524705ab660eb8d1feb9870ef2989fb2bdf4Jordan Rose // Trim edges from a subexpression back to the top level if the 2447e624524705ab660eb8d1feb9870ef2989fb2bdf4Jordan Rose // subexpression is on a different line. 2448e624524705ab660eb8d1feb9870ef2989fb2bdf4Jordan Rose // 2449e624524705ab660eb8d1feb9870ef2989fb2bdf4Jordan Rose // A.1 -> A -> B 2450e624524705ab660eb8d1feb9870ef2989fb2bdf4Jordan Rose // becomes 2451e624524705ab660eb8d1feb9870ef2989fb2bdf4Jordan Rose // A.1 -> B 2452e624524705ab660eb8d1feb9870ef2989fb2bdf4Jordan Rose // 2453e624524705ab660eb8d1feb9870ef2989fb2bdf4Jordan Rose // These edges just look ugly and don't usually add anything. 2454e624524705ab660eb8d1feb9870ef2989fb2bdf4Jordan Rose else if (s1Start && s2End && 2455e624524705ab660eb8d1feb9870ef2989fb2bdf4Jordan Rose lexicalContains(PM, s1Start, s1End)) { 2456e624524705ab660eb8d1feb9870ef2989fb2bdf4Jordan Rose SourceRange EdgeRange(PieceI->getEndLocation().asLocation(), 2457e624524705ab660eb8d1feb9870ef2989fb2bdf4Jordan Rose PieceI->getStartLocation().asLocation()); 2458e624524705ab660eb8d1feb9870ef2989fb2bdf4Jordan Rose if (!getLengthOnSingleLine(SM, EdgeRange).hasValue()) 2459e624524705ab660eb8d1feb9870ef2989fb2bdf4Jordan Rose removeEdge = true; 2460e624524705ab660eb8d1feb9870ef2989fb2bdf4Jordan Rose } 246152f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek } 246252f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek 246352f926cc32e4f4969f767e98d98f0137358d5f12Ted Kremenek if (removeEdge) { 246496b8134337883908fcc45484486fe200d6b3e32fTed Kremenek PieceI->setEndLocation(PieceNextI->getEndLocation()); 246596b8134337883908fcc45484486fe200d6b3e32fTed Kremenek path.erase(NextI); 246696b8134337883908fcc45484486fe200d6b3e32fTed Kremenek hasChanges = true; 246796b8134337883908fcc45484486fe200d6b3e32fTed Kremenek continue; 246896b8134337883908fcc45484486fe200d6b3e32fTed Kremenek } 2469f468fa16e37fc8fa6a915fe36aee8f0434709789Ted Kremenek } 2470481da5554d03271b0d87b695449963f7728c5895Ted Kremenek 2471e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek // Optimize edges for ObjC fast-enumeration loops. 2472e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek // 2473e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek // (X -> collection) -> (collection -> element) 2474e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek // 2475e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek // becomes: 2476e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek // 2477e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek // (X -> element) 2478e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek if (s1End == s2Start) { 2479e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek const ObjCForCollectionStmt *FS = 2480e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek dyn_cast_or_null<ObjCForCollectionStmt>(level3); 2481e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek if (FS && FS->getCollection()->IgnoreParens() == s2Start && 2482e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek s2End == FS->getElement()) { 2483e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek PieceI->setEndLocation(PieceNextI->getEndLocation()); 2484e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek path.erase(NextI); 2485e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek hasChanges = true; 2486e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek continue; 2487e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek } 2488e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek } 2489e86ee1a213d244bb66b7eef3e9ab2266908cf4afTed Kremenek 2490481da5554d03271b0d87b695449963f7728c5895Ted Kremenek // No changes at this index? Move to the next one. 2491481da5554d03271b0d87b695449963f7728c5895Ted Kremenek ++I; 2492bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek } 2493bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek 2494de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek if (!hasChanges) { 249596f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose // Adjust edges into subexpressions to make them more uniform 249696f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose // and aesthetically pleasing. 249796f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose addContextEdges(path, SM, PM, LC); 24983b5977e690b3d4476938a548bbd6f66c4a4a6dcdJordan Rose // Remove "cyclical" edges that include one or more context edges. 249922b0ad2d2a9c723bcdc94525a091fdbfbaa480faJordan Rose removeContextCycles(path, SM, PM); 250096f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose // Hoist edges originating from branch conditions to branches 250196f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose // for simple branches. 250296f1061fbe59faff5b266a3a04061cefcfe03e2fJordan Rose simplifySimpleBranches(path); 2503de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek // Remove any puny edges left over after primary optimization pass. 2504de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek removePunyEdges(path, SM, PM); 25051d85a9e8fb4e6ac513467b5fa825bd53e6fcba56Ted Kremenek // Remove identical events. 25061d85a9e8fb4e6ac513467b5fa825bd53e6fcba56Ted Kremenek removeIdenticalEvents(path); 2507de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek } 2508de7bc0d997cc69bd5c337ab82665c2f7ed989138Ted Kremenek 2509bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek return hasChanges; 2510bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek} 2511bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek 251201f1ff79f70b3e042995a43b29ccbf0fffc77d5fJordan Rose/// Drop the very first edge in a path, which should be a function entry edge. 25131089a57a88051f84aca66f3d8c92bda32a3a5c49Jordan Rose/// 25141089a57a88051f84aca66f3d8c92bda32a3a5c49Jordan Rose/// If the first edge is not a function entry edge (say, because the first 25151089a57a88051f84aca66f3d8c92bda32a3a5c49Jordan Rose/// statement had an invalid source location), this function does nothing. 25161089a57a88051f84aca66f3d8c92bda32a3a5c49Jordan Rose// FIXME: We should just generate invalid edges anyway and have the optimizer 25171089a57a88051f84aca66f3d8c92bda32a3a5c49Jordan Rose// deal with them. 251801f1ff79f70b3e042995a43b29ccbf0fffc77d5fJordan Rosestatic void dropFunctionEntryEdge(PathPieces &Path, 251901f1ff79f70b3e042995a43b29ccbf0fffc77d5fJordan Rose LocationContextMap &LCM, 252001f1ff79f70b3e042995a43b29ccbf0fffc77d5fJordan Rose SourceManager &SM) { 252101f1ff79f70b3e042995a43b29ccbf0fffc77d5fJordan Rose const PathDiagnosticControlFlowPiece *FirstEdge = 25221089a57a88051f84aca66f3d8c92bda32a3a5c49Jordan Rose dyn_cast<PathDiagnosticControlFlowPiece>(Path.front()); 25231089a57a88051f84aca66f3d8c92bda32a3a5c49Jordan Rose if (!FirstEdge) 25241089a57a88051f84aca66f3d8c92bda32a3a5c49Jordan Rose return; 25251089a57a88051f84aca66f3d8c92bda32a3a5c49Jordan Rose 25261089a57a88051f84aca66f3d8c92bda32a3a5c49Jordan Rose const Decl *D = LCM[&Path]->getDecl(); 25271089a57a88051f84aca66f3d8c92bda32a3a5c49Jordan Rose PathDiagnosticLocation EntryLoc = PathDiagnosticLocation::createBegin(D, SM); 25281089a57a88051f84aca66f3d8c92bda32a3a5c49Jordan Rose if (FirstEdge->getStartLocation() != EntryLoc) 25291089a57a88051f84aca66f3d8c92bda32a3a5c49Jordan Rose return; 253001f1ff79f70b3e042995a43b29ccbf0fffc77d5fJordan Rose 253101f1ff79f70b3e042995a43b29ccbf0fffc77d5fJordan Rose Path.pop_front(); 253201f1ff79f70b3e042995a43b29ccbf0fffc77d5fJordan Rose} 253301f1ff79f70b3e042995a43b29ccbf0fffc77d5fJordan Rose 253401f1ff79f70b3e042995a43b29ccbf0fffc77d5fJordan Rose 25355fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek//===----------------------------------------------------------------------===// 25363106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// Methods for BugType and subclasses. 25373106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 2538edcc199f5861dd8ad1ec3ad1b83512d2a92e515aJordan Rosevoid BugType::anchor() { } 2539404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis 25403106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenekvoid BugType::FlushReports(BugReporter &BR) {} 25413106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 254299ba9e3bd70671f3441fb974895f226a83ce0e66David Blaikievoid BuiltinBug::anchor() {} 254399ba9e3bd70671f3441fb974895f226a83ce0e66David Blaikie 25443106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 25453106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// Methods for BugReport and subclasses. 25463106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 2547e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks 254899ba9e3bd70671f3441fb974895f226a83ce0e66David Blaikievoid BugReport::NodeResolver::anchor() {} 254999ba9e3bd70671f3441fb974895f226a83ce0e66David Blaikie 25508e6431adab313e283a992698f6fc7afe62420999Anna Zaksvoid BugReport::addVisitor(BugReporterVisitor* visitor) { 25518e6431adab313e283a992698f6fc7afe62420999Anna Zaks if (!visitor) 25528e6431adab313e283a992698f6fc7afe62420999Anna Zaks return; 25538e6431adab313e283a992698f6fc7afe62420999Anna Zaks 25548e6431adab313e283a992698f6fc7afe62420999Anna Zaks llvm::FoldingSetNodeID ID; 25558e6431adab313e283a992698f6fc7afe62420999Anna Zaks visitor->Profile(ID); 25568e6431adab313e283a992698f6fc7afe62420999Anna Zaks void *InsertPos; 25578e6431adab313e283a992698f6fc7afe62420999Anna Zaks 25588e6431adab313e283a992698f6fc7afe62420999Anna Zaks if (CallbacksSet.FindNodeOrInsertPos(ID, InsertPos)) { 25598e6431adab313e283a992698f6fc7afe62420999Anna Zaks delete visitor; 25608e6431adab313e283a992698f6fc7afe62420999Anna Zaks return; 25618e6431adab313e283a992698f6fc7afe62420999Anna Zaks } 25628e6431adab313e283a992698f6fc7afe62420999Anna Zaks 25638e6431adab313e283a992698f6fc7afe62420999Anna Zaks CallbacksSet.InsertNode(visitor, InsertPos); 25643bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose Callbacks.push_back(visitor); 25653bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose ++ConfigurationChangeToken; 25668e6431adab313e283a992698f6fc7afe62420999Anna Zaks} 25678e6431adab313e283a992698f6fc7afe62420999Anna Zaks 25688e6431adab313e283a992698f6fc7afe62420999Anna ZaksBugReport::~BugReport() { 25698e6431adab313e283a992698f6fc7afe62420999Anna Zaks for (visitor_iterator I = visitor_begin(), E = visitor_end(); I != E; ++I) { 2570dc757b049796949e4b11646445a6598f0bdabd7aAnna Zaks delete *I; 25718e6431adab313e283a992698f6fc7afe62420999Anna Zaks } 2572c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek while (!interestingSymbols.empty()) { 2573c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek popInterestingSymbolsAndRegions(); 2574c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek } 25758e6431adab313e283a992698f6fc7afe62420999Anna Zaks} 2576e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks 257707189521a15d9c088216b943649cb9fe231cbb57Ted Kremenekconst Decl *BugReport::getDeclWithIssue() const { 257807189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek if (DeclWithIssue) 257907189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek return DeclWithIssue; 258007189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek 258107189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek const ExplodedNode *N = getErrorNode(); 258207189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek if (!N) 25836bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 25846bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 258507189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek const LocationContext *LC = N->getLocationContext(); 258607189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek return LC->getCurrentStackFrame()->getDecl(); 258707189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek} 258807189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek 2589e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaksvoid BugReport::Profile(llvm::FoldingSetNodeID& hash) const { 2590e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks hash.AddPointer(&BT); 2591e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks hash.AddString(Description); 259297bfb558f69c09b01a5c1510f08dc91eb62329a7Anna Zaks PathDiagnosticLocation UL = getUniqueingLocation(); 259397bfb558f69c09b01a5c1510f08dc91eb62329a7Anna Zaks if (UL.isValid()) { 259497bfb558f69c09b01a5c1510f08dc91eb62329a7Anna Zaks UL.Profile(hash); 2595ca8e36eb637e232475ef31c3f22d5da907390917Anna Zaks } else if (Location.isValid()) { 2596590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks Location.Profile(hash); 2597590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks } else { 2598590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks assert(ErrorNode); 2599590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks hash.AddPointer(GetCurrentOrPreviousStmt(ErrorNode)); 2600590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks } 2601e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks 2602e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks for (SmallVectorImpl<SourceRange>::const_iterator I = 2603e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks Ranges.begin(), E = Ranges.end(); I != E; ++I) { 2604e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks const SourceRange range = *I; 2605e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks if (!range.isValid()) 2606e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks continue; 2607e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks hash.AddInteger(range.getBegin().getRawEncoding()); 2608e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks hash.AddInteger(range.getEnd().getRawEncoding()); 2609e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks } 2610e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks} 26113106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 261276aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenekvoid BugReport::markInteresting(SymbolRef sym) { 261376aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek if (!sym) 261476aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek return; 26153bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose 26163bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose // If the symbol wasn't already in our set, note a configuration change. 2617c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek if (getInterestingSymbols().insert(sym).second) 26183bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose ++ConfigurationChangeToken; 26198ec588e2ac57311604cf80608c7d4b3fb3b022f7Jordy Rose 26208ec588e2ac57311604cf80608c7d4b3fb3b022f7Jordy Rose if (const SymbolMetadata *meta = dyn_cast<SymbolMetadata>(sym)) 2621c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek getInterestingRegions().insert(meta->getRegion()); 262276aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek} 262376aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek 262476aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenekvoid BugReport::markInteresting(const MemRegion *R) { 262576aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek if (!R) 262676aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek return; 26273bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose 26283bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose // If the base region wasn't already in our set, note a configuration change. 262976aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek R = R->getBaseRegion(); 2630c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek if (getInterestingRegions().insert(R).second) 26313bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose ++ConfigurationChangeToken; 26328ec588e2ac57311604cf80608c7d4b3fb3b022f7Jordy Rose 263376aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R)) 2634c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek getInterestingSymbols().insert(SR->getSymbol()); 263576aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek} 263676aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek 263776aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenekvoid BugReport::markInteresting(SVal V) { 263876aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek markInteresting(V.getAsRegion()); 263976aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek markInteresting(V.getAsSymbol()); 264076aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek} 264176aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek 264280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaksvoid BugReport::markInteresting(const LocationContext *LC) { 264380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks if (!LC) 264480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks return; 264580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks InterestingLocationContexts.insert(LC); 264680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks} 264780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks 2648c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenekbool BugReport::isInteresting(SVal V) { 264976aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek return isInteresting(V.getAsRegion()) || isInteresting(V.getAsSymbol()); 265076aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek} 265176aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek 2652c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenekbool BugReport::isInteresting(SymbolRef sym) { 265376aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek if (!sym) 265476aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek return false; 26558ec588e2ac57311604cf80608c7d4b3fb3b022f7Jordy Rose // We don't currently consider metadata symbols to be interesting 26568ec588e2ac57311604cf80608c7d4b3fb3b022f7Jordy Rose // even if we know their region is interesting. Is that correct behavior? 2657c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek return getInterestingSymbols().count(sym); 265876aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek} 265976aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek 2660c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenekbool BugReport::isInteresting(const MemRegion *R) { 266176aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek if (!R) 266276aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek return false; 266376aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek R = R->getBaseRegion(); 2664c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek bool b = getInterestingRegions().count(R); 266576aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek if (b) 266676aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek return true; 266776aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R)) 2668c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek return getInterestingSymbols().count(SR->getSymbol()); 266976aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek return false; 267076aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek} 2671c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek 267280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaksbool BugReport::isInteresting(const LocationContext *LC) { 267380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks if (!LC) 267480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks return false; 267580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks return InterestingLocationContexts.count(LC); 267680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks} 267780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks 2678c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenekvoid BugReport::lazyInitializeInterestingSets() { 2679c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek if (interestingSymbols.empty()) { 2680c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek interestingSymbols.push_back(new Symbols()); 2681c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek interestingRegions.push_back(new Regions()); 2682c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek } 2683c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek} 2684c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek 2685c4bac8e376b98d633bb00ee5f510d5e58449753cTed KremenekBugReport::Symbols &BugReport::getInterestingSymbols() { 2686c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek lazyInitializeInterestingSets(); 2687c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek return *interestingSymbols.back(); 2688c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek} 2689c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek 2690c4bac8e376b98d633bb00ee5f510d5e58449753cTed KremenekBugReport::Regions &BugReport::getInterestingRegions() { 2691c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek lazyInitializeInterestingSets(); 2692c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek return *interestingRegions.back(); 2693c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek} 2694c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek 2695c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenekvoid BugReport::pushInterestingSymbolsAndRegions() { 2696c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek interestingSymbols.push_back(new Symbols(getInterestingSymbols())); 2697c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek interestingRegions.push_back(new Regions(getInterestingRegions())); 2698c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek} 2699c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek 2700c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenekvoid BugReport::popInterestingSymbolsAndRegions() { 2701344472ebeded2fca2ed5013b9e87f81d09bfa908Robert Wilhelm delete interestingSymbols.pop_back_val(); 2702344472ebeded2fca2ed5013b9e87f81d09bfa908Robert Wilhelm delete interestingRegions.pop_back_val(); 2703c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek} 270476aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek 27059c378f705405d37f49795d5e915989de774fe11fTed Kremenekconst Stmt *BugReport::getStmt() const { 2706e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks if (!ErrorNode) 27076bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 2708e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks 2709212f6d3b5fb3fa55ba1e40671cfc336430abc8ddTom Care ProgramPoint ProgP = ErrorNode->getLocation(); 27106bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines const Stmt *S = nullptr; 27111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 27127a95de68c093991047ed8d339479ccad51b88663David Blaikie if (Optional<BlockEntrance> BE = ProgP.getAs<BlockEntrance>()) { 2713fafd3834754d2093e0ad7a1c005860fd527ecb7fZhongxing Xu CFGBlock &Exit = ProgP.getLocationContext()->getCFG()->getExit(); 271450d5bc4e3b53eb8bb4ebf198f1213348a3fa0f38Zhongxing Xu if (BE->getBlock() == &Exit) 2715212f6d3b5fb3fa55ba1e40671cfc336430abc8ddTom Care S = GetPreviousStmt(ErrorNode); 27163106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 27175f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek if (!S) 27180f8579274a010f360a371b53101859d9d6052314Anna Zaks S = PathDiagnosticLocation::getStmt(ErrorNode); 27191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 27201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return S; 27213106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 27223106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 2723640ccf071076e684713cc3c3276bb51982bff607Argyrios Kyrtzidisstd::pair<BugReport::ranges_iterator, BugReport::ranges_iterator> 2724e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna ZaksBugReport::getRanges() { 2725e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks // If no custom ranges, add the range of the statement corresponding to 2726e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks // the error node. 2727e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks if (Ranges.empty()) { 2728e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks if (const Expr *E = dyn_cast_or_null<Expr>(getStmt())) 2729e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks addRange(E->getSourceRange()); 2730e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks else 2731e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks return std::make_pair(ranges_iterator(), ranges_iterator()); 2732e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks } 2733e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks 273414924267950e75c6c1f6fcea39fa507b7168bc39Anna Zaks // User-specified absence of range info. 273514924267950e75c6c1f6fcea39fa507b7168bc39Anna Zaks if (Ranges.size() == 1 && !Ranges.begin()->isValid()) 273614924267950e75c6c1f6fcea39fa507b7168bc39Anna Zaks return std::make_pair(ranges_iterator(), ranges_iterator()); 273714924267950e75c6c1f6fcea39fa507b7168bc39Anna Zaks 2738e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks return std::make_pair(Ranges.begin(), Ranges.end()); 27393106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 27403106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 2741590dd8e0959d8df5621827768987c4792b74fc06Anna ZaksPathDiagnosticLocation BugReport::getLocation(const SourceManager &SM) const { 2742b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks if (ErrorNode) { 2743590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks assert(!Location.isValid() && 2744b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks "Either Location or ErrorNode should be specified but not both."); 27450f8579274a010f360a371b53101859d9d6052314Anna Zaks return PathDiagnosticLocation::createEndOfPath(ErrorNode, SM); 2746b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks } 2747b7530a4ca9a7ef62350682bbb374a06de6fdaa9fAnna Zaks 2748651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines assert(Location.isValid()); 2749651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return Location; 27503106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 27513106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 27523106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 27533106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// Methods for BugReporter and subclasses. 27543106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 27553106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 27564a5f724538cbc275370c9504e8169ce92503256cBenjamin KramerBugReportEquivClass::~BugReportEquivClass() { } 2757a2f4ec0df645fc249d2945beef9653f03b175417Zhongxing XuGRBugReporter::~GRBugReporter() { } 27583106198188ac6eb2753f1764d5c28376b0b76351Ted KremenekBugReporterData::~BugReporterData() {} 27593106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 276038b02b912e1a55c912f603c4369431264d36a381Zhongxing XuExplodedGraph &GRBugReporter::getGraph() { return Eng.getGraph(); } 27613106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 276218c66fdc3c4008d335885695fe36fb5353c5f672Ted KremenekProgramStateManager& 27633106198188ac6eb2753f1764d5c28376b0b76351Ted KremenekGRBugReporter::getStateManager() { return Eng.getStateManager(); } 27643106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 27653b030a28cda2b953758507769c1d436bec5ec45eAnna ZaksBugReporter::~BugReporter() { 27663b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks FlushReports(); 27673b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks 27683b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks // Free the bug reports we are tracking. 27693b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks typedef std::vector<BugReportEquivClass *> ContTy; 27703b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks for (ContTy::iterator I = EQClassesVector.begin(), E = EQClassesVector.end(); 27713b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks I != E; ++I) { 27723b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks delete *I; 27733b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks } 27743b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks} 27753106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 27763106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenekvoid BugReporter::FlushReports() { 27773106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (BugTypes.isEmpty()) 27783106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek return; 27793106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 27803106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // First flush the warnings for each BugType. This may end up creating new 2781404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // warnings and new BugTypes. 2782404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // FIXME: Only NSErrorChecker needs BugType's FlushReports. 2783404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // Turn NSErrorChecker into a proper checker and remove this. 27845f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<const BugType*, 16> bugTypes; 27853106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek for (BugTypesTy::iterator I=BugTypes.begin(), E=BugTypes.end(); I!=E; ++I) 2786404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis bugTypes.push_back(*I); 278709d19efaa147762f84aed55efa7930bb3616a4e5Craig Topper for (SmallVectorImpl<const BugType *>::iterator 2788404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis I = bugTypes.begin(), E = bugTypes.end(); I != E; ++I) 27893106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek const_cast<BugType*>(*I)->FlushReports(*this); 27903106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 2791d015f4febe85d3e3340172d70042840c51bbd836Anna Zaks // We need to flush reports in deterministic order to ensure the order 2792d015f4febe85d3e3340172d70042840c51bbd836Anna Zaks // of the reports is consistent between runs. 27930eb6c37dd4e4ad8fa2363003dea270f9fd6c2969Anna Zaks typedef std::vector<BugReportEquivClass *> ContVecTy; 27940eb6c37dd4e4ad8fa2363003dea270f9fd6c2969Anna Zaks for (ContVecTy::iterator EI=EQClassesVector.begin(), EE=EQClassesVector.end(); 27950eb6c37dd4e4ad8fa2363003dea270f9fd6c2969Anna Zaks EI != EE; ++EI){ 27960eb6c37dd4e4ad8fa2363003dea270f9fd6c2969Anna Zaks BugReportEquivClass& EQ = **EI; 2797404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis FlushReport(EQ); 27983106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 27993106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 2800404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // BugReporter owns and deletes only BugTypes created implicitly through 2801404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // EmitBasicReport. 2802404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // FIXME: There are leaks from checkers that assume that the BugTypes they 2803404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // create will be destroyed by the BugReporter. 2804651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines llvm::DeleteContainerSeconds(StrBugTypes); 2805404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis 28063106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Remove all references to the BugType objects. 28073baf672378f105602d2b12f03f00277ae1936fe9Ted Kremenek BugTypes = F.getEmptySet(); 28083106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 28093106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 28103106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 28113106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek// PathDiagnostics generation. 28123106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek//===----------------------------------------------------------------------===// 28133106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 28141efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rosenamespace { 28151efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose/// A wrapper around a report graph, which contains only a single path, and its 28161efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose/// node maps. 28171efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Roseclass ReportGraph { 28181efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rosepublic: 28191efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose InterExplodedGraphMap BackMap; 2820651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::unique_ptr<ExplodedGraph> Graph; 2821228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose const ExplodedNode *ErrorNode; 28221efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose size_t Index; 28231efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose}; 28241efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose 28251efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose/// A wrapper around a trimmed graph and its node maps. 28261efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Roseclass TrimmedGraph { 28271efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose InterExplodedGraphMap InverseMap; 28282110350909701fcd6b55c636e24a675f0a905feaJordan Rose 28292110350909701fcd6b55c636e24a675f0a905feaJordan Rose typedef llvm::DenseMap<const ExplodedNode *, unsigned> PriorityMapTy; 28302110350909701fcd6b55c636e24a675f0a905feaJordan Rose PriorityMapTy PriorityMap; 28312110350909701fcd6b55c636e24a675f0a905feaJordan Rose 2832228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose typedef std::pair<const ExplodedNode *, size_t> NodeIndexPair; 2833228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose SmallVector<NodeIndexPair, 32> ReportNodes; 2834228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose 2835651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::unique_ptr<ExplodedGraph> G; 2836228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose 2837228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose /// A helper class for sorting ExplodedNodes by priority. 2838228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose template <bool Descending> 2839228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose class PriorityCompare { 2840228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose const PriorityMapTy &PriorityMap; 2841228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose 2842228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose public: 2843228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose PriorityCompare(const PriorityMapTy &M) : PriorityMap(M) {} 2844228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose 2845228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose bool operator()(const ExplodedNode *LHS, const ExplodedNode *RHS) const { 2846228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose PriorityMapTy::const_iterator LI = PriorityMap.find(LHS); 2847228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose PriorityMapTy::const_iterator RI = PriorityMap.find(RHS); 2848228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose PriorityMapTy::const_iterator E = PriorityMap.end(); 2849228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose 2850228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose if (LI == E) 2851228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose return Descending; 2852228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose if (RI == E) 2853228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose return !Descending; 2854228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose 2855228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose return Descending ? LI->second > RI->second 2856228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose : LI->second < RI->second; 2857228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose } 2858228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose 2859228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose bool operator()(const NodeIndexPair &LHS, const NodeIndexPair &RHS) const { 2860228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose return (*this)(LHS.first, RHS.first); 2861228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose } 2862228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose }; 2863228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose 28641efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rosepublic: 28651efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose TrimmedGraph(const ExplodedGraph *OriginalGraph, 28662110350909701fcd6b55c636e24a675f0a905feaJordan Rose ArrayRef<const ExplodedNode *> Nodes); 28671efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose 2868228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose bool popNextReportGraph(ReportGraph &GraphWrapper); 28691efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose}; 28701efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose} 28711efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose 28722110350909701fcd6b55c636e24a675f0a905feaJordan RoseTrimmedGraph::TrimmedGraph(const ExplodedGraph *OriginalGraph, 28732110350909701fcd6b55c636e24a675f0a905feaJordan Rose ArrayRef<const ExplodedNode *> Nodes) { 28742110350909701fcd6b55c636e24a675f0a905feaJordan Rose // The trimmed graph is created in the body of the constructor to ensure 28752110350909701fcd6b55c636e24a675f0a905feaJordan Rose // that the DenseMaps have been initialized already. 2876228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose InterExplodedGraphMap ForwardMap; 28770f3a34fb7fea37ebfbcba8b400ccb697b9559b49Jordan Rose G.reset(OriginalGraph->trim(Nodes, &ForwardMap, &InverseMap)); 28781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 28793106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Find the (first) error node in the trimmed graph. We just need to consult 28801efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose // the node map which maps from nodes in the original graph to nodes 28813106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // in the new graph. 2882228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose llvm::SmallPtrSet<const ExplodedNode *, 32> RemainingNodes; 28833106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 28841efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose for (unsigned i = 0, count = Nodes.size(); i < count; ++i) { 2885228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose if (const ExplodedNode *NewNode = ForwardMap.lookup(Nodes[i])) { 2886228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose ReportNodes.push_back(std::make_pair(NewNode, i)); 2887228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose RemainingNodes.insert(NewNode); 28883106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 288940406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek } 28901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2891228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose assert(!RemainingNodes.empty() && "No error node found in the trimmed graph"); 2892228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose 2893228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose // Perform a forward BFS to find all the shortest paths. 2894228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose std::queue<const ExplodedNode *> WS; 2895228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose 2896228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose assert(G->num_roots() == 1); 2897228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose WS.push(*G->roots_begin()); 2898228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose unsigned Priority = 0; 28993106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 29003106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek while (!WS.empty()) { 2901228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose const ExplodedNode *Node = WS.front(); 29023106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek WS.pop(); 29031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 29042110350909701fcd6b55c636e24a675f0a905feaJordan Rose PriorityMapTy::iterator PriorityEntry; 29052110350909701fcd6b55c636e24a675f0a905feaJordan Rose bool IsNew; 2906651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::tie(PriorityEntry, IsNew) = 29072110350909701fcd6b55c636e24a675f0a905feaJordan Rose PriorityMap.insert(std::make_pair(Node, Priority)); 2908228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose ++Priority; 29091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 29102110350909701fcd6b55c636e24a675f0a905feaJordan Rose if (!IsNew) { 29112110350909701fcd6b55c636e24a675f0a905feaJordan Rose assert(PriorityEntry->second <= Priority); 29122110350909701fcd6b55c636e24a675f0a905feaJordan Rose continue; 29132110350909701fcd6b55c636e24a675f0a905feaJordan Rose } 29141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2915228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose if (RemainingNodes.erase(Node)) 2916228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose if (RemainingNodes.empty()) 2917228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose break; 2918a5f80b2ea6d30c5055c067530d63bb0dcaf937d0Jordan Rose 2919228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose for (ExplodedNode::const_pred_iterator I = Node->succ_begin(), 2920228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose E = Node->succ_end(); 29212110350909701fcd6b55c636e24a675f0a905feaJordan Rose I != E; ++I) 2922228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose WS.push(*I); 2923239b6e47d282bd66c8b559ac47b8b42b34da619eJordan Rose } 29242110350909701fcd6b55c636e24a675f0a905feaJordan Rose 2925228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose // Sort the error paths from longest to shortest. 2926228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose std::sort(ReportNodes.begin(), ReportNodes.end(), 2927228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose PriorityCompare<true>(PriorityMap)); 2928228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose} 29292110350909701fcd6b55c636e24a675f0a905feaJordan Rose 2930228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rosebool TrimmedGraph::popNextReportGraph(ReportGraph &GraphWrapper) { 2931228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose if (ReportNodes.empty()) 2932228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose return false; 29332110350909701fcd6b55c636e24a675f0a905feaJordan Rose 2934228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose const ExplodedNode *OrigN; 2935651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::tie(OrigN, GraphWrapper.Index) = ReportNodes.pop_back_val(); 2936228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose assert(PriorityMap.find(OrigN) != PriorityMap.end() && 2937228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose "error node not accessible from root"); 29382110350909701fcd6b55c636e24a675f0a905feaJordan Rose 29392110350909701fcd6b55c636e24a675f0a905feaJordan Rose // Create a new graph with a single path. This is the graph 29402110350909701fcd6b55c636e24a675f0a905feaJordan Rose // that will be returned to the caller. 29412110350909701fcd6b55c636e24a675f0a905feaJordan Rose ExplodedGraph *GNew = new ExplodedGraph(); 29422110350909701fcd6b55c636e24a675f0a905feaJordan Rose GraphWrapper.Graph.reset(GNew); 2943228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose GraphWrapper.BackMap.clear(); 29441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2945228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose // Now walk from the error node up the BFS path, always taking the 2946228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose // predeccessor with the lowest number. 29476bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines ExplodedNode *Succ = nullptr; 2948228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose while (true) { 29493106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Create the equivalent node in the new graph with the same state 29503106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // and location. 29513e5ebf1a05603e08f2d0b2b2a5fa9406fe4cfb22Jordan Rose ExplodedNode *NewN = GNew->getNode(OrigN->getLocation(), OrigN->getState(), 29523e5ebf1a05603e08f2d0b2b2a5fa9406fe4cfb22Jordan Rose OrigN->isSink()); 29531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 29543106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Store the mapping to the original node. 2955228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose InterExplodedGraphMap::const_iterator IMitr = InverseMap.find(OrigN); 29563106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek assert(IMitr != InverseMap.end() && "No mapping to original node."); 29571efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose GraphWrapper.BackMap[NewN] = IMitr->second; 29581eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 29593106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Link up the new node with the previous node. 2960228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose if (Succ) 2961228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose Succ->addPredecessor(NewN, *GNew); 2962228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose else 2963228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose GraphWrapper.ErrorNode = NewN; 29641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2965228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose Succ = NewN; 29661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 29673106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Are we at the final node? 2968228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose if (OrigN->pred_empty()) { 2969228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose GNew->addRoot(NewN); 29703106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 29713106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 29721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2973228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose // Find the next predeccessor node. We choose the node that is marked 29742110350909701fcd6b55c636e24a675f0a905feaJordan Rose // with the lowest BFS number. 2975228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose OrigN = *std::min_element(OrigN->pred_begin(), OrigN->pred_end(), 2976228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose PriorityCompare<false>(PriorityMap)); 29772110350909701fcd6b55c636e24a675f0a905feaJordan Rose } 29782110350909701fcd6b55c636e24a675f0a905feaJordan Rose 2979228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose return true; 29802110350909701fcd6b55c636e24a675f0a905feaJordan Rose} 29812110350909701fcd6b55c636e24a675f0a905feaJordan Rose 29822110350909701fcd6b55c636e24a675f0a905feaJordan Rose 29833106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek/// CompactPathDiagnostic - This function postprocesses a PathDiagnostic object 29843106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek/// and collapses PathDiagosticPieces that are expanded by macros. 298577d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenekstatic void CompactPathDiagnostic(PathPieces &path, const SourceManager& SM) { 29862042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek typedef std::vector<std::pair<IntrusiveRefCntPtr<PathDiagnosticMacroPiece>, 29872042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek SourceLocation> > MacroStackTy; 29881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2989c93dc7889644293e318e19d82830ea2acc45b678Dylan Noblesmith typedef std::vector<IntrusiveRefCntPtr<PathDiagnosticPiece> > 29903106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PiecesTy; 29911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 29923106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroStackTy MacroStack; 29933106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek PiecesTy Pieces; 29941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2995ed866e73bab7733f5226f84c52edefe23d694b2fTed Kremenek for (PathPieces::const_iterator I = path.begin(), E = path.end(); 29962042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek I!=E; ++I) { 299777d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek 2998ef8225444452a1486bd721f3285301fe84643b00Stephen Hines PathDiagnosticPiece *piece = I->get(); 299977d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek 300077d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek // Recursively compact calls. 300177d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek if (PathDiagnosticCallPiece *call=dyn_cast<PathDiagnosticCallPiece>(piece)){ 300277d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek CompactPathDiagnostic(call->path, SM); 300377d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek } 300477d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek 30053106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Get the location of the PathDiagnosticPiece. 300677d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek const FullSourceLoc Loc = piece->getLocation().asLocation(); 30071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 30083106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Determine the instantiation location, which is the location we group 30093106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // related PathDiagnosticPieces. 30101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump SourceLocation InstantiationLoc = Loc.isMacroID() ? 3011402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth SM.getExpansionLoc(Loc) : 30123106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek SourceLocation(); 30131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 30143106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (Loc.isFileID()) { 30153106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroStack.clear(); 301677d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek Pieces.push_back(piece); 30173106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek continue; 30183106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 3019706e3cf2fa7523b5497c52c11a2b6dad2a1ce2acTed Kremenek 30203106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek assert(Loc.isMacroID()); 30211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 30223106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Is the PathDiagnosticPiece within the same macro group? 30233106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (!MacroStack.empty() && InstantiationLoc == MacroStack.back().second) { 302477d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek MacroStack.back().first->subPieces.push_back(piece); 30253106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek continue; 30263106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 3027d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek 30283106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // We aren't in the same group. Are we descending into a new macro 30293106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // or are part of an old one? 3030c93dc7889644293e318e19d82830ea2acc45b678Dylan Noblesmith IntrusiveRefCntPtr<PathDiagnosticMacroPiece> MacroGroup; 3031d8c938b0f6b7a7156181be575239e4c6e15a2adbTed Kremenek 30323106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek SourceLocation ParentInstantiationLoc = InstantiationLoc.isMacroID() ? 3033402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth SM.getExpansionLoc(Loc) : 30343106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek SourceLocation(); 30351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 30363106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Walk the entire macro stack. 30373106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek while (!MacroStack.empty()) { 30383106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (InstantiationLoc == MacroStack.back().second) { 30393106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroGroup = MacroStack.back().first; 30403106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 30413106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 30421eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 30433106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (ParentInstantiationLoc == MacroStack.back().second) { 30443106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroGroup = MacroStack.back().first; 30453106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek break; 304661f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek } 30471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 30483106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroStack.pop_back(); 30496837faa083bebad39aa342f84c2b450fb6410eafTed Kremenek } 30501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 30513106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (!MacroGroup || ParentInstantiationLoc == MacroStack.back().second) { 30523106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Create a new macro group and add it to the stack. 3053590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks PathDiagnosticMacroPiece *NewGroup = 3054590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks new PathDiagnosticMacroPiece( 305577d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek PathDiagnosticLocation::createSingleLocation(piece->getLocation())); 30565a429954aedd8a830a70fcea2cb51561673e4fc3Ted Kremenek 30573106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek if (MacroGroup) 3058802e02463b880f53a6e645bde78cc412481ce9e0Ted Kremenek MacroGroup->subPieces.push_back(NewGroup); 30593106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek else { 30603106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek assert(InstantiationLoc.isFileID()); 30613106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek Pieces.push_back(NewGroup); 30623106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 30631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 30643106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroGroup = NewGroup; 30653106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek MacroStack.push_back(std::make_pair(MacroGroup, InstantiationLoc)); 30667dc8664a54f4ede40a5f4adee3f5081a59d7ee1cTed Kremenek } 30673106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek 30683106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Finally, add the PathDiagnosticPiece to the group. 306977d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek MacroGroup->subPieces.push_back(piece); 30703106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek } 30711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 30723106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek // Now take the pieces and construct a new PathDiagnostic. 307377d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek path.clear(); 30741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 307577d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek for (PiecesTy::iterator I=Pieces.begin(), E=Pieces.end(); I!=E; ++I) 307677d09441e59d3bced6c3d55505eb3a67a784fe02Ted Kremenek path.push_back(*I); 307761f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek} 307861f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek 30798347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rosebool GRBugReporter::generatePathDiagnostic(PathDiagnostic& PD, 3080c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek PathDiagnosticConsumer &PC, 3081c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek ArrayRef<BugReport *> &bugReports) { 308240406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek assert(!bugReports.empty()); 30838347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose 30849a9fe4068eed2fc72ec985e5ae393fb79a8fb9adJordan Rose bool HasValid = false; 3085228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose bool HasInvalid = false; 30862f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose SmallVector<const ExplodedNode *, 32> errorNodes; 3087c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek for (ArrayRef<BugReport*>::iterator I = bugReports.begin(), 30889a9fe4068eed2fc72ec985e5ae393fb79a8fb9adJordan Rose E = bugReports.end(); I != E; ++I) { 30899a9fe4068eed2fc72ec985e5ae393fb79a8fb9adJordan Rose if ((*I)->isValid()) { 30909a9fe4068eed2fc72ec985e5ae393fb79a8fb9adJordan Rose HasValid = true; 30919a9fe4068eed2fc72ec985e5ae393fb79a8fb9adJordan Rose errorNodes.push_back((*I)->getErrorNode()); 30929a9fe4068eed2fc72ec985e5ae393fb79a8fb9adJordan Rose } else { 3093228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose // Keep the errorNodes list in sync with the bugReports list. 3094228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose HasInvalid = true; 30956bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines errorNodes.push_back(nullptr); 30969a9fe4068eed2fc72ec985e5ae393fb79a8fb9adJordan Rose } 309740406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek } 30981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 30999a9fe4068eed2fc72ec985e5ae393fb79a8fb9adJordan Rose // If all the reports have been marked invalid by a previous path generation, 31009a9fe4068eed2fc72ec985e5ae393fb79a8fb9adJordan Rose // we're done. 31019a9fe4068eed2fc72ec985e5ae393fb79a8fb9adJordan Rose if (!HasValid) 31029a9fe4068eed2fc72ec985e5ae393fb79a8fb9adJordan Rose return false; 31039a9fe4068eed2fc72ec985e5ae393fb79a8fb9adJordan Rose 31042f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose typedef PathDiagnosticConsumer::PathGenerationScheme PathGenerationScheme; 31052f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose PathGenerationScheme ActiveScheme = PC.getGenerationScheme(); 31062f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose 3107af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek if (ActiveScheme == PathDiagnosticConsumer::Extensive) { 3108d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks AnalyzerOptions &options = getAnalyzerOptions(); 3109048eeea6852043990c87e52938b53b5337bd098eJordan Rose if (options.getBooleanOption("path-diagnostics-alternate", true)) { 3110af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek ActiveScheme = PathDiagnosticConsumer::AlternateExtensive; 3111af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek } 3112af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek } 3113af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek 31141efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose TrimmedGraph TrimG(&getGraph(), errorNodes); 3115228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose ReportGraph ErrorGraph; 31161efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose 3117228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose while (TrimG.popNextReportGraph(ErrorGraph)) { 31182f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // Find the BugReport with the original location. 31191efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose assert(ErrorGraph.Index < bugReports.size()); 31201efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose BugReport *R = bugReports[ErrorGraph.Index]; 31212f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose assert(R && "No original report found for sliced graph."); 31222f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose assert(R->isValid() && "Report selected by trimmed graph marked invalid."); 31232f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose 31242f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // Start building the path diagnostic... 31251efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose PathDiagnosticBuilder PDB(*this, R, ErrorGraph.BackMap, &PC); 31261efffab67364f5afcc25f5f5f77e0f7ba5d41055Jordan Rose const ExplodedNode *N = ErrorGraph.ErrorNode; 31272f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose 31282f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // Register additional node visitors. 31292f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose R->addVisitor(new NilReceiverBRVisitor()); 31302f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose R->addVisitor(new ConditionBRVisitor()); 31312f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose R->addVisitor(new LikelyFalsePositiveSuppressionBRVisitor()); 31322f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose 31332f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose BugReport::VisitorList visitors; 31342f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose unsigned origReportConfigToken, finalReportConfigToken; 3135d306a530fca74e40916121f5583e0545e470b3c4Ted Kremenek LocationContextMap LCM; 31362f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose 31372f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // While generating diagnostics, it's possible the visitors will decide 31382f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // new symbols and regions are interesting, or add other visitors based on 31392f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // the information they find. If they do, we need to regenerate the path 31402f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // based on our new report configuration. 31412f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose do { 31422f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // Get a clean copy of all the visitors. 31432f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose for (BugReport::visitor_iterator I = R->visitor_begin(), 31442f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose E = R->visitor_end(); I != E; ++I) 31452f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose visitors.push_back((*I)->clone()); 31462f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose 31472f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // Clear out the active path from any previous work. 31482f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose PD.resetPath(); 31492f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose origReportConfigToken = R->getConfigurationChangeToken(); 31502f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose 31512f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // Generate the very last diagnostic piece - the piece is visible before 31522f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // the trace is expanded. 31536bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines std::unique_ptr<PathDiagnosticPiece> LastPiece; 31542f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose for (BugReport::visitor_iterator I = visitors.begin(), E = visitors.end(); 31552f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose I != E; ++I) { 31562f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose if (PathDiagnosticPiece *Piece = (*I)->getEndPath(PDB, N, *R)) { 31572f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose assert (!LastPiece && 31582f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose "There can only be one final piece in a diagnostic."); 31596bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines LastPiece.reset(Piece); 31602f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose } 31613bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose } 316286ff12c8a8a356ca284ca7687749216fbfd74519Anna Zaks 31632f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose if (ActiveScheme != PathDiagnosticConsumer::None) { 31642f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose if (!LastPiece) 31656bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines LastPiece.reset(BugReporterVisitor::getDefaultEndPath(PDB, N, *R)); 31662f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose assert(LastPiece); 31676bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines PD.setEndOfPath(LastPiece.release()); 31688347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose } 31692f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose 3170d306a530fca74e40916121f5583e0545e470b3c4Ted Kremenek // Make sure we get a clean location context map so we don't 3171d306a530fca74e40916121f5583e0545e470b3c4Ted Kremenek // hold onto old mappings. 3172d306a530fca74e40916121f5583e0545e470b3c4Ted Kremenek LCM.clear(); 3173d306a530fca74e40916121f5583e0545e470b3c4Ted Kremenek 31742f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose switch (ActiveScheme) { 3175af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek case PathDiagnosticConsumer::AlternateExtensive: 3176af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek GenerateAlternateExtensivePathDiagnostic(PD, PDB, N, LCM, visitors); 3177af2836593979d4973bec5bd21f10eb6cc0d0f3e3Ted Kremenek break; 31782f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose case PathDiagnosticConsumer::Extensive: 3179d306a530fca74e40916121f5583e0545e470b3c4Ted Kremenek GenerateExtensivePathDiagnostic(PD, PDB, N, LCM, visitors); 31802f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose break; 31812f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose case PathDiagnosticConsumer::Minimal: 3182d306a530fca74e40916121f5583e0545e470b3c4Ted Kremenek GenerateMinimalPathDiagnostic(PD, PDB, N, LCM, visitors); 31832f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose break; 31842f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose case PathDiagnosticConsumer::None: 31852f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose GenerateVisitorsOnlyPathDiagnostic(PD, PDB, N, visitors); 31862f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose break; 3187d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose } 31883bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose 31892f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // Clean up the visitors we used. 31902f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose llvm::DeleteContainerPointers(visitors); 31913bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose 31922f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // Did anything change while generating this path? 31932f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose finalReportConfigToken = R->getConfigurationChangeToken(); 31942f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose } while (finalReportConfigToken != origReportConfigToken); 31953bc75ca0a636efdc93471c9b6bad43085a22bf3aJordy Rose 3196228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose if (!R->isValid()) 31972f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose continue; 3198b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek 31992f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // Finally, prune the diagnostic path of uninteresting stuff. 32002f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose if (!PD.path.empty()) { 3201d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks if (R->shouldPrunePath() && getAnalyzerOptions().shouldPrunePaths()) { 3202d306a530fca74e40916121f5583e0545e470b3c4Ted Kremenek bool stillHasNotes = removeUnneededCalls(PD.getMutablePieces(), R, LCM); 32032f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose assert(stillHasNotes); 32042f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose (void)stillHasNotes; 32052f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose } 32062f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose 32076838710779a23ea5dfdb5764ad7b7a7451b00bf8Anna Zaks // Redirect all call pieces to have valid locations. 32082f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose adjustCallLocations(PD.getMutablePieces()); 32096838710779a23ea5dfdb5764ad7b7a7451b00bf8Anna Zaks removePiecesWithInvalidLocations(PD.getMutablePieces()); 32106838710779a23ea5dfdb5764ad7b7a7451b00bf8Anna Zaks 3211bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek if (ActiveScheme == PathDiagnosticConsumer::AlternateExtensive) { 3212aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek SourceManager &SM = getSourceManager(); 3213aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek 3214aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek // Reduce the number of edges from a very conservative set 3215aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek // to an aesthetically pleasing subset that conveys the 3216aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek // necessary information. 321715676bec6fa9ad9466d93c163f2d1b8a3f559b3aTed Kremenek OptimizedCallsSet OCS; 3218bb518991ce4298d8662235fc8cb13813f011c18dJordan Rose while (optimizeEdges(PD.getMutablePieces(), SM, OCS, LCM)) {} 3219aecda966174516c0ac7c05ceb40e88fc99bcf27cTed Kremenek 322001f1ff79f70b3e042995a43b29ccbf0fffc77d5fJordan Rose // Drop the very first function-entry edge. It's not really necessary 322101f1ff79f70b3e042995a43b29ccbf0fffc77d5fJordan Rose // for top-level functions. 322201f1ff79f70b3e042995a43b29ccbf0fffc77d5fJordan Rose dropFunctionEntryEdge(PD.getMutablePieces(), LCM, SM); 3223bb521b8f14ca29ee4e17ae1f9877586ef0bf8378Ted Kremenek } 3224574c7cf6d0c8e8f8ecda360ae271d5391c404534Jordan Rose 3225d3d0dcfbf784c828c2f07384fd6a3401b0cd4e9eJordan Rose // Remove messages that are basically the same, and edges that may not 3226d3d0dcfbf784c828c2f07384fd6a3401b0cd4e9eJordan Rose // make sense. 3227574c7cf6d0c8e8f8ecda360ae271d5391c404534Jordan Rose // We have to do this after edge optimization in the Extensive mode. 3228574c7cf6d0c8e8f8ecda360ae271d5391c404534Jordan Rose removeRedundantMsgs(PD.getMutablePieces()); 3229d3d0dcfbf784c828c2f07384fd6a3401b0cd4e9eJordan Rose removeEdgesToDefaultInitializers(PD.getMutablePieces()); 3230b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek } 3231afa7cae15b117c4b75794c6c32424953d94b4359Jordan Rose 32322f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // We found a report and didn't suppress it. 32332f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose return true; 3234ed7948b55fa4b2505f240cc5287137f451172b4cTed Kremenek } 32358347d3d45e6f128bba19821f0d2f54cadd4d49bbJordan Rose 32362f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose // We suppressed all the reports in this equivalence class. 3237228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose assert(!HasInvalid && "Inconsistent suppression"); 3238228094a28f81ddba94427239dea5c6e59ff6aabcJordan Rose (void)HasInvalid; 32392f13eb116e62161c5e4d198f7831f226e5cea9daJordan Rose return false; 32403106198188ac6eb2753f1764d5c28376b0b76351Ted Kremenek} 32411aa44c7c9198796085b77c6bdd7c90030845a688Ted Kremenek 3242cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenekvoid BugReporter::Register(BugType *BT) { 32433baf672378f105602d2b12f03f00277ae1936fe9Ted Kremenek BugTypes = F.add(BugTypes, BT); 324476d90c8bf83d071fd1bdbffa6d9f2af87c6bb7b5Ted Kremenek} 324576d90c8bf83d071fd1bdbffa6d9f2af87c6bb7b5Ted Kremenek 3246785950e59424dca7ce0081bebf13c0acd2c4fff6Jordan Rosevoid BugReporter::emitReport(BugReport* R) { 3247651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // To guarantee memory release. 3248651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::unique_ptr<BugReport> UniqueR(R); 3249651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 3250cd007b18ba218925923a82ad4462fecf903f4a93Jordan Rose // Defensive checking: throw the bug away if it comes from a BodyFarm- 3251cd007b18ba218925923a82ad4462fecf903f4a93Jordan Rose // generated body. We do this very early because report processing relies 3252cd007b18ba218925923a82ad4462fecf903f4a93Jordan Rose // on the report's location being valid. 3253edc45d5a91f83d1135bc218f3c377e347ab0251fJordan Rose // FIXME: Valid bugs can occur in BodyFarm-generated bodies, so really we 3254edc45d5a91f83d1135bc218f3c377e347ab0251fJordan Rose // need to just find a reasonable location like we do later on with the path 3255edc45d5a91f83d1135bc218f3c377e347ab0251fJordan Rose // pieces. 3256cd007b18ba218925923a82ad4462fecf903f4a93Jordan Rose if (const ExplodedNode *E = R->getErrorNode()) { 3257cd007b18ba218925923a82ad4462fecf903f4a93Jordan Rose const LocationContext *LCtx = E->getLocationContext(); 3258cd007b18ba218925923a82ad4462fecf903f4a93Jordan Rose if (LCtx->getAnalysisDeclContext()->isBodyAutosynthesized()) 3259cd007b18ba218925923a82ad4462fecf903f4a93Jordan Rose return; 3260cd007b18ba218925923a82ad4462fecf903f4a93Jordan Rose } 3261cd007b18ba218925923a82ad4462fecf903f4a93Jordan Rose 3262cd007b18ba218925923a82ad4462fecf903f4a93Jordan Rose bool ValidSourceLoc = R->getLocation(getSourceManager()).isValid(); 3263cd007b18ba218925923a82ad4462fecf903f4a93Jordan Rose assert(ValidSourceLoc); 3264cd007b18ba218925923a82ad4462fecf903f4a93Jordan Rose // If we mess up in a release build, we'd still prefer to just drop the bug 3265cd007b18ba218925923a82ad4462fecf903f4a93Jordan Rose // instead of trying to go on. 3266cd007b18ba218925923a82ad4462fecf903f4a93Jordan Rose if (!ValidSourceLoc) 3267cd007b18ba218925923a82ad4462fecf903f4a93Jordan Rose return; 3268cd007b18ba218925923a82ad4462fecf903f4a93Jordan Rose 3269cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek // Compute the bug report's hash to determine its equivalence class. 3270cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek llvm::FoldingSetNodeID ID; 3271cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek R->Profile(ID); 32721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 32731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Lookup the equivance class. If there isn't one, create it. 3274cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek BugType& BT = R->getBugType(); 3275cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek Register(&BT); 3276cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek void *InsertPos; 3277404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis BugReportEquivClass* EQ = EQClasses.FindNodeOrInsertPos(ID, InsertPos); 32781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3279cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek if (!EQ) { 3280651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines EQ = new BugReportEquivClass(UniqueR.release()); 3281404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis EQClasses.InsertNode(EQ, InsertPos); 32823b030a28cda2b953758507769c1d436bec5ec45eAnna Zaks EQClassesVector.push_back(EQ); 3283cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek } 3284cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek else 3285651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines EQ->AddReport(UniqueR.release()); 328661f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek} 328761f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek 328806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 328906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek//===----------------------------------------------------------------------===// 329006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek// Emitting reports in equivalence classes. 329106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek//===----------------------------------------------------------------------===// 329206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 329306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremeneknamespace { 3294ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamstruct FRIEC_WLItem { 329506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek const ExplodedNode *N; 329606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek ExplodedNode::const_succ_iterator I, E; 329706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 329806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek FRIEC_WLItem(const ExplodedNode *n) 329906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek : N(n), I(N->succ_begin()), E(N->succ_end()) {} 330006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek}; 330106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek} 330206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 330361f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenekstatic BugReport * 330461f52bd3c524268e25b48a1ed3730aedd6cc8374Ted KremenekFindReportInEquivalenceClass(BugReportEquivClass& EQ, 33055f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVectorImpl<BugReport*> &bugReports) { 330661f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek 330706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek BugReportEquivClass::iterator I = EQ.begin(), E = EQ.end(); 330806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek assert(I != E); 33094a5f724538cbc275370c9504e8169ce92503256cBenjamin Kramer BugType& BT = I->getBugType(); 331061f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek 331140406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek // If we don't need to suppress any of the nodes because they are 331240406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek // post-dominated by a sink, simply add all the nodes in the equivalence class 331340406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek // to 'Nodes'. Any of the reports will serve as a "representative" report. 331461f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek if (!BT.isSuppressOnSink()) { 33154a5f724538cbc275370c9504e8169ce92503256cBenjamin Kramer BugReport *R = I; 331661f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek for (BugReportEquivClass::iterator I=EQ.begin(), E=EQ.end(); I!=E; ++I) { 33179c378f705405d37f49795d5e915989de774fe11fTed Kremenek const ExplodedNode *N = I->getErrorNode(); 331861f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek if (N) { 33194a5f724538cbc275370c9504e8169ce92503256cBenjamin Kramer R = I; 332040406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek bugReports.push_back(R); 332161f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek } 332261f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek } 332306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek return R; 332461f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek } 332561f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek 332606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // For bug reports that should be suppressed when all paths are post-dominated 332706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // by a sink node, iterate through the reports in the equivalence class 332806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // until we find one that isn't post-dominated (if one exists). We use a 332906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // DFS traversal of the ExplodedGraph to find a non-sink node. We could write 333006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // this as a recursive function, but we don't want to risk blowing out the 333106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // stack for very long paths. 33326bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines BugReport *exampleReport = nullptr; 333361f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek 333406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek for (; I != E; ++I) { 33354a5f724538cbc275370c9504e8169ce92503256cBenjamin Kramer const ExplodedNode *errorNode = I->getErrorNode(); 333606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 333740406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek if (!errorNode) 333806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek continue; 333940406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek if (errorNode->isSink()) { 3340b219cfc4d75f0a03630b7c4509ef791b7e97b2c8David Blaikie llvm_unreachable( 334106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek "BugType::isSuppressSink() should not be 'true' for sink end nodes"); 334206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek } 334361f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek // No successors? By definition this nodes isn't post-dominated by a sink. 334440406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek if (errorNode->succ_empty()) { 33454a5f724538cbc275370c9504e8169ce92503256cBenjamin Kramer bugReports.push_back(I); 334640406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek if (!exampleReport) 33474a5f724538cbc275370c9504e8169ce92503256cBenjamin Kramer exampleReport = I; 334861f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek continue; 334961f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek } 335061f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek 335106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // At this point we know that 'N' is not a sink and it has at least one 335206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // successor. Use a DFS worklist to find a non-sink end-of-path node. 335306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek typedef FRIEC_WLItem WLItem; 33545f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner typedef SmallVector<WLItem, 10> DFSWorkList; 335506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek llvm::DenseMap<const ExplodedNode *, unsigned> Visited; 335606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 335706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek DFSWorkList WL; 335840406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek WL.push_back(errorNode); 335940406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek Visited[errorNode] = 1; 336006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 336106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek while (!WL.empty()) { 336206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek WLItem &WI = WL.back(); 336306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek assert(!WI.N->succ_empty()); 336406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 336506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek for (; WI.I != WI.E; ++WI.I) { 336606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek const ExplodedNode *Succ = *WI.I; 336706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // End-of-path node? 336806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek if (Succ->succ_empty()) { 336961f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek // If we found an end-of-path node that is not a sink. 337061f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek if (!Succ->isSink()) { 33714a5f724538cbc275370c9504e8169ce92503256cBenjamin Kramer bugReports.push_back(I); 337240406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek if (!exampleReport) 33734a5f724538cbc275370c9504e8169ce92503256cBenjamin Kramer exampleReport = I; 337461f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek WL.clear(); 337561f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek break; 337661f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek } 337706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // Found a sink? Continue on to the next successor. 337806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek continue; 337906c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek } 338006c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // Mark the successor as visited. If it hasn't been explored, 338106c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek // enqueue it to the DFS worklist. 338206c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek unsigned &mark = Visited[Succ]; 338306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek if (!mark) { 338406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek mark = 1; 338506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek WL.push_back(Succ); 338606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek break; 338706c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek } 338806c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek } 338961f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek 339061f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek // The worklist may have been cleared at this point. First 339161f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek // check if it is empty before checking the last item. 339261f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek if (!WL.empty() && &WL.back() == &WI) 339306c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek WL.pop_back(); 339406c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek } 339506c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek } 339606c9cb4d1a29e708f51bce9f7ee5acbe1c3761c3Ted Kremenek 339761f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek // ExampleReport will be NULL if all the nodes in the equivalence class 339861f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek // were post-dominated by sinks. 339940406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek return exampleReport; 340061f52bd3c524268e25b48a1ed3730aedd6cc8374Ted Kremenek} 3401e0a58073b76fc016325a35152533b8468df2bf4aTed Kremenek 3402cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenekvoid BugReporter::FlushReport(BugReportEquivClass& EQ) { 34035f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<BugReport*, 10> bugReports; 340440406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek BugReport *exampleReport = FindReportInEquivalenceClass(EQ, bugReports); 3405c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek if (exampleReport) { 3406651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (PathDiagnosticConsumer *PDC : getPathDiagnosticConsumers()) { 3407651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines FlushReport(exampleReport, *PDC, bugReports); 3408c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek } 3409c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek } 3410c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek} 3411c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek 3412c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenekvoid BugReporter::FlushReport(BugReport *exampleReport, 3413c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek PathDiagnosticConsumer &PD, 3414c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek ArrayRef<BugReport*> bugReports) { 34151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3416cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek // FIXME: Make sure we use the 'R' for the path that was actually used. 34171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Probably doesn't make a difference in practice. 341840406fe63df2b932d6e9fd021f77f097f9d33afbTed Kremenek BugType& BT = exampleReport->getBugType(); 34191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3420651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::unique_ptr<PathDiagnostic> D(new PathDiagnostic( 3421651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines exampleReport->getBugType().getCheckName(), 3422651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines exampleReport->getDeclWithIssue(), exampleReport->getBugType().getName(), 3423651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines exampleReport->getDescription(), 3424651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines exampleReport->getShortDescription(/*Fallback=*/false), BT.getCategory(), 3425651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines exampleReport->getUniqueingLocation(), 3426651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines exampleReport->getUniqueingDecl())); 3427d49967f8764135ae65658e354b6d38e3637c9de3Ted Kremenek 3428cc08ca9b3cd2b715a699bcc772ce2e83a502915aJordan Rose MaxBugClassSize = std::max(bugReports.size(), 3429cc08ca9b3cd2b715a699bcc772ce2e83a502915aJordan Rose static_cast<size_t>(MaxBugClassSize)); 3430cc08ca9b3cd2b715a699bcc772ce2e83a502915aJordan Rose 3431c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek // Generate the full path diagnostic, using the generation scheme 3432d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose // specified by the PathDiagnosticConsumer. Note that we have to generate 3433d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose // path diagnostics even for consumers which do not support paths, because 3434d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose // the BugReporterVisitors may mark this bug as a false positive. 3435d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose if (!bugReports.empty()) 3436d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose if (!generatePathDiagnostic(*D.get(), PD, bugReports)) 3437d632d6fc606f0be438c3b6fe5c43f1b3f5db98b1Jordan Rose return; 34383148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek 3439cc08ca9b3cd2b715a699bcc772ce2e83a502915aJordan Rose MaxValidBugClassSize = std::max(bugReports.size(), 3440cc08ca9b3cd2b715a699bcc772ce2e83a502915aJordan Rose static_cast<size_t>(MaxValidBugClassSize)); 3441cc08ca9b3cd2b715a699bcc772ce2e83a502915aJordan Rose 3442d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks // Examine the report and see if the last piece is in a header. Reset the 3443d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks // report location to the last piece in the main source file. 3444d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks AnalyzerOptions& Opts = getAnalyzerOptions(); 3445d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks if (Opts.shouldReportIssuesInMainSourceFile() && !Opts.AnalyzeAll) 3446d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks D->resetDiagnosticLocationToMainFile(); 3447d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks 3448c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek // If the path is empty, generate a single step path with the location 3449c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek // of the issue. 3450802e02463b880f53a6e645bde78cc412481ce9e0Ted Kremenek if (D->path.empty()) { 3451c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek PathDiagnosticLocation L = exampleReport->getLocation(getSourceManager()); 3452c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek PathDiagnosticPiece *piece = 3453c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek new PathDiagnosticEventPiece(L, exampleReport->getDescription()); 3454c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek BugReport::ranges_iterator Beg, End; 3455651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::tie(Beg, End) = exampleReport->getRanges(); 345607189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek for ( ; Beg != End; ++Beg) 345707189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek piece->addRange(*Beg); 34583a46f5fd1709f6df03bbb8b0abf84052dc0f39ffJordan Rose D->setEndOfPath(piece); 34593148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek } 34601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3461c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek // Get the meta data. 3462c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek const BugReport::ExtraTextList &Meta = exampleReport->getExtraText(); 3463c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek for (BugReport::ExtraTextList::const_iterator i = Meta.begin(), 3464c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek e = Meta.end(); i != e; ++i) { 3465c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek D->addMeta(*i); 3466c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek } 3467c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek 3468651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines PD.HandlePathDiagnostic(D.release()); 346961f3e058056ab519d249aa67e3d52b0ead57c63eTed Kremenek} 347057202071e477530e9348bc76671ee369b2399b92Ted Kremenek 347107189521a15d9c088216b943649cb9fe231cbb57Ted Kremenekvoid BugReporter::EmitBasicReport(const Decl *DeclWithIssue, 3472651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const CheckerBase *Checker, 3473651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines StringRef Name, StringRef Category, 3474651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines StringRef Str, PathDiagnosticLocation Loc, 3475651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ArrayRef<SourceRange> Ranges) { 3476651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines EmitBasicReport(DeclWithIssue, Checker->getCheckName(), Name, Category, Str, 3477651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Loc, Ranges); 3478651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 3479651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesvoid BugReporter::EmitBasicReport(const Decl *DeclWithIssue, 3480651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines CheckName CheckName, 3481651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines StringRef name, StringRef category, 3482590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks StringRef str, PathDiagnosticLocation Loc, 348331b71f3097a338315a144067dde5b160c4e44fc9Jordan Rose ArrayRef<SourceRange> Ranges) { 34841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3485404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis // 'BT' is owned by BugReporter. 3486651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines BugType *BT = getBugTypeForName(CheckName, name, category); 3487590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks BugReport *R = new BugReport(*BT, str, Loc); 348807189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek R->setDeclWithIssue(DeclWithIssue); 348931b71f3097a338315a144067dde5b160c4e44fc9Jordan Rose for (ArrayRef<SourceRange>::iterator I = Ranges.begin(), E = Ranges.end(); 349031b71f3097a338315a144067dde5b160c4e44fc9Jordan Rose I != E; ++I) 349131b71f3097a338315a144067dde5b160c4e44fc9Jordan Rose R->addRange(*I); 3492785950e59424dca7ce0081bebf13c0acd2c4fff6Jordan Rose emitReport(R); 3493cabe66811fe43835b8c5a0854552768fc53261e3Ted Kremenek} 3494404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis 3495651f13cea278ec967336033dd032faef0e9fc2ecStephen HinesBugType *BugReporter::getBugTypeForName(CheckName CheckName, StringRef name, 34965f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef category) { 3497f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith SmallString<136> fullDesc; 3498651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines llvm::raw_svector_ostream(fullDesc) << CheckName.getName() << ":" << name 3499651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines << ":" << category; 3500404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis llvm::StringMapEntry<BugType *> & 3501404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis entry = StrBugTypes.GetOrCreateValue(fullDesc); 3502404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis BugType *BT = entry.getValue(); 3503404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis if (!BT) { 3504651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines BT = new BugType(CheckName, name, category); 3505404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis entry.setValue(BT); 3506404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis } 3507404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis return BT; 3508404fc3ad6bd844bf8ce70cbf9974ab297704a122Argyrios Kyrtzidis} 3509632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rose 3510651f13cea278ec967336033dd032faef0e9fc2ecStephen HinesLLVM_DUMP_METHOD void PathPieces::dump() const { 3511632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rose unsigned index = 0; 3512632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rose for (PathPieces::const_iterator I = begin(), E = end(); I != E; ++I) { 3513632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rose llvm::errs() << "[" << index++ << "] "; 3514632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rose (*I)->dump(); 3515632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rose llvm::errs() << "\n"; 3516632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rose } 3517632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rose} 3518632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rose 3519632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rosevoid PathDiagnosticCallPiece::dump() const { 3520632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rose llvm::errs() << "CALL\n--------------\n"; 3521632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rose 3522632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rose if (const Stmt *SLoc = getLocStmt(getLocation())) 3523632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rose SLoc->dump(); 3524632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rose else if (const NamedDecl *ND = dyn_cast<NamedDecl>(getCallee())) 3525632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rose llvm::errs() << *ND << "\n"; 3526632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rose else 3527632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rose getLocation().dump(); 3528632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rose} 3529632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rose 3530632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rosevoid PathDiagnosticEventPiece::dump() const { 3531632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rose llvm::errs() << "EVENT\n--------------\n"; 3532632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rose llvm::errs() << getString() << "\n"; 3533632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rose llvm::errs() << " ---- at ----\n"; 3534632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rose getLocation().dump(); 3535632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rose} 3536632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rose 3537632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rosevoid PathDiagnosticControlFlowPiece::dump() const { 3538632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rose llvm::errs() << "CONTROL\n--------------\n"; 3539632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rose getStartLocation().dump(); 3540632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rose llvm::errs() << " ---- to ----\n"; 3541632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rose getEndLocation().dump(); 3542632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rose} 3543632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rose 3544632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rosevoid PathDiagnosticMacroPiece::dump() const { 3545632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rose llvm::errs() << "MACRO\n--------------\n"; 3546632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rose // FIXME: Print which macro is being invoked. 3547632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rose} 3548632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rose 3549632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rosevoid PathDiagnosticLocation::dump() const { 3550632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rose if (!isValid()) { 3551632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rose llvm::errs() << "<INVALID>\n"; 3552632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rose return; 3553632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rose } 3554632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rose 3555632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rose switch (K) { 3556632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rose case RangeK: 3557632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rose // FIXME: actually print the range. 3558632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rose llvm::errs() << "<range>\n"; 3559632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rose break; 3560632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rose case SingleLocK: 3561632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rose asLocation().dump(); 3562632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rose llvm::errs() << "\n"; 3563632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rose break; 3564632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rose case StmtK: 3565632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rose if (S) 3566632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rose S->dump(); 3567632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rose else 3568632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rose llvm::errs() << "<NULL STMT>\n"; 3569632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rose break; 3570632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rose case DeclK: 3571632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rose if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(D)) 3572632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rose llvm::errs() << *ND << "\n"; 3573632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rose else if (isa<BlockDecl>(D)) 3574632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rose // FIXME: Make this nicer. 3575632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rose llvm::errs() << "<block>\n"; 3576632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rose else if (D) 3577632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rose llvm::errs() << "<unknown decl>\n"; 3578632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rose else 3579632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rose llvm::errs() << "<NULL DECL>\n"; 3580632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rose break; 3581632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rose } 3582632182d0e2011a6e21cf9abe34eef5a1f037e7efJordan Rose} 3583