1 // RUN: %clang_cc1 -fms-extensions -fno-threadsafe-statics -emit-llvm %s -o - -mconstructor-aliases -triple=i386-pc-win32 | FileCheck %s
2
3 // CHECK: @llvm.global_ctors = appending global [5 x { i32, void ()*, i8* }] [
4 // CHECK: { i32, void ()*, i8* } { i32 65535, void ()* @"\01??__Eselectany1@@YAXXZ", i8* getelementptr inbounds (%struct.S, %struct.S* @"\01?selectany1@@3US@@A", i32 0, i32 0) },
5 // CHECK: { i32, void ()*, i8* } { i32 65535, void ()* @"\01??__Eselectany2@@YAXXZ", i8* getelementptr inbounds (%struct.S, %struct.S* @"\01?selectany2@@3US@@A", i32 0, i32 0) },
6 // CHECK: { i32, void ()*, i8* } { i32 65535, void ()* @"\01??__Es@?$ExportedTemplate@H@@2US@@A@YAXXZ", i8* getelementptr inbounds (%struct.S, %struct.S* @"\01?s@?$ExportedTemplate@H@@2US@@A", i32 0, i32 0) },
7 // CHECK: { i32, void ()*, i8* } { i32 65535, void ()* @"\01??__Efoo@?$B@H@@2VA@@A@YAXXZ", i8* bitcast (%class.A* @"\01?foo@?$B@H@@2VA@@A" to i8*) },
8 // CHECK: { i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__sub_I_microsoft_abi_static_initializers.cpp, i8* null }
9 // CHECK: ]
10
11 struct S {
12 S();
13 ~S();
14 };
15
16 S s;
17
18 // CHECK: define internal void @"\01??__Es@@YAXXZ"()
19 // CHECK: call x86_thiscallcc %struct.S* @"\01??0S@@QAE@XZ"
20 // CHECK: call i32 @atexit(void ()* @"\01??__Fs@@YAXXZ")
21 // CHECK: ret void
22
23 // CHECK: define internal void @"\01??__Fs@@YAXXZ"()
24 // CHECK: call x86_thiscallcc void @"\01??1S@@QAE@XZ"
25 // CHECK: ret void
26
27 // These globals should have initializers comdat associative with the global.
28 // See @llvm.global_ctors above.
29 __declspec(selectany) S selectany1;
30 __declspec(selectany) S selectany2;
31 // CHECK: define linkonce_odr void @"\01??__Eselectany1@@YAXXZ"() {{.*}} comdat
32 // CHECK-NOT: @"\01??_Bselectany1
33 // CHECK: call x86_thiscallcc %struct.S* @"\01??0S@@QAE@XZ"
34 // CHECK: ret void
35 // CHECK: define linkonce_odr void @"\01??__Eselectany2@@YAXXZ"() {{.*}} comdat
36 // CHECK-NOT: @"\01??_Bselectany2
37 // CHECK: call x86_thiscallcc %struct.S* @"\01??0S@@QAE@XZ"
38 // CHECK: ret void
39
40 // The implicitly instantiated static data member should have initializer
41 // comdat associative with the global.
42 template <typename T> struct __declspec(dllexport) ExportedTemplate {
43 static S s;
44 };
45 template <typename T> S ExportedTemplate<T>::s;
useExportedTemplate(ExportedTemplate<int> x)46 void useExportedTemplate(ExportedTemplate<int> x) {
47 (void)x.s;
48 }
49
StaticLocal()50 void StaticLocal() {
51 static S TheS;
52 }
53
54 // CHECK-LABEL: define void @"\01?StaticLocal@@YAXXZ"()
55 // CHECK: load i32, i32* @"\01?$S1@?1??StaticLocal@@YAXXZ@4IA"
56 // CHECK: store i32 {{.*}}, i32* @"\01?$S1@?1??StaticLocal@@YAXXZ@4IA"
57 // CHECK: ret
58
MultipleStatics()59 void MultipleStatics() {
60 static S S1;
61 static S S2;
62 static S S3;
63 static S S4;
64 static S S5;
65 static S S6;
66 static S S7;
67 static S S8;
68 static S S9;
69 static S S10;
70 static S S11;
71 static S S12;
72 static S S13;
73 static S S14;
74 static S S15;
75 static S S16;
76 static S S17;
77 static S S18;
78 static S S19;
79 static S S20;
80 static S S21;
81 static S S22;
82 static S S23;
83 static S S24;
84 static S S25;
85 static S S26;
86 static S S27;
87 static S S28;
88 static S S29;
89 static S S30;
90 static S S31;
91 static S S32;
92 static S S33;
93 static S S34;
94 static S S35;
95 }
96 // CHECK-LABEL: define void @"\01?MultipleStatics@@YAXXZ"()
97 // CHECK: load i32, i32* @"\01?$S1@?1??MultipleStatics@@YAXXZ@4IA"
98 // CHECK: and i32 {{.*}}, 1
99 // CHECK: and i32 {{.*}}, 2
100 // CHECK: and i32 {{.*}}, 4
101 // CHECK: and i32 {{.*}}, 8
102 // CHECK: and i32 {{.*}}, 16
103 // ...
104 // CHECK: and i32 {{.*}}, -2147483648
105 // CHECK: load i32, i32* @"\01?$S1@?1??MultipleStatics@@YAXXZ@4IA.1"
106 // CHECK: and i32 {{.*}}, 1
107 // CHECK: and i32 {{.*}}, 2
108 // CHECK: and i32 {{.*}}, 4
109 // CHECK: ret
110
111 // Force WeakODRLinkage by using templates
112 class A {
113 public:
A()114 A() {}
~A()115 ~A() {}
116 int a;
117 };
118
119 template<typename T>
120 class B {
121 public:
122 static A foo;
123 };
124
125 template<typename T> A B<T>::foo;
126
UnreachableStatic()127 inline S &UnreachableStatic() {
128 if (0) {
129 static S s; // bit 1
130 return s;
131 }
132 static S s; // bit 2
133 return s;
134 }
135
136 // CHECK-LABEL: define linkonce_odr dereferenceable({{[0-9]+}}) %struct.S* @"\01?UnreachableStatic@@YAAAUS@@XZ"() {{.*}} comdat
137 // CHECK: and i32 {{.*}}, 2
138 // CHECK: or i32 {{.*}}, 2
139 // CHECK: ret
140
getS()141 inline S &getS() {
142 static S TheS;
143 return TheS;
144 }
145
146 // CHECK-LABEL: define linkonce_odr dereferenceable({{[0-9]+}}) %struct.S* @"\01?getS@@YAAAUS@@XZ"() {{.*}} comdat
147 // CHECK: load i32, i32* @"\01??_B?1??getS@@YAAAUS@@XZ@51"
148 // CHECK: and i32 {{.*}}, 1
149 // CHECK: icmp ne i32 {{.*}}, 0
150 // CHECK: br i1
151 // init:
152 // CHECK: or i32 {{.*}}, 1
153 // CHECK: store i32 {{.*}}, i32* @"\01??_B?1??getS@@YAAAUS@@XZ@51"
154 // CHECK: call x86_thiscallcc %struct.S* @"\01??0S@@QAE@XZ"(%struct.S* @"\01?TheS@?1??getS@@YAAAUS@@XZ@4U2@A")
155 // CHECK: call i32 @atexit(void ()* @"\01??__FTheS@?1??getS@@YAAAUS@@XZ@YAXXZ")
156 // CHECK: br label
157 // init.end:
158 // CHECK: ret %struct.S* @"\01?TheS@?1??getS@@YAAAUS@@XZ@4U2@A"
159
enum_in_function()160 inline int enum_in_function() {
161 // CHECK-LABEL: define linkonce_odr i32 @"\01?enum_in_function@@YAHXZ"() {{.*}} comdat
162 static enum e { foo, bar, baz } x;
163 // CHECK: @"\01?x@?1??enum_in_function@@YAHXZ@4W4e@?1??1@YAHXZ@A"
164 static int y;
165 // CHECK: @"\01?y@?1??enum_in_function@@YAHXZ@4HA"
166 return x + y;
167 };
168
169 struct T {
170 enum e { foo, bar, baz };
enum_in_structT171 int enum_in_struct() {
172 // CHECK-LABEL: define linkonce_odr x86_thiscallcc i32 @"\01?enum_in_struct@T@@QAEHXZ"({{.*}}) {{.*}} comdat
173 static int x;
174 // CHECK: @"\01?x@?1??enum_in_struct@T@@QAEHXZ@4HA"
175 return x++;
176 }
177 };
178
switch_test(int x)179 inline int switch_test(int x) {
180 // CHECK-LABEL: define linkonce_odr i32 @"\01?switch_test@@YAHH@Z"(i32 %x) {{.*}} comdat
181 switch (x) {
182 static int a;
183 // CHECK: @"\01?a@?3??switch_test@@YAHH@Z@4HA"
184 case 0:
185 a++;
186 return 1;
187 case 1:
188 static int b;
189 // CHECK: @"\01?b@?3??switch_test@@YAHH@Z@4HA"
190 return b++;
191 case 2: {
192 static int c;
193 // CHECK: @"\01?c@?4??switch_test@@YAHH@Z@4HA"
194 return b + c++;
195 }
196 };
197 }
198
199 int f();
switch_test2()200 inline void switch_test2() {
201 // CHECK-LABEL: define linkonce_odr void @"\01?switch_test2@@YAXXZ"() {{.*}} comdat
202 // CHECK: @"\01?x@?2??switch_test2@@YAXXZ@4HA"
203 switch (1) default: static int x = f();
204 }
205
206 namespace DynamicDLLImportInitVSMangling {
207 // Failing to pop the ExprEvalContexts when instantiating a dllimport var with
208 // dynamic initializer would cause subsequent static local numberings to be
209 // incorrect.
210 struct NonPOD { NonPOD(); };
211 template <typename T> struct A { static NonPOD x; };
212 template <typename T> NonPOD A<T>::x;
213 template struct __declspec(dllimport) A<int>;
214
switch_test3()215 inline int switch_test3() {
216 // CHECK-LABEL: define linkonce_odr i32 @"\01?switch_test3@DynamicDLLImportInitVSMangling@@YAHXZ"() {{.*}} comdat
217 static int local;
218 // CHECK: @"\01?local@?1??switch_test3@DynamicDLLImportInitVSMangling@@YAHXZ@4HA"
219 return local++;
220 }
221 }
222
force_usage()223 void force_usage() {
224 UnreachableStatic();
225 getS();
226 (void)B<int>::foo; // (void) - force usage
227 enum_in_function();
228 (void)&T::enum_in_struct;
229 switch_test(1);
230 switch_test2();
231 DynamicDLLImportInitVSMangling::switch_test3();
232 }
233
234 // CHECK: define linkonce_odr void @"\01??__Efoo@?$B@H@@2VA@@A@YAXXZ"() {{.*}} comdat
235 // CHECK-NOT: and
236 // CHECK-NOT: ?_Bfoo@
237 // CHECK: call x86_thiscallcc %class.A* @"\01??0A@@QAE@XZ"
238 // CHECK: call i32 @atexit(void ()* @"\01??__Ffoo@?$B@H@@2VA@@A@YAXXZ")
239 // CHECK: ret void
240
241 // CHECK: define linkonce_odr x86_thiscallcc %class.A* @"\01??0A@@QAE@XZ"({{.*}}) {{.*}} comdat
242
243 // CHECK: define linkonce_odr x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}}) {{.*}} comdat
244
245 // CHECK: define internal void @"\01??__Ffoo@?$B@H@@2VA@@A@YAXXZ"
246 // CHECK: call x86_thiscallcc void @"\01??1A@@QAE@XZ"{{.*}}foo
247 // CHECK: ret void
248
249 // CHECK: define internal void @_GLOBAL__sub_I_microsoft_abi_static_initializers.cpp()
250 // CHECK: call void @"\01??__Es@@YAXXZ"()
251 // CHECK: ret void
252