SourceLocation.h revision 3b4d5e955e819dd3a4bed37ea2e47d6e4cb05274
15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//===--- SourceLocation.h - Compact identifier for Source Files -*- C++ -*-===//
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//                     The LLVM Compiler Infrastructure
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// This file is distributed under the University of Illinois Open Source
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// License. See LICENSE.TXT for details.
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//===----------------------------------------------------------------------===//
902772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch//
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//  This file defines the SourceLocation class.
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//
1202772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch//===----------------------------------------------------------------------===//
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#ifndef LLVM_CLANG_SOURCELOCATION_H
1502772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch#define LLVM_CLANG_SOURCELOCATION_H
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include <cassert>
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "llvm/Bitcode/SerializationFwd.h"
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace llvm {
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  class MemoryBuffer;
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  template <typename T> struct DenseMapInfo;
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace clang {
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)class SourceManager;
285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)class FileEntry;
295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/// FileID - This is an opaque identifier used by SourceManager which refers to
315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/// a source file (MemoryBuffer) along with its #include path and #line data.
32f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)///
331e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)class FileID {
34e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch  /// ID - Opaque identifier, 0 is "invalid".
35e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch  unsigned ID;
36e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdochpublic:
37e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch  FileID() : ID(0) {}
38e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  bool isInvalid() const { return ID == 0; }
40c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  bool operator==(const FileID &RHS) const { return ID == RHS.ID; }
425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  bool operator<(const FileID &RHS) const { return ID < RHS.ID; }
435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  bool operator<=(const FileID &RHS) const { return ID <= RHS.ID; }
445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  bool operator!=(const FileID &RHS) const { return !(*this == RHS); }
455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  bool operator>(const FileID &RHS) const { return RHS < *this; }
465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  bool operator>=(const FileID &RHS) const { return RHS <= *this; }
475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  static FileID getSentinel() { return Create(~0U); }
495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  unsigned getHashValue() const { return ID; }
505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)private:
525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  friend class SourceManager;
535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  static FileID Create(unsigned V) {
545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    FileID F;
555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    F.ID = V;
565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return F;
575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  unsigned getOpaqueValue() const { return ID; }
59e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch};
60e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/// SourceLocation - This is a carefully crafted 32-bit identifier that encodes
635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/// a full include stack, line and column number information for a position in
645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/// an input translation unit.
655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)class SourceLocation {
665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  unsigned ID;
675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)public:
685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  enum {
695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // FileID Layout:
70e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    // bit 31: 0 -> FileID, 1 -> MacroID (invalid for FileID)
715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    //     30...17 -> ChunkID of location, index into SourceManager table.
725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ChunkIDBits  = 14,
73e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    //      0...16 -> Index into the chunk of the specified ChunkID.
74e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    FilePosBits = 32-1-ChunkIDBits,
75e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // MacroID Layout:
7702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch    // bit 31: 1 -> MacroID, 0 -> FileID (invalid for MacroID)
785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // bit 29,30: unused.
805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // bits 28...9 -> MacroID number.
825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    MacroIDBits       = 20,
835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // bits 8...0  -> Macro spelling offset
845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    MacroSpellingOffsBits = 9,
855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Useful constants.
885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ChunkSize = (1 << FilePosBits)
895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  };
905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
91926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)  SourceLocation() : ID(0) {}  // 0 is an invalid FileID.
925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  bool isFileID() const { return (ID >> 31) == 0; }
945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  bool isMacroID() const { return (ID >> 31) != 0; }
955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  /// isValid - Return true if this is a valid SourceLocation object.  Invalid
975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  /// SourceLocations are often used when events have no corresponding location
985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  /// in the source (e.g. a diagnostic is required for a command line option).
995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  ///
1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  bool isValid() const { return ID != 0; }
1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  bool isInvalid() const { return ID == 0; }
1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  static SourceLocation getFileLoc(unsigned ChunkID, unsigned FilePos) {
1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    SourceLocation L;
1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // If a FilePos is larger than (1<<FilePosBits), the SourceManager makes
1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // enough consequtive ChunkIDs that we have one for each chunk.
1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (FilePos >= ChunkSize) {
1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      ChunkID += FilePos >> FilePosBits;
1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      FilePos &= ChunkSize-1;
1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // FIXME: Find a way to handle out of ChunkID bits!  Maybe MaxFileID is an
113197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // escape of some sort?
114197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    assert(ChunkID < (1 << ChunkIDBits) && "Out of ChunkID's");
1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    L.ID = (ChunkID << FilePosBits) | FilePos;
117926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return L;
1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
119926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  static bool isValidMacroSpellingOffs(int Val) {
1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (Val >= 0)
1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      return Val < (1 << (MacroSpellingOffsBits-1));
1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return -Val <= (1 << (MacroSpellingOffsBits-1));
1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  static SourceLocation getMacroLoc(unsigned MacroID, int SpellingOffs) {
1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    assert(MacroID < (1 << MacroIDBits) && "Too many macros!");
12802772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch    assert(isValidMacroSpellingOffs(SpellingOffs) &&"spelling offs too large!");
129c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Mask off sign bits.
1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    SpellingOffs &= (1 << MacroSpellingOffsBits)-1;
132
133    SourceLocation L;
134    L.ID = (1 << 31) |
135           (MacroID << MacroSpellingOffsBits) |
136           SpellingOffs;
137    return L;
138  }
139
140
141  /// getChunkID - Return the chunk identifier for this SourceLocation.  This
142  /// ChunkID can be used with the SourceManager object to obtain an entire
143  /// include stack for a file position reference.
144  unsigned getChunkID() const {
145    assert(isFileID() && "can't get the file id of a non-file sloc!");
146    return ID >> FilePosBits;
147  }
148
149  /// getRawFilePos - Return the byte offset from the start of the file-chunk
150  /// referred to by ChunkID.  This method should not be used to get the offset
151  /// from the start of the file, instead you should use
152  /// SourceManager::getDecomposedFileLoc.  This method will be
153  //  incorrect for large files.
154  unsigned getRawFilePos() const {
155    assert(isFileID() && "can't get the file id of a non-file sloc!");
156    return ID & (ChunkSize-1);
157  }
158
159  unsigned getMacroID() const {
160    assert(isMacroID() && "Is not a macro id!");
161    return (ID >> MacroSpellingOffsBits) & ((1 << MacroIDBits)-1);
162  }
163
164  int getMacroSpellingOffs() const {
165    assert(isMacroID() && "Is not a macro id!");
166    int Val = ID & ((1 << MacroSpellingOffsBits)-1);
167    // Sign extend it properly.
168    unsigned ShAmt = sizeof(int)*8 - MacroSpellingOffsBits;
169    return (Val << ShAmt) >> ShAmt;
170  }
171
172  /// getFileLocWithOffset - Return a source location with the specified offset
173  /// from this file SourceLocation.
174  SourceLocation getFileLocWithOffset(int Offset) const {
175    unsigned ChunkID = getChunkID();
176    Offset += getRawFilePos();
177    // Handle negative offsets correctly.
178    while (Offset < 0) {
179      --ChunkID;
180      Offset += ChunkSize;
181    }
182    return getFileLoc(ChunkID, Offset);
183  }
184
185  /// getRawEncoding - When a SourceLocation itself cannot be used, this returns
186  /// an (opaque) 32-bit integer encoding for it.  This should only be passed
187  /// to SourceLocation::getFromRawEncoding, it should not be inspected
188  /// directly.
189  unsigned getRawEncoding() const { return ID; }
190
191
192  bool operator<(const SourceLocation &RHS) const {
193    return ID < RHS.ID;
194  }
195
196  /// getFromRawEncoding - Turn a raw encoding of a SourceLocation object into
197  /// a real SourceLocation.
198  static SourceLocation getFromRawEncoding(unsigned Encoding) {
199    SourceLocation X;
200    X.ID = Encoding;
201    return X;
202  }
203
204  /// Emit - Emit this SourceLocation object to Bitcode.
205  void Emit(llvm::Serializer& S) const;
206
207  /// ReadVal - Read a SourceLocation object from Bitcode.
208  static SourceLocation ReadVal(llvm::Deserializer& D);
209};
210
211inline bool operator==(const SourceLocation &LHS, const SourceLocation &RHS) {
212  return LHS.getRawEncoding() == RHS.getRawEncoding();
213}
214
215inline bool operator!=(const SourceLocation &LHS, const SourceLocation &RHS) {
216  return !(LHS == RHS);
217}
218
219/// SourceRange - a trival tuple used to represent a source range.
220class SourceRange {
221  SourceLocation B;
222  SourceLocation E;
223public:
224  SourceRange(): B(SourceLocation()), E(SourceLocation()) {}
225  SourceRange(SourceLocation loc) : B(loc), E(loc) {}
226  SourceRange(SourceLocation begin, SourceLocation end) : B(begin), E(end) {}
227
228  SourceLocation getBegin() const { return B; }
229  SourceLocation getEnd() const { return E; }
230
231  void setBegin(SourceLocation b) { B = b; }
232  void setEnd(SourceLocation e) { E = e; }
233
234  bool isValid() const { return B.isValid() && E.isValid(); }
235
236  /// Emit - Emit this SourceRange object to Bitcode.
237  void Emit(llvm::Serializer& S) const;
238
239  /// ReadVal - Read a SourceRange object from Bitcode.
240  static SourceRange ReadVal(llvm::Deserializer& D);
241};
242
243/// FullSourceLoc - A SourceLocation and its associated SourceManager.  Useful
244/// for argument passing to functions that expect both objects.
245class FullSourceLoc : public SourceLocation {
246  SourceManager* SrcMgr;
247public:
248  // Creates a FullSourceLoc where isValid() returns false.
249  explicit FullSourceLoc() : SrcMgr((SourceManager*) 0) {}
250
251  explicit FullSourceLoc(SourceLocation Loc, SourceManager &SM)
252    : SourceLocation(Loc), SrcMgr(&SM) {}
253
254  SourceManager& getManager() {
255    assert (SrcMgr && "SourceManager is NULL.");
256    return *SrcMgr;
257  }
258
259  const SourceManager& getManager() const {
260    assert (SrcMgr && "SourceManager is NULL.");
261    return *SrcMgr;
262  }
263
264  FileID getFileID() const;
265
266  FullSourceLoc getInstantiationLoc() const;
267  FullSourceLoc getSpellingLoc() const;
268  FullSourceLoc getIncludeLoc() const;
269
270  unsigned getLineNumber() const;
271  unsigned getColumnNumber() const;
272
273  unsigned getInstantiationLineNumber() const;
274  unsigned getInstantiationColumnNumber() const;
275
276  unsigned getSpellingLineNumber() const;
277  unsigned getSpellingColumnNumber() const;
278
279  const char *getCharacterData() const;
280
281  const llvm::MemoryBuffer* getBuffer() const;
282
283  const char* getSourceName() const;
284  const FileEntry* getFileEntryForLoc() const;
285
286  bool isInSystemHeader() const;
287
288  /// Prints information about this FullSourceLoc to stderr. Useful for
289  ///  debugging.
290  void dump() const;
291
292  friend inline bool
293  operator==(const FullSourceLoc &LHS, const FullSourceLoc &RHS) {
294    return LHS.getRawEncoding() == RHS.getRawEncoding() &&
295          LHS.SrcMgr == RHS.SrcMgr;
296  }
297
298  friend inline bool
299  operator!=(const FullSourceLoc &LHS, const FullSourceLoc &RHS) {
300    return !(LHS == RHS);
301  }
302
303};
304
305}  // end namespace clang
306
307namespace llvm {
308  /// Define DenseMapInfo so that FileID's can be used as keys in DenseMap and
309  /// DenseSets.
310  template <>
311  struct DenseMapInfo<clang::FileID> {
312    static inline clang::FileID getEmptyKey() {
313      return clang::FileID();
314    }
315    static inline clang::FileID getTombstoneKey() {
316      return clang::FileID::getSentinel();
317    }
318
319    static unsigned getHashValue(clang::FileID S) {
320      return S.getHashValue();
321    }
322
323    static bool isEqual(clang::FileID LHS, clang::FileID RHS) {
324      return LHS == RHS;
325    }
326
327    static bool isPod() { return true; }
328  };
329
330}  // end namespace llvm
331
332#endif
333