brintos

brintos / llvm-project-archived public Read only

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