<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Thu, Mar 19, 2015 at 1:37 PM, Alexey Samsonov <span dir="ltr"><<a href="mailto:vonosmas@gmail.com" target="_blank">vonosmas@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><br><div class="gmail_quote"><div><div class="h5">On Tue, Mar 17, 2015 at 6:42 PM, Richard Smith <span dir="ltr"><<a href="mailto:richard-llvm@metafoo.co.uk" target="_blank">richard-llvm@metafoo.co.uk</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: rsmith<br>
Date: Tue Mar 17 20:42:29 2015<br>
New Revision: 232583<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=232583&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=232583&view=rev</a><br>
Log:<br>
Make module files passed to a module build via -fmodule-file= available to<br>
consumers of that module.<br>
<br>
Previously, such a file would only be available if the module happened to<br>
actually import something from that module.<br>
<br>
Added:<br>
cfe/trunk/test/Modules/Inputs/explicit-build/d.h<br>
Modified:<br>
cfe/trunk/include/clang/Serialization/ASTBitCodes.h<br>
cfe/trunk/include/clang/Serialization/ModuleManager.h<br>
cfe/trunk/lib/Frontend/CompilerInstance.cpp<br>
cfe/trunk/lib/Serialization/ASTReader.cpp<br>
cfe/trunk/lib/Serialization/ASTWriter.cpp<br>
cfe/trunk/lib/Serialization/ModuleManager.cpp<br>
cfe/trunk/test/Modules/Inputs/explicit-build/module.modulemap<br>
cfe/trunk/test/Modules/explicit-build.cpp<br>
<br>
Modified: cfe/trunk/include/clang/Serialization/ASTBitCodes.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTBitCodes.h?rev=232583&r1=232582&r2=232583&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTBitCodes.h?rev=232583&r1=232582&r2=232583&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/Serialization/ASTBitCodes.h (original)<br>
+++ cfe/trunk/include/clang/Serialization/ASTBitCodes.h Tue Mar 17 20:42:29 2015<br>
@@ -295,6 +295,10 @@ namespace clang {<br>
<br>
/// \brief Record code for the module build directory.<br>
MODULE_DIRECTORY = 16,<br>
+<br>
+ /// \brief Record code for the list of other AST files made available by<br>
+ /// this AST file but not actually used by it.<br>
+ KNOWN_MODULE_FILES = 17,<br>
};<br>
<br>
/// \brief Record types that occur within the input-files block<br>
<br>
Modified: cfe/trunk/include/clang/Serialization/ModuleManager.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ModuleManager.h?rev=232583&r1=232582&r2=232583&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ModuleManager.h?rev=232583&r1=232582&r2=232583&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/Serialization/ModuleManager.h (original)<br>
+++ cfe/trunk/include/clang/Serialization/ModuleManager.h Tue Mar 17 20:42:29 2015<br>
@@ -35,7 +35,13 @@ class ModuleManager {<br>
<br>
/// \brief All loaded modules, indexed by name.<br>
llvm::DenseMap<const FileEntry *, ModuleFile *> Modules;<br>
-<br>
+<br>
+ typedef llvm::SetVector<const FileEntry *> AdditionalKnownModuleFileSet;<br>
+<br>
+ /// \brief Additional module files that are known but not loaded. Tracked<br>
+ /// here so that we can re-export them if necessary.<br>
+ AdditionalKnownModuleFileSet AdditionalKnownModuleFiles;<br>
+<br>
/// \brief FileManager that handles translating between filenames and<br>
/// FileEntry *.<br>
FileManager &FileMgr;<br>
@@ -219,6 +225,19 @@ public:<br>
/// has been "accepted", and will not (can not) be unloaded.<br>
void moduleFileAccepted(ModuleFile *MF);<br>
<br>
+ /// \brief Notification from the frontend that the given module file is<br>
+ /// part of this compilation (even if not imported) and, if this compilation<br>
+ /// is exported, should be made available to importers of it.<br>
+ bool addKnownModuleFile(StringRef FileName);<br>
+<br>
+ /// \brief Get a list of additional module files that are not currently<br>
+ /// loaded but are considered to be part of the current compilation.<br>
+ llvm::iterator_range<AdditionalKnownModuleFileSet::const_iterator><br>
+ getAdditionalKnownModuleFiles() {<br>
+ return llvm::make_range(AdditionalKnownModuleFiles.begin(),<br>
+ AdditionalKnownModuleFiles.end());<br>
+ }<br>
+<br>
/// \brief Visit each of the modules.<br>
///<br>
/// This routine visits each of the modules, starting with the<br>
<br>
Modified: cfe/trunk/lib/Frontend/CompilerInstance.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/CompilerInstance.cpp?rev=232583&r1=232582&r2=232583&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/CompilerInstance.cpp?rev=232583&r1=232582&r2=232583&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Frontend/CompilerInstance.cpp (original)<br>
+++ cfe/trunk/lib/Frontend/CompilerInstance.cpp Tue Mar 17 20:42:29 2015<br>
@@ -1331,6 +1331,19 @@ bool CompilerInstance::loadModuleFile(St<br>
}<br>
} RMN(*this);<br>
<br>
+ // If we don't already have an ASTReader, create one now.<br>
+ if (!ModuleManager)<br>
+ createModuleManager();<br>
+<br>
+ // Tell the module manager about this module file.<br>
+ if (getModuleManager()->getModuleManager().addKnownModuleFile(FileName)) {<br>
+ getDiagnostics().Report(SourceLocation(), diag::err_module_file_not_found)<br>
+ << FileName;<br>
+ return false;<br>
+ }<br>
+<br>
+ // Build our mapping of module names to module files from this file<br>
+ // and its imports.<br>
RMN.visitImport(FileName);<br>
<br>
if (RMN.Failed)<br>
<br>
Modified: cfe/trunk/lib/Serialization/ASTReader.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=232583&r1=232582&r2=232583&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=232583&r1=232582&r2=232583&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Serialization/ASTReader.cpp (original)<br>
+++ cfe/trunk/lib/Serialization/ASTReader.cpp Tue Mar 17 20:42:29 2015<br>
@@ -2462,6 +2462,9 @@ ASTReader::ReadControlBlock(ModuleFile &<br>
break;<br>
}<br>
<br>
+ case KNOWN_MODULE_FILES:<br>
+ break;<br>
+<br>
case LANGUAGE_OPTIONS: {<br>
bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch) == 0;<br>
// FIXME: The &F == *ModuleMgr.begin() check is wrong for modules.<br>
@@ -4248,6 +4251,8 @@ bool ASTReader::readASTFileControlBlock(<br>
FileManager &FileMgr,<br>
ASTReaderListener &Listener) {<br>
// Open the AST file.<br>
+ // FIXME: This allows use of the VFS; we do not allow use of the<br>
+ // VFS when actually loading a module.<br>
auto Buffer = FileMgr.getBufferForFile(Filename);<br>
if (!Buffer) {<br>
return true;<br>
@@ -4418,6 +4423,20 @@ bool ASTReader::readASTFileControlBlock(<br>
break;<br>
}<br>
<br>
+ case KNOWN_MODULE_FILES: {<br>
+ // Known-but-not-technically-used module files are treated as imports.<br>
+ if (!NeedsImports)<br>
+ break;<br>
+<br>
+ unsigned Idx = 0, N = Record.size();<br>
+ while (Idx < N) {<br>
+ std::string Filename = ReadString(Record, Idx);<br>
+ ResolveImportedPath(Filename, ModuleDir);<br>
+ Listener.visitImport(Filename);<br>
+ }<br>
+ break;<br>
+ }<br>
+<br>
default:<br>
// No other validation to perform.<br>
break;<br>
@@ -6842,6 +6861,9 @@ void ASTReader::StartTranslationUnit(AST<br>
EagerlyDeserializedDecls.clear();<br>
<br>
PassInterestingDeclsToConsumer();<br>
+<br>
+ if (DeserializationListener)<br>
+ DeserializationListener->ReaderInitialized(this);<br>
}<br>
<br>
void ASTReader::PrintStats() {<br>
<br>
Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=232583&r1=232582&r2=232583&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=232583&r1=232582&r2=232583&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)<br>
+++ cfe/trunk/lib/Serialization/ASTWriter.cpp Tue Mar 17 20:42:29 2015<br>
@@ -867,6 +867,7 @@ void ASTWriter::WriteBlockInfoBlock() {<br>
RECORD(MODULE_NAME);<br>
RECORD(MODULE_MAP_FILE);<br>
RECORD(IMPORTS);<br>
+ RECORD(KNOWN_MODULE_FILES);<br>
RECORD(LANGUAGE_OPTIONS);<br>
RECORD(TARGET_OPTIONS);<br>
RECORD(ORIGINAL_FILE);<br>
@@ -1222,20 +1223,28 @@ void ASTWriter::WriteControlBlock(Prepro<br>
serialization::ModuleManager &Mgr = Chain->getModuleManager();<br>
Record.clear();<br>
<br>
- for (ModuleManager::ModuleIterator M = Mgr.begin(), MEnd = Mgr.end();<br>
- M != MEnd; ++M) {<br>
+ for (auto *M : Mgr) {<br>
// Skip modules that weren't directly imported.<br>
- if (!(*M)->isDirectlyImported())<br>
+ if (!M->isDirectlyImported())<br>
continue;<br>
<br>
- Record.push_back((unsigned)(*M)->Kind); // FIXME: Stable encoding<br>
- AddSourceLocation((*M)->ImportLoc, Record);<br>
- Record.push_back((*M)->File->getSize());<br>
- Record.push_back((*M)->File->getModificationTime());<br>
- Record.push_back((*M)->Signature);<br>
- AddPath((*M)->FileName, Record);<br>
+ Record.push_back((unsigned)M->Kind); // FIXME: Stable encoding<br>
+ AddSourceLocation(M->ImportLoc, Record);<br>
+ Record.push_back(M->File->getSize());<br>
+ Record.push_back(M->File->getModificationTime());<br>
+ Record.push_back(M->Signature);<br>
+ AddPath(M->FileName, Record);<br>
}<br>
Stream.EmitRecord(IMPORTS, Record);<br>
+<br>
+ // Also emit a list of known module files that were not imported,<br>
+ // but are made available by this module.<br>
+ // FIXME: Should we also include a signature here?<br>
+ Record.clear();<br>
+ for (auto *E : Mgr.getAdditionalKnownModuleFiles())<br>
+ AddPath(E->getName(), Record);<br>
+ if (!Record.empty())<br>
+ Stream.EmitRecord(KNOWN_MODULE_FILES, Record);<br>
}<br>
<br>
// Language options.<br>
@@ -5655,6 +5664,8 @@ void ASTWriter::ReaderInitialized(ASTRea<br>
<br>
Chain = Reader;<br>
<br>
+ // Note, this will get called multiple times, once one the reader starts up<br>
+ // and again each time it's done reading a PCH or module.<br>
FirstDeclID = NUM_PREDEF_DECL_IDS + Chain->getTotalNumDecls();<br>
FirstTypeID = NUM_PREDEF_TYPE_IDS + Chain->getTotalNumTypes();<br>
FirstIdentID = NUM_PREDEF_IDENT_IDS + Chain->getTotalNumIdentifiers();<br>
<br>
Modified: cfe/trunk/lib/Serialization/ModuleManager.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ModuleManager.cpp?rev=232583&r1=232582&r2=232583&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ModuleManager.cpp?rev=232583&r1=232582&r2=232583&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Serialization/ModuleManager.cpp (original)<br>
+++ cfe/trunk/lib/Serialization/ModuleManager.cpp Tue Mar 17 20:42:29 2015<br>
@@ -227,6 +227,15 @@ ModuleManager::addInMemoryBuffer(StringR<br>
InMemoryBuffers[Entry] = std::move(Buffer);<br>
}<br>
<br>
+bool ModuleManager::addKnownModuleFile(StringRef FileName) {<br>
+ const FileEntry *File;<br>
+ if (lookupModuleFile(FileName, 0, 0, File))<br>
+ return true;<br>
+ if (!Modules.count(File))<br>
+ AdditionalKnownModuleFiles.insert(File);<br>
+ return false;<br>
+}<br>
+<br>
ModuleManager::VisitState *ModuleManager::allocateVisitState() {<br>
// Fast path: if we have a cached state, use it.<br>
if (FirstVisitState) {<br>
@@ -263,6 +272,8 @@ void ModuleManager::setGlobalIndex(Globa<br>
}<br>
<br>
void ModuleManager::moduleFileAccepted(ModuleFile *MF) {<br>
+ AdditionalKnownModuleFiles.remove(MF->File);<br>
+<br>
if (!GlobalIndex || GlobalIndex->loadedModuleFile(MF))<br>
return;<br>
<br>
<br>
Added: cfe/trunk/test/Modules/Inputs/explicit-build/d.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/explicit-build/d.h?rev=232583&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/explicit-build/d.h?rev=232583&view=auto</a><br>
==============================================================================<br>
(empty)<br>
<br>
Modified: cfe/trunk/test/Modules/Inputs/explicit-build/module.modulemap<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/explicit-build/module.modulemap?rev=232583&r1=232582&r2=232583&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/explicit-build/module.modulemap?rev=232583&r1=232582&r2=232583&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/Modules/Inputs/explicit-build/module.modulemap (original)<br>
+++ cfe/trunk/test/Modules/Inputs/explicit-build/module.modulemap Tue Mar 17 20:42:29 2015<br>
@@ -1,3 +1,4 @@<br>
module a { header "a.h" }<br>
module b { header "b.h" export * }<br>
module c { header "c.h" export * }<br>
+module d { header "d.h" }<br>
<br>
Modified: cfe/trunk/test/Modules/explicit-build.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/explicit-build.cpp?rev=232583&r1=232582&r2=232583&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/explicit-build.cpp?rev=232583&r1=232582&r2=232583&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/Modules/explicit-build.cpp (original)<br>
+++ cfe/trunk/test/Modules/explicit-build.cpp Tue Mar 17 20:42:29 2015<br>
@@ -64,6 +64,19 @@<br>
// RUN: -fmodule-file=%t/c.pcm \<br>
// RUN: -verify %s -DHAVE_A -DHAVE_B -DHAVE_C<br>
<br>
+// -------------------------------<br>
+// Check that -fmodule-file= in a module build makes the file transitively<br>
+// available even if it's not used.<br>
+// RUN: %clang_cc1 -x c++ -std=c++11 -fmodules -fno-implicit-modules -Rmodule-build -fno-modules-error-recovery \<br>
+// RUN: -fmodule-file=%t/b.pcm \<br>
+// RUN: -fmodule-name=d -emit-module %S/Inputs/explicit-build/module.modulemap -o %t/d.pcm \<br>
+// RUN: 2>&1 | FileCheck --check-prefix=CHECK-NO-IMPLICIT-BUILD %s --allow-empty<br>
+//<br>
+// RUN: %clang_cc1 -x c++ -std=c++11 -fmodules -fno-implicit-modules -Rmodule-build -fno-modules-error-recovery \<br>
+// RUN: -I%S/Inputs/explicit-build \<br>
+// RUN: -fmodule-file=%t/d.pcm \<br>
+// RUN: -verify %s -DHAVE_A -DHAVE_B<br></blockquote><div><br></div></div></div><div>^^</div><div>Do you need to add -fmodules-cache-path=%t to this invocation?</div></div></div></div></blockquote><div><br></div><div>That should not be necessary, because -fno-implicit-modules should disable all use of the module cache. If it doesn't do so, that'd be interesting to know and it would be a bug.</div></div></div></div>