summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2015-11-26 02:04:16 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2015-11-26 02:04:16 +0000
commit59763b390aea7f636dc3da3c06035e6fba9cfe09 (patch)
tree4928ef6f6a5f3b43ae42a2a1e9970b8626a9a200
parentd788d6ae0cc9a25ae1b3108b29637e9a129d4b80 (diff)
[modules] Refactor handling of -fmodules-embed-*. Track this properly rather
than reusing the "overridden buffer" mechanism. This will allow us to make embedded files and overridden files behave differently in future. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@254121 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Basic/SourceManager.h29
-rw-r--r--include/clang/Serialization/ASTReader.h1
-rw-r--r--lib/Basic/FileManager.cpp2
-rw-r--r--lib/Basic/SourceManager.cpp8
-rw-r--r--lib/Frontend/FrontendActions.cpp21
-rw-r--r--lib/Serialization/ASTReader.cpp39
-rw-r--r--lib/Serialization/ASTWriter.cpp13
7 files changed, 61 insertions, 52 deletions
diff --git a/include/clang/Basic/SourceManager.h b/include/clang/Basic/SourceManager.h
index 5006b00929..99392a0982 100644
--- a/include/clang/Basic/SourceManager.h
+++ b/include/clang/Basic/SourceManager.h
@@ -122,7 +122,7 @@ namespace SrcMgr {
/// \brief The number of lines in this ContentCache.
///
/// This is only valid if SourceLineCache is non-null.
- unsigned NumLines : 31;
+ unsigned NumLines;
/// \brief Indicates whether the buffer itself was provided to override
/// the actual file contents.
@@ -135,12 +135,17 @@ namespace SrcMgr {
/// file considered as a system one.
unsigned IsSystemFile : 1;
+ /// \brief True if this file may be transient, that is, if it might not
+ /// exist at some later point in time when this content entry is used,
+ /// after serialization and deserialization.
+ unsigned IsTransient : 1;
+
ContentCache(const FileEntry *Ent = nullptr) : ContentCache(Ent, Ent) {}
ContentCache(const FileEntry *Ent, const FileEntry *contentEnt)
: Buffer(nullptr, false), OrigEntry(Ent), ContentsEntry(contentEnt),
SourceLineCache(nullptr), NumLines(0), BufferOverridden(false),
- IsSystemFile(false) {}
+ IsSystemFile(false), IsTransient(false) {}
~ContentCache();
@@ -149,7 +154,7 @@ namespace SrcMgr {
/// is not transferred, so this is a logical error.
ContentCache(const ContentCache &RHS)
: Buffer(nullptr, false), SourceLineCache(nullptr),
- BufferOverridden(false), IsSystemFile(false) {
+ BufferOverridden(false), IsSystemFile(false), IsTransient(false) {
OrigEntry = RHS.OrigEntry;
ContentsEntry = RHS.ContentsEntry;
@@ -862,17 +867,13 @@ public:
/// This should be called before parsing has begun.
void disableFileContentsOverride(const FileEntry *File);
- /// \brief Request that the contents of the given source file are written
- /// to a created module file if they are used in this compilation. This
- /// removes the requirement that the file still exist when the module is used
- /// (but does not make the file visible to header search and the like when
- /// the module is used).
- void embedFileContentsInModule(const FileEntry *SourceFile);
-
- /// \brief Request that all files that are read during this compilation be
- /// written to any created module file.
- void setEmbedAllFileContentsInModule(bool Embed) {
- FilesAreTransient = Embed;
+ /// \brief Specify that a file is transient.
+ void setFileIsTransient(const FileEntry *SourceFile);
+
+ /// \brief Specify that all files that are read during this compilation are
+ /// transient.
+ void setAllFilesAreTransient(bool Transient) {
+ FilesAreTransient = Transient;
}
//===--------------------------------------------------------------------===//
diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h
index eb613802e3..588a6a978c 100644
--- a/include/clang/Serialization/ASTReader.h
+++ b/include/clang/Serialization/ASTReader.h
@@ -1058,6 +1058,7 @@ private:
off_t StoredSize;
time_t StoredTime;
bool Overridden;
+ bool Transient;
};
/// \brief Reads the stored information about an input file.
diff --git a/lib/Basic/FileManager.cpp b/lib/Basic/FileManager.cpp
index 8a523d26de..137ff6e658 100644
--- a/lib/Basic/FileManager.cpp
+++ b/lib/Basic/FileManager.cpp
@@ -137,7 +137,7 @@ void FileManager::addAncestorsAsVirtualDirs(StringRef Path) {
// at the same time. Therefore, if DirName is already in the cache,
// we don't need to recurse as its ancestors must also already be in
// the cache.
- if (NamedDirEnt.second)
+ if (NamedDirEnt.second && NamedDirEnt.second != NON_EXISTENT_DIR)
return;
// Add the virtual directory to the cache.
diff --git a/lib/Basic/SourceManager.cpp b/lib/Basic/SourceManager.cpp
index 7abcba1fb7..80a003fc93 100644
--- a/lib/Basic/SourceManager.cpp
+++ b/lib/Basic/SourceManager.cpp
@@ -439,7 +439,7 @@ SourceManager::getOrCreateContentCache(const FileEntry *FileEnt,
}
Entry->IsSystemFile = isSystemFile;
- Entry->BufferOverridden = FilesAreTransient;
+ Entry->IsTransient = FilesAreTransient;
return Entry;
}
@@ -674,11 +674,9 @@ void SourceManager::disableFileContentsOverride(const FileEntry *File) {
OverriddenFilesInfo->OverriddenFilesWithBuffer.erase(File);
}
-void SourceManager::embedFileContentsInModule(const FileEntry *File) {
- // We model an embedded file as a file whose buffer has been overridden
- // by its contents as they are now.
+void SourceManager::setFileIsTransient(const FileEntry *File) {
const SrcMgr::ContentCache *CC = getOrCreateContentCache(File);
- const_cast<SrcMgr::ContentCache *>(CC)->BufferOverridden = true;
+ const_cast<SrcMgr::ContentCache *>(CC)->IsTransient = true;
}
StringRef SourceManager::getBufferData(FileID FID, bool *Invalid) const {
diff --git a/lib/Frontend/FrontendActions.cpp b/lib/Frontend/FrontendActions.cpp
index 4edb958441..d6c88d20fc 100644
--- a/lib/Frontend/FrontendActions.cpp
+++ b/lib/Frontend/FrontendActions.cpp
@@ -277,6 +277,17 @@ bool GenerateModuleAction::BeginSourceFileAction(CompilerInstance &CI,
return false;
}
+ // Set up embedding for any specified files. Do this before we load any
+ // source files, including the primary module map for the compilation.
+ for (const auto &F : CI.getFrontendOpts().ModulesEmbedFiles) {
+ if (const auto *FE = CI.getFileManager().getFile(F, /*openFile*/true))
+ CI.getSourceManager().setFileIsTransient(FE);
+ else
+ CI.getDiagnostics().Report(diag::err_modules_embed_file_not_found) << F;
+ }
+ if (CI.getFrontendOpts().ModulesEmbedAllFiles)
+ CI.getSourceManager().setAllFilesAreTransient(true);
+
// Parse the module map file.
HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo();
if (HS.loadModuleMapFile(ModuleMap, IsSystem))
@@ -292,16 +303,6 @@ bool GenerateModuleAction::BeginSourceFileAction(CompilerInstance &CI,
return false;
}
- // Set up embedding for any specified files.
- for (const auto &F : CI.getFrontendOpts().ModulesEmbedFiles) {
- if (const auto *FE = CI.getFileManager().getFile(F, /*openFile*/true))
- CI.getSourceManager().embedFileContentsInModule(FE);
- else
- CI.getDiagnostics().Report(diag::err_modules_embed_file_not_found) << F;
- }
- if (CI.getFrontendOpts().ModulesEmbedAllFiles)
- CI.getSourceManager().setEmbedAllFileContentsInModule(true);
-
// If we're being run from the command-line, the module build stack will not
// have been filled in yet, so complete it now in order to allow us to detect
// module cycles.
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp
index fa84b94b08..2defd38e27 100644
--- a/lib/Serialization/ASTReader.cpp
+++ b/lib/Serialization/ASTReader.cpp
@@ -1259,7 +1259,8 @@ bool ASTReader::ReadSLocEntry(int ID) {
= SourceMgr.getOrCreateContentCache(File,
/*isSystemFile=*/FileCharacter != SrcMgr::C_User);
if (OverriddenBuffer && !ContentCache->BufferOverridden &&
- ContentCache->ContentsEntry == ContentCache->OrigEntry) {
+ ContentCache->ContentsEntry == ContentCache->OrigEntry &&
+ !ContentCache->getRawBuffer()) {
unsigned Code = SLocEntryCursor.ReadCode();
Record.clear();
unsigned RecCode = SLocEntryCursor.readRecord(Code, Record, &Blob);
@@ -1890,19 +1891,14 @@ ASTReader::readInputFileInfo(ModuleFile &F, unsigned ID) {
"invalid record type for input file");
(void)Result;
- std::string Filename;
- off_t StoredSize;
- time_t StoredTime;
- bool Overridden;
-
assert(Record[0] == ID && "Bogus stored ID or offset");
- StoredSize = static_cast<off_t>(Record[1]);
- StoredTime = static_cast<time_t>(Record[2]);
- Overridden = static_cast<bool>(Record[3]);
- Filename = Blob;
- ResolveImportedPath(F, Filename);
-
- InputFileInfo R = { std::move(Filename), StoredSize, StoredTime, Overridden };
+ InputFileInfo R;
+ R.StoredSize = static_cast<off_t>(Record[1]);
+ R.StoredTime = static_cast<time_t>(Record[2]);
+ R.Overridden = static_cast<bool>(Record[3]);
+ R.Transient = static_cast<bool>(Record[4]);
+ R.Filename = Blob;
+ ResolveImportedPath(F, R.Filename);
return R;
}
@@ -1927,11 +1923,10 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) {
off_t StoredSize = FI.StoredSize;
time_t StoredTime = FI.StoredTime;
bool Overridden = FI.Overridden;
+ bool Transient = FI.Transient;
StringRef Filename = FI.Filename;
- const FileEntry *File
- = Overridden? FileMgr.getVirtualFile(Filename, StoredSize, StoredTime)
- : FileMgr.getFile(Filename, /*OpenFile=*/false);
+ const FileEntry *File = FileMgr.getFile(Filename, /*OpenFile=*/false);
// If we didn't find the file, resolve it relative to the
// original directory from which this AST file was created.
@@ -1946,9 +1941,8 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) {
// For an overridden file, create a virtual file with the stored
// size/timestamp.
- if (Overridden && File == nullptr) {
+ if ((Overridden || Transient) && File == nullptr)
File = FileMgr.getVirtualFile(Filename, StoredSize, StoredTime);
- }
if (File == nullptr) {
if (Complain) {
@@ -1974,6 +1968,11 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) {
Error(diag::err_fe_pch_file_overridden, Filename);
// After emitting the diagnostic, recover by disabling the override so
// that the original file will be used.
+ //
+ // FIXME: This recovery is just as broken as the original state; there may
+ // be another precompiled module that's using the overridden contents, or
+ // we might be half way through parsing it. Instead, we should treat the
+ // overridden contents as belonging to a separate FileEntry.
SM.disableFileContentsOverride(File);
// The FileEntry is a virtual file entry with the size of the contents
// that would override the original contents. Set it to the original's
@@ -2024,8 +2023,10 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) {
IsOutOfDate = true;
}
+ // FIXME: If the file is overridden and we've already opened it,
+ // issue an error (or split it into a separate FileEntry).
- InputFile IF = InputFile(File, Overridden, IsOutOfDate);
+ InputFile IF = InputFile(File, Overridden || Transient, IsOutOfDate);
// Note that we've loaded this input file.
F.InputFilesLoaded[ID-1] = IF;
diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp
index 0b257a4a1b..e6eb9be25e 100644
--- a/lib/Serialization/ASTWriter.cpp
+++ b/lib/Serialization/ASTWriter.cpp
@@ -1485,6 +1485,7 @@ namespace {
struct InputFileEntry {
const FileEntry *File;
bool IsSystemFile;
+ bool IsTransient;
bool BufferOverridden;
};
}
@@ -1502,6 +1503,7 @@ void ASTWriter::WriteInputFiles(SourceManager &SourceMgr,
IFAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 12)); // Size
IFAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 32)); // Modification time
IFAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Overridden
+ IFAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Transient
IFAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name
unsigned IFAbbrevCode = Stream.EmitAbbrev(IFAbbrev);
@@ -1523,6 +1525,7 @@ void ASTWriter::WriteInputFiles(SourceManager &SourceMgr,
InputFileEntry Entry;
Entry.File = Cache->OrigEntry;
Entry.IsSystemFile = Cache->IsSystemFile;
+ Entry.IsTransient = Cache->IsTransient;
Entry.BufferOverridden = Cache->BufferOverridden;
if (Cache->IsSystemFile)
SortedFiles.push_back(Entry);
@@ -1552,8 +1555,12 @@ void ASTWriter::WriteInputFiles(SourceManager &SourceMgr,
// Emit size/modification time for this file.
// And whether this file was overridden.
RecordData::value_type Record[] = {
- INPUT_FILE, InputFileOffsets.size(), (uint64_t)Entry.File->getSize(),
- (uint64_t)getTimestampForOutput(Entry.File), Entry.BufferOverridden};
+ INPUT_FILE,
+ InputFileOffsets.size(),
+ (uint64_t)Entry.File->getSize(),
+ (uint64_t)getTimestampForOutput(Entry.File),
+ Entry.BufferOverridden,
+ Entry.IsTransient};
EmitRecordWithPath(IFAbbrevCode, Record, Entry.File->getName());
}
@@ -1902,7 +1909,7 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr,
Stream.EmitRecordWithAbbrev(SLocFileAbbrv, Record);
- if (Content->BufferOverridden) {
+ if (Content->BufferOverridden || Content->IsTransient) {
RecordData::value_type Record[] = {SM_SLOC_BUFFER_BLOB};
const llvm::MemoryBuffer *Buffer
= Content->getBuffer(PP.getDiagnostics(), PP.getSourceManager());