blob: 31cbfa5085e6ceeab60ccba3e219eb86445e02a4 [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>
Ted Kremenek0a449ee2007-10-25 18:27:10 +000018#include "llvm/Bitcode/SerializationFwd.h"
Chris Lattner9dc1f532007-07-20 16:37:10 +000019
Reid Spencer5f016e22007-07-11 17:01:13 +000020namespace clang {
21
22/// SourceLocation - This is a carefully crafted 32-bit identifier that encodes
23/// a full include stack, line and column number information for a position in
24/// an input translation unit.
25class SourceLocation {
26 unsigned ID;
27public:
28 enum {
29 FileIDBits = 14,
Chris Lattner9dc1f532007-07-20 16:37:10 +000030 FilePosBits = 32-1-FileIDBits,
31
Chris Lattnerd1623a82007-07-21 06:41:57 +000032 MacroIDBits = 20,
Chris Lattner31bb8be2007-07-20 18:00:12 +000033 MacroPhysOffsBits = 9,
Chris Lattner2c64b7b2007-10-16 21:07:07 +000034 MacroLogOffBits = 2,
35
36 ChunkSize = (1 << FilePosBits)
Reid Spencer5f016e22007-07-11 17:01:13 +000037 };
38
39 SourceLocation() : ID(0) {} // 0 is an invalid FileID.
40
Chris Lattner9dc1f532007-07-20 16:37:10 +000041 bool isFileID() const { return (ID >> 31) == 0; }
42 bool isMacroID() const { return (ID >> 31) != 0; }
43
44 static SourceLocation getFileLoc(unsigned FileID, unsigned FilePos) {
45 SourceLocation L;
Reid Spencer5f016e22007-07-11 17:01:13 +000046 // If a FilePos is larger than (1<<FilePosBits), the SourceManager makes
47 // enough consequtive FileIDs that we have one for each chunk.
Chris Lattner2c64b7b2007-10-16 21:07:07 +000048 if (FilePos >= ChunkSize) {
Reid Spencer5f016e22007-07-11 17:01:13 +000049 FileID += FilePos >> FilePosBits;
Chris Lattner2c64b7b2007-10-16 21:07:07 +000050 FilePos &= ChunkSize-1;
Reid Spencer5f016e22007-07-11 17:01:13 +000051 }
52
53 // FIXME: Find a way to handle out of FileID bits! Maybe MaxFileID is an
54 // escape of some sort?
Chris Lattner4cabcfe2007-08-02 04:14:33 +000055 assert(FileID < (1 << FileIDBits) && "Out of fileid's");
Reid Spencer5f016e22007-07-11 17:01:13 +000056
Chris Lattner9dc1f532007-07-20 16:37:10 +000057 L.ID = (FileID << FilePosBits) | FilePos;
58 return L;
Reid Spencer5f016e22007-07-11 17:01:13 +000059 }
60
Chris Lattnerd1623a82007-07-21 06:41:57 +000061 static bool isValidMacroPhysOffs(int Val) {
62 if (Val >= 0)
63 return Val < (1 << (MacroPhysOffsBits-1));
64 return -Val < (1 << (MacroPhysOffsBits-1));
65 }
66
67 static SourceLocation getMacroLoc(unsigned MacroID, int PhysOffs,
Chris Lattner9dc1f532007-07-20 16:37:10 +000068 unsigned LogOffs) {
Chris Lattner9dc1f532007-07-20 16:37:10 +000069 assert(MacroID < (1 << MacroIDBits) && "Too many macros!");
Chris Lattnerd1623a82007-07-21 06:41:57 +000070 assert(isValidMacroPhysOffs(PhysOffs) && "Physoffs too large!");
Chris Lattner9dc1f532007-07-20 16:37:10 +000071 assert(LogOffs < (1 << MacroLogOffBits) && "Logical offs too large!");
72
Chris Lattnerd1623a82007-07-21 06:41:57 +000073 PhysOffs &= (1 << MacroPhysOffsBits)-1;
74
75 SourceLocation L;
Chris Lattner9dc1f532007-07-20 16:37:10 +000076 L.ID = (1 << 31) | (MacroID << (MacroPhysOffsBits+MacroLogOffBits)) |
Chris Lattnerd1623a82007-07-21 06:41:57 +000077 (PhysOffs << MacroLogOffBits) |
78 LogOffs;
Chris Lattner9dc1f532007-07-20 16:37:10 +000079 return L;
80 }
81
82
Reid Spencer5f016e22007-07-11 17:01:13 +000083 /// isValid - Return true if this is a valid SourceLocation object. Invalid
84 /// SourceLocations are often used when events have no corresponding location
85 /// in the source (e.g. a diagnostic is required for a command line option).
86 ///
87 bool isValid() const { return ID != 0; }
Chris Lattner9dc1f532007-07-20 16:37:10 +000088 bool isInvalid() const { return ID == 0; }
Reid Spencer5f016e22007-07-11 17:01:13 +000089
90 /// getFileID - Return the file identifier for this SourceLocation. This
91 /// FileID can be used with the SourceManager object to obtain an entire
92 /// include stack for a file position reference.
Chris Lattner9dc1f532007-07-20 16:37:10 +000093 unsigned getFileID() const {
94 assert(isFileID() && "can't get the file id of a non-file sloc!");
95 return ID >> FilePosBits;
96 }
Reid Spencer5f016e22007-07-11 17:01:13 +000097
98 /// getRawFilePos - Return the byte offset from the start of the file-chunk
99 /// referred to by FileID. This method should not be used to get the offset
100 /// from the start of the file, instead you should use
101 /// SourceManager::getFilePos. This method will be incorrect for large files.
Chris Lattner9dc1f532007-07-20 16:37:10 +0000102 unsigned getRawFilePos() const {
103 assert(isFileID() && "can't get the file id of a non-file sloc!");
Chris Lattner2c64b7b2007-10-16 21:07:07 +0000104 return ID & (ChunkSize-1);
Chris Lattner9dc1f532007-07-20 16:37:10 +0000105 }
106
107 unsigned getMacroID() const {
108 assert(isMacroID() && "Is not a macro id!");
109 return (ID >> (MacroPhysOffsBits+MacroLogOffBits)) & ((1 << MacroIDBits)-1);
110 }
Reid Spencer5f016e22007-07-11 17:01:13 +0000111
Chris Lattnerd1623a82007-07-21 06:41:57 +0000112 int getMacroPhysOffs() const {
Chris Lattner9dc1f532007-07-20 16:37:10 +0000113 assert(isMacroID() && "Is not a macro id!");
Chris Lattnerd1623a82007-07-21 06:41:57 +0000114 int Val = (ID >> MacroLogOffBits) & ((1 << MacroPhysOffsBits)-1);
115 // Sign extend it properly.
116 unsigned ShAmt = sizeof(int)*8 - MacroPhysOffsBits;
117 return (Val << ShAmt) >> ShAmt;
Chris Lattner9dc1f532007-07-20 16:37:10 +0000118 }
119
120 unsigned getMacroLogOffs() const {
121 assert(isMacroID() && "Is not a macro id!");
Chris Lattner31bb8be2007-07-20 18:00:12 +0000122 return ID & ((1 << MacroLogOffBits)-1);
Chris Lattner9dc1f532007-07-20 16:37:10 +0000123 }
124
125 /// getFileLocWithOffset - Return a source location with the specified offset
126 /// from this file SourceLocation.
Chris Lattnerd1623a82007-07-21 06:41:57 +0000127 SourceLocation getFileLocWithOffset(int Offset) const {
Chris Lattner2c64b7b2007-10-16 21:07:07 +0000128 unsigned FileID = getFileID();
129 Offset += getRawFilePos();
130 // Handle negative offsets correctly.
131 while (Offset < 0) {
132 --FileID;
133 Offset += ChunkSize;
134 }
135 return getFileLoc(FileID, Offset);
Chris Lattner9dc1f532007-07-20 16:37:10 +0000136 }
Reid Spencer5f016e22007-07-11 17:01:13 +0000137
138 /// getRawEncoding - When a SourceLocation itself cannot be used, this returns
139 /// an (opaque) 32-bit integer encoding for it. This should only be passed
140 /// to SourceLocation::getFromRawEncoding, it should not be inspected
141 /// directly.
142 unsigned getRawEncoding() const { return ID; }
143
144 /// getFromRawEncoding - Turn a raw encoding of a SourceLocation object into
145 /// a real SourceLocation.
146 static SourceLocation getFromRawEncoding(unsigned Encoding) {
147 SourceLocation X;
148 X.ID = Encoding;
149 return X;
150 }
151};
152
153inline bool operator==(const SourceLocation &LHS, const SourceLocation &RHS) {
154 return LHS.getRawEncoding() == RHS.getRawEncoding();
155}
156
157inline bool operator!=(const SourceLocation &LHS, const SourceLocation &RHS) {
158 return !(LHS == RHS);
159}
160
161/// SourceRange - a trival tuple used to represent a source range.
162class SourceRange {
163 SourceLocation B;
164 SourceLocation E;
165public:
166 SourceRange(): B(SourceLocation()), E(SourceLocation()) {}
167 SourceRange(SourceLocation loc) : B(loc), E(loc) {}
168 SourceRange(SourceLocation begin, SourceLocation end) : B(begin), E(end) {}
169
Chris Lattner311ff022007-10-16 22:36:42 +0000170 SourceLocation getBegin() const { return B; }
171 SourceLocation getEnd() const { return E; }
Reid Spencer5f016e22007-07-11 17:01:13 +0000172
Chris Lattnere80a59c2007-07-25 00:24:17 +0000173 void setBegin(SourceLocation b) { B = b; }
174 void setEnd(SourceLocation e) { E = e; }
175
Reid Spencer5f016e22007-07-11 17:01:13 +0000176 bool isValid() const { return B.isValid() && E.isValid(); }
177};
178
179} // end namespace clang
180
Ted Kremenek19a95bc2007-10-25 16:02:43 +0000181//===----------------------------------------------------------------------===//
182// Serialization of SourceLocations and SourceRanges.
183//===----------------------------------------------------------------------===//
184
185namespace llvm {
186
187template<> struct SerializeTrait<clang::SourceLocation> {
188 static void Emit(Serializer& S, clang::SourceLocation L);
189 static clang::SourceLocation ReadVal(Deserializer& D);
190};
191
192template<> struct SerializeTrait<clang::SourceRange> {
193 static inline void Emit(Serializer& S, clang::SourceRange R) {
194 SerializeTrait<clang::SourceLocation>::Emit(S,R.getBegin());
195 SerializeTrait<clang::SourceLocation>::Emit(S,R.getEnd());
196 }
197
198 static inline clang::SourceRange ReadVal(Deserializer& D) {
199 using clang::SourceLocation;
200 SourceLocation L = SerializeTrait<SourceLocation>::ReadVal(D);
201 SourceLocation R = SerializeTrait<SourceLocation>::ReadVal(D);
202 return clang::SourceRange(L,R);
203 }
204};
205
206} // end namespace llvm
207
Reid Spencer5f016e22007-07-11 17:01:13 +0000208#endif