smeenai created this revision. smeenai added reviewers: compnerd, hans. smeenai added a subscriber: cfe-commits.
On MSVC, if an implicit instantiation already exists and an explicit instantiation definition with a DLL attribute is created, the DLL attribute still takes effect. Make clang match this behavior. https://reviews.llvm.org/D26657 Files: lib/Sema/SemaTemplate.cpp test/CodeGenCXX/dllexport.cpp test/CodeGenCXX/dllimport.cpp test/CodeGenCXX/windows-itanium-dllexport.cpp 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<double> g; +template class __declspec(dllexport) c<double>; + +// CHECK: define {{.*}} dllexport {{.*}} @_ZN1cIdEaSERKS0_ +// CHECK: define {{.*}} dllexport {{.*}} @_ZN1cIdE1fEv 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 <typename T> struct ImplicitInstantiationExplicitInstantiationDefImportedTemplate { void f() {} }; +ImplicitInstantiationExplicitInstantiationDefImportedTemplate<int> ImplicitInstantiationExplicitInstantiationDefImportedTemplateInstance; +template class __declspec(dllimport) ImplicitInstantiationExplicitInstantiationDefImportedTemplate<int>; +USEMEMFUNC(ImplicitInstantiationExplicitInstantiationDefImportedTemplate<int>, f); +// M32-DAG: declare dllimport x86_thiscallcc void @"\01?f@?$ImplicitInstantiationExplicitInstantiationDefImportedTemplate@H@@QAEXXZ" +// G32-DAG: define weak_odr x86_thiscallcc void @_ZN61ImplicitInstantiationExplicitInstantiationDefImportedTemplateIiE1fEv + template <typename T> struct PR23770BaseTemplate { void f() {} }; template <typename T> struct PR23770DerivedTemplate : PR23770BaseTemplate<int> {}; extern template struct PR23770DerivedTemplate<int>; 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 <typename T> struct ImplicitInstantiationExplicitInstantiationDefExportedTemplate { void f() {} }; +ImplicitInstantiationExplicitInstantiationDefExportedTemplate<int> ImplicitInstantiationExplicitInstantiationDefExportedTemplateInstance; +template class __declspec(dllexport) ImplicitInstantiationExplicitInstantiationDefExportedTemplate<int>; +USEMEMFUNC(ImplicitInstantiationExplicitInstantiationDefExportedTemplate<int>, 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: 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<InheritableAttr>( getDLLAttr(Specialization)->clone(getASTContext())); A->setInherited(true);
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<double> g; +template class __declspec(dllexport) c<double>; + +// CHECK: define {{.*}} dllexport {{.*}} @_ZN1cIdEaSERKS0_ +// CHECK: define {{.*}} dllexport {{.*}} @_ZN1cIdE1fEv 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 <typename T> struct ImplicitInstantiationExplicitInstantiationDefImportedTemplate { void f() {} }; +ImplicitInstantiationExplicitInstantiationDefImportedTemplate<int> ImplicitInstantiationExplicitInstantiationDefImportedTemplateInstance; +template class __declspec(dllimport) ImplicitInstantiationExplicitInstantiationDefImportedTemplate<int>; +USEMEMFUNC(ImplicitInstantiationExplicitInstantiationDefImportedTemplate<int>, f); +// M32-DAG: declare dllimport x86_thiscallcc void @"\01?f@?$ImplicitInstantiationExplicitInstantiationDefImportedTemplate@H@@QAEXXZ" +// G32-DAG: define weak_odr x86_thiscallcc void @_ZN61ImplicitInstantiationExplicitInstantiationDefImportedTemplateIiE1fEv + template <typename T> struct PR23770BaseTemplate { void f() {} }; template <typename T> struct PR23770DerivedTemplate : PR23770BaseTemplate<int> {}; extern template struct PR23770DerivedTemplate<int>; 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 <typename T> struct ImplicitInstantiationExplicitInstantiationDefExportedTemplate { void f() {} }; +ImplicitInstantiationExplicitInstantiationDefExportedTemplate<int> ImplicitInstantiationExplicitInstantiationDefExportedTemplateInstance; +template class __declspec(dllexport) ImplicitInstantiationExplicitInstantiationDefExportedTemplate<int>; +USEMEMFUNC(ImplicitInstantiationExplicitInstantiationDefExportedTemplate<int>, 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: 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<InheritableAttr>( getDLLAttr(Specialization)->clone(getASTContext())); A->setInherited(true);
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits