summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans Wennborg <hans@hanshq.net>2017-01-13 19:11:01 +0000
committerHans Wennborg <hans@hanshq.net>2017-01-13 19:11:01 +0000
commit0e2702f6089149dc7e532ee9c83c8635c6c948bb (patch)
tree1caaa272b4369a54e4bc050d33b8c896e2a64dcb
parent959137d5a2bbf584031588fcdb6de892d324be93 (diff)
Merging r291877:
------------------------------------------------------------------------ r291877 | smeenai | 2017-01-12 17:28:34 -0800 (Thu, 12 Jan 2017) | 13 lines [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/branches/release_40@291943 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Sema/SemaTemplate.cpp6
-rw-r--r--test/CodeGenCXX/dllexport.cpp20
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<DLLExportAttr>();
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<DLLExportAttr>() &&
+ bool NewlyDLLExported =
+ !PreviouslyDLLExported && Specialization->hasAttr<DLLExportAttr>();
+ 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<int>, 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 <typename T> struct ImplicitInstantiationExplicitInstantiationDefExportedTemplate { void f() {} };
+template <typename T> struct ImplicitInstantiationExportedExplicitInstantiationDefTemplate { virtual void f() {} };
+ImplicitInstantiationExportedExplicitInstantiationDefTemplate<int> ImplicitInstantiationExportedExplicitInstantiationDefTemplateInstance;
+template struct __declspec(dllexport) ImplicitInstantiationExportedExplicitInstantiationDefTemplate<int>;
+USEMEMFUNC(ImplicitInstantiationExportedExplicitInstantiationDefTemplate<int>, 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 <typename T> struct __declspec(dllexport) ImplicitInstantiationExplicitInstantiationDefExportedTemplate { virtual void f() {} };
ImplicitInstantiationExplicitInstantiationDefExportedTemplate<int> ImplicitInstantiationExplicitInstantiationDefExportedTemplateInstance;
-template class __declspec(dllexport) ImplicitInstantiationExplicitInstantiationDefExportedTemplate<int>;
+template struct ImplicitInstantiationExplicitInstantiationDefExportedTemplate<int>;
USEMEMFUNC(ImplicitInstantiationExplicitInstantiationDefExportedTemplate<int>, 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 <typename T> struct __declspec(dllexport) ImplicitInstantiationExportedExplicitInstantiationDefExportedTemplate { virtual void f() {} };
+ImplicitInstantiationExportedExplicitInstantiationDefExportedTemplate<int> ImplicitInstantiationExportedExplicitInstantiationDefExportedTemplateInstance;
+template struct __declspec(dllexport) ImplicitInstantiationExportedExplicitInstantiationDefExportedTemplate<int>;
+USEMEMFUNC(ImplicitInstantiationExportedExplicitInstantiationDefExportedTemplate<int>, 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*);