Index: lib/CodeGen/CGDeclCXX.cpp =================================================================== --- lib/CodeGen/CGDeclCXX.cpp +++ lib/CodeGen/CGDeclCXX.cpp @@ -467,7 +467,8 @@ } else if (auto *IPA = D->getAttr()) { OrderGlobalInits Key(IPA->getPriority(), PrioritizedCXXGlobalInits.size()); PrioritizedCXXGlobalInits.push_back(std::make_pair(Key, Fn)); - } else if (isTemplateInstantiation(D->getTemplateSpecializationKind())) { + } else if (isTemplateInstantiation(D->getTemplateSpecializationKind()) || + getContext().GetGVALinkageForVariable(D) == GVA_DiscardableODR) { // C++ [basic.start.init]p2: // Definitions of explicitly specialized class template static data // members have ordered initialization. Other class template static data @@ -481,6 +482,11 @@ // minor startup time optimization. In the MS C++ ABI, there are no guard // variables, so this COMDAT key is required for correctness. AddGlobalCtor(Fn, 65535, COMDATKey); + if (getTarget().getCXXABI().isMicrosoft() && COMDATKey) { + // In The MS C++, MS add template static data member in the linker + // drective. + addUsedGlobal(COMDATKey); + } } else if (D->hasAttr()) { // SelectAny globals will be comdat-folded. Put the initializer into a // COMDAT group associated with the global, so the initializers get folded Index: test/CodeGenCXX/microsoft-abi-template-static-init.cpp =================================================================== --- /dev/null +++ test/CodeGenCXX/microsoft-abi-template-static-init.cpp @@ -0,0 +1,92 @@ +// RUN: %clang_cc1 %s -triple=i686-pc-win32 -fms-extensions -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -triple=x86_64-pc-win32 -fms-extensions -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -triple=i686-pc-windows-msvc -fms-extensions -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -triple=x86_64-pc-windows-msvc -fms-extensions -emit-llvm -o - | FileCheck %s + +struct S { + S(); + ~S(); +}; + +template struct __declspec(dllexport) ExportedTemplate { + static S s; +}; +template S ExportedTemplate::s; +void useExportedTemplate(ExportedTemplate x) { + (void)x.s; +} +int f(); +namespace selectany_init { +// MS don't put selectany static var in the linker directive, init routine +// f() is not getting called if x is not referenced. +int __declspec(selectany) x = f(); +inline int __declspec(selectany) x1 = f(); +} + +namespace explicit_template_instantiation { +template struct A { static int x; }; +template int A::x = f(); +template struct A; +} + +namespace implicit_template_instantiation { +template struct A { static int x; }; +template int A::x = f(); +int g() { return A::x; } +} + + +template +struct X_ { + static T ioo; + static T init(); +}; +template T X_::ioo = X_::init(); +template struct X_; + +template +struct X { + static T ioo; + static T init(); +}; +// template specialized static data don't need in llvm.used, +// the static init routine get call from _GLOBAL__sub_I_ routines. +template <> int X::ioo = X::init(); +template struct X; +class a { +public: + a(); +}; +// For the static var inside unnamed namespace, the object is local to TU. +// No need to put static var in the linker directive. +// The static init routine is called before main. +namespace { +template class aj { +public: + static a al; +}; +template a aj::al; +class b : aj<3> { + void c(); +}; +void b::c() { al; } +} + +// C++17, inline static data member also need to use +struct A +{ + A(); + ~A(); +}; + +struct S1 +{ + inline static A aoo; // C++17 inline variable, thus also a definition +}; + +int foo(); +inline int zoo = foo(); +inline static int boo = foo(); + + +// CHECK: @llvm.used = appending global [7 x i8*] [i8* bitcast (i32* @"?x1@selectany_init@@3HA" to i8*), i8* bitcast (i32* @"?x@?$A@H@explicit_template_instantiation@@2HA" to i8*), i8* bitcast (i32* @"?ioo@?$X_@H@@2HA" to i8*), i8* getelementptr inbounds (%struct.A, %struct.A* @"?aoo@S1@@2UA@@A", i32 0, i32 0), i8* bitcast (i32* @"?zoo@@3HA" to i8*), i8* getelementptr inbounds (%struct.S, %struct.S* @"?s@?$ExportedTemplate@H@@2US@@A", i32 0, i32 0), i8* bitcast (i32* @"?x@?$A@H@implicit_template_instantiation@@2HA" to i8*)], section "llvm.metadata" Index: test/Modules/initializers.cpp =================================================================== --- test/Modules/initializers.cpp +++ test/Modules/initializers.cpp @@ -235,7 +235,6 @@ // CHECK-IMPORT: define {{.*}} @[[TU_INIT]]() // CHECK-IMPORT: call void @[[A_INIT]]() -// CHECK-IMPORT: call void @[[B_INIT]]() // CHECK-IMPORT: define {{.*}} @__tls_init() // CHECK-IMPORT: call void @[[C_INIT]]()