10b57cec5SDimitry Andric //===- SourceLocation.h - Compact identifier for Source Files ---*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric /// \file 100b57cec5SDimitry Andric /// Defines the clang::SourceLocation class and associated facilities. 110b57cec5SDimitry Andric // 120b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 130b57cec5SDimitry Andric 140b57cec5SDimitry Andric #ifndef LLVM_CLANG_BASIC_SOURCELOCATION_H 150b57cec5SDimitry Andric #define LLVM_CLANG_BASIC_SOURCELOCATION_H 160b57cec5SDimitry Andric 175f757f3fSDimitry Andric #include "clang/Basic/FileEntry.h" 180b57cec5SDimitry Andric #include "clang/Basic/LLVM.h" 190b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 200b57cec5SDimitry Andric #include <cassert> 210b57cec5SDimitry Andric #include <cstdint> 220b57cec5SDimitry Andric #include <string> 230b57cec5SDimitry Andric #include <utility> 240b57cec5SDimitry Andric 250b57cec5SDimitry Andric namespace llvm { 260b57cec5SDimitry Andric 27e8d8bef9SDimitry Andric class FoldingSetNodeID; 2881ad6265SDimitry Andric template <typename T, typename Enable> struct FoldingSetTrait; 29e8d8bef9SDimitry Andric 300b57cec5SDimitry Andric } // namespace llvm 310b57cec5SDimitry Andric 320b57cec5SDimitry Andric namespace clang { 330b57cec5SDimitry Andric 340b57cec5SDimitry Andric class SourceManager; 350b57cec5SDimitry Andric 360b57cec5SDimitry Andric /// An opaque identifier used by SourceManager which refers to a 370b57cec5SDimitry Andric /// source file (MemoryBuffer) along with its \#include path and \#line data. 380b57cec5SDimitry Andric /// 390b57cec5SDimitry Andric class FileID { 400b57cec5SDimitry Andric /// A mostly-opaque identifier, where 0 is "invalid", >0 is 410b57cec5SDimitry Andric /// this module, and <-1 is something loaded from another module. 420b57cec5SDimitry Andric int ID = 0; 430b57cec5SDimitry Andric 440b57cec5SDimitry Andric public: 450b57cec5SDimitry Andric bool isValid() const { return ID != 0; } 460b57cec5SDimitry Andric bool isInvalid() const { return ID == 0; } 470b57cec5SDimitry Andric 480b57cec5SDimitry Andric bool operator==(const FileID &RHS) const { return ID == RHS.ID; } 490b57cec5SDimitry Andric bool operator<(const FileID &RHS) const { return ID < RHS.ID; } 500b57cec5SDimitry Andric bool operator<=(const FileID &RHS) const { return ID <= RHS.ID; } 510b57cec5SDimitry Andric bool operator!=(const FileID &RHS) const { return !(*this == RHS); } 520b57cec5SDimitry Andric bool operator>(const FileID &RHS) const { return RHS < *this; } 530b57cec5SDimitry Andric bool operator>=(const FileID &RHS) const { return RHS <= *this; } 540b57cec5SDimitry Andric 550b57cec5SDimitry Andric static FileID getSentinel() { return get(-1); } 560b57cec5SDimitry Andric unsigned getHashValue() const { return static_cast<unsigned>(ID); } 570b57cec5SDimitry Andric 580b57cec5SDimitry Andric private: 590b57cec5SDimitry Andric friend class ASTWriter; 600b57cec5SDimitry Andric friend class ASTReader; 610b57cec5SDimitry Andric friend class SourceManager; 625f757f3fSDimitry Andric friend class SourceManagerTestHelper; 630b57cec5SDimitry Andric 640b57cec5SDimitry Andric static FileID get(int V) { 650b57cec5SDimitry Andric FileID F; 660b57cec5SDimitry Andric F.ID = V; 670b57cec5SDimitry Andric return F; 680b57cec5SDimitry Andric } 690b57cec5SDimitry Andric 700b57cec5SDimitry Andric int getOpaqueValue() const { return ID; } 710b57cec5SDimitry Andric }; 720b57cec5SDimitry Andric 730b57cec5SDimitry Andric /// Encodes a location in the source. The SourceManager can decode this 740b57cec5SDimitry Andric /// to get at the full include stack, line and column information. 750b57cec5SDimitry Andric /// 760b57cec5SDimitry Andric /// Technically, a source location is simply an offset into the manager's view 770b57cec5SDimitry Andric /// of the input source, which is all input buffers (including macro 780b57cec5SDimitry Andric /// expansions) concatenated in an effectively arbitrary order. The manager 790b57cec5SDimitry Andric /// actually maintains two blocks of input buffers. One, starting at offset 800b57cec5SDimitry Andric /// 0 and growing upwards, contains all buffers from this module. The other, 810b57cec5SDimitry Andric /// starting at the highest possible offset and growing downwards, contains 820b57cec5SDimitry Andric /// buffers of loaded modules. 830b57cec5SDimitry Andric /// 840b57cec5SDimitry Andric /// In addition, one bit of SourceLocation is used for quick access to the 850b57cec5SDimitry Andric /// information whether the location is in a file or a macro expansion. 860b57cec5SDimitry Andric /// 870b57cec5SDimitry Andric /// It is important that this type remains small. It is currently 32 bits wide. 880b57cec5SDimitry Andric class SourceLocation { 890b57cec5SDimitry Andric friend class ASTReader; 900b57cec5SDimitry Andric friend class ASTWriter; 910b57cec5SDimitry Andric friend class SourceManager; 9281ad6265SDimitry Andric friend struct llvm::FoldingSetTrait<SourceLocation, void>; 93*0fca6ea1SDimitry Andric friend class SourceLocationEncoding; 940b57cec5SDimitry Andric 95fe6060f1SDimitry Andric public: 96fe6060f1SDimitry Andric using UIntTy = uint32_t; 97fe6060f1SDimitry Andric using IntTy = int32_t; 980b57cec5SDimitry Andric 99fe6060f1SDimitry Andric private: 100fe6060f1SDimitry Andric UIntTy ID = 0; 101fe6060f1SDimitry Andric 102fe6060f1SDimitry Andric enum : UIntTy { MacroIDBit = 1ULL << (8 * sizeof(UIntTy) - 1) }; 1030b57cec5SDimitry Andric 1040b57cec5SDimitry Andric public: 1050b57cec5SDimitry Andric bool isFileID() const { return (ID & MacroIDBit) == 0; } 1060b57cec5SDimitry Andric bool isMacroID() const { return (ID & MacroIDBit) != 0; } 1070b57cec5SDimitry Andric 1080b57cec5SDimitry Andric /// Return true if this is a valid SourceLocation object. 1090b57cec5SDimitry Andric /// 1100b57cec5SDimitry Andric /// Invalid SourceLocations are often used when events have no corresponding 1110b57cec5SDimitry Andric /// location in the source (e.g. a diagnostic is required for a command line 1120b57cec5SDimitry Andric /// option). 1130b57cec5SDimitry Andric bool isValid() const { return ID != 0; } 1140b57cec5SDimitry Andric bool isInvalid() const { return ID == 0; } 1150b57cec5SDimitry Andric 1160b57cec5SDimitry Andric private: 1170b57cec5SDimitry Andric /// Return the offset into the manager's global input view. 118fe6060f1SDimitry Andric UIntTy getOffset() const { return ID & ~MacroIDBit; } 1190b57cec5SDimitry Andric 120fe6060f1SDimitry Andric static SourceLocation getFileLoc(UIntTy ID) { 1210b57cec5SDimitry Andric assert((ID & MacroIDBit) == 0 && "Ran out of source locations!"); 1220b57cec5SDimitry Andric SourceLocation L; 1230b57cec5SDimitry Andric L.ID = ID; 1240b57cec5SDimitry Andric return L; 1250b57cec5SDimitry Andric } 1260b57cec5SDimitry Andric 127fe6060f1SDimitry Andric static SourceLocation getMacroLoc(UIntTy ID) { 1280b57cec5SDimitry Andric assert((ID & MacroIDBit) == 0 && "Ran out of source locations!"); 1290b57cec5SDimitry Andric SourceLocation L; 1300b57cec5SDimitry Andric L.ID = MacroIDBit | ID; 1310b57cec5SDimitry Andric return L; 1320b57cec5SDimitry Andric } 1330b57cec5SDimitry Andric 1340b57cec5SDimitry Andric public: 1350b57cec5SDimitry Andric /// Return a source location with the specified offset from this 1360b57cec5SDimitry Andric /// SourceLocation. 137fe6060f1SDimitry Andric SourceLocation getLocWithOffset(IntTy Offset) const { 1380b57cec5SDimitry Andric assert(((getOffset()+Offset) & MacroIDBit) == 0 && "offset overflow"); 1390b57cec5SDimitry Andric SourceLocation L; 1400b57cec5SDimitry Andric L.ID = ID+Offset; 1410b57cec5SDimitry Andric return L; 1420b57cec5SDimitry Andric } 1430b57cec5SDimitry Andric 1440b57cec5SDimitry Andric /// When a SourceLocation itself cannot be used, this returns 1450b57cec5SDimitry Andric /// an (opaque) 32-bit integer encoding for it. 1460b57cec5SDimitry Andric /// 1470b57cec5SDimitry Andric /// This should only be passed to SourceLocation::getFromRawEncoding, it 1480b57cec5SDimitry Andric /// should not be inspected directly. 149fe6060f1SDimitry Andric UIntTy getRawEncoding() const { return ID; } 1500b57cec5SDimitry Andric 1510b57cec5SDimitry Andric /// Turn a raw encoding of a SourceLocation object into 1520b57cec5SDimitry Andric /// a real SourceLocation. 1530b57cec5SDimitry Andric /// 1540b57cec5SDimitry Andric /// \see getRawEncoding. 155fe6060f1SDimitry Andric static SourceLocation getFromRawEncoding(UIntTy Encoding) { 1560b57cec5SDimitry Andric SourceLocation X; 1570b57cec5SDimitry Andric X.ID = Encoding; 1580b57cec5SDimitry Andric return X; 1590b57cec5SDimitry Andric } 1600b57cec5SDimitry Andric 1610b57cec5SDimitry Andric /// When a SourceLocation itself cannot be used, this returns 1620b57cec5SDimitry Andric /// an (opaque) pointer encoding for it. 1630b57cec5SDimitry Andric /// 1640b57cec5SDimitry Andric /// This should only be passed to SourceLocation::getFromPtrEncoding, it 1650b57cec5SDimitry Andric /// should not be inspected directly. 1660b57cec5SDimitry Andric void* getPtrEncoding() const { 1670b57cec5SDimitry Andric // Double cast to avoid a warning "cast to pointer from integer of different 1680b57cec5SDimitry Andric // size". 1690b57cec5SDimitry Andric return (void*)(uintptr_t)getRawEncoding(); 1700b57cec5SDimitry Andric } 1710b57cec5SDimitry Andric 1720b57cec5SDimitry Andric /// Turn a pointer encoding of a SourceLocation object back 1730b57cec5SDimitry Andric /// into a real SourceLocation. 1740b57cec5SDimitry Andric static SourceLocation getFromPtrEncoding(const void *Encoding) { 175fe6060f1SDimitry Andric return getFromRawEncoding((SourceLocation::UIntTy)(uintptr_t)Encoding); 1760b57cec5SDimitry Andric } 1770b57cec5SDimitry Andric 1780b57cec5SDimitry Andric static bool isPairOfFileLocations(SourceLocation Start, SourceLocation End) { 1790b57cec5SDimitry Andric return Start.isValid() && Start.isFileID() && End.isValid() && 1800b57cec5SDimitry Andric End.isFileID(); 1810b57cec5SDimitry Andric } 1820b57cec5SDimitry Andric 183e8d8bef9SDimitry Andric unsigned getHashValue() const; 1840b57cec5SDimitry Andric void print(raw_ostream &OS, const SourceManager &SM) const; 1850b57cec5SDimitry Andric std::string printToString(const SourceManager &SM) const; 1860b57cec5SDimitry Andric void dump(const SourceManager &SM) const; 1870b57cec5SDimitry Andric }; 1880b57cec5SDimitry Andric 1890b57cec5SDimitry Andric inline bool operator==(const SourceLocation &LHS, const SourceLocation &RHS) { 1900b57cec5SDimitry Andric return LHS.getRawEncoding() == RHS.getRawEncoding(); 1910b57cec5SDimitry Andric } 1920b57cec5SDimitry Andric 1930b57cec5SDimitry Andric inline bool operator!=(const SourceLocation &LHS, const SourceLocation &RHS) { 1940b57cec5SDimitry Andric return !(LHS == RHS); 1950b57cec5SDimitry Andric } 1960b57cec5SDimitry Andric 197480093f4SDimitry Andric // Ordering is meaningful only if LHS and RHS have the same FileID! 198480093f4SDimitry Andric // Otherwise use SourceManager::isBeforeInTranslationUnit(). 1990b57cec5SDimitry Andric inline bool operator<(const SourceLocation &LHS, const SourceLocation &RHS) { 2000b57cec5SDimitry Andric return LHS.getRawEncoding() < RHS.getRawEncoding(); 2010b57cec5SDimitry Andric } 202480093f4SDimitry Andric inline bool operator>(const SourceLocation &LHS, const SourceLocation &RHS) { 203480093f4SDimitry Andric return LHS.getRawEncoding() > RHS.getRawEncoding(); 204480093f4SDimitry Andric } 205480093f4SDimitry Andric inline bool operator<=(const SourceLocation &LHS, const SourceLocation &RHS) { 206480093f4SDimitry Andric return LHS.getRawEncoding() <= RHS.getRawEncoding(); 207480093f4SDimitry Andric } 208480093f4SDimitry Andric inline bool operator>=(const SourceLocation &LHS, const SourceLocation &RHS) { 209480093f4SDimitry Andric return LHS.getRawEncoding() >= RHS.getRawEncoding(); 210480093f4SDimitry Andric } 2110b57cec5SDimitry Andric 2120b57cec5SDimitry Andric /// A trivial tuple used to represent a source range. 2130b57cec5SDimitry Andric class SourceRange { 2140b57cec5SDimitry Andric SourceLocation B; 2150b57cec5SDimitry Andric SourceLocation E; 2160b57cec5SDimitry Andric 2170b57cec5SDimitry Andric public: 2180b57cec5SDimitry Andric SourceRange() = default; 2190b57cec5SDimitry Andric SourceRange(SourceLocation loc) : B(loc), E(loc) {} 2200b57cec5SDimitry Andric SourceRange(SourceLocation begin, SourceLocation end) : B(begin), E(end) {} 2210b57cec5SDimitry Andric 2220b57cec5SDimitry Andric SourceLocation getBegin() const { return B; } 2230b57cec5SDimitry Andric SourceLocation getEnd() const { return E; } 2240b57cec5SDimitry Andric 2250b57cec5SDimitry Andric void setBegin(SourceLocation b) { B = b; } 2260b57cec5SDimitry Andric void setEnd(SourceLocation e) { E = e; } 2270b57cec5SDimitry Andric 2280b57cec5SDimitry Andric bool isValid() const { return B.isValid() && E.isValid(); } 2290b57cec5SDimitry Andric bool isInvalid() const { return !isValid(); } 2300b57cec5SDimitry Andric 2310b57cec5SDimitry Andric bool operator==(const SourceRange &X) const { 2320b57cec5SDimitry Andric return B == X.B && E == X.E; 2330b57cec5SDimitry Andric } 2340b57cec5SDimitry Andric 2350b57cec5SDimitry Andric bool operator!=(const SourceRange &X) const { 2360b57cec5SDimitry Andric return B != X.B || E != X.E; 2370b57cec5SDimitry Andric } 2380b57cec5SDimitry Andric 239480093f4SDimitry Andric // Returns true iff other is wholly contained within this range. 240480093f4SDimitry Andric bool fullyContains(const SourceRange &other) const { 241480093f4SDimitry Andric return B <= other.B && E >= other.E; 242480093f4SDimitry Andric } 243480093f4SDimitry Andric 2440b57cec5SDimitry Andric void print(raw_ostream &OS, const SourceManager &SM) const; 2450b57cec5SDimitry Andric std::string printToString(const SourceManager &SM) const; 2460b57cec5SDimitry Andric void dump(const SourceManager &SM) const; 2470b57cec5SDimitry Andric }; 2480b57cec5SDimitry Andric 2490b57cec5SDimitry Andric /// Represents a character-granular source range. 2500b57cec5SDimitry Andric /// 2510b57cec5SDimitry Andric /// The underlying SourceRange can either specify the starting/ending character 2520b57cec5SDimitry Andric /// of the range, or it can specify the start of the range and the start of the 2530b57cec5SDimitry Andric /// last token of the range (a "token range"). In the token range case, the 2540b57cec5SDimitry Andric /// size of the last token must be measured to determine the actual end of the 2550b57cec5SDimitry Andric /// range. 2560b57cec5SDimitry Andric class CharSourceRange { 2570b57cec5SDimitry Andric SourceRange Range; 2580b57cec5SDimitry Andric bool IsTokenRange = false; 2590b57cec5SDimitry Andric 2600b57cec5SDimitry Andric public: 2610b57cec5SDimitry Andric CharSourceRange() = default; 2620b57cec5SDimitry Andric CharSourceRange(SourceRange R, bool ITR) : Range(R), IsTokenRange(ITR) {} 2630b57cec5SDimitry Andric 2640b57cec5SDimitry Andric static CharSourceRange getTokenRange(SourceRange R) { 2650b57cec5SDimitry Andric return CharSourceRange(R, true); 2660b57cec5SDimitry Andric } 2670b57cec5SDimitry Andric 2680b57cec5SDimitry Andric static CharSourceRange getCharRange(SourceRange R) { 2690b57cec5SDimitry Andric return CharSourceRange(R, false); 2700b57cec5SDimitry Andric } 2710b57cec5SDimitry Andric 2720b57cec5SDimitry Andric static CharSourceRange getTokenRange(SourceLocation B, SourceLocation E) { 2730b57cec5SDimitry Andric return getTokenRange(SourceRange(B, E)); 2740b57cec5SDimitry Andric } 2750b57cec5SDimitry Andric 2760b57cec5SDimitry Andric static CharSourceRange getCharRange(SourceLocation B, SourceLocation E) { 2770b57cec5SDimitry Andric return getCharRange(SourceRange(B, E)); 2780b57cec5SDimitry Andric } 2790b57cec5SDimitry Andric 2800b57cec5SDimitry Andric /// Return true if the end of this range specifies the start of 2810b57cec5SDimitry Andric /// the last token. Return false if the end of this range specifies the last 2820b57cec5SDimitry Andric /// character in the range. 2830b57cec5SDimitry Andric bool isTokenRange() const { return IsTokenRange; } 2840b57cec5SDimitry Andric bool isCharRange() const { return !IsTokenRange; } 2850b57cec5SDimitry Andric 2860b57cec5SDimitry Andric SourceLocation getBegin() const { return Range.getBegin(); } 2870b57cec5SDimitry Andric SourceLocation getEnd() const { return Range.getEnd(); } 2880b57cec5SDimitry Andric SourceRange getAsRange() const { return Range; } 2890b57cec5SDimitry Andric 2900b57cec5SDimitry Andric void setBegin(SourceLocation b) { Range.setBegin(b); } 2910b57cec5SDimitry Andric void setEnd(SourceLocation e) { Range.setEnd(e); } 2920b57cec5SDimitry Andric void setTokenRange(bool TR) { IsTokenRange = TR; } 2930b57cec5SDimitry Andric 2940b57cec5SDimitry Andric bool isValid() const { return Range.isValid(); } 2950b57cec5SDimitry Andric bool isInvalid() const { return !isValid(); } 2960b57cec5SDimitry Andric }; 2970b57cec5SDimitry Andric 2980b57cec5SDimitry Andric /// Represents an unpacked "presumed" location which can be presented 2990b57cec5SDimitry Andric /// to the user. 3000b57cec5SDimitry Andric /// 3010b57cec5SDimitry Andric /// A 'presumed' location can be modified by \#line and GNU line marker 3020b57cec5SDimitry Andric /// directives and is always the expansion point of a normal location. 3030b57cec5SDimitry Andric /// 3040b57cec5SDimitry Andric /// You can get a PresumedLoc from a SourceLocation with SourceManager. 3050b57cec5SDimitry Andric class PresumedLoc { 3060b57cec5SDimitry Andric const char *Filename = nullptr; 3070b57cec5SDimitry Andric FileID ID; 3080b57cec5SDimitry Andric unsigned Line, Col; 3090b57cec5SDimitry Andric SourceLocation IncludeLoc; 3100b57cec5SDimitry Andric 3110b57cec5SDimitry Andric public: 3120b57cec5SDimitry Andric PresumedLoc() = default; 3130b57cec5SDimitry Andric PresumedLoc(const char *FN, FileID FID, unsigned Ln, unsigned Co, 3140b57cec5SDimitry Andric SourceLocation IL) 3150b57cec5SDimitry Andric : Filename(FN), ID(FID), Line(Ln), Col(Co), IncludeLoc(IL) {} 3160b57cec5SDimitry Andric 3170b57cec5SDimitry Andric /// Return true if this object is invalid or uninitialized. 3180b57cec5SDimitry Andric /// 3190b57cec5SDimitry Andric /// This occurs when created with invalid source locations or when walking 3200b57cec5SDimitry Andric /// off the top of a \#include stack. 3210b57cec5SDimitry Andric bool isInvalid() const { return Filename == nullptr; } 3220b57cec5SDimitry Andric bool isValid() const { return Filename != nullptr; } 3230b57cec5SDimitry Andric 3240b57cec5SDimitry Andric /// Return the presumed filename of this location. 3250b57cec5SDimitry Andric /// 3260b57cec5SDimitry Andric /// This can be affected by \#line etc. 3270b57cec5SDimitry Andric const char *getFilename() const { 3280b57cec5SDimitry Andric assert(isValid()); 3290b57cec5SDimitry Andric return Filename; 3300b57cec5SDimitry Andric } 3310b57cec5SDimitry Andric 3320b57cec5SDimitry Andric FileID getFileID() const { 3330b57cec5SDimitry Andric assert(isValid()); 3340b57cec5SDimitry Andric return ID; 3350b57cec5SDimitry Andric } 3360b57cec5SDimitry Andric 3370b57cec5SDimitry Andric /// Return the presumed line number of this location. 3380b57cec5SDimitry Andric /// 3390b57cec5SDimitry Andric /// This can be affected by \#line etc. 3400b57cec5SDimitry Andric unsigned getLine() const { 3410b57cec5SDimitry Andric assert(isValid()); 3420b57cec5SDimitry Andric return Line; 3430b57cec5SDimitry Andric } 3440b57cec5SDimitry Andric 3450b57cec5SDimitry Andric /// Return the presumed column number of this location. 3460b57cec5SDimitry Andric /// 3470b57cec5SDimitry Andric /// This cannot be affected by \#line, but is packaged here for convenience. 3480b57cec5SDimitry Andric unsigned getColumn() const { 3490b57cec5SDimitry Andric assert(isValid()); 3500b57cec5SDimitry Andric return Col; 3510b57cec5SDimitry Andric } 3520b57cec5SDimitry Andric 3530b57cec5SDimitry Andric /// Return the presumed include location of this location. 3540b57cec5SDimitry Andric /// 3550b57cec5SDimitry Andric /// This can be affected by GNU linemarker directives. 3560b57cec5SDimitry Andric SourceLocation getIncludeLoc() const { 3570b57cec5SDimitry Andric assert(isValid()); 3580b57cec5SDimitry Andric return IncludeLoc; 3590b57cec5SDimitry Andric } 3600b57cec5SDimitry Andric }; 3610b57cec5SDimitry Andric 3620b57cec5SDimitry Andric /// A SourceLocation and its associated SourceManager. 3630b57cec5SDimitry Andric /// 3640b57cec5SDimitry Andric /// This is useful for argument passing to functions that expect both objects. 365349cc55cSDimitry Andric /// 366349cc55cSDimitry Andric /// This class does not guarantee the presence of either the SourceManager or 367349cc55cSDimitry Andric /// a valid SourceLocation. Clients should use `isValid()` and `hasManager()` 368349cc55cSDimitry Andric /// before calling the member functions. 3690b57cec5SDimitry Andric class FullSourceLoc : public SourceLocation { 3700b57cec5SDimitry Andric const SourceManager *SrcMgr = nullptr; 3710b57cec5SDimitry Andric 3720b57cec5SDimitry Andric public: 3730b57cec5SDimitry Andric /// Creates a FullSourceLoc where isValid() returns \c false. 3740b57cec5SDimitry Andric FullSourceLoc() = default; 3750b57cec5SDimitry Andric 3760b57cec5SDimitry Andric explicit FullSourceLoc(SourceLocation Loc, const SourceManager &SM) 3770b57cec5SDimitry Andric : SourceLocation(Loc), SrcMgr(&SM) {} 3780b57cec5SDimitry Andric 379349cc55cSDimitry Andric /// Checks whether the SourceManager is present. 380349cc55cSDimitry Andric bool hasManager() const { return SrcMgr != nullptr; } 3810b57cec5SDimitry Andric 382349cc55cSDimitry Andric /// \pre hasManager() 3830b57cec5SDimitry Andric const SourceManager &getManager() const { 3840b57cec5SDimitry Andric assert(SrcMgr && "SourceManager is NULL."); 3850b57cec5SDimitry Andric return *SrcMgr; 3860b57cec5SDimitry Andric } 3870b57cec5SDimitry Andric 3880b57cec5SDimitry Andric FileID getFileID() const; 3890b57cec5SDimitry Andric 3900b57cec5SDimitry Andric FullSourceLoc getExpansionLoc() const; 3910b57cec5SDimitry Andric FullSourceLoc getSpellingLoc() const; 3920b57cec5SDimitry Andric FullSourceLoc getFileLoc() const; 3930b57cec5SDimitry Andric PresumedLoc getPresumedLoc(bool UseLineDirectives = true) const; 3940b57cec5SDimitry Andric bool isMacroArgExpansion(FullSourceLoc *StartLoc = nullptr) const; 3950b57cec5SDimitry Andric FullSourceLoc getImmediateMacroCallerLoc() const; 3960b57cec5SDimitry Andric std::pair<FullSourceLoc, StringRef> getModuleImportLoc() const; 3970b57cec5SDimitry Andric unsigned getFileOffset() const; 3980b57cec5SDimitry Andric 3990b57cec5SDimitry Andric unsigned getExpansionLineNumber(bool *Invalid = nullptr) const; 4000b57cec5SDimitry Andric unsigned getExpansionColumnNumber(bool *Invalid = nullptr) const; 4010b57cec5SDimitry Andric 402bdd1243dSDimitry Andric /// Decompose the underlying \c SourceLocation into a raw (FileID + Offset) 403bdd1243dSDimitry Andric /// pair, after walking through all expansion records. 404bdd1243dSDimitry Andric /// 405bdd1243dSDimitry Andric /// \see SourceManager::getDecomposedExpansionLoc 406bdd1243dSDimitry Andric std::pair<FileID, unsigned> getDecomposedExpansionLoc() const; 407bdd1243dSDimitry Andric 4080b57cec5SDimitry Andric unsigned getSpellingLineNumber(bool *Invalid = nullptr) const; 4090b57cec5SDimitry Andric unsigned getSpellingColumnNumber(bool *Invalid = nullptr) const; 4100b57cec5SDimitry Andric 4110b57cec5SDimitry Andric const char *getCharacterData(bool *Invalid = nullptr) const; 4120b57cec5SDimitry Andric 4130b57cec5SDimitry Andric unsigned getLineNumber(bool *Invalid = nullptr) const; 4140b57cec5SDimitry Andric unsigned getColumnNumber(bool *Invalid = nullptr) const; 4150b57cec5SDimitry Andric 4160b57cec5SDimitry Andric const FileEntry *getFileEntry() const; 4175f757f3fSDimitry Andric OptionalFileEntryRef getFileEntryRef() const; 4180b57cec5SDimitry Andric 4190b57cec5SDimitry Andric /// Return a StringRef to the source buffer data for the 4200b57cec5SDimitry Andric /// specified FileID. 4210b57cec5SDimitry Andric StringRef getBufferData(bool *Invalid = nullptr) const; 4220b57cec5SDimitry Andric 4230b57cec5SDimitry Andric /// Decompose the specified location into a raw FileID + Offset pair. 4240b57cec5SDimitry Andric /// 4250b57cec5SDimitry Andric /// The first element is the FileID, the second is the offset from the 4260b57cec5SDimitry Andric /// start of the buffer of the location. 4270b57cec5SDimitry Andric std::pair<FileID, unsigned> getDecomposedLoc() const; 4280b57cec5SDimitry Andric 4290b57cec5SDimitry Andric bool isInSystemHeader() const; 4300b57cec5SDimitry Andric 4310b57cec5SDimitry Andric /// Determines the order of 2 source locations in the translation unit. 4320b57cec5SDimitry Andric /// 4330b57cec5SDimitry Andric /// \returns true if this source location comes before 'Loc', false otherwise. 4340b57cec5SDimitry Andric bool isBeforeInTranslationUnitThan(SourceLocation Loc) const; 4350b57cec5SDimitry Andric 4360b57cec5SDimitry Andric /// Determines the order of 2 source locations in the translation unit. 4370b57cec5SDimitry Andric /// 4380b57cec5SDimitry Andric /// \returns true if this source location comes before 'Loc', false otherwise. 4390b57cec5SDimitry Andric bool isBeforeInTranslationUnitThan(FullSourceLoc Loc) const { 4400b57cec5SDimitry Andric assert(Loc.isValid()); 4410b57cec5SDimitry Andric assert(SrcMgr == Loc.SrcMgr && "Loc comes from another SourceManager!"); 4420b57cec5SDimitry Andric return isBeforeInTranslationUnitThan((SourceLocation)Loc); 4430b57cec5SDimitry Andric } 4440b57cec5SDimitry Andric 4450b57cec5SDimitry Andric /// Comparison function class, useful for sorting FullSourceLocs. 4460b57cec5SDimitry Andric struct BeforeThanCompare { 4470b57cec5SDimitry Andric bool operator()(const FullSourceLoc& lhs, const FullSourceLoc& rhs) const { 4480b57cec5SDimitry Andric return lhs.isBeforeInTranslationUnitThan(rhs); 4490b57cec5SDimitry Andric } 4500b57cec5SDimitry Andric }; 4510b57cec5SDimitry Andric 4520b57cec5SDimitry Andric /// Prints information about this FullSourceLoc to stderr. 4530b57cec5SDimitry Andric /// 4540b57cec5SDimitry Andric /// This is useful for debugging. 4550b57cec5SDimitry Andric void dump() const; 4560b57cec5SDimitry Andric 4570b57cec5SDimitry Andric friend bool 4580b57cec5SDimitry Andric operator==(const FullSourceLoc &LHS, const FullSourceLoc &RHS) { 4590b57cec5SDimitry Andric return LHS.getRawEncoding() == RHS.getRawEncoding() && 4600b57cec5SDimitry Andric LHS.SrcMgr == RHS.SrcMgr; 4610b57cec5SDimitry Andric } 4620b57cec5SDimitry Andric 4630b57cec5SDimitry Andric friend bool 4640b57cec5SDimitry Andric operator!=(const FullSourceLoc &LHS, const FullSourceLoc &RHS) { 4650b57cec5SDimitry Andric return !(LHS == RHS); 4660b57cec5SDimitry Andric } 4670b57cec5SDimitry Andric }; 4680b57cec5SDimitry Andric 4690b57cec5SDimitry Andric } // namespace clang 4700b57cec5SDimitry Andric 4710b57cec5SDimitry Andric namespace llvm { 4720b57cec5SDimitry Andric 4730b57cec5SDimitry Andric /// Define DenseMapInfo so that FileID's can be used as keys in DenseMap and 4740b57cec5SDimitry Andric /// DenseSets. 4750b57cec5SDimitry Andric template <> 476349cc55cSDimitry Andric struct DenseMapInfo<clang::FileID, void> { 4770b57cec5SDimitry Andric static clang::FileID getEmptyKey() { 4780b57cec5SDimitry Andric return {}; 4790b57cec5SDimitry Andric } 4800b57cec5SDimitry Andric 4810b57cec5SDimitry Andric static clang::FileID getTombstoneKey() { 4820b57cec5SDimitry Andric return clang::FileID::getSentinel(); 4830b57cec5SDimitry Andric } 4840b57cec5SDimitry Andric 4850b57cec5SDimitry Andric static unsigned getHashValue(clang::FileID S) { 4860b57cec5SDimitry Andric return S.getHashValue(); 4870b57cec5SDimitry Andric } 4880b57cec5SDimitry Andric 4890b57cec5SDimitry Andric static bool isEqual(clang::FileID LHS, clang::FileID RHS) { 4900b57cec5SDimitry Andric return LHS == RHS; 4910b57cec5SDimitry Andric } 4920b57cec5SDimitry Andric }; 4930b57cec5SDimitry Andric 494e8d8bef9SDimitry Andric /// Define DenseMapInfo so that SourceLocation's can be used as keys in 495e8d8bef9SDimitry Andric /// DenseMap and DenseSet. This trait class is eqivalent to 496e8d8bef9SDimitry Andric /// DenseMapInfo<unsigned> which uses SourceLocation::ID is used as a key. 497349cc55cSDimitry Andric template <> struct DenseMapInfo<clang::SourceLocation, void> { 498e8d8bef9SDimitry Andric static clang::SourceLocation getEmptyKey() { 499fe6060f1SDimitry Andric constexpr clang::SourceLocation::UIntTy Zero = 0; 500fe6060f1SDimitry Andric return clang::SourceLocation::getFromRawEncoding(~Zero); 501e8d8bef9SDimitry Andric } 502e8d8bef9SDimitry Andric 503e8d8bef9SDimitry Andric static clang::SourceLocation getTombstoneKey() { 504fe6060f1SDimitry Andric constexpr clang::SourceLocation::UIntTy Zero = 0; 505fe6060f1SDimitry Andric return clang::SourceLocation::getFromRawEncoding(~Zero - 1); 506e8d8bef9SDimitry Andric } 507e8d8bef9SDimitry Andric 508e8d8bef9SDimitry Andric static unsigned getHashValue(clang::SourceLocation Loc) { 509e8d8bef9SDimitry Andric return Loc.getHashValue(); 510e8d8bef9SDimitry Andric } 511e8d8bef9SDimitry Andric 512e8d8bef9SDimitry Andric static bool isEqual(clang::SourceLocation LHS, clang::SourceLocation RHS) { 513e8d8bef9SDimitry Andric return LHS == RHS; 514e8d8bef9SDimitry Andric } 515e8d8bef9SDimitry Andric }; 516e8d8bef9SDimitry Andric 517e8d8bef9SDimitry Andric // Allow calling FoldingSetNodeID::Add with SourceLocation object as parameter 51881ad6265SDimitry Andric template <> struct FoldingSetTrait<clang::SourceLocation, void> { 519e8d8bef9SDimitry Andric static void Profile(const clang::SourceLocation &X, FoldingSetNodeID &ID); 520e8d8bef9SDimitry Andric }; 521e8d8bef9SDimitry Andric 5220b57cec5SDimitry Andric } // namespace llvm 5230b57cec5SDimitry Andric 5240b57cec5SDimitry Andric #endif // LLVM_CLANG_BASIC_SOURCELOCATION_H 525