diff options
Diffstat (limited to 'test/CodeGenCXX/microsoft-abi-static-initializers.cpp')
-rw-r--r-- | test/CodeGenCXX/microsoft-abi-static-initializers.cpp | 123 |
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 } |