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