blob: 1ebb0ff3f8592f219f69ce1fef0e5bf151e7a4e1 [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//
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
Chris Lattner9dc1f532007-07-20 16:37:10 +000017#include <cassert>
18
Reid Spencer5f016e22007-07-11 17:01:13 +000019namespace clang {
20
21/// SourceLocation - This is a carefully crafted 32-bit identifier that encodes
22/// a full include stack, line and column number information for a position in
23/// an input translation unit.
24class SourceLocation {
25 unsigned ID;
26public:
27 enum {
28 FileIDBits = 14,
Chris Lattner9dc1f532007-07-20 16:37:10 +000029 FilePosBits = 32-1-FileIDBits,
30
Chris Lattnerd1623a82007-07-21 06:41:57 +000031 MacroIDBits = 20,
Chris Lattner31bb8be2007-07-20 18:00:12 +000032 MacroPhysOffsBits = 9,
Chris Lattner2c64b7b2007-10-16 21:07:07 +000033 MacroLogOffBits = 2,
34
35 ChunkSize = (1 << FilePosBits)
Reid Spencer5f016e22007-07-11 17:01:13 +000036 };
37
38 SourceLocation() : ID(0) {} // 0 is an invalid FileID.
39
Chris Lattner9dc1f532007-07-20 16:37:10 +000040 bool isFileID() const { return (ID >> 31) == 0; }
41 bool isMacroID() const { return (ID >> 31) != 0; }
42
43 static SourceLocation getFileLoc(unsigned FileID, unsigned FilePos) {
44 SourceLocation L;
Reid Spencer5f016e22007-07-11 17:01:13 +000045 // If a FilePos is larger than (1<<FilePosBits), the SourceManager makes
46 // enough consequtive FileIDs that we have one for each chunk.
Chris Lattner2c64b7b2007-10-16 21:07:07 +000047 if (FilePos >= ChunkSize) {
Reid Spencer5f016e22007-07-11 17:01:13 +000048 FileID += FilePos >> FilePosBits;
Chris Lattner2c64b7b2007-10-16 21:07:07 +000049 FilePos &= ChunkSize-1;
Reid Spencer5f016e22007-07-11 17:01:13 +000050 }
51
52 // FIXME: Find a way to handle out of FileID bits! Maybe MaxFileID is an
53 // escape of some sort?
Chris Lattner4cabcfe2007-08-02 04:14:33 +000054 assert(FileID < (1 << FileIDBits) && "Out of fileid's");
Reid Spencer5f016e22007-07-11 17:01:13 +000055
Chris Lattner9dc1f532007-07-20 16:37:10 +000056 L.ID = (FileID << FilePosBits) | FilePos;
57 return L;
Reid Spencer5f016e22007-07-11 17:01:13 +000058 }
59
Chris Lattnerd1623a82007-07-21 06:41:57 +000060 static bool isValidMacroPhysOffs(int Val) {
61 if (Val >= 0)
62 return Val < (1 << (MacroPhysOffsBits-1));
63 return -Val < (1 << (MacroPhysOffsBits-1));
64 }
65
66 static SourceLocation getMacroLoc(unsigned MacroID, int PhysOffs,
Chris Lattner9dc1f532007-07-20 16:37:10 +000067 unsigned LogOffs) {
Chris Lattner9dc1f532007-07-20 16:37:10 +000068 assert(MacroID < (1 << MacroIDBits) && "Too many macros!");
Chris Lattnerd1623a82007-07-21 06:41:57 +000069 assert(isValidMacroPhysOffs(PhysOffs) && "Physoffs too large!");
Chris Lattner9dc1f532007-07-20 16:37:10 +000070 assert(LogOffs < (1 << MacroLogOffBits) && "Logical offs too large!");
71
Chris Lattnerd1623a82007-07-21 06:41:57 +000072 PhysOffs &= (1 << MacroPhysOffsBits)-1;
73
74 SourceLocation L;
Chris Lattner9dc1f532007-07-20 16:37:10 +000075 L.ID = (1 << 31) | (MacroID << (MacroPhysOffsBits+MacroLogOffBits)) |
Chris Lattnerd1623a82007-07-21 06:41:57 +000076 (PhysOffs << MacroLogOffBits) |
77 LogOffs;
Chris Lattner9dc1f532007-07-20 16:37:10 +000078 return L;
79 }
80
81
Reid Spencer5f016e22007-07-11 17:01:13 +000082 /// isValid - Return true if this is a valid SourceLocation object. Invalid
83 /// SourceLocations are often used when events have no corresponding location
84 /// in the source (e.g. a diagnostic is required for a command line option).
85 ///
86 bool isValid() const { return ID != 0; }
Chris Lattner9dc1f532007-07-20 16:37:10 +000087 bool isInvalid() const { return ID == 0; }
Reid Spencer5f016e22007-07-11 17:01:13 +000088
89 /// getFileID - Return the file identifier for this SourceLocation. This
90 /// FileID can be used with the SourceManager object to obtain an entire
91 /// include stack for a file position reference.
Chris Lattner9dc1f532007-07-20 16:37:10 +000092 unsigned getFileID() const {
93 assert(isFileID() && "can't get the file id of a non-file sloc!");
94 return ID >> FilePosBits;
95 }
Reid Spencer5f016e22007-07-11 17:01:13 +000096
97 /// getRawFilePos - Return the byte offset from the start of the file-chunk
98 /// referred to by FileID. This method should not be used to get the offset
99 /// from the start of the file, instead you should use
100 /// SourceManager::getFilePos. This method will be incorrect for large files.
Chris Lattner9dc1f532007-07-20 16:37:10 +0000101 unsigned getRawFilePos() const {
102 assert(isFileID() && "can't get the file id of a non-file sloc!");
Chris Lattner2c64b7b2007-10-16 21:07:07 +0000103 return ID & (ChunkSize-1);
Chris Lattner9dc1f532007-07-20 16:37:10 +0000104 }
105
106 unsigned getMacroID() const {
107 assert(isMacroID() && "Is not a macro id!");
108 return (ID >> (MacroPhysOffsBits+MacroLogOffBits)) & ((1 << MacroIDBits)-1);
109 }
Reid Spencer5f016e22007-07-11 17:01:13 +0000110
Chris Lattnerd1623a82007-07-21 06:41:57 +0000111 int getMacroPhysOffs() const {
Chris Lattner9dc1f532007-07-20 16:37:10 +0000112 assert(isMacroID() && "Is not a macro id!");
Chris Lattnerd1623a82007-07-21 06:41:57 +0000113 int Val = (ID >> MacroLogOffBits) & ((1 << MacroPhysOffsBits)-1);
114 // Sign extend it properly.
115 unsigned ShAmt = sizeof(int)*8 - MacroPhysOffsBits;
116 return (Val << ShAmt) >> ShAmt;
Chris Lattner9dc1f532007-07-20 16:37:10 +0000117 }
118
119 unsigned getMacroLogOffs() const {
120 assert(isMacroID() && "Is not a macro id!");
Chris Lattner31bb8be2007-07-20 18:00:12 +0000121 return ID & ((1 << MacroLogOffBits)-1);
Chris Lattner9dc1f532007-07-20 16:37:10 +0000122 }
123
124 /// getFileLocWithOffset - Return a source location with the specified offset
125 /// from this file SourceLocation.
Chris Lattnerd1623a82007-07-21 06:41:57 +0000126 SourceLocation getFileLocWithOffset(int Offset) const {
Chris Lattner2c64b7b2007-10-16 21:07:07 +0000127 unsigned FileID = getFileID();
128 Offset += getRawFilePos();
129 // Handle negative offsets correctly.
130 while (Offset < 0) {
131 --FileID;
132 Offset += ChunkSize;
133 }
134 return getFileLoc(FileID, Offset);
Chris Lattner9dc1f532007-07-20 16:37:10 +0000135 }
Reid Spencer5f016e22007-07-11 17:01:13 +0000136
137 /// getRawEncoding - When a SourceLocation itself cannot be used, this returns
138 /// an (opaque) 32-bit integer encoding for it. This should only be passed
139 /// to SourceLocation::getFromRawEncoding, it should not be inspected
140 /// directly.
141 unsigned getRawEncoding() const { return ID; }
142
143 /// getFromRawEncoding - Turn a raw encoding of a SourceLocation object into
144 /// a real SourceLocation.
145 static SourceLocation getFromRawEncoding(unsigned Encoding) {
146 SourceLocation X;
147 X.ID = Encoding;
148 return X;
149 }
150};
151
152inline bool operator==(const SourceLocation &LHS, const SourceLocation &RHS) {
153 return LHS.getRawEncoding() == RHS.getRawEncoding();
154}
155
156inline bool operator!=(const SourceLocation &LHS, const SourceLocation &RHS) {
157 return !(LHS == RHS);
158}
159
160/// SourceRange - a trival tuple used to represent a source range.
161class SourceRange {
162 SourceLocation B;
163 SourceLocation E;
164public:
165 SourceRange(): B(SourceLocation()), E(SourceLocation()) {}
166 SourceRange(SourceLocation loc) : B(loc), E(loc) {}
167 SourceRange(SourceLocation begin, SourceLocation end) : B(begin), E(end) {}
168
169 SourceLocation Begin() const { return B; }
170 SourceLocation End() const { return E; }
171
Chris Lattnere80a59c2007-07-25 00:24:17 +0000172 void setBegin(SourceLocation b) { B = b; }
173 void setEnd(SourceLocation e) { E = e; }
174
Reid Spencer5f016e22007-07-11 17:01:13 +0000175 bool isValid() const { return B.isValid() && E.isValid(); }
176};
177
178} // end namespace clang
179
180#endif