PathDiagnostic.cpp revision 802e02463b880f53a6e645bde78cc412481ce9e0
1d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)//===--- PathDiagnostic.cpp - Path-Specific Diagnostic Handling -*- C++ -*-===//
2d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)//
3d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)//                     The LLVM Compiler Infrastructure
4d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)//
5d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// This file is distributed under the University of Illinois Open Source
6d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// License. See LICENSE.TXT for details.
7d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)//
8d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)//===----------------------------------------------------------------------===//
9d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)//
10d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)//  This file defines the PathDiagnostic-related interfaces.
11d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)//
12d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)//===----------------------------------------------------------------------===//
13d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
14d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
158bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
168bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "clang/AST/Expr.h"
17d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "clang/AST/Decl.h"
18d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "clang/AST/DeclObjC.h"
19d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "clang/AST/ParentMap.h"
20d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "clang/AST/StmtCXX.h"
21d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "llvm/ADT/SmallString.h"
22d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
23d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)using namespace clang;
24d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)using namespace ento;
25d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
26d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)bool PathDiagnosticMacroPiece::containsEvent() const {
27d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  for (PathPieces::const_iterator I = subPieces.begin(), E = subPieces.end();
28d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)       I!=E; ++I) {
29d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    if (isa<PathDiagnosticEventPiece>(*I))
30d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      return true;
31d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    if (PathDiagnosticMacroPiece *MP = dyn_cast<PathDiagnosticMacroPiece>(*I))
32d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      if (MP->containsEvent())
33d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        return true;
34d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
35d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  return false;
36d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
37d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
38d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)static StringRef StripTrailingDots(StringRef s) {
39d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  for (StringRef::size_type i = s.size(); i != 0; --i)
40d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    if (s[i - 1] != '.')
41d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      return s.substr(0, i);
42d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  return "";
43d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
44d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
45d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)PathDiagnosticPiece::PathDiagnosticPiece(StringRef s,
46d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                         Kind k, DisplayHint hint)
47d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  : str(StripTrailingDots(s)), kind(k), Hint(hint) {}
48d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)PathDiagnosticPiece::PathDiagnosticPiece(Kind k, DisplayHint hint)
508bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  : kind(k), Hint(hint) {}
518bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
528bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)PathDiagnosticPiece::~PathDiagnosticPiece() {}
538bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)PathDiagnosticEventPiece::~PathDiagnosticEventPiece() {}
548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)PathDiagnosticCallEnterPiece::~PathDiagnosticCallEnterPiece() {}
558bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)PathDiagnosticCallExitPiece::~PathDiagnosticCallExitPiece() {}
568bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)PathDiagnosticControlFlowPiece::~PathDiagnosticControlFlowPiece() {}
578bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)PathDiagnosticMacroPiece::~PathDiagnosticMacroPiece() {}
588bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)PathDiagnostic::PathDiagnostic() {}
598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)PathPieces::~PathPieces() {}
608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)PathDiagnostic::~PathDiagnostic() {}
618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
628bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)PathDiagnostic::PathDiagnostic(StringRef bugtype, StringRef desc,
638bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                               StringRef category)
648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  : BugType(StripTrailingDots(bugtype)),
658bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    Desc(StripTrailingDots(desc)),
668bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    Category(StripTrailingDots(category)) {}
678bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
688bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void PathDiagnosticConsumer::anchor() { }
698bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
708bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)PathDiagnosticConsumer::~PathDiagnosticConsumer() {
718bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // Delete the contents of the FoldingSet if it isn't empty already.
728bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  for (llvm::FoldingSet<PathDiagnostic>::iterator it =
738bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)       Diags.begin(), et = Diags.end() ; it != et ; ++it) {
748bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    delete &*it;
758bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
768bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
778bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
788bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void PathDiagnosticConsumer::HandlePathDiagnostic(PathDiagnostic *D) {
798bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (!D)
808bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return;
818bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
828bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (D->path.empty()) {
838bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    delete D;
848bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return;
858bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
86d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
87d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // We need to flatten the locations (convert Stmt* to locations) because
88d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // the referenced statements may be freed by the time the diagnostics
89d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // are emitted.
90d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  D->flattenLocations();
91d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
92d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Profile the node to see if we already have something matching it
93d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  llvm::FoldingSetNodeID profile;
94d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  D->Profile(profile);
95d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  void *InsertPos = 0;
96d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
97d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (PathDiagnostic *orig = Diags.FindNodeOrInsertPos(profile, InsertPos)) {
98d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // Keep the PathDiagnostic with the shorter path.
99d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    if (orig->path.size() <= D->path.size()) {
100d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      bool shouldKeepOriginal = true;
101d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      if (orig->path.size() == D->path.size()) {
102d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        // Here we break ties in a fairly arbitrary, but deterministic, way.
103d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        llvm::FoldingSetNodeID fullProfile, fullProfileOrig;
104d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        D->FullProfile(fullProfile);
105d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        orig->FullProfile(fullProfileOrig);
106d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        if (fullProfile.ComputeHash() < fullProfileOrig.ComputeHash())
107d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)          shouldKeepOriginal = false;
108d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      }
109d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
110d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      if (shouldKeepOriginal) {
111d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        delete D;
112d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        return;
113d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      }
114d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
115d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    Diags.RemoveNode(orig);
116d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    delete orig;
117d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
118d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
119d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  Diags.InsertNode(D);
120d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
121d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
122d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
123d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)namespace {
124d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)struct CompareDiagnostics {
125d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Compare if 'X' is "<" than 'Y'.
126d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  bool operator()(const PathDiagnostic *X, const PathDiagnostic *Y) const {
127d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // First compare by location
128d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    const FullSourceLoc &XLoc = X->getLocation().asLocation();
129d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    const FullSourceLoc &YLoc = Y->getLocation().asLocation();
130d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    if (XLoc < YLoc)
131d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      return true;
132d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    if (XLoc != YLoc)
133d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      return false;
1348bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1358bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // Next, compare by bug type.
1368bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    StringRef XBugType = X->getBugType();
1378bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    StringRef YBugType = Y->getBugType();
1388bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    if (XBugType < YBugType)
1398bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      return true;
1408bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    if (XBugType != YBugType)
1418bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      return false;
1428bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1438bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // Next, compare by bug description.
1448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    StringRef XDesc = X->getDescription();
1458bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    StringRef YDesc = Y->getDescription();
1468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    if (XDesc < YDesc)
147d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      return true;
148d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    if (XDesc != YDesc)
149d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      return false;
150d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
151d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // FIXME: Further refine by comparing PathDiagnosticPieces?
152d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    return false;
153d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
154d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)};
155d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
156d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
157d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void
158d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)PathDiagnosticConsumer::FlushDiagnostics(SmallVectorImpl<std::string> *Files) {
159d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (flushed)
160d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    return;
161d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
162d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  flushed = true;
163d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
164d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  std::vector<const PathDiagnostic *> BatchDiags;
165d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  for (llvm::FoldingSet<PathDiagnostic>::iterator it = Diags.begin(),
166d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)       et = Diags.end(); it != et; ++it) {
167d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    BatchDiags.push_back(&*it);
168d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
169d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
170d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Clear out the FoldingSet.
171d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  Diags.clear();
172d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
173d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Sort the diagnostics so that they are always emitted in a deterministic
174d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // order.
175d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (!BatchDiags.empty())
176d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    std::sort(BatchDiags.begin(), BatchDiags.end(), CompareDiagnostics());
177d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
178d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  FlushDiagnosticsImpl(BatchDiags, Files);
179d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
180d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Delete the flushed diagnostics.
181d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  for (std::vector<const PathDiagnostic *>::iterator it = BatchDiags.begin(),
182d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)       et = BatchDiags.end(); it != et; ++it) {
183d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    const PathDiagnostic *D = *it;
184d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    delete D;
185d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
186d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
187d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
188d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)//===----------------------------------------------------------------------===//
189d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// PathDiagnosticLocation methods.
190d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)//===----------------------------------------------------------------------===//
191d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
192d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)static SourceLocation getValidSourceLocation(const Stmt* S,
193d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                             LocationOrAnalysisDeclContext LAC) {
194d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  SourceLocation L = S->getLocStart();
195d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  assert(!LAC.isNull() && "A valid LocationContext or AnalysisDeclContext should "
196d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                          "be passed to PathDiagnosticLocation upon creation.");
197d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
198d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // S might be a temporary statement that does not have a location in the
199d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // source code, so find an enclosing statement and use it's location.
200d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (!L.isValid()) {
201d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
202d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    ParentMap *PM = 0;
203d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    if (LAC.is<const LocationContext*>())
204d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      PM = &LAC.get<const LocationContext*>()->getParentMap();
205d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    else
206d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      PM = &LAC.get<AnalysisDeclContext*>()->getParentMap();
207d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
208d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    while (!L.isValid()) {
209d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      S = PM->getParent(S);
210d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      L = S->getLocStart();
2118bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
2128bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
213d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
214d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  return L;
215d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
216d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
217d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)PathDiagnosticLocation
2188bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  PathDiagnosticLocation::createBegin(const Decl *D,
219d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                      const SourceManager &SM) {
220d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  return PathDiagnosticLocation(D->getLocStart(), SM, SingleLocK);
221d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
222d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
223d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)PathDiagnosticLocation
224d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  PathDiagnosticLocation::createBegin(const Stmt *S,
225d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                      const SourceManager &SM,
226d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                      LocationOrAnalysisDeclContext LAC) {
227d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  return PathDiagnosticLocation(getValidSourceLocation(S, LAC),
228d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                SM, SingleLocK);
229d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
230d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
231d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)PathDiagnosticLocation
232d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  PathDiagnosticLocation::createOperatorLoc(const BinaryOperator *BO,
233d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                            const SourceManager &SM) {
234d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  return PathDiagnosticLocation(BO->getOperatorLoc(), SM, SingleLocK);
235d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
236d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
237d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)PathDiagnosticLocation
238d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  PathDiagnosticLocation::createMemberLoc(const MemberExpr *ME,
239d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                          const SourceManager &SM) {
240d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  return PathDiagnosticLocation(ME->getMemberLoc(), SM, SingleLocK);
241d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
242d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
243d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)PathDiagnosticLocation
244d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  PathDiagnosticLocation::createBeginBrace(const CompoundStmt *CS,
245d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                           const SourceManager &SM) {
246d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  SourceLocation L = CS->getLBracLoc();
247d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  return PathDiagnosticLocation(L, SM, SingleLocK);
248d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
249d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
250d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)PathDiagnosticLocation
251d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  PathDiagnosticLocation::createEndBrace(const CompoundStmt *CS,
252d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                         const SourceManager &SM) {
253d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  SourceLocation L = CS->getRBracLoc();
254d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  return PathDiagnosticLocation(L, SM, SingleLocK);
255d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
256d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
257d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)PathDiagnosticLocation
258d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  PathDiagnosticLocation::createDeclBegin(const LocationContext *LC,
2598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                          const SourceManager &SM) {
2608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // FIXME: Should handle CXXTryStmt if analyser starts supporting C++.
2618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (const CompoundStmt *CS =
262d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        dyn_cast_or_null<CompoundStmt>(LC->getDecl()->getBody()))
263d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    if (!CS->body_empty()) {
264d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      SourceLocation Loc = (*CS->body_begin())->getLocStart();
265d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      return PathDiagnosticLocation(Loc, SM, SingleLocK);
266d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
267d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
268d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  return PathDiagnosticLocation();
269d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
270d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
271d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)PathDiagnosticLocation
272d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  PathDiagnosticLocation::createDeclEnd(const LocationContext *LC,
273d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                        const SourceManager &SM) {
274d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  SourceLocation L = LC->getDecl()->getBodyRBrace();
275d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  return PathDiagnosticLocation(L, SM, SingleLocK);
2768bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
2778bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
2788bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)PathDiagnosticLocation
2798bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  PathDiagnosticLocation::create(const ProgramPoint& P,
280d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                 const SourceManager &SMng) {
281d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
282d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  const Stmt* S = 0;
283d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (const BlockEdge *BE = dyn_cast<BlockEdge>(&P)) {
284d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    const CFGBlock *BSrc = BE->getSrc();
285d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    S = BSrc->getTerminatorCondition();
286d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
287  else if (const PostStmt *PS = dyn_cast<PostStmt>(&P)) {
288    S = PS->getStmt();
289  }
290
291  return PathDiagnosticLocation(S, SMng, P.getLocationContext());
292}
293
294PathDiagnosticLocation
295  PathDiagnosticLocation::createEndOfPath(const ExplodedNode* N,
296                                          const SourceManager &SM) {
297  assert(N && "Cannot create a location with a null node.");
298
299  const ExplodedNode *NI = N;
300
301  while (NI) {
302    ProgramPoint P = NI->getLocation();
303    const LocationContext *LC = P.getLocationContext();
304    if (const StmtPoint *PS = dyn_cast<StmtPoint>(&P))
305      return PathDiagnosticLocation(PS->getStmt(), SM, LC);
306    else if (const BlockEdge *BE = dyn_cast<BlockEdge>(&P)) {
307      const Stmt *Term = BE->getSrc()->getTerminator();
308      assert(Term);
309      return PathDiagnosticLocation(Term, SM, LC);
310    }
311    NI = NI->succ_empty() ? 0 : *(NI->succ_begin());
312  }
313
314  return createDeclEnd(N->getLocationContext(), SM);
315}
316
317PathDiagnosticLocation PathDiagnosticLocation::createSingleLocation(
318                                           const PathDiagnosticLocation &PDL) {
319  FullSourceLoc L = PDL.asLocation();
320  return PathDiagnosticLocation(L, L.getManager(), SingleLocK);
321}
322
323FullSourceLoc
324  PathDiagnosticLocation::genLocation(SourceLocation L,
325                                      LocationOrAnalysisDeclContext LAC) const {
326  assert(isValid());
327  // Note that we want a 'switch' here so that the compiler can warn us in
328  // case we add more cases.
329  switch (K) {
330    case SingleLocK:
331    case RangeK:
332      break;
333    case StmtK:
334      // Defensive checking.
335      if (!S)
336        break;
337      return FullSourceLoc(getValidSourceLocation(S, LAC),
338                           const_cast<SourceManager&>(*SM));
339    case DeclK:
340      // Defensive checking.
341      if (!D)
342        break;
343      return FullSourceLoc(D->getLocation(), const_cast<SourceManager&>(*SM));
344  }
345
346  return FullSourceLoc(L, const_cast<SourceManager&>(*SM));
347}
348
349PathDiagnosticRange
350  PathDiagnosticLocation::genRange(LocationOrAnalysisDeclContext LAC) const {
351  assert(isValid());
352  // Note that we want a 'switch' here so that the compiler can warn us in
353  // case we add more cases.
354  switch (K) {
355    case SingleLocK:
356      return PathDiagnosticRange(SourceRange(Loc,Loc), true);
357    case RangeK:
358      break;
359    case StmtK: {
360      const Stmt *S = asStmt();
361      switch (S->getStmtClass()) {
362        default:
363          break;
364        case Stmt::DeclStmtClass: {
365          const DeclStmt *DS = cast<DeclStmt>(S);
366          if (DS->isSingleDecl()) {
367            // Should always be the case, but we'll be defensive.
368            return SourceRange(DS->getLocStart(),
369                               DS->getSingleDecl()->getLocation());
370          }
371          break;
372        }
373          // FIXME: Provide better range information for different
374          //  terminators.
375        case Stmt::IfStmtClass:
376        case Stmt::WhileStmtClass:
377        case Stmt::DoStmtClass:
378        case Stmt::ForStmtClass:
379        case Stmt::ChooseExprClass:
380        case Stmt::IndirectGotoStmtClass:
381        case Stmt::SwitchStmtClass:
382        case Stmt::BinaryConditionalOperatorClass:
383        case Stmt::ConditionalOperatorClass:
384        case Stmt::ObjCForCollectionStmtClass: {
385          SourceLocation L = getValidSourceLocation(S, LAC);
386          return SourceRange(L, L);
387        }
388      }
389      SourceRange R = S->getSourceRange();
390      if (R.isValid())
391        return R;
392      break;
393    }
394    case DeclK:
395      if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
396        return MD->getSourceRange();
397      if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
398        if (Stmt *Body = FD->getBody())
399          return Body->getSourceRange();
400      }
401      else {
402        SourceLocation L = D->getLocation();
403        return PathDiagnosticRange(SourceRange(L, L), true);
404      }
405  }
406
407  return SourceRange(Loc,Loc);
408}
409
410void PathDiagnosticLocation::flatten() {
411  if (K == StmtK) {
412    K = RangeK;
413    S = 0;
414    D = 0;
415  }
416  else if (K == DeclK) {
417    K = SingleLocK;
418    S = 0;
419    D = 0;
420  }
421}
422
423//===----------------------------------------------------------------------===//
424// FoldingSet profiling methods.
425//===----------------------------------------------------------------------===//
426
427void PathDiagnosticLocation::Profile(llvm::FoldingSetNodeID &ID) const {
428  ID.AddInteger(Range.getBegin().getRawEncoding());
429  ID.AddInteger(Range.getEnd().getRawEncoding());
430  ID.AddInteger(Loc.getRawEncoding());
431  return;
432}
433
434void PathDiagnosticPiece::Profile(llvm::FoldingSetNodeID &ID) const {
435  ID.AddInteger((unsigned) getKind());
436  ID.AddString(str);
437  // FIXME: Add profiling support for code hints.
438  ID.AddInteger((unsigned) getDisplayHint());
439  for (range_iterator I = ranges_begin(), E = ranges_end(); I != E; ++I) {
440    ID.AddInteger(I->getBegin().getRawEncoding());
441    ID.AddInteger(I->getEnd().getRawEncoding());
442  }
443}
444
445void PathDiagnosticSpotPiece::Profile(llvm::FoldingSetNodeID &ID) const {
446  PathDiagnosticPiece::Profile(ID);
447  ID.Add(Pos);
448}
449
450void PathDiagnosticControlFlowPiece::Profile(llvm::FoldingSetNodeID &ID) const {
451  PathDiagnosticPiece::Profile(ID);
452  for (const_iterator I = begin(), E = end(); I != E; ++I)
453    ID.Add(*I);
454}
455
456void PathDiagnosticMacroPiece::Profile(llvm::FoldingSetNodeID &ID) const {
457  PathDiagnosticSpotPiece::Profile(ID);
458  for (PathPieces::const_iterator I = subPieces.begin(), E = subPieces.end();
459       I != E; ++I)
460    ID.Add(**I);
461}
462
463void PathDiagnostic::Profile(llvm::FoldingSetNodeID &ID) const {
464  if (!path.empty())
465    getLocation().Profile(ID);
466  ID.AddString(BugType);
467  ID.AddString(Desc);
468  ID.AddString(Category);
469}
470
471void PathDiagnostic::FullProfile(llvm::FoldingSetNodeID &ID) const {
472  Profile(ID);
473  for (PathPieces::const_iterator I = path.begin(), E = path.end(); I != E; ++I)
474    ID.Add(**I);
475  for (meta_iterator I = meta_begin(), E = meta_end(); I != E; ++I)
476    ID.AddString(*I);
477}
478