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()
81 : (unsigned)ContentsEntry->getSize();
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,
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 = llvm::needConversion(Filename);
612 if (NeedConversion && *NeedConversion) {
613 // Buffer size may increase due to potential z/OS EBCDIC to UTF-8
614 // conversion.
615 if (std::optional<llvm::MemoryBufferRef> Buffer =
616 File.getBufferOrNone(Diag, getFileManager())) {
617 unsigned BufSize = Buffer->getBufferSize();
618 if (BufSize > FileSize) {
619 if (File.ContentsEntry.has_value())
620 File.ContentsEntry->updateFileEntryBufferSize(BufSize);
621 FileSize = BufSize;
622 }
623 }
624 }
625 if (!(NextLocalOffset + FileSize + 1 > NextLocalOffset &&
626 NextLocalOffset + FileSize + 1 <= CurrentLoadedOffset)) {
627 Diag.Report(IncludePos, diag::err_sloc_space_too_large);
629 return FileID();
630 }
631 assert(LocalSLocEntryTable.size() == LocalLocOffsetTable.size());
632 LocalSLocEntryTable.push_back(
633 SLocEntry::get(NextLocalOffset,
634 FileInfo::get(IncludePos, File, FileCharacter, Filename)));
635 LocalLocOffsetTable.push_back(NextLocalOffset);
636 LastLookupStartOffset = NextLocalOffset;
637 // We do a +1 here because we want a SourceLocation that means "the end of the
638 // file", e.g. for the "no newline at the end of the file" diagnostic.
639 NextLocalOffset += FileSize + 1;
640 LastLookupEndOffset = NextLocalOffset;
641 updateSlocUsageStats();
642
643 // Set LastFileIDLookup to the newly created file. The next getFileID call is
644 // almost guaranteed to be from that file.
645 FileID FID = FileID::get(LocalSLocEntryTable.size()-1);
646 return LastFileIDLookup = FID;
647}
648
650 SourceLocation SpellingLoc, SourceLocation ExpansionLoc, unsigned Length) {
652 ExpansionLoc);
653 return createExpansionLocImpl(Info, Length);
654}
655
657 SourceLocation SpellingLoc, SourceLocation ExpansionLocStart,
658 SourceLocation ExpansionLocEnd, unsigned Length,
659 bool ExpansionIsTokenRange, int LoadedID,
660 SourceLocation::UIntTy LoadedOffset) {
662 SpellingLoc, ExpansionLocStart, ExpansionLocEnd, ExpansionIsTokenRange);
663 return createExpansionLocImpl(Info, Length, LoadedID, LoadedOffset);
664}
665
667 SourceLocation TokenStart,
668 SourceLocation TokenEnd) {
669 assert(getFileID(TokenStart) == getFileID(TokenEnd) &&
670 "token spans multiple files");
671 return createExpansionLocImpl(
672 ExpansionInfo::createForTokenSplit(Spelling, TokenStart, TokenEnd),
673 TokenEnd.getOffset() - TokenStart.getOffset());
674}
675
677SourceManager::createExpansionLocImpl(const ExpansionInfo &Info,
678 unsigned Length, int LoadedID,
679 SourceLocation::UIntTy LoadedOffset) {
680 if (LoadedID < 0) {
681 assert(LoadedID != -1 && "Loading sentinel FileID");
682 unsigned Index = unsigned(-LoadedID) - 2;
683 assert(Index < LoadedSLocEntryTable.size() && "FileID out of range");
684 assert(!SLocEntryLoaded[Index] && "FileID already loaded");
685 LoadedSLocEntryTable[Index] = SLocEntry::get(LoadedOffset, Info);
686 SLocEntryLoaded[Index] = SLocEntryOffsetLoaded[Index] = true;
687 return SourceLocation::getMacroLoc(LoadedOffset);
688 }
689 assert(LocalSLocEntryTable.size() == LocalLocOffsetTable.size());
690 LocalSLocEntryTable.push_back(SLocEntry::get(NextLocalOffset, Info));
691 LocalLocOffsetTable.push_back(NextLocalOffset);
692 if (NextLocalOffset + Length + 1 <= NextLocalOffset ||
693 NextLocalOffset + Length + 1 > CurrentLoadedOffset) {
694 Diag.Report(diag::err_sloc_space_too_large);
695 // FIXME: call `noteSLocAddressSpaceUsage` to report details to users and
696 // use a source location from `Info` to point at an error.
697 // Currently, both cause Clang to run indefinitely, this needs to be fixed.
698 // FIXME: return an error instead of crashing. Returning invalid source
699 // locations causes compiler to run indefinitely.
700 llvm::report_fatal_error("ran out of source locations");
701 }
702 // See createFileID for that +1.
703 NextLocalOffset += Length + 1;
704 updateSlocUsageStats();
705 return SourceLocation::getMacroLoc(NextLocalOffset - (Length + 1));
706}
707
708std::optional<llvm::MemoryBufferRef>
713
715 FileEntryRef SourceFile, std::unique_ptr<llvm::MemoryBuffer> Buffer) {
716 SrcMgr::ContentCache &IR = getOrCreateContentCache(SourceFile);
717
718 IR.setBuffer(std::move(Buffer));
719 IR.BufferOverridden = true;
720
721 getOverriddenFilesInfo().OverriddenFilesWithBuffer.insert(SourceFile);
722}
723
725 FileEntryRef NewFile) {
726 assert(SourceFile->getSize() == NewFile.getSize() &&
727 "Different sizes, use the FileManager to create a virtual file with "
728 "the correct size");
729 assert(FileInfos.find_as(SourceFile) == FileInfos.end() &&
730 "This function should be called at the initialization stage, before "
731 "any parsing occurs.");
732 // FileEntryRef is not default-constructible.
733 auto Pair = getOverriddenFilesInfo().OverriddenFiles.insert(
734 std::make_pair(SourceFile, NewFile));
735 if (!Pair.second)
736 Pair.first->second = NewFile;
737}
738
741 assert(isFileOverridden(&File.getFileEntry()));
742 OptionalFileEntryRef BypassFile = FileMgr.getBypassFile(File);
743
744 // If the file can't be found in the FS, give up.
745 if (!BypassFile)
746 return std::nullopt;
747
748 (void)getOrCreateContentCache(*BypassFile);
749 return BypassFile;
750}
751
753 getOrCreateContentCache(File).IsTransient = true;
754}
755
756std::optional<StringRef>
758 if (const SrcMgr::SLocEntry *Entry = getSLocEntryForFile(FID))
759 if (Entry->getFile().getContentCache().OrigEntry)
760 return Entry->getFile().getName();
761 return std::nullopt;
762}
763
764StringRef SourceManager::getBufferData(FileID FID, bool *Invalid) const {
765 auto B = getBufferDataOrNone(FID);
766 if (Invalid)
767 *Invalid = !B;
768 return B ? *B : "<<<<<INVALID SOURCE LOCATION>>>>>";
769}
770
771std::optional<StringRef>
773 if (const SrcMgr::SLocEntry *Entry = getSLocEntryForFile(FID))
774 return Entry->getFile().getContentCache().getBufferDataIfLoaded();
775 return std::nullopt;
776}
777
778std::optional<StringRef> SourceManager::getBufferDataOrNone(FileID FID) const {
779 if (const SrcMgr::SLocEntry *Entry = getSLocEntryForFile(FID))
780 if (auto B = Entry->getFile().getContentCache().getBufferOrNone(
781 Diag, getFileManager(), SourceLocation()))
782 return B->getBuffer();
783 return std::nullopt;
784}
785
786//===----------------------------------------------------------------------===//
787// SourceLocation manipulation methods.
788//===----------------------------------------------------------------------===//
789
790/// Return the FileID for a SourceLocation.
791///
792/// This is the cache-miss path of getFileID. Not as hot as that function, but
793/// still very important. It is responsible for finding the entry in the
794/// SLocEntry tables that contains the specified location.
795FileID SourceManager::getFileIDSlow(SourceLocation::UIntTy SLocOffset) const {
796 if (!SLocOffset)
797 return FileID::get(0);
798
799 // Now it is time to search for the correct file. See where the SLocOffset
800 // sits in the global view and consult local or loaded buffers for it.
801 if (SLocOffset < NextLocalOffset)
802 return getFileIDLocal(SLocOffset);
803 return getFileIDLoaded(SLocOffset);
804}
805
806/// Return the FileID for a SourceLocation with a low offset.
807///
808/// This function knows that the SourceLocation is in a local buffer, not a
809/// loaded one.
810FileID SourceManager::getFileIDLocal(SourceLocation::UIntTy SLocOffset) const {
811 assert(SLocOffset < NextLocalOffset && "Bad function choice");
812 assert(SLocOffset >= LocalSLocEntryTable[0].getOffset() && SLocOffset > 0 &&
813 "Invalid SLocOffset");
814 assert(LocalSLocEntryTable.size() == LocalLocOffsetTable.size());
815 assert(LastFileIDLookup.ID >= 0 && "Only cache local file sloc entry");
816
817 // After the first and second level caches, I see two common sorts of
818 // behavior: 1) a lot of searched FileID's are "near" the cached file
819 // location or are "near" the cached expansion location. 2) others are just
820 // completely random and may be a very long way away.
821 //
822 // To handle this, we do a linear search for up to 8 steps to catch #1 quickly
823 // then we fall back to a less cache efficient, but more scalable, binary
824 // search to find the location.
825
826 // See if this is near the file point - worst case we start scanning from the
827 // most newly created FileID.
828
829 // LessIndex - This is the lower bound of the range that we're searching.
830 // We know that the offset corresponding to the FileID is less than
831 // SLocOffset.
832 unsigned LessIndex = 0;
833 // upper bound of the search range.
834 unsigned GreaterIndex = LocalLocOffsetTable.size();
835 // Use the LastFileIDLookup to prune the search space.
836 if (LastLookupStartOffset < SLocOffset)
837 LessIndex = LastFileIDLookup.ID;
838 else
839 GreaterIndex = LastFileIDLookup.ID;
840
841 // Find the FileID that contains this.
842 unsigned NumProbes = 0;
843 while (true) {
844 --GreaterIndex;
845 assert(GreaterIndex < LocalLocOffsetTable.size());
846 if (LocalLocOffsetTable[GreaterIndex] <= SLocOffset) {
847 FileID Res = FileID::get(int(GreaterIndex));
848 // Remember it. We have good locality across FileID lookups.
849 LastFileIDLookup = Res;
850 LastLookupStartOffset = LocalLocOffsetTable[GreaterIndex];
851 LastLookupEndOffset =
852 GreaterIndex + 1 >= LocalLocOffsetTable.size()
853 ? NextLocalOffset
854 : LocalLocOffsetTable[GreaterIndex + 1];
855 NumLinearScans += NumProbes + 1;
856 return Res;
857 }
858 if (++NumProbes == 8)
859 break;
860 }
861
862 while (LessIndex < GreaterIndex) {
863 ++NumBinaryProbes;
864
865 unsigned MiddleIndex = LessIndex + (GreaterIndex - LessIndex) / 2;
866 if (LocalLocOffsetTable[MiddleIndex] <= SLocOffset)
867 LessIndex = MiddleIndex + 1;
868 else
869 GreaterIndex = MiddleIndex;
870 }
871
872 // At this point, LessIndex is the index of the *first element greater than*
873 // SLocOffset. The element we are actually looking for is the one immediately
874 // before it.
875 LastLookupStartOffset = LocalLocOffsetTable[LessIndex - 1];
876 LastLookupEndOffset = LocalLocOffsetTable[LessIndex];
877 return LastFileIDLookup = FileID::get(LessIndex - 1);
878}
879
880/// Return the FileID for a SourceLocation with a high offset.
881///
882/// This function knows that the SourceLocation is in a loaded buffer, not a
883/// local one.
884FileID SourceManager::getFileIDLoaded(SourceLocation::UIntTy SLocOffset) const {
885 if (SLocOffset < CurrentLoadedOffset) {
886 assert(0 && "Invalid SLocOffset or bad function choice");
887 return FileID();
888 }
889
890 return FileID::get(ExternalSLocEntries->getSLocEntryID(SLocOffset));
891}
892
893SourceLocation SourceManager::
894getExpansionLocSlowCase(SourceLocation Loc) const {
895 do {
896 // Note: If Loc indicates an offset into a token that came from a macro
897 // expansion (e.g. the 5th character of the token) we do not want to add
898 // this offset when going to the expansion location. The expansion
899 // location is the macro invocation, which the offset has nothing to do
900 // with. This is unlike when we get the spelling loc, because the offset
901 // directly correspond to the token whose spelling we're inspecting.
903 } while (!Loc.isFileID());
904
905 return Loc;
906}
907
908SourceLocation SourceManager::getSpellingLocSlowCase(SourceLocation Loc) const {
909 do {
910 const SLocEntry &Entry = getSLocEntry(getFileID(Loc));
912 Loc.getOffset() - Entry.getOffset());
913 } while (!Loc.isFileID());
914 return Loc;
915}
916
917SourceLocation SourceManager::getFileLocSlowCase(SourceLocation Loc) const {
918 do {
919 const SLocEntry &Entry = getSLocEntry(getFileID(Loc));
920 const ExpansionInfo &ExpInfo = Entry.getExpansion();
921 if (ExpInfo.isMacroArgExpansion()) {
922 Loc = ExpInfo.getSpellingLoc().getLocWithOffset(Loc.getOffset() -
923 Entry.getOffset());
924 } else {
925 Loc = ExpInfo.getExpansionLocStart();
926 }
927 } while (!Loc.isFileID());
928 return Loc;
929}
930
931/// getImmediateSpellingLoc - Given a SourceLocation object, return the
932/// spelling location referenced by the ID. This is the first level down
933/// towards the place where the characters that make up the lexed token can be
934/// found. This should not generally be used by clients.
936 if (Loc.isFileID()) return Loc;
937 FileIDAndOffset LocInfo = getDecomposedLoc(Loc);
938 Loc = getSLocEntry(LocInfo.first).getExpansion().getSpellingLoc();
939 return Loc.getLocWithOffset(LocInfo.second);
940}
941
942/// Return the filename of the file containing a SourceLocation.
943StringRef SourceManager::getFilename(SourceLocation SpellingLoc) const {
945 return F->getName();
946 return StringRef();
947}
948
949/// getImmediateExpansionRange - Loc is required to be an expansion location.
950/// Return the start/end of the expansion information.
953 assert(Loc.isMacroID() && "Not a macro expansion loc!");
954 const ExpansionInfo &Expansion = getSLocEntry(getFileID(Loc)).getExpansion();
955 return Expansion.getExpansionLocRange();
956}
957
963
964/// getExpansionRange - Given a SourceLocation object, return the range of
965/// tokens covered by the expansion in the ultimate file.
967 if (Loc.isFileID())
968 return CharSourceRange(SourceRange(Loc, Loc), true);
969
971
972 // Fully resolve the start and end locations to their ultimate expansion
973 // points.
974 while (!Res.getBegin().isFileID())
976 while (!Res.getEnd().isFileID()) {
978 Res.setEnd(EndRange.getEnd());
979 Res.setTokenRange(EndRange.isTokenRange());
980 }
981 return Res;
982}
983
985 SourceLocation *StartLoc) const {
986 if (!Loc.isMacroID()) return false;
987
988 FileID FID = getFileID(Loc);
989 const SrcMgr::ExpansionInfo &Expansion = getSLocEntry(FID).getExpansion();
990 if (!Expansion.isMacroArgExpansion()) return false;
991
992 if (StartLoc)
993 *StartLoc = Expansion.getExpansionLocStart();
994 return true;
995}
996
998 if (!Loc.isMacroID()) return false;
999
1000 FileID FID = getFileID(Loc);
1001 const SrcMgr::ExpansionInfo &Expansion = getSLocEntry(FID).getExpansion();
1002 return Expansion.isMacroBodyExpansion();
1003}
1004
1006 SourceLocation *MacroBegin) const {
1007 assert(Loc.isValid() && Loc.isMacroID() && "Expected a valid macro loc");
1008
1009 FileIDAndOffset DecompLoc = getDecomposedLoc(Loc);
1010 if (DecompLoc.second > 0)
1011 return false; // Does not point at the start of expansion range.
1012
1013 bool Invalid = false;
1014 const SrcMgr::ExpansionInfo &ExpInfo =
1015 getSLocEntry(DecompLoc.first, &Invalid).getExpansion();
1016 if (Invalid)
1017 return false;
1018 SourceLocation ExpLoc = ExpInfo.getExpansionLocStart();
1019
1020 if (ExpInfo.isMacroArgExpansion()) {
1021 // For macro argument expansions, check if the previous FileID is part of
1022 // the same argument expansion, in which case this Loc is not at the
1023 // beginning of the expansion.
1024 FileID PrevFID = getPreviousFileID(DecompLoc.first);
1025 if (!PrevFID.isInvalid()) {
1026 const SrcMgr::SLocEntry &PrevEntry = getSLocEntry(PrevFID, &Invalid);
1027 if (Invalid)
1028 return false;
1029 if (PrevEntry.isExpansion() &&
1030 PrevEntry.getExpansion().getExpansionLocStart() == ExpLoc)
1031 return false;
1032 }
1033 }
1034
1035 if (MacroBegin)
1036 *MacroBegin = ExpLoc;
1037 return true;
1038}
1039
1041 SourceLocation *MacroEnd) const {
1042 assert(Loc.isValid() && Loc.isMacroID() && "Expected a valid macro loc");
1043
1044 FileID FID = getFileID(Loc);
1045 SourceLocation NextLoc = Loc.getLocWithOffset(1);
1046 if (isInFileID(NextLoc, FID))
1047 return false; // Does not point at the end of expansion range.
1048
1049 bool Invalid = false;
1050 const SrcMgr::ExpansionInfo &ExpInfo =
1052 if (Invalid)
1053 return false;
1054
1055 if (ExpInfo.isMacroArgExpansion()) {
1056 // For macro argument expansions, check if the next FileID is part of the
1057 // same argument expansion, in which case this Loc is not at the end of the
1058 // expansion.
1059 FileID NextFID = getNextFileID(FID);
1060 if (!NextFID.isInvalid()) {
1061 const SrcMgr::SLocEntry &NextEntry = getSLocEntry(NextFID, &Invalid);
1062 if (Invalid)
1063 return false;
1064 if (NextEntry.isExpansion() &&
1065 NextEntry.getExpansion().getExpansionLocStart() ==
1066 ExpInfo.getExpansionLocStart())
1067 return false;
1068 }
1069 }
1070
1071 if (MacroEnd)
1072 *MacroEnd = ExpInfo.getExpansionLocEnd();
1073 return true;
1074}
1075
1076//===----------------------------------------------------------------------===//
1077// Queries about the code at a SourceLocation.
1078//===----------------------------------------------------------------------===//
1079
1080/// getCharacterData - Return a pointer to the start of the specified location
1081/// in the appropriate MemoryBuffer.
1083 bool *Invalid) const {
1084 // Note that this is a hot function in the getSpelling() path, which is
1085 // heavily used by -E mode.
1087
1088 // Note that calling 'getBuffer()' may lazily page in a source file.
1089 bool CharDataInvalid = false;
1090 const SLocEntry &Entry = getSLocEntry(LocInfo.first, &CharDataInvalid);
1091 if (CharDataInvalid || !Entry.isFile()) {
1092 if (Invalid)
1093 *Invalid = true;
1094
1095 return "<<<<INVALID BUFFER>>>>";
1096 }
1097 std::optional<llvm::MemoryBufferRef> Buffer =
1099 SourceLocation());
1100 if (Invalid)
1101 *Invalid = !Buffer;
1102 return Buffer ? Buffer->getBufferStart() + LocInfo.second
1103 : "<<<<INVALID BUFFER>>>>";
1104}
1105
1106/// getColumnNumber - Return the column # for the specified file position.
1107/// this is significantly cheaper to compute than the line number.
1108unsigned SourceManager::getColumnNumber(FileID FID, unsigned FilePos,
1109 bool *Invalid) const {
1110 std::optional<llvm::MemoryBufferRef> MemBuf = getBufferOrNone(FID);
1111 if (Invalid)
1112 *Invalid = !MemBuf;
1113
1114 if (!MemBuf)
1115 return 1;
1116
1117 // It is okay to request a position just past the end of the buffer.
1118 if (FilePos > MemBuf->getBufferSize()) {
1119 if (Invalid)
1120 *Invalid = true;
1121 return 1;
1122 }
1123
1124 const char *Buf = MemBuf->getBufferStart();
1125 // See if we just calculated the line number for this FilePos and can use
1126 // that to lookup the start of the line instead of searching for it.
1127 if (LastLineNoFileIDQuery == FID && LastLineNoContentCache->SourceLineCache &&
1128 LastLineNoResult < LastLineNoContentCache->SourceLineCache.size()) {
1129 const unsigned *SourceLineCache =
1130 LastLineNoContentCache->SourceLineCache.begin();
1131 unsigned LineStart = SourceLineCache[LastLineNoResult - 1];
1132 unsigned LineEnd = SourceLineCache[LastLineNoResult];
1133 if (FilePos >= LineStart && FilePos < LineEnd) {
1134 // LineEnd is the LineStart of the next line.
1135 // A line ends with separator LF or CR+LF on Windows.
1136 // FilePos might point to the last separator,
1137 // but we need a column number at most 1 + the last column.
1138 if (FilePos + 1 == LineEnd && FilePos > LineStart) {
1139 if (Buf[FilePos - 1] == '\r' || Buf[FilePos - 1] == '\n')
1140 --FilePos;
1141 }
1142 return (FilePos - LineStart) + 1;
1143 }
1144 }
1145
1146 unsigned LineStart = FilePos;
1147 while (LineStart && Buf[LineStart-1] != '\n' && Buf[LineStart-1] != '\r')
1148 --LineStart;
1149 return (FilePos - LineStart) + 1;
1150}
1151
1152// isInvalid - Return the result of calling loc.isInvalid(), and
1153// if Invalid is not null, set its value to same.
1154template<typename LocType>
1155static bool isInvalid(LocType Loc, bool *Invalid) {
1156 bool MyInvalid = Loc.isInvalid();
1157 if (Invalid)
1158 *Invalid = MyInvalid;
1159 return MyInvalid;
1160}
1161
1163 bool *Invalid) const {
1164 assert(Loc.isFileID());
1165 if (isInvalid(Loc, Invalid)) return 0;
1166 FileIDAndOffset LocInfo = getDecomposedLoc(Loc);
1167 return getColumnNumber(LocInfo.first, LocInfo.second, Invalid);
1168}
1169
1171 bool *Invalid) const {
1172 PresumedLoc PLoc = getPresumedLoc(Loc);
1173 if (isInvalid(PLoc, Invalid)) return 0;
1174 return PLoc.getColumn();
1175}
1176
1177// Check if multi-byte word x has bytes between m and n, included. This may also
1178// catch bytes equal to n + 1.
1179// The returned value holds a 0x80 at each byte position that holds a match.
1180// see http://graphics.stanford.edu/~seander/bithacks.html#HasBetweenInWord
1181template <class T>
1182static constexpr inline T likelyhasbetween(T x, unsigned char m,
1183 unsigned char n) {
1184 return ((x - ~static_cast<T>(0) / 255 * (n + 1)) & ~x &
1185 ((x & ~static_cast<T>(0) / 255 * 127) +
1186 (~static_cast<T>(0) / 255 * (127 - (m - 1))))) &
1187 ~static_cast<T>(0) / 255 * 128;
1188}
1189
1190LineOffsetMapping LineOffsetMapping::get(llvm::MemoryBufferRef Buffer,
1191 llvm::BumpPtrAllocator &Alloc) {
1192
1193 // Find the file offsets of all of the *physical* source lines. This does
1194 // not look at trigraphs, escaped newlines, or anything else tricky.
1195 SmallVector<unsigned, 256> LineOffsets;
1196
1197 // Line #1 starts at char 0.
1198 LineOffsets.push_back(0);
1199
1200 const unsigned char *Start = (const unsigned char *)Buffer.getBufferStart();
1201 const unsigned char *End = (const unsigned char *)Buffer.getBufferEnd();
1202 const unsigned char *Buf = Start;
1203
1204 uint64_t Word;
1205
1206 // scan sizeof(Word) bytes at a time for new lines.
1207 // This is much faster than scanning each byte independently.
1208 if ((unsigned long)(End - Start) > sizeof(Word)) {
1209 do {
1210 Word = llvm::support::endian::read64(Buf, llvm::endianness::little);
1211 // no new line => jump over sizeof(Word) bytes.
1212 auto Mask = likelyhasbetween(Word, '\n', '\r');
1213 if (!Mask) {
1214 Buf += sizeof(Word);
1215 continue;
1216 }
1217
1218 // At that point, Mask contains 0x80 set at each byte that holds a value
1219 // in [\n, \r + 1 [
1220
1221 // Scan for the next newline - it's very likely there's one.
1222 unsigned N = llvm::countr_zero(Mask) - 7; // -7 because 0x80 is the marker
1223 Word >>= N;
1224 Buf += N / 8 + 1;
1225 unsigned char Byte = Word;
1226 switch (Byte) {
1227 case '\r':
1228 // If this is \r\n, skip both characters.
1229 if (*Buf == '\n') {
1230 ++Buf;
1231 }
1232 [[fallthrough]];
1233 case '\n':
1234 LineOffsets.push_back(Buf - Start);
1235 };
1236 } while (Buf < End - sizeof(Word) - 1);
1237 }
1238
1239 // Handle tail using a regular check.
1240 while (Buf < End) {
1241 if (*Buf == '\n') {
1242 LineOffsets.push_back(Buf - Start + 1);
1243 } else if (*Buf == '\r') {
1244 // If this is \r\n, skip both characters.
1245 if (Buf + 1 < End && Buf[1] == '\n') {
1246 ++Buf;
1247 }
1248 LineOffsets.push_back(Buf - Start + 1);
1249 }
1250 ++Buf;
1251 }
1252
1253 return LineOffsetMapping(LineOffsets, Alloc);
1254}
1255
1257 llvm::BumpPtrAllocator &Alloc)
1258 : Storage(Alloc.Allocate<unsigned>(LineOffsets.size() + 1)) {
1259 Storage[0] = LineOffsets.size();
1260 std::copy(LineOffsets.begin(), LineOffsets.end(), Storage + 1);
1261}
1262
1263/// getLineNumber - Given a SourceLocation, return the spelling line number
1264/// for the position indicated. This requires building and caching a table of
1265/// line offsets for the MemoryBuffer, so this is not cheap: use only when
1266/// about to emit a diagnostic.
1267unsigned SourceManager::getLineNumber(FileID FID, unsigned FilePos,
1268 bool *Invalid) const {
1269 if (FID.isInvalid()) {
1270 if (Invalid)
1271 *Invalid = true;
1272 return 1;
1273 }
1274
1275 const ContentCache *Content;
1276 if (LastLineNoFileIDQuery == FID)
1277 Content = LastLineNoContentCache;
1278 else {
1279 bool MyInvalid = false;
1280 const SLocEntry &Entry = getSLocEntry(FID, &MyInvalid);
1281 if (MyInvalid || !Entry.isFile()) {
1282 if (Invalid)
1283 *Invalid = true;
1284 return 1;
1285 }
1286
1287 Content = &Entry.getFile().getContentCache();
1288 }
1289
1290 // If this is the first use of line information for this buffer, compute the
1291 // SourceLineCache for it on demand.
1292 if (!Content->SourceLineCache) {
1293 std::optional<llvm::MemoryBufferRef> Buffer =
1294 Content->getBufferOrNone(Diag, getFileManager(), SourceLocation());
1295 if (Invalid)
1296 *Invalid = !Buffer;
1297 if (!Buffer)
1298 return 1;
1299
1300 Content->SourceLineCache =
1301 LineOffsetMapping::get(*Buffer, ContentCacheAlloc);
1302 } else if (Invalid)
1303 *Invalid = false;
1304
1305 // Okay, we know we have a line number table. Do a binary search to find the
1306 // line number that this character position lands on.
1307 const unsigned *SourceLineCache = Content->SourceLineCache.begin();
1308 const unsigned *SourceLineCacheStart = SourceLineCache;
1309 const unsigned *SourceLineCacheEnd = Content->SourceLineCache.end();
1310
1311 unsigned QueriedFilePos = FilePos+1;
1312
1313 // FIXME: I would like to be convinced that this code is worth being as
1314 // complicated as it is, binary search isn't that slow.
1315 //
1316 // If it is worth being optimized, then in my opinion it could be more
1317 // performant, simpler, and more obviously correct by just "galloping" outward
1318 // from the queried file position. In fact, this could be incorporated into a
1319 // generic algorithm such as lower_bound_with_hint.
1320 //
1321 // If someone gives me a test case where this matters, and I will do it! - DWD
1322
1323 // If the previous query was to the same file, we know both the file pos from
1324 // that query and the line number returned. This allows us to narrow the
1325 // search space from the entire file to something near the match.
1326 if (LastLineNoFileIDQuery == FID) {
1327 if (QueriedFilePos >= LastLineNoFilePos) {
1328 // FIXME: Potential overflow?
1329 SourceLineCache = SourceLineCache+LastLineNoResult-1;
1330
1331 // The query is likely to be nearby the previous one. Here we check to
1332 // see if it is within 5, 10 or 20 lines. It can be far away in cases
1333 // where big comment blocks and vertical whitespace eat up lines but
1334 // contribute no tokens.
1335 if (SourceLineCache+5 < SourceLineCacheEnd) {
1336 if (SourceLineCache[5] > QueriedFilePos)
1337 SourceLineCacheEnd = SourceLineCache+5;
1338 else if (SourceLineCache+10 < SourceLineCacheEnd) {
1339 if (SourceLineCache[10] > QueriedFilePos)
1340 SourceLineCacheEnd = SourceLineCache+10;
1341 else if (SourceLineCache+20 < SourceLineCacheEnd) {
1342 if (SourceLineCache[20] > QueriedFilePos)
1343 SourceLineCacheEnd = SourceLineCache+20;
1344 }
1345 }
1346 }
1347 } else {
1348 if (LastLineNoResult < Content->SourceLineCache.size())
1349 SourceLineCacheEnd = SourceLineCache+LastLineNoResult+1;
1350 }
1351 }
1352
1353 const unsigned *Pos =
1354 std::lower_bound(SourceLineCache, SourceLineCacheEnd, QueriedFilePos);
1355 unsigned LineNo = Pos-SourceLineCacheStart;
1356
1357 LastLineNoFileIDQuery = FID;
1358 LastLineNoContentCache = Content;
1359 LastLineNoFilePos = QueriedFilePos;
1360 LastLineNoResult = LineNo;
1361 return LineNo;
1362}
1363
1365 assert(Loc.isFileID());
1366 if (isInvalid(Loc, Invalid)) return 0;
1367 FileIDAndOffset LocInfo = getDecomposedLoc(Loc);
1368 return getLineNumber(LocInfo.first, LocInfo.second);
1369}
1370
1372 bool *Invalid) const {
1373 PresumedLoc PLoc = getPresumedLoc(Loc);
1374 if (isInvalid(PLoc, Invalid)) return 0;
1375 return PLoc.getLine();
1376}
1377
1378/// getFileCharacteristic - return the file characteristic of the specified
1379/// source location, indicating whether this is a normal file, a system
1380/// header, or an "implicit extern C" system header.
1381///
1382/// This state can be modified with flags on GNU linemarker directives like:
1383/// # 4 "foo.h" 3
1384/// which changes all source locations in the current file after that to be
1385/// considered to be from a system header.
1388 assert(Loc.isValid() && "Can't get file characteristic of invalid loc!");
1390 const SLocEntry *SEntry = getSLocEntryForFile(LocInfo.first);
1391 if (!SEntry)
1392 return C_User;
1393
1394 const SrcMgr::FileInfo &FI = SEntry->getFile();
1395
1396 // If there are no #line directives in this file, just return the whole-file
1397 // state.
1398 if (!FI.hasLineDirectives())
1399 return FI.getFileCharacteristic();
1400
1401 assert(LineTable && "Can't have linetable entries without a LineTable!");
1402 // See if there is a #line directive before the location.
1403 const LineEntry *Entry =
1404 LineTable->FindNearestLineEntry(LocInfo.first, LocInfo.second);
1405
1406 // If this is before the first line marker, use the file characteristic.
1407 if (!Entry)
1408 return FI.getFileCharacteristic();
1409
1410 return Entry->FileKind;
1411}
1412
1413/// Return the filename or buffer identifier of the buffer the location is in.
1414/// Note that this name does not respect \#line directives. Use getPresumedLoc
1415/// for normal clients.
1417 bool *Invalid) const {
1418 if (isInvalid(Loc, Invalid)) return "<invalid loc>";
1419
1420 auto B = getBufferOrNone(getFileID(Loc));
1421 if (Invalid)
1422 *Invalid = !B;
1423 return B ? B->getBufferIdentifier() : "<invalid buffer>";
1424}
1425
1426/// getPresumedLoc - This method returns the "presumed" location of a
1427/// SourceLocation specifies. A "presumed location" can be modified by \#line
1428/// or GNU line marker directives. This provides a view on the data that a
1429/// user should see in diagnostics, for example.
1430///
1431/// Note that a presumed location is always given as the expansion point of an
1432/// expansion location, not at the spelling location.
1434 bool UseLineDirectives) const {
1435 if (Loc.isInvalid()) return PresumedLoc();
1436
1437 // Presumed locations are always for expansion points.
1439
1440 bool Invalid = false;
1441 const SLocEntry &Entry = getSLocEntry(LocInfo.first, &Invalid);
1442 if (Invalid || !Entry.isFile())
1443 return PresumedLoc();
1444
1445 const SrcMgr::FileInfo &FI = Entry.getFile();
1446 const SrcMgr::ContentCache *C = &FI.getContentCache();
1447
1448 // To get the source name, first consult the FileEntry (if one exists)
1449 // before the MemBuffer as this will avoid unnecessarily paging in the
1450 // MemBuffer.
1451 FileID FID = LocInfo.first;
1452 StringRef Filename;
1453 if (C->OrigEntry)
1454 Filename = C->OrigEntry->getName();
1455 else if (auto Buffer = C->getBufferOrNone(Diag, getFileManager()))
1456 Filename = Buffer->getBufferIdentifier();
1457
1458 unsigned LineNo = getLineNumber(LocInfo.first, LocInfo.second, &Invalid);
1459 if (Invalid)
1460 return PresumedLoc();
1461 unsigned ColNo = getColumnNumber(LocInfo.first, LocInfo.second, &Invalid);
1462 if (Invalid)
1463 return PresumedLoc();
1464
1465 SourceLocation IncludeLoc = FI.getIncludeLoc();
1466
1467 // If we have #line directives in this file, update and overwrite the physical
1468 // location info if appropriate.
1469 if (UseLineDirectives && FI.hasLineDirectives()) {
1470 assert(LineTable && "Can't have linetable entries without a LineTable!");
1471 // See if there is a #line directive before this. If so, get it.
1472 if (const LineEntry *Entry =
1473 LineTable->FindNearestLineEntry(LocInfo.first, LocInfo.second)) {
1474 // If the LineEntry indicates a filename, use it.
1475 if (Entry->FilenameID != -1) {
1476 Filename = LineTable->getFilename(Entry->FilenameID);
1477 // The contents of files referenced by #line are not in the
1478 // SourceManager
1479 FID = FileID::get(0);
1480 }
1481
1482 // Use the line number specified by the LineEntry. This line number may
1483 // be multiple lines down from the line entry. Add the difference in
1484 // physical line numbers from the query point and the line marker to the
1485 // total.
1486 unsigned MarkerLineNo = getLineNumber(LocInfo.first, Entry->FileOffset);
1487 LineNo = Entry->LineNo + (LineNo-MarkerLineNo-1);
1488
1489 // Note that column numbers are not molested by line markers.
1490
1491 // Handle virtual #include manipulation.
1492 if (Entry->IncludeOffset) {
1493 IncludeLoc = getLocForStartOfFile(LocInfo.first);
1494 IncludeLoc = IncludeLoc.getLocWithOffset(Entry->IncludeOffset);
1495 }
1496 }
1497 }
1498
1499 return PresumedLoc(Filename.data(), FID, LineNo, ColNo, IncludeLoc);
1500}
1501
1502/// Returns whether the PresumedLoc for a given SourceLocation is
1503/// in the main file.
1504///
1505/// This computes the "presumed" location for a SourceLocation, then checks
1506/// whether it came from a file other than the main file. This is different
1507/// from isWrittenInMainFile() because it takes line marker directives into
1508/// account.
1510 if (Loc.isInvalid()) return false;
1511
1512 // Presumed locations are always for expansion points.
1514
1515 const SLocEntry *Entry = getSLocEntryForFile(LocInfo.first);
1516 if (!Entry)
1517 return false;
1518
1519 const SrcMgr::FileInfo &FI = Entry->getFile();
1520
1521 // Check if there is a line directive for this location.
1522 if (FI.hasLineDirectives())
1523 if (const LineEntry *Entry =
1524 LineTable->FindNearestLineEntry(LocInfo.first, LocInfo.second))
1525 if (Entry->IncludeOffset)
1526 return false;
1527
1528 return FI.getIncludeLoc().isInvalid();
1529}
1530
1531/// The size of the SLocEntry that \p FID represents.
1533 bool Invalid = false;
1534 const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid);
1535 if (Invalid)
1536 return 0;
1537
1538 int ID = FID.ID;
1539 SourceLocation::UIntTy NextOffset;
1540 if ((ID > 0 && unsigned(ID+1) == local_sloc_entry_size()))
1541 NextOffset = getNextLocalOffset();
1542 else if (ID+1 == -1)
1543 NextOffset = MaxLoadedOffset;
1544 else
1545 NextOffset = getSLocEntry(FileID::get(ID+1)).getOffset();
1546
1547 return NextOffset - Entry.getOffset() - 1;
1548}
1549
1550//===----------------------------------------------------------------------===//
1551// Other miscellaneous methods.
1552//===----------------------------------------------------------------------===//
1553
1554/// Get the source location for the given file:line:col triplet.
1555///
1556/// If the source file is included multiple times, the source location will
1557/// be based upon an arbitrary inclusion.
1559 unsigned Line,
1560 unsigned Col) const {
1561 assert(SourceFile && "Null source file!");
1562 assert(Line && Col && "Line and column should start from 1!");
1563
1564 FileID FirstFID = translateFile(SourceFile);
1565 return translateLineCol(FirstFID, Line, Col);
1566}
1567
1568/// Get the FileID for the given file.
1569///
1570/// If the source file is included multiple times, the FileID will be the
1571/// first inclusion.
1573 assert(SourceFile && "Null source file!");
1574
1575 // First, check the main file ID, since it is common to look for a
1576 // location in the main file.
1577 if (MainFileID.isValid()) {
1578 bool Invalid = false;
1579 const SLocEntry &MainSLoc = getSLocEntry(MainFileID, &Invalid);
1580 if (Invalid)
1581 return FileID();
1582
1583 if (MainSLoc.isFile()) {
1584 if (MainSLoc.getFile().getContentCache().OrigEntry == SourceFile)
1585 return MainFileID;
1586 }
1587 }
1588
1589 // The location we're looking for isn't in the main file; look
1590 // through all of the local source locations.
1591 for (unsigned I = 0, N = local_sloc_entry_size(); I != N; ++I) {
1592 const SLocEntry &SLoc = getLocalSLocEntry(I);
1593 if (SLoc.isFile() &&
1594 SLoc.getFile().getContentCache().OrigEntry == SourceFile)
1595 return FileID::get(I);
1596 }
1597
1598 // If that still didn't help, try the modules.
1599 for (unsigned I = 0, N = loaded_sloc_entry_size(); I != N; ++I) {
1600 const SLocEntry &SLoc = getLoadedSLocEntry(I);
1601 if (SLoc.isFile() &&
1602 SLoc.getFile().getContentCache().OrigEntry == SourceFile)
1603 return FileID::get(-int(I) - 2);
1604 }
1605
1606 return FileID();
1607}
1608
1609/// Get the source location in \arg FID for the given line:col.
1610/// Returns null location if \arg FID is not a file SLocEntry.
1612 unsigned Line,
1613 unsigned Col) const {
1614 // Lines are used as a one-based index into a zero-based array. This assert
1615 // checks for possible buffer underruns.
1616 assert(Line && Col && "Line and column should start from 1!");
1617
1618 if (FID.isInvalid())
1619 return SourceLocation();
1620
1621 bool Invalid = false;
1622 const SLocEntry &Entry = getSLocEntry(FID, &Invalid);
1623 if (Invalid)
1624 return SourceLocation();
1625
1626 if (!Entry.isFile())
1627 return SourceLocation();
1628
1629 SourceLocation FileLoc = SourceLocation::getFileLoc(Entry.getOffset());
1630
1631 if (Line == 1 && Col == 1)
1632 return FileLoc;
1633
1634 const ContentCache *Content = &Entry.getFile().getContentCache();
1635
1636 // If this is the first use of line information for this buffer, compute the
1637 // SourceLineCache for it on demand.
1638 std::optional<llvm::MemoryBufferRef> Buffer =
1639 Content->getBufferOrNone(Diag, getFileManager());
1640 if (!Buffer)
1641 return SourceLocation();
1642 if (!Content->SourceLineCache)
1643 Content->SourceLineCache =
1644 LineOffsetMapping::get(*Buffer, ContentCacheAlloc);
1645
1646 if (Line > Content->SourceLineCache.size()) {
1647 unsigned Size = Buffer->getBufferSize();
1648 if (Size > 0)
1649 --Size;
1650 return FileLoc.getLocWithOffset(Size);
1651 }
1652
1653 unsigned FilePos = Content->SourceLineCache[Line - 1];
1654 const char *Buf = Buffer->getBufferStart() + FilePos;
1655 unsigned BufLength = Buffer->getBufferSize() - FilePos;
1656 if (BufLength == 0)
1657 return FileLoc.getLocWithOffset(FilePos);
1658
1659 unsigned i = 0;
1660
1661 // Check that the given column is valid.
1662 while (i < BufLength-1 && i < Col-1 && Buf[i] != '\n' && Buf[i] != '\r')
1663 ++i;
1664 return FileLoc.getLocWithOffset(FilePos + i);
1665}
1666
1667/// Compute a map of macro argument chunks to their expanded source
1668/// location. Chunks that are not part of a macro argument will map to an
1669/// invalid source location. e.g. if a file contains one macro argument at
1670/// offset 100 with length 10, this is how the map will be formed:
1671/// 0 -> SourceLocation()
1672/// 100 -> Expanded macro arg location
1673/// 110 -> SourceLocation()
1674void SourceManager::computeMacroArgsCache(MacroArgsMap &MacroArgsCache,
1675 FileID FID) const {
1676 assert(FID.isValid());
1677
1678 // Initially no macro argument chunk is present.
1679 MacroArgsCache.try_emplace(0);
1680
1681 int ID = FID.ID;
1682 while (true) {
1683 ++ID;
1684 // Stop if there are no more FileIDs to check.
1685 if (ID > 0) {
1686 if (unsigned(ID) >= local_sloc_entry_size())
1687 return;
1688 } else if (ID == -1) {
1689 return;
1690 }
1691
1692 bool Invalid = false;
1693 const SrcMgr::SLocEntry &Entry = getSLocEntryByID(ID, &Invalid);
1694 if (Invalid)
1695 return;
1696 if (Entry.isFile()) {
1697 auto& File = Entry.getFile();
1698 if (File.getFileCharacteristic() == C_User_ModuleMap ||
1699 File.getFileCharacteristic() == C_System_ModuleMap)
1700 continue;
1701
1702 SourceLocation IncludeLoc = File.getIncludeLoc();
1703 bool IncludedInFID =
1704 (IncludeLoc.isValid() && isInFileID(IncludeLoc, FID)) ||
1705 // Predefined header doesn't have a valid include location in main
1706 // file, but any files created by it should still be skipped when
1707 // computing macro args expanded in the main file.
1708 (FID == MainFileID && Entry.getFile().getName() == "<built-in>");
1709 if (IncludedInFID) {
1710 // Skip the files/macros of the #include'd file, we only care about
1711 // macros that lexed macro arguments from our file.
1712 if (Entry.getFile().NumCreatedFIDs)
1713 ID += Entry.getFile().NumCreatedFIDs - 1 /*because of next ++ID*/;
1714 continue;
1715 }
1716 // If file was included but not from FID, there is no more files/macros
1717 // that may be "contained" in this file.
1718 if (IncludeLoc.isValid())
1719 return;
1720 continue;
1721 }
1722
1723 const ExpansionInfo &ExpInfo = Entry.getExpansion();
1724
1725 if (ExpInfo.getExpansionLocStart().isFileID()) {
1726 if (!isInFileID(ExpInfo.getExpansionLocStart(), FID))
1727 return; // No more files/macros that may be "contained" in this file.
1728 }
1729
1730 if (!ExpInfo.isMacroArgExpansion())
1731 continue;
1732
1733 associateFileChunkWithMacroArgExp(MacroArgsCache, FID,
1734 ExpInfo.getSpellingLoc(),
1735 SourceLocation::getMacroLoc(Entry.getOffset()),
1736 getFileIDSize(FileID::get(ID)));
1737 }
1738}
1739
1740void SourceManager::associateFileChunkWithMacroArgExp(
1741 MacroArgsMap &MacroArgsCache,
1742 FileID FID,
1743 SourceLocation SpellLoc,
1744 SourceLocation ExpansionLoc,
1745 unsigned ExpansionLength) const {
1746 if (!SpellLoc.isFileID()) {
1747 SourceLocation::UIntTy SpellBeginOffs = SpellLoc.getOffset();
1748 SourceLocation::UIntTy SpellEndOffs = SpellBeginOffs + ExpansionLength;
1749
1750 // The spelling range for this macro argument expansion can span multiple
1751 // consecutive FileID entries. Go through each entry contained in the
1752 // spelling range and if one is itself a macro argument expansion, recurse
1753 // and associate the file chunk that it represents.
1754
1755 // Current FileID in the spelling range.
1756 auto [SpellFID, SpellRelativeOffs] = getDecomposedLoc(SpellLoc);
1757 while (true) {
1758 const SLocEntry &Entry = getSLocEntry(SpellFID);
1759 SourceLocation::UIntTy SpellFIDBeginOffs = Entry.getOffset();
1760 unsigned SpellFIDSize = getFileIDSize(SpellFID);
1761 SourceLocation::UIntTy SpellFIDEndOffs = SpellFIDBeginOffs + SpellFIDSize;
1762 const ExpansionInfo &Info = Entry.getExpansion();
1763 if (Info.isMacroArgExpansion()) {
1764 unsigned CurrSpellLength;
1765 if (SpellFIDEndOffs < SpellEndOffs)
1766 CurrSpellLength = SpellFIDSize - SpellRelativeOffs;
1767 else
1768 CurrSpellLength = ExpansionLength;
1769 associateFileChunkWithMacroArgExp(MacroArgsCache, FID,
1770 Info.getSpellingLoc().getLocWithOffset(SpellRelativeOffs),
1771 ExpansionLoc, CurrSpellLength);
1772 }
1773
1774 if (SpellFIDEndOffs >= SpellEndOffs)
1775 return; // we covered all FileID entries in the spelling range.
1776
1777 // Move to the next FileID entry in the spelling range.
1778 unsigned advance = SpellFIDSize - SpellRelativeOffs + 1;
1779 ExpansionLoc = ExpansionLoc.getLocWithOffset(advance);
1780 ExpansionLength -= advance;
1781 ++SpellFID.ID;
1782 SpellRelativeOffs = 0;
1783 }
1784 }
1785
1786 assert(SpellLoc.isFileID());
1787
1788 unsigned BeginOffs;
1789 if (!isInFileID(SpellLoc, FID, &BeginOffs))
1790 return;
1791
1792 unsigned EndOffs = BeginOffs + ExpansionLength;
1793
1794 // Add a new chunk for this macro argument. A previous macro argument chunk
1795 // may have been lexed again, so e.g. if the map is
1796 // 0 -> SourceLocation()
1797 // 100 -> Expanded loc #1
1798 // 110 -> SourceLocation()
1799 // and we found a new macro FileID that lexed from offset 105 with length 3,
1800 // the new map will be:
1801 // 0 -> SourceLocation()
1802 // 100 -> Expanded loc #1
1803 // 105 -> Expanded loc #2
1804 // 108 -> Expanded loc #1
1805 // 110 -> SourceLocation()
1806 //
1807 // Since re-lexed macro chunks will always be the same size or less of
1808 // previous chunks, we only need to find where the ending of the new macro
1809 // chunk is mapped to and update the map with new begin/end mappings.
1810
1811 MacroArgsMap::iterator I = MacroArgsCache.upper_bound(EndOffs);
1812 --I;
1813 SourceLocation EndOffsMappedLoc = I->second;
1814 MacroArgsCache[BeginOffs] = ExpansionLoc;
1815 MacroArgsCache[EndOffs] = EndOffsMappedLoc;
1816}
1817
1818void SourceManager::updateSlocUsageStats() const {
1819 SourceLocation::UIntTy UsedBytes =
1820 NextLocalOffset + (MaxLoadedOffset - CurrentLoadedOffset);
1821 MaxUsedSLocBytes.updateMax(UsedBytes);
1822}
1823
1824/// If \arg Loc points inside a function macro argument, the returned
1825/// location will be the macro location in which the argument was expanded.
1826/// If a macro argument is used multiple times, the expanded location will
1827/// be at the first expansion of the argument.
1828/// e.g.
1829/// MY_MACRO(foo);
1830/// ^
1831/// Passing a file location pointing at 'foo', will yield a macro location
1832/// where 'foo' was expanded into.
1833SourceLocation
1835 if (Loc.isInvalid() || !Loc.isFileID())
1836 return Loc;
1837
1838 auto [FID, Offset] = getDecomposedLoc(Loc);
1839 if (FID.isInvalid())
1840 return Loc;
1841
1842 std::unique_ptr<MacroArgsMap> &MacroArgsCache = MacroArgsCacheMap[FID];
1843 if (!MacroArgsCache) {
1844 MacroArgsCache = std::make_unique<MacroArgsMap>();
1845 computeMacroArgsCache(*MacroArgsCache, FID);
1846 }
1847
1848 assert(!MacroArgsCache->empty());
1849 MacroArgsMap::iterator I = MacroArgsCache->upper_bound(Offset);
1850 // In case every element in MacroArgsCache is greater than Offset we can't
1851 // decrement the iterator.
1852 if (I == MacroArgsCache->begin())
1853 return Loc;
1854
1855 --I;
1856
1857 SourceLocation::UIntTy MacroArgBeginOffs = I->first;
1858 SourceLocation MacroArgExpandedLoc = I->second;
1859 if (MacroArgExpandedLoc.isValid())
1860 return MacroArgExpandedLoc.getLocWithOffset(Offset - MacroArgBeginOffs);
1861
1862 return Loc;
1863}
1864
1866 if (FID.isInvalid())
1867 return std::make_pair(FileID(), 0);
1868
1869 // Uses IncludedLocMap to retrieve/cache the decomposed loc.
1870
1871 using DecompTy = FileIDAndOffset;
1872 auto InsertOp = IncludedLocMap.try_emplace(FID);
1873 DecompTy &DecompLoc = InsertOp.first->second;
1874 if (!InsertOp.second)
1875 return DecompLoc; // already in map.
1876
1877 SourceLocation UpperLoc;
1878 bool Invalid = false;
1879 const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid);
1880 if (!Invalid) {
1881 if (Entry.isExpansion())
1882 UpperLoc = Entry.getExpansion().getExpansionLocStart();
1883 else
1884 UpperLoc = Entry.getFile().getIncludeLoc();
1885 }
1886
1887 if (UpperLoc.isValid())
1888 DecompLoc = getDecomposedLoc(UpperLoc);
1889
1890 return DecompLoc;
1891}
1892
1894 assert(isLoadedSourceLocation(Loc) &&
1895 "Must be a source location in a loaded PCH/Module file");
1896
1897 auto [FID, Ignore] = getDecomposedLoc(Loc);
1898 // `LoadedSLocEntryAllocBegin` stores the sorted lowest FID of each loaded
1899 // allocation. Later allocations have lower FileIDs. The call below is to find
1900 // the lowest FID of a loaded allocation from any FID in the same allocation.
1901 // The lowest FID is used to identify a loaded allocation.
1902 const FileID *FirstFID =
1903 llvm::lower_bound(LoadedSLocEntryAllocBegin, FID, std::greater<FileID>{});
1904
1905 assert(FirstFID &&
1906 "The failure to find the first FileID of a "
1907 "loaded AST from a loaded source location was unexpected.");
1908 return *FirstFID;
1909}
1910
1912 const FileIDAndOffset &LOffs, const FileIDAndOffset &ROffs) const {
1913 // If one is local while the other is loaded.
1914 if (isLoadedFileID(LOffs.first) != isLoadedFileID(ROffs.first))
1915 return false;
1916
1917 if (isLoadedFileID(LOffs.first) && isLoadedFileID(ROffs.first)) {
1918 auto FindSLocEntryAlloc = [this](FileID FID) {
1919 // Loaded FileIDs are negative, we store the lowest FileID from each
1920 // allocation, later allocations have lower FileIDs.
1921 return llvm::lower_bound(LoadedSLocEntryAllocBegin, FID,
1922 std::greater<FileID>{});
1923 };
1924
1925 // If both are loaded from different AST files.
1926 if (FindSLocEntryAlloc(LOffs.first) != FindSLocEntryAlloc(ROffs.first))
1927 return false;
1928 }
1929
1930 return true;
1931}
1932
1933/// Given a decomposed source location, move it up the include/expansion stack
1934/// to the parent source location within the same translation unit. If this is
1935/// possible, return the decomposed version of the parent in Loc and return
1936/// false. If Loc is a top-level entry, return true and don't modify it.
1938 const SourceManager &SM) {
1939 FileIDAndOffset UpperLoc = SM.getDecomposedIncludedLoc(Loc.first);
1940 if (UpperLoc.first.isInvalid() ||
1941 !SM.isInTheSameTranslationUnitImpl(UpperLoc, Loc))
1942 return true; // We reached the top.
1943
1944 Loc = UpperLoc;
1945 return false;
1946}
1947
1948/// Return the cache entry for comparing the given file IDs
1949/// for isBeforeInTranslationUnit.
1950InBeforeInTUCacheEntry &SourceManager::getInBeforeInTUCache(FileID LFID,
1951 FileID RFID) const {
1952 // This is a magic number for limiting the cache size. It was experimentally
1953 // derived from a small Objective-C project (where the cache filled
1954 // out to ~250 items). We can make it larger if necessary.
1955 // FIXME: this is almost certainly full these days. Use an LRU cache?
1956 enum { MagicCacheSize = 300 };
1957 IsBeforeInTUCacheKey Key(LFID, RFID);
1958
1959 // If the cache size isn't too large, do a lookup and if necessary default
1960 // construct an entry. We can then return it to the caller for direct
1961 // use. When they update the value, the cache will get automatically
1962 // updated as well.
1963 if (IBTUCache.size() < MagicCacheSize)
1964 return IBTUCache.try_emplace(Key, LFID, RFID).first->second;
1965
1966 // Otherwise, do a lookup that will not construct a new value.
1967 InBeforeInTUCache::iterator I = IBTUCache.find(Key);
1968 if (I != IBTUCache.end())
1969 return I->second;
1970
1971 // Fall back to the overflow value.
1972 IBTUCacheOverflow.setQueryFIDs(LFID, RFID);
1973 return IBTUCacheOverflow;
1974}
1975
1976/// Determines the order of 2 source locations in the translation unit.
1977///
1978/// \returns true if LHS source location comes before RHS, false otherwise.
1980 SourceLocation RHS) const {
1981 assert(LHS.isValid() && RHS.isValid() && "Passed invalid source location!");
1982 if (LHS == RHS)
1983 return false;
1984
1985 FileIDAndOffset LOffs = getDecomposedLoc(LHS);
1986 FileIDAndOffset ROffs = getDecomposedLoc(RHS);
1987
1988 // getDecomposedLoc may have failed to return a valid FileID because, e.g. it
1989 // is a serialized one referring to a file that was removed after we loaded
1990 // the PCH.
1991 if (LOffs.first.isInvalid() || ROffs.first.isInvalid())
1992 return LOffs.first.isInvalid() && !ROffs.first.isInvalid();
1993
1994 std::pair<bool, bool> InSameTU = isInTheSameTranslationUnit(LOffs, ROffs);
1995 if (InSameTU.first)
1996 return InSameTU.second;
1997 // This case is used by libclang: clang_isBeforeInTranslationUnit
1998 return LOffs.first < ROffs.first;
1999}
2000
2001std::pair<bool, bool>
2003 FileIDAndOffset &ROffs) const {
2004 // If the source locations are not in the same TU, return early.
2005 if (!isInTheSameTranslationUnitImpl(LOffs, ROffs))
2006 return std::make_pair(false, false);
2007
2008 // If the source locations are in the same file, just compare offsets.
2009 if (LOffs.first == ROffs.first)
2010 return std::make_pair(true, LOffs.second < ROffs.second);
2011
2012 // If we are comparing a source location with multiple locations in the same
2013 // file, we get a big win by caching the result.
2014 InBeforeInTUCacheEntry &IsBeforeInTUCache =
2015 getInBeforeInTUCache(LOffs.first, ROffs.first);
2016
2017 // If we are comparing a source location with multiple locations in the same
2018 // file, we get a big win by caching the result.
2019 if (IsBeforeInTUCache.isCacheValid())
2020 return std::make_pair(
2021 true, IsBeforeInTUCache.getCachedResult(LOffs.second, ROffs.second));
2022
2023 // Okay, we missed in the cache, we'll compute the answer and populate it.
2024 // We need to find the common ancestor. The only way of doing this is to
2025 // build the complete include chain for one and then walking up the chain
2026 // of the other looking for a match.
2027
2028 // A location within a FileID on the path up from LOffs to the main file.
2029 struct Entry {
2030 FileIDAndOffset DecomposedLoc; // FileID redundant, but clearer.
2031 FileID ChildFID; // Used for breaking ties. Invalid for the initial loc.
2032 };
2033 llvm::SmallDenseMap<FileID, Entry, 16> LChain;
2034
2035 FileID LChild;
2036 do {
2037 LChain.try_emplace(LOffs.first, Entry{LOffs, LChild});
2038 // We catch the case where LOffs is in a file included by ROffs and
2039 // quit early. The other way round unfortunately remains suboptimal.
2040 if (LOffs.first == ROffs.first)
2041 break;
2042 LChild = LOffs.first;
2043 } while (!MoveUpTranslationUnitIncludeHierarchy(LOffs, *this));
2044
2045 FileID RChild;
2046 do {
2047 auto LIt = LChain.find(ROffs.first);
2048 if (LIt != LChain.end()) {
2049 // Compare the locations within the common file and cache them.
2050 LOffs = LIt->second.DecomposedLoc;
2051 LChild = LIt->second.ChildFID;
2052 // The relative order of LChild and RChild is a tiebreaker when
2053 // - locs expand to the same location (occurs in macro arg expansion)
2054 // - one loc is a parent of the other (we consider the parent as "first")
2055 // For the parent entry to be first, its invalid child file ID must
2056 // compare smaller to the valid child file ID of the other entry.
2057 // However loaded FileIDs are <0, so we perform *unsigned* comparison!
2058 // This changes the relative order of local vs loaded FileIDs, but it
2059 // doesn't matter as these are never mixed in macro expansion.
2060 unsigned LChildID = LChild.ID;
2061 unsigned RChildID = RChild.ID;
2062 assert(((LOffs.second != ROffs.second) ||
2063 (LChildID == 0 || RChildID == 0) ||
2065 getComposedLoc(RChild, 0), nullptr)) &&
2066 "Mixed local/loaded FileIDs with same include location?");
2067 IsBeforeInTUCache.setCommonLoc(LOffs.first, LOffs.second, ROffs.second,
2068 LChildID < RChildID);
2069 return std::make_pair(
2070 true, IsBeforeInTUCache.getCachedResult(LOffs.second, ROffs.second));
2071 }
2072 RChild = ROffs.first;
2073 } while (!MoveUpTranslationUnitIncludeHierarchy(ROffs, *this));
2074
2075 // If we found no match, the location is either in a built-ins buffer or
2076 // associated with global inline asm. PR5662 and PR22576 are examples.
2077
2078 StringRef LB = getBufferOrFake(LOffs.first).getBufferIdentifier();
2079 StringRef RB = getBufferOrFake(ROffs.first).getBufferIdentifier();
2080
2081 bool LIsBuiltins = LB == "<built-in>";
2082 bool RIsBuiltins = RB == "<built-in>";
2083 // Sort built-in before non-built-in.
2084 if (LIsBuiltins || RIsBuiltins) {
2085 if (LIsBuiltins != RIsBuiltins)
2086 return std::make_pair(true, LIsBuiltins);
2087 // Both are in built-in buffers, but from different files. We just claim
2088 // that lower IDs come first.
2089 return std::make_pair(true, LOffs.first < ROffs.first);
2090 }
2091
2092 bool LIsAsm = LB == "<inline asm>";
2093 bool RIsAsm = RB == "<inline asm>";
2094 // Sort assembler after built-ins, but before the rest.
2095 if (LIsAsm || RIsAsm) {
2096 if (LIsAsm != RIsAsm)
2097 return std::make_pair(true, RIsAsm);
2098 assert(LOffs.first == ROffs.first);
2099 return std::make_pair(true, false);
2100 }
2101
2102 bool LIsScratch = LB == "<scratch space>";
2103 bool RIsScratch = RB == "<scratch space>";
2104 // Sort scratch after inline asm, but before the rest.
2105 if (LIsScratch || RIsScratch) {
2106 if (LIsScratch != RIsScratch)
2107 return std::make_pair(true, LIsScratch);
2108 return std::make_pair(true, LOffs.second < ROffs.second);
2109 }
2110
2111 llvm_unreachable("Unsortable locations found");
2112}
2113
2115 llvm::errs() << "\n*** Source Manager Stats:\n";
2116 llvm::errs() << FileInfos.size() << " files mapped, " << MemBufferInfos.size()
2117 << " mem buffers mapped.\n";
2118 llvm::errs() << LocalSLocEntryTable.size() << " local SLocEntries allocated ("
2119 << llvm::capacity_in_bytes(LocalSLocEntryTable)
2120 << " bytes of capacity), " << NextLocalOffset
2121 << "B of SLoc address space used.\n";
2122 llvm::errs() << LoadedSLocEntryTable.size()
2123 << " loaded SLocEntries allocated ("
2124 << llvm::capacity_in_bytes(LoadedSLocEntryTable)
2125 << " bytes of capacity), "
2126 << MaxLoadedOffset - CurrentLoadedOffset
2127 << "B of SLoc address space used.\n";
2128
2129 unsigned NumLineNumsComputed = 0;
2130 unsigned NumFileBytesMapped = 0;
2131 for (fileinfo_iterator I = fileinfo_begin(), E = fileinfo_end(); I != E; ++I){
2132 NumLineNumsComputed += bool(I->second->SourceLineCache);
2133 NumFileBytesMapped += I->second->getSizeBytesMapped();
2134 }
2135 unsigned NumMacroArgsComputed = MacroArgsCacheMap.size();
2136
2137 llvm::errs() << NumFileBytesMapped << " bytes of files mapped, "
2138 << NumLineNumsComputed << " files with line #'s computed, "
2139 << NumMacroArgsComputed << " files with macro args computed.\n";
2140 llvm::errs() << "FileID scans: " << NumLinearScans << " linear, "
2141 << NumBinaryProbes << " binary.\n";
2142}
2143
2144LLVM_DUMP_METHOD void SourceManager::dump() const {
2145 llvm::raw_ostream &out = llvm::errs();
2146
2147 auto DumpSLocEntry = [&](int ID, const SrcMgr::SLocEntry &Entry,
2148 std::optional<SourceLocation::UIntTy> NextStart) {
2149 out << "SLocEntry <FileID " << ID << "> " << (Entry.isFile() ? "file" : "expansion")
2150 << " <SourceLocation " << Entry.getOffset() << ":";
2151 if (NextStart)
2152 out << *NextStart << ">\n";
2153 else
2154 out << "???\?>\n";
2155 if (Entry.isFile()) {
2156 auto &FI = Entry.getFile();
2157 if (FI.NumCreatedFIDs)
2158 out << " covers <FileID " << ID << ":" << int(ID + FI.NumCreatedFIDs)
2159 << ">\n";
2160 if (FI.getIncludeLoc().isValid())
2161 out << " included from " << FI.getIncludeLoc().getOffset() << "\n";
2162 auto &CC = FI.getContentCache();
2163 out << " for " << (CC.OrigEntry ? CC.OrigEntry->getName() : "<none>")
2164 << "\n";
2165 if (CC.BufferOverridden)
2166 out << " contents overridden\n";
2167 if (CC.ContentsEntry != CC.OrigEntry) {
2168 out << " contents from "
2169 << (CC.ContentsEntry ? CC.ContentsEntry->getName() : "<none>")
2170 << "\n";
2171 }
2172 } else {
2173 auto &EI = Entry.getExpansion();
2174 out << " spelling from " << EI.getSpellingLoc().getOffset() << "\n";
2175 out << " macro " << (EI.isMacroArgExpansion() ? "arg" : "body")
2176 << " range <" << EI.getExpansionLocStart().getOffset() << ":"
2177 << EI.getExpansionLocEnd().getOffset() << ">\n";
2178 }
2179 };
2180
2181 // Dump local SLocEntries.
2182 for (unsigned ID = 0, NumIDs = LocalSLocEntryTable.size(); ID != NumIDs; ++ID) {
2183 DumpSLocEntry(ID, LocalSLocEntryTable[ID],
2184 ID == NumIDs - 1 ? NextLocalOffset
2185 : LocalSLocEntryTable[ID + 1].getOffset());
2186 }
2187 // Dump loaded SLocEntries.
2188 std::optional<SourceLocation::UIntTy> NextStart;
2189 for (unsigned Index = 0; Index != LoadedSLocEntryTable.size(); ++Index) {
2190 int ID = -(int)Index - 2;
2191 if (SLocEntryLoaded[Index]) {
2192 DumpSLocEntry(ID, LoadedSLocEntryTable[Index], NextStart);
2193 NextStart = LoadedSLocEntryTable[Index].getOffset();
2194 } else {
2195 NextStart = std::nullopt;
2196 }
2197 }
2198}
2199
2201 DiagnosticsEngine &Diag, std::optional<unsigned> MaxNotes) const {
2202 struct Info {
2203 // A location where this file was entered.
2204 SourceLocation Loc;
2205 // Number of times this FileEntry was entered.
2206 unsigned Inclusions = 0;
2207 // Size usage from the file itself.
2208 uint64_t DirectSize = 0;
2209 // Total size usage from the file and its macro expansions.
2210 uint64_t TotalSize = 0;
2211 };
2212 using UsageMap = llvm::MapVector<const FileEntry*, Info>;
2213
2214 UsageMap Usage;
2215 uint64_t CountedSize = 0;
2216
2217 auto AddUsageForFileID = [&](FileID ID) {
2218 // The +1 here is because getFileIDSize doesn't include the extra byte for
2219 // the one-past-the-end location.
2220 unsigned Size = getFileIDSize(ID) + 1;
2221
2222 // Find the file that used this address space, either directly or by
2223 // macro expansion.
2224 SourceLocation FileStart = getFileLoc(getComposedLoc(ID, 0));
2225 FileID FileLocID = getFileID(FileStart);
2226 const FileEntry *Entry = getFileEntryForID(FileLocID);
2227
2228 Info &EntryInfo = Usage[Entry];
2229 if (EntryInfo.Loc.isInvalid())
2230 EntryInfo.Loc = FileStart;
2231 if (ID == FileLocID) {
2232 ++EntryInfo.Inclusions;
2233 EntryInfo.DirectSize += Size;
2234 }
2235 EntryInfo.TotalSize += Size;
2236 CountedSize += Size;
2237 };
2238
2239 // Loaded SLocEntries have indexes counting downwards from -2.
2240 for (size_t Index = 0; Index != LoadedSLocEntryTable.size(); ++Index) {
2241 AddUsageForFileID(FileID::get(-2 - Index));
2242 }
2243 // Local SLocEntries have indexes counting upwards from 0.
2244 for (size_t Index = 0; Index != LocalSLocEntryTable.size(); ++Index) {
2245 AddUsageForFileID(FileID::get(Index));
2246 }
2247
2248 // Sort the usage by size from largest to smallest. Break ties by raw source
2249 // location.
2250 auto SortedUsage = Usage.takeVector();
2251 auto Cmp = [](const UsageMap::value_type &A, const UsageMap::value_type &B) {
2252 return A.second.TotalSize > B.second.TotalSize ||
2253 (A.second.TotalSize == B.second.TotalSize &&
2254 A.second.Loc < B.second.Loc);
2255 };
2256 auto SortedEnd = SortedUsage.end();
2257 if (MaxNotes && SortedUsage.size() > *MaxNotes) {
2258 SortedEnd = SortedUsage.begin() + *MaxNotes;
2259 std::nth_element(SortedUsage.begin(), SortedEnd, SortedUsage.end(), Cmp);
2260 }
2261 std::sort(SortedUsage.begin(), SortedEnd, Cmp);
2262
2263 // Produce note on sloc address space usage total.
2264 uint64_t LocalUsage = NextLocalOffset;
2265 uint64_t LoadedUsage = MaxLoadedOffset - CurrentLoadedOffset;
2266 int UsagePercent = static_cast<int>(100.0 * double(LocalUsage + LoadedUsage) /
2267 MaxLoadedOffset);
2268 Diag.Report(diag::note_total_sloc_usage)
2269 << LocalUsage << LoadedUsage << (LocalUsage + LoadedUsage)
2270 << UsagePercent;
2271
2272 // Produce notes on sloc address space usage for each file with a high usage.
2273 uint64_t ReportedSize = 0;
2274 for (auto &[Entry, FileInfo] :
2275 llvm::make_range(SortedUsage.begin(), SortedEnd)) {
2276 Diag.Report(FileInfo.Loc, diag::note_file_sloc_usage)
2277 << FileInfo.Inclusions << FileInfo.DirectSize
2278 << (FileInfo.TotalSize - FileInfo.DirectSize);
2279 ReportedSize += FileInfo.TotalSize;
2280 }
2281
2282 // Describe any remaining usage not reported in the per-file usage.
2283 if (ReportedSize != CountedSize) {
2284 Diag.Report(diag::note_file_misc_sloc_usage)
2285 << (SortedUsage.end() - SortedEnd) << CountedSize - ReportedSize;
2286 }
2287}
2288
2290
2291/// Return the amount of memory used by memory buffers, breaking down
2292/// by heap-backed versus mmap'ed memory.
2294 size_t malloc_bytes = 0;
2295 size_t mmap_bytes = 0;
2296
2297 for (unsigned i = 0, e = MemBufferInfos.size(); i != e; ++i)
2298 if (size_t sized_mapped = MemBufferInfos[i]->getSizeBytesMapped())
2299 switch (MemBufferInfos[i]->getMemoryBufferKind()) {
2300 case llvm::MemoryBuffer::MemoryBuffer_MMap:
2301 mmap_bytes += sized_mapped;
2302 break;
2303 case llvm::MemoryBuffer::MemoryBuffer_Malloc:
2304 malloc_bytes += sized_mapped;
2305 break;
2306 }
2307
2308 return MemoryBufferSizes(malloc_bytes, mmap_bytes);
2309}
2310
2312 size_t size = llvm::capacity_in_bytes(MemBufferInfos) +
2313 llvm::capacity_in_bytes(LocalSLocEntryTable) +
2314 llvm::capacity_in_bytes(LoadedSLocEntryTable) +
2315 llvm::capacity_in_bytes(SLocEntryLoaded) +
2316 llvm::capacity_in_bytes(FileInfos);
2317
2318 if (OverriddenFilesInfo)
2319 size += llvm::capacity_in_bytes(OverriddenFilesInfo->OverriddenFiles);
2320
2321 return size;
2322}
2323
2325 StringRef Content) {
2326 auto InMemoryFileSystem =
2327 llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
2328 InMemoryFileSystem->addFile(
2329 FileName, 0,
2330 llvm::MemoryBuffer::getMemBuffer(Content, FileName,
2331 /*RequiresNullTerminator=*/false));
2332 // This is passed to `SM` as reference, so the pointer has to be referenced
2333 // in `Environment` so that `FileMgr` can out-live this function scope.
2334 FileMgr = std::make_unique<FileManager>(FileSystemOptions(),
2335 std::move(InMemoryFileSystem));
2336 DiagOpts = std::make_unique<DiagnosticOptions>();
2337 // This is passed to `SM` as reference, so the pointer has to be referenced
2338 // by `Environment` due to the same reason above.
2339 Diagnostics =
2340 std::make_unique<DiagnosticsEngine>(DiagnosticIDs::create(), *DiagOpts);
2341 SourceMgr = std::make_unique<SourceManager>(*Diagnostics, *FileMgr);
2342 FileEntryRef FE = llvm::cantFail(FileMgr->getFileRef(FileName));
2343 FileID ID =
2344 SourceMgr->createFileID(FE, SourceLocation(), clang::SrcMgr::C_User);
2345 assert(ID.isValid());
2346 SourceMgr->setMainFileID(ID);
2347}
Defines the Diagnostic-related interfaces.
Defines the clang::FileManager interface and associated types.
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
#define SM(sm)
static ParseState advance(ParseState S, size_t N)
Definition Parsing.cpp:137
Defines the clang::SourceLocation class and associated facilities.
Defines implementation details of the clang::SourceManager class.
static constexpr T likelyhasbetween(T x, unsigned char m, unsigned char n)
static bool isInvalid(LocType Loc, bool *Invalid)
STATISTIC(MaxUsedSLocBytes, "Maximum number of bytes used by source locations " "(both loaded and local).")
static bool MoveUpTranslationUnitIncludeHierarchy(FileIDAndOffset &Loc, const SourceManager &SM)
Given a decomposed source location, move it up the include/expansion stack to the parent source locat...
Defines the SourceManager interface.
__device__ double
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:232
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:358
off_t getSize() const
Definition FileEntry.h:346
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:302
unsigned getUID() const
Definition FileEntry.h:331
off_t getSize() const
Definition FileEntry.h:328
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,...
Keeps track of options that affect how file operations are performed.
Holds the cache used by isBeforeInTranslationUnit.
void setCommonLoc(FileID commonFID, unsigned lCommonOffset, unsigned rCommonOffset, bool LParentBeforeRParent)
bool getCachedResult(unsigned LOffset, unsigned ROffset) const
If the cache is valid, compute the result given the specified offsets in the LHS/RHS FileID's.
bool isCacheValid() const
Return true if the currently cached values match up with the specified LHS/RHS query.
Used to hold and unique data used to represent #line information.
const LineEntry * FindNearestLineEntry(FileID FID, unsigned Offset)
Find the line entry nearest to FID that is before it.
unsigned getLineTableFilenameID(StringRef Str)
void AddEntry(FileID FID, const std::vector< LineEntry > &Entries)
Add a new line entry that has already been encoded into the internal representation of the line table...
void AddLineNote(FileID FID, unsigned Offset, unsigned LineNo, int FilenameID, unsigned EntryExit, SrcMgr::CharacteristicKind FileKind)
Add a line note to the line table that indicates that there is a #line or GNU line marker at the spec...
Represents an unpacked "presumed" location which can be presented to the user.
unsigned getColumn() const
Return the presumed column number of this location.
unsigned getLine() const
Return the presumed line number of this location.
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
SourceLocation getLocWithOffset(IntTy Offset) const
Return a source location with the specified offset from this SourceLocation.
SourceManagerForFile(StringRef FileName, StringRef Content)
Creates SourceManager and necessary dependencies (e.g.
This class handles loading and caching of source files into memory.
std::optional< StringRef > getNonBuiltinFilenameForID(FileID FID) const
Returns the filename for the provided FileID, unless it's a built-in buffer that's not represented by...
FileIDAndOffset getDecomposedExpansionLoc(SourceLocation Loc) const
Decompose the specified location into a raw FileID + Offset pair.
bool isMacroBodyExpansion(SourceLocation Loc) const
Tests whether the given source location represents the expansion of a macro body.
FileIDAndOffset getDecomposedLoc(SourceLocation Loc) const
Decompose the specified location into a raw FileID + Offset pair.
unsigned getPresumedLineNumber(SourceLocation Loc, bool *Invalid=nullptr) const
FileID getFileID(SourceLocation SpellingLoc) const
Return the FileID for a SourceLocation.
bool isAtEndOfImmediateMacroExpansion(SourceLocation Loc, SourceLocation *MacroEnd=nullptr) const
Returns true if the given MacroID location points at the character end of the immediate macro expansi...
SourceLocation::UIntTy getNextLocalOffset() const
unsigned getColumnNumber(FileID FID, unsigned FilePos, bool *Invalid=nullptr) const
Return the column # for the specified file position.
void noteSLocAddressSpaceUsage(DiagnosticsEngine &Diag, std::optional< unsigned > MaxNotes=32) const
bool isInMainFile(SourceLocation Loc) const
Returns whether the PresumedLoc for a given SourceLocation is in the main file.
void AddLineNote(SourceLocation Loc, unsigned LineNo, int FilenameID, bool IsFileEntry, bool IsFileExit, SrcMgr::CharacteristicKind FileKind)
Add a line note to the line table for the FileID and offset specified by Loc.
SourceManager(DiagnosticsEngine &Diag, FileManager &FileMgr, bool UserFilesAreVolatile=false)
SourceLocation createTokenSplitLoc(SourceLocation SpellingLoc, SourceLocation TokenStart, SourceLocation TokenEnd)
Return a new SourceLocation that encodes that the token starting at TokenStart ends prematurely at To...
PresumedLoc getPresumedLoc(SourceLocation Loc, bool UseLineDirectives=true) const
Returns the "presumed" location of a SourceLocation specifies.
bool isInTheSameTranslationUnitImpl(const FileIDAndOffset &LOffs, const FileIDAndOffset &ROffs) const
Determines whether the two decomposed source location is in the same TU.
MemoryBufferSizes getMemoryBufferSizes() const
Return the amount of memory used by memory buffers, breaking down by heap-backed versus mmap'ed memor...
void setFileIsTransient(FileEntryRef SourceFile)
Specify that a file is transient.
bool isFileOverridden(const FileEntry *File) const
Returns true if the file contents have been overridden.
OptionalFileEntryRef getFileEntryRefForID(FileID FID) const
Returns the FileEntryRef for the provided FileID.
SourceLocation getFileLoc(SourceLocation Loc) const
Given Loc, if it is a macro location return the expansion location or the spelling location,...
SourceLocation translateLineCol(FileID FID, unsigned Line, unsigned Col) const
Get the source location in FID for the given line:col.
StringRef getBufferName(SourceLocation Loc, bool *Invalid=nullptr) const
Return the filename or buffer identifier of the buffer the location is in.
SourceLocation getTopMacroCallerLoc(SourceLocation Loc) const
std::optional< StringRef > getBufferDataOrNone(FileID FID) const
Return a StringRef to the source buffer data for the specified FileID, returning std::nullopt if inva...
FileID translateFile(const FileEntry *SourceFile) const
Get the FileID for the given file.
StringRef getBufferData(FileID FID, bool *Invalid=nullptr) const
Return a StringRef to the source buffer data for the specified FileID.
FileID createFileID(FileEntryRef SourceFile, SourceLocation IncludePos, SrcMgr::CharacteristicKind FileCharacter, int LoadedID=0, SourceLocation::UIntTy LoadedOffset=0)
Create a new FileID that represents the specified file being #included from the specified IncludePosi...
void PrintStats() const
Print statistics to stderr.
FileID getUniqueLoadedASTFileID(SourceLocation Loc) const
bool isMainFile(const FileEntry &SourceFile)
Returns true when the given FileEntry corresponds to the main file.
size_t getDataStructureSizes() const
Return the amount of memory used for various side tables and data structures in the SourceManager.
bool isMacroArgExpansion(SourceLocation Loc, SourceLocation *StartLoc=nullptr) const
Tests whether the given source location represents a macro argument's expansion into the function-lik...
const SrcMgr::SLocEntry & getLocalSLocEntry(unsigned Index) const
Get a local SLocEntry. This is exposed for indexing.
SourceLocation getComposedLoc(FileID FID, unsigned Offset) const
Form a SourceLocation from a FileID and Offset pair.
OptionalFileEntryRef bypassFileContentsOverride(FileEntryRef File)
Bypass the overridden contents of a file.
const SrcMgr::SLocEntry & getLoadedSLocEntry(unsigned Index, bool *Invalid=nullptr) const
Get a loaded SLocEntry. This is exposed for indexing.
llvm::DenseMap< FileEntryRef, SrcMgr::ContentCache * >::const_iterator fileinfo_iterator
FileManager & getFileManager() const
fileinfo_iterator fileinfo_end() const
unsigned local_sloc_entry_size() const
Get the number of local SLocEntries we have.
std::optional< StringRef > getBufferDataIfLoaded(FileID FID) const
Return a StringRef to the source buffer data for the specified FileID, returning std::nullopt if it's...
FileIDAndOffset getDecomposedSpellingLoc(SourceLocation Loc) const
Decompose the specified location into a raw FileID + Offset pair.
const char * getCharacterData(SourceLocation SL, bool *Invalid=nullptr) const
Return a pointer to the start of the specified location in the appropriate spelling MemoryBuffer.
std::pair< int, SourceLocation::UIntTy > AllocateLoadedSLocEntries(unsigned NumSLocEntries, SourceLocation::UIntTy TotalSize)
Allocate a number of loaded SLocEntries, which will be actually loaded on demand from the external so...
void overrideFileContents(FileEntryRef SourceFile, const llvm::MemoryBufferRef &Buffer)
Override the contents of the given source file by providing an already-allocated buffer.
llvm::MemoryBufferRef getBufferOrFake(FileID FID, SourceLocation Loc=SourceLocation()) const
Return the buffer for the specified FileID.
unsigned getFileIDSize(FileID FID) const
The size of the SLocEntry that FID represents.
unsigned getLineNumber(FileID FID, unsigned FilePos, bool *Invalid=nullptr) const
Given a SourceLocation, return the spelling line number for the position indicated.
CharSourceRange getImmediateExpansionRange(SourceLocation Loc) const
Return the start/end of the expansion information for an expansion location.
CharSourceRange getExpansionRange(SourceLocation Loc) const
Given a SourceLocation object, return the range of tokens covered by the expansion in the ultimate fi...
bool isInFileID(SourceLocation Loc, FileID FID, unsigned *RelativeOffset=nullptr) const
Given a specific FileID, returns true if Loc is inside that FileID chunk and sets relative offset (of...
unsigned getLineTableFilenameID(StringRef Str)
Return the uniqued ID for the specified filename.
void initializeForReplay(const SourceManager &Old)
Initialize this source manager suitably to replay the compilation described by Old.
FileIDAndOffset getDecomposedIncludedLoc(FileID FID) const
Returns the "included/expanded in" decomposed location of the given FileID.
bool isLoadedSourceLocation(SourceLocation Loc) const
Returns true if Loc came from a PCH/Module.
unsigned loaded_sloc_entry_size() const
Get the number of loaded SLocEntries we have.
FileID getOrCreateFileID(FileEntryRef SourceFile, SrcMgr::CharacteristicKind FileCharacter)
Get the FileID for SourceFile if it exists.
SourceLocation translateFileLineCol(const FileEntry *SourceFile, unsigned Line, unsigned Col) const
Get the source location for the given file:line:col triplet.
bool isLoadedFileID(FileID FID) const
Returns true if FID came from a PCH/Module.
const FileEntry * getFileEntryForID(FileID FID) const
Returns the FileEntry record for the provided FileID.
bool isInSameSLocAddrSpace(SourceLocation LHS, SourceLocation RHS, SourceLocation::IntTy *RelativeOffset) const
Return true if both LHS and RHS are in the local source location address space or the loaded one.
SourceLocation getLocForStartOfFile(FileID FID) const
Return the source location corresponding to the first byte of the specified file.
bool isAtStartOfImmediateMacroExpansion(SourceLocation Loc, SourceLocation *MacroBegin=nullptr) const
Returns true if the given MacroID location points at the beginning of the immediate macro expansion.
SrcMgr::CharacteristicKind getFileCharacteristic(SourceLocation Loc) const
Return the file characteristic of the specified source location, indicating whether this is a normal ...
SourceLocation createExpansionLoc(SourceLocation SpellingLoc, SourceLocation ExpansionLocStart, SourceLocation ExpansionLocEnd, unsigned Length, bool ExpansionIsTokenRange=true, int LoadedID=0, SourceLocation::UIntTy LoadedOffset=0)
Creates an expansion SLocEntry for a macro use.
unsigned getPresumedColumnNumber(SourceLocation Loc, bool *Invalid=nullptr) const
std::pair< bool, bool > isInTheSameTranslationUnit(FileIDAndOffset &LOffs, FileIDAndOffset &ROffs) const
Determines whether the two decomposed source location is in the same translation unit.
StringRef getFilename(SourceLocation SpellingLoc) const
Return the filename of the file containing a SourceLocation.
SourceLocation getMacroArgExpandedLocation(SourceLocation Loc) const
If Loc points inside a function macro argument, the returned location will be the macro location in w...
bool isBeforeInTranslationUnit(SourceLocation LHS, SourceLocation RHS) const
Determines the order of 2 source locations in the translation unit.
std::optional< llvm::MemoryBufferRef > getBufferOrNone(FileID FID, SourceLocation Loc=SourceLocation()) const
Return the buffer for the specified FileID.
fileinfo_iterator fileinfo_begin() const
LineTableInfo & getLineTable()
Retrieve the stored line table.
SourceLocation getImmediateSpellingLoc(SourceLocation Loc) const
Given a SourceLocation object, return the spelling location referenced by the ID.
std::optional< llvm::MemoryBufferRef > getMemoryBufferForFileOrNone(FileEntryRef File)
Retrieve the memory buffer associated with the given file.
const SrcMgr::SLocEntry & getSLocEntry(FileID FID, bool *Invalid=nullptr) const
SourceLocation createMacroArgExpansionLoc(SourceLocation SpellingLoc, SourceLocation ExpansionLoc, unsigned Length)
Creates an expansion SLocEntry for the substitution of an argument into a function-like macro's body.
A trivial tuple used to represent a source range.
One instance of this struct is kept for every file loaded or used.
void setBuffer(std::unique_ptr< llvm::MemoryBuffer > B)
Set the buffer.
std::optional< StringRef > getBufferDataIfLoaded() const
Return a StringRef to the source buffer data, only if it has already been loaded.
OptionalFileEntryRef ContentsEntry
References the file which the contents were actually loaded from.
unsigned getSizeBytesMapped() const
Returns the number of bytes actually mapped for this ContentCache.
unsigned IsTransient
True if this file may be transient, that is, if it might not exist at some later point in time when t...
unsigned getSize() const
Returns the size of the content encapsulated by this ContentCache.
llvm::MemoryBuffer::BufferKind getMemoryBufferKind() const
Returns the kind of memory used to back the memory buffer for this content cache.
unsigned IsFileVolatile
True if this content cache was initially created for a source file considered to be volatile (likely ...
LineOffsetMapping SourceLineCache
A bump pointer allocated array of offsets for each source line.
std::optional< llvm::MemoryBufferRef > getBufferOrNone(DiagnosticsEngine &Diag, FileManager &FM, SourceLocation Loc=SourceLocation()) const
Returns the memory buffer for the associated content.
static const char * getInvalidBOM(StringRef BufStr)
unsigned BufferOverridden
Indicates whether the buffer itself was provided to override the actual file contents.
OptionalFileEntryRef OrigEntry
Reference to the file entry representing this ContentCache.
Each ExpansionInfo encodes the expansion location - where the token was ultimately expanded,...
SourceLocation getExpansionLocStart() const
static ExpansionInfo create(SourceLocation SpellingLoc, SourceLocation Start, SourceLocation End, bool ExpansionIsTokenRange=true)
Return a ExpansionInfo for an expansion.
SourceLocation getSpellingLoc() const
CharSourceRange getExpansionLocRange() const
static ExpansionInfo createForMacroArg(SourceLocation SpellingLoc, SourceLocation ExpansionLoc)
Return a special ExpansionInfo for the expansion of a macro argument into a function-like macro's bod...
static ExpansionInfo createForTokenSplit(SourceLocation SpellingLoc, SourceLocation Start, SourceLocation End)
Return a special ExpansionInfo representing a token that ends prematurely.
SourceLocation getExpansionLocEnd() const
Information about a FileID, basically just the logical file that it represents and include stack info...
const ContentCache & getContentCache() const
CharacteristicKind getFileCharacteristic() const
Return whether this is a system header or not.
static FileInfo get(SourceLocation IL, ContentCache &Con, CharacteristicKind FileCharacter, StringRef Filename)
Return a FileInfo object.
bool hasLineDirectives() const
Return true if this FileID has #line directives in it.
void setHasLineDirectives()
Set the flag that indicates that this FileID has line table entries associated with it.
SourceLocation getIncludeLoc() const
const unsigned * begin() const
const unsigned * end() const
static LineOffsetMapping get(llvm::MemoryBufferRef Buffer, llvm::BumpPtrAllocator &Alloc)
This is a discriminated union of FileInfo and ExpansionInfo.
SourceLocation::UIntTy getOffset() const
static SLocEntry get(SourceLocation::UIntTy Offset, const FileInfo &FI)
const FileInfo & getFile() const
const ExpansionInfo & getExpansion() const
#define bool
Definition gpuintrin.h:32
Public enums and private classes that are part of the SourceManager implementation.
CharacteristicKind
Indicates whether a file or directory holds normal user code, system code, or system code which is im...
bool isSystem(CharacteristicKind CK)
Determine whether a file / directory characteristic is for system code.
StringRef getName(const HeaderType T)
Definition HeaderFile.h:38
The JSON file list parser is used to communicate input to InstallAPI.
CustomizableOptional< FileEntryRef > OptionalFileEntryRef
Definition FileEntry.h:208
std::pair< FileID, unsigned > FileIDAndOffset
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
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)