SourceLocation.h revision 0a449eed1dd2439b4b9c0a6291084816eab390c1
1//===--- SourceLocation.h - Compact identifier for Source Files -*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file was developed by Chris Lattner and is distributed under
6// the University of Illinois Open Source 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 <cassert>
18#include "llvm/Bitcode/SerializationFwd.h"
19
20namespace clang {
21
22/// SourceLocation - This is a carefully crafted 32-bit identifier that encodes
23/// a full include stack, line and column number information for a position in
24/// an input translation unit.
25class SourceLocation {
26  unsigned ID;
27public:
28  enum {
29    FileIDBits  = 14,
30    FilePosBits = 32-1-FileIDBits,
31
32    MacroIDBits       = 20,
33    MacroPhysOffsBits = 9,
34    MacroLogOffBits   = 2,
35
36    ChunkSize = (1 << FilePosBits)
37  };
38
39  SourceLocation() : ID(0) {}  // 0 is an invalid FileID.
40
41  bool isFileID() const { return (ID >> 31) == 0; }
42  bool isMacroID() const { return (ID >> 31) != 0; }
43
44  static SourceLocation getFileLoc(unsigned FileID, unsigned FilePos) {
45    SourceLocation L;
46    // If a FilePos is larger than (1<<FilePosBits), the SourceManager makes
47    // enough consequtive FileIDs that we have one for each chunk.
48    if (FilePos >= ChunkSize) {
49      FileID += FilePos >> FilePosBits;
50      FilePos &= ChunkSize-1;
51    }
52
53    // FIXME: Find a way to handle out of FileID bits!  Maybe MaxFileID is an
54    // escape of some sort?
55    assert(FileID < (1 << FileIDBits) && "Out of fileid's");
56
57    L.ID = (FileID << FilePosBits) | FilePos;
58    return L;
59  }
60
61  static bool isValidMacroPhysOffs(int Val) {
62    if (Val >= 0)
63      return Val < (1 << (MacroPhysOffsBits-1));
64    return -Val < (1 << (MacroPhysOffsBits-1));
65  }
66
67  static SourceLocation getMacroLoc(unsigned MacroID, int PhysOffs,
68                                    unsigned LogOffs) {
69    assert(MacroID < (1 << MacroIDBits) && "Too many macros!");
70    assert(isValidMacroPhysOffs(PhysOffs) && "Physoffs too large!");
71    assert(LogOffs  < (1 << MacroLogOffBits) && "Logical offs too large!");
72
73    PhysOffs &= (1 << MacroPhysOffsBits)-1;
74
75    SourceLocation L;
76    L.ID = (1 << 31) | (MacroID << (MacroPhysOffsBits+MacroLogOffBits)) |
77           (PhysOffs << MacroLogOffBits) |
78           LogOffs;
79    return L;
80  }
81
82
83  /// isValid - Return true if this is a valid SourceLocation object.  Invalid
84  /// SourceLocations are often used when events have no corresponding location
85  /// in the source (e.g. a diagnostic is required for a command line option).
86  ///
87  bool isValid() const { return ID != 0; }
88  bool isInvalid() const { return ID == 0; }
89
90  /// getFileID - Return the file identifier for this SourceLocation.  This
91  /// FileID can be used with the SourceManager object to obtain an entire
92  /// include stack for a file position reference.
93  unsigned getFileID() const {
94    assert(isFileID() && "can't get the file id of a non-file sloc!");
95    return ID >> FilePosBits;
96  }
97
98  /// getRawFilePos - Return the byte offset from the start of the file-chunk
99  /// referred to by FileID.  This method should not be used to get the offset
100  /// from the start of the file, instead you should use
101  /// SourceManager::getFilePos.  This method will be incorrect for large files.
102  unsigned getRawFilePos() const {
103    assert(isFileID() && "can't get the file id of a non-file sloc!");
104    return ID & (ChunkSize-1);
105  }
106
107  unsigned getMacroID() const {
108    assert(isMacroID() && "Is not a macro id!");
109    return (ID >> (MacroPhysOffsBits+MacroLogOffBits)) & ((1 << MacroIDBits)-1);
110  }
111
112  int getMacroPhysOffs() const {
113    assert(isMacroID() && "Is not a macro id!");
114    int Val = (ID >> MacroLogOffBits) & ((1 << MacroPhysOffsBits)-1);
115    // Sign extend it properly.
116    unsigned ShAmt = sizeof(int)*8 - MacroPhysOffsBits;
117    return (Val << ShAmt) >> ShAmt;
118  }
119
120  unsigned getMacroLogOffs() const {
121    assert(isMacroID() && "Is not a macro id!");
122    return ID & ((1 << MacroLogOffBits)-1);
123  }
124
125  /// getFileLocWithOffset - Return a source location with the specified offset
126  /// from this file SourceLocation.
127  SourceLocation getFileLocWithOffset(int Offset) const {
128    unsigned FileID = getFileID();
129    Offset += getRawFilePos();
130    // Handle negative offsets correctly.
131    while (Offset < 0) {
132      --FileID;
133      Offset += ChunkSize;
134    }
135    return getFileLoc(FileID, Offset);
136  }
137
138  /// getRawEncoding - When a SourceLocation itself cannot be used, this returns
139  /// an (opaque) 32-bit integer encoding for it.  This should only be passed
140  /// to SourceLocation::getFromRawEncoding, it should not be inspected
141  /// directly.
142  unsigned getRawEncoding() const { return ID; }
143
144  /// getFromRawEncoding - Turn a raw encoding of a SourceLocation object into
145  /// a real SourceLocation.
146  static SourceLocation getFromRawEncoding(unsigned Encoding) {
147    SourceLocation X;
148    X.ID = Encoding;
149    return X;
150  }
151};
152
153inline bool operator==(const SourceLocation &LHS, const SourceLocation &RHS) {
154  return LHS.getRawEncoding() == RHS.getRawEncoding();
155}
156
157inline bool operator!=(const SourceLocation &LHS, const SourceLocation &RHS) {
158  return !(LHS == RHS);
159}
160
161/// SourceRange - a trival tuple used to represent a source range.
162class SourceRange {
163  SourceLocation B;
164  SourceLocation E;
165public:
166  SourceRange(): B(SourceLocation()), E(SourceLocation()) {}
167  SourceRange(SourceLocation loc) : B(loc), E(loc) {}
168  SourceRange(SourceLocation begin, SourceLocation end) : B(begin), E(end) {}
169
170  SourceLocation getBegin() const { return B; }
171  SourceLocation getEnd() const { return E; }
172
173  void setBegin(SourceLocation b) { B = b; }
174  void setEnd(SourceLocation e) { E = e; }
175
176  bool isValid() const { return B.isValid() && E.isValid(); }
177};
178
179}  // end namespace clang
180
181//===----------------------------------------------------------------------===//
182// Serialization of SourceLocations and SourceRanges.
183//===----------------------------------------------------------------------===//
184
185namespace llvm {
186
187template<> struct SerializeTrait<clang::SourceLocation> {
188  static void Emit(Serializer& S, clang::SourceLocation L);
189  static clang::SourceLocation ReadVal(Deserializer& D);
190};
191
192template<> struct SerializeTrait<clang::SourceRange> {
193  static inline void Emit(Serializer& S, clang::SourceRange R) {
194    SerializeTrait<clang::SourceLocation>::Emit(S,R.getBegin());
195    SerializeTrait<clang::SourceLocation>::Emit(S,R.getEnd());
196  }
197
198  static inline clang::SourceRange ReadVal(Deserializer& D) {
199    using clang::SourceLocation;
200    SourceLocation L = SerializeTrait<SourceLocation>::ReadVal(D);
201    SourceLocation R = SerializeTrait<SourceLocation>::ReadVal(D);
202    return clang::SourceRange(L,R);
203  }
204};
205
206} // end namespace llvm
207
208#endif
209