1193326Sed//===--- SourceLocation.h - Compact identifier for Source Files -*- C++ -*-===//
2193326Sed//
3193326Sed//                     The LLVM Compiler Infrastructure
4193326Sed//
5193326Sed// This file is distributed under the University of Illinois Open Source
6193326Sed// License. See LICENSE.TXT for details.
7193326Sed//
8193326Sed//===----------------------------------------------------------------------===//
9239462Sdim///
10239462Sdim/// \file
11239462Sdim/// \brief Defines the clang::SourceLocation class and associated facilities.
12239462Sdim///
13193326Sed//===----------------------------------------------------------------------===//
14193326Sed
15193326Sed#ifndef LLVM_CLANG_SOURCELOCATION_H
16193326Sed#define LLVM_CLANG_SOURCELOCATION_H
17193326Sed
18226633Sdim#include "clang/Basic/LLVM.h"
19249423Sdim#include "llvm/Support/Compiler.h"
20218893Sdim#include "llvm/Support/PointerLikeTypeTraits.h"
21249423Sdim#include <cassert>
22221345Sdim#include <functional>
23243830Sdim#include <string>
24249423Sdim#include <utility>
25193326Sed
26193326Sednamespace llvm {
27193326Sed  class MemoryBuffer;
28193326Sed  template <typename T> struct DenseMapInfo;
29200583Srdivacky  template <typename T> struct isPodLike;
30193326Sed}
31193326Sed
32193326Sednamespace clang {
33198092Srdivacky
34193326Sedclass SourceManager;
35198092Srdivacky
36239462Sdim/// \brief An opaque identifier used by SourceManager which refers to a
37239462Sdim/// source file (MemoryBuffer) along with its \#include path and \#line data.
38193326Sed///
39193326Sedclass FileID {
40239462Sdim  /// \brief A mostly-opaque identifier, where 0 is "invalid", >0 is
41239462Sdim  /// this module, and <-1 is something loaded from another module.
42226633Sdim  int ID;
43193326Sedpublic:
44193326Sed  FileID() : ID(0) {}
45198092Srdivacky
46193326Sed  bool isInvalid() const { return ID == 0; }
47198092Srdivacky
48193326Sed  bool operator==(const FileID &RHS) const { return ID == RHS.ID; }
49193326Sed  bool operator<(const FileID &RHS) const { return ID < RHS.ID; }
50193326Sed  bool operator<=(const FileID &RHS) const { return ID <= RHS.ID; }
51193326Sed  bool operator!=(const FileID &RHS) const { return !(*this == RHS); }
52193326Sed  bool operator>(const FileID &RHS) const { return RHS < *this; }
53193326Sed  bool operator>=(const FileID &RHS) const { return RHS <= *this; }
54198092Srdivacky
55226633Sdim  static FileID getSentinel() { return get(-1); }
56226633Sdim  unsigned getHashValue() const { return static_cast<unsigned>(ID); }
57198092Srdivacky
58193326Sedprivate:
59193326Sed  friend class SourceManager;
60223017Sdim  friend class ASTWriter;
61223017Sdim  friend class ASTReader;
62223017Sdim
63226633Sdim  static FileID get(int V) {
64193326Sed    FileID F;
65193326Sed    F.ID = V;
66193326Sed    return F;
67193326Sed  }
68226633Sdim  int getOpaqueValue() const { return ID; }
69193326Sed};
70198092Srdivacky
71198092Srdivacky
72226633Sdim/// \brief Encodes a location in the source. The SourceManager can decode this
73226633Sdim/// to get at the full include stack, line and column information.
74226633Sdim///
75226633Sdim/// Technically, a source location is simply an offset into the manager's view
76226633Sdim/// of the input source, which is all input buffers (including macro
77226633Sdim/// expansions) concatenated in an effectively arbitrary order. The manager
78226633Sdim/// actually maintains two blocks of input buffers. One, starting at offset
79226633Sdim/// 0 and growing upwards, contains all buffers from this module. The other,
80226633Sdim/// starting at the highest possible offset and growing downwards, contains
81226633Sdim/// buffers of loaded modules.
82226633Sdim///
83226633Sdim/// In addition, one bit of SourceLocation is used for quick access to the
84226633Sdim/// information whether the location is in a file or a macro expansion.
85226633Sdim///
86226633Sdim/// It is important that this type remains small. It is currently 32 bits wide.
87193326Sedclass SourceLocation {
88193326Sed  unsigned ID;
89193326Sed  friend class SourceManager;
90226633Sdim  friend class ASTReader;
91226633Sdim  friend class ASTWriter;
92193326Sed  enum {
93193326Sed    MacroIDBit = 1U << 31
94193326Sed  };
95193326Sedpublic:
96193326Sed
97226633Sdim  SourceLocation() : ID(0) {}
98198092Srdivacky
99193326Sed  bool isFileID() const  { return (ID & MacroIDBit) == 0; }
100193326Sed  bool isMacroID() const { return (ID & MacroIDBit) != 0; }
101198092Srdivacky
102226633Sdim  /// \brief Return true if this is a valid SourceLocation object.
103193326Sed  ///
104226633Sdim  /// Invalid SourceLocations are often used when events have no corresponding
105226633Sdim  /// location in the source (e.g. a diagnostic is required for a command line
106226633Sdim  /// option).
107193326Sed  bool isValid() const { return ID != 0; }
108193326Sed  bool isInvalid() const { return ID == 0; }
109198092Srdivacky
110193326Sedprivate:
111226633Sdim  /// \brief Return the offset into the manager's global input view.
112193326Sed  unsigned getOffset() const {
113193326Sed    return ID & ~MacroIDBit;
114193326Sed  }
115193326Sed
116193326Sed  static SourceLocation getFileLoc(unsigned ID) {
117193326Sed    assert((ID & MacroIDBit) == 0 && "Ran out of source locations!");
118193326Sed    SourceLocation L;
119193326Sed    L.ID = ID;
120193326Sed    return L;
121193326Sed  }
122198092Srdivacky
123193326Sed  static SourceLocation getMacroLoc(unsigned ID) {
124193326Sed    assert((ID & MacroIDBit) == 0 && "Ran out of source locations!");
125193326Sed    SourceLocation L;
126193326Sed    L.ID = MacroIDBit | ID;
127193326Sed    return L;
128193326Sed  }
129193326Sedpublic:
130198092Srdivacky
131226633Sdim  /// \brief Return a source location with the specified offset from this
132226633Sdim  /// SourceLocation.
133226633Sdim  SourceLocation getLocWithOffset(int Offset) const {
134226633Sdim    assert(((getOffset()+Offset) & MacroIDBit) == 0 && "offset overflow");
135193326Sed    SourceLocation L;
136193326Sed    L.ID = ID+Offset;
137193326Sed    return L;
138193326Sed  }
139198092Srdivacky
140239462Sdim  /// \brief When a SourceLocation itself cannot be used, this returns
141239462Sdim  /// an (opaque) 32-bit integer encoding for it.
142239462Sdim  ///
143239462Sdim  /// This should only be passed to SourceLocation::getFromRawEncoding, it
144239462Sdim  /// should not be inspected directly.
145193326Sed  unsigned getRawEncoding() const { return ID; }
146198092Srdivacky
147239462Sdim  /// \brief Turn a raw encoding of a SourceLocation object into
148193326Sed  /// a real SourceLocation.
149239462Sdim  ///
150239462Sdim  /// \see getRawEncoding.
151193326Sed  static SourceLocation getFromRawEncoding(unsigned Encoding) {
152193326Sed    SourceLocation X;
153193326Sed    X.ID = Encoding;
154193326Sed    return X;
155193326Sed  }
156198092Srdivacky
157239462Sdim  /// \brief When a SourceLocation itself cannot be used, this returns
158239462Sdim  /// an (opaque) pointer encoding for it.
159239462Sdim  ///
160239462Sdim  /// This should only be passed to SourceLocation::getFromPtrEncoding, it
161239462Sdim  /// should not be inspected directly.
162218893Sdim  void* getPtrEncoding() const {
163218893Sdim    // Double cast to avoid a warning "cast to pointer from integer of different
164218893Sdim    // size".
165218893Sdim    return (void*)(uintptr_t)getRawEncoding();
166218893Sdim  }
167218893Sdim
168249423Sdim  /// \brief Turn a pointer encoding of a SourceLocation object back
169218893Sdim  /// into a real SourceLocation.
170239462Sdim  static SourceLocation getFromPtrEncoding(const void *Encoding) {
171218893Sdim    return getFromRawEncoding((unsigned)(uintptr_t)Encoding);
172218893Sdim  }
173218893Sdim
174226633Sdim  void print(raw_ostream &OS, const SourceManager &SM) const;
175243830Sdim  LLVM_ATTRIBUTE_USED std::string printToString(const SourceManager &SM) const;
176193326Sed  void dump(const SourceManager &SM) const;
177193326Sed};
178193326Sed
179193326Sedinline bool operator==(const SourceLocation &LHS, const SourceLocation &RHS) {
180193326Sed  return LHS.getRawEncoding() == RHS.getRawEncoding();
181193326Sed}
182193326Sed
183193326Sedinline bool operator!=(const SourceLocation &LHS, const SourceLocation &RHS) {
184193326Sed  return !(LHS == RHS);
185193326Sed}
186198092Srdivacky
187193326Sedinline bool operator<(const SourceLocation &LHS, const SourceLocation &RHS) {
188193326Sed  return LHS.getRawEncoding() < RHS.getRawEncoding();
189193326Sed}
190193326Sed
191239462Sdim/// \brief A trival tuple used to represent a source range.
192193326Sedclass SourceRange {
193193326Sed  SourceLocation B;
194193326Sed  SourceLocation E;
195193326Sedpublic:
196193326Sed  SourceRange(): B(SourceLocation()), E(SourceLocation()) {}
197193326Sed  SourceRange(SourceLocation loc) : B(loc), E(loc) {}
198193326Sed  SourceRange(SourceLocation begin, SourceLocation end) : B(begin), E(end) {}
199198092Srdivacky
200193326Sed  SourceLocation getBegin() const { return B; }
201193326Sed  SourceLocation getEnd() const { return E; }
202198092Srdivacky
203193326Sed  void setBegin(SourceLocation b) { B = b; }
204193326Sed  void setEnd(SourceLocation e) { E = e; }
205198092Srdivacky
206193326Sed  bool isValid() const { return B.isValid() && E.isValid(); }
207202379Srdivacky  bool isInvalid() const { return !isValid(); }
208198092Srdivacky
209193326Sed  bool operator==(const SourceRange &X) const {
210193326Sed    return B == X.B && E == X.E;
211193326Sed  }
212198092Srdivacky
213193326Sed  bool operator!=(const SourceRange &X) const {
214193326Sed    return B != X.B || E != X.E;
215193326Sed  }
216193326Sed};
217210299Sed
218239462Sdim/// \brief Represents a character-granular source range.
219239462Sdim///
220210299Sed/// The underlying SourceRange can either specify the starting/ending character
221249423Sdim/// of the range, or it can specify the start of the range and the start of the
222210299Sed/// last token of the range (a "token range").  In the token range case, the
223210299Sed/// size of the last token must be measured to determine the actual end of the
224210299Sed/// range.
225210299Sedclass CharSourceRange {
226210299Sed  SourceRange Range;
227210299Sed  bool IsTokenRange;
228210299Sedpublic:
229210299Sed  CharSourceRange() : IsTokenRange(false) {}
230249423Sdim  CharSourceRange(SourceRange R, bool ITR) : Range(R), IsTokenRange(ITR) {}
231198092Srdivacky
232210299Sed  static CharSourceRange getTokenRange(SourceRange R) {
233249423Sdim    return CharSourceRange(R, true);
234210299Sed  }
235210299Sed
236210299Sed  static CharSourceRange getCharRange(SourceRange R) {
237249423Sdim    return CharSourceRange(R, false);
238210299Sed  }
239210299Sed
240210299Sed  static CharSourceRange getTokenRange(SourceLocation B, SourceLocation E) {
241210299Sed    return getTokenRange(SourceRange(B, E));
242210299Sed  }
243210299Sed  static CharSourceRange getCharRange(SourceLocation B, SourceLocation E) {
244210299Sed    return getCharRange(SourceRange(B, E));
245210299Sed  }
246210299Sed
247239462Sdim  /// \brief Return true if the end of this range specifies the start of
248210299Sed  /// the last token.  Return false if the end of this range specifies the last
249210299Sed  /// character in the range.
250210299Sed  bool isTokenRange() const { return IsTokenRange; }
251234353Sdim  bool isCharRange() const { return !IsTokenRange; }
252210299Sed
253210299Sed  SourceLocation getBegin() const { return Range.getBegin(); }
254210299Sed  SourceLocation getEnd() const { return Range.getEnd(); }
255210299Sed  const SourceRange &getAsRange() const { return Range; }
256210299Sed
257210299Sed  void setBegin(SourceLocation b) { Range.setBegin(b); }
258210299Sed  void setEnd(SourceLocation e) { Range.setEnd(e); }
259210299Sed
260210299Sed  bool isValid() const { return Range.isValid(); }
261210299Sed  bool isInvalid() const { return !isValid(); }
262210299Sed};
263210299Sed
264239462Sdim/// \brief A SourceLocation and its associated SourceManager.
265239462Sdim///
266239462Sdim/// This is useful for argument passing to functions that expect both objects.
267193326Sedclass FullSourceLoc : public SourceLocation {
268207619Srdivacky  const SourceManager *SrcMgr;
269193326Sedpublic:
270239462Sdim  /// \brief Creates a FullSourceLoc where isValid() returns \c false.
271207619Srdivacky  explicit FullSourceLoc() : SrcMgr(0) {}
272193326Sed
273207619Srdivacky  explicit FullSourceLoc(SourceLocation Loc, const SourceManager &SM)
274193326Sed    : SourceLocation(Loc), SrcMgr(&SM) {}
275198092Srdivacky
276239462Sdim  /// \pre This FullSourceLoc has an associated SourceManager.
277193326Sed  const SourceManager &getManager() const {
278193326Sed    assert(SrcMgr && "SourceManager is NULL.");
279193326Sed    return *SrcMgr;
280193326Sed  }
281198092Srdivacky
282193326Sed  FileID getFileID() const;
283198092Srdivacky
284226633Sdim  FullSourceLoc getExpansionLoc() const;
285193326Sed  FullSourceLoc getSpellingLoc() const;
286193326Sed
287226633Sdim  unsigned getExpansionLineNumber(bool *Invalid = 0) const;
288226633Sdim  unsigned getExpansionColumnNumber(bool *Invalid = 0) const;
289193326Sed
290205408Srdivacky  unsigned getSpellingLineNumber(bool *Invalid = 0) const;
291205408Srdivacky  unsigned getSpellingColumnNumber(bool *Invalid = 0) const;
292193326Sed
293205408Srdivacky  const char *getCharacterData(bool *Invalid = 0) const;
294198092Srdivacky
295205408Srdivacky  const llvm::MemoryBuffer* getBuffer(bool *Invalid = 0) const;
296198092Srdivacky
297239462Sdim  /// \brief Return a StringRef to the source buffer data for the
298205219Srdivacky  /// specified FileID.
299226633Sdim  StringRef getBufferData(bool *Invalid = 0) const;
300198092Srdivacky
301239462Sdim  /// \brief Decompose the specified location into a raw FileID + Offset pair.
302239462Sdim  ///
303239462Sdim  /// The first element is the FileID, the second is the offset from the
304239462Sdim  /// start of the buffer of the location.
305193326Sed  std::pair<FileID, unsigned> getDecomposedLoc() const;
306193326Sed
307193326Sed  bool isInSystemHeader() const;
308198092Srdivacky
309218893Sdim  /// \brief Determines the order of 2 source locations in the translation unit.
310218893Sdim  ///
311218893Sdim  /// \returns true if this source location comes before 'Loc', false otherwise.
312218893Sdim  bool isBeforeInTranslationUnitThan(SourceLocation Loc) const;
313218893Sdim
314218893Sdim  /// \brief Determines the order of 2 source locations in the translation unit.
315218893Sdim  ///
316218893Sdim  /// \returns true if this source location comes before 'Loc', false otherwise.
317218893Sdim  bool isBeforeInTranslationUnitThan(FullSourceLoc Loc) const {
318218893Sdim    assert(Loc.isValid());
319218893Sdim    assert(SrcMgr == Loc.SrcMgr && "Loc comes from another SourceManager!");
320218893Sdim    return isBeforeInTranslationUnitThan((SourceLocation)Loc);
321218893Sdim  }
322218893Sdim
323221345Sdim  /// \brief Comparison function class, useful for sorting FullSourceLocs.
324221345Sdim  struct BeforeThanCompare : public std::binary_function<FullSourceLoc,
325221345Sdim                                                         FullSourceLoc, bool> {
326221345Sdim    bool operator()(const FullSourceLoc& lhs, const FullSourceLoc& rhs) const {
327221345Sdim      return lhs.isBeforeInTranslationUnitThan(rhs);
328221345Sdim    }
329221345Sdim  };
330221345Sdim
331239462Sdim  /// \brief Prints information about this FullSourceLoc to stderr.
332239462Sdim  ///
333239462Sdim  /// This is useful for debugging.
334234353Sdim  LLVM_ATTRIBUTE_USED void dump() const;
335193326Sed
336198092Srdivacky  friend inline bool
337193326Sed  operator==(const FullSourceLoc &LHS, const FullSourceLoc &RHS) {
338193326Sed    return LHS.getRawEncoding() == RHS.getRawEncoding() &&
339193326Sed          LHS.SrcMgr == RHS.SrcMgr;
340193326Sed  }
341193326Sed
342198092Srdivacky  friend inline bool
343193326Sed  operator!=(const FullSourceLoc &LHS, const FullSourceLoc &RHS) {
344193326Sed    return !(LHS == RHS);
345193326Sed  }
346193326Sed
347193326Sed};
348198092Srdivacky
349239462Sdim/// \brief Represents an unpacked "presumed" location which can be presented
350239462Sdim/// to the user.
351193326Sed///
352239462Sdim/// A 'presumed' location can be modified by \#line and GNU line marker
353239462Sdim/// directives and is always the expansion point of a normal location.
354239462Sdim///
355193326Sed/// You can get a PresumedLoc from a SourceLocation with SourceManager.
356193326Sedclass PresumedLoc {
357193326Sed  const char *Filename;
358193326Sed  unsigned Line, Col;
359193326Sed  SourceLocation IncludeLoc;
360193326Sedpublic:
361193326Sed  PresumedLoc() : Filename(0) {}
362193326Sed  PresumedLoc(const char *FN, unsigned Ln, unsigned Co, SourceLocation IL)
363193326Sed    : Filename(FN), Line(Ln), Col(Co), IncludeLoc(IL) {
364193326Sed  }
365198092Srdivacky
366239462Sdim  /// \brief Return true if this object is invalid or uninitialized.
367239462Sdim  ///
368239462Sdim  /// This occurs when created with invalid source locations or when walking
369239462Sdim  /// off the top of a \#include stack.
370193326Sed  bool isInvalid() const { return Filename == 0; }
371193326Sed  bool isValid() const { return Filename != 0; }
372198092Srdivacky
373239462Sdim  /// \brief Return the presumed filename of this location.
374239462Sdim  ///
375239462Sdim  /// This can be affected by \#line etc.
376193326Sed  const char *getFilename() const { return Filename; }
377193326Sed
378239462Sdim  /// \brief Return the presumed line number of this location.
379239462Sdim  ///
380239462Sdim  /// This can be affected by \#line etc.
381193326Sed  unsigned getLine() const { return Line; }
382198092Srdivacky
383239462Sdim  /// \brief Return the presumed column number of this location.
384239462Sdim  ///
385239462Sdim  /// This cannot be affected by \#line, but is packaged here for convenience.
386193326Sed  unsigned getColumn() const { return Col; }
387193326Sed
388239462Sdim  /// \brief Return the presumed include location of this location.
389239462Sdim  ///
390193326Sed  /// This can be affected by GNU linemarker directives.
391193326Sed  SourceLocation getIncludeLoc() const { return IncludeLoc; }
392193326Sed};
393193326Sed
394198092Srdivacky
395193326Sed}  // end namespace clang
396193326Sed
397193326Sednamespace llvm {
398193326Sed  /// Define DenseMapInfo so that FileID's can be used as keys in DenseMap and
399193326Sed  /// DenseSets.
400193326Sed  template <>
401193326Sed  struct DenseMapInfo<clang::FileID> {
402193326Sed    static inline clang::FileID getEmptyKey() {
403193326Sed      return clang::FileID();
404193326Sed    }
405193326Sed    static inline clang::FileID getTombstoneKey() {
406198092Srdivacky      return clang::FileID::getSentinel();
407193326Sed    }
408198092Srdivacky
409193326Sed    static unsigned getHashValue(clang::FileID S) {
410193326Sed      return S.getHashValue();
411193326Sed    }
412198092Srdivacky
413193326Sed    static bool isEqual(clang::FileID LHS, clang::FileID RHS) {
414193326Sed      return LHS == RHS;
415193326Sed    }
416193326Sed  };
417200583Srdivacky
418200583Srdivacky  template <>
419200583Srdivacky  struct isPodLike<clang::SourceLocation> { static const bool value = true; };
420200583Srdivacky  template <>
421200583Srdivacky  struct isPodLike<clang::FileID> { static const bool value = true; };
422198092Srdivacky
423218893Sdim  // Teach SmallPtrSet how to handle SourceLocation.
424218893Sdim  template<>
425218893Sdim  class PointerLikeTypeTraits<clang::SourceLocation> {
426218893Sdim  public:
427218893Sdim    static inline void *getAsVoidPointer(clang::SourceLocation L) {
428218893Sdim      return L.getPtrEncoding();
429218893Sdim    }
430218893Sdim    static inline clang::SourceLocation getFromVoidPointer(void *P) {
431218893Sdim      return clang::SourceLocation::getFromRawEncoding((unsigned)(uintptr_t)P);
432218893Sdim    }
433218893Sdim    enum { NumLowBitsAvailable = 0 };
434218893Sdim  };
435218893Sdim
436193326Sed}  // end namespace llvm
437193326Sed
438193326Sed#endif
439