Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. //===- SourceLocation.h - Compact identifier for Source Files ---*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. /// \file
  10. /// Defines the clang::SourceLocation class and associated facilities.
  11. //
  12. //===----------------------------------------------------------------------===//
  13.  
  14. #ifndef LLVM_CLANG_BASIC_SOURCELOCATION_H
  15. #define LLVM_CLANG_BASIC_SOURCELOCATION_H
  16.  
  17. #include "clang/Basic/LLVM.h"
  18. #include "llvm/ADT/StringRef.h"
  19. #include <cassert>
  20. #include <cstdint>
  21. #include <string>
  22. #include <utility>
  23.  
  24. namespace llvm {
  25.  
  26. class FoldingSetNodeID;
  27. template <typename T, typename Enable> struct FoldingSetTrait;
  28.  
  29. } // namespace llvm
  30.  
  31. namespace clang {
  32.  
  33. class SourceManager;
  34.  
  35. /// An opaque identifier used by SourceManager which refers to a
  36. /// source file (MemoryBuffer) along with its \#include path and \#line data.
  37. ///
  38. class FileID {
  39.   /// A mostly-opaque identifier, where 0 is "invalid", >0 is
  40.   /// this module, and <-1 is something loaded from another module.
  41.   int ID = 0;
  42.  
  43. public:
  44.   bool isValid() const { return ID != 0; }
  45.   bool isInvalid() const { return ID == 0; }
  46.  
  47.   bool operator==(const FileID &RHS) const { return ID == RHS.ID; }
  48.   bool operator<(const FileID &RHS) const { return ID < RHS.ID; }
  49.   bool operator<=(const FileID &RHS) const { return ID <= RHS.ID; }
  50.   bool operator!=(const FileID &RHS) const { return !(*this == RHS); }
  51.   bool operator>(const FileID &RHS) const { return RHS < *this; }
  52.   bool operator>=(const FileID &RHS) const { return RHS <= *this; }
  53.  
  54.   static FileID getSentinel() { return get(-1); }
  55.   unsigned getHashValue() const { return static_cast<unsigned>(ID); }
  56.  
  57. private:
  58.   friend class ASTWriter;
  59.   friend class ASTReader;
  60.   friend class SourceManager;
  61.  
  62.   static FileID get(int V) {
  63.     FileID F;
  64.     F.ID = V;
  65.     return F;
  66.   }
  67.  
  68.   int getOpaqueValue() const { return ID; }
  69. };
  70.  
  71. /// Encodes a location in the source. The SourceManager can decode this
  72. /// to get at the full include stack, line and column information.
  73. ///
  74. /// Technically, a source location is simply an offset into the manager's view
  75. /// of the input source, which is all input buffers (including macro
  76. /// expansions) concatenated in an effectively arbitrary order. The manager
  77. /// actually maintains two blocks of input buffers. One, starting at offset
  78. /// 0 and growing upwards, contains all buffers from this module. The other,
  79. /// starting at the highest possible offset and growing downwards, contains
  80. /// buffers of loaded modules.
  81. ///
  82. /// In addition, one bit of SourceLocation is used for quick access to the
  83. /// information whether the location is in a file or a macro expansion.
  84. ///
  85. /// It is important that this type remains small. It is currently 32 bits wide.
  86. class SourceLocation {
  87.   friend class ASTReader;
  88.   friend class ASTWriter;
  89.   friend class SourceManager;
  90.   friend struct llvm::FoldingSetTrait<SourceLocation, void>;
  91.  
  92. public:
  93.   using UIntTy = uint32_t;
  94.   using IntTy = int32_t;
  95.  
  96. private:
  97.   UIntTy ID = 0;
  98.  
  99.   enum : UIntTy { MacroIDBit = 1ULL << (8 * sizeof(UIntTy) - 1) };
  100.  
  101. public:
  102.   bool isFileID() const  { return (ID & MacroIDBit) == 0; }
  103.   bool isMacroID() const { return (ID & MacroIDBit) != 0; }
  104.  
  105.   /// Return true if this is a valid SourceLocation object.
  106.   ///
  107.   /// Invalid SourceLocations are often used when events have no corresponding
  108.   /// location in the source (e.g. a diagnostic is required for a command line
  109.   /// option).
  110.   bool isValid() const { return ID != 0; }
  111.   bool isInvalid() const { return ID == 0; }
  112.  
  113. private:
  114.   /// Return the offset into the manager's global input view.
  115.   UIntTy getOffset() const { return ID & ~MacroIDBit; }
  116.  
  117.   static SourceLocation getFileLoc(UIntTy ID) {
  118.     assert((ID & MacroIDBit) == 0 && "Ran out of source locations!");
  119.     SourceLocation L;
  120.     L.ID = ID;
  121.     return L;
  122.   }
  123.  
  124.   static SourceLocation getMacroLoc(UIntTy ID) {
  125.     assert((ID & MacroIDBit) == 0 && "Ran out of source locations!");
  126.     SourceLocation L;
  127.     L.ID = MacroIDBit | ID;
  128.     return L;
  129.   }
  130.  
  131. public:
  132.   /// Return a source location with the specified offset from this
  133.   /// SourceLocation.
  134.   SourceLocation getLocWithOffset(IntTy Offset) const {
  135.     assert(((getOffset()+Offset) & MacroIDBit) == 0 && "offset overflow");
  136.     SourceLocation L;
  137.     L.ID = ID+Offset;
  138.     return L;
  139.   }
  140.  
  141.   /// When a SourceLocation itself cannot be used, this returns
  142.   /// an (opaque) 32-bit integer encoding for it.
  143.   ///
  144.   /// This should only be passed to SourceLocation::getFromRawEncoding, it
  145.   /// should not be inspected directly.
  146.   UIntTy getRawEncoding() const { return ID; }
  147.  
  148.   /// Turn a raw encoding of a SourceLocation object into
  149.   /// a real SourceLocation.
  150.   ///
  151.   /// \see getRawEncoding.
  152.   static SourceLocation getFromRawEncoding(UIntTy Encoding) {
  153.     SourceLocation X;
  154.     X.ID = Encoding;
  155.     return X;
  156.   }
  157.  
  158.   /// When a SourceLocation itself cannot be used, this returns
  159.   /// an (opaque) pointer encoding for it.
  160.   ///
  161.   /// This should only be passed to SourceLocation::getFromPtrEncoding, it
  162.   /// should not be inspected directly.
  163.   void* getPtrEncoding() const {
  164.     // Double cast to avoid a warning "cast to pointer from integer of different
  165.     // size".
  166.     return (void*)(uintptr_t)getRawEncoding();
  167.   }
  168.  
  169.   /// Turn a pointer encoding of a SourceLocation object back
  170.   /// into a real SourceLocation.
  171.   static SourceLocation getFromPtrEncoding(const void *Encoding) {
  172.     return getFromRawEncoding((SourceLocation::UIntTy)(uintptr_t)Encoding);
  173.   }
  174.  
  175.   static bool isPairOfFileLocations(SourceLocation Start, SourceLocation End) {
  176.     return Start.isValid() && Start.isFileID() && End.isValid() &&
  177.            End.isFileID();
  178.   }
  179.  
  180.   unsigned getHashValue() const;
  181.   void print(raw_ostream &OS, const SourceManager &SM) const;
  182.   std::string printToString(const SourceManager &SM) const;
  183.   void dump(const SourceManager &SM) const;
  184. };
  185.  
  186. inline bool operator==(const SourceLocation &LHS, const SourceLocation &RHS) {
  187.   return LHS.getRawEncoding() == RHS.getRawEncoding();
  188. }
  189.  
  190. inline bool operator!=(const SourceLocation &LHS, const SourceLocation &RHS) {
  191.   return !(LHS == RHS);
  192. }
  193.  
  194. // Ordering is meaningful only if LHS and RHS have the same FileID!
  195. // Otherwise use SourceManager::isBeforeInTranslationUnit().
  196. inline bool operator<(const SourceLocation &LHS, const SourceLocation &RHS) {
  197.   return LHS.getRawEncoding() < RHS.getRawEncoding();
  198. }
  199. inline bool operator>(const SourceLocation &LHS, const SourceLocation &RHS) {
  200.   return LHS.getRawEncoding() > RHS.getRawEncoding();
  201. }
  202. inline bool operator<=(const SourceLocation &LHS, const SourceLocation &RHS) {
  203.   return LHS.getRawEncoding() <= RHS.getRawEncoding();
  204. }
  205. inline bool operator>=(const SourceLocation &LHS, const SourceLocation &RHS) {
  206.   return LHS.getRawEncoding() >= RHS.getRawEncoding();
  207. }
  208.  
  209. /// A trivial tuple used to represent a source range.
  210. class SourceRange {
  211.   SourceLocation B;
  212.   SourceLocation E;
  213.  
  214. public:
  215.   SourceRange() = default;
  216.   SourceRange(SourceLocation loc) : B(loc), E(loc) {}
  217.   SourceRange(SourceLocation begin, SourceLocation end) : B(begin), E(end) {}
  218.  
  219.   SourceLocation getBegin() const { return B; }
  220.   SourceLocation getEnd() const { return E; }
  221.  
  222.   void setBegin(SourceLocation b) { B = b; }
  223.   void setEnd(SourceLocation e) { E = e; }
  224.  
  225.   bool isValid() const { return B.isValid() && E.isValid(); }
  226.   bool isInvalid() const { return !isValid(); }
  227.  
  228.   bool operator==(const SourceRange &X) const {
  229.     return B == X.B && E == X.E;
  230.   }
  231.  
  232.   bool operator!=(const SourceRange &X) const {
  233.     return B != X.B || E != X.E;
  234.   }
  235.  
  236.   // Returns true iff other is wholly contained within this range.
  237.   bool fullyContains(const SourceRange &other) const {
  238.     return B <= other.B && E >= other.E;
  239.   }
  240.  
  241.   void print(raw_ostream &OS, const SourceManager &SM) const;
  242.   std::string printToString(const SourceManager &SM) const;
  243.   void dump(const SourceManager &SM) const;
  244. };
  245.  
  246. /// Represents a character-granular source range.
  247. ///
  248. /// The underlying SourceRange can either specify the starting/ending character
  249. /// of the range, or it can specify the start of the range and the start of the
  250. /// last token of the range (a "token range").  In the token range case, the
  251. /// size of the last token must be measured to determine the actual end of the
  252. /// range.
  253. class CharSourceRange {
  254.   SourceRange Range;
  255.   bool IsTokenRange = false;
  256.  
  257. public:
  258.   CharSourceRange() = default;
  259.   CharSourceRange(SourceRange R, bool ITR) : Range(R), IsTokenRange(ITR) {}
  260.  
  261.   static CharSourceRange getTokenRange(SourceRange R) {
  262.     return CharSourceRange(R, true);
  263.   }
  264.  
  265.   static CharSourceRange getCharRange(SourceRange R) {
  266.     return CharSourceRange(R, false);
  267.   }
  268.  
  269.   static CharSourceRange getTokenRange(SourceLocation B, SourceLocation E) {
  270.     return getTokenRange(SourceRange(B, E));
  271.   }
  272.  
  273.   static CharSourceRange getCharRange(SourceLocation B, SourceLocation E) {
  274.     return getCharRange(SourceRange(B, E));
  275.   }
  276.  
  277.   /// Return true if the end of this range specifies the start of
  278.   /// the last token.  Return false if the end of this range specifies the last
  279.   /// character in the range.
  280.   bool isTokenRange() const { return IsTokenRange; }
  281.   bool isCharRange() const { return !IsTokenRange; }
  282.  
  283.   SourceLocation getBegin() const { return Range.getBegin(); }
  284.   SourceLocation getEnd() const { return Range.getEnd(); }
  285.   SourceRange getAsRange() const { return Range; }
  286.  
  287.   void setBegin(SourceLocation b) { Range.setBegin(b); }
  288.   void setEnd(SourceLocation e) { Range.setEnd(e); }
  289.   void setTokenRange(bool TR) { IsTokenRange = TR; }
  290.  
  291.   bool isValid() const { return Range.isValid(); }
  292.   bool isInvalid() const { return !isValid(); }
  293. };
  294.  
  295. /// Represents an unpacked "presumed" location which can be presented
  296. /// to the user.
  297. ///
  298. /// A 'presumed' location can be modified by \#line and GNU line marker
  299. /// directives and is always the expansion point of a normal location.
  300. ///
  301. /// You can get a PresumedLoc from a SourceLocation with SourceManager.
  302. class PresumedLoc {
  303.   const char *Filename = nullptr;
  304.   FileID ID;
  305.   unsigned Line, Col;
  306.   SourceLocation IncludeLoc;
  307.  
  308. public:
  309.   PresumedLoc() = default;
  310.   PresumedLoc(const char *FN, FileID FID, unsigned Ln, unsigned Co,
  311.               SourceLocation IL)
  312.       : Filename(FN), ID(FID), Line(Ln), Col(Co), IncludeLoc(IL) {}
  313.  
  314.   /// Return true if this object is invalid or uninitialized.
  315.   ///
  316.   /// This occurs when created with invalid source locations or when walking
  317.   /// off the top of a \#include stack.
  318.   bool isInvalid() const { return Filename == nullptr; }
  319.   bool isValid() const { return Filename != nullptr; }
  320.  
  321.   /// Return the presumed filename of this location.
  322.   ///
  323.   /// This can be affected by \#line etc.
  324.   const char *getFilename() const {
  325.     assert(isValid());
  326.     return Filename;
  327.   }
  328.  
  329.   FileID getFileID() const {
  330.     assert(isValid());
  331.     return ID;
  332.   }
  333.  
  334.   /// Return the presumed line number of this location.
  335.   ///
  336.   /// This can be affected by \#line etc.
  337.   unsigned getLine() const {
  338.     assert(isValid());
  339.     return Line;
  340.   }
  341.  
  342.   /// Return the presumed column number of this location.
  343.   ///
  344.   /// This cannot be affected by \#line, but is packaged here for convenience.
  345.   unsigned getColumn() const {
  346.     assert(isValid());
  347.     return Col;
  348.   }
  349.  
  350.   /// Return the presumed include location of this location.
  351.   ///
  352.   /// This can be affected by GNU linemarker directives.
  353.   SourceLocation getIncludeLoc() const {
  354.     assert(isValid());
  355.     return IncludeLoc;
  356.   }
  357. };
  358.  
  359. class FileEntry;
  360.  
  361. /// A SourceLocation and its associated SourceManager.
  362. ///
  363. /// This is useful for argument passing to functions that expect both objects.
  364. ///
  365. /// This class does not guarantee the presence of either the SourceManager or
  366. /// a valid SourceLocation. Clients should use `isValid()` and `hasManager()`
  367. /// before calling the member functions.
  368. class FullSourceLoc : public SourceLocation {
  369.   const SourceManager *SrcMgr = nullptr;
  370.  
  371. public:
  372.   /// Creates a FullSourceLoc where isValid() returns \c false.
  373.   FullSourceLoc() = default;
  374.  
  375.   explicit FullSourceLoc(SourceLocation Loc, const SourceManager &SM)
  376.       : SourceLocation(Loc), SrcMgr(&SM) {}
  377.  
  378.   /// Checks whether the SourceManager is present.
  379.   bool hasManager() const { return SrcMgr != nullptr; }
  380.  
  381.   /// \pre hasManager()
  382.   const SourceManager &getManager() const {
  383.     assert(SrcMgr && "SourceManager is NULL.");
  384.     return *SrcMgr;
  385.   }
  386.  
  387.   FileID getFileID() const;
  388.  
  389.   FullSourceLoc getExpansionLoc() const;
  390.   FullSourceLoc getSpellingLoc() const;
  391.   FullSourceLoc getFileLoc() const;
  392.   PresumedLoc getPresumedLoc(bool UseLineDirectives = true) const;
  393.   bool isMacroArgExpansion(FullSourceLoc *StartLoc = nullptr) const;
  394.   FullSourceLoc getImmediateMacroCallerLoc() const;
  395.   std::pair<FullSourceLoc, StringRef> getModuleImportLoc() const;
  396.   unsigned getFileOffset() const;
  397.  
  398.   unsigned getExpansionLineNumber(bool *Invalid = nullptr) const;
  399.   unsigned getExpansionColumnNumber(bool *Invalid = nullptr) const;
  400.  
  401.   /// Decompose the underlying \c SourceLocation into a raw (FileID + Offset)
  402.   /// pair, after walking through all expansion records.
  403.   ///
  404.   /// \see SourceManager::getDecomposedExpansionLoc
  405.   std::pair<FileID, unsigned> getDecomposedExpansionLoc() const;
  406.  
  407.   unsigned getSpellingLineNumber(bool *Invalid = nullptr) const;
  408.   unsigned getSpellingColumnNumber(bool *Invalid = nullptr) const;
  409.  
  410.   const char *getCharacterData(bool *Invalid = nullptr) const;
  411.  
  412.   unsigned getLineNumber(bool *Invalid = nullptr) const;
  413.   unsigned getColumnNumber(bool *Invalid = nullptr) const;
  414.  
  415.   const FileEntry *getFileEntry() const;
  416.  
  417.   /// Return a StringRef to the source buffer data for the
  418.   /// specified FileID.
  419.   StringRef getBufferData(bool *Invalid = nullptr) const;
  420.  
  421.   /// Decompose the specified location into a raw FileID + Offset pair.
  422.   ///
  423.   /// The first element is the FileID, the second is the offset from the
  424.   /// start of the buffer of the location.
  425.   std::pair<FileID, unsigned> getDecomposedLoc() const;
  426.  
  427.   bool isInSystemHeader() const;
  428.  
  429.   /// Determines the order of 2 source locations in the translation unit.
  430.   ///
  431.   /// \returns true if this source location comes before 'Loc', false otherwise.
  432.   bool isBeforeInTranslationUnitThan(SourceLocation Loc) const;
  433.  
  434.   /// Determines the order of 2 source locations in the translation unit.
  435.   ///
  436.   /// \returns true if this source location comes before 'Loc', false otherwise.
  437.   bool isBeforeInTranslationUnitThan(FullSourceLoc Loc) const {
  438.     assert(Loc.isValid());
  439.     assert(SrcMgr == Loc.SrcMgr && "Loc comes from another SourceManager!");
  440.     return isBeforeInTranslationUnitThan((SourceLocation)Loc);
  441.   }
  442.  
  443.   /// Comparison function class, useful for sorting FullSourceLocs.
  444.   struct BeforeThanCompare {
  445.     bool operator()(const FullSourceLoc& lhs, const FullSourceLoc& rhs) const {
  446.       return lhs.isBeforeInTranslationUnitThan(rhs);
  447.     }
  448.   };
  449.  
  450.   /// Prints information about this FullSourceLoc to stderr.
  451.   ///
  452.   /// This is useful for debugging.
  453.   void dump() const;
  454.  
  455.   friend bool
  456.   operator==(const FullSourceLoc &LHS, const FullSourceLoc &RHS) {
  457.     return LHS.getRawEncoding() == RHS.getRawEncoding() &&
  458.           LHS.SrcMgr == RHS.SrcMgr;
  459.   }
  460.  
  461.   friend bool
  462.   operator!=(const FullSourceLoc &LHS, const FullSourceLoc &RHS) {
  463.     return !(LHS == RHS);
  464.   }
  465. };
  466.  
  467. } // namespace clang
  468.  
  469. namespace llvm {
  470.  
  471.   /// Define DenseMapInfo so that FileID's can be used as keys in DenseMap and
  472.   /// DenseSets.
  473.   template <>
  474.   struct DenseMapInfo<clang::FileID, void> {
  475.     static clang::FileID getEmptyKey() {
  476.       return {};
  477.     }
  478.  
  479.     static clang::FileID getTombstoneKey() {
  480.       return clang::FileID::getSentinel();
  481.     }
  482.  
  483.     static unsigned getHashValue(clang::FileID S) {
  484.       return S.getHashValue();
  485.     }
  486.  
  487.     static bool isEqual(clang::FileID LHS, clang::FileID RHS) {
  488.       return LHS == RHS;
  489.     }
  490.   };
  491.  
  492.   /// Define DenseMapInfo so that SourceLocation's can be used as keys in
  493.   /// DenseMap and DenseSet. This trait class is eqivalent to
  494.   /// DenseMapInfo<unsigned> which uses SourceLocation::ID is used as a key.
  495.   template <> struct DenseMapInfo<clang::SourceLocation, void> {
  496.     static clang::SourceLocation getEmptyKey() {
  497.       constexpr clang::SourceLocation::UIntTy Zero = 0;
  498.       return clang::SourceLocation::getFromRawEncoding(~Zero);
  499.     }
  500.  
  501.     static clang::SourceLocation getTombstoneKey() {
  502.       constexpr clang::SourceLocation::UIntTy Zero = 0;
  503.       return clang::SourceLocation::getFromRawEncoding(~Zero - 1);
  504.     }
  505.  
  506.     static unsigned getHashValue(clang::SourceLocation Loc) {
  507.       return Loc.getHashValue();
  508.     }
  509.  
  510.     static bool isEqual(clang::SourceLocation LHS, clang::SourceLocation RHS) {
  511.       return LHS == RHS;
  512.     }
  513.   };
  514.  
  515.   // Allow calling FoldingSetNodeID::Add with SourceLocation object as parameter
  516.   template <> struct FoldingSetTrait<clang::SourceLocation, void> {
  517.     static void Profile(const clang::SourceLocation &X, FoldingSetNodeID &ID);
  518.   };
  519.  
  520. } // namespace llvm
  521.  
  522. #endif // LLVM_CLANG_BASIC_SOURCELOCATION_H
  523.