clang 23.0.0git
SourceManager.cpp
Go to the documentation of this file.
1//===- SourceManager.cpp - Track and cache source files -------------------===//
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// This file implements the SourceManager interface.
10//
11//===----------------------------------------------------------------------===//
12
16#include "clang/Basic/LLVM.h"
19#include "llvm/ADT/DenseMap.h"
20#include "llvm/ADT/MapVector.h"
21#include "llvm/ADT/STLExtras.h"
22#include "llvm/ADT/SmallVector.h"
23#include "llvm/ADT/Statistic.h"
24#include "llvm/ADT/StringRef.h"
25#include "llvm/ADT/StringSwitch.h"
26#include "llvm/Support/Allocator.h"
27#include "llvm/Support/AutoConvert.h"
28#include "llvm/Support/Capacity.h"
29#include "llvm/Support/Compiler.h"
30#include "llvm/Support/Endian.h"
31#include "llvm/Support/ErrorHandling.h"
32#include "llvm/Support/MemoryBuffer.h"
33#include "llvm/Support/Path.h"
34#include "llvm/Support/raw_ostream.h"
35#include <algorithm>
36#include <cassert>
37#include <cstddef>
38#include <cstdint>
39#include <memory>
40#include <optional>
41#include <string>
42#include <tuple>
43#include <utility>
44#include <vector>
45
46using namespace clang;
47using namespace SrcMgr;
48using llvm::MemoryBuffer;
49
50#define DEBUG_TYPE "source-manager"
51
52static SrcMgr::ContentCache *cloneContentCache(llvm::BumpPtrAllocator &Alloc,
53 const ContentCache &Other) {
54 auto *Clone = new (Alloc.Allocate<ContentCache>()) ContentCache;
55 Clone->OrigEntry = Other.OrigEntry;
56 Clone->ContentsEntry = Other.ContentsEntry;
57 Clone->Filename = Other.Filename;
58 Clone->BufferOverridden = Other.BufferOverridden;
59 Clone->IsFileVolatile = Other.IsFileVolatile;
60 Clone->IsTransient = Other.IsTransient;
61 Clone->IsBufferInvalid = Other.IsBufferInvalid;
62 Clone->setUnownedBuffer(Other.getBufferIfLoaded());
63 return Clone;
64}
65
66// Reaching a limit of 2^31 results in a hard error. This metric allows to track
67// if particular invocation of the compiler is close to it.
68STATISTIC(MaxUsedSLocBytes, "Maximum number of bytes used by source locations "
69 "(both loaded and local).");
70
71//===----------------------------------------------------------------------===//
72// SourceManager Helper Classes
73//===----------------------------------------------------------------------===//
74
75/// getSizeBytesMapped - Returns the number of bytes actually mapped for this
76/// ContentCache. This can be 0 if the MemBuffer was not actually expanded.
78 return Buffer ? Buffer->getBufferSize() : 0;
79}
80
81/// Returns the kind of memory used to back the memory buffer for
82/// this content cache. This is used for performance analysis.
83llvm::MemoryBuffer::BufferKind ContentCache::getMemoryBufferKind() const {
84 if (Buffer == nullptr) {
85 assert(0 && "Buffer should never be null");
86 return llvm::MemoryBuffer::MemoryBuffer_Malloc;
87 }
88 return Buffer->getBufferKind();
89}
90
91/// getSize - Returns the size of the content encapsulated by this ContentCache.
92/// This can be the size of the source file or the size of an arbitrary
93/// scratch buffer. If the ContentCache encapsulates a source file, that
94/// file is not lazily brought in from disk to satisfy this query.
95unsigned ContentCache::getSize() const {
96 return Buffer ? (unsigned)Buffer->getBufferSize()
97 : (unsigned)ContentsEntry->getSize();
98}
99
100const char *ContentCache::getInvalidBOM(StringRef BufStr) {
101 // If the buffer is valid, check to see if it has a UTF Byte Order Mark
102 // (BOM). We only support UTF-8 with and without a BOM right now. See
103 // http://en.wikipedia.org/wiki/Byte_order_mark for more information.
104 const char *InvalidBOM =
105 llvm::StringSwitch<const char *>(BufStr)
106 .StartsWith(llvm::StringLiteral::withInnerNUL("\x00\x00\xFE\xFF"),
107 "UTF-32 (BE)")
108 .StartsWith(llvm::StringLiteral::withInnerNUL("\xFF\xFE\x00\x00"),
109 "UTF-32 (LE)")
110 .StartsWith("\xFE\xFF", "UTF-16 (BE)")
111 .StartsWith("\xFF\xFE", "UTF-16 (LE)")
112 .StartsWith("\x2B\x2F\x76", "UTF-7")
113 .StartsWith("\xF7\x64\x4C", "UTF-1")
114 .StartsWith("\xDD\x73\x66\x73", "UTF-EBCDIC")
115 .StartsWith("\x0E\xFE\xFF", "SCSU")
116 .StartsWith("\xFB\xEE\x28", "BOCU-1")
117 .StartsWith("\x84\x31\x95\x33", "GB-18030")
118 .Default(nullptr);
119
120 return InvalidBOM;
121}
122
123std::optional<llvm::MemoryBufferRef>
125 SourceLocation Loc) const {
126 // Lazily create the Buffer for ContentCaches that wrap files. If we already
127 // computed it, just return what we have.
128 if (IsBufferInvalid)
129 return std::nullopt;
130 if (Buffer)
131 return Buffer->getMemBufferRef();
132 if (!ContentsEntry)
133 return std::nullopt;
134
135 // Start with the assumption that the buffer is invalid to simplify early
136 // return paths.
137 IsBufferInvalid = true;
138
139 auto BufferOrError = FM.getBufferForFile(*ContentsEntry, IsFileVolatile);
140
141 // If we were unable to open the file, then we are in an inconsistent
142 // situation where the content cache referenced a file which no longer
143 // exists. Most likely, we were using a stat cache with an invalid entry but
144 // the file could also have been removed during processing. Since we can't
145 // really deal with this situation, just create an empty buffer.
146 if (!BufferOrError) {
147 Diag.Report(Loc, diag::err_cannot_open_file)
148 << ContentsEntry->getName() << BufferOrError.getError().message();
149
150 return std::nullopt;
151 }
152
153 Buffer = std::move(*BufferOrError);
154
155 // Check that the file's size fits in an 'unsigned' (with room for a
156 // past-the-end value). This is deeply regrettable, but various parts of
157 // Clang (including elsewhere in this file!) use 'unsigned' to represent file
158 // offsets, line numbers, string literal lengths, and so on, and fail
159 // miserably on large source files.
160 //
161 // Note: ContentsEntry could be a named pipe, in which case
162 // ContentsEntry::getSize() could have the wrong size. Use
163 // MemoryBuffer::getBufferSize() instead.
164 if (Buffer->getBufferSize() >= std::numeric_limits<unsigned>::max()) {
165 Diag.Report(Loc, diag::err_file_too_large) << ContentsEntry->getName();
166
167 return std::nullopt;
168 }
169
170 // Unless this is a named pipe (in which case we can handle a mismatch),
171 // check that the file's size is the same as in the file entry (which may
172 // have come from a stat cache).
173 // The buffer will always be larger than the file size on z/OS in the presence
174 // of characters outside the base character set.
175 assert(Buffer->getBufferSize() >= (size_t)ContentsEntry->getSize());
176 if (!ContentsEntry->isNamedPipe() &&
177 Buffer->getBufferSize() < (size_t)ContentsEntry->getSize()) {
178 Diag.Report(Loc, diag::err_file_modified) << ContentsEntry->getName();
179
180 return std::nullopt;
181 }
182
183 // If the buffer is valid, check to see if it has a UTF Byte Order Mark
184 // (BOM). We only support UTF-8 with and without a BOM right now. See
185 // http://en.wikipedia.org/wiki/Byte_order_mark for more information.
186 StringRef BufStr = Buffer->getBuffer();
187 const char *InvalidBOM = getInvalidBOM(BufStr);
188
189 if (InvalidBOM) {
190 Diag.Report(Loc, diag::err_unsupported_bom)
191 << InvalidBOM << ContentsEntry->getName();
192 return std::nullopt;
193 }
194
195 // Buffer has been validated.
196 IsBufferInvalid = false;
197 return Buffer->getMemBufferRef();
198}
199
201 auto IterBool = FilenameIDs.try_emplace(Name, FilenamesByID.size());
202 if (IterBool.second)
203 FilenamesByID.push_back(&*IterBool.first);
204 return IterBool.first->second;
205}
206
207/// Add a line note to the line table that indicates that there is a \#line or
208/// GNU line marker at the specified FID/Offset location which changes the
209/// presumed location to LineNo/FilenameID. If EntryExit is 0, then this doesn't
210/// change the presumed \#include stack. If it is 1, this is a file entry, if
211/// it is 2 then this is a file exit. FileKind specifies whether this is a
212/// system header or extern C system header.
213void LineTableInfo::AddLineNote(FileID FID, unsigned Offset, unsigned LineNo,
214 int FilenameID, unsigned EntryExit,
216 std::vector<LineEntry> &Entries = LineEntries[FID];
217
218 assert((Entries.empty() || Entries.back().FileOffset < Offset) &&
219 "Adding line entries out of order!");
220
221 unsigned IncludeOffset = 0;
222 if (EntryExit == 1) {
223 // Push #include
224 IncludeOffset = Offset-1;
225 } else {
226 const auto *PrevEntry = Entries.empty() ? nullptr : &Entries.back();
227 if (EntryExit == 2) {
228 // Pop #include
229 assert(PrevEntry && PrevEntry->IncludeOffset &&
230 "PPDirectives should have caught case when popping empty include "
231 "stack");
232 PrevEntry = FindNearestLineEntry(FID, PrevEntry->IncludeOffset);
233 }
234 if (PrevEntry) {
235 IncludeOffset = PrevEntry->IncludeOffset;
236 if (FilenameID == -1) {
237 // An unspecified FilenameID means use the previous (or containing)
238 // filename if available, or the main source file otherwise.
239 FilenameID = PrevEntry->FilenameID;
240 }
241 }
242 }
243
244 Entries.push_back(LineEntry::get(Offset, LineNo, FilenameID, FileKind,
245 IncludeOffset));
246}
247
248/// FindNearestLineEntry - Find the line entry nearest to FID that is before
249/// it. If there is no line entry before Offset in FID, return null.
251 unsigned Offset) {
252 const std::vector<LineEntry> &Entries = LineEntries[FID];
253 assert(!Entries.empty() && "No #line entries for this FID after all!");
254
255 // It is very common for the query to be after the last #line, check this
256 // first.
257 if (Entries.back().FileOffset <= Offset)
258 return &Entries.back();
259
260 // Do a binary search to find the maximal element that is still before Offset.
261 std::vector<LineEntry>::const_iterator I = llvm::upper_bound(Entries, Offset);
262 if (I == Entries.begin())
263 return nullptr;
264 return &*--I;
265}
266
267/// Add a new line entry that has already been encoded into
268/// the internal representation of the line table.
270 const std::vector<LineEntry> &Entries) {
271 LineEntries[FID] = Entries;
272}
273
274/// getLineTableFilenameID - Return the uniqued ID for the specified filename.
276 return getLineTable().getLineTableFilenameID(Name);
277}
278
279/// AddLineNote - Add a line note to the line table for the FileID and offset
280/// specified by Loc. If FilenameID is -1, it is considered to be
281/// unspecified.
283 int FilenameID, bool IsFileEntry,
284 bool IsFileExit,
287
288 bool Invalid = false;
289 SLocEntry &Entry = getSLocEntry(LocInfo.first, &Invalid);
290 if (!Entry.isFile() || Invalid)
291 return;
292
294
295 // Remember that this file has #line directives now if it doesn't already.
297
298 (void) getLineTable();
299
300 unsigned EntryExit = 0;
301 if (IsFileEntry)
302 EntryExit = 1;
303 else if (IsFileExit)
304 EntryExit = 2;
305
306 LineTable->AddLineNote(LocInfo.first, LocInfo.second, LineNo, FilenameID,
307 EntryExit, FileKind);
308}
309
311 if (!LineTable)
312 LineTable.reset(new LineTableInfo());
313 return *LineTable;
314}
315
316//===----------------------------------------------------------------------===//
317// Private 'Create' methods.
318//===----------------------------------------------------------------------===//
319
321 bool UserFilesAreVolatile)
322 : Diag(Diag), FileMgr(FileMgr), UserFilesAreVolatile(UserFilesAreVolatile) {
324 Diag.setSourceManager(this);
325}
326
328 // Delete FileEntry objects corresponding to content caches. Since the actual
329 // content cache objects are bump pointer allocated, we just have to run the
330 // dtors, but we call the deallocate method for completeness.
331 for (unsigned i = 0, e = MemBufferInfos.size(); i != e; ++i) {
332 if (MemBufferInfos[i]) {
333 MemBufferInfos[i]->~ContentCache();
334 ContentCacheAlloc.Deallocate(MemBufferInfos[i]);
335 }
336 }
337 for (auto I = FileInfos.begin(), E = FileInfos.end(); I != E; ++I) {
338 if (I->second) {
339 I->second->~ContentCache();
340 ContentCacheAlloc.Deallocate(I->second);
341 }
342 }
343 for (unsigned i = 0, e = FileIDContentCaches.size(); i != e; ++i) {
344 if (FileIDContentCaches[i]) {
345 FileIDContentCaches[i]->~ContentCache();
346 ContentCacheAlloc.Deallocate(FileIDContentCaches[i]);
347 }
348 }
349}
350
352 for (unsigned i = 0, e = FileIDContentCaches.size(); i != e; ++i) {
353 if (FileIDContentCaches[i]) {
354 FileIDContentCaches[i]->~ContentCache();
355 ContentCacheAlloc.Deallocate(FileIDContentCaches[i]);
356 }
357 }
358 FileIDContentCaches.clear();
359
360 MainFileID = FileID();
361 LocalSLocEntryTable.clear();
362 LocalLocOffsetTable.clear();
363 LoadedSLocEntryTable.clear();
364 SLocEntryLoaded.clear();
365 SLocEntryOffsetLoaded.clear();
366 LastLineNoFileIDQuery = FileID();
367 LastLineNoContentCache = nullptr;
368 LastFileIDLookup = FileID();
369 LastLookupStartOffset = LastLookupEndOffset = 0;
370
371 IncludedLocMap.clear();
372 if (LineTable)
373 LineTable->clear();
374
375 // Use up FileID #0 as an invalid expansion.
376 NextLocalOffset = 0;
377 CurrentLoadedOffset = MaxLoadedOffset;
379 // Diagnostics engine keeps some references to fileids, mostly for dealing
380 // with diagnostic pragmas, make sure they're reset as well.
381 Diag.ResetPragmas();
382}
383
384bool SourceManager::isMainFile(const FileEntry &SourceFile) {
385 assert(MainFileID.isValid() && "expected initialized SourceManager");
386 if (auto *FE = getFileEntryForID(MainFileID))
387 return FE->getUID() == SourceFile.getUID();
388 return false;
389}
390
392 assert(MainFileID.isInvalid() && "expected uninitialized SourceManager");
393
394 // Ensure all SLocEntries are loaded from the external source.
395 for (unsigned I = 0, N = Old.LoadedSLocEntryTable.size(); I != N; ++I)
396 if (!Old.SLocEntryLoaded[I])
397 Old.loadSLocEntry(I, nullptr);
398
399 // Inherit any content cache data from the old source manager.
400 for (auto &FileInfo : Old.FileInfos) {
401 SrcMgr::ContentCache *&Slot = FileInfos[FileInfo.first];
402 if (Slot)
403 continue;
404 Slot = cloneContentCache(ContentCacheAlloc, *FileInfo.second);
405 }
406}
407
408ContentCache &SourceManager::getOrCreateContentCache(FileEntryRef FileEnt,
409 bool isSystemFile) {
410 // Do we already have information about this file?
411 ContentCache *&Entry = FileInfos[FileEnt];
412 if (Entry)
413 return *Entry;
414
415 // Nope, create a new Cache entry.
416 Entry = ContentCacheAlloc.Allocate<ContentCache>();
417
418 if (OverriddenFilesInfo) {
419 // If the file contents are overridden with contents from another file,
420 // pass that file to ContentCache.
421 auto overI = OverriddenFilesInfo->OverriddenFiles.find(FileEnt);
422 if (overI == OverriddenFilesInfo->OverriddenFiles.end())
423 new (Entry) ContentCache(FileEnt);
424 else
425 new (Entry) ContentCache(OverridenFilesKeepOriginalName ? FileEnt
426 : overI->second,
427 overI->second);
428 } else {
429 new (Entry) ContentCache(FileEnt);
430 }
431
432 Entry->IsFileVolatile = UserFilesAreVolatile && !isSystemFile;
433 Entry->IsTransient = FilesAreTransient;
434 Entry->BufferOverridden |= FileEnt.isNamedPipe();
435
436 return *Entry;
437}
438
439/// Create a new ContentCache for the specified memory buffer.
440/// This does no caching.
441ContentCache &SourceManager::createMemBufferContentCache(
442 std::unique_ptr<llvm::MemoryBuffer> Buffer) {
443 // Add a new ContentCache to the MemBufferInfos list and return it.
444 ContentCache *Entry = ContentCacheAlloc.Allocate<ContentCache>();
445 new (Entry) ContentCache();
446 MemBufferInfos.push_back(Entry);
447 Entry->setBuffer(std::move(Buffer));
448 return *Entry;
449}
450
451const SrcMgr::SLocEntry &SourceManager::loadSLocEntry(unsigned Index,
452 bool *Invalid) const {
453 return const_cast<SourceManager *>(this)->loadSLocEntry(Index, Invalid);
454}
455
456SrcMgr::SLocEntry &SourceManager::loadSLocEntry(unsigned Index, bool *Invalid) {
457 assert(!SLocEntryLoaded[Index]);
458 if (ExternalSLocEntries->ReadSLocEntry(-(static_cast<int>(Index) + 2))) {
459 if (Invalid)
460 *Invalid = true;
461 // If the file of the SLocEntry changed we could still have loaded it.
462 if (!SLocEntryLoaded[Index]) {
463 // Try to recover; create a SLocEntry so the rest of clang can handle it.
464 if (!FakeSLocEntryForRecovery)
465 FakeSLocEntryForRecovery = std::make_unique<SLocEntry>(SLocEntry::get(
466 0, FileInfo::get(SourceLocation(), getFakeContentCacheForRecovery(),
467 SrcMgr::C_User, "")));
468 return *FakeSLocEntryForRecovery;
469 }
470 }
471
472 return LoadedSLocEntryTable[Index];
473}
474
475std::pair<int, SourceLocation::UIntTy>
477 SourceLocation::UIntTy TotalSize) {
478 assert(ExternalSLocEntries && "Don't have an external sloc source");
479 // Make sure we're not about to run out of source locations.
480 if (CurrentLoadedOffset < TotalSize ||
481 CurrentLoadedOffset - TotalSize < NextLocalOffset) {
482 return std::make_pair(0, 0);
483 }
484 LoadedSLocEntryTable.resize(LoadedSLocEntryTable.size() + NumSLocEntries);
485 SLocEntryLoaded.resize(LoadedSLocEntryTable.size());
486 SLocEntryOffsetLoaded.resize(LoadedSLocEntryTable.size());
487 CurrentLoadedOffset -= TotalSize;
488 updateSlocUsageStats();
489 int BaseID = -int(LoadedSLocEntryTable.size()) - 1;
490 LoadedSLocEntryAllocBegin.push_back(FileID::get(BaseID));
491 return std::make_pair(BaseID, CurrentLoadedOffset);
492}
493
494/// As part of recovering from missing or changed content, produce a
495/// fake, non-empty buffer.
496llvm::MemoryBufferRef SourceManager::getFakeBufferForRecovery() const {
497 if (!FakeBufferForRecovery)
498 FakeBufferForRecovery =
499 llvm::MemoryBuffer::getMemBuffer("<<<INVALID BUFFER>>");
500
501 return *FakeBufferForRecovery;
502}
503
504/// As part of recovering from missing or changed content, produce a
505/// fake content cache.
506SrcMgr::ContentCache &SourceManager::getFakeContentCacheForRecovery() const {
507 if (!FakeContentCacheForRecovery) {
508 FakeContentCacheForRecovery = std::make_unique<SrcMgr::ContentCache>();
509 FakeContentCacheForRecovery->setUnownedBuffer(getFakeBufferForRecovery());
510 }
511 return *FakeContentCacheForRecovery;
512}
513
514/// Returns the previous in-order FileID or an invalid FileID if there
515/// is no previous one.
516FileID SourceManager::getPreviousFileID(FileID FID) const {
517 if (FID.isInvalid())
518 return FileID();
519
520 int ID = FID.ID;
521 if (ID == -1)
522 return FileID();
523
524 if (ID > 0) {
525 if (ID-1 == 0)
526 return FileID();
527 } else if (unsigned(-(ID-1) - 2) >= LoadedSLocEntryTable.size()) {
528 return FileID();
529 }
530
531 return FileID::get(ID-1);
532}
533
534/// Returns the next in-order FileID or an invalid FileID if there is
535/// no next one.
536FileID SourceManager::getNextFileID(FileID FID) const {
537 if (FID.isInvalid())
538 return FileID();
539
540 int ID = FID.ID;
541 if (ID > 0) {
542 if (unsigned(ID+1) >= local_sloc_entry_size())
543 return FileID();
544 } else if (ID+1 >= -1) {
545 return FileID();
546 }
547
548 return FileID::get(ID+1);
549}
550
551//===----------------------------------------------------------------------===//
552// Methods to create new FileID's and macro expansions.
553//===----------------------------------------------------------------------===//
554
555/// Create a new FileID that represents the specified file
556/// being \#included from the specified IncludePosition.
558 SourceLocation IncludePos,
559 SrcMgr::CharacteristicKind FileCharacter,
560 int LoadedID,
561 SourceLocation::UIntTy LoadedOffset) {
562 SrcMgr::ContentCache &IR = getOrCreateContentCache(SourceFile,
563 isSystem(FileCharacter));
565 StringRef Filename = SourceFile.getName();
566
567 if (IR.OrigEntry && !IR.OrigEntry->isSameRef(SourceFile)) {
568 Cache = cloneContentCache(ContentCacheAlloc, IR);
569 Cache->OrigEntry = SourceFile;
570 FileIDContentCaches.push_back(Cache);
571 }
572
573 // If this is a named pipe, immediately load the buffer to ensure subsequent
574 // calls to ContentCache::getSize() are accurate.
575 if (Cache->ContentsEntry->isNamedPipe())
576 (void)Cache->getBufferOrNone(Diag, getFileManager(), SourceLocation());
577
578 return createFileIDImpl(*Cache, Filename, IncludePos, FileCharacter, LoadedID,
579 LoadedOffset);
580}
581
582/// Create a new FileID that represents the specified memory buffer.
583///
584/// This does no caching of the buffer and takes ownership of the
585/// MemoryBuffer, so only pass a MemoryBuffer to this once.
586FileID SourceManager::createFileID(std::unique_ptr<llvm::MemoryBuffer> Buffer,
587 SrcMgr::CharacteristicKind FileCharacter,
588 int LoadedID,
589 SourceLocation::UIntTy LoadedOffset,
590 SourceLocation IncludeLoc) {
591 StringRef Name = Buffer->getBufferIdentifier();
592 return createFileIDImpl(createMemBufferContentCache(std::move(Buffer)), Name,
593 IncludeLoc, FileCharacter, LoadedID, LoadedOffset);
594}
595
596/// Create a new FileID that represents the specified memory buffer.
597///
598/// This does not take ownership of the MemoryBuffer. The memory buffer must
599/// outlive the SourceManager.
600FileID SourceManager::createFileID(const llvm::MemoryBufferRef &Buffer,
601 SrcMgr::CharacteristicKind FileCharacter,
602 int LoadedID,
603 SourceLocation::UIntTy LoadedOffset,
604 SourceLocation IncludeLoc) {
605 return createFileID(llvm::MemoryBuffer::getMemBuffer(Buffer), FileCharacter,
606 LoadedID, LoadedOffset, IncludeLoc);
607}
608
609/// Get the FileID for \p SourceFile if it exists. Otherwise, create a
610/// new FileID for the \p SourceFile.
611FileID
613 SrcMgr::CharacteristicKind FileCharacter) {
614 FileID ID = translateFile(SourceFile);
615 return ID.isValid() ? ID : createFileID(SourceFile, SourceLocation(),
616 FileCharacter);
617}
618
619/// createFileID - Create a new FileID for the specified ContentCache and
620/// include position. This works regardless of whether the ContentCache
621/// corresponds to a file or some other input source.
622FileID SourceManager::createFileIDImpl(ContentCache &File, StringRef Filename,
623 SourceLocation IncludePos,
624 SrcMgr::CharacteristicKind FileCharacter,
625 int LoadedID,
626 SourceLocation::UIntTy LoadedOffset) {
627 if (LoadedID < 0) {
628 assert(LoadedID != -1 && "Loading sentinel FileID");
629 unsigned Index = unsigned(-LoadedID) - 2;
630 assert(Index < LoadedSLocEntryTable.size() && "FileID out of range");
631 assert(!SLocEntryLoaded[Index] && "FileID already loaded");
632 LoadedSLocEntryTable[Index] = SLocEntry::get(
633 LoadedOffset, FileInfo::get(IncludePos, File, FileCharacter, Filename));
634 SLocEntryLoaded[Index] = SLocEntryOffsetLoaded[Index] = true;
635 return FileID::get(LoadedID);
636 }
637 unsigned FileSize = File.getSize();
638 llvm::ErrorOr<bool> NeedConversion = llvm::needConversion(Filename);
639 if (NeedConversion && *NeedConversion) {
640 // Buffer size may increase due to potential z/OS EBCDIC to UTF-8
641 // conversion.
642 if (std::optional<llvm::MemoryBufferRef> Buffer =
643 File.getBufferOrNone(Diag, getFileManager())) {
644 unsigned BufSize = Buffer->getBufferSize();
645 if (BufSize > FileSize) {
646 if (File.ContentsEntry.has_value())
647 File.ContentsEntry->updateFileEntryBufferSize(BufSize);
648 FileSize = BufSize;
649 }
650 }
651 }
652 if (!(NextLocalOffset + FileSize + 1 > NextLocalOffset &&
653 NextLocalOffset + FileSize + 1 <= CurrentLoadedOffset)) {
654 Diag.Report(IncludePos, diag::err_sloc_space_too_large);
656 return FileID();
657 }
658 assert(LocalSLocEntryTable.size() == LocalLocOffsetTable.size());
659 LocalSLocEntryTable.push_back(
660 SLocEntry::get(NextLocalOffset,
661 FileInfo::get(IncludePos, File, FileCharacter, Filename)));
662 LocalLocOffsetTable.push_back(NextLocalOffset);
663 LastLookupStartOffset = NextLocalOffset;
664 // We do a +1 here because we want a SourceLocation that means "the end of the
665 // file", e.g. for the "no newline at the end of the file" diagnostic.
666 NextLocalOffset += FileSize + 1;
667 LastLookupEndOffset = NextLocalOffset;
668 updateSlocUsageStats();
669
670 // Set LastFileIDLookup to the newly created file. The next getFileID call is
671 // almost guaranteed to be from that file.
672 FileID FID = FileID::get(LocalSLocEntryTable.size()-1);
673 return LastFileIDLookup = FID;
674}
675
677 SourceLocation SpellingLoc, SourceLocation ExpansionLoc, unsigned Length) {
679 ExpansionLoc);
680 return createExpansionLocImpl(Info, Length);
681}
682
684 SourceLocation SpellingLoc, SourceLocation ExpansionLocStart,
685 SourceLocation ExpansionLocEnd, unsigned Length,
686 bool ExpansionIsTokenRange, int LoadedID,
687 SourceLocation::UIntTy LoadedOffset) {
689 SpellingLoc, ExpansionLocStart, ExpansionLocEnd, ExpansionIsTokenRange);
690 return createExpansionLocImpl(Info, Length, LoadedID, LoadedOffset);
691}
692
694 SourceLocation TokenStart,
695 SourceLocation TokenEnd) {
696 assert(getFileID(TokenStart) == getFileID(TokenEnd) &&
697 "token spans multiple files");
698 return createExpansionLocImpl(
699 ExpansionInfo::createForTokenSplit(Spelling, TokenStart, TokenEnd),
700 TokenEnd.getOffset() - TokenStart.getOffset());
701}
702
704SourceManager::createExpansionLocImpl(const ExpansionInfo &Info,
705 unsigned Length, int LoadedID,
706 SourceLocation::UIntTy LoadedOffset) {
707 if (LoadedID < 0) {
708 assert(LoadedID != -1 && "Loading sentinel FileID");
709 unsigned Index = unsigned(-LoadedID) - 2;
710 assert(Index < LoadedSLocEntryTable.size() && "FileID out of range");
711 assert(!SLocEntryLoaded[Index] && "FileID already loaded");
712 LoadedSLocEntryTable[Index] = SLocEntry::get(LoadedOffset, Info);
713 SLocEntryLoaded[Index] = SLocEntryOffsetLoaded[Index] = true;
714 return SourceLocation::getMacroLoc(LoadedOffset);
715 }
716 assert(LocalSLocEntryTable.size() == LocalLocOffsetTable.size());
717 LocalSLocEntryTable.push_back(SLocEntry::get(NextLocalOffset, Info));
718 LocalLocOffsetTable.push_back(NextLocalOffset);
719 if (NextLocalOffset + Length + 1 <= NextLocalOffset ||
720 NextLocalOffset + Length + 1 > CurrentLoadedOffset) {
721 Diag.Report(diag::err_sloc_space_too_large);
722 // FIXME: call `noteSLocAddressSpaceUsage` to report details to users and
723 // use a source location from `Info` to point at an error.
724 // Currently, both cause Clang to run indefinitely, this needs to be fixed.
725 // FIXME: return an error instead of crashing. Returning invalid source
726 // locations causes compiler to run indefinitely.
727 llvm::report_fatal_error("ran out of source locations");
728 }
729 // See createFileID for that +1.
730 NextLocalOffset += Length + 1;
731 updateSlocUsageStats();
732 return SourceLocation::getMacroLoc(NextLocalOffset - (Length + 1));
733}
734
735std::optional<llvm::MemoryBufferRef>
740
742 FileEntryRef SourceFile, std::unique_ptr<llvm::MemoryBuffer> Buffer) {
743 SrcMgr::ContentCache &IR = getOrCreateContentCache(SourceFile);
744
745 IR.setBuffer(std::move(Buffer));
746 IR.BufferOverridden = true;
747
748 getOverriddenFilesInfo().OverriddenFilesWithBuffer.insert(SourceFile);
749}
750
752 FileEntryRef NewFile) {
753 assert(SourceFile->getSize() == NewFile.getSize() &&
754 "Different sizes, use the FileManager to create a virtual file with "
755 "the correct size");
756 assert(FileInfos.find_as(SourceFile) == FileInfos.end() &&
757 "This function should be called at the initialization stage, before "
758 "any parsing occurs.");
759 // FileEntryRef is not default-constructible.
760 auto Pair = getOverriddenFilesInfo().OverriddenFiles.insert(
761 std::make_pair(SourceFile, NewFile));
762 if (!Pair.second)
763 Pair.first->second = NewFile;
764}
765
768 assert(isFileOverridden(&File.getFileEntry()));
769 OptionalFileEntryRef BypassFile = FileMgr.getBypassFile(File);
770
771 // If the file can't be found in the FS, give up.
772 if (!BypassFile)
773 return std::nullopt;
774
775 (void)getOrCreateContentCache(*BypassFile);
776 return BypassFile;
777}
778
780 getOrCreateContentCache(File).IsTransient = true;
781}
782
783std::optional<StringRef>
785 if (const SrcMgr::SLocEntry *Entry = getSLocEntryForFile(FID))
786 if (Entry->getFile().getContentCache().OrigEntry)
787 return Entry->getFile().getName();
788 return std::nullopt;
789}
790
791StringRef SourceManager::getBufferData(FileID FID, bool *Invalid) const {
792 auto B = getBufferDataOrNone(FID);
793 if (Invalid)
794 *Invalid = !B;
795 return B ? *B : "<<<<<INVALID SOURCE LOCATION>>>>>";
796}
797
798std::optional<StringRef>
800 if (const SrcMgr::SLocEntry *Entry = getSLocEntryForFile(FID))
801 return Entry->getFile().getContentCache().getBufferDataIfLoaded();
802 return std::nullopt;
803}
804
805std::optional<StringRef> SourceManager::getBufferDataOrNone(FileID FID) const {
806 if (const SrcMgr::SLocEntry *Entry = getSLocEntryForFile(FID))
807 if (auto B = Entry->getFile().getContentCache().getBufferOrNone(
808 Diag, getFileManager(), SourceLocation()))
809 return B->getBuffer();
810 return std::nullopt;
811}
812
813//===----------------------------------------------------------------------===//
814// SourceLocation manipulation methods.
815//===----------------------------------------------------------------------===//
816
817/// Return the FileID for a SourceLocation.
818///
819/// This is the cache-miss path of getFileID. Not as hot as that function, but
820/// still very important. It is responsible for finding the entry in the
821/// SLocEntry tables that contains the specified location.
822FileID SourceManager::getFileIDSlow(SourceLocation::UIntTy SLocOffset) const {
823 if (!SLocOffset)
824 return FileID::get(0);
825
826 // Now it is time to search for the correct file. See where the SLocOffset
827 // sits in the global view and consult local or loaded buffers for it.
828 if (SLocOffset < NextLocalOffset)
829 return getFileIDLocal(SLocOffset);
830 return getFileIDLoaded(SLocOffset);
831}
832
833/// Return the FileID for a SourceLocation with a low offset.
834///
835/// This function knows that the SourceLocation is in a local buffer, not a
836/// loaded one.
837FileID SourceManager::getFileIDLocal(SourceLocation::UIntTy SLocOffset) const {
838 assert(SLocOffset < NextLocalOffset && "Bad function choice");
839 assert(SLocOffset >= LocalSLocEntryTable[0].getOffset() && SLocOffset > 0 &&
840 "Invalid SLocOffset");
841 assert(LocalSLocEntryTable.size() == LocalLocOffsetTable.size());
842 assert(LastFileIDLookup.ID >= 0 && "Only cache local file sloc entry");
843
844 // After the first and second level caches, I see two common sorts of
845 // behavior: 1) a lot of searched FileID's are "near" the cached file
846 // location or are "near" the cached expansion location. 2) others are just
847 // completely random and may be a very long way away.
848 //
849 // To handle this, we do a linear search for up to 8 steps to catch #1 quickly
850 // then we fall back to a less cache efficient, but more scalable, binary
851 // search to find the location.
852
853 // See if this is near the file point - worst case we start scanning from the
854 // most newly created FileID.
855
856 // LessIndex - This is the lower bound of the range that we're searching.
857 // We know that the offset corresponding to the FileID is less than
858 // SLocOffset.
859 unsigned LessIndex = 0;
860 // upper bound of the search range.
861 unsigned GreaterIndex = LocalLocOffsetTable.size();
862 // Use the LastFileIDLookup to prune the search space.
863 if (LastLookupStartOffset < SLocOffset)
864 LessIndex = LastFileIDLookup.ID;
865 else
866 GreaterIndex = LastFileIDLookup.ID;
867
868 // Find the FileID that contains this.
869 unsigned NumProbes = 0;
870 while (true) {
871 --GreaterIndex;
872 assert(GreaterIndex < LocalLocOffsetTable.size());
873 if (LocalLocOffsetTable[GreaterIndex] <= SLocOffset) {
874 FileID Res = FileID::get(int(GreaterIndex));
875 // Remember it. We have good locality across FileID lookups.
876 LastFileIDLookup = Res;
877 LastLookupStartOffset = LocalLocOffsetTable[GreaterIndex];
878 LastLookupEndOffset =
879 GreaterIndex + 1 >= LocalLocOffsetTable.size()
880 ? NextLocalOffset
881 : LocalLocOffsetTable[GreaterIndex + 1];
882 NumLinearScans += NumProbes + 1;
883 return Res;
884 }
885 if (++NumProbes == 8)
886 break;
887 }
888
889 while (LessIndex < GreaterIndex) {
890 ++NumBinaryProbes;
891
892 unsigned MiddleIndex = LessIndex + (GreaterIndex - LessIndex) / 2;
893 if (LocalLocOffsetTable[MiddleIndex] <= SLocOffset)
894 LessIndex = MiddleIndex + 1;
895 else
896 GreaterIndex = MiddleIndex;
897 }
898
899 // At this point, LessIndex is the index of the *first element greater than*
900 // SLocOffset. The element we are actually looking for is the one immediately
901 // before it.
902 LastLookupStartOffset = LocalLocOffsetTable[LessIndex - 1];
903 LastLookupEndOffset = LocalLocOffsetTable[LessIndex];
904 return LastFileIDLookup = FileID::get(LessIndex - 1);
905}
906
907/// Return the FileID for a SourceLocation with a high offset.
908///
909/// This function knows that the SourceLocation is in a loaded buffer, not a
910/// local one.
911FileID SourceManager::getFileIDLoaded(SourceLocation::UIntTy SLocOffset) const {
912 if (SLocOffset < CurrentLoadedOffset) {
913 assert(0 && "Invalid SLocOffset or bad function choice");
914 return FileID();
915 }
916
917 return FileID::get(ExternalSLocEntries->getSLocEntryID(SLocOffset));
918}
919
920SourceLocation SourceManager::
921getExpansionLocSlowCase(SourceLocation Loc) const {
922 do {
923 // Note: If Loc indicates an offset into a token that came from a macro
924 // expansion (e.g. the 5th character of the token) we do not want to add
925 // this offset when going to the expansion location. The expansion
926 // location is the macro invocation, which the offset has nothing to do
927 // with. This is unlike when we get the spelling loc, because the offset
928 // directly correspond to the token whose spelling we're inspecting.
930 } while (!Loc.isFileID());
931
932 return Loc;
933}
934
935SourceLocation SourceManager::getSpellingLocSlowCase(SourceLocation Loc) const {
936 do {
937 const SLocEntry &Entry = getSLocEntry(getFileID(Loc));
939 Loc.getOffset() - Entry.getOffset());
940 } while (!Loc.isFileID());
941 return Loc;
942}
943
944SourceLocation SourceManager::getFileLocSlowCase(SourceLocation Loc) const {
945 do {
946 const SLocEntry &Entry = getSLocEntry(getFileID(Loc));
947 const ExpansionInfo &ExpInfo = Entry.getExpansion();
948 if (ExpInfo.isMacroArgExpansion()) {
949 Loc = ExpInfo.getSpellingLoc().getLocWithOffset(Loc.getOffset() -
950 Entry.getOffset());
951 } else {
952 Loc = ExpInfo.getExpansionLocStart();
953 }
954 } while (!Loc.isFileID());
955 return Loc;
956}
957
958/// getImmediateSpellingLoc - Given a SourceLocation object, return the
959/// spelling location referenced by the ID. This is the first level down
960/// towards the place where the characters that make up the lexed token can be
961/// found. This should not generally be used by clients.
963 if (Loc.isFileID()) return Loc;
964 FileIDAndOffset LocInfo = getDecomposedLoc(Loc);
965 Loc = getSLocEntry(LocInfo.first).getExpansion().getSpellingLoc();
966 return Loc.getLocWithOffset(LocInfo.second);
967}
968
969/// Return the filename of the file containing a SourceLocation.
970StringRef SourceManager::getFilename(SourceLocation SpellingLoc) const {
972 return F->getName();
973 return StringRef();
974}
975
976/// getImmediateExpansionRange - Loc is required to be an expansion location.
977/// Return the start/end of the expansion information.
980 assert(Loc.isMacroID() && "Not a macro expansion loc!");
981 const ExpansionInfo &Expansion = getSLocEntry(getFileID(Loc)).getExpansion();
982 return Expansion.getExpansionLocRange();
983}
984
990
991/// getExpansionRange - Given a SourceLocation object, return the range of
992/// tokens covered by the expansion in the ultimate file.
994 if (Loc.isFileID())
995 return CharSourceRange(SourceRange(Loc, Loc), true);
996
998
999 // Fully resolve the start and end locations to their ultimate expansion
1000 // points.
1001 while (!Res.getBegin().isFileID())
1003 while (!Res.getEnd().isFileID()) {
1005 Res.setEnd(EndRange.getEnd());
1006 Res.setTokenRange(EndRange.isTokenRange());
1007 }
1008 return Res;
1009}
1010
1012 SourceLocation *StartLoc) const {
1013 if (!Loc.isMacroID()) return false;
1014
1015 FileID FID = getFileID(Loc);
1016 const SrcMgr::ExpansionInfo &Expansion = getSLocEntry(FID).getExpansion();
1017 if (!Expansion.isMacroArgExpansion()) return false;
1018
1019 if (StartLoc)
1020 *StartLoc = Expansion.getExpansionLocStart();
1021 return true;
1022}
1023
1025 if (!Loc.isMacroID()) return false;
1026
1027 FileID FID = getFileID(Loc);
1028 const SrcMgr::ExpansionInfo &Expansion = getSLocEntry(FID).getExpansion();
1029 return Expansion.isMacroBodyExpansion();
1030}
1031
1033 SourceLocation *MacroBegin) const {
1034 assert(Loc.isValid() && Loc.isMacroID() && "Expected a valid macro loc");
1035
1036 FileIDAndOffset DecompLoc = getDecomposedLoc(Loc);
1037 if (DecompLoc.second > 0)
1038 return false; // Does not point at the start of expansion range.
1039
1040 bool Invalid = false;
1041 const SrcMgr::ExpansionInfo &ExpInfo =
1042 getSLocEntry(DecompLoc.first, &Invalid).getExpansion();
1043 if (Invalid)
1044 return false;
1045 SourceLocation ExpLoc = ExpInfo.getExpansionLocStart();
1046
1047 if (ExpInfo.isMacroArgExpansion()) {
1048 // For macro argument expansions, check if the previous FileID is part of
1049 // the same argument expansion, in which case this Loc is not at the
1050 // beginning of the expansion.
1051 FileID PrevFID = getPreviousFileID(DecompLoc.first);
1052 if (!PrevFID.isInvalid()) {
1053 const SrcMgr::SLocEntry &PrevEntry = getSLocEntry(PrevFID, &Invalid);
1054 if (Invalid)
1055 return false;
1056 if (PrevEntry.isExpansion() &&
1057 PrevEntry.getExpansion().getExpansionLocStart() == ExpLoc)
1058 return false;
1059 }
1060 }
1061
1062 if (MacroBegin)
1063 *MacroBegin = ExpLoc;
1064 return true;
1065}
1066
1068 SourceLocation *MacroEnd) const {
1069 assert(Loc.isValid() && Loc.isMacroID() && "Expected a valid macro loc");
1070
1071 FileID FID = getFileID(Loc);
1072 SourceLocation NextLoc = Loc.getLocWithOffset(1);
1073 if (isInFileID(NextLoc, FID))
1074 return false; // Does not point at the end of expansion range.
1075
1076 bool Invalid = false;
1077 const SrcMgr::ExpansionInfo &ExpInfo =
1079 if (Invalid)
1080 return false;
1081
1082 if (ExpInfo.isMacroArgExpansion()) {
1083 // For macro argument expansions, check if the next FileID is part of the
1084 // same argument expansion, in which case this Loc is not at the end of the
1085 // expansion.
1086 FileID NextFID = getNextFileID(FID);
1087 if (!NextFID.isInvalid()) {
1088 const SrcMgr::SLocEntry &NextEntry = getSLocEntry(NextFID, &Invalid);
1089 if (Invalid)
1090 return false;
1091 if (NextEntry.isExpansion() &&
1092 NextEntry.getExpansion().getExpansionLocStart() ==
1093 ExpInfo.getExpansionLocStart())
1094 return false;
1095 }
1096 }
1097
1098 if (MacroEnd)
1099 *MacroEnd = ExpInfo.getExpansionLocEnd();
1100 return true;
1101}
1102
1103//===----------------------------------------------------------------------===//
1104// Queries about the code at a SourceLocation.
1105//===----------------------------------------------------------------------===//
1106
1107/// getCharacterData - Return a pointer to the start of the specified location
1108/// in the appropriate MemoryBuffer.
1110 bool *Invalid) const {
1111 // Note that this is a hot function in the getSpelling() path, which is
1112 // heavily used by -E mode.
1114
1115 // Note that calling 'getBuffer()' may lazily page in a source file.
1116 bool CharDataInvalid = false;
1117 const SLocEntry &Entry = getSLocEntry(LocInfo.first, &CharDataInvalid);
1118 if (CharDataInvalid || !Entry.isFile()) {
1119 if (Invalid)
1120 *Invalid = true;
1121
1122 return "<<<<INVALID BUFFER>>>>";
1123 }
1124 std::optional<llvm::MemoryBufferRef> Buffer =
1126 SourceLocation());
1127 if (Invalid)
1128 *Invalid = !Buffer;
1129 return Buffer ? Buffer->getBufferStart() + LocInfo.second
1130 : "<<<<INVALID BUFFER>>>>";
1131}
1132
1133/// getColumnNumber - Return the column # for the specified file position.
1134/// this is significantly cheaper to compute than the line number.
1135unsigned SourceManager::getColumnNumber(FileID FID, unsigned FilePos,
1136 bool *Invalid) const {
1137 std::optional<llvm::MemoryBufferRef> MemBuf = getBufferOrNone(FID);
1138 if (Invalid)
1139 *Invalid = !MemBuf;
1140
1141 if (!MemBuf)
1142 return 1;
1143
1144 // It is okay to request a position just past the end of the buffer.
1145 if (FilePos > MemBuf->getBufferSize()) {
1146 if (Invalid)
1147 *Invalid = true;
1148 return 1;
1149 }
1150
1151 const char *Buf = MemBuf->getBufferStart();
1152 // See if we just calculated the line number for this FilePos and can use
1153 // that to lookup the start of the line instead of searching for it.
1154 if (LastLineNoFileIDQuery == FID && LastLineNoContentCache->SourceLineCache &&
1155 LastLineNoResult < LastLineNoContentCache->SourceLineCache.size()) {
1156 const unsigned *SourceLineCache =
1157 LastLineNoContentCache->SourceLineCache.begin();
1158 unsigned LineStart = SourceLineCache[LastLineNoResult - 1];
1159 unsigned LineEnd = SourceLineCache[LastLineNoResult];
1160 if (FilePos >= LineStart && FilePos < LineEnd) {
1161 // LineEnd is the LineStart of the next line.
1162 // A line ends with separator LF or CR+LF on Windows.
1163 // FilePos might point to the last separator,
1164 // but we need a column number at most 1 + the last column.
1165 if (FilePos + 1 == LineEnd && FilePos > LineStart) {
1166 if (Buf[FilePos - 1] == '\r' || Buf[FilePos - 1] == '\n')
1167 --FilePos;
1168 }
1169 return (FilePos - LineStart) + 1;
1170 }
1171 }
1172
1173 unsigned LineStart = FilePos;
1174 while (LineStart && Buf[LineStart-1] != '\n' && Buf[LineStart-1] != '\r')
1175 --LineStart;
1176 return (FilePos - LineStart) + 1;
1177}
1178
1179// isInvalid - Return the result of calling loc.isInvalid(), and
1180// if Invalid is not null, set its value to same.
1181template<typename LocType>
1182static bool isInvalid(LocType Loc, bool *Invalid) {
1183 bool MyInvalid = Loc.isInvalid();
1184 if (Invalid)
1185 *Invalid = MyInvalid;
1186 return MyInvalid;
1187}
1188
1190 bool *Invalid) const {
1191 assert(Loc.isFileID());
1192 if (isInvalid(Loc, Invalid)) return 0;
1193 FileIDAndOffset LocInfo = getDecomposedLoc(Loc);
1194 return getColumnNumber(LocInfo.first, LocInfo.second, Invalid);
1195}
1196
1198 bool *Invalid) const {
1199 PresumedLoc PLoc = getPresumedLoc(Loc);
1200 if (isInvalid(PLoc, Invalid)) return 0;
1201 return PLoc.getColumn();
1202}
1203
1204// Check if multi-byte word x has bytes between m and n, included. This may also
1205// catch bytes equal to n + 1.
1206// The returned value holds a 0x80 at each byte position that holds a match.
1207// see http://graphics.stanford.edu/~seander/bithacks.html#HasBetweenInWord
1208template <class T>
1209static constexpr inline T likelyhasbetween(T x, unsigned char m,
1210 unsigned char n) {
1211 return ((x - ~static_cast<T>(0) / 255 * (n + 1)) & ~x &
1212 ((x & ~static_cast<T>(0) / 255 * 127) +
1213 (~static_cast<T>(0) / 255 * (127 - (m - 1))))) &
1214 ~static_cast<T>(0) / 255 * 128;
1215}
1216
1217LineOffsetMapping LineOffsetMapping::get(llvm::MemoryBufferRef Buffer,
1218 llvm::BumpPtrAllocator &Alloc) {
1219
1220 // Find the file offsets of all of the *physical* source lines. This does
1221 // not look at trigraphs, escaped newlines, or anything else tricky.
1222 SmallVector<unsigned, 256> LineOffsets;
1223
1224 // Line #1 starts at char 0.
1225 LineOffsets.push_back(0);
1226
1227 const unsigned char *Start = (const unsigned char *)Buffer.getBufferStart();
1228 const unsigned char *End = (const unsigned char *)Buffer.getBufferEnd();
1229 const unsigned char *Buf = Start;
1230
1231 uint64_t Word;
1232
1233 // scan sizeof(Word) bytes at a time for new lines.
1234 // This is much faster than scanning each byte independently.
1235 if ((unsigned long)(End - Start) > sizeof(Word)) {
1236 do {
1237 Word = llvm::support::endian::read64(Buf, llvm::endianness::little);
1238 // no new line => jump over sizeof(Word) bytes.
1239 auto Mask = likelyhasbetween(Word, '\n', '\r');
1240 if (!Mask) {
1241 Buf += sizeof(Word);
1242 continue;
1243 }
1244
1245 // At that point, Mask contains 0x80 set at each byte that holds a value
1246 // in [\n, \r + 1 [
1247
1248 // Scan for the next newline - it's very likely there's one.
1249 unsigned N = llvm::countr_zero(Mask) - 7; // -7 because 0x80 is the marker
1250 Word >>= N;
1251 Buf += N / 8 + 1;
1252 unsigned char Byte = Word;
1253 switch (Byte) {
1254 case '\r':
1255 // If this is \r\n, skip both characters.
1256 if (*Buf == '\n') {
1257 ++Buf;
1258 }
1259 [[fallthrough]];
1260 case '\n':
1261 LineOffsets.push_back(Buf - Start);
1262 };
1263 } while (Buf < End - sizeof(Word) - 1);
1264 }
1265
1266 // Handle tail using a regular check.
1267 while (Buf < End) {
1268 if (*Buf == '\n') {
1269 LineOffsets.push_back(Buf - Start + 1);
1270 } else if (*Buf == '\r') {
1271 // If this is \r\n, skip both characters.
1272 if (Buf + 1 < End && Buf[1] == '\n') {
1273 ++Buf;
1274 }
1275 LineOffsets.push_back(Buf - Start + 1);
1276 }
1277 ++Buf;
1278 }
1279
1280 return LineOffsetMapping(LineOffsets, Alloc);
1281}
1282
1284 llvm::BumpPtrAllocator &Alloc)
1285 : Storage(Alloc.Allocate<unsigned>(LineOffsets.size() + 1)) {
1286 Storage[0] = LineOffsets.size();
1287 std::copy(LineOffsets.begin(), LineOffsets.end(), Storage + 1);
1288}
1289
1290/// getLineNumber - Given a SourceLocation, return the spelling line number
1291/// for the position indicated. This requires building and caching a table of
1292/// line offsets for the MemoryBuffer, so this is not cheap: use only when
1293/// about to emit a diagnostic.
1294unsigned SourceManager::getLineNumber(FileID FID, unsigned FilePos,
1295 bool *Invalid) const {
1296 if (FID.isInvalid()) {
1297 if (Invalid)
1298 *Invalid = true;
1299 return 1;
1300 }
1301
1302 const ContentCache *Content;
1303 if (LastLineNoFileIDQuery == FID)
1304 Content = LastLineNoContentCache;
1305 else {
1306 bool MyInvalid = false;
1307 const SLocEntry &Entry = getSLocEntry(FID, &MyInvalid);
1308 if (MyInvalid || !Entry.isFile()) {
1309 if (Invalid)
1310 *Invalid = true;
1311 return 1;
1312 }
1313
1314 Content = &Entry.getFile().getContentCache();
1315 }
1316
1317 // If this is the first use of line information for this buffer, compute the
1318 // SourceLineCache for it on demand.
1319 if (!Content->SourceLineCache) {
1320 std::optional<llvm::MemoryBufferRef> Buffer =
1321 Content->getBufferOrNone(Diag, getFileManager(), SourceLocation());
1322 if (Invalid)
1323 *Invalid = !Buffer;
1324 if (!Buffer)
1325 return 1;
1326
1327 Content->SourceLineCache =
1328 LineOffsetMapping::get(*Buffer, ContentCacheAlloc);
1329 } else if (Invalid)
1330 *Invalid = false;
1331
1332 // Okay, we know we have a line number table. Do a binary search to find the
1333 // line number that this character position lands on.
1334 const unsigned *SourceLineCache = Content->SourceLineCache.begin();
1335 const unsigned *SourceLineCacheStart = SourceLineCache;
1336 const unsigned *SourceLineCacheEnd = Content->SourceLineCache.end();
1337
1338 unsigned QueriedFilePos = FilePos+1;
1339
1340 // FIXME: I would like to be convinced that this code is worth being as
1341 // complicated as it is, binary search isn't that slow.
1342 //
1343 // If it is worth being optimized, then in my opinion it could be more
1344 // performant, simpler, and more obviously correct by just "galloping" outward
1345 // from the queried file position. In fact, this could be incorporated into a
1346 // generic algorithm such as lower_bound_with_hint.
1347 //
1348 // If someone gives me a test case where this matters, and I will do it! - DWD
1349
1350 // If the previous query was to the same file, we know both the file pos from
1351 // that query and the line number returned. This allows us to narrow the
1352 // search space from the entire file to something near the match.
1353 if (LastLineNoFileIDQuery == FID) {
1354 if (QueriedFilePos >= LastLineNoFilePos) {
1355 // FIXME: Potential overflow?
1356 SourceLineCache = SourceLineCache+LastLineNoResult-1;
1357
1358 // The query is likely to be nearby the previous one. Here we check to
1359 // see if it is within 5, 10 or 20 lines. It can be far away in cases
1360 // where big comment blocks and vertical whitespace eat up lines but
1361 // contribute no tokens.
1362 if (SourceLineCache+5 < SourceLineCacheEnd) {
1363 if (SourceLineCache[5] > QueriedFilePos)
1364 SourceLineCacheEnd = SourceLineCache+5;
1365 else if (SourceLineCache+10 < SourceLineCacheEnd) {
1366 if (SourceLineCache[10] > QueriedFilePos)
1367 SourceLineCacheEnd = SourceLineCache+10;
1368 else if (SourceLineCache+20 < SourceLineCacheEnd) {
1369 if (SourceLineCache[20] > QueriedFilePos)
1370 SourceLineCacheEnd = SourceLineCache+20;
1371 }
1372 }
1373 }
1374 } else {
1375 if (LastLineNoResult < Content->SourceLineCache.size())
1376 SourceLineCacheEnd = SourceLineCache+LastLineNoResult+1;
1377 }
1378 }
1379
1380 const unsigned *Pos =
1381 std::lower_bound(SourceLineCache, SourceLineCacheEnd, QueriedFilePos);
1382 unsigned LineNo = Pos-SourceLineCacheStart;
1383
1384 LastLineNoFileIDQuery = FID;
1385 LastLineNoContentCache = Content;
1386 LastLineNoFilePos = QueriedFilePos;
1387 LastLineNoResult = LineNo;
1388 return LineNo;
1389}
1390
1392 assert(Loc.isFileID());
1393 if (isInvalid(Loc, Invalid)) return 0;
1394 FileIDAndOffset LocInfo = getDecomposedLoc(Loc);
1395 return getLineNumber(LocInfo.first, LocInfo.second);
1396}
1397
1399 bool *Invalid) const {
1400 PresumedLoc PLoc = getPresumedLoc(Loc);
1401 if (isInvalid(PLoc, Invalid)) return 0;
1402 return PLoc.getLine();
1403}
1404
1405/// getFileCharacteristic - return the file characteristic of the specified
1406/// source location, indicating whether this is a normal file, a system
1407/// header, or an "implicit extern C" system header.
1408///
1409/// This state can be modified with flags on GNU linemarker directives like:
1410/// # 4 "foo.h" 3
1411/// which changes all source locations in the current file after that to be
1412/// considered to be from a system header.
1415 assert(Loc.isValid() && "Can't get file characteristic of invalid loc!");
1417 const SLocEntry *SEntry = getSLocEntryForFile(LocInfo.first);
1418 if (!SEntry)
1419 return C_User;
1420
1421 const SrcMgr::FileInfo &FI = SEntry->getFile();
1422
1423 // If there are no #line directives in this file, just return the whole-file
1424 // state.
1425 if (!FI.hasLineDirectives())
1426 return FI.getFileCharacteristic();
1427
1428 assert(LineTable && "Can't have linetable entries without a LineTable!");
1429 // See if there is a #line directive before the location.
1430 const LineEntry *Entry =
1431 LineTable->FindNearestLineEntry(LocInfo.first, LocInfo.second);
1432
1433 // If this is before the first line marker, use the file characteristic.
1434 if (!Entry)
1435 return FI.getFileCharacteristic();
1436
1437 return Entry->FileKind;
1438}
1439
1440/// Return the filename or buffer identifier of the buffer the location is in.
1441/// Note that this name does not respect \#line directives. Use getPresumedLoc
1442/// for normal clients.
1444 bool *Invalid) const {
1445 if (isInvalid(Loc, Invalid)) return "<invalid loc>";
1446
1447 auto B = getBufferOrNone(getFileID(Loc));
1448 if (Invalid)
1449 *Invalid = !B;
1450 return B ? B->getBufferIdentifier() : "<invalid buffer>";
1451}
1452
1453/// getPresumedLoc - This method returns the "presumed" location of a
1454/// SourceLocation specifies. A "presumed location" can be modified by \#line
1455/// or GNU line marker directives. This provides a view on the data that a
1456/// user should see in diagnostics, for example.
1457///
1458/// Note that a presumed location is always given as the expansion point of an
1459/// expansion location, not at the spelling location.
1461 bool UseLineDirectives) const {
1462 if (Loc.isInvalid()) return PresumedLoc();
1463
1464 // Presumed locations are always for expansion points.
1466
1467 bool Invalid = false;
1468 const SLocEntry &Entry = getSLocEntry(LocInfo.first, &Invalid);
1469 if (Invalid || !Entry.isFile())
1470 return PresumedLoc();
1471
1472 const SrcMgr::FileInfo &FI = Entry.getFile();
1473 const SrcMgr::ContentCache *C = &FI.getContentCache();
1474
1475 // To get the source name, first consult the FileEntry (if one exists)
1476 // before the MemBuffer as this will avoid unnecessarily paging in the
1477 // MemBuffer.
1478 FileID FID = LocInfo.first;
1479 StringRef Filename;
1480 if (C->OrigEntry)
1481 Filename = C->OrigEntry->getName();
1482 else if (auto Buffer = C->getBufferOrNone(Diag, getFileManager()))
1483 Filename = Buffer->getBufferIdentifier();
1484
1485 unsigned LineNo = getLineNumber(LocInfo.first, LocInfo.second, &Invalid);
1486 if (Invalid)
1487 return PresumedLoc();
1488 unsigned ColNo = getColumnNumber(LocInfo.first, LocInfo.second, &Invalid);
1489 if (Invalid)
1490 return PresumedLoc();
1491
1492 SourceLocation IncludeLoc = FI.getIncludeLoc();
1493
1494 // If we have #line directives in this file, update and overwrite the physical
1495 // location info if appropriate.
1496 if (UseLineDirectives && FI.hasLineDirectives()) {
1497 assert(LineTable && "Can't have linetable entries without a LineTable!");
1498 // See if there is a #line directive before this. If so, get it.
1499 if (const LineEntry *Entry =
1500 LineTable->FindNearestLineEntry(LocInfo.first, LocInfo.second)) {
1501 // If the LineEntry indicates a filename, use it.
1502 if (Entry->FilenameID != -1) {
1503 Filename = LineTable->getFilename(Entry->FilenameID);
1504 // The contents of files referenced by #line are not in the
1505 // SourceManager
1506 FID = FileID::get(0);
1507 }
1508
1509 // Use the line number specified by the LineEntry. This line number may
1510 // be multiple lines down from the line entry. Add the difference in
1511 // physical line numbers from the query point and the line marker to the
1512 // total.
1513 unsigned MarkerLineNo = getLineNumber(LocInfo.first, Entry->FileOffset);
1514 LineNo = Entry->LineNo + (LineNo-MarkerLineNo-1);
1515
1516 // Note that column numbers are not molested by line markers.
1517
1518 // Handle virtual #include manipulation.
1519 if (Entry->IncludeOffset) {
1520 IncludeLoc = getLocForStartOfFile(LocInfo.first);
1521 IncludeLoc = IncludeLoc.getLocWithOffset(Entry->IncludeOffset);
1522 }
1523 }
1524 }
1525
1526 return PresumedLoc(Filename.data(), FID, LineNo, ColNo, IncludeLoc);
1527}
1528
1529/// Returns whether the PresumedLoc for a given SourceLocation is
1530/// in the main file.
1531///
1532/// This computes the "presumed" location for a SourceLocation, then checks
1533/// whether it came from a file other than the main file. This is different
1534/// from isWrittenInMainFile() because it takes line marker directives into
1535/// account.
1537 if (Loc.isInvalid()) return false;
1538
1539 // Presumed locations are always for expansion points.
1541
1542 const SLocEntry *Entry = getSLocEntryForFile(LocInfo.first);
1543 if (!Entry)
1544 return false;
1545
1546 const SrcMgr::FileInfo &FI = Entry->getFile();
1547
1548 // Check if there is a line directive for this location.
1549 if (FI.hasLineDirectives())
1550 if (const LineEntry *Entry =
1551 LineTable->FindNearestLineEntry(LocInfo.first, LocInfo.second))
1552 if (Entry->IncludeOffset)
1553 return false;
1554
1555 return FI.getIncludeLoc().isInvalid();
1556}
1557
1558/// The size of the SLocEntry that \p FID represents.
1560 bool Invalid = false;
1561 const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid);
1562 if (Invalid)
1563 return 0;
1564
1565 int ID = FID.ID;
1566 SourceLocation::UIntTy NextOffset;
1567 if ((ID > 0 && unsigned(ID+1) == local_sloc_entry_size()))
1568 NextOffset = getNextLocalOffset();
1569 else if (ID+1 == -1)
1570 NextOffset = MaxLoadedOffset;
1571 else
1572 NextOffset = getSLocEntry(FileID::get(ID+1)).getOffset();
1573
1574 return NextOffset - Entry.getOffset() - 1;
1575}
1576
1577//===----------------------------------------------------------------------===//
1578// Other miscellaneous methods.
1579//===----------------------------------------------------------------------===//
1580
1581/// Get the source location for the given file:line:col triplet.
1582///
1583/// If the source file is included multiple times, the source location will
1584/// be based upon an arbitrary inclusion.
1586 unsigned Line,
1587 unsigned Col) const {
1588 assert(SourceFile && "Null source file!");
1589 assert(Line && Col && "Line and column should start from 1!");
1590
1591 FileID FirstFID = translateFile(SourceFile);
1592 return translateLineCol(FirstFID, Line, Col);
1593}
1594
1595/// Get the FileID for the given file.
1596///
1597/// If the source file is included multiple times, the FileID will be the
1598/// first inclusion.
1600 assert(SourceFile && "Null source file!");
1601
1602 // First, check the main file ID, since it is common to look for a
1603 // location in the main file.
1604 if (MainFileID.isValid()) {
1605 bool Invalid = false;
1606 const SLocEntry &MainSLoc = getSLocEntry(MainFileID, &Invalid);
1607 if (Invalid)
1608 return FileID();
1609
1610 if (MainSLoc.isFile()) {
1611 if (MainSLoc.getFile().getContentCache().OrigEntry == SourceFile)
1612 return MainFileID;
1613 }
1614 }
1615
1616 // The location we're looking for isn't in the main file; look
1617 // through all of the local source locations.
1618 for (unsigned I = 0, N = local_sloc_entry_size(); I != N; ++I) {
1619 const SLocEntry &SLoc = getLocalSLocEntry(I);
1620 if (SLoc.isFile() &&
1621 SLoc.getFile().getContentCache().OrigEntry == SourceFile)
1622 return FileID::get(I);
1623 }
1624
1625 // If that still didn't help, try the modules.
1626 for (unsigned I = 0, N = loaded_sloc_entry_size(); I != N; ++I) {
1627 const SLocEntry &SLoc = getLoadedSLocEntry(I);
1628 if (SLoc.isFile() &&
1629 SLoc.getFile().getContentCache().OrigEntry == SourceFile)
1630 return FileID::get(-int(I) - 2);
1631 }
1632
1633 return FileID();
1634}
1635
1636/// Get the source location in \arg FID for the given line:col.
1637/// Returns null location if \arg FID is not a file SLocEntry.
1639 unsigned Line,
1640 unsigned Col) const {
1641 // Lines are used as a one-based index into a zero-based array. This assert
1642 // checks for possible buffer underruns.
1643 assert(Line && Col && "Line and column should start from 1!");
1644
1645 if (FID.isInvalid())
1646 return SourceLocation();
1647
1648 bool Invalid = false;
1649 const SLocEntry &Entry = getSLocEntry(FID, &Invalid);
1650 if (Invalid)
1651 return SourceLocation();
1652
1653 if (!Entry.isFile())
1654 return SourceLocation();
1655
1656 SourceLocation FileLoc = SourceLocation::getFileLoc(Entry.getOffset());
1657
1658 if (Line == 1 && Col == 1)
1659 return FileLoc;
1660
1661 const ContentCache *Content = &Entry.getFile().getContentCache();
1662
1663 // If this is the first use of line information for this buffer, compute the
1664 // SourceLineCache for it on demand.
1665 std::optional<llvm::MemoryBufferRef> Buffer =
1666 Content->getBufferOrNone(Diag, getFileManager());
1667 if (!Buffer)
1668 return SourceLocation();
1669 if (!Content->SourceLineCache)
1670 Content->SourceLineCache =
1671 LineOffsetMapping::get(*Buffer, ContentCacheAlloc);
1672
1673 if (Line > Content->SourceLineCache.size()) {
1674 unsigned Size = Buffer->getBufferSize();
1675 if (Size > 0)
1676 --Size;
1677 return FileLoc.getLocWithOffset(Size);
1678 }
1679
1680 unsigned FilePos = Content->SourceLineCache[Line - 1];
1681 const char *Buf = Buffer->getBufferStart() + FilePos;
1682 unsigned BufLength = Buffer->getBufferSize() - FilePos;
1683 if (BufLength == 0)
1684 return FileLoc.getLocWithOffset(FilePos);
1685
1686 unsigned i = 0;
1687
1688 // Check that the given column is valid.
1689 while (i < BufLength-1 && i < Col-1 && Buf[i] != '\n' && Buf[i] != '\r')
1690 ++i;
1691 return FileLoc.getLocWithOffset(FilePos + i);
1692}
1693
1694/// Compute a map of macro argument chunks to their expanded source
1695/// location. Chunks that are not part of a macro argument will map to an
1696/// invalid source location. e.g. if a file contains one macro argument at
1697/// offset 100 with length 10, this is how the map will be formed:
1698/// 0 -> SourceLocation()
1699/// 100 -> Expanded macro arg location
1700/// 110 -> SourceLocation()
1701void SourceManager::computeMacroArgsCache(MacroArgsMap &MacroArgsCache,
1702 FileID FID) const {
1703 assert(FID.isValid());
1704
1705 // Initially no macro argument chunk is present.
1706 MacroArgsCache.try_emplace(0);
1707
1708 int ID = FID.ID;
1709 while (true) {
1710 ++ID;
1711 // Stop if there are no more FileIDs to check.
1712 if (ID > 0) {
1713 if (unsigned(ID) >= local_sloc_entry_size())
1714 return;
1715 } else if (ID == -1) {
1716 return;
1717 }
1718
1719 bool Invalid = false;
1720 const SrcMgr::SLocEntry &Entry = getSLocEntryByID(ID, &Invalid);
1721 if (Invalid)
1722 return;
1723 if (Entry.isFile()) {
1724 auto& File = Entry.getFile();
1725 if (File.getFileCharacteristic() == C_User_ModuleMap ||
1726 File.getFileCharacteristic() == C_System_ModuleMap)
1727 continue;
1728
1729 SourceLocation IncludeLoc = File.getIncludeLoc();
1730 bool IncludedInFID =
1731 (IncludeLoc.isValid() && isInFileID(IncludeLoc, FID)) ||
1732 // Predefined header doesn't have a valid include location in main
1733 // file, but any files created by it should still be skipped when
1734 // computing macro args expanded in the main file.
1735 (FID == MainFileID && Entry.getFile().getName() == "<built-in>");
1736 if (IncludedInFID) {
1737 // Skip the files/macros of the #include'd file, we only care about
1738 // macros that lexed macro arguments from our file.
1739 if (Entry.getFile().NumCreatedFIDs)
1740 ID += Entry.getFile().NumCreatedFIDs - 1 /*because of next ++ID*/;
1741 continue;
1742 }
1743 // If file was included but not from FID, there is no more files/macros
1744 // that may be "contained" in this file.
1745 if (IncludeLoc.isValid())
1746 return;
1747 continue;
1748 }
1749
1750 const ExpansionInfo &ExpInfo = Entry.getExpansion();
1751
1752 if (ExpInfo.getExpansionLocStart().isFileID()) {
1753 if (!isInFileID(ExpInfo.getExpansionLocStart(), FID))
1754 return; // No more files/macros that may be "contained" in this file.
1755 }
1756
1757 if (!ExpInfo.isMacroArgExpansion())
1758 continue;
1759
1760 associateFileChunkWithMacroArgExp(MacroArgsCache, FID,
1761 ExpInfo.getSpellingLoc(),
1762 SourceLocation::getMacroLoc(Entry.getOffset()),
1763 getFileIDSize(FileID::get(ID)));
1764 }
1765}
1766
1767void SourceManager::associateFileChunkWithMacroArgExp(
1768 MacroArgsMap &MacroArgsCache,
1769 FileID FID,
1770 SourceLocation SpellLoc,
1771 SourceLocation ExpansionLoc,
1772 unsigned ExpansionLength) const {
1773 if (!SpellLoc.isFileID()) {
1774 SourceLocation::UIntTy SpellBeginOffs = SpellLoc.getOffset();
1775 SourceLocation::UIntTy SpellEndOffs = SpellBeginOffs + ExpansionLength;
1776
1777 // The spelling range for this macro argument expansion can span multiple
1778 // consecutive FileID entries. Go through each entry contained in the
1779 // spelling range and if one is itself a macro argument expansion, recurse
1780 // and associate the file chunk that it represents.
1781
1782 // Current FileID in the spelling range.
1783 auto [SpellFID, SpellRelativeOffs] = getDecomposedLoc(SpellLoc);
1784 while (true) {
1785 const SLocEntry &Entry = getSLocEntry(SpellFID);
1786 SourceLocation::UIntTy SpellFIDBeginOffs = Entry.getOffset();
1787 unsigned SpellFIDSize = getFileIDSize(SpellFID);
1788 SourceLocation::UIntTy SpellFIDEndOffs = SpellFIDBeginOffs + SpellFIDSize;
1789 const ExpansionInfo &Info = Entry.getExpansion();
1790 if (Info.isMacroArgExpansion()) {
1791 unsigned CurrSpellLength;
1792 if (SpellFIDEndOffs < SpellEndOffs)
1793 CurrSpellLength = SpellFIDSize - SpellRelativeOffs;
1794 else
1795 CurrSpellLength = ExpansionLength;
1796 associateFileChunkWithMacroArgExp(MacroArgsCache, FID,
1797 Info.getSpellingLoc().getLocWithOffset(SpellRelativeOffs),
1798 ExpansionLoc, CurrSpellLength);
1799 }
1800
1801 if (SpellFIDEndOffs >= SpellEndOffs)
1802 return; // we covered all FileID entries in the spelling range.
1803
1804 // Move to the next FileID entry in the spelling range.
1805 unsigned advance = SpellFIDSize - SpellRelativeOffs + 1;
1806 ExpansionLoc = ExpansionLoc.getLocWithOffset(advance);
1807 ExpansionLength -= advance;
1808 ++SpellFID.ID;
1809 SpellRelativeOffs = 0;
1810 }
1811 }
1812
1813 assert(SpellLoc.isFileID());
1814
1815 unsigned BeginOffs;
1816 if (!isInFileID(SpellLoc, FID, &BeginOffs))
1817 return;
1818
1819 unsigned EndOffs = BeginOffs + ExpansionLength;
1820
1821 // Add a new chunk for this macro argument. A previous macro argument chunk
1822 // may have been lexed again, so e.g. if the map is
1823 // 0 -> SourceLocation()
1824 // 100 -> Expanded loc #1
1825 // 110 -> SourceLocation()
1826 // and we found a new macro FileID that lexed from offset 105 with length 3,
1827 // the new map will be:
1828 // 0 -> SourceLocation()
1829 // 100 -> Expanded loc #1
1830 // 105 -> Expanded loc #2
1831 // 108 -> Expanded loc #1
1832 // 110 -> SourceLocation()
1833 //
1834 // Since re-lexed macro chunks will always be the same size or less of
1835 // previous chunks, we only need to find where the ending of the new macro
1836 // chunk is mapped to and update the map with new begin/end mappings.
1837
1838 MacroArgsMap::iterator I = MacroArgsCache.upper_bound(EndOffs);
1839 --I;
1840 SourceLocation EndOffsMappedLoc = I->second;
1841 MacroArgsCache[BeginOffs] = ExpansionLoc;
1842 MacroArgsCache[EndOffs] = EndOffsMappedLoc;
1843}
1844
1845void SourceManager::updateSlocUsageStats() const {
1846 SourceLocation::UIntTy UsedBytes =
1847 NextLocalOffset + (MaxLoadedOffset - CurrentLoadedOffset);
1848 MaxUsedSLocBytes.updateMax(UsedBytes);
1849}
1850
1851/// If \arg Loc points inside a function macro argument, the returned
1852/// location will be the macro location in which the argument was expanded.
1853/// If a macro argument is used multiple times, the expanded location will
1854/// be at the first expansion of the argument.
1855/// e.g.
1856/// MY_MACRO(foo);
1857/// ^
1858/// Passing a file location pointing at 'foo', will yield a macro location
1859/// where 'foo' was expanded into.
1860SourceLocation
1862 if (Loc.isInvalid() || !Loc.isFileID())
1863 return Loc;
1864
1865 auto [FID, Offset] = getDecomposedLoc(Loc);
1866 if (FID.isInvalid())
1867 return Loc;
1868
1869 std::unique_ptr<MacroArgsMap> &MacroArgsCache = MacroArgsCacheMap[FID];
1870 if (!MacroArgsCache) {
1871 MacroArgsCache = std::make_unique<MacroArgsMap>();
1872 computeMacroArgsCache(*MacroArgsCache, FID);
1873 }
1874
1875 assert(!MacroArgsCache->empty());
1876 MacroArgsMap::iterator I = MacroArgsCache->upper_bound(Offset);
1877 // In case every element in MacroArgsCache is greater than Offset we can't
1878 // decrement the iterator.
1879 if (I == MacroArgsCache->begin())
1880 return Loc;
1881
1882 --I;
1883
1884 SourceLocation::UIntTy MacroArgBeginOffs = I->first;
1885 SourceLocation MacroArgExpandedLoc = I->second;
1886 if (MacroArgExpandedLoc.isValid())
1887 return MacroArgExpandedLoc.getLocWithOffset(Offset - MacroArgBeginOffs);
1888
1889 return Loc;
1890}
1891
1893 if (FID.isInvalid())
1894 return std::make_pair(FileID(), 0);
1895
1896 // Uses IncludedLocMap to retrieve/cache the decomposed loc.
1897
1898 using DecompTy = FileIDAndOffset;
1899 auto InsertOp = IncludedLocMap.try_emplace(FID);
1900 DecompTy &DecompLoc = InsertOp.first->second;
1901 if (!InsertOp.second)
1902 return DecompLoc; // already in map.
1903
1904 SourceLocation UpperLoc;
1905 bool Invalid = false;
1906 const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid);
1907 if (!Invalid) {
1908 if (Entry.isExpansion())
1909 UpperLoc = Entry.getExpansion().getExpansionLocStart();
1910 else
1911 UpperLoc = Entry.getFile().getIncludeLoc();
1912 }
1913
1914 if (UpperLoc.isValid())
1915 DecompLoc = getDecomposedLoc(UpperLoc);
1916
1917 return DecompLoc;
1918}
1919
1921 assert(isLoadedSourceLocation(Loc) &&
1922 "Must be a source location in a loaded PCH/Module file");
1923
1924 auto [FID, Ignore] = getDecomposedLoc(Loc);
1925 // `LoadedSLocEntryAllocBegin` stores the sorted lowest FID of each loaded
1926 // allocation. Later allocations have lower FileIDs. The call below is to find
1927 // the lowest FID of a loaded allocation from any FID in the same allocation.
1928 // The lowest FID is used to identify a loaded allocation.
1929 const FileID *FirstFID =
1930 llvm::lower_bound(LoadedSLocEntryAllocBegin, FID, std::greater<FileID>{});
1931
1932 assert(FirstFID &&
1933 "The failure to find the first FileID of a "
1934 "loaded AST from a loaded source location was unexpected.");
1935 return *FirstFID;
1936}
1937
1939 const FileIDAndOffset &LOffs, const FileIDAndOffset &ROffs) const {
1940 // If one is local while the other is loaded.
1941 if (isLoadedFileID(LOffs.first) != isLoadedFileID(ROffs.first))
1942 return false;
1943
1944 if (isLoadedFileID(LOffs.first) && isLoadedFileID(ROffs.first)) {
1945 auto FindSLocEntryAlloc = [this](FileID FID) {
1946 // Loaded FileIDs are negative, we store the lowest FileID from each
1947 // allocation, later allocations have lower FileIDs.
1948 return llvm::lower_bound(LoadedSLocEntryAllocBegin, FID,
1949 std::greater<FileID>{});
1950 };
1951
1952 // If both are loaded from different AST files.
1953 if (FindSLocEntryAlloc(LOffs.first) != FindSLocEntryAlloc(ROffs.first))
1954 return false;
1955 }
1956
1957 return true;
1958}
1959
1960/// Given a decomposed source location, move it up the include/expansion stack
1961/// to the parent source location within the same translation unit. If this is
1962/// possible, return the decomposed version of the parent in Loc and return
1963/// false. If Loc is a top-level entry, return true and don't modify it.
1965 const SourceManager &SM) {
1966 FileIDAndOffset UpperLoc = SM.getDecomposedIncludedLoc(Loc.first);
1967 if (UpperLoc.first.isInvalid() ||
1968 !SM.isInTheSameTranslationUnitImpl(UpperLoc, Loc))
1969 return true; // We reached the top.
1970
1971 Loc = UpperLoc;
1972 return false;
1973}
1974
1975/// Return the cache entry for comparing the given file IDs
1976/// for isBeforeInTranslationUnit.
1977InBeforeInTUCacheEntry &SourceManager::getInBeforeInTUCache(FileID LFID,
1978 FileID RFID) const {
1979 // This is a magic number for limiting the cache size. It was experimentally
1980 // derived from a small Objective-C project (where the cache filled
1981 // out to ~250 items). We can make it larger if necessary.
1982 // FIXME: this is almost certainly full these days. Use an LRU cache?
1983 enum { MagicCacheSize = 300 };
1984 IsBeforeInTUCacheKey Key(LFID, RFID);
1985
1986 // If the cache size isn't too large, do a lookup and if necessary default
1987 // construct an entry. We can then return it to the caller for direct
1988 // use. When they update the value, the cache will get automatically
1989 // updated as well.
1990 if (IBTUCache.size() < MagicCacheSize)
1991 return IBTUCache.try_emplace(Key, LFID, RFID).first->second;
1992
1993 // Otherwise, do a lookup that will not construct a new value.
1994 InBeforeInTUCache::iterator I = IBTUCache.find(Key);
1995 if (I != IBTUCache.end())
1996 return I->second;
1997
1998 // Fall back to the overflow value.
1999 IBTUCacheOverflow.setQueryFIDs(LFID, RFID);
2000 return IBTUCacheOverflow;
2001}
2002
2003/// Determines the order of 2 source locations in the translation unit.
2004///
2005/// \returns true if LHS source location comes before RHS, false otherwise.
2007 SourceLocation RHS) const {
2008 assert(LHS.isValid() && RHS.isValid() && "Passed invalid source location!");
2009 if (LHS == RHS)
2010 return false;
2011
2012 FileIDAndOffset LOffs = getDecomposedLoc(LHS);
2013 FileIDAndOffset ROffs = getDecomposedLoc(RHS);
2014
2015 // getDecomposedLoc may have failed to return a valid FileID because, e.g. it
2016 // is a serialized one referring to a file that was removed after we loaded
2017 // the PCH.
2018 if (LOffs.first.isInvalid() || ROffs.first.isInvalid())
2019 return LOffs.first.isInvalid() && !ROffs.first.isInvalid();
2020
2021 std::pair<bool, bool> InSameTU = isInTheSameTranslationUnit(LOffs, ROffs);
2022 if (InSameTU.first)
2023 return InSameTU.second;
2024 // This case is used by libclang: clang_isBeforeInTranslationUnit
2025 return LOffs.first < ROffs.first;
2026}
2027
2028std::pair<bool, bool>
2030 FileIDAndOffset &ROffs) const {
2031 // If the source locations are not in the same TU, return early.
2032 if (!isInTheSameTranslationUnitImpl(LOffs, ROffs))
2033 return std::make_pair(false, false);
2034
2035 // If the source locations are in the same file, just compare offsets.
2036 if (LOffs.first == ROffs.first)
2037 return std::make_pair(true, LOffs.second < ROffs.second);
2038
2039 // If we are comparing a source location with multiple locations in the same
2040 // file, we get a big win by caching the result.
2041 InBeforeInTUCacheEntry &IsBeforeInTUCache =
2042 getInBeforeInTUCache(LOffs.first, ROffs.first);
2043
2044 // If we are comparing a source location with multiple locations in the same
2045 // file, we get a big win by caching the result.
2046 if (IsBeforeInTUCache.isCacheValid())
2047 return std::make_pair(
2048 true, IsBeforeInTUCache.getCachedResult(LOffs.second, ROffs.second));
2049
2050 // Okay, we missed in the cache, we'll compute the answer and populate it.
2051 // We need to find the common ancestor. The only way of doing this is to
2052 // build the complete include chain for one and then walking up the chain
2053 // of the other looking for a match.
2054
2055 // A location within a FileID on the path up from LOffs to the main file.
2056 struct Entry {
2057 FileIDAndOffset DecomposedLoc; // FileID redundant, but clearer.
2058 FileID ChildFID; // Used for breaking ties. Invalid for the initial loc.
2059 };
2060 llvm::SmallDenseMap<FileID, Entry, 16> LChain;
2061
2062 FileID LChild;
2063 do {
2064 LChain.try_emplace(LOffs.first, Entry{LOffs, LChild});
2065 // We catch the case where LOffs is in a file included by ROffs and
2066 // quit early. The other way round unfortunately remains suboptimal.
2067 if (LOffs.first == ROffs.first)
2068 break;
2069 LChild = LOffs.first;
2070 } while (!MoveUpTranslationUnitIncludeHierarchy(LOffs, *this));
2071
2072 FileID RChild;
2073 do {
2074 auto LIt = LChain.find(ROffs.first);
2075 if (LIt != LChain.end()) {
2076 // Compare the locations within the common file and cache them.
2077 LOffs = LIt->second.DecomposedLoc;
2078 LChild = LIt->second.ChildFID;
2079 // The relative order of LChild and RChild is a tiebreaker when
2080 // - locs expand to the same location (occurs in macro arg expansion)
2081 // - one loc is a parent of the other (we consider the parent as "first")
2082 // For the parent entry to be first, its invalid child file ID must
2083 // compare smaller to the valid child file ID of the other entry.
2084 // However loaded FileIDs are <0, so we perform *unsigned* comparison!
2085 // This changes the relative order of local vs loaded FileIDs, but it
2086 // doesn't matter as these are never mixed in macro expansion.
2087 unsigned LChildID = LChild.ID;
2088 unsigned RChildID = RChild.ID;
2089 assert(((LOffs.second != ROffs.second) ||
2090 (LChildID == 0 || RChildID == 0) ||
2092 getComposedLoc(RChild, 0), nullptr)) &&
2093 "Mixed local/loaded FileIDs with same include location?");
2094 IsBeforeInTUCache.setCommonLoc(LOffs.first, LOffs.second, ROffs.second,
2095 LChildID < RChildID);
2096 return std::make_pair(
2097 true, IsBeforeInTUCache.getCachedResult(LOffs.second, ROffs.second));
2098 }
2099 RChild = ROffs.first;
2100 } while (!MoveUpTranslationUnitIncludeHierarchy(ROffs, *this));
2101
2102 // If we found no match, the location is either in a built-ins buffer or
2103 // associated with global inline asm. PR5662 and PR22576 are examples.
2104
2105 StringRef LB = getBufferOrFake(LOffs.first).getBufferIdentifier();
2106 StringRef RB = getBufferOrFake(ROffs.first).getBufferIdentifier();
2107
2108 bool LIsBuiltins = LB == "<built-in>";
2109 bool RIsBuiltins = RB == "<built-in>";
2110 // Sort built-in before non-built-in.
2111 if (LIsBuiltins || RIsBuiltins) {
2112 if (LIsBuiltins != RIsBuiltins)
2113 return std::make_pair(true, LIsBuiltins);
2114 // Both are in built-in buffers, but from different files. We just claim
2115 // that lower IDs come first.
2116 return std::make_pair(true, LOffs.first < ROffs.first);
2117 }
2118
2119 bool LIsAsm = LB == "<inline asm>";
2120 bool RIsAsm = RB == "<inline asm>";
2121 // Sort assembler after built-ins, but before the rest.
2122 if (LIsAsm || RIsAsm) {
2123 if (LIsAsm != RIsAsm)
2124 return std::make_pair(true, RIsAsm);
2125 assert(LOffs.first == ROffs.first);
2126 return std::make_pair(true, false);
2127 }
2128
2129 bool LIsScratch = LB == "<scratch space>";
2130 bool RIsScratch = RB == "<scratch space>";
2131 // Sort scratch after inline asm, but before the rest.
2132 if (LIsScratch || RIsScratch) {
2133 if (LIsScratch != RIsScratch)
2134 return std::make_pair(true, LIsScratch);
2135 return std::make_pair(true, LOffs.second < ROffs.second);
2136 }
2137
2138 llvm_unreachable("Unsortable locations found");
2139}
2140
2142 llvm::errs() << "\n*** Source Manager Stats:\n";
2143 llvm::errs() << FileInfos.size() << " files mapped, " << MemBufferInfos.size()
2144 << " mem buffers mapped.\n";
2145 llvm::errs() << LocalSLocEntryTable.size() << " local SLocEntries allocated ("
2146 << llvm::capacity_in_bytes(LocalSLocEntryTable)
2147 << " bytes of capacity), " << NextLocalOffset
2148 << "B of SLoc address space used.\n";
2149 llvm::errs() << LoadedSLocEntryTable.size()
2150 << " loaded SLocEntries allocated ("
2151 << llvm::capacity_in_bytes(LoadedSLocEntryTable)
2152 << " bytes of capacity), "
2153 << MaxLoadedOffset - CurrentLoadedOffset
2154 << "B of SLoc address space used.\n";
2155
2156 unsigned NumLineNumsComputed = 0;
2157 unsigned NumFileBytesMapped = 0;
2158 for (fileinfo_iterator I = fileinfo_begin(), E = fileinfo_end(); I != E; ++I){
2159 NumLineNumsComputed += bool(I->second->SourceLineCache);
2160 NumFileBytesMapped += I->second->getSizeBytesMapped();
2161 }
2162 unsigned NumMacroArgsComputed = MacroArgsCacheMap.size();
2163
2164 llvm::errs() << NumFileBytesMapped << " bytes of files mapped, "
2165 << NumLineNumsComputed << " files with line #'s computed, "
2166 << NumMacroArgsComputed << " files with macro args computed.\n";
2167 llvm::errs() << "FileID scans: " << NumLinearScans << " linear, "
2168 << NumBinaryProbes << " binary.\n";
2169}
2170
2171LLVM_DUMP_METHOD void SourceManager::dump() const {
2172 llvm::raw_ostream &out = llvm::errs();
2173
2174 auto DumpSLocEntry = [&](int ID, const SrcMgr::SLocEntry &Entry,
2175 std::optional<SourceLocation::UIntTy> NextStart) {
2176 out << "SLocEntry <FileID " << ID << "> " << (Entry.isFile() ? "file" : "expansion")
2177 << " <SourceLocation " << Entry.getOffset() << ":";
2178 if (NextStart)
2179 out << *NextStart << ">\n";
2180 else
2181 out << "???\?>\n";
2182 if (Entry.isFile()) {
2183 auto &FI = Entry.getFile();
2184 if (FI.NumCreatedFIDs)
2185 out << " covers <FileID " << ID << ":" << int(ID + FI.NumCreatedFIDs)
2186 << ">\n";
2187 if (FI.getIncludeLoc().isValid())
2188 out << " included from " << FI.getIncludeLoc().getOffset() << "\n";
2189 auto &CC = FI.getContentCache();
2190 out << " for " << (CC.OrigEntry ? CC.OrigEntry->getName() : "<none>")
2191 << "\n";
2192 if (CC.BufferOverridden)
2193 out << " contents overridden\n";
2194 if (CC.ContentsEntry != CC.OrigEntry) {
2195 out << " contents from "
2196 << (CC.ContentsEntry ? CC.ContentsEntry->getName() : "<none>")
2197 << "\n";
2198 }
2199 } else {
2200 auto &EI = Entry.getExpansion();
2201 out << " spelling from " << EI.getSpellingLoc().getOffset() << "\n";
2202 out << " macro " << (EI.isMacroArgExpansion() ? "arg" : "body")
2203 << " range <" << EI.getExpansionLocStart().getOffset() << ":"
2204 << EI.getExpansionLocEnd().getOffset() << ">\n";
2205 }
2206 };
2207
2208 // Dump local SLocEntries.
2209 for (unsigned ID = 0, NumIDs = LocalSLocEntryTable.size(); ID != NumIDs; ++ID) {
2210 DumpSLocEntry(ID, LocalSLocEntryTable[ID],
2211 ID == NumIDs - 1 ? NextLocalOffset
2212 : LocalSLocEntryTable[ID + 1].getOffset());
2213 }
2214 // Dump loaded SLocEntries.
2215 std::optional<SourceLocation::UIntTy> NextStart;
2216 for (unsigned Index = 0; Index != LoadedSLocEntryTable.size(); ++Index) {
2217 int ID = -(int)Index - 2;
2218 if (SLocEntryLoaded[Index]) {
2219 DumpSLocEntry(ID, LoadedSLocEntryTable[Index], NextStart);
2220 NextStart = LoadedSLocEntryTable[Index].getOffset();
2221 } else {
2222 NextStart = std::nullopt;
2223 }
2224 }
2225}
2226
2228 DiagnosticsEngine &Diag, std::optional<unsigned> MaxNotes) const {
2229 struct Info {
2230 // A location where this file was entered.
2231 SourceLocation Loc;
2232 // Number of times this FileEntry was entered.
2233 unsigned Inclusions = 0;
2234 // Size usage from the file itself.
2235 uint64_t DirectSize = 0;
2236 // Total size usage from the file and its macro expansions.
2237 uint64_t TotalSize = 0;
2238 };
2239 using UsageMap = llvm::MapVector<const FileEntry*, Info>;
2240
2241 UsageMap Usage;
2242 uint64_t CountedSize = 0;
2243
2244 auto AddUsageForFileID = [&](FileID ID) {
2245 // The +1 here is because getFileIDSize doesn't include the extra byte for
2246 // the one-past-the-end location.
2247 unsigned Size = getFileIDSize(ID) + 1;
2248
2249 // Find the file that used this address space, either directly or by
2250 // macro expansion.
2251 SourceLocation FileStart = getFileLoc(getComposedLoc(ID, 0));
2252 FileID FileLocID = getFileID(FileStart);
2253 const FileEntry *Entry = getFileEntryForID(FileLocID);
2254
2255 Info &EntryInfo = Usage[Entry];
2256 if (EntryInfo.Loc.isInvalid())
2257 EntryInfo.Loc = FileStart;
2258 if (ID == FileLocID) {
2259 ++EntryInfo.Inclusions;
2260 EntryInfo.DirectSize += Size;
2261 }
2262 EntryInfo.TotalSize += Size;
2263 CountedSize += Size;
2264 };
2265
2266 // Loaded SLocEntries have indexes counting downwards from -2.
2267 for (size_t Index = 0; Index != LoadedSLocEntryTable.size(); ++Index) {
2268 AddUsageForFileID(FileID::get(-2 - Index));
2269 }
2270 // Local SLocEntries have indexes counting upwards from 0.
2271 for (size_t Index = 0; Index != LocalSLocEntryTable.size(); ++Index) {
2272 AddUsageForFileID(FileID::get(Index));
2273 }
2274
2275 // Sort the usage by size from largest to smallest. Break ties by raw source
2276 // location.
2277 auto SortedUsage = Usage.takeVector();
2278 auto Cmp = [](const UsageMap::value_type &A, const UsageMap::value_type &B) {
2279 return A.second.TotalSize > B.second.TotalSize ||
2280 (A.second.TotalSize == B.second.TotalSize &&
2281 A.second.Loc < B.second.Loc);
2282 };
2283 auto SortedEnd = SortedUsage.end();
2284 if (MaxNotes && SortedUsage.size() > *MaxNotes) {
2285 SortedEnd = SortedUsage.begin() + *MaxNotes;
2286 std::nth_element(SortedUsage.begin(), SortedEnd, SortedUsage.end(), Cmp);
2287 }
2288 std::sort(SortedUsage.begin(), SortedEnd, Cmp);
2289
2290 // Produce note on sloc address space usage total.
2291 uint64_t LocalUsage = NextLocalOffset;
2292 uint64_t LoadedUsage = MaxLoadedOffset - CurrentLoadedOffset;
2293 int UsagePercent = static_cast<int>(100.0 * double(LocalUsage + LoadedUsage) /
2294 MaxLoadedOffset);
2295 Diag.Report(diag::note_total_sloc_usage)
2296 << LocalUsage << LoadedUsage << (LocalUsage + LoadedUsage)
2297 << UsagePercent;
2298
2299 // Produce notes on sloc address space usage for each file with a high usage.
2300 uint64_t ReportedSize = 0;
2301 for (auto &[Entry, FileInfo] :
2302 llvm::make_range(SortedUsage.begin(), SortedEnd)) {
2303 Diag.Report(FileInfo.Loc, diag::note_file_sloc_usage)
2304 << FileInfo.Inclusions << FileInfo.DirectSize
2305 << (FileInfo.TotalSize - FileInfo.DirectSize);
2306 ReportedSize += FileInfo.TotalSize;
2307 }
2308
2309 // Describe any remaining usage not reported in the per-file usage.
2310 if (ReportedSize != CountedSize) {
2311 Diag.Report(diag::note_file_misc_sloc_usage)
2312 << (SortedUsage.end() - SortedEnd) << CountedSize - ReportedSize;
2313 }
2314}
2315
2317
2318/// Return the amount of memory used by memory buffers, breaking down
2319/// by heap-backed versus mmap'ed memory.
2321 size_t malloc_bytes = 0;
2322 size_t mmap_bytes = 0;
2323
2324 for (unsigned i = 0, e = MemBufferInfos.size(); i != e; ++i)
2325 if (size_t sized_mapped = MemBufferInfos[i]->getSizeBytesMapped())
2326 switch (MemBufferInfos[i]->getMemoryBufferKind()) {
2327 case llvm::MemoryBuffer::MemoryBuffer_MMap:
2328 mmap_bytes += sized_mapped;
2329 break;
2330 case llvm::MemoryBuffer::MemoryBuffer_Malloc:
2331 malloc_bytes += sized_mapped;
2332 break;
2333 }
2334
2335 return MemoryBufferSizes(malloc_bytes, mmap_bytes);
2336}
2337
2339 size_t size = llvm::capacity_in_bytes(MemBufferInfos) +
2340 llvm::capacity_in_bytes(FileIDContentCaches) +
2341 llvm::capacity_in_bytes(LocalSLocEntryTable) +
2342 llvm::capacity_in_bytes(LoadedSLocEntryTable) +
2343 llvm::capacity_in_bytes(SLocEntryLoaded) +
2344 llvm::capacity_in_bytes(FileInfos);
2345
2346 if (OverriddenFilesInfo)
2347 size += llvm::capacity_in_bytes(OverriddenFilesInfo->OverriddenFiles);
2348
2349 return size;
2350}
2351
2353 StringRef Content) {
2354 auto InMemoryFileSystem =
2355 llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
2356 InMemoryFileSystem->addFile(
2357 FileName, 0,
2358 llvm::MemoryBuffer::getMemBuffer(Content, FileName,
2359 /*RequiresNullTerminator=*/false));
2360 // This is passed to `SM` as reference, so the pointer has to be referenced
2361 // in `Environment` so that `FileMgr` can out-live this function scope.
2362 FileMgr = std::make_unique<FileManager>(FileSystemOptions(),
2363 std::move(InMemoryFileSystem));
2364 DiagOpts = std::make_unique<DiagnosticOptions>();
2365 // This is passed to `SM` as reference, so the pointer has to be referenced
2366 // by `Environment` due to the same reason above.
2367 Diagnostics =
2368 std::make_unique<DiagnosticsEngine>(DiagnosticIDs::create(), *DiagOpts);
2369 SourceMgr = std::make_unique<SourceManager>(*Diagnostics, *FileMgr);
2370 FileEntryRef FE = llvm::cantFail(FileMgr->getFileRef(FileName));
2371 FileID ID =
2372 SourceMgr->createFileID(FE, SourceLocation(), clang::SrcMgr::C_User);
2373 assert(ID.isValid());
2374 SourceMgr->setMainFileID(ID);
2375}
Defines the Diagnostic-related interfaces.
Defines the clang::FileManager interface and associated types.
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
#define SM(sm)
static ParseState advance(ParseState S, size_t N)
Definition Parsing.cpp:137
Defines the clang::SourceLocation class and associated facilities.
Defines implementation details of the clang::SourceManager class.
static constexpr T likelyhasbetween(T x, unsigned char m, unsigned char n)
static bool isInvalid(LocType Loc, bool *Invalid)
STATISTIC(MaxUsedSLocBytes, "Maximum number of bytes used by source locations " "(both loaded and local).")
static bool MoveUpTranslationUnitIncludeHierarchy(FileIDAndOffset &Loc, const SourceManager &SM)
Given a decomposed source location, move it up the include/expansion stack to the parent source locat...
static SrcMgr::ContentCache * cloneContentCache(llvm::BumpPtrAllocator &Alloc, const ContentCache &Other)
Defines the SourceManager interface.
__device__ double
Represents a byte-granular source range.
void setEnd(SourceLocation e)
bool isTokenRange() const
Return true if the end of this range specifies the start of the last token.
void setBegin(SourceLocation b)
SourceLocation getEnd() const
SourceLocation getBegin() const
void setTokenRange(bool TR)
static llvm::IntrusiveRefCntPtr< DiagnosticIDs > create()
Concrete class used by the front-end to report problems and issues.
Definition Diagnostic.h:233
A reference to a FileEntry that includes the name of the file as it was accessed by the FileManager's...
Definition FileEntry.h:57
bool isSameRef(const FileEntryRef &RHS) const
Check if RHS referenced the file in exactly the same way.
Definition FileEntry.h:138
bool isNamedPipe() const
Definition FileEntry.h:329
off_t getSize() const
Definition FileEntry.h:317
StringRef getName() const
The name of this FileEntry.
Definition FileEntry.h:61
Cached information about one file (either on disk or in the virtual file system).
Definition FileEntry.h:273
unsigned getUID() const
Definition FileEntry.h:302
off_t getSize() const
Definition FileEntry.h:299
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
bool isValid() const
bool isInvalid() const
Implements support for file system lookup, file system caching, and directory search management.
Definition FileManager.h:52
llvm::ErrorOr< std::unique_ptr< llvm::MemoryBuffer > > getBufferForFile(FileEntryRef Entry, bool isVolatile=false, bool RequiresNullTerminator=true, std::optional< int64_t > MaybeLimit=std::nullopt, bool IsText=true)
Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful,...
Keeps track of options that affect how file operations are performed.
Holds the cache used by isBeforeInTranslationUnit.
void setCommonLoc(FileID commonFID, unsigned lCommonOffset, unsigned rCommonOffset, bool LParentBeforeRParent)
bool getCachedResult(unsigned LOffset, unsigned ROffset) const
If the cache is valid, compute the result given the specified offsets in the LHS/RHS FileID's.
bool isCacheValid() const
Return true if the currently cached values match up with the specified LHS/RHS query.
Used to hold and unique data used to represent #line information.
const LineEntry * FindNearestLineEntry(FileID FID, unsigned Offset)
Find the line entry nearest to FID that is before it.
unsigned getLineTableFilenameID(StringRef Str)
void AddEntry(FileID FID, const std::vector< LineEntry > &Entries)
Add a new line entry that has already been encoded into the internal representation of the line table...
void AddLineNote(FileID FID, unsigned Offset, unsigned LineNo, int FilenameID, unsigned EntryExit, SrcMgr::CharacteristicKind FileKind)
Add a line note to the line table that indicates that there is a #line or GNU line marker at the spec...
Represents an unpacked "presumed" location which can be presented to the user.
unsigned getColumn() const
Return the presumed column number of this location.
unsigned getLine() const
Return the presumed line number of this location.
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
SourceLocation getLocWithOffset(IntTy Offset) const
Return a source location with the specified offset from this SourceLocation.
SourceManagerForFile(StringRef FileName, StringRef Content)
Creates SourceManager and necessary dependencies (e.g.
This class handles loading and caching of source files into memory.
std::optional< StringRef > getNonBuiltinFilenameForID(FileID FID) const
Returns the filename for the provided FileID, unless it's a built-in buffer that's not represented by...
FileIDAndOffset getDecomposedExpansionLoc(SourceLocation Loc) const
Decompose the specified location into a raw FileID + Offset pair.
bool isMacroBodyExpansion(SourceLocation Loc) const
Tests whether the given source location represents the expansion of a macro body.
FileIDAndOffset getDecomposedLoc(SourceLocation Loc) const
Decompose the specified location into a raw FileID + Offset pair.
unsigned getPresumedLineNumber(SourceLocation Loc, bool *Invalid=nullptr) const
FileID getFileID(SourceLocation SpellingLoc) const
Return the FileID for a SourceLocation.
bool isAtEndOfImmediateMacroExpansion(SourceLocation Loc, SourceLocation *MacroEnd=nullptr) const
Returns true if the given MacroID location points at the character end of the immediate macro expansi...
SourceLocation::UIntTy getNextLocalOffset() const
unsigned getColumnNumber(FileID FID, unsigned FilePos, bool *Invalid=nullptr) const
Return the column # for the specified file position.
void noteSLocAddressSpaceUsage(DiagnosticsEngine &Diag, std::optional< unsigned > MaxNotes=32) const
bool isInMainFile(SourceLocation Loc) const
Returns whether the PresumedLoc for a given SourceLocation is in the main file.
void AddLineNote(SourceLocation Loc, unsigned LineNo, int FilenameID, bool IsFileEntry, bool IsFileExit, SrcMgr::CharacteristicKind FileKind)
Add a line note to the line table for the FileID and offset specified by Loc.
SourceManager(DiagnosticsEngine &Diag, FileManager &FileMgr, bool UserFilesAreVolatile=false)
SourceLocation createTokenSplitLoc(SourceLocation SpellingLoc, SourceLocation TokenStart, SourceLocation TokenEnd)
Return a new SourceLocation that encodes that the token starting at TokenStart ends prematurely at To...
PresumedLoc getPresumedLoc(SourceLocation Loc, bool UseLineDirectives=true) const
Returns the "presumed" location of a SourceLocation specifies.
bool isInTheSameTranslationUnitImpl(const FileIDAndOffset &LOffs, const FileIDAndOffset &ROffs) const
Determines whether the two decomposed source location is in the same TU.
MemoryBufferSizes getMemoryBufferSizes() const
Return the amount of memory used by memory buffers, breaking down by heap-backed versus mmap'ed memor...
void setFileIsTransient(FileEntryRef SourceFile)
Specify that a file is transient.
bool isFileOverridden(const FileEntry *File) const
Returns true if the file contents have been overridden.
OptionalFileEntryRef getFileEntryRefForID(FileID FID) const
Returns the FileEntryRef for the provided FileID.
SourceLocation getFileLoc(SourceLocation Loc) const
Given Loc, if it is a macro location return the expansion location or the spelling location,...
SourceLocation translateLineCol(FileID FID, unsigned Line, unsigned Col) const
Get the source location in FID for the given line:col.
StringRef getBufferName(SourceLocation Loc, bool *Invalid=nullptr) const
Return the filename or buffer identifier of the buffer the location is in.
SourceLocation getTopMacroCallerLoc(SourceLocation Loc) const
std::optional< StringRef > getBufferDataOrNone(FileID FID) const
Return a StringRef to the source buffer data for the specified FileID, returning std::nullopt if inva...
FileID translateFile(const FileEntry *SourceFile) const
Get the FileID for the given file.
StringRef getBufferData(FileID FID, bool *Invalid=nullptr) const
Return a StringRef to the source buffer data for the specified FileID.
FileID createFileID(FileEntryRef SourceFile, SourceLocation IncludePos, SrcMgr::CharacteristicKind FileCharacter, int LoadedID=0, SourceLocation::UIntTy LoadedOffset=0)
Create a new FileID that represents the specified file being #included from the specified IncludePosi...
void PrintStats() const
Print statistics to stderr.
FileID getUniqueLoadedASTFileID(SourceLocation Loc) const
bool isMainFile(const FileEntry &SourceFile)
Returns true when the given FileEntry corresponds to the main file.
size_t getDataStructureSizes() const
Return the amount of memory used for various side tables and data structures in the SourceManager.
bool isMacroArgExpansion(SourceLocation Loc, SourceLocation *StartLoc=nullptr) const
Tests whether the given source location represents a macro argument's expansion into the function-lik...
const SrcMgr::SLocEntry & getLocalSLocEntry(unsigned Index) const
Get a local SLocEntry. This is exposed for indexing.
SourceLocation getComposedLoc(FileID FID, unsigned Offset) const
Form a SourceLocation from a FileID and Offset pair.
OptionalFileEntryRef bypassFileContentsOverride(FileEntryRef File)
Bypass the overridden contents of a file.
const SrcMgr::SLocEntry & getLoadedSLocEntry(unsigned Index, bool *Invalid=nullptr) const
Get a loaded SLocEntry. This is exposed for indexing.
llvm::DenseMap< FileEntryRef, SrcMgr::ContentCache * >::const_iterator fileinfo_iterator
FileManager & getFileManager() const
fileinfo_iterator fileinfo_end() const
unsigned local_sloc_entry_size() const
Get the number of local SLocEntries we have.
std::optional< StringRef > getBufferDataIfLoaded(FileID FID) const
Return a StringRef to the source buffer data for the specified FileID, returning std::nullopt if it's...
FileIDAndOffset getDecomposedSpellingLoc(SourceLocation Loc) const
Decompose the specified location into a raw FileID + Offset pair.
const char * getCharacterData(SourceLocation SL, bool *Invalid=nullptr) const
Return a pointer to the start of the specified location in the appropriate spelling MemoryBuffer.
std::pair< int, SourceLocation::UIntTy > AllocateLoadedSLocEntries(unsigned NumSLocEntries, SourceLocation::UIntTy TotalSize)
Allocate a number of loaded SLocEntries, which will be actually loaded on demand from the external so...
void overrideFileContents(FileEntryRef SourceFile, const llvm::MemoryBufferRef &Buffer)
Override the contents of the given source file by providing an already-allocated buffer.
llvm::MemoryBufferRef getBufferOrFake(FileID FID, SourceLocation Loc=SourceLocation()) const
Return the buffer for the specified FileID.
unsigned getFileIDSize(FileID FID) const
The size of the SLocEntry that FID represents.
unsigned getLineNumber(FileID FID, unsigned FilePos, bool *Invalid=nullptr) const
Given a SourceLocation, return the spelling line number for the position indicated.
CharSourceRange getImmediateExpansionRange(SourceLocation Loc) const
Return the start/end of the expansion information for an expansion location.
CharSourceRange getExpansionRange(SourceLocation Loc) const
Given a SourceLocation object, return the range of tokens covered by the expansion in the ultimate fi...
bool isInFileID(SourceLocation Loc, FileID FID, unsigned *RelativeOffset=nullptr) const
Given a specific FileID, returns true if Loc is inside that FileID chunk and sets relative offset (of...
unsigned getLineTableFilenameID(StringRef Str)
Return the uniqued ID for the specified filename.
void initializeForReplay(const SourceManager &Old)
Initialize this source manager suitably to replay the compilation described by Old.
FileIDAndOffset getDecomposedIncludedLoc(FileID FID) const
Returns the "included/expanded in" decomposed location of the given FileID.
bool isLoadedSourceLocation(SourceLocation Loc) const
Returns true if Loc came from a PCH/Module.
unsigned loaded_sloc_entry_size() const
Get the number of loaded SLocEntries we have.
FileID getOrCreateFileID(FileEntryRef SourceFile, SrcMgr::CharacteristicKind FileCharacter)
Get the FileID for SourceFile if it exists.
SourceLocation translateFileLineCol(const FileEntry *SourceFile, unsigned Line, unsigned Col) const
Get the source location for the given file:line:col triplet.
bool isLoadedFileID(FileID FID) const
Returns true if FID came from a PCH/Module.
const FileEntry * getFileEntryForID(FileID FID) const
Returns the FileEntry record for the provided FileID.
bool isInSameSLocAddrSpace(SourceLocation LHS, SourceLocation RHS, SourceLocation::IntTy *RelativeOffset) const
Return true if both LHS and RHS are in the local source location address space or the loaded one.
SourceLocation getLocForStartOfFile(FileID FID) const
Return the source location corresponding to the first byte of the specified file.
bool isAtStartOfImmediateMacroExpansion(SourceLocation Loc, SourceLocation *MacroBegin=nullptr) const
Returns true if the given MacroID location points at the beginning of the immediate macro expansion.
SrcMgr::CharacteristicKind getFileCharacteristic(SourceLocation Loc) const
Return the file characteristic of the specified source location, indicating whether this is a normal ...
SourceLocation createExpansionLoc(SourceLocation SpellingLoc, SourceLocation ExpansionLocStart, SourceLocation ExpansionLocEnd, unsigned Length, bool ExpansionIsTokenRange=true, int LoadedID=0, SourceLocation::UIntTy LoadedOffset=0)
Creates an expansion SLocEntry for a macro use.
unsigned getPresumedColumnNumber(SourceLocation Loc, bool *Invalid=nullptr) const
std::pair< bool, bool > isInTheSameTranslationUnit(FileIDAndOffset &LOffs, FileIDAndOffset &ROffs) const
Determines whether the two decomposed source location is in the same translation unit.
StringRef getFilename(SourceLocation SpellingLoc) const
Return the filename of the file containing a SourceLocation.
SourceLocation getMacroArgExpandedLocation(SourceLocation Loc) const
If Loc points inside a function macro argument, the returned location will be the macro location in w...
bool isBeforeInTranslationUnit(SourceLocation LHS, SourceLocation RHS) const
Determines the order of 2 source locations in the translation unit.
std::optional< llvm::MemoryBufferRef > getBufferOrNone(FileID FID, SourceLocation Loc=SourceLocation()) const
Return the buffer for the specified FileID.
fileinfo_iterator fileinfo_begin() const
LineTableInfo & getLineTable()
Retrieve the stored line table.
SourceLocation getImmediateSpellingLoc(SourceLocation Loc) const
Given a SourceLocation object, return the spelling location referenced by the ID.
std::optional< llvm::MemoryBufferRef > getMemoryBufferForFileOrNone(FileEntryRef File)
Retrieve the memory buffer associated with the given file.
const SrcMgr::SLocEntry & getSLocEntry(FileID FID, bool *Invalid=nullptr) const
SourceLocation createMacroArgExpansionLoc(SourceLocation SpellingLoc, SourceLocation ExpansionLoc, unsigned Length)
Creates an expansion SLocEntry for the substitution of an argument into a function-like macro's body.
A trivial tuple used to represent a source range.
One instance of this struct is kept for every file loaded or used.
void setBuffer(std::unique_ptr< llvm::MemoryBuffer > B)
Set the buffer.
std::optional< StringRef > getBufferDataIfLoaded() const
Return a StringRef to the source buffer data, only if it has already been loaded.
OptionalFileEntryRef ContentsEntry
References the file which the contents were actually loaded from.
unsigned getSizeBytesMapped() const
Returns the number of bytes actually mapped for this ContentCache.
unsigned IsTransient
True if this file may be transient, that is, if it might not exist at some later point in time when t...
unsigned getSize() const
Returns the size of the content encapsulated by this ContentCache.
llvm::MemoryBuffer::BufferKind getMemoryBufferKind() const
Returns the kind of memory used to back the memory buffer for this content cache.
unsigned IsFileVolatile
True if this content cache was initially created for a source file considered to be volatile (likely ...
LineOffsetMapping SourceLineCache
A bump pointer allocated array of offsets for each source line.
std::optional< llvm::MemoryBufferRef > getBufferOrNone(DiagnosticsEngine &Diag, FileManager &FM, SourceLocation Loc=SourceLocation()) const
Returns the memory buffer for the associated content.
static const char * getInvalidBOM(StringRef BufStr)
unsigned BufferOverridden
Indicates whether the buffer itself was provided to override the actual file contents.
OptionalFileEntryRef OrigEntry
Reference to the file entry representing this ContentCache.
Each ExpansionInfo encodes the expansion location - where the token was ultimately expanded,...
SourceLocation getExpansionLocStart() const
static ExpansionInfo create(SourceLocation SpellingLoc, SourceLocation Start, SourceLocation End, bool ExpansionIsTokenRange=true)
Return a ExpansionInfo for an expansion.
SourceLocation getSpellingLoc() const
CharSourceRange getExpansionLocRange() const
static ExpansionInfo createForMacroArg(SourceLocation SpellingLoc, SourceLocation ExpansionLoc)
Return a special ExpansionInfo for the expansion of a macro argument into a function-like macro's bod...
static ExpansionInfo createForTokenSplit(SourceLocation SpellingLoc, SourceLocation Start, SourceLocation End)
Return a special ExpansionInfo representing a token that ends prematurely.
SourceLocation getExpansionLocEnd() const
Information about a FileID, basically just the logical file that it represents and include stack info...
const ContentCache & getContentCache() const
CharacteristicKind getFileCharacteristic() const
Return whether this is a system header or not.
static FileInfo get(SourceLocation IL, ContentCache &Con, CharacteristicKind FileCharacter, StringRef Filename)
Return a FileInfo object.
bool hasLineDirectives() const
Return true if this FileID has #line directives in it.
void setHasLineDirectives()
Set the flag that indicates that this FileID has line table entries associated with it.
SourceLocation getIncludeLoc() const
const unsigned * begin() const
const unsigned * end() const
static LineOffsetMapping get(llvm::MemoryBufferRef Buffer, llvm::BumpPtrAllocator &Alloc)
This is a discriminated union of FileInfo and ExpansionInfo.
SourceLocation::UIntTy getOffset() const
static SLocEntry get(SourceLocation::UIntTy Offset, const FileInfo &FI)
const FileInfo & getFile() const
const ExpansionInfo & getExpansion() const
Public enums and private classes that are part of the SourceManager implementation.
CharacteristicKind
Indicates whether a file or directory holds normal user code, system code, or system code which is im...
bool isSystem(CharacteristicKind CK)
Determine whether a file / directory characteristic is for system code.
StringRef getName(const HeaderType T)
Definition HeaderFile.h:38
The JSON file list parser is used to communicate input to InstallAPI.
CustomizableOptional< FileEntryRef > OptionalFileEntryRef
Definition FileEntry.h:196
std::pair< FileID, unsigned > FileIDAndOffset
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
@ Other
Other implicit parameter.
Definition Decl.h:1772
SrcMgr::CharacteristicKind FileKind
Set the 0 if no flags, 1 if a system header,.
static LineEntry get(unsigned Offs, unsigned Line, int Filename, SrcMgr::CharacteristicKind FileKind, unsigned IncludeOffset)