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