Hi Richard, I committed a follow-up patch in r284142 to fix issues with C/ObjC.
Let me know if you see any problem. Manman > On Jul 20, 2016, at 12:10 PM, Richard Smith via cfe-commits > <cfe-commits@lists.llvm.org> wrote: > > 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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits