]> granicus.if.org Git - clang/blob - include/clang/Basic/SourceLocation.h
Rename SourceLocation::getFileID to getChunkID, because it returns
[clang] / include / clang / Basic / SourceLocation.h
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 <cassert>
18 #include "llvm/Bitcode/SerializationFwd.h"
19
20 namespace llvm {
21   class MemoryBuffer;
22   template <typename T> struct DenseMapInfo;
23 }
24
25 namespace clang {
26   
27 class SourceManager;
28 class FileEntry;
29   
30 /// FileID - This is an opaque identifier used by SourceManager which refers to
31 /// a source file (MemoryBuffer) along with its #include path and #line data.
32 ///
33 class FileID {
34   /// ID - Opaque identifier, 0 is "invalid".
35   unsigned ID;
36 public:
37   FileID() : ID(0) {}
38   
39   bool isInvalid() const { return ID == 0; }
40   
41   bool operator==(const FileID &RHS) const { return ID == RHS.ID; }
42   bool operator<(const FileID &RHS) const { return ID < RHS.ID; }
43   bool operator<=(const FileID &RHS) const { return ID <= RHS.ID; }
44   bool operator!=(const FileID &RHS) const { return !(*this == RHS); }
45   bool operator>(const FileID &RHS) const { return RHS < *this; }
46   bool operator>=(const FileID &RHS) const { return RHS <= *this; }
47   
48   static FileID getSentinel() { return Create(~0U); }
49   unsigned getHashValue() const { return ID; }
50   
51 private:
52   friend class SourceManager;
53   static FileID Create(unsigned V) {
54     FileID F;
55     F.ID = V;
56     return F;
57   }
58   unsigned getOpaqueValue() const { return ID; }
59 };
60   
61     
62 /// SourceLocation - This is a carefully crafted 32-bit identifier that encodes
63 /// a full include stack, line and column number information for a position in
64 /// an input translation unit.
65 class SourceLocation {
66   unsigned ID;
67 public:
68   enum {
69     // FileID Layout:
70     // bit 31: 0 -> FileID, 1 -> MacroID (invalid for FileID)
71     //     30...17 -> ChunkID of location, index into SourceManager table.
72     ChunkIDBits  = 14,
73     //      0...16 -> Index into the chunk of the specified ChunkID.
74     FilePosBits = 32-1-ChunkIDBits,
75     
76     // MacroID Layout:
77     // bit 31: 1 -> MacroID, 0 -> FileID (invalid for MacroID)
78
79     // bit 29,30: unused.
80     
81     // bits 28...9 -> MacroID number.
82     MacroIDBits       = 20,
83     // bits 8...0  -> Macro spelling offset
84     MacroSpellingOffsBits = 9,
85     
86     
87     // Useful constants.
88     ChunkSize = (1 << FilePosBits)
89   };
90
91   SourceLocation() : ID(0) {}  // 0 is an invalid FileID.
92   
93   bool isFileID() const { return (ID >> 31) == 0; }
94   bool isMacroID() const { return (ID >> 31) != 0; }
95   
96   /// isValid - Return true if this is a valid SourceLocation object.  Invalid
97   /// SourceLocations are often used when events have no corresponding location
98   /// in the source (e.g. a diagnostic is required for a command line option).
99   ///
100   bool isValid() const { return ID != 0; }
101   bool isInvalid() const { return ID == 0; }
102   
103   static SourceLocation getFileLoc(unsigned ChunkID, unsigned FilePos) {
104     SourceLocation L;
105     // If a FilePos is larger than (1<<FilePosBits), the SourceManager makes
106     // enough consequtive ChunkIDs that we have one for each chunk.
107     if (FilePos >= ChunkSize) {
108       ChunkID += FilePos >> FilePosBits;
109       FilePos &= ChunkSize-1;
110     }
111     
112     // FIXME: Find a way to handle out of ChunkID bits!  Maybe MaxFileID is an
113     // escape of some sort?
114     assert(ChunkID < (1 << ChunkIDBits) && "Out of ChunkID's");
115     
116     L.ID = (ChunkID << FilePosBits) | FilePos;
117     return L;
118   }
119   
120   static bool isValidMacroSpellingOffs(int Val) {
121     if (Val >= 0)
122       return Val < (1 << (MacroSpellingOffsBits-1));
123     return -Val <= (1 << (MacroSpellingOffsBits-1));
124   }
125   
126   static SourceLocation getMacroLoc(unsigned MacroID, int SpellingOffs) {
127     assert(MacroID < (1 << MacroIDBits) && "Too many macros!");
128     assert(isValidMacroSpellingOffs(SpellingOffs) &&"spelling offs too large!");
129     
130     // Mask off sign bits.
131     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
211 inline bool operator==(const SourceLocation &LHS, const SourceLocation &RHS) {
212   return LHS.getRawEncoding() == RHS.getRawEncoding();
213 }
214
215 inline 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.
220 class SourceRange {
221   SourceLocation B;
222   SourceLocation E;
223 public:
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.
245 class FullSourceLoc : public SourceLocation {
246   SourceManager* SrcMgr;
247 public:
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
307 namespace 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