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