]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/clang/include/clang/Basic/SourceLocation.h
Import libxo-0.9.0:
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / clang / include / clang / Basic / SourceLocation.h
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