<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Thu, Oct 13, 2016 at 11:52 AM, Manman via cfe-commits <span dir="ltr"><<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi Richard,<br>
<br>
I committed a follow-up patch in r284142 to fix issues with C/ObjC.<br>
<br>
Let me know if you see any problem.<br></blockquote><div><br></div><div>Looks good, thank you!</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Manman<br>
<div class="HOEnZb"><div class="h5"><br>
> On Jul 20, 2016, at 12:10 PM, Richard Smith via cfe-commits <<a href="mailto:cfe-commits@lists.llvm.org">cfe-commits@lists.llvm.org</a>> wrote:<br>
><br>
> Author: rsmith<br>
> Date: Wed Jul 20 14:10:16 2016<br>
> New Revision: 276159<br>
><br>
> URL: <a href="http://llvm.org/viewvc/llvm-project?rev=276159&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project?rev=276159&view=rev</a><br>
> Log:<br>
> [modules] Don't emit initializers for VarDecls within a module eagerly whenever<br>
> we first touch any part of that module. Instead, defer them until the first<br>
> time that module is (transitively) imported. The initializer step for a module<br>
> then recursively initializes modules that its own headers imported.<br>
><br>
> For example, this avoids running the <iostream> global initializer in programs<br>
> that don't actually use iostreams, but do use other parts of the standard<br>
> library.<br>
><br>
> Added:<br>
>    cfe/trunk/test/Modules/Inputs/<wbr>unused-global-init/<br>
>      - copied from r275623, cfe/trunk/test/Modules/Inputs/<wbr>unused-global-init/<br>
>    cfe/trunk/test/Modules/unused-<wbr>global-init.cpp<br>
>      - copied, changed from r275623, cfe/trunk/test/Modules/unused-<wbr>global-init.cpp<br>
> Modified:<br>
>    cfe/trunk/include/clang/AST/<wbr>ASTContext.h<br>
>    cfe/trunk/include/clang/Sema/<wbr>Sema.h<br>
>    cfe/trunk/include/clang/<wbr>Serialization/ASTBitCodes.h<br>
>    cfe/trunk/lib/AST/ASTContext.<wbr>cpp<br>
>    cfe/trunk/lib/CodeGen/<wbr>CodeGenModule.cpp<br>
>    cfe/trunk/lib/Sema/SemaDecl.<wbr>cpp<br>
>    cfe/trunk/lib/Sema/SemaLookup.<wbr>cpp<br>
>    cfe/trunk/lib/Serialization/<wbr>ASTReader.cpp<br>
>    cfe/trunk/lib/Serialization/<wbr>ASTReaderDecl.cpp<br>
>    cfe/trunk/lib/Serialization/<wbr>ASTWriter.cpp<br>
>    cfe/trunk/lib/Serialization/<wbr>ASTWriterDecl.cpp<br>
>    cfe/trunk/test/Modules/Inputs/<wbr>unused-global-init/used.h<br>
>    cfe/trunk/test/Modules/odr.cpp<br>
>    cfe/trunk/test/Modules/<a href="http://templates.mm" rel="noreferrer" target="_blank">templat<wbr>es.mm</a><br>
><br>
> Modified: cfe/trunk/include/clang/AST/<wbr>ASTContext.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=276159&r1=276158&r2=276159&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/include/<wbr>clang/AST/ASTContext.h?rev=<wbr>276159&r1=276158&r2=276159&<wbr>view=diff</a><br>
> ==============================<wbr>==============================<wbr>==================<br>
> --- cfe/trunk/include/clang/AST/<wbr>ASTContext.h (original)<br>
> +++ cfe/trunk/include/clang/AST/<wbr>ASTContext.h Wed Jul 20 14:10:16 2016<br>
> @@ -312,6 +312,18 @@ class ASTContext : public RefCountedBase<br>
>   /// definitions of that entity.<br>
>   llvm::DenseMap<NamedDecl*, llvm::TinyPtrVector<Module*>> MergedDefModules;<br>
><br>
> +  /// \brief Initializers for a module, in order. Each Decl will be either<br>
> +  /// something that has a semantic effect on startup (such as a variable with<br>
> +  /// a non-constant initializer), or an ImportDecl (which recursively triggers<br>
> +  /// initialization of another module).<br>
> +  struct PerModuleInitializers {<br>
> +    llvm::SmallVector<Decl*, 4> Initializers;<br>
> +    llvm::SmallVector<uint32_t, 4> LazyInitializers;<br>
> +<br>
> +    void resolve(ASTContext &Ctx);<br>
> +  };<br>
> +  llvm::DenseMap<Module*, PerModuleInitializers*> ModuleInitializers;<br>
> +<br>
> public:<br>
>   /// \brief A type synonym for the TemplateOrInstantiation mapping.<br>
>   typedef llvm::PointerUnion<<wbr>VarTemplateDecl *, MemberSpecializationInfo *><br>
> @@ -883,6 +895,17 @@ public:<br>
>     return MergedIt->second;<br>
>   }<br>
><br>
> +  /// Add a declaration to the list of declarations that are initialized<br>
> +  /// for a module. This will typically be a global variable (with internal<br>
> +  /// linkage) that runs module initializers, such as the iostream initializer,<br>
> +  /// or an ImportDecl nominating another module that has initializers.<br>
> +  void addModuleInitializer(Module *M, Decl *Init);<br>
> +<br>
> +  void addLazyModuleInitializers(<wbr>Module *M, ArrayRef<uint32_t> IDs);<br>
> +<br>
> +  /// Get the initializations to perform when importing a module, if any.<br>
> +  ArrayRef<Decl*> getModuleInitializers(Module *M);<br>
> +<br>
>   TranslationUnitDecl *getTranslationUnitDecl() const { return TUDecl; }<br>
><br>
>   ExternCContextDecl *getExternCContextDecl() const;<br>
><br>
> Modified: cfe/trunk/include/clang/Sema/<wbr>Sema.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=276159&r1=276158&r2=276159&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/include/<wbr>clang/Sema/Sema.h?rev=276159&<wbr>r1=276158&r2=276159&view=diff</a><br>
> ==============================<wbr>==============================<wbr>==================<br>
> --- cfe/trunk/include/clang/Sema/<wbr>Sema.h (original)<br>
> +++ cfe/trunk/include/clang/Sema/<wbr>Sema.h Wed Jul 20 14:10:16 2016<br>
> @@ -1390,8 +1390,14 @@ private:<br>
>   bool RequireCompleteTypeImpl(<wbr>SourceLocation Loc, QualType T,<br>
>                                TypeDiagnoser *Diagnoser);<br>
><br>
> +  struct ModuleScope {<br>
> +    clang::Module *Module;<br>
> +    VisibleModuleSet OuterVisibleModules;<br>
> +  };<br>
> +  /// The modules we're currently parsing.<br>
> +  llvm::SmallVector<ModuleScope, 16> ModuleScopes;<br>
> +<br>
>   VisibleModuleSet VisibleModules;<br>
> -  llvm::SmallVector<<wbr>VisibleModuleSet, 16> VisibleModulesStack;<br>
><br>
>   Module *CachedFakeTopLevelModule;<br>
><br>
><br>
> Modified: cfe/trunk/include/clang/<wbr>Serialization/ASTBitCodes.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTBitCodes.h?rev=276159&r1=276158&r2=276159&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/include/<wbr>clang/Serialization/<wbr>ASTBitCodes.h?rev=276159&r1=<wbr>276158&r2=276159&view=diff</a><br>
> ==============================<wbr>==============================<wbr>==================<br>
> --- cfe/trunk/include/clang/<wbr>Serialization/ASTBitCodes.h (original)<br>
> +++ cfe/trunk/include/clang/<wbr>Serialization/ASTBitCodes.h Wed Jul 20 14:10:16 2016<br>
> @@ -684,6 +684,9 @@ namespace clang {<br>
>       /// \brief Specifies a header that is private to this submodule but<br>
>       /// must be textually included.<br>
>       SUBMODULE_PRIVATE_TEXTUAL_<wbr>HEADER = 15,<br>
> +      /// \brief Specifies some declarations with initializers that must be<br>
> +      /// emitted to initialize the module.<br>
> +      SUBMODULE_INITIALIZERS = 16,<br>
>     };<br>
><br>
>     /// \brief Record types used within a comments block.<br>
><br>
> Modified: cfe/trunk/lib/AST/ASTContext.<wbr>cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=276159&r1=276158&r2=276159&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/AST/<wbr>ASTContext.cpp?rev=276159&r1=<wbr>276158&r2=276159&view=diff</a><br>
> ==============================<wbr>==============================<wbr>==================<br>
> --- cfe/trunk/lib/AST/ASTContext.<wbr>cpp (original)<br>
> +++ cfe/trunk/lib/AST/ASTContext.<wbr>cpp Wed Jul 20 14:10:16 2016<br>
> @@ -901,6 +901,67 @@ void ASTContext::<wbr>deduplicateMergedDefini<br>
>   Merged.erase(std::remove(<wbr>Merged.begin(), Merged.end(), nullptr), Merged.end());<br>
> }<br>
><br>
> +void ASTContext::<wbr>PerModuleInitializers::<wbr>resolve(ASTContext &Ctx) {<br>
> +  if (LazyInitializers.empty())<br>
> +    return;<br>
> +<br>
> +  auto *Source = Ctx.getExternalSource();<br>
> +  assert(Source && "lazy initializers but no external source");<br>
> +<br>
> +  auto LazyInits = std::move(LazyInitializers);<br>
> +  LazyInitializers.clear();<br>
> +<br>
> +  for (auto ID : LazyInits)<br>
> +    Initializers.push_back(Source-<wbr>>GetExternalDecl(ID));<br>
> +<br>
> +  assert(LazyInitializers.empty(<wbr>) &&<br>
> +         "GetExternalDecl for lazy module initializer added more inits");<br>
> +}<br>
> +<br>
> +void ASTContext::<wbr>addModuleInitializer(Module *M, Decl *D) {<br>
> +  // One special case: if we add a module initializer that imports another<br>
> +  // module, and that module's only initializer is an ImportDecl, simplify.<br>
> +  if (auto *ID = dyn_cast<ImportDecl>(D)) {<br>
> +    auto It = ModuleInitializers.find(ID-><wbr>getImportedModule());<br>
> +<br>
> +    // Maybe the ImportDecl does nothing at all. (Common case.)<br>
> +    if (It == ModuleInitializers.end())<br>
> +      return;<br>
> +<br>
> +    // Maybe the ImportDecl only imports another ImportDecl.<br>
> +    auto &Imported = *It->second;<br>
> +    if (Imported.Initializers.size() + Imported.LazyInitializers.<wbr>size() == 1) {<br>
> +      Imported.resolve(*this);<br>
> +      auto *OnlyDecl = Imported.Initializers.front();<br>
> +      if (isa<ImportDecl>(OnlyDecl))<br>
> +        D = OnlyDecl;<br>
> +    }<br>
> +  }<br>
> +<br>
> +  auto *&Inits = ModuleInitializers[M];<br>
> +  if (!Inits)<br>
> +    Inits = new (*this) PerModuleInitializers;<br>
> +  Inits->Initializers.push_back(<wbr>D);<br>
> +}<br>
> +<br>
> +void ASTContext::<wbr>addLazyModuleInitializers(<wbr>Module *M, ArrayRef<uint32_t> IDs) {<br>
> +  auto *&Inits = ModuleInitializers[M];<br>
> +  if (!Inits)<br>
> +    Inits = new (*this) PerModuleInitializers;<br>
> +  Inits->LazyInitializers.<wbr>insert(Inits-><wbr>LazyInitializers.end(),<br>
> +                                 IDs.begin(), IDs.end());<br>
> +}<br>
> +<br>
> +ArrayRef<Decl*> ASTContext::<wbr>getModuleInitializers(Module *M) {<br>
> +  auto It = ModuleInitializers.find(M);<br>
> +  if (It == ModuleInitializers.end())<br>
> +    return None;<br>
> +<br>
> +  auto *Inits = It->second;<br>
> +  Inits->resolve(*this);<br>
> +  return Inits->Initializers;<br>
> +}<br>
> +<br>
> ExternCContextDecl *ASTContext::<wbr>getExternCContextDecl() const {<br>
>   if (!ExternCContext)<br>
>     ExternCContext = ExternCContextDecl::Create(*<wbr>this, getTranslationUnitDecl());<br>
> @@ -8575,6 +8636,8 @@ bool ASTContext::DeclMustBeEmitted(<wbr>const<br>
>     return !D->getDeclContext()-><wbr>isDependentContext();<br>
>   else if (isa<OMPDeclareReductionDecl>(<wbr>D))<br>
>     return !D->getDeclContext()-><wbr>isDependentContext();<br>
> +  else if (isa<ImportDecl>(D))<br>
> +    return true;<br>
>   else<br>
>     return false;<br>
><br>
><br>
> Modified: cfe/trunk/lib/CodeGen/<wbr>CodeGenModule.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=276159&r1=276158&r2=276159&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/CodeGen/<wbr>CodeGenModule.cpp?rev=276159&<wbr>r1=276158&r2=276159&view=diff</a><br>
> ==============================<wbr>==============================<wbr>==================<br>
> --- cfe/trunk/lib/CodeGen/<wbr>CodeGenModule.cpp (original)<br>
> +++ cfe/trunk/lib/CodeGen/<wbr>CodeGenModule.cpp Wed Jul 20 14:10:16 2016<br>
> @@ -3910,13 +3910,19 @@ void CodeGenModule::<wbr>EmitTopLevelDecl(Dec<br>
>   case Decl::Import: {<br>
>     auto *Import = cast<ImportDecl>(D);<br>
><br>
> -    // Ignore import declarations that come from imported modules.<br>
> -    if (Import-><wbr>getImportedOwningModule())<br>
> +    // If we've already imported this module, we're done.<br>
> +    if (!ImportedModules.insert(<wbr>Import->getImportedModule()))<br>
>       break;<br>
> -    if (CGDebugInfo *DI = getModuleDebugInfo())<br>
> -      DI->EmitImportDecl(*Import);<br>
><br>
> -    ImportedModules.insert(Import-<wbr>>getImportedModule());<br>
> +    // Emit debug information for direct imports.<br>
> +    if (!Import-><wbr>getImportedOwningModule()) {<br>
> +      if (CGDebugInfo *DI = getModuleDebugInfo())<br>
> +        DI->EmitImportDecl(*Import);<br>
> +    }<br>
> +<br>
> +    // Emit the module initializers.<br>
> +    for (auto *D : Context.getModuleInitializers(<wbr>Import->getImportedModule()))<br>
> +      EmitTopLevelDecl(D);<br>
>     break;<br>
>   }<br>
><br>
><br>
> Modified: cfe/trunk/lib/Sema/SemaDecl.<wbr>cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=276159&r1=276158&r2=276159&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Sema/<wbr>SemaDecl.cpp?rev=276159&r1=<wbr>276158&r2=276159&view=diff</a><br>
> ==============================<wbr>==============================<wbr>==================<br>
> --- cfe/trunk/lib/Sema/SemaDecl.<wbr>cpp (original)<br>
> +++ cfe/trunk/lib/Sema/SemaDecl.<wbr>cpp Wed Jul 20 14:10:16 2016<br>
> @@ -10473,6 +10473,11 @@ void Sema::<wbr>CheckCompleteVariableDeclarat<br>
>   // Require the destructor.<br>
>   if (const RecordType *recordType = baseType->getAs<RecordType>())<br>
>     FinalizeVarWithDestructor(var, recordType);<br>
> +<br>
> +  // If this variable must be emitted, add it as an initializer for the current<br>
> +  // module.<br>
> +  if (Context.DeclMustBeEmitted(<wbr>var) && !ModuleScopes.empty())<br>
> +    Context.addModuleInitializer(<wbr>ModuleScopes.back().Module, var);<br>
> }<br>
><br>
> /// \brief Determines if a variable's alignment is dependent.<br>
> @@ -15095,11 +15100,13 @@ DeclResult Sema::ActOnModuleImport(Sourc<br>
>     IdentifierLocs.push_back(Path[<wbr>I].second);<br>
>   }<br>
><br>
> -  ImportDecl *Import = ImportDecl::Create(Context,<br>
> -                                          Context.<wbr>getTranslationUnitDecl(),<br>
> +  TranslationUnitDecl *TU = getASTContext().<wbr>getTranslationUnitDecl();<br>
> +  ImportDecl *Import = ImportDecl::Create(Context, TU,<br>
>                                           AtLoc.isValid()? AtLoc : ImportLoc,<br>
>                                           Mod, IdentifierLocs);<br>
> -  Context.<wbr>getTranslationUnitDecl()-><wbr>addDecl(Import);<br>
> +  if (!ModuleScopes.empty())<br>
> +    Context.addModuleInitializer(<wbr>ModuleScopes.back().Module, Import);<br>
> +  TU->addDecl(Import);<br>
>   return Import;<br>
> }<br>
><br>
> @@ -15115,13 +15122,7 @@ void Sema::ActOnModuleInclude(<wbr>SourceLoca<br>
>       TUKind == TU_Module &&<br>
>       getSourceManager().<wbr>isWrittenInMainFile(<wbr>DirectiveLoc);<br>
><br>
> -  // Similarly, if we're in the implementation of a module, don't<br>
> -  // synthesize an illegal module import. FIXME: Why not?<br>
> -  bool ShouldAddImport =<br>
> -      !IsInModuleIncludes &&<br>
> -      (getLangOpts().CompilingModule ||<br>
> -       getLangOpts().CurrentModule.<wbr>empty() ||<br>
> -       getLangOpts().CurrentModule != Mod->getTopLevelModuleName());<br>
> +  bool ShouldAddImport = !IsInModuleIncludes;<br>
><br>
>   // If this module import was due to an inclusion directive, create an<br>
>   // implicit import declaration to capture it in the AST.<br>
> @@ -15130,6 +15131,8 @@ void Sema::ActOnModuleInclude(<wbr>SourceLoca<br>
>     ImportDecl *ImportD = ImportDecl::CreateImplicit(<wbr>getASTContext(), TU,<br>
>                                                      DirectiveLoc, Mod,<br>
>                                                      DirectiveLoc);<br>
> +    if (!ModuleScopes.empty())<br>
> +      Context.addModuleInitializer(<wbr>ModuleScopes.back().Module, ImportD);<br>
>     TU->addDecl(ImportD);<br>
>     Consumer.<wbr>HandleImplicitImportDecl(<wbr>ImportD);<br>
>   }<br>
> @@ -15141,8 +15144,11 @@ void Sema::ActOnModuleInclude(<wbr>SourceLoca<br>
> void Sema::ActOnModuleBegin(<wbr>SourceLocation DirectiveLoc, Module *Mod) {<br>
>   checkModuleImportContext(*<wbr>this, Mod, DirectiveLoc, CurContext);<br>
><br>
> +  ModuleScopes.push_back({});<br>
> +  ModuleScopes.back().Module = Mod;<br>
>   if (getLangOpts().<wbr>ModulesLocalVisibility)<br>
> -    VisibleModulesStack.push_back(<wbr>std::move(VisibleModules));<br>
> +    ModuleScopes.back().<wbr>OuterVisibleModules = std::move(VisibleModules);<br>
> +<br>
>   VisibleModules.setVisible(Mod, DirectiveLoc);<br>
> }<br>
><br>
> @@ -15150,8 +15156,11 @@ void Sema::ActOnModuleEnd(<wbr>SourceLocation<br>
>   checkModuleImportContext(*<wbr>this, Mod, DirectiveLoc, CurContext);<br>
><br>
>   if (getLangOpts().<wbr>ModulesLocalVisibility) {<br>
> -    VisibleModules = std::move(VisibleModulesStack.<wbr>back());<br>
> -    VisibleModulesStack.pop_back()<wbr>;<br>
> +    assert(!ModuleScopes.empty() && ModuleScopes.back().Module == Mod &&<br>
> +           "left the wrong module scope");<br>
> +    VisibleModules = std::move(ModuleScopes.back().<wbr>OuterVisibleModules);<br>
> +    ModuleScopes.pop_back();<br>
> +<br>
>     VisibleModules.setVisible(Mod, DirectiveLoc);<br>
>     // Leaving a module hides namespace names, so our visible namespace cache<br>
>     // is now out of date.<br>
><br>
> Modified: cfe/trunk/lib/Sema/SemaLookup.<wbr>cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=276159&r1=276158&r2=276159&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Sema/<wbr>SemaLookup.cpp?rev=276159&r1=<wbr>276158&r2=276159&view=diff</a><br>
> ==============================<wbr>==============================<wbr>==================<br>
> --- cfe/trunk/lib/Sema/SemaLookup.<wbr>cpp (original)<br>
> +++ cfe/trunk/lib/Sema/SemaLookup.<wbr>cpp Wed Jul 20 14:10:16 2016<br>
> @@ -1367,8 +1367,9 @@ Module *Sema::getOwningModule(Decl *Enti<br>
>       auto &SrcMgr = PP.getSourceManager();<br>
>       SourceLocation StartLoc =<br>
>           SrcMgr.getLocForStartOfFile(<wbr>SrcMgr.getMainFileID());<br>
> -      auto &TopLevel =<br>
> -          VisibleModulesStack.empty() ? VisibleModules : VisibleModulesStack[0];<br>
> +      auto &TopLevel = ModuleScopes.empty()<br>
> +                           ? VisibleModules<br>
> +                           : ModuleScopes[0].<wbr>OuterVisibleModules;<br>
>       TopLevel.setVisible(<wbr>CachedFakeTopLevelModule, StartLoc);<br>
>     }<br>
><br>
><br>
> Modified: cfe/trunk/lib/Serialization/<wbr>ASTReader.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=276159&r1=276158&r2=276159&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/<wbr>Serialization/ASTReader.cpp?<wbr>rev=276159&r1=276158&r2=<wbr>276159&view=diff</a><br>
> ==============================<wbr>==============================<wbr>==================<br>
> --- cfe/trunk/lib/Serialization/<wbr>ASTReader.cpp (original)<br>
> +++ cfe/trunk/lib/Serialization/<wbr>ASTReader.cpp Wed Jul 20 14:10:16 2016<br>
> @@ -4673,6 +4673,13 @@ ASTReader::ReadSubmoduleBlock(<wbr>ModuleFile<br>
>       UnresolvedModuleRefs.push_<wbr>back(Unresolved);<br>
>       break;<br>
>     }<br>
> +<br>
> +    case SUBMODULE_INITIALIZERS:<br>
> +      SmallVector<uint32_t, 16> Inits;<br>
> +      for (auto &ID : Record)<br>
> +        Inits.push_back(<wbr>getGlobalDeclID(F, ID));<br>
> +      Context.<wbr>addLazyModuleInitializers(<wbr>CurrentModule, Inits);<br>
> +      break;<br>
>     }<br>
>   }<br>
> }<br>
><br>
> Modified: cfe/trunk/lib/Serialization/<wbr>ASTReaderDecl.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=276159&r1=276158&r2=276159&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/<wbr>Serialization/ASTReaderDecl.<wbr>cpp?rev=276159&r1=276158&r2=<wbr>276159&view=diff</a><br>
> ==============================<wbr>==============================<wbr>==================<br>
> --- cfe/trunk/lib/Serialization/<wbr>ASTReaderDecl.cpp (original)<br>
> +++ cfe/trunk/lib/Serialization/<wbr>ASTReaderDecl.cpp Wed Jul 20 14:10:16 2016<br>
> @@ -2493,10 +2493,16 @@ inline void ASTReader::LoadedDecl(unsign<br>
> /// This routine should return true for anything that might affect<br>
> /// code generation, e.g., inline function definitions, Objective-C<br>
> /// declarations with metadata, etc.<br>
> -static bool isConsumerInterestedIn(Decl *D, bool HasBody) {<br>
> +static bool isConsumerInterestedIn(<wbr>ASTContext &Ctx, Decl *D, bool HasBody) {<br>
>   // An ObjCMethodDecl is never considered as "interesting" because its<br>
>   // implementation container always is.<br>
><br>
> +  // An ImportDecl or VarDecl imported from a module will get emitted when<br>
> +  // we import the relevant module.<br>
> +  if ((isa<ImportDecl>(D) || isa<VarDecl>(D)) && Ctx.DeclMustBeEmitted(D) &&<br>
> +      D->getImportedOwningModule())<br>
> +    return false;<br>
> +<br>
>   if (isa<FileScopeAsmDecl>(D) ||<br>
>       isa<ObjCProtocolDecl>(D) ||<br>
>       isa<ObjCImplDecl>(D) ||<br>
> @@ -3473,7 +3479,7 @@ Decl *ASTReader::ReadDeclRecord(<wbr>DeclID I<br>
>   // AST consumer might need to know about, queue it.<br>
>   // We don't pass it to the consumer immediately because we may be in recursive<br>
>   // loading, and some declarations may still be initializing.<br>
> -  if (isConsumerInterestedIn(D, Reader.hasPendingBody()))<br>
> +  if (isConsumerInterestedIn(<wbr>Context, D, Reader.hasPendingBody()))<br>
>     InterestingDecls.push_back(D);<br>
><br>
>   return D;<br>
> @@ -3488,7 +3494,7 @@ void ASTReader::<wbr>loadDeclUpdateRecords(se<br>
>     auto UpdateOffsets = std::move(UpdI->second);<br>
>     DeclUpdateOffsets.erase(UpdI);<br>
><br>
> -    bool WasInteresting = isConsumerInterestedIn(D, false);<br>
> +    bool WasInteresting = isConsumerInterestedIn(<wbr>Context, D, false);<br>
>     for (auto &FileAndOffset : UpdateOffsets) {<br>
>       ModuleFile *F = FileAndOffset.first;<br>
>       uint64_t Offset = FileAndOffset.second;<br>
> @@ -3509,7 +3515,7 @@ void ASTReader::<wbr>loadDeclUpdateRecords(se<br>
>       // We might have made this declaration interesting. If so, remember that<br>
>       // we need to hand it off to the consumer.<br>
>       if (!WasInteresting &&<br>
> -          isConsumerInterestedIn(D, Reader.hasPendingBody())) {<br>
> +          isConsumerInterestedIn(<wbr>Context, D, Reader.hasPendingBody())) {<br>
>         InterestingDecls.push_back(D);<br>
>         WasInteresting = true;<br>
>       }<br>
><br>
> Modified: cfe/trunk/lib/Serialization/<wbr>ASTWriter.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=276159&r1=276158&r2=276159&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/<wbr>Serialization/ASTWriter.cpp?<wbr>rev=276159&r1=276158&r2=<wbr>276159&view=diff</a><br>
> ==============================<wbr>==============================<wbr>==================<br>
> --- cfe/trunk/lib/Serialization/<wbr>ASTWriter.cpp (original)<br>
> +++ cfe/trunk/lib/Serialization/<wbr>ASTWriter.cpp Wed Jul 20 14:10:16 2016<br>
> @@ -1017,6 +1017,7 @@ void ASTWriter::<wbr>WriteBlockInfoBlock() {<br>
>   RECORD(SUBMODULE_PRIVATE_<wbr>HEADER);<br>
>   RECORD(SUBMODULE_TEXTUAL_<wbr>HEADER);<br>
>   RECORD(SUBMODULE_PRIVATE_<wbr>TEXTUAL_HEADER);<br>
> +  RECORD(SUBMODULE_INITIALIZERS)<wbr>;<br>
><br>
>   // Comments Block.<br>
>   BLOCK(COMMENTS_BLOCK);<br>
> @@ -2417,7 +2418,9 @@ unsigned ASTWriter::<wbr>getLocalOrImportedSu<br>
>   if (Known != SubmoduleIDs.end())<br>
>     return Known->second;<br>
><br>
> -  if (Mod->getTopLevelModule() != WritingModule)<br>
> +  auto *Top = Mod->getTopLevelModule();<br>
> +  if (Top != WritingModule &&<br>
> +      !Top->fullModuleNameIs(<wbr>StringRef(getLangOpts().<wbr>CurrentModule)))<br>
>     return 0;<br>
><br>
>   return SubmoduleIDs[Mod] = NextSubmoduleID++;<br>
> @@ -2649,6 +2652,13 @@ void ASTWriter::WriteSubmodules(<wbr>Module *<br>
>       Stream.EmitRecordWithBlob(<wbr>ConfigMacroAbbrev, Record, CM);<br>
>     }<br>
><br>
> +    // Emit the initializers, if any.<br>
> +    RecordData Inits;<br>
> +    for (Decl *D : Context-><wbr>getModuleInitializers(Mod))<br>
> +      Inits.push_back(GetDeclRef(D))<wbr>;<br>
> +    if (!Inits.empty())<br>
> +      Stream.EmitRecord(SUBMODULE_<wbr>INITIALIZERS, Inits);<br>
> +<br>
>     // Queue up the submodules of this module.<br>
>     for (auto *M : Mod->submodules())<br>
>       Q.push(M);<br>
> @@ -4514,6 +4524,17 @@ uint64_t ASTWriter::WriteASTCore(Sema &S<br>
>   // If we're emitting a module, write out the submodule information.<br>
>   if (WritingModule)<br>
>     WriteSubmodules(WritingModule)<wbr>;<br>
> +  else if (!getLangOpts().CurrentModule.<wbr>empty()) {<br>
> +    // If we're building a PCH in the implementation of a module, we may need<br>
> +    // the description of the current module.<br>
> +    //<br>
> +    // FIXME: We may need other modules that we did not load from an AST file,<br>
> +    // such as if a module declares a 'conflicts' on a different module.<br>
> +    Module *M = PP.getHeaderSearchInfo().<wbr>getModuleMap().findModule(<br>
> +        getLangOpts().CurrentModule);<br>
> +    if (M && !M->IsFromModuleFile)<br>
> +      WriteSubmodules(M);<br>
> +  }<br>
><br>
>   Stream.EmitRecord(SPECIAL_<wbr>TYPES, SpecialTypes);<br>
><br>
><br>
> Modified: cfe/trunk/lib/Serialization/<wbr>ASTWriterDecl.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterDecl.cpp?rev=276159&r1=276158&r2=276159&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/<wbr>Serialization/ASTWriterDecl.<wbr>cpp?rev=276159&r1=276158&r2=<wbr>276159&view=diff</a><br>
> ==============================<wbr>==============================<wbr>==================<br>
> --- cfe/trunk/lib/Serialization/<wbr>ASTWriterDecl.cpp (original)<br>
> +++ cfe/trunk/lib/Serialization/<wbr>ASTWriterDecl.cpp Wed Jul 20 14:10:16 2016<br>
> @@ -2122,11 +2122,11 @@ static bool isRequiredDecl(const Decl *D<br>
>       D->hasAttr<<wbr>OMPDeclareTargetDeclAttr>())<br>
>     return true;<br>
><br>
> -  // ImportDecl is used by codegen to determine the set of imported modules to<br>
> -  // search for inputs for automatic linking; include it if it has a semantic<br>
> -  // effect.<br>
> -  if (isa<ImportDecl>(D) && !WritingModule)<br>
> -    return true;<br>
> +  if (WritingModule && (isa<VarDecl>(D) || isa<ImportDecl>(D))) {<br>
> +    // These declarations are part of the module initializer, and are emitted<br>
> +    // if and when the module is imported, rather than being emitted eagerly.<br>
> +    return false;<br>
> +  }<br>
><br>
>   return Context.DeclMustBeEmitted(D);<br>
> }<br>
><br>
> Modified: cfe/trunk/test/Modules/Inputs/<wbr>unused-global-init/used.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/unused-global-init/used.h?rev=276159&r1=275623&r2=276159&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/<wbr>Modules/Inputs/unused-global-<wbr>init/used.h?rev=276159&r1=<wbr>275623&r2=276159&view=diff</a><br>
> ==============================<wbr>==============================<wbr>==================<br>
> --- cfe/trunk/test/Modules/Inputs/<wbr>unused-global-init/used.h (original)<br>
> +++ cfe/trunk/test/Modules/Inputs/<wbr>unused-global-init/used.h Wed Jul 20 14:10:16 2016<br>
> @@ -1,2 +1,2 @@<br>
> // used.h<br>
> -#include "other.h"<br>
> +#include "init.h"<br>
><br>
> Modified: cfe/trunk/test/Modules/odr.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/odr.cpp?rev=276159&r1=276158&r2=276159&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/<wbr>Modules/odr.cpp?rev=276159&r1=<wbr>276158&r2=276159&view=diff</a><br>
> ==============================<wbr>==============================<wbr>==================<br>
> --- cfe/trunk/test/Modules/odr.cpp (original)<br>
> +++ cfe/trunk/test/Modules/odr.cpp Wed Jul 20 14:10:16 2016<br>
> @@ -15,9 +15,9 @@ bool b = F<int>{0} == F<int>{1};<br>
> int x = f() + g();<br>
><br>
> // expected-note@a.h:5 {{definition has no member 'e2'}}<br>
> -// expected-note@b.h:3 {{declaration of 'f' does not match}}<br>
> -// expected-note@b.h:1 {{definition has no member 'n'}}<br>
> +// expected-note@a.h:3 {{declaration of 'f' does not match}}<br>
> +// expected-note@a.h:1 {{definition has no member 'm'}}<br>
><br>
> // expected-error@b.h:5 {{'E::e2' from module 'b' is not present in definition of 'E' in module 'a'}}<br>
> -// expected-error@a.h:3 {{'Y::f' from module 'a' is not present in definition of 'Y' in module 'b'}}<br>
> -// expected-error@a.h:2 {{'Y::n' from module 'a' is not present in definition of 'Y' in module 'b'}}<br>
> +// expected-error@b.h:3 {{'Y::f' from module 'b' is not present in definition of 'Y' in module 'a'}}<br>
> +// expected-error@b.h:2 {{'Y::m' from module 'b' is not present in definition of 'Y' in module 'a'}}<br>
><br>
> Modified: cfe/trunk/test/Modules/<a href="http://templates.mm" rel="noreferrer" target="_blank">templat<wbr>es.mm</a><br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/templates.mm?rev=276159&r1=276158&r2=276159&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/<wbr>Modules/templates.mm?rev=<wbr>276159&r1=276158&r2=276159&<wbr>view=diff</a><br>
> ==============================<wbr>==============================<wbr>==================<br>
> --- cfe/trunk/test/Modules/<a href="http://templates.mm" rel="noreferrer" target="_blank">templat<wbr>es.mm</a> (original)<br>
> +++ cfe/trunk/test/Modules/<a href="http://templates.mm" rel="noreferrer" target="_blank">templat<wbr>es.mm</a> Wed Jul 20 14:10:16 2016<br>
> @@ -12,10 +12,10 @@ void testInlineRedeclEarly() {<br>
><br>
> @import templates_right;<br>
><br>
> -// CHECK-DAG: @list_left = global %class.List { %"struct.List<int>::node"* null, i32 8 }, align 8<br>
> -// CHECK-DAG: @list_right = global %class.List { %"struct.List<int>::node"* null, i32 12 }, align 8<br>
> -// CHECK-DAG: @_ZZ15testMixedStructvE1l = {{.*}} constant %class.List { %{{.*}}* null, i32 1 }, align 8<br>
> -// CHECK-DAG: @_ZZ15testMixedStructvE1r = {{.*}} constant %class.List { %{{.*}}* null, i32 2 }, align 8<br>
> +// CHECK-DAG: @list_left = global %[[LIST:.*]] { %[[LISTNODE:.*]]* null, i32 8 }, align 8<br>
> +// CHECK-DAG: @list_right = global %[[LIST]] { %[[LISTNODE]]* null, i32 12 }, align 8<br>
> +// CHECK-DAG: @_ZZ15testMixedStructvE1l = {{.*}} constant %[[LIST]] { %{{.*}}* null, i32 1 }, align 8<br>
> +// CHECK-DAG: @_ZZ15testMixedStructvE1r = {{.*}} constant %[[LIST]] { %{{.*}}* null, i32 2 }, align 8<br>
> // CHECK-DAG: @_<wbr>ZN29WithUndefinedStaticDataMem<wbr>berIA_iE9undefinedE = external global<br>
><br>
> void testTemplateClasses() {<br>
><br>
> Copied: cfe/trunk/test/Modules/unused-<wbr>global-init.cpp (from r275623, cfe/trunk/test/Modules/unused-<wbr>global-init.cpp)<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/unused-global-init.cpp?p2=cfe/trunk/test/Modules/unused-global-init.cpp&p1=cfe/trunk/test/Modules/unused-global-init.cpp&r1=275623&r2=276159&rev=276159&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/<wbr>Modules/unused-global-init.<wbr>cpp?p2=cfe/trunk/test/Modules/<wbr>unused-global-init.cpp&p1=cfe/<wbr>trunk/test/Modules/unused-<wbr>global-init.cpp&r1=275623&r2=<wbr>276159&rev=276159&view=diff</a><br>
> ==============================<wbr>==============================<wbr>==================<br>
> --- cfe/trunk/test/Modules/unused-<wbr>global-init.cpp (original)<br>
> +++ cfe/trunk/test/Modules/unused-<wbr>global-init.cpp Wed Jul 20 14:10:16 2016<br>
> @@ -6,13 +6,14 @@<br>
> //<br>
> // No module file: init.h performs init.<br>
> // RUN: %clang_cc1 -fmodules -fno-implicit-modules -x c++ -I %S/Inputs/unused-global-init -triple %itanium_abi_triple -emit-llvm -o - %s -DINIT | FileCheck --check-prefix=CHECK-INIT %s<br>
> -// RUN: %clang_cc1 -fmodules -fno-implicit-modules -x c++ -I %S/Inputs/unused-global-init -triple %itanium_abi_triple -emit-llvm -o - %s -DOTHER -DUSED -DUNUSED | FileCheck --check-prefix=CHECK-NO-INIT %s<br>
> +// RUN: %clang_cc1 -fmodules -fno-implicit-modules -x c++ -I %S/Inputs/unused-global-init -triple %itanium_abi_triple -emit-llvm -o - %s -DUSED | FileCheck --check-prefix=CHECK-INIT %s<br>
> +// RUN: %clang_cc1 -fmodules -fno-implicit-modules -x c++ -I %S/Inputs/unused-global-init -triple %itanium_abi_triple -emit-llvm -o - %s -DOTHER -DUNUSED | FileCheck --check-prefix=CHECK-NO-INIT %s<br>
> //<br>
> // With module files: if there is a transitive import of any part of the<br>
> // module, we run its global initializers (even if the imported piece is not<br>
> // visible here).<br>
> // RUN: %clang_cc1 -fmodules -fno-implicit-modules -x c++ -I %S/Inputs/unused-global-init -triple %itanium_abi_triple -emit-llvm -o - %s -fmodule-file=%t/used.pcm -fmodule-file=%t/unused.pcm -DINIT | FileCheck --check-prefix=CHECK-INIT %s<br>
> -// RUN: %clang_cc1 -fmodules -fno-implicit-modules -x c++ -I %S/Inputs/unused-global-init -triple %itanium_abi_triple -emit-llvm -o - %s -fmodule-file=%t/used.pcm -fmodule-file=%t/unused.pcm -DOTHER | FileCheck --check-prefix=CHECK-INIT %s<br>
> +// RUN: %clang_cc1 -fmodules -fno-implicit-modules -x c++ -I %S/Inputs/unused-global-init -triple %itanium_abi_triple -emit-llvm -o - %s -fmodule-file=%t/used.pcm -fmodule-file=%t/unused.pcm -DOTHER | FileCheck --check-prefix=CHECK-NO-INIT %s<br>
> // RUN: %clang_cc1 -fmodules -fno-implicit-modules -x c++ -I %S/Inputs/unused-global-init -triple %itanium_abi_triple -emit-llvm -o - %s -fmodule-file=%t/used.pcm -fmodule-file=%t/unused.pcm -DUSED | FileCheck --check-prefix=CHECK-INIT %s<br>
> // RUN: %clang_cc1 -fmodules -fno-implicit-modules -x c++ -I %S/Inputs/unused-global-init -triple %itanium_abi_triple -emit-llvm -o - %s -fmodule-file=%t/used.pcm -fmodule-file=%t/unused.pcm -DUNUSED | FileCheck --check-prefix=CHECK-NO-INIT %s<br>
><br>
><br>
><br>
> ______________________________<wbr>_________________<br>
> cfe-commits mailing list<br>
> <a href="mailto:cfe-commits@lists.llvm.org">cfe-commits@lists.llvm.org</a><br>
> <a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/cfe-commits</a><br>
<br>
______________________________<wbr>_________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@lists.llvm.org">cfe-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/cfe-commits</a><br>
</div></div></blockquote></div><br></div></div>