summaryrefslogtreecommitdiffstats
path: root/test/CodeGenCXX/microsoft-abi-static-initializers.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'test/CodeGenCXX/microsoft-abi-static-initializers.cpp')
-rw-r--r--test/CodeGenCXX/microsoft-abi-static-initializers.cpp123
1 files changed, 103 insertions, 20 deletions
diff --git a/test/CodeGenCXX/microsoft-abi-static-initializers.cpp b/test/CodeGenCXX/microsoft-abi-static-initializers.cpp
index c0b9722..5f74c54 100644
--- a/test/CodeGenCXX/microsoft-abi-static-initializers.cpp
+++ b/test/CodeGenCXX/microsoft-abi-static-initializers.cpp
@@ -1,8 +1,9 @@
-// RUN: %clang_cc1 -emit-llvm %s -o - -mconstructor-aliases -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck %s
+// RUN: %clang_cc1 -fms-extensions -emit-llvm %s -o - -mconstructor-aliases -triple=i386-pc-win32 | FileCheck %s
-// CHECK: @llvm.global_ctors = appending global [2 x { i32, void ()* }]
-// CHECK: [{ i32, void ()* } { i32 65535, void ()* @"\01??__Efoo@?$B@H@@YAXXZ" },
-// CHECK: { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I_a }]
+// CHECK: @llvm.global_ctors = appending global [2 x { i32, void ()*, i8* }]
+// CHECK: [{ i32, void ()*, i8* } { i32 65535, void ()* @"\01??__Efoo@?$B@H@@2VA@@A@YAXXZ",
+// CHECK: i8* bitcast (%class.A* @"\01?foo@?$B@H@@2VA@@A" to i8*) },
+// CHECK: { i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__sub_I_microsoft_abi_static_initializers.cpp, i8* null }]
struct S {
S();
@@ -11,21 +12,34 @@ struct S {
S s;
-// CHECK: define internal void @"\01??__Es@@YAXXZ"() [[NUW:#[0-9]+]]
-// CHECK: %{{[.0-9A-Z_a-z]+}} = call x86_thiscallcc %struct.S* @"\01??0S@@QAE@XZ"
+// CHECK: define internal void @"\01??__Es@@YAXXZ"()
+// CHECK: call x86_thiscallcc %struct.S* @"\01??0S@@QAE@XZ"
// CHECK: call i32 @atexit(void ()* @"\01??__Fs@@YAXXZ")
// CHECK: ret void
-// CHECK: define internal void @"\01??__Fs@@YAXXZ"() [[NUW]] {
+// CHECK: define internal void @"\01??__Fs@@YAXXZ"()
// CHECK: call x86_thiscallcc void @"\01??1S@@QAE@XZ"
// CHECK: ret void
+// These globals should use distinct guard variables, and not different bits of
+// the same global.
+__declspec(selectany) S selectany1;
+__declspec(selectany) S selectany2;
+// CHECK: define linkonce_odr void @"\01??__Eselectany1@@YAXXZ"()
+// CHECK-NOT: @"\01??_Bselectany1
+// CHECK: call x86_thiscallcc %struct.S* @"\01??0S@@QAE@XZ"
+// CHECK: ret void
+// CHECK: define linkonce_odr void @"\01??__Eselectany2@@YAXXZ"()
+// CHECK-NOT: @"\01??_Bselectany2
+// CHECK: call x86_thiscallcc %struct.S* @"\01??0S@@QAE@XZ"
+// CHECK: ret void
+
void StaticLocal() {
static S TheS;
}
// CHECK-LABEL: define void @"\01?StaticLocal@@YAXXZ"()
-// CHECK: load i32* @"\01?$S1@?1??StaticLocal@@YAXXZ@4IA"
-// CHECK: store i32 {{.*}}, i32* @"\01?$S1@?1??StaticLocal@@YAXXZ@4IA"
+// CHECK: load i32* @"\01?$S1@?0??StaticLocal@@YAXXZ@4IA"
+// CHECK: store i32 {{.*}}, i32* @"\01?$S1@?0??StaticLocal@@YAXXZ@4IA"
// CHECK: ret
void MultipleStatics() {
@@ -66,7 +80,7 @@ void MultipleStatics() {
static S S35;
}
// CHECK-LABEL: define void @"\01?MultipleStatics@@YAXXZ"()
-// CHECK: load i32* @"\01?$S1@?1??MultipleStatics@@YAXXZ@4IA"
+// CHECK: load i32* @"\01?$S1@?0??MultipleStatics@@YAXXZ@4IA"
// CHECK: and i32 {{.*}}, 1
// CHECK: and i32 {{.*}}, 2
// CHECK: and i32 {{.*}}, 4
@@ -74,7 +88,7 @@ void MultipleStatics() {
// CHECK: and i32 {{.*}}, 16
// ...
// CHECK: and i32 {{.*}}, -2147483648
-// CHECK: load i32* @"\01?$S1@?1??MultipleStatics@@YAXXZ@4IA1"
+// CHECK: load i32* @"\01?$S1@?0??MultipleStatics@@YAXXZ@4IA1"
// CHECK: and i32 {{.*}}, 1
// CHECK: and i32 {{.*}}, 2
// CHECK: and i32 {{.*}}, 4
@@ -85,6 +99,7 @@ class A {
public:
A() {}
~A() {}
+ int a;
};
template<typename T>
@@ -104,7 +119,7 @@ inline S &UnreachableStatic() {
return s;
}
-// CHECK-LABEL: define linkonce_odr %struct.S* @"\01?UnreachableStatic@@YAAAUS@@XZ"()
+// CHECK-LABEL: define linkonce_odr dereferenceable({{[0-9]+}}) %struct.S* @"\01?UnreachableStatic@@YAAAUS@@XZ"()
// CHECK: and i32 {{.*}}, 2
// CHECK: or i32 {{.*}}, 2
// CHECK: ret
@@ -114,7 +129,7 @@ inline S &getS() {
return TheS;
}
-// CHECK-LABEL: define linkonce_odr %struct.S* @"\01?getS@@YAAAUS@@XZ"
+// CHECK-LABEL: define linkonce_odr dereferenceable({{[0-9]+}}) %struct.S* @"\01?getS@@YAAAUS@@XZ"
// CHECK: load i32* @"\01??_B?1??getS@@YAAAUS@@XZ@51"
// CHECK: and i32 {{.*}}, 1
// CHECK: icmp ne i32 {{.*}}, 0
@@ -128,27 +143,95 @@ inline S &getS() {
// init.end:
// CHECK: ret %struct.S* @"\01?TheS@?1??getS@@YAAAUS@@XZ@4U2@A"
+inline int enum_in_function() {
+ // CHECK-LABEL: define linkonce_odr i32 @"\01?enum_in_function@@YAHXZ"()
+ static enum e { foo, bar, baz } x;
+ // CHECK: @"\01?x@?1??enum_in_function@@YAHXZ@4W4e@?1??1@YAHXZ@A"
+ static int y;
+ // CHECK: @"\01?y@?1??enum_in_function@@YAHXZ@4HA"
+ return x + y;
+};
+
+struct T {
+ enum e { foo, bar, baz };
+ int enum_in_struct() {
+ // CHECK-LABEL: define linkonce_odr x86_thiscallcc i32 @"\01?enum_in_struct@T@@QAEHXZ"
+ static int x;
+ // CHECK: @"\01?x@?1??enum_in_struct@T@@QAEHXZ@4HA"
+ return x++;
+ }
+};
+
+inline int switch_test(int x) {
+ // CHECK-LABEL: define linkonce_odr i32 @"\01?switch_test@@YAHH@Z"(i32 %x)
+ switch (x) {
+ static int a;
+ // CHECK: @"\01?a@?3??switch_test@@YAHH@Z@4HA"
+ case 0:
+ a++;
+ return 1;
+ case 1:
+ static int b;
+ // CHECK: @"\01?b@?3??switch_test@@YAHH@Z@4HA"
+ return b++;
+ case 2: {
+ static int c;
+ // CHECK: @"\01?c@?4??switch_test@@YAHH@Z@4HA"
+ return b + c++;
+ }
+ };
+}
+
+int f();
+inline void switch_test2() {
+ // CHECK-LABEL: define linkonce_odr void @"\01?switch_test2@@YAXXZ"()
+ // CHECK: @"\01?x@?2??switch_test2@@YAXXZ@4HA"
+ switch (1) default: static int x = f();
+}
+
+namespace DynamicDLLImportInitVSMangling {
+ // Failing to pop the ExprEvalContexts when instantiating a dllimport var with
+ // dynamic initializer would cause subsequent static local numberings to be
+ // incorrect.
+ struct NonPOD { NonPOD(); };
+ template <typename T> struct A { static NonPOD x; };
+ template <typename T> NonPOD A<T>::x;
+ template struct __declspec(dllimport) A<int>;
+
+ inline int switch_test3() {
+ // CHECK-LABEL: define linkonce_odr i32 @"\01?switch_test3@DynamicDLLImportInitVSMangling@@YAHXZ"
+ static int local;
+ // CHECK: @"\01?local@?1??switch_test3@DynamicDLLImportInitVSMangling@@YAHXZ@4HA"
+ return local++;
+ }
+}
+
void force_usage() {
UnreachableStatic();
getS();
(void)B<int>::foo; // (void) - force usage
+ enum_in_function();
+ (void)&T::enum_in_struct;
+ switch_test(1);
+ switch_test2();
+ DynamicDLLImportInitVSMangling::switch_test3();
}
-// CHECK: define internal void @"\01??__Efoo@?$B@H@@YAXXZ"() [[NUW]]
-// CHECK: %{{[.0-9A-Z_a-z]+}} = call x86_thiscallcc %class.A* @"\01??0A@@QAE@XZ"
-// CHECK: call i32 @atexit(void ()* @"\01??__Ffoo@?$B@H@@YAXXZ")
+// CHECK: define linkonce_odr void @"\01??__Efoo@?$B@H@@2VA@@A@YAXXZ"()
+// CHECK-NOT: and
+// CHECK-NOT: ?_Bfoo@
+// CHECK: call x86_thiscallcc %class.A* @"\01??0A@@QAE@XZ"
+// CHECK: call i32 @atexit(void ()* @"\01??__Ffoo@?$B@H@@2VA@@A@YAXXZ")
// CHECK: ret void
// CHECK: define linkonce_odr x86_thiscallcc %class.A* @"\01??0A@@QAE@XZ"
// CHECK: define linkonce_odr x86_thiscallcc void @"\01??1A@@QAE@XZ"
-// CHECK: define internal void @"\01??__Ffoo@?$B@H@@YAXXZ"
+// CHECK: define internal void @"\01??__Ffoo@?$B@H@@2VA@@A@YAXXZ"
// CHECK: call x86_thiscallcc void @"\01??1A@@QAE@XZ"{{.*}}foo
// CHECK: ret void
-// CHECK: define internal void @_GLOBAL__I_a() [[NUW]] {
+// CHECK: define internal void @_GLOBAL__sub_I_microsoft_abi_static_initializers.cpp()
// CHECK: call void @"\01??__Es@@YAXXZ"()
// CHECK: ret void
-
-// CHECK: attributes [[NUW]] = { nounwind }
OpenPOWER on IntegriCloud