blob: 4c0f0e9d462ef86c98f6b4818b179b8ce53ad148 [file] [log] [blame]
Reid Spencer5f016e22007-07-11 17:01:13 +00001//===--- SourceLocation.h - Compact identifier for Source Files -*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
Chris Lattner0bc735f2007-12-29 19:59:25 +00005// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
Reid Spencer5f016e22007-07-11 17:01:13 +00007//
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
Chris Lattner9dc1f532007-07-20 16:37:10 +000017#include <cassert>
Ted Kremenek0a449ee2007-10-25 18:27:10 +000018#include "llvm/Bitcode/SerializationFwd.h"
Chris Lattner9dc1f532007-07-20 16:37:10 +000019
Ted Kremenek9c728dc2007-12-12 22:39:36 +000020namespace llvm {
Chris Lattner2b2453a2009-01-17 06:22:33 +000021 class MemoryBuffer;
22 template <typename T> struct DenseMapInfo;
Ted Kremenek9c728dc2007-12-12 22:39:36 +000023}
24
Reid Spencer5f016e22007-07-11 17:01:13 +000025namespace clang {
Ted Kremeneka9793ed2007-12-12 18:16:46 +000026
27class SourceManager;
Ted Kremenek9c728dc2007-12-12 22:39:36 +000028class FileEntry;
Chris Lattner2b2453a2009-01-17 06:22:33 +000029
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///
33class FileID {
34 /// ID - Opaque identifier, 0 is "invalid".
35 unsigned ID;
36public:
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
51private:
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
Reid Spencer5f016e22007-07-11 17:01:13 +000061
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.
65class SourceLocation {
66 unsigned ID;
67public:
68 enum {
Chris Lattnerb7489d82007-11-09 23:52:16 +000069 // FileID Layout:
70 // bit 31: 0 -> FileID, 1 -> MacroID (invalid for FileID)
Chris Lattner3b4d5e92009-01-17 08:45:21 +000071 // 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,
Chris Lattner9dc1f532007-07-20 16:37:10 +000075
Chris Lattnerb7489d82007-11-09 23:52:16 +000076 // MacroID Layout:
77 // bit 31: 1 -> MacroID, 0 -> FileID (invalid for MacroID)
78
Chris Lattnerf8484542008-02-03 08:24:13 +000079 // bit 29,30: unused.
80
Chris Lattnerb7489d82007-11-09 23:52:16 +000081 // bits 28...9 -> MacroID number.
Chris Lattnerd1623a82007-07-21 06:41:57 +000082 MacroIDBits = 20,
Chris Lattnerdf7c17a2009-01-16 07:00:02 +000083 // bits 8...0 -> Macro spelling offset
84 MacroSpellingOffsBits = 9,
Chris Lattner2c64b7b2007-10-16 21:07:07 +000085
Chris Lattnerb7489d82007-11-09 23:52:16 +000086
87 // Useful constants.
Chris Lattner2c64b7b2007-10-16 21:07:07 +000088 ChunkSize = (1 << FilePosBits)
Reid Spencer5f016e22007-07-11 17:01:13 +000089 };
90
91 SourceLocation() : ID(0) {} // 0 is an invalid FileID.
92
Chris Lattner9dc1f532007-07-20 16:37:10 +000093 bool isFileID() const { return (ID >> 31) == 0; }
94 bool isMacroID() const { return (ID >> 31) != 0; }
95
Chris Lattnerb7489d82007-11-09 23:52:16 +000096 /// 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
Chris Lattner3b4d5e92009-01-17 08:45:21 +0000103 static SourceLocation getFileLoc(unsigned ChunkID, unsigned FilePos) {
Chris Lattner9dc1f532007-07-20 16:37:10 +0000104 SourceLocation L;
Reid Spencer5f016e22007-07-11 17:01:13 +0000105 // If a FilePos is larger than (1<<FilePosBits), the SourceManager makes
Chris Lattner3b4d5e92009-01-17 08:45:21 +0000106 // enough consequtive ChunkIDs that we have one for each chunk.
Chris Lattner2c64b7b2007-10-16 21:07:07 +0000107 if (FilePos >= ChunkSize) {
Chris Lattner3b4d5e92009-01-17 08:45:21 +0000108 ChunkID += FilePos >> FilePosBits;
Chris Lattner2c64b7b2007-10-16 21:07:07 +0000109 FilePos &= ChunkSize-1;
Reid Spencer5f016e22007-07-11 17:01:13 +0000110 }
111
Chris Lattner3b4d5e92009-01-17 08:45:21 +0000112 // FIXME: Find a way to handle out of ChunkID bits! Maybe MaxFileID is an
Reid Spencer5f016e22007-07-11 17:01:13 +0000113 // escape of some sort?
Chris Lattner3b4d5e92009-01-17 08:45:21 +0000114 assert(ChunkID < (1 << ChunkIDBits) && "Out of ChunkID's");
Reid Spencer5f016e22007-07-11 17:01:13 +0000115
Chris Lattner3b4d5e92009-01-17 08:45:21 +0000116 L.ID = (ChunkID << FilePosBits) | FilePos;
Chris Lattner9dc1f532007-07-20 16:37:10 +0000117 return L;
Reid Spencer5f016e22007-07-11 17:01:13 +0000118 }
119
Chris Lattnerdf7c17a2009-01-16 07:00:02 +0000120 static bool isValidMacroSpellingOffs(int Val) {
Chris Lattnerd1623a82007-07-21 06:41:57 +0000121 if (Val >= 0)
Chris Lattnerdf7c17a2009-01-16 07:00:02 +0000122 return Val < (1 << (MacroSpellingOffsBits-1));
123 return -Val <= (1 << (MacroSpellingOffsBits-1));
Chris Lattnerd1623a82007-07-21 06:41:57 +0000124 }
125
Chris Lattnerdf7c17a2009-01-16 07:00:02 +0000126 static SourceLocation getMacroLoc(unsigned MacroID, int SpellingOffs) {
Chris Lattner9dc1f532007-07-20 16:37:10 +0000127 assert(MacroID < (1 << MacroIDBits) && "Too many macros!");
Chris Lattnerdf7c17a2009-01-16 07:00:02 +0000128 assert(isValidMacroSpellingOffs(SpellingOffs) &&"spelling offs too large!");
Chris Lattner9dc1f532007-07-20 16:37:10 +0000129
Chris Lattnerb7489d82007-11-09 23:52:16 +0000130 // Mask off sign bits.
Chris Lattnerdf7c17a2009-01-16 07:00:02 +0000131 SpellingOffs &= (1 << MacroSpellingOffsBits)-1;
Chris Lattnerd1623a82007-07-21 06:41:57 +0000132
133 SourceLocation L;
Chris Lattnerb7489d82007-11-09 23:52:16 +0000134 L.ID = (1 << 31) |
Chris Lattnerdf7c17a2009-01-16 07:00:02 +0000135 (MacroID << MacroSpellingOffsBits) |
136 SpellingOffs;
Chris Lattner9dc1f532007-07-20 16:37:10 +0000137 return L;
138 }
139
140
Chris Lattner3b4d5e92009-01-17 08:45:21 +0000141 /// getChunkID - Return the chunk identifier for this SourceLocation. This
142 /// ChunkID can be used with the SourceManager object to obtain an entire
Reid Spencer5f016e22007-07-11 17:01:13 +0000143 /// include stack for a file position reference.
Chris Lattner3b4d5e92009-01-17 08:45:21 +0000144 unsigned getChunkID() const {
Chris Lattner9dc1f532007-07-20 16:37:10 +0000145 assert(isFileID() && "can't get the file id of a non-file sloc!");
146 return ID >> FilePosBits;
147 }
Reid Spencer5f016e22007-07-11 17:01:13 +0000148
149 /// getRawFilePos - Return the byte offset from the start of the file-chunk
Chris Lattner3b4d5e92009-01-17 08:45:21 +0000150 /// referred to by ChunkID. This method should not be used to get the offset
Reid Spencer5f016e22007-07-11 17:01:13 +0000151 /// from the start of the file, instead you should use
Ted Kremenek9f68fa52008-03-18 20:13:06 +0000152 /// SourceManager::getDecomposedFileLoc. This method will be
153 // incorrect for large files.
Chris Lattner9dc1f532007-07-20 16:37:10 +0000154 unsigned getRawFilePos() const {
155 assert(isFileID() && "can't get the file id of a non-file sloc!");
Chris Lattner2c64b7b2007-10-16 21:07:07 +0000156 return ID & (ChunkSize-1);
Chris Lattner9dc1f532007-07-20 16:37:10 +0000157 }
158
159 unsigned getMacroID() const {
160 assert(isMacroID() && "Is not a macro id!");
Chris Lattnerdf7c17a2009-01-16 07:00:02 +0000161 return (ID >> MacroSpellingOffsBits) & ((1 << MacroIDBits)-1);
Chris Lattner9dc1f532007-07-20 16:37:10 +0000162 }
Reid Spencer5f016e22007-07-11 17:01:13 +0000163
Chris Lattnerdf7c17a2009-01-16 07:00:02 +0000164 int getMacroSpellingOffs() const {
Chris Lattner9dc1f532007-07-20 16:37:10 +0000165 assert(isMacroID() && "Is not a macro id!");
Chris Lattnerdf7c17a2009-01-16 07:00:02 +0000166 int Val = ID & ((1 << MacroSpellingOffsBits)-1);
Chris Lattnerd1623a82007-07-21 06:41:57 +0000167 // Sign extend it properly.
Chris Lattnerdf7c17a2009-01-16 07:00:02 +0000168 unsigned ShAmt = sizeof(int)*8 - MacroSpellingOffsBits;
Chris Lattnerd1623a82007-07-21 06:41:57 +0000169 return (Val << ShAmt) >> ShAmt;
Chris Lattner9dc1f532007-07-20 16:37:10 +0000170 }
171
Chris Lattner9dc1f532007-07-20 16:37:10 +0000172 /// getFileLocWithOffset - Return a source location with the specified offset
173 /// from this file SourceLocation.
Chris Lattnerd1623a82007-07-21 06:41:57 +0000174 SourceLocation getFileLocWithOffset(int Offset) const {
Chris Lattner3b4d5e92009-01-17 08:45:21 +0000175 unsigned ChunkID = getChunkID();
Chris Lattner2c64b7b2007-10-16 21:07:07 +0000176 Offset += getRawFilePos();
177 // Handle negative offsets correctly.
178 while (Offset < 0) {
Chris Lattner3b4d5e92009-01-17 08:45:21 +0000179 --ChunkID;
Chris Lattner2c64b7b2007-10-16 21:07:07 +0000180 Offset += ChunkSize;
181 }
Chris Lattner3b4d5e92009-01-17 08:45:21 +0000182 return getFileLoc(ChunkID, Offset);
Chris Lattner9dc1f532007-07-20 16:37:10 +0000183 }
Reid Spencer5f016e22007-07-11 17:01:13 +0000184
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
Chris Lattnercff9cc92008-10-12 05:44:03 +0000191
192 bool operator<(const SourceLocation &RHS) const {
193 return ID < RHS.ID;
194 }
195
Reid Spencer5f016e22007-07-11 17:01:13 +0000196 /// 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 }
Ted Kremenekbeb77132007-11-01 22:25:41 +0000203
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);
Reid Spencer5f016e22007-07-11 17:01:13 +0000209};
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
Chris Lattner311ff022007-10-16 22:36:42 +0000228 SourceLocation getBegin() const { return B; }
229 SourceLocation getEnd() const { return E; }
Reid Spencer5f016e22007-07-11 17:01:13 +0000230
Chris Lattnere80a59c2007-07-25 00:24:17 +0000231 void setBegin(SourceLocation b) { B = b; }
232 void setEnd(SourceLocation e) { E = e; }
233
Reid Spencer5f016e22007-07-11 17:01:13 +0000234 bool isValid() const { return B.isValid() && E.isValid(); }
Ted Kremenekbeb77132007-11-01 22:25:41 +0000235
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);
Reid Spencer5f016e22007-07-11 17:01:13 +0000241};
242
Chris Lattnera50bd542009-01-16 23:03:56 +0000243/// FullSourceLoc - A SourceLocation and its associated SourceManager. Useful
244/// for argument passing to functions that expect both objects.
245class FullSourceLoc : public SourceLocation {
Ted Kremenek9c728dc2007-12-12 22:39:36 +0000246 SourceManager* SrcMgr;
Ted Kremeneka9793ed2007-12-12 18:16:46 +0000247public:
Ted Kremenek1b924fd2007-12-12 18:54:21 +0000248 // Creates a FullSourceLoc where isValid() returns false.
Chris Lattnera50bd542009-01-16 23:03:56 +0000249 explicit FullSourceLoc() : SrcMgr((SourceManager*) 0) {}
Ted Kremeneka9793ed2007-12-12 18:16:46 +0000250
Chris Lattnera50bd542009-01-16 23:03:56 +0000251 explicit FullSourceLoc(SourceLocation Loc, SourceManager &SM)
252 : SourceLocation(Loc), SrcMgr(&SM) {}
Ted Kremenek1b924fd2007-12-12 18:54:21 +0000253
Ted Kremenek9c728dc2007-12-12 22:39:36 +0000254 SourceManager& getManager() {
255 assert (SrcMgr && "SourceManager is NULL.");
256 return *SrcMgr;
257 }
Ted Kremeneka9793ed2007-12-12 18:16:46 +0000258
Ted Kremenek1b924fd2007-12-12 18:54:21 +0000259 const SourceManager& getManager() const {
Ted Kremeneka9793ed2007-12-12 18:16:46 +0000260 assert (SrcMgr && "SourceManager is NULL.");
261 return *SrcMgr;
262 }
Ted Kremenek9c728dc2007-12-12 22:39:36 +0000263
Chris Lattner3b4d5e92009-01-17 08:45:21 +0000264 FileID getFileID() const;
265
Chris Lattnerf7cf85b2009-01-16 07:36:28 +0000266 FullSourceLoc getInstantiationLoc() const;
Chris Lattnerdf7c17a2009-01-16 07:00:02 +0000267 FullSourceLoc getSpellingLoc() const;
Chris Lattner5c38b632008-09-29 21:46:13 +0000268 FullSourceLoc getIncludeLoc() const;
Ted Kremenek9c728dc2007-12-12 22:39:36 +0000269
Ted Kremenek1758b072008-04-03 17:55:15 +0000270 unsigned getLineNumber() const;
271 unsigned getColumnNumber() const;
272
Chris Lattnerf7cf85b2009-01-16 07:36:28 +0000273 unsigned getInstantiationLineNumber() const;
274 unsigned getInstantiationColumnNumber() const;
Ted Kremenek9c728dc2007-12-12 22:39:36 +0000275
Chris Lattnerdf7c17a2009-01-16 07:00:02 +0000276 unsigned getSpellingLineNumber() const;
277 unsigned getSpellingColumnNumber() const;
Chris Lattner5c38b632008-09-29 21:46:13 +0000278
Ted Kremenek9c728dc2007-12-12 22:39:36 +0000279 const char *getCharacterData() const;
280
281 const llvm::MemoryBuffer* getBuffer() const;
282
283 const char* getSourceName() const;
284 const FileEntry* getFileEntryForLoc() const;
Nico Weber7bfaaae2008-08-10 19:59:06 +0000285
286 bool isInSystemHeader() const;
Ted Kremenek9c728dc2007-12-12 22:39:36 +0000287
Chris Lattner5c38b632008-09-29 21:46:13 +0000288 /// Prints information about this FullSourceLoc to stderr. Useful for
289 /// debugging.
290 void dump() const;
Douglas Gregor0b7a1582009-01-17 00:42:38 +0000291
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
Ted Kremeneka9793ed2007-12-12 18:16:46 +0000303};
Douglas Gregor0b7a1582009-01-17 00:42:38 +0000304
Reid Spencer5f016e22007-07-11 17:01:13 +0000305} // end namespace clang
306
Chris Lattner2b2453a2009-01-17 06:22:33 +0000307namespace 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
Reid Spencer5f016e22007-07-11 17:01:13 +0000332#endif