1d3abcdfa30e476571e214d5d74fb12ac43d153baTed Kremenek//===--- PathDiagnostic.cpp - Path-Specific Diagnostic Handling -*- C++ -*-===// 2d3abcdfa30e476571e214d5d74fb12ac43d153baTed Kremenek// 3d3abcdfa30e476571e214d5d74fb12ac43d153baTed Kremenek// The LLVM Compiler Infrastructure 4d3abcdfa30e476571e214d5d74fb12ac43d153baTed Kremenek// 5d3abcdfa30e476571e214d5d74fb12ac43d153baTed Kremenek// This file is distributed under the University of Illinois Open Source 6d3abcdfa30e476571e214d5d74fb12ac43d153baTed Kremenek// License. See LICENSE.TXT for details. 7d3abcdfa30e476571e214d5d74fb12ac43d153baTed Kremenek// 8d3abcdfa30e476571e214d5d74fb12ac43d153baTed Kremenek//===----------------------------------------------------------------------===// 9d3abcdfa30e476571e214d5d74fb12ac43d153baTed Kremenek// 10d3abcdfa30e476571e214d5d74fb12ac43d153baTed Kremenek// This file defines the PathDiagnostic-related interfaces. 11d3abcdfa30e476571e214d5d74fb12ac43d153baTed Kremenek// 12d3abcdfa30e476571e214d5d74fb12ac43d153baTed Kremenek//===----------------------------------------------------------------------===// 13d3abcdfa30e476571e214d5d74fb12ac43d153baTed Kremenek 149b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h" 15fea5f5a1e8fe558d716ddeddf1aecf63f2e9a54fTed Kremenek#include "clang/AST/Decl.h" 16183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose#include "clang/AST/DeclCXX.h" 17fea5f5a1e8fe558d716ddeddf1aecf63f2e9a54fTed Kremenek#include "clang/AST/DeclObjC.h" 1855fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/AST/Expr.h" 194d353eb8af7324c0ee3736c736668f6c9b162ee0Anna Zaks#include "clang/AST/ParentMap.h" 20d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl#include "clang/AST/StmtCXX.h" 2155fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Basic/SourceManager.h" 2255fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h" 23f4c839657742b823cea1a95b18422f1ba74d3dddChris Lattner#include "llvm/ADT/SmallString.h" 24615a092a511cd2dfe1a5364ebf5f80e55e33034dJordan Rose#include "llvm/ADT/StringExtras.h" 25a93d0f280693b8418bc88cf7a8c93325f7fcf4c6Benjamin Kramer#include "llvm/Support/raw_ostream.h" 261140186abc9c6bd39f50d9866892e0b050e5f938Ted Kremenek 27d3abcdfa30e476571e214d5d74fb12ac43d153baTed Kremenekusing namespace clang; 289ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremenekusing namespace ento; 290e5c8d4ca6c7e472ddde13495c8d3558983de85aTed Kremenek 300e5c8d4ca6c7e472ddde13495c8d3558983de85aTed Kremenekbool PathDiagnosticMacroPiece::containsEvent() const { 31ed866e73bab7733f5226f84c52edefe23d694b2fTed Kremenek for (PathPieces::const_iterator I = subPieces.begin(), E = subPieces.end(); 32802e02463b880f53a6e645bde78cc412481ce9e0Ted Kremenek I!=E; ++I) { 330e5c8d4ca6c7e472ddde13495c8d3558983de85aTed Kremenek if (isa<PathDiagnosticEventPiece>(*I)) 340e5c8d4ca6c7e472ddde13495c8d3558983de85aTed Kremenek return true; 35ed866e73bab7733f5226f84c52edefe23d694b2fTed Kremenek if (PathDiagnosticMacroPiece *MP = dyn_cast<PathDiagnosticMacroPiece>(*I)) 360e5c8d4ca6c7e472ddde13495c8d3558983de85aTed Kremenek if (MP->containsEvent()) 370e5c8d4ca6c7e472ddde13495c8d3558983de85aTed Kremenek return true; 380e5c8d4ca6c7e472ddde13495c8d3558983de85aTed Kremenek } 390e5c8d4ca6c7e472ddde13495c8d3558983de85aTed Kremenek return false; 400e5c8d4ca6c7e472ddde13495c8d3558983de85aTed Kremenek} 418af2975d50270813ae6366d007e9e1f5b65ddc68Ted Kremenek 425f9e272e632e951b1efe824cd16acb4d96077930Chris Lattnerstatic StringRef StripTrailingDots(StringRef s) { 435f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner for (StringRef::size_type i = s.size(); i != 0; --i) 44d8e494faa9f4bc13cd0a136b4d1ee1cfd52860eaBenjamin Kramer if (s[i - 1] != '.') 45d8e494faa9f4bc13cd0a136b4d1ee1cfd52860eaBenjamin Kramer return s.substr(0, i); 46d8e494faa9f4bc13cd0a136b4d1ee1cfd52860eaBenjamin Kramer return ""; 478af2975d50270813ae6366d007e9e1f5b65ddc68Ted Kremenek} 488af2975d50270813ae6366d007e9e1f5b65ddc68Ted Kremenek 495f9e272e632e951b1efe824cd16acb4d96077930Chris LattnerPathDiagnosticPiece::PathDiagnosticPiece(StringRef s, 50e3ce2656790523fd8c70653ee1ec41e5898f82ebTed Kremenek Kind k, DisplayHint hint) 51d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks : str(StripTrailingDots(s)), kind(k), Hint(hint), 52d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks LastInMainSourceFile(false) {} 534850451c8e93789c099d907dd469898ea9561ecbTed Kremenek 541f9bd0fbf5894b41bba5f2fdb0c6546a7a6ef3d8Ted KremenekPathDiagnosticPiece::PathDiagnosticPiece(Kind k, DisplayHint hint) 55d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks : kind(k), Hint(hint), LastInMainSourceFile(false) {} 56082cb8d7bd9bdb3fe58e8e1a2897c79c4ebcc3a7Ted Kremenek 574e06387c2d6d00c7a30167d4c2206756992dde38Ted KremenekPathDiagnosticPiece::~PathDiagnosticPiece() {} 581fbfd5b9b8b82aea084773b76dd1ec6796a7000cTed KremenekPathDiagnosticEventPiece::~PathDiagnosticEventPiece() {} 592042fc1f36d471f437023e8899f0c4fadded2341Ted KremenekPathDiagnosticCallPiece::~PathDiagnosticCallPiece() {} 601fbfd5b9b8b82aea084773b76dd1ec6796a7000cTed KremenekPathDiagnosticControlFlowPiece::~PathDiagnosticControlFlowPiece() {} 61802e02463b880f53a6e645bde78cc412481ce9e0Ted KremenekPathDiagnosticMacroPiece::~PathDiagnosticMacroPiece() {} 6207189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek 6307189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek 64802e02463b880f53a6e645bde78cc412481ce9e0Ted KremenekPathPieces::~PathPieces() {} 65b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose 66b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rosevoid PathPieces::flattenTo(PathPieces &Primary, PathPieces &Current, 67b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose bool ShouldFlattenMacros) const { 68ed866e73bab7733f5226f84c52edefe23d694b2fTed Kremenek for (PathPieces::const_iterator I = begin(), E = end(); I != E; ++I) { 69ed866e73bab7733f5226f84c52edefe23d694b2fTed Kremenek PathDiagnosticPiece *Piece = I->getPtr(); 70b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose 71b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose switch (Piece->getKind()) { 72b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose case PathDiagnosticPiece::Call: { 73b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose PathDiagnosticCallPiece *Call = cast<PathDiagnosticCallPiece>(Piece); 74b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose IntrusiveRefCntPtr<PathDiagnosticEventPiece> CallEnter = 75b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose Call->getCallEnterEvent(); 76b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose if (CallEnter) 77b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose Current.push_back(CallEnter); 78b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose Call->path.flattenTo(Primary, Primary, ShouldFlattenMacros); 79b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose IntrusiveRefCntPtr<PathDiagnosticEventPiece> callExit = 80b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose Call->getCallExitEvent(); 81b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose if (callExit) 82b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose Current.push_back(callExit); 83b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose break; 84b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose } 85b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose case PathDiagnosticPiece::Macro: { 86b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose PathDiagnosticMacroPiece *Macro = cast<PathDiagnosticMacroPiece>(Piece); 87b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose if (ShouldFlattenMacros) { 88b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose Macro->subPieces.flattenTo(Primary, Primary, ShouldFlattenMacros); 89b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose } else { 90b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose Current.push_back(Piece); 91b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose PathPieces NewPath; 92b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose Macro->subPieces.flattenTo(Primary, NewPath, ShouldFlattenMacros); 93b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose // FIXME: This probably shouldn't mutate the original path piece. 94b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose Macro->subPieces = NewPath; 95b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose } 96b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose break; 97b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose } 98b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose case PathDiagnosticPiece::Event: 99b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose case PathDiagnosticPiece::ControlFlow: 100b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose Current.push_back(Piece); 101b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose break; 102b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose } 103b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose } 104b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose} 105b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose 106b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose 107eb2303c76971f3cc89bbb367ce77564ccb7042c1Ted KremenekPathDiagnostic::~PathDiagnostic() {} 108eb2303c76971f3cc89bbb367ce77564ccb7042c1Ted Kremenek 10907189521a15d9c088216b943649cb9fe231cbb57Ted KremenekPathDiagnostic::PathDiagnostic(const Decl *declWithIssue, 1103a46f5fd1709f6df03bbb8b0abf84052dc0f39ffJordan Rose StringRef bugtype, StringRef verboseDesc, 11197bfb558f69c09b01a5c1510f08dc91eb62329a7Anna Zaks StringRef shortDesc, StringRef category, 11297bfb558f69c09b01a5c1510f08dc91eb62329a7Anna Zaks PathDiagnosticLocation LocationToUnique, 11397bfb558f69c09b01a5c1510f08dc91eb62329a7Anna Zaks const Decl *DeclToUnique) 11407189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek : DeclWithIssue(declWithIssue), 11507189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek BugType(StripTrailingDots(bugtype)), 1163a46f5fd1709f6df03bbb8b0abf84052dc0f39ffJordan Rose VerboseDesc(StripTrailingDots(verboseDesc)), 1173a46f5fd1709f6df03bbb8b0abf84052dc0f39ffJordan Rose ShortDesc(StripTrailingDots(shortDesc)), 1182042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek Category(StripTrailingDots(category)), 11997bfb558f69c09b01a5c1510f08dc91eb62329a7Anna Zaks UniqueingLoc(LocationToUnique), 12097bfb558f69c09b01a5c1510f08dc91eb62329a7Anna Zaks UniqueingDecl(DeclToUnique), 1212042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek path(pathImpl) {} 122a127ccaa38a23dbd9bd3884a2627c091075a7227Ted Kremenek 123d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaksstatic PathDiagnosticCallPiece * 124d95b70175646829c26344d5f0bda1ec3009f2a5bAnna ZaksgetFirstStackedCallToHeaderFile(PathDiagnosticCallPiece *CP, 125d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks const SourceManager &SMgr) { 12661dfd6f160f7501e140704990db9c449d29f8649Anna Zaks SourceLocation CallLoc = CP->callEnter.asLocation(); 12761dfd6f160f7501e140704990db9c449d29f8649Anna Zaks 12861dfd6f160f7501e140704990db9c449d29f8649Anna Zaks // If the call is within a macro, don't do anything (for now). 12961dfd6f160f7501e140704990db9c449d29f8649Anna Zaks if (CallLoc.isMacroID()) 13061dfd6f160f7501e140704990db9c449d29f8649Anna Zaks return 0; 13161dfd6f160f7501e140704990db9c449d29f8649Anna Zaks 13261dfd6f160f7501e140704990db9c449d29f8649Anna Zaks assert(SMgr.isFromMainFile(CallLoc) && 133d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks "The call piece should be in the main file."); 134d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks 135d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks // Check if CP represents a path through a function outside of the main file. 136d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks if (!SMgr.isFromMainFile(CP->callEnterWithin.asLocation())) 137d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks return CP; 138d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks 1395a8e1ad062420ef74707bf093889403d07664b17Anna Zaks const PathPieces &Path = CP->path; 1405a8e1ad062420ef74707bf093889403d07664b17Anna Zaks if (Path.empty()) 1415a8e1ad062420ef74707bf093889403d07664b17Anna Zaks return 0; 1425a8e1ad062420ef74707bf093889403d07664b17Anna Zaks 143d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks // Check if the last piece in the callee path is a call to a function outside 144d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks // of the main file. 145d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks if (PathDiagnosticCallPiece *CPInner = 146d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks dyn_cast<PathDiagnosticCallPiece>(Path.back())) { 147d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks return getFirstStackedCallToHeaderFile(CPInner, SMgr); 148d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks } 149d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks 150d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks // Otherwise, the last piece is in the main file. 151d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks return 0; 152d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks} 153d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks 154d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaksvoid PathDiagnostic::resetDiagnosticLocationToMainFile() { 155d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks if (path.empty()) 156d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks return; 157d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks 158d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks PathDiagnosticPiece *LastP = path.back().getPtr(); 159d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks assert(LastP); 1605a8e1ad062420ef74707bf093889403d07664b17Anna Zaks const SourceManager &SMgr = LastP->getLocation().getManager(); 161d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks 162d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks // We only need to check if the report ends inside headers, if the last piece 163d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks // is a call piece. 164d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks if (PathDiagnosticCallPiece *CP = dyn_cast<PathDiagnosticCallPiece>(LastP)) { 165d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks CP = getFirstStackedCallToHeaderFile(CP, SMgr); 166d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks if (CP) { 167d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks // Mark the piece. 168d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks CP->setAsLastInMainSourceFile(); 169d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks 170d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks // Update the path diagnostic message. 171d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks const NamedDecl *ND = dyn_cast<NamedDecl>(CP->getCallee()); 172d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks if (ND) { 173d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks SmallString<200> buf; 174d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks llvm::raw_svector_ostream os(buf); 1755a8e1ad062420ef74707bf093889403d07664b17Anna Zaks os << " (within a call to '" << ND->getDeclName() << "')"; 176d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks appendToDesc(os.str()); 177d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks } 178d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks 179d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks // Reset the report containing declaration and location. 180d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks DeclWithIssue = CP->getCaller(); 181d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks Loc = CP->getLocation(); 182d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks 183d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks return; 184d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks } 185d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks } 186d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks} 187d95b70175646829c26344d5f0bda1ec3009f2a5bAnna Zaks 18899ba9e3bd70671f3441fb974895f226a83ce0e66David Blaikievoid PathDiagnosticConsumer::anchor() { } 18999ba9e3bd70671f3441fb974895f226a83ce0e66David Blaikie 190bac341346f3c8e713a8f165120fd54b500ee3189Ted KremenekPathDiagnosticConsumer::~PathDiagnosticConsumer() { 191bac341346f3c8e713a8f165120fd54b500ee3189Ted Kremenek // Delete the contents of the FoldingSet if it isn't empty already. 192bac341346f3c8e713a8f165120fd54b500ee3189Ted Kremenek for (llvm::FoldingSet<PathDiagnostic>::iterator it = 193bac341346f3c8e713a8f165120fd54b500ee3189Ted Kremenek Diags.begin(), et = Diags.end() ; it != et ; ++it) { 194bac341346f3c8e713a8f165120fd54b500ee3189Ted Kremenek delete &*it; 195bac341346f3c8e713a8f165120fd54b500ee3189Ted Kremenek } 196bac341346f3c8e713a8f165120fd54b500ee3189Ted Kremenek} 197bac341346f3c8e713a8f165120fd54b500ee3189Ted Kremenek 198bac341346f3c8e713a8f165120fd54b500ee3189Ted Kremenekvoid PathDiagnosticConsumer::HandlePathDiagnostic(PathDiagnostic *D) { 199cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko OwningPtr<PathDiagnostic> OwningD(D); 200bac341346f3c8e713a8f165120fd54b500ee3189Ted Kremenek 20156d8fd0b8a65a7ccae3669cd650ca443cf24b73eTed Kremenek if (!D || D->path.empty()) 202bac341346f3c8e713a8f165120fd54b500ee3189Ted Kremenek return; 203bac341346f3c8e713a8f165120fd54b500ee3189Ted Kremenek 204bac341346f3c8e713a8f165120fd54b500ee3189Ted Kremenek // We need to flatten the locations (convert Stmt* to locations) because 205bac341346f3c8e713a8f165120fd54b500ee3189Ted Kremenek // the referenced statements may be freed by the time the diagnostics 206bac341346f3c8e713a8f165120fd54b500ee3189Ted Kremenek // are emitted. 207bac341346f3c8e713a8f165120fd54b500ee3189Ted Kremenek D->flattenLocations(); 208bac341346f3c8e713a8f165120fd54b500ee3189Ted Kremenek 20956d8fd0b8a65a7ccae3669cd650ca443cf24b73eTed Kremenek // If the PathDiagnosticConsumer does not support diagnostics that 21056d8fd0b8a65a7ccae3669cd650ca443cf24b73eTed Kremenek // cross file boundaries, prune out such diagnostics now. 21156d8fd0b8a65a7ccae3669cd650ca443cf24b73eTed Kremenek if (!supportsCrossFileDiagnostics()) { 21256d8fd0b8a65a7ccae3669cd650ca443cf24b73eTed Kremenek // Verify that the entire path is from the same FileID. 21356d8fd0b8a65a7ccae3669cd650ca443cf24b73eTed Kremenek FileID FID; 214ed866e73bab7733f5226f84c52edefe23d694b2fTed Kremenek const SourceManager &SMgr = (*D->path.begin())->getLocation().getManager(); 215cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko SmallVector<const PathPieces *, 5> WorkList; 21662ff52868976a8494224a2914f1869329777944cTed Kremenek WorkList.push_back(&D->path); 21756d8fd0b8a65a7ccae3669cd650ca443cf24b73eTed Kremenek 21862ff52868976a8494224a2914f1869329777944cTed Kremenek while (!WorkList.empty()) { 21962ff52868976a8494224a2914f1869329777944cTed Kremenek const PathPieces &path = *WorkList.back(); 22062ff52868976a8494224a2914f1869329777944cTed Kremenek WorkList.pop_back(); 22162ff52868976a8494224a2914f1869329777944cTed Kremenek 222ed866e73bab7733f5226f84c52edefe23d694b2fTed Kremenek for (PathPieces::const_iterator I = path.begin(), E = path.end(); 22362ff52868976a8494224a2914f1869329777944cTed Kremenek I != E; ++I) { 224ed866e73bab7733f5226f84c52edefe23d694b2fTed Kremenek const PathDiagnosticPiece *piece = I->getPtr(); 22562ff52868976a8494224a2914f1869329777944cTed Kremenek FullSourceLoc L = piece->getLocation().asLocation().getExpansionLoc(); 22656d8fd0b8a65a7ccae3669cd650ca443cf24b73eTed Kremenek 22762ff52868976a8494224a2914f1869329777944cTed Kremenek if (FID.isInvalid()) { 22862ff52868976a8494224a2914f1869329777944cTed Kremenek FID = SMgr.getFileID(L); 22962ff52868976a8494224a2914f1869329777944cTed Kremenek } else if (SMgr.getFileID(L) != FID) 23056d8fd0b8a65a7ccae3669cd650ca443cf24b73eTed Kremenek return; // FIXME: Emit a warning? 23162ff52868976a8494224a2914f1869329777944cTed Kremenek 23262ff52868976a8494224a2914f1869329777944cTed Kremenek // Check the source ranges. 2332b2c49d2ac5adb34f900f7a854a3ad5a6b0dff3cTed Kremenek ArrayRef<SourceRange> Ranges = piece->getRanges(); 2342b2c49d2ac5adb34f900f7a854a3ad5a6b0dff3cTed Kremenek for (ArrayRef<SourceRange>::iterator I = Ranges.begin(), 2352b2c49d2ac5adb34f900f7a854a3ad5a6b0dff3cTed Kremenek E = Ranges.end(); I != E; ++I) { 2362b2c49d2ac5adb34f900f7a854a3ad5a6b0dff3cTed Kremenek SourceLocation L = SMgr.getExpansionLoc(I->getBegin()); 23762ff52868976a8494224a2914f1869329777944cTed Kremenek if (!L.isFileID() || SMgr.getFileID(L) != FID) 23862ff52868976a8494224a2914f1869329777944cTed Kremenek return; // FIXME: Emit a warning? 2392b2c49d2ac5adb34f900f7a854a3ad5a6b0dff3cTed Kremenek L = SMgr.getExpansionLoc(I->getEnd()); 24062ff52868976a8494224a2914f1869329777944cTed Kremenek if (!L.isFileID() || SMgr.getFileID(L) != FID) 24162ff52868976a8494224a2914f1869329777944cTed Kremenek return; // FIXME: Emit a warning? 24262ff52868976a8494224a2914f1869329777944cTed Kremenek } 24362ff52868976a8494224a2914f1869329777944cTed Kremenek 24462ff52868976a8494224a2914f1869329777944cTed Kremenek if (const PathDiagnosticCallPiece *call = 24562ff52868976a8494224a2914f1869329777944cTed Kremenek dyn_cast<PathDiagnosticCallPiece>(piece)) { 24662ff52868976a8494224a2914f1869329777944cTed Kremenek WorkList.push_back(&call->path); 24762ff52868976a8494224a2914f1869329777944cTed Kremenek } 24862ff52868976a8494224a2914f1869329777944cTed Kremenek else if (const PathDiagnosticMacroPiece *macro = 24962ff52868976a8494224a2914f1869329777944cTed Kremenek dyn_cast<PathDiagnosticMacroPiece>(piece)) { 25062ff52868976a8494224a2914f1869329777944cTed Kremenek WorkList.push_back(¯o->subPieces); 25162ff52868976a8494224a2914f1869329777944cTed Kremenek } 25256d8fd0b8a65a7ccae3669cd650ca443cf24b73eTed Kremenek } 25356d8fd0b8a65a7ccae3669cd650ca443cf24b73eTed Kremenek } 25456d8fd0b8a65a7ccae3669cd650ca443cf24b73eTed Kremenek 25556d8fd0b8a65a7ccae3669cd650ca443cf24b73eTed Kremenek if (FID.isInvalid()) 25656d8fd0b8a65a7ccae3669cd650ca443cf24b73eTed Kremenek return; // FIXME: Emit a warning? 25756d8fd0b8a65a7ccae3669cd650ca443cf24b73eTed Kremenek } 25856d8fd0b8a65a7ccae3669cd650ca443cf24b73eTed Kremenek 259bac341346f3c8e713a8f165120fd54b500ee3189Ted Kremenek // Profile the node to see if we already have something matching it 260bac341346f3c8e713a8f165120fd54b500ee3189Ted Kremenek llvm::FoldingSetNodeID profile; 261bac341346f3c8e713a8f165120fd54b500ee3189Ted Kremenek D->Profile(profile); 262bac341346f3c8e713a8f165120fd54b500ee3189Ted Kremenek void *InsertPos = 0; 263bac341346f3c8e713a8f165120fd54b500ee3189Ted Kremenek 264bac341346f3c8e713a8f165120fd54b500ee3189Ted Kremenek if (PathDiagnostic *orig = Diags.FindNodeOrInsertPos(profile, InsertPos)) { 265bac341346f3c8e713a8f165120fd54b500ee3189Ted Kremenek // Keep the PathDiagnostic with the shorter path. 2665b978519d2c5f5b4541768a827b675e997d4cd34Anna Zaks // Note, the enclosing routine is called in deterministic order, so the 267d015f4febe85d3e3340172d70042840c51bbd836Anna Zaks // results will be consistent between runs (no reason to break ties if the 268d015f4febe85d3e3340172d70042840c51bbd836Anna Zaks // size is the same). 2692042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek const unsigned orig_size = orig->full_size(); 2702042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek const unsigned new_size = D->full_size(); 271d015f4febe85d3e3340172d70042840c51bbd836Anna Zaks if (orig_size <= new_size) 272d015f4febe85d3e3340172d70042840c51bbd836Anna Zaks return; 273bac341346f3c8e713a8f165120fd54b500ee3189Ted Kremenek 274acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek assert(orig != D); 275bac341346f3c8e713a8f165120fd54b500ee3189Ted Kremenek Diags.RemoveNode(orig); 276bac341346f3c8e713a8f165120fd54b500ee3189Ted Kremenek delete orig; 277bac341346f3c8e713a8f165120fd54b500ee3189Ted Kremenek } 278bac341346f3c8e713a8f165120fd54b500ee3189Ted Kremenek 27956d8fd0b8a65a7ccae3669cd650ca443cf24b73eTed Kremenek Diags.InsertNode(OwningD.take()); 280bac341346f3c8e713a8f165120fd54b500ee3189Ted Kremenek} 281bac341346f3c8e713a8f165120fd54b500ee3189Ted Kremenek 282dc84cd5efdd3430efb22546b4ac656aa0540b210David Blaikiestatic Optional<bool> comparePath(const PathPieces &X, const PathPieces &Y); 283dc84cd5efdd3430efb22546b4ac656aa0540b210David Blaikiestatic Optional<bool> 284acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted KremenekcompareControlFlow(const PathDiagnosticControlFlowPiece &X, 285acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek const PathDiagnosticControlFlowPiece &Y) { 286acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek FullSourceLoc XSL = X.getStartLocation().asLocation(); 287acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek FullSourceLoc YSL = Y.getStartLocation().asLocation(); 288acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek if (XSL != YSL) 289acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek return XSL.isBeforeInTranslationUnitThan(YSL); 290acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek FullSourceLoc XEL = X.getEndLocation().asLocation(); 291acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek FullSourceLoc YEL = Y.getEndLocation().asLocation(); 292acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek if (XEL != YEL) 293acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek return XEL.isBeforeInTranslationUnitThan(YEL); 29466874fb18afbffb8b2ca05576851a64534be3352David Blaikie return None; 295acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek} 296acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek 297dc84cd5efdd3430efb22546b4ac656aa0540b210David Blaikiestatic Optional<bool> compareMacro(const PathDiagnosticMacroPiece &X, 298dc84cd5efdd3430efb22546b4ac656aa0540b210David Blaikie const PathDiagnosticMacroPiece &Y) { 299acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek return comparePath(X.subPieces, Y.subPieces); 300acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek} 301acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek 302dc84cd5efdd3430efb22546b4ac656aa0540b210David Blaikiestatic Optional<bool> compareCall(const PathDiagnosticCallPiece &X, 303dc84cd5efdd3430efb22546b4ac656aa0540b210David Blaikie const PathDiagnosticCallPiece &Y) { 304acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek FullSourceLoc X_CEL = X.callEnter.asLocation(); 305acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek FullSourceLoc Y_CEL = Y.callEnter.asLocation(); 306acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek if (X_CEL != Y_CEL) 307acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek return X_CEL.isBeforeInTranslationUnitThan(Y_CEL); 308acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek FullSourceLoc X_CEWL = X.callEnterWithin.asLocation(); 309acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek FullSourceLoc Y_CEWL = Y.callEnterWithin.asLocation(); 310acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek if (X_CEWL != Y_CEWL) 311acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek return X_CEWL.isBeforeInTranslationUnitThan(Y_CEWL); 312acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek FullSourceLoc X_CRL = X.callReturn.asLocation(); 313acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek FullSourceLoc Y_CRL = Y.callReturn.asLocation(); 314acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek if (X_CRL != Y_CRL) 315acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek return X_CRL.isBeforeInTranslationUnitThan(Y_CRL); 316acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek return comparePath(X.path, Y.path); 317acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek} 318acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek 319dc84cd5efdd3430efb22546b4ac656aa0540b210David Blaikiestatic Optional<bool> comparePiece(const PathDiagnosticPiece &X, 320dc84cd5efdd3430efb22546b4ac656aa0540b210David Blaikie const PathDiagnosticPiece &Y) { 321acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek if (X.getKind() != Y.getKind()) 322acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek return X.getKind() < Y.getKind(); 323acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek 324acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek FullSourceLoc XL = X.getLocation().asLocation(); 325acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek FullSourceLoc YL = Y.getLocation().asLocation(); 326acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek if (XL != YL) 327acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek return XL.isBeforeInTranslationUnitThan(YL); 328acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek 329acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek if (X.getString() != Y.getString()) 330acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek return X.getString() < Y.getString(); 331acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek 332acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek if (X.getRanges().size() != Y.getRanges().size()) 333acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek return X.getRanges().size() < Y.getRanges().size(); 334acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek 335d727d39ca779920898d77f5dcbbb3980175594efTed Kremenek const SourceManager &SM = XL.getManager(); 336d727d39ca779920898d77f5dcbbb3980175594efTed Kremenek 337acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek for (unsigned i = 0, n = X.getRanges().size(); i < n; ++i) { 338acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek SourceRange XR = X.getRanges()[i]; 339acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek SourceRange YR = Y.getRanges()[i]; 340acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek if (XR != YR) { 341acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek if (XR.getBegin() != YR.getBegin()) 342d727d39ca779920898d77f5dcbbb3980175594efTed Kremenek return SM.isBeforeInTranslationUnit(XR.getBegin(), YR.getBegin()); 343d727d39ca779920898d77f5dcbbb3980175594efTed Kremenek return SM.isBeforeInTranslationUnit(XR.getEnd(), YR.getEnd()); 344acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek } 345acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek } 346acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek 347acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek switch (X.getKind()) { 348acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek case clang::ento::PathDiagnosticPiece::ControlFlow: 349acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek return compareControlFlow(cast<PathDiagnosticControlFlowPiece>(X), 350acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek cast<PathDiagnosticControlFlowPiece>(Y)); 351acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek case clang::ento::PathDiagnosticPiece::Event: 35266874fb18afbffb8b2ca05576851a64534be3352David Blaikie return None; 353acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek case clang::ento::PathDiagnosticPiece::Macro: 354acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek return compareMacro(cast<PathDiagnosticMacroPiece>(X), 355acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek cast<PathDiagnosticMacroPiece>(Y)); 356acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek case clang::ento::PathDiagnosticPiece::Call: 357acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek return compareCall(cast<PathDiagnosticCallPiece>(X), 358acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek cast<PathDiagnosticCallPiece>(Y)); 359acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek } 360acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek llvm_unreachable("all cases handled"); 361acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek} 362acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek 363dc84cd5efdd3430efb22546b4ac656aa0540b210David Blaikiestatic Optional<bool> comparePath(const PathPieces &X, const PathPieces &Y) { 364acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek if (X.size() != Y.size()) 365acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek return X.size() < Y.size(); 366b5142359abc50e151c18bde88fbabec98b65077cTed Kremenek 367ed866e73bab7733f5226f84c52edefe23d694b2fTed Kremenek PathPieces::const_iterator X_I = X.begin(), X_end = X.end(); 368ed866e73bab7733f5226f84c52edefe23d694b2fTed Kremenek PathPieces::const_iterator Y_I = Y.begin(), Y_end = Y.end(); 369b5142359abc50e151c18bde88fbabec98b65077cTed Kremenek 370b5142359abc50e151c18bde88fbabec98b65077cTed Kremenek for ( ; X_I != X_end && Y_I != Y_end; ++X_I, ++Y_I) { 371ed866e73bab7733f5226f84c52edefe23d694b2fTed Kremenek Optional<bool> b = comparePiece(**X_I, **Y_I); 372acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek if (b.hasValue()) 373acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek return b.getValue(); 374acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek } 375b5142359abc50e151c18bde88fbabec98b65077cTed Kremenek 37666874fb18afbffb8b2ca05576851a64534be3352David Blaikie return None; 377acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek} 378acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek 379acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenekstatic bool compare(const PathDiagnostic &X, const PathDiagnostic &Y) { 380acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek FullSourceLoc XL = X.getLocation().asLocation(); 381acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek FullSourceLoc YL = Y.getLocation().asLocation(); 382acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek if (XL != YL) 383acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek return XL.isBeforeInTranslationUnitThan(YL); 384acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek if (X.getBugType() != Y.getBugType()) 385acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek return X.getBugType() < Y.getBugType(); 386acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek if (X.getCategory() != Y.getCategory()) 387acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek return X.getCategory() < Y.getCategory(); 388acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek if (X.getVerboseDescription() != Y.getVerboseDescription()) 389acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek return X.getVerboseDescription() < Y.getVerboseDescription(); 390acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek if (X.getShortDescription() != Y.getShortDescription()) 391acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek return X.getShortDescription() < Y.getShortDescription(); 392acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek if (X.getDeclWithIssue() != Y.getDeclWithIssue()) { 393acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek const Decl *XD = X.getDeclWithIssue(); 394acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek if (!XD) 395acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek return true; 396acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek const Decl *YD = Y.getDeclWithIssue(); 397acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek if (!YD) 398acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek return false; 399acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek SourceLocation XDL = XD->getLocation(); 400acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek SourceLocation YDL = YD->getLocation(); 40115f9f74f0cc7c2923b1977c6d33059251e6df204Ted Kremenek if (XDL != YDL) { 40215f9f74f0cc7c2923b1977c6d33059251e6df204Ted Kremenek const SourceManager &SM = XL.getManager(); 40315f9f74f0cc7c2923b1977c6d33059251e6df204Ted Kremenek return SM.isBeforeInTranslationUnit(XDL, YDL); 40415f9f74f0cc7c2923b1977c6d33059251e6df204Ted Kremenek } 405acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek } 406acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek PathDiagnostic::meta_iterator XI = X.meta_begin(), XE = X.meta_end(); 407acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek PathDiagnostic::meta_iterator YI = Y.meta_begin(), YE = Y.meta_end(); 408acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek if (XE - XI != YE - YI) 409acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek return (XE - XI) < (YE - YI); 410acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek for ( ; XI != XE ; ++XI, ++YI) { 411acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek if (*XI != *YI) 412acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek return (*XI) < (*YI); 413acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek } 414dc84cd5efdd3430efb22546b4ac656aa0540b210David Blaikie Optional<bool> b = comparePath(X.path, Y.path); 415acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek assert(b.hasValue()); 416acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek return b.getValue(); 417acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek} 418bac341346f3c8e713a8f165120fd54b500ee3189Ted Kremenek 419bac341346f3c8e713a8f165120fd54b500ee3189Ted Kremeneknamespace { 420bac341346f3c8e713a8f165120fd54b500ee3189Ted Kremenekstruct CompareDiagnostics { 421bac341346f3c8e713a8f165120fd54b500ee3189Ted Kremenek // Compare if 'X' is "<" than 'Y'. 422bac341346f3c8e713a8f165120fd54b500ee3189Ted Kremenek bool operator()(const PathDiagnostic *X, const PathDiagnostic *Y) const { 423acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek if (X == Y) 424acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek return false; 425acc714ba6c448e6dc278acf9b6eafee44d7f48a7Ted Kremenek return compare(*X, *Y); 4260187a1b8b9b2b7657de0ba8b0d4f67d30bec83e8Ted Kremenek } 4270187a1b8b9b2b7657de0ba8b0d4f67d30bec83e8Ted Kremenek}; 428bac341346f3c8e713a8f165120fd54b500ee3189Ted Kremenek} 429bac341346f3c8e713a8f165120fd54b500ee3189Ted Kremenek 430c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenekvoid PathDiagnosticConsumer::FlushDiagnostics( 431c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek PathDiagnosticConsumer::FilesMade *Files) { 432bac341346f3c8e713a8f165120fd54b500ee3189Ted Kremenek if (flushed) 433bac341346f3c8e713a8f165120fd54b500ee3189Ted Kremenek return; 434bac341346f3c8e713a8f165120fd54b500ee3189Ted Kremenek 435bac341346f3c8e713a8f165120fd54b500ee3189Ted Kremenek flushed = true; 436bac341346f3c8e713a8f165120fd54b500ee3189Ted Kremenek 437bac341346f3c8e713a8f165120fd54b500ee3189Ted Kremenek std::vector<const PathDiagnostic *> BatchDiags; 438bac341346f3c8e713a8f165120fd54b500ee3189Ted Kremenek for (llvm::FoldingSet<PathDiagnostic>::iterator it = Diags.begin(), 439bac341346f3c8e713a8f165120fd54b500ee3189Ted Kremenek et = Diags.end(); it != et; ++it) { 4400187a1b8b9b2b7657de0ba8b0d4f67d30bec83e8Ted Kremenek const PathDiagnostic *D = &*it; 4410187a1b8b9b2b7657de0ba8b0d4f67d30bec83e8Ted Kremenek BatchDiags.push_back(D); 442bac341346f3c8e713a8f165120fd54b500ee3189Ted Kremenek } 443bac341346f3c8e713a8f165120fd54b500ee3189Ted Kremenek 444bac341346f3c8e713a8f165120fd54b500ee3189Ted Kremenek // Sort the diagnostics so that they are always emitted in a deterministic 445bac341346f3c8e713a8f165120fd54b500ee3189Ted Kremenek // order. 446bac341346f3c8e713a8f165120fd54b500ee3189Ted Kremenek if (!BatchDiags.empty()) 447bac341346f3c8e713a8f165120fd54b500ee3189Ted Kremenek std::sort(BatchDiags.begin(), BatchDiags.end(), CompareDiagnostics()); 448bac341346f3c8e713a8f165120fd54b500ee3189Ted Kremenek 449bac341346f3c8e713a8f165120fd54b500ee3189Ted Kremenek FlushDiagnosticsImpl(BatchDiags, Files); 450bac341346f3c8e713a8f165120fd54b500ee3189Ted Kremenek 451bac341346f3c8e713a8f165120fd54b500ee3189Ted Kremenek // Delete the flushed diagnostics. 452bac341346f3c8e713a8f165120fd54b500ee3189Ted Kremenek for (std::vector<const PathDiagnostic *>::iterator it = BatchDiags.begin(), 453bac341346f3c8e713a8f165120fd54b500ee3189Ted Kremenek et = BatchDiags.end(); it != et; ++it) { 454bac341346f3c8e713a8f165120fd54b500ee3189Ted Kremenek const PathDiagnostic *D = *it; 455bac341346f3c8e713a8f165120fd54b500ee3189Ted Kremenek delete D; 456bac341346f3c8e713a8f165120fd54b500ee3189Ted Kremenek } 4570187a1b8b9b2b7657de0ba8b0d4f67d30bec83e8Ted Kremenek 4580187a1b8b9b2b7657de0ba8b0d4f67d30bec83e8Ted Kremenek // Clear out the FoldingSet. 4590187a1b8b9b2b7657de0ba8b0d4f67d30bec83e8Ted Kremenek Diags.clear(); 46007453ac7b3d46f930733b44a593737bdd98706b6Ted Kremenek} 46107453ac7b3d46f930733b44a593737bdd98706b6Ted Kremenek 462b75e2602e246b44bb285be8cc31166302d77998fTed Kremenekvoid PathDiagnosticConsumer::FilesMade::addDiagnostic(const PathDiagnostic &PD, 463b75e2602e246b44bb285be8cc31166302d77998fTed Kremenek StringRef ConsumerName, 464b75e2602e246b44bb285be8cc31166302d77998fTed Kremenek StringRef FileName) { 465b75e2602e246b44bb285be8cc31166302d77998fTed Kremenek llvm::FoldingSetNodeID NodeID; 4663a46f5fd1709f6df03bbb8b0abf84052dc0f39ffJordan Rose NodeID.Add(PD); 467b75e2602e246b44bb285be8cc31166302d77998fTed Kremenek void *InsertPos; 468b75e2602e246b44bb285be8cc31166302d77998fTed Kremenek PDFileEntry *Entry = FindNodeOrInsertPos(NodeID, InsertPos); 469b75e2602e246b44bb285be8cc31166302d77998fTed Kremenek if (!Entry) { 470b75e2602e246b44bb285be8cc31166302d77998fTed Kremenek Entry = Alloc.Allocate<PDFileEntry>(); 471b75e2602e246b44bb285be8cc31166302d77998fTed Kremenek Entry = new (Entry) PDFileEntry(NodeID); 472b75e2602e246b44bb285be8cc31166302d77998fTed Kremenek InsertNode(Entry, InsertPos); 473b75e2602e246b44bb285be8cc31166302d77998fTed Kremenek } 474b75e2602e246b44bb285be8cc31166302d77998fTed Kremenek 475b75e2602e246b44bb285be8cc31166302d77998fTed Kremenek // Allocate persistent storage for the file name. 476b75e2602e246b44bb285be8cc31166302d77998fTed Kremenek char *FileName_cstr = (char*) Alloc.Allocate(FileName.size(), 1); 477b75e2602e246b44bb285be8cc31166302d77998fTed Kremenek memcpy(FileName_cstr, FileName.data(), FileName.size()); 478b75e2602e246b44bb285be8cc31166302d77998fTed Kremenek 479b75e2602e246b44bb285be8cc31166302d77998fTed Kremenek Entry->files.push_back(std::make_pair(ConsumerName, 480b75e2602e246b44bb285be8cc31166302d77998fTed Kremenek StringRef(FileName_cstr, 481b75e2602e246b44bb285be8cc31166302d77998fTed Kremenek FileName.size()))); 482b75e2602e246b44bb285be8cc31166302d77998fTed Kremenek} 483b75e2602e246b44bb285be8cc31166302d77998fTed Kremenek 484b75e2602e246b44bb285be8cc31166302d77998fTed KremenekPathDiagnosticConsumer::PDFileEntry::ConsumerFiles * 485b75e2602e246b44bb285be8cc31166302d77998fTed KremenekPathDiagnosticConsumer::FilesMade::getFiles(const PathDiagnostic &PD) { 486b75e2602e246b44bb285be8cc31166302d77998fTed Kremenek llvm::FoldingSetNodeID NodeID; 4873a46f5fd1709f6df03bbb8b0abf84052dc0f39ffJordan Rose NodeID.Add(PD); 488b75e2602e246b44bb285be8cc31166302d77998fTed Kremenek void *InsertPos; 489b75e2602e246b44bb285be8cc31166302d77998fTed Kremenek PDFileEntry *Entry = FindNodeOrInsertPos(NodeID, InsertPos); 490b75e2602e246b44bb285be8cc31166302d77998fTed Kremenek if (!Entry) 491b75e2602e246b44bb285be8cc31166302d77998fTed Kremenek return 0; 492b75e2602e246b44bb285be8cc31166302d77998fTed Kremenek return &Entry->files; 493b75e2602e246b44bb285be8cc31166302d77998fTed Kremenek} 494b75e2602e246b44bb285be8cc31166302d77998fTed Kremenek 49597b40036d4d4d1bf4e7be71fc2bce009de4e8c0cTed Kremenek//===----------------------------------------------------------------------===// 49697b40036d4d4d1bf4e7be71fc2bce009de4e8c0cTed Kremenek// PathDiagnosticLocation methods. 49797b40036d4d4d1bf4e7be71fc2bce009de4e8c0cTed Kremenek//===----------------------------------------------------------------------===// 49897b40036d4d4d1bf4e7be71fc2bce009de4e8c0cTed Kremenek 4990cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaksstatic SourceLocation getValidSourceLocation(const Stmt* S, 500183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose LocationOrAnalysisDeclContext LAC, 501183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose bool UseEnd = false) { 502183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose SourceLocation L = UseEnd ? S->getLocEnd() : S->getLocStart(); 5031d26f48dc2eea1c07431ca1519d7034a21b9bcffTed Kremenek assert(!LAC.isNull() && "A valid LocationContext or AnalysisDeclContext should " 504b66f4867702697f1f097ab95f8a23a39310430e0Anna Zaks "be passed to PathDiagnosticLocation upon creation."); 5050cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks 5060cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks // S might be a temporary statement that does not have a location in the 507183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose // source code, so find an enclosing statement and use its location. 508e97436732c0f20aa15ecbf92a5f905eee888528fAnna Zaks if (!L.isValid()) { 509b66f4867702697f1f097ab95f8a23a39310430e0Anna Zaks 5101d3ca251f9891623fac0dbe70eece42564e274edJordan Rose AnalysisDeclContext *ADC; 511b66f4867702697f1f097ab95f8a23a39310430e0Anna Zaks if (LAC.is<const LocationContext*>()) 5121d3ca251f9891623fac0dbe70eece42564e274edJordan Rose ADC = LAC.get<const LocationContext*>()->getAnalysisDeclContext(); 513b66f4867702697f1f097ab95f8a23a39310430e0Anna Zaks else 5141d3ca251f9891623fac0dbe70eece42564e274edJordan Rose ADC = LAC.get<AnalysisDeclContext*>(); 5151d3ca251f9891623fac0dbe70eece42564e274edJordan Rose 5161d3ca251f9891623fac0dbe70eece42564e274edJordan Rose ParentMap &PM = ADC->getParentMap(); 5171d3ca251f9891623fac0dbe70eece42564e274edJordan Rose 5181d3ca251f9891623fac0dbe70eece42564e274edJordan Rose const Stmt *Parent = S; 5191d3ca251f9891623fac0dbe70eece42564e274edJordan Rose do { 5201d3ca251f9891623fac0dbe70eece42564e274edJordan Rose Parent = PM.getParent(Parent); 5211d3ca251f9891623fac0dbe70eece42564e274edJordan Rose 5221d3ca251f9891623fac0dbe70eece42564e274edJordan Rose // In rare cases, we have implicit top-level expressions, 5231d3ca251f9891623fac0dbe70eece42564e274edJordan Rose // such as arguments for implicit member initializers. 5241d3ca251f9891623fac0dbe70eece42564e274edJordan Rose // In this case, fall back to the start of the body (even if we were 5251d3ca251f9891623fac0dbe70eece42564e274edJordan Rose // asked for the statement end location). 5261d3ca251f9891623fac0dbe70eece42564e274edJordan Rose if (!Parent) { 5271d3ca251f9891623fac0dbe70eece42564e274edJordan Rose const Stmt *Body = ADC->getBody(); 5281d3ca251f9891623fac0dbe70eece42564e274edJordan Rose if (Body) 5291d3ca251f9891623fac0dbe70eece42564e274edJordan Rose L = Body->getLocStart(); 5301d3ca251f9891623fac0dbe70eece42564e274edJordan Rose else 5311d3ca251f9891623fac0dbe70eece42564e274edJordan Rose L = ADC->getDecl()->getLocEnd(); 5321d3ca251f9891623fac0dbe70eece42564e274edJordan Rose break; 5331d3ca251f9891623fac0dbe70eece42564e274edJordan Rose } 534e97436732c0f20aa15ecbf92a5f905eee888528fAnna Zaks 5351d3ca251f9891623fac0dbe70eece42564e274edJordan Rose L = UseEnd ? Parent->getLocEnd() : Parent->getLocStart(); 5361d3ca251f9891623fac0dbe70eece42564e274edJordan Rose } while (!L.isValid()); 5370cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks } 5380cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks 5390cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks return L; 5400cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks} 5410cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks 5427ad4848d4744b8d60289f3e359250cebdaaf7114Jordan Rosestatic PathDiagnosticLocation 5437ad4848d4744b8d60289f3e359250cebdaaf7114Jordan RosegetLocationForCaller(const StackFrameContext *SFC, 5447ad4848d4744b8d60289f3e359250cebdaaf7114Jordan Rose const LocationContext *CallerCtx, 5457ad4848d4744b8d60289f3e359250cebdaaf7114Jordan Rose const SourceManager &SM) { 5467ad4848d4744b8d60289f3e359250cebdaaf7114Jordan Rose const CFGBlock &Block = *SFC->getCallSiteBlock(); 5477ad4848d4744b8d60289f3e359250cebdaaf7114Jordan Rose CFGElement Source = Block[SFC->getIndex()]; 5487ad4848d4744b8d60289f3e359250cebdaaf7114Jordan Rose 5497ad4848d4744b8d60289f3e359250cebdaaf7114Jordan Rose switch (Source.getKind()) { 5507ad4848d4744b8d60289f3e359250cebdaaf7114Jordan Rose case CFGElement::Statement: 551fdf6a279c9a75c778eba382d9a156697092982a1David Blaikie return PathDiagnosticLocation(Source.castAs<CFGStmt>().getStmt(), 5527ad4848d4744b8d60289f3e359250cebdaaf7114Jordan Rose SM, CallerCtx); 5537ad4848d4744b8d60289f3e359250cebdaaf7114Jordan Rose case CFGElement::Initializer: { 554fdf6a279c9a75c778eba382d9a156697092982a1David Blaikie const CFGInitializer &Init = Source.castAs<CFGInitializer>(); 5557ad4848d4744b8d60289f3e359250cebdaaf7114Jordan Rose return PathDiagnosticLocation(Init.getInitializer()->getInit(), 5567ad4848d4744b8d60289f3e359250cebdaaf7114Jordan Rose SM, CallerCtx); 5577ad4848d4744b8d60289f3e359250cebdaaf7114Jordan Rose } 5587ad4848d4744b8d60289f3e359250cebdaaf7114Jordan Rose case CFGElement::AutomaticObjectDtor: { 559fdf6a279c9a75c778eba382d9a156697092982a1David Blaikie const CFGAutomaticObjDtor &Dtor = Source.castAs<CFGAutomaticObjDtor>(); 5607ad4848d4744b8d60289f3e359250cebdaaf7114Jordan Rose return PathDiagnosticLocation::createEnd(Dtor.getTriggerStmt(), 5617ad4848d4744b8d60289f3e359250cebdaaf7114Jordan Rose SM, CallerCtx); 5627ad4848d4744b8d60289f3e359250cebdaaf7114Jordan Rose } 5637ad4848d4744b8d60289f3e359250cebdaaf7114Jordan Rose case CFGElement::BaseDtor: 5647ad4848d4744b8d60289f3e359250cebdaaf7114Jordan Rose case CFGElement::MemberDtor: { 5657ad4848d4744b8d60289f3e359250cebdaaf7114Jordan Rose const AnalysisDeclContext *CallerInfo = CallerCtx->getAnalysisDeclContext(); 5667ad4848d4744b8d60289f3e359250cebdaaf7114Jordan Rose if (const Stmt *CallerBody = CallerInfo->getBody()) 5677ad4848d4744b8d60289f3e359250cebdaaf7114Jordan Rose return PathDiagnosticLocation::createEnd(CallerBody, SM, CallerCtx); 5687ad4848d4744b8d60289f3e359250cebdaaf7114Jordan Rose return PathDiagnosticLocation::create(CallerInfo->getDecl(), SM); 5697ad4848d4744b8d60289f3e359250cebdaaf7114Jordan Rose } 5707ad4848d4744b8d60289f3e359250cebdaaf7114Jordan Rose case CFGElement::TemporaryDtor: 5717ad4848d4744b8d60289f3e359250cebdaaf7114Jordan Rose llvm_unreachable("not yet implemented!"); 5727ad4848d4744b8d60289f3e359250cebdaaf7114Jordan Rose } 5737ad4848d4744b8d60289f3e359250cebdaaf7114Jordan Rose 5747ad4848d4744b8d60289f3e359250cebdaaf7114Jordan Rose llvm_unreachable("Unknown CFGElement kind"); 5757ad4848d4744b8d60289f3e359250cebdaaf7114Jordan Rose} 5767ad4848d4744b8d60289f3e359250cebdaaf7114Jordan Rose 5777ad4848d4744b8d60289f3e359250cebdaaf7114Jordan Rose 5780cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna ZaksPathDiagnosticLocation 579590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks PathDiagnosticLocation::createBegin(const Decl *D, 580590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks const SourceManager &SM) { 581590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks return PathDiagnosticLocation(D->getLocStart(), SM, SingleLocK); 582590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks} 583590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks 584590dd8e0959d8df5621827768987c4792b74fc06Anna ZaksPathDiagnosticLocation 585590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks PathDiagnosticLocation::createBegin(const Stmt *S, 586590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks const SourceManager &SM, 5871d26f48dc2eea1c07431ca1519d7034a21b9bcffTed Kremenek LocationOrAnalysisDeclContext LAC) { 588b66f4867702697f1f097ab95f8a23a39310430e0Anna Zaks return PathDiagnosticLocation(getValidSourceLocation(S, LAC), 589b490c4bb01a5a3a86947851fa66823dda32ed012Anna Zaks SM, SingleLocK); 5900cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks} 5910cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks 592183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose 593183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan RosePathDiagnosticLocation 594183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan RosePathDiagnosticLocation::createEnd(const Stmt *S, 595183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose const SourceManager &SM, 596183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose LocationOrAnalysisDeclContext LAC) { 597183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose if (const CompoundStmt *CS = dyn_cast<CompoundStmt>(S)) 598183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose return createEndBrace(CS, SM); 599183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose return PathDiagnosticLocation(getValidSourceLocation(S, LAC, /*End=*/true), 600183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose SM, SingleLocK); 601183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose} 602183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose 6030cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna ZaksPathDiagnosticLocation 6040cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks PathDiagnosticLocation::createOperatorLoc(const BinaryOperator *BO, 6050cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks const SourceManager &SM) { 6060cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks return PathDiagnosticLocation(BO->getOperatorLoc(), SM, SingleLocK); 6070cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks} 6080cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks 6090cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna ZaksPathDiagnosticLocation 610590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks PathDiagnosticLocation::createMemberLoc(const MemberExpr *ME, 611590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks const SourceManager &SM) { 612590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks return PathDiagnosticLocation(ME->getMemberLoc(), SM, SingleLocK); 613590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks} 614590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks 615590dd8e0959d8df5621827768987c4792b74fc06Anna ZaksPathDiagnosticLocation 6160cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks PathDiagnosticLocation::createBeginBrace(const CompoundStmt *CS, 6170cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks const SourceManager &SM) { 6180cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks SourceLocation L = CS->getLBracLoc(); 6190cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks return PathDiagnosticLocation(L, SM, SingleLocK); 6200cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks} 6210cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks 6220cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna ZaksPathDiagnosticLocation 6230cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks PathDiagnosticLocation::createEndBrace(const CompoundStmt *CS, 6240cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks const SourceManager &SM) { 6250cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks SourceLocation L = CS->getRBracLoc(); 6260cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks return PathDiagnosticLocation(L, SM, SingleLocK); 6270cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks} 6280cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks 6290cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna ZaksPathDiagnosticLocation 6300cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks PathDiagnosticLocation::createDeclBegin(const LocationContext *LC, 6310cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks const SourceManager &SM) { 6320cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks // FIXME: Should handle CXXTryStmt if analyser starts supporting C++. 6330cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks if (const CompoundStmt *CS = 6340cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks dyn_cast_or_null<CompoundStmt>(LC->getDecl()->getBody())) 6350cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks if (!CS->body_empty()) { 6360cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks SourceLocation Loc = (*CS->body_begin())->getLocStart(); 6370cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks return PathDiagnosticLocation(Loc, SM, SingleLocK); 6380cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks } 6390cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks 6400cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks return PathDiagnosticLocation(); 6410cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks} 6420cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks 6430cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna ZaksPathDiagnosticLocation 6440cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks PathDiagnosticLocation::createDeclEnd(const LocationContext *LC, 6451531bb0c69d9afff6a6434e4cadf345eb628b287Anna Zaks const SourceManager &SM) { 6464fdf97bf51d2a156cec3232efd6dae110aa02aa0Anna Zaks SourceLocation L = LC->getDecl()->getBodyRBrace(); 6470cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks return PathDiagnosticLocation(L, SM, SingleLocK); 6484fdf97bf51d2a156cec3232efd6dae110aa02aa0Anna Zaks} 6494fdf97bf51d2a156cec3232efd6dae110aa02aa0Anna Zaks 6501531bb0c69d9afff6a6434e4cadf345eb628b287Anna ZaksPathDiagnosticLocation 6511531bb0c69d9afff6a6434e4cadf345eb628b287Anna Zaks PathDiagnosticLocation::create(const ProgramPoint& P, 6521531bb0c69d9afff6a6434e4cadf345eb628b287Anna Zaks const SourceManager &SMng) { 6534fdf97bf51d2a156cec3232efd6dae110aa02aa0Anna Zaks 6541531bb0c69d9afff6a6434e4cadf345eb628b287Anna Zaks const Stmt* S = 0; 6557a95de68c093991047ed8d339479ccad51b88663David Blaikie if (Optional<BlockEdge> BE = P.getAs<BlockEdge>()) { 6564fdf97bf51d2a156cec3232efd6dae110aa02aa0Anna Zaks const CFGBlock *BSrc = BE->getSrc(); 6574fdf97bf51d2a156cec3232efd6dae110aa02aa0Anna Zaks S = BSrc->getTerminatorCondition(); 6587a95de68c093991047ed8d339479ccad51b88663David Blaikie } else if (Optional<StmtPoint> SP = P.getAs<StmtPoint>()) { 6596a329ee7567cf3267ffab2bc755ea8c773d967e7Jordan Rose S = SP->getStmt(); 6607a95de68c093991047ed8d339479ccad51b88663David Blaikie if (P.getAs<PostStmtPurgeDeadSymbols>()) 66163bc186d6ac0b44ba4ec6fccb5f471b05c79b666Jordan Rose return PathDiagnosticLocation::createEnd(S, SMng, P.getLocationContext()); 662610f79cbab4d752349b5c81a94682a6a82b102e7Anna Zaks } else if (Optional<PostInitializer> PIP = P.getAs<PostInitializer>()) { 663610f79cbab4d752349b5c81a94682a6a82b102e7Anna Zaks return PathDiagnosticLocation(PIP->getInitializer()->getSourceLocation(), 664610f79cbab4d752349b5c81a94682a6a82b102e7Anna Zaks SMng); 6657a95de68c093991047ed8d339479ccad51b88663David Blaikie } else if (Optional<PostImplicitCall> PIE = P.getAs<PostImplicitCall>()) { 6667ad4848d4744b8d60289f3e359250cebdaaf7114Jordan Rose return PathDiagnosticLocation(PIE->getLocation(), SMng); 6677a95de68c093991047ed8d339479ccad51b88663David Blaikie } else if (Optional<CallEnter> CE = P.getAs<CallEnter>()) { 6687ad4848d4744b8d60289f3e359250cebdaaf7114Jordan Rose return getLocationForCaller(CE->getCalleeContext(), 6697ad4848d4744b8d60289f3e359250cebdaaf7114Jordan Rose CE->getLocationContext(), 6707ad4848d4744b8d60289f3e359250cebdaaf7114Jordan Rose SMng); 6717a95de68c093991047ed8d339479ccad51b88663David Blaikie } else if (Optional<CallExitEnd> CEE = P.getAs<CallExitEnd>()) { 6727ad4848d4744b8d60289f3e359250cebdaaf7114Jordan Rose return getLocationForCaller(CEE->getCalleeContext(), 6737ad4848d4744b8d60289f3e359250cebdaaf7114Jordan Rose CEE->getLocationContext(), 6747ad4848d4744b8d60289f3e359250cebdaaf7114Jordan Rose SMng); 6757a95de68c093991047ed8d339479ccad51b88663David Blaikie } else { 6766a329ee7567cf3267ffab2bc755ea8c773d967e7Jordan Rose llvm_unreachable("Unexpected ProgramPoint"); 6776a329ee7567cf3267ffab2bc755ea8c773d967e7Jordan Rose } 6784fdf97bf51d2a156cec3232efd6dae110aa02aa0Anna Zaks 6791531bb0c69d9afff6a6434e4cadf345eb628b287Anna Zaks return PathDiagnosticLocation(S, SMng, P.getLocationContext()); 6804fdf97bf51d2a156cec3232efd6dae110aa02aa0Anna Zaks} 6814fdf97bf51d2a156cec3232efd6dae110aa02aa0Anna Zaks 6820f8579274a010f360a371b53101859d9d6052314Anna Zaksconst Stmt *PathDiagnosticLocation::getStmt(const ExplodedNode *N) { 6830f8579274a010f360a371b53101859d9d6052314Anna Zaks ProgramPoint P = N->getLocation(); 6840f8579274a010f360a371b53101859d9d6052314Anna Zaks if (Optional<StmtPoint> SP = P.getAs<StmtPoint>()) 6850f8579274a010f360a371b53101859d9d6052314Anna Zaks return SP->getStmt(); 6860f8579274a010f360a371b53101859d9d6052314Anna Zaks if (Optional<BlockEdge> BE = P.getAs<BlockEdge>()) 6870f8579274a010f360a371b53101859d9d6052314Anna Zaks return BE->getSrc()->getTerminator(); 6880f8579274a010f360a371b53101859d9d6052314Anna Zaks if (Optional<CallEnter> CE = P.getAs<CallEnter>()) 6890f8579274a010f360a371b53101859d9d6052314Anna Zaks return CE->getCallExpr(); 6900f8579274a010f360a371b53101859d9d6052314Anna Zaks if (Optional<CallExitEnd> CEE = P.getAs<CallExitEnd>()) 6910f8579274a010f360a371b53101859d9d6052314Anna Zaks return CEE->getCalleeContext()->getCallSite(); 6920f8579274a010f360a371b53101859d9d6052314Anna Zaks if (Optional<PostInitializer> PIPP = P.getAs<PostInitializer>()) 6930f8579274a010f360a371b53101859d9d6052314Anna Zaks return PIPP->getInitializer()->getInit(); 6940f8579274a010f360a371b53101859d9d6052314Anna Zaks 6950f8579274a010f360a371b53101859d9d6052314Anna Zaks return 0; 6960f8579274a010f360a371b53101859d9d6052314Anna Zaks} 6970f8579274a010f360a371b53101859d9d6052314Anna Zaks 6980f8579274a010f360a371b53101859d9d6052314Anna Zaksconst Stmt *PathDiagnosticLocation::getNextStmt(const ExplodedNode *N) { 6990f8579274a010f360a371b53101859d9d6052314Anna Zaks for (N = N->getFirstSucc(); N; N = N->getFirstSucc()) { 7000f8579274a010f360a371b53101859d9d6052314Anna Zaks if (const Stmt *S = getStmt(N)) { 7010f8579274a010f360a371b53101859d9d6052314Anna Zaks // Check if the statement is '?' or '&&'/'||'. These are "merges", 7020f8579274a010f360a371b53101859d9d6052314Anna Zaks // not actual statement points. 7030f8579274a010f360a371b53101859d9d6052314Anna Zaks switch (S->getStmtClass()) { 7040f8579274a010f360a371b53101859d9d6052314Anna Zaks case Stmt::ChooseExprClass: 7050f8579274a010f360a371b53101859d9d6052314Anna Zaks case Stmt::BinaryConditionalOperatorClass: 7060f8579274a010f360a371b53101859d9d6052314Anna Zaks case Stmt::ConditionalOperatorClass: 7070f8579274a010f360a371b53101859d9d6052314Anna Zaks continue; 7080f8579274a010f360a371b53101859d9d6052314Anna Zaks case Stmt::BinaryOperatorClass: { 7090f8579274a010f360a371b53101859d9d6052314Anna Zaks BinaryOperatorKind Op = cast<BinaryOperator>(S)->getOpcode(); 7100f8579274a010f360a371b53101859d9d6052314Anna Zaks if (Op == BO_LAnd || Op == BO_LOr) 7110f8579274a010f360a371b53101859d9d6052314Anna Zaks continue; 7120f8579274a010f360a371b53101859d9d6052314Anna Zaks break; 7130f8579274a010f360a371b53101859d9d6052314Anna Zaks } 7140f8579274a010f360a371b53101859d9d6052314Anna Zaks default: 7150f8579274a010f360a371b53101859d9d6052314Anna Zaks break; 7160f8579274a010f360a371b53101859d9d6052314Anna Zaks } 7170f8579274a010f360a371b53101859d9d6052314Anna Zaks // We found the statement, so return it. 7180f8579274a010f360a371b53101859d9d6052314Anna Zaks return S; 7190f8579274a010f360a371b53101859d9d6052314Anna Zaks } 7200f8579274a010f360a371b53101859d9d6052314Anna Zaks } 7210f8579274a010f360a371b53101859d9d6052314Anna Zaks 7220f8579274a010f360a371b53101859d9d6052314Anna Zaks return 0; 7230f8579274a010f360a371b53101859d9d6052314Anna Zaks} 7240f8579274a010f360a371b53101859d9d6052314Anna Zaks 7250cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna ZaksPathDiagnosticLocation 7260f8579274a010f360a371b53101859d9d6052314Anna Zaks PathDiagnosticLocation::createEndOfPath(const ExplodedNode *N, 7270cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks const SourceManager &SM) { 72843f48b0b1bc763dc56db6e01de4fcc44ad389befAnna Zaks assert(N && "Cannot create a location with a null node."); 7290f8579274a010f360a371b53101859d9d6052314Anna Zaks const Stmt *S = getStmt(N); 73043f48b0b1bc763dc56db6e01de4fcc44ad389befAnna Zaks 7310f8579274a010f360a371b53101859d9d6052314Anna Zaks if (!S) 7320f8579274a010f360a371b53101859d9d6052314Anna Zaks S = getNextStmt(N); 73343f48b0b1bc763dc56db6e01de4fcc44ad389befAnna Zaks 734cf4ce93caedca1d91ec5824981f9e45eda20b261Jordan Rose if (S) { 7350f8579274a010f360a371b53101859d9d6052314Anna Zaks ProgramPoint P = N->getLocation(); 7360f8579274a010f360a371b53101859d9d6052314Anna Zaks const LocationContext *LC = N->getLocationContext(); 7370f8579274a010f360a371b53101859d9d6052314Anna Zaks 7380f8579274a010f360a371b53101859d9d6052314Anna Zaks // For member expressions, return the location of the '.' or '->'. 7390f8579274a010f360a371b53101859d9d6052314Anna Zaks if (const MemberExpr *ME = dyn_cast<MemberExpr>(S)) 7400f8579274a010f360a371b53101859d9d6052314Anna Zaks return PathDiagnosticLocation::createMemberLoc(ME, SM); 7410f8579274a010f360a371b53101859d9d6052314Anna Zaks 7420f8579274a010f360a371b53101859d9d6052314Anna Zaks // For binary operators, return the location of the operator. 7430f8579274a010f360a371b53101859d9d6052314Anna Zaks if (const BinaryOperator *B = dyn_cast<BinaryOperator>(S)) 7440f8579274a010f360a371b53101859d9d6052314Anna Zaks return PathDiagnosticLocation::createOperatorLoc(B, SM); 7450f8579274a010f360a371b53101859d9d6052314Anna Zaks 7460f8579274a010f360a371b53101859d9d6052314Anna Zaks if (P.getAs<PostStmtPurgeDeadSymbols>()) 7470f8579274a010f360a371b53101859d9d6052314Anna Zaks return PathDiagnosticLocation::createEnd(S, SM, LC); 7480f8579274a010f360a371b53101859d9d6052314Anna Zaks 749cf4ce93caedca1d91ec5824981f9e45eda20b261Jordan Rose if (S->getLocStart().isValid()) 750cf4ce93caedca1d91ec5824981f9e45eda20b261Jordan Rose return PathDiagnosticLocation(S, SM, LC); 751cf4ce93caedca1d91ec5824981f9e45eda20b261Jordan Rose return PathDiagnosticLocation(getValidSourceLocation(S, LC), SM); 752cf4ce93caedca1d91ec5824981f9e45eda20b261Jordan Rose } 753cf4ce93caedca1d91ec5824981f9e45eda20b261Jordan Rose 7540cd59482abd8aec9ed1eaad11f5fe9c1e42639f6Anna Zaks return createDeclEnd(N->getLocationContext(), SM); 7554d353eb8af7324c0ee3736c736668f6c9b162ee0Anna Zaks} 7564d353eb8af7324c0ee3736c736668f6c9b162ee0Anna Zaks 7571531bb0c69d9afff6a6434e4cadf345eb628b287Anna ZaksPathDiagnosticLocation PathDiagnosticLocation::createSingleLocation( 7581531bb0c69d9afff6a6434e4cadf345eb628b287Anna Zaks const PathDiagnosticLocation &PDL) { 7591531bb0c69d9afff6a6434e4cadf345eb628b287Anna Zaks FullSourceLoc L = PDL.asLocation(); 7601531bb0c69d9afff6a6434e4cadf345eb628b287Anna Zaks return PathDiagnosticLocation(L, L.getManager(), SingleLocK); 7611531bb0c69d9afff6a6434e4cadf345eb628b287Anna Zaks} 7621531bb0c69d9afff6a6434e4cadf345eb628b287Anna Zaks 763b490c4bb01a5a3a86947851fa66823dda32ed012Anna ZaksFullSourceLoc 76409ca9ef5f92cf4375a19bf7a80d571779c9f370fAnna Zaks PathDiagnosticLocation::genLocation(SourceLocation L, 7651d26f48dc2eea1c07431ca1519d7034a21b9bcffTed Kremenek LocationOrAnalysisDeclContext LAC) const { 7665fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek assert(isValid()); 767b77370289e818469250c640e1aa50b25ecffbce1Ted Kremenek // Note that we want a 'switch' here so that the compiler can warn us in 768b77370289e818469250c640e1aa50b25ecffbce1Ted Kremenek // case we add more cases. 76997b40036d4d4d1bf4e7be71fc2bce009de4e8c0cTed Kremenek switch (K) { 770fea5f5a1e8fe558d716ddeddf1aecf63f2e9a54fTed Kremenek case SingleLocK: 771fea5f5a1e8fe558d716ddeddf1aecf63f2e9a54fTed Kremenek case RangeK: 772a54650079b2aa7c683c05e4d5deea25c76ce3630Ted Kremenek break; 773fea5f5a1e8fe558d716ddeddf1aecf63f2e9a54fTed Kremenek case StmtK: 774f660f4b1bedd6b614acf52108894b805b807c50dTed Kremenek // Defensive checking. 775f660f4b1bedd6b614acf52108894b805b807c50dTed Kremenek if (!S) 776f660f4b1bedd6b614acf52108894b805b807c50dTed Kremenek break; 777b66f4867702697f1f097ab95f8a23a39310430e0Anna Zaks return FullSourceLoc(getValidSourceLocation(S, LAC), 7784d353eb8af7324c0ee3736c736668f6c9b162ee0Anna Zaks const_cast<SourceManager&>(*SM)); 779fea5f5a1e8fe558d716ddeddf1aecf63f2e9a54fTed Kremenek case DeclK: 780f660f4b1bedd6b614acf52108894b805b807c50dTed Kremenek // Defensive checking. 781f660f4b1bedd6b614acf52108894b805b807c50dTed Kremenek if (!D) 782f660f4b1bedd6b614acf52108894b805b807c50dTed Kremenek break; 783fea5f5a1e8fe558d716ddeddf1aecf63f2e9a54fTed Kremenek return FullSourceLoc(D->getLocation(), const_cast<SourceManager&>(*SM)); 78497b40036d4d4d1bf4e7be71fc2bce009de4e8c0cTed Kremenek } 7851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 786ef70724e66d8ede0edbe260fbcdd9781688bb1fdAnna Zaks return FullSourceLoc(L, const_cast<SourceManager&>(*SM)); 78797b40036d4d4d1bf4e7be71fc2bce009de4e8c0cTed Kremenek} 788becf8886d10c41a4605c5e66cd806492eb8b864cTed Kremenek 789b490c4bb01a5a3a86947851fa66823dda32ed012Anna ZaksPathDiagnosticRange 7901d26f48dc2eea1c07431ca1519d7034a21b9bcffTed Kremenek PathDiagnosticLocation::genRange(LocationOrAnalysisDeclContext LAC) const { 7915fb5dfb6646464db3cd6d54a6332375c8fe36b75Ted Kremenek assert(isValid()); 792becf8886d10c41a4605c5e66cd806492eb8b864cTed Kremenek // Note that we want a 'switch' here so that the compiler can warn us in 793becf8886d10c41a4605c5e66cd806492eb8b864cTed Kremenek // case we add more cases. 794becf8886d10c41a4605c5e66cd806492eb8b864cTed Kremenek switch (K) { 795fea5f5a1e8fe558d716ddeddf1aecf63f2e9a54fTed Kremenek case SingleLocK: 79609ca9ef5f92cf4375a19bf7a80d571779c9f370fAnna Zaks return PathDiagnosticRange(SourceRange(Loc,Loc), true); 797fea5f5a1e8fe558d716ddeddf1aecf63f2e9a54fTed Kremenek case RangeK: 798becf8886d10c41a4605c5e66cd806492eb8b864cTed Kremenek break; 7998f33290741c2c6190576523e06a0d3bb698554b1Ted Kremenek case StmtK: { 8008f33290741c2c6190576523e06a0d3bb698554b1Ted Kremenek const Stmt *S = asStmt(); 8018f33290741c2c6190576523e06a0d3bb698554b1Ted Kremenek switch (S->getStmtClass()) { 8028f33290741c2c6190576523e06a0d3bb698554b1Ted Kremenek default: 8038f33290741c2c6190576523e06a0d3bb698554b1Ted Kremenek break; 8041e63c29a2d9752f804d2b05015018d715a79525fTed Kremenek case Stmt::DeclStmtClass: { 8051e63c29a2d9752f804d2b05015018d715a79525fTed Kremenek const DeclStmt *DS = cast<DeclStmt>(S); 8061e63c29a2d9752f804d2b05015018d715a79525fTed Kremenek if (DS->isSingleDecl()) { 8071e63c29a2d9752f804d2b05015018d715a79525fTed Kremenek // Should always be the case, but we'll be defensive. 8081e63c29a2d9752f804d2b05015018d715a79525fTed Kremenek return SourceRange(DS->getLocStart(), 8091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump DS->getSingleDecl()->getLocation()); 8101e63c29a2d9752f804d2b05015018d715a79525fTed Kremenek } 8111e63c29a2d9752f804d2b05015018d715a79525fTed Kremenek break; 8121e63c29a2d9752f804d2b05015018d715a79525fTed Kremenek } 8138f33290741c2c6190576523e06a0d3bb698554b1Ted Kremenek // FIXME: Provide better range information for different 8148f33290741c2c6190576523e06a0d3bb698554b1Ted Kremenek // terminators. 8158f33290741c2c6190576523e06a0d3bb698554b1Ted Kremenek case Stmt::IfStmtClass: 8168f33290741c2c6190576523e06a0d3bb698554b1Ted Kremenek case Stmt::WhileStmtClass: 8178f33290741c2c6190576523e06a0d3bb698554b1Ted Kremenek case Stmt::DoStmtClass: 8188f33290741c2c6190576523e06a0d3bb698554b1Ted Kremenek case Stmt::ForStmtClass: 8198f33290741c2c6190576523e06a0d3bb698554b1Ted Kremenek case Stmt::ChooseExprClass: 8208f33290741c2c6190576523e06a0d3bb698554b1Ted Kremenek case Stmt::IndirectGotoStmtClass: 8218f33290741c2c6190576523e06a0d3bb698554b1Ted Kremenek case Stmt::SwitchStmtClass: 82256ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall case Stmt::BinaryConditionalOperatorClass: 8238f33290741c2c6190576523e06a0d3bb698554b1Ted Kremenek case Stmt::ConditionalOperatorClass: 8248f33290741c2c6190576523e06a0d3bb698554b1Ted Kremenek case Stmt::ObjCForCollectionStmtClass: { 825b66f4867702697f1f097ab95f8a23a39310430e0Anna Zaks SourceLocation L = getValidSourceLocation(S, LAC); 8268f33290741c2c6190576523e06a0d3bb698554b1Ted Kremenek return SourceRange(L, L); 8278f33290741c2c6190576523e06a0d3bb698554b1Ted Kremenek } 8288f33290741c2c6190576523e06a0d3bb698554b1Ted Kremenek } 82909ca9ef5f92cf4375a19bf7a80d571779c9f370fAnna Zaks SourceRange R = S->getSourceRange(); 83009ca9ef5f92cf4375a19bf7a80d571779c9f370fAnna Zaks if (R.isValid()) 83109ca9ef5f92cf4375a19bf7a80d571779c9f370fAnna Zaks return R; 83209ca9ef5f92cf4375a19bf7a80d571779c9f370fAnna Zaks break; 8338f33290741c2c6190576523e06a0d3bb698554b1Ted Kremenek } 834fea5f5a1e8fe558d716ddeddf1aecf63f2e9a54fTed Kremenek case DeclK: 835fea5f5a1e8fe558d716ddeddf1aecf63f2e9a54fTed Kremenek if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) 836fea5f5a1e8fe558d716ddeddf1aecf63f2e9a54fTed Kremenek return MD->getSourceRange(); 8377297134f128423fce2e88f92421ed135bded7d4eDouglas Gregor if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 838082a625c98588aa3e6f825c58e56ad13bd3d6de6Argyrios Kyrtzidis if (Stmt *Body = FD->getBody()) 839082a625c98588aa3e6f825c58e56ad13bd3d6de6Argyrios Kyrtzidis return Body->getSourceRange(); 8407297134f128423fce2e88f92421ed135bded7d4eDouglas Gregor } 841fea5f5a1e8fe558d716ddeddf1aecf63f2e9a54fTed Kremenek else { 842fea5f5a1e8fe558d716ddeddf1aecf63f2e9a54fTed Kremenek SourceLocation L = D->getLocation(); 8434c5fcd946971756bd644fe76511f292e10225981Ted Kremenek return PathDiagnosticRange(SourceRange(L, L), true); 844fea5f5a1e8fe558d716ddeddf1aecf63f2e9a54fTed Kremenek } 845becf8886d10c41a4605c5e66cd806492eb8b864cTed Kremenek } 8461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 84709ca9ef5f92cf4375a19bf7a80d571779c9f370fAnna Zaks return SourceRange(Loc,Loc); 848becf8886d10c41a4605c5e66cd806492eb8b864cTed Kremenek} 849becf8886d10c41a4605c5e66cd806492eb8b864cTed Kremenek 850fea5f5a1e8fe558d716ddeddf1aecf63f2e9a54fTed Kremenekvoid PathDiagnosticLocation::flatten() { 851fea5f5a1e8fe558d716ddeddf1aecf63f2e9a54fTed Kremenek if (K == StmtK) { 852fea5f5a1e8fe558d716ddeddf1aecf63f2e9a54fTed Kremenek K = RangeK; 853fea5f5a1e8fe558d716ddeddf1aecf63f2e9a54fTed Kremenek S = 0; 854fea5f5a1e8fe558d716ddeddf1aecf63f2e9a54fTed Kremenek D = 0; 855fea5f5a1e8fe558d716ddeddf1aecf63f2e9a54fTed Kremenek } 856fea5f5a1e8fe558d716ddeddf1aecf63f2e9a54fTed Kremenek else if (K == DeclK) { 857fea5f5a1e8fe558d716ddeddf1aecf63f2e9a54fTed Kremenek K = SingleLocK; 858fea5f5a1e8fe558d716ddeddf1aecf63f2e9a54fTed Kremenek S = 0; 859fea5f5a1e8fe558d716ddeddf1aecf63f2e9a54fTed Kremenek D = 0; 860fea5f5a1e8fe558d716ddeddf1aecf63f2e9a54fTed Kremenek } 861fea5f5a1e8fe558d716ddeddf1aecf63f2e9a54fTed Kremenek} 862fea5f5a1e8fe558d716ddeddf1aecf63f2e9a54fTed Kremenek 8632042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek//===----------------------------------------------------------------------===// 8642042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek// Manipulation of PathDiagnosticCallPieces. 8652042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek//===----------------------------------------------------------------------===// 8662042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek 8672042fc1f36d471f437023e8899f0c4fadded2341Ted KremenekPathDiagnosticCallPiece * 8682042fc1f36d471f437023e8899f0c4fadded2341Ted KremenekPathDiagnosticCallPiece::construct(const ExplodedNode *N, 8690b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks const CallExitEnd &CE, 8702042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek const SourceManager &SM) { 8710b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks const Decl *caller = CE.getLocationContext()->getDecl(); 872183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose PathDiagnosticLocation pos = getLocationForCaller(CE.getCalleeContext(), 873183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose CE.getLocationContext(), 874183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose SM); 8752042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek return new PathDiagnosticCallPiece(caller, pos); 8762042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek} 8772042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek 8782042fc1f36d471f437023e8899f0c4fadded2341Ted KremenekPathDiagnosticCallPiece * 8799373937945e1e075dfa08169eaccc1ad0b31f699Anna ZaksPathDiagnosticCallPiece::construct(PathPieces &path, 8809373937945e1e075dfa08169eaccc1ad0b31f699Anna Zaks const Decl *caller) { 8819373937945e1e075dfa08169eaccc1ad0b31f699Anna Zaks PathDiagnosticCallPiece *C = new PathDiagnosticCallPiece(path, caller); 8822042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek path.clear(); 8832042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek path.push_front(C); 8842042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek return C; 8852042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek} 8862042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek 8872042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenekvoid PathDiagnosticCallPiece::setCallee(const CallEnter &CE, 8882042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek const SourceManager &SM) { 889183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose const StackFrameContext *CalleeCtx = CE.getCalleeContext(); 890183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose Callee = CalleeCtx->getDecl(); 891183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose 892183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose callEnterWithin = PathDiagnosticLocation::createBegin(Callee, SM); 893183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose callEnter = getLocationForCaller(CalleeCtx, CE.getLocationContext(), SM); 8942042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek} 8952042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek 896e02be97811c785f91ac43a0feed2db862de1867fJordan Rosestatic inline void describeClass(raw_ostream &Out, const CXXRecordDecl *D, 897e02be97811c785f91ac43a0feed2db862de1867fJordan Rose StringRef Prefix = StringRef()) { 898e02be97811c785f91ac43a0feed2db862de1867fJordan Rose if (!D->getIdentifier()) 899e02be97811c785f91ac43a0feed2db862de1867fJordan Rose return; 900e02be97811c785f91ac43a0feed2db862de1867fJordan Rose Out << Prefix << '\'' << *D << '\''; 901e02be97811c785f91ac43a0feed2db862de1867fJordan Rose} 902e02be97811c785f91ac43a0feed2db862de1867fJordan Rose 903dc47c9a71c99ce2e5b9d84f1cd3487b6852b3543Jordan Rosestatic bool describeCodeDecl(raw_ostream &Out, const Decl *D, 904e02be97811c785f91ac43a0feed2db862de1867fJordan Rose bool ExtendedDescription, 905dc47c9a71c99ce2e5b9d84f1cd3487b6852b3543Jordan Rose StringRef Prefix = StringRef()) { 906dc47c9a71c99ce2e5b9d84f1cd3487b6852b3543Jordan Rose if (!D) 907dc47c9a71c99ce2e5b9d84f1cd3487b6852b3543Jordan Rose return false; 908dc47c9a71c99ce2e5b9d84f1cd3487b6852b3543Jordan Rose 909dc47c9a71c99ce2e5b9d84f1cd3487b6852b3543Jordan Rose if (isa<BlockDecl>(D)) { 910e02be97811c785f91ac43a0feed2db862de1867fJordan Rose if (ExtendedDescription) 911dc47c9a71c99ce2e5b9d84f1cd3487b6852b3543Jordan Rose Out << Prefix << "anonymous block"; 912e02be97811c785f91ac43a0feed2db862de1867fJordan Rose return ExtendedDescription; 913dc47c9a71c99ce2e5b9d84f1cd3487b6852b3543Jordan Rose } 914dc47c9a71c99ce2e5b9d84f1cd3487b6852b3543Jordan Rose 915dc47c9a71c99ce2e5b9d84f1cd3487b6852b3543Jordan Rose if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) { 916e02be97811c785f91ac43a0feed2db862de1867fJordan Rose Out << Prefix; 917e02be97811c785f91ac43a0feed2db862de1867fJordan Rose if (ExtendedDescription && !MD->isUserProvided()) { 918e02be97811c785f91ac43a0feed2db862de1867fJordan Rose if (MD->isExplicitlyDefaulted()) 919e02be97811c785f91ac43a0feed2db862de1867fJordan Rose Out << "defaulted "; 920e02be97811c785f91ac43a0feed2db862de1867fJordan Rose else 921e02be97811c785f91ac43a0feed2db862de1867fJordan Rose Out << "implicit "; 922e02be97811c785f91ac43a0feed2db862de1867fJordan Rose } 923e02be97811c785f91ac43a0feed2db862de1867fJordan Rose 924e02be97811c785f91ac43a0feed2db862de1867fJordan Rose if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(MD)) { 925e02be97811c785f91ac43a0feed2db862de1867fJordan Rose if (CD->isDefaultConstructor()) 926e02be97811c785f91ac43a0feed2db862de1867fJordan Rose Out << "default "; 927e02be97811c785f91ac43a0feed2db862de1867fJordan Rose else if (CD->isCopyConstructor()) 928e02be97811c785f91ac43a0feed2db862de1867fJordan Rose Out << "copy "; 929e02be97811c785f91ac43a0feed2db862de1867fJordan Rose else if (CD->isMoveConstructor()) 930e02be97811c785f91ac43a0feed2db862de1867fJordan Rose Out << "move "; 931e02be97811c785f91ac43a0feed2db862de1867fJordan Rose 932e02be97811c785f91ac43a0feed2db862de1867fJordan Rose Out << "constructor"; 933e02be97811c785f91ac43a0feed2db862de1867fJordan Rose describeClass(Out, MD->getParent(), " for "); 934e02be97811c785f91ac43a0feed2db862de1867fJordan Rose 935e02be97811c785f91ac43a0feed2db862de1867fJordan Rose } else if (isa<CXXDestructorDecl>(MD)) { 936e02be97811c785f91ac43a0feed2db862de1867fJordan Rose if (!MD->isUserProvided()) { 937e02be97811c785f91ac43a0feed2db862de1867fJordan Rose Out << "destructor"; 938e02be97811c785f91ac43a0feed2db862de1867fJordan Rose describeClass(Out, MD->getParent(), " for "); 939e02be97811c785f91ac43a0feed2db862de1867fJordan Rose } else { 940e02be97811c785f91ac43a0feed2db862de1867fJordan Rose // Use ~Foo for explicitly-written destructors. 941e02be97811c785f91ac43a0feed2db862de1867fJordan Rose Out << "'" << *MD << "'"; 942e02be97811c785f91ac43a0feed2db862de1867fJordan Rose } 943e02be97811c785f91ac43a0feed2db862de1867fJordan Rose 944e02be97811c785f91ac43a0feed2db862de1867fJordan Rose } else if (MD->isCopyAssignmentOperator()) { 945e02be97811c785f91ac43a0feed2db862de1867fJordan Rose Out << "copy assignment operator"; 946e02be97811c785f91ac43a0feed2db862de1867fJordan Rose describeClass(Out, MD->getParent(), " for "); 947e02be97811c785f91ac43a0feed2db862de1867fJordan Rose 948e02be97811c785f91ac43a0feed2db862de1867fJordan Rose } else if (MD->isMoveAssignmentOperator()) { 949e02be97811c785f91ac43a0feed2db862de1867fJordan Rose Out << "move assignment operator"; 950e02be97811c785f91ac43a0feed2db862de1867fJordan Rose describeClass(Out, MD->getParent(), " for "); 951e02be97811c785f91ac43a0feed2db862de1867fJordan Rose 952e02be97811c785f91ac43a0feed2db862de1867fJordan Rose } else { 953e02be97811c785f91ac43a0feed2db862de1867fJordan Rose if (MD->getParent()->getIdentifier()) 954e02be97811c785f91ac43a0feed2db862de1867fJordan Rose Out << "'" << *MD->getParent() << "::" << *MD << "'"; 955e02be97811c785f91ac43a0feed2db862de1867fJordan Rose else 956e02be97811c785f91ac43a0feed2db862de1867fJordan Rose Out << "'" << *MD << "'"; 957e02be97811c785f91ac43a0feed2db862de1867fJordan Rose } 958dc47c9a71c99ce2e5b9d84f1cd3487b6852b3543Jordan Rose 959dc47c9a71c99ce2e5b9d84f1cd3487b6852b3543Jordan Rose return true; 960dc47c9a71c99ce2e5b9d84f1cd3487b6852b3543Jordan Rose } 961dc47c9a71c99ce2e5b9d84f1cd3487b6852b3543Jordan Rose 962dc47c9a71c99ce2e5b9d84f1cd3487b6852b3543Jordan Rose Out << Prefix << '\'' << cast<NamedDecl>(*D) << '\''; 963dc47c9a71c99ce2e5b9d84f1cd3487b6852b3543Jordan Rose return true; 964dc47c9a71c99ce2e5b9d84f1cd3487b6852b3543Jordan Rose} 965dc47c9a71c99ce2e5b9d84f1cd3487b6852b3543Jordan Rose 9662042fc1f36d471f437023e8899f0c4fadded2341Ted KremenekIntrusiveRefCntPtr<PathDiagnosticEventPiece> 9672042fc1f36d471f437023e8899f0c4fadded2341Ted KremenekPathDiagnosticCallPiece::getCallEnterEvent() const { 9682042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek if (!Callee) 9692042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek return 0; 970dc47c9a71c99ce2e5b9d84f1cd3487b6852b3543Jordan Rose 9712042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek SmallString<256> buf; 9722042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek llvm::raw_svector_ostream Out(buf); 973dc47c9a71c99ce2e5b9d84f1cd3487b6852b3543Jordan Rose 974dc47c9a71c99ce2e5b9d84f1cd3487b6852b3543Jordan Rose Out << "Calling "; 975e02be97811c785f91ac43a0feed2db862de1867fJordan Rose describeCodeDecl(Out, Callee, /*ExtendedDescription=*/true); 976dc47c9a71c99ce2e5b9d84f1cd3487b6852b3543Jordan Rose 977368f3b070e8cb657a65bfa443d60256676d269e7Jordan Rose assert(callEnter.asLocation().isValid()); 978dc47c9a71c99ce2e5b9d84f1cd3487b6852b3543Jordan Rose return new PathDiagnosticEventPiece(callEnter, Out.str()); 9792042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek} 9802042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek 981097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted KremenekIntrusiveRefCntPtr<PathDiagnosticEventPiece> 982097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted KremenekPathDiagnosticCallPiece::getCallEnterWithinCallerEvent() const { 983368f3b070e8cb657a65bfa443d60256676d269e7Jordan Rose if (!callEnterWithin.asLocation().isValid()) 984368f3b070e8cb657a65bfa443d60256676d269e7Jordan Rose return 0; 985d474da062565596015558856333423199aed5eb1Jordan Rose if (Callee->isImplicit() || !Callee->hasBody()) 9862b9de0bc05e3e1092a9d1880e62aeaa54dc343e3Jordan Rose return 0; 9872b9de0bc05e3e1092a9d1880e62aeaa54dc343e3Jordan Rose if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Callee)) 9882b9de0bc05e3e1092a9d1880e62aeaa54dc343e3Jordan Rose if (MD->isDefaulted()) 9892b9de0bc05e3e1092a9d1880e62aeaa54dc343e3Jordan Rose return 0; 990dc47c9a71c99ce2e5b9d84f1cd3487b6852b3543Jordan Rose 991097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted Kremenek SmallString<256> buf; 992097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted Kremenek llvm::raw_svector_ostream Out(buf); 993dc47c9a71c99ce2e5b9d84f1cd3487b6852b3543Jordan Rose 994dc47c9a71c99ce2e5b9d84f1cd3487b6852b3543Jordan Rose Out << "Entered call"; 995e02be97811c785f91ac43a0feed2db862de1867fJordan Rose describeCodeDecl(Out, Caller, /*ExtendedDescription=*/false, " from "); 996dc47c9a71c99ce2e5b9d84f1cd3487b6852b3543Jordan Rose 997dc47c9a71c99ce2e5b9d84f1cd3487b6852b3543Jordan Rose return new PathDiagnosticEventPiece(callEnterWithin, Out.str()); 998097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted Kremenek} 999097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted Kremenek 1000097ebb3d8ce55d1f78a3f1e7a0978dbde5ee2898Ted KremenekIntrusiveRefCntPtr<PathDiagnosticEventPiece> 10012042fc1f36d471f437023e8899f0c4fadded2341Ted KremenekPathDiagnosticCallPiece::getCallExitEvent() const { 10029373937945e1e075dfa08169eaccc1ad0b31f699Anna Zaks if (NoExit) 10032042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek return 0; 1004dc47c9a71c99ce2e5b9d84f1cd3487b6852b3543Jordan Rose 10052042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek SmallString<256> buf; 10062042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek llvm::raw_svector_ostream Out(buf); 1007dc47c9a71c99ce2e5b9d84f1cd3487b6852b3543Jordan Rose 1008dc47c9a71c99ce2e5b9d84f1cd3487b6852b3543Jordan Rose if (!CallStackMessage.empty()) { 1009fbd58743fa6c793b84ed60a0e2325335a53da6c4Anna Zaks Out << CallStackMessage; 1010dc47c9a71c99ce2e5b9d84f1cd3487b6852b3543Jordan Rose } else { 1011e02be97811c785f91ac43a0feed2db862de1867fJordan Rose bool DidDescribe = describeCodeDecl(Out, Callee, 1012e02be97811c785f91ac43a0feed2db862de1867fJordan Rose /*ExtendedDescription=*/false, 1013dc47c9a71c99ce2e5b9d84f1cd3487b6852b3543Jordan Rose "Returning from "); 1014dc47c9a71c99ce2e5b9d84f1cd3487b6852b3543Jordan Rose if (!DidDescribe) 1015dc47c9a71c99ce2e5b9d84f1cd3487b6852b3543Jordan Rose Out << "Returning to caller"; 1016dc47c9a71c99ce2e5b9d84f1cd3487b6852b3543Jordan Rose } 1017dc47c9a71c99ce2e5b9d84f1cd3487b6852b3543Jordan Rose 1018368f3b070e8cb657a65bfa443d60256676d269e7Jordan Rose assert(callReturn.asLocation().isValid()); 10192042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek return new PathDiagnosticEventPiece(callReturn, Out.str()); 10202042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek} 10212042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek 10222042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenekstatic void compute_path_size(const PathPieces &pieces, unsigned &size) { 1023ed866e73bab7733f5226f84c52edefe23d694b2fTed Kremenek for (PathPieces::const_iterator it = pieces.begin(), 10242042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek et = pieces.end(); it != et; ++it) { 1025ed866e73bab7733f5226f84c52edefe23d694b2fTed Kremenek const PathDiagnosticPiece *piece = it->getPtr(); 10262042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek if (const PathDiagnosticCallPiece *cp = 10272042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek dyn_cast<PathDiagnosticCallPiece>(piece)) { 10282042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek compute_path_size(cp->path, size); 10292042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek } 10302042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek else 10312042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek ++size; 10322042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek } 10332042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek} 10342042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek 10352042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenekunsigned PathDiagnostic::full_size() { 10362042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek unsigned size = 0; 10372042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek compute_path_size(path, size); 10382042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek return size; 10392042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek} 10402042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek 1041db8338a35fa729c08bc2dfd87cdc43533506f548Ted Kremenek//===----------------------------------------------------------------------===// 1042db8338a35fa729c08bc2dfd87cdc43533506f548Ted Kremenek// FoldingSet profiling methods. 1043db8338a35fa729c08bc2dfd87cdc43533506f548Ted Kremenek//===----------------------------------------------------------------------===// 1044db8338a35fa729c08bc2dfd87cdc43533506f548Ted Kremenek 1045db8338a35fa729c08bc2dfd87cdc43533506f548Ted Kremenekvoid PathDiagnosticLocation::Profile(llvm::FoldingSetNodeID &ID) const { 104677ce46d769b581b8a6ddb0d58231b8be9a8a6026Anna Zaks ID.AddInteger(Range.getBegin().getRawEncoding()); 104777ce46d769b581b8a6ddb0d58231b8be9a8a6026Anna Zaks ID.AddInteger(Range.getEnd().getRawEncoding()); 104877ce46d769b581b8a6ddb0d58231b8be9a8a6026Anna Zaks ID.AddInteger(Loc.getRawEncoding()); 1049db8338a35fa729c08bc2dfd87cdc43533506f548Ted Kremenek return; 1050db8338a35fa729c08bc2dfd87cdc43533506f548Ted Kremenek} 1051db8338a35fa729c08bc2dfd87cdc43533506f548Ted Kremenek 1052db8338a35fa729c08bc2dfd87cdc43533506f548Ted Kremenekvoid PathDiagnosticPiece::Profile(llvm::FoldingSetNodeID &ID) const { 1053db8338a35fa729c08bc2dfd87cdc43533506f548Ted Kremenek ID.AddInteger((unsigned) getKind()); 1054db8338a35fa729c08bc2dfd87cdc43533506f548Ted Kremenek ID.AddString(str); 1055db8338a35fa729c08bc2dfd87cdc43533506f548Ted Kremenek // FIXME: Add profiling support for code hints. 1056db8338a35fa729c08bc2dfd87cdc43533506f548Ted Kremenek ID.AddInteger((unsigned) getDisplayHint()); 10572b2c49d2ac5adb34f900f7a854a3ad5a6b0dff3cTed Kremenek ArrayRef<SourceRange> Ranges = getRanges(); 10582b2c49d2ac5adb34f900f7a854a3ad5a6b0dff3cTed Kremenek for (ArrayRef<SourceRange>::iterator I = Ranges.begin(), E = Ranges.end(); 10592b2c49d2ac5adb34f900f7a854a3ad5a6b0dff3cTed Kremenek I != E; ++I) { 1060db8338a35fa729c08bc2dfd87cdc43533506f548Ted Kremenek ID.AddInteger(I->getBegin().getRawEncoding()); 1061db8338a35fa729c08bc2dfd87cdc43533506f548Ted Kremenek ID.AddInteger(I->getEnd().getRawEncoding()); 1062db8338a35fa729c08bc2dfd87cdc43533506f548Ted Kremenek } 1063db8338a35fa729c08bc2dfd87cdc43533506f548Ted Kremenek} 1064db8338a35fa729c08bc2dfd87cdc43533506f548Ted Kremenek 10652042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenekvoid PathDiagnosticCallPiece::Profile(llvm::FoldingSetNodeID &ID) const { 10662042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek PathDiagnosticPiece::Profile(ID); 1067ed866e73bab7733f5226f84c52edefe23d694b2fTed Kremenek for (PathPieces::const_iterator it = path.begin(), 10682042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek et = path.end(); it != et; ++it) { 1069ed866e73bab7733f5226f84c52edefe23d694b2fTed Kremenek ID.Add(**it); 10702042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek } 10712042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek} 10722042fc1f36d471f437023e8899f0c4fadded2341Ted Kremenek 1073db8338a35fa729c08bc2dfd87cdc43533506f548Ted Kremenekvoid PathDiagnosticSpotPiece::Profile(llvm::FoldingSetNodeID &ID) const { 1074db8338a35fa729c08bc2dfd87cdc43533506f548Ted Kremenek PathDiagnosticPiece::Profile(ID); 1075db8338a35fa729c08bc2dfd87cdc43533506f548Ted Kremenek ID.Add(Pos); 1076db8338a35fa729c08bc2dfd87cdc43533506f548Ted Kremenek} 1077fea5f5a1e8fe558d716ddeddf1aecf63f2e9a54fTed Kremenek 1078db8338a35fa729c08bc2dfd87cdc43533506f548Ted Kremenekvoid PathDiagnosticControlFlowPiece::Profile(llvm::FoldingSetNodeID &ID) const { 1079db8338a35fa729c08bc2dfd87cdc43533506f548Ted Kremenek PathDiagnosticPiece::Profile(ID); 1080db8338a35fa729c08bc2dfd87cdc43533506f548Ted Kremenek for (const_iterator I = begin(), E = end(); I != E; ++I) 1081db8338a35fa729c08bc2dfd87cdc43533506f548Ted Kremenek ID.Add(*I); 1082db8338a35fa729c08bc2dfd87cdc43533506f548Ted Kremenek} 1083db8338a35fa729c08bc2dfd87cdc43533506f548Ted Kremenek 1084db8338a35fa729c08bc2dfd87cdc43533506f548Ted Kremenekvoid PathDiagnosticMacroPiece::Profile(llvm::FoldingSetNodeID &ID) const { 1085db8338a35fa729c08bc2dfd87cdc43533506f548Ted Kremenek PathDiagnosticSpotPiece::Profile(ID); 1086ed866e73bab7733f5226f84c52edefe23d694b2fTed Kremenek for (PathPieces::const_iterator I = subPieces.begin(), E = subPieces.end(); 1087802e02463b880f53a6e645bde78cc412481ce9e0Ted Kremenek I != E; ++I) 1088ed866e73bab7733f5226f84c52edefe23d694b2fTed Kremenek ID.Add(**I); 1089db8338a35fa729c08bc2dfd87cdc43533506f548Ted Kremenek} 1090db8338a35fa729c08bc2dfd87cdc43533506f548Ted Kremenek 1091db8338a35fa729c08bc2dfd87cdc43533506f548Ted Kremenekvoid PathDiagnostic::Profile(llvm::FoldingSetNodeID &ID) const { 10923a46f5fd1709f6df03bbb8b0abf84052dc0f39ffJordan Rose ID.Add(getLocation()); 1093db8338a35fa729c08bc2dfd87cdc43533506f548Ted Kremenek ID.AddString(BugType); 10943a46f5fd1709f6df03bbb8b0abf84052dc0f39ffJordan Rose ID.AddString(VerboseDesc); 1095db8338a35fa729c08bc2dfd87cdc43533506f548Ted Kremenek ID.AddString(Category); 1096bac341346f3c8e713a8f165120fd54b500ee3189Ted Kremenek} 1097bac341346f3c8e713a8f165120fd54b500ee3189Ted Kremenek 1098bac341346f3c8e713a8f165120fd54b500ee3189Ted Kremenekvoid PathDiagnostic::FullProfile(llvm::FoldingSetNodeID &ID) const { 1099bac341346f3c8e713a8f165120fd54b500ee3189Ted Kremenek Profile(ID); 1100ed866e73bab7733f5226f84c52edefe23d694b2fTed Kremenek for (PathPieces::const_iterator I = path.begin(), E = path.end(); I != E; ++I) 1101ed866e73bab7733f5226f84c52edefe23d694b2fTed Kremenek ID.Add(**I); 1102db8338a35fa729c08bc2dfd87cdc43533506f548Ted Kremenek for (meta_iterator I = meta_begin(), E = meta_end(); I != E; ++I) 1103db8338a35fa729c08bc2dfd87cdc43533506f548Ted Kremenek ID.AddString(*I); 1104db8338a35fa729c08bc2dfd87cdc43533506f548Ted Kremenek} 110556a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks 110656a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna ZaksStackHintGenerator::~StackHintGenerator() {} 110756a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks 110856a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaksstd::string StackHintGeneratorForSymbol::getMessage(const ExplodedNode *N){ 110956a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks ProgramPoint P = N->getLocation(); 1110df1f94ebfac4578e27ad008522c7b333e977e51bDavid Blaikie CallExitEnd CExit = P.castAs<CallExitEnd>(); 111156a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks 1112183ba8e19d49ab1ae25d3cdd0a19591369c5ab9fJordan Rose // FIXME: Use CallEvent to abstract this over all calls. 1113df1f94ebfac4578e27ad008522c7b333e977e51bDavid Blaikie const Stmt *CallSite = CExit.getCalleeContext()->getCallSite(); 1114852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose const CallExpr *CE = dyn_cast_or_null<CallExpr>(CallSite); 111556a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks if (!CE) 111656a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks return ""; 111756a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks 111856a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks if (!N) 111956a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks return getMessageForSymbolNotFound(); 112056a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks 112156a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks // Check if one of the parameters are set to the interesting symbol. 112256a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks ProgramStateRef State = N->getState(); 112356a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks const LocationContext *LCtx = N->getLocationContext(); 112456a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks unsigned ArgIndex = 0; 112556a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks for (CallExpr::const_arg_iterator I = CE->arg_begin(), 112656a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks E = CE->arg_end(); I != E; ++I, ++ArgIndex){ 112756a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks SVal SV = State->getSVal(*I, LCtx); 112856a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks 112956a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks // Check if the variable corresponding to the symbol is passed by value. 113056a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks SymbolRef AS = SV.getAsLocSymbol(); 113156a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks if (AS == Sym) { 113256a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks return getMessageForArg(*I, ArgIndex); 113356a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks } 113456a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks 113556a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks // Check if the parameter is a pointer to the symbol. 1136dc84cd5efdd3430efb22546b4ac656aa0540b210David Blaikie if (Optional<loc::MemRegionVal> Reg = SV.getAs<loc::MemRegionVal>()) { 113756a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks SVal PSV = State->getSVal(Reg->getRegion()); 113856a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks SymbolRef AS = PSV.getAsLocSymbol(); 113956a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks if (AS == Sym) { 114056a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks return getMessageForArg(*I, ArgIndex); 114156a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks } 114256a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks } 114356a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks } 114456a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks 114556a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks // Check if we are returning the interesting symbol. 114656a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks SVal SV = State->getSVal(CE, LCtx); 114756a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks SymbolRef RetSym = SV.getAsLocSymbol(); 114856a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks if (RetSym == Sym) { 114956a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks return getMessageForReturn(CE); 115056a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks } 115156a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks 115256a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks return getMessageForSymbolNotFound(); 115356a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks} 115456a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks 115556a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaksstd::string StackHintGeneratorForSymbol::getMessageForArg(const Expr *ArgE, 1156615a092a511cd2dfe1a5364ebf5f80e55e33034dJordan Rose unsigned ArgIndex) { 1157615a092a511cd2dfe1a5364ebf5f80e55e33034dJordan Rose // Printed parameters start at 1, not 0. 1158615a092a511cd2dfe1a5364ebf5f80e55e33034dJordan Rose ++ArgIndex; 1159615a092a511cd2dfe1a5364ebf5f80e55e33034dJordan Rose 116056a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks SmallString<200> buf; 116156a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks llvm::raw_svector_ostream os(buf); 116256a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks 1163615a092a511cd2dfe1a5364ebf5f80e55e33034dJordan Rose os << Msg << " via " << ArgIndex << llvm::getOrdinalSuffix(ArgIndex) 1164615a092a511cd2dfe1a5364ebf5f80e55e33034dJordan Rose << " parameter"; 116556a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks 116656a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks return os.str(); 116756a938ff85a444eb3d30d2634d92ce5b1f6fae56Anna Zaks} 1168