SourceLocation.h revision db999aad8a1b9dc265b2e627be334be6580a86a3
14b95526e5c4eb4fecde1cd642cf991a82c51b9f2johannkoenig@chromium.org//===--- SourceLocation.h - Compact identifier for Source Files -*- C++ -*-===//
24b95526e5c4eb4fecde1cd642cf991a82c51b9f2johannkoenig@chromium.org//
36fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org//                     The LLVM Compiler Infrastructure
46fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org//
56fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org// This file is distributed under the University of Illinois Open Source
66fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org// License. See LICENSE.TXT for details.
76fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org//
86fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org//===----------------------------------------------------------------------===//
96fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org//
10dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org//  This file defines the SourceLocation class.
11dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org//
12dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org//===----------------------------------------------------------------------===//
13dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org
146fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org#ifndef LLVM_CLANG_SOURCELOCATION_H
156fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org#define LLVM_CLANG_SOURCELOCATION_H
166fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
176fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org#include "clang/Basic/LLVM.h"
186fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org#include "llvm/Support/PointerLikeTypeTraits.h"
196fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org#include <utility>
206fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org#include <functional>
216fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org#include <cassert>
226fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
236fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.orgnamespace llvm {
246fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  class MemoryBuffer;
256fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  template <typename T> struct DenseMapInfo;
266fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  template <typename T> struct isPodLike;
276fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org}
286fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
29daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.orgnamespace clang {
30daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org
31daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.orgclass SourceManager;
326fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
33daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org/// FileID - This is an opaque identifier used by SourceManager which refers to
34daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org/// a source file (MemoryBuffer) along with its #include path and #line data.
35daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org///
366fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.orgclass FileID {
37daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  /// ID - Opaque identifier, 0 is "invalid". >0 is this module, <-1 is
38daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  /// something loaded from another module.
39daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  int ID;
406fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.orgpublic:
41daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  FileID() : ID(0) {}
42daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org
43daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  bool isInvalid() const { return ID == 0; }
446fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
45daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  bool operator==(const FileID &RHS) const { return ID == RHS.ID; }
46daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  bool operator<(const FileID &RHS) const { return ID < RHS.ID; }
476fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  bool operator<=(const FileID &RHS) const { return ID <= RHS.ID; }
48daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  bool operator!=(const FileID &RHS) const { return !(*this == RHS); }
49daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  bool operator>(const FileID &RHS) const { return RHS < *this; }
506fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  bool operator>=(const FileID &RHS) const { return RHS <= *this; }
51daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org
52daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  static FileID getSentinel() { return get(-1); }
536fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  unsigned getHashValue() const { return static_cast<unsigned>(ID); }
54daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org
55daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.orgprivate:
566fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  friend class SourceManager;
57daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  friend class ASTWriter;
58daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  friend class ASTReader;
596fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
60daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  static FileID get(int V) {
61daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org    FileID F;
626fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    F.ID = V;
63daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org    return F;
64daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  }
656fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  int getOpaqueValue() const { return ID; }
666fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org};
676fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
686fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
696fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org/// \brief Encodes a location in the source. The SourceManager can decode this
706fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org/// to get at the full include stack, line and column information.
716fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org///
726fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org/// Technically, a source location is simply an offset into the manager's view
736fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org/// of the input source, which is all input buffers (including macro
74daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org/// instantiations) concatenated in an effectively arbitrary order. The manager
75daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org/// actually maintains two blocks of input buffers. One, starting at offset 0
76daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org/// and growing upwards, contains all buffers from this module. The other,
776fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org/// starting at the highest possible offset and growing downwards, contains
78daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org/// buffers of loaded modules.
79daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org///
80daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org/// In addition, one bit of SourceLocation is used for quick access to the
816fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org/// information whether the location is in a file or a macro instantiation.
82daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org///
83daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org/// It is important that this type remains small. It is currently 32 bits wide.
846fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.orgclass SourceLocation {
85daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  unsigned ID;
86daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  friend class SourceManager;
87daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  enum {
886fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    MacroIDBit = 1U << 31
89daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  };
90daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.orgpublic:
91daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org
926fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  SourceLocation() : ID(0) {}
93daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org
94daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  bool isFileID() const  { return (ID & MacroIDBit) == 0; }
95daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  bool isMacroID() const { return (ID & MacroIDBit) != 0; }
966fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
97daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  /// \brief Return true if this is a valid SourceLocation object.
98daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  ///
99daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  /// Invalid SourceLocations are often used when events have no corresponding
1006fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  /// location in the source (e.g. a diagnostic is required for a command line
101daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  /// option).
102daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  bool isValid() const { return ID != 0; }
1036fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  bool isInvalid() const { return ID == 0; }
104daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org
105daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.orgprivate:
106daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  /// \brief Return the offset into the manager's global input view.
1076fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  unsigned getOffset() const {
108daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org    return ID & ~MacroIDBit;
109daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  }
1106fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
1116fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  static SourceLocation getFileLoc(unsigned ID) {
1126fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    assert((ID & MacroIDBit) == 0 && "Ran out of source locations!");
1136fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    SourceLocation L;
1146fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    L.ID = ID;
1156fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    return L;
1166fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  }
117daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org
118daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  static SourceLocation getMacroLoc(unsigned ID) {
1196fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    assert((ID & MacroIDBit) == 0 && "Ran out of source locations!");
120daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org    SourceLocation L;
121daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org    L.ID = MacroIDBit | ID;
1226fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    return L;
123daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  }
124daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.orgpublic:
1256fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
126daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  /// getFileLocWithOffset - Return a source location with the specified offset
127daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  /// from this file SourceLocation.
1286fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  SourceLocation getFileLocWithOffset(int Offset) const {
129daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org    assert(((getOffset()+Offset) & MacroIDBit) == 0 &&
130daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org           "offset overflow or macro loc");
131daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org    SourceLocation L;
1326fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    L.ID = ID+Offset;
133daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org    return L;
134daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  }
135daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org
1366fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  /// getRawEncoding - When a SourceLocation itself cannot be used, this returns
137daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  /// an (opaque) 32-bit integer encoding for it.  This should only be passed
138daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  /// to SourceLocation::getFromRawEncoding, it should not be inspected
139daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  /// directly.
1406fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  unsigned getRawEncoding() const { return ID; }
141daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org
142daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  /// getFromRawEncoding - Turn a raw encoding of a SourceLocation object into
143daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  /// a real SourceLocation.
1446fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  static SourceLocation getFromRawEncoding(unsigned Encoding) {
145daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org    SourceLocation X;
146daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org    X.ID = Encoding;
147daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org    return X;
1486fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  }
149daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org
150daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  /// getPtrEncoding - When a SourceLocation itself cannot be used, this returns
151daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  /// an (opaque) pointer encoding for it.  This should only be passed
1526fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  /// to SourceLocation::getFromPtrEncoding, it should not be inspected
153daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  /// directly.
154daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  void* getPtrEncoding() const {
155daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org    // Double cast to avoid a warning "cast to pointer from integer of different
1566fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    // size".
157daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org    return (void*)(uintptr_t)getRawEncoding();
158daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  }
159daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org
1606fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  /// getFromPtrEncoding - Turn a pointer encoding of a SourceLocation object
161daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  /// into a real SourceLocation.
162daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  static SourceLocation getFromPtrEncoding(void *Encoding) {
163daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org    return getFromRawEncoding((unsigned)(uintptr_t)Encoding);
1646fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  }
165daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org
166daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  void print(raw_ostream &OS, const SourceManager &SM) const;
1676fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  void dump(const SourceManager &SM) const;
168daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org};
169daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org
1706fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.orginline bool operator==(const SourceLocation &LHS, const SourceLocation &RHS) {
171daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  return LHS.getRawEncoding() == RHS.getRawEncoding();
172daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org}
1736fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
174daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.orginline bool operator!=(const SourceLocation &LHS, const SourceLocation &RHS) {
175daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  return !(LHS == RHS);
1766fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org}
177daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org
178daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.orginline bool operator<(const SourceLocation &LHS, const SourceLocation &RHS) {
179daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  return LHS.getRawEncoding() < RHS.getRawEncoding();
1806fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org}
181daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org
182daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org/// SourceRange - a trival tuple used to represent a source range.
1836fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.orgclass SourceRange {
184daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  SourceLocation B;
185daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  SourceLocation E;
1866fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.orgpublic:
187daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  SourceRange(): B(SourceLocation()), E(SourceLocation()) {}
188daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  SourceRange(SourceLocation loc) : B(loc), E(loc) {}
1896fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  SourceRange(SourceLocation begin, SourceLocation end) : B(begin), E(end) {}
190daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org
191daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  SourceLocation getBegin() const { return B; }
1926fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  SourceLocation getEnd() const { return E; }
193daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org
194daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  void setBegin(SourceLocation b) { B = b; }
1956fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  void setEnd(SourceLocation e) { E = e; }
196daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org
197daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  bool isValid() const { return B.isValid() && E.isValid(); }
1986fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  bool isInvalid() const { return !isValid(); }
199daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org
200daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  bool operator==(const SourceRange &X) const {
201daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org    return B == X.B && E == X.E;
202daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  }
203daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org
2046fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  bool operator!=(const SourceRange &X) const {
2056fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    return B != X.B || E != X.E;
2066fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  }
2076fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org};
2086fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
209daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org/// CharSourceRange - This class represents a character granular source range.
210daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org/// The underlying SourceRange can either specify the starting/ending character
2116fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org/// of the range, or it can specify the start or the range and the start of the
212daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org/// last token of the range (a "token range").  In the token range case, the
213daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org/// size of the last token must be measured to determine the actual end of the
2146fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org/// range.
215daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.orgclass CharSourceRange {
216daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  SourceRange Range;
217daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  bool IsTokenRange;
218daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.orgpublic:
219daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  CharSourceRange() : IsTokenRange(false) {}
2206fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  CharSourceRange(SourceRange R, bool ITR) : Range(R),IsTokenRange(ITR){}
2216fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
2226fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  static CharSourceRange getTokenRange(SourceRange R) {
2236fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    CharSourceRange Result;
224daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org    Result.Range = R;
225daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org    Result.IsTokenRange = true;
2266fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    return Result;
2276fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  }
2286fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
2296fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  static CharSourceRange getCharRange(SourceRange R) {
230daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org    CharSourceRange Result;
231daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org    Result.Range = R;
232daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org    Result.IsTokenRange = false;
233daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org    return Result;
234daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  }
2356fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
2366fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  static CharSourceRange getTokenRange(SourceLocation B, SourceLocation E) {
2376fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    return getTokenRange(SourceRange(B, E));
2386fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  }
239daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  static CharSourceRange getCharRange(SourceLocation B, SourceLocation E) {
240daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org    return getCharRange(SourceRange(B, E));
241daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  }
242daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org
243daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  /// isTokenRange - Return true if the end of this range specifies the start of
244daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  /// the last token.  Return false if the end of this range specifies the last
245daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  /// character in the range.
246daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  bool isTokenRange() const { return IsTokenRange; }
2476fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
2486fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  SourceLocation getBegin() const { return Range.getBegin(); }
2496fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  SourceLocation getEnd() const { return Range.getEnd(); }
2506fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  const SourceRange &getAsRange() const { return Range; }
251daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org
252daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  void setBegin(SourceLocation b) { Range.setBegin(b); }
2536fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  void setEnd(SourceLocation e) { Range.setEnd(e); }
254daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org
255daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  bool isValid() const { return Range.isValid(); }
2566fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  bool isInvalid() const { return !isValid(); }
257daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org};
258daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org
2596fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org/// FullSourceLoc - A SourceLocation and its associated SourceManager.  Useful
260daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org/// for argument passing to functions that expect both objects.
261daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.orgclass FullSourceLoc : public SourceLocation {
2626fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  const SourceManager *SrcMgr;
263daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.orgpublic:
264daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  /// Creates a FullSourceLoc where isValid() returns false.
2656fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  explicit FullSourceLoc() : SrcMgr(0) {}
2666fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
2676fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  explicit FullSourceLoc(SourceLocation Loc, const SourceManager &SM)
2686fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    : SourceLocation(Loc), SrcMgr(&SM) {}
2696fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
2706fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  const SourceManager &getManager() const {
2716fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    assert(SrcMgr && "SourceManager is NULL.");
2726fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    return *SrcMgr;
2736fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  }
274daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org
275daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  FileID getFileID() const;
276daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org
277daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  FullSourceLoc getInstantiationLoc() const;
278daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  FullSourceLoc getSpellingLoc() const;
279daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org
280daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  unsigned getInstantiationLineNumber(bool *Invalid = 0) const;
281daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  unsigned getInstantiationColumnNumber(bool *Invalid = 0) const;
282daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org
283daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  unsigned getSpellingLineNumber(bool *Invalid = 0) const;
284daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  unsigned getSpellingColumnNumber(bool *Invalid = 0) const;
2856fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
2866fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  const char *getCharacterData(bool *Invalid = 0) const;
2876fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
2886fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  const llvm::MemoryBuffer* getBuffer(bool *Invalid = 0) const;
289daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org
290daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  /// getBufferData - Return a StringRef to the source buffer data for the
291daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  /// specified FileID.
2926fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  StringRef getBufferData(bool *Invalid = 0) const;
293daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org
294daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  /// getDecomposedLoc - Decompose the specified location into a raw FileID +
295daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  /// Offset pair.  The first element is the FileID, the second is the
2966fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  /// offset from the start of the buffer of the location.
297daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  std::pair<FileID, unsigned> getDecomposedLoc() const;
298daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org
299daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  bool isInSystemHeader() const;
3006fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
301daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  /// \brief Determines the order of 2 source locations in the translation unit.
302daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  ///
303daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  /// \returns true if this source location comes before 'Loc', false otherwise.
3046fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  bool isBeforeInTranslationUnitThan(SourceLocation Loc) const;
305daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org
306daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  /// \brief Determines the order of 2 source locations in the translation unit.
3076fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  ///
308daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  /// \returns true if this source location comes before 'Loc', false otherwise.
309daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  bool isBeforeInTranslationUnitThan(FullSourceLoc Loc) const {
310daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org    assert(Loc.isValid());
3116fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    assert(SrcMgr == Loc.SrcMgr && "Loc comes from another SourceManager!");
312daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org    return isBeforeInTranslationUnitThan((SourceLocation)Loc);
313daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  }
3146fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
315daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  /// \brief Comparison function class, useful for sorting FullSourceLocs.
316daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  struct BeforeThanCompare : public std::binary_function<FullSourceLoc,
3176fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org                                                         FullSourceLoc, bool> {
318daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org    bool operator()(const FullSourceLoc& lhs, const FullSourceLoc& rhs) const {
319daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org      return lhs.isBeforeInTranslationUnitThan(rhs);
3206fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    }
321daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  };
322daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org
323daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  /// Prints information about this FullSourceLoc to stderr. Useful for
3246fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  ///  debugging.
3256fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  void dump() const { SourceLocation::dump(*SrcMgr); }
3266fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
3276fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  friend inline bool
3286fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  operator==(const FullSourceLoc &LHS, const FullSourceLoc &RHS) {
329daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org    return LHS.getRawEncoding() == RHS.getRawEncoding() &&
330daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org          LHS.SrcMgr == RHS.SrcMgr;
331daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  }
332daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org
3336fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  friend inline bool
3346fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  operator!=(const FullSourceLoc &LHS, const FullSourceLoc &RHS) {
3356fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    return !(LHS == RHS);
3366fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  }
337daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org
338daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org};
339daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org
3406fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org/// PresumedLoc - This class represents an unpacked "presumed" location which
341daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org/// can be presented to the user.  A 'presumed' location can be modified by
342daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org/// #line and GNU line marker directives and is always the instantiation point
3436fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org/// of a normal location.
344daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org///
345daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org/// You can get a PresumedLoc from a SourceLocation with SourceManager.
3466fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.orgclass PresumedLoc {
347daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  const char *Filename;
348daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  unsigned Line, Col;
349daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  SourceLocation IncludeLoc;
350daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.orgpublic:
351daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  PresumedLoc() : Filename(0) {}
352daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  PresumedLoc(const char *FN, unsigned Ln, unsigned Co, SourceLocation IL)
353daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org    : Filename(FN), Line(Ln), Col(Co), IncludeLoc(IL) {
354daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  }
355daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org
356daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  /// isInvalid - Return true if this object is invalid or uninitialized. This
357daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  /// occurs when created with invalid source locations or when walking off
358daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  /// the top of a #include stack.
359daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  bool isInvalid() const { return Filename == 0; }
360daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  bool isValid() const { return Filename != 0; }
361daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org
362daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  /// getFilename - Return the presumed filename of this location.  This can be
363daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  /// affected by #line etc.
364daa317752787969f0b39e74dacf35acc11e4b79afgalligan@chromium.org  const char *getFilename() const { return Filename; }
3656fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
3666fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  /// getLine - Return the presumed line number of this location.  This can be
3676fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  /// affected by #line etc.
3686fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  unsigned getLine() const { return Line; }
3696fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
3706fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  /// getColumn - Return the presumed column number of this location.  This can
3716fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  /// not be affected by #line, but is packaged here for convenience.
3726fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  unsigned getColumn() const { return Col; }
3736fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
3746fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  /// getIncludeLoc - Return the presumed include location of this location.
3756fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  /// This can be affected by GNU linemarker directives.
3766fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  SourceLocation getIncludeLoc() const { return IncludeLoc; }
3776fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org};
3786fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
3796fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
3806fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org}  // end namespace clang
3816fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
3826fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.orgnamespace llvm {
383dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org  /// Define DenseMapInfo so that FileID's can be used as keys in DenseMap and
384dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org  /// DenseSets.
385dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org  template <>
386dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org  struct DenseMapInfo<clang::FileID> {
387dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org    static inline clang::FileID getEmptyKey() {
3886fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org      return clang::FileID();
389    }
390    static inline clang::FileID getTombstoneKey() {
391      return clang::FileID::getSentinel();
392    }
393
394    static unsigned getHashValue(clang::FileID S) {
395      return S.getHashValue();
396    }
397
398    static bool isEqual(clang::FileID LHS, clang::FileID RHS) {
399      return LHS == RHS;
400    }
401  };
402
403  template <>
404  struct isPodLike<clang::SourceLocation> { static const bool value = true; };
405  template <>
406  struct isPodLike<clang::FileID> { static const bool value = true; };
407
408  // Teach SmallPtrSet how to handle SourceLocation.
409  template<>
410  class PointerLikeTypeTraits<clang::SourceLocation> {
411  public:
412    static inline void *getAsVoidPointer(clang::SourceLocation L) {
413      return L.getPtrEncoding();
414    }
415    static inline clang::SourceLocation getFromVoidPointer(void *P) {
416      return clang::SourceLocation::getFromRawEncoding((unsigned)(uintptr_t)P);
417    }
418    enum { NumLowBitsAvailable = 0 };
419  };
420
421}  // end namespace llvm
422
423#endif
424