Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1 | //===--- SourceManager.h - Track and cache source files ---------*- C++ -*-===// |
| 2 | // |
| 3 | // The LLVM Compiler Infrastructure |
| 4 | // |
Chris Lattner | 0bc735f | 2007-12-29 19:59:25 +0000 | [diff] [blame] | 5 | // This file is distributed under the University of Illinois Open Source |
| 6 | // License. See LICENSE.TXT for details. |
Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
| 9 | // |
| 10 | // This file defines the SourceManager interface. |
| 11 | // |
| 12 | //===----------------------------------------------------------------------===// |
| 13 | |
| 14 | #ifndef LLVM_CLANG_SOURCEMANAGER_H |
| 15 | #define LLVM_CLANG_SOURCEMANAGER_H |
| 16 | |
| 17 | #include "clang/Basic/SourceLocation.h" |
Chris Lattner | 0d0bf8c | 2009-02-03 07:30:45 +0000 | [diff] [blame] | 18 | #include "llvm/Support/Allocator.h" |
Chris Lattner | 464c4b3 | 2009-01-26 18:21:04 +0000 | [diff] [blame] | 19 | #include "llvm/Support/DataTypes.h" |
Chris Lattner | 0d0bf8c | 2009-02-03 07:30:45 +0000 | [diff] [blame] | 20 | #include "llvm/ADT/DenseMap.h" |
Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 21 | #include <vector> |
Chris Lattner | 9dc62f0 | 2007-07-12 15:32:57 +0000 | [diff] [blame] | 22 | #include <cassert> |
Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 23 | |
| 24 | namespace llvm { |
| 25 | class MemoryBuffer; |
| 26 | } |
| 27 | |
| 28 | namespace clang { |
| 29 | |
| 30 | class SourceManager; |
Ted Kremenek | 099b474 | 2007-12-05 00:14:18 +0000 | [diff] [blame] | 31 | class FileManager; |
Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 32 | class FileEntry; |
| 33 | class IdentifierTokenInfo; |
Chris Lattner | 5b9a504 | 2009-01-26 07:57:50 +0000 | [diff] [blame] | 34 | class LineTableInfo; |
Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 35 | |
Chris Lattner | 0b9e736 | 2008-09-26 21:18:42 +0000 | [diff] [blame] | 36 | /// SrcMgr - Public enums and private classes that are part of the |
| 37 | /// SourceManager implementation. |
Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 38 | /// |
| 39 | namespace SrcMgr { |
Chris Lattner | 9d72851 | 2008-10-27 01:19:25 +0000 | [diff] [blame] | 40 | /// CharacteristicKind - This is used to represent whether a file or directory |
Chris Lattner | 0b9e736 | 2008-09-26 21:18:42 +0000 | [diff] [blame] | 41 | /// holds normal user code, system code, or system code which is implicitly |
| 42 | /// 'extern "C"' in C++ mode. Entire directories can be tagged with this |
| 43 | /// (this is maintained by DirectoryLookup and friends) as can specific |
| 44 | /// FileIDInfos when a #pragma system_header is seen or various other cases. |
| 45 | /// |
Chris Lattner | 9d72851 | 2008-10-27 01:19:25 +0000 | [diff] [blame] | 46 | enum CharacteristicKind { |
Chris Lattner | 0b9e736 | 2008-09-26 21:18:42 +0000 | [diff] [blame] | 47 | C_User, C_System, C_ExternCSystem |
| 48 | }; |
| 49 | |
Ted Kremenek | 78d85f5 | 2007-10-30 21:08:08 +0000 | [diff] [blame] | 50 | /// ContentCache - Once instance of this struct is kept for every file |
Chris Lattner | 06a062d | 2009-01-19 08:02:45 +0000 | [diff] [blame] | 51 | /// loaded or used. This object owns the MemoryBuffer object. |
Ted Kremenek | c16c208 | 2009-01-06 01:55:26 +0000 | [diff] [blame] | 52 | class ContentCache { |
| 53 | /// Buffer - The actual buffer containing the characters from the input |
| 54 | /// file. This is owned by the ContentCache object. |
Chris Lattner | 0581659 | 2009-01-17 03:54:16 +0000 | [diff] [blame] | 55 | mutable const llvm::MemoryBuffer *Buffer; |
Ted Kremenek | c16c208 | 2009-01-06 01:55:26 +0000 | [diff] [blame] | 56 | |
| 57 | public: |
Ted Kremenek | 78d85f5 | 2007-10-30 21:08:08 +0000 | [diff] [blame] | 58 | /// Reference to the file entry. This reference does not own |
| 59 | /// the FileEntry object. It is possible for this to be NULL if |
| 60 | /// the ContentCache encapsulates an imaginary text buffer. |
Chris Lattner | 0581659 | 2009-01-17 03:54:16 +0000 | [diff] [blame] | 61 | const FileEntry *Entry; |
Ted Kremenek | 78d85f5 | 2007-10-30 21:08:08 +0000 | [diff] [blame] | 62 | |
Chris Lattner | 0d0bf8c | 2009-02-03 07:30:45 +0000 | [diff] [blame] | 63 | /// SourceLineCache - A bump pointer allocated array of offsets for each |
| 64 | /// source line. This is lazily computed. This is owned by the |
| 65 | /// SourceManager BumpPointerAllocator object. |
Chris Lattner | 0581659 | 2009-01-17 03:54:16 +0000 | [diff] [blame] | 66 | unsigned *SourceLineCache; |
Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 67 | |
Ted Kremenek | b6427f8 | 2007-12-04 18:59:28 +0000 | [diff] [blame] | 68 | /// NumLines - The number of lines in this ContentCache. This is only valid |
| 69 | /// if SourceLineCache is non-null. |
Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 70 | unsigned NumLines; |
Ted Kremenek | c16c208 | 2009-01-06 01:55:26 +0000 | [diff] [blame] | 71 | |
| 72 | /// getBuffer - Returns the memory buffer for the associated content. |
Chris Lattner | 0581659 | 2009-01-17 03:54:16 +0000 | [diff] [blame] | 73 | const llvm::MemoryBuffer *getBuffer() const; |
Ted Kremenek | c16c208 | 2009-01-06 01:55:26 +0000 | [diff] [blame] | 74 | |
| 75 | /// getSize - Returns the size of the content encapsulated by this |
| 76 | /// ContentCache. This can be the size of the source file or the size of an |
| 77 | /// arbitrary scratch buffer. If the ContentCache encapsulates a source |
| 78 | /// file this size is retrieved from the file's FileEntry. |
| 79 | unsigned getSize() const; |
| 80 | |
| 81 | /// getSizeBytesMapped - Returns the number of bytes actually mapped for |
| 82 | /// this ContentCache. This can be 0 if the MemBuffer was not actually |
| 83 | /// instantiated. |
| 84 | unsigned getSizeBytesMapped() const; |
| 85 | |
Chris Lattner | 0581659 | 2009-01-17 03:54:16 +0000 | [diff] [blame] | 86 | void setBuffer(const llvm::MemoryBuffer *B) { |
Ted Kremenek | c16c208 | 2009-01-06 01:55:26 +0000 | [diff] [blame] | 87 | assert(!Buffer && "MemoryBuffer already set."); |
| 88 | Buffer = B; |
| 89 | } |
Ted Kremenek | 78d85f5 | 2007-10-30 21:08:08 +0000 | [diff] [blame] | 90 | |
Chris Lattner | 0d0bf8c | 2009-02-03 07:30:45 +0000 | [diff] [blame] | 91 | ContentCache(const FileEntry *Ent = 0) |
| 92 | : Buffer(0), Entry(Ent), SourceLineCache(0), NumLines(0) {} |
Ted Kremenek | 78d85f5 | 2007-10-30 21:08:08 +0000 | [diff] [blame] | 93 | |
| 94 | ~ContentCache(); |
Ted Kremenek | 0d892d8 | 2007-10-30 22:57:35 +0000 | [diff] [blame] | 95 | |
| 96 | /// The copy ctor does not allow copies where source object has either |
| 97 | /// a non-NULL Buffer or SourceLineCache. Ownership of allocated memory |
| 98 | /// is not transfered, so this is a logical error. |
Chris Lattner | 0d0bf8c | 2009-02-03 07:30:45 +0000 | [diff] [blame] | 99 | ContentCache(const ContentCache &RHS) : Buffer(0), SourceLineCache(0) { |
Ted Kremenek | 0d892d8 | 2007-10-30 22:57:35 +0000 | [diff] [blame] | 100 | Entry = RHS.Entry; |
| 101 | |
Chris Lattner | 0d0bf8c | 2009-02-03 07:30:45 +0000 | [diff] [blame] | 102 | assert (RHS.Buffer == 0 && RHS.SourceLineCache == 0 |
Ted Kremenek | 0d892d8 | 2007-10-30 22:57:35 +0000 | [diff] [blame] | 103 | && "Passed ContentCache object cannot own a buffer."); |
| 104 | |
| 105 | NumLines = RHS.NumLines; |
| 106 | } |
| 107 | |
| 108 | private: |
| 109 | // Disable assignments. |
Chris Lattner | 0581659 | 2009-01-17 03:54:16 +0000 | [diff] [blame] | 110 | ContentCache &operator=(const ContentCache& RHS); |
Ted Kremenek | 78d85f5 | 2007-10-30 21:08:08 +0000 | [diff] [blame] | 111 | }; |
Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 112 | |
Chris Lattner | de7aeef | 2009-01-26 00:43:02 +0000 | [diff] [blame] | 113 | /// FileInfo - Information about a FileID, basically just the logical file |
| 114 | /// that it represents and include stack information. |
Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 115 | /// |
Chris Lattner | de7aeef | 2009-01-26 00:43:02 +0000 | [diff] [blame] | 116 | /// Each FileInfo has include stack information, indicating where it came |
| 117 | /// from. This information encodes the #include chain that a token was |
| 118 | /// instantiated from. The main include file has an invalid IncludeLoc. |
Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 119 | /// |
Chris Lattner | de7aeef | 2009-01-26 00:43:02 +0000 | [diff] [blame] | 120 | /// FileInfos contain a "ContentCache *", with the contents of the file. |
Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 121 | /// |
Chris Lattner | de7aeef | 2009-01-26 00:43:02 +0000 | [diff] [blame] | 122 | class FileInfo { |
Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 123 | /// IncludeLoc - The location of the #include that brought in this file. |
Chris Lattner | de7aeef | 2009-01-26 00:43:02 +0000 | [diff] [blame] | 124 | /// This is an invalid SLOC for the main file (top of the #include chain). |
| 125 | unsigned IncludeLoc; // Really a SourceLocation |
Chris Lattner | 9dc1f53 | 2007-07-20 16:37:10 +0000 | [diff] [blame] | 126 | |
Chris Lattner | 6e1aff2 | 2009-01-26 06:49:09 +0000 | [diff] [blame] | 127 | /// Data - This contains the ContentCache* and the bits indicating the |
| 128 | /// characteristic of the file and whether it has #line info, all bitmangled |
| 129 | /// together. |
| 130 | uintptr_t Data; |
Ted Kremenek | 78d85f5 | 2007-10-30 21:08:08 +0000 | [diff] [blame] | 131 | public: |
Chris Lattner | de7aeef | 2009-01-26 00:43:02 +0000 | [diff] [blame] | 132 | /// get - Return a FileInfo object. |
| 133 | static FileInfo get(SourceLocation IL, const ContentCache *Con, |
| 134 | CharacteristicKind FileCharacter) { |
| 135 | FileInfo X; |
| 136 | X.IncludeLoc = IL.getRawEncoding(); |
Chris Lattner | 6e1aff2 | 2009-01-26 06:49:09 +0000 | [diff] [blame] | 137 | X.Data = (uintptr_t)Con; |
Chris Lattner | 00282d6 | 2009-02-03 07:41:46 +0000 | [diff] [blame] | 138 | assert((X.Data & 7) == 0 &&"ContentCache pointer insufficiently aligned"); |
Chris Lattner | 6e1aff2 | 2009-01-26 06:49:09 +0000 | [diff] [blame] | 139 | assert((unsigned)FileCharacter < 4 && "invalid file character"); |
| 140 | X.Data |= (unsigned)FileCharacter; |
Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 141 | return X; |
| 142 | } |
| 143 | |
Chris Lattner | de7aeef | 2009-01-26 00:43:02 +0000 | [diff] [blame] | 144 | SourceLocation getIncludeLoc() const { |
| 145 | return SourceLocation::getFromRawEncoding(IncludeLoc); |
| 146 | } |
Chris Lattner | 6e1aff2 | 2009-01-26 06:49:09 +0000 | [diff] [blame] | 147 | const ContentCache* getContentCache() const { |
Chris Lattner | 00282d6 | 2009-02-03 07:41:46 +0000 | [diff] [blame] | 148 | return reinterpret_cast<const ContentCache*>(Data & ~7UL); |
Chris Lattner | 6e1aff2 | 2009-01-26 06:49:09 +0000 | [diff] [blame] | 149 | } |
Chris Lattner | de7aeef | 2009-01-26 00:43:02 +0000 | [diff] [blame] | 150 | |
Chris Lattner | 0b9e736 | 2008-09-26 21:18:42 +0000 | [diff] [blame] | 151 | /// getCharacteristic - Return whether this is a system header or not. |
Chris Lattner | 9d72851 | 2008-10-27 01:19:25 +0000 | [diff] [blame] | 152 | CharacteristicKind getFileCharacteristic() const { |
Chris Lattner | 6e1aff2 | 2009-01-26 06:49:09 +0000 | [diff] [blame] | 153 | return (CharacteristicKind)(Data & 3); |
Chris Lattner | 0b9e736 | 2008-09-26 21:18:42 +0000 | [diff] [blame] | 154 | } |
Chris Lattner | ac50e34 | 2009-02-03 22:13:05 +0000 | [diff] [blame] | 155 | |
| 156 | /// hasLineDirectives - Return true if this FileID has #line directives in |
| 157 | /// it. |
| 158 | bool hasLineDirectives() const { return (Data & 4) != 0; } |
| 159 | |
| 160 | /// setHasLineDirectives - Set the flag that indicates that this FileID has |
| 161 | /// line table entries associated with it. |
| 162 | void setHasLineDirectives() { |
| 163 | Data |= 4; |
| 164 | } |
Chris Lattner | 9dc1f53 | 2007-07-20 16:37:10 +0000 | [diff] [blame] | 165 | }; |
| 166 | |
Chris Lattner | de7aeef | 2009-01-26 00:43:02 +0000 | [diff] [blame] | 167 | /// InstantiationInfo - Each InstantiationInfo encodes the Instantiation |
| 168 | /// location - where the token was ultimately instantiated, and the |
| 169 | /// SpellingLoc - where the actual character data for the token came from. |
| 170 | class InstantiationInfo { |
Chris Lattner | e7fb484 | 2009-02-15 20:52:18 +0000 | [diff] [blame] | 171 | // Really these are all SourceLocations. |
| 172 | |
| 173 | /// SpellingLoc - Where the spelling for the token can be found. |
| 174 | unsigned SpellingLoc; |
| 175 | |
| 176 | /// InstantiationLocStart/InstantiationLocEnd - In a macro expansion, these |
Douglas Gregor | 14f7900 | 2009-04-10 03:52:48 +0000 | [diff] [blame] | 177 | /// indicate the start and end of the instantiation. In object-like macros, |
Chris Lattner | e7fb484 | 2009-02-15 20:52:18 +0000 | [diff] [blame] | 178 | /// these will be the same. In a function-like macro instantiation, the |
| 179 | /// start will be the identifier and the end will be the ')'. |
| 180 | unsigned InstantiationLocStart, InstantiationLocEnd; |
Chris Lattner | 9dc1f53 | 2007-07-20 16:37:10 +0000 | [diff] [blame] | 181 | public: |
Chris Lattner | de7aeef | 2009-01-26 00:43:02 +0000 | [diff] [blame] | 182 | SourceLocation getSpellingLoc() const { |
| 183 | return SourceLocation::getFromRawEncoding(SpellingLoc); |
| 184 | } |
Chris Lattner | e7fb484 | 2009-02-15 20:52:18 +0000 | [diff] [blame] | 185 | SourceLocation getInstantiationLocStart() const { |
| 186 | return SourceLocation::getFromRawEncoding(InstantiationLocStart); |
| 187 | } |
| 188 | SourceLocation getInstantiationLocEnd() const { |
| 189 | return SourceLocation::getFromRawEncoding(InstantiationLocEnd); |
| 190 | } |
Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 191 | |
Chris Lattner | e7fb484 | 2009-02-15 20:52:18 +0000 | [diff] [blame] | 192 | std::pair<SourceLocation,SourceLocation> getInstantiationLocRange() const { |
| 193 | return std::make_pair(getInstantiationLocStart(), |
| 194 | getInstantiationLocEnd()); |
| 195 | } |
| 196 | |
| 197 | /// get - Return a InstantiationInfo for an expansion. IL specifies |
Chris Lattner | df7c17a | 2009-01-16 07:00:02 +0000 | [diff] [blame] | 198 | /// the instantiation location (where the macro is expanded), and SL |
| 199 | /// specifies the spelling location (where the characters from the token |
Chris Lattner | e7fb484 | 2009-02-15 20:52:18 +0000 | [diff] [blame] | 200 | /// come from). IL and PL can both refer to normal File SLocs or |
| 201 | /// instantiation locations. |
| 202 | static InstantiationInfo get(SourceLocation ILStart, SourceLocation ILEnd, |
| 203 | SourceLocation SL) { |
Chris Lattner | de7aeef | 2009-01-26 00:43:02 +0000 | [diff] [blame] | 204 | InstantiationInfo X; |
Chris Lattner | de7aeef | 2009-01-26 00:43:02 +0000 | [diff] [blame] | 205 | X.SpellingLoc = SL.getRawEncoding(); |
Chris Lattner | e7fb484 | 2009-02-15 20:52:18 +0000 | [diff] [blame] | 206 | X.InstantiationLocStart = ILStart.getRawEncoding(); |
| 207 | X.InstantiationLocEnd = ILEnd.getRawEncoding(); |
Chris Lattner | 9dc1f53 | 2007-07-20 16:37:10 +0000 | [diff] [blame] | 208 | return X; |
Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 209 | } |
| 210 | }; |
Chris Lattner | de7aeef | 2009-01-26 00:43:02 +0000 | [diff] [blame] | 211 | |
| 212 | /// SLocEntry - This is a discriminated union of FileInfo and |
| 213 | /// InstantiationInfo. SourceManager keeps an array of these objects, and |
| 214 | /// they are uniquely identified by the FileID datatype. |
| 215 | class SLocEntry { |
| 216 | unsigned Offset; // low bit is set for instantiation info. |
| 217 | union { |
| 218 | FileInfo File; |
| 219 | InstantiationInfo Instantiation; |
| 220 | }; |
| 221 | public: |
| 222 | unsigned getOffset() const { return Offset >> 1; } |
| 223 | |
| 224 | bool isInstantiation() const { return Offset & 1; } |
| 225 | bool isFile() const { return !isInstantiation(); } |
| 226 | |
| 227 | const FileInfo &getFile() const { |
| 228 | assert(isFile() && "Not a file SLocEntry!"); |
| 229 | return File; |
| 230 | } |
| 231 | |
| 232 | const InstantiationInfo &getInstantiation() const { |
| 233 | assert(isInstantiation() && "Not an instantiation SLocEntry!"); |
| 234 | return Instantiation; |
| 235 | } |
| 236 | |
| 237 | static SLocEntry get(unsigned Offset, const FileInfo &FI) { |
| 238 | SLocEntry E; |
| 239 | E.Offset = Offset << 1; |
| 240 | E.File = FI; |
| 241 | return E; |
| 242 | } |
| 243 | |
| 244 | static SLocEntry get(unsigned Offset, const InstantiationInfo &II) { |
| 245 | SLocEntry E; |
| 246 | E.Offset = (Offset << 1) | 1; |
| 247 | E.Instantiation = II; |
| 248 | return E; |
| 249 | } |
| 250 | }; |
Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 251 | } // end SrcMgr namespace. |
Douglas Gregor | 7f94b0b | 2009-04-27 06:38:32 +0000 | [diff] [blame] | 252 | |
| 253 | /// \brief External source of source location entries. |
| 254 | class ExternalSLocEntrySource { |
| 255 | public: |
| 256 | virtual ~ExternalSLocEntrySource(); |
| 257 | |
| 258 | /// \brief Read the source location entry with index ID. |
| 259 | virtual void ReadSLocEntry(unsigned ID) = 0; |
| 260 | }; |
| 261 | |
Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 262 | /// SourceManager - This file handles loading and caching of source files into |
| 263 | /// memory. This object owns the MemoryBuffer objects for all of the loaded |
| 264 | /// files and assigns unique FileID's for each unique #include chain. |
| 265 | /// |
| 266 | /// The SourceManager can be queried for information about SourceLocation |
Chris Lattner | f7cf85b | 2009-01-16 07:36:28 +0000 | [diff] [blame] | 267 | /// objects, turning them into either spelling or instantiation locations. |
| 268 | /// Spelling locations represent where the bytes corresponding to a token came |
| 269 | /// from and instantiation locations represent where the location is in the |
| 270 | /// user's view. In the case of a macro expansion, for example, the spelling |
| 271 | /// location indicates where the expanded token came from and the instantiation |
| 272 | /// location specifies where it was expanded. |
Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 273 | class SourceManager { |
Chris Lattner | 0d0bf8c | 2009-02-03 07:30:45 +0000 | [diff] [blame] | 274 | mutable llvm::BumpPtrAllocator ContentCacheAlloc; |
| 275 | |
Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 276 | /// FileInfos - Memoized information about all of the files tracked by this |
Ted Kremenek | 0d892d8 | 2007-10-30 22:57:35 +0000 | [diff] [blame] | 277 | /// SourceManager. This set allows us to merge ContentCache entries based |
| 278 | /// on their FileEntry*. All ContentCache objects will thus have unique, |
| 279 | /// non-null, FileEntry pointers. |
Chris Lattner | 0d0bf8c | 2009-02-03 07:30:45 +0000 | [diff] [blame] | 280 | llvm::DenseMap<const FileEntry*, SrcMgr::ContentCache*> FileInfos; |
Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 281 | |
| 282 | /// MemBufferInfos - Information about various memory buffers that we have |
Chris Lattner | 0d0bf8c | 2009-02-03 07:30:45 +0000 | [diff] [blame] | 283 | /// read in. All FileEntry* within the stored ContentCache objects are NULL, |
| 284 | /// as they do not refer to a file. |
| 285 | std::vector<SrcMgr::ContentCache*> MemBufferInfos; |
Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 286 | |
Chris Lattner | de7aeef | 2009-01-26 00:43:02 +0000 | [diff] [blame] | 287 | /// SLocEntryTable - This is an array of SLocEntry's that we have created. |
| 288 | /// FileID is an index into this vector. This array is sorted by the offset. |
| 289 | std::vector<SrcMgr::SLocEntry> SLocEntryTable; |
| 290 | /// NextOffset - This is the next available offset that a new SLocEntry can |
| 291 | /// start at. It is SLocEntryTable.back().getOffset()+size of back() entry. |
| 292 | unsigned NextOffset; |
Douglas Gregor | 7f94b0b | 2009-04-27 06:38:32 +0000 | [diff] [blame] | 293 | |
| 294 | /// \brief If source location entries are being lazily loaded from |
| 295 | /// an external source, this vector indicates whether the Ith source |
| 296 | /// location entry has already been loaded from the external storage. |
| 297 | std::vector<bool> SLocEntryLoaded; |
| 298 | |
| 299 | /// \brief An external source for source location entries. |
| 300 | ExternalSLocEntrySource *ExternalSLocEntries; |
| 301 | |
Chris Lattner | de7aeef | 2009-01-26 00:43:02 +0000 | [diff] [blame] | 302 | /// LastFileIDLookup - This is a one-entry cache to speed up getFileID. |
| 303 | /// LastFileIDLookup records the last FileID looked up or created, because it |
| 304 | /// is very common to look up many tokens from the same file. |
| 305 | mutable FileID LastFileIDLookup; |
Chris Lattner | 9dc1f53 | 2007-07-20 16:37:10 +0000 | [diff] [blame] | 306 | |
Chris Lattner | 5b9a504 | 2009-01-26 07:57:50 +0000 | [diff] [blame] | 307 | /// LineTable - This holds information for #line directives. It is referenced |
| 308 | /// by indices from SLocEntryTable. |
| 309 | LineTableInfo *LineTable; |
| 310 | |
Chris Lattner | 5e36a7a | 2007-07-24 05:57:19 +0000 | [diff] [blame] | 311 | /// LastLineNo - These ivars serve as a cache used in the getLineNumber |
| 312 | /// method which is used to speedup getLineNumber calls to nearby locations. |
Chris Lattner | 2b2453a | 2009-01-17 06:22:33 +0000 | [diff] [blame] | 313 | mutable FileID LastLineNoFileIDQuery; |
Chris Lattner | f812a45 | 2008-11-18 06:51:15 +0000 | [diff] [blame] | 314 | mutable SrcMgr::ContentCache *LastLineNoContentCache; |
| 315 | mutable unsigned LastLineNoFilePos; |
| 316 | mutable unsigned LastLineNoResult; |
Ted Kremenek | 78d85f5 | 2007-10-30 21:08:08 +0000 | [diff] [blame] | 317 | |
Ted Kremenek | 76edd0e | 2007-12-19 22:29:55 +0000 | [diff] [blame] | 318 | /// MainFileID - The file ID for the main source file of the translation unit. |
Chris Lattner | 2b2453a | 2009-01-17 06:22:33 +0000 | [diff] [blame] | 319 | FileID MainFileID; |
Steve Naroff | 49c1f4a | 2008-02-02 00:10:46 +0000 | [diff] [blame] | 320 | |
Chris Lattner | de7aeef | 2009-01-26 00:43:02 +0000 | [diff] [blame] | 321 | // Statistics for -print-stats. |
| 322 | mutable unsigned NumLinearScans, NumBinaryProbes; |
| 323 | |
Steve Naroff | 49c1f4a | 2008-02-02 00:10:46 +0000 | [diff] [blame] | 324 | // SourceManager doesn't support copy construction. |
| 325 | explicit SourceManager(const SourceManager&); |
| 326 | void operator=(const SourceManager&); |
Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 327 | public: |
Douglas Gregor | 7f94b0b | 2009-04-27 06:38:32 +0000 | [diff] [blame] | 328 | SourceManager() |
| 329 | : ExternalSLocEntries(0), LineTable(0), NumLinearScans(0), |
| 330 | NumBinaryProbes(0) { |
Chris Lattner | de7aeef | 2009-01-26 00:43:02 +0000 | [diff] [blame] | 331 | clearIDTables(); |
| 332 | } |
Chris Lattner | 5b9a504 | 2009-01-26 07:57:50 +0000 | [diff] [blame] | 333 | ~SourceManager(); |
Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 334 | |
Chris Lattner | 5b9a504 | 2009-01-26 07:57:50 +0000 | [diff] [blame] | 335 | void clearIDTables(); |
| 336 | |
Chris Lattner | 06a062d | 2009-01-19 08:02:45 +0000 | [diff] [blame] | 337 | //===--------------------------------------------------------------------===// |
| 338 | // MainFileID creation and querying methods. |
| 339 | //===--------------------------------------------------------------------===// |
| 340 | |
Ted Kremenek | 76edd0e | 2007-12-19 22:29:55 +0000 | [diff] [blame] | 341 | /// getMainFileID - Returns the FileID of the main source file. |
Chris Lattner | 2b2453a | 2009-01-17 06:22:33 +0000 | [diff] [blame] | 342 | FileID getMainFileID() const { return MainFileID; } |
Ted Kremenek | 76edd0e | 2007-12-19 22:29:55 +0000 | [diff] [blame] | 343 | |
Chris Lattner | 06a062d | 2009-01-19 08:02:45 +0000 | [diff] [blame] | 344 | /// createMainFileID - Create the FileID for the main source file. |
| 345 | FileID createMainFileID(const FileEntry *SourceFile, |
| 346 | SourceLocation IncludePos) { |
| 347 | assert(MainFileID.isInvalid() && "MainFileID already set!"); |
| 348 | MainFileID = createFileID(SourceFile, IncludePos, SrcMgr::C_User); |
| 349 | return MainFileID; |
| 350 | } |
| 351 | |
| 352 | //===--------------------------------------------------------------------===// |
Chris Lattner | de7aeef | 2009-01-26 00:43:02 +0000 | [diff] [blame] | 353 | // Methods to create new FileID's and instantiations. |
Chris Lattner | 06a062d | 2009-01-19 08:02:45 +0000 | [diff] [blame] | 354 | //===--------------------------------------------------------------------===// |
| 355 | |
Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 356 | /// createFileID - Create a new FileID that represents the specified file |
| 357 | /// being #included from the specified IncludePosition. This returns 0 on |
| 358 | /// error and translates NULL into standard input. |
Douglas Gregor | 7f94b0b | 2009-04-27 06:38:32 +0000 | [diff] [blame] | 359 | /// PreallocateID should be non-zero to specify which a pre-allocated, |
| 360 | /// lazily computed source location is being filled in by this operation. |
Chris Lattner | 2b2453a | 2009-01-17 06:22:33 +0000 | [diff] [blame] | 361 | FileID createFileID(const FileEntry *SourceFile, SourceLocation IncludePos, |
Douglas Gregor | 7f94b0b | 2009-04-27 06:38:32 +0000 | [diff] [blame] | 362 | SrcMgr::CharacteristicKind FileCharacter, |
| 363 | unsigned PreallocatedID = 0, |
| 364 | unsigned Offset = 0) { |
Chris Lattner | de7aeef | 2009-01-26 00:43:02 +0000 | [diff] [blame] | 365 | const SrcMgr::ContentCache *IR = getOrCreateContentCache(SourceFile); |
Chris Lattner | 2b2453a | 2009-01-17 06:22:33 +0000 | [diff] [blame] | 366 | if (IR == 0) return FileID(); // Error opening file? |
Douglas Gregor | 7f94b0b | 2009-04-27 06:38:32 +0000 | [diff] [blame] | 367 | return createFileID(IR, IncludePos, FileCharacter, PreallocatedID, Offset); |
Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 368 | } |
| 369 | |
| 370 | /// createFileIDForMemBuffer - Create a new FileID that represents the |
| 371 | /// specified memory buffer. This does no caching of the buffer and takes |
| 372 | /// ownership of the MemoryBuffer, so only pass a MemoryBuffer to this once. |
Douglas Gregor | 7f94b0b | 2009-04-27 06:38:32 +0000 | [diff] [blame] | 373 | FileID createFileIDForMemBuffer(const llvm::MemoryBuffer *Buffer, |
| 374 | unsigned PreallocatedID = 0, |
| 375 | unsigned Offset = 0) { |
Nico Weber | 7bfaaae | 2008-08-10 19:59:06 +0000 | [diff] [blame] | 376 | return createFileID(createMemBufferContentCache(Buffer), SourceLocation(), |
Douglas Gregor | 7f94b0b | 2009-04-27 06:38:32 +0000 | [diff] [blame] | 377 | SrcMgr::C_User, PreallocatedID, Offset); |
Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 378 | } |
| 379 | |
Ted Kremenek | 1036b68 | 2007-12-19 23:48:45 +0000 | [diff] [blame] | 380 | /// createMainFileIDForMembuffer - Create the FileID for a memory buffer |
| 381 | /// that will represent the FileID for the main source. One example |
| 382 | /// of when this would be used is when the main source is read from STDIN. |
Chris Lattner | 2b2453a | 2009-01-17 06:22:33 +0000 | [diff] [blame] | 383 | FileID createMainFileIDForMemBuffer(const llvm::MemoryBuffer *Buffer) { |
| 384 | assert(MainFileID.isInvalid() && "MainFileID already set!"); |
Chris Lattner | 7697b5c | 2007-12-20 01:38:17 +0000 | [diff] [blame] | 385 | MainFileID = createFileIDForMemBuffer(Buffer); |
Ted Kremenek | 1036b68 | 2007-12-19 23:48:45 +0000 | [diff] [blame] | 386 | return MainFileID; |
| 387 | } |
Chris Lattner | 06a062d | 2009-01-19 08:02:45 +0000 | [diff] [blame] | 388 | |
Chris Lattner | de7aeef | 2009-01-26 00:43:02 +0000 | [diff] [blame] | 389 | /// createInstantiationLoc - Return a new SourceLocation that encodes the fact |
| 390 | /// that a token at Loc should actually be referenced from InstantiationLoc. |
| 391 | /// TokLength is the length of the token being instantiated. |
| 392 | SourceLocation createInstantiationLoc(SourceLocation Loc, |
Chris Lattner | e7fb484 | 2009-02-15 20:52:18 +0000 | [diff] [blame] | 393 | SourceLocation InstantiationLocStart, |
| 394 | SourceLocation InstantiationLocEnd, |
Douglas Gregor | 7f94b0b | 2009-04-27 06:38:32 +0000 | [diff] [blame] | 395 | unsigned TokLength, |
| 396 | unsigned PreallocatedID = 0, |
| 397 | unsigned Offset = 0); |
Chris Lattner | de7aeef | 2009-01-26 00:43:02 +0000 | [diff] [blame] | 398 | |
Chris Lattner | 06a062d | 2009-01-19 08:02:45 +0000 | [diff] [blame] | 399 | //===--------------------------------------------------------------------===// |
| 400 | // FileID manipulation methods. |
| 401 | //===--------------------------------------------------------------------===// |
| 402 | |
| 403 | /// getBuffer - Return the buffer for the specified FileID. |
| 404 | /// |
| 405 | const llvm::MemoryBuffer *getBuffer(FileID FID) const { |
Chris Lattner | de7aeef | 2009-01-26 00:43:02 +0000 | [diff] [blame] | 406 | return getSLocEntry(FID).getFile().getContentCache()->getBuffer(); |
Chris Lattner | 06a062d | 2009-01-19 08:02:45 +0000 | [diff] [blame] | 407 | } |
| 408 | |
| 409 | /// getFileEntryForID - Returns the FileEntry record for the provided FileID. |
| 410 | const FileEntry *getFileEntryForID(FileID FID) const { |
Chris Lattner | de7aeef | 2009-01-26 00:43:02 +0000 | [diff] [blame] | 411 | return getSLocEntry(FID).getFile().getContentCache()->Entry; |
Chris Lattner | 06a062d | 2009-01-19 08:02:45 +0000 | [diff] [blame] | 412 | } |
| 413 | |
| 414 | /// getBufferData - Return a pointer to the start and end of the source buffer |
| 415 | /// data for the specified FileID. |
| 416 | std::pair<const char*, const char*> getBufferData(FileID FID) const; |
| 417 | |
| 418 | |
| 419 | //===--------------------------------------------------------------------===// |
| 420 | // SourceLocation manipulation methods. |
| 421 | //===--------------------------------------------------------------------===// |
Ted Kremenek | 1036b68 | 2007-12-19 23:48:45 +0000 | [diff] [blame] | 422 | |
Chris Lattner | 668ab1a | 2009-03-13 01:05:57 +0000 | [diff] [blame] | 423 | /// getFileID - Return the FileID for a SourceLocation. This is a very |
Chris Lattner | de7aeef | 2009-01-26 00:43:02 +0000 | [diff] [blame] | 424 | /// hot method that is used for all SourceManager queries that start with a |
| 425 | /// SourceLocation object. It is responsible for finding the entry in |
| 426 | /// SLocEntryTable which contains the specified location. |
| 427 | /// |
| 428 | FileID getFileID(SourceLocation SpellingLoc) const { |
| 429 | unsigned SLocOffset = SpellingLoc.getOffset(); |
| 430 | |
| 431 | // If our one-entry cache covers this offset, just return it. |
| 432 | if (isOffsetInFileID(LastFileIDLookup, SLocOffset)) |
| 433 | return LastFileIDLookup; |
| 434 | |
| 435 | return getFileIDSlow(SLocOffset); |
| 436 | } |
| 437 | |
Chris Lattner | 2b2453a | 2009-01-17 06:22:33 +0000 | [diff] [blame] | 438 | /// getLocForStartOfFile - Return the source location corresponding to the |
| 439 | /// first byte of the specified file. |
| 440 | SourceLocation getLocForStartOfFile(FileID FID) const { |
Douglas Gregor | 7f94b0b | 2009-04-27 06:38:32 +0000 | [diff] [blame] | 441 | assert(FID.ID < SLocEntryTable.size() && "FileID out of range"); |
| 442 | assert(getSLocEntry(FID).isFile() && "FileID is not a file"); |
| 443 | unsigned FileOffset = getSLocEntry(FID).getOffset(); |
Chris Lattner | de7aeef | 2009-01-26 00:43:02 +0000 | [diff] [blame] | 444 | return SourceLocation::getFileLoc(FileOffset); |
Chris Lattner | 2b2453a | 2009-01-17 06:22:33 +0000 | [diff] [blame] | 445 | } |
| 446 | |
Chris Lattner | 6678133 | 2009-02-15 21:26:50 +0000 | [diff] [blame] | 447 | /// getInstantiationLoc - Given a SourceLocation object, return the |
| 448 | /// instantiation location referenced by the ID. |
Chris Lattner | de7aeef | 2009-01-26 00:43:02 +0000 | [diff] [blame] | 449 | SourceLocation getInstantiationLoc(SourceLocation Loc) const { |
Chris Lattner | addb797 | 2009-01-26 20:04:19 +0000 | [diff] [blame] | 450 | // Handle the non-mapped case inline, defer to out of line code to handle |
| 451 | // instantiations. |
Chris Lattner | de7aeef | 2009-01-26 00:43:02 +0000 | [diff] [blame] | 452 | if (Loc.isFileID()) return Loc; |
Chris Lattner | addb797 | 2009-01-26 20:04:19 +0000 | [diff] [blame] | 453 | return getInstantiationLocSlowCase(Loc); |
Chris Lattner | de7aeef | 2009-01-26 00:43:02 +0000 | [diff] [blame] | 454 | } |
| 455 | |
Chris Lattner | e7fb484 | 2009-02-15 20:52:18 +0000 | [diff] [blame] | 456 | /// getImmediateInstantiationRange - Loc is required to be an instantiation |
| 457 | /// location. Return the start/end of the instantiation information. |
| 458 | std::pair<SourceLocation,SourceLocation> |
| 459 | getImmediateInstantiationRange(SourceLocation Loc) const; |
| 460 | |
Chris Lattner | 6678133 | 2009-02-15 21:26:50 +0000 | [diff] [blame] | 461 | /// getInstantiationRange - Given a SourceLocation object, return the |
| 462 | /// range of tokens covered by the instantiation in the ultimate file. |
| 463 | std::pair<SourceLocation,SourceLocation> |
| 464 | getInstantiationRange(SourceLocation Loc) const; |
| 465 | |
| 466 | |
Chris Lattner | de7aeef | 2009-01-26 00:43:02 +0000 | [diff] [blame] | 467 | /// getSpellingLoc - Given a SourceLocation object, return the spelling |
| 468 | /// location referenced by the ID. This is the place where the characters |
| 469 | /// that make up the lexed token can be found. |
| 470 | SourceLocation getSpellingLoc(SourceLocation Loc) const { |
Chris Lattner | addb797 | 2009-01-26 20:04:19 +0000 | [diff] [blame] | 471 | // Handle the non-mapped case inline, defer to out of line code to handle |
| 472 | // instantiations. |
Chris Lattner | de7aeef | 2009-01-26 00:43:02 +0000 | [diff] [blame] | 473 | if (Loc.isFileID()) return Loc; |
Chris Lattner | addb797 | 2009-01-26 20:04:19 +0000 | [diff] [blame] | 474 | return getSpellingLocSlowCase(Loc); |
Chris Lattner | de7aeef | 2009-01-26 00:43:02 +0000 | [diff] [blame] | 475 | } |
Chris Lattner | 387616e | 2009-02-17 08:04:48 +0000 | [diff] [blame] | 476 | |
| 477 | /// getImmediateSpellingLoc - Given a SourceLocation object, return the |
| 478 | /// spelling location referenced by the ID. This is the first level down |
| 479 | /// towards the place where the characters that make up the lexed token can be |
| 480 | /// found. This should not generally be used by clients. |
| 481 | SourceLocation getImmediateSpellingLoc(SourceLocation Loc) const; |
Chris Lattner | de7aeef | 2009-01-26 00:43:02 +0000 | [diff] [blame] | 482 | |
| 483 | /// getDecomposedLoc - Decompose the specified location into a raw FileID + |
| 484 | /// Offset pair. The first element is the FileID, the second is the |
| 485 | /// offset from the start of the buffer of the location. |
| 486 | std::pair<FileID, unsigned> getDecomposedLoc(SourceLocation Loc) const { |
| 487 | FileID FID = getFileID(Loc); |
| 488 | return std::make_pair(FID, Loc.getOffset()-getSLocEntry(FID).getOffset()); |
| 489 | } |
| 490 | |
| 491 | /// getDecomposedInstantiationLoc - Decompose the specified location into a |
| 492 | /// raw FileID + Offset pair. If the location is an instantiation record, |
| 493 | /// walk through it until we find the final location instantiated. |
| 494 | std::pair<FileID, unsigned> |
| 495 | getDecomposedInstantiationLoc(SourceLocation Loc) const { |
| 496 | FileID FID = getFileID(Loc); |
| 497 | const SrcMgr::SLocEntry *E = &getSLocEntry(FID); |
| 498 | |
| 499 | unsigned Offset = Loc.getOffset()-E->getOffset(); |
| 500 | if (Loc.isFileID()) |
| 501 | return std::make_pair(FID, Offset); |
| 502 | |
| 503 | return getDecomposedInstantiationLocSlowCase(E, Offset); |
| 504 | } |
| 505 | |
| 506 | /// getDecomposedSpellingLoc - Decompose the specified location into a raw |
| 507 | /// FileID + Offset pair. If the location is an instantiation record, walk |
| 508 | /// through it until we find its spelling record. |
| 509 | std::pair<FileID, unsigned> |
| 510 | getDecomposedSpellingLoc(SourceLocation Loc) const { |
| 511 | FileID FID = getFileID(Loc); |
| 512 | const SrcMgr::SLocEntry *E = &getSLocEntry(FID); |
| 513 | |
| 514 | unsigned Offset = Loc.getOffset()-E->getOffset(); |
| 515 | if (Loc.isFileID()) |
| 516 | return std::make_pair(FID, Offset); |
| 517 | return getDecomposedSpellingLocSlowCase(E, Offset); |
| 518 | } |
| 519 | |
Chris Lattner | 52c2908 | 2009-01-27 06:27:13 +0000 | [diff] [blame] | 520 | /// getFileOffset - This method returns the offset from the start |
| 521 | /// of the file that the specified SourceLocation represents. This is not very |
| 522 | /// meaningful for a macro ID. |
| 523 | unsigned getFileOffset(SourceLocation SpellingLoc) const { |
Chris Lattner | de7aeef | 2009-01-26 00:43:02 +0000 | [diff] [blame] | 524 | return getDecomposedLoc(SpellingLoc).second; |
| 525 | } |
| 526 | |
| 527 | |
| 528 | //===--------------------------------------------------------------------===// |
| 529 | // Queries about the code at a SourceLocation. |
| 530 | //===--------------------------------------------------------------------===// |
| 531 | |
Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 532 | /// getCharacterData - Return a pointer to the start of the specified location |
Chris Lattner | de7aeef | 2009-01-26 00:43:02 +0000 | [diff] [blame] | 533 | /// in the appropriate spelling MemoryBuffer. |
Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 534 | const char *getCharacterData(SourceLocation SL) const; |
| 535 | |
Chris Lattner | 9dc1f53 | 2007-07-20 16:37:10 +0000 | [diff] [blame] | 536 | /// getColumnNumber - Return the column # for the specified file position. |
| 537 | /// This is significantly cheaper to compute than the line number. This |
| 538 | /// returns zero if the column number isn't known. This may only be called on |
Chris Lattner | f7cf85b | 2009-01-16 07:36:28 +0000 | [diff] [blame] | 539 | /// a file sloc, so you must choose a spelling or instantiation location |
| 540 | /// before calling this method. |
Chris Lattner | 7da5aea | 2009-02-04 00:55:58 +0000 | [diff] [blame] | 541 | unsigned getColumnNumber(FileID FID, unsigned FilePos) const; |
| 542 | unsigned getSpellingColumnNumber(SourceLocation Loc) const; |
| 543 | unsigned getInstantiationColumnNumber(SourceLocation Loc) const; |
Chris Lattner | 9dc1f53 | 2007-07-20 16:37:10 +0000 | [diff] [blame] | 544 | |
| 545 | |
Chris Lattner | df7c17a | 2009-01-16 07:00:02 +0000 | [diff] [blame] | 546 | /// getLineNumber - Given a SourceLocation, return the spelling line number |
Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 547 | /// for the position indicated. This requires building and caching a table of |
| 548 | /// line offsets for the MemoryBuffer, so this is not cheap: use only when |
| 549 | /// about to emit a diagnostic. |
Chris Lattner | 30fc933 | 2009-02-04 01:06:56 +0000 | [diff] [blame] | 550 | unsigned getLineNumber(FileID FID, unsigned FilePos) const; |
Chris Lattner | de7aeef | 2009-01-26 00:43:02 +0000 | [diff] [blame] | 551 | |
Chris Lattner | 30fc933 | 2009-02-04 01:06:56 +0000 | [diff] [blame] | 552 | unsigned getInstantiationLineNumber(SourceLocation Loc) const; |
| 553 | unsigned getSpellingLineNumber(SourceLocation Loc) const; |
Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 554 | |
Chris Lattner | bff5c51 | 2009-02-17 08:39:06 +0000 | [diff] [blame] | 555 | /// Return the filename or buffer identifier of the buffer the location is in. |
| 556 | /// Note that this name does not respect #line directives. Use getPresumedLoc |
| 557 | /// for normal clients. |
| 558 | const char *getBufferName(SourceLocation Loc) const; |
| 559 | |
Chris Lattner | 6b30667 | 2009-02-04 05:33:01 +0000 | [diff] [blame] | 560 | /// getFileCharacteristic - return the file characteristic of the specified |
| 561 | /// source location, indicating whether this is a normal file, a system |
| 562 | /// header, or an "implicit extern C" system header. |
| 563 | /// |
| 564 | /// This state can be modified with flags on GNU linemarker directives like: |
| 565 | /// # 4 "foo.h" 3 |
| 566 | /// which changes all source locations in the current file after that to be |
| 567 | /// considered to be from a system header. |
| 568 | SrcMgr::CharacteristicKind getFileCharacteristic(SourceLocation Loc) const; |
Chris Lattner | de7aeef | 2009-01-26 00:43:02 +0000 | [diff] [blame] | 569 | |
Chris Lattner | b9c3f96 | 2009-01-27 07:57:44 +0000 | [diff] [blame] | 570 | /// getPresumedLoc - This method returns the "presumed" location of a |
| 571 | /// SourceLocation specifies. A "presumed location" can be modified by #line |
| 572 | /// or GNU line marker directives. This provides a view on the data that a |
| 573 | /// user should see in diagnostics, for example. |
| 574 | /// |
| 575 | /// Note that a presumed location is always given as the instantiation point |
| 576 | /// of an instantiation location, not at the spelling location. |
| 577 | PresumedLoc getPresumedLoc(SourceLocation Loc) const; |
Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 578 | |
Ted Kremenek | 9fd87b1 | 2008-04-14 21:04:18 +0000 | [diff] [blame] | 579 | /// isFromSameFile - Returns true if both SourceLocations correspond to |
| 580 | /// the same file. |
| 581 | bool isFromSameFile(SourceLocation Loc1, SourceLocation Loc2) const { |
Chris Lattner | a11d617 | 2009-01-19 07:46:45 +0000 | [diff] [blame] | 582 | return getFileID(Loc1) == getFileID(Loc2); |
Ted Kremenek | 9fd87b1 | 2008-04-14 21:04:18 +0000 | [diff] [blame] | 583 | } |
| 584 | |
| 585 | /// isFromMainFile - Returns true if the file of provided SourceLocation is |
| 586 | /// the main file. |
| 587 | bool isFromMainFile(SourceLocation Loc) const { |
Chris Lattner | a11d617 | 2009-01-19 07:46:45 +0000 | [diff] [blame] | 588 | return getFileID(Loc) == getMainFileID(); |
Ted Kremenek | 9fd87b1 | 2008-04-14 21:04:18 +0000 | [diff] [blame] | 589 | } |
Chris Lattner | de7aeef | 2009-01-26 00:43:02 +0000 | [diff] [blame] | 590 | |
Nico Weber | 7bfaaae | 2008-08-10 19:59:06 +0000 | [diff] [blame] | 591 | /// isInSystemHeader - Returns if a SourceLocation is in a system header. |
| 592 | bool isInSystemHeader(SourceLocation Loc) const { |
Chris Lattner | 0b9e736 | 2008-09-26 21:18:42 +0000 | [diff] [blame] | 593 | return getFileCharacteristic(Loc) != SrcMgr::C_User; |
Nico Weber | 7bfaaae | 2008-08-10 19:59:06 +0000 | [diff] [blame] | 594 | } |
Chris Lattner | 06a062d | 2009-01-19 08:02:45 +0000 | [diff] [blame] | 595 | |
| 596 | //===--------------------------------------------------------------------===// |
Chris Lattner | 5b9a504 | 2009-01-26 07:57:50 +0000 | [diff] [blame] | 597 | // Line Table Manipulation Routines |
| 598 | //===--------------------------------------------------------------------===// |
| 599 | |
| 600 | /// getLineTableFilenameID - Return the uniqued ID for the specified filename. |
| 601 | /// |
| 602 | unsigned getLineTableFilenameID(const char *Ptr, unsigned Len); |
| 603 | |
Chris Lattner | 4c4ea17 | 2009-02-03 21:52:55 +0000 | [diff] [blame] | 604 | /// AddLineNote - Add a line note to the line table for the FileID and offset |
| 605 | /// specified by Loc. If FilenameID is -1, it is considered to be |
| 606 | /// unspecified. |
| 607 | void AddLineNote(SourceLocation Loc, unsigned LineNo, int FilenameID); |
Chris Lattner | 9d79eba | 2009-02-04 05:21:58 +0000 | [diff] [blame] | 608 | void AddLineNote(SourceLocation Loc, unsigned LineNo, int FilenameID, |
| 609 | bool IsFileEntry, bool IsFileExit, |
| 610 | bool IsSystemHeader, bool IsExternCHeader); |
Douglas Gregor | bd94500 | 2009-04-13 16:31:14 +0000 | [diff] [blame] | 611 | |
| 612 | /// \brief Determine if the source manager has a line table. |
| 613 | bool hasLineTable() const { return LineTable != 0; } |
| 614 | |
| 615 | /// \brief Retrieve the stored line table. |
| 616 | LineTableInfo &getLineTable(); |
| 617 | |
Chris Lattner | 5b9a504 | 2009-01-26 07:57:50 +0000 | [diff] [blame] | 618 | //===--------------------------------------------------------------------===// |
Chris Lattner | 06a062d | 2009-01-19 08:02:45 +0000 | [diff] [blame] | 619 | // Other miscellaneous methods. |
| 620 | //===--------------------------------------------------------------------===// |
Ted Kremenek | e55f4ee | 2008-11-19 22:41:46 +0000 | [diff] [blame] | 621 | |
Chris Lattner | c6fe32a | 2009-01-17 03:48:08 +0000 | [diff] [blame] | 622 | // Iterators over FileInfos. |
Chris Lattner | 0d0bf8c | 2009-02-03 07:30:45 +0000 | [diff] [blame] | 623 | typedef llvm::DenseMap<const FileEntry*, SrcMgr::ContentCache*> |
| 624 | ::const_iterator fileinfo_iterator; |
Chris Lattner | c6fe32a | 2009-01-17 03:48:08 +0000 | [diff] [blame] | 625 | fileinfo_iterator fileinfo_begin() const { return FileInfos.begin(); } |
| 626 | fileinfo_iterator fileinfo_end() const { return FileInfos.end(); } |
| 627 | |
Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 628 | /// PrintStats - Print statistics to stderr. |
| 629 | /// |
| 630 | void PrintStats() const; |
Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 631 | |
Douglas Gregor | 14f7900 | 2009-04-10 03:52:48 +0000 | [diff] [blame] | 632 | // Iteration over the source location entry table. |
| 633 | typedef std::vector<SrcMgr::SLocEntry>::const_iterator sloc_entry_iterator; |
| 634 | |
| 635 | sloc_entry_iterator sloc_entry_begin() const { |
| 636 | return SLocEntryTable.begin(); |
| 637 | } |
| 638 | |
| 639 | sloc_entry_iterator sloc_entry_end() const { |
| 640 | return SLocEntryTable.end(); |
| 641 | } |
| 642 | |
| 643 | unsigned sloc_entry_size() const { return SLocEntryTable.size(); } |
| 644 | |
Douglas Gregor | bd94500 | 2009-04-13 16:31:14 +0000 | [diff] [blame] | 645 | const SrcMgr::SLocEntry &getSLocEntry(FileID FID) const { |
| 646 | assert(FID.ID < SLocEntryTable.size() && "Invalid id"); |
Douglas Gregor | 7f94b0b | 2009-04-27 06:38:32 +0000 | [diff] [blame] | 647 | if (ExternalSLocEntries && |
| 648 | FID.ID < SLocEntryLoaded.size() && |
| 649 | !SLocEntryLoaded[FID.ID]) |
| 650 | ExternalSLocEntries->ReadSLocEntry(FID.ID); |
Douglas Gregor | bd94500 | 2009-04-13 16:31:14 +0000 | [diff] [blame] | 651 | return SLocEntryTable[FID.ID]; |
| 652 | } |
| 653 | |
Douglas Gregor | f60e991 | 2009-04-15 18:05:10 +0000 | [diff] [blame] | 654 | unsigned getNextOffset() const { return NextOffset; } |
| 655 | |
Douglas Gregor | 7f94b0b | 2009-04-27 06:38:32 +0000 | [diff] [blame] | 656 | /// \brief Preallocate some number of source location entries, which |
| 657 | /// will be loaded as needed from the given external source. |
| 658 | void PreallocateSLocEntries(ExternalSLocEntrySource *Source, |
| 659 | unsigned NumSLocEntries, |
| 660 | unsigned NextOffset); |
| 661 | |
Douglas Gregor | 2bf1eb0 | 2009-04-27 21:28:04 +0000 | [diff] [blame^] | 662 | /// \brief Clear out any preallocated source location entries that |
| 663 | /// haven't already been loaded. |
| 664 | void ClearPreallocatedSLocEntries(); |
| 665 | |
Ted Kremenek | 78d85f5 | 2007-10-30 21:08:08 +0000 | [diff] [blame] | 666 | private: |
Chris Lattner | de7aeef | 2009-01-26 00:43:02 +0000 | [diff] [blame] | 667 | /// isOffsetInFileID - Return true if the specified FileID contains the |
| 668 | /// specified SourceLocation offset. This is a very hot method. |
| 669 | inline bool isOffsetInFileID(FileID FID, unsigned SLocOffset) const { |
| 670 | const SrcMgr::SLocEntry &Entry = getSLocEntry(FID); |
| 671 | // If the entry is after the offset, it can't contain it. |
| 672 | if (SLocOffset < Entry.getOffset()) return false; |
| 673 | |
| 674 | // If this is the last entry than it does. Otherwise, the entry after it |
| 675 | // has to not include it. |
| 676 | if (FID.ID+1 == SLocEntryTable.size()) return true; |
Douglas Gregor | 7f94b0b | 2009-04-27 06:38:32 +0000 | [diff] [blame] | 677 | |
| 678 | return SLocOffset < getSLocEntry(FileID::get(FID.ID+1)).getOffset(); |
Chris Lattner | de7aeef | 2009-01-26 00:43:02 +0000 | [diff] [blame] | 679 | } |
| 680 | |
Ted Kremenek | 78d85f5 | 2007-10-30 21:08:08 +0000 | [diff] [blame] | 681 | /// createFileID - Create a new fileID for the specified ContentCache and |
| 682 | /// include position. This works regardless of whether the ContentCache |
| 683 | /// corresponds to a file or some other input source. |
Chris Lattner | 2b2453a | 2009-01-17 06:22:33 +0000 | [diff] [blame] | 684 | FileID createFileID(const SrcMgr::ContentCache* File, |
| 685 | SourceLocation IncludePos, |
Douglas Gregor | 7f94b0b | 2009-04-27 06:38:32 +0000 | [diff] [blame] | 686 | SrcMgr::CharacteristicKind DirCharacter, |
| 687 | unsigned PreallocatedID = 0, |
| 688 | unsigned Offset = 0); |
Ted Kremenek | 78d85f5 | 2007-10-30 21:08:08 +0000 | [diff] [blame] | 689 | |
Chris Lattner | de7aeef | 2009-01-26 00:43:02 +0000 | [diff] [blame] | 690 | const SrcMgr::ContentCache * |
| 691 | getOrCreateContentCache(const FileEntry *SourceFile); |
Ted Kremenek | c16c208 | 2009-01-06 01:55:26 +0000 | [diff] [blame] | 692 | |
Ted Kremenek | 78d85f5 | 2007-10-30 21:08:08 +0000 | [diff] [blame] | 693 | /// createMemBufferContentCache - Create a new ContentCache for the specified |
| 694 | /// memory buffer. |
| 695 | const SrcMgr::ContentCache* |
Chris Lattner | 2b2453a | 2009-01-17 06:22:33 +0000 | [diff] [blame] | 696 | createMemBufferContentCache(const llvm::MemoryBuffer *Buf); |
Chris Lattner | 9dc1f53 | 2007-07-20 16:37:10 +0000 | [diff] [blame] | 697 | |
Chris Lattner | de7aeef | 2009-01-26 00:43:02 +0000 | [diff] [blame] | 698 | FileID getFileIDSlow(unsigned SLocOffset) const; |
| 699 | |
Chris Lattner | addb797 | 2009-01-26 20:04:19 +0000 | [diff] [blame] | 700 | SourceLocation getInstantiationLocSlowCase(SourceLocation Loc) const; |
| 701 | SourceLocation getSpellingLocSlowCase(SourceLocation Loc) const; |
| 702 | |
Chris Lattner | de7aeef | 2009-01-26 00:43:02 +0000 | [diff] [blame] | 703 | std::pair<FileID, unsigned> |
| 704 | getDecomposedInstantiationLocSlowCase(const SrcMgr::SLocEntry *E, |
| 705 | unsigned Offset) const; |
| 706 | std::pair<FileID, unsigned> |
| 707 | getDecomposedSpellingLocSlowCase(const SrcMgr::SLocEntry *E, |
| 708 | unsigned Offset) const; |
Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 709 | }; |
| 710 | |
| 711 | |
| 712 | } // end namespace clang |
| 713 | |
| 714 | #endif |