r359212 - Fix bug 37903:MS ABI: handle inline static data member and inline variable as template static data member

Jennifer Yu via cfe-commits cfe-commits at lists.llvm.org
Thu Apr 25 10:45:45 PDT 2019


Author: jyu2
Date: Thu Apr 25 10:45:45 2019
New Revision: 359212

URL: http://llvm.org/viewvc/llvm-project?rev=359212&view=rev
Log:
Fix bug 37903:MS ABI: handle inline static data member and inline variable as template static data member

Added:
    cfe/trunk/test/CodeGenCXX/microsoft-abi-template-static-init.cpp
Modified:
    cfe/trunk/lib/CodeGen/CGDeclCXX.cpp
    cfe/trunk/test/Modules/initializers.cpp

Modified: cfe/trunk/lib/CodeGen/CGDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDeclCXX.cpp?rev=359212&r1=359211&r2=359212&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGDeclCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGDeclCXX.cpp Thu Apr 25 10:45:45 2019
@@ -467,7 +467,8 @@ CodeGenModule::EmitCXXGlobalVarDeclInitF
   } else if (auto *IPA = D->getAttr<InitPriorityAttr>()) {
     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 @@ CodeGenModule::EmitCXXGlobalVarDeclInitF
     // 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<SelectAnyAttr>()) {
     // SelectAny globals will be comdat-folded. Put the initializer into a
     // COMDAT group associated with the global, so the initializers get folded

Added: cfe/trunk/test/CodeGenCXX/microsoft-abi-template-static-init.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/microsoft-abi-template-static-init.cpp?rev=359212&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenCXX/microsoft-abi-template-static-init.cpp (added)
+++ cfe/trunk/test/CodeGenCXX/microsoft-abi-template-static-init.cpp Thu Apr 25 10:45:45 2019
@@ -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 <typename T> struct __declspec(dllexport) ExportedTemplate {
+  static S s;
+};
+template <typename T> S ExportedTemplate<T>::s;
+void useExportedTemplate(ExportedTemplate<int> 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 <typename T> struct A { static  int x; };
+template <typename T> int A<T>::x = f();
+template struct A<int>;
+}
+
+namespace implicit_template_instantiation {
+template <typename T> struct A { static  int x; };
+template <typename T>  int A<T>::x = f();
+int g() { return A<int>::x; }
+}
+
+
+template <class T>
+struct X_ {
+  static T ioo;
+  static T init();
+};
+template <class T> T X_<T>::ioo = X_<T>::init();
+template struct X_<int>;
+
+template <class T>
+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<int>::ioo = X<int>::init();
+template struct X<int>;
+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 <int> class aj {
+public:
+  static a al;
+};
+template <int am> a aj<am>::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 at selectany_init@@3HA" to i8*), i8* bitcast (i32* @"?x@?$A at H@explicit_template_instantiation@@2HA" to i8*), i8* bitcast (i32* @"?ioo@?$X_ at H@@2HA" to i8*), i8* getelementptr inbounds (%struct.A, %struct.A* @"?aoo at S1@@2UA@@A", i32 0, i32 0), i8* bitcast (i32* @"?zoo@@3HA" to i8*), i8* getelementptr inbounds (%struct.S, %struct.S* @"?s@?$ExportedTemplate at H@@2US@@A", i32 0, i32 0), i8* bitcast (i32* @"?x@?$A at H@implicit_template_instantiation@@2HA" to i8*)], section "llvm.metadata"

Modified: cfe/trunk/test/Modules/initializers.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/initializers.cpp?rev=359212&r1=359211&r2=359212&view=diff
==============================================================================
--- cfe/trunk/test/Modules/initializers.cpp (original)
+++ cfe/trunk/test/Modules/initializers.cpp Thu Apr 25 10:45:45 2019
@@ -235,7 +235,6 @@ inline void use(bool b, ...) {
 
 // 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]]()




More information about the cfe-commits mailing list