]> granicus.if.org Git - clang/blob - include/clang/Basic/SourceLocation.h
make a bunch of more SourceLocation methods private.
[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   friend class SourceManager;
68 public:
69   enum {
70     // FileID Layout:
71     // bit 31: 0 -> FileID, 1 -> MacroID (invalid for FileID)
72     //     30...17 -> ChunkID of location, index into SourceManager table.
73     ChunkIDBits  = 14,
74     //      0...16 -> Index into the chunk of the specified ChunkID.
75     FilePosBits = 32-1-ChunkIDBits,
76     
77     // MacroID Layout:
78     // bit 31: 1 -> MacroID, 0 -> FileID (invalid for MacroID)
79
80     // bit 29,30: unused.
81     
82     // bits 28...9 -> MacroID number.
83     MacroIDBits       = 20,
84     // bits 8...0  -> Macro spelling offset
85     MacroSpellingOffsBits = 9,
86     
87     
88     // Useful constants.
89     ChunkSize = (1 << FilePosBits)
90   };
91
92   SourceLocation() : ID(0) {}  // 0 is an invalid FileID.
93   
94   bool isFileID() const { return (ID >> 31) == 0; }
95   bool isMacroID() const { return (ID >> 31) != 0; }
96   
97   /// isValid - Return true if this is a valid SourceLocation object.  Invalid
98   /// SourceLocations are often used when events have no corresponding location
99   /// in the source (e.g. a diagnostic is required for a command line option).
100   ///
101   bool isValid() const { return ID != 0; }
102   bool isInvalid() const { return ID == 0; }
103   
104   /// getChunkID - Return the chunk identifier for this SourceLocation.  This
105   /// ChunkID can be used with the SourceManager object to obtain an entire
106   /// include stack for a file position reference.
107   unsigned getChunkID() const {
108     assert(isFileID() && "can't get the file id of a non-file sloc!");
109     return ID >> FilePosBits;
110   }
111   
112   unsigned getMacroID() const {
113     assert(isMacroID() && "Is not a macro id!");
114     return (ID >> MacroSpellingOffsBits) & ((1 << MacroIDBits)-1);
115   }
116   
117 private:
118   static SourceLocation getFileLoc(unsigned ChunkID, unsigned FilePos) {
119     SourceLocation L;
120     // If a FilePos is larger than (1<<FilePosBits), the SourceManager makes
121     // enough consequtive ChunkIDs that we have one for each chunk.
122     if (FilePos >= ChunkSize) {
123       ChunkID += FilePos >> FilePosBits;
124       FilePos &= ChunkSize-1;
125     }
126     
127     // FIXME: Find a way to handle out of ChunkID bits!  Maybe MaxFileID is an
128     // escape of some sort?
129     assert(ChunkID < (1 << ChunkIDBits) && "Out of ChunkID's");
130     
131     L.ID = (ChunkID << FilePosBits) | FilePos;
132     return L;
133   }
134   
135   static bool isValidMacroSpellingOffs(int Val) {
136     if (Val >= 0)
137       return Val < (1 << (MacroSpellingOffsBits-1));
138     return -Val <= (1 << (MacroSpellingOffsBits-1));
139   }
140   
141   static SourceLocation getMacroLoc(unsigned MacroID, int SpellingOffs) {
142     assert(MacroID < (1 << MacroIDBits) && "Too many macros!");
143     assert(isValidMacroSpellingOffs(SpellingOffs) &&"spelling offs too large!");
144     
145     // Mask off sign bits.
146     SpellingOffs &= (1 << MacroSpellingOffsBits)-1;
147     
148     SourceLocation L;
149     L.ID = (1 << 31) |
150            (MacroID << MacroSpellingOffsBits) |
151            SpellingOffs;
152     return L;
153   }
154
155   /// getRawFilePos - Return the byte offset from the start of the file-chunk
156   /// referred to by ChunkID.  This method should not be used to get the offset
157   /// from the start of the file, instead you should use
158   /// SourceManager::getDecomposedFileLoc.  This method will be 
159   //  incorrect for large files.
160   unsigned getRawFilePos() const { 
161     assert(isFileID() && "can't get the file id of a non-file sloc!");
162     return ID & (ChunkSize-1);
163   }
164
165   int getMacroSpellingOffs() const {
166     assert(isMacroID() && "Is not a macro id!");
167     int Val = ID & ((1 << MacroSpellingOffsBits)-1);
168     // Sign extend it properly.
169     unsigned ShAmt = sizeof(int)*8 - MacroSpellingOffsBits;
170     return (Val << ShAmt) >> ShAmt;
171   }
172 public:
173   
174   /// getFileLocWithOffset - Return a source location with the specified offset
175   /// from this file SourceLocation.
176   SourceLocation getFileLocWithOffset(int Offset) const {
177     unsigned ChunkID = getChunkID();
178     Offset += getRawFilePos();
179     // Handle negative offsets correctly.
180     while (Offset < 0) {
181       --ChunkID;
182       Offset += ChunkSize;
183     }
184     return getFileLoc(ChunkID, Offset);
185   }
186   
187   /// getRawEncoding - When a SourceLocation itself cannot be used, this returns
188   /// an (opaque) 32-bit integer encoding for it.  This should only be passed
189   /// to SourceLocation::getFromRawEncoding, it should not be inspected
190   /// directly.
191   unsigned getRawEncoding() const { return ID; }
192   
193   
194   bool operator<(const SourceLocation &RHS) const {
195     return ID < RHS.ID;
196   }
197   
198   /// getFromRawEncoding - Turn a raw encoding of a SourceLocation object into
199   /// a real SourceLocation.
200   static SourceLocation getFromRawEncoding(unsigned Encoding) {
201     SourceLocation X;
202     X.ID = Encoding;
203     return X;
204   }
205   
206   /// Emit - Emit this SourceLocation object to Bitcode.
207   void Emit(llvm::Serializer& S) const;
208   
209   /// ReadVal - Read a SourceLocation object from Bitcode.
210   static SourceLocation ReadVal(llvm::Deserializer& D);
211 };
212
213 inline bool operator==(const SourceLocation &LHS, const SourceLocation &RHS) {
214   return LHS.getRawEncoding() == RHS.getRawEncoding();
215 }
216
217 inline bool operator!=(const SourceLocation &LHS, const SourceLocation &RHS) {
218   return !(LHS == RHS);
219 }
220
221 /// SourceRange - a trival tuple used to represent a source range.
222 class SourceRange {
223   SourceLocation B;
224   SourceLocation E;
225 public:
226   SourceRange(): B(SourceLocation()), E(SourceLocation()) {}
227   SourceRange(SourceLocation loc) : B(loc), E(loc) {}
228   SourceRange(SourceLocation begin, SourceLocation end) : B(begin), E(end) {}
229     
230   SourceLocation getBegin() const { return B; }
231   SourceLocation getEnd() const { return E; }
232   
233   void setBegin(SourceLocation b) { B = b; }
234   void setEnd(SourceLocation e) { E = e; }
235   
236   bool isValid() const { return B.isValid() && E.isValid(); }
237   
238   /// Emit - Emit this SourceRange object to Bitcode.
239   void Emit(llvm::Serializer& S) const;    
240
241   /// ReadVal - Read a SourceRange object from Bitcode.
242   static SourceRange ReadVal(llvm::Deserializer& D);
243 };
244   
245 /// FullSourceLoc - A SourceLocation and its associated SourceManager.  Useful
246 /// for argument passing to functions that expect both objects.
247 class FullSourceLoc : public SourceLocation {
248   SourceManager* SrcMgr;
249 public:
250   // Creates a FullSourceLoc where isValid() returns false.
251   explicit FullSourceLoc() : SrcMgr((SourceManager*) 0) {}
252
253   explicit FullSourceLoc(SourceLocation Loc, SourceManager &SM) 
254     : SourceLocation(Loc), SrcMgr(&SM) {}
255     
256   SourceManager& getManager() {
257     assert (SrcMgr && "SourceManager is NULL.");
258     return *SrcMgr;
259   }
260   
261   const SourceManager& getManager() const {
262     assert (SrcMgr && "SourceManager is NULL.");
263     return *SrcMgr;
264   }
265   
266   FileID getFileID() const;
267   
268   FullSourceLoc getInstantiationLoc() const;
269   FullSourceLoc getSpellingLoc() const;
270   FullSourceLoc getIncludeLoc() const;
271
272   unsigned getLineNumber() const;
273   unsigned getColumnNumber() const;
274   
275   unsigned getInstantiationLineNumber() const;
276   unsigned getInstantiationColumnNumber() const;
277
278   unsigned getSpellingLineNumber() const;
279   unsigned getSpellingColumnNumber() const;
280
281   const char *getCharacterData() const;
282   
283   const llvm::MemoryBuffer* getBuffer() const;
284   
285   const char* getSourceName() const;
286   const FileEntry* getFileEntryForLoc() const;
287
288   bool isInSystemHeader() const;
289   
290   /// Prints information about this FullSourceLoc to stderr. Useful for
291   ///  debugging.
292   void dump() const;
293
294   friend inline bool 
295   operator==(const FullSourceLoc &LHS, const FullSourceLoc &RHS) {
296     return LHS.getRawEncoding() == RHS.getRawEncoding() &&
297           LHS.SrcMgr == RHS.SrcMgr;
298   }
299
300   friend inline bool 
301   operator!=(const FullSourceLoc &LHS, const FullSourceLoc &RHS) {
302     return !(LHS == RHS);
303   }
304
305 };
306  
307 }  // end namespace clang
308
309 namespace llvm {
310   /// Define DenseMapInfo so that FileID's can be used as keys in DenseMap and
311   /// DenseSets.
312   template <>
313   struct DenseMapInfo<clang::FileID> {
314     static inline clang::FileID getEmptyKey() {
315       return clang::FileID();
316     }
317     static inline clang::FileID getTombstoneKey() {
318       return clang::FileID::getSentinel(); 
319     }
320     
321     static unsigned getHashValue(clang::FileID S) {
322       return S.getHashValue();
323     }
324     
325     static bool isEqual(clang::FileID LHS, clang::FileID RHS) {
326       return LHS == RHS;
327     }
328     
329     static bool isPod() { return true; }
330   };
331   
332 }  // end namespace llvm
333
334 #endif