SourceLocation.h revision a77c031cb66f75d22672070052cc6e0205289ff8
1//===--- SourceLocation.h - Compact identifier for Source Files -*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10//  This file defines the SourceLocation class.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_CLANG_SOURCELOCATION_H
15#define LLVM_CLANG_SOURCELOCATION_H
16
17#include "clang/Basic/LLVM.h"
18#include "llvm/Support/PointerLikeTypeTraits.h"
19#include <utility>
20#include <functional>
21#include <cassert>
22
23namespace llvm {
24  class MemoryBuffer;
25  template <typename T> struct DenseMapInfo;
26  template <typename T> struct isPodLike;
27}
28
29namespace clang {
30
31class SourceManager;
32
33/// FileID - This is an opaque identifier used by SourceManager which refers to
34/// a source file (MemoryBuffer) along with its #include path and #line data.
35///
36class FileID {
37  /// ID - Opaque identifier, 0 is "invalid". >0 is this module, <-1 is
38  /// something loaded from another module.
39  int ID;
40public:
41  FileID() : ID(0) {}
42
43  bool isInvalid() const { return ID == 0; }
44
45  bool operator==(const FileID &RHS) const { return ID == RHS.ID; }
46  bool operator<(const FileID &RHS) const { return ID < RHS.ID; }
47  bool operator<=(const FileID &RHS) const { return ID <= RHS.ID; }
48  bool operator!=(const FileID &RHS) const { return !(*this == RHS); }
49  bool operator>(const FileID &RHS) const { return RHS < *this; }
50  bool operator>=(const FileID &RHS) const { return RHS <= *this; }
51
52  static FileID getSentinel() { return get(-1); }
53  unsigned getHashValue() const { return static_cast<unsigned>(ID); }
54
55private:
56  friend class SourceManager;
57  friend class ASTWriter;
58  friend class ASTReader;
59
60  static FileID get(int V) {
61    FileID F;
62    F.ID = V;
63    return F;
64  }
65  int getOpaqueValue() const { return ID; }
66};
67
68
69/// \brief Encodes a location in the source. The SourceManager can decode this
70/// to get at the full include stack, line and column information.
71///
72/// Technically, a source location is simply an offset into the manager's view
73/// of the input source, which is all input buffers (including macro
74/// instantiations) concatenated in an effectively arbitrary order. The manager
75/// actually maintains two blocks of input buffers. One, starting at offset 0
76/// and growing upwards, contains all buffers from this module. The other,
77/// starting at the highest possible offset and growing downwards, contains
78/// buffers of loaded modules.
79///
80/// In addition, one bit of SourceLocation is used for quick access to the
81/// information whether the location is in a file or a macro instantiation.
82///
83/// It is important that this type remains small. It is currently 32 bits wide.
84class SourceLocation {
85  unsigned ID;
86  friend class SourceManager;
87  enum {
88    MacroIDBit = 1U << 31
89  };
90public:
91
92  SourceLocation() : ID(0) {}
93
94  bool isFileID() const  { return (ID & MacroIDBit) == 0; }
95  bool isMacroID() const { return (ID & MacroIDBit) != 0; }
96
97  /// \brief Return true if this is a valid SourceLocation object.
98  ///
99  /// Invalid SourceLocations are often used when events have no corresponding
100  /// location in the source (e.g. a diagnostic is required for a command line
101  /// option).
102  bool isValid() const { return ID != 0; }
103  bool isInvalid() const { return ID == 0; }
104
105private:
106  /// \brief Return the offset into the manager's global input view.
107  unsigned getOffset() const {
108    return ID & ~MacroIDBit;
109  }
110
111  static SourceLocation getFileLoc(unsigned ID) {
112    assert((ID & MacroIDBit) == 0 && "Ran out of source locations!");
113    SourceLocation L;
114    L.ID = ID;
115    return L;
116  }
117
118  static SourceLocation getMacroLoc(unsigned ID) {
119    assert((ID & MacroIDBit) == 0 && "Ran out of source locations!");
120    SourceLocation L;
121    L.ID = MacroIDBit | ID;
122    return L;
123  }
124public:
125
126  /// getFileLocWithOffset - Return a source location with the specified offset
127  /// from this file SourceLocation.
128  SourceLocation getFileLocWithOffset(int Offset) const {
129    assert(((getOffset()+Offset) & MacroIDBit) == 0 &&
130           "offset overflow or macro loc");
131    SourceLocation L;
132    L.ID = ID+Offset;
133    return L;
134  }
135
136  /// getRawEncoding - When a SourceLocation itself cannot be used, this returns
137  /// an (opaque) 32-bit integer encoding for it.  This should only be passed
138  /// to SourceLocation::getFromRawEncoding, it should not be inspected
139  /// directly.
140  unsigned getRawEncoding() const { return ID; }
141
142  /// getFromRawEncoding - Turn a raw encoding of a SourceLocation object into
143  /// a real SourceLocation.
144  static SourceLocation getFromRawEncoding(unsigned Encoding) {
145    SourceLocation X;
146    X.ID = Encoding;
147    return X;
148  }
149
150  /// getPtrEncoding - When a SourceLocation itself cannot be used, this returns
151  /// an (opaque) pointer encoding for it.  This should only be passed
152  /// to SourceLocation::getFromPtrEncoding, it should not be inspected
153  /// directly.
154  void* getPtrEncoding() const {
155    // Double cast to avoid a warning "cast to pointer from integer of different
156    // size".
157    return (void*)(uintptr_t)getRawEncoding();
158  }
159
160  /// getFromPtrEncoding - Turn a pointer encoding of a SourceLocation object
161  /// into a real SourceLocation.
162  static SourceLocation getFromPtrEncoding(void *Encoding) {
163    return getFromRawEncoding((unsigned)(uintptr_t)Encoding);
164  }
165
166  void print(raw_ostream &OS, const SourceManager &SM) const;
167  void dump(const SourceManager &SM) const;
168};
169
170inline bool operator==(const SourceLocation &LHS, const SourceLocation &RHS) {
171  return LHS.getRawEncoding() == RHS.getRawEncoding();
172}
173
174inline bool operator!=(const SourceLocation &LHS, const SourceLocation &RHS) {
175  return !(LHS == RHS);
176}
177
178inline bool operator<(const SourceLocation &LHS, const SourceLocation &RHS) {
179  return LHS.getRawEncoding() < RHS.getRawEncoding();
180}
181
182/// SourceRange - a trival tuple used to represent a source range.
183class SourceRange {
184  SourceLocation B;
185  SourceLocation E;
186public:
187  SourceRange(): B(SourceLocation()), E(SourceLocation()) {}
188  SourceRange(SourceLocation loc) : B(loc), E(loc) {}
189  SourceRange(SourceLocation begin, SourceLocation end) : B(begin), E(end) {}
190
191  SourceLocation getBegin() const { return B; }
192  SourceLocation getEnd() const { return E; }
193
194  void setBegin(SourceLocation b) { B = b; }
195  void setEnd(SourceLocation e) { E = e; }
196
197  bool isValid() const { return B.isValid() && E.isValid(); }
198  bool isInvalid() const { return !isValid(); }
199
200  bool operator==(const SourceRange &X) const {
201    return B == X.B && E == X.E;
202  }
203
204  bool operator!=(const SourceRange &X) const {
205    return B != X.B || E != X.E;
206  }
207};
208
209/// CharSourceRange - This class represents a character granular source range.
210/// The underlying SourceRange can either specify the starting/ending character
211/// of the range, or it can specify the start or the range and the start of the
212/// last token of the range (a "token range").  In the token range case, the
213/// size of the last token must be measured to determine the actual end of the
214/// range.
215class CharSourceRange {
216  SourceRange Range;
217  bool IsTokenRange;
218public:
219  CharSourceRange() : IsTokenRange(false) {}
220  CharSourceRange(SourceRange R, bool ITR) : Range(R),IsTokenRange(ITR){}
221
222  static CharSourceRange getTokenRange(SourceRange R) {
223    CharSourceRange Result;
224    Result.Range = R;
225    Result.IsTokenRange = true;
226    return Result;
227  }
228
229  static CharSourceRange getCharRange(SourceRange R) {
230    CharSourceRange Result;
231    Result.Range = R;
232    Result.IsTokenRange = false;
233    return Result;
234  }
235
236  static CharSourceRange getTokenRange(SourceLocation B, SourceLocation E) {
237    return getTokenRange(SourceRange(B, E));
238  }
239  static CharSourceRange getCharRange(SourceLocation B, SourceLocation E) {
240    return getCharRange(SourceRange(B, E));
241  }
242
243  /// isTokenRange - Return true if the end of this range specifies the start of
244  /// the last token.  Return false if the end of this range specifies the last
245  /// character in the range.
246  bool isTokenRange() const { return IsTokenRange; }
247
248  SourceLocation getBegin() const { return Range.getBegin(); }
249  SourceLocation getEnd() const { return Range.getEnd(); }
250  const SourceRange &getAsRange() const { return Range; }
251
252  void setBegin(SourceLocation b) { Range.setBegin(b); }
253  void setEnd(SourceLocation e) { Range.setEnd(e); }
254
255  bool isValid() const { return Range.isValid(); }
256  bool isInvalid() const { return !isValid(); }
257};
258
259/// FullSourceLoc - A SourceLocation and its associated SourceManager.  Useful
260/// for argument passing to functions that expect both objects.
261class FullSourceLoc : public SourceLocation {
262  const SourceManager *SrcMgr;
263public:
264  /// Creates a FullSourceLoc where isValid() returns false.
265  explicit FullSourceLoc() : SrcMgr(0) {}
266
267  explicit FullSourceLoc(SourceLocation Loc, const SourceManager &SM)
268    : SourceLocation(Loc), SrcMgr(&SM) {}
269
270  const SourceManager &getManager() const {
271    assert(SrcMgr && "SourceManager is NULL.");
272    return *SrcMgr;
273  }
274
275  FileID getFileID() const;
276
277  FullSourceLoc getExpansionLoc() const;
278  FullSourceLoc getSpellingLoc() const;
279
280  unsigned getInstantiationLineNumber(bool *Invalid = 0) const;
281  unsigned getExpansionColumnNumber(bool *Invalid = 0) const;
282
283  unsigned getSpellingLineNumber(bool *Invalid = 0) const;
284  unsigned getSpellingColumnNumber(bool *Invalid = 0) const;
285
286  const char *getCharacterData(bool *Invalid = 0) const;
287
288  const llvm::MemoryBuffer* getBuffer(bool *Invalid = 0) const;
289
290  /// getBufferData - Return a StringRef to the source buffer data for the
291  /// specified FileID.
292  StringRef getBufferData(bool *Invalid = 0) const;
293
294  /// getDecomposedLoc - Decompose the specified location into a raw FileID +
295  /// Offset pair.  The first element is the FileID, the second is the
296  /// offset from the start of the buffer of the location.
297  std::pair<FileID, unsigned> getDecomposedLoc() const;
298
299  bool isInSystemHeader() const;
300
301  /// \brief Determines the order of 2 source locations in the translation unit.
302  ///
303  /// \returns true if this source location comes before 'Loc', false otherwise.
304  bool isBeforeInTranslationUnitThan(SourceLocation Loc) const;
305
306  /// \brief Determines the order of 2 source locations in the translation unit.
307  ///
308  /// \returns true if this source location comes before 'Loc', false otherwise.
309  bool isBeforeInTranslationUnitThan(FullSourceLoc Loc) const {
310    assert(Loc.isValid());
311    assert(SrcMgr == Loc.SrcMgr && "Loc comes from another SourceManager!");
312    return isBeforeInTranslationUnitThan((SourceLocation)Loc);
313  }
314
315  /// \brief Comparison function class, useful for sorting FullSourceLocs.
316  struct BeforeThanCompare : public std::binary_function<FullSourceLoc,
317                                                         FullSourceLoc, bool> {
318    bool operator()(const FullSourceLoc& lhs, const FullSourceLoc& rhs) const {
319      return lhs.isBeforeInTranslationUnitThan(rhs);
320    }
321  };
322
323  /// Prints information about this FullSourceLoc to stderr. Useful for
324  ///  debugging.
325  void dump() const { SourceLocation::dump(*SrcMgr); }
326
327  friend inline bool
328  operator==(const FullSourceLoc &LHS, const FullSourceLoc &RHS) {
329    return LHS.getRawEncoding() == RHS.getRawEncoding() &&
330          LHS.SrcMgr == RHS.SrcMgr;
331  }
332
333  friend inline bool
334  operator!=(const FullSourceLoc &LHS, const FullSourceLoc &RHS) {
335    return !(LHS == RHS);
336  }
337
338};
339
340/// PresumedLoc - This class represents an unpacked "presumed" location which
341/// can be presented to the user.  A 'presumed' location can be modified by
342/// #line and GNU line marker directives and is always the instantiation point
343/// of a normal location.
344///
345/// You can get a PresumedLoc from a SourceLocation with SourceManager.
346class PresumedLoc {
347  const char *Filename;
348  unsigned Line, Col;
349  SourceLocation IncludeLoc;
350public:
351  PresumedLoc() : Filename(0) {}
352  PresumedLoc(const char *FN, unsigned Ln, unsigned Co, SourceLocation IL)
353    : Filename(FN), Line(Ln), Col(Co), IncludeLoc(IL) {
354  }
355
356  /// isInvalid - Return true if this object is invalid or uninitialized. This
357  /// occurs when created with invalid source locations or when walking off
358  /// the top of a #include stack.
359  bool isInvalid() const { return Filename == 0; }
360  bool isValid() const { return Filename != 0; }
361
362  /// getFilename - Return the presumed filename of this location.  This can be
363  /// affected by #line etc.
364  const char *getFilename() const { return Filename; }
365
366  /// getLine - Return the presumed line number of this location.  This can be
367  /// affected by #line etc.
368  unsigned getLine() const { return Line; }
369
370  /// getColumn - Return the presumed column number of this location.  This can
371  /// not be affected by #line, but is packaged here for convenience.
372  unsigned getColumn() const { return Col; }
373
374  /// getIncludeLoc - Return the presumed include location of this location.
375  /// This can be affected by GNU linemarker directives.
376  SourceLocation getIncludeLoc() const { return IncludeLoc; }
377};
378
379
380}  // end namespace clang
381
382namespace llvm {
383  /// Define DenseMapInfo so that FileID's can be used as keys in DenseMap and
384  /// DenseSets.
385  template <>
386  struct DenseMapInfo<clang::FileID> {
387    static inline clang::FileID getEmptyKey() {
388      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