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(&macro->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