Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1 | //===--- SourceLocation.h - Compact identifier for Source Files -*- C++ -*-===// |
| 2 | // |
| 3 | // The LLVM Compiler Infrastructure |
| 4 | // |
| 5 | // This file was developed by Chris Lattner and is distributed under |
| 6 | // the University of Illinois Open Source License. See LICENSE.TXT for details. |
| 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
| 9 | // |
| 10 | // This file defines the SourceLocation class. |
| 11 | // |
| 12 | //===----------------------------------------------------------------------===// |
| 13 | |
| 14 | #ifndef LLVM_CLANG_SOURCELOCATION_H |
| 15 | #define LLVM_CLANG_SOURCELOCATION_H |
| 16 | |
Chris Lattner | 9dc1f53 | 2007-07-20 16:37:10 +0000 | [diff] [blame^] | 17 | #include <cassert> |
| 18 | |
Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 19 | namespace clang { |
| 20 | |
| 21 | /// SourceLocation - This is a carefully crafted 32-bit identifier that encodes |
| 22 | /// a full include stack, line and column number information for a position in |
| 23 | /// an input translation unit. |
| 24 | class SourceLocation { |
| 25 | unsigned ID; |
| 26 | public: |
| 27 | enum { |
| 28 | FileIDBits = 14, |
Chris Lattner | 9dc1f53 | 2007-07-20 16:37:10 +0000 | [diff] [blame^] | 29 | FilePosBits = 32-1-FileIDBits, |
| 30 | |
| 31 | MacroIDBits = 23, |
| 32 | MacroPhysOffsBits = 5, |
| 33 | MacroLogOffBits = 3 |
Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 34 | }; |
| 35 | |
| 36 | SourceLocation() : ID(0) {} // 0 is an invalid FileID. |
| 37 | |
Chris Lattner | 9dc1f53 | 2007-07-20 16:37:10 +0000 | [diff] [blame^] | 38 | bool isFileID() const { return (ID >> 31) == 0; } |
| 39 | bool isMacroID() const { return (ID >> 31) != 0; } |
| 40 | |
| 41 | static SourceLocation getFileLoc(unsigned FileID, unsigned FilePos) { |
| 42 | SourceLocation L; |
Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 43 | // If a FilePos is larger than (1<<FilePosBits), the SourceManager makes |
| 44 | // enough consequtive FileIDs that we have one for each chunk. |
| 45 | if (FilePos >= (1 << FilePosBits)) { |
| 46 | FileID += FilePos >> FilePosBits; |
| 47 | FilePos &= (1 << FilePosBits)-1; |
| 48 | } |
| 49 | |
| 50 | // FIXME: Find a way to handle out of FileID bits! Maybe MaxFileID is an |
| 51 | // escape of some sort? |
| 52 | if (FileID >= (1 << FileIDBits)) |
| 53 | FileID = (1 << FileIDBits)-1; |
| 54 | |
Chris Lattner | 9dc1f53 | 2007-07-20 16:37:10 +0000 | [diff] [blame^] | 55 | L.ID = (FileID << FilePosBits) | FilePos; |
| 56 | return L; |
Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 57 | } |
| 58 | |
Chris Lattner | 9dc1f53 | 2007-07-20 16:37:10 +0000 | [diff] [blame^] | 59 | static SourceLocation getMacroLoc(unsigned MacroID, unsigned PhysOffs, |
| 60 | unsigned LogOffs) { |
| 61 | SourceLocation L; |
| 62 | |
| 63 | assert(MacroID < (1 << MacroIDBits) && "Too many macros!"); |
| 64 | assert(PhysOffs < (1 << MacroPhysOffsBits) && "Physoffs too large!"); |
| 65 | assert(LogOffs < (1 << MacroLogOffBits) && "Logical offs too large!"); |
| 66 | |
| 67 | L.ID = (1 << 31) | (MacroID << (MacroPhysOffsBits+MacroLogOffBits)) | |
| 68 | (PhysOffs << MacroLogOffBits) | LogOffs; |
| 69 | return L; |
| 70 | } |
| 71 | |
| 72 | |
Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 73 | /// isValid - Return true if this is a valid SourceLocation object. Invalid |
| 74 | /// SourceLocations are often used when events have no corresponding location |
| 75 | /// in the source (e.g. a diagnostic is required for a command line option). |
| 76 | /// |
| 77 | bool isValid() const { return ID != 0; } |
Chris Lattner | 9dc1f53 | 2007-07-20 16:37:10 +0000 | [diff] [blame^] | 78 | bool isInvalid() const { return ID == 0; } |
Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 79 | |
| 80 | /// getFileID - Return the file identifier for this SourceLocation. This |
| 81 | /// FileID can be used with the SourceManager object to obtain an entire |
| 82 | /// include stack for a file position reference. |
Chris Lattner | 9dc1f53 | 2007-07-20 16:37:10 +0000 | [diff] [blame^] | 83 | unsigned getFileID() const { |
| 84 | assert(isFileID() && "can't get the file id of a non-file sloc!"); |
| 85 | return ID >> FilePosBits; |
| 86 | } |
Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 87 | |
| 88 | /// getRawFilePos - Return the byte offset from the start of the file-chunk |
| 89 | /// referred to by FileID. This method should not be used to get the offset |
| 90 | /// from the start of the file, instead you should use |
| 91 | /// SourceManager::getFilePos. This method will be incorrect for large files. |
Chris Lattner | 9dc1f53 | 2007-07-20 16:37:10 +0000 | [diff] [blame^] | 92 | unsigned getRawFilePos() const { |
| 93 | assert(isFileID() && "can't get the file id of a non-file sloc!"); |
| 94 | return ID & ((1 << FilePosBits)-1); |
| 95 | } |
| 96 | |
| 97 | unsigned getMacroID() const { |
| 98 | assert(isMacroID() && "Is not a macro id!"); |
| 99 | return (ID >> (MacroPhysOffsBits+MacroLogOffBits)) & ((1 << MacroIDBits)-1); |
| 100 | } |
Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 101 | |
Chris Lattner | 9dc1f53 | 2007-07-20 16:37:10 +0000 | [diff] [blame^] | 102 | unsigned getMacroPhysOffs() const { |
| 103 | assert(isMacroID() && "Is not a macro id!"); |
| 104 | return (ID >> MacroLogOffBits) & ((1 << MacroPhysOffsBits)-1); |
| 105 | } |
| 106 | |
| 107 | unsigned getMacroLogOffs() const { |
| 108 | assert(isMacroID() && "Is not a macro id!"); |
| 109 | return ID & ((1 << MacroPhysOffsBits)-1); |
| 110 | } |
| 111 | |
| 112 | /// getFileLocWithOffset - Return a source location with the specified offset |
| 113 | /// from this file SourceLocation. |
| 114 | SourceLocation getFileLocWithOffset(unsigned Offset) const { |
| 115 | return getFileLoc(getFileID(), getRawFilePos()+Offset); |
| 116 | } |
Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 117 | |
| 118 | /// getRawEncoding - When a SourceLocation itself cannot be used, this returns |
| 119 | /// an (opaque) 32-bit integer encoding for it. This should only be passed |
| 120 | /// to SourceLocation::getFromRawEncoding, it should not be inspected |
| 121 | /// directly. |
| 122 | unsigned getRawEncoding() const { return ID; } |
| 123 | |
| 124 | /// getFromRawEncoding - Turn a raw encoding of a SourceLocation object into |
| 125 | /// a real SourceLocation. |
| 126 | static SourceLocation getFromRawEncoding(unsigned Encoding) { |
| 127 | SourceLocation X; |
| 128 | X.ID = Encoding; |
| 129 | return X; |
| 130 | } |
| 131 | }; |
| 132 | |
| 133 | inline bool operator==(const SourceLocation &LHS, const SourceLocation &RHS) { |
| 134 | return LHS.getRawEncoding() == RHS.getRawEncoding(); |
| 135 | } |
| 136 | |
| 137 | inline bool operator!=(const SourceLocation &LHS, const SourceLocation &RHS) { |
| 138 | return !(LHS == RHS); |
| 139 | } |
| 140 | |
| 141 | /// SourceRange - a trival tuple used to represent a source range. |
| 142 | class SourceRange { |
| 143 | SourceLocation B; |
| 144 | SourceLocation E; |
| 145 | public: |
| 146 | SourceRange(): B(SourceLocation()), E(SourceLocation()) {} |
| 147 | SourceRange(SourceLocation loc) : B(loc), E(loc) {} |
| 148 | SourceRange(SourceLocation begin, SourceLocation end) : B(begin), E(end) {} |
| 149 | |
| 150 | SourceLocation Begin() const { return B; } |
| 151 | SourceLocation End() const { return E; } |
| 152 | |
| 153 | bool isValid() const { return B.isValid() && E.isValid(); } |
| 154 | }; |
| 155 | |
| 156 | } // end namespace clang |
| 157 | |
| 158 | #endif |