1// RUN: %clang_cc1 -fms-extensions -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
11struct S {
12  S();
13  ~S();
14};
15
16S 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.
42template <typename T> struct __declspec(dllexport) ExportedTemplate {
43  static S s;
44};
45template <typename T> S ExportedTemplate<T>::s;
46void useExportedTemplate(ExportedTemplate<int> x) {
47  (void)x.s;
48}
49
50void 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
59void 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@4IA1"
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
112class A {
113 public:
114  A() {}
115  ~A() {}
116  int a;
117};
118
119template<typename T>
120class B {
121 public:
122  static A foo;
123};
124
125template<typename T> A B<T>::foo;
126
127inline 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
141inline 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
160inline 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
169struct T {
170  enum e { foo, bar, baz };
171  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
179inline 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
199int f();
200inline 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
206namespace 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
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
223void 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