Index: lib/Sema/SemaTemplate.cpp =================================================================== --- lib/Sema/SemaTemplate.cpp +++ lib/Sema/SemaTemplate.cpp @@ -7665,20 +7665,22 @@ Specialization->getDefinition()); if (Def) { TemplateSpecializationKind Old_TSK = Def->getTemplateSpecializationKind(); - // Fix a TSK_ExplicitInstantiationDeclaration followed by a - // TSK_ExplicitInstantiationDefinition - if (Old_TSK == TSK_ExplicitInstantiationDeclaration && + // Fix a TSK_ExplicitInstantiationDeclaration or a TSK_ImplicitInstantiation + // followed by a TSK_ExplicitInstantiationDefinition + if ((Old_TSK == TSK_ExplicitInstantiationDeclaration || + Old_TSK == TSK_ImplicitInstantiation) && (TSK == TSK_ExplicitInstantiationDefinition || DLLImportExplicitInstantiationDef)) { // FIXME: Need to notify the ASTMutationListener that we did this. Def->setTemplateSpecializationKind(TSK); - if (!getDLLAttr(Def) && getDLLAttr(Specialization) && + if (getDLLAttr(Specialization) && + (!getDLLAttr(Def) || Old_TSK == TSK_ImplicitInstantiation) && (Context.getTargetInfo().getCXXABI().isMicrosoft() || Context.getTargetInfo().getTriple().isWindowsItaniumEnvironment())) { // In the MS ABI, an explicit instantiation definition can add a dll - // attribute to a template with a previous instantiation declaration. - // MinGW doesn't allow this. + // attribute to a template with a previous instantiation declaration + // or implicit instantiation. MinGW doesn't allow this. auto *A = cast( getDLLAttr(Specialization)->clone(getASTContext())); A->setInherited(true); Index: test/CodeGenCXX/dllexport.cpp =================================================================== --- test/CodeGenCXX/dllexport.cpp +++ test/CodeGenCXX/dllexport.cpp @@ -771,6 +771,13 @@ // M32-DAG: define weak_odr dllexport x86_thiscallcc %struct.ExplicitInstantiationDeclExportedDefTemplate* @"\01??0?$ExplicitInstantiationDeclExportedDefTemplate@H@@QAE@XZ" // G32-DAG: define weak_odr x86_thiscallcc void @_ZN44ExplicitInstantiationDeclExportedDefTemplateIiE1fEv +template struct ImplicitInstantiationExplicitInstantiationDefExportedTemplate { void f() {} }; +ImplicitInstantiationExplicitInstantiationDefExportedTemplate ImplicitInstantiationExplicitInstantiationDefExportedTemplateInstance; +template class __declspec(dllexport) ImplicitInstantiationExplicitInstantiationDefExportedTemplate; +USEMEMFUNC(ImplicitInstantiationExplicitInstantiationDefExportedTemplate, f); +// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?f@?$ImplicitInstantiationExplicitInstantiationDefExportedTemplate@H@@QAEXXZ" +// G32-DAG: define weak_odr x86_thiscallcc void @_ZN61ImplicitInstantiationExplicitInstantiationDefExportedTemplateIiE1fEv + namespace { struct InternalLinkageType {}; } struct __declspec(dllexport) PR23308 { void f(InternalLinkageType*); Index: test/CodeGenCXX/dllimport.cpp =================================================================== --- test/CodeGenCXX/dllimport.cpp +++ test/CodeGenCXX/dllimport.cpp @@ -814,6 +814,13 @@ // M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"\01?f@?$ExplicitInstantiationDeclExportedDefImportedTemplate@H@@QAEXXZ" // M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc %struct.ExplicitInstantiationDeclExportedDefImportedTemplate* @"\01??0?$ExplicitInstantiationDeclExportedDefImportedTemplate@H@@QAE@XZ" +template struct ImplicitInstantiationExplicitInstantiationDefImportedTemplate { void f() {} }; +ImplicitInstantiationExplicitInstantiationDefImportedTemplate ImplicitInstantiationExplicitInstantiationDefImportedTemplateInstance; +template class __declspec(dllimport) ImplicitInstantiationExplicitInstantiationDefImportedTemplate; +USEMEMFUNC(ImplicitInstantiationExplicitInstantiationDefImportedTemplate, f); +// M32-DAG: declare dllimport x86_thiscallcc void @"\01?f@?$ImplicitInstantiationExplicitInstantiationDefImportedTemplate@H@@QAEXXZ" +// G32-DAG: define weak_odr x86_thiscallcc void @_ZN61ImplicitInstantiationExplicitInstantiationDefImportedTemplateIiE1fEv + template struct PR23770BaseTemplate { void f() {} }; template struct PR23770DerivedTemplate : PR23770BaseTemplate {}; extern template struct PR23770DerivedTemplate; Index: test/CodeGenCXX/windows-itanium-dllexport.cpp =================================================================== --- test/CodeGenCXX/windows-itanium-dllexport.cpp +++ test/CodeGenCXX/windows-itanium-dllexport.cpp @@ -23,3 +23,8 @@ // CHECK: define {{.*}} dllexport {{.*}} @_ZN1cIcEaSERKS0_ // CHECK: define {{.*}} dllexport {{.*}} @_ZN1cIcE1fEv +c g; +template class __declspec(dllexport) c; + +// CHECK: define {{.*}} dllexport {{.*}} @_ZN1cIdEaSERKS0_ +// CHECK: define {{.*}} dllexport {{.*}} @_ZN1cIdE1fEv