1918e0ca7SEugene Zelenko //===- SourceManager.cpp - Track and cache source files -------------------===//
27a51313dSChris Lattner //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67a51313dSChris Lattner //
77a51313dSChris Lattner //===----------------------------------------------------------------------===//
87a51313dSChris Lattner //
97a51313dSChris Lattner //  This file implements the SourceManager interface.
107a51313dSChris Lattner //
117a51313dSChris Lattner //===----------------------------------------------------------------------===//
127a51313dSChris Lattner 
137a51313dSChris Lattner #include "clang/Basic/SourceManager.h"
14802b7760SDouglas Gregor #include "clang/Basic/Diagnostic.h"
157a51313dSChris Lattner #include "clang/Basic/FileManager.h"
16918e0ca7SEugene Zelenko #include "clang/Basic/LLVM.h"
17918e0ca7SEugene Zelenko #include "clang/Basic/SourceLocation.h"
183a02247dSChandler Carruth #include "clang/Basic/SourceManagerInternals.h"
19918e0ca7SEugene Zelenko #include "llvm/ADT/DenseMap.h"
20918e0ca7SEugene Zelenko #include "llvm/ADT/None.h"
21e08464fbSReid Kleckner #include "llvm/ADT/Optional.h"
2261ef3db2SArgyrios Kyrtzidis #include "llvm/ADT/STLExtras.h"
23918e0ca7SEugene Zelenko #include "llvm/ADT/SmallVector.h"
24918e0ca7SEugene Zelenko #include "llvm/ADT/StringRef.h"
25e08464fbSReid Kleckner #include "llvm/ADT/StringSwitch.h"
26918e0ca7SEugene Zelenko #include "llvm/Support/Allocator.h"
273a02247dSChandler Carruth #include "llvm/Support/Capacity.h"
287a51313dSChris Lattner #include "llvm/Support/Compiler.h"
29918e0ca7SEugene Zelenko #include "llvm/Support/ErrorHandling.h"
30918e0ca7SEugene Zelenko #include "llvm/Support/FileSystem.h"
31918e0ca7SEugene Zelenko #include "llvm/Support/MathExtras.h"
327a51313dSChris Lattner #include "llvm/Support/MemoryBuffer.h"
338aaf4995SMichael J. Spencer #include "llvm/Support/Path.h"
343a02247dSChandler Carruth #include "llvm/Support/raw_ostream.h"
357a51313dSChris Lattner #include <algorithm>
36918e0ca7SEugene Zelenko #include <cassert>
37918e0ca7SEugene Zelenko #include <cstddef>
38918e0ca7SEugene Zelenko #include <cstdint>
39918e0ca7SEugene Zelenko #include <memory>
40918e0ca7SEugene Zelenko #include <tuple>
41918e0ca7SEugene Zelenko #include <utility>
42918e0ca7SEugene Zelenko #include <vector>
43802b7760SDouglas Gregor 
447a51313dSChris Lattner using namespace clang;
457a51313dSChris Lattner using namespace SrcMgr;
467a51313dSChris Lattner using llvm::MemoryBuffer;
477a51313dSChris Lattner 
48153a0f1fSChris Lattner //===----------------------------------------------------------------------===//
494fa23625SChris Lattner // SourceManager Helper Classes
50153a0f1fSChris Lattner //===----------------------------------------------------------------------===//
514fa23625SChris Lattner 
5264ee782eSChandler Carruth /// getSizeBytesMapped - Returns the number of bytes actually mapped for this
5364ee782eSChandler Carruth /// ContentCache. This can be 0 if the MemBuffer was not actually expanded.
5412c2af44STed Kremenek unsigned ContentCache::getSizeBytesMapped() const {
5529631451SDuncan P. N. Exon Smith   return Buffer ? Buffer->getBufferSize() : 0;
5612c2af44STed Kremenek }
5712c2af44STed Kremenek 
588d587900STed Kremenek /// Returns the kind of memory used to back the memory buffer for
598d587900STed Kremenek /// this content cache.  This is used for performance analysis.
608d587900STed Kremenek llvm::MemoryBuffer::BufferKind ContentCache::getMemoryBufferKind() const {
6129631451SDuncan P. N. Exon Smith   assert(Buffer);
628d587900STed Kremenek 
638d587900STed Kremenek   // Should be unreachable, but keep for sanity.
6429631451SDuncan P. N. Exon Smith   if (!Buffer)
658d587900STed Kremenek     return llvm::MemoryBuffer::MemoryBuffer_Malloc;
668d587900STed Kremenek 
6729631451SDuncan P. N. Exon Smith   return Buffer->getBufferKind();
688d587900STed Kremenek }
698d587900STed Kremenek 
7012c2af44STed Kremenek /// getSize - Returns the size of the content encapsulated by this ContentCache.
7112c2af44STed Kremenek ///  This can be the size of the source file or the size of an arbitrary
7212c2af44STed Kremenek ///  scratch buffer.  If the ContentCache encapsulates a source file, that
7353ad6b94SDouglas Gregor ///  file is not lazily brought in from disk to satisfy this query.
7412c2af44STed Kremenek unsigned ContentCache::getSize() const {
7529631451SDuncan P. N. Exon Smith   return Buffer ? (unsigned)Buffer->getBufferSize()
7611e6f0a6SArgyrios Kyrtzidis                 : (unsigned)ContentsEntry->getSize();
7712c2af44STed Kremenek }
7812c2af44STed Kremenek 
798fa5e98fSpaulhoad const char *ContentCache::getInvalidBOM(StringRef BufStr) {
808fa5e98fSpaulhoad   // If the buffer is valid, check to see if it has a UTF Byte Order Mark
818fa5e98fSpaulhoad   // (BOM).  We only support UTF-8 with and without a BOM right now.  See
828fa5e98fSpaulhoad   // http://en.wikipedia.org/wiki/Byte_order_mark for more information.
838fa5e98fSpaulhoad   const char *InvalidBOM =
848fa5e98fSpaulhoad       llvm::StringSwitch<const char *>(BufStr)
858fa5e98fSpaulhoad           .StartsWith(llvm::StringLiteral::withInnerNUL("\x00\x00\xFE\xFF"),
868fa5e98fSpaulhoad                       "UTF-32 (BE)")
878fa5e98fSpaulhoad           .StartsWith(llvm::StringLiteral::withInnerNUL("\xFF\xFE\x00\x00"),
888fa5e98fSpaulhoad                       "UTF-32 (LE)")
898fa5e98fSpaulhoad           .StartsWith("\xFE\xFF", "UTF-16 (BE)")
908fa5e98fSpaulhoad           .StartsWith("\xFF\xFE", "UTF-16 (LE)")
918fa5e98fSpaulhoad           .StartsWith("\x2B\x2F\x76", "UTF-7")
928fa5e98fSpaulhoad           .StartsWith("\xF7\x64\x4C", "UTF-1")
938fa5e98fSpaulhoad           .StartsWith("\xDD\x73\x66\x73", "UTF-EBCDIC")
948fa5e98fSpaulhoad           .StartsWith("\x0E\xFE\xFF", "SCSU")
958fa5e98fSpaulhoad           .StartsWith("\xFB\xEE\x28", "BOCU-1")
968fa5e98fSpaulhoad           .StartsWith("\x84\x31\x95\x33", "GB-18030")
978fa5e98fSpaulhoad           .Default(nullptr);
988fa5e98fSpaulhoad 
998fa5e98fSpaulhoad   return InvalidBOM;
1008fa5e98fSpaulhoad }
1018fa5e98fSpaulhoad 
102d758f79eSDuncan P. N. Exon Smith llvm::Optional<llvm::MemoryBufferRef>
103d758f79eSDuncan P. N. Exon Smith ContentCache::getBufferOrNone(DiagnosticsEngine &Diag, FileManager &FM,
104d758f79eSDuncan P. N. Exon Smith                               SourceLocation Loc) const {
1055631b052SChris Lattner   // Lazily create the Buffer for ContentCaches that wrap files.  If we already
10657540c5bSChris Lattner   // computed it, just return what we have.
1071d78e210SDuncan P. N. Exon Smith   if (IsBufferInvalid)
108747b134dSDuncan P. N. Exon Smith     return None;
10929631451SDuncan P. N. Exon Smith   if (Buffer)
11029631451SDuncan P. N. Exon Smith     return Buffer->getMemBufferRef();
111d758f79eSDuncan P. N. Exon Smith   if (!ContentsEntry)
112747b134dSDuncan P. N. Exon Smith     return None;
1135631b052SChris Lattner 
1144aa97e3dSDuncan P. N. Exon Smith   // Start with the assumption that the buffer is invalid to simplify early
1154aa97e3dSDuncan P. N. Exon Smith   // return paths.
1164aa97e3dSDuncan P. N. Exon Smith   IsBufferInvalid = true;
1174aa97e3dSDuncan P. N. Exon Smith 
118979ae80aSRichard Smith   // Check that the file's size fits in an 'unsigned' (with room for a
119979ae80aSRichard Smith   // past-the-end value). This is deeply regrettable, but various parts of
120979ae80aSRichard Smith   // Clang (including elsewhere in this file!) use 'unsigned' to represent file
121979ae80aSRichard Smith   // offsets, line numbers, string literal lengths, and so on, and fail
122979ae80aSRichard Smith   // miserably on large source files.
123a372bb21SSimon Pilgrim   if ((uint64_t)ContentsEntry->getSize() >=
124a372bb21SSimon Pilgrim       std::numeric_limits<unsigned>::max()) {
125979ae80aSRichard Smith     if (Diag.isDiagnosticInFlight())
126979ae80aSRichard Smith       Diag.SetDelayedDiagnostic(diag::err_file_too_large,
127979ae80aSRichard Smith                                 ContentsEntry->getName());
128979ae80aSRichard Smith     else
129979ae80aSRichard Smith       Diag.Report(Loc, diag::err_file_too_large)
130979ae80aSRichard Smith         << ContentsEntry->getName();
131979ae80aSRichard Smith 
132747b134dSDuncan P. N. Exon Smith     return None;
133979ae80aSRichard Smith   }
134979ae80aSRichard Smith 
135f5848190SDuncan P. N. Exon Smith   auto BufferOrError = FM.getBufferForFile(ContentsEntry, IsFileVolatile);
1367cea5f17SDaniel Dunbar 
1377cea5f17SDaniel Dunbar   // If we were unable to open the file, then we are in an inconsistent
1387cea5f17SDaniel Dunbar   // situation where the content cache referenced a file which no longer
1397cea5f17SDaniel Dunbar   // exists. Most likely, we were using a stat cache with an invalid entry but
1407cea5f17SDaniel Dunbar   // the file could also have been removed during processing. Since we can't
1417cea5f17SDaniel Dunbar   // really deal with this situation, just create an empty buffer.
142a885796dSBenjamin Kramer   if (!BufferOrError) {
14385795316SDouglas Gregor     if (Diag.isDiagnosticInFlight())
14485795316SDouglas Gregor       Diag.SetDelayedDiagnostic(diag::err_cannot_open_file,
145a885796dSBenjamin Kramer                                 ContentsEntry->getName(),
146a885796dSBenjamin Kramer                                 BufferOrError.getError().message());
14785795316SDouglas Gregor     else
148d0040648SArgyrios Kyrtzidis       Diag.Report(Loc, diag::err_cannot_open_file)
149a885796dSBenjamin Kramer           << ContentsEntry->getName() << BufferOrError.getError().message();
15085795316SDouglas Gregor 
151747b134dSDuncan P. N. Exon Smith     return None;
1525631b052SChris Lattner   }
1535631b052SChris Lattner 
15429631451SDuncan P. N. Exon Smith   Buffer = std::move(*BufferOrError);
155a885796dSBenjamin Kramer 
1564ac569b2SChris Lattner   // Check that the file's size is the same as in the file entry (which may
1574ac569b2SChris Lattner   // have come from a stat cache).
158156e8b37SDuncan P. N. Exon Smith   if (Buffer->getBufferSize() != (size_t)ContentsEntry->getSize()) {
15985795316SDouglas Gregor     if (Diag.isDiagnosticInFlight())
16085795316SDouglas Gregor       Diag.SetDelayedDiagnostic(diag::err_file_modified,
16111e6f0a6SArgyrios Kyrtzidis                                 ContentsEntry->getName());
16285795316SDouglas Gregor     else
163d0040648SArgyrios Kyrtzidis       Diag.Report(Loc, diag::err_file_modified)
16411e6f0a6SArgyrios Kyrtzidis         << ContentsEntry->getName();
16585795316SDouglas Gregor 
166747b134dSDuncan P. N. Exon Smith     return None;
1677cea5f17SDaniel Dunbar   }
1688fbe98b3SChris Lattner 
1698fbe98b3SChris Lattner   // If the buffer is valid, check to see if it has a UTF Byte Order Mark
1707f36a79eSEric Christopher   // (BOM).  We only support UTF-8 with and without a BOM right now.  See
1718fbe98b3SChris Lattner   // http://en.wikipedia.org/wiki/Byte_order_mark for more information.
17229631451SDuncan P. N. Exon Smith   StringRef BufStr = Buffer->getBuffer();
1738fa5e98fSpaulhoad   const char *InvalidBOM = getInvalidBOM(BufStr);
1748fbe98b3SChris Lattner 
1757f36a79eSEric Christopher   if (InvalidBOM) {
176d0040648SArgyrios Kyrtzidis     Diag.Report(Loc, diag::err_unsupported_bom)
1777f36a79eSEric Christopher       << InvalidBOM << ContentsEntry->getName();
178747b134dSDuncan P. N. Exon Smith     return None;
179763ea559STed Kremenek   }
180802b7760SDouglas Gregor 
1814aa97e3dSDuncan P. N. Exon Smith   // Buffer has been validated.
1824aa97e3dSDuncan P. N. Exon Smith   IsBufferInvalid = false;
18329631451SDuncan P. N. Exon Smith   return Buffer->getMemBufferRef();
18412c2af44STed Kremenek }
18512c2af44STed Kremenek 
1860e62c1ccSChris Lattner unsigned LineTableInfo::getLineTableFilenameID(StringRef Name) {
187eae2b49fSFangrui Song   auto IterBool = FilenameIDs.try_emplace(Name, FilenamesByID.size());
18813156b68SDavid Blaikie   if (IterBool.second)
18913156b68SDavid Blaikie     FilenamesByID.push_back(&*IterBool.first);
19013156b68SDavid Blaikie   return IterBool.first->second;
191b5fba6f8SChris Lattner }
192b5fba6f8SChris Lattner 
193eb00ee07SReid Kleckner /// Add a line note to the line table that indicates that there is a \#line or
194eb00ee07SReid Kleckner /// GNU line marker at the specified FID/Offset location which changes the
195eb00ee07SReid Kleckner /// presumed location to LineNo/FilenameID. If EntryExit is 0, then this doesn't
196eb00ee07SReid Kleckner /// change the presumed \#include stack.  If it is 1, this is a file entry, if
197eb00ee07SReid Kleckner /// it is 2 then this is a file exit. FileKind specifies whether this is a
198eb00ee07SReid Kleckner /// system header or extern C system header.
199eb00ee07SReid Kleckner void LineTableInfo::AddLineNote(FileID FID, unsigned Offset, unsigned LineNo,
200eb00ee07SReid Kleckner                                 int FilenameID, unsigned EntryExit,
2010a1a8d85SChris Lattner                                 SrcMgr::CharacteristicKind FileKind) {
2020a1a8d85SChris Lattner   std::vector<LineEntry> &Entries = LineEntries[FID];
2030a1a8d85SChris Lattner 
204eb00ee07SReid Kleckner   // An unspecified FilenameID means use the last filename if available, or the
205eb00ee07SReid Kleckner   // main source file otherwise.
206eb00ee07SReid Kleckner   if (FilenameID == -1 && !Entries.empty())
207eb00ee07SReid Kleckner     FilenameID = Entries.back().FilenameID;
208eb00ee07SReid Kleckner 
2090a1a8d85SChris Lattner   assert((Entries.empty() || Entries.back().FileOffset < Offset) &&
2100a1a8d85SChris Lattner          "Adding line entries out of order!");
2110a1a8d85SChris Lattner 
2121c967784SChris Lattner   unsigned IncludeOffset = 0;
2131c967784SChris Lattner   if (EntryExit == 0) {  // No #include stack change.
2141c967784SChris Lattner     IncludeOffset = Entries.empty() ? 0 : Entries.back().IncludeOffset;
2151c967784SChris Lattner   } else if (EntryExit == 1) {
2161c967784SChris Lattner     IncludeOffset = Offset-1;
2171c967784SChris Lattner   } else if (EntryExit == 2) {
2181c967784SChris Lattner     assert(!Entries.empty() && Entries.back().IncludeOffset &&
2191c967784SChris Lattner        "PPDirectives should have caught case when popping empty include stack");
2200a1a8d85SChris Lattner 
2211c967784SChris Lattner     // Get the include loc of the last entries' include loc as our include loc.
2221c967784SChris Lattner     IncludeOffset = 0;
2231c967784SChris Lattner     if (const LineEntry *PrevEntry =
2241c967784SChris Lattner           FindNearestLineEntry(FID, Entries.back().IncludeOffset))
2251c967784SChris Lattner       IncludeOffset = PrevEntry->IncludeOffset;
2261c967784SChris Lattner   }
2270a1a8d85SChris Lattner 
2281c967784SChris Lattner   Entries.push_back(LineEntry::get(Offset, LineNo, FilenameID, FileKind,
2291c967784SChris Lattner                                    IncludeOffset));
2300a1a8d85SChris Lattner }
2310a1a8d85SChris Lattner 
232d4293922SChris Lattner /// FindNearestLineEntry - Find the line entry nearest to FID that is before
233d4293922SChris Lattner /// it.  If there is no line entry before Offset in FID, return null.
23402c2dbf4SDouglas Gregor const LineEntry *LineTableInfo::FindNearestLineEntry(FileID FID,
235d4293922SChris Lattner                                                      unsigned Offset) {
236d4293922SChris Lattner   const std::vector<LineEntry> &Entries = LineEntries[FID];
237d4293922SChris Lattner   assert(!Entries.empty() && "No #line entries for this FID after all!");
238d4293922SChris Lattner 
239334a2adaSChris Lattner   // It is very common for the query to be after the last #line, check this
240334a2adaSChris Lattner   // first.
241334a2adaSChris Lattner   if (Entries.back().FileOffset <= Offset)
242334a2adaSChris Lattner     return &Entries.back();
243d4293922SChris Lattner 
244334a2adaSChris Lattner   // Do a binary search to find the maximal element that is still before Offset.
2457264a474SFangrui Song   std::vector<LineEntry>::const_iterator I = llvm::upper_bound(Entries, Offset);
2467264a474SFangrui Song   if (I == Entries.begin())
2477264a474SFangrui Song     return nullptr;
248334a2adaSChris Lattner   return &*--I;
249d4293922SChris Lattner }
2506e0e1f49SChris Lattner 
2519fc8faf9SAdrian Prantl /// Add a new line entry that has already been encoded into
2524c7626e7SDouglas Gregor /// the internal representation of the line table.
25302c2dbf4SDouglas Gregor void LineTableInfo::AddEntry(FileID FID,
2544c7626e7SDouglas Gregor                              const std::vector<LineEntry> &Entries) {
2554c7626e7SDouglas Gregor   LineEntries[FID] = Entries;
2564c7626e7SDouglas Gregor }
2576e0e1f49SChris Lattner 
258b5fba6f8SChris Lattner /// getLineTableFilenameID - Return the uniqued ID for the specified filename.
2590e62c1ccSChris Lattner unsigned SourceManager::getLineTableFilenameID(StringRef Name) {
2605eeeab7dSVedant Kumar   return getLineTable().getLineTableFilenameID(Name);
261b5fba6f8SChris Lattner }
262b5fba6f8SChris Lattner 
2631eaa70a6SChris Lattner /// AddLineNote - Add a line note to the line table for the FileID and offset
2641eaa70a6SChris Lattner /// specified by Loc.  If FilenameID is -1, it is considered to be
2651eaa70a6SChris Lattner /// unspecified.
2661eaa70a6SChris Lattner void SourceManager::AddLineNote(SourceLocation Loc, unsigned LineNo,
2670a1a8d85SChris Lattner                                 int FilenameID, bool IsFileEntry,
268eb00ee07SReid Kleckner                                 bool IsFileExit,
269eb00ee07SReid Kleckner                                 SrcMgr::CharacteristicKind FileKind) {
270c7ca5218SChandler Carruth   std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(Loc);
27149f754f4SDouglas Gregor 
27249f754f4SDouglas Gregor   bool Invalid = false;
27349f754f4SDouglas Gregor   const SLocEntry &Entry = getSLocEntry(LocInfo.first, &Invalid);
27449f754f4SDouglas Gregor   if (!Entry.isFile() || Invalid)
27549f754f4SDouglas Gregor     return;
27649f754f4SDouglas Gregor 
27749f754f4SDouglas Gregor   const SrcMgr::FileInfo &FileInfo = Entry.getFile();
2780a1a8d85SChris Lattner 
2790a1a8d85SChris Lattner   // Remember that this file has #line directives now if it doesn't already.
2800a1a8d85SChris Lattner   const_cast<SrcMgr::FileInfo&>(FileInfo).setHasLineDirectives();
2810a1a8d85SChris Lattner 
2825eeeab7dSVedant Kumar   (void) getLineTable();
2830a1a8d85SChris Lattner 
2840a1a8d85SChris Lattner   unsigned EntryExit = 0;
2850a1a8d85SChris Lattner   if (IsFileEntry)
2860a1a8d85SChris Lattner     EntryExit = 1;
2870a1a8d85SChris Lattner   else if (IsFileExit)
2880a1a8d85SChris Lattner     EntryExit = 2;
2890a1a8d85SChris Lattner 
29002c2dbf4SDouglas Gregor   LineTable->AddLineNote(LocInfo.first, LocInfo.second, LineNo, FilenameID,
2910a1a8d85SChris Lattner                          EntryExit, FileKind);
2920a1a8d85SChris Lattner }
2930a1a8d85SChris Lattner 
2944c7626e7SDouglas Gregor LineTableInfo &SourceManager::getLineTable() {
295f1186c5aSCraig Topper   if (!LineTable)
296a2dcbd36SNico Weber     LineTable.reset(new LineTableInfo());
2974c7626e7SDouglas Gregor   return *LineTable;
2984c7626e7SDouglas Gregor }
2991eaa70a6SChris Lattner 
300153a0f1fSChris Lattner //===----------------------------------------------------------------------===//
3014fa23625SChris Lattner // Private 'Create' methods.
302153a0f1fSChris Lattner //===----------------------------------------------------------------------===//
30312c2af44STed Kremenek 
3046d7833f1SArgyrios Kyrtzidis SourceManager::SourceManager(DiagnosticsEngine &Diag, FileManager &FileMgr,
3056d7833f1SArgyrios Kyrtzidis                              bool UserFilesAreVolatile)
306918e0ca7SEugene Zelenko   : Diag(Diag), FileMgr(FileMgr), UserFilesAreVolatile(UserFilesAreVolatile) {
307d0040648SArgyrios Kyrtzidis   clearIDTables();
308d0040648SArgyrios Kyrtzidis   Diag.setSourceManager(this);
309d0040648SArgyrios Kyrtzidis }
310d0040648SArgyrios Kyrtzidis 
311b5fba6f8SChris Lattner SourceManager::~SourceManager() {
312c8233df6SChris Lattner   // Delete FileEntry objects corresponding to content caches.  Since the actual
313c8233df6SChris Lattner   // content cache objects are bump pointer allocated, we just have to run the
314c8233df6SChris Lattner   // dtors, but we call the deallocate method for completeness.
315c8233df6SChris Lattner   for (unsigned i = 0, e = MemBufferInfos.size(); i != e; ++i) {
316af41b3f0SArgyrios Kyrtzidis     if (MemBufferInfos[i]) {
317c8233df6SChris Lattner       MemBufferInfos[i]->~ContentCache();
318c8233df6SChris Lattner       ContentCacheAlloc.Deallocate(MemBufferInfos[i]);
319c8233df6SChris Lattner     }
320af41b3f0SArgyrios Kyrtzidis   }
321c8233df6SChris Lattner   for (llvm::DenseMap<const FileEntry*, SrcMgr::ContentCache*>::iterator
322c8233df6SChris Lattner        I = FileInfos.begin(), E = FileInfos.end(); I != E; ++I) {
323af41b3f0SArgyrios Kyrtzidis     if (I->second) {
324c8233df6SChris Lattner       I->second->~ContentCache();
325c8233df6SChris Lattner       ContentCacheAlloc.Deallocate(I->second);
326c8233df6SChris Lattner     }
327af41b3f0SArgyrios Kyrtzidis   }
328b5fba6f8SChris Lattner }
329b5fba6f8SChris Lattner 
330b5fba6f8SChris Lattner void SourceManager::clearIDTables() {
331b5fba6f8SChris Lattner   MainFileID = FileID();
332925296b4SDouglas Gregor   LocalSLocEntryTable.clear();
333925296b4SDouglas Gregor   LoadedSLocEntryTable.clear();
334925296b4SDouglas Gregor   SLocEntryLoaded.clear();
335b5fba6f8SChris Lattner   LastLineNoFileIDQuery = FileID();
336f1186c5aSCraig Topper   LastLineNoContentCache = nullptr;
337b5fba6f8SChris Lattner   LastFileIDLookup = FileID();
338b5fba6f8SChris Lattner 
339b5fba6f8SChris Lattner   if (LineTable)
340b5fba6f8SChris Lattner     LineTable->clear();
341b5fba6f8SChris Lattner 
34264ee782eSChandler Carruth   // Use up FileID #0 as an invalid expansion.
343925296b4SDouglas Gregor   NextLocalOffset = 0;
34492a47bd9SArgyrios Kyrtzidis   CurrentLoadedOffset = MaxLoadedOffset;
345115b077fSChandler Carruth   createExpansionLoc(SourceLocation(), SourceLocation(), SourceLocation(), 1);
346b5fba6f8SChris Lattner }
347b5fba6f8SChris Lattner 
348168db924SDuncan P. N. Exon Smith bool SourceManager::isMainFile(const FileEntry &SourceFile) {
34911d612acSAlex Lorenz   assert(MainFileID.isValid() && "expected initialized SourceManager");
350168db924SDuncan P. N. Exon Smith   if (auto *FE = getFileEntryForID(MainFileID))
35111d612acSAlex Lorenz     return FE->getUID() == SourceFile.getUID();
352168db924SDuncan P. N. Exon Smith   return false;
35311d612acSAlex Lorenz }
35411d612acSAlex Lorenz 
355ab75597dSRichard Smith void SourceManager::initializeForReplay(const SourceManager &Old) {
356ab75597dSRichard Smith   assert(MainFileID.isInvalid() && "expected uninitialized SourceManager");
357ab75597dSRichard Smith 
358ab75597dSRichard Smith   auto CloneContentCache = [&](const ContentCache *Cache) -> ContentCache * {
359ab75597dSRichard Smith     auto *Clone = new (ContentCacheAlloc.Allocate<ContentCache>()) ContentCache;
360ab75597dSRichard Smith     Clone->OrigEntry = Cache->OrigEntry;
361ab75597dSRichard Smith     Clone->ContentsEntry = Cache->ContentsEntry;
362ab75597dSRichard Smith     Clone->BufferOverridden = Cache->BufferOverridden;
363f5848190SDuncan P. N. Exon Smith     Clone->IsFileVolatile = Cache->IsFileVolatile;
364ab75597dSRichard Smith     Clone->IsTransient = Cache->IsTransient;
365156e8b37SDuncan P. N. Exon Smith     Clone->setUnownedBuffer(Cache->getBufferIfLoaded());
366ab75597dSRichard Smith     return Clone;
367ab75597dSRichard Smith   };
368ab75597dSRichard Smith 
369ab75597dSRichard Smith   // Ensure all SLocEntries are loaded from the external source.
370ab75597dSRichard Smith   for (unsigned I = 0, N = Old.LoadedSLocEntryTable.size(); I != N; ++I)
371ab75597dSRichard Smith     if (!Old.SLocEntryLoaded[I])
372ab75597dSRichard Smith       Old.loadSLocEntry(I, nullptr);
373ab75597dSRichard Smith 
374ab75597dSRichard Smith   // Inherit any content cache data from the old source manager.
375ab75597dSRichard Smith   for (auto &FileInfo : Old.FileInfos) {
376ab75597dSRichard Smith     SrcMgr::ContentCache *&Slot = FileInfos[FileInfo.first];
377ab75597dSRichard Smith     if (Slot)
378ab75597dSRichard Smith       continue;
379ab75597dSRichard Smith     Slot = CloneContentCache(FileInfo.second);
380ab75597dSRichard Smith   }
381ab75597dSRichard Smith }
382ab75597dSRichard Smith 
3834fa23625SChris Lattner /// getOrCreateContentCache - Create or return a cached ContentCache for the
3844fa23625SChris Lattner /// specified file.
3854fa23625SChris Lattner const ContentCache *
3866d7833f1SArgyrios Kyrtzidis SourceManager::getOrCreateContentCache(const FileEntry *FileEnt,
3876d7833f1SArgyrios Kyrtzidis                                        bool isSystemFile) {
3887a51313dSChris Lattner   assert(FileEnt && "Didn't specify a file entry to use?");
3894fa23625SChris Lattner 
3907a51313dSChris Lattner   // Do we already have information about this file?
391c8233df6SChris Lattner   ContentCache *&Entry = FileInfos[FileEnt];
392c8233df6SChris Lattner   if (Entry) return Entry;
3937a51313dSChris Lattner 
39447c48087SChandler Carruth   // Nope, create a new Cache entry.
39547c48087SChandler Carruth   Entry = ContentCacheAlloc.Allocate<ContentCache>();
39611e6f0a6SArgyrios Kyrtzidis 
3976eec06d0SArgyrios Kyrtzidis   if (OverriddenFilesInfo) {
39811e6f0a6SArgyrios Kyrtzidis     // If the file contents are overridden with contents from another file,
39911e6f0a6SArgyrios Kyrtzidis     // pass that file to ContentCache.
40011e6f0a6SArgyrios Kyrtzidis     llvm::DenseMap<const FileEntry *, const FileEntry *>::iterator
4016eec06d0SArgyrios Kyrtzidis         overI = OverriddenFilesInfo->OverriddenFiles.find(FileEnt);
4026eec06d0SArgyrios Kyrtzidis     if (overI == OverriddenFilesInfo->OverriddenFiles.end())
403c8233df6SChris Lattner       new (Entry) ContentCache(FileEnt);
40411e6f0a6SArgyrios Kyrtzidis     else
40597d3a38cSArgyrios Kyrtzidis       new (Entry) ContentCache(OverridenFilesKeepOriginalName ? FileEnt
40697d3a38cSArgyrios Kyrtzidis                                                               : overI->second,
40797d3a38cSArgyrios Kyrtzidis                                overI->second);
4086eec06d0SArgyrios Kyrtzidis   } else {
4096eec06d0SArgyrios Kyrtzidis     new (Entry) ContentCache(FileEnt);
4106eec06d0SArgyrios Kyrtzidis   }
41111e6f0a6SArgyrios Kyrtzidis 
412f5848190SDuncan P. N. Exon Smith   Entry->IsFileVolatile = UserFilesAreVolatile && !isSystemFile;
413a8cfffa3SRichard Smith   Entry->IsTransient = FilesAreTransient;
4146d7833f1SArgyrios Kyrtzidis 
415c8233df6SChris Lattner   return Entry;
4167a51313dSChris Lattner }
4177a51313dSChris Lattner 
4186d9bc278SRichard Smith /// Create a new ContentCache for the specified memory buffer.
4196d9bc278SRichard Smith /// This does no caching.
42051d1d585SDuncan P. N. Exon Smith const ContentCache *SourceManager::createMemBufferContentCache(
42151d1d585SDuncan P. N. Exon Smith     std::unique_ptr<llvm::MemoryBuffer> Buffer) {
42247c48087SChandler Carruth   // Add a new ContentCache to the MemBufferInfos list and return it.
42347c48087SChandler Carruth   ContentCache *Entry = ContentCacheAlloc.Allocate<ContentCache>();
424c8233df6SChris Lattner   new (Entry) ContentCache();
425c8233df6SChris Lattner   MemBufferInfos.push_back(Entry);
42629631451SDuncan P. N. Exon Smith   Entry->setBuffer(std::move(Buffer));
427c8233df6SChris Lattner   return Entry;
4287a51313dSChris Lattner }
4297a51313dSChris Lattner 
430969fdfddSArgyrios Kyrtzidis const SrcMgr::SLocEntry &SourceManager::loadSLocEntry(unsigned Index,
431969fdfddSArgyrios Kyrtzidis                                                       bool *Invalid) const {
432969fdfddSArgyrios Kyrtzidis   assert(!SLocEntryLoaded[Index]);
433969fdfddSArgyrios Kyrtzidis   if (ExternalSLocEntries->ReadSLocEntry(-(static_cast<int>(Index) + 2))) {
434969fdfddSArgyrios Kyrtzidis     if (Invalid)
435969fdfddSArgyrios Kyrtzidis       *Invalid = true;
436969fdfddSArgyrios Kyrtzidis     // If the file of the SLocEntry changed we could still have loaded it.
437969fdfddSArgyrios Kyrtzidis     if (!SLocEntryLoaded[Index]) {
438969fdfddSArgyrios Kyrtzidis       // Try to recover; create a SLocEntry so the rest of clang can handle it.
4394dc5573aSAlex Lorenz       LoadedSLocEntryTable[Index] = SLocEntry::get(
44074a87834SDuncan P. N. Exon Smith           0, FileInfo::get(SourceLocation(), *getFakeContentCacheForRecovery(),
4414dc5573aSAlex Lorenz                            SrcMgr::C_User, ""));
442969fdfddSArgyrios Kyrtzidis     }
443969fdfddSArgyrios Kyrtzidis   }
444969fdfddSArgyrios Kyrtzidis 
445969fdfddSArgyrios Kyrtzidis   return LoadedSLocEntryTable[Index];
446969fdfddSArgyrios Kyrtzidis }
447969fdfddSArgyrios Kyrtzidis 
448925296b4SDouglas Gregor std::pair<int, unsigned>
449925296b4SDouglas Gregor SourceManager::AllocateLoadedSLocEntries(unsigned NumSLocEntries,
450925296b4SDouglas Gregor                                          unsigned TotalSize) {
451925296b4SDouglas Gregor   assert(ExternalSLocEntries && "Don't have an external sloc source");
45278d81ecfSRichard Smith   // Make sure we're not about to run out of source locations.
45378d81ecfSRichard Smith   if (CurrentLoadedOffset - TotalSize < NextLocalOffset)
45478d81ecfSRichard Smith     return std::make_pair(0, 0);
455925296b4SDouglas Gregor   LoadedSLocEntryTable.resize(LoadedSLocEntryTable.size() + NumSLocEntries);
456925296b4SDouglas Gregor   SLocEntryLoaded.resize(LoadedSLocEntryTable.size());
457925296b4SDouglas Gregor   CurrentLoadedOffset -= TotalSize;
458925296b4SDouglas Gregor   int ID = LoadedSLocEntryTable.size();
459925296b4SDouglas Gregor   return std::make_pair(-ID - 1, CurrentLoadedOffset);
4600bc12935SDouglas Gregor }
4610bc12935SDouglas Gregor 
4629fc8faf9SAdrian Prantl /// As part of recovering from missing or changed content, produce a
46349f754f4SDouglas Gregor /// fake, non-empty buffer.
46466cc07b4SDavid Blaikie llvm::MemoryBuffer *SourceManager::getFakeBufferForRecovery() const {
46549f754f4SDouglas Gregor   if (!FakeBufferForRecovery)
466d87f8d76SRafael Espindola     FakeBufferForRecovery =
467d87f8d76SRafael Espindola         llvm::MemoryBuffer::getMemBuffer("<<<INVALID BUFFER>>");
46849f754f4SDouglas Gregor 
469e0f6d886SRafael Espindola   return FakeBufferForRecovery.get();
47049f754f4SDouglas Gregor }
471258ae54aSDouglas Gregor 
4729fc8faf9SAdrian Prantl /// As part of recovering from missing or changed content, produce a
473969fdfddSArgyrios Kyrtzidis /// fake content cache.
474969fdfddSArgyrios Kyrtzidis const SrcMgr::ContentCache *
475969fdfddSArgyrios Kyrtzidis SourceManager::getFakeContentCacheForRecovery() const {
476969fdfddSArgyrios Kyrtzidis   if (!FakeContentCacheForRecovery) {
4772b3d49b6SJonas Devlieghere     FakeContentCacheForRecovery = std::make_unique<SrcMgr::ContentCache>();
478156e8b37SDuncan P. N. Exon Smith     FakeContentCacheForRecovery->setUnownedBuffer(
479156e8b37SDuncan P. N. Exon Smith         getFakeBufferForRecovery()->getMemBufferRef());
480969fdfddSArgyrios Kyrtzidis   }
481e0f6d886SRafael Espindola   return FakeContentCacheForRecovery.get();
482969fdfddSArgyrios Kyrtzidis }
483969fdfddSArgyrios Kyrtzidis 
4849fc8faf9SAdrian Prantl /// Returns the previous in-order FileID or an invalid FileID if there
485065d720cSArgyrios Kyrtzidis /// is no previous one.
486065d720cSArgyrios Kyrtzidis FileID SourceManager::getPreviousFileID(FileID FID) const {
487065d720cSArgyrios Kyrtzidis   if (FID.isInvalid())
488065d720cSArgyrios Kyrtzidis     return FileID();
489065d720cSArgyrios Kyrtzidis 
490065d720cSArgyrios Kyrtzidis   int ID = FID.ID;
491065d720cSArgyrios Kyrtzidis   if (ID == -1)
492065d720cSArgyrios Kyrtzidis     return FileID();
493065d720cSArgyrios Kyrtzidis 
494065d720cSArgyrios Kyrtzidis   if (ID > 0) {
495065d720cSArgyrios Kyrtzidis     if (ID-1 == 0)
496065d720cSArgyrios Kyrtzidis       return FileID();
497065d720cSArgyrios Kyrtzidis   } else if (unsigned(-(ID-1) - 2) >= LoadedSLocEntryTable.size()) {
498065d720cSArgyrios Kyrtzidis     return FileID();
499065d720cSArgyrios Kyrtzidis   }
500065d720cSArgyrios Kyrtzidis 
501065d720cSArgyrios Kyrtzidis   return FileID::get(ID-1);
502065d720cSArgyrios Kyrtzidis }
503065d720cSArgyrios Kyrtzidis 
5049fc8faf9SAdrian Prantl /// Returns the next in-order FileID or an invalid FileID if there is
505065d720cSArgyrios Kyrtzidis /// no next one.
506065d720cSArgyrios Kyrtzidis FileID SourceManager::getNextFileID(FileID FID) const {
507065d720cSArgyrios Kyrtzidis   if (FID.isInvalid())
508065d720cSArgyrios Kyrtzidis     return FileID();
509065d720cSArgyrios Kyrtzidis 
510065d720cSArgyrios Kyrtzidis   int ID = FID.ID;
511065d720cSArgyrios Kyrtzidis   if (ID > 0) {
512065d720cSArgyrios Kyrtzidis     if (unsigned(ID+1) >= local_sloc_entry_size())
513065d720cSArgyrios Kyrtzidis       return FileID();
514065d720cSArgyrios Kyrtzidis   } else if (ID+1 >= -1) {
515065d720cSArgyrios Kyrtzidis     return FileID();
516065d720cSArgyrios Kyrtzidis   }
517065d720cSArgyrios Kyrtzidis 
518065d720cSArgyrios Kyrtzidis   return FileID::get(ID+1);
519065d720cSArgyrios Kyrtzidis }
520065d720cSArgyrios Kyrtzidis 
5214fa23625SChris Lattner //===----------------------------------------------------------------------===//
52264ee782eSChandler Carruth // Methods to create new FileID's and macro expansions.
5234fa23625SChris Lattner //===----------------------------------------------------------------------===//
5247a51313dSChris Lattner 
525e08464fbSReid Kleckner /// Create a new FileID that represents the specified file
526e08464fbSReid Kleckner /// being \#included from the specified IncludePosition.
527e08464fbSReid Kleckner ///
528e08464fbSReid Kleckner /// This translates NULL into standard input.
529e08464fbSReid Kleckner FileID SourceManager::createFileID(const FileEntry *SourceFile,
530e08464fbSReid Kleckner                                    SourceLocation IncludePos,
531e08464fbSReid Kleckner                                    SrcMgr::CharacteristicKind FileCharacter,
532e08464fbSReid Kleckner                                    int LoadedID, unsigned LoadedOffset) {
533e08464fbSReid Kleckner   assert(SourceFile && "Null source file!");
534e08464fbSReid Kleckner   const SrcMgr::ContentCache *IR =
535e08464fbSReid Kleckner       getOrCreateContentCache(SourceFile, isSystem(FileCharacter));
536e08464fbSReid Kleckner   assert(IR && "getOrCreateContentCache() cannot return NULL");
53774a87834SDuncan P. N. Exon Smith   return createFileIDImpl(*IR, SourceFile->getName(), IncludePos, FileCharacter,
538e08464fbSReid Kleckner 		      LoadedID, LoadedOffset);
539e08464fbSReid Kleckner }
540e08464fbSReid Kleckner 
541e08464fbSReid Kleckner FileID SourceManager::createFileID(FileEntryRef SourceFile,
542e08464fbSReid Kleckner                                    SourceLocation IncludePos,
543e08464fbSReid Kleckner                                    SrcMgr::CharacteristicKind FileCharacter,
544e08464fbSReid Kleckner                                    int LoadedID, unsigned LoadedOffset) {
545e08464fbSReid Kleckner   const SrcMgr::ContentCache *IR = getOrCreateContentCache(
546e08464fbSReid Kleckner       &SourceFile.getFileEntry(), isSystem(FileCharacter));
547e08464fbSReid Kleckner   assert(IR && "getOrCreateContentCache() cannot return NULL");
54874a87834SDuncan P. N. Exon Smith   return createFileIDImpl(*IR, SourceFile.getName(), IncludePos, FileCharacter,
549e08464fbSReid Kleckner                           LoadedID, LoadedOffset);
550e08464fbSReid Kleckner }
551e08464fbSReid Kleckner 
552e08464fbSReid Kleckner /// Create a new FileID that represents the specified memory buffer.
553e08464fbSReid Kleckner ///
554e08464fbSReid Kleckner /// This does no caching of the buffer and takes ownership of the
555e08464fbSReid Kleckner /// MemoryBuffer, so only pass a MemoryBuffer to this once.
556e08464fbSReid Kleckner FileID SourceManager::createFileID(std::unique_ptr<llvm::MemoryBuffer> Buffer,
557e08464fbSReid Kleckner                                    SrcMgr::CharacteristicKind FileCharacter,
558e08464fbSReid Kleckner                                    int LoadedID, unsigned LoadedOffset,
559e08464fbSReid Kleckner                                    SourceLocation IncludeLoc) {
560e08464fbSReid Kleckner   StringRef Name = Buffer->getBufferIdentifier();
56174a87834SDuncan P. N. Exon Smith   return createFileIDImpl(*createMemBufferContentCache(std::move(Buffer)), Name,
56251d1d585SDuncan P. N. Exon Smith                           IncludeLoc, FileCharacter, LoadedID, LoadedOffset);
563e08464fbSReid Kleckner }
564e08464fbSReid Kleckner 
565e08464fbSReid Kleckner /// Create a new FileID that represents the specified memory buffer.
566e08464fbSReid Kleckner ///
567e08464fbSReid Kleckner /// This does not take ownership of the MemoryBuffer. The memory buffer must
568e08464fbSReid Kleckner /// outlive the SourceManager.
56951d1d585SDuncan P. N. Exon Smith FileID SourceManager::createFileID(const llvm::MemoryBufferRef &Buffer,
570e08464fbSReid Kleckner                                    SrcMgr::CharacteristicKind FileCharacter,
571e08464fbSReid Kleckner                                    int LoadedID, unsigned LoadedOffset,
572e08464fbSReid Kleckner                                    SourceLocation IncludeLoc) {
57351d1d585SDuncan P. N. Exon Smith   return createFileID(llvm::MemoryBuffer::getMemBuffer(Buffer), FileCharacter,
57451d1d585SDuncan P. N. Exon Smith                       LoadedID, LoadedOffset, IncludeLoc);
575e08464fbSReid Kleckner }
576e08464fbSReid Kleckner 
577e08464fbSReid Kleckner /// Get the FileID for \p SourceFile if it exists. Otherwise, create a
578e08464fbSReid Kleckner /// new FileID for the \p SourceFile.
579e08464fbSReid Kleckner FileID
580e08464fbSReid Kleckner SourceManager::getOrCreateFileID(const FileEntry *SourceFile,
581e08464fbSReid Kleckner                                  SrcMgr::CharacteristicKind FileCharacter) {
582e08464fbSReid Kleckner   FileID ID = translateFile(SourceFile);
583e08464fbSReid Kleckner   return ID.isValid() ? ID : createFileID(SourceFile, SourceLocation(),
584e08464fbSReid Kleckner 					  FileCharacter);
585e08464fbSReid Kleckner }
586e08464fbSReid Kleckner 
587ce46f02aSDan Gohman /// createFileID - Create a new FileID for the specified ContentCache and
5887a51313dSChris Lattner /// include position.  This works regardless of whether the ContentCache
5897a51313dSChris Lattner /// corresponds to a file or some other input source.
59074a87834SDuncan P. N. Exon Smith FileID SourceManager::createFileIDImpl(const ContentCache &File,
59174a87834SDuncan P. N. Exon Smith                                        StringRef Filename,
5924c311643SNico Weber                                        SourceLocation IncludePos,
593258ae54aSDouglas Gregor                                        SrcMgr::CharacteristicKind FileCharacter,
594925296b4SDouglas Gregor                                        int LoadedID, unsigned LoadedOffset) {
595925296b4SDouglas Gregor   if (LoadedID < 0) {
596925296b4SDouglas Gregor     assert(LoadedID != -1 && "Loading sentinel FileID");
597925296b4SDouglas Gregor     unsigned Index = unsigned(-LoadedID) - 2;
598925296b4SDouglas Gregor     assert(Index < LoadedSLocEntryTable.size() && "FileID out of range");
599925296b4SDouglas Gregor     assert(!SLocEntryLoaded[Index] && "FileID already loaded");
6004dc5573aSAlex Lorenz     LoadedSLocEntryTable[Index] = SLocEntry::get(
6014dc5573aSAlex Lorenz         LoadedOffset, FileInfo::get(IncludePos, File, FileCharacter, Filename));
602925296b4SDouglas Gregor     SLocEntryLoaded[Index] = true;
603925296b4SDouglas Gregor     return FileID::get(LoadedID);
604258ae54aSDouglas Gregor   }
60574a87834SDuncan P. N. Exon Smith   unsigned FileSize = File.getSize();
606bce360b7SDiogo Sampaio   if (!(NextLocalOffset + FileSize + 1 > NextLocalOffset &&
607bce360b7SDiogo Sampaio         NextLocalOffset + FileSize + 1 <= CurrentLoadedOffset)) {
608bce360b7SDiogo Sampaio     Diag.Report(IncludePos, diag::err_include_too_large);
609bce360b7SDiogo Sampaio     return FileID();
610bce360b7SDiogo Sampaio   }
6114dc5573aSAlex Lorenz   LocalSLocEntryTable.push_back(
6124dc5573aSAlex Lorenz       SLocEntry::get(NextLocalOffset,
6134dc5573aSAlex Lorenz                      FileInfo::get(IncludePos, File, FileCharacter, Filename)));
614925296b4SDouglas Gregor   // We do a +1 here because we want a SourceLocation that means "the end of the
615925296b4SDouglas Gregor   // file", e.g. for the "no newline at the end of the file" diagnostic.
616925296b4SDouglas Gregor   NextLocalOffset += FileSize + 1;
6174fa23625SChris Lattner 
6184fa23625SChris Lattner   // Set LastFileIDLookup to the newly created file.  The next getFileID call is
6194fa23625SChris Lattner   // almost guaranteed to be from that file.
620925296b4SDouglas Gregor   FileID FID = FileID::get(LocalSLocEntryTable.size()-1);
6210152c6cbSArgyrios Kyrtzidis   return LastFileIDLookup = FID;
6227a51313dSChris Lattner }
6237a51313dSChris Lattner 
624402bb388SChandler Carruth SourceLocation
625115b077fSChandler Carruth SourceManager::createMacroArgExpansionLoc(SourceLocation SpellingLoc,
626115b077fSChandler Carruth                                           SourceLocation ExpansionLoc,
627402bb388SChandler Carruth                                           unsigned TokLength) {
62873ee5d7fSChandler Carruth   ExpansionInfo Info = ExpansionInfo::createForMacroArg(SpellingLoc,
62973ee5d7fSChandler Carruth                                                         ExpansionLoc);
63073ee5d7fSChandler Carruth   return createExpansionLocImpl(Info, TokLength);
631402bb388SChandler Carruth }
632402bb388SChandler Carruth 
633115b077fSChandler Carruth SourceLocation
634115b077fSChandler Carruth SourceManager::createExpansionLoc(SourceLocation SpellingLoc,
635115b077fSChandler Carruth                                   SourceLocation ExpansionLocStart,
636115b077fSChandler Carruth                                   SourceLocation ExpansionLocEnd,
637258ae54aSDouglas Gregor                                   unsigned TokLength,
638b5f8171aSRichard Smith                                   bool ExpansionIsTokenRange,
639925296b4SDouglas Gregor                                   int LoadedID,
640925296b4SDouglas Gregor                                   unsigned LoadedOffset) {
641b5f8171aSRichard Smith   ExpansionInfo Info = ExpansionInfo::create(
642b5f8171aSRichard Smith       SpellingLoc, ExpansionLocStart, ExpansionLocEnd, ExpansionIsTokenRange);
64373ee5d7fSChandler Carruth   return createExpansionLocImpl(Info, TokLength, LoadedID, LoadedOffset);
644402bb388SChandler Carruth }
645402bb388SChandler Carruth 
646b5f8171aSRichard Smith SourceLocation SourceManager::createTokenSplitLoc(SourceLocation Spelling,
647b5f8171aSRichard Smith                                                   SourceLocation TokenStart,
648b5f8171aSRichard Smith                                                   SourceLocation TokenEnd) {
649b5f8171aSRichard Smith   assert(getFileID(TokenStart) == getFileID(TokenEnd) &&
650b5f8171aSRichard Smith          "token spans multiple files");
651b5f8171aSRichard Smith   return createExpansionLocImpl(
652b5f8171aSRichard Smith       ExpansionInfo::createForTokenSplit(Spelling, TokenStart, TokenEnd),
653b5f8171aSRichard Smith       TokenEnd.getOffset() - TokenStart.getOffset());
654b5f8171aSRichard Smith }
655b5f8171aSRichard Smith 
656402bb388SChandler Carruth SourceLocation
65773ee5d7fSChandler Carruth SourceManager::createExpansionLocImpl(const ExpansionInfo &Info,
658402bb388SChandler Carruth                                       unsigned TokLength,
659925296b4SDouglas Gregor                                       int LoadedID,
660925296b4SDouglas Gregor                                       unsigned LoadedOffset) {
661925296b4SDouglas Gregor   if (LoadedID < 0) {
662925296b4SDouglas Gregor     assert(LoadedID != -1 && "Loading sentinel FileID");
663925296b4SDouglas Gregor     unsigned Index = unsigned(-LoadedID) - 2;
664925296b4SDouglas Gregor     assert(Index < LoadedSLocEntryTable.size() && "FileID out of range");
665925296b4SDouglas Gregor     assert(!SLocEntryLoaded[Index] && "FileID already loaded");
66673ee5d7fSChandler Carruth     LoadedSLocEntryTable[Index] = SLocEntry::get(LoadedOffset, Info);
667925296b4SDouglas Gregor     SLocEntryLoaded[Index] = true;
668925296b4SDouglas Gregor     return SourceLocation::getMacroLoc(LoadedOffset);
669258ae54aSDouglas Gregor   }
67073ee5d7fSChandler Carruth   LocalSLocEntryTable.push_back(SLocEntry::get(NextLocalOffset, Info));
671925296b4SDouglas Gregor   assert(NextLocalOffset + TokLength + 1 > NextLocalOffset &&
672925296b4SDouglas Gregor          NextLocalOffset + TokLength + 1 <= CurrentLoadedOffset &&
673925296b4SDouglas Gregor          "Ran out of source locations!");
674925296b4SDouglas Gregor   // See createFileID for that +1.
675925296b4SDouglas Gregor   NextLocalOffset += TokLength + 1;
676925296b4SDouglas Gregor   return SourceLocation::getMacroLoc(NextLocalOffset - (TokLength + 1));
6777a51313dSChris Lattner }
6787a51313dSChris Lattner 
6792dc7e0c6SDuncan P. N. Exon Smith llvm::Optional<llvm::MemoryBufferRef>
6802dc7e0c6SDuncan P. N. Exon Smith SourceManager::getMemoryBufferForFileOrNone(const FileEntry *File) {
68153ad6b94SDouglas Gregor   const SrcMgr::ContentCache *IR = getOrCreateContentCache(File);
682802b7760SDouglas Gregor   assert(IR && "getOrCreateContentCache() cannot return NULL");
6832dc7e0c6SDuncan P. N. Exon Smith   return IR->getBufferOrNone(Diag, getFileManager(), SourceLocation());
68453ad6b94SDouglas Gregor }
68553ad6b94SDouglas Gregor 
68629631451SDuncan P. N. Exon Smith void SourceManager::overrideFileContents(
68729631451SDuncan P. N. Exon Smith     const FileEntry *SourceFile, std::unique_ptr<llvm::MemoryBuffer> Buffer) {
68829631451SDuncan P. N. Exon Smith   auto *IR =
68929631451SDuncan P. N. Exon Smith       const_cast<SrcMgr::ContentCache *>(getOrCreateContentCache(SourceFile));
6905d223dcbSDan Gohman   assert(IR && "getOrCreateContentCache() cannot return NULL");
69153ad6b94SDouglas Gregor 
69229631451SDuncan P. N. Exon Smith   IR->setBuffer(std::move(Buffer));
69329631451SDuncan P. N. Exon Smith   IR->BufferOverridden = true;
6946eec06d0SArgyrios Kyrtzidis 
6956eec06d0SArgyrios Kyrtzidis   getOverriddenFilesInfo().OverriddenFilesWithBuffer.insert(SourceFile);
69653ad6b94SDouglas Gregor }
69753ad6b94SDouglas Gregor 
69811e6f0a6SArgyrios Kyrtzidis void SourceManager::overrideFileContents(const FileEntry *SourceFile,
69911e6f0a6SArgyrios Kyrtzidis                                          const FileEntry *NewFile) {
70011e6f0a6SArgyrios Kyrtzidis   assert(SourceFile->getSize() == NewFile->getSize() &&
70111e6f0a6SArgyrios Kyrtzidis          "Different sizes, use the FileManager to create a virtual file with "
70211e6f0a6SArgyrios Kyrtzidis          "the correct size");
70311e6f0a6SArgyrios Kyrtzidis   assert(FileInfos.count(SourceFile) == 0 &&
70411e6f0a6SArgyrios Kyrtzidis          "This function should be called at the initialization stage, before "
70511e6f0a6SArgyrios Kyrtzidis          "any parsing occurs.");
7066eec06d0SArgyrios Kyrtzidis   getOverriddenFilesInfo().OverriddenFiles[SourceFile] = NewFile;
7076eec06d0SArgyrios Kyrtzidis }
7086eec06d0SArgyrios Kyrtzidis 
709e1b7f22bSDuncan P. N. Exon Smith const FileEntry *
710e1b7f22bSDuncan P. N. Exon Smith SourceManager::bypassFileContentsOverride(const FileEntry &File) {
711e1b7f22bSDuncan P. N. Exon Smith   assert(isFileOverridden(&File));
712e1b7f22bSDuncan P. N. Exon Smith   llvm::Optional<FileEntryRef> BypassFile =
713e1b7f22bSDuncan P. N. Exon Smith       FileMgr.getBypassFile(FileEntryRef(File.getName(), File));
7146eec06d0SArgyrios Kyrtzidis 
715e1b7f22bSDuncan P. N. Exon Smith   // If the file can't be found in the FS, give up.
716e1b7f22bSDuncan P. N. Exon Smith   if (!BypassFile)
717e1b7f22bSDuncan P. N. Exon Smith     return nullptr;
7186eec06d0SArgyrios Kyrtzidis 
719e1b7f22bSDuncan P. N. Exon Smith   const FileEntry *FE = &BypassFile->getFileEntry();
720e1b7f22bSDuncan P. N. Exon Smith   (void)getOrCreateContentCache(FE);
721e1b7f22bSDuncan P. N. Exon Smith   return FE;
72211e6f0a6SArgyrios Kyrtzidis }
72311e6f0a6SArgyrios Kyrtzidis 
724a8cfffa3SRichard Smith void SourceManager::setFileIsTransient(const FileEntry *File) {
725fb1e7f7dSRichard Smith   const SrcMgr::ContentCache *CC = getOrCreateContentCache(File);
726a8cfffa3SRichard Smith   const_cast<SrcMgr::ContentCache *>(CC)->IsTransient = true;
727fb1e7f7dSRichard Smith }
728fb1e7f7dSRichard Smith 
729cf593d22SDuncan P. N. Exon Smith Optional<StringRef>
730cf593d22SDuncan P. N. Exon Smith SourceManager::getNonBuiltinFilenameForID(FileID FID) const {
731b6c6daa9SDuncan P. N. Exon Smith   if (const SrcMgr::SLocEntry *Entry = getSLocEntryForFile(FID))
73274a87834SDuncan P. N. Exon Smith     if (Entry->getFile().getContentCache().OrigEntry)
733cf593d22SDuncan P. N. Exon Smith       return Entry->getFile().getName();
734e08464fbSReid Kleckner   return None;
735e08464fbSReid Kleckner }
736e08464fbSReid Kleckner 
7370e62c1ccSChris Lattner StringRef SourceManager::getBufferData(FileID FID, bool *Invalid) const {
738d758f79eSDuncan P. N. Exon Smith   auto B = getBufferDataOrNone(FID);
73986af9844SDouglas Gregor   if (Invalid)
740d758f79eSDuncan P. N. Exon Smith     *Invalid = !B;
741d758f79eSDuncan P. N. Exon Smith   return B ? *B : "<<<<<INVALID SOURCE LOCATION>>>>>";
74286af9844SDouglas Gregor }
74386af9844SDouglas Gregor 
744d758f79eSDuncan P. N. Exon Smith llvm::Optional<StringRef>
745d758f79eSDuncan P. N. Exon Smith SourceManager::getBufferDataIfLoaded(FileID FID) const {
746b6c6daa9SDuncan P. N. Exon Smith   if (const SrcMgr::SLocEntry *Entry = getSLocEntryForFile(FID))
74774a87834SDuncan P. N. Exon Smith     return Entry->getFile().getContentCache().getBufferDataIfLoaded();
748d758f79eSDuncan P. N. Exon Smith   return None;
749d758f79eSDuncan P. N. Exon Smith }
750d758f79eSDuncan P. N. Exon Smith 
751d758f79eSDuncan P. N. Exon Smith llvm::Optional<StringRef> SourceManager::getBufferDataOrNone(FileID FID) const {
752b6c6daa9SDuncan P. N. Exon Smith   if (const SrcMgr::SLocEntry *Entry = getSLocEntryForFile(FID))
75374a87834SDuncan P. N. Exon Smith     if (auto B = Entry->getFile().getContentCache().getBufferOrNone(
754d758f79eSDuncan P. N. Exon Smith             Diag, getFileManager(), SourceLocation()))
755d758f79eSDuncan P. N. Exon Smith       return B->getBuffer();
756d758f79eSDuncan P. N. Exon Smith   return None;
757802b7760SDouglas Gregor }
758d32480d3SChris Lattner 
759153a0f1fSChris Lattner //===----------------------------------------------------------------------===//
7604fa23625SChris Lattner // SourceLocation manipulation methods.
761153a0f1fSChris Lattner //===----------------------------------------------------------------------===//
7624fa23625SChris Lattner 
7639fc8faf9SAdrian Prantl /// Return the FileID for a SourceLocation.
7644fa23625SChris Lattner ///
765925296b4SDouglas Gregor /// This is the cache-miss path of getFileID. Not as hot as that function, but
766925296b4SDouglas Gregor /// still very important. It is responsible for finding the entry in the
767925296b4SDouglas Gregor /// SLocEntry tables that contains the specified location.
7684fa23625SChris Lattner FileID SourceManager::getFileIDSlow(unsigned SLocOffset) const {
76949f754f4SDouglas Gregor   if (!SLocOffset)
77049f754f4SDouglas Gregor     return FileID::get(0);
7714fa23625SChris Lattner 
772925296b4SDouglas Gregor   // Now it is time to search for the correct file. See where the SLocOffset
773925296b4SDouglas Gregor   // sits in the global view and consult local or loaded buffers for it.
774925296b4SDouglas Gregor   if (SLocOffset < NextLocalOffset)
775925296b4SDouglas Gregor     return getFileIDLocal(SLocOffset);
776925296b4SDouglas Gregor   return getFileIDLoaded(SLocOffset);
777925296b4SDouglas Gregor }
778925296b4SDouglas Gregor 
7799fc8faf9SAdrian Prantl /// Return the FileID for a SourceLocation with a low offset.
780925296b4SDouglas Gregor ///
781925296b4SDouglas Gregor /// This function knows that the SourceLocation is in a local buffer, not a
782925296b4SDouglas Gregor /// loaded one.
783925296b4SDouglas Gregor FileID SourceManager::getFileIDLocal(unsigned SLocOffset) const {
784925296b4SDouglas Gregor   assert(SLocOffset < NextLocalOffset && "Bad function choice");
785925296b4SDouglas Gregor 
7864fa23625SChris Lattner   // After the first and second level caches, I see two common sorts of
78764ee782eSChandler Carruth   // behavior: 1) a lot of searched FileID's are "near" the cached file
78864ee782eSChandler Carruth   // location or are "near" the cached expansion location. 2) others are just
7894fa23625SChris Lattner   // completely random and may be a very long way away.
7904fa23625SChris Lattner   //
7914fa23625SChris Lattner   // To handle this, we do a linear search for up to 8 steps to catch #1 quickly
7924fa23625SChris Lattner   // then we fall back to a less cache efficient, but more scalable, binary
7934fa23625SChris Lattner   // search to find the location.
7944fa23625SChris Lattner 
7954fa23625SChris Lattner   // See if this is near the file point - worst case we start scanning from the
7964fa23625SChris Lattner   // most newly created FileID.
7972999b77fSBenjamin Kramer   const SrcMgr::SLocEntry *I;
7984fa23625SChris Lattner 
799925296b4SDouglas Gregor   if (LastFileIDLookup.ID < 0 ||
800925296b4SDouglas Gregor       LocalSLocEntryTable[LastFileIDLookup.ID].getOffset() < SLocOffset) {
8014fa23625SChris Lattner     // Neither loc prunes our search.
802925296b4SDouglas Gregor     I = LocalSLocEntryTable.end();
8034fa23625SChris Lattner   } else {
8044fa23625SChris Lattner     // Perhaps it is near the file point.
805925296b4SDouglas Gregor     I = LocalSLocEntryTable.begin()+LastFileIDLookup.ID;
8064fa23625SChris Lattner   }
8074fa23625SChris Lattner 
8084fa23625SChris Lattner   // Find the FileID that contains this.  "I" is an iterator that points to a
8094fa23625SChris Lattner   // FileID whose offset is known to be larger than SLocOffset.
8104fa23625SChris Lattner   unsigned NumProbes = 0;
811918e0ca7SEugene Zelenko   while (true) {
8124fa23625SChris Lattner     --I;
8134fa23625SChris Lattner     if (I->getOffset() <= SLocOffset) {
814925296b4SDouglas Gregor       FileID Res = FileID::get(int(I - LocalSLocEntryTable.begin()));
8157b8cf98bSNick Desaulniers       // Remember it.  We have good locality across FileID lookups.
8164fa23625SChris Lattner       LastFileIDLookup = Res;
8174fa23625SChris Lattner       NumLinearScans += NumProbes+1;
8184fa23625SChris Lattner       return Res;
8194fa23625SChris Lattner     }
8204fa23625SChris Lattner     if (++NumProbes == 8)
8214fa23625SChris Lattner       break;
8224fa23625SChris Lattner   }
8234fa23625SChris Lattner 
8244fa23625SChris Lattner   // Convert "I" back into an index.  We know that it is an entry whose index is
8254fa23625SChris Lattner   // larger than the offset we are looking for.
826925296b4SDouglas Gregor   unsigned GreaterIndex = I - LocalSLocEntryTable.begin();
8274fa23625SChris Lattner   // LessIndex - This is the lower bound of the range that we're searching.
8284fa23625SChris Lattner   // We know that the offset corresponding to the FileID is is less than
8294fa23625SChris Lattner   // SLocOffset.
8304fa23625SChris Lattner   unsigned LessIndex = 0;
8314fa23625SChris Lattner   NumProbes = 0;
832918e0ca7SEugene Zelenko   while (true) {
8334fa23625SChris Lattner     unsigned MiddleIndex = (GreaterIndex-LessIndex)/2+LessIndex;
8348cce7af0SNick Desaulniers     unsigned MidOffset = getLocalSLocEntry(MiddleIndex).getOffset();
8354fa23625SChris Lattner 
8364fa23625SChris Lattner     ++NumProbes;
8374fa23625SChris Lattner 
8384fa23625SChris Lattner     // If the offset of the midpoint is too large, chop the high side of the
8394fa23625SChris Lattner     // range to the midpoint.
8404fa23625SChris Lattner     if (MidOffset > SLocOffset) {
8414fa23625SChris Lattner       GreaterIndex = MiddleIndex;
8424fa23625SChris Lattner       continue;
8434fa23625SChris Lattner     }
8444fa23625SChris Lattner 
8454fa23625SChris Lattner     // If the middle index contains the value, succeed and return.
846408efffbSNick Desaulniers     if (MiddleIndex + 1 == LocalSLocEntryTable.size() ||
847408efffbSNick Desaulniers         SLocOffset < getLocalSLocEntry(MiddleIndex + 1).getOffset()) {
8484fa23625SChris Lattner       FileID Res = FileID::get(MiddleIndex);
8494fa23625SChris Lattner 
8507b8cf98bSNick Desaulniers       // Remember it.  We have good locality across FileID lookups.
8514fa23625SChris Lattner       LastFileIDLookup = Res;
8524fa23625SChris Lattner       NumBinaryProbes += NumProbes;
8534fa23625SChris Lattner       return Res;
8544fa23625SChris Lattner     }
8554fa23625SChris Lattner 
8564fa23625SChris Lattner     // Otherwise, move the low-side up to the middle index.
8574fa23625SChris Lattner     LessIndex = MiddleIndex;
8584fa23625SChris Lattner   }
8594fa23625SChris Lattner }
8604fa23625SChris Lattner 
8619fc8faf9SAdrian Prantl /// Return the FileID for a SourceLocation with a high offset.
862925296b4SDouglas Gregor ///
863925296b4SDouglas Gregor /// This function knows that the SourceLocation is in a loaded buffer, not a
864925296b4SDouglas Gregor /// local one.
865925296b4SDouglas Gregor FileID SourceManager::getFileIDLoaded(unsigned SLocOffset) const {
86625029d49SArgyrios Kyrtzidis   // Sanity checking, otherwise a bug may lead to hanging in release build.
8678edffaa6SArgyrios Kyrtzidis   if (SLocOffset < CurrentLoadedOffset) {
8688edffaa6SArgyrios Kyrtzidis     assert(0 && "Invalid SLocOffset or bad function choice");
86925029d49SArgyrios Kyrtzidis     return FileID();
8708edffaa6SArgyrios Kyrtzidis   }
87125029d49SArgyrios Kyrtzidis 
872925296b4SDouglas Gregor   // Essentially the same as the local case, but the loaded array is sorted
873925296b4SDouglas Gregor   // in the other direction.
874925296b4SDouglas Gregor 
875925296b4SDouglas Gregor   // First do a linear scan from the last lookup position, if possible.
876925296b4SDouglas Gregor   unsigned I;
877925296b4SDouglas Gregor   int LastID = LastFileIDLookup.ID;
878925296b4SDouglas Gregor   if (LastID >= 0 || getLoadedSLocEntryByID(LastID).getOffset() < SLocOffset)
879925296b4SDouglas Gregor     I = 0;
880925296b4SDouglas Gregor   else
881925296b4SDouglas Gregor     I = (-LastID - 2) + 1;
882925296b4SDouglas Gregor 
883925296b4SDouglas Gregor   unsigned NumProbes;
884925296b4SDouglas Gregor   for (NumProbes = 0; NumProbes < 8; ++NumProbes, ++I) {
885925296b4SDouglas Gregor     // Make sure the entry is loaded!
886925296b4SDouglas Gregor     const SrcMgr::SLocEntry &E = getLoadedSLocEntry(I);
887925296b4SDouglas Gregor     if (E.getOffset() <= SLocOffset) {
888925296b4SDouglas Gregor       FileID Res = FileID::get(-int(I) - 2);
889925296b4SDouglas Gregor       LastFileIDLookup = Res;
890925296b4SDouglas Gregor       NumLinearScans += NumProbes + 1;
891925296b4SDouglas Gregor       return Res;
892925296b4SDouglas Gregor     }
893925296b4SDouglas Gregor   }
894925296b4SDouglas Gregor 
895925296b4SDouglas Gregor   // Linear scan failed. Do the binary search. Note the reverse sorting of the
896925296b4SDouglas Gregor   // table: GreaterIndex is the one where the offset is greater, which is
897925296b4SDouglas Gregor   // actually a lower index!
898925296b4SDouglas Gregor   unsigned GreaterIndex = I;
899925296b4SDouglas Gregor   unsigned LessIndex = LoadedSLocEntryTable.size();
900925296b4SDouglas Gregor   NumProbes = 0;
901918e0ca7SEugene Zelenko   while (true) {
902925296b4SDouglas Gregor     ++NumProbes;
903925296b4SDouglas Gregor     unsigned MiddleIndex = (LessIndex - GreaterIndex) / 2 + GreaterIndex;
904925296b4SDouglas Gregor     const SrcMgr::SLocEntry &E = getLoadedSLocEntry(MiddleIndex);
9057dc4f33cSArgyrios Kyrtzidis     if (E.getOffset() == 0)
9067dc4f33cSArgyrios Kyrtzidis       return FileID(); // invalid entry.
907925296b4SDouglas Gregor 
908925296b4SDouglas Gregor     ++NumProbes;
909925296b4SDouglas Gregor 
910925296b4SDouglas Gregor     if (E.getOffset() > SLocOffset) {
9117dc4f33cSArgyrios Kyrtzidis       // Sanity checking, otherwise a bug may lead to hanging in release build.
9127dc4f33cSArgyrios Kyrtzidis       if (GreaterIndex == MiddleIndex) {
9137dc4f33cSArgyrios Kyrtzidis         assert(0 && "binary search missed the entry");
9147dc4f33cSArgyrios Kyrtzidis         return FileID();
9157dc4f33cSArgyrios Kyrtzidis       }
916925296b4SDouglas Gregor       GreaterIndex = MiddleIndex;
917925296b4SDouglas Gregor       continue;
918925296b4SDouglas Gregor     }
919925296b4SDouglas Gregor 
920925296b4SDouglas Gregor     if (isOffsetInFileID(FileID::get(-int(MiddleIndex) - 2), SLocOffset)) {
921925296b4SDouglas Gregor       FileID Res = FileID::get(-int(MiddleIndex) - 2);
922925296b4SDouglas Gregor       LastFileIDLookup = Res;
923925296b4SDouglas Gregor       NumBinaryProbes += NumProbes;
924925296b4SDouglas Gregor       return Res;
925925296b4SDouglas Gregor     }
926925296b4SDouglas Gregor 
9271ca73445SArgyrios Kyrtzidis     // Sanity checking, otherwise a bug may lead to hanging in release build.
9281ca73445SArgyrios Kyrtzidis     if (LessIndex == MiddleIndex) {
9291ca73445SArgyrios Kyrtzidis       assert(0 && "binary search missed the entry");
9301ca73445SArgyrios Kyrtzidis       return FileID();
9311ca73445SArgyrios Kyrtzidis     }
932925296b4SDouglas Gregor     LessIndex = MiddleIndex;
933925296b4SDouglas Gregor   }
934925296b4SDouglas Gregor }
935925296b4SDouglas Gregor 
936659ac5f0SChris Lattner SourceLocation SourceManager::
937c84d769cSChandler Carruth getExpansionLocSlowCase(SourceLocation Loc) const {
938659ac5f0SChris Lattner   do {
9395647d319SChris Lattner     // Note: If Loc indicates an offset into a token that came from a macro
9405647d319SChris Lattner     // expansion (e.g. the 5th character of the token) we do not want to add
941ee4c1d12SChandler Carruth     // this offset when going to the expansion location.  The expansion
9425647d319SChris Lattner     // location is the macro invocation, which the offset has nothing to do
9435647d319SChris Lattner     // with.  This is unlike when we get the spelling loc, because the offset
9445647d319SChris Lattner     // directly correspond to the token whose spelling we're inspecting.
945ee4c1d12SChandler Carruth     Loc = getSLocEntry(getFileID(Loc)).getExpansion().getExpansionLocStart();
946659ac5f0SChris Lattner   } while (!Loc.isFileID());
947659ac5f0SChris Lattner 
948659ac5f0SChris Lattner   return Loc;
949659ac5f0SChris Lattner }
950659ac5f0SChris Lattner 
951659ac5f0SChris Lattner SourceLocation SourceManager::getSpellingLocSlowCase(SourceLocation Loc) const {
952659ac5f0SChris Lattner   do {
953659ac5f0SChris Lattner     std::pair<FileID, unsigned> LocInfo = getDecomposedLoc(Loc);
954ee4c1d12SChandler Carruth     Loc = getSLocEntry(LocInfo.first).getExpansion().getSpellingLoc();
955e6e67deeSArgyrios Kyrtzidis     Loc = Loc.getLocWithOffset(LocInfo.second);
956659ac5f0SChris Lattner   } while (!Loc.isFileID());
957659ac5f0SChris Lattner   return Loc;
958659ac5f0SChris Lattner }
959659ac5f0SChris Lattner 
9607f6b029cSArgyrios Kyrtzidis SourceLocation SourceManager::getFileLocSlowCase(SourceLocation Loc) const {
9617f6b029cSArgyrios Kyrtzidis   do {
9627f6b029cSArgyrios Kyrtzidis     if (isMacroArgExpansion(Loc))
9637f6b029cSArgyrios Kyrtzidis       Loc = getImmediateSpellingLoc(Loc);
9647f6b029cSArgyrios Kyrtzidis     else
965b5f8171aSRichard Smith       Loc = getImmediateExpansionRange(Loc).getBegin();
9667f6b029cSArgyrios Kyrtzidis   } while (!Loc.isFileID());
9677f6b029cSArgyrios Kyrtzidis   return Loc;
9687f6b029cSArgyrios Kyrtzidis }
9697f6b029cSArgyrios Kyrtzidis 
970659ac5f0SChris Lattner 
9714fa23625SChris Lattner std::pair<FileID, unsigned>
972c7ca5218SChandler Carruth SourceManager::getDecomposedExpansionLocSlowCase(
973c8f7e213SArgyrios Kyrtzidis                                              const SrcMgr::SLocEntry *E) const {
97464ee782eSChandler Carruth   // If this is an expansion record, walk through all the expansion points.
9754fa23625SChris Lattner   FileID FID;
9764fa23625SChris Lattner   SourceLocation Loc;
977c8f7e213SArgyrios Kyrtzidis   unsigned Offset;
9784fa23625SChris Lattner   do {
979ee4c1d12SChandler Carruth     Loc = E->getExpansion().getExpansionLocStart();
9804fa23625SChris Lattner 
9814fa23625SChris Lattner     FID = getFileID(Loc);
9824fa23625SChris Lattner     E = &getSLocEntry(FID);
983c8f7e213SArgyrios Kyrtzidis     Offset = Loc.getOffset()-E->getOffset();
98431af4e08SChris Lattner   } while (!Loc.isFileID());
9854fa23625SChris Lattner 
9864fa23625SChris Lattner   return std::make_pair(FID, Offset);
9874fa23625SChris Lattner }
9884fa23625SChris Lattner 
9894fa23625SChris Lattner std::pair<FileID, unsigned>
9904fa23625SChris Lattner SourceManager::getDecomposedSpellingLocSlowCase(const SrcMgr::SLocEntry *E,
9914fa23625SChris Lattner                                                 unsigned Offset) const {
99264ee782eSChandler Carruth   // If this is an expansion record, walk through all the expansion points.
99331af4e08SChris Lattner   FileID FID;
99431af4e08SChris Lattner   SourceLocation Loc;
99531af4e08SChris Lattner   do {
996ee4c1d12SChandler Carruth     Loc = E->getExpansion().getSpellingLoc();
997e6e67deeSArgyrios Kyrtzidis     Loc = Loc.getLocWithOffset(Offset);
99831af4e08SChris Lattner 
99931af4e08SChris Lattner     FID = getFileID(Loc);
10004fa23625SChris Lattner     E = &getSLocEntry(FID);
10012797df6aSArgyrios Kyrtzidis     Offset = Loc.getOffset()-E->getOffset();
100231af4e08SChris Lattner   } while (!Loc.isFileID());
100331af4e08SChris Lattner 
10044fa23625SChris Lattner   return std::make_pair(FID, Offset);
10054fa23625SChris Lattner }
10064fa23625SChris Lattner 
10078ad52d50SChris Lattner /// getImmediateSpellingLoc - Given a SourceLocation object, return the
10088ad52d50SChris Lattner /// spelling location referenced by the ID.  This is the first level down
10098ad52d50SChris Lattner /// towards the place where the characters that make up the lexed token can be
10108ad52d50SChris Lattner /// found.  This should not generally be used by clients.
10118ad52d50SChris Lattner SourceLocation SourceManager::getImmediateSpellingLoc(SourceLocation Loc) const{
10128ad52d50SChris Lattner   if (Loc.isFileID()) return Loc;
10138ad52d50SChris Lattner   std::pair<FileID, unsigned> LocInfo = getDecomposedLoc(Loc);
1014ee4c1d12SChandler Carruth   Loc = getSLocEntry(LocInfo.first).getExpansion().getSpellingLoc();
1015e6e67deeSArgyrios Kyrtzidis   return Loc.getLocWithOffset(LocInfo.second);
10168ad52d50SChris Lattner }
10178ad52d50SChris Lattner 
1018e08464fbSReid Kleckner /// Return the filename of the file containing a SourceLocation.
1019e08464fbSReid Kleckner StringRef SourceManager::getFilename(SourceLocation SpellingLoc) const {
1020e08464fbSReid Kleckner   if (const FileEntry *F = getFileEntryForID(getFileID(SpellingLoc)))
1021e08464fbSReid Kleckner     return F->getName();
1022e08464fbSReid Kleckner   return StringRef();
1023e08464fbSReid Kleckner }
1024e08464fbSReid Kleckner 
102564ee782eSChandler Carruth /// getImmediateExpansionRange - Loc is required to be an expansion location.
102664ee782eSChandler Carruth /// Return the start/end of the expansion information.
1027b5f8171aSRichard Smith CharSourceRange
1028ca757587SChandler Carruth SourceManager::getImmediateExpansionRange(SourceLocation Loc) const {
102964ee782eSChandler Carruth   assert(Loc.isMacroID() && "Not a macro expansion loc!");
1030ee4c1d12SChandler Carruth   const ExpansionInfo &Expansion = getSLocEntry(getFileID(Loc)).getExpansion();
103173ee5d7fSChandler Carruth   return Expansion.getExpansionLocRange();
10329dc9c206SChris Lattner }
10339dc9c206SChris Lattner 
1034441e8fdfSGeorge Karpenkov SourceLocation SourceManager::getTopMacroCallerLoc(SourceLocation Loc) const {
1035441e8fdfSGeorge Karpenkov   while (isMacroArgExpansion(Loc))
1036441e8fdfSGeorge Karpenkov     Loc = getImmediateSpellingLoc(Loc);
1037441e8fdfSGeorge Karpenkov   return Loc;
1038441e8fdfSGeorge Karpenkov }
1039441e8fdfSGeorge Karpenkov 
10406d28d7f2SChandler Carruth /// getExpansionRange - Given a SourceLocation object, return the range of
10416d28d7f2SChandler Carruth /// tokens covered by the expansion in the ultimate file.
1042b5f8171aSRichard Smith CharSourceRange SourceManager::getExpansionRange(SourceLocation Loc) const {
1043b5f8171aSRichard Smith   if (Loc.isFileID())
1044b5f8171aSRichard Smith     return CharSourceRange(SourceRange(Loc, Loc), true);
1045f52c0b26SChris Lattner 
1046b5f8171aSRichard Smith   CharSourceRange Res = getImmediateExpansionRange(Loc);
1047f52c0b26SChris Lattner 
104864ee782eSChandler Carruth   // Fully resolve the start and end locations to their ultimate expansion
1049f52c0b26SChris Lattner   // points.
1050b5f8171aSRichard Smith   while (!Res.getBegin().isFileID())
1051b5f8171aSRichard Smith     Res.setBegin(getImmediateExpansionRange(Res.getBegin()).getBegin());
1052b5f8171aSRichard Smith   while (!Res.getEnd().isFileID()) {
1053b5f8171aSRichard Smith     CharSourceRange EndRange = getImmediateExpansionRange(Res.getEnd());
1054b5f8171aSRichard Smith     Res.setEnd(EndRange.getEnd());
1055b5f8171aSRichard Smith     Res.setTokenRange(EndRange.isTokenRange());
1056b5f8171aSRichard Smith   }
1057f52c0b26SChris Lattner   return Res;
1058f52c0b26SChris Lattner }
1059f52c0b26SChris Lattner 
1060c3096249SRichard Trieu bool SourceManager::isMacroArgExpansion(SourceLocation Loc,
1061c3096249SRichard Trieu                                         SourceLocation *StartLoc) const {
1062402bb388SChandler Carruth   if (!Loc.isMacroID()) return false;
1063402bb388SChandler Carruth 
1064402bb388SChandler Carruth   FileID FID = getFileID(Loc);
1065b1e71a7dSMatt Beaumont-Gay   const SrcMgr::ExpansionInfo &Expansion = getSLocEntry(FID).getExpansion();
1066c3096249SRichard Trieu   if (!Expansion.isMacroArgExpansion()) return false;
1067c3096249SRichard Trieu 
1068c3096249SRichard Trieu   if (StartLoc)
1069c3096249SRichard Trieu     *StartLoc = Expansion.getExpansionLocStart();
1070c3096249SRichard Trieu   return true;
1071402bb388SChandler Carruth }
10729dc9c206SChris Lattner 
1073b1e71a7dSMatt Beaumont-Gay bool SourceManager::isMacroBodyExpansion(SourceLocation Loc) const {
1074b1e71a7dSMatt Beaumont-Gay   if (!Loc.isMacroID()) return false;
1075b1e71a7dSMatt Beaumont-Gay 
1076b1e71a7dSMatt Beaumont-Gay   FileID FID = getFileID(Loc);
1077b1e71a7dSMatt Beaumont-Gay   const SrcMgr::ExpansionInfo &Expansion = getSLocEntry(FID).getExpansion();
1078b1e71a7dSMatt Beaumont-Gay   return Expansion.isMacroBodyExpansion();
1079b1e71a7dSMatt Beaumont-Gay }
1080b1e71a7dSMatt Beaumont-Gay 
1081065d720cSArgyrios Kyrtzidis bool SourceManager::isAtStartOfImmediateMacroExpansion(SourceLocation Loc,
1082065d720cSArgyrios Kyrtzidis                                              SourceLocation *MacroBegin) const {
1083065d720cSArgyrios Kyrtzidis   assert(Loc.isValid() && Loc.isMacroID() && "Expected a valid macro loc");
1084065d720cSArgyrios Kyrtzidis 
1085065d720cSArgyrios Kyrtzidis   std::pair<FileID, unsigned> DecompLoc = getDecomposedLoc(Loc);
1086065d720cSArgyrios Kyrtzidis   if (DecompLoc.second > 0)
1087065d720cSArgyrios Kyrtzidis     return false; // Does not point at the start of expansion range.
1088065d720cSArgyrios Kyrtzidis 
1089065d720cSArgyrios Kyrtzidis   bool Invalid = false;
1090065d720cSArgyrios Kyrtzidis   const SrcMgr::ExpansionInfo &ExpInfo =
1091065d720cSArgyrios Kyrtzidis       getSLocEntry(DecompLoc.first, &Invalid).getExpansion();
1092065d720cSArgyrios Kyrtzidis   if (Invalid)
1093065d720cSArgyrios Kyrtzidis     return false;
1094065d720cSArgyrios Kyrtzidis   SourceLocation ExpLoc = ExpInfo.getExpansionLocStart();
1095065d720cSArgyrios Kyrtzidis 
1096065d720cSArgyrios Kyrtzidis   if (ExpInfo.isMacroArgExpansion()) {
1097065d720cSArgyrios Kyrtzidis     // For macro argument expansions, check if the previous FileID is part of
1098065d720cSArgyrios Kyrtzidis     // the same argument expansion, in which case this Loc is not at the
1099065d720cSArgyrios Kyrtzidis     // beginning of the expansion.
1100065d720cSArgyrios Kyrtzidis     FileID PrevFID = getPreviousFileID(DecompLoc.first);
1101065d720cSArgyrios Kyrtzidis     if (!PrevFID.isInvalid()) {
1102065d720cSArgyrios Kyrtzidis       const SrcMgr::SLocEntry &PrevEntry = getSLocEntry(PrevFID, &Invalid);
1103065d720cSArgyrios Kyrtzidis       if (Invalid)
1104065d720cSArgyrios Kyrtzidis         return false;
1105065d720cSArgyrios Kyrtzidis       if (PrevEntry.isExpansion() &&
1106065d720cSArgyrios Kyrtzidis           PrevEntry.getExpansion().getExpansionLocStart() == ExpLoc)
1107065d720cSArgyrios Kyrtzidis         return false;
1108065d720cSArgyrios Kyrtzidis     }
1109065d720cSArgyrios Kyrtzidis   }
1110065d720cSArgyrios Kyrtzidis 
1111065d720cSArgyrios Kyrtzidis   if (MacroBegin)
1112065d720cSArgyrios Kyrtzidis     *MacroBegin = ExpLoc;
1113065d720cSArgyrios Kyrtzidis   return true;
1114065d720cSArgyrios Kyrtzidis }
1115065d720cSArgyrios Kyrtzidis 
1116065d720cSArgyrios Kyrtzidis bool SourceManager::isAtEndOfImmediateMacroExpansion(SourceLocation Loc,
1117065d720cSArgyrios Kyrtzidis                                                SourceLocation *MacroEnd) const {
1118065d720cSArgyrios Kyrtzidis   assert(Loc.isValid() && Loc.isMacroID() && "Expected a valid macro loc");
1119065d720cSArgyrios Kyrtzidis 
1120065d720cSArgyrios Kyrtzidis   FileID FID = getFileID(Loc);
1121065d720cSArgyrios Kyrtzidis   SourceLocation NextLoc = Loc.getLocWithOffset(1);
1122065d720cSArgyrios Kyrtzidis   if (isInFileID(NextLoc, FID))
1123065d720cSArgyrios Kyrtzidis     return false; // Does not point at the end of expansion range.
1124065d720cSArgyrios Kyrtzidis 
1125065d720cSArgyrios Kyrtzidis   bool Invalid = false;
1126065d720cSArgyrios Kyrtzidis   const SrcMgr::ExpansionInfo &ExpInfo =
1127065d720cSArgyrios Kyrtzidis       getSLocEntry(FID, &Invalid).getExpansion();
1128065d720cSArgyrios Kyrtzidis   if (Invalid)
1129065d720cSArgyrios Kyrtzidis     return false;
1130065d720cSArgyrios Kyrtzidis 
1131065d720cSArgyrios Kyrtzidis   if (ExpInfo.isMacroArgExpansion()) {
1132065d720cSArgyrios Kyrtzidis     // For macro argument expansions, check if the next FileID is part of the
1133065d720cSArgyrios Kyrtzidis     // same argument expansion, in which case this Loc is not at the end of the
1134065d720cSArgyrios Kyrtzidis     // expansion.
1135065d720cSArgyrios Kyrtzidis     FileID NextFID = getNextFileID(FID);
1136065d720cSArgyrios Kyrtzidis     if (!NextFID.isInvalid()) {
1137065d720cSArgyrios Kyrtzidis       const SrcMgr::SLocEntry &NextEntry = getSLocEntry(NextFID, &Invalid);
1138065d720cSArgyrios Kyrtzidis       if (Invalid)
1139065d720cSArgyrios Kyrtzidis         return false;
1140065d720cSArgyrios Kyrtzidis       if (NextEntry.isExpansion() &&
1141065d720cSArgyrios Kyrtzidis           NextEntry.getExpansion().getExpansionLocStart() ==
1142065d720cSArgyrios Kyrtzidis               ExpInfo.getExpansionLocStart())
1143065d720cSArgyrios Kyrtzidis         return false;
1144065d720cSArgyrios Kyrtzidis     }
1145065d720cSArgyrios Kyrtzidis   }
1146065d720cSArgyrios Kyrtzidis 
1147065d720cSArgyrios Kyrtzidis   if (MacroEnd)
1148065d720cSArgyrios Kyrtzidis     *MacroEnd = ExpInfo.getExpansionLocEnd();
1149065d720cSArgyrios Kyrtzidis   return true;
1150065d720cSArgyrios Kyrtzidis }
1151065d720cSArgyrios Kyrtzidis 
11524fa23625SChris Lattner //===----------------------------------------------------------------------===//
11534fa23625SChris Lattner // Queries about the code at a SourceLocation.
11544fa23625SChris Lattner //===----------------------------------------------------------------------===//
11557a51313dSChris Lattner 
11567a51313dSChris Lattner /// getCharacterData - Return a pointer to the start of the specified location
11577a51313dSChris Lattner /// in the appropriate MemoryBuffer.
11587bda4b83SDouglas Gregor const char *SourceManager::getCharacterData(SourceLocation SL,
11597bda4b83SDouglas Gregor                                             bool *Invalid) const {
11607a51313dSChris Lattner   // Note that this is a hot function in the getSpelling() path, which is
11617a51313dSChris Lattner   // heavily used by -E mode.
11624fa23625SChris Lattner   std::pair<FileID, unsigned> LocInfo = getDecomposedSpellingLoc(SL);
1163d32480d3SChris Lattner 
116412c2af44STed Kremenek   // Note that calling 'getBuffer()' may lazily page in a source file.
11657bda4b83SDouglas Gregor   bool CharDataInvalid = false;
116649f754f4SDouglas Gregor   const SLocEntry &Entry = getSLocEntry(LocInfo.first, &CharDataInvalid);
116749f754f4SDouglas Gregor   if (CharDataInvalid || !Entry.isFile()) {
116849f754f4SDouglas Gregor     if (Invalid)
116949f754f4SDouglas Gregor       *Invalid = true;
117049f754f4SDouglas Gregor 
117149f754f4SDouglas Gregor     return "<<<<INVALID BUFFER>>>>";
117249f754f4SDouglas Gregor   }
1173d758f79eSDuncan P. N. Exon Smith   llvm::Optional<llvm::MemoryBufferRef> Buffer =
117474a87834SDuncan P. N. Exon Smith       Entry.getFile().getContentCache().getBufferOrNone(Diag, getFileManager(),
1175d758f79eSDuncan P. N. Exon Smith                                                         SourceLocation());
11767bda4b83SDouglas Gregor   if (Invalid)
1177d758f79eSDuncan P. N. Exon Smith     *Invalid = !Buffer;
1178d758f79eSDuncan P. N. Exon Smith   return Buffer ? Buffer->getBufferStart() + LocInfo.second
1179d758f79eSDuncan P. N. Exon Smith                 : "<<<<INVALID BUFFER>>>>";
11807a51313dSChris Lattner }
11817a51313dSChris Lattner 
11827a51313dSChris Lattner /// getColumnNumber - Return the column # for the specified file position.
1183e4ad4176SChris Lattner /// this is significantly cheaper to compute than the line number.
11847bda4b83SDouglas Gregor unsigned SourceManager::getColumnNumber(FileID FID, unsigned FilePos,
11857bda4b83SDouglas Gregor                                         bool *Invalid) const {
118654c1bcabSDuncan P. N. Exon Smith   llvm::Optional<llvm::MemoryBufferRef> MemBuf = getBufferOrNone(FID);
11877bda4b83SDouglas Gregor   if (Invalid)
118854c1bcabSDuncan P. N. Exon Smith     *Invalid = !MemBuf;
11897bda4b83SDouglas Gregor 
119054c1bcabSDuncan P. N. Exon Smith   if (!MemBuf)
11917bda4b83SDouglas Gregor     return 1;
11927a51313dSChris Lattner 
11938d63d5b8SJordan Rose   // It is okay to request a position just past the end of the buffer.
11948d63d5b8SJordan Rose   if (FilePos > MemBuf->getBufferSize()) {
11956c8d29f7SArgyrios Kyrtzidis     if (Invalid)
11968d63d5b8SJordan Rose       *Invalid = true;
11976c8d29f7SArgyrios Kyrtzidis     return 1;
11986c8d29f7SArgyrios Kyrtzidis   }
11996c8d29f7SArgyrios Kyrtzidis 
1200a0b99e45SChih-Hung Hsieh   const char *Buf = MemBuf->getBufferStart();
12015e79ee08SCraig Topper   // See if we just calculated the line number for this FilePos and can use
12025e79ee08SCraig Topper   // that to lookup the start of the line instead of searching for it.
1203*dbbc4f4eSDuncan P. N. Exon Smith   if (LastLineNoFileIDQuery == FID && LastLineNoContentCache->SourceLineCache &&
1204*dbbc4f4eSDuncan P. N. Exon Smith       LastLineNoResult < LastLineNoContentCache->SourceLineCache.size()) {
1205*dbbc4f4eSDuncan P. N. Exon Smith     const unsigned *SourceLineCache =
1206*dbbc4f4eSDuncan P. N. Exon Smith         LastLineNoContentCache->SourceLineCache.begin();
12075e79ee08SCraig Topper     unsigned LineStart = SourceLineCache[LastLineNoResult - 1];
12085e79ee08SCraig Topper     unsigned LineEnd = SourceLineCache[LastLineNoResult];
1209a0b99e45SChih-Hung Hsieh     if (FilePos >= LineStart && FilePos < LineEnd) {
1210a0b99e45SChih-Hung Hsieh       // LineEnd is the LineStart of the next line.
1211a0b99e45SChih-Hung Hsieh       // A line ends with separator LF or CR+LF on Windows.
1212a0b99e45SChih-Hung Hsieh       // FilePos might point to the last separator,
1213a0b99e45SChih-Hung Hsieh       // but we need a column number at most 1 + the last column.
1214a0b99e45SChih-Hung Hsieh       if (FilePos + 1 == LineEnd && FilePos > LineStart) {
1215a0b99e45SChih-Hung Hsieh         if (Buf[FilePos - 1] == '\r' || Buf[FilePos - 1] == '\n')
1216a0b99e45SChih-Hung Hsieh           --FilePos;
1217a0b99e45SChih-Hung Hsieh       }
12185e79ee08SCraig Topper       return FilePos - LineStart + 1;
12195e79ee08SCraig Topper     }
1220a0b99e45SChih-Hung Hsieh   }
12215e79ee08SCraig Topper 
12227a51313dSChris Lattner   unsigned LineStart = FilePos;
12237a51313dSChris Lattner   while (LineStart && Buf[LineStart-1] != '\n' && Buf[LineStart-1] != '\r')
12247a51313dSChris Lattner     --LineStart;
12257a51313dSChris Lattner   return FilePos-LineStart+1;
12267a51313dSChris Lattner }
12277a51313dSChris Lattner 
1228ea6d7f33SZhanyong Wan // isInvalid - Return the result of calling loc.isInvalid(), and
1229ea6d7f33SZhanyong Wan // if Invalid is not null, set its value to same.
123041e66291SRichard Smith template<typename LocType>
123141e66291SRichard Smith static bool isInvalid(LocType Loc, bool *Invalid) {
1232ea6d7f33SZhanyong Wan   bool MyInvalid = Loc.isInvalid();
1233ea6d7f33SZhanyong Wan   if (Invalid)
1234ea6d7f33SZhanyong Wan     *Invalid = MyInvalid;
1235ea6d7f33SZhanyong Wan   return MyInvalid;
1236ea6d7f33SZhanyong Wan }
1237ea6d7f33SZhanyong Wan 
12387bda4b83SDouglas Gregor unsigned SourceManager::getSpellingColumnNumber(SourceLocation Loc,
12397bda4b83SDouglas Gregor                                                 bool *Invalid) const {
1240ea6d7f33SZhanyong Wan   if (isInvalid(Loc, Invalid)) return 0;
1241e4ad4176SChris Lattner   std::pair<FileID, unsigned> LocInfo = getDecomposedSpellingLoc(Loc);
12427bda4b83SDouglas Gregor   return getColumnNumber(LocInfo.first, LocInfo.second, Invalid);
1243e4ad4176SChris Lattner }
1244e4ad4176SChris Lattner 
124542f35f9cSChandler Carruth unsigned SourceManager::getExpansionColumnNumber(SourceLocation Loc,
12467bda4b83SDouglas Gregor                                                  bool *Invalid) const {
1247ea6d7f33SZhanyong Wan   if (isInvalid(Loc, Invalid)) return 0;
1248c7ca5218SChandler Carruth   std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(Loc);
12497bda4b83SDouglas Gregor   return getColumnNumber(LocInfo.first, LocInfo.second, Invalid);
1250e4ad4176SChris Lattner }
1251e4ad4176SChris Lattner 
12521aef0c56SChandler Carruth unsigned SourceManager::getPresumedColumnNumber(SourceLocation Loc,
12531aef0c56SChandler Carruth                                                 bool *Invalid) const {
125441e66291SRichard Smith   PresumedLoc PLoc = getPresumedLoc(Loc);
125541e66291SRichard Smith   if (isInvalid(PLoc, Invalid)) return 0;
125641e66291SRichard Smith   return PLoc.getColumn();
12571aef0c56SChandler Carruth }
12581aef0c56SChandler Carruth 
1259543036a4SBenjamin Kramer #ifdef __SSE2__
1260543036a4SBenjamin Kramer #include <emmintrin.h>
1261543036a4SBenjamin Kramer #endif
1262543036a4SBenjamin Kramer 
1263c3ce5840SChandler Carruth static LLVM_ATTRIBUTE_NOINLINE void
12649c902b55SDavid Blaikie ComputeLineNumbers(DiagnosticsEngine &Diag, ContentCache *FI,
12657bda4b83SDouglas Gregor                    llvm::BumpPtrAllocator &Alloc,
1266fb24a3a4SChris Lattner                    const SourceManager &SM, bool &Invalid);
12679c902b55SDavid Blaikie static void ComputeLineNumbers(DiagnosticsEngine &Diag, ContentCache *FI,
1268fb24a3a4SChris Lattner                                llvm::BumpPtrAllocator &Alloc,
1269fb24a3a4SChris Lattner                                const SourceManager &SM, bool &Invalid) {
127012c2af44STed Kremenek   // Note that calling 'getBuffer()' may lazily page in the file.
1271d758f79eSDuncan P. N. Exon Smith   llvm::Optional<llvm::MemoryBufferRef> Buffer =
1272d758f79eSDuncan P. N. Exon Smith       FI->getBufferOrNone(Diag, SM.getFileManager(), SourceLocation());
1273d758f79eSDuncan P. N. Exon Smith   Invalid = !Buffer;
12747bda4b83SDouglas Gregor   if (Invalid)
12757bda4b83SDouglas Gregor     return;
12767a51313dSChris Lattner 
1277*dbbc4f4eSDuncan P. N. Exon Smith   FI->SourceLineCache = LineOffsetMapping::get(*Buffer, Alloc);
1278*dbbc4f4eSDuncan P. N. Exon Smith }
1279*dbbc4f4eSDuncan P. N. Exon Smith 
1280*dbbc4f4eSDuncan P. N. Exon Smith LineOffsetMapping LineOffsetMapping::get(llvm::MemoryBufferRef Buffer,
1281*dbbc4f4eSDuncan P. N. Exon Smith                                          llvm::BumpPtrAllocator &Alloc) {
12827a51313dSChris Lattner   // Find the file offsets of all of the *physical* source lines.  This does
12837a51313dSChris Lattner   // not look at trigraphs, escaped newlines, or anything else tricky.
12840e62c1ccSChris Lattner   SmallVector<unsigned, 256> LineOffsets;
12857a51313dSChris Lattner 
12867a51313dSChris Lattner   // Line #1 starts at char 0.
12877a51313dSChris Lattner   LineOffsets.push_back(0);
12887a51313dSChris Lattner 
1289*dbbc4f4eSDuncan P. N. Exon Smith   const unsigned char *Buf = (const unsigned char *)Buffer.getBufferStart();
1290*dbbc4f4eSDuncan P. N. Exon Smith   const unsigned char *End = (const unsigned char *)Buffer.getBufferEnd();
1291f28972faSJan Korous   const std::size_t BufLen = End - Buf;
1292d906e731SFangrui Song   unsigned I = 0;
1293f28972faSJan Korous   while (I < BufLen) {
1294f28972faSJan Korous     if (Buf[I] == '\n') {
1295f28972faSJan Korous       LineOffsets.push_back(I + 1);
1296f28972faSJan Korous     } else if (Buf[I] == '\r') {
1297d906e731SFangrui Song       // If this is \r\n, skip both characters.
1298f28972faSJan Korous       if (I + 1 < BufLen && Buf[I + 1] == '\n')
1299d906e731SFangrui Song         ++I;
1300f28972faSJan Korous       LineOffsets.push_back(I + 1);
13017a51313dSChris Lattner     }
1302f28972faSJan Korous     ++I;
13037a51313dSChris Lattner   }
13047a51313dSChris Lattner 
1305*dbbc4f4eSDuncan P. N. Exon Smith   return LineOffsetMapping(LineOffsets, Alloc);
1306*dbbc4f4eSDuncan P. N. Exon Smith }
1307*dbbc4f4eSDuncan P. N. Exon Smith 
1308*dbbc4f4eSDuncan P. N. Exon Smith LineOffsetMapping::LineOffsetMapping(ArrayRef<unsigned> LineOffsets,
1309*dbbc4f4eSDuncan P. N. Exon Smith                                      llvm::BumpPtrAllocator &Alloc)
1310*dbbc4f4eSDuncan P. N. Exon Smith     : Storage(Alloc.Allocate<unsigned>(LineOffsets.size() + 1)) {
1311*dbbc4f4eSDuncan P. N. Exon Smith   Storage[0] = LineOffsets.size();
1312*dbbc4f4eSDuncan P. N. Exon Smith   std::copy(LineOffsets.begin(), LineOffsets.end(), Storage + 1);
13137a51313dSChris Lattner }
13147a51313dSChris Lattner 
131553e384f6SChris Lattner /// getLineNumber - Given a SourceLocation, return the spelling line number
13167a51313dSChris Lattner /// for the position indicated.  This requires building and caching a table of
13177a51313dSChris Lattner /// line offsets for the MemoryBuffer, so this is not cheap: use only when
13187a51313dSChris Lattner /// about to emit a diagnostic.
13197bda4b83SDouglas Gregor unsigned SourceManager::getLineNumber(FileID FID, unsigned FilePos,
13207bda4b83SDouglas Gregor                                       bool *Invalid) const {
1321f15eac11SArgyrios Kyrtzidis   if (FID.isInvalid()) {
1322f15eac11SArgyrios Kyrtzidis     if (Invalid)
1323f15eac11SArgyrios Kyrtzidis       *Invalid = true;
1324f15eac11SArgyrios Kyrtzidis     return 1;
1325f15eac11SArgyrios Kyrtzidis   }
1326f15eac11SArgyrios Kyrtzidis 
13277a51313dSChris Lattner   ContentCache *Content;
132888ea93e6SChris Lattner   if (LastLineNoFileIDQuery == FID)
13297a51313dSChris Lattner     Content = LastLineNoContentCache;
133049f754f4SDouglas Gregor   else {
133149f754f4SDouglas Gregor     bool MyInvalid = false;
133249f754f4SDouglas Gregor     const SLocEntry &Entry = getSLocEntry(FID, &MyInvalid);
133349f754f4SDouglas Gregor     if (MyInvalid || !Entry.isFile()) {
133449f754f4SDouglas Gregor       if (Invalid)
133549f754f4SDouglas Gregor         *Invalid = true;
133649f754f4SDouglas Gregor       return 1;
133749f754f4SDouglas Gregor     }
133849f754f4SDouglas Gregor 
133974a87834SDuncan P. N. Exon Smith     Content = const_cast<ContentCache *>(&Entry.getFile().getContentCache());
134049f754f4SDouglas Gregor   }
13417a51313dSChris Lattner 
13427a51313dSChris Lattner   // If this is the first use of line information for this buffer, compute the
13437a51313dSChris Lattner   /// SourceLineCache for it on demand.
1344f1186c5aSCraig Topper   if (!Content->SourceLineCache) {
13457bda4b83SDouglas Gregor     bool MyInvalid = false;
1346fb24a3a4SChris Lattner     ComputeLineNumbers(Diag, Content, ContentCacheAlloc, *this, MyInvalid);
13477bda4b83SDouglas Gregor     if (Invalid)
13487bda4b83SDouglas Gregor       *Invalid = MyInvalid;
13497bda4b83SDouglas Gregor     if (MyInvalid)
13507bda4b83SDouglas Gregor       return 1;
13517bda4b83SDouglas Gregor   } else if (Invalid)
13527bda4b83SDouglas Gregor     *Invalid = false;
13537a51313dSChris Lattner 
13547a51313dSChris Lattner   // Okay, we know we have a line number table.  Do a binary search to find the
13557a51313dSChris Lattner   // line number that this character position lands on.
1356*dbbc4f4eSDuncan P. N. Exon Smith   const unsigned *SourceLineCache = Content->SourceLineCache.begin();
1357*dbbc4f4eSDuncan P. N. Exon Smith   const unsigned *SourceLineCacheStart = SourceLineCache;
1358*dbbc4f4eSDuncan P. N. Exon Smith   const unsigned *SourceLineCacheEnd = Content->SourceLineCache.end();
13597a51313dSChris Lattner 
136088ea93e6SChris Lattner   unsigned QueriedFilePos = FilePos+1;
13617a51313dSChris Lattner 
136270f924dfSDaniel Dunbar   // FIXME: I would like to be convinced that this code is worth being as
136370f924dfSDaniel Dunbar   // complicated as it is, binary search isn't that slow.
136470f924dfSDaniel Dunbar   //
136570f924dfSDaniel Dunbar   // If it is worth being optimized, then in my opinion it could be more
136670f924dfSDaniel Dunbar   // performant, simpler, and more obviously correct by just "galloping" outward
136770f924dfSDaniel Dunbar   // from the queried file position. In fact, this could be incorporated into a
136870f924dfSDaniel Dunbar   // generic algorithm such as lower_bound_with_hint.
136970f924dfSDaniel Dunbar   //
137070f924dfSDaniel Dunbar   // If someone gives me a test case where this matters, and I will do it! - DWD
137170f924dfSDaniel Dunbar 
13727a51313dSChris Lattner   // If the previous query was to the same file, we know both the file pos from
13737a51313dSChris Lattner   // that query and the line number returned.  This allows us to narrow the
13747a51313dSChris Lattner   // search space from the entire file to something near the match.
137588ea93e6SChris Lattner   if (LastLineNoFileIDQuery == FID) {
13767a51313dSChris Lattner     if (QueriedFilePos >= LastLineNoFilePos) {
137770f924dfSDaniel Dunbar       // FIXME: Potential overflow?
13787a51313dSChris Lattner       SourceLineCache = SourceLineCache+LastLineNoResult-1;
13797a51313dSChris Lattner 
13807a51313dSChris Lattner       // The query is likely to be nearby the previous one.  Here we check to
13817a51313dSChris Lattner       // see if it is within 5, 10 or 20 lines.  It can be far away in cases
13827a51313dSChris Lattner       // where big comment blocks and vertical whitespace eat up lines but
13837a51313dSChris Lattner       // contribute no tokens.
13847a51313dSChris Lattner       if (SourceLineCache+5 < SourceLineCacheEnd) {
13857a51313dSChris Lattner         if (SourceLineCache[5] > QueriedFilePos)
13867a51313dSChris Lattner           SourceLineCacheEnd = SourceLineCache+5;
13877a51313dSChris Lattner         else if (SourceLineCache+10 < SourceLineCacheEnd) {
13887a51313dSChris Lattner           if (SourceLineCache[10] > QueriedFilePos)
13897a51313dSChris Lattner             SourceLineCacheEnd = SourceLineCache+10;
13907a51313dSChris Lattner           else if (SourceLineCache+20 < SourceLineCacheEnd) {
13917a51313dSChris Lattner             if (SourceLineCache[20] > QueriedFilePos)
13927a51313dSChris Lattner               SourceLineCacheEnd = SourceLineCache+20;
13937a51313dSChris Lattner           }
13947a51313dSChris Lattner         }
13957a51313dSChris Lattner       }
13967a51313dSChris Lattner     } else {
1397*dbbc4f4eSDuncan P. N. Exon Smith       if (LastLineNoResult < Content->SourceLineCache.size())
13987a51313dSChris Lattner         SourceLineCacheEnd = SourceLineCache+LastLineNoResult+1;
13997a51313dSChris Lattner     }
14007a51313dSChris Lattner   }
14017a51313dSChris Lattner 
1402*dbbc4f4eSDuncan P. N. Exon Smith   const unsigned *Pos =
1403*dbbc4f4eSDuncan P. N. Exon Smith       std::lower_bound(SourceLineCache, SourceLineCacheEnd, QueriedFilePos);
14047a51313dSChris Lattner   unsigned LineNo = Pos-SourceLineCacheStart;
14057a51313dSChris Lattner 
140688ea93e6SChris Lattner   LastLineNoFileIDQuery = FID;
14077a51313dSChris Lattner   LastLineNoContentCache = Content;
14087a51313dSChris Lattner   LastLineNoFilePos = QueriedFilePos;
14097a51313dSChris Lattner   LastLineNoResult = LineNo;
14107a51313dSChris Lattner   return LineNo;
14117a51313dSChris Lattner }
14127a51313dSChris Lattner 
14131aef0c56SChandler Carruth unsigned SourceManager::getSpellingLineNumber(SourceLocation Loc,
14141aef0c56SChandler Carruth                                               bool *Invalid) const {
14151aef0c56SChandler Carruth   if (isInvalid(Loc, Invalid)) return 0;
14161aef0c56SChandler Carruth   std::pair<FileID, unsigned> LocInfo = getDecomposedSpellingLoc(Loc);
14171aef0c56SChandler Carruth   return getLineNumber(LocInfo.first, LocInfo.second);
14181aef0c56SChandler Carruth }
1419d48db211SChandler Carruth unsigned SourceManager::getExpansionLineNumber(SourceLocation Loc,
14207bda4b83SDouglas Gregor                                                bool *Invalid) const {
1421ea6d7f33SZhanyong Wan   if (isInvalid(Loc, Invalid)) return 0;
1422c7ca5218SChandler Carruth   std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(Loc);
142388ea93e6SChris Lattner   return getLineNumber(LocInfo.first, LocInfo.second);
142488ea93e6SChris Lattner }
14251aef0c56SChandler Carruth unsigned SourceManager::getPresumedLineNumber(SourceLocation Loc,
14267bda4b83SDouglas Gregor                                               bool *Invalid) const {
14279c52767fSRichard Smith   PresumedLoc PLoc = getPresumedLoc(Loc);
14289c52767fSRichard Smith   if (isInvalid(PLoc, Invalid)) return 0;
14299c52767fSRichard Smith   return PLoc.getLine();
143088ea93e6SChris Lattner }
143188ea93e6SChris Lattner 
143295d9c5e7SChris Lattner /// getFileCharacteristic - return the file characteristic of the specified
143395d9c5e7SChris Lattner /// source location, indicating whether this is a normal file, a system
143495d9c5e7SChris Lattner /// header, or an "implicit extern C" system header.
143595d9c5e7SChris Lattner ///
143695d9c5e7SChris Lattner /// This state can be modified with flags on GNU linemarker directives like:
143795d9c5e7SChris Lattner ///   # 4 "foo.h" 3
143895d9c5e7SChris Lattner /// which changes all source locations in the current file after that to be
143995d9c5e7SChris Lattner /// considered to be from a system header.
144095d9c5e7SChris Lattner SrcMgr::CharacteristicKind
144195d9c5e7SChris Lattner SourceManager::getFileCharacteristic(SourceLocation Loc) const {
14428b563665SYaron Keren   assert(Loc.isValid() && "Can't get file characteristic of invalid loc!");
1443c7ca5218SChandler Carruth   std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(Loc);
1444b6c6daa9SDuncan P. N. Exon Smith   const SLocEntry *SEntry = getSLocEntryForFile(LocInfo.first);
1445b6c6daa9SDuncan P. N. Exon Smith   if (!SEntry)
144649f754f4SDouglas Gregor     return C_User;
144749f754f4SDouglas Gregor 
1448b6c6daa9SDuncan P. N. Exon Smith   const SrcMgr::FileInfo &FI = SEntry->getFile();
144995d9c5e7SChris Lattner 
145095d9c5e7SChris Lattner   // If there are no #line directives in this file, just return the whole-file
145195d9c5e7SChris Lattner   // state.
145295d9c5e7SChris Lattner   if (!FI.hasLineDirectives())
145395d9c5e7SChris Lattner     return FI.getFileCharacteristic();
145495d9c5e7SChris Lattner 
145595d9c5e7SChris Lattner   assert(LineTable && "Can't have linetable entries without a LineTable!");
145695d9c5e7SChris Lattner   // See if there is a #line directive before the location.
145795d9c5e7SChris Lattner   const LineEntry *Entry =
145802c2dbf4SDouglas Gregor     LineTable->FindNearestLineEntry(LocInfo.first, LocInfo.second);
145995d9c5e7SChris Lattner 
146095d9c5e7SChris Lattner   // If this is before the first line marker, use the file characteristic.
146195d9c5e7SChris Lattner   if (!Entry)
146295d9c5e7SChris Lattner     return FI.getFileCharacteristic();
146395d9c5e7SChris Lattner 
146495d9c5e7SChris Lattner   return Entry->FileKind;
146595d9c5e7SChris Lattner }
146695d9c5e7SChris Lattner 
1467a6f037ceSChris Lattner /// Return the filename or buffer identifier of the buffer the location is in.
146887a2acf1SJames Dennett /// Note that this name does not respect \#line directives.  Use getPresumedLoc
1469a6f037ceSChris Lattner /// for normal clients.
147099d1b295SMehdi Amini StringRef SourceManager::getBufferName(SourceLocation Loc,
14717bda4b83SDouglas Gregor                                        bool *Invalid) const {
1472ea6d7f33SZhanyong Wan   if (isInvalid(Loc, Invalid)) return "<invalid loc>";
1473a6f037ceSChris Lattner 
147454c1bcabSDuncan P. N. Exon Smith   auto B = getBufferOrNone(getFileID(Loc));
147554c1bcabSDuncan P. N. Exon Smith   if (Invalid)
147654c1bcabSDuncan P. N. Exon Smith     *Invalid = !B;
147754c1bcabSDuncan P. N. Exon Smith   return B ? B->getBufferIdentifier() : "<invalid buffer>";
1478a6f037ceSChris Lattner }
1479a6f037ceSChris Lattner 
1480f1ca7d3eSChris Lattner /// getPresumedLoc - This method returns the "presumed" location of a
148187a2acf1SJames Dennett /// SourceLocation specifies.  A "presumed location" can be modified by \#line
1482f1ca7d3eSChris Lattner /// or GNU line marker directives.  This provides a view on the data that a
1483f1ca7d3eSChris Lattner /// user should see in diagnostics, for example.
1484f1ca7d3eSChris Lattner ///
148564ee782eSChandler Carruth /// Note that a presumed location is always given as the expansion point of an
148664ee782eSChandler Carruth /// expansion location, not at the spelling location.
14870b50cb79SRichard Smith PresumedLoc SourceManager::getPresumedLoc(SourceLocation Loc,
14880b50cb79SRichard Smith                                           bool UseLineDirectives) const {
1489f1ca7d3eSChris Lattner   if (Loc.isInvalid()) return PresumedLoc();
14904fa23625SChris Lattner 
149164ee782eSChandler Carruth   // Presumed locations are always for expansion points.
1492c7ca5218SChandler Carruth   std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(Loc);
1493f1ca7d3eSChris Lattner 
149449f754f4SDouglas Gregor   bool Invalid = false;
149549f754f4SDouglas Gregor   const SLocEntry &Entry = getSLocEntry(LocInfo.first, &Invalid);
149649f754f4SDouglas Gregor   if (Invalid || !Entry.isFile())
149749f754f4SDouglas Gregor     return PresumedLoc();
149849f754f4SDouglas Gregor 
149949f754f4SDouglas Gregor   const SrcMgr::FileInfo &FI = Entry.getFile();
150074a87834SDuncan P. N. Exon Smith   const SrcMgr::ContentCache *C = &FI.getContentCache();
15014fa23625SChris Lattner 
1502d4293922SChris Lattner   // To get the source name, first consult the FileEntry (if one exists)
1503d4293922SChris Lattner   // before the MemBuffer as this will avoid unnecessarily paging in the
1504d4293922SChris Lattner   // MemBuffer.
1505047e65dbSAlexandre Ganea   FileID FID = LocInfo.first;
150699d1b295SMehdi Amini   StringRef Filename;
150711e6f0a6SArgyrios Kyrtzidis   if (C->OrigEntry)
150811e6f0a6SArgyrios Kyrtzidis     Filename = C->OrigEntry->getName();
1509d758f79eSDuncan P. N. Exon Smith   else if (auto Buffer = C->getBufferOrNone(Diag, getFileManager()))
1510d758f79eSDuncan P. N. Exon Smith     Filename = Buffer->getBufferIdentifier();
151149f754f4SDouglas Gregor 
151275f26d6cSDouglas Gregor   unsigned LineNo = getLineNumber(LocInfo.first, LocInfo.second, &Invalid);
151375f26d6cSDouglas Gregor   if (Invalid)
151475f26d6cSDouglas Gregor     return PresumedLoc();
151575f26d6cSDouglas Gregor   unsigned ColNo  = getColumnNumber(LocInfo.first, LocInfo.second, &Invalid);
151675f26d6cSDouglas Gregor   if (Invalid)
151775f26d6cSDouglas Gregor     return PresumedLoc();
151875f26d6cSDouglas Gregor 
1519d4293922SChris Lattner   SourceLocation IncludeLoc = FI.getIncludeLoc();
1520f1ca7d3eSChris Lattner 
1521d4293922SChris Lattner   // If we have #line directives in this file, update and overwrite the physical
1522d4293922SChris Lattner   // location info if appropriate.
15230b50cb79SRichard Smith   if (UseLineDirectives && FI.hasLineDirectives()) {
1524d4293922SChris Lattner     assert(LineTable && "Can't have linetable entries without a LineTable!");
1525d4293922SChris Lattner     // See if there is a #line directive before this.  If so, get it.
1526d4293922SChris Lattner     if (const LineEntry *Entry =
152702c2dbf4SDouglas Gregor           LineTable->FindNearestLineEntry(LocInfo.first, LocInfo.second)) {
1528c1219ff7SChris Lattner       // If the LineEntry indicates a filename, use it.
1529047e65dbSAlexandre Ganea       if (Entry->FilenameID != -1) {
1530d4293922SChris Lattner         Filename = LineTable->getFilename(Entry->FilenameID);
1531047e65dbSAlexandre Ganea         // The contents of files referenced by #line are not in the
1532047e65dbSAlexandre Ganea         // SourceManager
1533047e65dbSAlexandre Ganea         FID = FileID::get(0);
1534047e65dbSAlexandre Ganea       }
1535c1219ff7SChris Lattner 
1536c1219ff7SChris Lattner       // Use the line number specified by the LineEntry.  This line number may
1537c1219ff7SChris Lattner       // be multiple lines down from the line entry.  Add the difference in
1538c1219ff7SChris Lattner       // physical line numbers from the query point and the line marker to the
1539c1219ff7SChris Lattner       // total.
1540c1219ff7SChris Lattner       unsigned MarkerLineNo = getLineNumber(LocInfo.first, Entry->FileOffset);
1541c1219ff7SChris Lattner       LineNo = Entry->LineNo + (LineNo-MarkerLineNo-1);
1542c1219ff7SChris Lattner 
154320c50ba2SChris Lattner       // Note that column numbers are not molested by line markers.
15441c967784SChris Lattner 
15451c967784SChris Lattner       // Handle virtual #include manipulation.
15461c967784SChris Lattner       if (Entry->IncludeOffset) {
15471c967784SChris Lattner         IncludeLoc = getLocForStartOfFile(LocInfo.first);
1548e6e67deeSArgyrios Kyrtzidis         IncludeLoc = IncludeLoc.getLocWithOffset(Entry->IncludeOffset);
15491c967784SChris Lattner       }
1550d4293922SChris Lattner     }
1551d4293922SChris Lattner   }
1552d4293922SChris Lattner 
1553047e65dbSAlexandre Ganea   return PresumedLoc(Filename.data(), FID, LineNo, ColNo, IncludeLoc);
15544fa23625SChris Lattner }
15554fa23625SChris Lattner 
15569fc8faf9SAdrian Prantl /// Returns whether the PresumedLoc for a given SourceLocation is
1557e7800df4SBenjamin Kramer /// in the main file.
1558e7800df4SBenjamin Kramer ///
1559e7800df4SBenjamin Kramer /// This computes the "presumed" location for a SourceLocation, then checks
1560e7800df4SBenjamin Kramer /// whether it came from a file other than the main file. This is different
1561e7800df4SBenjamin Kramer /// from isWrittenInMainFile() because it takes line marker directives into
1562e7800df4SBenjamin Kramer /// account.
1563e7800df4SBenjamin Kramer bool SourceManager::isInMainFile(SourceLocation Loc) const {
1564e7800df4SBenjamin Kramer   if (Loc.isInvalid()) return false;
1565e7800df4SBenjamin Kramer 
1566e7800df4SBenjamin Kramer   // Presumed locations are always for expansion points.
1567e7800df4SBenjamin Kramer   std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(Loc);
1568e7800df4SBenjamin Kramer 
1569b6c6daa9SDuncan P. N. Exon Smith   const SLocEntry *Entry = getSLocEntryForFile(LocInfo.first);
1570b6c6daa9SDuncan P. N. Exon Smith   if (!Entry)
1571e7800df4SBenjamin Kramer     return false;
1572e7800df4SBenjamin Kramer 
1573b6c6daa9SDuncan P. N. Exon Smith   const SrcMgr::FileInfo &FI = Entry->getFile();
1574e7800df4SBenjamin Kramer 
1575e7800df4SBenjamin Kramer   // Check if there is a line directive for this location.
1576e7800df4SBenjamin Kramer   if (FI.hasLineDirectives())
1577e7800df4SBenjamin Kramer     if (const LineEntry *Entry =
1578e7800df4SBenjamin Kramer             LineTable->FindNearestLineEntry(LocInfo.first, LocInfo.second))
1579e7800df4SBenjamin Kramer       if (Entry->IncludeOffset)
1580e7800df4SBenjamin Kramer         return false;
1581e7800df4SBenjamin Kramer 
1582e7800df4SBenjamin Kramer   return FI.getIncludeLoc().isInvalid();
1583e7800df4SBenjamin Kramer }
1584e7800df4SBenjamin Kramer 
15859fc8faf9SAdrian Prantl /// The size of the SLocEntry that \p FID represents.
1586296374b5SArgyrios Kyrtzidis unsigned SourceManager::getFileIDSize(FileID FID) const {
1587296374b5SArgyrios Kyrtzidis   bool Invalid = false;
1588296374b5SArgyrios Kyrtzidis   const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid);
1589296374b5SArgyrios Kyrtzidis   if (Invalid)
1590296374b5SArgyrios Kyrtzidis     return 0;
1591296374b5SArgyrios Kyrtzidis 
1592296374b5SArgyrios Kyrtzidis   int ID = FID.ID;
1593296374b5SArgyrios Kyrtzidis   unsigned NextOffset;
1594296374b5SArgyrios Kyrtzidis   if ((ID > 0 && unsigned(ID+1) == local_sloc_entry_size()))
1595296374b5SArgyrios Kyrtzidis     NextOffset = getNextLocalOffset();
1596296374b5SArgyrios Kyrtzidis   else if (ID+1 == -1)
1597296374b5SArgyrios Kyrtzidis     NextOffset = MaxLoadedOffset;
1598296374b5SArgyrios Kyrtzidis   else
1599296374b5SArgyrios Kyrtzidis     NextOffset = getSLocEntry(FileID::get(ID+1)).getOffset();
1600296374b5SArgyrios Kyrtzidis 
1601296374b5SArgyrios Kyrtzidis   return NextOffset - Entry.getOffset() - 1;
1602296374b5SArgyrios Kyrtzidis }
1603296374b5SArgyrios Kyrtzidis 
16044fa23625SChris Lattner //===----------------------------------------------------------------------===//
16054fa23625SChris Lattner // Other miscellaneous methods.
16064fa23625SChris Lattner //===----------------------------------------------------------------------===//
16074fa23625SChris Lattner 
16089fc8faf9SAdrian Prantl /// Get the source location for the given file:line:col triplet.
160988f663c0SArgyrios Kyrtzidis ///
161088f663c0SArgyrios Kyrtzidis /// If the source file is included multiple times, the source location will
1611925296b4SDouglas Gregor /// be based upon an arbitrary inclusion.
161292a47bd9SArgyrios Kyrtzidis SourceLocation SourceManager::translateFileLineCol(const FileEntry *SourceFile,
16137c06d866SArgyrios Kyrtzidis                                                   unsigned Line,
16147c06d866SArgyrios Kyrtzidis                                                   unsigned Col) const {
161588f663c0SArgyrios Kyrtzidis   assert(SourceFile && "Null source file!");
161688f663c0SArgyrios Kyrtzidis   assert(Line && Col && "Line and column should start from 1!");
161788f663c0SArgyrios Kyrtzidis 
161804a6e5f8SArgyrios Kyrtzidis   FileID FirstFID = translateFile(SourceFile);
161904a6e5f8SArgyrios Kyrtzidis   return translateLineCol(FirstFID, Line, Col);
162004a6e5f8SArgyrios Kyrtzidis }
162104a6e5f8SArgyrios Kyrtzidis 
16229fc8faf9SAdrian Prantl /// Get the FileID for the given file.
162304a6e5f8SArgyrios Kyrtzidis ///
162404a6e5f8SArgyrios Kyrtzidis /// If the source file is included multiple times, the FileID will be the
162504a6e5f8SArgyrios Kyrtzidis /// first inclusion.
162604a6e5f8SArgyrios Kyrtzidis FileID SourceManager::translateFile(const FileEntry *SourceFile) const {
162704a6e5f8SArgyrios Kyrtzidis   assert(SourceFile && "Null source file!");
162804a6e5f8SArgyrios Kyrtzidis 
1629e664276bSDouglas Gregor   // First, check the main file ID, since it is common to look for a
1630e664276bSDouglas Gregor   // location in the main file.
16318b563665SYaron Keren   if (MainFileID.isValid()) {
163249f754f4SDouglas Gregor     bool Invalid = false;
163349f754f4SDouglas Gregor     const SLocEntry &MainSLoc = getSLocEntry(MainFileID, &Invalid);
163449f754f4SDouglas Gregor     if (Invalid)
163504a6e5f8SArgyrios Kyrtzidis       return FileID();
163649f754f4SDouglas Gregor 
1637e664276bSDouglas Gregor     if (MainSLoc.isFile()) {
163874a87834SDuncan P. N. Exon Smith       if (MainSLoc.getFile().getContentCache().OrigEntry == SourceFile)
163906abd696SAlex Lorenz         return MainFileID;
1640d766be68SDouglas Gregor     }
1641d766be68SDouglas Gregor   }
1642e664276bSDouglas Gregor 
1643e664276bSDouglas Gregor   // The location we're looking for isn't in the main file; look
1644925296b4SDouglas Gregor   // through all of the local source locations.
1645925296b4SDouglas Gregor   for (unsigned I = 0, N = local_sloc_entry_size(); I != N; ++I) {
16468cce7af0SNick Desaulniers     const SLocEntry &SLoc = getLocalSLocEntry(I);
164774a87834SDuncan P. N. Exon Smith     if (SLoc.isFile() &&
164874a87834SDuncan P. N. Exon Smith         SLoc.getFile().getContentCache().OrigEntry == SourceFile)
164906abd696SAlex Lorenz       return FileID::get(I);
1650e664276bSDouglas Gregor   }
165106abd696SAlex Lorenz 
1652925296b4SDouglas Gregor   // If that still didn't help, try the modules.
1653925296b4SDouglas Gregor   for (unsigned I = 0, N = loaded_sloc_entry_size(); I != N; ++I) {
1654925296b4SDouglas Gregor     const SLocEntry &SLoc = getLoadedSLocEntry(I);
165574a87834SDuncan P. N. Exon Smith     if (SLoc.isFile() &&
165674a87834SDuncan P. N. Exon Smith         SLoc.getFile().getContentCache().OrigEntry == SourceFile)
165706abd696SAlex Lorenz       return FileID::get(-int(I) - 2);
1658e664276bSDouglas Gregor   }
1659e664276bSDouglas Gregor 
166004a6e5f8SArgyrios Kyrtzidis   return FileID();
1661532c5196SArgyrios Kyrtzidis }
1662532c5196SArgyrios Kyrtzidis 
16639fc8faf9SAdrian Prantl /// Get the source location in \arg FID for the given line:col.
1664532c5196SArgyrios Kyrtzidis /// Returns null location if \arg FID is not a file SLocEntry.
1665532c5196SArgyrios Kyrtzidis SourceLocation SourceManager::translateLineCol(FileID FID,
16667c06d866SArgyrios Kyrtzidis                                                unsigned Line,
16677c06d866SArgyrios Kyrtzidis                                                unsigned Col) const {
1668ef1cf830SAaron Ballman   // Lines are used as a one-based index into a zero-based array. This assert
1669ef1cf830SAaron Ballman   // checks for possible buffer underruns.
1670fe2c0ff9SGabor Horvath   assert(Line && Col && "Line and column should start from 1!");
1671ef1cf830SAaron Ballman 
1672532c5196SArgyrios Kyrtzidis   if (FID.isInvalid())
1673532c5196SArgyrios Kyrtzidis     return SourceLocation();
1674532c5196SArgyrios Kyrtzidis 
1675532c5196SArgyrios Kyrtzidis   bool Invalid = false;
1676532c5196SArgyrios Kyrtzidis   const SLocEntry &Entry = getSLocEntry(FID, &Invalid);
1677532c5196SArgyrios Kyrtzidis   if (Invalid)
1678532c5196SArgyrios Kyrtzidis     return SourceLocation();
1679532c5196SArgyrios Kyrtzidis 
1680532c5196SArgyrios Kyrtzidis   if (!Entry.isFile())
168188f663c0SArgyrios Kyrtzidis     return SourceLocation();
1682e664276bSDouglas Gregor 
16837c2b28a1SArgyrios Kyrtzidis   SourceLocation FileLoc = SourceLocation::getFileLoc(Entry.getOffset());
16847c2b28a1SArgyrios Kyrtzidis 
1685e664276bSDouglas Gregor   if (Line == 1 && Col == 1)
16867c2b28a1SArgyrios Kyrtzidis     return FileLoc;
1687e664276bSDouglas Gregor 
168874a87834SDuncan P. N. Exon Smith   ContentCache *Content =
168974a87834SDuncan P. N. Exon Smith       const_cast<ContentCache *>(&Entry.getFile().getContentCache());
169088f663c0SArgyrios Kyrtzidis 
169188f663c0SArgyrios Kyrtzidis   // If this is the first use of line information for this buffer, compute the
1692925296b4SDouglas Gregor   // SourceLineCache for it on demand.
1693f1186c5aSCraig Topper   if (!Content->SourceLineCache) {
16947bda4b83SDouglas Gregor     bool MyInvalid = false;
1695fb24a3a4SChris Lattner     ComputeLineNumbers(Diag, Content, ContentCacheAlloc, *this, MyInvalid);
16967bda4b83SDouglas Gregor     if (MyInvalid)
16977bda4b83SDouglas Gregor       return SourceLocation();
16987bda4b83SDouglas Gregor   }
169988f663c0SArgyrios Kyrtzidis 
1700d758f79eSDuncan P. N. Exon Smith   llvm::Optional<llvm::MemoryBufferRef> Buffer =
1701d758f79eSDuncan P. N. Exon Smith       Content->getBufferOrNone(Diag, getFileManager());
1702d758f79eSDuncan P. N. Exon Smith   if (!Buffer)
1703d758f79eSDuncan P. N. Exon Smith     return SourceLocation();
1704d758f79eSDuncan P. N. Exon Smith 
1705*dbbc4f4eSDuncan P. N. Exon Smith   if (Line > Content->SourceLineCache.size()) {
1706d758f79eSDuncan P. N. Exon Smith     unsigned Size = Buffer->getBufferSize();
1707b8b9f28eSDouglas Gregor     if (Size > 0)
1708b8b9f28eSDouglas Gregor       --Size;
17097c2b28a1SArgyrios Kyrtzidis     return FileLoc.getLocWithOffset(Size);
1710b8b9f28eSDouglas Gregor   }
1711b8b9f28eSDouglas Gregor 
1712b8b9f28eSDouglas Gregor   unsigned FilePos = Content->SourceLineCache[Line - 1];
17132a8bc152SDylan Noblesmith   const char *Buf = Buffer->getBufferStart() + FilePos;
17142a8bc152SDylan Noblesmith   unsigned BufLength = Buffer->getBufferSize() - FilePos;
17157c2b28a1SArgyrios Kyrtzidis   if (BufLength == 0)
17167c2b28a1SArgyrios Kyrtzidis     return FileLoc.getLocWithOffset(FilePos);
17177c2b28a1SArgyrios Kyrtzidis 
1718b8b9f28eSDouglas Gregor   unsigned i = 0;
1719b8b9f28eSDouglas Gregor 
1720b8b9f28eSDouglas Gregor   // Check that the given column is valid.
1721b8b9f28eSDouglas Gregor   while (i < BufLength-1 && i < Col-1 && Buf[i] != '\n' && Buf[i] != '\r')
1722b8b9f28eSDouglas Gregor     ++i;
17237c2b28a1SArgyrios Kyrtzidis   return FileLoc.getLocWithOffset(FilePos + i);
172488f663c0SArgyrios Kyrtzidis }
172588f663c0SArgyrios Kyrtzidis 
17269fc8faf9SAdrian Prantl /// Compute a map of macro argument chunks to their expanded source
172761ef3db2SArgyrios Kyrtzidis /// location. Chunks that are not part of a macro argument will map to an
172861ef3db2SArgyrios Kyrtzidis /// invalid source location. e.g. if a file contains one macro argument at
172961ef3db2SArgyrios Kyrtzidis /// offset 100 with length 10, this is how the map will be formed:
173061ef3db2SArgyrios Kyrtzidis ///     0   -> SourceLocation()
173161ef3db2SArgyrios Kyrtzidis ///     100 -> Expanded macro arg location
173261ef3db2SArgyrios Kyrtzidis ///     110 -> SourceLocation()
1733d2c6a6d1SVedant Kumar void SourceManager::computeMacroArgsCache(MacroArgsMap &MacroArgsCache,
17347c06d866SArgyrios Kyrtzidis                                           FileID FID) const {
17358b563665SYaron Keren   assert(FID.isValid());
173661ef3db2SArgyrios Kyrtzidis 
173761ef3db2SArgyrios Kyrtzidis   // Initially no macro argument chunk is present.
173861ef3db2SArgyrios Kyrtzidis   MacroArgsCache.insert(std::make_pair(0, SourceLocation()));
173961ef3db2SArgyrios Kyrtzidis 
174061ef3db2SArgyrios Kyrtzidis   int ID = FID.ID;
1741918e0ca7SEugene Zelenko   while (true) {
174261ef3db2SArgyrios Kyrtzidis     ++ID;
174361ef3db2SArgyrios Kyrtzidis     // Stop if there are no more FileIDs to check.
174461ef3db2SArgyrios Kyrtzidis     if (ID > 0) {
174561ef3db2SArgyrios Kyrtzidis       if (unsigned(ID) >= local_sloc_entry_size())
174661ef3db2SArgyrios Kyrtzidis         return;
174761ef3db2SArgyrios Kyrtzidis     } else if (ID == -1) {
174861ef3db2SArgyrios Kyrtzidis       return;
174961ef3db2SArgyrios Kyrtzidis     }
175061ef3db2SArgyrios Kyrtzidis 
1751fe68302fSArgyrios Kyrtzidis     bool Invalid = false;
1752fe68302fSArgyrios Kyrtzidis     const SrcMgr::SLocEntry &Entry = getSLocEntryByID(ID, &Invalid);
1753fe68302fSArgyrios Kyrtzidis     if (Invalid)
1754fe68302fSArgyrios Kyrtzidis       return;
175561ef3db2SArgyrios Kyrtzidis     if (Entry.isFile()) {
17568277a513SJan Korous       auto& File = Entry.getFile();
1757e7870223SJan Korous       if (File.getFileCharacteristic() == C_User_ModuleMap ||
1758e7870223SJan Korous           File.getFileCharacteristic() == C_System_ModuleMap)
1759e7870223SJan Korous         continue;
1760e7870223SJan Korous 
1761e7870223SJan Korous       SourceLocation IncludeLoc = File.getIncludeLoc();
1762411a254aSKadir Cetinkaya       bool IncludedInFID =
1763411a254aSKadir Cetinkaya           (IncludeLoc.isValid() && isInFileID(IncludeLoc, FID)) ||
1764411a254aSKadir Cetinkaya           // Predefined header doesn't have a valid include location in main
1765411a254aSKadir Cetinkaya           // file, but any files created by it should still be skipped when
1766411a254aSKadir Cetinkaya           // computing macro args expanded in the main file.
1767411a254aSKadir Cetinkaya           (FID == MainFileID && Entry.getFile().Filename == "<built-in>");
1768411a254aSKadir Cetinkaya       if (IncludedInFID) {
1769411a254aSKadir Cetinkaya         // Skip the files/macros of the #include'd file, we only care about
1770411a254aSKadir Cetinkaya         // macros that lexed macro arguments from our file.
177161ef3db2SArgyrios Kyrtzidis         if (Entry.getFile().NumCreatedFIDs)
177261ef3db2SArgyrios Kyrtzidis           ID += Entry.getFile().NumCreatedFIDs - 1 /*because of next ++ID*/;
177361ef3db2SArgyrios Kyrtzidis         continue;
1774411a254aSKadir Cetinkaya       } else if (IncludeLoc.isValid()) {
1775411a254aSKadir Cetinkaya         // If file was included but not from FID, there is no more files/macros
1776411a254aSKadir Cetinkaya         // that may be "contained" in this file.
1777411a254aSKadir Cetinkaya         return;
1778411a254aSKadir Cetinkaya       }
1779411a254aSKadir Cetinkaya       continue;
178061ef3db2SArgyrios Kyrtzidis     }
178161ef3db2SArgyrios Kyrtzidis 
1782e841c901SArgyrios Kyrtzidis     const ExpansionInfo &ExpInfo = Entry.getExpansion();
1783e841c901SArgyrios Kyrtzidis 
1784e841c901SArgyrios Kyrtzidis     if (ExpInfo.getExpansionLocStart().isFileID()) {
1785e841c901SArgyrios Kyrtzidis       if (!isInFileID(ExpInfo.getExpansionLocStart(), FID))
1786e841c901SArgyrios Kyrtzidis         return; // No more files/macros that may be "contained" in this file.
1787e841c901SArgyrios Kyrtzidis     }
1788e841c901SArgyrios Kyrtzidis 
1789e841c901SArgyrios Kyrtzidis     if (!ExpInfo.isMacroArgExpansion())
179061ef3db2SArgyrios Kyrtzidis       continue;
179161ef3db2SArgyrios Kyrtzidis 
179273ccdb9cSArgyrios Kyrtzidis     associateFileChunkWithMacroArgExp(MacroArgsCache, FID,
179373ccdb9cSArgyrios Kyrtzidis                                  ExpInfo.getSpellingLoc(),
179473ccdb9cSArgyrios Kyrtzidis                                  SourceLocation::getMacroLoc(Entry.getOffset()),
179573ccdb9cSArgyrios Kyrtzidis                                  getFileIDSize(FileID::get(ID)));
1796e841c901SArgyrios Kyrtzidis   }
179773ccdb9cSArgyrios Kyrtzidis }
179873ccdb9cSArgyrios Kyrtzidis 
179973ccdb9cSArgyrios Kyrtzidis void SourceManager::associateFileChunkWithMacroArgExp(
180073ccdb9cSArgyrios Kyrtzidis                                          MacroArgsMap &MacroArgsCache,
180173ccdb9cSArgyrios Kyrtzidis                                          FileID FID,
180273ccdb9cSArgyrios Kyrtzidis                                          SourceLocation SpellLoc,
180373ccdb9cSArgyrios Kyrtzidis                                          SourceLocation ExpansionLoc,
180473ccdb9cSArgyrios Kyrtzidis                                          unsigned ExpansionLength) const {
180573ccdb9cSArgyrios Kyrtzidis   if (!SpellLoc.isFileID()) {
180673ccdb9cSArgyrios Kyrtzidis     unsigned SpellBeginOffs = SpellLoc.getOffset();
180773ccdb9cSArgyrios Kyrtzidis     unsigned SpellEndOffs = SpellBeginOffs + ExpansionLength;
180873ccdb9cSArgyrios Kyrtzidis 
180973ccdb9cSArgyrios Kyrtzidis     // The spelling range for this macro argument expansion can span multiple
181073ccdb9cSArgyrios Kyrtzidis     // consecutive FileID entries. Go through each entry contained in the
181173ccdb9cSArgyrios Kyrtzidis     // spelling range and if one is itself a macro argument expansion, recurse
181273ccdb9cSArgyrios Kyrtzidis     // and associate the file chunk that it represents.
181373ccdb9cSArgyrios Kyrtzidis 
181473ccdb9cSArgyrios Kyrtzidis     FileID SpellFID; // Current FileID in the spelling range.
181573ccdb9cSArgyrios Kyrtzidis     unsigned SpellRelativeOffs;
1816867ea1d4SBenjamin Kramer     std::tie(SpellFID, SpellRelativeOffs) = getDecomposedLoc(SpellLoc);
1817918e0ca7SEugene Zelenko     while (true) {
181873ccdb9cSArgyrios Kyrtzidis       const SLocEntry &Entry = getSLocEntry(SpellFID);
181973ccdb9cSArgyrios Kyrtzidis       unsigned SpellFIDBeginOffs = Entry.getOffset();
182073ccdb9cSArgyrios Kyrtzidis       unsigned SpellFIDSize = getFileIDSize(SpellFID);
182173ccdb9cSArgyrios Kyrtzidis       unsigned SpellFIDEndOffs = SpellFIDBeginOffs + SpellFIDSize;
182273ccdb9cSArgyrios Kyrtzidis       const ExpansionInfo &Info = Entry.getExpansion();
182373ccdb9cSArgyrios Kyrtzidis       if (Info.isMacroArgExpansion()) {
182473ccdb9cSArgyrios Kyrtzidis         unsigned CurrSpellLength;
182573ccdb9cSArgyrios Kyrtzidis         if (SpellFIDEndOffs < SpellEndOffs)
182673ccdb9cSArgyrios Kyrtzidis           CurrSpellLength = SpellFIDSize - SpellRelativeOffs;
182773ccdb9cSArgyrios Kyrtzidis         else
182873ccdb9cSArgyrios Kyrtzidis           CurrSpellLength = ExpansionLength;
182973ccdb9cSArgyrios Kyrtzidis         associateFileChunkWithMacroArgExp(MacroArgsCache, FID,
183073ccdb9cSArgyrios Kyrtzidis                       Info.getSpellingLoc().getLocWithOffset(SpellRelativeOffs),
183173ccdb9cSArgyrios Kyrtzidis                       ExpansionLoc, CurrSpellLength);
183273ccdb9cSArgyrios Kyrtzidis       }
183373ccdb9cSArgyrios Kyrtzidis 
183473ccdb9cSArgyrios Kyrtzidis       if (SpellFIDEndOffs >= SpellEndOffs)
183573ccdb9cSArgyrios Kyrtzidis         return; // we covered all FileID entries in the spelling range.
183673ccdb9cSArgyrios Kyrtzidis 
183773ccdb9cSArgyrios Kyrtzidis       // Move to the next FileID entry in the spelling range.
183873ccdb9cSArgyrios Kyrtzidis       unsigned advance = SpellFIDSize - SpellRelativeOffs + 1;
183973ccdb9cSArgyrios Kyrtzidis       ExpansionLoc = ExpansionLoc.getLocWithOffset(advance);
184073ccdb9cSArgyrios Kyrtzidis       ExpansionLength -= advance;
184173ccdb9cSArgyrios Kyrtzidis       ++SpellFID.ID;
184273ccdb9cSArgyrios Kyrtzidis       SpellRelativeOffs = 0;
184373ccdb9cSArgyrios Kyrtzidis     }
184473ccdb9cSArgyrios Kyrtzidis   }
184573ccdb9cSArgyrios Kyrtzidis 
184673ccdb9cSArgyrios Kyrtzidis   assert(SpellLoc.isFileID());
1847e841c901SArgyrios Kyrtzidis 
184861ef3db2SArgyrios Kyrtzidis   unsigned BeginOffs;
184961ef3db2SArgyrios Kyrtzidis   if (!isInFileID(SpellLoc, FID, &BeginOffs))
185073ccdb9cSArgyrios Kyrtzidis     return;
1851e841c901SArgyrios Kyrtzidis 
185273ccdb9cSArgyrios Kyrtzidis   unsigned EndOffs = BeginOffs + ExpansionLength;
185361ef3db2SArgyrios Kyrtzidis 
185461ef3db2SArgyrios Kyrtzidis   // Add a new chunk for this macro argument. A previous macro argument chunk
185561ef3db2SArgyrios Kyrtzidis   // may have been lexed again, so e.g. if the map is
185661ef3db2SArgyrios Kyrtzidis   //     0   -> SourceLocation()
185761ef3db2SArgyrios Kyrtzidis   //     100 -> Expanded loc #1
185861ef3db2SArgyrios Kyrtzidis   //     110 -> SourceLocation()
18592a8c18d9SAlexander Kornienko   // and we found a new macro FileID that lexed from offset 105 with length 3,
186061ef3db2SArgyrios Kyrtzidis   // the new map will be:
186161ef3db2SArgyrios Kyrtzidis   //     0   -> SourceLocation()
186261ef3db2SArgyrios Kyrtzidis   //     100 -> Expanded loc #1
186361ef3db2SArgyrios Kyrtzidis   //     105 -> Expanded loc #2
186461ef3db2SArgyrios Kyrtzidis   //     108 -> Expanded loc #1
186561ef3db2SArgyrios Kyrtzidis   //     110 -> SourceLocation()
186661ef3db2SArgyrios Kyrtzidis   //
186761ef3db2SArgyrios Kyrtzidis   // Since re-lexed macro chunks will always be the same size or less of
186861ef3db2SArgyrios Kyrtzidis   // previous chunks, we only need to find where the ending of the new macro
186961ef3db2SArgyrios Kyrtzidis   // chunk is mapped to and update the map with new begin/end mappings.
187061ef3db2SArgyrios Kyrtzidis 
18714bdd6aa1SArgyrios Kyrtzidis   MacroArgsMap::iterator I = MacroArgsCache.upper_bound(EndOffs);
187261ef3db2SArgyrios Kyrtzidis   --I;
187361ef3db2SArgyrios Kyrtzidis   SourceLocation EndOffsMappedLoc = I->second;
187473ccdb9cSArgyrios Kyrtzidis   MacroArgsCache[BeginOffs] = ExpansionLoc;
187561ef3db2SArgyrios Kyrtzidis   MacroArgsCache[EndOffs] = EndOffsMappedLoc;
187661ef3db2SArgyrios Kyrtzidis }
187761ef3db2SArgyrios Kyrtzidis 
18789fc8faf9SAdrian Prantl /// If \arg Loc points inside a function macro argument, the returned
187992a47bd9SArgyrios Kyrtzidis /// location will be the macro location in which the argument was expanded.
188092a47bd9SArgyrios Kyrtzidis /// If a macro argument is used multiple times, the expanded location will
188192a47bd9SArgyrios Kyrtzidis /// be at the first expansion of the argument.
188292a47bd9SArgyrios Kyrtzidis /// e.g.
188392a47bd9SArgyrios Kyrtzidis ///   MY_MACRO(foo);
188492a47bd9SArgyrios Kyrtzidis ///             ^
188592a47bd9SArgyrios Kyrtzidis /// Passing a file location pointing at 'foo', will yield a macro location
188692a47bd9SArgyrios Kyrtzidis /// where 'foo' was expanded into.
18877c06d866SArgyrios Kyrtzidis SourceLocation
18887c06d866SArgyrios Kyrtzidis SourceManager::getMacroArgExpandedLocation(SourceLocation Loc) const {
188961ef3db2SArgyrios Kyrtzidis   if (Loc.isInvalid() || !Loc.isFileID())
189092a47bd9SArgyrios Kyrtzidis     return Loc;
189192a47bd9SArgyrios Kyrtzidis 
189261ef3db2SArgyrios Kyrtzidis   FileID FID;
189361ef3db2SArgyrios Kyrtzidis   unsigned Offset;
1894867ea1d4SBenjamin Kramer   std::tie(FID, Offset) = getDecomposedLoc(Loc);
189592a47bd9SArgyrios Kyrtzidis   if (FID.isInvalid())
189692a47bd9SArgyrios Kyrtzidis     return Loc;
189792a47bd9SArgyrios Kyrtzidis 
1898d2c6a6d1SVedant Kumar   std::unique_ptr<MacroArgsMap> &MacroArgsCache = MacroArgsCacheMap[FID];
1899d2c6a6d1SVedant Kumar   if (!MacroArgsCache) {
19002b3d49b6SJonas Devlieghere     MacroArgsCache = std::make_unique<MacroArgsMap>();
1901ecc31440SVedant Kumar     computeMacroArgsCache(*MacroArgsCache, FID);
1902d2c6a6d1SVedant Kumar   }
190392a47bd9SArgyrios Kyrtzidis 
19044bdd6aa1SArgyrios Kyrtzidis   assert(!MacroArgsCache->empty());
19054bdd6aa1SArgyrios Kyrtzidis   MacroArgsMap::iterator I = MacroArgsCache->upper_bound(Offset);
1906ae726fecSJan Korous   // In case every element in MacroArgsCache is greater than Offset we can't
1907ae726fecSJan Korous   // decrement the iterator.
1908ae726fecSJan Korous   if (I == MacroArgsCache->begin())
1909ae726fecSJan Korous     return Loc;
1910ae726fecSJan Korous 
191161ef3db2SArgyrios Kyrtzidis   --I;
191261ef3db2SArgyrios Kyrtzidis 
191361ef3db2SArgyrios Kyrtzidis   unsigned MacroArgBeginOffs = I->first;
191461ef3db2SArgyrios Kyrtzidis   SourceLocation MacroArgExpandedLoc = I->second;
191561ef3db2SArgyrios Kyrtzidis   if (MacroArgExpandedLoc.isValid())
1916e6e67deeSArgyrios Kyrtzidis     return MacroArgExpandedLoc.getLocWithOffset(Offset - MacroArgBeginOffs);
191761ef3db2SArgyrios Kyrtzidis 
191892a47bd9SArgyrios Kyrtzidis   return Loc;
191992a47bd9SArgyrios Kyrtzidis }
192092a47bd9SArgyrios Kyrtzidis 
192137613a9cSArgyrios Kyrtzidis std::pair<FileID, unsigned>
192237613a9cSArgyrios Kyrtzidis SourceManager::getDecomposedIncludedLoc(FileID FID) const {
19235dca8643SArgyrios Kyrtzidis   if (FID.isInvalid())
19245dca8643SArgyrios Kyrtzidis     return std::make_pair(FileID(), 0);
19255dca8643SArgyrios Kyrtzidis 
192637613a9cSArgyrios Kyrtzidis   // Uses IncludedLocMap to retrieve/cache the decomposed loc.
192737613a9cSArgyrios Kyrtzidis 
1928918e0ca7SEugene Zelenko   using DecompTy = std::pair<FileID, unsigned>;
1929eae2b49fSFangrui Song   auto InsertOp = IncludedLocMap.try_emplace(FID);
193037613a9cSArgyrios Kyrtzidis   DecompTy &DecompLoc = InsertOp.first->second;
193137613a9cSArgyrios Kyrtzidis   if (!InsertOp.second)
193237613a9cSArgyrios Kyrtzidis     return DecompLoc; // already in map.
193337613a9cSArgyrios Kyrtzidis 
193437613a9cSArgyrios Kyrtzidis   SourceLocation UpperLoc;
19355dca8643SArgyrios Kyrtzidis   bool Invalid = false;
19365dca8643SArgyrios Kyrtzidis   const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid);
19375dca8643SArgyrios Kyrtzidis   if (!Invalid) {
193837613a9cSArgyrios Kyrtzidis     if (Entry.isExpansion())
193937613a9cSArgyrios Kyrtzidis       UpperLoc = Entry.getExpansion().getExpansionLocStart();
194037613a9cSArgyrios Kyrtzidis     else
194137613a9cSArgyrios Kyrtzidis       UpperLoc = Entry.getFile().getIncludeLoc();
19425dca8643SArgyrios Kyrtzidis   }
194337613a9cSArgyrios Kyrtzidis 
194437613a9cSArgyrios Kyrtzidis   if (UpperLoc.isValid())
194537613a9cSArgyrios Kyrtzidis     DecompLoc = getDecomposedLoc(UpperLoc);
194637613a9cSArgyrios Kyrtzidis 
194737613a9cSArgyrios Kyrtzidis   return DecompLoc;
194837613a9cSArgyrios Kyrtzidis }
194937613a9cSArgyrios Kyrtzidis 
195064ee782eSChandler Carruth /// Given a decomposed source location, move it up the include/expansion stack
195164ee782eSChandler Carruth /// to the parent source location.  If this is possible, return the decomposed
195264ee782eSChandler Carruth /// version of the parent in Loc and return false.  If Loc is the top-level
195364ee782eSChandler Carruth /// entry, return true and don't modify it.
1954a99fa1aeSChris Lattner static bool MoveUpIncludeHierarchy(std::pair<FileID, unsigned> &Loc,
1955a99fa1aeSChris Lattner                                    const SourceManager &SM) {
195637613a9cSArgyrios Kyrtzidis   std::pair<FileID, unsigned> UpperLoc = SM.getDecomposedIncludedLoc(Loc.first);
195737613a9cSArgyrios Kyrtzidis   if (UpperLoc.first.isInvalid())
1958a99fa1aeSChris Lattner     return true; // We reached the top.
1959a99fa1aeSChris Lattner 
196037613a9cSArgyrios Kyrtzidis   Loc = UpperLoc;
1961a99fa1aeSChris Lattner   return false;
1962a99fa1aeSChris Lattner }
1963a99fa1aeSChris Lattner 
196408037045STed Kremenek /// Return the cache entry for comparing the given file IDs
196508037045STed Kremenek /// for isBeforeInTranslationUnit.
196608037045STed Kremenek InBeforeInTUCacheEntry &SourceManager::getInBeforeInTUCache(FileID LFID,
196708037045STed Kremenek                                                             FileID RFID) const {
196808037045STed Kremenek   // This is a magic number for limiting the cache size.  It was experimentally
196908037045STed Kremenek   // derived from a small Objective-C project (where the cache filled
197008037045STed Kremenek   // out to ~250 items).  We can make it larger if necessary.
197108037045STed Kremenek   enum { MagicCacheSize = 300 };
197208037045STed Kremenek   IsBeforeInTUCacheKey Key(LFID, RFID);
197308037045STed Kremenek 
197408037045STed Kremenek   // If the cache size isn't too large, do a lookup and if necessary default
197508037045STed Kremenek   // construct an entry.  We can then return it to the caller for direct
197608037045STed Kremenek   // use.  When they update the value, the cache will get automatically
197708037045STed Kremenek   // updated as well.
197808037045STed Kremenek   if (IBTUCache.size() < MagicCacheSize)
197908037045STed Kremenek     return IBTUCache[Key];
198008037045STed Kremenek 
198108037045STed Kremenek   // Otherwise, do a lookup that will not construct a new value.
198208037045STed Kremenek   InBeforeInTUCache::iterator I = IBTUCache.find(Key);
198308037045STed Kremenek   if (I != IBTUCache.end())
198408037045STed Kremenek     return I->second;
198508037045STed Kremenek 
198608037045STed Kremenek   // Fall back to the overflow value.
198708037045STed Kremenek   return IBTUCacheOverflow;
198808037045STed Kremenek }
1989a99fa1aeSChris Lattner 
19909fc8faf9SAdrian Prantl /// Determines the order of 2 source locations in the translation unit.
199133661d9fSArgyrios Kyrtzidis ///
199233661d9fSArgyrios Kyrtzidis /// \returns true if LHS source location comes before RHS, false otherwise.
199333661d9fSArgyrios Kyrtzidis bool SourceManager::isBeforeInTranslationUnit(SourceLocation LHS,
199433661d9fSArgyrios Kyrtzidis                                               SourceLocation RHS) const {
199533661d9fSArgyrios Kyrtzidis   assert(LHS.isValid() && RHS.isValid() && "Passed invalid source location!");
199633661d9fSArgyrios Kyrtzidis   if (LHS == RHS)
199733661d9fSArgyrios Kyrtzidis     return false;
199833661d9fSArgyrios Kyrtzidis 
199933661d9fSArgyrios Kyrtzidis   std::pair<FileID, unsigned> LOffs = getDecomposedLoc(LHS);
200033661d9fSArgyrios Kyrtzidis   std::pair<FileID, unsigned> ROffs = getDecomposedLoc(RHS);
200133661d9fSArgyrios Kyrtzidis 
20025fd822c2SArgyrios Kyrtzidis   // getDecomposedLoc may have failed to return a valid FileID because, e.g. it
20035fd822c2SArgyrios Kyrtzidis   // is a serialized one referring to a file that was removed after we loaded
20045fd822c2SArgyrios Kyrtzidis   // the PCH.
20055dca8643SArgyrios Kyrtzidis   if (LOffs.first.isInvalid() || ROffs.first.isInvalid())
2006d6111d3cSArgyrios Kyrtzidis     return LOffs.first.isInvalid() && !ROffs.first.isInvalid();
20075dca8643SArgyrios Kyrtzidis 
20087848b388SGabor Horvath   std::pair<bool, bool> InSameTU = isInTheSameTranslationUnit(LOffs, ROffs);
20097848b388SGabor Horvath   if (InSameTU.first)
20107848b388SGabor Horvath     return InSameTU.second;
201133661d9fSArgyrios Kyrtzidis 
20121d3b431cSJoerg Sonnenberger   // If we arrived here, the location is either in a built-ins buffer or
20131d3b431cSJoerg Sonnenberger   // associated with global inline asm. PR5662 and PR22576 are examples.
20141d3b431cSJoerg Sonnenberger 
201554c1bcabSDuncan P. N. Exon Smith   StringRef LB = getBufferOrFake(LOffs.first).getBufferIdentifier();
201654c1bcabSDuncan P. N. Exon Smith   StringRef RB = getBufferOrFake(ROffs.first).getBufferIdentifier();
201799d1b295SMehdi Amini   bool LIsBuiltins = LB == "<built-in>";
201899d1b295SMehdi Amini   bool RIsBuiltins = RB == "<built-in>";
20191d3b431cSJoerg Sonnenberger   // Sort built-in before non-built-in.
20201d3b431cSJoerg Sonnenberger   if (LIsBuiltins || RIsBuiltins) {
2021925296b4SDouglas Gregor     if (LIsBuiltins != RIsBuiltins)
2022925296b4SDouglas Gregor       return LIsBuiltins;
2023925296b4SDouglas Gregor     // Both are in built-in buffers, but from different files. We just claim that
2024925296b4SDouglas Gregor     // lower IDs come first.
202566d2f924SChris Lattner     return LOffs.first < ROffs.first;
202633661d9fSArgyrios Kyrtzidis   }
202799d1b295SMehdi Amini   bool LIsAsm = LB == "<inline asm>";
202899d1b295SMehdi Amini   bool RIsAsm = RB == "<inline asm>";
20291d3b431cSJoerg Sonnenberger   // Sort assembler after built-ins, but before the rest.
20301d3b431cSJoerg Sonnenberger   if (LIsAsm || RIsAsm) {
20311d3b431cSJoerg Sonnenberger     if (LIsAsm != RIsAsm)
20321d3b431cSJoerg Sonnenberger       return RIsAsm;
20331d3b431cSJoerg Sonnenberger     assert(LOffs.first == ROffs.first);
20341d3b431cSJoerg Sonnenberger     return false;
20351d3b431cSJoerg Sonnenberger   }
203699d1b295SMehdi Amini   bool LIsScratch = LB == "<scratch space>";
203799d1b295SMehdi Amini   bool RIsScratch = RB == "<scratch space>";
2038154e57f8SYury Gribov   // Sort scratch after inline asm, but before the rest.
2039154e57f8SYury Gribov   if (LIsScratch || RIsScratch) {
2040154e57f8SYury Gribov     if (LIsScratch != RIsScratch)
2041154e57f8SYury Gribov       return LIsScratch;
2042154e57f8SYury Gribov     return LOffs.second < ROffs.second;
2043154e57f8SYury Gribov   }
20441d3b431cSJoerg Sonnenberger   llvm_unreachable("Unsortable locations found");
20451d3b431cSJoerg Sonnenberger }
20464fa23625SChris Lattner 
20477848b388SGabor Horvath std::pair<bool, bool> SourceManager::isInTheSameTranslationUnit(
20487848b388SGabor Horvath     std::pair<FileID, unsigned> &LOffs,
20497848b388SGabor Horvath     std::pair<FileID, unsigned> &ROffs) const {
20507848b388SGabor Horvath   // If the source locations are in the same file, just compare offsets.
20517848b388SGabor Horvath   if (LOffs.first == ROffs.first)
20527848b388SGabor Horvath     return std::make_pair(true, LOffs.second < ROffs.second);
20537848b388SGabor Horvath 
20547848b388SGabor Horvath   // If we are comparing a source location with multiple locations in the same
20557848b388SGabor Horvath   // file, we get a big win by caching the result.
20567848b388SGabor Horvath   InBeforeInTUCacheEntry &IsBeforeInTUCache =
20577848b388SGabor Horvath     getInBeforeInTUCache(LOffs.first, ROffs.first);
20587848b388SGabor Horvath 
20597848b388SGabor Horvath   // If we are comparing a source location with multiple locations in the same
20607848b388SGabor Horvath   // file, we get a big win by caching the result.
20617848b388SGabor Horvath   if (IsBeforeInTUCache.isCacheValid(LOffs.first, ROffs.first))
20627848b388SGabor Horvath     return std::make_pair(
20637848b388SGabor Horvath         true, IsBeforeInTUCache.getCachedResult(LOffs.second, ROffs.second));
20647848b388SGabor Horvath 
20657848b388SGabor Horvath   // Okay, we missed in the cache, start updating the cache for this query.
20667848b388SGabor Horvath   IsBeforeInTUCache.setQueryFIDs(LOffs.first, ROffs.first,
20677848b388SGabor Horvath                           /*isLFIDBeforeRFID=*/LOffs.first.ID < ROffs.first.ID);
20687848b388SGabor Horvath 
20697848b388SGabor Horvath   // We need to find the common ancestor. The only way of doing this is to
20707848b388SGabor Horvath   // build the complete include chain for one and then walking up the chain
20717848b388SGabor Horvath   // of the other looking for a match.
20727848b388SGabor Horvath   // We use a map from FileID to Offset to store the chain. Easier than writing
20737848b388SGabor Horvath   // a custom set hash info that only depends on the first part of a pair.
2074918e0ca7SEugene Zelenko   using LocSet = llvm::SmallDenseMap<FileID, unsigned, 16>;
20757848b388SGabor Horvath   LocSet LChain;
20767848b388SGabor Horvath   do {
20777848b388SGabor Horvath     LChain.insert(LOffs);
20787848b388SGabor Horvath     // We catch the case where LOffs is in a file included by ROffs and
20797848b388SGabor Horvath     // quit early. The other way round unfortunately remains suboptimal.
20807848b388SGabor Horvath   } while (LOffs.first != ROffs.first && !MoveUpIncludeHierarchy(LOffs, *this));
20817848b388SGabor Horvath   LocSet::iterator I;
20827848b388SGabor Horvath   while((I = LChain.find(ROffs.first)) == LChain.end()) {
20837848b388SGabor Horvath     if (MoveUpIncludeHierarchy(ROffs, *this))
20847848b388SGabor Horvath       break; // Met at topmost file.
20857848b388SGabor Horvath   }
20867848b388SGabor Horvath   if (I != LChain.end())
20877848b388SGabor Horvath     LOffs = *I;
20887848b388SGabor Horvath 
20897848b388SGabor Horvath   // If we exited because we found a nearest common ancestor, compare the
20907848b388SGabor Horvath   // locations within the common file and cache them.
20917848b388SGabor Horvath   if (LOffs.first == ROffs.first) {
20927848b388SGabor Horvath     IsBeforeInTUCache.setCommonLoc(LOffs.first, LOffs.second, ROffs.second);
20937848b388SGabor Horvath     return std::make_pair(
20947848b388SGabor Horvath         true, IsBeforeInTUCache.getCachedResult(LOffs.second, ROffs.second));
20957848b388SGabor Horvath   }
20967848b388SGabor Horvath   // Clear the lookup cache, it depends on a common location.
20977848b388SGabor Horvath   IsBeforeInTUCache.clear();
20987848b388SGabor Horvath   return std::make_pair(false, false);
20997848b388SGabor Horvath }
21007848b388SGabor Horvath 
21017a51313dSChris Lattner void SourceManager::PrintStats() const {
210289b422c1SBenjamin Kramer   llvm::errs() << "\n*** Source Manager Stats:\n";
210389b422c1SBenjamin Kramer   llvm::errs() << FileInfos.size() << " files mapped, " << MemBufferInfos.size()
21046d61c3e6SChris Lattner                << " mem buffers mapped.\n";
2105925296b4SDouglas Gregor   llvm::errs() << LocalSLocEntryTable.size() << " local SLocEntry's allocated ("
210643e0c4a8STed Kremenek                << llvm::capacity_in_bytes(LocalSLocEntryTable)
21072cc62093SArgyrios Kyrtzidis                << " bytes of capacity), "
2108925296b4SDouglas Gregor                << NextLocalOffset << "B of Sloc address space used.\n";
2109925296b4SDouglas Gregor   llvm::errs() << LoadedSLocEntryTable.size()
2110925296b4SDouglas Gregor                << " loaded SLocEntries allocated, "
211192a47bd9SArgyrios Kyrtzidis                << MaxLoadedOffset - CurrentLoadedOffset
2112925296b4SDouglas Gregor                << "B of Sloc address space used.\n";
21137a51313dSChris Lattner 
21147a51313dSChris Lattner   unsigned NumLineNumsComputed = 0;
21157a51313dSChris Lattner   unsigned NumFileBytesMapped = 0;
2116c8233df6SChris Lattner   for (fileinfo_iterator I = fileinfo_begin(), E = fileinfo_end(); I != E; ++I){
2117*dbbc4f4eSDuncan P. N. Exon Smith     NumLineNumsComputed += bool(I->second->SourceLineCache);
2118c8233df6SChris Lattner     NumFileBytesMapped  += I->second->getSizeBytesMapped();
21197a51313dSChris Lattner   }
21204bdd6aa1SArgyrios Kyrtzidis   unsigned NumMacroArgsComputed = MacroArgsCacheMap.size();
21217a51313dSChris Lattner 
212289b422c1SBenjamin Kramer   llvm::errs() << NumFileBytesMapped << " bytes of files mapped, "
212361ef3db2SArgyrios Kyrtzidis                << NumLineNumsComputed << " files with line #'s computed, "
212461ef3db2SArgyrios Kyrtzidis                << NumMacroArgsComputed << " files with macro args computed.\n";
212589b422c1SBenjamin Kramer   llvm::errs() << "FileID scans: " << NumLinearScans << " linear, "
21264fa23625SChris Lattner                << NumBinaryProbes << " binary.\n";
21277a51313dSChris Lattner }
2128258ae54aSDouglas Gregor 
212903a06dd1SRichard Smith LLVM_DUMP_METHOD void SourceManager::dump() const {
213003a06dd1SRichard Smith   llvm::raw_ostream &out = llvm::errs();
213103a06dd1SRichard Smith 
213203a06dd1SRichard Smith   auto DumpSLocEntry = [&](int ID, const SrcMgr::SLocEntry &Entry,
213303a06dd1SRichard Smith                            llvm::Optional<unsigned> NextStart) {
213403a06dd1SRichard Smith     out << "SLocEntry <FileID " << ID << "> " << (Entry.isFile() ? "file" : "expansion")
213503a06dd1SRichard Smith         << " <SourceLocation " << Entry.getOffset() << ":";
213603a06dd1SRichard Smith     if (NextStart)
213703a06dd1SRichard Smith       out << *NextStart << ">\n";
213803a06dd1SRichard Smith     else
213903a06dd1SRichard Smith       out << "???\?>\n";
214003a06dd1SRichard Smith     if (Entry.isFile()) {
214103a06dd1SRichard Smith       auto &FI = Entry.getFile();
214203a06dd1SRichard Smith       if (FI.NumCreatedFIDs)
214303a06dd1SRichard Smith         out << "  covers <FileID " << ID << ":" << int(ID + FI.NumCreatedFIDs)
214403a06dd1SRichard Smith             << ">\n";
214503a06dd1SRichard Smith       if (FI.getIncludeLoc().isValid())
214603a06dd1SRichard Smith         out << "  included from " << FI.getIncludeLoc().getOffset() << "\n";
214774a87834SDuncan P. N. Exon Smith       auto &CC = FI.getContentCache();
214874a87834SDuncan P. N. Exon Smith       out << "  for " << (CC.OrigEntry ? CC.OrigEntry->getName() : "<none>")
214903a06dd1SRichard Smith           << "\n";
215074a87834SDuncan P. N. Exon Smith       if (CC.BufferOverridden)
215103a06dd1SRichard Smith         out << "  contents overridden\n";
215274a87834SDuncan P. N. Exon Smith       if (CC.ContentsEntry != CC.OrigEntry) {
215303a06dd1SRichard Smith         out << "  contents from "
215474a87834SDuncan P. N. Exon Smith             << (CC.ContentsEntry ? CC.ContentsEntry->getName() : "<none>")
215503a06dd1SRichard Smith             << "\n";
215603a06dd1SRichard Smith       }
215703a06dd1SRichard Smith     } else {
215803a06dd1SRichard Smith       auto &EI = Entry.getExpansion();
215903a06dd1SRichard Smith       out << "  spelling from " << EI.getSpellingLoc().getOffset() << "\n";
216003a06dd1SRichard Smith       out << "  macro " << (EI.isMacroArgExpansion() ? "arg" : "body")
216103a06dd1SRichard Smith           << " range <" << EI.getExpansionLocStart().getOffset() << ":"
216203a06dd1SRichard Smith           << EI.getExpansionLocEnd().getOffset() << ">\n";
216303a06dd1SRichard Smith     }
216403a06dd1SRichard Smith   };
216503a06dd1SRichard Smith 
216603a06dd1SRichard Smith   // Dump local SLocEntries.
216703a06dd1SRichard Smith   for (unsigned ID = 0, NumIDs = LocalSLocEntryTable.size(); ID != NumIDs; ++ID) {
216803a06dd1SRichard Smith     DumpSLocEntry(ID, LocalSLocEntryTable[ID],
216903a06dd1SRichard Smith                   ID == NumIDs - 1 ? NextLocalOffset
217003a06dd1SRichard Smith                                    : LocalSLocEntryTable[ID + 1].getOffset());
217103a06dd1SRichard Smith   }
217203a06dd1SRichard Smith   // Dump loaded SLocEntries.
217303a06dd1SRichard Smith   llvm::Optional<unsigned> NextStart;
217403a06dd1SRichard Smith   for (unsigned Index = 0; Index != LoadedSLocEntryTable.size(); ++Index) {
217503a06dd1SRichard Smith     int ID = -(int)Index - 2;
217603a06dd1SRichard Smith     if (SLocEntryLoaded[Index]) {
217703a06dd1SRichard Smith       DumpSLocEntry(ID, LoadedSLocEntryTable[Index], NextStart);
217803a06dd1SRichard Smith       NextStart = LoadedSLocEntryTable[Index].getOffset();
217903a06dd1SRichard Smith     } else {
218003a06dd1SRichard Smith       NextStart = None;
218103a06dd1SRichard Smith     }
218203a06dd1SRichard Smith   }
218303a06dd1SRichard Smith }
218403a06dd1SRichard Smith 
2185918e0ca7SEugene Zelenko ExternalSLocEntrySource::~ExternalSLocEntrySource() = default;
21868d587900STed Kremenek 
21878d587900STed Kremenek /// Return the amount of memory used by memory buffers, breaking down
21888d587900STed Kremenek /// by heap-backed versus mmap'ed memory.
21898d587900STed Kremenek SourceManager::MemoryBufferSizes SourceManager::getMemoryBufferSizes() const {
21908d587900STed Kremenek   size_t malloc_bytes = 0;
21918d587900STed Kremenek   size_t mmap_bytes = 0;
21928d587900STed Kremenek 
21938d587900STed Kremenek   for (unsigned i = 0, e = MemBufferInfos.size(); i != e; ++i)
21948d587900STed Kremenek     if (size_t sized_mapped = MemBufferInfos[i]->getSizeBytesMapped())
21958d587900STed Kremenek       switch (MemBufferInfos[i]->getMemoryBufferKind()) {
21968d587900STed Kremenek         case llvm::MemoryBuffer::MemoryBuffer_MMap:
21978d587900STed Kremenek           mmap_bytes += sized_mapped;
21988d587900STed Kremenek           break;
21998d587900STed Kremenek         case llvm::MemoryBuffer::MemoryBuffer_Malloc:
22008d587900STed Kremenek           malloc_bytes += sized_mapped;
22018d587900STed Kremenek           break;
22028d587900STed Kremenek       }
22038d587900STed Kremenek 
22048d587900STed Kremenek   return MemoryBufferSizes(malloc_bytes, mmap_bytes);
22058d587900STed Kremenek }
22068d587900STed Kremenek 
2207120992adSTed Kremenek size_t SourceManager::getDataStructureSizes() const {
22086eec06d0SArgyrios Kyrtzidis   size_t size = llvm::capacity_in_bytes(MemBufferInfos)
220943e0c4a8STed Kremenek     + llvm::capacity_in_bytes(LocalSLocEntryTable)
221043e0c4a8STed Kremenek     + llvm::capacity_in_bytes(LoadedSLocEntryTable)
221143e0c4a8STed Kremenek     + llvm::capacity_in_bytes(SLocEntryLoaded)
22126eec06d0SArgyrios Kyrtzidis     + llvm::capacity_in_bytes(FileInfos);
22136eec06d0SArgyrios Kyrtzidis 
22146eec06d0SArgyrios Kyrtzidis   if (OverriddenFilesInfo)
22156eec06d0SArgyrios Kyrtzidis     size += llvm::capacity_in_bytes(OverriddenFilesInfo->OverriddenFiles);
22166eec06d0SArgyrios Kyrtzidis 
22176eec06d0SArgyrios Kyrtzidis   return size;
2218120992adSTed Kremenek }
22192e538089SEric Liu 
22202e538089SEric Liu SourceManagerForFile::SourceManagerForFile(StringRef FileName,
22212e538089SEric Liu                                            StringRef Content) {
22222e538089SEric Liu   // This is referenced by `FileMgr` and will be released by `FileMgr` when it
22232e538089SEric Liu   // is deleted.
2224fc51490bSJonas Devlieghere   IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem(
2225fc51490bSJonas Devlieghere       new llvm::vfs::InMemoryFileSystem);
22262e538089SEric Liu   InMemoryFileSystem->addFile(
22272e538089SEric Liu       FileName, 0,
22282e538089SEric Liu       llvm::MemoryBuffer::getMemBuffer(Content, FileName,
22292e538089SEric Liu                                        /*RequiresNullTerminator=*/false));
22302e538089SEric Liu   // This is passed to `SM` as reference, so the pointer has to be referenced
22312e538089SEric Liu   // in `Environment` so that `FileMgr` can out-live this function scope.
22322e538089SEric Liu   FileMgr =
22332b3d49b6SJonas Devlieghere       std::make_unique<FileManager>(FileSystemOptions(), InMemoryFileSystem);
22342e538089SEric Liu   // This is passed to `SM` as reference, so the pointer has to be referenced
22352e538089SEric Liu   // by `Environment` due to the same reason above.
22362b3d49b6SJonas Devlieghere   Diagnostics = std::make_unique<DiagnosticsEngine>(
22372e538089SEric Liu       IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs),
22382e538089SEric Liu       new DiagnosticOptions);
22392b3d49b6SJonas Devlieghere   SourceMgr = std::make_unique<SourceManager>(*Diagnostics, *FileMgr);
22408d323d15SHarlan Haskins   FileID ID = SourceMgr->createFileID(*FileMgr->getFile(FileName),
22412e538089SEric Liu                                       SourceLocation(), clang::SrcMgr::C_User);
22422e538089SEric Liu   assert(ID.isValid());
22432e538089SEric Liu   SourceMgr->setMainFileID(ID);
22442e538089SEric Liu }
2245