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/// \file 11/// \brief Defines the clang::SourceLocation class and associated facilities. 12/// 13//===----------------------------------------------------------------------===// 14 15#ifndef LLVM_CLANG_BASIC_SOURCELOCATION_H 16#define LLVM_CLANG_BASIC_SOURCELOCATION_H 17 18#include "clang/Basic/LLVM.h" 19#include "llvm/Support/Compiler.h" 20#include "llvm/Support/PointerLikeTypeTraits.h" 21#include <cassert> 22#include <functional> 23#include <string> 24#include <utility> 25 26namespace llvm { 27 class MemoryBuffer; 28 template <typename T> struct DenseMapInfo; 29 template <typename T> struct isPodLike; 30} 31 32namespace clang { 33 34class SourceManager; 35 36/// \brief An opaque identifier used by SourceManager which refers to a 37/// source file (MemoryBuffer) along with its \#include path and \#line data. 38/// 39class FileID { 40 /// \brief A mostly-opaque identifier, where 0 is "invalid", >0 is 41 /// this module, and <-1 is something loaded from another module. 42 int ID = 0; 43 44public: 45 bool isValid() const { return ID != 0; } 46 bool isInvalid() const { return ID == 0; } 47 48 bool operator==(const FileID &RHS) const { return ID == RHS.ID; } 49 bool operator<(const FileID &RHS) const { return ID < RHS.ID; } 50 bool operator<=(const FileID &RHS) const { return ID <= RHS.ID; } 51 bool operator!=(const FileID &RHS) const { return !(*this == RHS); } 52 bool operator>(const FileID &RHS) const { return RHS < *this; } 53 bool operator>=(const FileID &RHS) const { return RHS <= *this; } 54 55 static FileID getSentinel() { return get(-1); } 56 unsigned getHashValue() const { return static_cast<unsigned>(ID); } 57 58private: 59 friend class SourceManager; 60 friend class ASTWriter; 61 friend class ASTReader; 62 63 static FileID get(int V) { 64 FileID F; 65 F.ID = V; 66 return F; 67 } 68 int getOpaqueValue() const { return ID; } 69}; 70 71 72/// \brief Encodes a location in the source. The SourceManager can decode this 73/// to get at the full include stack, line and column information. 74/// 75/// Technically, a source location is simply an offset into the manager's view 76/// of the input source, which is all input buffers (including macro 77/// expansions) concatenated in an effectively arbitrary order. The manager 78/// actually maintains two blocks of input buffers. One, starting at offset 79/// 0 and growing upwards, contains all buffers from this module. The other, 80/// starting at the highest possible offset and growing downwards, contains 81/// buffers of loaded modules. 82/// 83/// In addition, one bit of SourceLocation is used for quick access to the 84/// information whether the location is in a file or a macro expansion. 85/// 86/// It is important that this type remains small. It is currently 32 bits wide. 87class SourceLocation { 88 unsigned ID = 0; 89 friend class SourceManager; 90 friend class ASTReader; 91 friend class ASTWriter; 92 enum : unsigned { 93 MacroIDBit = 1U << 31 94 }; 95 96public: 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 /// \brief Turn a pointer encoding of a SourceLocation object back 167 /// into a real SourceLocation. 168 static SourceLocation getFromPtrEncoding(const void *Encoding) { 169 return getFromRawEncoding((unsigned)(uintptr_t)Encoding); 170 } 171 172 static bool isPairOfFileLocations(SourceLocation Start, SourceLocation End) { 173 return Start.isValid() && Start.isFileID() && End.isValid() && 174 End.isFileID(); 175 } 176 177 void print(raw_ostream &OS, const SourceManager &SM) const; 178 std::string printToString(const SourceManager &SM) const; 179 void dump(const SourceManager &SM) const; 180}; 181 182inline bool operator==(const SourceLocation &LHS, const SourceLocation &RHS) { 183 return LHS.getRawEncoding() == RHS.getRawEncoding(); 184} 185 186inline bool operator!=(const SourceLocation &LHS, const SourceLocation &RHS) { 187 return !(LHS == RHS); 188} 189 190inline bool operator<(const SourceLocation &LHS, const SourceLocation &RHS) { 191 return LHS.getRawEncoding() < RHS.getRawEncoding(); 192} 193 194/// \brief A trivial tuple used to represent a source range. 195class SourceRange { 196 SourceLocation B; 197 SourceLocation E; 198 199public: 200 SourceRange() = default; 201 SourceRange(SourceLocation loc) : B(loc), E(loc) {} 202 SourceRange(SourceLocation begin, SourceLocation end) : B(begin), E(end) {} 203 204 SourceLocation getBegin() const { return B; } 205 SourceLocation getEnd() const { return E; } 206 207 void setBegin(SourceLocation b) { B = b; } 208 void setEnd(SourceLocation e) { E = e; } 209 210 bool isValid() const { return B.isValid() && E.isValid(); } 211 bool isInvalid() const { return !isValid(); } 212 213 bool operator==(const SourceRange &X) const { 214 return B == X.B && E == X.E; 215 } 216 217 bool operator!=(const SourceRange &X) const { 218 return B != X.B || E != X.E; 219 } 220}; 221 222/// \brief Represents a character-granular source range. 223/// 224/// The underlying SourceRange can either specify the starting/ending character 225/// of the range, or it can specify the start of the range and the start of the 226/// last token of the range (a "token range"). In the token range case, the 227/// size of the last token must be measured to determine the actual end of the 228/// range. 229class CharSourceRange { 230 SourceRange Range; 231 bool IsTokenRange = false; 232 233public: 234 CharSourceRange() = default; 235 CharSourceRange(SourceRange R, bool ITR) : Range(R), IsTokenRange(ITR) {} 236 237 static CharSourceRange getTokenRange(SourceRange R) { 238 return CharSourceRange(R, true); 239 } 240 241 static CharSourceRange getCharRange(SourceRange R) { 242 return CharSourceRange(R, false); 243 } 244 245 static CharSourceRange getTokenRange(SourceLocation B, SourceLocation E) { 246 return getTokenRange(SourceRange(B, E)); 247 } 248 static CharSourceRange getCharRange(SourceLocation B, SourceLocation E) { 249 return getCharRange(SourceRange(B, E)); 250 } 251 252 /// \brief Return true if the end of this range specifies the start of 253 /// the last token. Return false if the end of this range specifies the last 254 /// character in the range. 255 bool isTokenRange() const { return IsTokenRange; } 256 bool isCharRange() const { return !IsTokenRange; } 257 258 SourceLocation getBegin() const { return Range.getBegin(); } 259 SourceLocation getEnd() const { return Range.getEnd(); } 260 SourceRange getAsRange() const { return Range; } 261 262 void setBegin(SourceLocation b) { Range.setBegin(b); } 263 void setEnd(SourceLocation e) { Range.setEnd(e); } 264 265 bool isValid() const { return Range.isValid(); } 266 bool isInvalid() const { return !isValid(); } 267}; 268 269/// \brief Represents an unpacked "presumed" location which can be presented 270/// to the user. 271/// 272/// A 'presumed' location can be modified by \#line and GNU line marker 273/// directives and is always the expansion point of a normal location. 274/// 275/// You can get a PresumedLoc from a SourceLocation with SourceManager. 276class PresumedLoc { 277 const char *Filename; 278 unsigned Line, Col; 279 SourceLocation IncludeLoc; 280 281public: 282 PresumedLoc() : Filename(nullptr) {} 283 PresumedLoc(const char *FN, unsigned Ln, unsigned Co, SourceLocation IL) 284 : Filename(FN), Line(Ln), Col(Co), IncludeLoc(IL) {} 285 286 /// \brief Return true if this object is invalid or uninitialized. 287 /// 288 /// This occurs when created with invalid source locations or when walking 289 /// off the top of a \#include stack. 290 bool isInvalid() const { return Filename == nullptr; } 291 bool isValid() const { return Filename != nullptr; } 292 293 /// \brief Return the presumed filename of this location. 294 /// 295 /// This can be affected by \#line etc. 296 const char *getFilename() const { 297 assert(isValid()); 298 return Filename; 299 } 300 301 /// \brief Return the presumed line number of this location. 302 /// 303 /// This can be affected by \#line etc. 304 unsigned getLine() const { 305 assert(isValid()); 306 return Line; 307 } 308 309 /// \brief Return the presumed column number of this location. 310 /// 311 /// This cannot be affected by \#line, but is packaged here for convenience. 312 unsigned getColumn() const { 313 assert(isValid()); 314 return Col; 315 } 316 317 /// \brief Return the presumed include location of this location. 318 /// 319 /// This can be affected by GNU linemarker directives. 320 SourceLocation getIncludeLoc() const { 321 assert(isValid()); 322 return IncludeLoc; 323 } 324}; 325 326class FileEntry; 327 328/// \brief A SourceLocation and its associated SourceManager. 329/// 330/// This is useful for argument passing to functions that expect both objects. 331class FullSourceLoc : public SourceLocation { 332 const SourceManager *SrcMgr = nullptr; 333 334public: 335 /// \brief Creates a FullSourceLoc where isValid() returns \c false. 336 FullSourceLoc() = default; 337 338 explicit FullSourceLoc(SourceLocation Loc, const SourceManager &SM) 339 : SourceLocation(Loc), SrcMgr(&SM) {} 340 341 bool hasManager() const { 342 bool hasSrcMgr = SrcMgr != nullptr; 343 assert(hasSrcMgr == isValid() && "FullSourceLoc has location but no manager"); 344 return hasSrcMgr; 345 } 346 347 /// \pre This FullSourceLoc has an associated SourceManager. 348 const SourceManager &getManager() const { 349 assert(SrcMgr && "SourceManager is NULL."); 350 return *SrcMgr; 351 } 352 353 FileID getFileID() const; 354 355 FullSourceLoc getExpansionLoc() const; 356 FullSourceLoc getSpellingLoc() const; 357 FullSourceLoc getFileLoc() const; 358 std::pair<FullSourceLoc, FullSourceLoc> getImmediateExpansionRange() const; 359 PresumedLoc getPresumedLoc(bool UseLineDirectives = true) const; 360 bool isMacroArgExpansion(FullSourceLoc *StartLoc = nullptr) const; 361 FullSourceLoc getImmediateMacroCallerLoc() const; 362 std::pair<FullSourceLoc, StringRef> getModuleImportLoc() const; 363 unsigned getFileOffset() const; 364 365 unsigned getExpansionLineNumber(bool *Invalid = nullptr) const; 366 unsigned getExpansionColumnNumber(bool *Invalid = nullptr) const; 367 368 unsigned getSpellingLineNumber(bool *Invalid = nullptr) const; 369 unsigned getSpellingColumnNumber(bool *Invalid = nullptr) const; 370 371 const char *getCharacterData(bool *Invalid = nullptr) const; 372 373 unsigned getLineNumber(bool *Invalid = nullptr) const; 374 unsigned getColumnNumber(bool *Invalid = nullptr) const; 375 376 std::pair<FullSourceLoc, FullSourceLoc> getExpansionRange() const; 377 378 const FileEntry *getFileEntry() const; 379 380 /// \brief Return a StringRef to the source buffer data for the 381 /// specified FileID. 382 StringRef getBufferData(bool *Invalid = nullptr) const; 383 384 /// \brief Decompose the specified location into a raw FileID + Offset pair. 385 /// 386 /// The first element is the FileID, the second is the offset from the 387 /// start of the buffer of the location. 388 std::pair<FileID, unsigned> getDecomposedLoc() const; 389 390 bool isInSystemHeader() const; 391 392 /// \brief Determines the order of 2 source locations in the translation unit. 393 /// 394 /// \returns true if this source location comes before 'Loc', false otherwise. 395 bool isBeforeInTranslationUnitThan(SourceLocation Loc) const; 396 397 /// \brief Determines the order of 2 source locations in the translation unit. 398 /// 399 /// \returns true if this source location comes before 'Loc', false otherwise. 400 bool isBeforeInTranslationUnitThan(FullSourceLoc Loc) const { 401 assert(Loc.isValid()); 402 assert(SrcMgr == Loc.SrcMgr && "Loc comes from another SourceManager!"); 403 return isBeforeInTranslationUnitThan((SourceLocation)Loc); 404 } 405 406 /// \brief Comparison function class, useful for sorting FullSourceLocs. 407 struct BeforeThanCompare { 408 bool operator()(const FullSourceLoc& lhs, const FullSourceLoc& rhs) const { 409 return lhs.isBeforeInTranslationUnitThan(rhs); 410 } 411 }; 412 413 /// \brief Prints information about this FullSourceLoc to stderr. 414 /// 415 /// This is useful for debugging. 416 void dump() const; 417 418 friend inline bool 419 operator==(const FullSourceLoc &LHS, const FullSourceLoc &RHS) { 420 return LHS.getRawEncoding() == RHS.getRawEncoding() && 421 LHS.SrcMgr == RHS.SrcMgr; 422 } 423 424 friend inline bool 425 operator!=(const FullSourceLoc &LHS, const FullSourceLoc &RHS) { 426 return !(LHS == RHS); 427 } 428 429}; 430 431 432 433} // end namespace clang 434 435namespace llvm { 436 /// Define DenseMapInfo so that FileID's can be used as keys in DenseMap and 437 /// DenseSets. 438 template <> 439 struct DenseMapInfo<clang::FileID> { 440 static inline clang::FileID getEmptyKey() { 441 return clang::FileID(); 442 } 443 static inline clang::FileID getTombstoneKey() { 444 return clang::FileID::getSentinel(); 445 } 446 447 static unsigned getHashValue(clang::FileID S) { 448 return S.getHashValue(); 449 } 450 451 static bool isEqual(clang::FileID LHS, clang::FileID RHS) { 452 return LHS == RHS; 453 } 454 }; 455 456 template <> 457 struct isPodLike<clang::SourceLocation> { static const bool value = true; }; 458 template <> 459 struct isPodLike<clang::FileID> { static const bool value = true; }; 460 461 // Teach SmallPtrSet how to handle SourceLocation. 462 template<> 463 struct PointerLikeTypeTraits<clang::SourceLocation> { 464 static inline void *getAsVoidPointer(clang::SourceLocation L) { 465 return L.getPtrEncoding(); 466 } 467 static inline clang::SourceLocation getFromVoidPointer(void *P) { 468 return clang::SourceLocation::getFromRawEncoding((unsigned)(uintptr_t)P); 469 } 470 enum { NumLowBitsAvailable = 0 }; 471 }; 472 473} // end namespace llvm 474 475#endif 476