SourceLocation.h revision a6c10681e57c292e16a18bdb9891c8db6ebe5c83
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 "clang/Basic/LLVM.h" 18#include "llvm/Support/PointerLikeTypeTraits.h" 19#include "llvm/Support/Compiler.h" 20#include <utility> 21#include <functional> 22#include <cassert> 23 24namespace llvm { 25 class MemoryBuffer; 26 template <typename T> struct DenseMapInfo; 27 template <typename T> struct isPodLike; 28} 29 30namespace clang { 31 32class SourceManager; 33 34/// FileID - This is an opaque identifier used by SourceManager which refers to 35/// a source file (MemoryBuffer) along with its #include path and #line data. 36/// 37class FileID { 38 /// ID - Opaque identifier, 0 is "invalid". >0 is this module, <-1 is 39 /// something loaded from another module. 40 int ID; 41public: 42 FileID() : ID(0) {} 43 44 bool isInvalid() const { return ID == 0; } 45 46 bool operator==(const FileID &RHS) const { return ID == RHS.ID; } 47 bool operator<(const FileID &RHS) const { return ID < RHS.ID; } 48 bool operator<=(const FileID &RHS) const { return ID <= RHS.ID; } 49 bool operator!=(const FileID &RHS) const { return !(*this == RHS); } 50 bool operator>(const FileID &RHS) const { return RHS < *this; } 51 bool operator>=(const FileID &RHS) const { return RHS <= *this; } 52 53 static FileID getSentinel() { return get(-1); } 54 unsigned getHashValue() const { return static_cast<unsigned>(ID); } 55 56private: 57 friend class SourceManager; 58 friend class ASTWriter; 59 friend class ASTReader; 60 61 static FileID get(int V) { 62 FileID F; 63 F.ID = V; 64 return F; 65 } 66 int getOpaqueValue() const { return ID; } 67}; 68 69 70/// \brief Encodes a location in the source. The SourceManager can decode this 71/// to get at the full include stack, line and column information. 72/// 73/// Technically, a source location is simply an offset into the manager's view 74/// of the input source, which is all input buffers (including macro 75/// expansions) concatenated in an effectively arbitrary order. The manager 76/// actually maintains two blocks of input buffers. One, starting at offset 77/// 0 and growing upwards, contains all buffers from this module. The other, 78/// starting at the highest possible offset and growing downwards, contains 79/// buffers of loaded modules. 80/// 81/// In addition, one bit of SourceLocation is used for quick access to the 82/// information whether the location is in a file or a macro expansion. 83/// 84/// It is important that this type remains small. It is currently 32 bits wide. 85class SourceLocation { 86 unsigned ID; 87 friend class SourceManager; 88 friend class ASTReader; 89 friend class ASTWriter; 90 enum { 91 MacroIDBit = 1U << 31 92 }; 93public: 94 95 SourceLocation() : ID(0) {} 96 97 bool isFileID() const { return (ID & MacroIDBit) == 0; } 98 bool isMacroID() const { return (ID & MacroIDBit) != 0; } 99 100 /// \brief Return true if this is a valid SourceLocation object. 101 /// 102 /// Invalid SourceLocations are often used when events have no corresponding 103 /// location in the source (e.g. a diagnostic is required for a command line 104 /// option). 105 bool isValid() const { return ID != 0; } 106 bool isInvalid() const { return ID == 0; } 107 108private: 109 /// \brief Return the offset into the manager's global input view. 110 unsigned getOffset() const { 111 return ID & ~MacroIDBit; 112 } 113 114 static SourceLocation getFileLoc(unsigned ID) { 115 assert((ID & MacroIDBit) == 0 && "Ran out of source locations!"); 116 SourceLocation L; 117 L.ID = ID; 118 return L; 119 } 120 121 static SourceLocation getMacroLoc(unsigned ID) { 122 assert((ID & MacroIDBit) == 0 && "Ran out of source locations!"); 123 SourceLocation L; 124 L.ID = MacroIDBit | ID; 125 return L; 126 } 127public: 128 129 /// \brief Return a source location with the specified offset from this 130 /// SourceLocation. 131 SourceLocation getLocWithOffset(int Offset) const { 132 assert(((getOffset()+Offset) & MacroIDBit) == 0 && "offset overflow"); 133 SourceLocation L; 134 L.ID = ID+Offset; 135 return L; 136 } 137 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 /// getPtrEncoding - When a SourceLocation itself cannot be used, this returns 153 /// an (opaque) pointer encoding for it. This should only be passed 154 /// to SourceLocation::getFromPtrEncoding, it should not be inspected 155 /// directly. 156 void* getPtrEncoding() const { 157 // Double cast to avoid a warning "cast to pointer from integer of different 158 // size". 159 return (void*)(uintptr_t)getRawEncoding(); 160 } 161 162 /// getFromPtrEncoding - Turn a pointer encoding of a SourceLocation object 163 /// into a real SourceLocation. 164 static SourceLocation getFromPtrEncoding(void *Encoding) { 165 return getFromRawEncoding((unsigned)(uintptr_t)Encoding); 166 } 167 168 void print(raw_ostream &OS, const SourceManager &SM) const; 169 void dump(const SourceManager &SM) const; 170}; 171 172inline bool operator==(const SourceLocation &LHS, const SourceLocation &RHS) { 173 return LHS.getRawEncoding() == RHS.getRawEncoding(); 174} 175 176inline bool operator!=(const SourceLocation &LHS, const SourceLocation &RHS) { 177 return !(LHS == RHS); 178} 179 180inline bool operator<(const SourceLocation &LHS, const SourceLocation &RHS) { 181 return LHS.getRawEncoding() < RHS.getRawEncoding(); 182} 183 184/// SourceRange - a trival tuple used to represent a source range. 185class SourceRange { 186 SourceLocation B; 187 SourceLocation E; 188public: 189 SourceRange(): B(SourceLocation()), E(SourceLocation()) {} 190 SourceRange(SourceLocation loc) : B(loc), E(loc) {} 191 SourceRange(SourceLocation begin, SourceLocation end) : B(begin), E(end) {} 192 193 SourceLocation getBegin() const { return B; } 194 SourceLocation getEnd() const { return E; } 195 196 void setBegin(SourceLocation b) { B = b; } 197 void setEnd(SourceLocation e) { E = e; } 198 199 bool isValid() const { return B.isValid() && E.isValid(); } 200 bool isInvalid() const { return !isValid(); } 201 202 bool operator==(const SourceRange &X) const { 203 return B == X.B && E == X.E; 204 } 205 206 bool operator!=(const SourceRange &X) const { 207 return B != X.B || E != X.E; 208 } 209}; 210 211/// CharSourceRange - This class represents a character granular source range. 212/// The underlying SourceRange can either specify the starting/ending character 213/// of the range, or it can specify the start or the range and the start of the 214/// last token of the range (a "token range"). In the token range case, the 215/// size of the last token must be measured to determine the actual end of the 216/// range. 217class CharSourceRange { 218 SourceRange Range; 219 bool IsTokenRange; 220public: 221 CharSourceRange() : IsTokenRange(false) {} 222 CharSourceRange(SourceRange R, bool ITR) : Range(R),IsTokenRange(ITR){} 223 224 static CharSourceRange getTokenRange(SourceRange R) { 225 CharSourceRange Result; 226 Result.Range = R; 227 Result.IsTokenRange = true; 228 return Result; 229 } 230 231 static CharSourceRange getCharRange(SourceRange R) { 232 CharSourceRange Result; 233 Result.Range = R; 234 Result.IsTokenRange = false; 235 return Result; 236 } 237 238 static CharSourceRange getTokenRange(SourceLocation B, SourceLocation E) { 239 return getTokenRange(SourceRange(B, E)); 240 } 241 static CharSourceRange getCharRange(SourceLocation B, SourceLocation E) { 242 return getCharRange(SourceRange(B, E)); 243 } 244 245 /// isTokenRange - Return true if the end of this range specifies the start of 246 /// the last token. Return false if the end of this range specifies the last 247 /// character in the range. 248 bool isTokenRange() const { return IsTokenRange; } 249 bool isCharRange() const { return !IsTokenRange; } 250 251 SourceLocation getBegin() const { return Range.getBegin(); } 252 SourceLocation getEnd() const { return Range.getEnd(); } 253 const SourceRange &getAsRange() const { return Range; } 254 255 void setBegin(SourceLocation b) { Range.setBegin(b); } 256 void setEnd(SourceLocation e) { Range.setEnd(e); } 257 258 bool isValid() const { return Range.isValid(); } 259 bool isInvalid() const { return !isValid(); } 260}; 261 262/// FullSourceLoc - A SourceLocation and its associated SourceManager. Useful 263/// for argument passing to functions that expect both objects. 264class FullSourceLoc : public SourceLocation { 265 const SourceManager *SrcMgr; 266public: 267 /// Creates a FullSourceLoc where isValid() returns false. 268 explicit FullSourceLoc() : SrcMgr(0) {} 269 270 explicit FullSourceLoc(SourceLocation Loc, const SourceManager &SM) 271 : SourceLocation(Loc), SrcMgr(&SM) {} 272 273 const SourceManager &getManager() const { 274 assert(SrcMgr && "SourceManager is NULL."); 275 return *SrcMgr; 276 } 277 278 FileID getFileID() const; 279 280 FullSourceLoc getExpansionLoc() const; 281 FullSourceLoc getSpellingLoc() const; 282 283 unsigned getExpansionLineNumber(bool *Invalid = 0) const; 284 unsigned getExpansionColumnNumber(bool *Invalid = 0) const; 285 286 unsigned getSpellingLineNumber(bool *Invalid = 0) const; 287 unsigned getSpellingColumnNumber(bool *Invalid = 0) const; 288 289 const char *getCharacterData(bool *Invalid = 0) const; 290 291 const llvm::MemoryBuffer* getBuffer(bool *Invalid = 0) const; 292 293 /// getBufferData - Return a StringRef to the source buffer data for the 294 /// specified FileID. 295 StringRef getBufferData(bool *Invalid = 0) const; 296 297 /// getDecomposedLoc - Decompose the specified location into a raw FileID + 298 /// Offset pair. The first element is the FileID, the second is the 299 /// offset from the start of the buffer of the location. 300 std::pair<FileID, unsigned> getDecomposedLoc() const; 301 302 bool isInSystemHeader() const; 303 304 /// \brief Determines the order of 2 source locations in the translation unit. 305 /// 306 /// \returns true if this source location comes before 'Loc', false otherwise. 307 bool isBeforeInTranslationUnitThan(SourceLocation Loc) const; 308 309 /// \brief Determines the order of 2 source locations in the translation unit. 310 /// 311 /// \returns true if this source location comes before 'Loc', false otherwise. 312 bool isBeforeInTranslationUnitThan(FullSourceLoc Loc) const { 313 assert(Loc.isValid()); 314 assert(SrcMgr == Loc.SrcMgr && "Loc comes from another SourceManager!"); 315 return isBeforeInTranslationUnitThan((SourceLocation)Loc); 316 } 317 318 /// \brief Comparison function class, useful for sorting FullSourceLocs. 319 struct BeforeThanCompare : public std::binary_function<FullSourceLoc, 320 FullSourceLoc, bool> { 321 bool operator()(const FullSourceLoc& lhs, const FullSourceLoc& rhs) const { 322 return lhs.isBeforeInTranslationUnitThan(rhs); 323 } 324 }; 325 326 /// Prints information about this FullSourceLoc to stderr. Useful for 327 /// debugging. 328 LLVM_ATTRIBUTE_USED void dump() const; 329 330 friend inline bool 331 operator==(const FullSourceLoc &LHS, const FullSourceLoc &RHS) { 332 return LHS.getRawEncoding() == RHS.getRawEncoding() && 333 LHS.SrcMgr == RHS.SrcMgr; 334 } 335 336 friend inline bool 337 operator!=(const FullSourceLoc &LHS, const FullSourceLoc &RHS) { 338 return !(LHS == RHS); 339 } 340 341}; 342 343/// PresumedLoc - This class represents an unpacked "presumed" location which 344/// can be presented to the user. A 'presumed' location can be modified by 345/// #line and GNU line marker directives and is always the expansion point of 346/// a normal location. 347/// 348/// You can get a PresumedLoc from a SourceLocation with SourceManager. 349class PresumedLoc { 350 const char *Filename; 351 unsigned Line, Col; 352 SourceLocation IncludeLoc; 353public: 354 PresumedLoc() : Filename(0) {} 355 PresumedLoc(const char *FN, unsigned Ln, unsigned Co, SourceLocation IL) 356 : Filename(FN), Line(Ln), Col(Co), IncludeLoc(IL) { 357 } 358 359 /// isInvalid - Return true if this object is invalid or uninitialized. This 360 /// occurs when created with invalid source locations or when walking off 361 /// the top of a #include stack. 362 bool isInvalid() const { return Filename == 0; } 363 bool isValid() const { return Filename != 0; } 364 365 /// getFilename - Return the presumed filename of this location. This can be 366 /// affected by #line etc. 367 const char *getFilename() const { return Filename; } 368 369 /// getLine - Return the presumed line number of this location. This can be 370 /// affected by #line etc. 371 unsigned getLine() const { return Line; } 372 373 /// getColumn - Return the presumed column number of this location. This can 374 /// not be affected by #line, but is packaged here for convenience. 375 unsigned getColumn() const { return Col; } 376 377 /// getIncludeLoc - Return the presumed include location of this location. 378 /// This can be affected by GNU linemarker directives. 379 SourceLocation getIncludeLoc() const { return IncludeLoc; } 380}; 381 382 383} // end namespace clang 384 385namespace llvm { 386 /// Define DenseMapInfo so that FileID's can be used as keys in DenseMap and 387 /// DenseSets. 388 template <> 389 struct DenseMapInfo<clang::FileID> { 390 static inline clang::FileID getEmptyKey() { 391 return clang::FileID(); 392 } 393 static inline clang::FileID getTombstoneKey() { 394 return clang::FileID::getSentinel(); 395 } 396 397 static unsigned getHashValue(clang::FileID S) { 398 return S.getHashValue(); 399 } 400 401 static bool isEqual(clang::FileID LHS, clang::FileID RHS) { 402 return LHS == RHS; 403 } 404 }; 405 406 template <> 407 struct isPodLike<clang::SourceLocation> { static const bool value = true; }; 408 template <> 409 struct isPodLike<clang::FileID> { static const bool value = true; }; 410 411 // Teach SmallPtrSet how to handle SourceLocation. 412 template<> 413 class PointerLikeTypeTraits<clang::SourceLocation> { 414 public: 415 static inline void *getAsVoidPointer(clang::SourceLocation L) { 416 return L.getPtrEncoding(); 417 } 418 static inline clang::SourceLocation getFromVoidPointer(void *P) { 419 return clang::SourceLocation::getFromRawEncoding((unsigned)(uintptr_t)P); 420 } 421 enum { NumLowBitsAvailable = 0 }; 422 }; 423 424} // end namespace llvm 425 426#endif 427