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