clang 18.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 (llvm::DenseMap<const FileEntry*, SrcMgr::ContentCache*>::iterator
328 I = FileInfos.begin(), E = FileInfos.end(); I != E; ++I) {
329 if (I->second) {
330 I->second->~ContentCache();
331 ContentCacheAlloc.Deallocate(I->second);
332 }
333 }
334}
335
337 MainFileID = FileID();
338 LocalSLocEntryTable.clear();
339 LoadedSLocEntryTable.clear();
340 SLocEntryLoaded.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 assert(!SLocEntryLoaded[Index]);
435 if (ExternalSLocEntries->ReadSLocEntry(-(static_cast<int>(Index) + 2))) {
436 if (Invalid)
437 *Invalid = true;
438 // If the file of the SLocEntry changed we could still have loaded it.
439 if (!SLocEntryLoaded[Index]) {
440 // Try to recover; create a SLocEntry so the rest of clang can handle it.
441 if (!FakeSLocEntryForRecovery)
442 FakeSLocEntryForRecovery = std::make_unique<SLocEntry>(SLocEntry::get(
443 0, FileInfo::get(SourceLocation(), getFakeContentCacheForRecovery(),
444 SrcMgr::C_User, "")));
445 return *FakeSLocEntryForRecovery;
446 }
447 }
448
449 return LoadedSLocEntryTable[Index];
450}
451
452std::pair<int, SourceLocation::UIntTy>
454 SourceLocation::UIntTy TotalSize) {
455 assert(ExternalSLocEntries && "Don't have an external sloc source");
456 // Make sure we're not about to run out of source locations.
457 if (CurrentLoadedOffset < TotalSize ||
458 CurrentLoadedOffset - TotalSize < NextLocalOffset) {
459 return std::make_pair(0, 0);
460 }
461 LoadedSLocEntryTable.resize(LoadedSLocEntryTable.size() + NumSLocEntries);
462 SLocEntryLoaded.resize(LoadedSLocEntryTable.size());
463 CurrentLoadedOffset -= TotalSize;
464 int ID = LoadedSLocEntryTable.size();
465 return std::make_pair(-ID - 1, CurrentLoadedOffset);
466}
467
468/// As part of recovering from missing or changed content, produce a
469/// fake, non-empty buffer.
470llvm::MemoryBufferRef SourceManager::getFakeBufferForRecovery() const {
471 if (!FakeBufferForRecovery)
472 FakeBufferForRecovery =
473 llvm::MemoryBuffer::getMemBuffer("<<<INVALID BUFFER>>");
474
475 return *FakeBufferForRecovery;
476}
477
478/// As part of recovering from missing or changed content, produce a
479/// fake content cache.
480SrcMgr::ContentCache &SourceManager::getFakeContentCacheForRecovery() const {
481 if (!FakeContentCacheForRecovery) {
482 FakeContentCacheForRecovery = std::make_unique<SrcMgr::ContentCache>();
483 FakeContentCacheForRecovery->setUnownedBuffer(getFakeBufferForRecovery());
484 }
485 return *FakeContentCacheForRecovery;
486}
487
488/// Returns the previous in-order FileID or an invalid FileID if there
489/// is no previous one.
490FileID SourceManager::getPreviousFileID(FileID FID) const {
491 if (FID.isInvalid())
492 return FileID();
493
494 int ID = FID.ID;
495 if (ID == -1)
496 return FileID();
497
498 if (ID > 0) {
499 if (ID-1 == 0)
500 return FileID();
501 } else if (unsigned(-(ID-1) - 2) >= LoadedSLocEntryTable.size()) {
502 return FileID();
503 }
504
505 return FileID::get(ID-1);
506}
507
508/// Returns the next in-order FileID or an invalid FileID if there is
509/// no next one.
510FileID SourceManager::getNextFileID(FileID FID) const {
511 if (FID.isInvalid())
512 return FileID();
513
514 int ID = FID.ID;
515 if (ID > 0) {
516 if (unsigned(ID+1) >= local_sloc_entry_size())
517 return FileID();
518 } else if (ID+1 >= -1) {
519 return FileID();
520 }
521
522 return FileID::get(ID+1);
523}
524
525//===----------------------------------------------------------------------===//
526// Methods to create new FileID's and macro expansions.
527//===----------------------------------------------------------------------===//
528
529/// Create a new FileID that represents the specified file
530/// being \#included from the specified IncludePosition.
531///
532/// This translates NULL into standard input.
534 SourceLocation IncludePos,
535 SrcMgr::CharacteristicKind FileCharacter,
536 int LoadedID,
537 SourceLocation::UIntTy LoadedOffset) {
538 return createFileID(SourceFile->getLastRef(), IncludePos, FileCharacter,
539 LoadedID, LoadedOffset);
540}
541
543 SourceLocation IncludePos,
544 SrcMgr::CharacteristicKind FileCharacter,
545 int LoadedID,
546 SourceLocation::UIntTy LoadedOffset) {
547 SrcMgr::ContentCache &IR = getOrCreateContentCache(SourceFile,
548 isSystem(FileCharacter));
549
550 // If this is a named pipe, immediately load the buffer to ensure subsequent
551 // calls to ContentCache::getSize() are accurate.
552 if (IR.ContentsEntry->isNamedPipe())
553 (void)IR.getBufferOrNone(Diag, getFileManager(), SourceLocation());
554
555 return createFileIDImpl(IR, SourceFile.getName(), IncludePos, FileCharacter,
556 LoadedID, LoadedOffset);
557}
558
559/// Create a new FileID that represents the specified memory buffer.
560///
561/// This does no caching of the buffer and takes ownership of the
562/// MemoryBuffer, so only pass a MemoryBuffer to this once.
563FileID SourceManager::createFileID(std::unique_ptr<llvm::MemoryBuffer> Buffer,
564 SrcMgr::CharacteristicKind FileCharacter,
565 int LoadedID,
566 SourceLocation::UIntTy LoadedOffset,
567 SourceLocation IncludeLoc) {
568 StringRef Name = Buffer->getBufferIdentifier();
569 return createFileIDImpl(createMemBufferContentCache(std::move(Buffer)), Name,
570 IncludeLoc, FileCharacter, LoadedID, LoadedOffset);
571}
572
573/// Create a new FileID that represents the specified memory buffer.
574///
575/// This does not take ownership of the MemoryBuffer. The memory buffer must
576/// outlive the SourceManager.
577FileID SourceManager::createFileID(const llvm::MemoryBufferRef &Buffer,
578 SrcMgr::CharacteristicKind FileCharacter,
579 int LoadedID,
580 SourceLocation::UIntTy LoadedOffset,
581 SourceLocation IncludeLoc) {
582 return createFileID(llvm::MemoryBuffer::getMemBuffer(Buffer), FileCharacter,
583 LoadedID, LoadedOffset, IncludeLoc);
584}
585
586/// Get the FileID for \p SourceFile if it exists. Otherwise, create a
587/// new FileID for the \p SourceFile.
588FileID
590 SrcMgr::CharacteristicKind FileCharacter) {
591 FileID ID = translateFile(SourceFile);
592 return ID.isValid() ? ID : createFileID(SourceFile, SourceLocation(),
593 FileCharacter);
594}
595
596/// createFileID - Create a new FileID for the specified ContentCache and
597/// include position. This works regardless of whether the ContentCache
598/// corresponds to a file or some other input source.
599FileID SourceManager::createFileIDImpl(ContentCache &File, StringRef Filename,
600 SourceLocation IncludePos,
601 SrcMgr::CharacteristicKind FileCharacter,
602 int LoadedID,
603 SourceLocation::UIntTy LoadedOffset) {
604 if (LoadedID < 0) {
605 assert(LoadedID != -1 && "Loading sentinel FileID");
606 unsigned Index = unsigned(-LoadedID) - 2;
607 assert(Index < LoadedSLocEntryTable.size() && "FileID out of range");
608 assert(!SLocEntryLoaded[Index] && "FileID already loaded");
609 LoadedSLocEntryTable[Index] = SLocEntry::get(
610 LoadedOffset, FileInfo::get(IncludePos, File, FileCharacter, Filename));
611 SLocEntryLoaded[Index] = true;
612 return FileID::get(LoadedID);
613 }
614 unsigned FileSize = File.getSize();
615 if (!(NextLocalOffset + FileSize + 1 > NextLocalOffset &&
616 NextLocalOffset + FileSize + 1 <= CurrentLoadedOffset)) {
617 Diag.Report(IncludePos, diag::err_include_too_large);
619 return FileID();
620 }
621 LocalSLocEntryTable.push_back(
622 SLocEntry::get(NextLocalOffset,
623 FileInfo::get(IncludePos, File, FileCharacter, Filename)));
624 // We do a +1 here because we want a SourceLocation that means "the end of the
625 // file", e.g. for the "no newline at the end of the file" diagnostic.
626 NextLocalOffset += FileSize + 1;
627
628 // Set LastFileIDLookup to the newly created file. The next getFileID call is
629 // almost guaranteed to be from that file.
630 FileID FID = FileID::get(LocalSLocEntryTable.size()-1);
631 return LastFileIDLookup = FID;
632}
633
635 SourceLocation SpellingLoc, SourceLocation ExpansionLoc, unsigned Length) {
637 ExpansionLoc);
638 return createExpansionLocImpl(Info, Length);
639}
640
642 SourceLocation SpellingLoc, SourceLocation ExpansionLocStart,
643 SourceLocation ExpansionLocEnd, unsigned Length,
644 bool ExpansionIsTokenRange, int LoadedID,
645 SourceLocation::UIntTy LoadedOffset) {
647 SpellingLoc, ExpansionLocStart, ExpansionLocEnd, ExpansionIsTokenRange);
648 return createExpansionLocImpl(Info, Length, LoadedID, LoadedOffset);
649}
650
652 SourceLocation TokenStart,
653 SourceLocation TokenEnd) {
654 assert(getFileID(TokenStart) == getFileID(TokenEnd) &&
655 "token spans multiple files");
656 return createExpansionLocImpl(
657 ExpansionInfo::createForTokenSplit(Spelling, TokenStart, TokenEnd),
658 TokenEnd.getOffset() - TokenStart.getOffset());
659}
660
662SourceManager::createExpansionLocImpl(const ExpansionInfo &Info,
663 unsigned Length, int LoadedID,
664 SourceLocation::UIntTy LoadedOffset) {
665 if (LoadedID < 0) {
666 assert(LoadedID != -1 && "Loading sentinel FileID");
667 unsigned Index = unsigned(-LoadedID) - 2;
668 assert(Index < LoadedSLocEntryTable.size() && "FileID out of range");
669 assert(!SLocEntryLoaded[Index] && "FileID already loaded");
670 LoadedSLocEntryTable[Index] = SLocEntry::get(LoadedOffset, Info);
671 SLocEntryLoaded[Index] = true;
672 return SourceLocation::getMacroLoc(LoadedOffset);
673 }
674 LocalSLocEntryTable.push_back(SLocEntry::get(NextLocalOffset, Info));
675 // FIXME: Produce a proper diagnostic for this case.
676 assert(NextLocalOffset + Length + 1 > NextLocalOffset &&
677 NextLocalOffset + Length + 1 <= CurrentLoadedOffset &&
678 "Ran out of source locations!");
679 // See createFileID for that +1.
680 NextLocalOffset += Length + 1;
681 return SourceLocation::getMacroLoc(NextLocalOffset - (Length + 1));
682}
683
684std::optional<llvm::MemoryBufferRef>
686 SrcMgr::ContentCache &IR = getOrCreateContentCache(File->getLastRef());
687 return IR.getBufferOrNone(Diag, getFileManager(), SourceLocation());
688}
689
691 const FileEntry *SourceFile, std::unique_ptr<llvm::MemoryBuffer> Buffer) {
692 SrcMgr::ContentCache &IR = getOrCreateContentCache(SourceFile->getLastRef());
693
694 IR.setBuffer(std::move(Buffer));
695 IR.BufferOverridden = true;
696
697 getOverriddenFilesInfo().OverriddenFilesWithBuffer.insert(SourceFile);
698}
699
701 FileEntryRef NewFile) {
702 assert(SourceFile->getSize() == NewFile.getSize() &&
703 "Different sizes, use the FileManager to create a virtual file with "
704 "the correct size");
705 assert(FileInfos.count(SourceFile) == 0 &&
706 "This function should be called at the initialization stage, before "
707 "any parsing occurs.");
708 // FileEntryRef is not default-constructible.
709 auto Pair = getOverriddenFilesInfo().OverriddenFiles.insert(
710 std::make_pair(SourceFile, NewFile));
711 if (!Pair.second)
712 Pair.first->second = NewFile;
713}
714
717 assert(isFileOverridden(&File.getFileEntry()));
718 OptionalFileEntryRef BypassFile = FileMgr.getBypassFile(File);
719
720 // If the file can't be found in the FS, give up.
721 if (!BypassFile)
722 return std::nullopt;
723
724 (void)getOrCreateContentCache(*BypassFile);
725 return BypassFile;
726}
727
729 getOrCreateContentCache(File->getLastRef()).IsTransient = true;
730}
731
732std::optional<StringRef>
734 if (const SrcMgr::SLocEntry *Entry = getSLocEntryForFile(FID))
735 if (Entry->getFile().getContentCache().OrigEntry)
736 return Entry->getFile().getName();
737 return std::nullopt;
738}
739
740StringRef SourceManager::getBufferData(FileID FID, bool *Invalid) const {
741 auto B = getBufferDataOrNone(FID);
742 if (Invalid)
743 *Invalid = !B;
744 return B ? *B : "<<<<<INVALID SOURCE LOCATION>>>>>";
745}
746
747std::optional<StringRef>
749 if (const SrcMgr::SLocEntry *Entry = getSLocEntryForFile(FID))
750 return Entry->getFile().getContentCache().getBufferDataIfLoaded();
751 return std::nullopt;
752}
753
754std::optional<StringRef> SourceManager::getBufferDataOrNone(FileID FID) const {
755 if (const SrcMgr::SLocEntry *Entry = getSLocEntryForFile(FID))
756 if (auto B = Entry->getFile().getContentCache().getBufferOrNone(
757 Diag, getFileManager(), SourceLocation()))
758 return B->getBuffer();
759 return std::nullopt;
760}
761
762//===----------------------------------------------------------------------===//
763// SourceLocation manipulation methods.
764//===----------------------------------------------------------------------===//
765
766/// Return the FileID for a SourceLocation.
767///
768/// This is the cache-miss path of getFileID. Not as hot as that function, but
769/// still very important. It is responsible for finding the entry in the
770/// SLocEntry tables that contains the specified location.
771FileID SourceManager::getFileIDSlow(SourceLocation::UIntTy SLocOffset) const {
772 if (!SLocOffset)
773 return FileID::get(0);
774
775 // Now it is time to search for the correct file. See where the SLocOffset
776 // sits in the global view and consult local or loaded buffers for it.
777 if (SLocOffset < NextLocalOffset)
778 return getFileIDLocal(SLocOffset);
779 return getFileIDLoaded(SLocOffset);
780}
781
782/// Return the FileID for a SourceLocation with a low offset.
783///
784/// This function knows that the SourceLocation is in a local buffer, not a
785/// loaded one.
786FileID SourceManager::getFileIDLocal(SourceLocation::UIntTy SLocOffset) const {
787 assert(SLocOffset < NextLocalOffset && "Bad function choice");
788
789 // After the first and second level caches, I see two common sorts of
790 // behavior: 1) a lot of searched FileID's are "near" the cached file
791 // location or are "near" the cached expansion location. 2) others are just
792 // completely random and may be a very long way away.
793 //
794 // To handle this, we do a linear search for up to 8 steps to catch #1 quickly
795 // then we fall back to a less cache efficient, but more scalable, binary
796 // search to find the location.
797
798 // See if this is near the file point - worst case we start scanning from the
799 // most newly created FileID.
800
801 // LessIndex - This is the lower bound of the range that we're searching.
802 // We know that the offset corresponding to the FileID is less than
803 // SLocOffset.
804 unsigned LessIndex = 0;
805 // upper bound of the search range.
806 unsigned GreaterIndex = LocalSLocEntryTable.size();
807 if (LastFileIDLookup.ID >= 0) {
808 // Use the LastFileIDLookup to prune the search space.
809 if (LocalSLocEntryTable[LastFileIDLookup.ID].getOffset() < SLocOffset)
810 LessIndex = LastFileIDLookup.ID;
811 else
812 GreaterIndex = LastFileIDLookup.ID;
813 }
814
815 // Find the FileID that contains this.
816 unsigned NumProbes = 0;
817 while (true) {
818 --GreaterIndex;
819 assert(GreaterIndex < LocalSLocEntryTable.size());
820 if (LocalSLocEntryTable[GreaterIndex].getOffset() <= SLocOffset) {
821 FileID Res = FileID::get(int(GreaterIndex));
822 // Remember it. We have good locality across FileID lookups.
823 LastFileIDLookup = Res;
824 NumLinearScans += NumProbes+1;
825 return Res;
826 }
827 if (++NumProbes == 8)
828 break;
829 }
830
831 NumProbes = 0;
832 while (true) {
833 unsigned MiddleIndex = (GreaterIndex-LessIndex)/2+LessIndex;
834 SourceLocation::UIntTy MidOffset =
835 getLocalSLocEntry(MiddleIndex).getOffset();
836
837 ++NumProbes;
838
839 // If the offset of the midpoint is too large, chop the high side of the
840 // range to the midpoint.
841 if (MidOffset > SLocOffset) {
842 GreaterIndex = MiddleIndex;
843 continue;
844 }
845
846 // If the middle index contains the value, succeed and return.
847 if (MiddleIndex + 1 == LocalSLocEntryTable.size() ||
848 SLocOffset < getLocalSLocEntry(MiddleIndex + 1).getOffset()) {
849 FileID Res = FileID::get(MiddleIndex);
850
851 // Remember it. We have good locality across FileID lookups.
852 LastFileIDLookup = Res;
853 NumBinaryProbes += NumProbes;
854 return Res;
855 }
856
857 // Otherwise, move the low-side up to the middle index.
858 LessIndex = MiddleIndex;
859 }
860}
861
862/// Return the FileID for a SourceLocation with a high offset.
863///
864/// This function knows that the SourceLocation is in a loaded buffer, not a
865/// local one.
866FileID SourceManager::getFileIDLoaded(SourceLocation::UIntTy SLocOffset) const {
867 if (SLocOffset < CurrentLoadedOffset) {
868 assert(0 && "Invalid SLocOffset or bad function choice");
869 return FileID();
870 }
871
872 // Essentially the same as the local case, but the loaded array is sorted
873 // in the other direction (decreasing order).
874 // GreaterIndex is the one where the offset is greater, which is actually a
875 // lower index!
876 unsigned GreaterIndex = 0;
877 unsigned LessIndex = LoadedSLocEntryTable.size();
878 if (LastFileIDLookup.ID < 0) {
879 // Prune the search space.
880 int LastID = LastFileIDLookup.ID;
881 if (getLoadedSLocEntryByID(LastID).getOffset() > SLocOffset)
882 GreaterIndex =
883 (-LastID - 2) + 1; // Exclude LastID, else we would have hit the cache
884 else
885 LessIndex = -LastID - 2;
886 }
887
888 // First do a linear scan from the last lookup position, if possible.
889 unsigned NumProbes;
890 bool Invalid = false;
891 for (NumProbes = 0; NumProbes < 8; ++NumProbes, ++GreaterIndex) {
892 // Make sure the entry is loaded!
893 const SrcMgr::SLocEntry &E = getLoadedSLocEntry(GreaterIndex, &Invalid);
894 if (Invalid)
895 return FileID(); // invalid entry.
896 if (E.getOffset() <= SLocOffset) {
897 FileID Res = FileID::get(-int(GreaterIndex) - 2);
898 LastFileIDLookup = Res;
899 NumLinearScans += NumProbes + 1;
900 return Res;
901 }
902 }
903
904 // Linear scan failed. Do the binary search.
905 NumProbes = 0;
906 while (true) {
907 ++NumProbes;
908 unsigned MiddleIndex = (LessIndex - GreaterIndex) / 2 + GreaterIndex;
909 const SrcMgr::SLocEntry &E = getLoadedSLocEntry(MiddleIndex, &Invalid);
910 if (Invalid)
911 return FileID(); // invalid entry.
912
913 if (E.getOffset() > SLocOffset) {
914 if (GreaterIndex == MiddleIndex) {
915 assert(0 && "binary search missed the entry");
916 return FileID();
917 }
918 GreaterIndex = MiddleIndex;
919 continue;
920 }
921
922 if (isOffsetInFileID(FileID::get(-int(MiddleIndex) - 2), SLocOffset)) {
923 FileID Res = FileID::get(-int(MiddleIndex) - 2);
924 LastFileIDLookup = Res;
925 NumBinaryProbes += NumProbes;
926 return Res;
927 }
928
929 if (LessIndex == MiddleIndex) {
930 assert(0 && "binary search missed the entry");
931 return FileID();
932 }
933 LessIndex = MiddleIndex;
934 }
935}
936
937SourceLocation SourceManager::
938getExpansionLocSlowCase(SourceLocation Loc) const {
939 do {
940 // Note: If Loc indicates an offset into a token that came from a macro
941 // expansion (e.g. the 5th character of the token) we do not want to add
942 // this offset when going to the expansion location. The expansion
943 // location is the macro invocation, which the offset has nothing to do
944 // with. This is unlike when we get the spelling loc, because the offset
945 // directly correspond to the token whose spelling we're inspecting.
947 } while (!Loc.isFileID());
948
949 return Loc;
950}
951
952SourceLocation SourceManager::getSpellingLocSlowCase(SourceLocation Loc) const {
953 do {
954 std::pair<FileID, unsigned> LocInfo = getDecomposedLoc(Loc);
955 Loc = getSLocEntry(LocInfo.first).getExpansion().getSpellingLoc();
956 Loc = Loc.getLocWithOffset(LocInfo.second);
957 } while (!Loc.isFileID());
958 return Loc;
959}
960
961SourceLocation SourceManager::getFileLocSlowCase(SourceLocation Loc) const {
962 do {
963 if (isMacroArgExpansion(Loc))
964 Loc = getImmediateSpellingLoc(Loc);
965 else
967 } while (!Loc.isFileID());
968 return Loc;
969}
970
971
972std::pair<FileID, unsigned>
973SourceManager::getDecomposedExpansionLocSlowCase(
974 const SrcMgr::SLocEntry *E) const {
975 // If this is an expansion record, walk through all the expansion points.
976 FileID FID;
977 SourceLocation Loc;
978 unsigned Offset;
979 do {
981
982 FID = getFileID(Loc);
983 E = &getSLocEntry(FID);
984 Offset = Loc.getOffset()-E->getOffset();
985 } while (!Loc.isFileID());
986
987 return std::make_pair(FID, Offset);
988}
989
990std::pair<FileID, unsigned>
991SourceManager::getDecomposedSpellingLocSlowCase(const SrcMgr::SLocEntry *E,
992 unsigned Offset) const {
993 // If this is an expansion record, walk through all the expansion points.
994 FileID FID;
995 SourceLocation Loc;
996 do {
997 Loc = E->getExpansion().getSpellingLoc();
998 Loc = Loc.getLocWithOffset(Offset);
999
1000 FID = getFileID(Loc);
1001 E = &getSLocEntry(FID);
1002 Offset = Loc.getOffset()-E->getOffset();
1003 } while (!Loc.isFileID());
1004
1005 return std::make_pair(FID, Offset);
1006}
1007
1008/// getImmediateSpellingLoc - Given a SourceLocation object, return the
1009/// spelling location referenced by the ID. This is the first level down
1010/// towards the place where the characters that make up the lexed token can be
1011/// found. This should not generally be used by clients.
1013 if (Loc.isFileID()) return Loc;
1014 std::pair<FileID, unsigned> LocInfo = getDecomposedLoc(Loc);
1015 Loc = getSLocEntry(LocInfo.first).getExpansion().getSpellingLoc();
1016 return Loc.getLocWithOffset(LocInfo.second);
1017}
1018
1019/// Return the filename of the file containing a SourceLocation.
1020StringRef SourceManager::getFilename(SourceLocation SpellingLoc) const {
1022 return F->getName();
1023 return StringRef();
1024}
1025
1026/// getImmediateExpansionRange - Loc is required to be an expansion location.
1027/// Return the start/end of the expansion information.
1030 assert(Loc.isMacroID() && "Not a macro expansion loc!");
1031 const ExpansionInfo &Expansion = getSLocEntry(getFileID(Loc)).getExpansion();
1032 return Expansion.getExpansionLocRange();
1033}
1034
1036 while (isMacroArgExpansion(Loc))
1037 Loc = getImmediateSpellingLoc(Loc);
1038 return Loc;
1039}
1040
1041/// getExpansionRange - Given a SourceLocation object, return the range of
1042/// tokens covered by the expansion in the ultimate file.
1044 if (Loc.isFileID())
1045 return CharSourceRange(SourceRange(Loc, Loc), true);
1046
1048
1049 // Fully resolve the start and end locations to their ultimate expansion
1050 // points.
1051 while (!Res.getBegin().isFileID())
1053 while (!Res.getEnd().isFileID()) {
1055 Res.setEnd(EndRange.getEnd());
1056 Res.setTokenRange(EndRange.isTokenRange());
1057 }
1058 return Res;
1059}
1060
1062 SourceLocation *StartLoc) const {
1063 if (!Loc.isMacroID()) return false;
1064
1065 FileID FID = getFileID(Loc);
1066 const SrcMgr::ExpansionInfo &Expansion = getSLocEntry(FID).getExpansion();
1067 if (!Expansion.isMacroArgExpansion()) return false;
1068
1069 if (StartLoc)
1070 *StartLoc = Expansion.getExpansionLocStart();
1071 return true;
1072}
1073
1075 if (!Loc.isMacroID()) return false;
1076
1077 FileID FID = getFileID(Loc);
1078 const SrcMgr::ExpansionInfo &Expansion = getSLocEntry(FID).getExpansion();
1079 return Expansion.isMacroBodyExpansion();
1080}
1081
1083 SourceLocation *MacroBegin) const {
1084 assert(Loc.isValid() && Loc.isMacroID() && "Expected a valid macro loc");
1085
1086 std::pair<FileID, unsigned> DecompLoc = getDecomposedLoc(Loc);
1087 if (DecompLoc.second > 0)
1088 return false; // Does not point at the start of expansion range.
1089
1090 bool Invalid = false;
1091 const SrcMgr::ExpansionInfo &ExpInfo =
1092 getSLocEntry(DecompLoc.first, &Invalid).getExpansion();
1093 if (Invalid)
1094 return false;
1095 SourceLocation ExpLoc = ExpInfo.getExpansionLocStart();
1096
1097 if (ExpInfo.isMacroArgExpansion()) {
1098 // For macro argument expansions, check if the previous FileID is part of
1099 // the same argument expansion, in which case this Loc is not at the
1100 // beginning of the expansion.
1101 FileID PrevFID = getPreviousFileID(DecompLoc.first);
1102 if (!PrevFID.isInvalid()) {
1103 const SrcMgr::SLocEntry &PrevEntry = getSLocEntry(PrevFID, &Invalid);
1104 if (Invalid)
1105 return false;
1106 if (PrevEntry.isExpansion() &&
1107 PrevEntry.getExpansion().getExpansionLocStart() == ExpLoc)
1108 return false;
1109 }
1110 }
1111
1112 if (MacroBegin)
1113 *MacroBegin = ExpLoc;
1114 return true;
1115}
1116
1118 SourceLocation *MacroEnd) const {
1119 assert(Loc.isValid() && Loc.isMacroID() && "Expected a valid macro loc");
1120
1121 FileID FID = getFileID(Loc);
1122 SourceLocation NextLoc = Loc.getLocWithOffset(1);
1123 if (isInFileID(NextLoc, FID))
1124 return false; // Does not point at the end of expansion range.
1125
1126 bool Invalid = false;
1127 const SrcMgr::ExpansionInfo &ExpInfo =
1129 if (Invalid)
1130 return false;
1131
1132 if (ExpInfo.isMacroArgExpansion()) {
1133 // For macro argument expansions, check if the next FileID is part of the
1134 // same argument expansion, in which case this Loc is not at the end of the
1135 // expansion.
1136 FileID NextFID = getNextFileID(FID);
1137 if (!NextFID.isInvalid()) {
1138 const SrcMgr::SLocEntry &NextEntry = getSLocEntry(NextFID, &Invalid);
1139 if (Invalid)
1140 return false;
1141 if (NextEntry.isExpansion() &&
1142 NextEntry.getExpansion().getExpansionLocStart() ==
1143 ExpInfo.getExpansionLocStart())
1144 return false;
1145 }
1146 }
1147
1148 if (MacroEnd)
1149 *MacroEnd = ExpInfo.getExpansionLocEnd();
1150 return true;
1151}
1152
1153//===----------------------------------------------------------------------===//
1154// Queries about the code at a SourceLocation.
1155//===----------------------------------------------------------------------===//
1156
1157/// getCharacterData - Return a pointer to the start of the specified location
1158/// in the appropriate MemoryBuffer.
1160 bool *Invalid) const {
1161 // Note that this is a hot function in the getSpelling() path, which is
1162 // heavily used by -E mode.
1163 std::pair<FileID, unsigned> LocInfo = getDecomposedSpellingLoc(SL);
1164
1165 // Note that calling 'getBuffer()' may lazily page in a source file.
1166 bool CharDataInvalid = false;
1167 const SLocEntry &Entry = getSLocEntry(LocInfo.first, &CharDataInvalid);
1168 if (CharDataInvalid || !Entry.isFile()) {
1169 if (Invalid)
1170 *Invalid = true;
1171
1172 return "<<<<INVALID BUFFER>>>>";
1173 }
1174 std::optional<llvm::MemoryBufferRef> Buffer =
1176 SourceLocation());
1177 if (Invalid)
1178 *Invalid = !Buffer;
1179 return Buffer ? Buffer->getBufferStart() + LocInfo.second
1180 : "<<<<INVALID BUFFER>>>>";
1181}
1182
1183/// getColumnNumber - Return the column # for the specified file position.
1184/// this is significantly cheaper to compute than the line number.
1185unsigned SourceManager::getColumnNumber(FileID FID, unsigned FilePos,
1186 bool *Invalid) const {
1187 std::optional<llvm::MemoryBufferRef> MemBuf = getBufferOrNone(FID);
1188 if (Invalid)
1189 *Invalid = !MemBuf;
1190
1191 if (!MemBuf)
1192 return 1;
1193
1194 // It is okay to request a position just past the end of the buffer.
1195 if (FilePos > MemBuf->getBufferSize()) {
1196 if (Invalid)
1197 *Invalid = true;
1198 return 1;
1199 }
1200
1201 const char *Buf = MemBuf->getBufferStart();
1202 // See if we just calculated the line number for this FilePos and can use
1203 // that to lookup the start of the line instead of searching for it.
1204 if (LastLineNoFileIDQuery == FID && LastLineNoContentCache->SourceLineCache &&
1205 LastLineNoResult < LastLineNoContentCache->SourceLineCache.size()) {
1206 const unsigned *SourceLineCache =
1207 LastLineNoContentCache->SourceLineCache.begin();
1208 unsigned LineStart = SourceLineCache[LastLineNoResult - 1];
1209 unsigned LineEnd = SourceLineCache[LastLineNoResult];
1210 if (FilePos >= LineStart && FilePos < LineEnd) {
1211 // LineEnd is the LineStart of the next line.
1212 // A line ends with separator LF or CR+LF on Windows.
1213 // FilePos might point to the last separator,
1214 // but we need a column number at most 1 + the last column.
1215 if (FilePos + 1 == LineEnd && FilePos > LineStart) {
1216 if (Buf[FilePos - 1] == '\r' || Buf[FilePos - 1] == '\n')
1217 --FilePos;
1218 }
1219 return FilePos - LineStart + 1;
1220 }
1221 }
1222
1223 unsigned LineStart = FilePos;
1224 while (LineStart && Buf[LineStart-1] != '\n' && Buf[LineStart-1] != '\r')
1225 --LineStart;
1226 return FilePos-LineStart+1;
1227}
1228
1229// isInvalid - Return the result of calling loc.isInvalid(), and
1230// if Invalid is not null, set its value to same.
1231template<typename LocType>
1232static bool isInvalid(LocType Loc, bool *Invalid) {
1233 bool MyInvalid = Loc.isInvalid();
1234 if (Invalid)
1235 *Invalid = MyInvalid;
1236 return MyInvalid;
1237}
1238
1240 bool *Invalid) const {
1241 if (isInvalid(Loc, Invalid)) return 0;
1242 std::pair<FileID, unsigned> LocInfo = getDecomposedSpellingLoc(Loc);
1243 return getColumnNumber(LocInfo.first, LocInfo.second, Invalid);
1244}
1245
1247 bool *Invalid) const {
1248 if (isInvalid(Loc, Invalid)) return 0;
1249 std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(Loc);
1250 return getColumnNumber(LocInfo.first, LocInfo.second, Invalid);
1251}
1252
1254 bool *Invalid) const {
1255 PresumedLoc PLoc = getPresumedLoc(Loc);
1256 if (isInvalid(PLoc, Invalid)) return 0;
1257 return PLoc.getColumn();
1258}
1259
1260// Check if mutli-byte word x has bytes between m and n, included. This may also
1261// catch bytes equal to n + 1.
1262// The returned value holds a 0x80 at each byte position that holds a match.
1263// see http://graphics.stanford.edu/~seander/bithacks.html#HasBetweenInWord
1264template <class T>
1265static constexpr inline T likelyhasbetween(T x, unsigned char m,
1266 unsigned char n) {
1267 return ((x - ~static_cast<T>(0) / 255 * (n + 1)) & ~x &
1268 ((x & ~static_cast<T>(0) / 255 * 127) +
1269 (~static_cast<T>(0) / 255 * (127 - (m - 1))))) &
1270 ~static_cast<T>(0) / 255 * 128;
1271}
1272
1273LineOffsetMapping LineOffsetMapping::get(llvm::MemoryBufferRef Buffer,
1274 llvm::BumpPtrAllocator &Alloc) {
1275
1276 // Find the file offsets of all of the *physical* source lines. This does
1277 // not look at trigraphs, escaped newlines, or anything else tricky.
1278 SmallVector<unsigned, 256> LineOffsets;
1279
1280 // Line #1 starts at char 0.
1281 LineOffsets.push_back(0);
1282
1283 const unsigned char *Start = (const unsigned char *)Buffer.getBufferStart();
1284 const unsigned char *End = (const unsigned char *)Buffer.getBufferEnd();
1285 const unsigned char *Buf = Start;
1286
1287 uint64_t Word;
1288
1289 // scan sizeof(Word) bytes at a time for new lines.
1290 // This is much faster than scanning each byte independently.
1291 if ((unsigned long)(End - Start) > sizeof(Word)) {
1292 do {
1293 Word = llvm::support::endian::read64(Buf, llvm::support::little);
1294 // no new line => jump over sizeof(Word) bytes.
1295 auto Mask = likelyhasbetween(Word, '\n', '\r');
1296 if (!Mask) {
1297 Buf += sizeof(Word);
1298 continue;
1299 }
1300
1301 // At that point, Mask contains 0x80 set at each byte that holds a value
1302 // in [\n, \r + 1 [
1303
1304 // Scan for the next newline - it's very likely there's one.
1305 unsigned N = llvm::countr_zero(Mask) - 7; // -7 because 0x80 is the marker
1306 Word >>= N;
1307 Buf += N / 8 + 1;
1308 unsigned char Byte = Word;
1309 switch (Byte) {
1310 case '\r':
1311 // If this is \r\n, skip both characters.
1312 if (*Buf == '\n') {
1313 ++Buf;
1314 }
1315 [[fallthrough]];
1316 case '\n':
1317 LineOffsets.push_back(Buf - Start);
1318 };
1319 } while (Buf < End - sizeof(Word) - 1);
1320 }
1321
1322 // Handle tail using a regular check.
1323 while (Buf < End) {
1324 if (*Buf == '\n') {
1325 LineOffsets.push_back(Buf - Start + 1);
1326 } else if (*Buf == '\r') {
1327 // If this is \r\n, skip both characters.
1328 if (Buf + 1 < End && Buf[1] == '\n') {
1329 ++Buf;
1330 }
1331 LineOffsets.push_back(Buf - Start + 1);
1332 }
1333 ++Buf;
1334 }
1335
1336 return LineOffsetMapping(LineOffsets, Alloc);
1337}
1338
1340 llvm::BumpPtrAllocator &Alloc)
1341 : Storage(Alloc.Allocate<unsigned>(LineOffsets.size() + 1)) {
1342 Storage[0] = LineOffsets.size();
1343 std::copy(LineOffsets.begin(), LineOffsets.end(), Storage + 1);
1344}
1345
1346/// getLineNumber - Given a SourceLocation, return the spelling line number
1347/// for the position indicated. This requires building and caching a table of
1348/// line offsets for the MemoryBuffer, so this is not cheap: use only when
1349/// about to emit a diagnostic.
1350unsigned SourceManager::getLineNumber(FileID FID, unsigned FilePos,
1351 bool *Invalid) const {
1352 if (FID.isInvalid()) {
1353 if (Invalid)
1354 *Invalid = true;
1355 return 1;
1356 }
1357
1358 const ContentCache *Content;
1359 if (LastLineNoFileIDQuery == FID)
1360 Content = LastLineNoContentCache;
1361 else {
1362 bool MyInvalid = false;
1363 const SLocEntry &Entry = getSLocEntry(FID, &MyInvalid);
1364 if (MyInvalid || !Entry.isFile()) {
1365 if (Invalid)
1366 *Invalid = true;
1367 return 1;
1368 }
1369
1370 Content = &Entry.getFile().getContentCache();
1371 }
1372
1373 // If this is the first use of line information for this buffer, compute the
1374 /// SourceLineCache for it on demand.
1375 if (!Content->SourceLineCache) {
1376 std::optional<llvm::MemoryBufferRef> Buffer =
1377 Content->getBufferOrNone(Diag, getFileManager(), SourceLocation());
1378 if (Invalid)
1379 *Invalid = !Buffer;
1380 if (!Buffer)
1381 return 1;
1382
1383 Content->SourceLineCache =
1384 LineOffsetMapping::get(*Buffer, ContentCacheAlloc);
1385 } else if (Invalid)
1386 *Invalid = false;
1387
1388 // Okay, we know we have a line number table. Do a binary search to find the
1389 // line number that this character position lands on.
1390 const unsigned *SourceLineCache = Content->SourceLineCache.begin();
1391 const unsigned *SourceLineCacheStart = SourceLineCache;
1392 const unsigned *SourceLineCacheEnd = Content->SourceLineCache.end();
1393
1394 unsigned QueriedFilePos = FilePos+1;
1395
1396 // FIXME: I would like to be convinced that this code is worth being as
1397 // complicated as it is, binary search isn't that slow.
1398 //
1399 // If it is worth being optimized, then in my opinion it could be more
1400 // performant, simpler, and more obviously correct by just "galloping" outward
1401 // from the queried file position. In fact, this could be incorporated into a
1402 // generic algorithm such as lower_bound_with_hint.
1403 //
1404 // If someone gives me a test case where this matters, and I will do it! - DWD
1405
1406 // If the previous query was to the same file, we know both the file pos from
1407 // that query and the line number returned. This allows us to narrow the
1408 // search space from the entire file to something near the match.
1409 if (LastLineNoFileIDQuery == FID) {
1410 if (QueriedFilePos >= LastLineNoFilePos) {
1411 // FIXME: Potential overflow?
1412 SourceLineCache = SourceLineCache+LastLineNoResult-1;
1413
1414 // The query is likely to be nearby the previous one. Here we check to
1415 // see if it is within 5, 10 or 20 lines. It can be far away in cases
1416 // where big comment blocks and vertical whitespace eat up lines but
1417 // contribute no tokens.
1418 if (SourceLineCache+5 < SourceLineCacheEnd) {
1419 if (SourceLineCache[5] > QueriedFilePos)
1420 SourceLineCacheEnd = SourceLineCache+5;
1421 else if (SourceLineCache+10 < SourceLineCacheEnd) {
1422 if (SourceLineCache[10] > QueriedFilePos)
1423 SourceLineCacheEnd = SourceLineCache+10;
1424 else if (SourceLineCache+20 < SourceLineCacheEnd) {
1425 if (SourceLineCache[20] > QueriedFilePos)
1426 SourceLineCacheEnd = SourceLineCache+20;
1427 }
1428 }
1429 }
1430 } else {
1431 if (LastLineNoResult < Content->SourceLineCache.size())
1432 SourceLineCacheEnd = SourceLineCache+LastLineNoResult+1;
1433 }
1434 }
1435
1436 const unsigned *Pos =
1437 std::lower_bound(SourceLineCache, SourceLineCacheEnd, QueriedFilePos);
1438 unsigned LineNo = Pos-SourceLineCacheStart;
1439
1440 LastLineNoFileIDQuery = FID;
1441 LastLineNoContentCache = Content;
1442 LastLineNoFilePos = QueriedFilePos;
1443 LastLineNoResult = LineNo;
1444 return LineNo;
1445}
1446
1448 bool *Invalid) const {
1449 if (isInvalid(Loc, Invalid)) return 0;
1450 std::pair<FileID, unsigned> LocInfo = getDecomposedSpellingLoc(Loc);
1451 return getLineNumber(LocInfo.first, LocInfo.second);
1452}
1454 bool *Invalid) const {
1455 if (isInvalid(Loc, Invalid)) return 0;
1456 std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(Loc);
1457 return getLineNumber(LocInfo.first, LocInfo.second);
1458}
1460 bool *Invalid) const {
1461 PresumedLoc PLoc = getPresumedLoc(Loc);
1462 if (isInvalid(PLoc, Invalid)) return 0;
1463 return PLoc.getLine();
1464}
1465
1466/// getFileCharacteristic - return the file characteristic of the specified
1467/// source location, indicating whether this is a normal file, a system
1468/// header, or an "implicit extern C" system header.
1469///
1470/// This state can be modified with flags on GNU linemarker directives like:
1471/// # 4 "foo.h" 3
1472/// which changes all source locations in the current file after that to be
1473/// considered to be from a system header.
1476 assert(Loc.isValid() && "Can't get file characteristic of invalid loc!");
1477 std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(Loc);
1478 const SLocEntry *SEntry = getSLocEntryForFile(LocInfo.first);
1479 if (!SEntry)
1480 return C_User;
1481
1482 const SrcMgr::FileInfo &FI = SEntry->getFile();
1483
1484 // If there are no #line directives in this file, just return the whole-file
1485 // state.
1486 if (!FI.hasLineDirectives())
1487 return FI.getFileCharacteristic();
1488
1489 assert(LineTable && "Can't have linetable entries without a LineTable!");
1490 // See if there is a #line directive before the location.
1491 const LineEntry *Entry =
1492 LineTable->FindNearestLineEntry(LocInfo.first, LocInfo.second);
1493
1494 // If this is before the first line marker, use the file characteristic.
1495 if (!Entry)
1496 return FI.getFileCharacteristic();
1497
1498 return Entry->FileKind;
1499}
1500
1501/// Return the filename or buffer identifier of the buffer the location is in.
1502/// Note that this name does not respect \#line directives. Use getPresumedLoc
1503/// for normal clients.
1505 bool *Invalid) const {
1506 if (isInvalid(Loc, Invalid)) return "<invalid loc>";
1507
1508 auto B = getBufferOrNone(getFileID(Loc));
1509 if (Invalid)
1510 *Invalid = !B;
1511 return B ? B->getBufferIdentifier() : "<invalid buffer>";
1512}
1513
1514/// getPresumedLoc - This method returns the "presumed" location of a
1515/// SourceLocation specifies. A "presumed location" can be modified by \#line
1516/// or GNU line marker directives. This provides a view on the data that a
1517/// user should see in diagnostics, for example.
1518///
1519/// Note that a presumed location is always given as the expansion point of an
1520/// expansion location, not at the spelling location.
1522 bool UseLineDirectives) const {
1523 if (Loc.isInvalid()) return PresumedLoc();
1524
1525 // Presumed locations are always for expansion points.
1526 std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(Loc);
1527
1528 bool Invalid = false;
1529 const SLocEntry &Entry = getSLocEntry(LocInfo.first, &Invalid);
1530 if (Invalid || !Entry.isFile())
1531 return PresumedLoc();
1532
1533 const SrcMgr::FileInfo &FI = Entry.getFile();
1534 const SrcMgr::ContentCache *C = &FI.getContentCache();
1535
1536 // To get the source name, first consult the FileEntry (if one exists)
1537 // before the MemBuffer as this will avoid unnecessarily paging in the
1538 // MemBuffer.
1539 FileID FID = LocInfo.first;
1540 StringRef Filename;
1541 if (C->OrigEntry)
1542 Filename = C->OrigEntry->getName();
1543 else if (auto Buffer = C->getBufferOrNone(Diag, getFileManager()))
1544 Filename = Buffer->getBufferIdentifier();
1545
1546 unsigned LineNo = getLineNumber(LocInfo.first, LocInfo.second, &Invalid);
1547 if (Invalid)
1548 return PresumedLoc();
1549 unsigned ColNo = getColumnNumber(LocInfo.first, LocInfo.second, &Invalid);
1550 if (Invalid)
1551 return PresumedLoc();
1552
1553 SourceLocation IncludeLoc = FI.getIncludeLoc();
1554
1555 // If we have #line directives in this file, update and overwrite the physical
1556 // location info if appropriate.
1557 if (UseLineDirectives && FI.hasLineDirectives()) {
1558 assert(LineTable && "Can't have linetable entries without a LineTable!");
1559 // See if there is a #line directive before this. If so, get it.
1560 if (const LineEntry *Entry =
1561 LineTable->FindNearestLineEntry(LocInfo.first, LocInfo.second)) {
1562 // If the LineEntry indicates a filename, use it.
1563 if (Entry->FilenameID != -1) {
1564 Filename = LineTable->getFilename(Entry->FilenameID);
1565 // The contents of files referenced by #line are not in the
1566 // SourceManager
1567 FID = FileID::get(0);
1568 }
1569
1570 // Use the line number specified by the LineEntry. This line number may
1571 // be multiple lines down from the line entry. Add the difference in
1572 // physical line numbers from the query point and the line marker to the
1573 // total.
1574 unsigned MarkerLineNo = getLineNumber(LocInfo.first, Entry->FileOffset);
1575 LineNo = Entry->LineNo + (LineNo-MarkerLineNo-1);
1576
1577 // Note that column numbers are not molested by line markers.
1578
1579 // Handle virtual #include manipulation.
1580 if (Entry->IncludeOffset) {
1581 IncludeLoc = getLocForStartOfFile(LocInfo.first);
1582 IncludeLoc = IncludeLoc.getLocWithOffset(Entry->IncludeOffset);
1583 }
1584 }
1585 }
1586
1587 return PresumedLoc(Filename.data(), FID, LineNo, ColNo, IncludeLoc);
1588}
1589
1590/// Returns whether the PresumedLoc for a given SourceLocation is
1591/// in the main file.
1592///
1593/// This computes the "presumed" location for a SourceLocation, then checks
1594/// whether it came from a file other than the main file. This is different
1595/// from isWrittenInMainFile() because it takes line marker directives into
1596/// account.
1598 if (Loc.isInvalid()) return false;
1599
1600 // Presumed locations are always for expansion points.
1601 std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(Loc);
1602
1603 const SLocEntry *Entry = getSLocEntryForFile(LocInfo.first);
1604 if (!Entry)
1605 return false;
1606
1607 const SrcMgr::FileInfo &FI = Entry->getFile();
1608
1609 // Check if there is a line directive for this location.
1610 if (FI.hasLineDirectives())
1611 if (const LineEntry *Entry =
1612 LineTable->FindNearestLineEntry(LocInfo.first, LocInfo.second))
1613 if (Entry->IncludeOffset)
1614 return false;
1615
1616 return FI.getIncludeLoc().isInvalid();
1617}
1618
1619/// The size of the SLocEntry that \p FID represents.
1621 bool Invalid = false;
1622 const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid);
1623 if (Invalid)
1624 return 0;
1625
1626 int ID = FID.ID;
1627 SourceLocation::UIntTy NextOffset;
1628 if ((ID > 0 && unsigned(ID+1) == local_sloc_entry_size()))
1629 NextOffset = getNextLocalOffset();
1630 else if (ID+1 == -1)
1631 NextOffset = MaxLoadedOffset;
1632 else
1633 NextOffset = getSLocEntry(FileID::get(ID+1)).getOffset();
1634
1635 return NextOffset - Entry.getOffset() - 1;
1636}
1637
1638//===----------------------------------------------------------------------===//
1639// Other miscellaneous methods.
1640//===----------------------------------------------------------------------===//
1641
1642/// Get the source location for the given file:line:col triplet.
1643///
1644/// If the source file is included multiple times, the source location will
1645/// be based upon an arbitrary inclusion.
1647 unsigned Line,
1648 unsigned Col) const {
1649 assert(SourceFile && "Null source file!");
1650 assert(Line && Col && "Line and column should start from 1!");
1651
1652 FileID FirstFID = translateFile(SourceFile);
1653 return translateLineCol(FirstFID, Line, Col);
1654}
1655
1656/// Get the FileID for the given file.
1657///
1658/// If the source file is included multiple times, the FileID will be the
1659/// first inclusion.
1661 assert(SourceFile && "Null source file!");
1662
1663 // First, check the main file ID, since it is common to look for a
1664 // location in the main file.
1665 if (MainFileID.isValid()) {
1666 bool Invalid = false;
1667 const SLocEntry &MainSLoc = getSLocEntry(MainFileID, &Invalid);
1668 if (Invalid)
1669 return FileID();
1670
1671 if (MainSLoc.isFile()) {
1672 if (MainSLoc.getFile().getContentCache().OrigEntry == SourceFile)
1673 return MainFileID;
1674 }
1675 }
1676
1677 // The location we're looking for isn't in the main file; look
1678 // through all of the local source locations.
1679 for (unsigned I = 0, N = local_sloc_entry_size(); I != N; ++I) {
1680 const SLocEntry &SLoc = getLocalSLocEntry(I);
1681 if (SLoc.isFile() &&
1682 SLoc.getFile().getContentCache().OrigEntry == SourceFile)
1683 return FileID::get(I);
1684 }
1685
1686 // If that still didn't help, try the modules.
1687 for (unsigned I = 0, N = loaded_sloc_entry_size(); I != N; ++I) {
1688 const SLocEntry &SLoc = getLoadedSLocEntry(I);
1689 if (SLoc.isFile() &&
1690 SLoc.getFile().getContentCache().OrigEntry == SourceFile)
1691 return FileID::get(-int(I) - 2);
1692 }
1693
1694 return FileID();
1695}
1696
1697/// Get the source location in \arg FID for the given line:col.
1698/// Returns null location if \arg FID is not a file SLocEntry.
1700 unsigned Line,
1701 unsigned Col) const {
1702 // Lines are used as a one-based index into a zero-based array. This assert
1703 // checks for possible buffer underruns.
1704 assert(Line && Col && "Line and column should start from 1!");
1705
1706 if (FID.isInvalid())
1707 return SourceLocation();
1708
1709 bool Invalid = false;
1710 const SLocEntry &Entry = getSLocEntry(FID, &Invalid);
1711 if (Invalid)
1712 return SourceLocation();
1713
1714 if (!Entry.isFile())
1715 return SourceLocation();
1716
1717 SourceLocation FileLoc = SourceLocation::getFileLoc(Entry.getOffset());
1718
1719 if (Line == 1 && Col == 1)
1720 return FileLoc;
1721
1722 const ContentCache *Content = &Entry.getFile().getContentCache();
1723
1724 // If this is the first use of line information for this buffer, compute the
1725 // SourceLineCache for it on demand.
1726 std::optional<llvm::MemoryBufferRef> Buffer =
1727 Content->getBufferOrNone(Diag, getFileManager());
1728 if (!Buffer)
1729 return SourceLocation();
1730 if (!Content->SourceLineCache)
1731 Content->SourceLineCache =
1732 LineOffsetMapping::get(*Buffer, ContentCacheAlloc);
1733
1734 if (Line > Content->SourceLineCache.size()) {
1735 unsigned Size = Buffer->getBufferSize();
1736 if (Size > 0)
1737 --Size;
1738 return FileLoc.getLocWithOffset(Size);
1739 }
1740
1741 unsigned FilePos = Content->SourceLineCache[Line - 1];
1742 const char *Buf = Buffer->getBufferStart() + FilePos;
1743 unsigned BufLength = Buffer->getBufferSize() - FilePos;
1744 if (BufLength == 0)
1745 return FileLoc.getLocWithOffset(FilePos);
1746
1747 unsigned i = 0;
1748
1749 // Check that the given column is valid.
1750 while (i < BufLength-1 && i < Col-1 && Buf[i] != '\n' && Buf[i] != '\r')
1751 ++i;
1752 return FileLoc.getLocWithOffset(FilePos + i);
1753}
1754
1755/// Compute a map of macro argument chunks to their expanded source
1756/// location. Chunks that are not part of a macro argument will map to an
1757/// invalid source location. e.g. if a file contains one macro argument at
1758/// offset 100 with length 10, this is how the map will be formed:
1759/// 0 -> SourceLocation()
1760/// 100 -> Expanded macro arg location
1761/// 110 -> SourceLocation()
1762void SourceManager::computeMacroArgsCache(MacroArgsMap &MacroArgsCache,
1763 FileID FID) const {
1764 assert(FID.isValid());
1765
1766 // Initially no macro argument chunk is present.
1767 MacroArgsCache.insert(std::make_pair(0, SourceLocation()));
1768
1769 int ID = FID.ID;
1770 while (true) {
1771 ++ID;
1772 // Stop if there are no more FileIDs to check.
1773 if (ID > 0) {
1774 if (unsigned(ID) >= local_sloc_entry_size())
1775 return;
1776 } else if (ID == -1) {
1777 return;
1778 }
1779
1780 bool Invalid = false;
1781 const SrcMgr::SLocEntry &Entry = getSLocEntryByID(ID, &Invalid);
1782 if (Invalid)
1783 return;
1784 if (Entry.isFile()) {
1785 auto& File = Entry.getFile();
1786 if (File.getFileCharacteristic() == C_User_ModuleMap ||
1787 File.getFileCharacteristic() == C_System_ModuleMap)
1788 continue;
1789
1790 SourceLocation IncludeLoc = File.getIncludeLoc();
1791 bool IncludedInFID =
1792 (IncludeLoc.isValid() && isInFileID(IncludeLoc, FID)) ||
1793 // Predefined header doesn't have a valid include location in main
1794 // file, but any files created by it should still be skipped when
1795 // computing macro args expanded in the main file.
1796 (FID == MainFileID && Entry.getFile().getName() == "<built-in>");
1797 if (IncludedInFID) {
1798 // Skip the files/macros of the #include'd file, we only care about
1799 // macros that lexed macro arguments from our file.
1800 if (Entry.getFile().NumCreatedFIDs)
1801 ID += Entry.getFile().NumCreatedFIDs - 1 /*because of next ++ID*/;
1802 continue;
1803 }
1804 // If file was included but not from FID, there is no more files/macros
1805 // that may be "contained" in this file.
1806 if (IncludeLoc.isValid())
1807 return;
1808 continue;
1809 }
1810
1811 const ExpansionInfo &ExpInfo = Entry.getExpansion();
1812
1813 if (ExpInfo.getExpansionLocStart().isFileID()) {
1814 if (!isInFileID(ExpInfo.getExpansionLocStart(), FID))
1815 return; // No more files/macros that may be "contained" in this file.
1816 }
1817
1818 if (!ExpInfo.isMacroArgExpansion())
1819 continue;
1820
1821 associateFileChunkWithMacroArgExp(MacroArgsCache, FID,
1822 ExpInfo.getSpellingLoc(),
1823 SourceLocation::getMacroLoc(Entry.getOffset()),
1824 getFileIDSize(FileID::get(ID)));
1825 }
1826}
1827
1828void SourceManager::associateFileChunkWithMacroArgExp(
1829 MacroArgsMap &MacroArgsCache,
1830 FileID FID,
1831 SourceLocation SpellLoc,
1832 SourceLocation ExpansionLoc,
1833 unsigned ExpansionLength) const {
1834 if (!SpellLoc.isFileID()) {
1835 SourceLocation::UIntTy SpellBeginOffs = SpellLoc.getOffset();
1836 SourceLocation::UIntTy SpellEndOffs = SpellBeginOffs + ExpansionLength;
1837
1838 // The spelling range for this macro argument expansion can span multiple
1839 // consecutive FileID entries. Go through each entry contained in the
1840 // spelling range and if one is itself a macro argument expansion, recurse
1841 // and associate the file chunk that it represents.
1842
1843 FileID SpellFID; // Current FileID in the spelling range.
1844 unsigned SpellRelativeOffs;
1845 std::tie(SpellFID, SpellRelativeOffs) = getDecomposedLoc(SpellLoc);
1846 while (true) {
1847 const SLocEntry &Entry = getSLocEntry(SpellFID);
1848 SourceLocation::UIntTy SpellFIDBeginOffs = Entry.getOffset();
1849 unsigned SpellFIDSize = getFileIDSize(SpellFID);
1850 SourceLocation::UIntTy SpellFIDEndOffs = SpellFIDBeginOffs + SpellFIDSize;
1851 const ExpansionInfo &Info = Entry.getExpansion();
1852 if (Info.isMacroArgExpansion()) {
1853 unsigned CurrSpellLength;
1854 if (SpellFIDEndOffs < SpellEndOffs)
1855 CurrSpellLength = SpellFIDSize - SpellRelativeOffs;
1856 else
1857 CurrSpellLength = ExpansionLength;
1858 associateFileChunkWithMacroArgExp(MacroArgsCache, FID,
1859 Info.getSpellingLoc().getLocWithOffset(SpellRelativeOffs),
1860 ExpansionLoc, CurrSpellLength);
1861 }
1862
1863 if (SpellFIDEndOffs >= SpellEndOffs)
1864 return; // we covered all FileID entries in the spelling range.
1865
1866 // Move to the next FileID entry in the spelling range.
1867 unsigned advance = SpellFIDSize - SpellRelativeOffs + 1;
1868 ExpansionLoc = ExpansionLoc.getLocWithOffset(advance);
1869 ExpansionLength -= advance;
1870 ++SpellFID.ID;
1871 SpellRelativeOffs = 0;
1872 }
1873 }
1874
1875 assert(SpellLoc.isFileID());
1876
1877 unsigned BeginOffs;
1878 if (!isInFileID(SpellLoc, FID, &BeginOffs))
1879 return;
1880
1881 unsigned EndOffs = BeginOffs + ExpansionLength;
1882
1883 // Add a new chunk for this macro argument. A previous macro argument chunk
1884 // may have been lexed again, so e.g. if the map is
1885 // 0 -> SourceLocation()
1886 // 100 -> Expanded loc #1
1887 // 110 -> SourceLocation()
1888 // and we found a new macro FileID that lexed from offset 105 with length 3,
1889 // the new map will be:
1890 // 0 -> SourceLocation()
1891 // 100 -> Expanded loc #1
1892 // 105 -> Expanded loc #2
1893 // 108 -> Expanded loc #1
1894 // 110 -> SourceLocation()
1895 //
1896 // Since re-lexed macro chunks will always be the same size or less of
1897 // previous chunks, we only need to find where the ending of the new macro
1898 // chunk is mapped to and update the map with new begin/end mappings.
1899
1900 MacroArgsMap::iterator I = MacroArgsCache.upper_bound(EndOffs);
1901 --I;
1902 SourceLocation EndOffsMappedLoc = I->second;
1903 MacroArgsCache[BeginOffs] = ExpansionLoc;
1904 MacroArgsCache[EndOffs] = EndOffsMappedLoc;
1905}
1906
1907/// If \arg Loc points inside a function macro argument, the returned
1908/// location will be the macro location in which the argument was expanded.
1909/// If a macro argument is used multiple times, the expanded location will
1910/// be at the first expansion of the argument.
1911/// e.g.
1912/// MY_MACRO(foo);
1913/// ^
1914/// Passing a file location pointing at 'foo', will yield a macro location
1915/// where 'foo' was expanded into.
1918 if (Loc.isInvalid() || !Loc.isFileID())
1919 return Loc;
1920
1921 FileID FID;
1922 unsigned Offset;
1923 std::tie(FID, Offset) = getDecomposedLoc(Loc);
1924 if (FID.isInvalid())
1925 return Loc;
1926
1927 std::unique_ptr<MacroArgsMap> &MacroArgsCache = MacroArgsCacheMap[FID];
1928 if (!MacroArgsCache) {
1929 MacroArgsCache = std::make_unique<MacroArgsMap>();
1930 computeMacroArgsCache(*MacroArgsCache, FID);
1931 }
1932
1933 assert(!MacroArgsCache->empty());
1934 MacroArgsMap::iterator I = MacroArgsCache->upper_bound(Offset);
1935 // In case every element in MacroArgsCache is greater than Offset we can't
1936 // decrement the iterator.
1937 if (I == MacroArgsCache->begin())
1938 return Loc;
1939
1940 --I;
1941
1942 SourceLocation::UIntTy MacroArgBeginOffs = I->first;
1943 SourceLocation MacroArgExpandedLoc = I->second;
1944 if (MacroArgExpandedLoc.isValid())
1945 return MacroArgExpandedLoc.getLocWithOffset(Offset - MacroArgBeginOffs);
1946
1947 return Loc;
1948}
1949
1950std::pair<FileID, unsigned>
1952 if (FID.isInvalid())
1953 return std::make_pair(FileID(), 0);
1954
1955 // Uses IncludedLocMap to retrieve/cache the decomposed loc.
1956
1957 using DecompTy = std::pair<FileID, unsigned>;
1958 auto InsertOp = IncludedLocMap.try_emplace(FID);
1959 DecompTy &DecompLoc = InsertOp.first->second;
1960 if (!InsertOp.second)
1961 return DecompLoc; // already in map.
1962
1963 SourceLocation UpperLoc;
1964 bool Invalid = false;
1965 const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid);
1966 if (!Invalid) {
1967 if (Entry.isExpansion())
1968 UpperLoc = Entry.getExpansion().getExpansionLocStart();
1969 else
1970 UpperLoc = Entry.getFile().getIncludeLoc();
1971 }
1972
1973 if (UpperLoc.isValid())
1974 DecompLoc = getDecomposedLoc(UpperLoc);
1975
1976 return DecompLoc;
1977}
1978
1979/// Given a decomposed source location, move it up the include/expansion stack
1980/// to the parent source location. If this is possible, return the decomposed
1981/// version of the parent in Loc and return false. If Loc is the top-level
1982/// entry, return true and don't modify it.
1983static bool MoveUpIncludeHierarchy(std::pair<FileID, unsigned> &Loc,
1984 const SourceManager &SM) {
1985 std::pair<FileID, unsigned> UpperLoc = SM.getDecomposedIncludedLoc(Loc.first);
1986 if (UpperLoc.first.isInvalid())
1987 return true; // We reached the top.
1988
1989 Loc = UpperLoc;
1990 return false;
1991}
1992
1993/// Return the cache entry for comparing the given file IDs
1994/// for isBeforeInTranslationUnit.
1995InBeforeInTUCacheEntry &SourceManager::getInBeforeInTUCache(FileID LFID,
1996 FileID RFID) const {
1997 // This is a magic number for limiting the cache size. It was experimentally
1998 // derived from a small Objective-C project (where the cache filled
1999 // out to ~250 items). We can make it larger if necessary.
2000 // FIXME: this is almost certainly full these days. Use an LRU cache?
2001 enum { MagicCacheSize = 300 };
2002 IsBeforeInTUCacheKey Key(LFID, RFID);
2003
2004 // If the cache size isn't too large, do a lookup and if necessary default
2005 // construct an entry. We can then return it to the caller for direct
2006 // use. When they update the value, the cache will get automatically
2007 // updated as well.
2008 if (IBTUCache.size() < MagicCacheSize)
2009 return IBTUCache.try_emplace(Key, LFID, RFID).first->second;
2010
2011 // Otherwise, do a lookup that will not construct a new value.
2012 InBeforeInTUCache::iterator I = IBTUCache.find(Key);
2013 if (I != IBTUCache.end())
2014 return I->second;
2015
2016 // Fall back to the overflow value.
2017 IBTUCacheOverflow.setQueryFIDs(LFID, RFID);
2018 return IBTUCacheOverflow;
2019}
2020
2021/// Determines the order of 2 source locations in the translation unit.
2022///
2023/// \returns true if LHS source location comes before RHS, false otherwise.
2025 SourceLocation RHS) const {
2026 assert(LHS.isValid() && RHS.isValid() && "Passed invalid source location!");
2027 if (LHS == RHS)
2028 return false;
2029
2030 std::pair<FileID, unsigned> LOffs = getDecomposedLoc(LHS);
2031 std::pair<FileID, unsigned> ROffs = getDecomposedLoc(RHS);
2032
2033 // getDecomposedLoc may have failed to return a valid FileID because, e.g. it
2034 // is a serialized one referring to a file that was removed after we loaded
2035 // the PCH.
2036 if (LOffs.first.isInvalid() || ROffs.first.isInvalid())
2037 return LOffs.first.isInvalid() && !ROffs.first.isInvalid();
2038
2039 std::pair<bool, bool> InSameTU = isInTheSameTranslationUnit(LOffs, ROffs);
2040 if (InSameTU.first)
2041 return InSameTU.second;
2042
2043 // If we arrived here, the location is either in a built-ins buffer or
2044 // associated with global inline asm. PR5662 and PR22576 are examples.
2045
2046 StringRef LB = getBufferOrFake(LOffs.first).getBufferIdentifier();
2047 StringRef RB = getBufferOrFake(ROffs.first).getBufferIdentifier();
2048 bool LIsBuiltins = LB == "<built-in>";
2049 bool RIsBuiltins = RB == "<built-in>";
2050 // Sort built-in before non-built-in.
2051 if (LIsBuiltins || RIsBuiltins) {
2052 if (LIsBuiltins != RIsBuiltins)
2053 return LIsBuiltins;
2054 // Both are in built-in buffers, but from different files. We just claim that
2055 // lower IDs come first.
2056 return LOffs.first < ROffs.first;
2057 }
2058 bool LIsAsm = LB == "<inline asm>";
2059 bool RIsAsm = RB == "<inline asm>";
2060 // Sort assembler after built-ins, but before the rest.
2061 if (LIsAsm || RIsAsm) {
2062 if (LIsAsm != RIsAsm)
2063 return RIsAsm;
2064 assert(LOffs.first == ROffs.first);
2065 return false;
2066 }
2067 bool LIsScratch = LB == "<scratch space>";
2068 bool RIsScratch = RB == "<scratch space>";
2069 // Sort scratch after inline asm, but before the rest.
2070 if (LIsScratch || RIsScratch) {
2071 if (LIsScratch != RIsScratch)
2072 return LIsScratch;
2073 return LOffs.second < ROffs.second;
2074 }
2075 llvm_unreachable("Unsortable locations found");
2076}
2077
2079 std::pair<FileID, unsigned> &LOffs,
2080 std::pair<FileID, unsigned> &ROffs) const {
2081 // If the source locations are in the same file, just compare offsets.
2082 if (LOffs.first == ROffs.first)
2083 return std::make_pair(true, LOffs.second < ROffs.second);
2084
2085 // If we are comparing a source location with multiple locations in the same
2086 // file, we get a big win by caching the result.
2087 InBeforeInTUCacheEntry &IsBeforeInTUCache =
2088 getInBeforeInTUCache(LOffs.first, ROffs.first);
2089
2090 // If we are comparing a source location with multiple locations in the same
2091 // file, we get a big win by caching the result.
2092 if (IsBeforeInTUCache.isCacheValid())
2093 return std::make_pair(
2094 true, IsBeforeInTUCache.getCachedResult(LOffs.second, ROffs.second));
2095
2096 // Okay, we missed in the cache, we'll compute the answer and populate it.
2097 // We need to find the common ancestor. The only way of doing this is to
2098 // build the complete include chain for one and then walking up the chain
2099 // of the other looking for a match.
2100
2101 // A location within a FileID on the path up from LOffs to the main file.
2102 struct Entry {
2103 unsigned Offset;
2104 FileID ParentFID; // Used for breaking ties.
2105 };
2106 llvm::SmallDenseMap<FileID, Entry, 16> LChain;
2107
2108 FileID Parent;
2109 do {
2110 LChain.try_emplace(LOffs.first, Entry{LOffs.second, Parent});
2111 // We catch the case where LOffs is in a file included by ROffs and
2112 // quit early. The other way round unfortunately remains suboptimal.
2113 if (LOffs.first == ROffs.first)
2114 break;
2115 Parent = LOffs.first;
2116 } while (!MoveUpIncludeHierarchy(LOffs, *this));
2117
2118 Parent = FileID();
2119 do {
2120 auto I = LChain.find(ROffs.first);
2121 if (I != LChain.end()) {
2122 // Compare the locations within the common file and cache them.
2123 LOffs.first = I->first;
2124 LOffs.second = I->second.Offset;
2125 // The relative order of LParent and RParent is a tiebreaker when
2126 // - locs expand to the same location (occurs in macro arg expansion)
2127 // - one loc is a parent of the other (we consider the parent as "first")
2128 // For the parent to be first, the invalid file ID must compare smaller.
2129 // However loaded FileIDs are <0, so we perform *unsigned* comparison!
2130 // This changes the relative order of local vs loaded FileIDs, but it
2131 // doesn't matter as these are never mixed in macro expansion.
2132 unsigned LParent = I->second.ParentFID.ID;
2133 unsigned RParent = Parent.ID;
2134 assert(((LOffs.second != ROffs.second) ||
2135 (LParent == 0 || RParent == 0) ||
2136 isInSameSLocAddrSpace(getComposedLoc(I->second.ParentFID, 0),
2137 getComposedLoc(Parent, 0), nullptr)) &&
2138 "Mixed local/loaded FileIDs with same include location?");
2139 IsBeforeInTUCache.setCommonLoc(LOffs.first, LOffs.second, ROffs.second,
2140 LParent < RParent);
2141 return std::make_pair(
2142 true, IsBeforeInTUCache.getCachedResult(LOffs.second, ROffs.second));
2143 }
2144 Parent = ROffs.first;
2145 } while (!MoveUpIncludeHierarchy(ROffs, *this));
2146
2147 // If we found no match, we're not in the same TU.
2148 // We don't cache this, but it is rare.
2149 return std::make_pair(false, false);
2150}
2151
2153 llvm::errs() << "\n*** Source Manager Stats:\n";
2154 llvm::errs() << FileInfos.size() << " files mapped, " << MemBufferInfos.size()
2155 << " mem buffers mapped.\n";
2156 llvm::errs() << LocalSLocEntryTable.size() << " local SLocEntry's allocated ("
2157 << llvm::capacity_in_bytes(LocalSLocEntryTable)
2158 << " bytes of capacity), "
2159 << NextLocalOffset << "B of Sloc address space used.\n";
2160 llvm::errs() << LoadedSLocEntryTable.size()
2161 << " loaded SLocEntries allocated, "
2162 << MaxLoadedOffset - CurrentLoadedOffset
2163 << "B of Sloc address space used.\n";
2164
2165 unsigned NumLineNumsComputed = 0;
2166 unsigned NumFileBytesMapped = 0;
2167 for (fileinfo_iterator I = fileinfo_begin(), E = fileinfo_end(); I != E; ++I){
2168 NumLineNumsComputed += bool(I->second->SourceLineCache);
2169 NumFileBytesMapped += I->second->getSizeBytesMapped();
2170 }
2171 unsigned NumMacroArgsComputed = MacroArgsCacheMap.size();
2172
2173 llvm::errs() << NumFileBytesMapped << " bytes of files mapped, "
2174 << NumLineNumsComputed << " files with line #'s computed, "
2175 << NumMacroArgsComputed << " files with macro args computed.\n";
2176 llvm::errs() << "FileID scans: " << NumLinearScans << " linear, "
2177 << NumBinaryProbes << " binary.\n";
2178}
2179
2180LLVM_DUMP_METHOD void SourceManager::dump() const {
2181 llvm::raw_ostream &out = llvm::errs();
2182
2183 auto DumpSLocEntry = [&](int ID, const SrcMgr::SLocEntry &Entry,
2184 std::optional<SourceLocation::UIntTy> NextStart) {
2185 out << "SLocEntry <FileID " << ID << "> " << (Entry.isFile() ? "file" : "expansion")
2186 << " <SourceLocation " << Entry.getOffset() << ":";
2187 if (NextStart)
2188 out << *NextStart << ">\n";
2189 else
2190 out << "???\?>\n";
2191 if (Entry.isFile()) {
2192 auto &FI = Entry.getFile();
2193 if (FI.NumCreatedFIDs)
2194 out << " covers <FileID " << ID << ":" << int(ID + FI.NumCreatedFIDs)
2195 << ">\n";
2196 if (FI.getIncludeLoc().isValid())
2197 out << " included from " << FI.getIncludeLoc().getOffset() << "\n";
2198 auto &CC = FI.getContentCache();
2199 out << " for " << (CC.OrigEntry ? CC.OrigEntry->getName() : "<none>")
2200 << "\n";
2201 if (CC.BufferOverridden)
2202 out << " contents overridden\n";
2203 if (CC.ContentsEntry != CC.OrigEntry) {
2204 out << " contents from "
2205 << (CC.ContentsEntry ? CC.ContentsEntry->getName() : "<none>")
2206 << "\n";
2207 }
2208 } else {
2209 auto &EI = Entry.getExpansion();
2210 out << " spelling from " << EI.getSpellingLoc().getOffset() << "\n";
2211 out << " macro " << (EI.isMacroArgExpansion() ? "arg" : "body")
2212 << " range <" << EI.getExpansionLocStart().getOffset() << ":"
2213 << EI.getExpansionLocEnd().getOffset() << ">\n";
2214 }
2215 };
2216
2217 // Dump local SLocEntries.
2218 for (unsigned ID = 0, NumIDs = LocalSLocEntryTable.size(); ID != NumIDs; ++ID) {
2219 DumpSLocEntry(ID, LocalSLocEntryTable[ID],
2220 ID == NumIDs - 1 ? NextLocalOffset
2221 : LocalSLocEntryTable[ID + 1].getOffset());
2222 }
2223 // Dump loaded SLocEntries.
2224 std::optional<SourceLocation::UIntTy> NextStart;
2225 for (unsigned Index = 0; Index != LoadedSLocEntryTable.size(); ++Index) {
2226 int ID = -(int)Index - 2;
2227 if (SLocEntryLoaded[Index]) {
2228 DumpSLocEntry(ID, LoadedSLocEntryTable[Index], NextStart);
2229 NextStart = LoadedSLocEntryTable[Index].getOffset();
2230 } else {
2231 NextStart = std::nullopt;
2232 }
2233 }
2234}
2235
2237 DiagnosticsEngine &Diag, std::optional<unsigned> MaxNotes) const {
2238 struct Info {
2239 // A location where this file was entered.
2240 SourceLocation Loc;
2241 // Number of times this FileEntry was entered.
2242 unsigned Inclusions = 0;
2243 // Size usage from the file itself.
2244 uint64_t DirectSize = 0;
2245 // Total size usage from the file and its macro expansions.
2246 uint64_t TotalSize = 0;
2247 };
2248 using UsageMap = llvm::MapVector<const FileEntry*, Info>;
2249
2250 UsageMap Usage;
2251 uint64_t CountedSize = 0;
2252
2253 auto AddUsageForFileID = [&](FileID ID) {
2254 // The +1 here is because getFileIDSize doesn't include the extra byte for
2255 // the one-past-the-end location.
2256 unsigned Size = getFileIDSize(ID) + 1;
2257
2258 // Find the file that used this address space, either directly or by
2259 // macro expansion.
2260 SourceLocation FileStart = getFileLoc(getComposedLoc(ID, 0));
2261 FileID FileLocID = getFileID(FileStart);
2262 const FileEntry *Entry = getFileEntryForID(FileLocID);
2263
2264 Info &EntryInfo = Usage[Entry];
2265 if (EntryInfo.Loc.isInvalid())
2266 EntryInfo.Loc = FileStart;
2267 if (ID == FileLocID) {
2268 ++EntryInfo.Inclusions;
2269 EntryInfo.DirectSize += Size;
2270 }
2271 EntryInfo.TotalSize += Size;
2272 CountedSize += Size;
2273 };
2274
2275 // Loaded SLocEntries have indexes counting downwards from -2.
2276 for (size_t Index = 0; Index != LoadedSLocEntryTable.size(); ++Index) {
2277 AddUsageForFileID(FileID::get(-2 - Index));
2278 }
2279 // Local SLocEntries have indexes counting upwards from 0.
2280 for (size_t Index = 0; Index != LocalSLocEntryTable.size(); ++Index) {
2281 AddUsageForFileID(FileID::get(Index));
2282 }
2283
2284 // Sort the usage by size from largest to smallest. Break ties by raw source
2285 // location.
2286 auto SortedUsage = Usage.takeVector();
2287 auto Cmp = [](const UsageMap::value_type &A, const UsageMap::value_type &B) {
2288 return A.second.TotalSize > B.second.TotalSize ||
2289 (A.second.TotalSize == B.second.TotalSize &&
2290 A.second.Loc < B.second.Loc);
2291 };
2292 auto SortedEnd = SortedUsage.end();
2293 if (MaxNotes && SortedUsage.size() > *MaxNotes) {
2294 SortedEnd = SortedUsage.begin() + *MaxNotes;
2295 std::nth_element(SortedUsage.begin(), SortedEnd, SortedUsage.end(), Cmp);
2296 }
2297 std::sort(SortedUsage.begin(), SortedEnd, Cmp);
2298
2299 // Produce note on sloc address space usage total.
2300 uint64_t LocalUsage = NextLocalOffset;
2301 uint64_t LoadedUsage = MaxLoadedOffset - CurrentLoadedOffset;
2302 int UsagePercent = static_cast<int>(100.0 * double(LocalUsage + LoadedUsage) /
2303 MaxLoadedOffset);
2304 Diag.Report(SourceLocation(), diag::note_total_sloc_usage)
2305 << LocalUsage << LoadedUsage << (LocalUsage + LoadedUsage) << UsagePercent;
2306
2307 // Produce notes on sloc address space usage for each file with a high usage.
2308 uint64_t ReportedSize = 0;
2309 for (auto &[Entry, FileInfo] :
2310 llvm::make_range(SortedUsage.begin(), SortedEnd)) {
2311 Diag.Report(FileInfo.Loc, diag::note_file_sloc_usage)
2312 << FileInfo.Inclusions << FileInfo.DirectSize
2313 << (FileInfo.TotalSize - FileInfo.DirectSize);
2314 ReportedSize += FileInfo.TotalSize;
2315 }
2316
2317 // Describe any remaining usage not reported in the per-file usage.
2318 if (ReportedSize != CountedSize) {
2319 Diag.Report(SourceLocation(), diag::note_file_misc_sloc_usage)
2320 << (SortedUsage.end() - SortedEnd) << CountedSize - ReportedSize;
2321 }
2322}
2323
2325
2326/// Return the amount of memory used by memory buffers, breaking down
2327/// by heap-backed versus mmap'ed memory.
2329 size_t malloc_bytes = 0;
2330 size_t mmap_bytes = 0;
2331
2332 for (unsigned i = 0, e = MemBufferInfos.size(); i != e; ++i)
2333 if (size_t sized_mapped = MemBufferInfos[i]->getSizeBytesMapped())
2334 switch (MemBufferInfos[i]->getMemoryBufferKind()) {
2335 case llvm::MemoryBuffer::MemoryBuffer_MMap:
2336 mmap_bytes += sized_mapped;
2337 break;
2338 case llvm::MemoryBuffer::MemoryBuffer_Malloc:
2339 malloc_bytes += sized_mapped;
2340 break;
2341 }
2342
2343 return MemoryBufferSizes(malloc_bytes, mmap_bytes);
2344}
2345
2347 size_t size = llvm::capacity_in_bytes(MemBufferInfos)
2348 + llvm::capacity_in_bytes(LocalSLocEntryTable)
2349 + llvm::capacity_in_bytes(LoadedSLocEntryTable)
2350 + llvm::capacity_in_bytes(SLocEntryLoaded)
2351 + llvm::capacity_in_bytes(FileInfos);
2352
2353 if (OverriddenFilesInfo)
2354 size += llvm::capacity_in_bytes(OverriddenFilesInfo->OverriddenFiles);
2355
2356 return size;
2357}
2358
2360 StringRef Content) {
2361 // This is referenced by `FileMgr` and will be released by `FileMgr` when it
2362 // is deleted.
2364 new llvm::vfs::InMemoryFileSystem);
2365 InMemoryFileSystem->addFile(
2366 FileName, 0,
2367 llvm::MemoryBuffer::getMemBuffer(Content, FileName,
2368 /*RequiresNullTerminator=*/false));
2369 // This is passed to `SM` as reference, so the pointer has to be referenced
2370 // in `Environment` so that `FileMgr` can out-live this function scope.
2371 FileMgr =
2372 std::make_unique<FileManager>(FileSystemOptions(), InMemoryFileSystem);
2373 // This is passed to `SM` as reference, so the pointer has to be referenced
2374 // by `Environment` due to the same reason above.
2375 Diagnostics = std::make_unique<DiagnosticsEngine>(
2377 new DiagnosticOptions);
2378 SourceMgr = std::make_unique<SourceManager>(*Diagnostics, *FileMgr);
2379 FileID ID = SourceMgr->createFileID(*FileMgr->getFile(FileName),
2381 assert(ID.isValid());
2382 SourceMgr->setMainFileID(ID);
2383}
NodeId Parent
Definition: ASTDiff.cpp:191
#define SM(sm)
Definition: Cuda.cpp:80
Defines the Diagnostic-related interfaces.
Defines the clang::FileManager interface and associated types.
unsigned Offset
Definition: Format.cpp:2938
StringRef Filename
Definition: Format.cpp:2936
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
Defines the clang::SourceLocation class and associated facilities.
Defines implementation details of the clang::SourceManager class.
static constexpr T likelyhasbetween(T x, unsigned char m, unsigned char n)
static bool isInvalid(LocType Loc, bool *Invalid)
static bool MoveUpIncludeHierarchy(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...
Defines the SourceManager interface.
TypePropertyCache< Private > Cache
Definition: Type.cpp:4166
__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:1542
void setSourceManager(SourceManager *SrcMgr)
Definition: Diagnostic.h:584
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:447
off_t getSize() const
Definition: FileEntry.h:435
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:385
FileEntryRef getLastRef() const
Definition: FileEntry.h:417
unsigned getUID() const
Definition: FileEntry.h:421
off_t getSize() const
Definition: FileEntry.h:420
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...
void setFileIsTransient(const FileEntry *SourceFile)
Specify that a file is transient.
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...
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.
void overrideFileContents(const FileEntry *SourceFile, const llvm::MemoryBufferRef &Buffer)
Override the contents of the given source file by providing an already-allocated buffer.
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...
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.
const SrcMgr::SLocEntry & getLoadedSLocEntry(unsigned Index, bool *Invalid=nullptr) const
Get a loaded SLocEntry. This is exposed for indexing.
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...
FileID getOrCreateFileID(const FileEntry *SourceFile, SrcMgr::CharacteristicKind FileCharacter)
Get the FileID for SourceFile if it exists.
unsigned getSpellingLineNumber(SourceLocation Loc, bool *Invalid=nullptr) const
FileID createFileID(const FileEntry *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...
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.
std::optional< llvm::MemoryBufferRef > getMemoryBufferForFileOrNone(const FileEntry *File)
Retrieve the memory buffer associated with the given file.
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.
llvm::DenseMap< const FileEntry *, SrcMgr::ContentCache * >::const_iterator fileinfo_iterator
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.
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.
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...
OptionalFileEntryRefDegradesToFileEntryPtr OrigEntry
Reference to the file entry representing this ContentCache.
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.
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:4120
CharacteristicKind
Indicates whether a file or directory holds normal user code, system code, or system code which is im...
Definition: SourceManager.h:80
bool isSystem(CharacteristicKind CK)
Determine whether a file / directory characteristic is for system code.
Definition: SourceManager.h:89
@ C
Languages that the frontend can parse and compile.
#define bool
Definition: stdbool.h:20
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)