From ad2389cf904e0146e42fcb41f3f4961049ae31e4 Mon Sep 17 00:00:00 2001 From: Shoaib Meenai Date: Fri, 13 Jan 2017 01:28:34 +0000 Subject: [PATCH] [Sema] Restrict explicit instantation definition dllexport In the case where the template class itself is already `dllexport`, the implicit instantiation will have already emitted all members. When we check the explicit instantiation definition, the `Specialization` will have inherited the `dllexport` attribute, so we'll attempt to emit all members for a second time, which causes an assertion failure. Restrict the exporting to when the `dllexport` attribute is newly introduced by the explicit instantiation definition. Fixes PR31608. Differential Revision: https://reviews.llvm.org/D28590 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@291877 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaTemplate.cpp | 6 ++++-- test/CodeGenCXX/dllexport.cpp | 20 +++++++++++++++++--- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 7edef7075c..8ad5b5951e 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -7789,6 +7789,7 @@ Sema::ActOnExplicitInstantiation(Scope *S, Specialization->setTemplateKeywordLoc(TemplateLoc); Specialization->setBraceRange(SourceRange()); + bool PreviouslyDLLExported = Specialization->hasAttr(); if (Attr) ProcessDeclAttributeList(S, Specialization, Attr); @@ -7851,8 +7852,9 @@ Sema::ActOnExplicitInstantiation(Scope *S, // Fix a TSK_ImplicitInstantiation followed by a // TSK_ExplicitInstantiationDefinition - if (Old_TSK == TSK_ImplicitInstantiation && - Specialization->hasAttr() && + bool NewlyDLLExported = + !PreviouslyDLLExported && Specialization->hasAttr(); + if (Old_TSK == TSK_ImplicitInstantiation && NewlyDLLExported && (Context.getTargetInfo().getCXXABI().isMicrosoft() || Context.getTargetInfo().getTriple().isWindowsItaniumEnvironment())) { // In the MS ABI, an explicit instantiation definition can add a dll diff --git a/test/CodeGenCXX/dllexport.cpp b/test/CodeGenCXX/dllexport.cpp index fe40bc0aac..33e524cc9b 100644 --- a/test/CodeGenCXX/dllexport.cpp +++ b/test/CodeGenCXX/dllexport.cpp @@ -732,13 +732,27 @@ USEMEMFUNC(ExplicitInstantiationDeclExportedDefTemplate, f); // 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() {} }; +template struct ImplicitInstantiationExportedExplicitInstantiationDefTemplate { virtual void f() {} }; +ImplicitInstantiationExportedExplicitInstantiationDefTemplate ImplicitInstantiationExportedExplicitInstantiationDefTemplateInstance; +template struct __declspec(dllexport) ImplicitInstantiationExportedExplicitInstantiationDefTemplate; +USEMEMFUNC(ImplicitInstantiationExportedExplicitInstantiationDefTemplate, f); +// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?f@?$ImplicitInstantiationExportedExplicitInstantiationDefTemplate@H@@UAEXXZ" +// G32-DAG: define weak_odr x86_thiscallcc void @_ZN61ImplicitInstantiationExportedExplicitInstantiationDefTemplateIiE1fEv + +template struct __declspec(dllexport) ImplicitInstantiationExplicitInstantiationDefExportedTemplate { virtual void f() {} }; ImplicitInstantiationExplicitInstantiationDefExportedTemplate ImplicitInstantiationExplicitInstantiationDefExportedTemplateInstance; -template class __declspec(dllexport) ImplicitInstantiationExplicitInstantiationDefExportedTemplate; +template struct ImplicitInstantiationExplicitInstantiationDefExportedTemplate; USEMEMFUNC(ImplicitInstantiationExplicitInstantiationDefExportedTemplate, f); -// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?f@?$ImplicitInstantiationExplicitInstantiationDefExportedTemplate@H@@QAEXXZ" +// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?f@?$ImplicitInstantiationExplicitInstantiationDefExportedTemplate@H@@UAEXXZ" // G32-DAG: define weak_odr x86_thiscallcc void @_ZN61ImplicitInstantiationExplicitInstantiationDefExportedTemplateIiE1fEv +template struct __declspec(dllexport) ImplicitInstantiationExportedExplicitInstantiationDefExportedTemplate { virtual void f() {} }; +ImplicitInstantiationExportedExplicitInstantiationDefExportedTemplate ImplicitInstantiationExportedExplicitInstantiationDefExportedTemplateInstance; +template struct __declspec(dllexport) ImplicitInstantiationExportedExplicitInstantiationDefExportedTemplate; +USEMEMFUNC(ImplicitInstantiationExportedExplicitInstantiationDefExportedTemplate, f); +// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?f@?$ImplicitInstantiationExportedExplicitInstantiationDefExportedTemplate@H@@UAEXXZ" +// G32-DAG: define weak_odr x86_thiscallcc void @_ZN69ImplicitInstantiationExportedExplicitInstantiationDefExportedTemplateIiE1fEv + namespace { struct InternalLinkageType {}; } struct __declspec(dllexport) PR23308 { void f(InternalLinkageType*); -- 2.40.0