1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
|
// RUN: %clang_cc1 -no-opaque-pointers %s -std=c++1y -triple=x86_64-pc-linux -emit-llvm -o - | FileCheck --check-prefix=ELF --check-prefix=ALL %s
// RUN: %clang_cc1 -no-opaque-pointers %s -std=c++1y -triple=x86_64-apple-darwin -emit-llvm -o - | FileCheck --check-prefix=MACHO --check-prefix=ALL %s
// RUN: %clang_cc1 -no-opaque-pointers %s -std=c++1y -triple=x86_64-pc-linux -emit-llvm -fdeclspec -DSELECTANY -o - | FileCheck --check-prefix=ELF-SELECTANY %s
#ifdef SELECTANY
struct S {
S();
~S();
};
int f();
// ELF-SELECTANY: @llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @__cxx_global_var_init, i8* bitcast (i32* @selectany to i8*) }]
// ELF-SELECTANY: @llvm.used = appending global [1 x i8*] [i8* bitcast (i32* @selectany to i8*)]
int __declspec(selectany) selectany = f();
#else
// ALL: ; ModuleID
extern "C" int foo();
template<typename T> struct A { static int a; };
template<typename T> int A<T>::a = foo();
// ALLK-NOT: @_ZN1AIcE1aE
template<> int A<char>::a;
// ALL: @_ZN1AIbE1aE ={{.*}} global i32 10
template<> int A<bool>::a = 10;
// ALL: @llvm.global_ctors = appending global [8 x { i32, void ()*, i8* }]
// ELF: [{ i32, void ()*, i8* } { i32 65535, void ()* @[[unordered1:[^,]*]], i8* bitcast (i32* @_ZN1AIsE1aE to i8*) },
// MACHO: [{ i32, void ()*, i8* } { i32 65535, void ()* @[[unordered1:[^,]*]], i8* null },
// ELF: { i32, void ()*, i8* } { i32 65535, void ()* @[[unordered2:[^,]*]], i8* bitcast (i16* @_Z1xIsE to i8*) },
// MACHO: { i32, void ()*, i8* } { i32 65535, void ()* @[[unordered2:[^,]*]], i8* null },
// ELF: { i32, void ()*, i8* } { i32 65535, void ()* @[[unordered3:[^,]*]], i8* bitcast (i32* @_ZN2ns1aIiE1iE to i8*) },
// MACHO: { i32, void ()*, i8* } { i32 65535, void ()* @[[unordered3:[^,]*]], i8* null },
// ELF: { i32, void ()*, i8* } { i32 65535, void ()* @[[unordered4:[^,]*]], i8* bitcast (i32* @_ZN2ns1b1iIiEE to i8*) },
// MACHO: { i32, void ()*, i8* } { i32 65535, void ()* @[[unordered4:[^,]*]], i8* null },
// ELF: { i32, void ()*, i8* } { i32 65535, void ()* @[[unordered5:[^,]*]], i8* bitcast (i32* @_ZN1AIvE1aE to i8*) },
// MACHO: { i32, void ()*, i8* } { i32 65535, void ()* @[[unordered5:[^,]*]], i8* null },
// ELF: { i32, void ()*, i8* } { i32 65535, void ()* @[[unordered6:[^,]*]], i8* @_Z1xIcE },
// MACHO: { i32, void ()*, i8* } { i32 65535, void ()* @[[unordered6:[^,]*]], i8* null },
// ALL: { i32, void ()*, i8* } { i32 65535, void ()* @[[unordered7:[^,]*]], i8* null },
// ALL: { i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__sub_I_static_member_variable_explicit_specialization.cpp, i8* null }]
/// llvm.used ensures SHT_INIT_ARRAY in a section group cannot be GCed.
// ELF: @llvm.used = appending global [6 x i8*] [i8* bitcast (i32* @_ZN1AIsE1aE to i8*), i8* bitcast (i16* @_Z1xIsE to i8*), i8* bitcast (i32* @_ZN2ns1aIiE1iE to i8*), i8* bitcast (i32* @_ZN2ns1b1iIiEE to i8*), i8* bitcast (i32* @_ZN1AIvE1aE to i8*), i8* @_Z1xIcE]
template int A<short>::a; // Unordered
int b = foo();
int c = foo();
int d = A<void>::a; // Unordered
// An explicit specialization is ordered, and goes in __GLOBAL_sub_I_static_member_variable_explicit_specialization.cpp.
template<> struct A<int> { static int a; };
int A<int>::a = foo();
template<typename T> struct S { static T x; static T y; };
template<> int S<int>::x = foo();
template<> int S<int>::y = S<int>::x;
template<typename T> T x = foo();
template short x<short>; // Unordered
template<> int x<int> = foo();
int e = x<char>; // Unordered
namespace ns {
template <typename T> struct a {
static int i;
};
template<typename T> int a<T>::i = foo();
template struct a<int>;
struct b {
template <typename T> static T i;
};
template<typename T> T b::i = foo();
template int b::i<int>;
}
namespace {
template<typename T> struct Internal { static int a; };
template<typename T> int Internal<T>::a = foo();
}
int *use_internal_a = &Internal<int>::a;
#endif
// ALL: define internal void @[[unordered1]](
// ALL: call i32 @foo()
// ALL: store {{.*}} @_ZN1AIsE1aE
// ALL: ret
// ALL: define internal void @[[unordered2]](
// ALL: call i32 @foo()
// ALL: store {{.*}} @_Z1xIsE
// ALL: ret
// ALL: define internal void @[[unordered3]](
// ALL: call i32 @foo()
// ALL: store {{.*}} @_ZN2ns1aIiE1iE
// ALL: ret
// ALL: define internal void @[[unordered4]](
// ALL: call i32 @foo()
// ALL: store {{.*}} @_ZN2ns1b1iIiEE
// ALL: ret
// ALL: define internal void @[[unordered5]](
// ALL: call i32 @foo()
// ALL: store {{.*}} @_ZN1AIvE1aE
// ALL: ret
// ALL: define internal void @[[unordered6]](
// ALL: call i32 @foo()
// ALL: store {{.*}} @_Z1xIcE
// ALL: ret
// ALL: define internal void @[[unordered7]](
// ALL: call i32 @foo()
// ALL: store {{.*}} @_ZN12_GLOBAL__N_18InternalIiE1aE
// ALL: ret
// ALL: define internal void @_GLOBAL__sub_I_static_member_variable_explicit_specialization.cpp()
// We call unique stubs for every ordered dynamic initializer in the TU.
// ALL: call
// ALL: call
// ALL: call
// ALL: call
// ALL: call
// ALL: call
// ALL: call
// ALL: call
// ALL-NOT: call
// ALL: ret
|