Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:36:50

0001 //===- SourceLocation.h - Compact identifier for Source Files ---*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 /// \file
0010 /// Defines the clang::SourceLocation class and associated facilities.
0011 //
0012 //===----------------------------------------------------------------------===//
0013 
0014 #ifndef LLVM_CLANG_BASIC_SOURCELOCATION_H
0015 #define LLVM_CLANG_BASIC_SOURCELOCATION_H
0016 
0017 #include "clang/Basic/FileEntry.h"
0018 #include "clang/Basic/LLVM.h"
0019 #include "llvm/ADT/StringRef.h"
0020 #include <cassert>
0021 #include <cstdint>
0022 #include <string>
0023 #include <utility>
0024 
0025 namespace llvm {
0026 
0027 class FoldingSetNodeID;
0028 template <typename T, typename Enable> struct FoldingSetTrait;
0029 
0030 } // namespace llvm
0031 
0032 namespace clang {
0033 
0034 class SourceManager;
0035 
0036 /// An opaque identifier used by SourceManager which refers to a
0037 /// source file (MemoryBuffer) along with its \#include path and \#line data.
0038 ///
0039 class FileID {
0040   /// A mostly-opaque identifier, where 0 is "invalid", >0 is
0041   /// this module, and <-1 is something loaded from another module.
0042   int ID = 0;
0043 
0044 public:
0045   bool isValid() const { return ID != 0; }
0046   bool isInvalid() const { return ID == 0; }
0047 
0048   bool operator==(const FileID &RHS) const { return ID == RHS.ID; }
0049   bool operator<(const FileID &RHS) const { return ID < RHS.ID; }
0050   bool operator<=(const FileID &RHS) const { return ID <= RHS.ID; }
0051   bool operator!=(const FileID &RHS) const { return !(*this == RHS); }
0052   bool operator>(const FileID &RHS) const { return RHS < *this; }
0053   bool operator>=(const FileID &RHS) const { return RHS <= *this; }
0054 
0055   static FileID getSentinel() { return get(-1); }
0056   unsigned getHashValue() const { return static_cast<unsigned>(ID); }
0057 
0058 private:
0059   friend class ASTWriter;
0060   friend class ASTReader;
0061   friend class SourceManager;
0062   friend class SourceManagerTestHelper;
0063 
0064   static FileID get(int V) {
0065     FileID F;
0066     F.ID = V;
0067     return F;
0068   }
0069 
0070   int getOpaqueValue() const { return ID; }
0071 };
0072 
0073 /// Encodes a location in the source. The SourceManager can decode this
0074 /// to get at the full include stack, line and column information.
0075 ///
0076 /// Technically, a source location is simply an offset into the manager's view
0077 /// of the input source, which is all input buffers (including macro
0078 /// expansions) concatenated in an effectively arbitrary order. The manager
0079 /// actually maintains two blocks of input buffers. One, starting at offset
0080 /// 0 and growing upwards, contains all buffers from this module. The other,
0081 /// starting at the highest possible offset and growing downwards, contains
0082 /// buffers of loaded modules.
0083 ///
0084 /// In addition, one bit of SourceLocation is used for quick access to the
0085 /// information whether the location is in a file or a macro expansion.
0086 ///
0087 /// It is important that this type remains small. It is currently 32 bits wide.
0088 class SourceLocation {
0089   friend class ASTReader;
0090   friend class ASTWriter;
0091   friend class SourceManager;
0092   friend struct llvm::FoldingSetTrait<SourceLocation, void>;
0093   friend class SourceLocationEncoding;
0094 
0095 public:
0096   using UIntTy = uint32_t;
0097   using IntTy = int32_t;
0098 
0099 private:
0100   UIntTy ID = 0;
0101 
0102   enum : UIntTy { MacroIDBit = 1ULL << (8 * sizeof(UIntTy) - 1) };
0103 
0104 public:
0105   bool isFileID() const  { return (ID & MacroIDBit) == 0; }
0106   bool isMacroID() const { return (ID & MacroIDBit) != 0; }
0107 
0108   /// Return true if this is a valid SourceLocation object.
0109   ///
0110   /// Invalid SourceLocations are often used when events have no corresponding
0111   /// location in the source (e.g. a diagnostic is required for a command line
0112   /// option).
0113   bool isValid() const { return ID != 0; }
0114   bool isInvalid() const { return ID == 0; }
0115 
0116 private:
0117   /// Return the offset into the manager's global input view.
0118   UIntTy getOffset() const { return ID & ~MacroIDBit; }
0119 
0120   static SourceLocation getFileLoc(UIntTy ID) {
0121     assert((ID & MacroIDBit) == 0 && "Ran out of source locations!");
0122     SourceLocation L;
0123     L.ID = ID;
0124     return L;
0125   }
0126 
0127   static SourceLocation getMacroLoc(UIntTy ID) {
0128     assert((ID & MacroIDBit) == 0 && "Ran out of source locations!");
0129     SourceLocation L;
0130     L.ID = MacroIDBit | ID;
0131     return L;
0132   }
0133 
0134 public:
0135   /// Return a source location with the specified offset from this
0136   /// SourceLocation.
0137   SourceLocation getLocWithOffset(IntTy Offset) const {
0138     assert(((getOffset()+Offset) & MacroIDBit) == 0 && "offset overflow");
0139     SourceLocation L;
0140     L.ID = ID+Offset;
0141     return L;
0142   }
0143 
0144   /// When a SourceLocation itself cannot be used, this returns
0145   /// an (opaque) 32-bit integer encoding for it.
0146   ///
0147   /// This should only be passed to SourceLocation::getFromRawEncoding, it
0148   /// should not be inspected directly.
0149   UIntTy getRawEncoding() const { return ID; }
0150 
0151   /// Turn a raw encoding of a SourceLocation object into
0152   /// a real SourceLocation.
0153   ///
0154   /// \see getRawEncoding.
0155   static SourceLocation getFromRawEncoding(UIntTy Encoding) {
0156     SourceLocation X;
0157     X.ID = Encoding;
0158     return X;
0159   }
0160 
0161   /// When a SourceLocation itself cannot be used, this returns
0162   /// an (opaque) pointer encoding for it.
0163   ///
0164   /// This should only be passed to SourceLocation::getFromPtrEncoding, it
0165   /// should not be inspected directly.
0166   void* getPtrEncoding() const {
0167     // Double cast to avoid a warning "cast to pointer from integer of different
0168     // size".
0169     return (void*)(uintptr_t)getRawEncoding();
0170   }
0171 
0172   /// Turn a pointer encoding of a SourceLocation object back
0173   /// into a real SourceLocation.
0174   static SourceLocation getFromPtrEncoding(const void *Encoding) {
0175     return getFromRawEncoding((SourceLocation::UIntTy)(uintptr_t)Encoding);
0176   }
0177 
0178   static bool isPairOfFileLocations(SourceLocation Start, SourceLocation End) {
0179     return Start.isValid() && Start.isFileID() && End.isValid() &&
0180            End.isFileID();
0181   }
0182 
0183   unsigned getHashValue() const;
0184   void print(raw_ostream &OS, const SourceManager &SM) const;
0185   std::string printToString(const SourceManager &SM) const;
0186   void dump(const SourceManager &SM) const;
0187 };
0188 
0189 inline bool operator==(const SourceLocation &LHS, const SourceLocation &RHS) {
0190   return LHS.getRawEncoding() == RHS.getRawEncoding();
0191 }
0192 
0193 inline bool operator!=(const SourceLocation &LHS, const SourceLocation &RHS) {
0194   return !(LHS == RHS);
0195 }
0196 
0197 // Ordering is meaningful only if LHS and RHS have the same FileID!
0198 // Otherwise use SourceManager::isBeforeInTranslationUnit().
0199 inline bool operator<(const SourceLocation &LHS, const SourceLocation &RHS) {
0200   return LHS.getRawEncoding() < RHS.getRawEncoding();
0201 }
0202 inline bool operator>(const SourceLocation &LHS, const SourceLocation &RHS) {
0203   return LHS.getRawEncoding() > RHS.getRawEncoding();
0204 }
0205 inline bool operator<=(const SourceLocation &LHS, const SourceLocation &RHS) {
0206   return LHS.getRawEncoding() <= RHS.getRawEncoding();
0207 }
0208 inline bool operator>=(const SourceLocation &LHS, const SourceLocation &RHS) {
0209   return LHS.getRawEncoding() >= RHS.getRawEncoding();
0210 }
0211 
0212 /// A trivial tuple used to represent a source range.
0213 class SourceRange {
0214   SourceLocation B;
0215   SourceLocation E;
0216 
0217 public:
0218   SourceRange() = default;
0219   SourceRange(SourceLocation loc) : B(loc), E(loc) {}
0220   SourceRange(SourceLocation begin, SourceLocation end) : B(begin), E(end) {}
0221 
0222   SourceLocation getBegin() const { return B; }
0223   SourceLocation getEnd() const { return E; }
0224 
0225   void setBegin(SourceLocation b) { B = b; }
0226   void setEnd(SourceLocation e) { E = e; }
0227 
0228   bool isValid() const { return B.isValid() && E.isValid(); }
0229   bool isInvalid() const { return !isValid(); }
0230 
0231   bool operator==(const SourceRange &X) const {
0232     return B == X.B && E == X.E;
0233   }
0234 
0235   bool operator!=(const SourceRange &X) const {
0236     return B != X.B || E != X.E;
0237   }
0238 
0239   // Returns true iff other is wholly contained within this range.
0240   bool fullyContains(const SourceRange &other) const {
0241     return B <= other.B && E >= other.E;
0242   }
0243 
0244   void print(raw_ostream &OS, const SourceManager &SM) const;
0245   std::string printToString(const SourceManager &SM) const;
0246   void dump(const SourceManager &SM) const;
0247 };
0248 
0249 /// Represents a character-granular source range.
0250 ///
0251 /// The underlying SourceRange can either specify the starting/ending character
0252 /// of the range, or it can specify the start of the range and the start of the
0253 /// last token of the range (a "token range").  In the token range case, the
0254 /// size of the last token must be measured to determine the actual end of the
0255 /// range.
0256 class CharSourceRange {
0257   SourceRange Range;
0258   bool IsTokenRange = false;
0259 
0260 public:
0261   CharSourceRange() = default;
0262   CharSourceRange(SourceRange R, bool ITR) : Range(R), IsTokenRange(ITR) {}
0263 
0264   static CharSourceRange getTokenRange(SourceRange R) {
0265     return CharSourceRange(R, true);
0266   }
0267 
0268   static CharSourceRange getCharRange(SourceRange R) {
0269     return CharSourceRange(R, false);
0270   }
0271 
0272   static CharSourceRange getTokenRange(SourceLocation B, SourceLocation E) {
0273     return getTokenRange(SourceRange(B, E));
0274   }
0275 
0276   static CharSourceRange getCharRange(SourceLocation B, SourceLocation E) {
0277     return getCharRange(SourceRange(B, E));
0278   }
0279 
0280   /// Return true if the end of this range specifies the start of
0281   /// the last token.  Return false if the end of this range specifies the last
0282   /// character in the range.
0283   bool isTokenRange() const { return IsTokenRange; }
0284   bool isCharRange() const { return !IsTokenRange; }
0285 
0286   SourceLocation getBegin() const { return Range.getBegin(); }
0287   SourceLocation getEnd() const { return Range.getEnd(); }
0288   SourceRange getAsRange() const { return Range; }
0289 
0290   void setBegin(SourceLocation b) { Range.setBegin(b); }
0291   void setEnd(SourceLocation e) { Range.setEnd(e); }
0292   void setTokenRange(bool TR) { IsTokenRange = TR; }
0293 
0294   bool isValid() const { return Range.isValid(); }
0295   bool isInvalid() const { return !isValid(); }
0296 };
0297 
0298 /// Represents an unpacked "presumed" location which can be presented
0299 /// to the user.
0300 ///
0301 /// A 'presumed' location can be modified by \#line and GNU line marker
0302 /// directives and is always the expansion point of a normal location.
0303 ///
0304 /// You can get a PresumedLoc from a SourceLocation with SourceManager.
0305 class PresumedLoc {
0306   const char *Filename = nullptr;
0307   FileID ID;
0308   unsigned Line, Col;
0309   SourceLocation IncludeLoc;
0310 
0311 public:
0312   PresumedLoc() = default;
0313   PresumedLoc(const char *FN, FileID FID, unsigned Ln, unsigned Co,
0314               SourceLocation IL)
0315       : Filename(FN), ID(FID), Line(Ln), Col(Co), IncludeLoc(IL) {}
0316 
0317   /// Return true if this object is invalid or uninitialized.
0318   ///
0319   /// This occurs when created with invalid source locations or when walking
0320   /// off the top of a \#include stack.
0321   bool isInvalid() const { return Filename == nullptr; }
0322   bool isValid() const { return Filename != nullptr; }
0323 
0324   /// Return the presumed filename of this location.
0325   ///
0326   /// This can be affected by \#line etc.
0327   const char *getFilename() const {
0328     assert(isValid());
0329     return Filename;
0330   }
0331 
0332   FileID getFileID() const {
0333     assert(isValid());
0334     return ID;
0335   }
0336 
0337   /// Return the presumed line number of this location.
0338   ///
0339   /// This can be affected by \#line etc.
0340   unsigned getLine() const {
0341     assert(isValid());
0342     return Line;
0343   }
0344 
0345   /// Return the presumed column number of this location.
0346   ///
0347   /// This cannot be affected by \#line, but is packaged here for convenience.
0348   unsigned getColumn() const {
0349     assert(isValid());
0350     return Col;
0351   }
0352 
0353   /// Return the presumed include location of this location.
0354   ///
0355   /// This can be affected by GNU linemarker directives.
0356   SourceLocation getIncludeLoc() const {
0357     assert(isValid());
0358     return IncludeLoc;
0359   }
0360 };
0361 
0362 /// A SourceLocation and its associated SourceManager.
0363 ///
0364 /// This is useful for argument passing to functions that expect both objects.
0365 ///
0366 /// This class does not guarantee the presence of either the SourceManager or
0367 /// a valid SourceLocation. Clients should use `isValid()` and `hasManager()`
0368 /// before calling the member functions.
0369 class FullSourceLoc : public SourceLocation {
0370   const SourceManager *SrcMgr = nullptr;
0371 
0372 public:
0373   /// Creates a FullSourceLoc where isValid() returns \c false.
0374   FullSourceLoc() = default;
0375 
0376   explicit FullSourceLoc(SourceLocation Loc, const SourceManager &SM)
0377       : SourceLocation(Loc), SrcMgr(&SM) {}
0378 
0379   /// Checks whether the SourceManager is present.
0380   bool hasManager() const { return SrcMgr != nullptr; }
0381 
0382   /// \pre hasManager()
0383   const SourceManager &getManager() const {
0384     assert(SrcMgr && "SourceManager is NULL.");
0385     return *SrcMgr;
0386   }
0387 
0388   FileID getFileID() const;
0389 
0390   FullSourceLoc getExpansionLoc() const;
0391   FullSourceLoc getSpellingLoc() const;
0392   FullSourceLoc getFileLoc() const;
0393   PresumedLoc getPresumedLoc(bool UseLineDirectives = true) const;
0394   bool isMacroArgExpansion(FullSourceLoc *StartLoc = nullptr) const;
0395   FullSourceLoc getImmediateMacroCallerLoc() const;
0396   std::pair<FullSourceLoc, StringRef> getModuleImportLoc() const;
0397   unsigned getFileOffset() const;
0398 
0399   unsigned getExpansionLineNumber(bool *Invalid = nullptr) const;
0400   unsigned getExpansionColumnNumber(bool *Invalid = nullptr) const;
0401 
0402   /// Decompose the underlying \c SourceLocation into a raw (FileID + Offset)
0403   /// pair, after walking through all expansion records.
0404   ///
0405   /// \see SourceManager::getDecomposedExpansionLoc
0406   std::pair<FileID, unsigned> getDecomposedExpansionLoc() const;
0407 
0408   unsigned getSpellingLineNumber(bool *Invalid = nullptr) const;
0409   unsigned getSpellingColumnNumber(bool *Invalid = nullptr) const;
0410 
0411   const char *getCharacterData(bool *Invalid = nullptr) const;
0412 
0413   unsigned getLineNumber(bool *Invalid = nullptr) const;
0414   unsigned getColumnNumber(bool *Invalid = nullptr) const;
0415 
0416   const FileEntry *getFileEntry() const;
0417   OptionalFileEntryRef getFileEntryRef() const;
0418 
0419   /// Return a StringRef to the source buffer data for the
0420   /// specified FileID.
0421   StringRef getBufferData(bool *Invalid = nullptr) const;
0422 
0423   /// Decompose the specified location into a raw FileID + Offset pair.
0424   ///
0425   /// The first element is the FileID, the second is the offset from the
0426   /// start of the buffer of the location.
0427   std::pair<FileID, unsigned> getDecomposedLoc() const;
0428 
0429   bool isInSystemHeader() const;
0430 
0431   /// Determines the order of 2 source locations in the translation unit.
0432   ///
0433   /// \returns true if this source location comes before 'Loc', false otherwise.
0434   bool isBeforeInTranslationUnitThan(SourceLocation Loc) const;
0435 
0436   /// Determines the order of 2 source locations in the translation unit.
0437   ///
0438   /// \returns true if this source location comes before 'Loc', false otherwise.
0439   bool isBeforeInTranslationUnitThan(FullSourceLoc Loc) const {
0440     assert(Loc.isValid());
0441     assert(SrcMgr == Loc.SrcMgr && "Loc comes from another SourceManager!");
0442     return isBeforeInTranslationUnitThan((SourceLocation)Loc);
0443   }
0444 
0445   /// Comparison function class, useful for sorting FullSourceLocs.
0446   struct BeforeThanCompare {
0447     bool operator()(const FullSourceLoc& lhs, const FullSourceLoc& rhs) const {
0448       return lhs.isBeforeInTranslationUnitThan(rhs);
0449     }
0450   };
0451 
0452   /// Prints information about this FullSourceLoc to stderr.
0453   ///
0454   /// This is useful for debugging.
0455   void dump() const;
0456 
0457   friend bool
0458   operator==(const FullSourceLoc &LHS, const FullSourceLoc &RHS) {
0459     return LHS.getRawEncoding() == RHS.getRawEncoding() &&
0460           LHS.SrcMgr == RHS.SrcMgr;
0461   }
0462 
0463   friend bool
0464   operator!=(const FullSourceLoc &LHS, const FullSourceLoc &RHS) {
0465     return !(LHS == RHS);
0466   }
0467 };
0468 
0469 } // namespace clang
0470 
0471 namespace llvm {
0472 
0473   /// Define DenseMapInfo so that FileID's can be used as keys in DenseMap and
0474   /// DenseSets.
0475   template <>
0476   struct DenseMapInfo<clang::FileID, void> {
0477     static clang::FileID getEmptyKey() {
0478       return {};
0479     }
0480 
0481     static clang::FileID getTombstoneKey() {
0482       return clang::FileID::getSentinel();
0483     }
0484 
0485     static unsigned getHashValue(clang::FileID S) {
0486       return S.getHashValue();
0487     }
0488 
0489     static bool isEqual(clang::FileID LHS, clang::FileID RHS) {
0490       return LHS == RHS;
0491     }
0492   };
0493 
0494   /// Define DenseMapInfo so that SourceLocation's can be used as keys in
0495   /// DenseMap and DenseSet. This trait class is eqivalent to
0496   /// DenseMapInfo<unsigned> which uses SourceLocation::ID is used as a key.
0497   template <> struct DenseMapInfo<clang::SourceLocation, void> {
0498     static clang::SourceLocation getEmptyKey() {
0499       constexpr clang::SourceLocation::UIntTy Zero = 0;
0500       return clang::SourceLocation::getFromRawEncoding(~Zero);
0501     }
0502 
0503     static clang::SourceLocation getTombstoneKey() {
0504       constexpr clang::SourceLocation::UIntTy Zero = 0;
0505       return clang::SourceLocation::getFromRawEncoding(~Zero - 1);
0506     }
0507 
0508     static unsigned getHashValue(clang::SourceLocation Loc) {
0509       return Loc.getHashValue();
0510     }
0511 
0512     static bool isEqual(clang::SourceLocation LHS, clang::SourceLocation RHS) {
0513       return LHS == RHS;
0514     }
0515   };
0516 
0517   // Allow calling FoldingSetNodeID::Add with SourceLocation object as parameter
0518   template <> struct FoldingSetTrait<clang::SourceLocation, void> {
0519     static void Profile(const clang::SourceLocation &X, FoldingSetNodeID &ID);
0520   };
0521 
0522 } // namespace llvm
0523 
0524 #endif // LLVM_CLANG_BASIC_SOURCELOCATION_H