From 6d1780cfb8d72f2434560262a30af8bb2ebf8420 Mon Sep 17 00:00:00 2001 From: David Majnemer Date: Fri, 17 Jul 2015 23:36:49 +0000 Subject: [PATCH] [MS ABI] Explicit specialization of static data members are weak Normally, explicit specializations are treated like strong external definitions. However, MSVC treats explicit specializations of static data members as weak. MSVC 2013's implementation has such an explicit specialization which leads to clang emitting a strong definition in each translation unit which includes it. Tweak clang's linkage calculation to give such entities GVA_StrongODR linkage instead. This fixes PR24165. llvm-svn: 242592 --- clang/lib/AST/ASTContext.cpp | 6 +++++- clang/test/CodeGenCXX/dllexport-members.cpp | 6 +++--- clang/test/CodeGenCXX/microsoft-compatibility.cpp | 10 ++++++++++ 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index fb96301..61bd107 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -8285,9 +8285,13 @@ static GVALinkage basicGVALinkageForVariable(const ASTContext &Context, switch (VD->getTemplateSpecializationKind()) { case TSK_Undeclared: - case TSK_ExplicitSpecialization: return GVA_StrongExternal; + case TSK_ExplicitSpecialization: + return Context.getLangOpts().MSVCCompat && VD->isStaticDataMember() + ? GVA_StrongODR + : GVA_StrongExternal; + case TSK_ExplicitInstantiationDefinition: return GVA_StrongODR; diff --git a/clang/test/CodeGenCXX/dllexport-members.cpp b/clang/test/CodeGenCXX/dllexport-members.cpp index 4038d0b..da9e19c 100644 --- a/clang/test/CodeGenCXX/dllexport-members.cpp +++ b/clang/test/CodeGenCXX/dllexport-members.cpp @@ -623,13 +623,13 @@ extern template const int MemVarTmpl::ExportedStaticVar; template const int MemVarTmpl::ExportedStaticVar; // Export specialization of an exported member variable template. -// MSC-DAG: @"\01??$ExportedStaticVar@UExplicitSpec_Def_Exported@@@MemVarTmpl@@2HB" = dllexport constant i32 1, align 4 +// MSC-DAG: @"\01??$ExportedStaticVar@UExplicitSpec_Def_Exported@@@MemVarTmpl@@2HB" = weak_odr dllexport constant i32 1, comdat, align 4 // GNU-DAG: @_ZN10MemVarTmpl17ExportedStaticVarI25ExplicitSpec_Def_ExportedEE = dllexport constant i32 1, align 4 template<> __declspec(dllexport) const int MemVarTmpl::ExportedStaticVar = 1; // Not exporting specialization of an exported member variable template without // explicit dllexport. -// MSC-DAG: @"\01??$ExportedStaticVar@UExplicitSpec_NotExported@@@MemVarTmpl@@2HB" = constant i32 1, align 4 +// MSC-DAG: @"\01??$ExportedStaticVar@UExplicitSpec_NotExported@@@MemVarTmpl@@2HB" = weak_odr constant i32 1, comdat, align 4 // GNU-DAG: @_ZN10MemVarTmpl17ExportedStaticVarI24ExplicitSpec_NotExportedEE = constant i32 1, align 4 template<> const int MemVarTmpl::ExportedStaticVar = 1; @@ -648,6 +648,6 @@ extern template __declspec(dllexport) const int MemVarTmpl::StaticVar; // Export specialization of a non-exported member variable template. -// MSC-DAG: @"\01??$StaticVar@UExplicitSpec_Def_Exported@@@MemVarTmpl@@2HB" = dllexport constant i32 1, align 4 +// MSC-DAG: @"\01??$StaticVar@UExplicitSpec_Def_Exported@@@MemVarTmpl@@2HB" = weak_odr dllexport constant i32 1, comdat, align 4 // GNU-DAG: @_ZN10MemVarTmpl9StaticVarI25ExplicitSpec_Def_ExportedEE = dllexport constant i32 1, align 4 template<> __declspec(dllexport) const int MemVarTmpl::StaticVar = 1; diff --git a/clang/test/CodeGenCXX/microsoft-compatibility.cpp b/clang/test/CodeGenCXX/microsoft-compatibility.cpp index 297184a..3676024 100644 --- a/clang/test/CodeGenCXX/microsoft-compatibility.cpp +++ b/clang/test/CodeGenCXX/microsoft-compatibility.cpp @@ -1,5 +1,15 @@ // RUN: %clang_cc1 %s -triple i686-pc-win32 -std=c++11 -fms-compatibility -emit-llvm -o - | FileCheck %s +template +struct S { + static const int x[]; +}; + +template <> +const int S::x[] = {1}; + +// CHECK-LABEL: @"\01?x@?$S@D@@2QBHB" = weak_odr constant [1 x i32] [i32 1], comdat + template void destroy(T *p) { p->~T(); -- 2.7.4