blob: 2e0fb4d6709fdf676c32b408b94981908895cfc6 [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;
Chris Lattnerbcc2a672009-01-19 06:46:35 +000067 friend class SourceManager;
Reid Spencer5f016e22007-07-11 17:01:13 +000068public:
69 enum {
Chris Lattnerb7489d82007-11-09 23:52:16 +000070 // FileID Layout:
71 // bit 31: 0 -> FileID, 1 -> MacroID (invalid for FileID)
Chris Lattner3b4d5e92009-01-17 08:45:21 +000072 // 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,
Chris Lattner9dc1f532007-07-20 16:37:10 +000076
Chris Lattnerb7489d82007-11-09 23:52:16 +000077 // MacroID Layout:
78 // bit 31: 1 -> MacroID, 0 -> FileID (invalid for MacroID)
79
Chris Lattnerf8484542008-02-03 08:24:13 +000080 // bit 29,30: unused.
81
Chris Lattnerb7489d82007-11-09 23:52:16 +000082 // bits 28...9 -> MacroID number.
Chris Lattnerd1623a82007-07-21 06:41:57 +000083 MacroIDBits = 20,
Chris Lattnerdf7c17a2009-01-16 07:00:02 +000084 // bits 8...0 -> Macro spelling offset
85 MacroSpellingOffsBits = 9,
Chris Lattner2c64b7b2007-10-16 21:07:07 +000086
Chris Lattnerb7489d82007-11-09 23:52:16 +000087
88 // Useful constants.
Chris Lattner2c64b7b2007-10-16 21:07:07 +000089 ChunkSize = (1 << FilePosBits)
Reid Spencer5f016e22007-07-11 17:01:13 +000090 };
91
92 SourceLocation() : ID(0) {} // 0 is an invalid FileID.
93
Chris Lattner9dc1f532007-07-20 16:37:10 +000094 bool isFileID() const { return (ID >> 31) == 0; }
95 bool isMacroID() const { return (ID >> 31) != 0; }
96
Chris Lattnerb7489d82007-11-09 23:52:16 +000097 /// 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
Chris Lattner4d10ef12009-01-19 06:55:08 +0000104 /// 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
Chris Lattnerbcc2a672009-01-19 06:46:35 +0000117private:
Chris Lattner3b4d5e92009-01-17 08:45:21 +0000118 static SourceLocation getFileLoc(unsigned ChunkID, unsigned FilePos) {
Chris Lattner9dc1f532007-07-20 16:37:10 +0000119 SourceLocation L;
Reid Spencer5f016e22007-07-11 17:01:13 +0000120 // If a FilePos is larger than (1<<FilePosBits), the SourceManager makes
Chris Lattner3b4d5e92009-01-17 08:45:21 +0000121 // enough consequtive ChunkIDs that we have one for each chunk.
Chris Lattner2c64b7b2007-10-16 21:07:07 +0000122 if (FilePos >= ChunkSize) {
Chris Lattner3b4d5e92009-01-17 08:45:21 +0000123 ChunkID += FilePos >> FilePosBits;
Chris Lattner2c64b7b2007-10-16 21:07:07 +0000124 FilePos &= ChunkSize-1;
Reid Spencer5f016e22007-07-11 17:01:13 +0000125 }
126
Chris Lattner3b4d5e92009-01-17 08:45:21 +0000127 // FIXME: Find a way to handle out of ChunkID bits! Maybe MaxFileID is an
Reid Spencer5f016e22007-07-11 17:01:13 +0000128 // escape of some sort?
Chris Lattner3b4d5e92009-01-17 08:45:21 +0000129 assert(ChunkID < (1 << ChunkIDBits) && "Out of ChunkID's");
Reid Spencer5f016e22007-07-11 17:01:13 +0000130
Chris Lattner3b4d5e92009-01-17 08:45:21 +0000131 L.ID = (ChunkID << FilePosBits) | FilePos;
Chris Lattner9dc1f532007-07-20 16:37:10 +0000132 return L;
Reid Spencer5f016e22007-07-11 17:01:13 +0000133 }
134
Chris Lattnerdf7c17a2009-01-16 07:00:02 +0000135 static bool isValidMacroSpellingOffs(int Val) {
Chris Lattnerd1623a82007-07-21 06:41:57 +0000136 if (Val >= 0)
Chris Lattnerdf7c17a2009-01-16 07:00:02 +0000137 return Val < (1 << (MacroSpellingOffsBits-1));
138 return -Val <= (1 << (MacroSpellingOffsBits-1));
Chris Lattnerd1623a82007-07-21 06:41:57 +0000139 }
140
Chris Lattnerdf7c17a2009-01-16 07:00:02 +0000141 static SourceLocation getMacroLoc(unsigned MacroID, int SpellingOffs) {
Chris Lattner9dc1f532007-07-20 16:37:10 +0000142 assert(MacroID < (1 << MacroIDBits) && "Too many macros!");
Chris Lattnerdf7c17a2009-01-16 07:00:02 +0000143 assert(isValidMacroSpellingOffs(SpellingOffs) &&"spelling offs too large!");
Chris Lattner9dc1f532007-07-20 16:37:10 +0000144
Chris Lattnerb7489d82007-11-09 23:52:16 +0000145 // Mask off sign bits.
Chris Lattnerdf7c17a2009-01-16 07:00:02 +0000146 SpellingOffs &= (1 << MacroSpellingOffsBits)-1;
Chris Lattnerd1623a82007-07-21 06:41:57 +0000147
148 SourceLocation L;
Chris Lattnerb7489d82007-11-09 23:52:16 +0000149 L.ID = (1 << 31) |
Chris Lattnerdf7c17a2009-01-16 07:00:02 +0000150 (MacroID << MacroSpellingOffsBits) |
151 SpellingOffs;
Chris Lattner9dc1f532007-07-20 16:37:10 +0000152 return L;
153 }
Chris Lattner4d10ef12009-01-19 06:55:08 +0000154
Reid Spencer5f016e22007-07-11 17:01:13 +0000155 /// getRawFilePos - Return the byte offset from the start of the file-chunk
Chris Lattner3b4d5e92009-01-17 08:45:21 +0000156 /// referred to by ChunkID. This method should not be used to get the offset
Reid Spencer5f016e22007-07-11 17:01:13 +0000157 /// from the start of the file, instead you should use
Ted Kremenek9f68fa52008-03-18 20:13:06 +0000158 /// SourceManager::getDecomposedFileLoc. This method will be
159 // incorrect for large files.
Chris Lattner9dc1f532007-07-20 16:37:10 +0000160 unsigned getRawFilePos() const {
161 assert(isFileID() && "can't get the file id of a non-file sloc!");
Chris Lattner2c64b7b2007-10-16 21:07:07 +0000162 return ID & (ChunkSize-1);
Chris Lattner9dc1f532007-07-20 16:37:10 +0000163 }
164
Chris Lattnerdf7c17a2009-01-16 07:00:02 +0000165 int getMacroSpellingOffs() const {
Chris Lattner9dc1f532007-07-20 16:37:10 +0000166 assert(isMacroID() && "Is not a macro id!");
Chris Lattnerdf7c17a2009-01-16 07:00:02 +0000167 int Val = ID & ((1 << MacroSpellingOffsBits)-1);
Chris Lattnerd1623a82007-07-21 06:41:57 +0000168 // Sign extend it properly.
Chris Lattnerdf7c17a2009-01-16 07:00:02 +0000169 unsigned ShAmt = sizeof(int)*8 - MacroSpellingOffsBits;
Chris Lattnerd1623a82007-07-21 06:41:57 +0000170 return (Val << ShAmt) >> ShAmt;
Chris Lattner9dc1f532007-07-20 16:37:10 +0000171 }
Chris Lattner4d10ef12009-01-19 06:55:08 +0000172public:
Chris Lattner9dc1f532007-07-20 16:37:10 +0000173
Chris Lattner9dc1f532007-07-20 16:37:10 +0000174 /// getFileLocWithOffset - Return a source location with the specified offset
175 /// from this file SourceLocation.
Chris Lattnerd1623a82007-07-21 06:41:57 +0000176 SourceLocation getFileLocWithOffset(int Offset) const {
Chris Lattner3b4d5e92009-01-17 08:45:21 +0000177 unsigned ChunkID = getChunkID();
Chris Lattner2c64b7b2007-10-16 21:07:07 +0000178 Offset += getRawFilePos();
179 // Handle negative offsets correctly.
180 while (Offset < 0) {
Chris Lattner3b4d5e92009-01-17 08:45:21 +0000181 --ChunkID;
Chris Lattner2c64b7b2007-10-16 21:07:07 +0000182 Offset += ChunkSize;
183 }
Chris Lattner3b4d5e92009-01-17 08:45:21 +0000184 return getFileLoc(ChunkID, Offset);
Chris Lattner9dc1f532007-07-20 16:37:10 +0000185 }
Reid Spencer5f016e22007-07-11 17:01:13 +0000186
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
Chris Lattnercff9cc92008-10-12 05:44:03 +0000193
194 bool operator<(const SourceLocation &RHS) const {
195 return ID < RHS.ID;
196 }
197
Reid Spencer5f016e22007-07-11 17:01:13 +0000198 /// 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 }
Ted Kremenekbeb77132007-11-01 22:25:41 +0000205
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);
Reid Spencer5f016e22007-07-11 17:01:13 +0000211};
212
213inline bool operator==(const SourceLocation &LHS, const SourceLocation &RHS) {
214 return LHS.getRawEncoding() == RHS.getRawEncoding();
215}
216
217inline 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.
222class SourceRange {
223 SourceLocation B;
224 SourceLocation E;
225public:
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
Chris Lattner311ff022007-10-16 22:36:42 +0000230 SourceLocation getBegin() const { return B; }
231 SourceLocation getEnd() const { return E; }
Reid Spencer5f016e22007-07-11 17:01:13 +0000232
Chris Lattnere80a59c2007-07-25 00:24:17 +0000233 void setBegin(SourceLocation b) { B = b; }
234 void setEnd(SourceLocation e) { E = e; }
235
Reid Spencer5f016e22007-07-11 17:01:13 +0000236 bool isValid() const { return B.isValid() && E.isValid(); }
Ted Kremenekbeb77132007-11-01 22:25:41 +0000237
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);
Reid Spencer5f016e22007-07-11 17:01:13 +0000243};
244
Chris Lattnera50bd542009-01-16 23:03:56 +0000245/// FullSourceLoc - A SourceLocation and its associated SourceManager. Useful
246/// for argument passing to functions that expect both objects.
247class FullSourceLoc : public SourceLocation {
Ted Kremenek9c728dc2007-12-12 22:39:36 +0000248 SourceManager* SrcMgr;
Ted Kremeneka9793ed2007-12-12 18:16:46 +0000249public:
Ted Kremenek1b924fd2007-12-12 18:54:21 +0000250 // Creates a FullSourceLoc where isValid() returns false.
Chris Lattnera50bd542009-01-16 23:03:56 +0000251 explicit FullSourceLoc() : SrcMgr((SourceManager*) 0) {}
Ted Kremeneka9793ed2007-12-12 18:16:46 +0000252
Chris Lattnera50bd542009-01-16 23:03:56 +0000253 explicit FullSourceLoc(SourceLocation Loc, SourceManager &SM)
254 : SourceLocation(Loc), SrcMgr(&SM) {}
Ted Kremenek1b924fd2007-12-12 18:54:21 +0000255
Ted Kremenek9c728dc2007-12-12 22:39:36 +0000256 SourceManager& getManager() {
257 assert (SrcMgr && "SourceManager is NULL.");
258 return *SrcMgr;
259 }
Ted Kremeneka9793ed2007-12-12 18:16:46 +0000260
Ted Kremenek1b924fd2007-12-12 18:54:21 +0000261 const SourceManager& getManager() const {
Ted Kremeneka9793ed2007-12-12 18:16:46 +0000262 assert (SrcMgr && "SourceManager is NULL.");
263 return *SrcMgr;
264 }
Ted Kremenek9c728dc2007-12-12 22:39:36 +0000265
Chris Lattner3b4d5e92009-01-17 08:45:21 +0000266 FileID getFileID() const;
267
Chris Lattnerf7cf85b2009-01-16 07:36:28 +0000268 FullSourceLoc getInstantiationLoc() const;
Chris Lattnerdf7c17a2009-01-16 07:00:02 +0000269 FullSourceLoc getSpellingLoc() const;
Chris Lattner5c38b632008-09-29 21:46:13 +0000270 FullSourceLoc getIncludeLoc() const;
Ted Kremenek9c728dc2007-12-12 22:39:36 +0000271
Ted Kremenek1758b072008-04-03 17:55:15 +0000272 unsigned getLineNumber() const;
273 unsigned getColumnNumber() const;
274
Chris Lattnerf7cf85b2009-01-16 07:36:28 +0000275 unsigned getInstantiationLineNumber() const;
276 unsigned getInstantiationColumnNumber() const;
Ted Kremenek9c728dc2007-12-12 22:39:36 +0000277
Chris Lattnerdf7c17a2009-01-16 07:00:02 +0000278 unsigned getSpellingLineNumber() const;
279 unsigned getSpellingColumnNumber() const;
Chris Lattner5c38b632008-09-29 21:46:13 +0000280
Ted Kremenek9c728dc2007-12-12 22:39:36 +0000281 const char *getCharacterData() const;
282
283 const llvm::MemoryBuffer* getBuffer() const;
284
285 const char* getSourceName() const;
286 const FileEntry* getFileEntryForLoc() const;
Nico Weber7bfaaae2008-08-10 19:59:06 +0000287
288 bool isInSystemHeader() const;
Ted Kremenek9c728dc2007-12-12 22:39:36 +0000289
Chris Lattner5c38b632008-09-29 21:46:13 +0000290 /// Prints information about this FullSourceLoc to stderr. Useful for
291 /// debugging.
292 void dump() const;
Douglas Gregor0b7a1582009-01-17 00:42:38 +0000293
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
Ted Kremeneka9793ed2007-12-12 18:16:46 +0000305};
Douglas Gregor0b7a1582009-01-17 00:42:38 +0000306
Reid Spencer5f016e22007-07-11 17:01:13 +0000307} // end namespace clang
308
Chris Lattner2b2453a2009-01-17 06:22:33 +0000309namespace 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
Reid Spencer5f016e22007-07-11 17:01:13 +0000334#endif