[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.

llvm-svn: 242592

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

index fb96301..61bd107 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 4038d0b..da9e19c 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 297184a..3676024 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();