xref: /freebsd-src/contrib/llvm-project/clang/include/clang/Basic/SourceLocation.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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