Jennifer Yu | c19f4f8 | 2019-04-25 17:45:45 +0000 | [diff] [blame] | 1 | // RUN: %clang_cc1 %s -triple=i686-pc-win32 -fms-extensions -emit-llvm -o - | FileCheck %s |
| 2 | // RUN: %clang_cc1 %s -triple=x86_64-pc-win32 -fms-extensions -emit-llvm -o - | FileCheck %s |
| 3 | // RUN: %clang_cc1 %s -triple=i686-pc-windows-msvc -fms-extensions -emit-llvm -o - | FileCheck %s |
| 4 | // RUN: %clang_cc1 %s -triple=x86_64-pc-windows-msvc -fms-extensions -emit-llvm -o - | FileCheck %s |
| 5 | |
| 6 | struct S { |
| 7 | S(); |
| 8 | ~S(); |
| 9 | }; |
| 10 | |
| 11 | template <typename T> struct __declspec(dllexport) ExportedTemplate { |
| 12 | static S s; |
| 13 | }; |
| 14 | template <typename T> S ExportedTemplate<T>::s; |
| 15 | void useExportedTemplate(ExportedTemplate<int> x) { |
| 16 | (void)x.s; |
| 17 | } |
| 18 | int f(); |
| 19 | namespace selectany_init { |
| 20 | // MS don't put selectany static var in the linker directive, init routine |
| 21 | // f() is not getting called if x is not referenced. |
| 22 | int __declspec(selectany) x = f(); |
| 23 | inline int __declspec(selectany) x1 = f(); |
| 24 | } |
| 25 | |
| 26 | namespace explicit_template_instantiation { |
| 27 | template <typename T> struct A { static int x; }; |
| 28 | template <typename T> int A<T>::x = f(); |
| 29 | template struct A<int>; |
| 30 | } |
| 31 | |
| 32 | namespace implicit_template_instantiation { |
| 33 | template <typename T> struct A { static int x; }; |
| 34 | template <typename T> int A<T>::x = f(); |
| 35 | int g() { return A<int>::x; } |
| 36 | } |
| 37 | |
| 38 | |
| 39 | template <class T> |
| 40 | struct X_ { |
| 41 | static T ioo; |
| 42 | static T init(); |
| 43 | }; |
| 44 | template <class T> T X_<T>::ioo = X_<T>::init(); |
| 45 | template struct X_<int>; |
| 46 | |
| 47 | template <class T> |
| 48 | struct X { |
| 49 | static T ioo; |
| 50 | static T init(); |
| 51 | }; |
| 52 | // template specialized static data don't need in llvm.used, |
| 53 | // the static init routine get call from _GLOBAL__sub_I_ routines. |
| 54 | template <> int X<int>::ioo = X<int>::init(); |
| 55 | template struct X<int>; |
| 56 | class a { |
| 57 | public: |
| 58 | a(); |
| 59 | }; |
| 60 | // For the static var inside unnamed namespace, the object is local to TU. |
| 61 | // No need to put static var in the linker directive. |
| 62 | // The static init routine is called before main. |
| 63 | namespace { |
| 64 | template <int> class aj { |
| 65 | public: |
| 66 | static a al; |
| 67 | }; |
| 68 | template <int am> a aj<am>::al; |
| 69 | class b : aj<3> { |
| 70 | void c(); |
| 71 | }; |
| 72 | void b::c() { al; } |
| 73 | } |
| 74 | |
| 75 | // C++17, inline static data member also need to use |
| 76 | struct A |
| 77 | { |
| 78 | A(); |
| 79 | ~A(); |
| 80 | }; |
| 81 | |
| 82 | struct S1 |
| 83 | { |
| 84 | inline static A aoo; // C++17 inline variable, thus also a definition |
| 85 | }; |
| 86 | |
| 87 | int foo(); |
| 88 | inline int zoo = foo(); |
| 89 | inline static int boo = foo(); |
| 90 | |
| 91 | |
| 92 | // 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" |