[modules] Don't emit initializers for VarDecls within a module eagerly whenever
we first touch any part of that module. Instead, defer them until the first
time that module is (transitively) imported. The initializer step for a module
then recursively initializes modules that its own headers imported.
For example, this avoids running the <iostream> global initializer in programs
that don't actually use iostreams, but do use other parts of the standard
library.
llvm-svn: 276159
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index 314eee0..dbba5fd 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -1017,6 +1017,7 @@
RECORD(SUBMODULE_PRIVATE_HEADER);
RECORD(SUBMODULE_TEXTUAL_HEADER);
RECORD(SUBMODULE_PRIVATE_TEXTUAL_HEADER);
+ RECORD(SUBMODULE_INITIALIZERS);
// Comments Block.
BLOCK(COMMENTS_BLOCK);
@@ -2417,7 +2418,9 @@
if (Known != SubmoduleIDs.end())
return Known->second;
- if (Mod->getTopLevelModule() != WritingModule)
+ auto *Top = Mod->getTopLevelModule();
+ if (Top != WritingModule &&
+ !Top->fullModuleNameIs(StringRef(getLangOpts().CurrentModule)))
return 0;
return SubmoduleIDs[Mod] = NextSubmoduleID++;
@@ -2649,6 +2652,13 @@
Stream.EmitRecordWithBlob(ConfigMacroAbbrev, Record, CM);
}
+ // Emit the initializers, if any.
+ RecordData Inits;
+ for (Decl *D : Context->getModuleInitializers(Mod))
+ Inits.push_back(GetDeclRef(D));
+ if (!Inits.empty())
+ Stream.EmitRecord(SUBMODULE_INITIALIZERS, Inits);
+
// Queue up the submodules of this module.
for (auto *M : Mod->submodules())
Q.push(M);
@@ -4514,6 +4524,17 @@
// If we're emitting a module, write out the submodule information.
if (WritingModule)
WriteSubmodules(WritingModule);
+ else if (!getLangOpts().CurrentModule.empty()) {
+ // If we're building a PCH in the implementation of a module, we may need
+ // the description of the current module.
+ //
+ // FIXME: We may need other modules that we did not load from an AST file,
+ // such as if a module declares a 'conflicts' on a different module.
+ Module *M = PP.getHeaderSearchInfo().getModuleMap().findModule(
+ getLangOpts().CurrentModule);
+ if (M && !M->IsFromModuleFile)
+ WriteSubmodules(M);
+ }
Stream.EmitRecord(SPECIAL_TYPES, SpecialTypes);