Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
14 | pmbaty | 1 | //===- SourceManager.h - Track and cache source files -----------*- C++ -*-===// |
2 | // |
||
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
||
4 | // See https://llvm.org/LICENSE.txt for license information. |
||
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
||
6 | // |
||
7 | //===----------------------------------------------------------------------===// |
||
8 | // |
||
9 | /// \file |
||
10 | /// Defines the SourceManager interface. |
||
11 | /// |
||
12 | /// There are three different types of locations in a %file: a spelling |
||
13 | /// location, an expansion location, and a presumed location. |
||
14 | /// |
||
15 | /// Given an example of: |
||
16 | /// \code |
||
17 | /// #define min(x, y) x < y ? x : y |
||
18 | /// \endcode |
||
19 | /// |
||
20 | /// and then later on a use of min: |
||
21 | /// \code |
||
22 | /// #line 17 |
||
23 | /// return min(a, b); |
||
24 | /// \endcode |
||
25 | /// |
||
26 | /// The expansion location is the line in the source code where the macro |
||
27 | /// was expanded (the return statement), the spelling location is the |
||
28 | /// location in the source where the macro was originally defined, |
||
29 | /// and the presumed location is where the line directive states that |
||
30 | /// the line is 17, or any other line. |
||
31 | // |
||
32 | //===----------------------------------------------------------------------===// |
||
33 | |||
34 | #ifndef LLVM_CLANG_BASIC_SOURCEMANAGER_H |
||
35 | #define LLVM_CLANG_BASIC_SOURCEMANAGER_H |
||
36 | |||
37 | #include "clang/Basic/Diagnostic.h" |
||
38 | #include "clang/Basic/FileEntry.h" |
||
39 | #include "clang/Basic/FileManager.h" |
||
40 | #include "clang/Basic/SourceLocation.h" |
||
41 | #include "llvm/ADT/ArrayRef.h" |
||
42 | #include "llvm/ADT/BitVector.h" |
||
43 | #include "llvm/ADT/DenseMap.h" |
||
44 | #include "llvm/ADT/DenseSet.h" |
||
45 | #include "llvm/ADT/IntrusiveRefCntPtr.h" |
||
46 | #include "llvm/ADT/PointerIntPair.h" |
||
47 | #include "llvm/ADT/SmallVector.h" |
||
48 | #include "llvm/ADT/StringRef.h" |
||
49 | #include "llvm/Support/Allocator.h" |
||
50 | #include "llvm/Support/Compiler.h" |
||
51 | #include "llvm/Support/MemoryBuffer.h" |
||
52 | #include <cassert> |
||
53 | #include <cstddef> |
||
54 | #include <map> |
||
55 | #include <memory> |
||
56 | #include <optional> |
||
57 | #include <string> |
||
58 | #include <utility> |
||
59 | #include <vector> |
||
60 | |||
61 | namespace clang { |
||
62 | |||
63 | class ASTReader; |
||
64 | class ASTWriter; |
||
65 | class FileManager; |
||
66 | class LineTableInfo; |
||
67 | class SourceManager; |
||
68 | |||
69 | /// Public enums and private classes that are part of the |
||
70 | /// SourceManager implementation. |
||
71 | namespace SrcMgr { |
||
72 | |||
73 | /// Indicates whether a file or directory holds normal user code, |
||
74 | /// system code, or system code which is implicitly 'extern "C"' in C++ mode. |
||
75 | /// |
||
76 | /// Entire directories can be tagged with this (this is maintained by |
||
77 | /// DirectoryLookup and friends) as can specific FileInfos when a \#pragma |
||
78 | /// system_header is seen or in various other cases. |
||
79 | /// |
||
80 | enum CharacteristicKind { |
||
81 | C_User, |
||
82 | C_System, |
||
83 | C_ExternCSystem, |
||
84 | C_User_ModuleMap, |
||
85 | C_System_ModuleMap |
||
86 | }; |
||
87 | |||
88 | /// Determine whether a file / directory characteristic is for system code. |
||
89 | inline bool isSystem(CharacteristicKind CK) { |
||
90 | return CK != C_User && CK != C_User_ModuleMap; |
||
91 | } |
||
92 | |||
93 | /// Determine whether a file characteristic is for a module map. |
||
94 | inline bool isModuleMap(CharacteristicKind CK) { |
||
95 | return CK == C_User_ModuleMap || CK == C_System_ModuleMap; |
||
96 | } |
||
97 | |||
98 | /// Mapping of line offsets into a source file. This does not own the storage |
||
99 | /// for the line numbers. |
||
100 | class LineOffsetMapping { |
||
101 | public: |
||
102 | explicit operator bool() const { return Storage; } |
||
103 | unsigned size() const { |
||
104 | assert(Storage); |
||
105 | return Storage[0]; |
||
106 | } |
||
107 | ArrayRef<unsigned> getLines() const { |
||
108 | assert(Storage); |
||
109 | return ArrayRef<unsigned>(Storage + 1, Storage + 1 + size()); |
||
110 | } |
||
111 | const unsigned *begin() const { return getLines().begin(); } |
||
112 | const unsigned *end() const { return getLines().end(); } |
||
113 | const unsigned &operator[](int I) const { return getLines()[I]; } |
||
114 | |||
115 | static LineOffsetMapping get(llvm::MemoryBufferRef Buffer, |
||
116 | llvm::BumpPtrAllocator &Alloc); |
||
117 | |||
118 | LineOffsetMapping() = default; |
||
119 | LineOffsetMapping(ArrayRef<unsigned> LineOffsets, |
||
120 | llvm::BumpPtrAllocator &Alloc); |
||
121 | |||
122 | private: |
||
123 | /// First element is the size, followed by elements at off-by-one indexes. |
||
124 | unsigned *Storage = nullptr; |
||
125 | }; |
||
126 | |||
127 | /// One instance of this struct is kept for every file loaded or used. |
||
128 | /// |
||
129 | /// This object owns the MemoryBuffer object. |
||
130 | class alignas(8) ContentCache { |
||
131 | /// The actual buffer containing the characters from the input |
||
132 | /// file. |
||
133 | mutable std::unique_ptr<llvm::MemoryBuffer> Buffer; |
||
134 | |||
135 | public: |
||
136 | /// Reference to the file entry representing this ContentCache. |
||
137 | /// |
||
138 | /// This reference does not own the FileEntry object. |
||
139 | /// |
||
140 | /// It is possible for this to be NULL if the ContentCache encapsulates |
||
141 | /// an imaginary text buffer. |
||
142 | /// |
||
143 | /// FIXME: Make non-optional using a virtual file as needed, remove \c |
||
144 | /// Filename and use \c OrigEntry.getNameAsRequested() instead. |
||
145 | OptionalFileEntryRefDegradesToFileEntryPtr OrigEntry; |
||
146 | |||
147 | /// References the file which the contents were actually loaded from. |
||
148 | /// |
||
149 | /// Can be different from 'Entry' if we overridden the contents of one file |
||
150 | /// with the contents of another file. |
||
151 | const FileEntry *ContentsEntry; |
||
152 | |||
153 | /// The filename that is used to access OrigEntry. |
||
154 | /// |
||
155 | /// FIXME: Remove this once OrigEntry is a FileEntryRef with a stable name. |
||
156 | StringRef Filename; |
||
157 | |||
158 | /// A bump pointer allocated array of offsets for each source line. |
||
159 | /// |
||
160 | /// This is lazily computed. The lines are owned by the SourceManager |
||
161 | /// BumpPointerAllocator object. |
||
162 | mutable LineOffsetMapping SourceLineCache; |
||
163 | |||
164 | /// Indicates whether the buffer itself was provided to override |
||
165 | /// the actual file contents. |
||
166 | /// |
||
167 | /// When true, the original entry may be a virtual file that does not |
||
168 | /// exist. |
||
169 | unsigned BufferOverridden : 1; |
||
170 | |||
171 | /// True if this content cache was initially created for a source file |
||
172 | /// considered to be volatile (likely to change between stat and open). |
||
173 | unsigned IsFileVolatile : 1; |
||
174 | |||
175 | /// True if this file may be transient, that is, if it might not |
||
176 | /// exist at some later point in time when this content entry is used, |
||
177 | /// after serialization and deserialization. |
||
178 | unsigned IsTransient : 1; |
||
179 | |||
180 | mutable unsigned IsBufferInvalid : 1; |
||
181 | |||
182 | ContentCache() |
||
183 | : OrigEntry(std::nullopt), ContentsEntry(nullptr), |
||
184 | BufferOverridden(false), IsFileVolatile(false), IsTransient(false), |
||
185 | IsBufferInvalid(false) {} |
||
186 | |||
187 | ContentCache(FileEntryRef Ent) : ContentCache(Ent, Ent) {} |
||
188 | |||
189 | ContentCache(FileEntryRef Ent, const FileEntry *contentEnt) |
||
190 | : OrigEntry(Ent), ContentsEntry(contentEnt), BufferOverridden(false), |
||
191 | IsFileVolatile(false), IsTransient(false), IsBufferInvalid(false) {} |
||
192 | |||
193 | /// The copy ctor does not allow copies where source object has either |
||
194 | /// a non-NULL Buffer or SourceLineCache. Ownership of allocated memory |
||
195 | /// is not transferred, so this is a logical error. |
||
196 | ContentCache(const ContentCache &RHS) |
||
197 | : BufferOverridden(false), IsFileVolatile(false), IsTransient(false), |
||
198 | IsBufferInvalid(false) { |
||
199 | OrigEntry = RHS.OrigEntry; |
||
200 | ContentsEntry = RHS.ContentsEntry; |
||
201 | |||
202 | assert(!RHS.Buffer && !RHS.SourceLineCache && |
||
203 | "Passed ContentCache object cannot own a buffer."); |
||
204 | } |
||
205 | |||
206 | ContentCache &operator=(const ContentCache &RHS) = delete; |
||
207 | |||
208 | /// Returns the memory buffer for the associated content. |
||
209 | /// |
||
210 | /// \param Diag Object through which diagnostics will be emitted if the |
||
211 | /// buffer cannot be retrieved. |
||
212 | /// |
||
213 | /// \param Loc If specified, is the location that invalid file diagnostics |
||
214 | /// will be emitted at. |
||
215 | std::optional<llvm::MemoryBufferRef> |
||
216 | getBufferOrNone(DiagnosticsEngine &Diag, FileManager &FM, |
||
217 | SourceLocation Loc = SourceLocation()) const; |
||
218 | |||
219 | /// Returns the size of the content encapsulated by this |
||
220 | /// ContentCache. |
||
221 | /// |
||
222 | /// This can be the size of the source file or the size of an |
||
223 | /// arbitrary scratch buffer. If the ContentCache encapsulates a source |
||
224 | /// file this size is retrieved from the file's FileEntry. |
||
225 | unsigned getSize() const; |
||
226 | |||
227 | /// Returns the number of bytes actually mapped for this |
||
228 | /// ContentCache. |
||
229 | /// |
||
230 | /// This can be 0 if the MemBuffer was not actually expanded. |
||
231 | unsigned getSizeBytesMapped() const; |
||
232 | |||
233 | /// Returns the kind of memory used to back the memory buffer for |
||
234 | /// this content cache. This is used for performance analysis. |
||
235 | llvm::MemoryBuffer::BufferKind getMemoryBufferKind() const; |
||
236 | |||
237 | /// Return the buffer, only if it has been loaded. |
||
238 | std::optional<llvm::MemoryBufferRef> getBufferIfLoaded() const { |
||
239 | if (Buffer) |
||
240 | return Buffer->getMemBufferRef(); |
||
241 | return std::nullopt; |
||
242 | } |
||
243 | |||
244 | /// Return a StringRef to the source buffer data, only if it has already |
||
245 | /// been loaded. |
||
246 | std::optional<StringRef> getBufferDataIfLoaded() const { |
||
247 | if (Buffer) |
||
248 | return Buffer->getBuffer(); |
||
249 | return std::nullopt; |
||
250 | } |
||
251 | |||
252 | /// Set the buffer. |
||
253 | void setBuffer(std::unique_ptr<llvm::MemoryBuffer> B) { |
||
254 | IsBufferInvalid = false; |
||
255 | Buffer = std::move(B); |
||
256 | } |
||
257 | |||
258 | /// Set the buffer to one that's not owned (or to nullptr). |
||
259 | /// |
||
260 | /// \pre Buffer cannot already be set. |
||
261 | void setUnownedBuffer(std::optional<llvm::MemoryBufferRef> B) { |
||
262 | assert(!Buffer && "Expected to be called right after construction"); |
||
263 | if (B) |
||
264 | setBuffer(llvm::MemoryBuffer::getMemBuffer(*B)); |
||
265 | } |
||
266 | |||
267 | // If BufStr has an invalid BOM, returns the BOM name; otherwise, returns |
||
268 | // nullptr |
||
269 | static const char *getInvalidBOM(StringRef BufStr); |
||
270 | }; |
||
271 | |||
272 | // Assert that the \c ContentCache objects will always be 8-byte aligned so |
||
273 | // that we can pack 3 bits of integer into pointers to such objects. |
||
274 | static_assert(alignof(ContentCache) >= 8, |
||
275 | "ContentCache must be 8-byte aligned."); |
||
276 | |||
277 | /// Information about a FileID, basically just the logical file |
||
278 | /// that it represents and include stack information. |
||
279 | /// |
||
280 | /// Each FileInfo has include stack information, indicating where it came |
||
281 | /// from. This information encodes the \#include chain that a token was |
||
282 | /// expanded from. The main include file has an invalid IncludeLoc. |
||
283 | /// |
||
284 | /// FileInfo should not grow larger than ExpansionInfo. Doing so will |
||
285 | /// cause memory to bloat in compilations with many unloaded macro |
||
286 | /// expansions, since the two data structurs are stored in a union in |
||
287 | /// SLocEntry. Extra fields should instead go in "ContentCache *", which |
||
288 | /// stores file contents and other bits on the side. |
||
289 | /// |
||
290 | class FileInfo { |
||
291 | friend class clang::SourceManager; |
||
292 | friend class clang::ASTWriter; |
||
293 | friend class clang::ASTReader; |
||
294 | |||
295 | /// The location of the \#include that brought in this file. |
||
296 | /// |
||
297 | /// This is an invalid SLOC for the main file (top of the \#include chain). |
||
298 | SourceLocation IncludeLoc; |
||
299 | |||
300 | /// Number of FileIDs (files and macros) that were created during |
||
301 | /// preprocessing of this \#include, including this SLocEntry. |
||
302 | /// |
||
303 | /// Zero means the preprocessor didn't provide such info for this SLocEntry. |
||
304 | unsigned NumCreatedFIDs : 31; |
||
305 | |||
306 | /// Whether this FileInfo has any \#line directives. |
||
307 | unsigned HasLineDirectives : 1; |
||
308 | |||
309 | /// The content cache and the characteristic of the file. |
||
310 | llvm::PointerIntPair<const ContentCache *, 3, CharacteristicKind> |
||
311 | ContentAndKind; |
||
312 | |||
313 | public: |
||
314 | /// Return a FileInfo object. |
||
315 | static FileInfo get(SourceLocation IL, ContentCache &Con, |
||
316 | CharacteristicKind FileCharacter, StringRef Filename) { |
||
317 | FileInfo X; |
||
318 | X.IncludeLoc = IL; |
||
319 | X.NumCreatedFIDs = 0; |
||
320 | X.HasLineDirectives = false; |
||
321 | X.ContentAndKind.setPointer(&Con); |
||
322 | X.ContentAndKind.setInt(FileCharacter); |
||
323 | Con.Filename = Filename; |
||
324 | return X; |
||
325 | } |
||
326 | |||
327 | SourceLocation getIncludeLoc() const { |
||
328 | return IncludeLoc; |
||
329 | } |
||
330 | |||
331 | const ContentCache &getContentCache() const { |
||
332 | return *ContentAndKind.getPointer(); |
||
333 | } |
||
334 | |||
335 | /// Return whether this is a system header or not. |
||
336 | CharacteristicKind getFileCharacteristic() const { |
||
337 | return ContentAndKind.getInt(); |
||
338 | } |
||
339 | |||
340 | /// Return true if this FileID has \#line directives in it. |
||
341 | bool hasLineDirectives() const { return HasLineDirectives; } |
||
342 | |||
343 | /// Set the flag that indicates that this FileID has |
||
344 | /// line table entries associated with it. |
||
345 | void setHasLineDirectives() { HasLineDirectives = true; } |
||
346 | |||
347 | /// Returns the name of the file that was used when the file was loaded from |
||
348 | /// the underlying file system. |
||
349 | StringRef getName() const { return getContentCache().Filename; } |
||
350 | }; |
||
351 | |||
352 | /// Each ExpansionInfo encodes the expansion location - where |
||
353 | /// the token was ultimately expanded, and the SpellingLoc - where the actual |
||
354 | /// character data for the token came from. |
||
355 | class ExpansionInfo { |
||
356 | // Really these are all SourceLocations. |
||
357 | |||
358 | /// Where the spelling for the token can be found. |
||
359 | SourceLocation SpellingLoc; |
||
360 | |||
361 | /// In a macro expansion, ExpansionLocStart and ExpansionLocEnd |
||
362 | /// indicate the start and end of the expansion. In object-like macros, |
||
363 | /// they will be the same. In a function-like macro expansion, the start |
||
364 | /// will be the identifier and the end will be the ')'. Finally, in |
||
365 | /// macro-argument instantiations, the end will be 'SourceLocation()', an |
||
366 | /// invalid location. |
||
367 | SourceLocation ExpansionLocStart, ExpansionLocEnd; |
||
368 | |||
369 | /// Whether the expansion range is a token range. |
||
370 | bool ExpansionIsTokenRange; |
||
371 | |||
372 | public: |
||
373 | SourceLocation getSpellingLoc() const { |
||
374 | return SpellingLoc.isInvalid() ? getExpansionLocStart() : SpellingLoc; |
||
375 | } |
||
376 | |||
377 | SourceLocation getExpansionLocStart() const { |
||
378 | return ExpansionLocStart; |
||
379 | } |
||
380 | |||
381 | SourceLocation getExpansionLocEnd() const { |
||
382 | return ExpansionLocEnd.isInvalid() ? getExpansionLocStart() |
||
383 | : ExpansionLocEnd; |
||
384 | } |
||
385 | |||
386 | bool isExpansionTokenRange() const { return ExpansionIsTokenRange; } |
||
387 | |||
388 | CharSourceRange getExpansionLocRange() const { |
||
389 | return CharSourceRange( |
||
390 | SourceRange(getExpansionLocStart(), getExpansionLocEnd()), |
||
391 | isExpansionTokenRange()); |
||
392 | } |
||
393 | |||
394 | bool isMacroArgExpansion() const { |
||
395 | // Note that this needs to return false for default constructed objects. |
||
396 | return getExpansionLocStart().isValid() && ExpansionLocEnd.isInvalid(); |
||
397 | } |
||
398 | |||
399 | bool isMacroBodyExpansion() const { |
||
400 | return getExpansionLocStart().isValid() && ExpansionLocEnd.isValid(); |
||
401 | } |
||
402 | |||
403 | bool isFunctionMacroExpansion() const { |
||
404 | return getExpansionLocStart().isValid() && |
||
405 | getExpansionLocStart() != getExpansionLocEnd(); |
||
406 | } |
||
407 | |||
408 | /// Return a ExpansionInfo for an expansion. |
||
409 | /// |
||
410 | /// Start and End specify the expansion range (where the macro is |
||
411 | /// expanded), and SpellingLoc specifies the spelling location (where |
||
412 | /// the characters from the token come from). All three can refer to |
||
413 | /// normal File SLocs or expansion locations. |
||
414 | static ExpansionInfo create(SourceLocation SpellingLoc, SourceLocation Start, |
||
415 | SourceLocation End, |
||
416 | bool ExpansionIsTokenRange = true) { |
||
417 | ExpansionInfo X; |
||
418 | X.SpellingLoc = SpellingLoc; |
||
419 | X.ExpansionLocStart = Start; |
||
420 | X.ExpansionLocEnd = End; |
||
421 | X.ExpansionIsTokenRange = ExpansionIsTokenRange; |
||
422 | return X; |
||
423 | } |
||
424 | |||
425 | /// Return a special ExpansionInfo for the expansion of |
||
426 | /// a macro argument into a function-like macro's body. |
||
427 | /// |
||
428 | /// ExpansionLoc specifies the expansion location (where the macro is |
||
429 | /// expanded). This doesn't need to be a range because a macro is always |
||
430 | /// expanded at a macro parameter reference, and macro parameters are |
||
431 | /// always exactly one token. SpellingLoc specifies the spelling location |
||
432 | /// (where the characters from the token come from). ExpansionLoc and |
||
433 | /// SpellingLoc can both refer to normal File SLocs or expansion locations. |
||
434 | /// |
||
435 | /// Given the code: |
||
436 | /// \code |
||
437 | /// #define F(x) f(x) |
||
438 | /// F(42); |
||
439 | /// \endcode |
||
440 | /// |
||
441 | /// When expanding '\c F(42)', the '\c x' would call this with an |
||
442 | /// SpellingLoc pointing at '\c 42' and an ExpansionLoc pointing at its |
||
443 | /// location in the definition of '\c F'. |
||
444 | static ExpansionInfo createForMacroArg(SourceLocation SpellingLoc, |
||
445 | SourceLocation ExpansionLoc) { |
||
446 | // We store an intentionally invalid source location for the end of the |
||
447 | // expansion range to mark that this is a macro argument location rather |
||
448 | // than a normal one. |
||
449 | return create(SpellingLoc, ExpansionLoc, SourceLocation()); |
||
450 | } |
||
451 | |||
452 | /// Return a special ExpansionInfo representing a token that ends |
||
453 | /// prematurely. This is used to model a '>>' token that has been split |
||
454 | /// into '>' tokens and similar cases. Unlike for the other forms of |
||
455 | /// expansion, the expansion range in this case is a character range, not |
||
456 | /// a token range. |
||
457 | static ExpansionInfo createForTokenSplit(SourceLocation SpellingLoc, |
||
458 | SourceLocation Start, |
||
459 | SourceLocation End) { |
||
460 | return create(SpellingLoc, Start, End, false); |
||
461 | } |
||
462 | }; |
||
463 | |||
464 | // Assert that the \c FileInfo objects are no bigger than \c ExpansionInfo |
||
465 | // objects. This controls the size of \c SLocEntry, of which we have one for |
||
466 | // each macro expansion. The number of (unloaded) macro expansions can be |
||
467 | // very large. Any other fields needed in FileInfo should go in ContentCache. |
||
468 | static_assert(sizeof(FileInfo) <= sizeof(ExpansionInfo), |
||
469 | "FileInfo must be no larger than ExpansionInfo."); |
||
470 | |||
471 | /// This is a discriminated union of FileInfo and ExpansionInfo. |
||
472 | /// |
||
473 | /// SourceManager keeps an array of these objects, and they are uniquely |
||
474 | /// identified by the FileID datatype. |
||
475 | class SLocEntry { |
||
476 | static constexpr int OffsetBits = 8 * sizeof(SourceLocation::UIntTy) - 1; |
||
477 | SourceLocation::UIntTy Offset : OffsetBits; |
||
478 | SourceLocation::UIntTy IsExpansion : 1; |
||
479 | union { |
||
480 | FileInfo File; |
||
481 | ExpansionInfo Expansion; |
||
482 | }; |
||
483 | |||
484 | public: |
||
485 | SLocEntry() : Offset(), IsExpansion(), File() {} |
||
486 | |||
487 | SourceLocation::UIntTy getOffset() const { return Offset; } |
||
488 | |||
489 | bool isExpansion() const { return IsExpansion; } |
||
490 | bool isFile() const { return !isExpansion(); } |
||
491 | |||
492 | const FileInfo &getFile() const { |
||
493 | assert(isFile() && "Not a file SLocEntry!"); |
||
494 | return File; |
||
495 | } |
||
496 | |||
497 | const ExpansionInfo &getExpansion() const { |
||
498 | assert(isExpansion() && "Not a macro expansion SLocEntry!"); |
||
499 | return Expansion; |
||
500 | } |
||
501 | |||
502 | static SLocEntry get(SourceLocation::UIntTy Offset, const FileInfo &FI) { |
||
503 | assert(!(Offset & (1ULL << OffsetBits)) && "Offset is too large"); |
||
504 | SLocEntry E; |
||
505 | E.Offset = Offset; |
||
506 | E.IsExpansion = false; |
||
507 | E.File = FI; |
||
508 | return E; |
||
509 | } |
||
510 | |||
511 | static SLocEntry get(SourceLocation::UIntTy Offset, |
||
512 | const ExpansionInfo &Expansion) { |
||
513 | assert(!(Offset & (1ULL << OffsetBits)) && "Offset is too large"); |
||
514 | SLocEntry E; |
||
515 | E.Offset = Offset; |
||
516 | E.IsExpansion = true; |
||
517 | new (&E.Expansion) ExpansionInfo(Expansion); |
||
518 | return E; |
||
519 | } |
||
520 | }; |
||
521 | |||
522 | } // namespace SrcMgr |
||
523 | |||
524 | /// External source of source location entries. |
||
525 | class ExternalSLocEntrySource { |
||
526 | public: |
||
527 | virtual ~ExternalSLocEntrySource(); |
||
528 | |||
529 | /// Read the source location entry with index ID, which will always be |
||
530 | /// less than -1. |
||
531 | /// |
||
532 | /// \returns true if an error occurred that prevented the source-location |
||
533 | /// entry from being loaded. |
||
534 | virtual bool ReadSLocEntry(int ID) = 0; |
||
535 | |||
536 | /// Retrieve the module import location and name for the given ID, if |
||
537 | /// in fact it was loaded from a module (rather than, say, a precompiled |
||
538 | /// header). |
||
539 | virtual std::pair<SourceLocation, StringRef> getModuleImportLoc(int ID) = 0; |
||
540 | }; |
||
541 | |||
542 | /// Holds the cache used by isBeforeInTranslationUnit. |
||
543 | /// |
||
544 | /// The cache structure is complex enough to be worth breaking out of |
||
545 | /// SourceManager. |
||
546 | class InBeforeInTUCacheEntry { |
||
547 | /// The FileID's of the cached query. |
||
548 | /// |
||
549 | /// If these match up with a subsequent query, the result can be reused. |
||
550 | FileID LQueryFID, RQueryFID; |
||
551 | |||
552 | /// The relative order of FileIDs that the CommonFID *immediately* includes. |
||
553 | /// |
||
554 | /// This is used to compare macro expansion locations. |
||
555 | bool LChildBeforeRChild; |
||
556 | |||
557 | /// The file found in common between the two \#include traces, i.e., |
||
558 | /// the nearest common ancestor of the \#include tree. |
||
559 | FileID CommonFID; |
||
560 | |||
561 | /// The offset of the previous query in CommonFID. |
||
562 | /// |
||
563 | /// Usually, this represents the location of the \#include for QueryFID, but |
||
564 | /// if LQueryFID is a parent of RQueryFID (or vice versa) then these can be a |
||
565 | /// random token in the parent. |
||
566 | unsigned LCommonOffset, RCommonOffset; |
||
567 | |||
568 | public: |
||
569 | InBeforeInTUCacheEntry() = default; |
||
570 | InBeforeInTUCacheEntry(FileID L, FileID R) : LQueryFID(L), RQueryFID(R) { |
||
571 | assert(L != R); |
||
572 | } |
||
573 | |||
574 | /// Return true if the currently cached values match up with |
||
575 | /// the specified LHS/RHS query. |
||
576 | /// |
||
577 | /// If not, we can't use the cache. |
||
578 | bool isCacheValid() const { |
||
579 | return CommonFID.isValid(); |
||
580 | } |
||
581 | |||
582 | /// If the cache is valid, compute the result given the |
||
583 | /// specified offsets in the LHS/RHS FileID's. |
||
584 | bool getCachedResult(unsigned LOffset, unsigned ROffset) const { |
||
585 | // If one of the query files is the common file, use the offset. Otherwise, |
||
586 | // use the #include loc in the common file. |
||
587 | if (LQueryFID != CommonFID) LOffset = LCommonOffset; |
||
588 | if (RQueryFID != CommonFID) ROffset = RCommonOffset; |
||
589 | |||
590 | // It is common for multiple macro expansions to be "included" from the same |
||
591 | // location (expansion location), in which case use the order of the FileIDs |
||
592 | // to determine which came first. This will also take care the case where |
||
593 | // one of the locations points at the inclusion/expansion point of the other |
||
594 | // in which case its FileID will come before the other. |
||
595 | if (LOffset == ROffset) |
||
596 | return LChildBeforeRChild; |
||
597 | |||
598 | return LOffset < ROffset; |
||
599 | } |
||
600 | |||
601 | /// Set up a new query. |
||
602 | /// If it matches the old query, we can keep the cached answer. |
||
603 | void setQueryFIDs(FileID LHS, FileID RHS) { |
||
604 | assert(LHS != RHS); |
||
605 | if (LQueryFID != LHS || RQueryFID != RHS) { |
||
606 | LQueryFID = LHS; |
||
607 | RQueryFID = RHS; |
||
608 | CommonFID = FileID(); |
||
609 | } |
||
610 | } |
||
611 | |||
612 | void setCommonLoc(FileID commonFID, unsigned lCommonOffset, |
||
613 | unsigned rCommonOffset, bool LParentBeforeRParent) { |
||
614 | CommonFID = commonFID; |
||
615 | LCommonOffset = lCommonOffset; |
||
616 | RCommonOffset = rCommonOffset; |
||
617 | LChildBeforeRChild = LParentBeforeRParent; |
||
618 | } |
||
619 | }; |
||
620 | |||
621 | /// The stack used when building modules on demand, which is used |
||
622 | /// to provide a link between the source managers of the different compiler |
||
623 | /// instances. |
||
624 | using ModuleBuildStack = ArrayRef<std::pair<std::string, FullSourceLoc>>; |
||
625 | |||
626 | /// This class handles loading and caching of source files into memory. |
||
627 | /// |
||
628 | /// This object owns the MemoryBuffer objects for all of the loaded |
||
629 | /// files and assigns unique FileID's for each unique \#include chain. |
||
630 | /// |
||
631 | /// The SourceManager can be queried for information about SourceLocation |
||
632 | /// objects, turning them into either spelling or expansion locations. Spelling |
||
633 | /// locations represent where the bytes corresponding to a token came from and |
||
634 | /// expansion locations represent where the location is in the user's view. In |
||
635 | /// the case of a macro expansion, for example, the spelling location indicates |
||
636 | /// where the expanded token came from and the expansion location specifies |
||
637 | /// where it was expanded. |
||
638 | class SourceManager : public RefCountedBase<SourceManager> { |
||
639 | /// DiagnosticsEngine object. |
||
640 | DiagnosticsEngine &Diag; |
||
641 | |||
642 | FileManager &FileMgr; |
||
643 | |||
644 | mutable llvm::BumpPtrAllocator ContentCacheAlloc; |
||
645 | |||
646 | /// Memoized information about all of the files tracked by this |
||
647 | /// SourceManager. |
||
648 | /// |
||
649 | /// This map allows us to merge ContentCache entries based |
||
650 | /// on their FileEntry*. All ContentCache objects will thus have unique, |
||
651 | /// non-null, FileEntry pointers. |
||
652 | llvm::DenseMap<const FileEntry*, SrcMgr::ContentCache*> FileInfos; |
||
653 | |||
654 | /// True if the ContentCache for files that are overridden by other |
||
655 | /// files, should report the original file name. Defaults to true. |
||
656 | bool OverridenFilesKeepOriginalName = true; |
||
657 | |||
658 | /// True if non-system source files should be treated as volatile |
||
659 | /// (likely to change while trying to use them). Defaults to false. |
||
660 | bool UserFilesAreVolatile; |
||
661 | |||
662 | /// True if all files read during this compilation should be treated |
||
663 | /// as transient (may not be present in later compilations using a module |
||
664 | /// file created from this compilation). Defaults to false. |
||
665 | bool FilesAreTransient = false; |
||
666 | |||
667 | struct OverriddenFilesInfoTy { |
||
668 | /// Files that have been overridden with the contents from another |
||
669 | /// file. |
||
670 | llvm::DenseMap<const FileEntry *, FileEntryRef> OverriddenFiles; |
||
671 | |||
672 | /// Files that were overridden with a memory buffer. |
||
673 | llvm::DenseSet<const FileEntry *> OverriddenFilesWithBuffer; |
||
674 | }; |
||
675 | |||
676 | /// Lazily create the object keeping overridden files info, since |
||
677 | /// it is uncommonly used. |
||
678 | std::unique_ptr<OverriddenFilesInfoTy> OverriddenFilesInfo; |
||
679 | |||
680 | OverriddenFilesInfoTy &getOverriddenFilesInfo() { |
||
681 | if (!OverriddenFilesInfo) |
||
682 | OverriddenFilesInfo.reset(new OverriddenFilesInfoTy); |
||
683 | return *OverriddenFilesInfo; |
||
684 | } |
||
685 | |||
686 | /// Information about various memory buffers that we have read in. |
||
687 | /// |
||
688 | /// All FileEntry* within the stored ContentCache objects are NULL, |
||
689 | /// as they do not refer to a file. |
||
690 | std::vector<SrcMgr::ContentCache*> MemBufferInfos; |
||
691 | |||
692 | /// The table of SLocEntries that are local to this module. |
||
693 | /// |
||
694 | /// Positive FileIDs are indexes into this table. Entry 0 indicates an invalid |
||
695 | /// expansion. |
||
696 | SmallVector<SrcMgr::SLocEntry, 0> LocalSLocEntryTable; |
||
697 | |||
698 | /// The table of SLocEntries that are loaded from other modules. |
||
699 | /// |
||
700 | /// Negative FileIDs are indexes into this table. To get from ID to an index, |
||
701 | /// use (-ID - 2). |
||
702 | SmallVector<SrcMgr::SLocEntry, 0> LoadedSLocEntryTable; |
||
703 | |||
704 | /// The starting offset of the next local SLocEntry. |
||
705 | /// |
||
706 | /// This is LocalSLocEntryTable.back().Offset + the size of that entry. |
||
707 | SourceLocation::UIntTy NextLocalOffset; |
||
708 | |||
709 | /// The starting offset of the latest batch of loaded SLocEntries. |
||
710 | /// |
||
711 | /// This is LoadedSLocEntryTable.back().Offset, except that that entry might |
||
712 | /// not have been loaded, so that value would be unknown. |
||
713 | SourceLocation::UIntTy CurrentLoadedOffset; |
||
714 | |||
715 | /// The highest possible offset is 2^31-1 (2^63-1 for 64-bit source |
||
716 | /// locations), so CurrentLoadedOffset starts at 2^31 (2^63 resp.). |
||
717 | static const SourceLocation::UIntTy MaxLoadedOffset = |
||
718 | 1ULL << (8 * sizeof(SourceLocation::UIntTy) - 1); |
||
719 | |||
720 | /// A bitmap that indicates whether the entries of LoadedSLocEntryTable |
||
721 | /// have already been loaded from the external source. |
||
722 | /// |
||
723 | /// Same indexing as LoadedSLocEntryTable. |
||
724 | llvm::BitVector SLocEntryLoaded; |
||
725 | |||
726 | /// An external source for source location entries. |
||
727 | ExternalSLocEntrySource *ExternalSLocEntries = nullptr; |
||
728 | |||
729 | /// A one-entry cache to speed up getFileID. |
||
730 | /// |
||
731 | /// LastFileIDLookup records the last FileID looked up or created, because it |
||
732 | /// is very common to look up many tokens from the same file. |
||
733 | mutable FileID LastFileIDLookup; |
||
734 | |||
735 | /// Holds information for \#line directives. |
||
736 | /// |
||
737 | /// This is referenced by indices from SLocEntryTable. |
||
738 | std::unique_ptr<LineTableInfo> LineTable; |
||
739 | |||
740 | /// These ivars serve as a cache used in the getLineNumber |
||
741 | /// method which is used to speedup getLineNumber calls to nearby locations. |
||
742 | mutable FileID LastLineNoFileIDQuery; |
||
743 | mutable const SrcMgr::ContentCache *LastLineNoContentCache; |
||
744 | mutable unsigned LastLineNoFilePos; |
||
745 | mutable unsigned LastLineNoResult; |
||
746 | |||
747 | /// The file ID for the main source file of the translation unit. |
||
748 | FileID MainFileID; |
||
749 | |||
750 | /// The file ID for the precompiled preamble there is one. |
||
751 | FileID PreambleFileID; |
||
752 | |||
753 | // Statistics for -print-stats. |
||
754 | mutable unsigned NumLinearScans = 0; |
||
755 | mutable unsigned NumBinaryProbes = 0; |
||
756 | |||
757 | /// Associates a FileID with its "included/expanded in" decomposed |
||
758 | /// location. |
||
759 | /// |
||
760 | /// Used to cache results from and speed-up \c getDecomposedIncludedLoc |
||
761 | /// function. |
||
762 | mutable llvm::DenseMap<FileID, std::pair<FileID, unsigned>> IncludedLocMap; |
||
763 | |||
764 | /// The key value into the IsBeforeInTUCache table. |
||
765 | using IsBeforeInTUCacheKey = std::pair<FileID, FileID>; |
||
766 | |||
767 | /// The IsBeforeInTranslationUnitCache is a mapping from FileID pairs |
||
768 | /// to cache results. |
||
769 | using InBeforeInTUCache = |
||
770 | llvm::DenseMap<IsBeforeInTUCacheKey, InBeforeInTUCacheEntry>; |
||
771 | |||
772 | /// Cache results for the isBeforeInTranslationUnit method. |
||
773 | mutable InBeforeInTUCache IBTUCache; |
||
774 | mutable InBeforeInTUCacheEntry IBTUCacheOverflow; |
||
775 | |||
776 | /// Return the cache entry for comparing the given file IDs |
||
777 | /// for isBeforeInTranslationUnit. |
||
778 | InBeforeInTUCacheEntry &getInBeforeInTUCache(FileID LFID, FileID RFID) const; |
||
779 | |||
780 | // Cache for the "fake" buffer used for error-recovery purposes. |
||
781 | mutable std::unique_ptr<llvm::MemoryBuffer> FakeBufferForRecovery; |
||
782 | |||
783 | mutable std::unique_ptr<SrcMgr::ContentCache> FakeContentCacheForRecovery; |
||
784 | |||
785 | mutable std::unique_ptr<SrcMgr::SLocEntry> FakeSLocEntryForRecovery; |
||
786 | |||
787 | /// Lazily computed map of macro argument chunks to their expanded |
||
788 | /// source location. |
||
789 | using MacroArgsMap = std::map<unsigned, SourceLocation>; |
||
790 | |||
791 | mutable llvm::DenseMap<FileID, std::unique_ptr<MacroArgsMap>> |
||
792 | MacroArgsCacheMap; |
||
793 | |||
794 | /// The stack of modules being built, which is used to detect |
||
795 | /// cycles in the module dependency graph as modules are being built, as |
||
796 | /// well as to describe why we're rebuilding a particular module. |
||
797 | /// |
||
798 | /// There is no way to set this value from the command line. If we ever need |
||
799 | /// to do so (e.g., if on-demand module construction moves out-of-process), |
||
800 | /// we can add a cc1-level option to do so. |
||
801 | SmallVector<std::pair<std::string, FullSourceLoc>, 2> StoredModuleBuildStack; |
||
802 | |||
803 | public: |
||
804 | SourceManager(DiagnosticsEngine &Diag, FileManager &FileMgr, |
||
805 | bool UserFilesAreVolatile = false); |
||
806 | explicit SourceManager(const SourceManager &) = delete; |
||
807 | SourceManager &operator=(const SourceManager &) = delete; |
||
808 | ~SourceManager(); |
||
809 | |||
810 | void clearIDTables(); |
||
811 | |||
812 | /// Initialize this source manager suitably to replay the compilation |
||
813 | /// described by \p Old. Requires that \p Old outlive \p *this. |
||
814 | void initializeForReplay(const SourceManager &Old); |
||
815 | |||
816 | DiagnosticsEngine &getDiagnostics() const { return Diag; } |
||
817 | |||
818 | FileManager &getFileManager() const { return FileMgr; } |
||
819 | |||
820 | /// Set true if the SourceManager should report the original file name |
||
821 | /// for contents of files that were overridden by other files. Defaults to |
||
822 | /// true. |
||
823 | void setOverridenFilesKeepOriginalName(bool value) { |
||
824 | OverridenFilesKeepOriginalName = value; |
||
825 | } |
||
826 | |||
827 | /// True if non-system source files should be treated as volatile |
||
828 | /// (likely to change while trying to use them). |
||
829 | bool userFilesAreVolatile() const { return UserFilesAreVolatile; } |
||
830 | |||
831 | /// Retrieve the module build stack. |
||
832 | ModuleBuildStack getModuleBuildStack() const { |
||
833 | return StoredModuleBuildStack; |
||
834 | } |
||
835 | |||
836 | /// Set the module build stack. |
||
837 | void setModuleBuildStack(ModuleBuildStack stack) { |
||
838 | StoredModuleBuildStack.clear(); |
||
839 | StoredModuleBuildStack.append(stack.begin(), stack.end()); |
||
840 | } |
||
841 | |||
842 | /// Push an entry to the module build stack. |
||
843 | void pushModuleBuildStack(StringRef moduleName, FullSourceLoc importLoc) { |
||
844 | StoredModuleBuildStack.push_back(std::make_pair(moduleName.str(),importLoc)); |
||
845 | } |
||
846 | |||
847 | //===--------------------------------------------------------------------===// |
||
848 | // MainFileID creation and querying methods. |
||
849 | //===--------------------------------------------------------------------===// |
||
850 | |||
851 | /// Returns the FileID of the main source file. |
||
852 | FileID getMainFileID() const { return MainFileID; } |
||
853 | |||
854 | /// Set the file ID for the main source file. |
||
855 | void setMainFileID(FileID FID) { |
||
856 | MainFileID = FID; |
||
857 | } |
||
858 | |||
859 | /// Returns true when the given FileEntry corresponds to the main file. |
||
860 | /// |
||
861 | /// The main file should be set prior to calling this function. |
||
862 | bool isMainFile(const FileEntry &SourceFile); |
||
863 | |||
864 | /// Set the file ID for the precompiled preamble. |
||
865 | void setPreambleFileID(FileID Preamble) { |
||
866 | assert(PreambleFileID.isInvalid() && "PreambleFileID already set!"); |
||
867 | PreambleFileID = Preamble; |
||
868 | } |
||
869 | |||
870 | /// Get the file ID for the precompiled preamble if there is one. |
||
871 | FileID getPreambleFileID() const { return PreambleFileID; } |
||
872 | |||
873 | //===--------------------------------------------------------------------===// |
||
874 | // Methods to create new FileID's and macro expansions. |
||
875 | //===--------------------------------------------------------------------===// |
||
876 | |||
877 | /// Create a new FileID that represents the specified file |
||
878 | /// being \#included from the specified IncludePosition. |
||
879 | /// |
||
880 | /// This translates NULL into standard input. |
||
881 | FileID createFileID(const FileEntry *SourceFile, SourceLocation IncludePos, |
||
882 | SrcMgr::CharacteristicKind FileCharacter, |
||
883 | int LoadedID = 0, |
||
884 | SourceLocation::UIntTy LoadedOffset = 0); |
||
885 | |||
886 | FileID createFileID(FileEntryRef SourceFile, SourceLocation IncludePos, |
||
887 | SrcMgr::CharacteristicKind FileCharacter, |
||
888 | int LoadedID = 0, |
||
889 | SourceLocation::UIntTy LoadedOffset = 0); |
||
890 | |||
891 | /// Create a new FileID that represents the specified memory buffer. |
||
892 | /// |
||
893 | /// This does no caching of the buffer and takes ownership of the |
||
894 | /// MemoryBuffer, so only pass a MemoryBuffer to this once. |
||
895 | FileID createFileID(std::unique_ptr<llvm::MemoryBuffer> Buffer, |
||
896 | SrcMgr::CharacteristicKind FileCharacter = SrcMgr::C_User, |
||
897 | int LoadedID = 0, SourceLocation::UIntTy LoadedOffset = 0, |
||
898 | SourceLocation IncludeLoc = SourceLocation()); |
||
899 | |||
900 | /// Create a new FileID that represents the specified memory buffer. |
||
901 | /// |
||
902 | /// This does not take ownership of the MemoryBuffer. The memory buffer must |
||
903 | /// outlive the SourceManager. |
||
904 | FileID createFileID(const llvm::MemoryBufferRef &Buffer, |
||
905 | SrcMgr::CharacteristicKind FileCharacter = SrcMgr::C_User, |
||
906 | int LoadedID = 0, SourceLocation::UIntTy LoadedOffset = 0, |
||
907 | SourceLocation IncludeLoc = SourceLocation()); |
||
908 | |||
909 | /// Get the FileID for \p SourceFile if it exists. Otherwise, create a |
||
910 | /// new FileID for the \p SourceFile. |
||
911 | FileID getOrCreateFileID(const FileEntry *SourceFile, |
||
912 | SrcMgr::CharacteristicKind FileCharacter); |
||
913 | |||
914 | /// Creates an expansion SLocEntry for the substitution of an argument into a |
||
915 | /// function-like macro's body. Returns the start of the expansion. |
||
916 | /// |
||
917 | /// The macro argument was written at \p SpellingLoc with length \p Length. |
||
918 | /// \p ExpansionLoc is the parameter name in the (expanded) macro body. |
||
919 | SourceLocation createMacroArgExpansionLoc(SourceLocation SpellingLoc, |
||
920 | SourceLocation ExpansionLoc, |
||
921 | unsigned Length); |
||
922 | |||
923 | /// Creates an expansion SLocEntry for a macro use. Returns its start. |
||
924 | /// |
||
925 | /// The macro body begins at \p SpellingLoc with length \p Length. |
||
926 | /// The macro use spans [ExpansionLocStart, ExpansionLocEnd]. |
||
927 | SourceLocation createExpansionLoc(SourceLocation SpellingLoc, |
||
928 | SourceLocation ExpansionLocStart, |
||
929 | SourceLocation ExpansionLocEnd, |
||
930 | unsigned Length, |
||
931 | bool ExpansionIsTokenRange = true, |
||
932 | int LoadedID = 0, |
||
933 | SourceLocation::UIntTy LoadedOffset = 0); |
||
934 | |||
935 | /// Return a new SourceLocation that encodes that the token starting |
||
936 | /// at \p TokenStart ends prematurely at \p TokenEnd. |
||
937 | SourceLocation createTokenSplitLoc(SourceLocation SpellingLoc, |
||
938 | SourceLocation TokenStart, |
||
939 | SourceLocation TokenEnd); |
||
940 | |||
941 | /// Retrieve the memory buffer associated with the given file. |
||
942 | /// |
||
943 | /// Returns std::nullopt if the buffer is not valid. |
||
944 | std::optional<llvm::MemoryBufferRef> |
||
945 | getMemoryBufferForFileOrNone(const FileEntry *File); |
||
946 | |||
947 | /// Retrieve the memory buffer associated with the given file. |
||
948 | /// |
||
949 | /// Returns a fake buffer if there isn't a real one. |
||
950 | llvm::MemoryBufferRef getMemoryBufferForFileOrFake(const FileEntry *File) { |
||
951 | if (auto B = getMemoryBufferForFileOrNone(File)) |
||
952 | return *B; |
||
953 | return getFakeBufferForRecovery(); |
||
954 | } |
||
955 | |||
956 | /// Override the contents of the given source file by providing an |
||
957 | /// already-allocated buffer. |
||
958 | /// |
||
959 | /// \param SourceFile the source file whose contents will be overridden. |
||
960 | /// |
||
961 | /// \param Buffer the memory buffer whose contents will be used as the |
||
962 | /// data in the given source file. |
||
963 | void overrideFileContents(const FileEntry *SourceFile, |
||
964 | const llvm::MemoryBufferRef &Buffer) { |
||
965 | overrideFileContents(SourceFile, llvm::MemoryBuffer::getMemBuffer(Buffer)); |
||
966 | } |
||
967 | |||
968 | /// Override the contents of the given source file by providing an |
||
969 | /// already-allocated buffer. |
||
970 | /// |
||
971 | /// \param SourceFile the source file whose contents will be overridden. |
||
972 | /// |
||
973 | /// \param Buffer the memory buffer whose contents will be used as the |
||
974 | /// data in the given source file. |
||
975 | void overrideFileContents(const FileEntry *SourceFile, |
||
976 | std::unique_ptr<llvm::MemoryBuffer> Buffer); |
||
977 | void overrideFileContents(FileEntryRef SourceFile, |
||
978 | std::unique_ptr<llvm::MemoryBuffer> Buffer) { |
||
979 | overrideFileContents(&SourceFile.getFileEntry(), std::move(Buffer)); |
||
980 | } |
||
981 | |||
982 | /// Override the given source file with another one. |
||
983 | /// |
||
984 | /// \param SourceFile the source file which will be overridden. |
||
985 | /// |
||
986 | /// \param NewFile the file whose contents will be used as the |
||
987 | /// data instead of the contents of the given source file. |
||
988 | void overrideFileContents(const FileEntry *SourceFile, FileEntryRef NewFile); |
||
989 | |||
990 | /// Returns true if the file contents have been overridden. |
||
991 | bool isFileOverridden(const FileEntry *File) const { |
||
992 | if (OverriddenFilesInfo) { |
||
993 | if (OverriddenFilesInfo->OverriddenFilesWithBuffer.count(File)) |
||
994 | return true; |
||
995 | if (OverriddenFilesInfo->OverriddenFiles.find(File) != |
||
996 | OverriddenFilesInfo->OverriddenFiles.end()) |
||
997 | return true; |
||
998 | } |
||
999 | return false; |
||
1000 | } |
||
1001 | |||
1002 | /// Bypass the overridden contents of a file. This creates a new FileEntry |
||
1003 | /// and initializes the content cache for it. Returns std::nullopt if there |
||
1004 | /// is no such file in the filesystem. |
||
1005 | /// |
||
1006 | /// This should be called before parsing has begun. |
||
1007 | OptionalFileEntryRef bypassFileContentsOverride(FileEntryRef File); |
||
1008 | |||
1009 | /// Specify that a file is transient. |
||
1010 | void setFileIsTransient(const FileEntry *SourceFile); |
||
1011 | |||
1012 | /// Specify that all files that are read during this compilation are |
||
1013 | /// transient. |
||
1014 | void setAllFilesAreTransient(bool Transient) { |
||
1015 | FilesAreTransient = Transient; |
||
1016 | } |
||
1017 | |||
1018 | //===--------------------------------------------------------------------===// |
||
1019 | // FileID manipulation methods. |
||
1020 | //===--------------------------------------------------------------------===// |
||
1021 | |||
1022 | /// Return the buffer for the specified FileID. |
||
1023 | /// |
||
1024 | /// If there is an error opening this buffer the first time, return |
||
1025 | /// std::nullopt. |
||
1026 | std::optional<llvm::MemoryBufferRef> |
||
1027 | getBufferOrNone(FileID FID, SourceLocation Loc = SourceLocation()) const { |
||
1028 | if (auto *Entry = getSLocEntryForFile(FID)) |
||
1029 | return Entry->getFile().getContentCache().getBufferOrNone( |
||
1030 | Diag, getFileManager(), Loc); |
||
1031 | return std::nullopt; |
||
1032 | } |
||
1033 | |||
1034 | /// Return the buffer for the specified FileID. |
||
1035 | /// |
||
1036 | /// If there is an error opening this buffer the first time, this |
||
1037 | /// manufactures a temporary buffer and returns it. |
||
1038 | llvm::MemoryBufferRef |
||
1039 | getBufferOrFake(FileID FID, SourceLocation Loc = SourceLocation()) const { |
||
1040 | if (auto B = getBufferOrNone(FID, Loc)) |
||
1041 | return *B; |
||
1042 | return getFakeBufferForRecovery(); |
||
1043 | } |
||
1044 | |||
1045 | /// Returns the FileEntry record for the provided FileID. |
||
1046 | const FileEntry *getFileEntryForID(FileID FID) const { |
||
1047 | if (auto *Entry = getSLocEntryForFile(FID)) |
||
1048 | return Entry->getFile().getContentCache().OrigEntry; |
||
1049 | return nullptr; |
||
1050 | } |
||
1051 | |||
1052 | /// Returns the FileEntryRef for the provided FileID. |
||
1053 | OptionalFileEntryRef getFileEntryRefForID(FileID FID) const { |
||
1054 | if (auto *Entry = getSLocEntryForFile(FID)) |
||
1055 | return Entry->getFile().getContentCache().OrigEntry; |
||
1056 | return std::nullopt; |
||
1057 | } |
||
1058 | |||
1059 | /// Returns the filename for the provided FileID, unless it's a built-in |
||
1060 | /// buffer that's not represented by a filename. |
||
1061 | /// |
||
1062 | /// Returns std::nullopt for non-files and built-in files. |
||
1063 | std::optional<StringRef> getNonBuiltinFilenameForID(FileID FID) const; |
||
1064 | |||
1065 | /// Returns the FileEntry record for the provided SLocEntry. |
||
1066 | const FileEntry *getFileEntryForSLocEntry(const SrcMgr::SLocEntry &sloc) const |
||
1067 | { |
||
1068 | return sloc.getFile().getContentCache().OrigEntry; |
||
1069 | } |
||
1070 | |||
1071 | /// Return a StringRef to the source buffer data for the |
||
1072 | /// specified FileID. |
||
1073 | /// |
||
1074 | /// \param FID The file ID whose contents will be returned. |
||
1075 | /// \param Invalid If non-NULL, will be set true if an error occurred. |
||
1076 | StringRef getBufferData(FileID FID, bool *Invalid = nullptr) const; |
||
1077 | |||
1078 | /// Return a StringRef to the source buffer data for the |
||
1079 | /// specified FileID, returning std::nullopt if invalid. |
||
1080 | /// |
||
1081 | /// \param FID The file ID whose contents will be returned. |
||
1082 | std::optional<StringRef> getBufferDataOrNone(FileID FID) const; |
||
1083 | |||
1084 | /// Return a StringRef to the source buffer data for the |
||
1085 | /// specified FileID, returning std::nullopt if it's not yet loaded. |
||
1086 | /// |
||
1087 | /// \param FID The file ID whose contents will be returned. |
||
1088 | std::optional<StringRef> getBufferDataIfLoaded(FileID FID) const; |
||
1089 | |||
1090 | /// Get the number of FileIDs (files and macros) that were created |
||
1091 | /// during preprocessing of \p FID, including it. |
||
1092 | unsigned getNumCreatedFIDsForFileID(FileID FID) const { |
||
1093 | if (auto *Entry = getSLocEntryForFile(FID)) |
||
1094 | return Entry->getFile().NumCreatedFIDs; |
||
1095 | return 0; |
||
1096 | } |
||
1097 | |||
1098 | /// Set the number of FileIDs (files and macros) that were created |
||
1099 | /// during preprocessing of \p FID, including it. |
||
1100 | void setNumCreatedFIDsForFileID(FileID FID, unsigned NumFIDs, |
||
1101 | bool Force = false) const { |
||
1102 | auto *Entry = getSLocEntryForFile(FID); |
||
1103 | if (!Entry) |
||
1104 | return; |
||
1105 | assert((Force || Entry->getFile().NumCreatedFIDs == 0) && "Already set!"); |
||
1106 | const_cast<SrcMgr::FileInfo &>(Entry->getFile()).NumCreatedFIDs = NumFIDs; |
||
1107 | } |
||
1108 | |||
1109 | //===--------------------------------------------------------------------===// |
||
1110 | // SourceLocation manipulation methods. |
||
1111 | //===--------------------------------------------------------------------===// |
||
1112 | |||
1113 | /// Return the FileID for a SourceLocation. |
||
1114 | /// |
||
1115 | /// This is a very hot method that is used for all SourceManager queries |
||
1116 | /// that start with a SourceLocation object. It is responsible for finding |
||
1117 | /// the entry in SLocEntryTable which contains the specified location. |
||
1118 | /// |
||
1119 | FileID getFileID(SourceLocation SpellingLoc) const { |
||
1120 | return getFileID(SpellingLoc.getOffset()); |
||
1121 | } |
||
1122 | |||
1123 | /// Return the filename of the file containing a SourceLocation. |
||
1124 | StringRef getFilename(SourceLocation SpellingLoc) const; |
||
1125 | |||
1126 | /// Return the source location corresponding to the first byte of |
||
1127 | /// the specified file. |
||
1128 | SourceLocation getLocForStartOfFile(FileID FID) const { |
||
1129 | if (auto *Entry = getSLocEntryForFile(FID)) |
||
1130 | return SourceLocation::getFileLoc(Entry->getOffset()); |
||
1131 | return SourceLocation(); |
||
1132 | } |
||
1133 | |||
1134 | /// Return the source location corresponding to the last byte of the |
||
1135 | /// specified file. |
||
1136 | SourceLocation getLocForEndOfFile(FileID FID) const { |
||
1137 | if (auto *Entry = getSLocEntryForFile(FID)) |
||
1138 | return SourceLocation::getFileLoc(Entry->getOffset() + |
||
1139 | getFileIDSize(FID)); |
||
1140 | return SourceLocation(); |
||
1141 | } |
||
1142 | |||
1143 | /// Returns the include location if \p FID is a \#include'd file |
||
1144 | /// otherwise it returns an invalid location. |
||
1145 | SourceLocation getIncludeLoc(FileID FID) const { |
||
1146 | if (auto *Entry = getSLocEntryForFile(FID)) |
||
1147 | return Entry->getFile().getIncludeLoc(); |
||
1148 | return SourceLocation(); |
||
1149 | } |
||
1150 | |||
1151 | // Returns the import location if the given source location is |
||
1152 | // located within a module, or an invalid location if the source location |
||
1153 | // is within the current translation unit. |
||
1154 | std::pair<SourceLocation, StringRef> |
||
1155 | getModuleImportLoc(SourceLocation Loc) const { |
||
1156 | FileID FID = getFileID(Loc); |
||
1157 | |||
1158 | // Positive file IDs are in the current translation unit, and -1 is a |
||
1159 | // placeholder. |
||
1160 | if (FID.ID >= -1) |
||
1161 | return std::make_pair(SourceLocation(), ""); |
||
1162 | |||
1163 | return ExternalSLocEntries->getModuleImportLoc(FID.ID); |
||
1164 | } |
||
1165 | |||
1166 | /// Given a SourceLocation object \p Loc, return the expansion |
||
1167 | /// location referenced by the ID. |
||
1168 | SourceLocation getExpansionLoc(SourceLocation Loc) const { |
||
1169 | // Handle the non-mapped case inline, defer to out of line code to handle |
||
1170 | // expansions. |
||
1171 | if (Loc.isFileID()) return Loc; |
||
1172 | return getExpansionLocSlowCase(Loc); |
||
1173 | } |
||
1174 | |||
1175 | /// Given \p Loc, if it is a macro location return the expansion |
||
1176 | /// location or the spelling location, depending on if it comes from a |
||
1177 | /// macro argument or not. |
||
1178 | SourceLocation getFileLoc(SourceLocation Loc) const { |
||
1179 | if (Loc.isFileID()) return Loc; |
||
1180 | return getFileLocSlowCase(Loc); |
||
1181 | } |
||
1182 | |||
1183 | /// Return the start/end of the expansion information for an |
||
1184 | /// expansion location. |
||
1185 | /// |
||
1186 | /// \pre \p Loc is required to be an expansion location. |
||
1187 | CharSourceRange getImmediateExpansionRange(SourceLocation Loc) const; |
||
1188 | |||
1189 | /// Given a SourceLocation object, return the range of |
||
1190 | /// tokens covered by the expansion in the ultimate file. |
||
1191 | CharSourceRange getExpansionRange(SourceLocation Loc) const; |
||
1192 | |||
1193 | /// Given a SourceRange object, return the range of |
||
1194 | /// tokens or characters covered by the expansion in the ultimate file. |
||
1195 | CharSourceRange getExpansionRange(SourceRange Range) const { |
||
1196 | SourceLocation Begin = getExpansionRange(Range.getBegin()).getBegin(); |
||
1197 | CharSourceRange End = getExpansionRange(Range.getEnd()); |
||
1198 | return CharSourceRange(SourceRange(Begin, End.getEnd()), |
||
1199 | End.isTokenRange()); |
||
1200 | } |
||
1201 | |||
1202 | /// Given a CharSourceRange object, return the range of |
||
1203 | /// tokens or characters covered by the expansion in the ultimate file. |
||
1204 | CharSourceRange getExpansionRange(CharSourceRange Range) const { |
||
1205 | CharSourceRange Expansion = getExpansionRange(Range.getAsRange()); |
||
1206 | if (Expansion.getEnd() == Range.getEnd()) |
||
1207 | Expansion.setTokenRange(Range.isTokenRange()); |
||
1208 | return Expansion; |
||
1209 | } |
||
1210 | |||
1211 | /// Given a SourceLocation object, return the spelling |
||
1212 | /// location referenced by the ID. |
||
1213 | /// |
||
1214 | /// This is the place where the characters that make up the lexed token |
||
1215 | /// can be found. |
||
1216 | SourceLocation getSpellingLoc(SourceLocation Loc) const { |
||
1217 | // Handle the non-mapped case inline, defer to out of line code to handle |
||
1218 | // expansions. |
||
1219 | if (Loc.isFileID()) return Loc; |
||
1220 | return getSpellingLocSlowCase(Loc); |
||
1221 | } |
||
1222 | |||
1223 | /// Given a SourceLocation object, return the spelling location |
||
1224 | /// referenced by the ID. |
||
1225 | /// |
||
1226 | /// This is the first level down towards the place where the characters |
||
1227 | /// that make up the lexed token can be found. This should not generally |
||
1228 | /// be used by clients. |
||
1229 | SourceLocation getImmediateSpellingLoc(SourceLocation Loc) const; |
||
1230 | |||
1231 | /// Form a SourceLocation from a FileID and Offset pair. |
||
1232 | SourceLocation getComposedLoc(FileID FID, unsigned Offset) const { |
||
1233 | auto *Entry = getSLocEntryOrNull(FID); |
||
1234 | if (!Entry) |
||
1235 | return SourceLocation(); |
||
1236 | |||
1237 | SourceLocation::UIntTy GlobalOffset = Entry->getOffset() + Offset; |
||
1238 | return Entry->isFile() ? SourceLocation::getFileLoc(GlobalOffset) |
||
1239 | : SourceLocation::getMacroLoc(GlobalOffset); |
||
1240 | } |
||
1241 | |||
1242 | /// Decompose the specified location into a raw FileID + Offset pair. |
||
1243 | /// |
||
1244 | /// The first element is the FileID, the second is the offset from the |
||
1245 | /// start of the buffer of the location. |
||
1246 | std::pair<FileID, unsigned> getDecomposedLoc(SourceLocation Loc) const { |
||
1247 | FileID FID = getFileID(Loc); |
||
1248 | auto *Entry = getSLocEntryOrNull(FID); |
||
1249 | if (!Entry) |
||
1250 | return std::make_pair(FileID(), 0); |
||
1251 | return std::make_pair(FID, Loc.getOffset() - Entry->getOffset()); |
||
1252 | } |
||
1253 | |||
1254 | /// Decompose the specified location into a raw FileID + Offset pair. |
||
1255 | /// |
||
1256 | /// If the location is an expansion record, walk through it until we find |
||
1257 | /// the final location expanded. |
||
1258 | std::pair<FileID, unsigned> |
||
1259 | getDecomposedExpansionLoc(SourceLocation Loc) const { |
||
1260 | FileID FID = getFileID(Loc); |
||
1261 | auto *E = getSLocEntryOrNull(FID); |
||
1262 | if (!E) |
||
1263 | return std::make_pair(FileID(), 0); |
||
1264 | |||
1265 | unsigned Offset = Loc.getOffset()-E->getOffset(); |
||
1266 | if (Loc.isFileID()) |
||
1267 | return std::make_pair(FID, Offset); |
||
1268 | |||
1269 | return getDecomposedExpansionLocSlowCase(E); |
||
1270 | } |
||
1271 | |||
1272 | /// Decompose the specified location into a raw FileID + Offset pair. |
||
1273 | /// |
||
1274 | /// If the location is an expansion record, walk through it until we find |
||
1275 | /// its spelling record. |
||
1276 | std::pair<FileID, unsigned> |
||
1277 | getDecomposedSpellingLoc(SourceLocation Loc) const { |
||
1278 | FileID FID = getFileID(Loc); |
||
1279 | auto *E = getSLocEntryOrNull(FID); |
||
1280 | if (!E) |
||
1281 | return std::make_pair(FileID(), 0); |
||
1282 | |||
1283 | unsigned Offset = Loc.getOffset()-E->getOffset(); |
||
1284 | if (Loc.isFileID()) |
||
1285 | return std::make_pair(FID, Offset); |
||
1286 | return getDecomposedSpellingLocSlowCase(E, Offset); |
||
1287 | } |
||
1288 | |||
1289 | /// Returns the "included/expanded in" decomposed location of the given |
||
1290 | /// FileID. |
||
1291 | std::pair<FileID, unsigned> getDecomposedIncludedLoc(FileID FID) const; |
||
1292 | |||
1293 | /// Returns the offset from the start of the file that the |
||
1294 | /// specified SourceLocation represents. |
||
1295 | /// |
||
1296 | /// This is not very meaningful for a macro ID. |
||
1297 | unsigned getFileOffset(SourceLocation SpellingLoc) const { |
||
1298 | return getDecomposedLoc(SpellingLoc).second; |
||
1299 | } |
||
1300 | |||
1301 | /// Tests whether the given source location represents a macro |
||
1302 | /// argument's expansion into the function-like macro definition. |
||
1303 | /// |
||
1304 | /// \param StartLoc If non-null and function returns true, it is set to the |
||
1305 | /// start location of the macro argument expansion. |
||
1306 | /// |
||
1307 | /// Such source locations only appear inside of the expansion |
||
1308 | /// locations representing where a particular function-like macro was |
||
1309 | /// expanded. |
||
1310 | bool isMacroArgExpansion(SourceLocation Loc, |
||
1311 | SourceLocation *StartLoc = nullptr) const; |
||
1312 | |||
1313 | /// Tests whether the given source location represents the expansion of |
||
1314 | /// a macro body. |
||
1315 | /// |
||
1316 | /// This is equivalent to testing whether the location is part of a macro |
||
1317 | /// expansion but not the expansion of an argument to a function-like macro. |
||
1318 | bool isMacroBodyExpansion(SourceLocation Loc) const; |
||
1319 | |||
1320 | /// Returns true if the given MacroID location points at the beginning |
||
1321 | /// of the immediate macro expansion. |
||
1322 | /// |
||
1323 | /// \param MacroBegin If non-null and function returns true, it is set to the |
||
1324 | /// begin location of the immediate macro expansion. |
||
1325 | bool isAtStartOfImmediateMacroExpansion(SourceLocation Loc, |
||
1326 | SourceLocation *MacroBegin = nullptr) const; |
||
1327 | |||
1328 | /// Returns true if the given MacroID location points at the character |
||
1329 | /// end of the immediate macro expansion. |
||
1330 | /// |
||
1331 | /// \param MacroEnd If non-null and function returns true, it is set to the |
||
1332 | /// character end location of the immediate macro expansion. |
||
1333 | bool |
||
1334 | isAtEndOfImmediateMacroExpansion(SourceLocation Loc, |
||
1335 | SourceLocation *MacroEnd = nullptr) const; |
||
1336 | |||
1337 | /// Returns true if \p Loc is inside the [\p Start, +\p Length) |
||
1338 | /// chunk of the source location address space. |
||
1339 | /// |
||
1340 | /// If it's true and \p RelativeOffset is non-null, it will be set to the |
||
1341 | /// relative offset of \p Loc inside the chunk. |
||
1342 | bool |
||
1343 | isInSLocAddrSpace(SourceLocation Loc, SourceLocation Start, unsigned Length, |
||
1344 | SourceLocation::UIntTy *RelativeOffset = nullptr) const { |
||
1345 | assert(((Start.getOffset() < NextLocalOffset && |
||
1346 | Start.getOffset()+Length <= NextLocalOffset) || |
||
1347 | (Start.getOffset() >= CurrentLoadedOffset && |
||
1348 | Start.getOffset()+Length < MaxLoadedOffset)) && |
||
1349 | "Chunk is not valid SLoc address space"); |
||
1350 | SourceLocation::UIntTy LocOffs = Loc.getOffset(); |
||
1351 | SourceLocation::UIntTy BeginOffs = Start.getOffset(); |
||
1352 | SourceLocation::UIntTy EndOffs = BeginOffs + Length; |
||
1353 | if (LocOffs >= BeginOffs && LocOffs < EndOffs) { |
||
1354 | if (RelativeOffset) |
||
1355 | *RelativeOffset = LocOffs - BeginOffs; |
||
1356 | return true; |
||
1357 | } |
||
1358 | |||
1359 | return false; |
||
1360 | } |
||
1361 | |||
1362 | /// Return true if both \p LHS and \p RHS are in the local source |
||
1363 | /// location address space or the loaded one. |
||
1364 | /// |
||
1365 | /// If it's true and \p RelativeOffset is non-null, it will be set to the |
||
1366 | /// offset of \p RHS relative to \p LHS. |
||
1367 | bool isInSameSLocAddrSpace(SourceLocation LHS, SourceLocation RHS, |
||
1368 | SourceLocation::IntTy *RelativeOffset) const { |
||
1369 | SourceLocation::UIntTy LHSOffs = LHS.getOffset(), RHSOffs = RHS.getOffset(); |
||
1370 | bool LHSLoaded = LHSOffs >= CurrentLoadedOffset; |
||
1371 | bool RHSLoaded = RHSOffs >= CurrentLoadedOffset; |
||
1372 | |||
1373 | if (LHSLoaded == RHSLoaded) { |
||
1374 | if (RelativeOffset) |
||
1375 | *RelativeOffset = RHSOffs - LHSOffs; |
||
1376 | return true; |
||
1377 | } |
||
1378 | |||
1379 | return false; |
||
1380 | } |
||
1381 | |||
1382 | //===--------------------------------------------------------------------===// |
||
1383 | // Queries about the code at a SourceLocation. |
||
1384 | //===--------------------------------------------------------------------===// |
||
1385 | |||
1386 | /// Return a pointer to the start of the specified location |
||
1387 | /// in the appropriate spelling MemoryBuffer. |
||
1388 | /// |
||
1389 | /// \param Invalid If non-NULL, will be set \c true if an error occurs. |
||
1390 | const char *getCharacterData(SourceLocation SL, |
||
1391 | bool *Invalid = nullptr) const; |
||
1392 | |||
1393 | /// Return the column # for the specified file position. |
||
1394 | /// |
||
1395 | /// This is significantly cheaper to compute than the line number. This |
||
1396 | /// returns zero if the column number isn't known. This may only be called |
||
1397 | /// on a file sloc, so you must choose a spelling or expansion location |
||
1398 | /// before calling this method. |
||
1399 | unsigned getColumnNumber(FileID FID, unsigned FilePos, |
||
1400 | bool *Invalid = nullptr) const; |
||
1401 | unsigned getSpellingColumnNumber(SourceLocation Loc, |
||
1402 | bool *Invalid = nullptr) const; |
||
1403 | unsigned getExpansionColumnNumber(SourceLocation Loc, |
||
1404 | bool *Invalid = nullptr) const; |
||
1405 | unsigned getPresumedColumnNumber(SourceLocation Loc, |
||
1406 | bool *Invalid = nullptr) const; |
||
1407 | |||
1408 | /// Given a SourceLocation, return the spelling line number |
||
1409 | /// for the position indicated. |
||
1410 | /// |
||
1411 | /// This requires building and caching a table of line offsets for the |
||
1412 | /// MemoryBuffer, so this is not cheap: use only when about to emit a |
||
1413 | /// diagnostic. |
||
1414 | unsigned getLineNumber(FileID FID, unsigned FilePos, bool *Invalid = nullptr) const; |
||
1415 | unsigned getSpellingLineNumber(SourceLocation Loc, bool *Invalid = nullptr) const; |
||
1416 | unsigned getExpansionLineNumber(SourceLocation Loc, bool *Invalid = nullptr) const; |
||
1417 | unsigned getPresumedLineNumber(SourceLocation Loc, bool *Invalid = nullptr) const; |
||
1418 | |||
1419 | /// Return the filename or buffer identifier of the buffer the |
||
1420 | /// location is in. |
||
1421 | /// |
||
1422 | /// Note that this name does not respect \#line directives. Use |
||
1423 | /// getPresumedLoc for normal clients. |
||
1424 | StringRef getBufferName(SourceLocation Loc, bool *Invalid = nullptr) const; |
||
1425 | |||
1426 | /// Return the file characteristic of the specified source |
||
1427 | /// location, indicating whether this is a normal file, a system |
||
1428 | /// header, or an "implicit extern C" system header. |
||
1429 | /// |
||
1430 | /// This state can be modified with flags on GNU linemarker directives like: |
||
1431 | /// \code |
||
1432 | /// # 4 "foo.h" 3 |
||
1433 | /// \endcode |
||
1434 | /// which changes all source locations in the current file after that to be |
||
1435 | /// considered to be from a system header. |
||
1436 | SrcMgr::CharacteristicKind getFileCharacteristic(SourceLocation Loc) const; |
||
1437 | |||
1438 | /// Returns the "presumed" location of a SourceLocation specifies. |
||
1439 | /// |
||
1440 | /// A "presumed location" can be modified by \#line or GNU line marker |
||
1441 | /// directives. This provides a view on the data that a user should see |
||
1442 | /// in diagnostics, for example. |
||
1443 | /// |
||
1444 | /// Note that a presumed location is always given as the expansion point of |
||
1445 | /// an expansion location, not at the spelling location. |
||
1446 | /// |
||
1447 | /// \returns The presumed location of the specified SourceLocation. If the |
||
1448 | /// presumed location cannot be calculated (e.g., because \p Loc is invalid |
||
1449 | /// or the file containing \p Loc has changed on disk), returns an invalid |
||
1450 | /// presumed location. |
||
1451 | PresumedLoc getPresumedLoc(SourceLocation Loc, |
||
1452 | bool UseLineDirectives = true) const; |
||
1453 | |||
1454 | /// Returns whether the PresumedLoc for a given SourceLocation is |
||
1455 | /// in the main file. |
||
1456 | /// |
||
1457 | /// This computes the "presumed" location for a SourceLocation, then checks |
||
1458 | /// whether it came from a file other than the main file. This is different |
||
1459 | /// from isWrittenInMainFile() because it takes line marker directives into |
||
1460 | /// account. |
||
1461 | bool isInMainFile(SourceLocation Loc) const; |
||
1462 | |||
1463 | /// Returns true if the spelling locations for both SourceLocations |
||
1464 | /// are part of the same file buffer. |
||
1465 | /// |
||
1466 | /// This check ignores line marker directives. |
||
1467 | bool isWrittenInSameFile(SourceLocation Loc1, SourceLocation Loc2) const { |
||
1468 | return getFileID(Loc1) == getFileID(Loc2); |
||
1469 | } |
||
1470 | |||
1471 | /// Returns true if the spelling location for the given location |
||
1472 | /// is in the main file buffer. |
||
1473 | /// |
||
1474 | /// This check ignores line marker directives. |
||
1475 | bool isWrittenInMainFile(SourceLocation Loc) const { |
||
1476 | return getFileID(Loc) == getMainFileID(); |
||
1477 | } |
||
1478 | |||
1479 | /// Returns whether \p Loc is located in a <built-in> file. |
||
1480 | bool isWrittenInBuiltinFile(SourceLocation Loc) const { |
||
1481 | PresumedLoc Presumed = getPresumedLoc(Loc); |
||
1482 | if (Presumed.isInvalid()) |
||
1483 | return false; |
||
1484 | StringRef Filename(Presumed.getFilename()); |
||
1485 | return Filename.equals("<built-in>"); |
||
1486 | } |
||
1487 | |||
1488 | /// Returns whether \p Loc is located in a <command line> file. |
||
1489 | bool isWrittenInCommandLineFile(SourceLocation Loc) const { |
||
1490 | PresumedLoc Presumed = getPresumedLoc(Loc); |
||
1491 | if (Presumed.isInvalid()) |
||
1492 | return false; |
||
1493 | StringRef Filename(Presumed.getFilename()); |
||
1494 | return Filename.equals("<command line>"); |
||
1495 | } |
||
1496 | |||
1497 | /// Returns whether \p Loc is located in a <scratch space> file. |
||
1498 | bool isWrittenInScratchSpace(SourceLocation Loc) const { |
||
1499 | PresumedLoc Presumed = getPresumedLoc(Loc); |
||
1500 | if (Presumed.isInvalid()) |
||
1501 | return false; |
||
1502 | StringRef Filename(Presumed.getFilename()); |
||
1503 | return Filename.equals("<scratch space>"); |
||
1504 | } |
||
1505 | |||
1506 | /// Returns if a SourceLocation is in a system header. |
||
1507 | bool isInSystemHeader(SourceLocation Loc) const { |
||
1508 | if (Loc.isInvalid()) |
||
1509 | return false; |
||
1510 | return isSystem(getFileCharacteristic(Loc)); |
||
1511 | } |
||
1512 | |||
1513 | /// Returns if a SourceLocation is in an "extern C" system header. |
||
1514 | bool isInExternCSystemHeader(SourceLocation Loc) const { |
||
1515 | return getFileCharacteristic(Loc) == SrcMgr::C_ExternCSystem; |
||
1516 | } |
||
1517 | |||
1518 | /// Returns whether \p Loc is expanded from a macro in a system header. |
||
1519 | bool isInSystemMacro(SourceLocation loc) const { |
||
1520 | if (!loc.isMacroID()) |
||
1521 | return false; |
||
1522 | |||
1523 | // This happens when the macro is the result of a paste, in that case |
||
1524 | // its spelling is the scratch memory, so we take the parent context. |
||
1525 | // There can be several level of token pasting. |
||
1526 | if (isWrittenInScratchSpace(getSpellingLoc(loc))) { |
||
1527 | do { |
||
1528 | loc = getImmediateMacroCallerLoc(loc); |
||
1529 | } while (isWrittenInScratchSpace(getSpellingLoc(loc))); |
||
1530 | return isInSystemMacro(loc); |
||
1531 | } |
||
1532 | |||
1533 | return isInSystemHeader(getSpellingLoc(loc)); |
||
1534 | } |
||
1535 | |||
1536 | /// The size of the SLocEntry that \p FID represents. |
||
1537 | unsigned getFileIDSize(FileID FID) const; |
||
1538 | |||
1539 | /// Given a specific FileID, returns true if \p Loc is inside that |
||
1540 | /// FileID chunk and sets relative offset (offset of \p Loc from beginning |
||
1541 | /// of FileID) to \p relativeOffset. |
||
1542 | bool isInFileID(SourceLocation Loc, FileID FID, |
||
1543 | unsigned *RelativeOffset = nullptr) const { |
||
1544 | SourceLocation::UIntTy Offs = Loc.getOffset(); |
||
1545 | if (isOffsetInFileID(FID, Offs)) { |
||
1546 | if (RelativeOffset) |
||
1547 | *RelativeOffset = Offs - getSLocEntry(FID).getOffset(); |
||
1548 | return true; |
||
1549 | } |
||
1550 | |||
1551 | return false; |
||
1552 | } |
||
1553 | |||
1554 | //===--------------------------------------------------------------------===// |
||
1555 | // Line Table Manipulation Routines |
||
1556 | //===--------------------------------------------------------------------===// |
||
1557 | |||
1558 | /// Return the uniqued ID for the specified filename. |
||
1559 | unsigned getLineTableFilenameID(StringRef Str); |
||
1560 | |||
1561 | /// Add a line note to the line table for the FileID and offset |
||
1562 | /// specified by Loc. |
||
1563 | /// |
||
1564 | /// If FilenameID is -1, it is considered to be unspecified. |
||
1565 | void AddLineNote(SourceLocation Loc, unsigned LineNo, int FilenameID, |
||
1566 | bool IsFileEntry, bool IsFileExit, |
||
1567 | SrcMgr::CharacteristicKind FileKind); |
||
1568 | |||
1569 | /// Determine if the source manager has a line table. |
||
1570 | bool hasLineTable() const { return LineTable != nullptr; } |
||
1571 | |||
1572 | /// Retrieve the stored line table. |
||
1573 | LineTableInfo &getLineTable(); |
||
1574 | |||
1575 | //===--------------------------------------------------------------------===// |
||
1576 | // Queries for performance analysis. |
||
1577 | //===--------------------------------------------------------------------===// |
||
1578 | |||
1579 | /// Return the total amount of physical memory allocated by the |
||
1580 | /// ContentCache allocator. |
||
1581 | size_t getContentCacheSize() const { |
||
1582 | return ContentCacheAlloc.getTotalMemory(); |
||
1583 | } |
||
1584 | |||
1585 | struct MemoryBufferSizes { |
||
1586 | const size_t malloc_bytes; |
||
1587 | const size_t mmap_bytes; |
||
1588 | |||
1589 | MemoryBufferSizes(size_t malloc_bytes, size_t mmap_bytes) |
||
1590 | : malloc_bytes(malloc_bytes), mmap_bytes(mmap_bytes) {} |
||
1591 | }; |
||
1592 | |||
1593 | /// Return the amount of memory used by memory buffers, breaking down |
||
1594 | /// by heap-backed versus mmap'ed memory. |
||
1595 | MemoryBufferSizes getMemoryBufferSizes() const; |
||
1596 | |||
1597 | /// Return the amount of memory used for various side tables and |
||
1598 | /// data structures in the SourceManager. |
||
1599 | size_t getDataStructureSizes() const; |
||
1600 | |||
1601 | //===--------------------------------------------------------------------===// |
||
1602 | // Other miscellaneous methods. |
||
1603 | //===--------------------------------------------------------------------===// |
||
1604 | |||
1605 | /// Get the source location for the given file:line:col triplet. |
||
1606 | /// |
||
1607 | /// If the source file is included multiple times, the source location will |
||
1608 | /// be based upon the first inclusion. |
||
1609 | SourceLocation translateFileLineCol(const FileEntry *SourceFile, |
||
1610 | unsigned Line, unsigned Col) const; |
||
1611 | |||
1612 | /// Get the FileID for the given file. |
||
1613 | /// |
||
1614 | /// If the source file is included multiple times, the FileID will be the |
||
1615 | /// first inclusion. |
||
1616 | FileID translateFile(const FileEntry *SourceFile) const; |
||
1617 | FileID translateFile(FileEntryRef SourceFile) const { |
||
1618 | return translateFile(&SourceFile.getFileEntry()); |
||
1619 | } |
||
1620 | |||
1621 | /// Get the source location in \p FID for the given line:col. |
||
1622 | /// Returns null location if \p FID is not a file SLocEntry. |
||
1623 | SourceLocation translateLineCol(FileID FID, |
||
1624 | unsigned Line, unsigned Col) const; |
||
1625 | |||
1626 | /// If \p Loc points inside a function macro argument, the returned |
||
1627 | /// location will be the macro location in which the argument was expanded. |
||
1628 | /// If a macro argument is used multiple times, the expanded location will |
||
1629 | /// be at the first expansion of the argument. |
||
1630 | /// e.g. |
||
1631 | /// MY_MACRO(foo); |
||
1632 | /// ^ |
||
1633 | /// Passing a file location pointing at 'foo', will yield a macro location |
||
1634 | /// where 'foo' was expanded into. |
||
1635 | SourceLocation getMacroArgExpandedLocation(SourceLocation Loc) const; |
||
1636 | |||
1637 | /// Determines the order of 2 source locations in the translation unit. |
||
1638 | /// |
||
1639 | /// \returns true if LHS source location comes before RHS, false otherwise. |
||
1640 | bool isBeforeInTranslationUnit(SourceLocation LHS, SourceLocation RHS) const; |
||
1641 | |||
1642 | /// Determines whether the two decomposed source location is in the |
||
1643 | /// same translation unit. As a byproduct, it also calculates the order |
||
1644 | /// of the source locations in case they are in the same TU. |
||
1645 | /// |
||
1646 | /// \returns Pair of bools the first component is true if the two locations |
||
1647 | /// are in the same TU. The second bool is true if the first is true |
||
1648 | /// and \p LOffs is before \p ROffs. |
||
1649 | std::pair<bool, bool> |
||
1650 | isInTheSameTranslationUnit(std::pair<FileID, unsigned> &LOffs, |
||
1651 | std::pair<FileID, unsigned> &ROffs) const; |
||
1652 | |||
1653 | /// Determines the order of 2 source locations in the "source location |
||
1654 | /// address space". |
||
1655 | bool isBeforeInSLocAddrSpace(SourceLocation LHS, SourceLocation RHS) const { |
||
1656 | return isBeforeInSLocAddrSpace(LHS, RHS.getOffset()); |
||
1657 | } |
||
1658 | |||
1659 | /// Determines the order of a source location and a source location |
||
1660 | /// offset in the "source location address space". |
||
1661 | /// |
||
1662 | /// Note that we always consider source locations loaded from |
||
1663 | bool isBeforeInSLocAddrSpace(SourceLocation LHS, |
||
1664 | SourceLocation::UIntTy RHS) const { |
||
1665 | SourceLocation::UIntTy LHSOffset = LHS.getOffset(); |
||
1666 | bool LHSLoaded = LHSOffset >= CurrentLoadedOffset; |
||
1667 | bool RHSLoaded = RHS >= CurrentLoadedOffset; |
||
1668 | if (LHSLoaded == RHSLoaded) |
||
1669 | return LHSOffset < RHS; |
||
1670 | |||
1671 | return LHSLoaded; |
||
1672 | } |
||
1673 | |||
1674 | /// Return true if the Point is within Start and End. |
||
1675 | bool isPointWithin(SourceLocation Location, SourceLocation Start, |
||
1676 | SourceLocation End) const { |
||
1677 | return Location == Start || Location == End || |
||
1678 | (isBeforeInTranslationUnit(Start, Location) && |
||
1679 | isBeforeInTranslationUnit(Location, End)); |
||
1680 | } |
||
1681 | |||
1682 | // Iterators over FileInfos. |
||
1683 | using fileinfo_iterator = |
||
1684 | llvm::DenseMap<const FileEntry*, SrcMgr::ContentCache*>::const_iterator; |
||
1685 | |||
1686 | fileinfo_iterator fileinfo_begin() const { return FileInfos.begin(); } |
||
1687 | fileinfo_iterator fileinfo_end() const { return FileInfos.end(); } |
||
1688 | bool hasFileInfo(const FileEntry *File) const { |
||
1689 | return FileInfos.find(File) != FileInfos.end(); |
||
1690 | } |
||
1691 | |||
1692 | /// Print statistics to stderr. |
||
1693 | void PrintStats() const; |
||
1694 | |||
1695 | void dump() const; |
||
1696 | |||
1697 | // Produce notes describing the current source location address space usage. |
||
1698 | void noteSLocAddressSpaceUsage(DiagnosticsEngine &Diag, |
||
1699 | std::optional<unsigned> MaxNotes = 32) const; |
||
1700 | |||
1701 | /// Get the number of local SLocEntries we have. |
||
1702 | unsigned local_sloc_entry_size() const { return LocalSLocEntryTable.size(); } |
||
1703 | |||
1704 | /// Get a local SLocEntry. This is exposed for indexing. |
||
1705 | const SrcMgr::SLocEntry &getLocalSLocEntry(unsigned Index) const { |
||
1706 | assert(Index < LocalSLocEntryTable.size() && "Invalid index"); |
||
1707 | return LocalSLocEntryTable[Index]; |
||
1708 | } |
||
1709 | |||
1710 | /// Get the number of loaded SLocEntries we have. |
||
1711 | unsigned loaded_sloc_entry_size() const { return LoadedSLocEntryTable.size();} |
||
1712 | |||
1713 | /// Get a loaded SLocEntry. This is exposed for indexing. |
||
1714 | const SrcMgr::SLocEntry &getLoadedSLocEntry(unsigned Index, |
||
1715 | bool *Invalid = nullptr) const { |
||
1716 | assert(Index < LoadedSLocEntryTable.size() && "Invalid index"); |
||
1717 | if (SLocEntryLoaded[Index]) |
||
1718 | return LoadedSLocEntryTable[Index]; |
||
1719 | return loadSLocEntry(Index, Invalid); |
||
1720 | } |
||
1721 | |||
1722 | const SrcMgr::SLocEntry &getSLocEntry(FileID FID, |
||
1723 | bool *Invalid = nullptr) const { |
||
1724 | if (FID.ID == 0 || FID.ID == -1) { |
||
1725 | if (Invalid) *Invalid = true; |
||
1726 | return LocalSLocEntryTable[0]; |
||
1727 | } |
||
1728 | return getSLocEntryByID(FID.ID, Invalid); |
||
1729 | } |
||
1730 | |||
1731 | SourceLocation::UIntTy getNextLocalOffset() const { return NextLocalOffset; } |
||
1732 | |||
1733 | void setExternalSLocEntrySource(ExternalSLocEntrySource *Source) { |
||
1734 | assert(LoadedSLocEntryTable.empty() && |
||
1735 | "Invalidating existing loaded entries"); |
||
1736 | ExternalSLocEntries = Source; |
||
1737 | } |
||
1738 | |||
1739 | /// Allocate a number of loaded SLocEntries, which will be actually |
||
1740 | /// loaded on demand from the external source. |
||
1741 | /// |
||
1742 | /// NumSLocEntries will be allocated, which occupy a total of TotalSize space |
||
1743 | /// in the global source view. The lowest ID and the base offset of the |
||
1744 | /// entries will be returned. |
||
1745 | std::pair<int, SourceLocation::UIntTy> |
||
1746 | AllocateLoadedSLocEntries(unsigned NumSLocEntries, |
||
1747 | SourceLocation::UIntTy TotalSize); |
||
1748 | |||
1749 | /// Returns true if \p Loc came from a PCH/Module. |
||
1750 | bool isLoadedSourceLocation(SourceLocation Loc) const { |
||
1751 | return isLoadedOffset(Loc.getOffset()); |
||
1752 | } |
||
1753 | |||
1754 | /// Returns true if \p Loc did not come from a PCH/Module. |
||
1755 | bool isLocalSourceLocation(SourceLocation Loc) const { |
||
1756 | return isLocalOffset(Loc.getOffset()); |
||
1757 | } |
||
1758 | |||
1759 | /// Returns true if \p FID came from a PCH/Module. |
||
1760 | bool isLoadedFileID(FileID FID) const { |
||
1761 | assert(FID.ID != -1 && "Using FileID sentinel value"); |
||
1762 | return FID.ID < 0; |
||
1763 | } |
||
1764 | |||
1765 | /// Returns true if \p FID did not come from a PCH/Module. |
||
1766 | bool isLocalFileID(FileID FID) const { |
||
1767 | return !isLoadedFileID(FID); |
||
1768 | } |
||
1769 | |||
1770 | /// Gets the location of the immediate macro caller, one level up the stack |
||
1771 | /// toward the initial macro typed into the source. |
||
1772 | SourceLocation getImmediateMacroCallerLoc(SourceLocation Loc) const { |
||
1773 | if (!Loc.isMacroID()) return Loc; |
||
1774 | |||
1775 | // When we have the location of (part of) an expanded parameter, its |
||
1776 | // spelling location points to the argument as expanded in the macro call, |
||
1777 | // and therefore is used to locate the macro caller. |
||
1778 | if (isMacroArgExpansion(Loc)) |
||
1779 | return getImmediateSpellingLoc(Loc); |
||
1780 | |||
1781 | // Otherwise, the caller of the macro is located where this macro is |
||
1782 | // expanded (while the spelling is part of the macro definition). |
||
1783 | return getImmediateExpansionRange(Loc).getBegin(); |
||
1784 | } |
||
1785 | |||
1786 | /// \return Location of the top-level macro caller. |
||
1787 | SourceLocation getTopMacroCallerLoc(SourceLocation Loc) const; |
||
1788 | |||
1789 | private: |
||
1790 | friend class ASTReader; |
||
1791 | friend class ASTWriter; |
||
1792 | |||
1793 | llvm::MemoryBufferRef getFakeBufferForRecovery() const; |
||
1794 | SrcMgr::ContentCache &getFakeContentCacheForRecovery() const; |
||
1795 | |||
1796 | const SrcMgr::SLocEntry &loadSLocEntry(unsigned Index, bool *Invalid) const; |
||
1797 | |||
1798 | const SrcMgr::SLocEntry *getSLocEntryOrNull(FileID FID) const { |
||
1799 | bool Invalid = false; |
||
1800 | const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid); |
||
1801 | return Invalid ? nullptr : &Entry; |
||
1802 | } |
||
1803 | |||
1804 | const SrcMgr::SLocEntry *getSLocEntryForFile(FileID FID) const { |
||
1805 | if (auto *Entry = getSLocEntryOrNull(FID)) |
||
1806 | if (Entry->isFile()) |
||
1807 | return Entry; |
||
1808 | return nullptr; |
||
1809 | } |
||
1810 | |||
1811 | /// Get the entry with the given unwrapped FileID. |
||
1812 | /// Invalid will not be modified for Local IDs. |
||
1813 | const SrcMgr::SLocEntry &getSLocEntryByID(int ID, |
||
1814 | bool *Invalid = nullptr) const { |
||
1815 | assert(ID != -1 && "Using FileID sentinel value"); |
||
1816 | if (ID < 0) |
||
1817 | return getLoadedSLocEntryByID(ID, Invalid); |
||
1818 | return getLocalSLocEntry(static_cast<unsigned>(ID)); |
||
1819 | } |
||
1820 | |||
1821 | const SrcMgr::SLocEntry & |
||
1822 | getLoadedSLocEntryByID(int ID, bool *Invalid = nullptr) const { |
||
1823 | return getLoadedSLocEntry(static_cast<unsigned>(-ID - 2), Invalid); |
||
1824 | } |
||
1825 | |||
1826 | FileID getFileID(SourceLocation::UIntTy SLocOffset) const { |
||
1827 | // If our one-entry cache covers this offset, just return it. |
||
1828 | if (isOffsetInFileID(LastFileIDLookup, SLocOffset)) |
||
1829 | return LastFileIDLookup; |
||
1830 | |||
1831 | return getFileIDSlow(SLocOffset); |
||
1832 | } |
||
1833 | |||
1834 | bool isLocalOffset(SourceLocation::UIntTy SLocOffset) const { |
||
1835 | return SLocOffset < CurrentLoadedOffset; |
||
1836 | } |
||
1837 | |||
1838 | bool isLoadedOffset(SourceLocation::UIntTy SLocOffset) const { |
||
1839 | return SLocOffset >= CurrentLoadedOffset; |
||
1840 | } |
||
1841 | |||
1842 | /// Implements the common elements of storing an expansion info struct into |
||
1843 | /// the SLocEntry table and producing a source location that refers to it. |
||
1844 | SourceLocation |
||
1845 | createExpansionLocImpl(const SrcMgr::ExpansionInfo &Expansion, |
||
1846 | unsigned Length, int LoadedID = 0, |
||
1847 | SourceLocation::UIntTy LoadedOffset = 0); |
||
1848 | |||
1849 | /// Return true if the specified FileID contains the |
||
1850 | /// specified SourceLocation offset. This is a very hot method. |
||
1851 | inline bool isOffsetInFileID(FileID FID, |
||
1852 | SourceLocation::UIntTy SLocOffset) const { |
||
1853 | const SrcMgr::SLocEntry &Entry = getSLocEntry(FID); |
||
1854 | // If the entry is after the offset, it can't contain it. |
||
1855 | if (SLocOffset < Entry.getOffset()) return false; |
||
1856 | |||
1857 | // If this is the very last entry then it does. |
||
1858 | if (FID.ID == -2) |
||
1859 | return true; |
||
1860 | |||
1861 | // If it is the last local entry, then it does if the location is local. |
||
1862 | if (FID.ID+1 == static_cast<int>(LocalSLocEntryTable.size())) |
||
1863 | return SLocOffset < NextLocalOffset; |
||
1864 | |||
1865 | // Otherwise, the entry after it has to not include it. This works for both |
||
1866 | // local and loaded entries. |
||
1867 | return SLocOffset < getSLocEntryByID(FID.ID+1).getOffset(); |
||
1868 | } |
||
1869 | |||
1870 | /// Returns the previous in-order FileID or an invalid FileID if there |
||
1871 | /// is no previous one. |
||
1872 | FileID getPreviousFileID(FileID FID) const; |
||
1873 | |||
1874 | /// Returns the next in-order FileID or an invalid FileID if there is |
||
1875 | /// no next one. |
||
1876 | FileID getNextFileID(FileID FID) const; |
||
1877 | |||
1878 | /// Create a new fileID for the specified ContentCache and |
||
1879 | /// include position. |
||
1880 | /// |
||
1881 | /// This works regardless of whether the ContentCache corresponds to a |
||
1882 | /// file or some other input source. |
||
1883 | FileID createFileIDImpl(SrcMgr::ContentCache &File, StringRef Filename, |
||
1884 | SourceLocation IncludePos, |
||
1885 | SrcMgr::CharacteristicKind DirCharacter, int LoadedID, |
||
1886 | SourceLocation::UIntTy LoadedOffset); |
||
1887 | |||
1888 | SrcMgr::ContentCache &getOrCreateContentCache(FileEntryRef SourceFile, |
||
1889 | bool isSystemFile = false); |
||
1890 | |||
1891 | /// Create a new ContentCache for the specified memory buffer. |
||
1892 | SrcMgr::ContentCache & |
||
1893 | createMemBufferContentCache(std::unique_ptr<llvm::MemoryBuffer> Buf); |
||
1894 | |||
1895 | FileID getFileIDSlow(SourceLocation::UIntTy SLocOffset) const; |
||
1896 | FileID getFileIDLocal(SourceLocation::UIntTy SLocOffset) const; |
||
1897 | FileID getFileIDLoaded(SourceLocation::UIntTy SLocOffset) const; |
||
1898 | |||
1899 | SourceLocation getExpansionLocSlowCase(SourceLocation Loc) const; |
||
1900 | SourceLocation getSpellingLocSlowCase(SourceLocation Loc) const; |
||
1901 | SourceLocation getFileLocSlowCase(SourceLocation Loc) const; |
||
1902 | |||
1903 | std::pair<FileID, unsigned> |
||
1904 | getDecomposedExpansionLocSlowCase(const SrcMgr::SLocEntry *E) const; |
||
1905 | std::pair<FileID, unsigned> |
||
1906 | getDecomposedSpellingLocSlowCase(const SrcMgr::SLocEntry *E, |
||
1907 | unsigned Offset) const; |
||
1908 | void computeMacroArgsCache(MacroArgsMap &MacroArgsCache, FileID FID) const; |
||
1909 | void associateFileChunkWithMacroArgExp(MacroArgsMap &MacroArgsCache, |
||
1910 | FileID FID, |
||
1911 | SourceLocation SpellLoc, |
||
1912 | SourceLocation ExpansionLoc, |
||
1913 | unsigned ExpansionLength) const; |
||
1914 | }; |
||
1915 | |||
1916 | /// Comparison function object. |
||
1917 | template<typename T> |
||
1918 | class BeforeThanCompare; |
||
1919 | |||
1920 | /// Compare two source locations. |
||
1921 | template<> |
||
1922 | class BeforeThanCompare<SourceLocation> { |
||
1923 | SourceManager &SM; |
||
1924 | |||
1925 | public: |
||
1926 | explicit BeforeThanCompare(SourceManager &SM) : SM(SM) {} |
||
1927 | |||
1928 | bool operator()(SourceLocation LHS, SourceLocation RHS) const { |
||
1929 | return SM.isBeforeInTranslationUnit(LHS, RHS); |
||
1930 | } |
||
1931 | }; |
||
1932 | |||
1933 | /// Compare two non-overlapping source ranges. |
||
1934 | template<> |
||
1935 | class BeforeThanCompare<SourceRange> { |
||
1936 | SourceManager &SM; |
||
1937 | |||
1938 | public: |
||
1939 | explicit BeforeThanCompare(SourceManager &SM) : SM(SM) {} |
||
1940 | |||
1941 | bool operator()(SourceRange LHS, SourceRange RHS) const { |
||
1942 | return SM.isBeforeInTranslationUnit(LHS.getBegin(), RHS.getBegin()); |
||
1943 | } |
||
1944 | }; |
||
1945 | |||
1946 | /// SourceManager and necessary dependencies (e.g. VFS, FileManager) for a |
||
1947 | /// single in-memorty file. |
||
1948 | class SourceManagerForFile { |
||
1949 | public: |
||
1950 | /// Creates SourceManager and necessary dependencies (e.g. VFS, FileManager). |
||
1951 | /// The main file in the SourceManager will be \p FileName with \p Content. |
||
1952 | SourceManagerForFile(StringRef FileName, StringRef Content); |
||
1953 | |||
1954 | SourceManager &get() { |
||
1955 | assert(SourceMgr); |
||
1956 | return *SourceMgr; |
||
1957 | } |
||
1958 | |||
1959 | private: |
||
1960 | // The order of these fields are important - they should be in the same order |
||
1961 | // as they are created in `createSourceManagerForFile` so that they can be |
||
1962 | // deleted in the reverse order as they are created. |
||
1963 | std::unique_ptr<FileManager> FileMgr; |
||
1964 | std::unique_ptr<DiagnosticsEngine> Diagnostics; |
||
1965 | std::unique_ptr<SourceManager> SourceMgr; |
||
1966 | }; |
||
1967 | |||
1968 | } // namespace clang |
||
1969 | |||
1970 | #endif // LLVM_CLANG_BASIC_SOURCEMANAGER_H |