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 24 namespace llvm { 25 class MemoryBuffer; 26 template <typename T> struct DenseMapInfo; 27 template <typename T> struct isPodLike; 28 } 29 30 namespace clang { 31 32 class 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 /// 37 class FileID { 38 /// ID - Opaque identifier, 0 is "invalid". >0 is this module, <-1 is 39 /// something loaded from another module. 40 int ID; 41 public: FileID()42 FileID() : ID(0) {} 43 isInvalid()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 getSentinel()53 static FileID getSentinel() { return get(-1); } getHashValue()54 unsigned getHashValue() const { return static_cast<unsigned>(ID); } 55 56 private: 57 friend class SourceManager; 58 friend class ASTWriter; 59 friend class ASTReader; 60 get(int V)61 static FileID get(int V) { 62 FileID F; 63 F.ID = V; 64 return F; 65 } getOpaqueValue()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. 85 class SourceLocation { 86 unsigned ID; 87 friend class SourceManager; 88 friend class ASTReader; 89 friend class ASTWriter; 90 enum { 91 MacroIDBit = 1U << 31 92 }; 93 public: 94 SourceLocation()95 SourceLocation() : ID(0) {} 96 isFileID()97 bool isFileID() const { return (ID & MacroIDBit) == 0; } isMacroID()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). isValid()105 bool isValid() const { return ID != 0; } isInvalid()106 bool isInvalid() const { return ID == 0; } 107 108 private: 109 /// \brief Return the offset into the manager's global input view. getOffset()110 unsigned getOffset() const { 111 return ID & ~MacroIDBit; 112 } 113 getFileLoc(unsigned ID)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 getMacroLoc(unsigned ID)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 } 127 public: 128 129 /// \brief Return a source location with the specified offset from this 130 /// SourceLocation. getLocWithOffset(int Offset)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. getRawEncoding()142 unsigned getRawEncoding() const { return ID; } 143 144 /// getFromRawEncoding - Turn a raw encoding of a SourceLocation object into 145 /// a real SourceLocation. getFromRawEncoding(unsigned Encoding)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. getPtrEncoding()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. getFromPtrEncoding(void * Encoding)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 172 inline bool operator==(const SourceLocation &LHS, const SourceLocation &RHS) { 173 return LHS.getRawEncoding() == RHS.getRawEncoding(); 174 } 175 176 inline bool operator!=(const SourceLocation &LHS, const SourceLocation &RHS) { 177 return !(LHS == RHS); 178 } 179 180 inline 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. 185 class SourceRange { 186 SourceLocation B; 187 SourceLocation E; 188 public: SourceRange()189 SourceRange(): B(SourceLocation()), E(SourceLocation()) {} SourceRange(SourceLocation loc)190 SourceRange(SourceLocation loc) : B(loc), E(loc) {} SourceRange(SourceLocation begin,SourceLocation end)191 SourceRange(SourceLocation begin, SourceLocation end) : B(begin), E(end) {} 192 getBegin()193 SourceLocation getBegin() const { return B; } getEnd()194 SourceLocation getEnd() const { return E; } 195 setBegin(SourceLocation b)196 void setBegin(SourceLocation b) { B = b; } setEnd(SourceLocation e)197 void setEnd(SourceLocation e) { E = e; } 198 isValid()199 bool isValid() const { return B.isValid() && E.isValid(); } isInvalid()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. 217 class CharSourceRange { 218 SourceRange Range; 219 bool IsTokenRange; 220 public: CharSourceRange()221 CharSourceRange() : IsTokenRange(false) {} CharSourceRange(SourceRange R,bool ITR)222 CharSourceRange(SourceRange R, bool ITR) : Range(R),IsTokenRange(ITR){} 223 getTokenRange(SourceRange R)224 static CharSourceRange getTokenRange(SourceRange R) { 225 CharSourceRange Result; 226 Result.Range = R; 227 Result.IsTokenRange = true; 228 return Result; 229 } 230 getCharRange(SourceRange R)231 static CharSourceRange getCharRange(SourceRange R) { 232 CharSourceRange Result; 233 Result.Range = R; 234 Result.IsTokenRange = false; 235 return Result; 236 } 237 getTokenRange(SourceLocation B,SourceLocation E)238 static CharSourceRange getTokenRange(SourceLocation B, SourceLocation E) { 239 return getTokenRange(SourceRange(B, E)); 240 } getCharRange(SourceLocation B,SourceLocation E)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. isTokenRange()248 bool isTokenRange() const { return IsTokenRange; } isCharRange()249 bool isCharRange() const { return !IsTokenRange; } 250 getBegin()251 SourceLocation getBegin() const { return Range.getBegin(); } getEnd()252 SourceLocation getEnd() const { return Range.getEnd(); } getAsRange()253 const SourceRange &getAsRange() const { return Range; } 254 setBegin(SourceLocation b)255 void setBegin(SourceLocation b) { Range.setBegin(b); } setEnd(SourceLocation e)256 void setEnd(SourceLocation e) { Range.setEnd(e); } 257 isValid()258 bool isValid() const { return Range.isValid(); } isInvalid()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. 264 class FullSourceLoc : public SourceLocation { 265 const SourceManager *SrcMgr; 266 public: 267 /// Creates a FullSourceLoc where isValid() returns false. FullSourceLoc()268 explicit FullSourceLoc() : SrcMgr(0) {} 269 FullSourceLoc(SourceLocation Loc,const SourceManager & SM)270 explicit FullSourceLoc(SourceLocation Loc, const SourceManager &SM) 271 : SourceLocation(Loc), SrcMgr(&SM) {} 272 getManager()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. isBeforeInTranslationUnitThan(FullSourceLoc Loc)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> { operatorBeforeThanCompare321 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. 349 class PresumedLoc { 350 const char *Filename; 351 unsigned Line, Col; 352 SourceLocation IncludeLoc; 353 public: PresumedLoc()354 PresumedLoc() : Filename(0) {} PresumedLoc(const char * FN,unsigned Ln,unsigned Co,SourceLocation IL)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. isInvalid()362 bool isInvalid() const { return Filename == 0; } isValid()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. getFilename()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. getLine()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. getColumn()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. getIncludeLoc()379 SourceLocation getIncludeLoc() const { return IncludeLoc; } 380 }; 381 382 383 } // end namespace clang 384 385 namespace 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