1327952Sdim//===- SourceManager.cpp - Track and cache source files -------------------===// 2193326Sed// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6193326Sed// 7193326Sed//===----------------------------------------------------------------------===// 8193326Sed// 9193326Sed// This file implements the SourceManager interface. 10193326Sed// 11193326Sed//===----------------------------------------------------------------------===// 12193326Sed 13193326Sed#include "clang/Basic/SourceManager.h" 14205219Srdivacky#include "clang/Basic/Diagnostic.h" 15193326Sed#include "clang/Basic/FileManager.h" 16327952Sdim#include "clang/Basic/LLVM.h" 17327952Sdim#include "clang/Basic/SourceLocation.h" 18249423Sdim#include "clang/Basic/SourceManagerInternals.h" 19327952Sdim#include "llvm/ADT/DenseMap.h" 20218893Sdim#include "llvm/ADT/Optional.h" 21327952Sdim#include "llvm/ADT/None.h" 22226633Sdim#include "llvm/ADT/STLExtras.h" 23327952Sdim#include "llvm/ADT/SmallVector.h" 24249423Sdim#include "llvm/ADT/StringSwitch.h" 25327952Sdim#include "llvm/ADT/StringRef.h" 26327952Sdim#include "llvm/Support/Allocator.h" 27249423Sdim#include "llvm/Support/Capacity.h" 28193326Sed#include "llvm/Support/Compiler.h" 29327952Sdim#include "llvm/Support/ErrorHandling.h" 30327952Sdim#include "llvm/Support/FileSystem.h" 31327952Sdim#include "llvm/Support/MathExtras.h" 32193326Sed#include "llvm/Support/MemoryBuffer.h" 33249423Sdim#include "llvm/Support/Path.h" 34198092Srdivacky#include "llvm/Support/raw_ostream.h" 35193326Sed#include <algorithm> 36327952Sdim#include <cassert> 37327952Sdim#include <cstddef> 38327952Sdim#include <cstdint> 39327952Sdim#include <memory> 40327952Sdim#include <tuple> 41327952Sdim#include <utility> 42327952Sdim#include <vector> 43205219Srdivacky 44193326Sedusing namespace clang; 45193326Sedusing namespace SrcMgr; 46193326Sedusing llvm::MemoryBuffer; 47193326Sed 48193326Sed//===----------------------------------------------------------------------===// 49193326Sed// SourceManager Helper Classes 50193326Sed//===----------------------------------------------------------------------===// 51193326Sed 52193326SedContentCache::~ContentCache() { 53212904Sdim if (shouldFreeBuffer()) 54212904Sdim delete Buffer.getPointer(); 55193326Sed} 56193326Sed 57226633Sdim/// getSizeBytesMapped - Returns the number of bytes actually mapped for this 58226633Sdim/// ContentCache. This can be 0 if the MemBuffer was not actually expanded. 59193326Sedunsigned ContentCache::getSizeBytesMapped() const { 60205408Srdivacky return Buffer.getPointer() ? Buffer.getPointer()->getBufferSize() : 0; 61193326Sed} 62193326Sed 63221345Sdim/// Returns the kind of memory used to back the memory buffer for 64221345Sdim/// this content cache. This is used for performance analysis. 65221345Sdimllvm::MemoryBuffer::BufferKind ContentCache::getMemoryBufferKind() const { 66221345Sdim assert(Buffer.getPointer()); 67221345Sdim 68221345Sdim // Should be unreachable, but keep for sanity. 69221345Sdim if (!Buffer.getPointer()) 70221345Sdim return llvm::MemoryBuffer::MemoryBuffer_Malloc; 71276479Sdim 72353358Sdim const llvm::MemoryBuffer *buf = Buffer.getPointer(); 73221345Sdim return buf->getBufferKind(); 74221345Sdim} 75221345Sdim 76193326Sed/// getSize - Returns the size of the content encapsulated by this ContentCache. 77193326Sed/// This can be the size of the source file or the size of an arbitrary 78193326Sed/// scratch buffer. If the ContentCache encapsulates a source file, that 79200583Srdivacky/// file is not lazily brought in from disk to satisfy this query. 80193326Sedunsigned ContentCache::getSize() const { 81205408Srdivacky return Buffer.getPointer() ? (unsigned) Buffer.getPointer()->getBufferSize() 82221345Sdim : (unsigned) ContentsEntry->getSize(); 83193326Sed} 84193326Sed 85353358Sdimvoid ContentCache::replaceBuffer(const llvm::MemoryBuffer *B, bool DoNotFree) { 86239462Sdim if (B && B == Buffer.getPointer()) { 87234353Sdim assert(0 && "Replacing with the same buffer"); 88234353Sdim Buffer.setInt(DoNotFree? DoNotFreeFlag : 0); 89234353Sdim return; 90234353Sdim } 91321369Sdim 92212904Sdim if (shouldFreeBuffer()) 93212904Sdim delete Buffer.getPointer(); 94205408Srdivacky Buffer.setPointer(B); 95321369Sdim Buffer.setInt((B && DoNotFree) ? DoNotFreeFlag : 0); 96200583Srdivacky} 97200583Srdivacky 98360784Sdimconst char *ContentCache::getInvalidBOM(StringRef BufStr) { 99360784Sdim // If the buffer is valid, check to see if it has a UTF Byte Order Mark 100360784Sdim // (BOM). We only support UTF-8 with and without a BOM right now. See 101360784Sdim // http://en.wikipedia.org/wiki/Byte_order_mark for more information. 102360784Sdim const char *InvalidBOM = 103360784Sdim llvm::StringSwitch<const char *>(BufStr) 104360784Sdim .StartsWith(llvm::StringLiteral::withInnerNUL("\x00\x00\xFE\xFF"), 105360784Sdim "UTF-32 (BE)") 106360784Sdim .StartsWith(llvm::StringLiteral::withInnerNUL("\xFF\xFE\x00\x00"), 107360784Sdim "UTF-32 (LE)") 108360784Sdim .StartsWith("\xFE\xFF", "UTF-16 (BE)") 109360784Sdim .StartsWith("\xFF\xFE", "UTF-16 (LE)") 110360784Sdim .StartsWith("\x2B\x2F\x76", "UTF-7") 111360784Sdim .StartsWith("\xF7\x64\x4C", "UTF-1") 112360784Sdim .StartsWith("\xDD\x73\x66\x73", "UTF-EBCDIC") 113360784Sdim .StartsWith("\x0E\xFE\xFF", "SCSU") 114360784Sdim .StartsWith("\xFB\xEE\x28", "BOCU-1") 115360784Sdim .StartsWith("\x84\x31\x95\x33", "GB-18030") 116360784Sdim .Default(nullptr); 117360784Sdim 118360784Sdim return InvalidBOM; 119360784Sdim} 120360784Sdim 121353358Sdimconst llvm::MemoryBuffer *ContentCache::getBuffer(DiagnosticsEngine &Diag, 122360784Sdim FileManager &FM, 123353358Sdim SourceLocation Loc, 124353358Sdim bool *Invalid) const { 125218893Sdim // Lazily create the Buffer for ContentCaches that wrap files. If we already 126221345Sdim // computed it, just return what we have. 127276479Sdim if (Buffer.getPointer() || !ContentsEntry) { 128218893Sdim if (Invalid) 129218893Sdim *Invalid = isBufferInvalid(); 130341825Sdim 131218893Sdim return Buffer.getPointer(); 132341825Sdim } 133206084Srdivacky 134353358Sdim // Check that the file's size fits in an 'unsigned' (with room for a 135353358Sdim // past-the-end value). This is deeply regrettable, but various parts of 136353358Sdim // Clang (including elsewhere in this file!) use 'unsigned' to represent file 137353358Sdim // offsets, line numbers, string literal lengths, and so on, and fail 138353358Sdim // miserably on large source files. 139353358Sdim if ((uint64_t)ContentsEntry->getSize() >= 140353358Sdim std::numeric_limits<unsigned>::max()) { 141353358Sdim // We can't make a memory buffer of the required size, so just make a small 142353358Sdim // one. We should never hit a situation where we've already parsed to a 143353358Sdim // later offset of the file, so it shouldn't matter that the buffer is 144353358Sdim // smaller than the file. 145353358Sdim Buffer.setPointer( 146353358Sdim llvm::MemoryBuffer::getMemBuffer("", ContentsEntry->getName()) 147353358Sdim .release()); 148353358Sdim if (Diag.isDiagnosticInFlight()) 149353358Sdim Diag.SetDelayedDiagnostic(diag::err_file_too_large, 150353358Sdim ContentsEntry->getName()); 151353358Sdim else 152353358Sdim Diag.Report(Loc, diag::err_file_too_large) 153353358Sdim << ContentsEntry->getName(); 154353358Sdim 155353358Sdim Buffer.setInt(Buffer.getInt() | InvalidFlag); 156353358Sdim if (Invalid) *Invalid = true; 157353358Sdim return Buffer.getPointer(); 158353358Sdim } 159353358Sdim 160360784Sdim auto BufferOrError = FM.getBufferForFile(ContentsEntry, IsFileVolatile); 161206084Srdivacky 162218893Sdim // If we were unable to open the file, then we are in an inconsistent 163218893Sdim // situation where the content cache referenced a file which no longer 164218893Sdim // exists. Most likely, we were using a stat cache with an invalid entry but 165218893Sdim // the file could also have been removed during processing. Since we can't 166218893Sdim // really deal with this situation, just create an empty buffer. 167218893Sdim // 168218893Sdim // FIXME: This is definitely not ideal, but our immediate clients can't 169218893Sdim // currently handle returning a null entry here. Ideally we should detect 170218893Sdim // that we are in an inconsistent situation and error out as quickly as 171218893Sdim // possible. 172280031Sdim if (!BufferOrError) { 173280031Sdim StringRef FillStr("<<<MISSING SOURCE FILE>>>\n"); 174327952Sdim auto BackupBuffer = llvm::WritableMemoryBuffer::getNewUninitMemBuffer( 175327952Sdim ContentsEntry->getSize(), "<invalid>"); 176327952Sdim char *Ptr = BackupBuffer->getBufferStart(); 177221345Sdim for (unsigned i = 0, e = ContentsEntry->getSize(); i != e; ++i) 178218893Sdim Ptr[i] = FillStr[i % FillStr.size()]; 179327952Sdim Buffer.setPointer(BackupBuffer.release()); 180207619Srdivacky 181218893Sdim if (Diag.isDiagnosticInFlight()) 182280031Sdim Diag.SetDelayedDiagnostic(diag::err_cannot_open_file, 183280031Sdim ContentsEntry->getName(), 184280031Sdim BufferOrError.getError().message()); 185280031Sdim else 186218893Sdim Diag.Report(Loc, diag::err_cannot_open_file) 187280031Sdim << ContentsEntry->getName() << BufferOrError.getError().message(); 188206084Srdivacky 189218893Sdim Buffer.setInt(Buffer.getInt() | InvalidFlag); 190341825Sdim 191218893Sdim if (Invalid) *Invalid = true; 192218893Sdim return Buffer.getPointer(); 193198092Srdivacky } 194280031Sdim 195280031Sdim Buffer.setPointer(BufferOrError->release()); 196280031Sdim 197218893Sdim // Check that the file's size is the same as in the file entry (which may 198218893Sdim // have come from a stat cache). 199221345Sdim if (getRawBuffer()->getBufferSize() != (size_t)ContentsEntry->getSize()) { 200218893Sdim if (Diag.isDiagnosticInFlight()) 201218893Sdim Diag.SetDelayedDiagnostic(diag::err_file_modified, 202221345Sdim ContentsEntry->getName()); 203218893Sdim else 204218893Sdim Diag.Report(Loc, diag::err_file_modified) 205221345Sdim << ContentsEntry->getName(); 206218893Sdim 207218893Sdim Buffer.setInt(Buffer.getInt() | InvalidFlag); 208218893Sdim if (Invalid) *Invalid = true; 209218893Sdim return Buffer.getPointer(); 210218893Sdim } 211221345Sdim 212218893Sdim // If the buffer is valid, check to see if it has a UTF Byte Order Mark 213221345Sdim // (BOM). We only support UTF-8 with and without a BOM right now. See 214218893Sdim // http://en.wikipedia.org/wiki/Byte_order_mark for more information. 215226633Sdim StringRef BufStr = Buffer.getPointer()->getBuffer(); 216360784Sdim const char *InvalidBOM = getInvalidBOM(BufStr); 217218893Sdim 218221345Sdim if (InvalidBOM) { 219218893Sdim Diag.Report(Loc, diag::err_unsupported_bom) 220221345Sdim << InvalidBOM << ContentsEntry->getName(); 221218893Sdim Buffer.setInt(Buffer.getInt() | InvalidFlag); 222218893Sdim } 223341825Sdim 224205408Srdivacky if (Invalid) 225212904Sdim *Invalid = isBufferInvalid(); 226341825Sdim 227205408Srdivacky return Buffer.getPointer(); 228198092Srdivacky} 229198092Srdivacky 230226633Sdimunsigned LineTableInfo::getLineTableFilenameID(StringRef Name) { 231344779Sdim auto IterBool = FilenameIDs.try_emplace(Name, FilenamesByID.size()); 232280031Sdim if (IterBool.second) 233280031Sdim FilenamesByID.push_back(&*IterBool.first); 234280031Sdim return IterBool.first->second; 235193326Sed} 236193326Sed 237321369Sdim/// Add a line note to the line table that indicates that there is a \#line or 238321369Sdim/// GNU line marker at the specified FID/Offset location which changes the 239321369Sdim/// presumed location to LineNo/FilenameID. If EntryExit is 0, then this doesn't 240321369Sdim/// change the presumed \#include stack. If it is 1, this is a file entry, if 241321369Sdim/// it is 2 then this is a file exit. FileKind specifies whether this is a 242321369Sdim/// system header or extern C system header. 243321369Sdimvoid LineTableInfo::AddLineNote(FileID FID, unsigned Offset, unsigned LineNo, 244321369Sdim int FilenameID, unsigned EntryExit, 245321369Sdim SrcMgr::CharacteristicKind FileKind) { 246193326Sed std::vector<LineEntry> &Entries = LineEntries[FID]; 247198092Srdivacky 248321369Sdim // An unspecified FilenameID means use the last filename if available, or the 249321369Sdim // main source file otherwise. 250321369Sdim if (FilenameID == -1 && !Entries.empty()) 251321369Sdim FilenameID = Entries.back().FilenameID; 252198092Srdivacky 253193326Sed assert((Entries.empty() || Entries.back().FileOffset < Offset) && 254193326Sed "Adding line entries out of order!"); 255193326Sed 256193326Sed unsigned IncludeOffset = 0; 257193326Sed if (EntryExit == 0) { // No #include stack change. 258193326Sed IncludeOffset = Entries.empty() ? 0 : Entries.back().IncludeOffset; 259193326Sed } else if (EntryExit == 1) { 260193326Sed IncludeOffset = Offset-1; 261193326Sed } else if (EntryExit == 2) { 262193326Sed assert(!Entries.empty() && Entries.back().IncludeOffset && 263193326Sed "PPDirectives should have caught case when popping empty include stack"); 264198092Srdivacky 265193326Sed // Get the include loc of the last entries' include loc as our include loc. 266193326Sed IncludeOffset = 0; 267193326Sed if (const LineEntry *PrevEntry = 268193326Sed FindNearestLineEntry(FID, Entries.back().IncludeOffset)) 269193326Sed IncludeOffset = PrevEntry->IncludeOffset; 270193326Sed } 271198092Srdivacky 272193326Sed Entries.push_back(LineEntry::get(Offset, LineNo, FilenameID, FileKind, 273193326Sed IncludeOffset)); 274193326Sed} 275193326Sed 276193326Sed/// FindNearestLineEntry - Find the line entry nearest to FID that is before 277193326Sed/// it. If there is no line entry before Offset in FID, return null. 278239462Sdimconst LineEntry *LineTableInfo::FindNearestLineEntry(FileID FID, 279193326Sed unsigned Offset) { 280193326Sed const std::vector<LineEntry> &Entries = LineEntries[FID]; 281193326Sed assert(!Entries.empty() && "No #line entries for this FID after all!"); 282193326Sed 283193326Sed // It is very common for the query to be after the last #line, check this 284193326Sed // first. 285193326Sed if (Entries.back().FileOffset <= Offset) 286193326Sed return &Entries.back(); 287193326Sed 288193326Sed // Do a binary search to find the maximal element that is still before Offset. 289353358Sdim std::vector<LineEntry>::const_iterator I = llvm::upper_bound(Entries, Offset); 290353358Sdim if (I == Entries.begin()) 291353358Sdim return nullptr; 292193326Sed return &*--I; 293193326Sed} 294193326Sed 295341825Sdim/// Add a new line entry that has already been encoded into 296193326Sed/// the internal representation of the line table. 297239462Sdimvoid LineTableInfo::AddEntry(FileID FID, 298193326Sed const std::vector<LineEntry> &Entries) { 299193326Sed LineEntries[FID] = Entries; 300193326Sed} 301193326Sed 302193326Sed/// getLineTableFilenameID - Return the uniqued ID for the specified filename. 303226633Sdimunsigned SourceManager::getLineTableFilenameID(StringRef Name) { 304296417Sdim return getLineTable().getLineTableFilenameID(Name); 305193326Sed} 306193326Sed 307193326Sed/// AddLineNote - Add a line note to the line table for the FileID and offset 308193326Sed/// specified by Loc. If FilenameID is -1, it is considered to be 309193326Sed/// unspecified. 310193326Sedvoid SourceManager::AddLineNote(SourceLocation Loc, unsigned LineNo, 311321369Sdim int FilenameID, bool IsFileEntry, 312321369Sdim bool IsFileExit, 313321369Sdim SrcMgr::CharacteristicKind FileKind) { 314226633Sdim std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(Loc); 315198092Srdivacky 316221345Sdim bool Invalid = false; 317221345Sdim const SLocEntry &Entry = getSLocEntry(LocInfo.first, &Invalid); 318221345Sdim if (!Entry.isFile() || Invalid) 319221345Sdim return; 320193326Sed 321221345Sdim const SrcMgr::FileInfo &FileInfo = Entry.getFile(); 322221345Sdim 323193326Sed // Remember that this file has #line directives now if it doesn't already. 324193326Sed const_cast<SrcMgr::FileInfo&>(FileInfo).setHasLineDirectives(); 325198092Srdivacky 326296417Sdim (void) getLineTable(); 327198092Srdivacky 328193326Sed unsigned EntryExit = 0; 329193326Sed if (IsFileEntry) 330193326Sed EntryExit = 1; 331193326Sed else if (IsFileExit) 332193326Sed EntryExit = 2; 333198092Srdivacky 334239462Sdim LineTable->AddLineNote(LocInfo.first, LocInfo.second, LineNo, FilenameID, 335193326Sed EntryExit, FileKind); 336193326Sed} 337193326Sed 338193326SedLineTableInfo &SourceManager::getLineTable() { 339276479Sdim if (!LineTable) 340353358Sdim LineTable.reset(new LineTableInfo()); 341193326Sed return *LineTable; 342193326Sed} 343193326Sed 344193326Sed//===----------------------------------------------------------------------===// 345193326Sed// Private 'Create' methods. 346193326Sed//===----------------------------------------------------------------------===// 347193326Sed 348239462SdimSourceManager::SourceManager(DiagnosticsEngine &Diag, FileManager &FileMgr, 349239462Sdim bool UserFilesAreVolatile) 350327952Sdim : Diag(Diag), FileMgr(FileMgr), UserFilesAreVolatile(UserFilesAreVolatile) { 351218893Sdim clearIDTables(); 352218893Sdim Diag.setSourceManager(this); 353218893Sdim} 354218893Sdim 355193326SedSourceManager::~SourceManager() { 356193326Sed // Delete FileEntry objects corresponding to content caches. Since the actual 357193326Sed // content cache objects are bump pointer allocated, we just have to run the 358193326Sed // dtors, but we call the deallocate method for completeness. 359193326Sed for (unsigned i = 0, e = MemBufferInfos.size(); i != e; ++i) { 360234353Sdim if (MemBufferInfos[i]) { 361234353Sdim MemBufferInfos[i]->~ContentCache(); 362234353Sdim ContentCacheAlloc.Deallocate(MemBufferInfos[i]); 363234353Sdim } 364193326Sed } 365193326Sed for (llvm::DenseMap<const FileEntry*, SrcMgr::ContentCache*>::iterator 366193326Sed I = FileInfos.begin(), E = FileInfos.end(); I != E; ++I) { 367234353Sdim if (I->second) { 368234353Sdim I->second->~ContentCache(); 369234353Sdim ContentCacheAlloc.Deallocate(I->second); 370234353Sdim } 371193326Sed } 372193326Sed} 373193326Sed 374193326Sedvoid SourceManager::clearIDTables() { 375193326Sed MainFileID = FileID(); 376226633Sdim LocalSLocEntryTable.clear(); 377226633Sdim LoadedSLocEntryTable.clear(); 378226633Sdim SLocEntryLoaded.clear(); 379193326Sed LastLineNoFileIDQuery = FileID(); 380276479Sdim LastLineNoContentCache = nullptr; 381193326Sed LastFileIDLookup = FileID(); 382198092Srdivacky 383193326Sed if (LineTable) 384193326Sed LineTable->clear(); 385198092Srdivacky 386226633Sdim // Use up FileID #0 as an invalid expansion. 387226633Sdim NextLocalOffset = 0; 388226633Sdim CurrentLoadedOffset = MaxLoadedOffset; 389327952Sdim createExpansionLoc(SourceLocation(), SourceLocation(), SourceLocation(), 1); 390193326Sed} 391193326Sed 392321369Sdimvoid SourceManager::initializeForReplay(const SourceManager &Old) { 393321369Sdim assert(MainFileID.isInvalid() && "expected uninitialized SourceManager"); 394321369Sdim 395321369Sdim auto CloneContentCache = [&](const ContentCache *Cache) -> ContentCache * { 396321369Sdim auto *Clone = new (ContentCacheAlloc.Allocate<ContentCache>()) ContentCache; 397321369Sdim Clone->OrigEntry = Cache->OrigEntry; 398321369Sdim Clone->ContentsEntry = Cache->ContentsEntry; 399321369Sdim Clone->BufferOverridden = Cache->BufferOverridden; 400360784Sdim Clone->IsFileVolatile = Cache->IsFileVolatile; 401321369Sdim Clone->IsTransient = Cache->IsTransient; 402321369Sdim Clone->replaceBuffer(Cache->getRawBuffer(), /*DoNotFree*/true); 403321369Sdim return Clone; 404321369Sdim }; 405321369Sdim 406321369Sdim // Ensure all SLocEntries are loaded from the external source. 407321369Sdim for (unsigned I = 0, N = Old.LoadedSLocEntryTable.size(); I != N; ++I) 408321369Sdim if (!Old.SLocEntryLoaded[I]) 409321369Sdim Old.loadSLocEntry(I, nullptr); 410321369Sdim 411321369Sdim // Inherit any content cache data from the old source manager. 412321369Sdim for (auto &FileInfo : Old.FileInfos) { 413321369Sdim SrcMgr::ContentCache *&Slot = FileInfos[FileInfo.first]; 414321369Sdim if (Slot) 415321369Sdim continue; 416321369Sdim Slot = CloneContentCache(FileInfo.second); 417321369Sdim } 418321369Sdim} 419321369Sdim 420193326Sed/// getOrCreateContentCache - Create or return a cached ContentCache for the 421193326Sed/// specified file. 422193326Sedconst ContentCache * 423239462SdimSourceManager::getOrCreateContentCache(const FileEntry *FileEnt, 424239462Sdim bool isSystemFile) { 425193326Sed assert(FileEnt && "Didn't specify a file entry to use?"); 426198092Srdivacky 427193326Sed // Do we already have information about this file? 428193326Sed ContentCache *&Entry = FileInfos[FileEnt]; 429193326Sed if (Entry) return Entry; 430198092Srdivacky 431276479Sdim // Nope, create a new Cache entry. 432276479Sdim Entry = ContentCacheAlloc.Allocate<ContentCache>(); 433221345Sdim 434239462Sdim if (OverriddenFilesInfo) { 435239462Sdim // If the file contents are overridden with contents from another file, 436239462Sdim // pass that file to ContentCache. 437239462Sdim llvm::DenseMap<const FileEntry *, const FileEntry *>::iterator 438239462Sdim overI = OverriddenFilesInfo->OverriddenFiles.find(FileEnt); 439239462Sdim if (overI == OverriddenFilesInfo->OverriddenFiles.end()) 440239462Sdim new (Entry) ContentCache(FileEnt); 441239462Sdim else 442239462Sdim new (Entry) ContentCache(OverridenFilesKeepOriginalName ? FileEnt 443239462Sdim : overI->second, 444239462Sdim overI->second); 445239462Sdim } else { 446221345Sdim new (Entry) ContentCache(FileEnt); 447239462Sdim } 448221345Sdim 449360784Sdim Entry->IsFileVolatile = UserFilesAreVolatile && !isSystemFile; 450296417Sdim Entry->IsTransient = FilesAreTransient; 451239462Sdim 452193326Sed return Entry; 453193326Sed} 454193326Sed 455327952Sdim/// Create a new ContentCache for the specified memory buffer. 456327952Sdim/// This does no caching. 457327952Sdimconst ContentCache * 458353358SdimSourceManager::createMemBufferContentCache(const llvm::MemoryBuffer *Buffer, 459327952Sdim bool DoNotFree) { 460276479Sdim // Add a new ContentCache to the MemBufferInfos list and return it. 461276479Sdim ContentCache *Entry = ContentCacheAlloc.Allocate<ContentCache>(); 462193326Sed new (Entry) ContentCache(); 463193326Sed MemBufferInfos.push_back(Entry); 464327952Sdim Entry->replaceBuffer(Buffer, DoNotFree); 465193326Sed return Entry; 466193326Sed} 467193326Sed 468234353Sdimconst SrcMgr::SLocEntry &SourceManager::loadSLocEntry(unsigned Index, 469234353Sdim bool *Invalid) const { 470234353Sdim assert(!SLocEntryLoaded[Index]); 471234353Sdim if (ExternalSLocEntries->ReadSLocEntry(-(static_cast<int>(Index) + 2))) { 472234353Sdim if (Invalid) 473234353Sdim *Invalid = true; 474234353Sdim // If the file of the SLocEntry changed we could still have loaded it. 475234353Sdim if (!SLocEntryLoaded[Index]) { 476234353Sdim // Try to recover; create a SLocEntry so the rest of clang can handle it. 477360784Sdim LoadedSLocEntryTable[Index] = SLocEntry::get( 478360784Sdim 0, FileInfo::get(SourceLocation(), getFakeContentCacheForRecovery(), 479360784Sdim SrcMgr::C_User, "")); 480234353Sdim } 481234353Sdim } 482234353Sdim 483234353Sdim return LoadedSLocEntryTable[Index]; 484234353Sdim} 485234353Sdim 486226633Sdimstd::pair<int, unsigned> 487226633SdimSourceManager::AllocateLoadedSLocEntries(unsigned NumSLocEntries, 488226633Sdim unsigned TotalSize) { 489226633Sdim assert(ExternalSLocEntries && "Don't have an external sloc source"); 490296417Sdim // Make sure we're not about to run out of source locations. 491296417Sdim if (CurrentLoadedOffset - TotalSize < NextLocalOffset) 492296417Sdim return std::make_pair(0, 0); 493226633Sdim LoadedSLocEntryTable.resize(LoadedSLocEntryTable.size() + NumSLocEntries); 494226633Sdim SLocEntryLoaded.resize(LoadedSLocEntryTable.size()); 495226633Sdim CurrentLoadedOffset -= TotalSize; 496226633Sdim int ID = LoadedSLocEntryTable.size(); 497226633Sdim return std::make_pair(-ID - 1, CurrentLoadedOffset); 498193326Sed} 499193326Sed 500341825Sdim/// As part of recovering from missing or changed content, produce a 501221345Sdim/// fake, non-empty buffer. 502276479Sdimllvm::MemoryBuffer *SourceManager::getFakeBufferForRecovery() const { 503221345Sdim if (!FakeBufferForRecovery) 504280031Sdim FakeBufferForRecovery = 505280031Sdim llvm::MemoryBuffer::getMemBuffer("<<<INVALID BUFFER>>"); 506280031Sdim 507280031Sdim return FakeBufferForRecovery.get(); 508221345Sdim} 509193326Sed 510341825Sdim/// As part of recovering from missing or changed content, produce a 511234353Sdim/// fake content cache. 512234353Sdimconst SrcMgr::ContentCache * 513234353SdimSourceManager::getFakeContentCacheForRecovery() const { 514234353Sdim if (!FakeContentCacheForRecovery) { 515360784Sdim FakeContentCacheForRecovery = std::make_unique<SrcMgr::ContentCache>(); 516234353Sdim FakeContentCacheForRecovery->replaceBuffer(getFakeBufferForRecovery(), 517234353Sdim /*DoNotFree=*/true); 518234353Sdim } 519280031Sdim return FakeContentCacheForRecovery.get(); 520234353Sdim} 521234353Sdim 522341825Sdim/// Returns the previous in-order FileID or an invalid FileID if there 523261991Sdim/// is no previous one. 524261991SdimFileID SourceManager::getPreviousFileID(FileID FID) const { 525261991Sdim if (FID.isInvalid()) 526261991Sdim return FileID(); 527261991Sdim 528261991Sdim int ID = FID.ID; 529261991Sdim if (ID == -1) 530261991Sdim return FileID(); 531261991Sdim 532261991Sdim if (ID > 0) { 533261991Sdim if (ID-1 == 0) 534261991Sdim return FileID(); 535261991Sdim } else if (unsigned(-(ID-1) - 2) >= LoadedSLocEntryTable.size()) { 536261991Sdim return FileID(); 537261991Sdim } 538261991Sdim 539261991Sdim return FileID::get(ID-1); 540261991Sdim} 541261991Sdim 542341825Sdim/// Returns the next in-order FileID or an invalid FileID if there is 543261991Sdim/// no next one. 544261991SdimFileID SourceManager::getNextFileID(FileID FID) const { 545261991Sdim if (FID.isInvalid()) 546261991Sdim return FileID(); 547261991Sdim 548261991Sdim int ID = FID.ID; 549261991Sdim if (ID > 0) { 550261991Sdim if (unsigned(ID+1) >= local_sloc_entry_size()) 551261991Sdim return FileID(); 552261991Sdim } else if (ID+1 >= -1) { 553261991Sdim return FileID(); 554261991Sdim } 555261991Sdim 556261991Sdim return FileID::get(ID+1); 557261991Sdim} 558261991Sdim 559193326Sed//===----------------------------------------------------------------------===// 560226633Sdim// Methods to create new FileID's and macro expansions. 561193326Sed//===----------------------------------------------------------------------===// 562193326Sed 563212904Sdim/// createFileID - Create a new FileID for the specified ContentCache and 564193326Sed/// include position. This works regardless of whether the ContentCache 565193326Sed/// corresponds to a file or some other input source. 566360784SdimFileID SourceManager::createFileID(const ContentCache *File, StringRef Filename, 567193326Sed SourceLocation IncludePos, 568193326Sed SrcMgr::CharacteristicKind FileCharacter, 569226633Sdim int LoadedID, unsigned LoadedOffset) { 570226633Sdim if (LoadedID < 0) { 571226633Sdim assert(LoadedID != -1 && "Loading sentinel FileID"); 572226633Sdim unsigned Index = unsigned(-LoadedID) - 2; 573226633Sdim assert(Index < LoadedSLocEntryTable.size() && "FileID out of range"); 574226633Sdim assert(!SLocEntryLoaded[Index] && "FileID already loaded"); 575360784Sdim LoadedSLocEntryTable[Index] = SLocEntry::get( 576360784Sdim LoadedOffset, FileInfo::get(IncludePos, File, FileCharacter, Filename)); 577226633Sdim SLocEntryLoaded[Index] = true; 578226633Sdim return FileID::get(LoadedID); 579193326Sed } 580360784Sdim LocalSLocEntryTable.push_back( 581360784Sdim SLocEntry::get(NextLocalOffset, 582360784Sdim FileInfo::get(IncludePos, File, FileCharacter, Filename))); 583193326Sed unsigned FileSize = File->getSize(); 584226633Sdim assert(NextLocalOffset + FileSize + 1 > NextLocalOffset && 585226633Sdim NextLocalOffset + FileSize + 1 <= CurrentLoadedOffset && 586226633Sdim "Ran out of source locations!"); 587226633Sdim // We do a +1 here because we want a SourceLocation that means "the end of the 588226633Sdim // file", e.g. for the "no newline at the end of the file" diagnostic. 589226633Sdim NextLocalOffset += FileSize + 1; 590198092Srdivacky 591193326Sed // Set LastFileIDLookup to the newly created file. The next getFileID call is 592193326Sed // almost guaranteed to be from that file. 593226633Sdim FileID FID = FileID::get(LocalSLocEntryTable.size()-1); 594194711Sed return LastFileIDLookup = FID; 595193326Sed} 596193326Sed 597224145SdimSourceLocation 598226633SdimSourceManager::createMacroArgExpansionLoc(SourceLocation SpellingLoc, 599226633Sdim SourceLocation ExpansionLoc, 600226633Sdim unsigned TokLength) { 601226633Sdim ExpansionInfo Info = ExpansionInfo::createForMacroArg(SpellingLoc, 602226633Sdim ExpansionLoc); 603226633Sdim return createExpansionLocImpl(Info, TokLength); 604224145Sdim} 605224145Sdim 606226633SdimSourceLocation 607226633SdimSourceManager::createExpansionLoc(SourceLocation SpellingLoc, 608226633Sdim SourceLocation ExpansionLocStart, 609226633Sdim SourceLocation ExpansionLocEnd, 610226633Sdim unsigned TokLength, 611341825Sdim bool ExpansionIsTokenRange, 612226633Sdim int LoadedID, 613226633Sdim unsigned LoadedOffset) { 614341825Sdim ExpansionInfo Info = ExpansionInfo::create( 615341825Sdim SpellingLoc, ExpansionLocStart, ExpansionLocEnd, ExpansionIsTokenRange); 616226633Sdim return createExpansionLocImpl(Info, TokLength, LoadedID, LoadedOffset); 617224145Sdim} 618224145Sdim 619341825SdimSourceLocation SourceManager::createTokenSplitLoc(SourceLocation Spelling, 620341825Sdim SourceLocation TokenStart, 621341825Sdim SourceLocation TokenEnd) { 622341825Sdim assert(getFileID(TokenStart) == getFileID(TokenEnd) && 623341825Sdim "token spans multiple files"); 624341825Sdim return createExpansionLocImpl( 625341825Sdim ExpansionInfo::createForTokenSplit(Spelling, TokenStart, TokenEnd), 626341825Sdim TokenEnd.getOffset() - TokenStart.getOffset()); 627341825Sdim} 628341825Sdim 629224145SdimSourceLocation 630226633SdimSourceManager::createExpansionLocImpl(const ExpansionInfo &Info, 631226633Sdim unsigned TokLength, 632226633Sdim int LoadedID, 633226633Sdim unsigned LoadedOffset) { 634226633Sdim if (LoadedID < 0) { 635226633Sdim assert(LoadedID != -1 && "Loading sentinel FileID"); 636226633Sdim unsigned Index = unsigned(-LoadedID) - 2; 637226633Sdim assert(Index < LoadedSLocEntryTable.size() && "FileID out of range"); 638226633Sdim assert(!SLocEntryLoaded[Index] && "FileID already loaded"); 639226633Sdim LoadedSLocEntryTable[Index] = SLocEntry::get(LoadedOffset, Info); 640226633Sdim SLocEntryLoaded[Index] = true; 641226633Sdim return SourceLocation::getMacroLoc(LoadedOffset); 642193326Sed } 643226633Sdim LocalSLocEntryTable.push_back(SLocEntry::get(NextLocalOffset, Info)); 644226633Sdim assert(NextLocalOffset + TokLength + 1 > NextLocalOffset && 645226633Sdim NextLocalOffset + TokLength + 1 <= CurrentLoadedOffset && 646226633Sdim "Ran out of source locations!"); 647226633Sdim // See createFileID for that +1. 648226633Sdim NextLocalOffset += TokLength + 1; 649226633Sdim return SourceLocation::getMacroLoc(NextLocalOffset - (TokLength + 1)); 650193326Sed} 651193326Sed 652353358Sdimconst llvm::MemoryBuffer * 653353358SdimSourceManager::getMemoryBufferForFile(const FileEntry *File, bool *Invalid) { 654200583Srdivacky const SrcMgr::ContentCache *IR = getOrCreateContentCache(File); 655205219Srdivacky assert(IR && "getOrCreateContentCache() cannot return NULL"); 656360784Sdim return IR->getBuffer(Diag, getFileManager(), SourceLocation(), Invalid); 657200583Srdivacky} 658200583Srdivacky 659218893Sdimvoid SourceManager::overrideFileContents(const FileEntry *SourceFile, 660276479Sdim llvm::MemoryBuffer *Buffer, 661212904Sdim bool DoNotFree) { 662200583Srdivacky const SrcMgr::ContentCache *IR = getOrCreateContentCache(SourceFile); 663218893Sdim assert(IR && "getOrCreateContentCache() cannot return NULL"); 664200583Srdivacky 665212904Sdim const_cast<SrcMgr::ContentCache *>(IR)->replaceBuffer(Buffer, DoNotFree); 666234353Sdim const_cast<SrcMgr::ContentCache *>(IR)->BufferOverridden = true; 667239462Sdim 668239462Sdim getOverriddenFilesInfo().OverriddenFilesWithBuffer.insert(SourceFile); 669200583Srdivacky} 670200583Srdivacky 671221345Sdimvoid SourceManager::overrideFileContents(const FileEntry *SourceFile, 672221345Sdim const FileEntry *NewFile) { 673221345Sdim assert(SourceFile->getSize() == NewFile->getSize() && 674221345Sdim "Different sizes, use the FileManager to create a virtual file with " 675221345Sdim "the correct size"); 676221345Sdim assert(FileInfos.count(SourceFile) == 0 && 677221345Sdim "This function should be called at the initialization stage, before " 678221345Sdim "any parsing occurs."); 679239462Sdim getOverriddenFilesInfo().OverriddenFiles[SourceFile] = NewFile; 680221345Sdim} 681221345Sdim 682360784Sdimconst FileEntry * 683360784SdimSourceManager::bypassFileContentsOverride(const FileEntry &File) { 684360784Sdim assert(isFileOverridden(&File)); 685360784Sdim llvm::Optional<FileEntryRef> BypassFile = 686360784Sdim FileMgr.getBypassFile(FileEntryRef(File.getName(), File)); 687239462Sdim 688360784Sdim // If the file can't be found in the FS, give up. 689360784Sdim if (!BypassFile) 690360784Sdim return nullptr; 691239462Sdim 692360784Sdim const FileEntry *FE = &BypassFile->getFileEntry(); 693360784Sdim (void)getOrCreateContentCache(FE); 694360784Sdim return FE; 695239462Sdim} 696239462Sdim 697296417Sdimvoid SourceManager::setFileIsTransient(const FileEntry *File) { 698296417Sdim const SrcMgr::ContentCache *CC = getOrCreateContentCache(File); 699296417Sdim const_cast<SrcMgr::ContentCache *>(CC)->IsTransient = true; 700296417Sdim} 701296417Sdim 702226633SdimStringRef SourceManager::getBufferData(FileID FID, bool *Invalid) const { 703205408Srdivacky bool MyInvalid = false; 704226633Sdim const SLocEntry &SLoc = getSLocEntry(FID, &MyInvalid); 705221345Sdim if (!SLoc.isFile() || MyInvalid) { 706341825Sdim if (Invalid) 707218893Sdim *Invalid = true; 708218893Sdim return "<<<<<INVALID SOURCE LOCATION>>>>>"; 709218893Sdim } 710276479Sdim 711353358Sdim const llvm::MemoryBuffer *Buf = SLoc.getFile().getContentCache()->getBuffer( 712360784Sdim Diag, getFileManager(), SourceLocation(), &MyInvalid); 713205219Srdivacky if (Invalid) 714205408Srdivacky *Invalid = MyInvalid; 715205408Srdivacky 716205408Srdivacky if (MyInvalid) 717218893Sdim return "<<<<<INVALID SOURCE LOCATION>>>>>"; 718341825Sdim 719205219Srdivacky return Buf->getBuffer(); 720193326Sed} 721193326Sed 722193326Sed//===----------------------------------------------------------------------===// 723193326Sed// SourceLocation manipulation methods. 724193326Sed//===----------------------------------------------------------------------===// 725193326Sed 726341825Sdim/// Return the FileID for a SourceLocation. 727193326Sed/// 728226633Sdim/// This is the cache-miss path of getFileID. Not as hot as that function, but 729226633Sdim/// still very important. It is responsible for finding the entry in the 730226633Sdim/// SLocEntry tables that contains the specified location. 731193326SedFileID SourceManager::getFileIDSlow(unsigned SLocOffset) const { 732221345Sdim if (!SLocOffset) 733221345Sdim return FileID::get(0); 734198092Srdivacky 735226633Sdim // Now it is time to search for the correct file. See where the SLocOffset 736226633Sdim // sits in the global view and consult local or loaded buffers for it. 737226633Sdim if (SLocOffset < NextLocalOffset) 738226633Sdim return getFileIDLocal(SLocOffset); 739226633Sdim return getFileIDLoaded(SLocOffset); 740226633Sdim} 741226633Sdim 742341825Sdim/// Return the FileID for a SourceLocation with a low offset. 743226633Sdim/// 744226633Sdim/// This function knows that the SourceLocation is in a local buffer, not a 745226633Sdim/// loaded one. 746226633SdimFileID SourceManager::getFileIDLocal(unsigned SLocOffset) const { 747226633Sdim assert(SLocOffset < NextLocalOffset && "Bad function choice"); 748226633Sdim 749193326Sed // After the first and second level caches, I see two common sorts of 750226633Sdim // behavior: 1) a lot of searched FileID's are "near" the cached file 751226633Sdim // location or are "near" the cached expansion location. 2) others are just 752193326Sed // completely random and may be a very long way away. 753193326Sed // 754193326Sed // To handle this, we do a linear search for up to 8 steps to catch #1 quickly 755193326Sed // then we fall back to a less cache efficient, but more scalable, binary 756193326Sed // search to find the location. 757198092Srdivacky 758193326Sed // See if this is near the file point - worst case we start scanning from the 759193326Sed // most newly created FileID. 760249423Sdim const SrcMgr::SLocEntry *I; 761198092Srdivacky 762226633Sdim if (LastFileIDLookup.ID < 0 || 763226633Sdim LocalSLocEntryTable[LastFileIDLookup.ID].getOffset() < SLocOffset) { 764193326Sed // Neither loc prunes our search. 765226633Sdim I = LocalSLocEntryTable.end(); 766193326Sed } else { 767193326Sed // Perhaps it is near the file point. 768226633Sdim I = LocalSLocEntryTable.begin()+LastFileIDLookup.ID; 769193326Sed } 770193326Sed 771193326Sed // Find the FileID that contains this. "I" is an iterator that points to a 772193326Sed // FileID whose offset is known to be larger than SLocOffset. 773193326Sed unsigned NumProbes = 0; 774327952Sdim while (true) { 775193326Sed --I; 776193326Sed if (I->getOffset() <= SLocOffset) { 777226633Sdim FileID Res = FileID::get(int(I - LocalSLocEntryTable.begin())); 778193326Sed 779226633Sdim // If this isn't an expansion, remember it. We have good locality across 780226633Sdim // FileID lookups. 781226633Sdim if (!I->isExpansion()) 782193326Sed LastFileIDLookup = Res; 783193326Sed NumLinearScans += NumProbes+1; 784193326Sed return Res; 785193326Sed } 786193326Sed if (++NumProbes == 8) 787193326Sed break; 788193326Sed } 789198092Srdivacky 790193326Sed // Convert "I" back into an index. We know that it is an entry whose index is 791193326Sed // larger than the offset we are looking for. 792226633Sdim unsigned GreaterIndex = I - LocalSLocEntryTable.begin(); 793193326Sed // LessIndex - This is the lower bound of the range that we're searching. 794193326Sed // We know that the offset corresponding to the FileID is is less than 795193326Sed // SLocOffset. 796193326Sed unsigned LessIndex = 0; 797193326Sed NumProbes = 0; 798327952Sdim while (true) { 799221345Sdim bool Invalid = false; 800193326Sed unsigned MiddleIndex = (GreaterIndex-LessIndex)/2+LessIndex; 801226633Sdim unsigned MidOffset = getLocalSLocEntry(MiddleIndex, &Invalid).getOffset(); 802221345Sdim if (Invalid) 803221345Sdim return FileID::get(0); 804341825Sdim 805193326Sed ++NumProbes; 806198092Srdivacky 807193326Sed // If the offset of the midpoint is too large, chop the high side of the 808193326Sed // range to the midpoint. 809193326Sed if (MidOffset > SLocOffset) { 810193326Sed GreaterIndex = MiddleIndex; 811193326Sed continue; 812193326Sed } 813198092Srdivacky 814193326Sed // If the middle index contains the value, succeed and return. 815226633Sdim // FIXME: This could be made faster by using a function that's aware of 816226633Sdim // being in the local area. 817193326Sed if (isOffsetInFileID(FileID::get(MiddleIndex), SLocOffset)) { 818193326Sed FileID Res = FileID::get(MiddleIndex); 819193326Sed 820226633Sdim // If this isn't a macro expansion, remember it. We have good locality 821193326Sed // across FileID lookups. 822226633Sdim if (!LocalSLocEntryTable[MiddleIndex].isExpansion()) 823193326Sed LastFileIDLookup = Res; 824193326Sed NumBinaryProbes += NumProbes; 825193326Sed return Res; 826193326Sed } 827198092Srdivacky 828193326Sed // Otherwise, move the low-side up to the middle index. 829193326Sed LessIndex = MiddleIndex; 830193326Sed } 831193326Sed} 832193326Sed 833341825Sdim/// Return the FileID for a SourceLocation with a high offset. 834226633Sdim/// 835226633Sdim/// This function knows that the SourceLocation is in a loaded buffer, not a 836226633Sdim/// local one. 837226633SdimFileID SourceManager::getFileIDLoaded(unsigned SLocOffset) const { 838226633Sdim // Sanity checking, otherwise a bug may lead to hanging in release build. 839234353Sdim if (SLocOffset < CurrentLoadedOffset) { 840234353Sdim assert(0 && "Invalid SLocOffset or bad function choice"); 841226633Sdim return FileID(); 842234353Sdim } 843226633Sdim 844226633Sdim // Essentially the same as the local case, but the loaded array is sorted 845226633Sdim // in the other direction. 846226633Sdim 847226633Sdim // First do a linear scan from the last lookup position, if possible. 848226633Sdim unsigned I; 849226633Sdim int LastID = LastFileIDLookup.ID; 850226633Sdim if (LastID >= 0 || getLoadedSLocEntryByID(LastID).getOffset() < SLocOffset) 851226633Sdim I = 0; 852226633Sdim else 853226633Sdim I = (-LastID - 2) + 1; 854226633Sdim 855226633Sdim unsigned NumProbes; 856226633Sdim for (NumProbes = 0; NumProbes < 8; ++NumProbes, ++I) { 857226633Sdim // Make sure the entry is loaded! 858226633Sdim const SrcMgr::SLocEntry &E = getLoadedSLocEntry(I); 859226633Sdim if (E.getOffset() <= SLocOffset) { 860226633Sdim FileID Res = FileID::get(-int(I) - 2); 861226633Sdim 862226633Sdim if (!E.isExpansion()) 863226633Sdim LastFileIDLookup = Res; 864226633Sdim NumLinearScans += NumProbes + 1; 865226633Sdim return Res; 866226633Sdim } 867226633Sdim } 868226633Sdim 869226633Sdim // Linear scan failed. Do the binary search. Note the reverse sorting of the 870226633Sdim // table: GreaterIndex is the one where the offset is greater, which is 871226633Sdim // actually a lower index! 872226633Sdim unsigned GreaterIndex = I; 873226633Sdim unsigned LessIndex = LoadedSLocEntryTable.size(); 874226633Sdim NumProbes = 0; 875327952Sdim while (true) { 876226633Sdim ++NumProbes; 877226633Sdim unsigned MiddleIndex = (LessIndex - GreaterIndex) / 2 + GreaterIndex; 878226633Sdim const SrcMgr::SLocEntry &E = getLoadedSLocEntry(MiddleIndex); 879249423Sdim if (E.getOffset() == 0) 880249423Sdim return FileID(); // invalid entry. 881226633Sdim 882226633Sdim ++NumProbes; 883226633Sdim 884226633Sdim if (E.getOffset() > SLocOffset) { 885249423Sdim // Sanity checking, otherwise a bug may lead to hanging in release build. 886249423Sdim if (GreaterIndex == MiddleIndex) { 887249423Sdim assert(0 && "binary search missed the entry"); 888249423Sdim return FileID(); 889249423Sdim } 890226633Sdim GreaterIndex = MiddleIndex; 891226633Sdim continue; 892226633Sdim } 893226633Sdim 894226633Sdim if (isOffsetInFileID(FileID::get(-int(MiddleIndex) - 2), SLocOffset)) { 895226633Sdim FileID Res = FileID::get(-int(MiddleIndex) - 2); 896226633Sdim if (!E.isExpansion()) 897226633Sdim LastFileIDLookup = Res; 898226633Sdim NumBinaryProbes += NumProbes; 899226633Sdim return Res; 900226633Sdim } 901226633Sdim 902249423Sdim // Sanity checking, otherwise a bug may lead to hanging in release build. 903249423Sdim if (LessIndex == MiddleIndex) { 904249423Sdim assert(0 && "binary search missed the entry"); 905249423Sdim return FileID(); 906249423Sdim } 907226633Sdim LessIndex = MiddleIndex; 908226633Sdim } 909226633Sdim} 910226633Sdim 911193326SedSourceLocation SourceManager:: 912226633SdimgetExpansionLocSlowCase(SourceLocation Loc) const { 913193326Sed do { 914203955Srdivacky // Note: If Loc indicates an offset into a token that came from a macro 915203955Srdivacky // expansion (e.g. the 5th character of the token) we do not want to add 916226633Sdim // this offset when going to the expansion location. The expansion 917203955Srdivacky // location is the macro invocation, which the offset has nothing to do 918203955Srdivacky // with. This is unlike when we get the spelling loc, because the offset 919203955Srdivacky // directly correspond to the token whose spelling we're inspecting. 920226633Sdim Loc = getSLocEntry(getFileID(Loc)).getExpansion().getExpansionLocStart(); 921193326Sed } while (!Loc.isFileID()); 922193326Sed 923193326Sed return Loc; 924193326Sed} 925193326Sed 926193326SedSourceLocation SourceManager::getSpellingLocSlowCase(SourceLocation Loc) const { 927193326Sed do { 928193326Sed std::pair<FileID, unsigned> LocInfo = getDecomposedLoc(Loc); 929226633Sdim Loc = getSLocEntry(LocInfo.first).getExpansion().getSpellingLoc(); 930226633Sdim Loc = Loc.getLocWithOffset(LocInfo.second); 931193326Sed } while (!Loc.isFileID()); 932193326Sed return Loc; 933193326Sed} 934193326Sed 935226633SdimSourceLocation SourceManager::getFileLocSlowCase(SourceLocation Loc) const { 936226633Sdim do { 937226633Sdim if (isMacroArgExpansion(Loc)) 938226633Sdim Loc = getImmediateSpellingLoc(Loc); 939226633Sdim else 940341825Sdim Loc = getImmediateExpansionRange(Loc).getBegin(); 941226633Sdim } while (!Loc.isFileID()); 942226633Sdim return Loc; 943226633Sdim} 944193326Sed 945226633Sdim 946193326Sedstd::pair<FileID, unsigned> 947226633SdimSourceManager::getDecomposedExpansionLocSlowCase( 948224145Sdim const SrcMgr::SLocEntry *E) const { 949226633Sdim // If this is an expansion record, walk through all the expansion points. 950193326Sed FileID FID; 951193326Sed SourceLocation Loc; 952224145Sdim unsigned Offset; 953193326Sed do { 954226633Sdim Loc = E->getExpansion().getExpansionLocStart(); 955198092Srdivacky 956193326Sed FID = getFileID(Loc); 957193326Sed E = &getSLocEntry(FID); 958224145Sdim Offset = Loc.getOffset()-E->getOffset(); 959193326Sed } while (!Loc.isFileID()); 960198092Srdivacky 961193326Sed return std::make_pair(FID, Offset); 962193326Sed} 963193326Sed 964193326Sedstd::pair<FileID, unsigned> 965193326SedSourceManager::getDecomposedSpellingLocSlowCase(const SrcMgr::SLocEntry *E, 966193326Sed unsigned Offset) const { 967226633Sdim // If this is an expansion record, walk through all the expansion points. 968193326Sed FileID FID; 969193326Sed SourceLocation Loc; 970193326Sed do { 971226633Sdim Loc = E->getExpansion().getSpellingLoc(); 972226633Sdim Loc = Loc.getLocWithOffset(Offset); 973198092Srdivacky 974193326Sed FID = getFileID(Loc); 975193326Sed E = &getSLocEntry(FID); 976226633Sdim Offset = Loc.getOffset()-E->getOffset(); 977193326Sed } while (!Loc.isFileID()); 978198092Srdivacky 979193326Sed return std::make_pair(FID, Offset); 980193326Sed} 981193326Sed 982193326Sed/// getImmediateSpellingLoc - Given a SourceLocation object, return the 983193326Sed/// spelling location referenced by the ID. This is the first level down 984193326Sed/// towards the place where the characters that make up the lexed token can be 985193326Sed/// found. This should not generally be used by clients. 986193326SedSourceLocation SourceManager::getImmediateSpellingLoc(SourceLocation Loc) const{ 987193326Sed if (Loc.isFileID()) return Loc; 988193326Sed std::pair<FileID, unsigned> LocInfo = getDecomposedLoc(Loc); 989226633Sdim Loc = getSLocEntry(LocInfo.first).getExpansion().getSpellingLoc(); 990226633Sdim return Loc.getLocWithOffset(LocInfo.second); 991193326Sed} 992193326Sed 993226633Sdim/// getImmediateExpansionRange - Loc is required to be an expansion location. 994226633Sdim/// Return the start/end of the expansion information. 995341825SdimCharSourceRange 996226633SdimSourceManager::getImmediateExpansionRange(SourceLocation Loc) const { 997226633Sdim assert(Loc.isMacroID() && "Not a macro expansion loc!"); 998226633Sdim const ExpansionInfo &Expansion = getSLocEntry(getFileID(Loc)).getExpansion(); 999226633Sdim return Expansion.getExpansionLocRange(); 1000193326Sed} 1001193326Sed 1002341825SdimSourceLocation SourceManager::getTopMacroCallerLoc(SourceLocation Loc) const { 1003341825Sdim while (isMacroArgExpansion(Loc)) 1004341825Sdim Loc = getImmediateSpellingLoc(Loc); 1005341825Sdim return Loc; 1006341825Sdim} 1007341825Sdim 1008226633Sdim/// getExpansionRange - Given a SourceLocation object, return the range of 1009226633Sdim/// tokens covered by the expansion in the ultimate file. 1010341825SdimCharSourceRange SourceManager::getExpansionRange(SourceLocation Loc) const { 1011341825Sdim if (Loc.isFileID()) 1012341825Sdim return CharSourceRange(SourceRange(Loc, Loc), true); 1013198092Srdivacky 1014341825Sdim CharSourceRange Res = getImmediateExpansionRange(Loc); 1015198092Srdivacky 1016226633Sdim // Fully resolve the start and end locations to their ultimate expansion 1017193326Sed // points. 1018341825Sdim while (!Res.getBegin().isFileID()) 1019341825Sdim Res.setBegin(getImmediateExpansionRange(Res.getBegin()).getBegin()); 1020341825Sdim while (!Res.getEnd().isFileID()) { 1021341825Sdim CharSourceRange EndRange = getImmediateExpansionRange(Res.getEnd()); 1022341825Sdim Res.setEnd(EndRange.getEnd()); 1023341825Sdim Res.setTokenRange(EndRange.isTokenRange()); 1024341825Sdim } 1025193326Sed return Res; 1026193326Sed} 1027193326Sed 1028296417Sdimbool SourceManager::isMacroArgExpansion(SourceLocation Loc, 1029296417Sdim SourceLocation *StartLoc) const { 1030224145Sdim if (!Loc.isMacroID()) return false; 1031193326Sed 1032224145Sdim FileID FID = getFileID(Loc); 1033249423Sdim const SrcMgr::ExpansionInfo &Expansion = getSLocEntry(FID).getExpansion(); 1034296417Sdim if (!Expansion.isMacroArgExpansion()) return false; 1035296417Sdim 1036296417Sdim if (StartLoc) 1037296417Sdim *StartLoc = Expansion.getExpansionLocStart(); 1038296417Sdim return true; 1039224145Sdim} 1040193326Sed 1041249423Sdimbool SourceManager::isMacroBodyExpansion(SourceLocation Loc) const { 1042249423Sdim if (!Loc.isMacroID()) return false; 1043224145Sdim 1044249423Sdim FileID FID = getFileID(Loc); 1045249423Sdim const SrcMgr::ExpansionInfo &Expansion = getSLocEntry(FID).getExpansion(); 1046249423Sdim return Expansion.isMacroBodyExpansion(); 1047249423Sdim} 1048249423Sdim 1049261991Sdimbool SourceManager::isAtStartOfImmediateMacroExpansion(SourceLocation Loc, 1050261991Sdim SourceLocation *MacroBegin) const { 1051261991Sdim assert(Loc.isValid() && Loc.isMacroID() && "Expected a valid macro loc"); 1052249423Sdim 1053261991Sdim std::pair<FileID, unsigned> DecompLoc = getDecomposedLoc(Loc); 1054261991Sdim if (DecompLoc.second > 0) 1055261991Sdim return false; // Does not point at the start of expansion range. 1056261991Sdim 1057261991Sdim bool Invalid = false; 1058261991Sdim const SrcMgr::ExpansionInfo &ExpInfo = 1059261991Sdim getSLocEntry(DecompLoc.first, &Invalid).getExpansion(); 1060261991Sdim if (Invalid) 1061261991Sdim return false; 1062261991Sdim SourceLocation ExpLoc = ExpInfo.getExpansionLocStart(); 1063261991Sdim 1064261991Sdim if (ExpInfo.isMacroArgExpansion()) { 1065261991Sdim // For macro argument expansions, check if the previous FileID is part of 1066261991Sdim // the same argument expansion, in which case this Loc is not at the 1067261991Sdim // beginning of the expansion. 1068261991Sdim FileID PrevFID = getPreviousFileID(DecompLoc.first); 1069261991Sdim if (!PrevFID.isInvalid()) { 1070261991Sdim const SrcMgr::SLocEntry &PrevEntry = getSLocEntry(PrevFID, &Invalid); 1071261991Sdim if (Invalid) 1072261991Sdim return false; 1073261991Sdim if (PrevEntry.isExpansion() && 1074261991Sdim PrevEntry.getExpansion().getExpansionLocStart() == ExpLoc) 1075261991Sdim return false; 1076261991Sdim } 1077261991Sdim } 1078261991Sdim 1079261991Sdim if (MacroBegin) 1080261991Sdim *MacroBegin = ExpLoc; 1081261991Sdim return true; 1082261991Sdim} 1083261991Sdim 1084261991Sdimbool SourceManager::isAtEndOfImmediateMacroExpansion(SourceLocation Loc, 1085261991Sdim SourceLocation *MacroEnd) const { 1086261991Sdim assert(Loc.isValid() && Loc.isMacroID() && "Expected a valid macro loc"); 1087261991Sdim 1088261991Sdim FileID FID = getFileID(Loc); 1089261991Sdim SourceLocation NextLoc = Loc.getLocWithOffset(1); 1090261991Sdim if (isInFileID(NextLoc, FID)) 1091261991Sdim return false; // Does not point at the end of expansion range. 1092261991Sdim 1093261991Sdim bool Invalid = false; 1094261991Sdim const SrcMgr::ExpansionInfo &ExpInfo = 1095261991Sdim getSLocEntry(FID, &Invalid).getExpansion(); 1096261991Sdim if (Invalid) 1097261991Sdim return false; 1098261991Sdim 1099261991Sdim if (ExpInfo.isMacroArgExpansion()) { 1100261991Sdim // For macro argument expansions, check if the next FileID is part of the 1101261991Sdim // same argument expansion, in which case this Loc is not at the end of the 1102261991Sdim // expansion. 1103261991Sdim FileID NextFID = getNextFileID(FID); 1104261991Sdim if (!NextFID.isInvalid()) { 1105261991Sdim const SrcMgr::SLocEntry &NextEntry = getSLocEntry(NextFID, &Invalid); 1106261991Sdim if (Invalid) 1107261991Sdim return false; 1108261991Sdim if (NextEntry.isExpansion() && 1109261991Sdim NextEntry.getExpansion().getExpansionLocStart() == 1110261991Sdim ExpInfo.getExpansionLocStart()) 1111261991Sdim return false; 1112261991Sdim } 1113261991Sdim } 1114261991Sdim 1115261991Sdim if (MacroEnd) 1116261991Sdim *MacroEnd = ExpInfo.getExpansionLocEnd(); 1117261991Sdim return true; 1118261991Sdim} 1119261991Sdim 1120193326Sed//===----------------------------------------------------------------------===// 1121193326Sed// Queries about the code at a SourceLocation. 1122193326Sed//===----------------------------------------------------------------------===// 1123193326Sed 1124193326Sed/// getCharacterData - Return a pointer to the start of the specified location 1125193326Sed/// in the appropriate MemoryBuffer. 1126205219Srdivackyconst char *SourceManager::getCharacterData(SourceLocation SL, 1127205219Srdivacky bool *Invalid) const { 1128193326Sed // Note that this is a hot function in the getSpelling() path, which is 1129193326Sed // heavily used by -E mode. 1130193326Sed std::pair<FileID, unsigned> LocInfo = getDecomposedSpellingLoc(SL); 1131198092Srdivacky 1132193326Sed // Note that calling 'getBuffer()' may lazily page in a source file. 1133205219Srdivacky bool CharDataInvalid = false; 1134221345Sdim const SLocEntry &Entry = getSLocEntry(LocInfo.first, &CharDataInvalid); 1135221345Sdim if (CharDataInvalid || !Entry.isFile()) { 1136221345Sdim if (Invalid) 1137221345Sdim *Invalid = true; 1138341825Sdim 1139221345Sdim return "<<<<INVALID BUFFER>>>>"; 1140221345Sdim } 1141353358Sdim const llvm::MemoryBuffer *Buffer = 1142353358Sdim Entry.getFile().getContentCache()->getBuffer( 1143360784Sdim Diag, getFileManager(), SourceLocation(), &CharDataInvalid); 1144205219Srdivacky if (Invalid) 1145205219Srdivacky *Invalid = CharDataInvalid; 1146205219Srdivacky return Buffer->getBufferStart() + (CharDataInvalid? 0 : LocInfo.second); 1147193326Sed} 1148193326Sed 1149193326Sed/// getColumnNumber - Return the column # for the specified file position. 1150193326Sed/// this is significantly cheaper to compute than the line number. 1151205219Srdivackyunsigned SourceManager::getColumnNumber(FileID FID, unsigned FilePos, 1152205219Srdivacky bool *Invalid) const { 1153205219Srdivacky bool MyInvalid = false; 1154353358Sdim const llvm::MemoryBuffer *MemBuf = getBuffer(FID, &MyInvalid); 1155205219Srdivacky if (Invalid) 1156205219Srdivacky *Invalid = MyInvalid; 1157198092Srdivacky 1158205219Srdivacky if (MyInvalid) 1159205219Srdivacky return 1; 1160205219Srdivacky 1161239462Sdim // It is okay to request a position just past the end of the buffer. 1162239462Sdim if (FilePos > MemBuf->getBufferSize()) { 1163234353Sdim if (Invalid) 1164239462Sdim *Invalid = true; 1165234353Sdim return 1; 1166234353Sdim } 1167234353Sdim 1168321369Sdim const char *Buf = MemBuf->getBufferStart(); 1169243830Sdim // See if we just calculated the line number for this FilePos and can use 1170243830Sdim // that to lookup the start of the line instead of searching for it. 1171243830Sdim if (LastLineNoFileIDQuery == FID && 1172276479Sdim LastLineNoContentCache->SourceLineCache != nullptr && 1173249423Sdim LastLineNoResult < LastLineNoContentCache->NumLines) { 1174243830Sdim unsigned *SourceLineCache = LastLineNoContentCache->SourceLineCache; 1175243830Sdim unsigned LineStart = SourceLineCache[LastLineNoResult - 1]; 1176243830Sdim unsigned LineEnd = SourceLineCache[LastLineNoResult]; 1177321369Sdim if (FilePos >= LineStart && FilePos < LineEnd) { 1178321369Sdim // LineEnd is the LineStart of the next line. 1179321369Sdim // A line ends with separator LF or CR+LF on Windows. 1180321369Sdim // FilePos might point to the last separator, 1181321369Sdim // but we need a column number at most 1 + the last column. 1182321369Sdim if (FilePos + 1 == LineEnd && FilePos > LineStart) { 1183321369Sdim if (Buf[FilePos - 1] == '\r' || Buf[FilePos - 1] == '\n') 1184321369Sdim --FilePos; 1185321369Sdim } 1186243830Sdim return FilePos - LineStart + 1; 1187321369Sdim } 1188243830Sdim } 1189243830Sdim 1190193326Sed unsigned LineStart = FilePos; 1191193326Sed while (LineStart && Buf[LineStart-1] != '\n' && Buf[LineStart-1] != '\r') 1192193326Sed --LineStart; 1193193326Sed return FilePos-LineStart+1; 1194193326Sed} 1195193326Sed 1196218893Sdim// isInvalid - Return the result of calling loc.isInvalid(), and 1197218893Sdim// if Invalid is not null, set its value to same. 1198309124Sdimtemplate<typename LocType> 1199309124Sdimstatic bool isInvalid(LocType Loc, bool *Invalid) { 1200218893Sdim bool MyInvalid = Loc.isInvalid(); 1201218893Sdim if (Invalid) 1202218893Sdim *Invalid = MyInvalid; 1203218893Sdim return MyInvalid; 1204218893Sdim} 1205218893Sdim 1206205219Srdivackyunsigned SourceManager::getSpellingColumnNumber(SourceLocation Loc, 1207205219Srdivacky bool *Invalid) const { 1208218893Sdim if (isInvalid(Loc, Invalid)) return 0; 1209193326Sed std::pair<FileID, unsigned> LocInfo = getDecomposedSpellingLoc(Loc); 1210205219Srdivacky return getColumnNumber(LocInfo.first, LocInfo.second, Invalid); 1211193326Sed} 1212193326Sed 1213226633Sdimunsigned SourceManager::getExpansionColumnNumber(SourceLocation Loc, 1214226633Sdim bool *Invalid) const { 1215218893Sdim if (isInvalid(Loc, Invalid)) return 0; 1216226633Sdim std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(Loc); 1217205219Srdivacky return getColumnNumber(LocInfo.first, LocInfo.second, Invalid); 1218193326Sed} 1219193326Sed 1220219077Sdimunsigned SourceManager::getPresumedColumnNumber(SourceLocation Loc, 1221219077Sdim bool *Invalid) const { 1222309124Sdim PresumedLoc PLoc = getPresumedLoc(Loc); 1223309124Sdim if (isInvalid(PLoc, Invalid)) return 0; 1224309124Sdim return PLoc.getColumn(); 1225219077Sdim} 1226219077Sdim 1227234353Sdim#ifdef __SSE2__ 1228234353Sdim#include <emmintrin.h> 1229234353Sdim#endif 1230234353Sdim 1231218893Sdimstatic LLVM_ATTRIBUTE_NOINLINE void 1232226633SdimComputeLineNumbers(DiagnosticsEngine &Diag, ContentCache *FI, 1233207619Srdivacky llvm::BumpPtrAllocator &Alloc, 1234207619Srdivacky const SourceManager &SM, bool &Invalid); 1235226633Sdimstatic void ComputeLineNumbers(DiagnosticsEngine &Diag, ContentCache *FI, 1236207619Srdivacky llvm::BumpPtrAllocator &Alloc, 1237207619Srdivacky const SourceManager &SM, bool &Invalid) { 1238193326Sed // Note that calling 'getBuffer()' may lazily page in the file. 1239353358Sdim const MemoryBuffer *Buffer = 1240360784Sdim FI->getBuffer(Diag, SM.getFileManager(), SourceLocation(), &Invalid); 1241205219Srdivacky if (Invalid) 1242205219Srdivacky return; 1243198092Srdivacky 1244193326Sed // Find the file offsets of all of the *physical* source lines. This does 1245193326Sed // not look at trigraphs, escaped newlines, or anything else tricky. 1246226633Sdim SmallVector<unsigned, 256> LineOffsets; 1247198092Srdivacky 1248193326Sed // Line #1 starts at char 0. 1249193326Sed LineOffsets.push_back(0); 1250198092Srdivacky 1251193326Sed const unsigned char *Buf = (const unsigned char *)Buffer->getBufferStart(); 1252193326Sed const unsigned char *End = (const unsigned char *)Buffer->getBufferEnd(); 1253360784Sdim const std::size_t BufLen = End - Buf; 1254344779Sdim unsigned I = 0; 1255360784Sdim while (I < BufLen) { 1256360784Sdim if (Buf[I] == '\n') { 1257360784Sdim LineOffsets.push_back(I + 1); 1258360784Sdim } else if (Buf[I] == '\r') { 1259344779Sdim // If this is \r\n, skip both characters. 1260360784Sdim if (I + 1 < BufLen && Buf[I + 1] == '\n') 1261344779Sdim ++I; 1262360784Sdim LineOffsets.push_back(I + 1); 1263193326Sed } 1264360784Sdim ++I; 1265193326Sed } 1266198092Srdivacky 1267193326Sed // Copy the offsets into the FileInfo structure. 1268193326Sed FI->NumLines = LineOffsets.size(); 1269193326Sed FI->SourceLineCache = Alloc.Allocate<unsigned>(LineOffsets.size()); 1270193326Sed std::copy(LineOffsets.begin(), LineOffsets.end(), FI->SourceLineCache); 1271193326Sed} 1272193326Sed 1273193326Sed/// getLineNumber - Given a SourceLocation, return the spelling line number 1274193326Sed/// for the position indicated. This requires building and caching a table of 1275193326Sed/// line offsets for the MemoryBuffer, so this is not cheap: use only when 1276193326Sed/// about to emit a diagnostic. 1277341825Sdimunsigned SourceManager::getLineNumber(FileID FID, unsigned FilePos, 1278205219Srdivacky bool *Invalid) const { 1279223017Sdim if (FID.isInvalid()) { 1280223017Sdim if (Invalid) 1281223017Sdim *Invalid = true; 1282223017Sdim return 1; 1283223017Sdim } 1284223017Sdim 1285193326Sed ContentCache *Content; 1286193326Sed if (LastLineNoFileIDQuery == FID) 1287193326Sed Content = LastLineNoContentCache; 1288221345Sdim else { 1289221345Sdim bool MyInvalid = false; 1290221345Sdim const SLocEntry &Entry = getSLocEntry(FID, &MyInvalid); 1291221345Sdim if (MyInvalid || !Entry.isFile()) { 1292221345Sdim if (Invalid) 1293221345Sdim *Invalid = true; 1294221345Sdim return 1; 1295221345Sdim } 1296341825Sdim 1297221345Sdim Content = const_cast<ContentCache*>(Entry.getFile().getContentCache()); 1298221345Sdim } 1299341825Sdim 1300193326Sed // If this is the first use of line information for this buffer, compute the 1301193326Sed /// SourceLineCache for it on demand. 1302276479Sdim if (!Content->SourceLineCache) { 1303205219Srdivacky bool MyInvalid = false; 1304207619Srdivacky ComputeLineNumbers(Diag, Content, ContentCacheAlloc, *this, MyInvalid); 1305205219Srdivacky if (Invalid) 1306205219Srdivacky *Invalid = MyInvalid; 1307205219Srdivacky if (MyInvalid) 1308205219Srdivacky return 1; 1309205219Srdivacky } else if (Invalid) 1310205219Srdivacky *Invalid = false; 1311193326Sed 1312193326Sed // Okay, we know we have a line number table. Do a binary search to find the 1313193326Sed // line number that this character position lands on. 1314193326Sed unsigned *SourceLineCache = Content->SourceLineCache; 1315193326Sed unsigned *SourceLineCacheStart = SourceLineCache; 1316193326Sed unsigned *SourceLineCacheEnd = SourceLineCache + Content->NumLines; 1317198092Srdivacky 1318193326Sed unsigned QueriedFilePos = FilePos+1; 1319193326Sed 1320193326Sed // FIXME: I would like to be convinced that this code is worth being as 1321198092Srdivacky // complicated as it is, binary search isn't that slow. 1322193326Sed // 1323193326Sed // If it is worth being optimized, then in my opinion it could be more 1324193326Sed // performant, simpler, and more obviously correct by just "galloping" outward 1325193326Sed // from the queried file position. In fact, this could be incorporated into a 1326193326Sed // generic algorithm such as lower_bound_with_hint. 1327193326Sed // 1328193326Sed // If someone gives me a test case where this matters, and I will do it! - DWD 1329193326Sed 1330193326Sed // If the previous query was to the same file, we know both the file pos from 1331193326Sed // that query and the line number returned. This allows us to narrow the 1332193326Sed // search space from the entire file to something near the match. 1333193326Sed if (LastLineNoFileIDQuery == FID) { 1334193326Sed if (QueriedFilePos >= LastLineNoFilePos) { 1335193326Sed // FIXME: Potential overflow? 1336193326Sed SourceLineCache = SourceLineCache+LastLineNoResult-1; 1337198092Srdivacky 1338193326Sed // The query is likely to be nearby the previous one. Here we check to 1339193326Sed // see if it is within 5, 10 or 20 lines. It can be far away in cases 1340193326Sed // where big comment blocks and vertical whitespace eat up lines but 1341193326Sed // contribute no tokens. 1342193326Sed if (SourceLineCache+5 < SourceLineCacheEnd) { 1343193326Sed if (SourceLineCache[5] > QueriedFilePos) 1344193326Sed SourceLineCacheEnd = SourceLineCache+5; 1345193326Sed else if (SourceLineCache+10 < SourceLineCacheEnd) { 1346193326Sed if (SourceLineCache[10] > QueriedFilePos) 1347193326Sed SourceLineCacheEnd = SourceLineCache+10; 1348193326Sed else if (SourceLineCache+20 < SourceLineCacheEnd) { 1349193326Sed if (SourceLineCache[20] > QueriedFilePos) 1350193326Sed SourceLineCacheEnd = SourceLineCache+20; 1351193326Sed } 1352193326Sed } 1353193326Sed } 1354193326Sed } else { 1355193326Sed if (LastLineNoResult < Content->NumLines) 1356193326Sed SourceLineCacheEnd = SourceLineCache+LastLineNoResult+1; 1357193326Sed } 1358193326Sed } 1359198092Srdivacky 1360193326Sed unsigned *Pos 1361193326Sed = std::lower_bound(SourceLineCache, SourceLineCacheEnd, QueriedFilePos); 1362193326Sed unsigned LineNo = Pos-SourceLineCacheStart; 1363198092Srdivacky 1364193326Sed LastLineNoFileIDQuery = FID; 1365193326Sed LastLineNoContentCache = Content; 1366193326Sed LastLineNoFilePos = QueriedFilePos; 1367193326Sed LastLineNoResult = LineNo; 1368193326Sed return LineNo; 1369193326Sed} 1370193326Sed 1371341825Sdimunsigned SourceManager::getSpellingLineNumber(SourceLocation Loc, 1372219077Sdim bool *Invalid) const { 1373219077Sdim if (isInvalid(Loc, Invalid)) return 0; 1374219077Sdim std::pair<FileID, unsigned> LocInfo = getDecomposedSpellingLoc(Loc); 1375219077Sdim return getLineNumber(LocInfo.first, LocInfo.second); 1376219077Sdim} 1377226633Sdimunsigned SourceManager::getExpansionLineNumber(SourceLocation Loc, 1378226633Sdim bool *Invalid) const { 1379218893Sdim if (isInvalid(Loc, Invalid)) return 0; 1380226633Sdim std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(Loc); 1381193326Sed return getLineNumber(LocInfo.first, LocInfo.second); 1382193326Sed} 1383219077Sdimunsigned SourceManager::getPresumedLineNumber(SourceLocation Loc, 1384205219Srdivacky bool *Invalid) const { 1385309124Sdim PresumedLoc PLoc = getPresumedLoc(Loc); 1386309124Sdim if (isInvalid(PLoc, Invalid)) return 0; 1387309124Sdim return PLoc.getLine(); 1388193326Sed} 1389193326Sed 1390193326Sed/// getFileCharacteristic - return the file characteristic of the specified 1391198092Srdivacky/// source location, indicating whether this is a normal file, a system 1392193326Sed/// header, or an "implicit extern C" system header. 1393193326Sed/// 1394193326Sed/// This state can be modified with flags on GNU linemarker directives like: 1395193326Sed/// # 4 "foo.h" 3 1396193326Sed/// which changes all source locations in the current file after that to be 1397193326Sed/// considered to be from a system header. 1398198092SrdivackySrcMgr::CharacteristicKind 1399193326SedSourceManager::getFileCharacteristic(SourceLocation Loc) const { 1400296417Sdim assert(Loc.isValid() && "Can't get file characteristic of invalid loc!"); 1401226633Sdim std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(Loc); 1402221345Sdim bool Invalid = false; 1403221345Sdim const SLocEntry &SEntry = getSLocEntry(LocInfo.first, &Invalid); 1404221345Sdim if (Invalid || !SEntry.isFile()) 1405221345Sdim return C_User; 1406341825Sdim 1407221345Sdim const SrcMgr::FileInfo &FI = SEntry.getFile(); 1408193326Sed 1409193326Sed // If there are no #line directives in this file, just return the whole-file 1410193326Sed // state. 1411193326Sed if (!FI.hasLineDirectives()) 1412193326Sed return FI.getFileCharacteristic(); 1413198092Srdivacky 1414193326Sed assert(LineTable && "Can't have linetable entries without a LineTable!"); 1415193326Sed // See if there is a #line directive before the location. 1416193326Sed const LineEntry *Entry = 1417239462Sdim LineTable->FindNearestLineEntry(LocInfo.first, LocInfo.second); 1418198092Srdivacky 1419193326Sed // If this is before the first line marker, use the file characteristic. 1420193326Sed if (!Entry) 1421193326Sed return FI.getFileCharacteristic(); 1422193326Sed 1423193326Sed return Entry->FileKind; 1424193326Sed} 1425193326Sed 1426193326Sed/// Return the filename or buffer identifier of the buffer the location is in. 1427239462Sdim/// Note that this name does not respect \#line directives. Use getPresumedLoc 1428193326Sed/// for normal clients. 1429314564SdimStringRef SourceManager::getBufferName(SourceLocation Loc, 1430314564Sdim bool *Invalid) const { 1431218893Sdim if (isInvalid(Loc, Invalid)) return "<invalid loc>"; 1432198092Srdivacky 1433205219Srdivacky return getBuffer(getFileID(Loc), Invalid)->getBufferIdentifier(); 1434193326Sed} 1435193326Sed 1436193326Sed/// getPresumedLoc - This method returns the "presumed" location of a 1437239462Sdim/// SourceLocation specifies. A "presumed location" can be modified by \#line 1438193326Sed/// or GNU line marker directives. This provides a view on the data that a 1439193326Sed/// user should see in diagnostics, for example. 1440193326Sed/// 1441226633Sdim/// Note that a presumed location is always given as the expansion point of an 1442226633Sdim/// expansion location, not at the spelling location. 1443249423SdimPresumedLoc SourceManager::getPresumedLoc(SourceLocation Loc, 1444249423Sdim bool UseLineDirectives) const { 1445193326Sed if (Loc.isInvalid()) return PresumedLoc(); 1446198092Srdivacky 1447226633Sdim // Presumed locations are always for expansion points. 1448226633Sdim std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(Loc); 1449198092Srdivacky 1450221345Sdim bool Invalid = false; 1451221345Sdim const SLocEntry &Entry = getSLocEntry(LocInfo.first, &Invalid); 1452221345Sdim if (Invalid || !Entry.isFile()) 1453221345Sdim return PresumedLoc(); 1454341825Sdim 1455221345Sdim const SrcMgr::FileInfo &FI = Entry.getFile(); 1456193326Sed const SrcMgr::ContentCache *C = FI.getContentCache(); 1457198092Srdivacky 1458193326Sed // To get the source name, first consult the FileEntry (if one exists) 1459193326Sed // before the MemBuffer as this will avoid unnecessarily paging in the 1460193326Sed // MemBuffer. 1461353358Sdim FileID FID = LocInfo.first; 1462314564Sdim StringRef Filename; 1463221345Sdim if (C->OrigEntry) 1464221345Sdim Filename = C->OrigEntry->getName(); 1465207619Srdivacky else 1466360784Sdim Filename = C->getBuffer(Diag, getFileManager())->getBufferIdentifier(); 1467221345Sdim 1468218893Sdim unsigned LineNo = getLineNumber(LocInfo.first, LocInfo.second, &Invalid); 1469218893Sdim if (Invalid) 1470218893Sdim return PresumedLoc(); 1471218893Sdim unsigned ColNo = getColumnNumber(LocInfo.first, LocInfo.second, &Invalid); 1472218893Sdim if (Invalid) 1473218893Sdim return PresumedLoc(); 1474341825Sdim 1475193326Sed SourceLocation IncludeLoc = FI.getIncludeLoc(); 1476198092Srdivacky 1477193326Sed // If we have #line directives in this file, update and overwrite the physical 1478193326Sed // location info if appropriate. 1479249423Sdim if (UseLineDirectives && FI.hasLineDirectives()) { 1480193326Sed assert(LineTable && "Can't have linetable entries without a LineTable!"); 1481193326Sed // See if there is a #line directive before this. If so, get it. 1482193326Sed if (const LineEntry *Entry = 1483239462Sdim LineTable->FindNearestLineEntry(LocInfo.first, LocInfo.second)) { 1484193326Sed // If the LineEntry indicates a filename, use it. 1485353358Sdim if (Entry->FilenameID != -1) { 1486193326Sed Filename = LineTable->getFilename(Entry->FilenameID); 1487353358Sdim // The contents of files referenced by #line are not in the 1488353358Sdim // SourceManager 1489353358Sdim FID = FileID::get(0); 1490353358Sdim } 1491193326Sed 1492193326Sed // Use the line number specified by the LineEntry. This line number may 1493193326Sed // be multiple lines down from the line entry. Add the difference in 1494193326Sed // physical line numbers from the query point and the line marker to the 1495193326Sed // total. 1496193326Sed unsigned MarkerLineNo = getLineNumber(LocInfo.first, Entry->FileOffset); 1497193326Sed LineNo = Entry->LineNo + (LineNo-MarkerLineNo-1); 1498198092Srdivacky 1499193326Sed // Note that column numbers are not molested by line markers. 1500198092Srdivacky 1501193326Sed // Handle virtual #include manipulation. 1502193326Sed if (Entry->IncludeOffset) { 1503193326Sed IncludeLoc = getLocForStartOfFile(LocInfo.first); 1504226633Sdim IncludeLoc = IncludeLoc.getLocWithOffset(Entry->IncludeOffset); 1505193326Sed } 1506193326Sed } 1507193326Sed } 1508193326Sed 1509353358Sdim return PresumedLoc(Filename.data(), FID, LineNo, ColNo, IncludeLoc); 1510193326Sed} 1511193326Sed 1512341825Sdim/// Returns whether the PresumedLoc for a given SourceLocation is 1513261991Sdim/// in the main file. 1514261991Sdim/// 1515261991Sdim/// This computes the "presumed" location for a SourceLocation, then checks 1516261991Sdim/// whether it came from a file other than the main file. This is different 1517261991Sdim/// from isWrittenInMainFile() because it takes line marker directives into 1518261991Sdim/// account. 1519261991Sdimbool SourceManager::isInMainFile(SourceLocation Loc) const { 1520261991Sdim if (Loc.isInvalid()) return false; 1521261991Sdim 1522261991Sdim // Presumed locations are always for expansion points. 1523261991Sdim std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(Loc); 1524261991Sdim 1525261991Sdim bool Invalid = false; 1526261991Sdim const SLocEntry &Entry = getSLocEntry(LocInfo.first, &Invalid); 1527261991Sdim if (Invalid || !Entry.isFile()) 1528261991Sdim return false; 1529261991Sdim 1530261991Sdim const SrcMgr::FileInfo &FI = Entry.getFile(); 1531261991Sdim 1532261991Sdim // Check if there is a line directive for this location. 1533261991Sdim if (FI.hasLineDirectives()) 1534261991Sdim if (const LineEntry *Entry = 1535261991Sdim LineTable->FindNearestLineEntry(LocInfo.first, LocInfo.second)) 1536261991Sdim if (Entry->IncludeOffset) 1537261991Sdim return false; 1538261991Sdim 1539261991Sdim return FI.getIncludeLoc().isInvalid(); 1540261991Sdim} 1541261991Sdim 1542341825Sdim/// The size of the SLocEntry that \p FID represents. 1543226633Sdimunsigned SourceManager::getFileIDSize(FileID FID) const { 1544226633Sdim bool Invalid = false; 1545226633Sdim const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid); 1546226633Sdim if (Invalid) 1547226633Sdim return 0; 1548226633Sdim 1549226633Sdim int ID = FID.ID; 1550226633Sdim unsigned NextOffset; 1551226633Sdim if ((ID > 0 && unsigned(ID+1) == local_sloc_entry_size())) 1552226633Sdim NextOffset = getNextLocalOffset(); 1553226633Sdim else if (ID+1 == -1) 1554226633Sdim NextOffset = MaxLoadedOffset; 1555226633Sdim else 1556226633Sdim NextOffset = getSLocEntry(FileID::get(ID+1)).getOffset(); 1557226633Sdim 1558226633Sdim return NextOffset - Entry.getOffset() - 1; 1559226633Sdim} 1560226633Sdim 1561193326Sed//===----------------------------------------------------------------------===// 1562193326Sed// Other miscellaneous methods. 1563193326Sed//===----------------------------------------------------------------------===// 1564193326Sed 1565341825Sdim/// Get the source location for the given file:line:col triplet. 1566194613Sed/// 1567194613Sed/// If the source file is included multiple times, the source location will 1568226633Sdim/// be based upon an arbitrary inclusion. 1569226633SdimSourceLocation SourceManager::translateFileLineCol(const FileEntry *SourceFile, 1570226633Sdim unsigned Line, 1571226633Sdim unsigned Col) const { 1572194613Sed assert(SourceFile && "Null source file!"); 1573194613Sed assert(Line && Col && "Line and column should start from 1!"); 1574193326Sed 1575226633Sdim FileID FirstFID = translateFile(SourceFile); 1576226633Sdim return translateLineCol(FirstFID, Line, Col); 1577226633Sdim} 1578226633Sdim 1579341825Sdim/// Get the FileID for the given file. 1580226633Sdim/// 1581226633Sdim/// If the source file is included multiple times, the FileID will be the 1582226633Sdim/// first inclusion. 1583226633SdimFileID SourceManager::translateFile(const FileEntry *SourceFile) const { 1584226633Sdim assert(SourceFile && "Null source file!"); 1585226633Sdim 1586200583Srdivacky // First, check the main file ID, since it is common to look for a 1587200583Srdivacky // location in the main file. 1588296417Sdim if (MainFileID.isValid()) { 1589221345Sdim bool Invalid = false; 1590221345Sdim const SLocEntry &MainSLoc = getSLocEntry(MainFileID, &Invalid); 1591221345Sdim if (Invalid) 1592226633Sdim return FileID(); 1593341825Sdim 1594218893Sdim if (MainSLoc.isFile()) { 1595360784Sdim const ContentCache *MainContentCache = 1596360784Sdim MainSLoc.getFile().getContentCache(); 1597360784Sdim if (MainContentCache && MainContentCache->OrigEntry == SourceFile) 1598360784Sdim return MainFileID; 1599218893Sdim } 1600200583Srdivacky } 1601200583Srdivacky 1602360784Sdim // The location we're looking for isn't in the main file; look 1603360784Sdim // through all of the local source locations. 1604360784Sdim for (unsigned I = 0, N = local_sloc_entry_size(); I != N; ++I) { 1605360784Sdim bool Invalid = false; 1606360784Sdim const SLocEntry &SLoc = getLocalSLocEntry(I, &Invalid); 1607360784Sdim if (Invalid) 1608360784Sdim return FileID(); 1609341825Sdim 1610360784Sdim if (SLoc.isFile() && SLoc.getFile().getContentCache() && 1611360784Sdim SLoc.getFile().getContentCache()->OrigEntry == SourceFile) 1612360784Sdim return FileID::get(I); 1613200583Srdivacky } 1614218893Sdim 1615360784Sdim // If that still didn't help, try the modules. 1616360784Sdim for (unsigned I = 0, N = loaded_sloc_entry_size(); I != N; ++I) { 1617360784Sdim const SLocEntry &SLoc = getLoadedSLocEntry(I); 1618360784Sdim if (SLoc.isFile() && SLoc.getFile().getContentCache() && 1619360784Sdim SLoc.getFile().getContentCache()->OrigEntry == SourceFile) 1620360784Sdim return FileID::get(-int(I) - 2); 1621218893Sdim } 1622341825Sdim 1623360784Sdim return FileID(); 1624226633Sdim} 1625226633Sdim 1626341825Sdim/// Get the source location in \arg FID for the given line:col. 1627226633Sdim/// Returns null location if \arg FID is not a file SLocEntry. 1628226633SdimSourceLocation SourceManager::translateLineCol(FileID FID, 1629226633Sdim unsigned Line, 1630226633Sdim unsigned Col) const { 1631261991Sdim // Lines are used as a one-based index into a zero-based array. This assert 1632261991Sdim // checks for possible buffer underruns. 1633296417Sdim assert(Line && Col && "Line and column should start from 1!"); 1634261991Sdim 1635226633Sdim if (FID.isInvalid()) 1636200583Srdivacky return SourceLocation(); 1637200583Srdivacky 1638226633Sdim bool Invalid = false; 1639226633Sdim const SLocEntry &Entry = getSLocEntry(FID, &Invalid); 1640226633Sdim if (Invalid) 1641226633Sdim return SourceLocation(); 1642261991Sdim 1643226633Sdim if (!Entry.isFile()) 1644226633Sdim return SourceLocation(); 1645226633Sdim 1646226633Sdim SourceLocation FileLoc = SourceLocation::getFileLoc(Entry.getOffset()); 1647226633Sdim 1648218893Sdim if (Line == 1 && Col == 1) 1649226633Sdim return FileLoc; 1650218893Sdim 1651218893Sdim ContentCache *Content 1652226633Sdim = const_cast<ContentCache *>(Entry.getFile().getContentCache()); 1653218893Sdim if (!Content) 1654218893Sdim return SourceLocation(); 1655261991Sdim 1656218893Sdim // If this is the first use of line information for this buffer, compute the 1657226633Sdim // SourceLineCache for it on demand. 1658276479Sdim if (!Content->SourceLineCache) { 1659218893Sdim bool MyInvalid = false; 1660218893Sdim ComputeLineNumbers(Diag, Content, ContentCacheAlloc, *this, MyInvalid); 1661218893Sdim if (MyInvalid) 1662218893Sdim return SourceLocation(); 1663218893Sdim } 1664218893Sdim 1665204643Srdivacky if (Line > Content->NumLines) { 1666360784Sdim unsigned Size = Content->getBuffer(Diag, getFileManager())->getBufferSize(); 1667204643Srdivacky if (Size > 0) 1668204643Srdivacky --Size; 1669226633Sdim return FileLoc.getLocWithOffset(Size); 1670204643Srdivacky } 1671204643Srdivacky 1672360784Sdim const llvm::MemoryBuffer *Buffer = Content->getBuffer(Diag, getFileManager()); 1673204643Srdivacky unsigned FilePos = Content->SourceLineCache[Line - 1]; 1674234353Sdim const char *Buf = Buffer->getBufferStart() + FilePos; 1675234353Sdim unsigned BufLength = Buffer->getBufferSize() - FilePos; 1676226633Sdim if (BufLength == 0) 1677226633Sdim return FileLoc.getLocWithOffset(FilePos); 1678226633Sdim 1679204643Srdivacky unsigned i = 0; 1680204643Srdivacky 1681204643Srdivacky // Check that the given column is valid. 1682204643Srdivacky while (i < BufLength-1 && i < Col-1 && Buf[i] != '\n' && Buf[i] != '\r') 1683204643Srdivacky ++i; 1684261991Sdim return FileLoc.getLocWithOffset(FilePos + i); 1685194613Sed} 1686194613Sed 1687341825Sdim/// Compute a map of macro argument chunks to their expanded source 1688226633Sdim/// location. Chunks that are not part of a macro argument will map to an 1689226633Sdim/// invalid source location. e.g. if a file contains one macro argument at 1690226633Sdim/// offset 100 with length 10, this is how the map will be formed: 1691226633Sdim/// 0 -> SourceLocation() 1692226633Sdim/// 100 -> Expanded macro arg location 1693226633Sdim/// 110 -> SourceLocation() 1694314564Sdimvoid SourceManager::computeMacroArgsCache(MacroArgsMap &MacroArgsCache, 1695226633Sdim FileID FID) const { 1696296417Sdim assert(FID.isValid()); 1697226633Sdim 1698226633Sdim // Initially no macro argument chunk is present. 1699226633Sdim MacroArgsCache.insert(std::make_pair(0, SourceLocation())); 1700226633Sdim 1701226633Sdim int ID = FID.ID; 1702327952Sdim while (true) { 1703226633Sdim ++ID; 1704226633Sdim // Stop if there are no more FileIDs to check. 1705226633Sdim if (ID > 0) { 1706226633Sdim if (unsigned(ID) >= local_sloc_entry_size()) 1707226633Sdim return; 1708226633Sdim } else if (ID == -1) { 1709226633Sdim return; 1710226633Sdim } 1711226633Sdim 1712261991Sdim bool Invalid = false; 1713261991Sdim const SrcMgr::SLocEntry &Entry = getSLocEntryByID(ID, &Invalid); 1714261991Sdim if (Invalid) 1715261991Sdim return; 1716226633Sdim if (Entry.isFile()) { 1717226633Sdim SourceLocation IncludeLoc = Entry.getFile().getIncludeLoc(); 1718226633Sdim if (IncludeLoc.isInvalid()) 1719226633Sdim continue; 1720226633Sdim if (!isInFileID(IncludeLoc, FID)) 1721226633Sdim return; // No more files/macros that may be "contained" in this file. 1722226633Sdim 1723226633Sdim // Skip the files/macros of the #include'd file, we only care about macros 1724226633Sdim // that lexed macro arguments from our file. 1725226633Sdim if (Entry.getFile().NumCreatedFIDs) 1726226633Sdim ID += Entry.getFile().NumCreatedFIDs - 1/*because of next ++ID*/; 1727226633Sdim continue; 1728226633Sdim } 1729226633Sdim 1730234353Sdim const ExpansionInfo &ExpInfo = Entry.getExpansion(); 1731234353Sdim 1732234353Sdim if (ExpInfo.getExpansionLocStart().isFileID()) { 1733234353Sdim if (!isInFileID(ExpInfo.getExpansionLocStart(), FID)) 1734234353Sdim return; // No more files/macros that may be "contained" in this file. 1735234353Sdim } 1736234353Sdim 1737234353Sdim if (!ExpInfo.isMacroArgExpansion()) 1738226633Sdim continue; 1739234353Sdim 1740243830Sdim associateFileChunkWithMacroArgExp(MacroArgsCache, FID, 1741243830Sdim ExpInfo.getSpellingLoc(), 1742243830Sdim SourceLocation::getMacroLoc(Entry.getOffset()), 1743243830Sdim getFileIDSize(FileID::get(ID))); 1744243830Sdim } 1745243830Sdim} 1746243830Sdim 1747243830Sdimvoid SourceManager::associateFileChunkWithMacroArgExp( 1748243830Sdim MacroArgsMap &MacroArgsCache, 1749243830Sdim FileID FID, 1750243830Sdim SourceLocation SpellLoc, 1751243830Sdim SourceLocation ExpansionLoc, 1752243830Sdim unsigned ExpansionLength) const { 1753243830Sdim if (!SpellLoc.isFileID()) { 1754243830Sdim unsigned SpellBeginOffs = SpellLoc.getOffset(); 1755243830Sdim unsigned SpellEndOffs = SpellBeginOffs + ExpansionLength; 1756243830Sdim 1757243830Sdim // The spelling range for this macro argument expansion can span multiple 1758243830Sdim // consecutive FileID entries. Go through each entry contained in the 1759243830Sdim // spelling range and if one is itself a macro argument expansion, recurse 1760243830Sdim // and associate the file chunk that it represents. 1761243830Sdim 1762243830Sdim FileID SpellFID; // Current FileID in the spelling range. 1763243830Sdim unsigned SpellRelativeOffs; 1764276479Sdim std::tie(SpellFID, SpellRelativeOffs) = getDecomposedLoc(SpellLoc); 1765327952Sdim while (true) { 1766243830Sdim const SLocEntry &Entry = getSLocEntry(SpellFID); 1767243830Sdim unsigned SpellFIDBeginOffs = Entry.getOffset(); 1768243830Sdim unsigned SpellFIDSize = getFileIDSize(SpellFID); 1769243830Sdim unsigned SpellFIDEndOffs = SpellFIDBeginOffs + SpellFIDSize; 1770243830Sdim const ExpansionInfo &Info = Entry.getExpansion(); 1771243830Sdim if (Info.isMacroArgExpansion()) { 1772243830Sdim unsigned CurrSpellLength; 1773243830Sdim if (SpellFIDEndOffs < SpellEndOffs) 1774243830Sdim CurrSpellLength = SpellFIDSize - SpellRelativeOffs; 1775243830Sdim else 1776243830Sdim CurrSpellLength = ExpansionLength; 1777243830Sdim associateFileChunkWithMacroArgExp(MacroArgsCache, FID, 1778243830Sdim Info.getSpellingLoc().getLocWithOffset(SpellRelativeOffs), 1779243830Sdim ExpansionLoc, CurrSpellLength); 1780243830Sdim } 1781243830Sdim 1782243830Sdim if (SpellFIDEndOffs >= SpellEndOffs) 1783243830Sdim return; // we covered all FileID entries in the spelling range. 1784243830Sdim 1785243830Sdim // Move to the next FileID entry in the spelling range. 1786243830Sdim unsigned advance = SpellFIDSize - SpellRelativeOffs + 1; 1787243830Sdim ExpansionLoc = ExpansionLoc.getLocWithOffset(advance); 1788243830Sdim ExpansionLength -= advance; 1789243830Sdim ++SpellFID.ID; 1790243830Sdim SpellRelativeOffs = 0; 1791234353Sdim } 1792243830Sdim } 1793226633Sdim 1794243830Sdim assert(SpellLoc.isFileID()); 1795226633Sdim 1796243830Sdim unsigned BeginOffs; 1797243830Sdim if (!isInFileID(SpellLoc, FID, &BeginOffs)) 1798243830Sdim return; 1799243830Sdim 1800243830Sdim unsigned EndOffs = BeginOffs + ExpansionLength; 1801243830Sdim 1802243830Sdim // Add a new chunk for this macro argument. A previous macro argument chunk 1803243830Sdim // may have been lexed again, so e.g. if the map is 1804243830Sdim // 0 -> SourceLocation() 1805243830Sdim // 100 -> Expanded loc #1 1806243830Sdim // 110 -> SourceLocation() 1807341825Sdim // and we found a new macro FileID that lexed from offset 105 with length 3, 1808243830Sdim // the new map will be: 1809243830Sdim // 0 -> SourceLocation() 1810243830Sdim // 100 -> Expanded loc #1 1811243830Sdim // 105 -> Expanded loc #2 1812243830Sdim // 108 -> Expanded loc #1 1813243830Sdim // 110 -> SourceLocation() 1814243830Sdim // 1815243830Sdim // Since re-lexed macro chunks will always be the same size or less of 1816243830Sdim // previous chunks, we only need to find where the ending of the new macro 1817243830Sdim // chunk is mapped to and update the map with new begin/end mappings. 1818243830Sdim 1819243830Sdim MacroArgsMap::iterator I = MacroArgsCache.upper_bound(EndOffs); 1820243830Sdim --I; 1821243830Sdim SourceLocation EndOffsMappedLoc = I->second; 1822243830Sdim MacroArgsCache[BeginOffs] = ExpansionLoc; 1823243830Sdim MacroArgsCache[EndOffs] = EndOffsMappedLoc; 1824226633Sdim} 1825226633Sdim 1826341825Sdim/// If \arg Loc points inside a function macro argument, the returned 1827226633Sdim/// location will be the macro location in which the argument was expanded. 1828226633Sdim/// If a macro argument is used multiple times, the expanded location will 1829226633Sdim/// be at the first expansion of the argument. 1830226633Sdim/// e.g. 1831226633Sdim/// MY_MACRO(foo); 1832226633Sdim/// ^ 1833226633Sdim/// Passing a file location pointing at 'foo', will yield a macro location 1834226633Sdim/// where 'foo' was expanded into. 1835226633SdimSourceLocation 1836226633SdimSourceManager::getMacroArgExpandedLocation(SourceLocation Loc) const { 1837226633Sdim if (Loc.isInvalid() || !Loc.isFileID()) 1838226633Sdim return Loc; 1839226633Sdim 1840226633Sdim FileID FID; 1841226633Sdim unsigned Offset; 1842276479Sdim std::tie(FID, Offset) = getDecomposedLoc(Loc); 1843226633Sdim if (FID.isInvalid()) 1844226633Sdim return Loc; 1845226633Sdim 1846314564Sdim std::unique_ptr<MacroArgsMap> &MacroArgsCache = MacroArgsCacheMap[FID]; 1847314564Sdim if (!MacroArgsCache) { 1848360784Sdim MacroArgsCache = std::make_unique<MacroArgsMap>(); 1849314564Sdim computeMacroArgsCache(*MacroArgsCache, FID); 1850314564Sdim } 1851226633Sdim 1852226633Sdim assert(!MacroArgsCache->empty()); 1853226633Sdim MacroArgsMap::iterator I = MacroArgsCache->upper_bound(Offset); 1854226633Sdim --I; 1855341825Sdim 1856226633Sdim unsigned MacroArgBeginOffs = I->first; 1857226633Sdim SourceLocation MacroArgExpandedLoc = I->second; 1858226633Sdim if (MacroArgExpandedLoc.isValid()) 1859226633Sdim return MacroArgExpandedLoc.getLocWithOffset(Offset - MacroArgBeginOffs); 1860226633Sdim 1861226633Sdim return Loc; 1862226633Sdim} 1863226633Sdim 1864251662Sdimstd::pair<FileID, unsigned> 1865251662SdimSourceManager::getDecomposedIncludedLoc(FileID FID) const { 1866261991Sdim if (FID.isInvalid()) 1867261991Sdim return std::make_pair(FileID(), 0); 1868261991Sdim 1869251662Sdim // Uses IncludedLocMap to retrieve/cache the decomposed loc. 1870251662Sdim 1871327952Sdim using DecompTy = std::pair<FileID, unsigned>; 1872344779Sdim auto InsertOp = IncludedLocMap.try_emplace(FID); 1873251662Sdim DecompTy &DecompLoc = InsertOp.first->second; 1874251662Sdim if (!InsertOp.second) 1875251662Sdim return DecompLoc; // already in map. 1876251662Sdim 1877251662Sdim SourceLocation UpperLoc; 1878261991Sdim bool Invalid = false; 1879261991Sdim const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid); 1880261991Sdim if (!Invalid) { 1881261991Sdim if (Entry.isExpansion()) 1882261991Sdim UpperLoc = Entry.getExpansion().getExpansionLocStart(); 1883261991Sdim else 1884261991Sdim UpperLoc = Entry.getFile().getIncludeLoc(); 1885261991Sdim } 1886251662Sdim 1887251662Sdim if (UpperLoc.isValid()) 1888251662Sdim DecompLoc = getDecomposedLoc(UpperLoc); 1889251662Sdim 1890251662Sdim return DecompLoc; 1891251662Sdim} 1892251662Sdim 1893226633Sdim/// Given a decomposed source location, move it up the include/expansion stack 1894226633Sdim/// to the parent source location. If this is possible, return the decomposed 1895226633Sdim/// version of the parent in Loc and return false. If Loc is the top-level 1896226633Sdim/// entry, return true and don't modify it. 1897208600Srdivackystatic bool MoveUpIncludeHierarchy(std::pair<FileID, unsigned> &Loc, 1898208600Srdivacky const SourceManager &SM) { 1899251662Sdim std::pair<FileID, unsigned> UpperLoc = SM.getDecomposedIncludedLoc(Loc.first); 1900251662Sdim if (UpperLoc.first.isInvalid()) 1901208600Srdivacky return true; // We reached the top. 1902251662Sdim 1903251662Sdim Loc = UpperLoc; 1904208600Srdivacky return false; 1905208600Srdivacky} 1906208600Srdivacky 1907249423Sdim/// Return the cache entry for comparing the given file IDs 1908249423Sdim/// for isBeforeInTranslationUnit. 1909249423SdimInBeforeInTUCacheEntry &SourceManager::getInBeforeInTUCache(FileID LFID, 1910249423Sdim FileID RFID) const { 1911249423Sdim // This is a magic number for limiting the cache size. It was experimentally 1912249423Sdim // derived from a small Objective-C project (where the cache filled 1913249423Sdim // out to ~250 items). We can make it larger if necessary. 1914249423Sdim enum { MagicCacheSize = 300 }; 1915249423Sdim IsBeforeInTUCacheKey Key(LFID, RFID); 1916249423Sdim 1917249423Sdim // If the cache size isn't too large, do a lookup and if necessary default 1918249423Sdim // construct an entry. We can then return it to the caller for direct 1919249423Sdim // use. When they update the value, the cache will get automatically 1920249423Sdim // updated as well. 1921249423Sdim if (IBTUCache.size() < MagicCacheSize) 1922249423Sdim return IBTUCache[Key]; 1923249423Sdim 1924249423Sdim // Otherwise, do a lookup that will not construct a new value. 1925249423Sdim InBeforeInTUCache::iterator I = IBTUCache.find(Key); 1926249423Sdim if (I != IBTUCache.end()) 1927249423Sdim return I->second; 1928249423Sdim 1929249423Sdim // Fall back to the overflow value. 1930249423Sdim return IBTUCacheOverflow; 1931249423Sdim} 1932249423Sdim 1933341825Sdim/// Determines the order of 2 source locations in the translation unit. 1934195099Sed/// 1935195099Sed/// \returns true if LHS source location comes before RHS, false otherwise. 1936195099Sedbool SourceManager::isBeforeInTranslationUnit(SourceLocation LHS, 1937195099Sed SourceLocation RHS) const { 1938195099Sed assert(LHS.isValid() && RHS.isValid() && "Passed invalid source location!"); 1939195099Sed if (LHS == RHS) 1940195099Sed return false; 1941198092Srdivacky 1942195099Sed std::pair<FileID, unsigned> LOffs = getDecomposedLoc(LHS); 1943195099Sed std::pair<FileID, unsigned> ROffs = getDecomposedLoc(RHS); 1944198092Srdivacky 1945261991Sdim // getDecomposedLoc may have failed to return a valid FileID because, e.g. it 1946261991Sdim // is a serialized one referring to a file that was removed after we loaded 1947261991Sdim // the PCH. 1948261991Sdim if (LOffs.first.isInvalid() || ROffs.first.isInvalid()) 1949261991Sdim return LOffs.first.isInvalid() && !ROffs.first.isInvalid(); 1950261991Sdim 1951321369Sdim std::pair<bool, bool> InSameTU = isInTheSameTranslationUnit(LOffs, ROffs); 1952321369Sdim if (InSameTU.first) 1953321369Sdim return InSameTU.second; 1954321369Sdim 1955321369Sdim // If we arrived here, the location is either in a built-ins buffer or 1956321369Sdim // associated with global inline asm. PR5662 and PR22576 are examples. 1957321369Sdim 1958321369Sdim StringRef LB = getBuffer(LOffs.first)->getBufferIdentifier(); 1959321369Sdim StringRef RB = getBuffer(ROffs.first)->getBufferIdentifier(); 1960321369Sdim bool LIsBuiltins = LB == "<built-in>"; 1961321369Sdim bool RIsBuiltins = RB == "<built-in>"; 1962321369Sdim // Sort built-in before non-built-in. 1963321369Sdim if (LIsBuiltins || RIsBuiltins) { 1964321369Sdim if (LIsBuiltins != RIsBuiltins) 1965321369Sdim return LIsBuiltins; 1966321369Sdim // Both are in built-in buffers, but from different files. We just claim that 1967321369Sdim // lower IDs come first. 1968321369Sdim return LOffs.first < ROffs.first; 1969321369Sdim } 1970321369Sdim bool LIsAsm = LB == "<inline asm>"; 1971321369Sdim bool RIsAsm = RB == "<inline asm>"; 1972321369Sdim // Sort assembler after built-ins, but before the rest. 1973321369Sdim if (LIsAsm || RIsAsm) { 1974321369Sdim if (LIsAsm != RIsAsm) 1975321369Sdim return RIsAsm; 1976321369Sdim assert(LOffs.first == ROffs.first); 1977321369Sdim return false; 1978321369Sdim } 1979321369Sdim bool LIsScratch = LB == "<scratch space>"; 1980321369Sdim bool RIsScratch = RB == "<scratch space>"; 1981321369Sdim // Sort scratch after inline asm, but before the rest. 1982321369Sdim if (LIsScratch || RIsScratch) { 1983321369Sdim if (LIsScratch != RIsScratch) 1984321369Sdim return LIsScratch; 1985321369Sdim return LOffs.second < ROffs.second; 1986321369Sdim } 1987321369Sdim llvm_unreachable("Unsortable locations found"); 1988321369Sdim} 1989321369Sdim 1990321369Sdimstd::pair<bool, bool> SourceManager::isInTheSameTranslationUnit( 1991321369Sdim std::pair<FileID, unsigned> &LOffs, 1992321369Sdim std::pair<FileID, unsigned> &ROffs) const { 1993195099Sed // If the source locations are in the same file, just compare offsets. 1994195099Sed if (LOffs.first == ROffs.first) 1995321369Sdim return std::make_pair(true, LOffs.second < ROffs.second); 1996194613Sed 1997195099Sed // If we are comparing a source location with multiple locations in the same 1998195099Sed // file, we get a big win by caching the result. 1999249423Sdim InBeforeInTUCacheEntry &IsBeforeInTUCache = 2000249423Sdim getInBeforeInTUCache(LOffs.first, ROffs.first); 2001249423Sdim 2002249423Sdim // If we are comparing a source location with multiple locations in the same 2003249423Sdim // file, we get a big win by caching the result. 2004208600Srdivacky if (IsBeforeInTUCache.isCacheValid(LOffs.first, ROffs.first)) 2005321369Sdim return std::make_pair( 2006321369Sdim true, IsBeforeInTUCache.getCachedResult(LOffs.second, ROffs.second)); 2007198092Srdivacky 2008208600Srdivacky // Okay, we missed in the cache, start updating the cache for this query. 2009226633Sdim IsBeforeInTUCache.setQueryFIDs(LOffs.first, ROffs.first, 2010226633Sdim /*isLFIDBeforeRFID=*/LOffs.first.ID < ROffs.first.ID); 2011198092Srdivacky 2012226633Sdim // We need to find the common ancestor. The only way of doing this is to 2013226633Sdim // build the complete include chain for one and then walking up the chain 2014226633Sdim // of the other looking for a match. 2015226633Sdim // We use a map from FileID to Offset to store the chain. Easier than writing 2016226633Sdim // a custom set hash info that only depends on the first part of a pair. 2017327952Sdim using LocSet = llvm::SmallDenseMap<FileID, unsigned, 16>; 2018226633Sdim LocSet LChain; 2019208600Srdivacky do { 2020226633Sdim LChain.insert(LOffs); 2021226633Sdim // We catch the case where LOffs is in a file included by ROffs and 2022226633Sdim // quit early. The other way round unfortunately remains suboptimal. 2023226633Sdim } while (LOffs.first != ROffs.first && !MoveUpIncludeHierarchy(LOffs, *this)); 2024226633Sdim LocSet::iterator I; 2025226633Sdim while((I = LChain.find(ROffs.first)) == LChain.end()) { 2026226633Sdim if (MoveUpIncludeHierarchy(ROffs, *this)) 2027226633Sdim break; // Met at topmost file. 2028226633Sdim } 2029226633Sdim if (I != LChain.end()) 2030226633Sdim LOffs = *I; 2031195099Sed 2032208600Srdivacky // If we exited because we found a nearest common ancestor, compare the 2033208600Srdivacky // locations within the common file and cache them. 2034208600Srdivacky if (LOffs.first == ROffs.first) { 2035208600Srdivacky IsBeforeInTUCache.setCommonLoc(LOffs.first, LOffs.second, ROffs.second); 2036321369Sdim return std::make_pair( 2037321369Sdim true, IsBeforeInTUCache.getCachedResult(LOffs.second, ROffs.second)); 2038195099Sed } 2039226633Sdim // Clear the lookup cache, it depends on a common location. 2040226633Sdim IsBeforeInTUCache.clear(); 2041321369Sdim return std::make_pair(false, false); 2042195099Sed} 2043195099Sed 2044193326Sedvoid SourceManager::PrintStats() const { 2045198092Srdivacky llvm::errs() << "\n*** Source Manager Stats:\n"; 2046198092Srdivacky llvm::errs() << FileInfos.size() << " files mapped, " << MemBufferInfos.size() 2047198092Srdivacky << " mem buffers mapped.\n"; 2048226633Sdim llvm::errs() << LocalSLocEntryTable.size() << " local SLocEntry's allocated (" 2049226633Sdim << llvm::capacity_in_bytes(LocalSLocEntryTable) 2050224145Sdim << " bytes of capacity), " 2051226633Sdim << NextLocalOffset << "B of Sloc address space used.\n"; 2052226633Sdim llvm::errs() << LoadedSLocEntryTable.size() 2053226633Sdim << " loaded SLocEntries allocated, " 2054226633Sdim << MaxLoadedOffset - CurrentLoadedOffset 2055226633Sdim << "B of Sloc address space used.\n"; 2056341825Sdim 2057193326Sed unsigned NumLineNumsComputed = 0; 2058193326Sed unsigned NumFileBytesMapped = 0; 2059193326Sed for (fileinfo_iterator I = fileinfo_begin(), E = fileinfo_end(); I != E; ++I){ 2060276479Sdim NumLineNumsComputed += I->second->SourceLineCache != nullptr; 2061193326Sed NumFileBytesMapped += I->second->getSizeBytesMapped(); 2062193326Sed } 2063226633Sdim unsigned NumMacroArgsComputed = MacroArgsCacheMap.size(); 2064198092Srdivacky 2065198092Srdivacky llvm::errs() << NumFileBytesMapped << " bytes of files mapped, " 2066226633Sdim << NumLineNumsComputed << " files with line #'s computed, " 2067226633Sdim << NumMacroArgsComputed << " files with macro args computed.\n"; 2068198092Srdivacky llvm::errs() << "FileID scans: " << NumLinearScans << " linear, " 2069198092Srdivacky << NumBinaryProbes << " binary.\n"; 2070193326Sed} 2071193326Sed 2072296417SdimLLVM_DUMP_METHOD void SourceManager::dump() const { 2073296417Sdim llvm::raw_ostream &out = llvm::errs(); 2074296417Sdim 2075296417Sdim auto DumpSLocEntry = [&](int ID, const SrcMgr::SLocEntry &Entry, 2076296417Sdim llvm::Optional<unsigned> NextStart) { 2077296417Sdim out << "SLocEntry <FileID " << ID << "> " << (Entry.isFile() ? "file" : "expansion") 2078296417Sdim << " <SourceLocation " << Entry.getOffset() << ":"; 2079296417Sdim if (NextStart) 2080296417Sdim out << *NextStart << ">\n"; 2081296417Sdim else 2082296417Sdim out << "???\?>\n"; 2083296417Sdim if (Entry.isFile()) { 2084296417Sdim auto &FI = Entry.getFile(); 2085296417Sdim if (FI.NumCreatedFIDs) 2086296417Sdim out << " covers <FileID " << ID << ":" << int(ID + FI.NumCreatedFIDs) 2087296417Sdim << ">\n"; 2088296417Sdim if (FI.getIncludeLoc().isValid()) 2089296417Sdim out << " included from " << FI.getIncludeLoc().getOffset() << "\n"; 2090296417Sdim if (auto *CC = FI.getContentCache()) { 2091296417Sdim out << " for " << (CC->OrigEntry ? CC->OrigEntry->getName() : "<none>") 2092296417Sdim << "\n"; 2093296417Sdim if (CC->BufferOverridden) 2094296417Sdim out << " contents overridden\n"; 2095296417Sdim if (CC->ContentsEntry != CC->OrigEntry) { 2096296417Sdim out << " contents from " 2097296417Sdim << (CC->ContentsEntry ? CC->ContentsEntry->getName() : "<none>") 2098296417Sdim << "\n"; 2099296417Sdim } 2100296417Sdim } 2101296417Sdim } else { 2102296417Sdim auto &EI = Entry.getExpansion(); 2103296417Sdim out << " spelling from " << EI.getSpellingLoc().getOffset() << "\n"; 2104296417Sdim out << " macro " << (EI.isMacroArgExpansion() ? "arg" : "body") 2105296417Sdim << " range <" << EI.getExpansionLocStart().getOffset() << ":" 2106296417Sdim << EI.getExpansionLocEnd().getOffset() << ">\n"; 2107296417Sdim } 2108296417Sdim }; 2109296417Sdim 2110296417Sdim // Dump local SLocEntries. 2111296417Sdim for (unsigned ID = 0, NumIDs = LocalSLocEntryTable.size(); ID != NumIDs; ++ID) { 2112296417Sdim DumpSLocEntry(ID, LocalSLocEntryTable[ID], 2113296417Sdim ID == NumIDs - 1 ? NextLocalOffset 2114296417Sdim : LocalSLocEntryTable[ID + 1].getOffset()); 2115296417Sdim } 2116296417Sdim // Dump loaded SLocEntries. 2117296417Sdim llvm::Optional<unsigned> NextStart; 2118296417Sdim for (unsigned Index = 0; Index != LoadedSLocEntryTable.size(); ++Index) { 2119296417Sdim int ID = -(int)Index - 2; 2120296417Sdim if (SLocEntryLoaded[Index]) { 2121296417Sdim DumpSLocEntry(ID, LoadedSLocEntryTable[Index], NextStart); 2122296417Sdim NextStart = LoadedSLocEntryTable[Index].getOffset(); 2123296417Sdim } else { 2124296417Sdim NextStart = None; 2125296417Sdim } 2126296417Sdim } 2127296417Sdim} 2128296417Sdim 2129327952SdimExternalSLocEntrySource::~ExternalSLocEntrySource() = default; 2130221345Sdim 2131221345Sdim/// Return the amount of memory used by memory buffers, breaking down 2132221345Sdim/// by heap-backed versus mmap'ed memory. 2133221345SdimSourceManager::MemoryBufferSizes SourceManager::getMemoryBufferSizes() const { 2134221345Sdim size_t malloc_bytes = 0; 2135221345Sdim size_t mmap_bytes = 0; 2136341825Sdim 2137221345Sdim for (unsigned i = 0, e = MemBufferInfos.size(); i != e; ++i) 2138221345Sdim if (size_t sized_mapped = MemBufferInfos[i]->getSizeBytesMapped()) 2139221345Sdim switch (MemBufferInfos[i]->getMemoryBufferKind()) { 2140221345Sdim case llvm::MemoryBuffer::MemoryBuffer_MMap: 2141221345Sdim mmap_bytes += sized_mapped; 2142221345Sdim break; 2143221345Sdim case llvm::MemoryBuffer::MemoryBuffer_Malloc: 2144221345Sdim malloc_bytes += sized_mapped; 2145221345Sdim break; 2146221345Sdim } 2147341825Sdim 2148221345Sdim return MemoryBufferSizes(malloc_bytes, mmap_bytes); 2149221345Sdim} 2150221345Sdim 2151226633Sdimsize_t SourceManager::getDataStructureSizes() const { 2152239462Sdim size_t size = llvm::capacity_in_bytes(MemBufferInfos) 2153226633Sdim + llvm::capacity_in_bytes(LocalSLocEntryTable) 2154226633Sdim + llvm::capacity_in_bytes(LoadedSLocEntryTable) 2155226633Sdim + llvm::capacity_in_bytes(SLocEntryLoaded) 2156239462Sdim + llvm::capacity_in_bytes(FileInfos); 2157341825Sdim 2158239462Sdim if (OverriddenFilesInfo) 2159239462Sdim size += llvm::capacity_in_bytes(OverriddenFilesInfo->OverriddenFiles); 2160239462Sdim 2161239462Sdim return size; 2162226633Sdim} 2163341825Sdim 2164341825SdimSourceManagerForFile::SourceManagerForFile(StringRef FileName, 2165341825Sdim StringRef Content) { 2166341825Sdim // This is referenced by `FileMgr` and will be released by `FileMgr` when it 2167341825Sdim // is deleted. 2168344779Sdim IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem( 2169344779Sdim new llvm::vfs::InMemoryFileSystem); 2170341825Sdim InMemoryFileSystem->addFile( 2171341825Sdim FileName, 0, 2172341825Sdim llvm::MemoryBuffer::getMemBuffer(Content, FileName, 2173341825Sdim /*RequiresNullTerminator=*/false)); 2174341825Sdim // This is passed to `SM` as reference, so the pointer has to be referenced 2175341825Sdim // in `Environment` so that `FileMgr` can out-live this function scope. 2176341825Sdim FileMgr = 2177360784Sdim std::make_unique<FileManager>(FileSystemOptions(), InMemoryFileSystem); 2178341825Sdim // This is passed to `SM` as reference, so the pointer has to be referenced 2179341825Sdim // by `Environment` due to the same reason above. 2180360784Sdim Diagnostics = std::make_unique<DiagnosticsEngine>( 2181341825Sdim IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs), 2182341825Sdim new DiagnosticOptions); 2183360784Sdim SourceMgr = std::make_unique<SourceManager>(*Diagnostics, *FileMgr); 2184360784Sdim FileID ID = SourceMgr->createFileID(*FileMgr->getFile(FileName), 2185341825Sdim SourceLocation(), clang::SrcMgr::C_User); 2186341825Sdim assert(ID.isValid()); 2187341825Sdim SourceMgr->setMainFileID(ID); 2188341825Sdim} 2189