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 ()* @"??__Eselectany1@@YAXXZ", i8* getelementptr inbounds (%struct.S, %struct.S* @"?selectany1@@3US@@A", i32 0, i32 0) },
5 // CHECK: { i32, void ()*, i8* } { i32 65535, void ()* @"??__Eselectany2@@YAXXZ", i8* getelementptr inbounds (%struct.S, %struct.S* @"?selectany2@@3US@@A", i32 0, i32 0) },
6 // CHECK: { i32, void ()*, i8* } { i32 65535, void ()* @"??__E?s@?$ExportedTemplate@H@@2US@@A@@YAXXZ", i8* getelementptr inbounds (%struct.S, %struct.S* @"?s@?$ExportedTemplate@H@@2US@@A", i32 0, i32 0) },
7 // CHECK: { i32, void ()*, i8* } { i32 65535, void ()* @"??__E?foo@?$B@H@@2VA@@A@@YAXXZ", i8* bitcast (%class.A* @"?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 @"??__Es@@YAXXZ"()
19 // CHECK: call x86_thiscallcc %struct.S* @"??0S@@QAE@XZ"
20 // CHECK: call i32 @atexit(void ()* @"??__Fs@@YAXXZ")
21 // CHECK: ret void
22 
23 // CHECK: define internal void @"??__Fs@@YAXXZ"()
24 // CHECK: call x86_thiscallcc void @"??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 dso_local void @"??__Eselectany1@@YAXXZ"() {{.*}} comdat
32 // CHECK-NOT: @"??_Bselectany1
33 // CHECK: call x86_thiscallcc %struct.S* @"??0S@@QAE@XZ"
34 // CHECK: ret void
35 // CHECK: define linkonce_odr dso_local void @"??__Eselectany2@@YAXXZ"() {{.*}} comdat
36 // CHECK-NOT: @"??_Bselectany2
37 // CHECK: call x86_thiscallcc %struct.S* @"??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 dso_local void @"?StaticLocal@@YAXXZ"()
55 // CHECK: load i32, i32* @"?$S1@?1??StaticLocal@@YAXXZ@4IA"
56 // CHECK: store i32 {{.*}}, i32* @"?$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 dso_local void @"?MultipleStatics@@YAXXZ"()
97 // CHECK: load i32, i32* @"?$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* @"?$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 dso_local nonnull align {{[0-9]+}} dereferenceable({{[0-9]+}}) %struct.S* @"?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 dso_local nonnull align {{[0-9]+}} dereferenceable({{[0-9]+}}) %struct.S* @"?getS@@YAAAUS@@XZ"() {{.*}} comdat
147 // CHECK: load i32, i32* @"??_B?1??getS@@YAAAUS@@XZ@51"
148 // CHECK: and i32 {{.*}}, 1
149 // CHECK: icmp eq i32 {{.*}}, 0
150 // CHECK: br i1
151 //   init:
152 // CHECK: or i32 {{.*}}, 1
153 // CHECK: store i32 {{.*}}, i32* @"??_B?1??getS@@YAAAUS@@XZ@51"
154 // CHECK: call x86_thiscallcc %struct.S* @"??0S@@QAE@XZ"(%struct.S* {{[^,]*}} @"?TheS@?1??getS@@YAAAUS@@XZ@4U2@A")
155 // CHECK: call i32 @atexit(void ()* @"??__FTheS@?1??getS@@YAAAUS@@XZ@YAXXZ")
156 // CHECK: br label
157 //   init.end:
158 // CHECK: ret %struct.S* @"?TheS@?1??getS@@YAAAUS@@XZ@4U2@A"
159 
enum_in_function()160 inline int enum_in_function() {
161   // CHECK-LABEL: define linkonce_odr dso_local i32 @"?enum_in_function@@YAHXZ"() {{.*}} comdat
162   static enum e { foo, bar, baz } x;
163   // CHECK: @"?x@?1??enum_in_function@@YAHXZ@4W4e@?1??1@YAHXZ@A"
164   static int y;
165   // CHECK: @"?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 dso_local x86_thiscallcc i32 @"?enum_in_struct@T@@QAEHXZ"({{.*}}) {{.*}} comdat
173     static int x;
174     // CHECK: @"?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 dso_local i32 @"?switch_test@@YAHH@Z"(i32 %x) {{.*}} comdat
181   switch (x) {
182     static int a;
183     // CHECK: @"?a@?3??switch_test@@YAHH@Z@4HA"
184     case 0:
185       a++;
186       return 1;
187     case 1:
188       static int b;
189       // CHECK: @"?b@?3??switch_test@@YAHH@Z@4HA"
190       return b++;
191     case 2: {
192       static int c;
193       // CHECK: @"?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 dso_local void @"?switch_test2@@YAXXZ"() {{.*}} comdat
202   // CHECK: @"?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 dso_local i32 @"?switch_test3@DynamicDLLImportInitVSMangling@@YAHXZ"() {{.*}} comdat
217     static int local;
218     // CHECK: @"?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 dso_local void @"??__E?foo@?$B@H@@2VA@@A@@YAXXZ"() {{.*}} comdat
235 // CHECK-NOT: and
236 // CHECK-NOT: ?_Bfoo@
237 // CHECK: call x86_thiscallcc %class.A* @"??0A@@QAE@XZ"
238 // CHECK: call i32 @atexit(void ()* @"??__F?foo@?$B@H@@2VA@@A@@YAXXZ")
239 // CHECK: ret void
240 
241 // CHECK: define linkonce_odr dso_local x86_thiscallcc %class.A* @"??0A@@QAE@XZ"({{.*}}) {{.*}} comdat
242 
243 // CHECK: define linkonce_odr dso_local x86_thiscallcc void @"??1A@@QAE@XZ"({{.*}}) {{.*}} comdat
244 
245 // CHECK: define internal void @"??__F?foo@?$B@H@@2VA@@A@@YAXXZ"
246 // CHECK: call x86_thiscallcc void @"??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 @"??__Es@@YAXXZ"()
251 // CHECK: ret void
252