]> granicus.if.org Git - clang/commitdiff
[MS ABI] Explicit specialization of static data members are weak
authorDavid Majnemer <david.majnemer@gmail.com>
Fri, 17 Jul 2015 23:36:49 +0000 (23:36 +0000)
committerDavid Majnemer <david.majnemer@gmail.com>
Fri, 17 Jul 2015 23:36:49 +0000 (23:36 +0000)
Normally, explicit specializations are treated like strong external
definitions.  However, MSVC treats explicit specializations of static
data members as weak.  MSVC 2013's <regex> 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.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@242592 91177308-0d34-0410-b5e6-96231b3b80d8

lib/AST/ASTContext.cpp
test/CodeGenCXX/dllexport-members.cpp
test/CodeGenCXX/microsoft-compatibility.cpp

index fb9630180dcae871eafc16a9cd0d25091378dda0..61bd1077941fdb151f69e3aa393fab5573066ece 100644 (file)
@@ -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;
 
index 4038d0ba467dd524799deabbd51d1edf815a962f..da9e19cb15236422e3fb2c47412b2b1557b0e569 100644 (file)
@@ -623,13 +623,13 @@ extern template const int MemVarTmpl::ExportedStaticVar<ExplicitDecl_Exported>;
 template const int MemVarTmpl::ExportedStaticVar<ExplicitInst_Exported>;
 
 // 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<ExplicitSpec_Def_Exported> = 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<ExplicitSpec_NotExported> = 1;
 
@@ -648,6 +648,6 @@ extern template __declspec(dllexport) const int MemVarTmpl::StaticVar<ExplicitDe
 template __declspec(dllexport) const int MemVarTmpl::StaticVar<ExplicitInst_Exported>;
 
 // 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<ExplicitSpec_Def_Exported> = 1;
index 297184a1df2a4a4429d5166b8e4fa04e040608e9..36760243d49b85f0b26a386fe2244542e937a35a 100644 (file)
@@ -1,5 +1,15 @@
 // RUN: %clang_cc1 %s -triple i686-pc-win32 -std=c++11 -fms-compatibility -emit-llvm -o - | FileCheck %s
 
+template <typename>
+struct S {
+  static const int x[];
+};
+
+template <>
+const int S<char>::x[] = {1};
+
+// CHECK-LABEL: @"\01?x@?$S@D@@2QBHB" = weak_odr constant [1 x i32] [i32 1], comdat
+
 template<class T>
 void destroy(T *p) {
   p->~T();