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