Author: rsmith Date: Wed Jul 20 14:10:16 2016 New Revision: 276159 URL: http://llvm.org/viewvc/llvm-project?rev=276159&view=rev Log: [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. Added: cfe/trunk/test/Modules/Inputs/unused-global-init/ - copied from r275623, cfe/trunk/test/Modules/Inputs/unused-global-init/ cfe/trunk/test/Modules/unused-global-init.cpp - copied, changed from r275623, cfe/trunk/test/Modules/unused-global-init.cpp Modified: cfe/trunk/include/clang/AST/ASTContext.h cfe/trunk/include/clang/Sema/Sema.h cfe/trunk/include/clang/Serialization/ASTBitCodes.h cfe/trunk/lib/AST/ASTContext.cpp cfe/trunk/lib/CodeGen/CodeGenModule.cpp cfe/trunk/lib/Sema/SemaDecl.cpp cfe/trunk/lib/Sema/SemaLookup.cpp cfe/trunk/lib/Serialization/ASTReader.cpp cfe/trunk/lib/Serialization/ASTReaderDecl.cpp cfe/trunk/lib/Serialization/ASTWriter.cpp cfe/trunk/lib/Serialization/ASTWriterDecl.cpp cfe/trunk/test/Modules/Inputs/unused-global-init/used.h cfe/trunk/test/Modules/odr.cpp cfe/trunk/test/Modules/templates.mm Modified: cfe/trunk/include/clang/AST/ASTContext.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=276159&r1=276158&r2=276159&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/ASTContext.h (original) +++ cfe/trunk/include/clang/AST/ASTContext.h Wed Jul 20 14:10:16 2016 @@ -312,6 +312,18 @@ class ASTContext : public RefCountedBase /// definitions of that entity. llvm::DenseMap<NamedDecl*, llvm::TinyPtrVector<Module*>> MergedDefModules; + /// \brief Initializers for a module, in order. Each Decl will be either + /// something that has a semantic effect on startup (such as a variable with + /// a non-constant initializer), or an ImportDecl (which recursively triggers + /// initialization of another module). + struct PerModuleInitializers { + llvm::SmallVector<Decl*, 4> Initializers; + llvm::SmallVector<uint32_t, 4> LazyInitializers; + + void resolve(ASTContext &Ctx); + }; + llvm::DenseMap<Module*, PerModuleInitializers*> ModuleInitializers; + public: /// \brief A type synonym for the TemplateOrInstantiation mapping. typedef llvm::PointerUnion<VarTemplateDecl *, MemberSpecializationInfo *> @@ -883,6 +895,17 @@ public: return MergedIt->second; } + /// Add a declaration to the list of declarations that are initialized + /// for a module. This will typically be a global variable (with internal + /// linkage) that runs module initializers, such as the iostream initializer, + /// or an ImportDecl nominating another module that has initializers. + void addModuleInitializer(Module *M, Decl *Init); + + void addLazyModuleInitializers(Module *M, ArrayRef<uint32_t> IDs); + + /// Get the initializations to perform when importing a module, if any. + ArrayRef<Decl*> getModuleInitializers(Module *M); + TranslationUnitDecl *getTranslationUnitDecl() const { return TUDecl; } ExternCContextDecl *getExternCContextDecl() const; Modified: cfe/trunk/include/clang/Sema/Sema.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=276159&r1=276158&r2=276159&view=diff ============================================================================== --- cfe/trunk/include/clang/Sema/Sema.h (original) +++ cfe/trunk/include/clang/Sema/Sema.h Wed Jul 20 14:10:16 2016 @@ -1390,8 +1390,14 @@ private: bool RequireCompleteTypeImpl(SourceLocation Loc, QualType T, TypeDiagnoser *Diagnoser); + struct ModuleScope { + clang::Module *Module; + VisibleModuleSet OuterVisibleModules; + }; + /// The modules we're currently parsing. + llvm::SmallVector<ModuleScope, 16> ModuleScopes; + VisibleModuleSet VisibleModules; - llvm::SmallVector<VisibleModuleSet, 16> VisibleModulesStack; Module *CachedFakeTopLevelModule; Modified: cfe/trunk/include/clang/Serialization/ASTBitCodes.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTBitCodes.h?rev=276159&r1=276158&r2=276159&view=diff ============================================================================== --- cfe/trunk/include/clang/Serialization/ASTBitCodes.h (original) +++ cfe/trunk/include/clang/Serialization/ASTBitCodes.h Wed Jul 20 14:10:16 2016 @@ -684,6 +684,9 @@ namespace clang { /// \brief Specifies a header that is private to this submodule but /// must be textually included. SUBMODULE_PRIVATE_TEXTUAL_HEADER = 15, + /// \brief Specifies some declarations with initializers that must be + /// emitted to initialize the module. + SUBMODULE_INITIALIZERS = 16, }; /// \brief Record types used within a comments block. Modified: cfe/trunk/lib/AST/ASTContext.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=276159&r1=276158&r2=276159&view=diff ============================================================================== --- cfe/trunk/lib/AST/ASTContext.cpp (original) +++ cfe/trunk/lib/AST/ASTContext.cpp Wed Jul 20 14:10:16 2016 @@ -901,6 +901,67 @@ void ASTContext::deduplicateMergedDefini Merged.erase(std::remove(Merged.begin(), Merged.end(), nullptr), Merged.end()); } +void ASTContext::PerModuleInitializers::resolve(ASTContext &Ctx) { + if (LazyInitializers.empty()) + return; + + auto *Source = Ctx.getExternalSource(); + assert(Source && "lazy initializers but no external source"); + + auto LazyInits = std::move(LazyInitializers); + LazyInitializers.clear(); + + for (auto ID : LazyInits) + Initializers.push_back(Source->GetExternalDecl(ID)); + + assert(LazyInitializers.empty() && + "GetExternalDecl for lazy module initializer added more inits"); +} + +void ASTContext::addModuleInitializer(Module *M, Decl *D) { + // One special case: if we add a module initializer that imports another + // module, and that module's only initializer is an ImportDecl, simplify. + if (auto *ID = dyn_cast<ImportDecl>(D)) { + auto It = ModuleInitializers.find(ID->getImportedModule()); + + // Maybe the ImportDecl does nothing at all. (Common case.) + if (It == ModuleInitializers.end()) + return; + + // Maybe the ImportDecl only imports another ImportDecl. + auto &Imported = *It->second; + if (Imported.Initializers.size() + Imported.LazyInitializers.size() == 1) { + Imported.resolve(*this); + auto *OnlyDecl = Imported.Initializers.front(); + if (isa<ImportDecl>(OnlyDecl)) + D = OnlyDecl; + } + } + + auto *&Inits = ModuleInitializers[M]; + if (!Inits) + Inits = new (*this) PerModuleInitializers; + Inits->Initializers.push_back(D); +} + +void ASTContext::addLazyModuleInitializers(Module *M, ArrayRef<uint32_t> IDs) { + auto *&Inits = ModuleInitializers[M]; + if (!Inits) + Inits = new (*this) PerModuleInitializers; + Inits->LazyInitializers.insert(Inits->LazyInitializers.end(), + IDs.begin(), IDs.end()); +} + +ArrayRef<Decl*> ASTContext::getModuleInitializers(Module *M) { + auto It = ModuleInitializers.find(M); + if (It == ModuleInitializers.end()) + return None; + + auto *Inits = It->second; + Inits->resolve(*this); + return Inits->Initializers; +} + ExternCContextDecl *ASTContext::getExternCContextDecl() const { if (!ExternCContext) ExternCContext = ExternCContextDecl::Create(*this, getTranslationUnitDecl()); @@ -8575,6 +8636,8 @@ bool ASTContext::DeclMustBeEmitted(const return !D->getDeclContext()->isDependentContext(); else if (isa<OMPDeclareReductionDecl>(D)) return !D->getDeclContext()->isDependentContext(); + else if (isa<ImportDecl>(D)) + return true; else return false; Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=276159&r1=276158&r2=276159&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original) +++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Wed Jul 20 14:10:16 2016 @@ -3910,13 +3910,19 @@ void CodeGenModule::EmitTopLevelDecl(Dec case Decl::Import: { auto *Import = cast<ImportDecl>(D); - // Ignore import declarations that come from imported modules. - if (Import->getImportedOwningModule()) + // If we've already imported this module, we're done. + if (!ImportedModules.insert(Import->getImportedModule())) break; - if (CGDebugInfo *DI = getModuleDebugInfo()) - DI->EmitImportDecl(*Import); - ImportedModules.insert(Import->getImportedModule()); + // Emit debug information for direct imports. + if (!Import->getImportedOwningModule()) { + if (CGDebugInfo *DI = getModuleDebugInfo()) + DI->EmitImportDecl(*Import); + } + + // Emit the module initializers. + for (auto *D : Context.getModuleInitializers(Import->getImportedModule())) + EmitTopLevelDecl(D); break; } Modified: cfe/trunk/lib/Sema/SemaDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=276159&r1=276158&r2=276159&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaDecl.cpp (original) +++ cfe/trunk/lib/Sema/SemaDecl.cpp Wed Jul 20 14:10:16 2016 @@ -10473,6 +10473,11 @@ void Sema::CheckCompleteVariableDeclarat // Require the destructor. if (const RecordType *recordType = baseType->getAs<RecordType>()) FinalizeVarWithDestructor(var, recordType); + + // If this variable must be emitted, add it as an initializer for the current + // module. + if (Context.DeclMustBeEmitted(var) && !ModuleScopes.empty()) + Context.addModuleInitializer(ModuleScopes.back().Module, var); } /// \brief Determines if a variable's alignment is dependent. @@ -15095,11 +15100,13 @@ DeclResult Sema::ActOnModuleImport(Sourc IdentifierLocs.push_back(Path[I].second); } - ImportDecl *Import = ImportDecl::Create(Context, - Context.getTranslationUnitDecl(), + TranslationUnitDecl *TU = getASTContext().getTranslationUnitDecl(); + ImportDecl *Import = ImportDecl::Create(Context, TU, AtLoc.isValid()? AtLoc : ImportLoc, Mod, IdentifierLocs); - Context.getTranslationUnitDecl()->addDecl(Import); + if (!ModuleScopes.empty()) + Context.addModuleInitializer(ModuleScopes.back().Module, Import); + TU->addDecl(Import); return Import; } @@ -15115,13 +15122,7 @@ void Sema::ActOnModuleInclude(SourceLoca TUKind == TU_Module && getSourceManager().isWrittenInMainFile(DirectiveLoc); - // Similarly, if we're in the implementation of a module, don't - // synthesize an illegal module import. FIXME: Why not? - bool ShouldAddImport = - !IsInModuleIncludes && - (getLangOpts().CompilingModule || - getLangOpts().CurrentModule.empty() || - getLangOpts().CurrentModule != Mod->getTopLevelModuleName()); + bool ShouldAddImport = !IsInModuleIncludes; // If this module import was due to an inclusion directive, create an // implicit import declaration to capture it in the AST. @@ -15130,6 +15131,8 @@ void Sema::ActOnModuleInclude(SourceLoca ImportDecl *ImportD = ImportDecl::CreateImplicit(getASTContext(), TU, DirectiveLoc, Mod, DirectiveLoc); + if (!ModuleScopes.empty()) + Context.addModuleInitializer(ModuleScopes.back().Module, ImportD); TU->addDecl(ImportD); Consumer.HandleImplicitImportDecl(ImportD); } @@ -15141,8 +15144,11 @@ void Sema::ActOnModuleInclude(SourceLoca void Sema::ActOnModuleBegin(SourceLocation DirectiveLoc, Module *Mod) { checkModuleImportContext(*this, Mod, DirectiveLoc, CurContext); + ModuleScopes.push_back({}); + ModuleScopes.back().Module = Mod; if (getLangOpts().ModulesLocalVisibility) - VisibleModulesStack.push_back(std::move(VisibleModules)); + ModuleScopes.back().OuterVisibleModules = std::move(VisibleModules); + VisibleModules.setVisible(Mod, DirectiveLoc); } @@ -15150,8 +15156,11 @@ void Sema::ActOnModuleEnd(SourceLocation checkModuleImportContext(*this, Mod, DirectiveLoc, CurContext); if (getLangOpts().ModulesLocalVisibility) { - VisibleModules = std::move(VisibleModulesStack.back()); - VisibleModulesStack.pop_back(); + assert(!ModuleScopes.empty() && ModuleScopes.back().Module == Mod && + "left the wrong module scope"); + VisibleModules = std::move(ModuleScopes.back().OuterVisibleModules); + ModuleScopes.pop_back(); + VisibleModules.setVisible(Mod, DirectiveLoc); // Leaving a module hides namespace names, so our visible namespace cache // is now out of date. Modified: cfe/trunk/lib/Sema/SemaLookup.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=276159&r1=276158&r2=276159&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaLookup.cpp (original) +++ cfe/trunk/lib/Sema/SemaLookup.cpp Wed Jul 20 14:10:16 2016 @@ -1367,8 +1367,9 @@ Module *Sema::getOwningModule(Decl *Enti auto &SrcMgr = PP.getSourceManager(); SourceLocation StartLoc = SrcMgr.getLocForStartOfFile(SrcMgr.getMainFileID()); - auto &TopLevel = - VisibleModulesStack.empty() ? VisibleModules : VisibleModulesStack[0]; + auto &TopLevel = ModuleScopes.empty() + ? VisibleModules + : ModuleScopes[0].OuterVisibleModules; TopLevel.setVisible(CachedFakeTopLevelModule, StartLoc); } Modified: cfe/trunk/lib/Serialization/ASTReader.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=276159&r1=276158&r2=276159&view=diff ============================================================================== --- cfe/trunk/lib/Serialization/ASTReader.cpp (original) +++ cfe/trunk/lib/Serialization/ASTReader.cpp Wed Jul 20 14:10:16 2016 @@ -4673,6 +4673,13 @@ ASTReader::ReadSubmoduleBlock(ModuleFile UnresolvedModuleRefs.push_back(Unresolved); break; } + + case SUBMODULE_INITIALIZERS: + SmallVector<uint32_t, 16> Inits; + for (auto &ID : Record) + Inits.push_back(getGlobalDeclID(F, ID)); + Context.addLazyModuleInitializers(CurrentModule, Inits); + break; } } } Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=276159&r1=276158&r2=276159&view=diff ============================================================================== --- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original) +++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Wed Jul 20 14:10:16 2016 @@ -2493,10 +2493,16 @@ inline void ASTReader::LoadedDecl(unsign /// This routine should return true for anything that might affect /// code generation, e.g., inline function definitions, Objective-C /// declarations with metadata, etc. -static bool isConsumerInterestedIn(Decl *D, bool HasBody) { +static bool isConsumerInterestedIn(ASTContext &Ctx, Decl *D, bool HasBody) { // An ObjCMethodDecl is never considered as "interesting" because its // implementation container always is. + // An ImportDecl or VarDecl imported from a module will get emitted when + // we import the relevant module. + if ((isa<ImportDecl>(D) || isa<VarDecl>(D)) && Ctx.DeclMustBeEmitted(D) && + D->getImportedOwningModule()) + return false; + if (isa<FileScopeAsmDecl>(D) || isa<ObjCProtocolDecl>(D) || isa<ObjCImplDecl>(D) || @@ -3473,7 +3479,7 @@ Decl *ASTReader::ReadDeclRecord(DeclID I // AST consumer might need to know about, queue it. // We don't pass it to the consumer immediately because we may be in recursive // loading, and some declarations may still be initializing. - if (isConsumerInterestedIn(D, Reader.hasPendingBody())) + if (isConsumerInterestedIn(Context, D, Reader.hasPendingBody())) InterestingDecls.push_back(D); return D; @@ -3488,7 +3494,7 @@ void ASTReader::loadDeclUpdateRecords(se auto UpdateOffsets = std::move(UpdI->second); DeclUpdateOffsets.erase(UpdI); - bool WasInteresting = isConsumerInterestedIn(D, false); + bool WasInteresting = isConsumerInterestedIn(Context, D, false); for (auto &FileAndOffset : UpdateOffsets) { ModuleFile *F = FileAndOffset.first; uint64_t Offset = FileAndOffset.second; @@ -3509,7 +3515,7 @@ void ASTReader::loadDeclUpdateRecords(se // We might have made this declaration interesting. If so, remember that // we need to hand it off to the consumer. if (!WasInteresting && - isConsumerInterestedIn(D, Reader.hasPendingBody())) { + isConsumerInterestedIn(Context, D, Reader.hasPendingBody())) { InterestingDecls.push_back(D); WasInteresting = true; } Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=276159&r1=276158&r2=276159&view=diff ============================================================================== --- cfe/trunk/lib/Serialization/ASTWriter.cpp (original) +++ cfe/trunk/lib/Serialization/ASTWriter.cpp Wed Jul 20 14:10:16 2016 @@ -1017,6 +1017,7 @@ void ASTWriter::WriteBlockInfoBlock() { 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 @@ unsigned ASTWriter::getLocalOrImportedSu 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 @@ void ASTWriter::WriteSubmodules(Module * 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 @@ uint64_t ASTWriter::WriteASTCore(Sema &S // 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); Modified: cfe/trunk/lib/Serialization/ASTWriterDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterDecl.cpp?rev=276159&r1=276158&r2=276159&view=diff ============================================================================== --- cfe/trunk/lib/Serialization/ASTWriterDecl.cpp (original) +++ cfe/trunk/lib/Serialization/ASTWriterDecl.cpp Wed Jul 20 14:10:16 2016 @@ -2122,11 +2122,11 @@ static bool isRequiredDecl(const Decl *D D->hasAttr<OMPDeclareTargetDeclAttr>()) return true; - // ImportDecl is used by codegen to determine the set of imported modules to - // search for inputs for automatic linking; include it if it has a semantic - // effect. - if (isa<ImportDecl>(D) && !WritingModule) - return true; + if (WritingModule && (isa<VarDecl>(D) || isa<ImportDecl>(D))) { + // These declarations are part of the module initializer, and are emitted + // if and when the module is imported, rather than being emitted eagerly. + return false; + } return Context.DeclMustBeEmitted(D); } Modified: cfe/trunk/test/Modules/Inputs/unused-global-init/used.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/unused-global-init/used.h?rev=276159&r1=275623&r2=276159&view=diff ============================================================================== --- cfe/trunk/test/Modules/Inputs/unused-global-init/used.h (original) +++ cfe/trunk/test/Modules/Inputs/unused-global-init/used.h Wed Jul 20 14:10:16 2016 @@ -1,2 +1,2 @@ // used.h -#include "other.h" +#include "init.h" Modified: cfe/trunk/test/Modules/odr.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/odr.cpp?rev=276159&r1=276158&r2=276159&view=diff ============================================================================== --- cfe/trunk/test/Modules/odr.cpp (original) +++ cfe/trunk/test/Modules/odr.cpp Wed Jul 20 14:10:16 2016 @@ -15,9 +15,9 @@ bool b = F<int>{0} == F<int>{1}; int x = f() + g(); // expected-note@a.h:5 {{definition has no member 'e2'}} -// expected-note@b.h:3 {{declaration of 'f' does not match}} -// expected-note@b.h:1 {{definition has no member 'n'}} +// expected-note@a.h:3 {{declaration of 'f' does not match}} +// expected-note@a.h:1 {{definition has no member 'm'}} // expected-error@b.h:5 {{'E::e2' from module 'b' is not present in definition of 'E' in module 'a'}} -// expected-error@a.h:3 {{'Y::f' from module 'a' is not present in definition of 'Y' in module 'b'}} -// expected-error@a.h:2 {{'Y::n' from module 'a' is not present in definition of 'Y' in module 'b'}} +// expected-error@b.h:3 {{'Y::f' from module 'b' is not present in definition of 'Y' in module 'a'}} +// expected-error@b.h:2 {{'Y::m' from module 'b' is not present in definition of 'Y' in module 'a'}} Modified: cfe/trunk/test/Modules/templates.mm URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/templates.mm?rev=276159&r1=276158&r2=276159&view=diff ============================================================================== --- cfe/trunk/test/Modules/templates.mm (original) +++ cfe/trunk/test/Modules/templates.mm Wed Jul 20 14:10:16 2016 @@ -12,10 +12,10 @@ void testInlineRedeclEarly() { @import templates_right; -// CHECK-DAG: @list_left = global %class.List { %"struct.List<int>::node"* null, i32 8 }, align 8 -// CHECK-DAG: @list_right = global %class.List { %"struct.List<int>::node"* null, i32 12 }, align 8 -// CHECK-DAG: @_ZZ15testMixedStructvE1l = {{.*}} constant %class.List { %{{.*}}* null, i32 1 }, align 8 -// CHECK-DAG: @_ZZ15testMixedStructvE1r = {{.*}} constant %class.List { %{{.*}}* null, i32 2 }, align 8 +// CHECK-DAG: @list_left = global %[[LIST:.*]] { %[[LISTNODE:.*]]* null, i32 8 }, align 8 +// CHECK-DAG: @list_right = global %[[LIST]] { %[[LISTNODE]]* null, i32 12 }, align 8 +// CHECK-DAG: @_ZZ15testMixedStructvE1l = {{.*}} constant %[[LIST]] { %{{.*}}* null, i32 1 }, align 8 +// CHECK-DAG: @_ZZ15testMixedStructvE1r = {{.*}} constant %[[LIST]] { %{{.*}}* null, i32 2 }, align 8 // CHECK-DAG: @_ZN29WithUndefinedStaticDataMemberIA_iE9undefinedE = external global void testTemplateClasses() { Copied: cfe/trunk/test/Modules/unused-global-init.cpp (from r275623, cfe/trunk/test/Modules/unused-global-init.cpp) URL: 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 ============================================================================== --- cfe/trunk/test/Modules/unused-global-init.cpp (original) +++ cfe/trunk/test/Modules/unused-global-init.cpp Wed Jul 20 14:10:16 2016 @@ -6,13 +6,14 @@ // // No module file: init.h performs init. // 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 -// 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 +// 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 +// 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 // // With module files: if there is a transitive import of any part of the // module, we run its global initializers (even if the imported piece is not // visible here). // 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 -// 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 +// 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 // 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 // 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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits