SourceLocation.h revision 4bd495c2a4fc742dde435115f66c722217975bd2
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/// \brief An opaque identifier used by SourceManager which refers to a 35/// 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 /// \brief When a SourceLocation itself cannot be used, this returns 139 /// an (opaque) 32-bit integer encoding for it. 140 /// 141 /// This should only be passed to SourceLocation::getFromRawEncoding, it 142 /// should not be inspected directly. 143 unsigned getRawEncoding() const { return ID; } 144 145 /// \brief Turn a raw encoding of a SourceLocation object into 146 /// a real SourceLocation. 147 /// 148 /// \see getRawEncoding. 149 static SourceLocation getFromRawEncoding(unsigned Encoding) { 150 SourceLocation X; 151 X.ID = Encoding; 152 return X; 153 } 154 155 /// \brief When a SourceLocation itself cannot be used, this returns 156 /// an (opaque) pointer encoding for it. 157 /// 158 /// This should only be passed to SourceLocation::getFromPtrEncoding, it 159 /// should not be inspected directly. 160 void* getPtrEncoding() const { 161 // Double cast to avoid a warning "cast to pointer from integer of different 162 // size". 163 return (void*)(uintptr_t)getRawEncoding(); 164 } 165 166 /// getFromPtrEncoding - Turn a pointer encoding of a SourceLocation object 167 /// into a real SourceLocation. 168 static SourceLocation getFromPtrEncoding(void *Encoding) { 169 return getFromRawEncoding((unsigned)(uintptr_t)Encoding); 170 } 171 172 void print(raw_ostream &OS, const SourceManager &SM) const; 173 void dump(const SourceManager &SM) const; 174}; 175 176inline bool operator==(const SourceLocation &LHS, const SourceLocation &RHS) { 177 return LHS.getRawEncoding() == RHS.getRawEncoding(); 178} 179 180inline bool operator!=(const SourceLocation &LHS, const SourceLocation &RHS) { 181 return !(LHS == RHS); 182} 183 184inline bool operator<(const SourceLocation &LHS, const SourceLocation &RHS) { 185 return LHS.getRawEncoding() < RHS.getRawEncoding(); 186} 187 188/// SourceRange - a trival tuple used to represent a source range. 189class SourceRange { 190 SourceLocation B; 191 SourceLocation E; 192public: 193 SourceRange(): B(SourceLocation()), E(SourceLocation()) {} 194 SourceRange(SourceLocation loc) : B(loc), E(loc) {} 195 SourceRange(SourceLocation begin, SourceLocation end) : B(begin), E(end) {} 196 197 SourceLocation getBegin() const { return B; } 198 SourceLocation getEnd() const { return E; } 199 200 void setBegin(SourceLocation b) { B = b; } 201 void setEnd(SourceLocation e) { E = e; } 202 203 bool isValid() const { return B.isValid() && E.isValid(); } 204 bool isInvalid() const { return !isValid(); } 205 206 bool operator==(const SourceRange &X) const { 207 return B == X.B && E == X.E; 208 } 209 210 bool operator!=(const SourceRange &X) const { 211 return B != X.B || E != X.E; 212 } 213}; 214 215/// CharSourceRange - This class represents a character granular source range. 216/// The underlying SourceRange can either specify the starting/ending character 217/// of the range, or it can specify the start or the range and the start of the 218/// last token of the range (a "token range"). In the token range case, the 219/// size of the last token must be measured to determine the actual end of the 220/// range. 221class CharSourceRange { 222 SourceRange Range; 223 bool IsTokenRange; 224public: 225 CharSourceRange() : IsTokenRange(false) {} 226 CharSourceRange(SourceRange R, bool ITR) : Range(R),IsTokenRange(ITR){} 227 228 static CharSourceRange getTokenRange(SourceRange R) { 229 CharSourceRange Result; 230 Result.Range = R; 231 Result.IsTokenRange = true; 232 return Result; 233 } 234 235 static CharSourceRange getCharRange(SourceRange R) { 236 CharSourceRange Result; 237 Result.Range = R; 238 Result.IsTokenRange = false; 239 return Result; 240 } 241 242 static CharSourceRange getTokenRange(SourceLocation B, SourceLocation E) { 243 return getTokenRange(SourceRange(B, E)); 244 } 245 static CharSourceRange getCharRange(SourceLocation B, SourceLocation E) { 246 return getCharRange(SourceRange(B, E)); 247 } 248 249 /// isTokenRange - Return true if the end of this range specifies the start of 250 /// the last token. Return false if the end of this range specifies the last 251 /// character in the range. 252 bool isTokenRange() const { return IsTokenRange; } 253 bool isCharRange() const { return !IsTokenRange; } 254 255 SourceLocation getBegin() const { return Range.getBegin(); } 256 SourceLocation getEnd() const { return Range.getEnd(); } 257 const SourceRange &getAsRange() const { return Range; } 258 259 void setBegin(SourceLocation b) { Range.setBegin(b); } 260 void setEnd(SourceLocation e) { Range.setEnd(e); } 261 262 bool isValid() const { return Range.isValid(); } 263 bool isInvalid() const { return !isValid(); } 264}; 265 266/// FullSourceLoc - A SourceLocation and its associated SourceManager. Useful 267/// for argument passing to functions that expect both objects. 268class FullSourceLoc : public SourceLocation { 269 const SourceManager *SrcMgr; 270public: 271 /// Creates a FullSourceLoc where isValid() returns false. 272 explicit FullSourceLoc() : SrcMgr(0) {} 273 274 explicit FullSourceLoc(SourceLocation Loc, const SourceManager &SM) 275 : SourceLocation(Loc), SrcMgr(&SM) {} 276 277 const SourceManager &getManager() const { 278 assert(SrcMgr && "SourceManager is NULL."); 279 return *SrcMgr; 280 } 281 282 FileID getFileID() const; 283 284 FullSourceLoc getExpansionLoc() const; 285 FullSourceLoc getSpellingLoc() const; 286 287 unsigned getExpansionLineNumber(bool *Invalid = 0) const; 288 unsigned getExpansionColumnNumber(bool *Invalid = 0) const; 289 290 unsigned getSpellingLineNumber(bool *Invalid = 0) const; 291 unsigned getSpellingColumnNumber(bool *Invalid = 0) const; 292 293 const char *getCharacterData(bool *Invalid = 0) const; 294 295 const llvm::MemoryBuffer* getBuffer(bool *Invalid = 0) const; 296 297 /// getBufferData - Return a StringRef to the source buffer data for the 298 /// specified FileID. 299 StringRef getBufferData(bool *Invalid = 0) const; 300 301 /// getDecomposedLoc - Decompose the specified location into a raw FileID + 302 /// Offset pair. The first element is the FileID, the second is the 303 /// offset from the start of the buffer of the location. 304 std::pair<FileID, unsigned> getDecomposedLoc() const; 305 306 bool isInSystemHeader() const; 307 308 /// \brief Determines the order of 2 source locations in the translation unit. 309 /// 310 /// \returns true if this source location comes before 'Loc', false otherwise. 311 bool isBeforeInTranslationUnitThan(SourceLocation Loc) const; 312 313 /// \brief Determines the order of 2 source locations in the translation unit. 314 /// 315 /// \returns true if this source location comes before 'Loc', false otherwise. 316 bool isBeforeInTranslationUnitThan(FullSourceLoc Loc) const { 317 assert(Loc.isValid()); 318 assert(SrcMgr == Loc.SrcMgr && "Loc comes from another SourceManager!"); 319 return isBeforeInTranslationUnitThan((SourceLocation)Loc); 320 } 321 322 /// \brief Comparison function class, useful for sorting FullSourceLocs. 323 struct BeforeThanCompare : public std::binary_function<FullSourceLoc, 324 FullSourceLoc, bool> { 325 bool operator()(const FullSourceLoc& lhs, const FullSourceLoc& rhs) const { 326 return lhs.isBeforeInTranslationUnitThan(rhs); 327 } 328 }; 329 330 /// Prints information about this FullSourceLoc to stderr. Useful for 331 /// debugging. 332 LLVM_ATTRIBUTE_USED void dump() const; 333 334 friend inline bool 335 operator==(const FullSourceLoc &LHS, const FullSourceLoc &RHS) { 336 return LHS.getRawEncoding() == RHS.getRawEncoding() && 337 LHS.SrcMgr == RHS.SrcMgr; 338 } 339 340 friend inline bool 341 operator!=(const FullSourceLoc &LHS, const FullSourceLoc &RHS) { 342 return !(LHS == RHS); 343 } 344 345}; 346 347/// PresumedLoc - This class represents an unpacked "presumed" location which 348/// can be presented to the user. A 'presumed' location can be modified by 349/// \#line and GNU line marker directives and is always the expansion point of 350/// a normal location. 351/// 352/// You can get a PresumedLoc from a SourceLocation with SourceManager. 353class PresumedLoc { 354 const char *Filename; 355 unsigned Line, Col; 356 SourceLocation IncludeLoc; 357public: 358 PresumedLoc() : Filename(0) {} 359 PresumedLoc(const char *FN, unsigned Ln, unsigned Co, SourceLocation IL) 360 : Filename(FN), Line(Ln), Col(Co), IncludeLoc(IL) { 361 } 362 363 /// isInvalid - Return true if this object is invalid or uninitialized. This 364 /// occurs when created with invalid source locations or when walking off 365 /// the top of a \#include stack. 366 bool isInvalid() const { return Filename == 0; } 367 bool isValid() const { return Filename != 0; } 368 369 /// \brief Return the presumed filename of this location. 370 /// 371 /// This can be affected by \#line etc. 372 const char *getFilename() const { return Filename; } 373 374 /// \brief Return the presumed line number of this location. 375 /// 376 /// This can be affected by \#line etc. 377 unsigned getLine() const { return Line; } 378 379 /// \brief Return the presumed column number of this location. 380 /// 381 /// This cannot be affected by \#line, but is packaged here for convenience. 382 unsigned getColumn() const { return Col; } 383 384 /// \brief Return the presumed include location of this location. 385 /// 386 /// This can be affected by GNU linemarker directives. 387 SourceLocation getIncludeLoc() const { return IncludeLoc; } 388}; 389 390 391} // end namespace clang 392 393namespace llvm { 394 /// Define DenseMapInfo so that FileID's can be used as keys in DenseMap and 395 /// DenseSets. 396 template <> 397 struct DenseMapInfo<clang::FileID> { 398 static inline clang::FileID getEmptyKey() { 399 return clang::FileID(); 400 } 401 static inline clang::FileID getTombstoneKey() { 402 return clang::FileID::getSentinel(); 403 } 404 405 static unsigned getHashValue(clang::FileID S) { 406 return S.getHashValue(); 407 } 408 409 static bool isEqual(clang::FileID LHS, clang::FileID RHS) { 410 return LHS == RHS; 411 } 412 }; 413 414 template <> 415 struct isPodLike<clang::SourceLocation> { static const bool value = true; }; 416 template <> 417 struct isPodLike<clang::FileID> { static const bool value = true; }; 418 419 // Teach SmallPtrSet how to handle SourceLocation. 420 template<> 421 class PointerLikeTypeTraits<clang::SourceLocation> { 422 public: 423 static inline void *getAsVoidPointer(clang::SourceLocation L) { 424 return L.getPtrEncoding(); 425 } 426 static inline clang::SourceLocation getFromVoidPointer(void *P) { 427 return clang::SourceLocation::getFromRawEncoding((unsigned)(uintptr_t)P); 428 } 429 enum { NumLowBitsAvailable = 0 }; 430 }; 431 432} // end namespace llvm 433 434#endif 435