1193326Sed//===--- SourceManager.cpp - Track and cache source files -----------------===// 2193326Sed// 3193326Sed// The LLVM Compiler Infrastructure 4193326Sed// 5193326Sed// This file is distributed under the University of Illinois Open Source 6193326Sed// License. See LICENSE.TXT for details. 7193326Sed// 8193326Sed//===----------------------------------------------------------------------===// 9193326Sed// 10193326Sed// This file implements the SourceManager interface. 11193326Sed// 12193326Sed//===----------------------------------------------------------------------===// 13193326Sed 14193326Sed#include "clang/Basic/SourceManager.h" 15205219Srdivacky#include "clang/Basic/Diagnostic.h" 16193326Sed#include "clang/Basic/FileManager.h" 17252723Sdim#include "clang/Basic/SourceManagerInternals.h" 18218893Sdim#include "llvm/ADT/Optional.h" 19226890Sdim#include "llvm/ADT/STLExtras.h" 20252723Sdim#include "llvm/ADT/StringSwitch.h" 21252723Sdim#include "llvm/Support/Capacity.h" 22193326Sed#include "llvm/Support/Compiler.h" 23193326Sed#include "llvm/Support/MemoryBuffer.h" 24252723Sdim#include "llvm/Support/Path.h" 25198092Srdivacky#include "llvm/Support/raw_ostream.h" 26193326Sed#include <algorithm> 27252723Sdim#include <cstring> 28205219Srdivacky#include <string> 29218893Sdim#include <sys/stat.h> 30205219Srdivacky 31193326Sedusing namespace clang; 32193326Sedusing namespace SrcMgr; 33193326Sedusing llvm::MemoryBuffer; 34193326Sed 35193326Sed//===----------------------------------------------------------------------===// 36193326Sed// SourceManager Helper Classes 37193326Sed//===----------------------------------------------------------------------===// 38193326Sed 39193326SedContentCache::~ContentCache() { 40212904Sdim if (shouldFreeBuffer()) 41212904Sdim delete Buffer.getPointer(); 42193326Sed} 43193326Sed 44226890Sdim/// getSizeBytesMapped - Returns the number of bytes actually mapped for this 45226890Sdim/// ContentCache. This can be 0 if the MemBuffer was not actually expanded. 46193326Sedunsigned ContentCache::getSizeBytesMapped() const { 47205408Srdivacky return Buffer.getPointer() ? Buffer.getPointer()->getBufferSize() : 0; 48193326Sed} 49193326Sed 50221345Sdim/// Returns the kind of memory used to back the memory buffer for 51221345Sdim/// this content cache. This is used for performance analysis. 52221345Sdimllvm::MemoryBuffer::BufferKind ContentCache::getMemoryBufferKind() const { 53221345Sdim assert(Buffer.getPointer()); 54221345Sdim 55221345Sdim // Should be unreachable, but keep for sanity. 56221345Sdim if (!Buffer.getPointer()) 57221345Sdim return llvm::MemoryBuffer::MemoryBuffer_Malloc; 58221345Sdim 59221345Sdim const llvm::MemoryBuffer *buf = Buffer.getPointer(); 60221345Sdim return buf->getBufferKind(); 61221345Sdim} 62221345Sdim 63193326Sed/// getSize - Returns the size of the content encapsulated by this ContentCache. 64193326Sed/// This can be the size of the source file or the size of an arbitrary 65193326Sed/// scratch buffer. If the ContentCache encapsulates a source file, that 66200583Srdivacky/// file is not lazily brought in from disk to satisfy this query. 67193326Sedunsigned ContentCache::getSize() const { 68205408Srdivacky return Buffer.getPointer() ? (unsigned) Buffer.getPointer()->getBufferSize() 69221345Sdim : (unsigned) ContentsEntry->getSize(); 70193326Sed} 71193326Sed 72212904Sdimvoid ContentCache::replaceBuffer(const llvm::MemoryBuffer *B, 73212904Sdim bool DoNotFree) { 74245431Sdim if (B && B == Buffer.getPointer()) { 75235633Sdim assert(0 && "Replacing with the same buffer"); 76235633Sdim Buffer.setInt(DoNotFree? DoNotFreeFlag : 0); 77235633Sdim return; 78235633Sdim } 79200583Srdivacky 80212904Sdim if (shouldFreeBuffer()) 81212904Sdim delete Buffer.getPointer(); 82205408Srdivacky Buffer.setPointer(B); 83212904Sdim Buffer.setInt(DoNotFree? DoNotFreeFlag : 0); 84200583Srdivacky} 85200583Srdivacky 86226890Sdimconst llvm::MemoryBuffer *ContentCache::getBuffer(DiagnosticsEngine &Diag, 87207619Srdivacky const SourceManager &SM, 88207619Srdivacky SourceLocation Loc, 89205219Srdivacky bool *Invalid) const { 90218893Sdim // Lazily create the Buffer for ContentCaches that wrap files. If we already 91221345Sdim // computed it, just return what we have. 92221345Sdim if (Buffer.getPointer() || ContentsEntry == 0) { 93218893Sdim if (Invalid) 94218893Sdim *Invalid = isBufferInvalid(); 95205408Srdivacky 96218893Sdim return Buffer.getPointer(); 97218893Sdim } 98206084Srdivacky 99218893Sdim std::string ErrorStr; 100245431Sdim bool isVolatile = SM.userFilesAreVolatile() && !IsSystemFile; 101245431Sdim Buffer.setPointer(SM.getFileManager().getBufferForFile(ContentsEntry, 102245431Sdim &ErrorStr, 103245431Sdim isVolatile)); 104206084Srdivacky 105218893Sdim // If we were unable to open the file, then we are in an inconsistent 106218893Sdim // situation where the content cache referenced a file which no longer 107218893Sdim // exists. Most likely, we were using a stat cache with an invalid entry but 108218893Sdim // the file could also have been removed during processing. Since we can't 109218893Sdim // really deal with this situation, just create an empty buffer. 110218893Sdim // 111218893Sdim // FIXME: This is definitely not ideal, but our immediate clients can't 112218893Sdim // currently handle returning a null entry here. Ideally we should detect 113218893Sdim // that we are in an inconsistent situation and error out as quickly as 114218893Sdim // possible. 115218893Sdim if (!Buffer.getPointer()) { 116226890Sdim const StringRef FillStr("<<<MISSING SOURCE FILE>>>\n"); 117221345Sdim Buffer.setPointer(MemoryBuffer::getNewMemBuffer(ContentsEntry->getSize(), 118218893Sdim "<invalid>")); 119218893Sdim char *Ptr = const_cast<char*>(Buffer.getPointer()->getBufferStart()); 120221345Sdim for (unsigned i = 0, e = ContentsEntry->getSize(); i != e; ++i) 121218893Sdim Ptr[i] = FillStr[i % FillStr.size()]; 122207619Srdivacky 123218893Sdim if (Diag.isDiagnosticInFlight()) 124218893Sdim Diag.SetDelayedDiagnostic(diag::err_cannot_open_file, 125221345Sdim ContentsEntry->getName(), ErrorStr); 126218893Sdim else 127218893Sdim Diag.Report(Loc, diag::err_cannot_open_file) 128221345Sdim << ContentsEntry->getName() << ErrorStr; 129206084Srdivacky 130218893Sdim Buffer.setInt(Buffer.getInt() | InvalidFlag); 131207619Srdivacky 132218893Sdim if (Invalid) *Invalid = true; 133218893Sdim return Buffer.getPointer(); 134198092Srdivacky } 135205219Srdivacky 136218893Sdim // Check that the file's size is the same as in the file entry (which may 137218893Sdim // have come from a stat cache). 138221345Sdim if (getRawBuffer()->getBufferSize() != (size_t)ContentsEntry->getSize()) { 139218893Sdim if (Diag.isDiagnosticInFlight()) 140218893Sdim Diag.SetDelayedDiagnostic(diag::err_file_modified, 141221345Sdim ContentsEntry->getName()); 142218893Sdim else 143218893Sdim Diag.Report(Loc, diag::err_file_modified) 144221345Sdim << ContentsEntry->getName(); 145218893Sdim 146218893Sdim Buffer.setInt(Buffer.getInt() | InvalidFlag); 147218893Sdim if (Invalid) *Invalid = true; 148218893Sdim return Buffer.getPointer(); 149218893Sdim } 150221345Sdim 151218893Sdim // If the buffer is valid, check to see if it has a UTF Byte Order Mark 152221345Sdim // (BOM). We only support UTF-8 with and without a BOM right now. See 153218893Sdim // http://en.wikipedia.org/wiki/Byte_order_mark for more information. 154226890Sdim StringRef BufStr = Buffer.getPointer()->getBuffer(); 155221345Sdim const char *InvalidBOM = llvm::StringSwitch<const char *>(BufStr) 156218893Sdim .StartsWith("\xFE\xFF", "UTF-16 (BE)") 157218893Sdim .StartsWith("\xFF\xFE", "UTF-16 (LE)") 158218893Sdim .StartsWith("\x00\x00\xFE\xFF", "UTF-32 (BE)") 159218893Sdim .StartsWith("\xFF\xFE\x00\x00", "UTF-32 (LE)") 160218893Sdim .StartsWith("\x2B\x2F\x76", "UTF-7") 161218893Sdim .StartsWith("\xF7\x64\x4C", "UTF-1") 162218893Sdim .StartsWith("\xDD\x73\x66\x73", "UTF-EBCDIC") 163218893Sdim .StartsWith("\x0E\xFE\xFF", "SDSU") 164218893Sdim .StartsWith("\xFB\xEE\x28", "BOCU-1") 165218893Sdim .StartsWith("\x84\x31\x95\x33", "GB-18030") 166218893Sdim .Default(0); 167218893Sdim 168221345Sdim if (InvalidBOM) { 169218893Sdim Diag.Report(Loc, diag::err_unsupported_bom) 170221345Sdim << InvalidBOM << ContentsEntry->getName(); 171218893Sdim Buffer.setInt(Buffer.getInt() | InvalidFlag); 172218893Sdim } 173218893Sdim 174205408Srdivacky if (Invalid) 175212904Sdim *Invalid = isBufferInvalid(); 176205408Srdivacky 177205408Srdivacky return Buffer.getPointer(); 178198092Srdivacky} 179198092Srdivacky 180226890Sdimunsigned LineTableInfo::getLineTableFilenameID(StringRef Name) { 181193326Sed // Look up the filename in the string table, returning the pre-existing value 182193326Sed // if it exists. 183198092Srdivacky llvm::StringMapEntry<unsigned> &Entry = 184224145Sdim FilenameIDs.GetOrCreateValue(Name, ~0U); 185193326Sed if (Entry.getValue() != ~0U) 186193326Sed return Entry.getValue(); 187198092Srdivacky 188193326Sed // Otherwise, assign this the next available ID. 189193326Sed Entry.setValue(FilenamesByID.size()); 190193326Sed FilenamesByID.push_back(&Entry); 191193326Sed return FilenamesByID.size()-1; 192193326Sed} 193193326Sed 194193326Sed/// AddLineNote - Add a line note to the line table that indicates that there 195245431Sdim/// is a \#line at the specified FID/Offset location which changes the presumed 196193326Sed/// location to LineNo/FilenameID. 197245431Sdimvoid LineTableInfo::AddLineNote(FileID FID, unsigned Offset, 198193326Sed unsigned LineNo, int FilenameID) { 199193326Sed std::vector<LineEntry> &Entries = LineEntries[FID]; 200198092Srdivacky 201193326Sed assert((Entries.empty() || Entries.back().FileOffset < Offset) && 202193326Sed "Adding line entries out of order!"); 203198092Srdivacky 204193326Sed SrcMgr::CharacteristicKind Kind = SrcMgr::C_User; 205193326Sed unsigned IncludeOffset = 0; 206198092Srdivacky 207193326Sed if (!Entries.empty()) { 208193326Sed // If this is a '#line 4' after '#line 42 "foo.h"', make sure to remember 209193326Sed // that we are still in "foo.h". 210193326Sed if (FilenameID == -1) 211193326Sed FilenameID = Entries.back().FilenameID; 212198092Srdivacky 213193326Sed // If we are after a line marker that switched us to system header mode, or 214193326Sed // that set #include information, preserve it. 215193326Sed Kind = Entries.back().FileKind; 216193326Sed IncludeOffset = Entries.back().IncludeOffset; 217193326Sed } 218198092Srdivacky 219193326Sed Entries.push_back(LineEntry::get(Offset, LineNo, FilenameID, Kind, 220193326Sed IncludeOffset)); 221193326Sed} 222193326Sed 223193326Sed/// AddLineNote This is the same as the previous version of AddLineNote, but is 224193326Sed/// used for GNU line markers. If EntryExit is 0, then this doesn't change the 225245431Sdim/// presumed \#include stack. If it is 1, this is a file entry, if it is 2 then 226193326Sed/// this is a file exit. FileKind specifies whether this is a system header or 227193326Sed/// extern C system header. 228245431Sdimvoid LineTableInfo::AddLineNote(FileID FID, unsigned Offset, 229193326Sed unsigned LineNo, int FilenameID, 230193326Sed unsigned EntryExit, 231193326Sed SrcMgr::CharacteristicKind FileKind) { 232193326Sed assert(FilenameID != -1 && "Unspecified filename should use other accessor"); 233198092Srdivacky 234193326Sed std::vector<LineEntry> &Entries = LineEntries[FID]; 235198092Srdivacky 236193326Sed assert((Entries.empty() || Entries.back().FileOffset < Offset) && 237193326Sed "Adding line entries out of order!"); 238193326Sed 239193326Sed unsigned IncludeOffset = 0; 240193326Sed if (EntryExit == 0) { // No #include stack change. 241193326Sed IncludeOffset = Entries.empty() ? 0 : Entries.back().IncludeOffset; 242193326Sed } else if (EntryExit == 1) { 243193326Sed IncludeOffset = Offset-1; 244193326Sed } else if (EntryExit == 2) { 245193326Sed assert(!Entries.empty() && Entries.back().IncludeOffset && 246193326Sed "PPDirectives should have caught case when popping empty include stack"); 247198092Srdivacky 248193326Sed // Get the include loc of the last entries' include loc as our include loc. 249193326Sed IncludeOffset = 0; 250193326Sed if (const LineEntry *PrevEntry = 251193326Sed FindNearestLineEntry(FID, Entries.back().IncludeOffset)) 252193326Sed IncludeOffset = PrevEntry->IncludeOffset; 253193326Sed } 254198092Srdivacky 255193326Sed Entries.push_back(LineEntry::get(Offset, LineNo, FilenameID, FileKind, 256193326Sed IncludeOffset)); 257193326Sed} 258193326Sed 259193326Sed 260193326Sed/// FindNearestLineEntry - Find the line entry nearest to FID that is before 261193326Sed/// it. If there is no line entry before Offset in FID, return null. 262245431Sdimconst LineEntry *LineTableInfo::FindNearestLineEntry(FileID FID, 263193326Sed unsigned Offset) { 264193326Sed const std::vector<LineEntry> &Entries = LineEntries[FID]; 265193326Sed assert(!Entries.empty() && "No #line entries for this FID after all!"); 266193326Sed 267193326Sed // It is very common for the query to be after the last #line, check this 268193326Sed // first. 269193326Sed if (Entries.back().FileOffset <= Offset) 270193326Sed return &Entries.back(); 271193326Sed 272193326Sed // Do a binary search to find the maximal element that is still before Offset. 273193326Sed std::vector<LineEntry>::const_iterator I = 274193326Sed std::upper_bound(Entries.begin(), Entries.end(), Offset); 275193326Sed if (I == Entries.begin()) return 0; 276193326Sed return &*--I; 277193326Sed} 278193326Sed 279193326Sed/// \brief Add a new line entry that has already been encoded into 280193326Sed/// the internal representation of the line table. 281245431Sdimvoid LineTableInfo::AddEntry(FileID FID, 282193326Sed const std::vector<LineEntry> &Entries) { 283193326Sed LineEntries[FID] = Entries; 284193326Sed} 285193326Sed 286193326Sed/// getLineTableFilenameID - Return the uniqued ID for the specified filename. 287198092Srdivacky/// 288226890Sdimunsigned SourceManager::getLineTableFilenameID(StringRef Name) { 289193326Sed if (LineTable == 0) 290193326Sed LineTable = new LineTableInfo(); 291224145Sdim return LineTable->getLineTableFilenameID(Name); 292193326Sed} 293193326Sed 294193326Sed 295193326Sed/// AddLineNote - Add a line note to the line table for the FileID and offset 296193326Sed/// specified by Loc. If FilenameID is -1, it is considered to be 297193326Sed/// unspecified. 298193326Sedvoid SourceManager::AddLineNote(SourceLocation Loc, unsigned LineNo, 299193326Sed int FilenameID) { 300226890Sdim std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(Loc); 301198092Srdivacky 302221345Sdim bool Invalid = false; 303221345Sdim const SLocEntry &Entry = getSLocEntry(LocInfo.first, &Invalid); 304221345Sdim if (!Entry.isFile() || Invalid) 305221345Sdim return; 306221345Sdim 307221345Sdim const SrcMgr::FileInfo &FileInfo = Entry.getFile(); 308193326Sed 309193326Sed // Remember that this file has #line directives now if it doesn't already. 310193326Sed const_cast<SrcMgr::FileInfo&>(FileInfo).setHasLineDirectives(); 311198092Srdivacky 312193326Sed if (LineTable == 0) 313193326Sed LineTable = new LineTableInfo(); 314245431Sdim LineTable->AddLineNote(LocInfo.first, LocInfo.second, LineNo, FilenameID); 315193326Sed} 316193326Sed 317193326Sed/// AddLineNote - Add a GNU line marker to the line table. 318193326Sedvoid SourceManager::AddLineNote(SourceLocation Loc, unsigned LineNo, 319193326Sed int FilenameID, bool IsFileEntry, 320193326Sed bool IsFileExit, bool IsSystemHeader, 321193326Sed bool IsExternCHeader) { 322193326Sed // If there is no filename and no flags, this is treated just like a #line, 323193326Sed // which does not change the flags of the previous line marker. 324193326Sed if (FilenameID == -1) { 325193326Sed assert(!IsFileEntry && !IsFileExit && !IsSystemHeader && !IsExternCHeader && 326193326Sed "Can't set flags without setting the filename!"); 327193326Sed return AddLineNote(Loc, LineNo, FilenameID); 328193326Sed } 329198092Srdivacky 330226890Sdim std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(Loc); 331198092Srdivacky 332221345Sdim bool Invalid = false; 333221345Sdim const SLocEntry &Entry = getSLocEntry(LocInfo.first, &Invalid); 334221345Sdim if (!Entry.isFile() || Invalid) 335221345Sdim return; 336221345Sdim 337221345Sdim const SrcMgr::FileInfo &FileInfo = Entry.getFile(); 338221345Sdim 339193326Sed // Remember that this file has #line directives now if it doesn't already. 340193326Sed const_cast<SrcMgr::FileInfo&>(FileInfo).setHasLineDirectives(); 341198092Srdivacky 342193326Sed if (LineTable == 0) 343193326Sed LineTable = new LineTableInfo(); 344198092Srdivacky 345193326Sed SrcMgr::CharacteristicKind FileKind; 346193326Sed if (IsExternCHeader) 347193326Sed FileKind = SrcMgr::C_ExternCSystem; 348193326Sed else if (IsSystemHeader) 349193326Sed FileKind = SrcMgr::C_System; 350193326Sed else 351193326Sed FileKind = SrcMgr::C_User; 352198092Srdivacky 353193326Sed unsigned EntryExit = 0; 354193326Sed if (IsFileEntry) 355193326Sed EntryExit = 1; 356193326Sed else if (IsFileExit) 357193326Sed EntryExit = 2; 358198092Srdivacky 359245431Sdim LineTable->AddLineNote(LocInfo.first, LocInfo.second, LineNo, FilenameID, 360193326Sed EntryExit, FileKind); 361193326Sed} 362193326Sed 363193326SedLineTableInfo &SourceManager::getLineTable() { 364193326Sed if (LineTable == 0) 365193326Sed LineTable = new LineTableInfo(); 366193326Sed return *LineTable; 367193326Sed} 368193326Sed 369193326Sed//===----------------------------------------------------------------------===// 370193326Sed// Private 'Create' methods. 371193326Sed//===----------------------------------------------------------------------===// 372193326Sed 373245431SdimSourceManager::SourceManager(DiagnosticsEngine &Diag, FileManager &FileMgr, 374245431Sdim bool UserFilesAreVolatile) 375221345Sdim : Diag(Diag), FileMgr(FileMgr), OverridenFilesKeepOriginalName(true), 376245431Sdim UserFilesAreVolatile(UserFilesAreVolatile), 377218893Sdim ExternalSLocEntries(0), LineTable(0), NumLinearScans(0), 378235633Sdim NumBinaryProbes(0), FakeBufferForRecovery(0), 379235633Sdim FakeContentCacheForRecovery(0) { 380218893Sdim clearIDTables(); 381218893Sdim Diag.setSourceManager(this); 382218893Sdim} 383218893Sdim 384193326SedSourceManager::~SourceManager() { 385193326Sed delete LineTable; 386198092Srdivacky 387193326Sed // Delete FileEntry objects corresponding to content caches. Since the actual 388193326Sed // content cache objects are bump pointer allocated, we just have to run the 389193326Sed // dtors, but we call the deallocate method for completeness. 390193326Sed for (unsigned i = 0, e = MemBufferInfos.size(); i != e; ++i) { 391235633Sdim if (MemBufferInfos[i]) { 392235633Sdim MemBufferInfos[i]->~ContentCache(); 393235633Sdim ContentCacheAlloc.Deallocate(MemBufferInfos[i]); 394235633Sdim } 395193326Sed } 396193326Sed for (llvm::DenseMap<const FileEntry*, SrcMgr::ContentCache*>::iterator 397193326Sed I = FileInfos.begin(), E = FileInfos.end(); I != E; ++I) { 398235633Sdim if (I->second) { 399235633Sdim I->second->~ContentCache(); 400235633Sdim ContentCacheAlloc.Deallocate(I->second); 401235633Sdim } 402193326Sed } 403221345Sdim 404221345Sdim delete FakeBufferForRecovery; 405235633Sdim delete FakeContentCacheForRecovery; 406226890Sdim 407226890Sdim for (llvm::DenseMap<FileID, MacroArgsMap *>::iterator 408226890Sdim I = MacroArgsCacheMap.begin(),E = MacroArgsCacheMap.end(); I!=E; ++I) { 409226890Sdim delete I->second; 410226890Sdim } 411193326Sed} 412193326Sed 413193326Sedvoid SourceManager::clearIDTables() { 414193326Sed MainFileID = FileID(); 415226890Sdim LocalSLocEntryTable.clear(); 416226890Sdim LoadedSLocEntryTable.clear(); 417226890Sdim SLocEntryLoaded.clear(); 418193326Sed LastLineNoFileIDQuery = FileID(); 419193326Sed LastLineNoContentCache = 0; 420193326Sed LastFileIDLookup = FileID(); 421198092Srdivacky 422193326Sed if (LineTable) 423193326Sed LineTable->clear(); 424198092Srdivacky 425226890Sdim // Use up FileID #0 as an invalid expansion. 426226890Sdim NextLocalOffset = 0; 427226890Sdim CurrentLoadedOffset = MaxLoadedOffset; 428226890Sdim createExpansionLoc(SourceLocation(),SourceLocation(),SourceLocation(), 1); 429193326Sed} 430193326Sed 431193326Sed/// getOrCreateContentCache - Create or return a cached ContentCache for the 432193326Sed/// specified file. 433193326Sedconst ContentCache * 434245431SdimSourceManager::getOrCreateContentCache(const FileEntry *FileEnt, 435245431Sdim bool isSystemFile) { 436193326Sed assert(FileEnt && "Didn't specify a file entry to use?"); 437198092Srdivacky 438193326Sed // Do we already have information about this file? 439193326Sed ContentCache *&Entry = FileInfos[FileEnt]; 440193326Sed if (Entry) return Entry; 441198092Srdivacky 442193326Sed // Nope, create a new Cache entry. Make sure it is at least 8-byte aligned 443193326Sed // so that FileInfo can use the low 3 bits of the pointer for its own 444193326Sed // nefarious purposes. 445193326Sed unsigned EntryAlign = llvm::AlignOf<ContentCache>::Alignment; 446193326Sed EntryAlign = std::max(8U, EntryAlign); 447193326Sed Entry = ContentCacheAlloc.Allocate<ContentCache>(1, EntryAlign); 448221345Sdim 449245431Sdim if (OverriddenFilesInfo) { 450245431Sdim // If the file contents are overridden with contents from another file, 451245431Sdim // pass that file to ContentCache. 452245431Sdim llvm::DenseMap<const FileEntry *, const FileEntry *>::iterator 453245431Sdim overI = OverriddenFilesInfo->OverriddenFiles.find(FileEnt); 454245431Sdim if (overI == OverriddenFilesInfo->OverriddenFiles.end()) 455245431Sdim new (Entry) ContentCache(FileEnt); 456245431Sdim else 457245431Sdim new (Entry) ContentCache(OverridenFilesKeepOriginalName ? FileEnt 458245431Sdim : overI->second, 459245431Sdim overI->second); 460245431Sdim } else { 461221345Sdim new (Entry) ContentCache(FileEnt); 462245431Sdim } 463221345Sdim 464245431Sdim Entry->IsSystemFile = isSystemFile; 465245431Sdim 466193326Sed return Entry; 467193326Sed} 468193326Sed 469193326Sed 470193326Sed/// createMemBufferContentCache - Create a new ContentCache for the specified 471193326Sed/// memory buffer. This does no caching. 472193326Sedconst ContentCache* 473193326SedSourceManager::createMemBufferContentCache(const MemoryBuffer *Buffer) { 474193326Sed // Add a new ContentCache to the MemBufferInfos list and return it. Make sure 475193326Sed // it is at least 8-byte aligned so that FileInfo can use the low 3 bits of 476193326Sed // the pointer for its own nefarious purposes. 477193326Sed unsigned EntryAlign = llvm::AlignOf<ContentCache>::Alignment; 478193326Sed EntryAlign = std::max(8U, EntryAlign); 479193326Sed ContentCache *Entry = ContentCacheAlloc.Allocate<ContentCache>(1, EntryAlign); 480193326Sed new (Entry) ContentCache(); 481193326Sed MemBufferInfos.push_back(Entry); 482193326Sed Entry->setBuffer(Buffer); 483193326Sed return Entry; 484193326Sed} 485193326Sed 486235633Sdimconst SrcMgr::SLocEntry &SourceManager::loadSLocEntry(unsigned Index, 487235633Sdim bool *Invalid) const { 488235633Sdim assert(!SLocEntryLoaded[Index]); 489235633Sdim if (ExternalSLocEntries->ReadSLocEntry(-(static_cast<int>(Index) + 2))) { 490235633Sdim if (Invalid) 491235633Sdim *Invalid = true; 492235633Sdim // If the file of the SLocEntry changed we could still have loaded it. 493235633Sdim if (!SLocEntryLoaded[Index]) { 494235633Sdim // Try to recover; create a SLocEntry so the rest of clang can handle it. 495235633Sdim LoadedSLocEntryTable[Index] = SLocEntry::get(0, 496235633Sdim FileInfo::get(SourceLocation(), 497235633Sdim getFakeContentCacheForRecovery(), 498235633Sdim SrcMgr::C_User)); 499235633Sdim } 500235633Sdim } 501235633Sdim 502235633Sdim return LoadedSLocEntryTable[Index]; 503235633Sdim} 504235633Sdim 505226890Sdimstd::pair<int, unsigned> 506226890SdimSourceManager::AllocateLoadedSLocEntries(unsigned NumSLocEntries, 507226890Sdim unsigned TotalSize) { 508226890Sdim assert(ExternalSLocEntries && "Don't have an external sloc source"); 509226890Sdim LoadedSLocEntryTable.resize(LoadedSLocEntryTable.size() + NumSLocEntries); 510226890Sdim SLocEntryLoaded.resize(LoadedSLocEntryTable.size()); 511226890Sdim CurrentLoadedOffset -= TotalSize; 512226890Sdim assert(CurrentLoadedOffset >= NextLocalOffset && "Out of source locations"); 513226890Sdim int ID = LoadedSLocEntryTable.size(); 514226890Sdim return std::make_pair(-ID - 1, CurrentLoadedOffset); 515193326Sed} 516193326Sed 517221345Sdim/// \brief As part of recovering from missing or changed content, produce a 518221345Sdim/// fake, non-empty buffer. 519221345Sdimconst llvm::MemoryBuffer *SourceManager::getFakeBufferForRecovery() const { 520221345Sdim if (!FakeBufferForRecovery) 521221345Sdim FakeBufferForRecovery 522221345Sdim = llvm::MemoryBuffer::getMemBuffer("<<<INVALID BUFFER>>"); 523221345Sdim 524221345Sdim return FakeBufferForRecovery; 525221345Sdim} 526193326Sed 527235633Sdim/// \brief As part of recovering from missing or changed content, produce a 528235633Sdim/// fake content cache. 529235633Sdimconst SrcMgr::ContentCache * 530235633SdimSourceManager::getFakeContentCacheForRecovery() const { 531235633Sdim if (!FakeContentCacheForRecovery) { 532235633Sdim FakeContentCacheForRecovery = new ContentCache(); 533235633Sdim FakeContentCacheForRecovery->replaceBuffer(getFakeBufferForRecovery(), 534235633Sdim /*DoNotFree=*/true); 535235633Sdim } 536235633Sdim return FakeContentCacheForRecovery; 537235633Sdim} 538235633Sdim 539263509Sdim/// \brief Returns the previous in-order FileID or an invalid FileID if there 540263509Sdim/// is no previous one. 541263509SdimFileID SourceManager::getPreviousFileID(FileID FID) const { 542263509Sdim if (FID.isInvalid()) 543263509Sdim return FileID(); 544263509Sdim 545263509Sdim int ID = FID.ID; 546263509Sdim if (ID == -1) 547263509Sdim return FileID(); 548263509Sdim 549263509Sdim if (ID > 0) { 550263509Sdim if (ID-1 == 0) 551263509Sdim return FileID(); 552263509Sdim } else if (unsigned(-(ID-1) - 2) >= LoadedSLocEntryTable.size()) { 553263509Sdim return FileID(); 554263509Sdim } 555263509Sdim 556263509Sdim return FileID::get(ID-1); 557263509Sdim} 558263509Sdim 559263509Sdim/// \brief Returns the next in-order FileID or an invalid FileID if there is 560263509Sdim/// no next one. 561263509SdimFileID SourceManager::getNextFileID(FileID FID) const { 562263509Sdim if (FID.isInvalid()) 563263509Sdim return FileID(); 564263509Sdim 565263509Sdim int ID = FID.ID; 566263509Sdim if (ID > 0) { 567263509Sdim if (unsigned(ID+1) >= local_sloc_entry_size()) 568263509Sdim return FileID(); 569263509Sdim } else if (ID+1 >= -1) { 570263509Sdim return FileID(); 571263509Sdim } 572263509Sdim 573263509Sdim return FileID::get(ID+1); 574263509Sdim} 575263509Sdim 576193326Sed//===----------------------------------------------------------------------===// 577226890Sdim// Methods to create new FileID's and macro expansions. 578193326Sed//===----------------------------------------------------------------------===// 579193326Sed 580212904Sdim/// createFileID - Create a new FileID for the specified ContentCache and 581193326Sed/// include position. This works regardless of whether the ContentCache 582193326Sed/// corresponds to a file or some other input source. 583193326SedFileID SourceManager::createFileID(const ContentCache *File, 584193326Sed SourceLocation IncludePos, 585193326Sed SrcMgr::CharacteristicKind FileCharacter, 586226890Sdim int LoadedID, unsigned LoadedOffset) { 587226890Sdim if (LoadedID < 0) { 588226890Sdim assert(LoadedID != -1 && "Loading sentinel FileID"); 589226890Sdim unsigned Index = unsigned(-LoadedID) - 2; 590226890Sdim assert(Index < LoadedSLocEntryTable.size() && "FileID out of range"); 591226890Sdim assert(!SLocEntryLoaded[Index] && "FileID already loaded"); 592226890Sdim LoadedSLocEntryTable[Index] = SLocEntry::get(LoadedOffset, 593226890Sdim FileInfo::get(IncludePos, File, FileCharacter)); 594226890Sdim SLocEntryLoaded[Index] = true; 595226890Sdim return FileID::get(LoadedID); 596193326Sed } 597226890Sdim LocalSLocEntryTable.push_back(SLocEntry::get(NextLocalOffset, 598226890Sdim FileInfo::get(IncludePos, File, 599226890Sdim FileCharacter))); 600193326Sed unsigned FileSize = File->getSize(); 601226890Sdim assert(NextLocalOffset + FileSize + 1 > NextLocalOffset && 602226890Sdim NextLocalOffset + FileSize + 1 <= CurrentLoadedOffset && 603226890Sdim "Ran out of source locations!"); 604226890Sdim // We do a +1 here because we want a SourceLocation that means "the end of the 605226890Sdim // file", e.g. for the "no newline at the end of the file" diagnostic. 606226890Sdim NextLocalOffset += FileSize + 1; 607198092Srdivacky 608193326Sed // Set LastFileIDLookup to the newly created file. The next getFileID call is 609193326Sed // almost guaranteed to be from that file. 610226890Sdim FileID FID = FileID::get(LocalSLocEntryTable.size()-1); 611194711Sed return LastFileIDLookup = FID; 612193326Sed} 613193326Sed 614224145SdimSourceLocation 615226890SdimSourceManager::createMacroArgExpansionLoc(SourceLocation SpellingLoc, 616226890Sdim SourceLocation ExpansionLoc, 617226890Sdim unsigned TokLength) { 618226890Sdim ExpansionInfo Info = ExpansionInfo::createForMacroArg(SpellingLoc, 619226890Sdim ExpansionLoc); 620226890Sdim return createExpansionLocImpl(Info, TokLength); 621224145Sdim} 622224145Sdim 623226890SdimSourceLocation 624226890SdimSourceManager::createExpansionLoc(SourceLocation SpellingLoc, 625226890Sdim SourceLocation ExpansionLocStart, 626226890Sdim SourceLocation ExpansionLocEnd, 627226890Sdim unsigned TokLength, 628226890Sdim int LoadedID, 629226890Sdim unsigned LoadedOffset) { 630226890Sdim ExpansionInfo Info = ExpansionInfo::create(SpellingLoc, ExpansionLocStart, 631226890Sdim ExpansionLocEnd); 632226890Sdim return createExpansionLocImpl(Info, TokLength, LoadedID, LoadedOffset); 633224145Sdim} 634224145Sdim 635224145SdimSourceLocation 636226890SdimSourceManager::createExpansionLocImpl(const ExpansionInfo &Info, 637226890Sdim unsigned TokLength, 638226890Sdim int LoadedID, 639226890Sdim unsigned LoadedOffset) { 640226890Sdim if (LoadedID < 0) { 641226890Sdim assert(LoadedID != -1 && "Loading sentinel FileID"); 642226890Sdim unsigned Index = unsigned(-LoadedID) - 2; 643226890Sdim assert(Index < LoadedSLocEntryTable.size() && "FileID out of range"); 644226890Sdim assert(!SLocEntryLoaded[Index] && "FileID already loaded"); 645226890Sdim LoadedSLocEntryTable[Index] = SLocEntry::get(LoadedOffset, Info); 646226890Sdim SLocEntryLoaded[Index] = true; 647226890Sdim return SourceLocation::getMacroLoc(LoadedOffset); 648193326Sed } 649226890Sdim LocalSLocEntryTable.push_back(SLocEntry::get(NextLocalOffset, Info)); 650226890Sdim assert(NextLocalOffset + TokLength + 1 > NextLocalOffset && 651226890Sdim NextLocalOffset + TokLength + 1 <= CurrentLoadedOffset && 652226890Sdim "Ran out of source locations!"); 653226890Sdim // See createFileID for that +1. 654226890Sdim NextLocalOffset += TokLength + 1; 655226890Sdim return SourceLocation::getMacroLoc(NextLocalOffset - (TokLength + 1)); 656193326Sed} 657193326Sed 658200583Srdivackyconst llvm::MemoryBuffer * 659205219SrdivackySourceManager::getMemoryBufferForFile(const FileEntry *File, 660205219Srdivacky bool *Invalid) { 661200583Srdivacky const SrcMgr::ContentCache *IR = getOrCreateContentCache(File); 662205219Srdivacky assert(IR && "getOrCreateContentCache() cannot return NULL"); 663207619Srdivacky return IR->getBuffer(Diag, *this, SourceLocation(), Invalid); 664200583Srdivacky} 665200583Srdivacky 666218893Sdimvoid SourceManager::overrideFileContents(const FileEntry *SourceFile, 667212904Sdim const llvm::MemoryBuffer *Buffer, 668212904Sdim bool DoNotFree) { 669200583Srdivacky const SrcMgr::ContentCache *IR = getOrCreateContentCache(SourceFile); 670218893Sdim assert(IR && "getOrCreateContentCache() cannot return NULL"); 671200583Srdivacky 672212904Sdim const_cast<SrcMgr::ContentCache *>(IR)->replaceBuffer(Buffer, DoNotFree); 673235633Sdim const_cast<SrcMgr::ContentCache *>(IR)->BufferOverridden = true; 674245431Sdim 675245431Sdim getOverriddenFilesInfo().OverriddenFilesWithBuffer.insert(SourceFile); 676200583Srdivacky} 677200583Srdivacky 678221345Sdimvoid SourceManager::overrideFileContents(const FileEntry *SourceFile, 679221345Sdim const FileEntry *NewFile) { 680221345Sdim assert(SourceFile->getSize() == NewFile->getSize() && 681221345Sdim "Different sizes, use the FileManager to create a virtual file with " 682221345Sdim "the correct size"); 683221345Sdim assert(FileInfos.count(SourceFile) == 0 && 684221345Sdim "This function should be called at the initialization stage, before " 685221345Sdim "any parsing occurs."); 686245431Sdim getOverriddenFilesInfo().OverriddenFiles[SourceFile] = NewFile; 687221345Sdim} 688221345Sdim 689245431Sdimvoid SourceManager::disableFileContentsOverride(const FileEntry *File) { 690245431Sdim if (!isFileOverridden(File)) 691245431Sdim return; 692245431Sdim 693245431Sdim const SrcMgr::ContentCache *IR = getOrCreateContentCache(File); 694245431Sdim const_cast<SrcMgr::ContentCache *>(IR)->replaceBuffer(0); 695245431Sdim const_cast<SrcMgr::ContentCache *>(IR)->ContentsEntry = IR->OrigEntry; 696245431Sdim 697245431Sdim assert(OverriddenFilesInfo); 698245431Sdim OverriddenFilesInfo->OverriddenFiles.erase(File); 699245431Sdim OverriddenFilesInfo->OverriddenFilesWithBuffer.erase(File); 700245431Sdim} 701245431Sdim 702226890SdimStringRef SourceManager::getBufferData(FileID FID, bool *Invalid) const { 703205408Srdivacky bool MyInvalid = false; 704226890Sdim const SLocEntry &SLoc = getSLocEntry(FID, &MyInvalid); 705221345Sdim if (!SLoc.isFile() || MyInvalid) { 706218893Sdim if (Invalid) 707218893Sdim *Invalid = true; 708218893Sdim return "<<<<<INVALID SOURCE LOCATION>>>>>"; 709218893Sdim } 710218893Sdim 711218893Sdim const llvm::MemoryBuffer *Buf 712218893Sdim = SLoc.getFile().getContentCache()->getBuffer(Diag, *this, SourceLocation(), 713218893Sdim &MyInvalid); 714205219Srdivacky if (Invalid) 715205408Srdivacky *Invalid = MyInvalid; 716205408Srdivacky 717205408Srdivacky if (MyInvalid) 718218893Sdim return "<<<<<INVALID SOURCE LOCATION>>>>>"; 719205219Srdivacky 720205219Srdivacky return Buf->getBuffer(); 721193326Sed} 722193326Sed 723193326Sed//===----------------------------------------------------------------------===// 724193326Sed// SourceLocation manipulation methods. 725193326Sed//===----------------------------------------------------------------------===// 726193326Sed 727226890Sdim/// \brief Return the FileID for a SourceLocation. 728193326Sed/// 729226890Sdim/// This is the cache-miss path of getFileID. Not as hot as that function, but 730226890Sdim/// still very important. It is responsible for finding the entry in the 731226890Sdim/// SLocEntry tables that contains the specified location. 732193326SedFileID SourceManager::getFileIDSlow(unsigned SLocOffset) const { 733221345Sdim if (!SLocOffset) 734221345Sdim return FileID::get(0); 735198092Srdivacky 736226890Sdim // Now it is time to search for the correct file. See where the SLocOffset 737226890Sdim // sits in the global view and consult local or loaded buffers for it. 738226890Sdim if (SLocOffset < NextLocalOffset) 739226890Sdim return getFileIDLocal(SLocOffset); 740226890Sdim return getFileIDLoaded(SLocOffset); 741226890Sdim} 742226890Sdim 743226890Sdim/// \brief Return the FileID for a SourceLocation with a low offset. 744226890Sdim/// 745226890Sdim/// This function knows that the SourceLocation is in a local buffer, not a 746226890Sdim/// loaded one. 747226890SdimFileID SourceManager::getFileIDLocal(unsigned SLocOffset) const { 748226890Sdim assert(SLocOffset < NextLocalOffset && "Bad function choice"); 749226890Sdim 750193326Sed // After the first and second level caches, I see two common sorts of 751226890Sdim // behavior: 1) a lot of searched FileID's are "near" the cached file 752226890Sdim // location or are "near" the cached expansion location. 2) others are just 753193326Sed // completely random and may be a very long way away. 754193326Sed // 755193326Sed // To handle this, we do a linear search for up to 8 steps to catch #1 quickly 756193326Sed // then we fall back to a less cache efficient, but more scalable, binary 757193326Sed // search to find the location. 758198092Srdivacky 759193326Sed // See if this is near the file point - worst case we start scanning from the 760193326Sed // most newly created FileID. 761252723Sdim const SrcMgr::SLocEntry *I; 762198092Srdivacky 763226890Sdim if (LastFileIDLookup.ID < 0 || 764226890Sdim LocalSLocEntryTable[LastFileIDLookup.ID].getOffset() < SLocOffset) { 765193326Sed // Neither loc prunes our search. 766226890Sdim I = LocalSLocEntryTable.end(); 767193326Sed } else { 768193326Sed // Perhaps it is near the file point. 769226890Sdim I = LocalSLocEntryTable.begin()+LastFileIDLookup.ID; 770193326Sed } 771193326Sed 772193326Sed // Find the FileID that contains this. "I" is an iterator that points to a 773193326Sed // FileID whose offset is known to be larger than SLocOffset. 774193326Sed unsigned NumProbes = 0; 775193326Sed while (1) { 776193326Sed --I; 777193326Sed if (I->getOffset() <= SLocOffset) { 778226890Sdim FileID Res = FileID::get(int(I - LocalSLocEntryTable.begin())); 779193326Sed 780226890Sdim // If this isn't an expansion, remember it. We have good locality across 781226890Sdim // FileID lookups. 782226890Sdim if (!I->isExpansion()) 783193326Sed LastFileIDLookup = Res; 784193326Sed NumLinearScans += NumProbes+1; 785193326Sed return Res; 786193326Sed } 787193326Sed if (++NumProbes == 8) 788193326Sed break; 789193326Sed } 790198092Srdivacky 791193326Sed // Convert "I" back into an index. We know that it is an entry whose index is 792193326Sed // larger than the offset we are looking for. 793226890Sdim unsigned GreaterIndex = I - LocalSLocEntryTable.begin(); 794193326Sed // LessIndex - This is the lower bound of the range that we're searching. 795193326Sed // We know that the offset corresponding to the FileID is is less than 796193326Sed // SLocOffset. 797193326Sed unsigned LessIndex = 0; 798193326Sed NumProbes = 0; 799193326Sed while (1) { 800221345Sdim bool Invalid = false; 801193326Sed unsigned MiddleIndex = (GreaterIndex-LessIndex)/2+LessIndex; 802226890Sdim unsigned MidOffset = getLocalSLocEntry(MiddleIndex, &Invalid).getOffset(); 803221345Sdim if (Invalid) 804221345Sdim return FileID::get(0); 805221345Sdim 806193326Sed ++NumProbes; 807198092Srdivacky 808193326Sed // If the offset of the midpoint is too large, chop the high side of the 809193326Sed // range to the midpoint. 810193326Sed if (MidOffset > SLocOffset) { 811193326Sed GreaterIndex = MiddleIndex; 812193326Sed continue; 813193326Sed } 814198092Srdivacky 815193326Sed // If the middle index contains the value, succeed and return. 816226890Sdim // FIXME: This could be made faster by using a function that's aware of 817226890Sdim // being in the local area. 818193326Sed if (isOffsetInFileID(FileID::get(MiddleIndex), SLocOffset)) { 819193326Sed FileID Res = FileID::get(MiddleIndex); 820193326Sed 821226890Sdim // If this isn't a macro expansion, remember it. We have good locality 822193326Sed // across FileID lookups. 823226890Sdim if (!LocalSLocEntryTable[MiddleIndex].isExpansion()) 824193326Sed LastFileIDLookup = Res; 825193326Sed NumBinaryProbes += NumProbes; 826193326Sed return Res; 827193326Sed } 828198092Srdivacky 829193326Sed // Otherwise, move the low-side up to the middle index. 830193326Sed LessIndex = MiddleIndex; 831193326Sed } 832193326Sed} 833193326Sed 834226890Sdim/// \brief Return the FileID for a SourceLocation with a high offset. 835226890Sdim/// 836226890Sdim/// This function knows that the SourceLocation is in a loaded buffer, not a 837226890Sdim/// local one. 838226890SdimFileID SourceManager::getFileIDLoaded(unsigned SLocOffset) const { 839226890Sdim // Sanity checking, otherwise a bug may lead to hanging in release build. 840235633Sdim if (SLocOffset < CurrentLoadedOffset) { 841235633Sdim assert(0 && "Invalid SLocOffset or bad function choice"); 842226890Sdim return FileID(); 843235633Sdim } 844226890Sdim 845226890Sdim // Essentially the same as the local case, but the loaded array is sorted 846226890Sdim // in the other direction. 847226890Sdim 848226890Sdim // First do a linear scan from the last lookup position, if possible. 849226890Sdim unsigned I; 850226890Sdim int LastID = LastFileIDLookup.ID; 851226890Sdim if (LastID >= 0 || getLoadedSLocEntryByID(LastID).getOffset() < SLocOffset) 852226890Sdim I = 0; 853226890Sdim else 854226890Sdim I = (-LastID - 2) + 1; 855226890Sdim 856226890Sdim unsigned NumProbes; 857226890Sdim for (NumProbes = 0; NumProbes < 8; ++NumProbes, ++I) { 858226890Sdim // Make sure the entry is loaded! 859226890Sdim const SrcMgr::SLocEntry &E = getLoadedSLocEntry(I); 860226890Sdim if (E.getOffset() <= SLocOffset) { 861226890Sdim FileID Res = FileID::get(-int(I) - 2); 862226890Sdim 863226890Sdim if (!E.isExpansion()) 864226890Sdim LastFileIDLookup = Res; 865226890Sdim NumLinearScans += NumProbes + 1; 866226890Sdim return Res; 867226890Sdim } 868226890Sdim } 869226890Sdim 870226890Sdim // Linear scan failed. Do the binary search. Note the reverse sorting of the 871226890Sdim // table: GreaterIndex is the one where the offset is greater, which is 872226890Sdim // actually a lower index! 873226890Sdim unsigned GreaterIndex = I; 874226890Sdim unsigned LessIndex = LoadedSLocEntryTable.size(); 875226890Sdim NumProbes = 0; 876226890Sdim while (1) { 877226890Sdim ++NumProbes; 878226890Sdim unsigned MiddleIndex = (LessIndex - GreaterIndex) / 2 + GreaterIndex; 879226890Sdim const SrcMgr::SLocEntry &E = getLoadedSLocEntry(MiddleIndex); 880252723Sdim if (E.getOffset() == 0) 881252723Sdim return FileID(); // invalid entry. 882226890Sdim 883226890Sdim ++NumProbes; 884226890Sdim 885226890Sdim if (E.getOffset() > SLocOffset) { 886252723Sdim // Sanity checking, otherwise a bug may lead to hanging in release build. 887252723Sdim if (GreaterIndex == MiddleIndex) { 888252723Sdim assert(0 && "binary search missed the entry"); 889252723Sdim return FileID(); 890252723Sdim } 891226890Sdim GreaterIndex = MiddleIndex; 892226890Sdim continue; 893226890Sdim } 894226890Sdim 895226890Sdim if (isOffsetInFileID(FileID::get(-int(MiddleIndex) - 2), SLocOffset)) { 896226890Sdim FileID Res = FileID::get(-int(MiddleIndex) - 2); 897226890Sdim if (!E.isExpansion()) 898226890Sdim LastFileIDLookup = Res; 899226890Sdim NumBinaryProbes += NumProbes; 900226890Sdim return Res; 901226890Sdim } 902226890Sdim 903252723Sdim // Sanity checking, otherwise a bug may lead to hanging in release build. 904252723Sdim if (LessIndex == MiddleIndex) { 905252723Sdim assert(0 && "binary search missed the entry"); 906252723Sdim return FileID(); 907252723Sdim } 908226890Sdim LessIndex = MiddleIndex; 909226890Sdim } 910226890Sdim} 911226890Sdim 912193326SedSourceLocation SourceManager:: 913226890SdimgetExpansionLocSlowCase(SourceLocation Loc) const { 914193326Sed do { 915203955Srdivacky // Note: If Loc indicates an offset into a token that came from a macro 916203955Srdivacky // expansion (e.g. the 5th character of the token) we do not want to add 917226890Sdim // this offset when going to the expansion location. The expansion 918203955Srdivacky // location is the macro invocation, which the offset has nothing to do 919203955Srdivacky // with. This is unlike when we get the spelling loc, because the offset 920203955Srdivacky // directly correspond to the token whose spelling we're inspecting. 921226890Sdim Loc = getSLocEntry(getFileID(Loc)).getExpansion().getExpansionLocStart(); 922193326Sed } while (!Loc.isFileID()); 923193326Sed 924193326Sed return Loc; 925193326Sed} 926193326Sed 927193326SedSourceLocation SourceManager::getSpellingLocSlowCase(SourceLocation Loc) const { 928193326Sed do { 929193326Sed std::pair<FileID, unsigned> LocInfo = getDecomposedLoc(Loc); 930226890Sdim Loc = getSLocEntry(LocInfo.first).getExpansion().getSpellingLoc(); 931226890Sdim Loc = Loc.getLocWithOffset(LocInfo.second); 932193326Sed } while (!Loc.isFileID()); 933193326Sed return Loc; 934193326Sed} 935193326Sed 936226890SdimSourceLocation SourceManager::getFileLocSlowCase(SourceLocation Loc) const { 937226890Sdim do { 938226890Sdim if (isMacroArgExpansion(Loc)) 939226890Sdim Loc = getImmediateSpellingLoc(Loc); 940226890Sdim else 941226890Sdim Loc = getImmediateExpansionRange(Loc).first; 942226890Sdim } while (!Loc.isFileID()); 943226890Sdim return Loc; 944226890Sdim} 945193326Sed 946226890Sdim 947193326Sedstd::pair<FileID, unsigned> 948226890SdimSourceManager::getDecomposedExpansionLocSlowCase( 949224145Sdim const SrcMgr::SLocEntry *E) const { 950226890Sdim // If this is an expansion record, walk through all the expansion points. 951193326Sed FileID FID; 952193326Sed SourceLocation Loc; 953224145Sdim unsigned Offset; 954193326Sed do { 955226890Sdim Loc = E->getExpansion().getExpansionLocStart(); 956198092Srdivacky 957193326Sed FID = getFileID(Loc); 958193326Sed E = &getSLocEntry(FID); 959224145Sdim Offset = Loc.getOffset()-E->getOffset(); 960193326Sed } while (!Loc.isFileID()); 961198092Srdivacky 962193326Sed return std::make_pair(FID, Offset); 963193326Sed} 964193326Sed 965193326Sedstd::pair<FileID, unsigned> 966193326SedSourceManager::getDecomposedSpellingLocSlowCase(const SrcMgr::SLocEntry *E, 967193326Sed unsigned Offset) const { 968226890Sdim // If this is an expansion record, walk through all the expansion points. 969193326Sed FileID FID; 970193326Sed SourceLocation Loc; 971193326Sed do { 972226890Sdim Loc = E->getExpansion().getSpellingLoc(); 973226890Sdim Loc = Loc.getLocWithOffset(Offset); 974198092Srdivacky 975193326Sed FID = getFileID(Loc); 976193326Sed E = &getSLocEntry(FID); 977226890Sdim Offset = Loc.getOffset()-E->getOffset(); 978193326Sed } while (!Loc.isFileID()); 979198092Srdivacky 980193326Sed return std::make_pair(FID, Offset); 981193326Sed} 982193326Sed 983193326Sed/// getImmediateSpellingLoc - Given a SourceLocation object, return the 984193326Sed/// spelling location referenced by the ID. This is the first level down 985193326Sed/// towards the place where the characters that make up the lexed token can be 986193326Sed/// found. This should not generally be used by clients. 987193326SedSourceLocation SourceManager::getImmediateSpellingLoc(SourceLocation Loc) const{ 988193326Sed if (Loc.isFileID()) return Loc; 989193326Sed std::pair<FileID, unsigned> LocInfo = getDecomposedLoc(Loc); 990226890Sdim Loc = getSLocEntry(LocInfo.first).getExpansion().getSpellingLoc(); 991226890Sdim return Loc.getLocWithOffset(LocInfo.second); 992193326Sed} 993193326Sed 994193326Sed 995226890Sdim/// getImmediateExpansionRange - Loc is required to be an expansion location. 996226890Sdim/// Return the start/end of the expansion information. 997193326Sedstd::pair<SourceLocation,SourceLocation> 998226890SdimSourceManager::getImmediateExpansionRange(SourceLocation Loc) const { 999226890Sdim assert(Loc.isMacroID() && "Not a macro expansion loc!"); 1000226890Sdim const ExpansionInfo &Expansion = getSLocEntry(getFileID(Loc)).getExpansion(); 1001226890Sdim return Expansion.getExpansionLocRange(); 1002193326Sed} 1003193326Sed 1004226890Sdim/// getExpansionRange - Given a SourceLocation object, return the range of 1005226890Sdim/// tokens covered by the expansion in the ultimate file. 1006193326Sedstd::pair<SourceLocation,SourceLocation> 1007226890SdimSourceManager::getExpansionRange(SourceLocation Loc) const { 1008193326Sed if (Loc.isFileID()) return std::make_pair(Loc, Loc); 1009198092Srdivacky 1010193326Sed std::pair<SourceLocation,SourceLocation> Res = 1011226890Sdim getImmediateExpansionRange(Loc); 1012198092Srdivacky 1013226890Sdim // Fully resolve the start and end locations to their ultimate expansion 1014193326Sed // points. 1015193326Sed while (!Res.first.isFileID()) 1016226890Sdim Res.first = getImmediateExpansionRange(Res.first).first; 1017193326Sed while (!Res.second.isFileID()) 1018226890Sdim Res.second = getImmediateExpansionRange(Res.second).second; 1019193326Sed return Res; 1020193326Sed} 1021193326Sed 1022226890Sdimbool SourceManager::isMacroArgExpansion(SourceLocation Loc) const { 1023224145Sdim if (!Loc.isMacroID()) return false; 1024193326Sed 1025224145Sdim FileID FID = getFileID(Loc); 1026252723Sdim const SrcMgr::ExpansionInfo &Expansion = getSLocEntry(FID).getExpansion(); 1027226890Sdim return Expansion.isMacroArgExpansion(); 1028224145Sdim} 1029193326Sed 1030252723Sdimbool SourceManager::isMacroBodyExpansion(SourceLocation Loc) const { 1031252723Sdim if (!Loc.isMacroID()) return false; 1032224145Sdim 1033252723Sdim FileID FID = getFileID(Loc); 1034252723Sdim const SrcMgr::ExpansionInfo &Expansion = getSLocEntry(FID).getExpansion(); 1035252723Sdim return Expansion.isMacroBodyExpansion(); 1036252723Sdim} 1037252723Sdim 1038263509Sdimbool SourceManager::isAtStartOfImmediateMacroExpansion(SourceLocation Loc, 1039263509Sdim SourceLocation *MacroBegin) const { 1040263509Sdim assert(Loc.isValid() && Loc.isMacroID() && "Expected a valid macro loc"); 1041252723Sdim 1042263509Sdim std::pair<FileID, unsigned> DecompLoc = getDecomposedLoc(Loc); 1043263509Sdim if (DecompLoc.second > 0) 1044263509Sdim return false; // Does not point at the start of expansion range. 1045263509Sdim 1046263509Sdim bool Invalid = false; 1047263509Sdim const SrcMgr::ExpansionInfo &ExpInfo = 1048263509Sdim getSLocEntry(DecompLoc.first, &Invalid).getExpansion(); 1049263509Sdim if (Invalid) 1050263509Sdim return false; 1051263509Sdim SourceLocation ExpLoc = ExpInfo.getExpansionLocStart(); 1052263509Sdim 1053263509Sdim if (ExpInfo.isMacroArgExpansion()) { 1054263509Sdim // For macro argument expansions, check if the previous FileID is part of 1055263509Sdim // the same argument expansion, in which case this Loc is not at the 1056263509Sdim // beginning of the expansion. 1057263509Sdim FileID PrevFID = getPreviousFileID(DecompLoc.first); 1058263509Sdim if (!PrevFID.isInvalid()) { 1059263509Sdim const SrcMgr::SLocEntry &PrevEntry = getSLocEntry(PrevFID, &Invalid); 1060263509Sdim if (Invalid) 1061263509Sdim return false; 1062263509Sdim if (PrevEntry.isExpansion() && 1063263509Sdim PrevEntry.getExpansion().getExpansionLocStart() == ExpLoc) 1064263509Sdim return false; 1065263509Sdim } 1066263509Sdim } 1067263509Sdim 1068263509Sdim if (MacroBegin) 1069263509Sdim *MacroBegin = ExpLoc; 1070263509Sdim return true; 1071263509Sdim} 1072263509Sdim 1073263509Sdimbool SourceManager::isAtEndOfImmediateMacroExpansion(SourceLocation Loc, 1074263509Sdim SourceLocation *MacroEnd) const { 1075263509Sdim assert(Loc.isValid() && Loc.isMacroID() && "Expected a valid macro loc"); 1076263509Sdim 1077263509Sdim FileID FID = getFileID(Loc); 1078263509Sdim SourceLocation NextLoc = Loc.getLocWithOffset(1); 1079263509Sdim if (isInFileID(NextLoc, FID)) 1080263509Sdim return false; // Does not point at the end of expansion range. 1081263509Sdim 1082263509Sdim bool Invalid = false; 1083263509Sdim const SrcMgr::ExpansionInfo &ExpInfo = 1084263509Sdim getSLocEntry(FID, &Invalid).getExpansion(); 1085263509Sdim if (Invalid) 1086263509Sdim return false; 1087263509Sdim 1088263509Sdim if (ExpInfo.isMacroArgExpansion()) { 1089263509Sdim // For macro argument expansions, check if the next FileID is part of the 1090263509Sdim // same argument expansion, in which case this Loc is not at the end of the 1091263509Sdim // expansion. 1092263509Sdim FileID NextFID = getNextFileID(FID); 1093263509Sdim if (!NextFID.isInvalid()) { 1094263509Sdim const SrcMgr::SLocEntry &NextEntry = getSLocEntry(NextFID, &Invalid); 1095263509Sdim if (Invalid) 1096263509Sdim return false; 1097263509Sdim if (NextEntry.isExpansion() && 1098263509Sdim NextEntry.getExpansion().getExpansionLocStart() == 1099263509Sdim ExpInfo.getExpansionLocStart()) 1100263509Sdim return false; 1101263509Sdim } 1102263509Sdim } 1103263509Sdim 1104263509Sdim if (MacroEnd) 1105263509Sdim *MacroEnd = ExpInfo.getExpansionLocEnd(); 1106263509Sdim return true; 1107263509Sdim} 1108263509Sdim 1109263509Sdim 1110193326Sed//===----------------------------------------------------------------------===// 1111193326Sed// Queries about the code at a SourceLocation. 1112193326Sed//===----------------------------------------------------------------------===// 1113193326Sed 1114193326Sed/// getCharacterData - Return a pointer to the start of the specified location 1115193326Sed/// in the appropriate MemoryBuffer. 1116205219Srdivackyconst char *SourceManager::getCharacterData(SourceLocation SL, 1117205219Srdivacky bool *Invalid) const { 1118193326Sed // Note that this is a hot function in the getSpelling() path, which is 1119193326Sed // heavily used by -E mode. 1120193326Sed std::pair<FileID, unsigned> LocInfo = getDecomposedSpellingLoc(SL); 1121198092Srdivacky 1122193326Sed // Note that calling 'getBuffer()' may lazily page in a source file. 1123205219Srdivacky bool CharDataInvalid = false; 1124221345Sdim const SLocEntry &Entry = getSLocEntry(LocInfo.first, &CharDataInvalid); 1125221345Sdim if (CharDataInvalid || !Entry.isFile()) { 1126221345Sdim if (Invalid) 1127221345Sdim *Invalid = true; 1128221345Sdim 1129221345Sdim return "<<<<INVALID BUFFER>>>>"; 1130221345Sdim } 1131205219Srdivacky const llvm::MemoryBuffer *Buffer 1132221345Sdim = Entry.getFile().getContentCache() 1133221345Sdim ->getBuffer(Diag, *this, SourceLocation(), &CharDataInvalid); 1134205219Srdivacky if (Invalid) 1135205219Srdivacky *Invalid = CharDataInvalid; 1136205219Srdivacky return Buffer->getBufferStart() + (CharDataInvalid? 0 : LocInfo.second); 1137193326Sed} 1138193326Sed 1139193326Sed 1140193326Sed/// getColumnNumber - Return the column # for the specified file position. 1141193326Sed/// this is significantly cheaper to compute than the line number. 1142205219Srdivackyunsigned SourceManager::getColumnNumber(FileID FID, unsigned FilePos, 1143205219Srdivacky bool *Invalid) const { 1144205219Srdivacky bool MyInvalid = false; 1145235633Sdim const llvm::MemoryBuffer *MemBuf = getBuffer(FID, &MyInvalid); 1146205219Srdivacky if (Invalid) 1147205219Srdivacky *Invalid = MyInvalid; 1148198092Srdivacky 1149205219Srdivacky if (MyInvalid) 1150205219Srdivacky return 1; 1151205219Srdivacky 1152245431Sdim // It is okay to request a position just past the end of the buffer. 1153245431Sdim if (FilePos > MemBuf->getBufferSize()) { 1154235633Sdim if (Invalid) 1155245431Sdim *Invalid = true; 1156235633Sdim return 1; 1157235633Sdim } 1158235633Sdim 1159245431Sdim // See if we just calculated the line number for this FilePos and can use 1160245431Sdim // that to lookup the start of the line instead of searching for it. 1161245431Sdim if (LastLineNoFileIDQuery == FID && 1162252723Sdim LastLineNoContentCache->SourceLineCache != 0 && 1163252723Sdim LastLineNoResult < LastLineNoContentCache->NumLines) { 1164245431Sdim unsigned *SourceLineCache = LastLineNoContentCache->SourceLineCache; 1165245431Sdim unsigned LineStart = SourceLineCache[LastLineNoResult - 1]; 1166245431Sdim unsigned LineEnd = SourceLineCache[LastLineNoResult]; 1167245431Sdim if (FilePos >= LineStart && FilePos < LineEnd) 1168245431Sdim return FilePos - LineStart + 1; 1169245431Sdim } 1170245431Sdim 1171235633Sdim const char *Buf = MemBuf->getBufferStart(); 1172193326Sed unsigned LineStart = FilePos; 1173193326Sed while (LineStart && Buf[LineStart-1] != '\n' && Buf[LineStart-1] != '\r') 1174193326Sed --LineStart; 1175193326Sed return FilePos-LineStart+1; 1176193326Sed} 1177193326Sed 1178218893Sdim// isInvalid - Return the result of calling loc.isInvalid(), and 1179218893Sdim// if Invalid is not null, set its value to same. 1180218893Sdimstatic bool isInvalid(SourceLocation Loc, bool *Invalid) { 1181218893Sdim bool MyInvalid = Loc.isInvalid(); 1182218893Sdim if (Invalid) 1183218893Sdim *Invalid = MyInvalid; 1184218893Sdim return MyInvalid; 1185218893Sdim} 1186218893Sdim 1187205219Srdivackyunsigned SourceManager::getSpellingColumnNumber(SourceLocation Loc, 1188205219Srdivacky bool *Invalid) const { 1189218893Sdim if (isInvalid(Loc, Invalid)) return 0; 1190193326Sed std::pair<FileID, unsigned> LocInfo = getDecomposedSpellingLoc(Loc); 1191205219Srdivacky return getColumnNumber(LocInfo.first, LocInfo.second, Invalid); 1192193326Sed} 1193193326Sed 1194226890Sdimunsigned SourceManager::getExpansionColumnNumber(SourceLocation Loc, 1195226890Sdim bool *Invalid) const { 1196218893Sdim if (isInvalid(Loc, Invalid)) return 0; 1197226890Sdim std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(Loc); 1198205219Srdivacky return getColumnNumber(LocInfo.first, LocInfo.second, Invalid); 1199193326Sed} 1200193326Sed 1201219077Sdimunsigned SourceManager::getPresumedColumnNumber(SourceLocation Loc, 1202219077Sdim bool *Invalid) const { 1203219077Sdim if (isInvalid(Loc, Invalid)) return 0; 1204219077Sdim return getPresumedLoc(Loc).getColumn(); 1205219077Sdim} 1206219077Sdim 1207235633Sdim#ifdef __SSE2__ 1208235633Sdim#include <emmintrin.h> 1209235633Sdim#endif 1210235633Sdim 1211218893Sdimstatic LLVM_ATTRIBUTE_NOINLINE void 1212226890SdimComputeLineNumbers(DiagnosticsEngine &Diag, ContentCache *FI, 1213207619Srdivacky llvm::BumpPtrAllocator &Alloc, 1214207619Srdivacky const SourceManager &SM, bool &Invalid); 1215226890Sdimstatic void ComputeLineNumbers(DiagnosticsEngine &Diag, ContentCache *FI, 1216207619Srdivacky llvm::BumpPtrAllocator &Alloc, 1217207619Srdivacky const SourceManager &SM, bool &Invalid) { 1218193326Sed // Note that calling 'getBuffer()' may lazily page in the file. 1219207619Srdivacky const MemoryBuffer *Buffer = FI->getBuffer(Diag, SM, SourceLocation(), 1220207619Srdivacky &Invalid); 1221205219Srdivacky if (Invalid) 1222205219Srdivacky return; 1223198092Srdivacky 1224193326Sed // Find the file offsets of all of the *physical* source lines. This does 1225193326Sed // not look at trigraphs, escaped newlines, or anything else tricky. 1226226890Sdim SmallVector<unsigned, 256> LineOffsets; 1227198092Srdivacky 1228193326Sed // Line #1 starts at char 0. 1229193326Sed LineOffsets.push_back(0); 1230198092Srdivacky 1231193326Sed const unsigned char *Buf = (const unsigned char *)Buffer->getBufferStart(); 1232193326Sed const unsigned char *End = (const unsigned char *)Buffer->getBufferEnd(); 1233193326Sed unsigned Offs = 0; 1234193326Sed while (1) { 1235193326Sed // Skip over the contents of the line. 1236193326Sed const unsigned char *NextBuf = (const unsigned char *)Buf; 1237235633Sdim 1238235633Sdim#ifdef __SSE2__ 1239235633Sdim // Try to skip to the next newline using SSE instructions. This is very 1240235633Sdim // performance sensitive for programs with lots of diagnostics and in -E 1241235633Sdim // mode. 1242235633Sdim __m128i CRs = _mm_set1_epi8('\r'); 1243235633Sdim __m128i LFs = _mm_set1_epi8('\n'); 1244235633Sdim 1245235633Sdim // First fix up the alignment to 16 bytes. 1246235633Sdim while (((uintptr_t)NextBuf & 0xF) != 0) { 1247235633Sdim if (*NextBuf == '\n' || *NextBuf == '\r' || *NextBuf == '\0') 1248235633Sdim goto FoundSpecialChar; 1249235633Sdim ++NextBuf; 1250235633Sdim } 1251235633Sdim 1252235633Sdim // Scan 16 byte chunks for '\r' and '\n'. Ignore '\0'. 1253235633Sdim while (NextBuf+16 <= End) { 1254245431Sdim const __m128i Chunk = *(const __m128i*)NextBuf; 1255235633Sdim __m128i Cmp = _mm_or_si128(_mm_cmpeq_epi8(Chunk, CRs), 1256235633Sdim _mm_cmpeq_epi8(Chunk, LFs)); 1257235633Sdim unsigned Mask = _mm_movemask_epi8(Cmp); 1258235633Sdim 1259235633Sdim // If we found a newline, adjust the pointer and jump to the handling code. 1260235633Sdim if (Mask != 0) { 1261263509Sdim NextBuf += llvm::countTrailingZeros(Mask); 1262235633Sdim goto FoundSpecialChar; 1263235633Sdim } 1264235633Sdim NextBuf += 16; 1265235633Sdim } 1266235633Sdim#endif 1267235633Sdim 1268193326Sed while (*NextBuf != '\n' && *NextBuf != '\r' && *NextBuf != '\0') 1269193326Sed ++NextBuf; 1270235633Sdim 1271235633Sdim#ifdef __SSE2__ 1272235633SdimFoundSpecialChar: 1273235633Sdim#endif 1274193326Sed Offs += NextBuf-Buf; 1275193326Sed Buf = NextBuf; 1276198092Srdivacky 1277193326Sed if (Buf[0] == '\n' || Buf[0] == '\r') { 1278193326Sed // If this is \n\r or \r\n, skip both characters. 1279193326Sed if ((Buf[1] == '\n' || Buf[1] == '\r') && Buf[0] != Buf[1]) 1280193326Sed ++Offs, ++Buf; 1281193326Sed ++Offs, ++Buf; 1282193326Sed LineOffsets.push_back(Offs); 1283193326Sed } else { 1284193326Sed // Otherwise, this is a null. If end of file, exit. 1285193326Sed if (Buf == End) break; 1286193326Sed // Otherwise, skip the null. 1287193326Sed ++Offs, ++Buf; 1288193326Sed } 1289193326Sed } 1290198092Srdivacky 1291193326Sed // Copy the offsets into the FileInfo structure. 1292193326Sed FI->NumLines = LineOffsets.size(); 1293193326Sed FI->SourceLineCache = Alloc.Allocate<unsigned>(LineOffsets.size()); 1294193326Sed std::copy(LineOffsets.begin(), LineOffsets.end(), FI->SourceLineCache); 1295193326Sed} 1296193326Sed 1297193326Sed/// getLineNumber - Given a SourceLocation, return the spelling line number 1298193326Sed/// for the position indicated. This requires building and caching a table of 1299193326Sed/// line offsets for the MemoryBuffer, so this is not cheap: use only when 1300193326Sed/// about to emit a diagnostic. 1301205219Srdivackyunsigned SourceManager::getLineNumber(FileID FID, unsigned FilePos, 1302205219Srdivacky bool *Invalid) const { 1303223017Sdim if (FID.isInvalid()) { 1304223017Sdim if (Invalid) 1305223017Sdim *Invalid = true; 1306223017Sdim return 1; 1307223017Sdim } 1308223017Sdim 1309193326Sed ContentCache *Content; 1310193326Sed if (LastLineNoFileIDQuery == FID) 1311193326Sed Content = LastLineNoContentCache; 1312221345Sdim else { 1313221345Sdim bool MyInvalid = false; 1314221345Sdim const SLocEntry &Entry = getSLocEntry(FID, &MyInvalid); 1315221345Sdim if (MyInvalid || !Entry.isFile()) { 1316221345Sdim if (Invalid) 1317221345Sdim *Invalid = true; 1318221345Sdim return 1; 1319221345Sdim } 1320221345Sdim 1321221345Sdim Content = const_cast<ContentCache*>(Entry.getFile().getContentCache()); 1322221345Sdim } 1323221345Sdim 1324193326Sed // If this is the first use of line information for this buffer, compute the 1325193326Sed /// SourceLineCache for it on demand. 1326205219Srdivacky if (Content->SourceLineCache == 0) { 1327205219Srdivacky bool MyInvalid = false; 1328207619Srdivacky ComputeLineNumbers(Diag, Content, ContentCacheAlloc, *this, MyInvalid); 1329205219Srdivacky if (Invalid) 1330205219Srdivacky *Invalid = MyInvalid; 1331205219Srdivacky if (MyInvalid) 1332205219Srdivacky return 1; 1333205219Srdivacky } else if (Invalid) 1334205219Srdivacky *Invalid = false; 1335193326Sed 1336193326Sed // Okay, we know we have a line number table. Do a binary search to find the 1337193326Sed // line number that this character position lands on. 1338193326Sed unsigned *SourceLineCache = Content->SourceLineCache; 1339193326Sed unsigned *SourceLineCacheStart = SourceLineCache; 1340193326Sed unsigned *SourceLineCacheEnd = SourceLineCache + Content->NumLines; 1341198092Srdivacky 1342193326Sed unsigned QueriedFilePos = FilePos+1; 1343193326Sed 1344193326Sed // FIXME: I would like to be convinced that this code is worth being as 1345198092Srdivacky // complicated as it is, binary search isn't that slow. 1346193326Sed // 1347193326Sed // If it is worth being optimized, then in my opinion it could be more 1348193326Sed // performant, simpler, and more obviously correct by just "galloping" outward 1349193326Sed // from the queried file position. In fact, this could be incorporated into a 1350193326Sed // generic algorithm such as lower_bound_with_hint. 1351193326Sed // 1352193326Sed // If someone gives me a test case where this matters, and I will do it! - DWD 1353193326Sed 1354193326Sed // If the previous query was to the same file, we know both the file pos from 1355193326Sed // that query and the line number returned. This allows us to narrow the 1356193326Sed // search space from the entire file to something near the match. 1357193326Sed if (LastLineNoFileIDQuery == FID) { 1358193326Sed if (QueriedFilePos >= LastLineNoFilePos) { 1359193326Sed // FIXME: Potential overflow? 1360193326Sed SourceLineCache = SourceLineCache+LastLineNoResult-1; 1361198092Srdivacky 1362193326Sed // The query is likely to be nearby the previous one. Here we check to 1363193326Sed // see if it is within 5, 10 or 20 lines. It can be far away in cases 1364193326Sed // where big comment blocks and vertical whitespace eat up lines but 1365193326Sed // contribute no tokens. 1366193326Sed if (SourceLineCache+5 < SourceLineCacheEnd) { 1367193326Sed if (SourceLineCache[5] > QueriedFilePos) 1368193326Sed SourceLineCacheEnd = SourceLineCache+5; 1369193326Sed else if (SourceLineCache+10 < SourceLineCacheEnd) { 1370193326Sed if (SourceLineCache[10] > QueriedFilePos) 1371193326Sed SourceLineCacheEnd = SourceLineCache+10; 1372193326Sed else if (SourceLineCache+20 < SourceLineCacheEnd) { 1373193326Sed if (SourceLineCache[20] > QueriedFilePos) 1374193326Sed SourceLineCacheEnd = SourceLineCache+20; 1375193326Sed } 1376193326Sed } 1377193326Sed } 1378193326Sed } else { 1379193326Sed if (LastLineNoResult < Content->NumLines) 1380193326Sed SourceLineCacheEnd = SourceLineCache+LastLineNoResult+1; 1381193326Sed } 1382193326Sed } 1383198092Srdivacky 1384193326Sed // If the spread is large, do a "radix" test as our initial guess, based on 1385193326Sed // the assumption that lines average to approximately the same length. 1386193326Sed // NOTE: This is currently disabled, as it does not appear to be profitable in 1387193326Sed // initial measurements. 1388193326Sed if (0 && SourceLineCacheEnd-SourceLineCache > 20) { 1389193326Sed unsigned FileLen = Content->SourceLineCache[Content->NumLines-1]; 1390198092Srdivacky 1391193326Sed // Take a stab at guessing where it is. 1392193326Sed unsigned ApproxPos = Content->NumLines*QueriedFilePos / FileLen; 1393198092Srdivacky 1394193326Sed // Check for -10 and +10 lines. 1395193326Sed unsigned LowerBound = std::max(int(ApproxPos-10), 0); 1396193326Sed unsigned UpperBound = std::min(ApproxPos+10, FileLen); 1397193326Sed 1398193326Sed // If the computed lower bound is less than the query location, move it in. 1399193326Sed if (SourceLineCache < SourceLineCacheStart+LowerBound && 1400193326Sed SourceLineCacheStart[LowerBound] < QueriedFilePos) 1401193326Sed SourceLineCache = SourceLineCacheStart+LowerBound; 1402198092Srdivacky 1403193326Sed // If the computed upper bound is greater than the query location, move it. 1404193326Sed if (SourceLineCacheEnd > SourceLineCacheStart+UpperBound && 1405193326Sed SourceLineCacheStart[UpperBound] >= QueriedFilePos) 1406193326Sed SourceLineCacheEnd = SourceLineCacheStart+UpperBound; 1407193326Sed } 1408198092Srdivacky 1409193326Sed unsigned *Pos 1410193326Sed = std::lower_bound(SourceLineCache, SourceLineCacheEnd, QueriedFilePos); 1411193326Sed unsigned LineNo = Pos-SourceLineCacheStart; 1412198092Srdivacky 1413193326Sed LastLineNoFileIDQuery = FID; 1414193326Sed LastLineNoContentCache = Content; 1415193326Sed LastLineNoFilePos = QueriedFilePos; 1416193326Sed LastLineNoResult = LineNo; 1417193326Sed return LineNo; 1418193326Sed} 1419193326Sed 1420219077Sdimunsigned SourceManager::getSpellingLineNumber(SourceLocation Loc, 1421219077Sdim bool *Invalid) const { 1422219077Sdim if (isInvalid(Loc, Invalid)) return 0; 1423219077Sdim std::pair<FileID, unsigned> LocInfo = getDecomposedSpellingLoc(Loc); 1424219077Sdim return getLineNumber(LocInfo.first, LocInfo.second); 1425219077Sdim} 1426226890Sdimunsigned SourceManager::getExpansionLineNumber(SourceLocation Loc, 1427226890Sdim bool *Invalid) const { 1428218893Sdim if (isInvalid(Loc, Invalid)) return 0; 1429226890Sdim std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(Loc); 1430193326Sed return getLineNumber(LocInfo.first, LocInfo.second); 1431193326Sed} 1432219077Sdimunsigned SourceManager::getPresumedLineNumber(SourceLocation Loc, 1433205219Srdivacky bool *Invalid) const { 1434218893Sdim if (isInvalid(Loc, Invalid)) return 0; 1435219077Sdim return getPresumedLoc(Loc).getLine(); 1436193326Sed} 1437193326Sed 1438193326Sed/// getFileCharacteristic - return the file characteristic of the specified 1439198092Srdivacky/// source location, indicating whether this is a normal file, a system 1440193326Sed/// header, or an "implicit extern C" system header. 1441193326Sed/// 1442193326Sed/// This state can be modified with flags on GNU linemarker directives like: 1443193326Sed/// # 4 "foo.h" 3 1444193326Sed/// which changes all source locations in the current file after that to be 1445193326Sed/// considered to be from a system header. 1446198092SrdivackySrcMgr::CharacteristicKind 1447193326SedSourceManager::getFileCharacteristic(SourceLocation Loc) const { 1448193326Sed assert(!Loc.isInvalid() && "Can't get file characteristic of invalid loc!"); 1449226890Sdim std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(Loc); 1450221345Sdim bool Invalid = false; 1451221345Sdim const SLocEntry &SEntry = getSLocEntry(LocInfo.first, &Invalid); 1452221345Sdim if (Invalid || !SEntry.isFile()) 1453221345Sdim return C_User; 1454221345Sdim 1455221345Sdim const SrcMgr::FileInfo &FI = SEntry.getFile(); 1456193326Sed 1457193326Sed // If there are no #line directives in this file, just return the whole-file 1458193326Sed // state. 1459193326Sed if (!FI.hasLineDirectives()) 1460193326Sed return FI.getFileCharacteristic(); 1461198092Srdivacky 1462193326Sed assert(LineTable && "Can't have linetable entries without a LineTable!"); 1463193326Sed // See if there is a #line directive before the location. 1464193326Sed const LineEntry *Entry = 1465245431Sdim LineTable->FindNearestLineEntry(LocInfo.first, LocInfo.second); 1466198092Srdivacky 1467193326Sed // If this is before the first line marker, use the file characteristic. 1468193326Sed if (!Entry) 1469193326Sed return FI.getFileCharacteristic(); 1470193326Sed 1471193326Sed return Entry->FileKind; 1472193326Sed} 1473193326Sed 1474193326Sed/// Return the filename or buffer identifier of the buffer the location is in. 1475245431Sdim/// Note that this name does not respect \#line directives. Use getPresumedLoc 1476193326Sed/// for normal clients. 1477205219Srdivackyconst char *SourceManager::getBufferName(SourceLocation Loc, 1478205219Srdivacky bool *Invalid) const { 1479218893Sdim if (isInvalid(Loc, Invalid)) return "<invalid loc>"; 1480198092Srdivacky 1481205219Srdivacky return getBuffer(getFileID(Loc), Invalid)->getBufferIdentifier(); 1482193326Sed} 1483193326Sed 1484193326Sed 1485193326Sed/// getPresumedLoc - This method returns the "presumed" location of a 1486245431Sdim/// SourceLocation specifies. A "presumed location" can be modified by \#line 1487193326Sed/// or GNU line marker directives. This provides a view on the data that a 1488193326Sed/// user should see in diagnostics, for example. 1489193326Sed/// 1490226890Sdim/// Note that a presumed location is always given as the expansion point of an 1491226890Sdim/// expansion location, not at the spelling location. 1492252723SdimPresumedLoc SourceManager::getPresumedLoc(SourceLocation Loc, 1493252723Sdim bool UseLineDirectives) const { 1494193326Sed if (Loc.isInvalid()) return PresumedLoc(); 1495198092Srdivacky 1496226890Sdim // Presumed locations are always for expansion points. 1497226890Sdim std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(Loc); 1498198092Srdivacky 1499221345Sdim bool Invalid = false; 1500221345Sdim const SLocEntry &Entry = getSLocEntry(LocInfo.first, &Invalid); 1501221345Sdim if (Invalid || !Entry.isFile()) 1502221345Sdim return PresumedLoc(); 1503221345Sdim 1504221345Sdim const SrcMgr::FileInfo &FI = Entry.getFile(); 1505193326Sed const SrcMgr::ContentCache *C = FI.getContentCache(); 1506198092Srdivacky 1507193326Sed // To get the source name, first consult the FileEntry (if one exists) 1508193326Sed // before the MemBuffer as this will avoid unnecessarily paging in the 1509193326Sed // MemBuffer. 1510207619Srdivacky const char *Filename; 1511221345Sdim if (C->OrigEntry) 1512221345Sdim Filename = C->OrigEntry->getName(); 1513207619Srdivacky else 1514207619Srdivacky Filename = C->getBuffer(Diag, *this)->getBufferIdentifier(); 1515221345Sdim 1516218893Sdim unsigned LineNo = getLineNumber(LocInfo.first, LocInfo.second, &Invalid); 1517218893Sdim if (Invalid) 1518218893Sdim return PresumedLoc(); 1519218893Sdim unsigned ColNo = getColumnNumber(LocInfo.first, LocInfo.second, &Invalid); 1520218893Sdim if (Invalid) 1521218893Sdim return PresumedLoc(); 1522218893Sdim 1523193326Sed SourceLocation IncludeLoc = FI.getIncludeLoc(); 1524198092Srdivacky 1525193326Sed // If we have #line directives in this file, update and overwrite the physical 1526193326Sed // location info if appropriate. 1527252723Sdim if (UseLineDirectives && FI.hasLineDirectives()) { 1528193326Sed assert(LineTable && "Can't have linetable entries without a LineTable!"); 1529193326Sed // See if there is a #line directive before this. If so, get it. 1530193326Sed if (const LineEntry *Entry = 1531245431Sdim LineTable->FindNearestLineEntry(LocInfo.first, LocInfo.second)) { 1532193326Sed // If the LineEntry indicates a filename, use it. 1533193326Sed if (Entry->FilenameID != -1) 1534193326Sed Filename = LineTable->getFilename(Entry->FilenameID); 1535193326Sed 1536193326Sed // Use the line number specified by the LineEntry. This line number may 1537193326Sed // be multiple lines down from the line entry. Add the difference in 1538193326Sed // physical line numbers from the query point and the line marker to the 1539193326Sed // total. 1540193326Sed unsigned MarkerLineNo = getLineNumber(LocInfo.first, Entry->FileOffset); 1541193326Sed LineNo = Entry->LineNo + (LineNo-MarkerLineNo-1); 1542198092Srdivacky 1543193326Sed // Note that column numbers are not molested by line markers. 1544198092Srdivacky 1545193326Sed // Handle virtual #include manipulation. 1546193326Sed if (Entry->IncludeOffset) { 1547193326Sed IncludeLoc = getLocForStartOfFile(LocInfo.first); 1548226890Sdim IncludeLoc = IncludeLoc.getLocWithOffset(Entry->IncludeOffset); 1549193326Sed } 1550193326Sed } 1551193326Sed } 1552193326Sed 1553193326Sed return PresumedLoc(Filename, LineNo, ColNo, IncludeLoc); 1554193326Sed} 1555193326Sed 1556263509Sdim/// \brief Returns whether the PresumedLoc for a given SourceLocation is 1557263509Sdim/// in the main file. 1558263509Sdim/// 1559263509Sdim/// This computes the "presumed" location for a SourceLocation, then checks 1560263509Sdim/// whether it came from a file other than the main file. This is different 1561263509Sdim/// from isWrittenInMainFile() because it takes line marker directives into 1562263509Sdim/// account. 1563263509Sdimbool SourceManager::isInMainFile(SourceLocation Loc) const { 1564263509Sdim if (Loc.isInvalid()) return false; 1565263509Sdim 1566263509Sdim // Presumed locations are always for expansion points. 1567263509Sdim std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(Loc); 1568263509Sdim 1569263509Sdim bool Invalid = false; 1570263509Sdim const SLocEntry &Entry = getSLocEntry(LocInfo.first, &Invalid); 1571263509Sdim if (Invalid || !Entry.isFile()) 1572263509Sdim return false; 1573263509Sdim 1574263509Sdim const SrcMgr::FileInfo &FI = Entry.getFile(); 1575263509Sdim 1576263509Sdim // Check if there is a line directive for this location. 1577263509Sdim if (FI.hasLineDirectives()) 1578263509Sdim if (const LineEntry *Entry = 1579263509Sdim LineTable->FindNearestLineEntry(LocInfo.first, LocInfo.second)) 1580263509Sdim if (Entry->IncludeOffset) 1581263509Sdim return false; 1582263509Sdim 1583263509Sdim return FI.getIncludeLoc().isInvalid(); 1584263509Sdim} 1585263509Sdim 1586226890Sdim/// \brief The size of the SLocEnty that \arg FID represents. 1587226890Sdimunsigned SourceManager::getFileIDSize(FileID FID) const { 1588226890Sdim bool Invalid = false; 1589226890Sdim const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid); 1590226890Sdim if (Invalid) 1591226890Sdim return 0; 1592226890Sdim 1593226890Sdim int ID = FID.ID; 1594226890Sdim unsigned NextOffset; 1595226890Sdim if ((ID > 0 && unsigned(ID+1) == local_sloc_entry_size())) 1596226890Sdim NextOffset = getNextLocalOffset(); 1597226890Sdim else if (ID+1 == -1) 1598226890Sdim NextOffset = MaxLoadedOffset; 1599226890Sdim else 1600226890Sdim NextOffset = getSLocEntry(FileID::get(ID+1)).getOffset(); 1601226890Sdim 1602226890Sdim return NextOffset - Entry.getOffset() - 1; 1603226890Sdim} 1604226890Sdim 1605193326Sed//===----------------------------------------------------------------------===// 1606193326Sed// Other miscellaneous methods. 1607193326Sed//===----------------------------------------------------------------------===// 1608193326Sed 1609218893Sdim/// \brief Retrieve the inode for the given file entry, if possible. 1610218893Sdim/// 1611218893Sdim/// This routine involves a system call, and therefore should only be used 1612218893Sdim/// in non-performance-critical code. 1613263509Sdimstatic Optional<llvm::sys::fs::UniqueID> 1614263509SdimgetActualFileUID(const FileEntry *File) { 1615218893Sdim if (!File) 1616252723Sdim return None; 1617263509Sdim 1618263509Sdim llvm::sys::fs::UniqueID ID; 1619263509Sdim if (llvm::sys::fs::getUniqueID(File->getName(), ID)) 1620252723Sdim return None; 1621263509Sdim 1622263509Sdim return ID; 1623218893Sdim} 1624218893Sdim 1625194613Sed/// \brief Get the source location for the given file:line:col triplet. 1626194613Sed/// 1627194613Sed/// If the source file is included multiple times, the source location will 1628226890Sdim/// be based upon an arbitrary inclusion. 1629226890SdimSourceLocation SourceManager::translateFileLineCol(const FileEntry *SourceFile, 1630226890Sdim unsigned Line, 1631226890Sdim unsigned Col) const { 1632194613Sed assert(SourceFile && "Null source file!"); 1633194613Sed assert(Line && Col && "Line and column should start from 1!"); 1634193326Sed 1635226890Sdim FileID FirstFID = translateFile(SourceFile); 1636226890Sdim return translateLineCol(FirstFID, Line, Col); 1637226890Sdim} 1638226890Sdim 1639226890Sdim/// \brief Get the FileID for the given file. 1640226890Sdim/// 1641226890Sdim/// If the source file is included multiple times, the FileID will be the 1642226890Sdim/// first inclusion. 1643226890SdimFileID SourceManager::translateFile(const FileEntry *SourceFile) const { 1644226890Sdim assert(SourceFile && "Null source file!"); 1645226890Sdim 1646200583Srdivacky // Find the first file ID that corresponds to the given file. 1647200583Srdivacky FileID FirstFID; 1648200583Srdivacky 1649200583Srdivacky // First, check the main file ID, since it is common to look for a 1650200583Srdivacky // location in the main file. 1651263509Sdim Optional<llvm::sys::fs::UniqueID> SourceFileUID; 1652252723Sdim Optional<StringRef> SourceFileName; 1653200583Srdivacky if (!MainFileID.isInvalid()) { 1654221345Sdim bool Invalid = false; 1655221345Sdim const SLocEntry &MainSLoc = getSLocEntry(MainFileID, &Invalid); 1656221345Sdim if (Invalid) 1657226890Sdim return FileID(); 1658221345Sdim 1659218893Sdim if (MainSLoc.isFile()) { 1660218893Sdim const ContentCache *MainContentCache 1661218893Sdim = MainSLoc.getFile().getContentCache(); 1662218893Sdim if (!MainContentCache) { 1663218893Sdim // Can't do anything 1664221345Sdim } else if (MainContentCache->OrigEntry == SourceFile) { 1665218893Sdim FirstFID = MainFileID; 1666218893Sdim } else { 1667218893Sdim // Fall back: check whether we have the same base name and inode 1668218893Sdim // as the main file. 1669221345Sdim const FileEntry *MainFile = MainContentCache->OrigEntry; 1670218893Sdim SourceFileName = llvm::sys::path::filename(SourceFile->getName()); 1671218893Sdim if (*SourceFileName == llvm::sys::path::filename(MainFile->getName())) { 1672263509Sdim SourceFileUID = getActualFileUID(SourceFile); 1673263509Sdim if (SourceFileUID) { 1674263509Sdim if (Optional<llvm::sys::fs::UniqueID> MainFileUID = 1675263509Sdim getActualFileUID(MainFile)) { 1676263509Sdim if (*SourceFileUID == *MainFileUID) { 1677218893Sdim FirstFID = MainFileID; 1678218893Sdim SourceFile = MainFile; 1679218893Sdim } 1680218893Sdim } 1681218893Sdim } 1682218893Sdim } 1683218893Sdim } 1684218893Sdim } 1685200583Srdivacky } 1686200583Srdivacky 1687200583Srdivacky if (FirstFID.isInvalid()) { 1688200583Srdivacky // The location we're looking for isn't in the main file; look 1689226890Sdim // through all of the local source locations. 1690226890Sdim for (unsigned I = 0, N = local_sloc_entry_size(); I != N; ++I) { 1691221345Sdim bool Invalid = false; 1692226890Sdim const SLocEntry &SLoc = getLocalSLocEntry(I, &Invalid); 1693221345Sdim if (Invalid) 1694226890Sdim return FileID(); 1695221345Sdim 1696218893Sdim if (SLoc.isFile() && 1697218893Sdim SLoc.getFile().getContentCache() && 1698221345Sdim SLoc.getFile().getContentCache()->OrigEntry == SourceFile) { 1699200583Srdivacky FirstFID = FileID::get(I); 1700200583Srdivacky break; 1701200583Srdivacky } 1702200583Srdivacky } 1703226890Sdim // If that still didn't help, try the modules. 1704226890Sdim if (FirstFID.isInvalid()) { 1705226890Sdim for (unsigned I = 0, N = loaded_sloc_entry_size(); I != N; ++I) { 1706226890Sdim const SLocEntry &SLoc = getLoadedSLocEntry(I); 1707226890Sdim if (SLoc.isFile() && 1708226890Sdim SLoc.getFile().getContentCache() && 1709226890Sdim SLoc.getFile().getContentCache()->OrigEntry == SourceFile) { 1710226890Sdim FirstFID = FileID::get(-int(I) - 2); 1711226890Sdim break; 1712226890Sdim } 1713226890Sdim } 1714226890Sdim } 1715200583Srdivacky } 1716218893Sdim 1717218893Sdim // If we haven't found what we want yet, try again, but this time stat() 1718218893Sdim // each of the files in case the files have changed since we originally 1719263509Sdim // parsed the file. 1720218893Sdim if (FirstFID.isInvalid() && 1721263509Sdim (SourceFileName || 1722218893Sdim (SourceFileName = llvm::sys::path::filename(SourceFile->getName()))) && 1723263509Sdim (SourceFileUID || (SourceFileUID = getActualFileUID(SourceFile)))) { 1724221345Sdim bool Invalid = false; 1725226890Sdim for (unsigned I = 0, N = local_sloc_entry_size(); I != N; ++I) { 1726226890Sdim FileID IFileID; 1727226890Sdim IFileID.ID = I; 1728226890Sdim const SLocEntry &SLoc = getSLocEntry(IFileID, &Invalid); 1729221345Sdim if (Invalid) 1730226890Sdim return FileID(); 1731221345Sdim 1732218893Sdim if (SLoc.isFile()) { 1733218893Sdim const ContentCache *FileContentCache 1734218893Sdim = SLoc.getFile().getContentCache(); 1735221345Sdim const FileEntry *Entry =FileContentCache? FileContentCache->OrigEntry : 0; 1736218893Sdim if (Entry && 1737218893Sdim *SourceFileName == llvm::sys::path::filename(Entry->getName())) { 1738263509Sdim if (Optional<llvm::sys::fs::UniqueID> EntryUID = 1739263509Sdim getActualFileUID(Entry)) { 1740263509Sdim if (*SourceFileUID == *EntryUID) { 1741218893Sdim FirstFID = FileID::get(I); 1742218893Sdim SourceFile = Entry; 1743218893Sdim break; 1744218893Sdim } 1745218893Sdim } 1746218893Sdim } 1747218893Sdim } 1748218893Sdim } 1749218893Sdim } 1750226890Sdim 1751245431Sdim (void) SourceFile; 1752226890Sdim return FirstFID; 1753226890Sdim} 1754226890Sdim 1755226890Sdim/// \brief Get the source location in \arg FID for the given line:col. 1756226890Sdim/// Returns null location if \arg FID is not a file SLocEntry. 1757226890SdimSourceLocation SourceManager::translateLineCol(FileID FID, 1758226890Sdim unsigned Line, 1759226890Sdim unsigned Col) const { 1760263509Sdim // Lines are used as a one-based index into a zero-based array. This assert 1761263509Sdim // checks for possible buffer underruns. 1762263509Sdim assert(Line != 0 && "Passed a zero-based line"); 1763263509Sdim 1764226890Sdim if (FID.isInvalid()) 1765200583Srdivacky return SourceLocation(); 1766200583Srdivacky 1767226890Sdim bool Invalid = false; 1768226890Sdim const SLocEntry &Entry = getSLocEntry(FID, &Invalid); 1769226890Sdim if (Invalid) 1770226890Sdim return SourceLocation(); 1771263509Sdim 1772226890Sdim if (!Entry.isFile()) 1773226890Sdim return SourceLocation(); 1774226890Sdim 1775226890Sdim SourceLocation FileLoc = SourceLocation::getFileLoc(Entry.getOffset()); 1776226890Sdim 1777218893Sdim if (Line == 1 && Col == 1) 1778226890Sdim return FileLoc; 1779218893Sdim 1780218893Sdim ContentCache *Content 1781226890Sdim = const_cast<ContentCache *>(Entry.getFile().getContentCache()); 1782218893Sdim if (!Content) 1783218893Sdim return SourceLocation(); 1784263509Sdim 1785218893Sdim // If this is the first use of line information for this buffer, compute the 1786226890Sdim // SourceLineCache for it on demand. 1787218893Sdim if (Content->SourceLineCache == 0) { 1788218893Sdim bool MyInvalid = false; 1789218893Sdim ComputeLineNumbers(Diag, Content, ContentCacheAlloc, *this, MyInvalid); 1790218893Sdim if (MyInvalid) 1791218893Sdim return SourceLocation(); 1792218893Sdim } 1793218893Sdim 1794204643Srdivacky if (Line > Content->NumLines) { 1795207619Srdivacky unsigned Size = Content->getBuffer(Diag, *this)->getBufferSize(); 1796204643Srdivacky if (Size > 0) 1797204643Srdivacky --Size; 1798226890Sdim return FileLoc.getLocWithOffset(Size); 1799204643Srdivacky } 1800204643Srdivacky 1801235633Sdim const llvm::MemoryBuffer *Buffer = Content->getBuffer(Diag, *this); 1802204643Srdivacky unsigned FilePos = Content->SourceLineCache[Line - 1]; 1803235633Sdim const char *Buf = Buffer->getBufferStart() + FilePos; 1804235633Sdim unsigned BufLength = Buffer->getBufferSize() - FilePos; 1805226890Sdim if (BufLength == 0) 1806226890Sdim return FileLoc.getLocWithOffset(FilePos); 1807226890Sdim 1808204643Srdivacky unsigned i = 0; 1809204643Srdivacky 1810204643Srdivacky // Check that the given column is valid. 1811204643Srdivacky while (i < BufLength-1 && i < Col-1 && Buf[i] != '\n' && Buf[i] != '\r') 1812204643Srdivacky ++i; 1813263509Sdim return FileLoc.getLocWithOffset(FilePos + i); 1814194613Sed} 1815194613Sed 1816226890Sdim/// \brief Compute a map of macro argument chunks to their expanded source 1817226890Sdim/// location. Chunks that are not part of a macro argument will map to an 1818226890Sdim/// invalid source location. e.g. if a file contains one macro argument at 1819226890Sdim/// offset 100 with length 10, this is how the map will be formed: 1820226890Sdim/// 0 -> SourceLocation() 1821226890Sdim/// 100 -> Expanded macro arg location 1822226890Sdim/// 110 -> SourceLocation() 1823226890Sdimvoid SourceManager::computeMacroArgsCache(MacroArgsMap *&CachePtr, 1824226890Sdim FileID FID) const { 1825226890Sdim assert(!FID.isInvalid()); 1826226890Sdim assert(!CachePtr); 1827226890Sdim 1828226890Sdim CachePtr = new MacroArgsMap(); 1829226890Sdim MacroArgsMap &MacroArgsCache = *CachePtr; 1830226890Sdim // Initially no macro argument chunk is present. 1831226890Sdim MacroArgsCache.insert(std::make_pair(0, SourceLocation())); 1832226890Sdim 1833226890Sdim int ID = FID.ID; 1834226890Sdim while (1) { 1835226890Sdim ++ID; 1836226890Sdim // Stop if there are no more FileIDs to check. 1837226890Sdim if (ID > 0) { 1838226890Sdim if (unsigned(ID) >= local_sloc_entry_size()) 1839226890Sdim return; 1840226890Sdim } else if (ID == -1) { 1841226890Sdim return; 1842226890Sdim } 1843226890Sdim 1844263509Sdim bool Invalid = false; 1845263509Sdim const SrcMgr::SLocEntry &Entry = getSLocEntryByID(ID, &Invalid); 1846263509Sdim if (Invalid) 1847263509Sdim return; 1848226890Sdim if (Entry.isFile()) { 1849226890Sdim SourceLocation IncludeLoc = Entry.getFile().getIncludeLoc(); 1850226890Sdim if (IncludeLoc.isInvalid()) 1851226890Sdim continue; 1852226890Sdim if (!isInFileID(IncludeLoc, FID)) 1853226890Sdim return; // No more files/macros that may be "contained" in this file. 1854226890Sdim 1855226890Sdim // Skip the files/macros of the #include'd file, we only care about macros 1856226890Sdim // that lexed macro arguments from our file. 1857226890Sdim if (Entry.getFile().NumCreatedFIDs) 1858226890Sdim ID += Entry.getFile().NumCreatedFIDs - 1/*because of next ++ID*/; 1859226890Sdim continue; 1860226890Sdim } 1861226890Sdim 1862235633Sdim const ExpansionInfo &ExpInfo = Entry.getExpansion(); 1863235633Sdim 1864235633Sdim if (ExpInfo.getExpansionLocStart().isFileID()) { 1865235633Sdim if (!isInFileID(ExpInfo.getExpansionLocStart(), FID)) 1866235633Sdim return; // No more files/macros that may be "contained" in this file. 1867235633Sdim } 1868235633Sdim 1869235633Sdim if (!ExpInfo.isMacroArgExpansion()) 1870226890Sdim continue; 1871235633Sdim 1872245431Sdim associateFileChunkWithMacroArgExp(MacroArgsCache, FID, 1873245431Sdim ExpInfo.getSpellingLoc(), 1874245431Sdim SourceLocation::getMacroLoc(Entry.getOffset()), 1875245431Sdim getFileIDSize(FileID::get(ID))); 1876245431Sdim } 1877245431Sdim} 1878245431Sdim 1879245431Sdimvoid SourceManager::associateFileChunkWithMacroArgExp( 1880245431Sdim MacroArgsMap &MacroArgsCache, 1881245431Sdim FileID FID, 1882245431Sdim SourceLocation SpellLoc, 1883245431Sdim SourceLocation ExpansionLoc, 1884245431Sdim unsigned ExpansionLength) const { 1885245431Sdim if (!SpellLoc.isFileID()) { 1886245431Sdim unsigned SpellBeginOffs = SpellLoc.getOffset(); 1887245431Sdim unsigned SpellEndOffs = SpellBeginOffs + ExpansionLength; 1888245431Sdim 1889245431Sdim // The spelling range for this macro argument expansion can span multiple 1890245431Sdim // consecutive FileID entries. Go through each entry contained in the 1891245431Sdim // spelling range and if one is itself a macro argument expansion, recurse 1892245431Sdim // and associate the file chunk that it represents. 1893245431Sdim 1894245431Sdim FileID SpellFID; // Current FileID in the spelling range. 1895245431Sdim unsigned SpellRelativeOffs; 1896245431Sdim llvm::tie(SpellFID, SpellRelativeOffs) = getDecomposedLoc(SpellLoc); 1897245431Sdim while (1) { 1898245431Sdim const SLocEntry &Entry = getSLocEntry(SpellFID); 1899245431Sdim unsigned SpellFIDBeginOffs = Entry.getOffset(); 1900245431Sdim unsigned SpellFIDSize = getFileIDSize(SpellFID); 1901245431Sdim unsigned SpellFIDEndOffs = SpellFIDBeginOffs + SpellFIDSize; 1902245431Sdim const ExpansionInfo &Info = Entry.getExpansion(); 1903245431Sdim if (Info.isMacroArgExpansion()) { 1904245431Sdim unsigned CurrSpellLength; 1905245431Sdim if (SpellFIDEndOffs < SpellEndOffs) 1906245431Sdim CurrSpellLength = SpellFIDSize - SpellRelativeOffs; 1907245431Sdim else 1908245431Sdim CurrSpellLength = ExpansionLength; 1909245431Sdim associateFileChunkWithMacroArgExp(MacroArgsCache, FID, 1910245431Sdim Info.getSpellingLoc().getLocWithOffset(SpellRelativeOffs), 1911245431Sdim ExpansionLoc, CurrSpellLength); 1912245431Sdim } 1913245431Sdim 1914245431Sdim if (SpellFIDEndOffs >= SpellEndOffs) 1915245431Sdim return; // we covered all FileID entries in the spelling range. 1916245431Sdim 1917245431Sdim // Move to the next FileID entry in the spelling range. 1918245431Sdim unsigned advance = SpellFIDSize - SpellRelativeOffs + 1; 1919245431Sdim ExpansionLoc = ExpansionLoc.getLocWithOffset(advance); 1920245431Sdim ExpansionLength -= advance; 1921245431Sdim ++SpellFID.ID; 1922245431Sdim SpellRelativeOffs = 0; 1923235633Sdim } 1924235633Sdim 1925245431Sdim } 1926226890Sdim 1927245431Sdim assert(SpellLoc.isFileID()); 1928226890Sdim 1929245431Sdim unsigned BeginOffs; 1930245431Sdim if (!isInFileID(SpellLoc, FID, &BeginOffs)) 1931245431Sdim return; 1932245431Sdim 1933245431Sdim unsigned EndOffs = BeginOffs + ExpansionLength; 1934245431Sdim 1935245431Sdim // Add a new chunk for this macro argument. A previous macro argument chunk 1936245431Sdim // may have been lexed again, so e.g. if the map is 1937245431Sdim // 0 -> SourceLocation() 1938245431Sdim // 100 -> Expanded loc #1 1939245431Sdim // 110 -> SourceLocation() 1940245431Sdim // and we found a new macro FileID that lexed from offet 105 with length 3, 1941245431Sdim // the new map will be: 1942245431Sdim // 0 -> SourceLocation() 1943245431Sdim // 100 -> Expanded loc #1 1944245431Sdim // 105 -> Expanded loc #2 1945245431Sdim // 108 -> Expanded loc #1 1946245431Sdim // 110 -> SourceLocation() 1947245431Sdim // 1948245431Sdim // Since re-lexed macro chunks will always be the same size or less of 1949245431Sdim // previous chunks, we only need to find where the ending of the new macro 1950245431Sdim // chunk is mapped to and update the map with new begin/end mappings. 1951245431Sdim 1952245431Sdim MacroArgsMap::iterator I = MacroArgsCache.upper_bound(EndOffs); 1953245431Sdim --I; 1954245431Sdim SourceLocation EndOffsMappedLoc = I->second; 1955245431Sdim MacroArgsCache[BeginOffs] = ExpansionLoc; 1956245431Sdim MacroArgsCache[EndOffs] = EndOffsMappedLoc; 1957226890Sdim} 1958226890Sdim 1959226890Sdim/// \brief If \arg Loc points inside a function macro argument, the returned 1960226890Sdim/// location will be the macro location in which the argument was expanded. 1961226890Sdim/// If a macro argument is used multiple times, the expanded location will 1962226890Sdim/// be at the first expansion of the argument. 1963226890Sdim/// e.g. 1964226890Sdim/// MY_MACRO(foo); 1965226890Sdim/// ^ 1966226890Sdim/// Passing a file location pointing at 'foo', will yield a macro location 1967226890Sdim/// where 'foo' was expanded into. 1968226890SdimSourceLocation 1969226890SdimSourceManager::getMacroArgExpandedLocation(SourceLocation Loc) const { 1970226890Sdim if (Loc.isInvalid() || !Loc.isFileID()) 1971226890Sdim return Loc; 1972226890Sdim 1973226890Sdim FileID FID; 1974226890Sdim unsigned Offset; 1975226890Sdim llvm::tie(FID, Offset) = getDecomposedLoc(Loc); 1976226890Sdim if (FID.isInvalid()) 1977226890Sdim return Loc; 1978226890Sdim 1979226890Sdim MacroArgsMap *&MacroArgsCache = MacroArgsCacheMap[FID]; 1980226890Sdim if (!MacroArgsCache) 1981226890Sdim computeMacroArgsCache(MacroArgsCache, FID); 1982226890Sdim 1983226890Sdim assert(!MacroArgsCache->empty()); 1984226890Sdim MacroArgsMap::iterator I = MacroArgsCache->upper_bound(Offset); 1985226890Sdim --I; 1986226890Sdim 1987226890Sdim unsigned MacroArgBeginOffs = I->first; 1988226890Sdim SourceLocation MacroArgExpandedLoc = I->second; 1989226890Sdim if (MacroArgExpandedLoc.isValid()) 1990226890Sdim return MacroArgExpandedLoc.getLocWithOffset(Offset - MacroArgBeginOffs); 1991226890Sdim 1992226890Sdim return Loc; 1993226890Sdim} 1994226890Sdim 1995252723Sdimstd::pair<FileID, unsigned> 1996252723SdimSourceManager::getDecomposedIncludedLoc(FileID FID) const { 1997263509Sdim if (FID.isInvalid()) 1998263509Sdim return std::make_pair(FileID(), 0); 1999263509Sdim 2000252723Sdim // Uses IncludedLocMap to retrieve/cache the decomposed loc. 2001252723Sdim 2002252723Sdim typedef std::pair<FileID, unsigned> DecompTy; 2003252723Sdim typedef llvm::DenseMap<FileID, DecompTy> MapTy; 2004252723Sdim std::pair<MapTy::iterator, bool> 2005252723Sdim InsertOp = IncludedLocMap.insert(std::make_pair(FID, DecompTy())); 2006252723Sdim DecompTy &DecompLoc = InsertOp.first->second; 2007252723Sdim if (!InsertOp.second) 2008252723Sdim return DecompLoc; // already in map. 2009252723Sdim 2010252723Sdim SourceLocation UpperLoc; 2011263509Sdim bool Invalid = false; 2012263509Sdim const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid); 2013263509Sdim if (!Invalid) { 2014263509Sdim if (Entry.isExpansion()) 2015263509Sdim UpperLoc = Entry.getExpansion().getExpansionLocStart(); 2016263509Sdim else 2017263509Sdim UpperLoc = Entry.getFile().getIncludeLoc(); 2018263509Sdim } 2019252723Sdim 2020252723Sdim if (UpperLoc.isValid()) 2021252723Sdim DecompLoc = getDecomposedLoc(UpperLoc); 2022252723Sdim 2023252723Sdim return DecompLoc; 2024252723Sdim} 2025252723Sdim 2026226890Sdim/// Given a decomposed source location, move it up the include/expansion stack 2027226890Sdim/// to the parent source location. If this is possible, return the decomposed 2028226890Sdim/// version of the parent in Loc and return false. If Loc is the top-level 2029226890Sdim/// entry, return true and don't modify it. 2030208600Srdivackystatic bool MoveUpIncludeHierarchy(std::pair<FileID, unsigned> &Loc, 2031208600Srdivacky const SourceManager &SM) { 2032252723Sdim std::pair<FileID, unsigned> UpperLoc = SM.getDecomposedIncludedLoc(Loc.first); 2033252723Sdim if (UpperLoc.first.isInvalid()) 2034208600Srdivacky return true; // We reached the top. 2035252723Sdim 2036252723Sdim Loc = UpperLoc; 2037208600Srdivacky return false; 2038208600Srdivacky} 2039208600Srdivacky 2040252723Sdim/// Return the cache entry for comparing the given file IDs 2041252723Sdim/// for isBeforeInTranslationUnit. 2042252723SdimInBeforeInTUCacheEntry &SourceManager::getInBeforeInTUCache(FileID LFID, 2043252723Sdim FileID RFID) const { 2044252723Sdim // This is a magic number for limiting the cache size. It was experimentally 2045252723Sdim // derived from a small Objective-C project (where the cache filled 2046252723Sdim // out to ~250 items). We can make it larger if necessary. 2047252723Sdim enum { MagicCacheSize = 300 }; 2048252723Sdim IsBeforeInTUCacheKey Key(LFID, RFID); 2049252723Sdim 2050252723Sdim // If the cache size isn't too large, do a lookup and if necessary default 2051252723Sdim // construct an entry. We can then return it to the caller for direct 2052252723Sdim // use. When they update the value, the cache will get automatically 2053252723Sdim // updated as well. 2054252723Sdim if (IBTUCache.size() < MagicCacheSize) 2055252723Sdim return IBTUCache[Key]; 2056252723Sdim 2057252723Sdim // Otherwise, do a lookup that will not construct a new value. 2058252723Sdim InBeforeInTUCache::iterator I = IBTUCache.find(Key); 2059252723Sdim if (I != IBTUCache.end()) 2060252723Sdim return I->second; 2061252723Sdim 2062252723Sdim // Fall back to the overflow value. 2063252723Sdim return IBTUCacheOverflow; 2064252723Sdim} 2065252723Sdim 2066195099Sed/// \brief Determines the order of 2 source locations in the translation unit. 2067195099Sed/// 2068195099Sed/// \returns true if LHS source location comes before RHS, false otherwise. 2069195099Sedbool SourceManager::isBeforeInTranslationUnit(SourceLocation LHS, 2070195099Sed SourceLocation RHS) const { 2071195099Sed assert(LHS.isValid() && RHS.isValid() && "Passed invalid source location!"); 2072195099Sed if (LHS == RHS) 2073195099Sed return false; 2074198092Srdivacky 2075195099Sed std::pair<FileID, unsigned> LOffs = getDecomposedLoc(LHS); 2076195099Sed std::pair<FileID, unsigned> ROffs = getDecomposedLoc(RHS); 2077198092Srdivacky 2078263509Sdim // getDecomposedLoc may have failed to return a valid FileID because, e.g. it 2079263509Sdim // is a serialized one referring to a file that was removed after we loaded 2080263509Sdim // the PCH. 2081263509Sdim if (LOffs.first.isInvalid() || ROffs.first.isInvalid()) 2082263509Sdim return LOffs.first.isInvalid() && !ROffs.first.isInvalid(); 2083263509Sdim 2084195099Sed // If the source locations are in the same file, just compare offsets. 2085195099Sed if (LOffs.first == ROffs.first) 2086195099Sed return LOffs.second < ROffs.second; 2087194613Sed 2088195099Sed // If we are comparing a source location with multiple locations in the same 2089195099Sed // file, we get a big win by caching the result. 2090252723Sdim InBeforeInTUCacheEntry &IsBeforeInTUCache = 2091252723Sdim getInBeforeInTUCache(LOffs.first, ROffs.first); 2092252723Sdim 2093252723Sdim // If we are comparing a source location with multiple locations in the same 2094252723Sdim // file, we get a big win by caching the result. 2095208600Srdivacky if (IsBeforeInTUCache.isCacheValid(LOffs.first, ROffs.first)) 2096208600Srdivacky return IsBeforeInTUCache.getCachedResult(LOffs.second, ROffs.second); 2097198092Srdivacky 2098208600Srdivacky // Okay, we missed in the cache, start updating the cache for this query. 2099226890Sdim IsBeforeInTUCache.setQueryFIDs(LOffs.first, ROffs.first, 2100226890Sdim /*isLFIDBeforeRFID=*/LOffs.first.ID < ROffs.first.ID); 2101198092Srdivacky 2102226890Sdim // We need to find the common ancestor. The only way of doing this is to 2103226890Sdim // build the complete include chain for one and then walking up the chain 2104226890Sdim // of the other looking for a match. 2105226890Sdim // We use a map from FileID to Offset to store the chain. Easier than writing 2106226890Sdim // a custom set hash info that only depends on the first part of a pair. 2107252723Sdim typedef llvm::SmallDenseMap<FileID, unsigned, 16> LocSet; 2108226890Sdim LocSet LChain; 2109208600Srdivacky do { 2110226890Sdim LChain.insert(LOffs); 2111226890Sdim // We catch the case where LOffs is in a file included by ROffs and 2112226890Sdim // quit early. The other way round unfortunately remains suboptimal. 2113226890Sdim } while (LOffs.first != ROffs.first && !MoveUpIncludeHierarchy(LOffs, *this)); 2114226890Sdim LocSet::iterator I; 2115226890Sdim while((I = LChain.find(ROffs.first)) == LChain.end()) { 2116226890Sdim if (MoveUpIncludeHierarchy(ROffs, *this)) 2117226890Sdim break; // Met at topmost file. 2118226890Sdim } 2119226890Sdim if (I != LChain.end()) 2120226890Sdim LOffs = *I; 2121195099Sed 2122208600Srdivacky // If we exited because we found a nearest common ancestor, compare the 2123208600Srdivacky // locations within the common file and cache them. 2124208600Srdivacky if (LOffs.first == ROffs.first) { 2125208600Srdivacky IsBeforeInTUCache.setCommonLoc(LOffs.first, LOffs.second, ROffs.second); 2126208600Srdivacky return IsBeforeInTUCache.getCachedResult(LOffs.second, ROffs.second); 2127195099Sed } 2128195099Sed 2129226890Sdim // This can happen if a location is in a built-ins buffer. 2130226890Sdim // But see PR5662. 2131226890Sdim // Clear the lookup cache, it depends on a common location. 2132226890Sdim IsBeforeInTUCache.clear(); 2133226890Sdim bool LIsBuiltins = strcmp("<built-in>", 2134226890Sdim getBuffer(LOffs.first)->getBufferIdentifier()) == 0; 2135226890Sdim bool RIsBuiltins = strcmp("<built-in>", 2136226890Sdim getBuffer(ROffs.first)->getBufferIdentifier()) == 0; 2137226890Sdim // built-in is before non-built-in 2138226890Sdim if (LIsBuiltins != RIsBuiltins) 2139226890Sdim return LIsBuiltins; 2140226890Sdim assert(LIsBuiltins && RIsBuiltins && 2141226890Sdim "Non-built-in locations must be rooted in the main file"); 2142226890Sdim // Both are in built-in buffers, but from different files. We just claim that 2143226890Sdim // lower IDs come first. 2144208600Srdivacky return LOffs.first < ROffs.first; 2145195099Sed} 2146195099Sed 2147193326Sedvoid SourceManager::PrintStats() const { 2148198092Srdivacky llvm::errs() << "\n*** Source Manager Stats:\n"; 2149198092Srdivacky llvm::errs() << FileInfos.size() << " files mapped, " << MemBufferInfos.size() 2150198092Srdivacky << " mem buffers mapped.\n"; 2151226890Sdim llvm::errs() << LocalSLocEntryTable.size() << " local SLocEntry's allocated (" 2152226890Sdim << llvm::capacity_in_bytes(LocalSLocEntryTable) 2153224145Sdim << " bytes of capacity), " 2154226890Sdim << NextLocalOffset << "B of Sloc address space used.\n"; 2155226890Sdim llvm::errs() << LoadedSLocEntryTable.size() 2156226890Sdim << " loaded SLocEntries allocated, " 2157226890Sdim << MaxLoadedOffset - CurrentLoadedOffset 2158226890Sdim << "B of Sloc address space used.\n"; 2159226890Sdim 2160193326Sed unsigned NumLineNumsComputed = 0; 2161193326Sed unsigned NumFileBytesMapped = 0; 2162193326Sed for (fileinfo_iterator I = fileinfo_begin(), E = fileinfo_end(); I != E; ++I){ 2163193326Sed NumLineNumsComputed += I->second->SourceLineCache != 0; 2164193326Sed NumFileBytesMapped += I->second->getSizeBytesMapped(); 2165193326Sed } 2166226890Sdim unsigned NumMacroArgsComputed = MacroArgsCacheMap.size(); 2167198092Srdivacky 2168198092Srdivacky llvm::errs() << NumFileBytesMapped << " bytes of files mapped, " 2169226890Sdim << NumLineNumsComputed << " files with line #'s computed, " 2170226890Sdim << NumMacroArgsComputed << " files with macro args computed.\n"; 2171198092Srdivacky llvm::errs() << "FileID scans: " << NumLinearScans << " linear, " 2172198092Srdivacky << NumBinaryProbes << " binary.\n"; 2173193326Sed} 2174193326Sed 2175193326SedExternalSLocEntrySource::~ExternalSLocEntrySource() { } 2176221345Sdim 2177221345Sdim/// Return the amount of memory used by memory buffers, breaking down 2178221345Sdim/// by heap-backed versus mmap'ed memory. 2179221345SdimSourceManager::MemoryBufferSizes SourceManager::getMemoryBufferSizes() const { 2180221345Sdim size_t malloc_bytes = 0; 2181221345Sdim size_t mmap_bytes = 0; 2182221345Sdim 2183221345Sdim for (unsigned i = 0, e = MemBufferInfos.size(); i != e; ++i) 2184221345Sdim if (size_t sized_mapped = MemBufferInfos[i]->getSizeBytesMapped()) 2185221345Sdim switch (MemBufferInfos[i]->getMemoryBufferKind()) { 2186221345Sdim case llvm::MemoryBuffer::MemoryBuffer_MMap: 2187221345Sdim mmap_bytes += sized_mapped; 2188221345Sdim break; 2189221345Sdim case llvm::MemoryBuffer::MemoryBuffer_Malloc: 2190221345Sdim malloc_bytes += sized_mapped; 2191221345Sdim break; 2192221345Sdim } 2193221345Sdim 2194221345Sdim return MemoryBufferSizes(malloc_bytes, mmap_bytes); 2195221345Sdim} 2196221345Sdim 2197226890Sdimsize_t SourceManager::getDataStructureSizes() const { 2198245431Sdim size_t size = llvm::capacity_in_bytes(MemBufferInfos) 2199226890Sdim + llvm::capacity_in_bytes(LocalSLocEntryTable) 2200226890Sdim + llvm::capacity_in_bytes(LoadedSLocEntryTable) 2201226890Sdim + llvm::capacity_in_bytes(SLocEntryLoaded) 2202245431Sdim + llvm::capacity_in_bytes(FileInfos); 2203245431Sdim 2204245431Sdim if (OverriddenFilesInfo) 2205245431Sdim size += llvm::capacity_in_bytes(OverriddenFilesInfo->OverriddenFiles); 2206245431Sdim 2207245431Sdim return size; 2208226890Sdim} 2209