253 lines · cpp
1// RUN: %clang_cc1 -fms-extensions -fno-threadsafe-statics -emit-llvm %s -o - -mconstructor-aliases -triple=i386-pc-win32 | FileCheck %s2 3// CHECK: @llvm.global_ctors = appending global [5 x { i32, ptr, ptr }] [4// CHECK: { i32, ptr, ptr } { i32 65535, ptr @"??__Eselectany1@@YAXXZ", ptr @"?selectany1@@3US@@A" },5// CHECK: { i32, ptr, ptr } { i32 65535, ptr @"??__Eselectany2@@YAXXZ", ptr @"?selectany2@@3US@@A" },6// CHECK: { i32, ptr, ptr } { i32 65535, ptr @"??__E?s@?$ExportedTemplate@H@@2US@@A@@YAXXZ", ptr @"?s@?$ExportedTemplate@H@@2US@@A" },7// CHECK: { i32, ptr, ptr } { i32 65535, ptr @"??__E?foo@?$B@H@@2VA@@A@@YAXXZ", ptr @"?foo@?$B@H@@2VA@@A" },8// CHECK: { i32, ptr, ptr } { i32 65535, ptr @_GLOBAL__sub_I_microsoft_abi_static_initializers.cpp, ptr null }9// CHECK: ]10 11struct S {12 S();13 ~S();14};15 16S s;17 18// CHECK: define internal void @"??__Es@@YAXXZ"()19// CHECK: call x86_thiscallcc noundef ptr @"??0S@@QAE@XZ"20// CHECK: call i32 @atexit(ptr @"??__Fs@@YAXXZ")21// CHECK: ret void22 23// CHECK: define internal void @"??__Fs@@YAXXZ"()24// CHECK: call x86_thiscallcc void @"??1S@@QAE@XZ"25// CHECK: ret void26 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"() {{.*}} comdat32// CHECK-NOT: @"??_Bselectany133// CHECK: call x86_thiscallcc noundef ptr @"??0S@@QAE@XZ"34// CHECK: ret void35// CHECK: define linkonce_odr dso_local void @"??__Eselectany2@@YAXXZ"() {{.*}} comdat36// CHECK-NOT: @"??_Bselectany237// CHECK: call x86_thiscallcc noundef ptr @"??0S@@QAE@XZ"38// CHECK: ret void39 40// The implicitly instantiated static data member should have initializer41// 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 dso_local void @"?StaticLocal@@YAXXZ"()55// CHECK: load i32, ptr @"?$S1@?1??StaticLocal@@YAXXZ@4IA"56// CHECK: store i32 {{.*}}, ptr @"?$S1@?1??StaticLocal@@YAXXZ@4IA"57// CHECK: ret58 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 dso_local void @"?MultipleStatics@@YAXXZ"()97// CHECK: load i32, ptr @"?$S1@?1??MultipleStatics@@YAXXZ@4IA"98// CHECK: and i32 {{.*}}, 199// CHECK: and i32 {{.*}}, 2100// CHECK: and i32 {{.*}}, 4101// CHECK: and i32 {{.*}}, 8102// CHECK: and i32 {{.*}}, 16103// ...104// CHECK: and i32 {{.*}}, -2147483648105// CHECK: load i32, ptr @"?$S1@?1??MultipleStatics@@YAXXZ@4IA.1"106// CHECK: and i32 {{.*}}, 1107// CHECK: and i32 {{.*}}, 2108// CHECK: and i32 {{.*}}, 4109// CHECK: ret110 111// Force WeakODRLinkage by using templates112class 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 1130 return s;131 }132 static S s; // bit 2133 return s;134}135 136// CHECK-LABEL: define linkonce_odr dso_local noundef nonnull align {{[0-9]+}} dereferenceable({{[0-9]+}}) ptr @"?UnreachableStatic@@YAAAUS@@XZ"() {{.*}} comdat137// CHECK: and i32 {{.*}}, 2138// CHECK: or i32 {{.*}}, 2139// CHECK: ret140 141inline S &getS() {142 static S TheS;143 return TheS;144}145 146// CHECK-LABEL: define linkonce_odr dso_local noundef nonnull align {{[0-9]+}} dereferenceable({{[0-9]+}}) ptr @"?getS@@YAAAUS@@XZ"() {{.*}} comdat147// CHECK: load i32, ptr @"??_B?1??getS@@YAAAUS@@XZ@51"148// CHECK: and i32 {{.*}}, 1149// CHECK: icmp eq i32 {{.*}}, 0150// CHECK: br i1151// init:152// CHECK: or i32 {{.*}}, 1153// CHECK: store i32 {{.*}}, ptr @"??_B?1??getS@@YAAAUS@@XZ@51"154// CHECK: call x86_thiscallcc noundef ptr @"??0S@@QAE@XZ"(ptr {{[^,]*}} @"?TheS@?1??getS@@YAAAUS@@XZ@4U2@A")155// CHECK: call i32 @atexit(ptr @"??__FTheS@?1??getS@@YAAAUS@@XZ@YAXXZ")156// CHECK: br label157// init.end:158// CHECK: ret ptr @"?TheS@?1??getS@@YAAAUS@@XZ@4U2@A"159 160inline int enum_in_function() {161 // CHECK-LABEL: define linkonce_odr dso_local noundef i32 @"?enum_in_function@@YAHXZ"() {{.*}} comdat162 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 169struct T {170 enum e { foo, bar, baz };171 int enum_in_struct() {172 // CHECK-LABEL: define linkonce_odr dso_local x86_thiscallcc noundef i32 @"?enum_in_struct@T@@QAEHXZ"({{.*}}) {{.*}} comdat173 static int x;174 // CHECK: @"?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 dso_local noundef i32 @"?switch_test@@YAHH@Z"(i32 noundef %x) {{.*}} comdat181 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 return 0;198}199 200int f();201inline void switch_test2() {202 // CHECK-LABEL: define linkonce_odr dso_local void @"?switch_test2@@YAXXZ"() {{.*}} comdat203 // CHECK: @"?x@?2??switch_test2@@YAXXZ@4HA"204 switch (1) default: static int x = f();205}206 207namespace DynamicDLLImportInitVSMangling {208 // Failing to pop the ExprEvalContexts when instantiating a dllimport var with209 // dynamic initializer would cause subsequent static local numberings to be210 // incorrect.211 struct NonPOD { NonPOD(); };212 template <typename T> struct A { static NonPOD x; };213 template <typename T> NonPOD A<T>::x;214 template struct __declspec(dllimport) A<int>;215 216 inline int switch_test3() {217 // CHECK-LABEL: define linkonce_odr dso_local noundef i32 @"?switch_test3@DynamicDLLImportInitVSMangling@@YAHXZ"() {{.*}} comdat218 static int local;219 // CHECK: @"?local@?1??switch_test3@DynamicDLLImportInitVSMangling@@YAHXZ@4HA"220 return local++;221 }222}223 224void force_usage() {225 UnreachableStatic();226 getS();227 (void)B<int>::foo; // (void) - force usage228 enum_in_function();229 (void)&T::enum_in_struct;230 switch_test(1);231 switch_test2();232 DynamicDLLImportInitVSMangling::switch_test3();233}234 235// CHECK: define linkonce_odr dso_local void @"??__E?foo@?$B@H@@2VA@@A@@YAXXZ"() {{.*}} comdat236// CHECK-NOT: and237// CHECK-NOT: ?_Bfoo@238// CHECK: call x86_thiscallcc noundef ptr @"??0A@@QAE@XZ"239// CHECK: call i32 @atexit(ptr @"??__F?foo@?$B@H@@2VA@@A@@YAXXZ")240// CHECK: ret void241 242// CHECK: define linkonce_odr dso_local x86_thiscallcc noundef ptr @"??0A@@QAE@XZ"({{.*}}) {{.*}} comdat243 244// CHECK: define linkonce_odr dso_local x86_thiscallcc void @"??1A@@QAE@XZ"({{.*}}) {{.*}} comdat245 246// CHECK: define internal void @"??__F?foo@?$B@H@@2VA@@A@@YAXXZ"247// CHECK: call x86_thiscallcc void @"??1A@@QAE@XZ"{{.*}}foo248// CHECK: ret void249 250// CHECK: define internal void @_GLOBAL__sub_I_microsoft_abi_static_initializers.cpp()251// CHECK: call void @"??__Es@@YAXXZ"()252// CHECK: ret void253