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