summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2015-03-18 01:42:29 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2015-03-18 01:42:29 +0000
commit7f330cdb31a4221be501d5d969f2e8a62f457e14 (patch)
tree2786520a130f64d0284b5ba00c2478ab7310aafd
parent59aca1970828616abecb5691e6f956a94b7b494b (diff)
downloadbcm5719-llvm-7f330cdb31a4221be501d5d969f2e8a62f457e14.tar.gz
bcm5719-llvm-7f330cdb31a4221be501d5d969f2e8a62f457e14.zip
Make module files passed to a module build via -fmodule-file= available to
consumers of that module. Previously, such a file would only be available if the module happened to actually import something from that module. llvm-svn: 232583
-rw-r--r--clang/include/clang/Serialization/ASTBitCodes.h4
-rw-r--r--clang/include/clang/Serialization/ModuleManager.h21
-rw-r--r--clang/lib/Frontend/CompilerInstance.cpp13
-rw-r--r--clang/lib/Serialization/ASTReader.cpp22
-rw-r--r--clang/lib/Serialization/ASTWriter.cpp29
-rw-r--r--clang/lib/Serialization/ModuleManager.cpp11
-rw-r--r--clang/test/Modules/Inputs/explicit-build/d.h0
-rw-r--r--clang/test/Modules/Inputs/explicit-build/module.modulemap1
-rw-r--r--clang/test/Modules/explicit-build.cpp13
9 files changed, 104 insertions, 10 deletions
diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h
index 1e26927fbff..3668d4c6320 100644
--- a/clang/include/clang/Serialization/ASTBitCodes.h
+++ b/clang/include/clang/Serialization/ASTBitCodes.h
@@ -295,6 +295,10 @@ namespace clang {
/// \brief Record code for the module build directory.
MODULE_DIRECTORY = 16,
+
+ /// \brief Record code for the list of other AST files made available by
+ /// this AST file but not actually used by it.
+ KNOWN_MODULE_FILES = 17,
};
/// \brief Record types that occur within the input-files block
diff --git a/clang/include/clang/Serialization/ModuleManager.h b/clang/include/clang/Serialization/ModuleManager.h
index 3d10fad0a1b..d20c7e2fbbb 100644
--- a/clang/include/clang/Serialization/ModuleManager.h
+++ b/clang/include/clang/Serialization/ModuleManager.h
@@ -35,7 +35,13 @@ class ModuleManager {
/// \brief All loaded modules, indexed by name.
llvm::DenseMap<const FileEntry *, ModuleFile *> Modules;
-
+
+ typedef llvm::SetVector<const FileEntry *> AdditionalKnownModuleFileSet;
+
+ /// \brief Additional module files that are known but not loaded. Tracked
+ /// here so that we can re-export them if necessary.
+ AdditionalKnownModuleFileSet AdditionalKnownModuleFiles;
+
/// \brief FileManager that handles translating between filenames and
/// FileEntry *.
FileManager &FileMgr;
@@ -219,6 +225,19 @@ public:
/// has been "accepted", and will not (can not) be unloaded.
void moduleFileAccepted(ModuleFile *MF);
+ /// \brief Notification from the frontend that the given module file is
+ /// part of this compilation (even if not imported) and, if this compilation
+ /// is exported, should be made available to importers of it.
+ bool addKnownModuleFile(StringRef FileName);
+
+ /// \brief Get a list of additional module files that are not currently
+ /// loaded but are considered to be part of the current compilation.
+ llvm::iterator_range<AdditionalKnownModuleFileSet::const_iterator>
+ getAdditionalKnownModuleFiles() {
+ return llvm::make_range(AdditionalKnownModuleFiles.begin(),
+ AdditionalKnownModuleFiles.end());
+ }
+
/// \brief Visit each of the modules.
///
/// This routine visits each of the modules, starting with the
diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp
index 2dac20bcb0f..ee8c4032caf 100644
--- a/clang/lib/Frontend/CompilerInstance.cpp
+++ b/clang/lib/Frontend/CompilerInstance.cpp
@@ -1331,6 +1331,19 @@ bool CompilerInstance::loadModuleFile(StringRef FileName) {
}
} RMN(*this);
+ // If we don't already have an ASTReader, create one now.
+ if (!ModuleManager)
+ createModuleManager();
+
+ // Tell the module manager about this module file.
+ if (getModuleManager()->getModuleManager().addKnownModuleFile(FileName)) {
+ getDiagnostics().Report(SourceLocation(), diag::err_module_file_not_found)
+ << FileName;
+ return false;
+ }
+
+ // Build our mapping of module names to module files from this file
+ // and its imports.
RMN.visitImport(FileName);
if (RMN.Failed)
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index ec14eec2ab3..f4b4c4b9879 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -2462,6 +2462,9 @@ ASTReader::ReadControlBlock(ModuleFile &F,
break;
}
+ case KNOWN_MODULE_FILES:
+ break;
+
case LANGUAGE_OPTIONS: {
bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch) == 0;
// FIXME: The &F == *ModuleMgr.begin() check is wrong for modules.
@@ -4248,6 +4251,8 @@ bool ASTReader::readASTFileControlBlock(StringRef Filename,
FileManager &FileMgr,
ASTReaderListener &Listener) {
// Open the AST file.
+ // FIXME: This allows use of the VFS; we do not allow use of the
+ // VFS when actually loading a module.
auto Buffer = FileMgr.getBufferForFile(Filename);
if (!Buffer) {
return true;
@@ -4418,6 +4423,20 @@ bool ASTReader::readASTFileControlBlock(StringRef Filename,
break;
}
+ case KNOWN_MODULE_FILES: {
+ // Known-but-not-technically-used module files are treated as imports.
+ if (!NeedsImports)
+ break;
+
+ unsigned Idx = 0, N = Record.size();
+ while (Idx < N) {
+ std::string Filename = ReadString(Record, Idx);
+ ResolveImportedPath(Filename, ModuleDir);
+ Listener.visitImport(Filename);
+ }
+ break;
+ }
+
default:
// No other validation to perform.
break;
@@ -6842,6 +6861,9 @@ void ASTReader::StartTranslationUnit(ASTConsumer *Consumer) {
EagerlyDeserializedDecls.clear();
PassInterestingDeclsToConsumer();
+
+ if (DeserializationListener)
+ DeserializationListener->ReaderInitialized(this);
}
void ASTReader::PrintStats() {
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index 5bf1dcdd645..10a52f81abc 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -867,6 +867,7 @@ void ASTWriter::WriteBlockInfoBlock() {
RECORD(MODULE_NAME);
RECORD(MODULE_MAP_FILE);
RECORD(IMPORTS);
+ RECORD(KNOWN_MODULE_FILES);
RECORD(LANGUAGE_OPTIONS);
RECORD(TARGET_OPTIONS);
RECORD(ORIGINAL_FILE);
@@ -1222,20 +1223,28 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context,
serialization::ModuleManager &Mgr = Chain->getModuleManager();
Record.clear();
- for (ModuleManager::ModuleIterator M = Mgr.begin(), MEnd = Mgr.end();
- M != MEnd; ++M) {
+ for (auto *M : Mgr) {
// Skip modules that weren't directly imported.
- if (!(*M)->isDirectlyImported())
+ if (!M->isDirectlyImported())
continue;
- Record.push_back((unsigned)(*M)->Kind); // FIXME: Stable encoding
- AddSourceLocation((*M)->ImportLoc, Record);
- Record.push_back((*M)->File->getSize());
- Record.push_back((*M)->File->getModificationTime());
- Record.push_back((*M)->Signature);
- AddPath((*M)->FileName, Record);
+ Record.push_back((unsigned)M->Kind); // FIXME: Stable encoding
+ AddSourceLocation(M->ImportLoc, Record);
+ Record.push_back(M->File->getSize());
+ Record.push_back(M->File->getModificationTime());
+ Record.push_back(M->Signature);
+ AddPath(M->FileName, Record);
}
Stream.EmitRecord(IMPORTS, Record);
+
+ // Also emit a list of known module files that were not imported,
+ // but are made available by this module.
+ // FIXME: Should we also include a signature here?
+ Record.clear();
+ for (auto *E : Mgr.getAdditionalKnownModuleFiles())
+ AddPath(E->getName(), Record);
+ if (!Record.empty())
+ Stream.EmitRecord(KNOWN_MODULE_FILES, Record);
}
// Language options.
@@ -5655,6 +5664,8 @@ void ASTWriter::ReaderInitialized(ASTReader *Reader) {
Chain = Reader;
+ // Note, this will get called multiple times, once one the reader starts up
+ // and again each time it's done reading a PCH or module.
FirstDeclID = NUM_PREDEF_DECL_IDS + Chain->getTotalNumDecls();
FirstTypeID = NUM_PREDEF_TYPE_IDS + Chain->getTotalNumTypes();
FirstIdentID = NUM_PREDEF_IDENT_IDS + Chain->getTotalNumIdentifiers();
diff --git a/clang/lib/Serialization/ModuleManager.cpp b/clang/lib/Serialization/ModuleManager.cpp
index ac98ca0b872..b073984119f 100644
--- a/clang/lib/Serialization/ModuleManager.cpp
+++ b/clang/lib/Serialization/ModuleManager.cpp
@@ -227,6 +227,15 @@ ModuleManager::addInMemoryBuffer(StringRef FileName,
InMemoryBuffers[Entry] = std::move(Buffer);
}
+bool ModuleManager::addKnownModuleFile(StringRef FileName) {
+ const FileEntry *File;
+ if (lookupModuleFile(FileName, 0, 0, File))
+ return true;
+ if (!Modules.count(File))
+ AdditionalKnownModuleFiles.insert(File);
+ return false;
+}
+
ModuleManager::VisitState *ModuleManager::allocateVisitState() {
// Fast path: if we have a cached state, use it.
if (FirstVisitState) {
@@ -263,6 +272,8 @@ void ModuleManager::setGlobalIndex(GlobalModuleIndex *Index) {
}
void ModuleManager::moduleFileAccepted(ModuleFile *MF) {
+ AdditionalKnownModuleFiles.remove(MF->File);
+
if (!GlobalIndex || GlobalIndex->loadedModuleFile(MF))
return;
diff --git a/clang/test/Modules/Inputs/explicit-build/d.h b/clang/test/Modules/Inputs/explicit-build/d.h
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/clang/test/Modules/Inputs/explicit-build/d.h
diff --git a/clang/test/Modules/Inputs/explicit-build/module.modulemap b/clang/test/Modules/Inputs/explicit-build/module.modulemap
index bd6ea830c2d..992eed68358 100644
--- a/clang/test/Modules/Inputs/explicit-build/module.modulemap
+++ b/clang/test/Modules/Inputs/explicit-build/module.modulemap
@@ -1,3 +1,4 @@
module a { header "a.h" }
module b { header "b.h" export * }
module c { header "c.h" export * }
+module d { header "d.h" }
diff --git a/clang/test/Modules/explicit-build.cpp b/clang/test/Modules/explicit-build.cpp
index ff98f92b1f5..6fe9f7ee46a 100644
--- a/clang/test/Modules/explicit-build.cpp
+++ b/clang/test/Modules/explicit-build.cpp
@@ -64,6 +64,19 @@
// RUN: -fmodule-file=%t/c.pcm \
// RUN: -verify %s -DHAVE_A -DHAVE_B -DHAVE_C
+// -------------------------------
+// Check that -fmodule-file= in a module build makes the file transitively
+// available even if it's not used.
+// RUN: %clang_cc1 -x c++ -std=c++11 -fmodules -fno-implicit-modules -Rmodule-build -fno-modules-error-recovery \
+// RUN: -fmodule-file=%t/b.pcm \
+// RUN: -fmodule-name=d -emit-module %S/Inputs/explicit-build/module.modulemap -o %t/d.pcm \
+// RUN: 2>&1 | FileCheck --check-prefix=CHECK-NO-IMPLICIT-BUILD %s --allow-empty
+//
+// RUN: %clang_cc1 -x c++ -std=c++11 -fmodules -fno-implicit-modules -Rmodule-build -fno-modules-error-recovery \
+// RUN: -I%S/Inputs/explicit-build \
+// RUN: -fmodule-file=%t/d.pcm \
+// RUN: -verify %s -DHAVE_A -DHAVE_B
+
#if HAVE_A
#include "a.h"
static_assert(a == 1, "");
OpenPOWER on IntegriCloud