Skip to content
This repository was archived by the owner on Nov 1, 2021. It is now read-only.

Commit b1c8649

Browse files
committed
Currently we can only remap a file by creating a MemoryBuffer and replacing the file contents with it.
Allow remapping a file by specifying another filename whose contents should be loaded if the original file gets loaded. This allows to override files without having to create & load buffers in advance. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@127052 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 15727dd commit b1c8649

File tree

8 files changed

+159
-60
lines changed

8 files changed

+159
-60
lines changed

Diff for: include/clang/Basic/SourceManager.h

+30-6
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,16 @@ namespace SrcMgr {
6666
mutable llvm::PointerIntPair<const llvm::MemoryBuffer *, 2> Buffer;
6767

6868
public:
69-
/// Reference to the file entry. This reference does not own
70-
/// the FileEntry object. It is possible for this to be NULL if
69+
/// Reference to the file entry representing this ContentCache.
70+
/// This reference does not own the FileEntry object.
71+
/// It is possible for this to be NULL if
7172
/// the ContentCache encapsulates an imaginary text buffer.
72-
const FileEntry *Entry;
73+
const FileEntry *OrigEntry;
74+
75+
/// \brief References the file which the contents were actually loaded from.
76+
/// Can be different from 'Entry' if we overridden the contents of one file
77+
/// with the contents of another file.
78+
const FileEntry *ContentsEntry;
7379

7480
/// SourceLineCache - A bump pointer allocated array of offsets for each
7581
/// source line. This is lazily computed. This is owned by the
@@ -132,7 +138,12 @@ namespace SrcMgr {
132138
}
133139

134140
ContentCache(const FileEntry *Ent = 0)
135-
: Buffer(0, false), Entry(Ent), SourceLineCache(0), NumLines(0) {}
141+
: Buffer(0, false), OrigEntry(Ent), ContentsEntry(Ent),
142+
SourceLineCache(0), NumLines(0) {}
143+
144+
ContentCache(const FileEntry *Ent, const FileEntry *contentEnt)
145+
: Buffer(0, false), OrigEntry(Ent), ContentsEntry(contentEnt),
146+
SourceLineCache(0), NumLines(0) {}
136147

137148
~ContentCache();
138149

@@ -142,7 +153,8 @@ namespace SrcMgr {
142153
ContentCache(const ContentCache &RHS)
143154
: Buffer(0, false), SourceLineCache(0)
144155
{
145-
Entry = RHS.Entry;
156+
OrigEntry = RHS.OrigEntry;
157+
ContentsEntry = RHS.ContentsEntry;
146158

147159
assert (RHS.Buffer.getPointer() == 0 && RHS.SourceLineCache == 0
148160
&& "Passed ContentCache object cannot own a buffer.");
@@ -380,6 +392,9 @@ class SourceManager {
380392
/// non-null, FileEntry pointers.
381393
llvm::DenseMap<const FileEntry*, SrcMgr::ContentCache*> FileInfos;
382394

395+
/// \brief Files that have been overriden with the contents from another file.
396+
llvm::DenseMap<const FileEntry *, const FileEntry *> OverriddenFiles;
397+
383398
/// MemBufferInfos - Information about various memory buffers that we have
384399
/// read in. All FileEntry* within the stored ContentCache objects are NULL,
385400
/// as they do not refer to a file.
@@ -527,6 +542,15 @@ class SourceManager {
527542
const llvm::MemoryBuffer *Buffer,
528543
bool DoNotFree = false);
529544

545+
/// \brief Override the the given source file with another one.
546+
///
547+
/// \param SourceFile the source file which will be overriden.
548+
///
549+
/// \param NewFile the file whose contents will be used as the
550+
/// data instead of the contents of the given source file.
551+
void overrideFileContents(const FileEntry *SourceFile,
552+
const FileEntry *NewFile);
553+
530554
//===--------------------------------------------------------------------===//
531555
// FileID manipulation methods.
532556
//===--------------------------------------------------------------------===//
@@ -547,7 +571,7 @@ class SourceManager {
547571

548572
/// getFileEntryForID - Returns the FileEntry record for the provided FileID.
549573
const FileEntry *getFileEntryForID(FileID FID) const {
550-
return getSLocEntry(FID).getFile().getContentCache()->Entry;
574+
return getSLocEntry(FID).getFile().getContentCache()->OrigEntry;
551575
}
552576

553577
/// getBufferData - Return a StringRef to the source buffer data for the

Diff for: include/clang/Frontend/ASTUnit.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -535,9 +535,11 @@ class ASTUnit {
535535
/// that might still be used as a precompiled header or preamble.
536536
bool isCompleteTranslationUnit() const { return CompleteTranslationUnit; }
537537

538+
typedef llvm::PointerUnion<const char *, const llvm::MemoryBuffer *>
539+
FilenameOrMemBuf;
538540
/// \brief A mapping from a file name to the memory buffer that stores the
539541
/// remapped contents of that file.
540-
typedef std::pair<std::string, const llvm::MemoryBuffer *> RemappedFile;
542+
typedef std::pair<std::string, FilenameOrMemBuf> RemappedFile;
541543

542544
/// \brief Create a ASTUnit from an AST file.
543545
///

Diff for: lib/AST/ASTImporter.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -4156,12 +4156,12 @@ FileID ASTImporter::Import(FileID FromID) {
41564156
// Map the FileID for to the "to" source manager.
41574157
FileID ToID;
41584158
const SrcMgr::ContentCache *Cache = FromSLoc.getFile().getContentCache();
4159-
if (Cache->Entry) {
4159+
if (Cache->OrigEntry) {
41604160
// FIXME: We probably want to use getVirtualFile(), so we don't hit the
41614161
// disk again
41624162
// FIXME: We definitely want to re-use the existing MemoryBuffer, rather
41634163
// than mmap the files several times.
4164-
const FileEntry *Entry = ToFileManager.getFile(Cache->Entry->getName());
4164+
const FileEntry *Entry = ToFileManager.getFile(Cache->OrigEntry->getName());
41654165
ToID = ToSM.createFileID(Entry, ToIncludeLoc,
41664166
FromSLoc.getFile().getFileCharacteristic());
41674167
} else {

Diff for: lib/Basic/SourceManager.cpp

+38-18
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ unsigned ContentCache::getSizeBytesMapped() const {
5252
/// file is not lazily brought in from disk to satisfy this query.
5353
unsigned ContentCache::getSize() const {
5454
return Buffer.getPointer() ? (unsigned) Buffer.getPointer()->getBufferSize()
55-
: (unsigned) Entry->getSize();
55+
: (unsigned) ContentsEntry->getSize();
5656
}
5757

5858
void ContentCache::replaceBuffer(const llvm::MemoryBuffer *B,
@@ -71,15 +71,15 @@ const llvm::MemoryBuffer *ContentCache::getBuffer(Diagnostic &Diag,
7171
bool *Invalid) const {
7272
// Lazily create the Buffer for ContentCaches that wrap files. If we already
7373
// computed it, jsut return what we have.
74-
if (Buffer.getPointer() || Entry == 0) {
74+
if (Buffer.getPointer() || ContentsEntry == 0) {
7575
if (Invalid)
7676
*Invalid = isBufferInvalid();
7777

7878
return Buffer.getPointer();
7979
}
8080

8181
std::string ErrorStr;
82-
Buffer.setPointer(SM.getFileManager().getBufferForFile(Entry, &ErrorStr));
82+
Buffer.setPointer(SM.getFileManager().getBufferForFile(ContentsEntry, &ErrorStr));
8383

8484
// If we were unable to open the file, then we are in an inconsistent
8585
// situation where the content cache referenced a file which no longer
@@ -93,18 +93,18 @@ const llvm::MemoryBuffer *ContentCache::getBuffer(Diagnostic &Diag,
9393
// possible.
9494
if (!Buffer.getPointer()) {
9595
const llvm::StringRef FillStr("<<<MISSING SOURCE FILE>>>\n");
96-
Buffer.setPointer(MemoryBuffer::getNewMemBuffer(Entry->getSize(),
96+
Buffer.setPointer(MemoryBuffer::getNewMemBuffer(ContentsEntry->getSize(),
9797
"<invalid>"));
9898
char *Ptr = const_cast<char*>(Buffer.getPointer()->getBufferStart());
99-
for (unsigned i = 0, e = Entry->getSize(); i != e; ++i)
99+
for (unsigned i = 0, e = ContentsEntry->getSize(); i != e; ++i)
100100
Ptr[i] = FillStr[i % FillStr.size()];
101101

102102
if (Diag.isDiagnosticInFlight())
103103
Diag.SetDelayedDiagnostic(diag::err_cannot_open_file,
104-
Entry->getName(), ErrorStr);
104+
ContentsEntry->getName(), ErrorStr);
105105
else
106106
Diag.Report(Loc, diag::err_cannot_open_file)
107-
<< Entry->getName() << ErrorStr;
107+
<< ContentsEntry->getName() << ErrorStr;
108108

109109
Buffer.setInt(Buffer.getInt() | InvalidFlag);
110110

@@ -114,13 +114,13 @@ const llvm::MemoryBuffer *ContentCache::getBuffer(Diagnostic &Diag,
114114

115115
// Check that the file's size is the same as in the file entry (which may
116116
// have come from a stat cache).
117-
if (getRawBuffer()->getBufferSize() != (size_t)Entry->getSize()) {
117+
if (getRawBuffer()->getBufferSize() != (size_t)ContentsEntry->getSize()) {
118118
if (Diag.isDiagnosticInFlight())
119119
Diag.SetDelayedDiagnostic(diag::err_file_modified,
120-
Entry->getName());
120+
ContentsEntry->getName());
121121
else
122122
Diag.Report(Loc, diag::err_file_modified)
123-
<< Entry->getName();
123+
<< ContentsEntry->getName();
124124

125125
Buffer.setInt(Buffer.getInt() | InvalidFlag);
126126
if (Invalid) *Invalid = true;
@@ -147,7 +147,7 @@ const llvm::MemoryBuffer *ContentCache::getBuffer(Diagnostic &Diag,
147147

148148
if (BOM) {
149149
Diag.Report(Loc, diag::err_unsupported_bom)
150-
<< BOM << Entry->getName();
150+
<< BOM << ContentsEntry->getName();
151151
Buffer.setInt(Buffer.getInt() | InvalidFlag);
152152
}
153153

@@ -395,7 +395,16 @@ SourceManager::getOrCreateContentCache(const FileEntry *FileEnt) {
395395
unsigned EntryAlign = llvm::AlignOf<ContentCache>::Alignment;
396396
EntryAlign = std::max(8U, EntryAlign);
397397
Entry = ContentCacheAlloc.Allocate<ContentCache>(1, EntryAlign);
398-
new (Entry) ContentCache(FileEnt);
398+
399+
// If the file contents are overridden with contents from another file,
400+
// pass that file to ContentCache.
401+
llvm::DenseMap<const FileEntry *, const FileEntry *>::iterator
402+
overI = OverriddenFiles.find(FileEnt);
403+
if (overI == OverriddenFiles.end())
404+
new (Entry) ContentCache(FileEnt);
405+
else
406+
new (Entry) ContentCache(FileEnt, overI->second);
407+
399408
return Entry;
400409
}
401410

@@ -531,6 +540,17 @@ void SourceManager::overrideFileContents(const FileEntry *SourceFile,
531540
const_cast<SrcMgr::ContentCache *>(IR)->replaceBuffer(Buffer, DoNotFree);
532541
}
533542

543+
void SourceManager::overrideFileContents(const FileEntry *SourceFile,
544+
const FileEntry *NewFile) {
545+
assert(SourceFile->getSize() == NewFile->getSize() &&
546+
"Different sizes, use the FileManager to create a virtual file with "
547+
"the correct size");
548+
assert(FileInfos.count(SourceFile) == 0 &&
549+
"This function should be called at the initialization stage, before "
550+
"any parsing occurs.");
551+
OverriddenFiles[SourceFile] = NewFile;
552+
}
553+
534554
llvm::StringRef SourceManager::getBufferData(FileID FID, bool *Invalid) const {
535555
bool MyInvalid = false;
536556
const SLocEntry &SLoc = getSLocEntry(FID.ID);
@@ -1071,8 +1091,8 @@ PresumedLoc SourceManager::getPresumedLoc(SourceLocation Loc) const {
10711091
// before the MemBuffer as this will avoid unnecessarily paging in the
10721092
// MemBuffer.
10731093
const char *Filename;
1074-
if (C->Entry)
1075-
Filename = C->Entry->getName();
1094+
if (C->OrigEntry)
1095+
Filename = C->OrigEntry->getName();
10761096
else
10771097
Filename = C->getBuffer(Diag, *this)->getBufferIdentifier();
10781098
bool Invalid = false;
@@ -1158,12 +1178,12 @@ SourceLocation SourceManager::getLocation(const FileEntry *SourceFile,
11581178
= MainSLoc.getFile().getContentCache();
11591179
if (!MainContentCache) {
11601180
// Can't do anything
1161-
} else if (MainContentCache->Entry == SourceFile) {
1181+
} else if (MainContentCache->OrigEntry == SourceFile) {
11621182
FirstFID = MainFileID;
11631183
} else {
11641184
// Fall back: check whether we have the same base name and inode
11651185
// as the main file.
1166-
const FileEntry *MainFile = MainContentCache->Entry;
1186+
const FileEntry *MainFile = MainContentCache->OrigEntry;
11671187
SourceFileName = llvm::sys::path::filename(SourceFile->getName());
11681188
if (*SourceFileName == llvm::sys::path::filename(MainFile->getName())) {
11691189
SourceFileInode = getActualFileInode(SourceFile);
@@ -1188,7 +1208,7 @@ SourceLocation SourceManager::getLocation(const FileEntry *SourceFile,
11881208
const SLocEntry &SLoc = getSLocEntry(I);
11891209
if (SLoc.isFile() &&
11901210
SLoc.getFile().getContentCache() &&
1191-
SLoc.getFile().getContentCache()->Entry == SourceFile) {
1211+
SLoc.getFile().getContentCache()->OrigEntry == SourceFile) {
11921212
FirstFID = FileID::get(I);
11931213
break;
11941214
}
@@ -1208,7 +1228,7 @@ SourceLocation SourceManager::getLocation(const FileEntry *SourceFile,
12081228
if (SLoc.isFile()) {
12091229
const ContentCache *FileContentCache
12101230
= SLoc.getFile().getContentCache();
1211-
const FileEntry *Entry =FileContentCache? FileContentCache->Entry : 0;
1231+
const FileEntry *Entry =FileContentCache? FileContentCache->OrigEntry : 0;
12121232
if (Entry &&
12131233
*SourceFileName == llvm::sys::path::filename(Entry->getName())) {
12141234
if (llvm::Optional<ino_t> EntryInode = getActualFileInode(Entry)) {

Diff for: lib/Frontend/ASTUnit.cpp

+75-25
Original file line numberDiff line numberDiff line change
@@ -508,22 +508,50 @@ ASTUnit *ASTUnit::LoadFromASTFile(const std::string &Filename,
508508
AST->HeaderInfo.reset(new HeaderSearch(AST->getFileManager()));
509509

510510
for (unsigned I = 0; I != NumRemappedFiles; ++I) {
511-
// Create the file entry for the file that we're mapping from.
512-
const FileEntry *FromFile
513-
= AST->getFileManager().getVirtualFile(RemappedFiles[I].first,
514-
RemappedFiles[I].second->getBufferSize(),
515-
0);
516-
if (!FromFile) {
517-
AST->getDiagnostics().Report(diag::err_fe_remap_missing_from_file)
518-
<< RemappedFiles[I].first;
519-
delete RemappedFiles[I].second;
520-
continue;
511+
FilenameOrMemBuf fileOrBuf = RemappedFiles[I].second;
512+
if (const llvm::MemoryBuffer *
513+
memBuf = fileOrBuf.dyn_cast<const llvm::MemoryBuffer *>()) {
514+
// Create the file entry for the file that we're mapping from.
515+
const FileEntry *FromFile
516+
= AST->getFileManager().getVirtualFile(RemappedFiles[I].first,
517+
memBuf->getBufferSize(),
518+
0);
519+
if (!FromFile) {
520+
AST->getDiagnostics().Report(diag::err_fe_remap_missing_from_file)
521+
<< RemappedFiles[I].first;
522+
delete memBuf;
523+
continue;
524+
}
525+
526+
// Override the contents of the "from" file with the contents of
527+
// the "to" file.
528+
AST->getSourceManager().overrideFileContents(FromFile, memBuf);
529+
530+
} else {
531+
const char *fname = fileOrBuf.get<const char *>();
532+
const FileEntry *ToFile = AST->FileMgr->getFile(fname);
533+
if (!ToFile) {
534+
AST->getDiagnostics().Report(diag::err_fe_remap_missing_to_file)
535+
<< RemappedFiles[I].first << fname;
536+
continue;
537+
}
538+
539+
// Create the file entry for the file that we're mapping from.
540+
const FileEntry *FromFile
541+
= AST->getFileManager().getVirtualFile(RemappedFiles[I].first,
542+
ToFile->getSize(),
543+
0);
544+
if (!FromFile) {
545+
AST->getDiagnostics().Report(diag::err_fe_remap_missing_from_file)
546+
<< RemappedFiles[I].first;
547+
delete memBuf;
548+
continue;
549+
}
550+
551+
// Override the contents of the "from" file with the contents of
552+
// the "to" file.
553+
AST->getSourceManager().overrideFileContents(FromFile, ToFile);
521554
}
522-
523-
// Override the contents of the "from" file with the contents of
524-
// the "to" file.
525-
AST->getSourceManager().overrideFileContents(FromFile,
526-
RemappedFiles[I].second);
527555
}
528556

529557
// Gather Info for preprocessor construction later on.
@@ -1391,7 +1419,7 @@ llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble(
13911419
FEnd = SourceMgr.fileinfo_end();
13921420
F != FEnd;
13931421
++F) {
1394-
const FileEntry *File = F->second->Entry;
1422+
const FileEntry *File = F->second->OrigEntry;
13951423
if (!File || F->second->getRawBuffer() == MainFileBuffer)
13961424
continue;
13971425

@@ -1612,9 +1640,16 @@ ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin,
16121640
}
16131641

16141642
// Override any files that need remapping
1615-
for (unsigned I = 0; I != NumRemappedFiles; ++I)
1616-
CI->getPreprocessorOpts().addRemappedFile(RemappedFiles[I].first,
1617-
RemappedFiles[I].second);
1643+
for (unsigned I = 0; I != NumRemappedFiles; ++I) {
1644+
FilenameOrMemBuf fileOrBuf = RemappedFiles[I].second;
1645+
if (const llvm::MemoryBuffer *
1646+
memBuf = fileOrBuf.dyn_cast<const llvm::MemoryBuffer *>()) {
1647+
CI->getPreprocessorOpts().addRemappedFile(RemappedFiles[I].first, memBuf);
1648+
} else {
1649+
const char *fname = fileOrBuf.get<const char *>();
1650+
CI->getPreprocessorOpts().addRemappedFile(RemappedFiles[I].first, fname);
1651+
}
1652+
}
16181653

16191654
// Override the resources path.
16201655
CI->getHeaderSearchOpts().ResourceDir = ResourceFilesPath;
@@ -1665,9 +1700,18 @@ bool ASTUnit::Reparse(RemappedFile *RemappedFiles, unsigned NumRemappedFiles) {
16651700
delete R->second;
16661701
}
16671702
Invocation->getPreprocessorOpts().clearRemappedFiles();
1668-
for (unsigned I = 0; I != NumRemappedFiles; ++I)
1669-
Invocation->getPreprocessorOpts().addRemappedFile(RemappedFiles[I].first,
1670-
RemappedFiles[I].second);
1703+
for (unsigned I = 0; I != NumRemappedFiles; ++I) {
1704+
FilenameOrMemBuf fileOrBuf = RemappedFiles[I].second;
1705+
if (const llvm::MemoryBuffer *
1706+
memBuf = fileOrBuf.dyn_cast<const llvm::MemoryBuffer *>()) {
1707+
Invocation->getPreprocessorOpts().addRemappedFile(RemappedFiles[I].first,
1708+
memBuf);
1709+
} else {
1710+
const char *fname = fileOrBuf.get<const char *>();
1711+
Invocation->getPreprocessorOpts().addRemappedFile(RemappedFiles[I].first,
1712+
fname);
1713+
}
1714+
}
16711715

16721716
// If we have a preamble file lying around, or if we might try to
16731717
// build a precompiled preamble, do so now.
@@ -2000,9 +2044,15 @@ void ASTUnit::CodeComplete(llvm::StringRef File, unsigned Line, unsigned Column,
20002044
PreprocessorOpts.clearRemappedFiles();
20012045
PreprocessorOpts.RetainRemappedFileBuffers = true;
20022046
for (unsigned I = 0; I != NumRemappedFiles; ++I) {
2003-
PreprocessorOpts.addRemappedFile(RemappedFiles[I].first,
2004-
RemappedFiles[I].second);
2005-
OwnedBuffers.push_back(RemappedFiles[I].second);
2047+
FilenameOrMemBuf fileOrBuf = RemappedFiles[I].second;
2048+
if (const llvm::MemoryBuffer *
2049+
memBuf = fileOrBuf.dyn_cast<const llvm::MemoryBuffer *>()) {
2050+
PreprocessorOpts.addRemappedFile(RemappedFiles[I].first, memBuf);
2051+
OwnedBuffers.push_back(memBuf);
2052+
} else {
2053+
const char *fname = fileOrBuf.get<const char *>();
2054+
PreprocessorOpts.addRemappedFile(RemappedFiles[I].first, fname);
2055+
}
20062056
}
20072057

20082058
// Use the code completion consumer we were given, but adding any cached

0 commit comments

Comments
 (0)