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