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