diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2017-01-02 19:18:08 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2017-01-02 19:18:08 +0000 |
| commit | bab175ec4b075c8076ba14c762900392533f6ee4 (patch) | |
| tree | 01f4f29419a2cb10abe13c1e63cd2a66068b0137 /test/CodeGenCXX | |
| parent | 8b7a8012d223fac5d17d16a66bb39168a9a1dfc0 (diff) | |
Notes
Diffstat (limited to 'test/CodeGenCXX')
174 files changed, 2996 insertions, 516 deletions
diff --git a/test/CodeGenCXX/PR26569.cpp b/test/CodeGenCXX/PR26569.cpp index 3e2d2ffeba14..859b6e26f0c4 100644 --- a/test/CodeGenCXX/PR26569.cpp +++ b/test/CodeGenCXX/PR26569.cpp @@ -1,6 +1,6 @@ -// RUN: %clang_cc1 -triple i686-pc-win32 -fms-extensions -emit-llvm -O1 -disable-llvm-optzns %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple i686-pc-win32 -fms-extensions -emit-llvm -O1 -disable-llvm-passes %s -o - | FileCheck %s -class A { +class __declspec(dllimport) A { virtual void m_fn1(); }; template <typename> @@ -9,12 +9,12 @@ class B : virtual A {}; extern template class __declspec(dllimport) B<int>; class __declspec(dllexport) C : B<int> {}; -// CHECK-DAG: @[[VTABLE_C:.*]] = private unnamed_addr constant [2 x i8*] [i8* bitcast (%rtti.CompleteObjectLocator* @"\01??_R4C@@6B@" to i8*), i8* bitcast (void (%class.A*)* @"\01?m_fn1@A@@EAEXXZ" to i8*)] -// CHECK-DAG: @[[VTABLE_B:.*]] = private unnamed_addr constant [2 x i8*] [i8* bitcast (%rtti.CompleteObjectLocator* @"\01??_R4?$B@H@@6B@" to i8*), i8* bitcast (void (%class.A*)* @"\01?m_fn1@A@@EAEXXZ" to i8*)], comdat($"\01??_S?$B@H@@6B@") -// CHECK-DAG: @[[VTABLE_A:.*]] = private unnamed_addr constant [2 x i8*] [i8* bitcast (%rtti.CompleteObjectLocator* @"\01??_R4A@@6B@" to i8*), i8* bitcast (void (%class.A*)* @"\01?m_fn1@A@@EAEXXZ" to i8*)], comdat($"\01??_7A@@6B@") +// CHECK-DAG: @[[VTABLE_C:.*]] = private unnamed_addr constant { [2 x i8*] } { [2 x i8*] [i8* bitcast (%rtti.CompleteObjectLocator* @"\01??_R4C@@6B@" to i8*), i8* bitcast (void (%class.A*)* @"\01?m_fn1@A@@EAEXXZ" to i8*)] } +// CHECK-DAG: @[[VTABLE_B:.*]] = private unnamed_addr constant { [2 x i8*] } { [2 x i8*] [i8* bitcast (%rtti.CompleteObjectLocator* @"\01??_R4?$B@H@@6B@" to i8*), i8* bitcast (void (%class.A*)* @"\01?m_fn1@A@@EAEXXZ" to i8*)] }, comdat($"\01??_S?$B@H@@6B@") +// CHECK-DAG: @[[VTABLE_A:.*]] = private unnamed_addr constant { [2 x i8*] } { [2 x i8*] [i8* bitcast (%rtti.CompleteObjectLocator* @"\01??_R4A@@6B@" to i8*), i8* bitcast (void (%class.A*)* @"\01?m_fn1@A@@EAEXXZ" to i8*)] }, comdat($"\01??_SA@@6B@") -// CHECK-DAG: @"\01??_7C@@6B@" = dllexport unnamed_addr alias i8*, getelementptr inbounds ([2 x i8*], [2 x i8*]* @[[VTABLE_C]], i32 0, i32 1) -// CHECK-DAG: @"\01??_S?$B@H@@6B@" = unnamed_addr alias i8*, getelementptr inbounds ([2 x i8*], [2 x i8*]* @[[VTABLE_B]], i32 0, i32 1) -// CHECK-DAG: @"\01??_7A@@6B@" = unnamed_addr alias i8*, getelementptr inbounds ([2 x i8*], [2 x i8*]* @[[VTABLE_A]], i32 0, i32 1) +// CHECK-DAG: @"\01??_7C@@6B@" = dllexport unnamed_addr alias i8*, getelementptr inbounds ({ [2 x i8*] }, { [2 x i8*] }* @[[VTABLE_C]], i32 0, i32 0, i32 1) +// CHECK-DAG: @"\01??_S?$B@H@@6B@" = unnamed_addr alias i8*, getelementptr inbounds ({ [2 x i8*] }, { [2 x i8*] }* @[[VTABLE_B]], i32 0, i32 0, i32 1) +// CHECK-DAG: @"\01??_SA@@6B@" = unnamed_addr alias i8*, getelementptr inbounds ({ [2 x i8*] }, { [2 x i8*] }* @[[VTABLE_A]], i32 0, i32 0, i32 1) // CHECK-DAG: @"\01??_8?$B@H@@7B@" = available_externally dllimport unnamed_addr constant [2 x i32] [i32 0, i32 4] diff --git a/test/CodeGenCXX/alias-available-externally.cpp b/test/CodeGenCXX/alias-available-externally.cpp new file mode 100644 index 000000000000..473e93be0a75 --- /dev/null +++ b/test/CodeGenCXX/alias-available-externally.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -O1 -std=c++11 -emit-llvm -triple %itanium_abi_triple -disable-llvm-passes -o - %s | FileCheck %s +// Clang should not generate alias to available_externally definitions. +// Check that the destructor of Foo is defined. +// The destructors have different return type for different targets. +// CHECK: define linkonce_odr {{.*}} @_ZN3FooD2Ev +template <class CharT> +struct String { + String() {} + ~String(); +}; + +template <class CharT> +inline __attribute__((visibility("hidden"), always_inline)) +String<CharT>::~String() {} + +extern template struct String<char>; + +struct Foo : public String<char> { Foo() { String<char> s; } }; + +Foo f; diff --git a/test/CodeGenCXX/alloc-size.cpp b/test/CodeGenCXX/alloc-size.cpp new file mode 100644 index 000000000000..e93e231b70e8 --- /dev/null +++ b/test/CodeGenCXX/alloc-size.cpp @@ -0,0 +1,72 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -O0 %s -o - 2>&1 -std=c++11 | FileCheck %s + +namespace templates { +void *my_malloc(int N) __attribute__((alloc_size(1))); +void *my_calloc(int N, int M) __attribute__((alloc_size(1, 2))); + +struct MyType { + int arr[4]; +}; + +template <typename T> int callMalloc(); + +template <typename T, int N> int callCalloc(); + +// CHECK-LABEL: define i32 @_ZN9templates6testItEv() +int testIt() { + // CHECK: call i32 @_ZN9templates10callMallocINS_6MyTypeEEEiv + // CHECK: call i32 @_ZN9templates10callCallocINS_6MyTypeELi4EEEiv + return callMalloc<MyType>() + callCalloc<MyType, 4>(); +} + +// CHECK-LABEL: define linkonce_odr i32 +// @_ZN9templates10callMallocINS_6MyTypeEEEiv +template <typename T> int callMalloc() { + static_assert(sizeof(T) == 16, ""); + // CHECK: ret i32 16 + return __builtin_object_size(my_malloc(sizeof(T)), 0); +} + +// CHECK-LABEL: define linkonce_odr i32 +// @_ZN9templates10callCallocINS_6MyTypeELi4EEEiv +template <typename T, int N> int callCalloc() { + static_assert(sizeof(T) * N == 64, ""); + // CHECK: ret i32 64 + return __builtin_object_size(my_malloc(sizeof(T) * N), 0); +} +} + +namespace templated_alloc_size { +using size_t = unsigned long; + +// We don't need bodies for any of these, because they're only used in +// __builtin_object_size, and that shouldn't need anything but a function +// decl with alloc_size on it. +template <typename T> +T *my_malloc(size_t N = sizeof(T)) __attribute__((alloc_size(1))); + +template <typename T> +T *my_calloc(size_t M, size_t N = sizeof(T)) __attribute__((alloc_size(2, 1))); + +template <size_t N> +void *dependent_malloc(size_t NT = N) __attribute__((alloc_size(1))); + +template <size_t N, size_t M> +void *dependent_calloc(size_t NT = N, size_t MT = M) + __attribute__((alloc_size(1, 2))); + +template <typename T, size_t M> +void *dependent_calloc2(size_t NT = sizeof(T), size_t MT = M) + __attribute__((alloc_size(1, 2))); + +// CHECK-LABEL: define i32 @_ZN20templated_alloc_size6testItEv +int testIt() { + // 122 = 4 + 5*4 + 6 + 7*8 + 4*9 + // CHECK: ret i32 122 + return __builtin_object_size(my_malloc<int>(), 0) + + __builtin_object_size(my_calloc<int>(5), 0) + + __builtin_object_size(dependent_malloc<6>(), 0) + + __builtin_object_size(dependent_calloc<7, 8>(), 0) + + __builtin_object_size(dependent_calloc2<int, 9>(), 0); +} +} diff --git a/test/CodeGenCXX/apple-kext-indirect-call-2.cpp b/test/CodeGenCXX/apple-kext-indirect-call-2.cpp index d441b78140e7..3b2cda8b583b 100644 --- a/test/CodeGenCXX/apple-kext-indirect-call-2.cpp +++ b/test/CodeGenCXX/apple-kext-indirect-call-2.cpp @@ -1,9 +1,9 @@ // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fapple-kext -fno-rtti -emit-llvm -o - %s | FileCheck %s -// CHECK: @_ZTV1A = unnamed_addr constant [4 x i8*] [i8* null, i8* null, i8* bitcast (i8* (%struct.A*)* @_ZNK1A3abcEv to i8*), i8* null] -// CHECK: @_ZTV4Base = unnamed_addr constant [4 x i8*] [i8* null, i8* null, i8* bitcast (i8* (%struct.Base*)* @_ZNK4Base3abcEv to i8*), i8* null] -// CHECK: @_ZTV8Derived2 = unnamed_addr constant [5 x i8*] [i8* null, i8* null, i8* null, i8* bitcast (i8* (%struct.Derived2*)* @_ZNK8Derived23efgEv to i8*), i8* null] -// CHECK: @_ZTV2D2 = unnamed_addr constant [5 x i8*] [i8* null, i8* null, i8* null, i8* bitcast (i8* (%struct.D2*)* @_ZNK2D23abcEv to i8*), i8* null] +// CHECK: @_ZTV1A = unnamed_addr constant { [4 x i8*] } { [4 x i8*] [i8* null, i8* null, i8* bitcast (i8* (%struct.A*)* @_ZNK1A3abcEv to i8*), i8* null] } +// CHECK: @_ZTV4Base = unnamed_addr constant { [4 x i8*] } { [4 x i8*] [i8* null, i8* null, i8* bitcast (i8* (%struct.Base*)* @_ZNK4Base3abcEv to i8*), i8* null] } +// CHECK: @_ZTV8Derived2 = unnamed_addr constant { [5 x i8*] } { [5 x i8*] [i8* null, i8* null, i8* null, i8* bitcast (i8* (%struct.Derived2*)* @_ZNK8Derived23efgEv to i8*), i8* null] } +// CHECK: @_ZTV2D2 = unnamed_addr constant { [5 x i8*] } { [5 x i8*] [i8* null, i8* null, i8* null, i8* bitcast (i8* (%struct.D2*)* @_ZNK2D23abcEv to i8*), i8* null] } struct A { virtual const char* abc(void) const; @@ -18,7 +18,7 @@ struct B : virtual A { void B::VF() {} void FUNC(B* p) { -// CHECK: [[T1:%.*]] = load i8* (%struct.A*)*, i8* (%struct.A*)** getelementptr inbounds (i8* (%struct.A*)*, i8* (%struct.A*)** bitcast ([4 x i8*]* @_ZTV1A to i8* (%struct.A*)**), i64 2) +// CHECK: [[T1:%.*]] = load i8* (%struct.A*)*, i8* (%struct.A*)** getelementptr inbounds (i8* (%struct.A*)*, i8* (%struct.A*)** bitcast ({ [4 x i8*] }* @_ZTV1A to i8* (%struct.A*)**), i64 2) // CHECK-NEXT: [[T2:%.*]] = call i8* [[T1]] const char* c = p->A::abc(); } @@ -33,7 +33,7 @@ struct Derived : public Base { }; void FUNC1(Derived* p) { -// CHECK: [[U1:%.*]] = load i8* (%struct.Base*)*, i8* (%struct.Base*)** getelementptr inbounds (i8* (%struct.Base*)*, i8* (%struct.Base*)** bitcast ([4 x i8*]* @_ZTV4Base to i8* (%struct.Base*)**), i64 2) +// CHECK: [[U1:%.*]] = load i8* (%struct.Base*)*, i8* (%struct.Base*)** getelementptr inbounds (i8* (%struct.Base*)*, i8* (%struct.Base*)** bitcast ({ [4 x i8*] }* @_ZTV4Base to i8* (%struct.Base*)**), i64 2) // CHECK-NEXT: [[U2:%.*]] = call i8* [[U1]] char* c = p->Base::abc(); } @@ -49,7 +49,7 @@ struct Derived2 : virtual Base2 { char* Derived2::efg(void) const { return 0; } void FUNC2(Derived2* p) { -// CHECK: [[V1:%.*]] = load i8* (%struct.Derived2*)*, i8* (%struct.Derived2*)** getelementptr inbounds (i8* (%struct.Derived2*)*, i8* (%struct.Derived2*)** bitcast ([5 x i8*]* @_ZTV8Derived2 to i8* (%struct.Derived2*)**), i64 3) +// CHECK: [[V1:%.*]] = load i8* (%struct.Derived2*)*, i8* (%struct.Derived2*)** getelementptr inbounds (i8* (%struct.Derived2*)*, i8* (%struct.Derived2*)** bitcast ({ [5 x i8*] }* @_ZTV8Derived2 to i8* (%struct.Derived2*)**), i64 3) // CHECK-NEXT: [[V2:%.*]] = call i8* [[V1]] char* c = p->Derived2::efg(); } @@ -70,7 +70,7 @@ struct Sub : D1, D2 { char* D2::abc(void) const { return 0; } void FUNC3(Sub* p) { -// CHECK: [[W1:%.*]] = load i8* (%struct.D2*)*, i8* (%struct.D2*)** getelementptr inbounds (i8* (%struct.D2*)*, i8* (%struct.D2*)** bitcast ([5 x i8*]* @_ZTV2D2 to i8* (%struct.D2*)**), i64 3) +// CHECK: [[W1:%.*]] = load i8* (%struct.D2*)*, i8* (%struct.D2*)** getelementptr inbounds (i8* (%struct.D2*)*, i8* (%struct.D2*)** bitcast ({ [5 x i8*] }* @_ZTV2D2 to i8* (%struct.D2*)**), i64 3) // CHECK-NEXT: [[W2:%.*]] = call i8* [[W1]] char* c = p->D2::abc(); } diff --git a/test/CodeGenCXX/apple-kext-indirect-call.cpp b/test/CodeGenCXX/apple-kext-indirect-call.cpp index e4c03b5da50b..ac0e3f4d39c6 100644 --- a/test/CodeGenCXX/apple-kext-indirect-call.cpp +++ b/test/CodeGenCXX/apple-kext-indirect-call.cpp @@ -1,6 +1,6 @@ // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fapple-kext -emit-llvm -o - %s | FileCheck %s -// CHECK: @_ZTV5TemplIiE = internal unnamed_addr constant [5 x i8*] [i8* null, i8* bitcast ({ i8*, i8* }* @_ZTI5TemplIiE to i8*), i8* bitcast (void (%struct.Templ*)* @_ZN5TemplIiE1fEv to i8*), i8* bitcast (void (%struct.Templ*)* @_ZN5TemplIiE1gEv to i8*), i8* null] +// CHECK: @_ZTV5TemplIiE = internal unnamed_addr constant { [5 x i8*] } { [5 x i8*] [i8* null, i8* bitcast ({ i8*, i8* }* @_ZTI5TemplIiE to i8*), i8* bitcast (void (%struct.Templ*)* @_ZN5TemplIiE1fEv to i8*), i8* bitcast (void (%struct.Templ*)* @_ZN5TemplIiE1gEv to i8*), i8* null] } struct Base { virtual void abc(void) const; @@ -12,7 +12,7 @@ void FUNC(Base* p) { p->Base::abc(); } -// CHECK: getelementptr inbounds (void (%struct.Base*)*, void (%struct.Base*)** bitcast ([4 x i8*]* @_ZTV4Base to void (%struct.Base*)**), i64 2) +// CHECK: getelementptr inbounds (void (%struct.Base*)*, void (%struct.Base*)** bitcast ({ [4 x i8*] }* @_ZTV4Base to void (%struct.Base*)**), i64 2) // CHECK-NOT: call void @_ZNK4Base3abcEv template<class T> @@ -37,6 +37,6 @@ void f(SubTempl<int>* t) { t->Templ::f(); } -// CHECK: getelementptr inbounds (void (%struct.Templ*)*, void (%struct.Templ*)** bitcast ([5 x i8*]* @_ZTV5TemplIiE to void (%struct.Templ*)**), i64 2) +// CHECK: getelementptr inbounds (void (%struct.Templ*)*, void (%struct.Templ*)** bitcast ({ [5 x i8*] }* @_ZTV5TemplIiE to void (%struct.Templ*)**), i64 2) // CHECK: define internal void @_ZN5TemplIiE1fEv(%struct.Templ* %this) // CHECK: define internal void @_ZN5TemplIiE1gEv(%struct.Templ* %this) diff --git a/test/CodeGenCXX/apple-kext-indirect-virtual-dtor-call.cpp b/test/CodeGenCXX/apple-kext-indirect-virtual-dtor-call.cpp index 5f6bdb230fe7..4cfa88d99455 100644 --- a/test/CodeGenCXX/apple-kext-indirect-virtual-dtor-call.cpp +++ b/test/CodeGenCXX/apple-kext-indirect-virtual-dtor-call.cpp @@ -1,6 +1,6 @@ // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fapple-kext -fno-rtti -emit-llvm -o - %s | FileCheck %s -// CHECK: @_ZTV5TemplIiE = internal unnamed_addr constant [7 x i8*] [i8* null, i8* null, i8* bitcast (void (%struct.Templ*)* @_ZN5TemplIiED1Ev to i8*), i8* bitcast (void (%struct.Templ*)* @_ZN5TemplIiED0Ev to i8*), i8* bitcast (void (%struct.Templ*)* @_ZN5TemplIiE1fEv to i8*), i8* bitcast (void (%struct.Templ*)* @_ZN5TemplIiE1gEv to i8*), i8* null] +// CHECK: @_ZTV5TemplIiE = internal unnamed_addr constant { [7 x i8*] } { [7 x i8*] [i8* null, i8* null, i8* bitcast (void (%struct.Templ*)* @_ZN5TemplIiED1Ev to i8*), i8* bitcast (void (%struct.Templ*)* @_ZN5TemplIiED0Ev to i8*), i8* bitcast (void (%struct.Templ*)* @_ZN5TemplIiE1fEv to i8*), i8* bitcast (void (%struct.Templ*)* @_ZN5TemplIiE1gEv to i8*), i8* null] } struct B1 { virtual ~B1(); @@ -12,10 +12,10 @@ void DELETE(B1 *pb1) { pb1->B1::~B1(); } // CHECK-LABEL: define void @_ZN2B1D0Ev -// CHECK: [[T1:%.*]] = load void (%struct.B1*)*, void (%struct.B1*)** getelementptr inbounds (void (%struct.B1*)*, void (%struct.B1*)** bitcast ([5 x i8*]* @_ZTV2B1 to void (%struct.B1*)**), i64 2) +// CHECK: [[T1:%.*]] = load void (%struct.B1*)*, void (%struct.B1*)** getelementptr inbounds (void (%struct.B1*)*, void (%struct.B1*)** bitcast ({ [5 x i8*] }* @_ZTV2B1 to void (%struct.B1*)**), i64 2) // CHECK-NEXT: call void [[T1]](%struct.B1* [[T2:%.*]]) // CHECK-LABEL: define void @_Z6DELETEP2B1 -// CHECK: [[T3:%.*]] = load void (%struct.B1*)*, void (%struct.B1*)** getelementptr inbounds (void (%struct.B1*)*, void (%struct.B1*)** bitcast ([5 x i8*]* @_ZTV2B1 to void (%struct.B1*)**), i64 2) +// CHECK: [[T3:%.*]] = load void (%struct.B1*)*, void (%struct.B1*)** getelementptr inbounds (void (%struct.B1*)*, void (%struct.B1*)** bitcast ({ [5 x i8*] }* @_ZTV2B1 to void (%struct.B1*)**), i64 2) // CHECK-NEXT: call void [[T3]](%struct.B1* [[T4:%.*]]) template<class T> @@ -42,7 +42,7 @@ void f(SubTempl<int>* t) { t->Templ::~Templ(); } -// CHECK: getelementptr inbounds (void (%struct.Templ*)*, void (%struct.Templ*)** bitcast ([7 x i8*]* @_ZTV5TemplIiE to void (%struct.Templ*)**), i64 2) +// CHECK: getelementptr inbounds (void (%struct.Templ*)*, void (%struct.Templ*)** bitcast ({ [7 x i8*] }* @_ZTV5TemplIiE to void (%struct.Templ*)**), i64 2) // CHECK: declare void @_ZN5TemplIiED0Ev(%struct.Templ*) // CHECK: define internal void @_ZN5TemplIiE1fEv(%struct.Templ* %this) // CHECK: define internal void @_ZN5TemplIiE1gEv(%struct.Templ* %this) diff --git a/test/CodeGenCXX/arm-swiftcall.cpp b/test/CodeGenCXX/arm-swiftcall.cpp index 535350c808d3..5c932c77b1da 100644 --- a/test/CodeGenCXX/arm-swiftcall.cpp +++ b/test/CodeGenCXX/arm-swiftcall.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple armv7-apple-darwin9 -emit-llvm -o - %s -Wno-return-type-c-linkage | FileCheck %s +// RUN: %clang_cc1 -triple armv7-apple-darwin9 -emit-llvm -o - %s -Wno-return-type-c-linkage -std=c++03 | FileCheck %s -check-prefixes=CHECK // This isn't really testing anything ARM-specific; it's just a convenient // 32-bit platform. diff --git a/test/CodeGenCXX/arm64.cpp b/test/CodeGenCXX/arm64.cpp index 19f72726e690..80438397c3f2 100644 --- a/test/CodeGenCXX/arm64.cpp +++ b/test/CodeGenCXX/arm64.cpp @@ -84,3 +84,39 @@ namespace test2 { // CHECK-GLOBALS-DAG: @_ZTIN5test21EIiEE = weak_odr constant { {{.*}}, i8* inttoptr (i64 add (i64 ptrtoint ([14 x i8]* @_ZTSN5test21EIiEE to i64), i64 -9223372036854775808) to i8*) } } + +// ARM64 reserves the top half of the vtable offset in virtual +// member pointers. +namespace test3 { + struct A { + virtual void foo(); + virtual void bar(); + }; + + // The offset half of the pointer is still initialized to zero. + // CHECK-GLOBALS-DAG: @_ZN5test34mptrE = global { i64, i64 } { i64 0, i64 1 } + void (A::*mptr)() = &A::foo; + + // CHECK-LABEL: define void @_ZN5test34testEv() + // CHECK: [[TEMP:%.*]] = alloca [[A:.*]], align 8 + // CHECK: [[MEMPTR:%.*]] = load { i64, i64 }, { i64, i64 }* @_ZN5test34mptrE, align 8 + // CHECK: [[ADJUST_AND_IS_VIRTUAL:%.*]] = extractvalue { i64, i64 } [[MEMPTR]], 1 + // CHECK: [[ADJUST:%.*]] = ashr i64 [[ADJUST_AND_IS_VIRTUAL]], 1 + // CHECK: [[T0:%.*]] = bitcast [[A]]* [[TEMP]] to i8* + // CHECK: [[T1:%.*]] = getelementptr inbounds i8, i8* [[T0]], i64 [[ADJUST]] + // CHECK: [[ADJUSTED:%.*]] = bitcast i8* [[T1]] to [[A]]* + // CHECK: [[MEMBER:%.*]] = extractvalue { i64, i64 } [[MEMPTR]], 0 + // CHECK: [[T0:%.*]] = and i64 [[ADJUST_AND_IS_VIRTUAL]], 1 + // CHECK: [[IS_VIRTUAL:%.*]] = icmp ne i64 [[T0]], 0 + // CHECK: br i1 [[IS_VIRTUAL]], + // CHECK: [[T0:%.*]] = bitcast [[A]]* [[ADJUSTED]] to i8** + // CHECK: [[VPTR:%.*]] = load i8*, i8** [[T0]], align 8 + // CHECK: [[TRUNC:%.*]] = trunc i64 [[MEMBER]] to i32 + // CHECK: [[ZEXT:%.*]] = zext i32 [[TRUNC]] to i64 + // CHECK: [[T0:%.*]] = getelementptr i8, i8* [[VPTR]], i64 [[ZEXT]] + // CHECK: [[T1:%.*]] = bitcast i8* [[T0]] to void ([[A]]*)** + // CHECK: load void ([[A]]*)*, void ([[A]]*)** [[T1]], + void test() { + (A().*mptr)(); + } +} diff --git a/test/CodeGenCXX/atomicinit.cpp b/test/CodeGenCXX/atomicinit.cpp index 96f44d52f286..4c30ec35212f 100644 --- a/test/CodeGenCXX/atomicinit.cpp +++ b/test/CodeGenCXX/atomicinit.cpp @@ -51,8 +51,8 @@ struct AtomicBoolMember { }; // CHECK-LABEL: define void @_ZN16AtomicBoolMemberC2Eb -// CHECK: {{zext i1.*to i8}} -// CHECK-NEXT: store i8 +// CHECK: zext i1 {{.*}} to i8 +// CHECK: store i8 // CHECK-NEXT: ret void AtomicBoolMember::AtomicBoolMember(bool b) : ab(b) { } diff --git a/test/CodeGenCXX/attr.cpp b/test/CodeGenCXX/attr.cpp index 67993b4227a1..7f5595f6f044 100644 --- a/test/CodeGenCXX/attr.cpp +++ b/test/CodeGenCXX/attr.cpp @@ -31,4 +31,4 @@ int test1() { return 10; } // CHECK at top of file extern "C" int test2() __attribute__((alias("_Z5test1v"))); -// CHECK: attributes [[NUW]] = { nounwind{{.*}} } +// CHECK: attributes [[NUW]] = { noinline nounwind{{.*}} } diff --git a/test/CodeGenCXX/block-in-ctor-dtor.cpp b/test/CodeGenCXX/block-in-ctor-dtor.cpp index 0dc0ab00437f..0ec9db1db728 100644 --- a/test/CodeGenCXX/block-in-ctor-dtor.cpp +++ b/test/CodeGenCXX/block-in-ctor-dtor.cpp @@ -42,7 +42,5 @@ X::~X() { // CHECK-LABEL: define internal void @___ZN4ZoneD2Ev_block_invoke_ // CHECK-LABEL: define internal void @___ZN1XC2Ev_block_invoke // CHECK-LABEL: define internal void @___ZN1XC2Ev_block_invoke_ -// CHECK-LABEL: define internal void @___ZN1XC1Ev_block_invoke -// CHECK-LABEL: define internal void @___ZN1XC1Ev_block_invoke_ // CHECK-LABEL: define internal void @___ZN1XD2Ev_block_invoke // CHECK-LABEL: define internal void @___ZN1XD2Ev_block_invoke_ diff --git a/test/CodeGenCXX/builtins-arm-exclusive.cpp b/test/CodeGenCXX/builtins-arm-exclusive.cpp new file mode 100644 index 000000000000..06f7a023adec --- /dev/null +++ b/test/CodeGenCXX/builtins-arm-exclusive.cpp @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -Wall -Werror -triple thumbv8-linux-gnueabi -fno-signed-char -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -Wall -Werror -triple arm64-apple-ios7.0 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-ARM64 + +bool b; + +// CHECK-LABEL: @_Z10test_ldrexv() +// CHECK: call i32 @llvm.arm.ldrex.p0i8(i8* @b) + +// CHECK-ARM64-LABEL: @_Z10test_ldrexv() +// CHECK-ARM64: call i64 @llvm.aarch64.ldxr.p0i8(i8* @b) + +void test_ldrex() { + b = __builtin_arm_ldrex(&b); +} + +// CHECK-LABEL: @_Z10tset_strexv() +// CHECK: %{{.*}} = call i32 @llvm.arm.strex.p0i8(i32 1, i8* @b) + +// CHECK-ARM64-LABEL: @_Z10tset_strexv() +// CHECK-ARM64: %{{.*}} = call i32 @llvm.aarch64.stxr.p0i8(i64 1, i8* @b) + +void tset_strex() { + __builtin_arm_strex(true, &b); +} diff --git a/test/CodeGenCXX/catch-undef-behavior.cpp b/test/CodeGenCXX/catch-undef-behavior.cpp index 3ca7f6d65ad4..179c33412267 100644 --- a/test/CodeGenCXX/catch-undef-behavior.cpp +++ b/test/CodeGenCXX/catch-undef-behavior.cpp @@ -277,13 +277,13 @@ int array_index(const int (&a)[4], int n) { int multi_array_index(int n, int m) { int arr[4][6]; - // CHECK: %[[IDX2_OK:.*]] = icmp ult i64 %{{.*}}, 6 - // CHECK: br i1 %[[IDX2_OK]] - // CHECK: call void @__ubsan_handle_out_of_bounds( - // CHECK: %[[IDX1_OK:.*]] = icmp ult i64 %{{.*}}, 4 // CHECK: br i1 %[[IDX1_OK]] // CHECK: call void @__ubsan_handle_out_of_bounds( + + // CHECK: %[[IDX2_OK:.*]] = icmp ult i64 %{{.*}}, 6 + // CHECK: br i1 %[[IDX2_OK]] + // CHECK: call void @__ubsan_handle_out_of_bounds( return arr[n][m]; } diff --git a/test/CodeGenCXX/cfi-cross-dso.cpp b/test/CodeGenCXX/cfi-cross-dso.cpp index d67927d4d2ed..bfa0705c6f8f 100644 --- a/test/CodeGenCXX/cfi-cross-dso.cpp +++ b/test/CodeGenCXX/cfi-cross-dso.cpp @@ -26,7 +26,7 @@ void g() { b.f(); } -// MS: @[[B_VTABLE:.*]] = private unnamed_addr constant [2 x i8*] {{.*}}@"\01??_R4B@?A@@6B@"{{.*}}@"\01?f@B@?A@@UEAAXXZ" +// MS: @[[B_VTABLE:.*]] = private unnamed_addr constant { [2 x i8*] } {{.*}}@"\01??_R4B@?A@@6B@"{{.*}}@"\01?f@B@?A@@UEAAXXZ" // CHECK: %[[VT:.*]] = load void (%struct.A*)**, void (%struct.A*)*** // CHECK: %[[VT2:.*]] = bitcast {{.*}}%[[VT]] to i8*, !nosanitize diff --git a/test/CodeGenCXX/compound-literals.cpp b/test/CodeGenCXX/compound-literals.cpp index 69632a7de2f4..a9882bc6d241 100644 --- a/test/CodeGenCXX/compound-literals.cpp +++ b/test/CodeGenCXX/compound-literals.cpp @@ -12,6 +12,9 @@ struct Y { X x; }; +// CHECK: @.compoundliteral = internal global [5 x i32] [i32 1, i32 2, i32 3, i32 4, i32 5], align 4 +// CHECK: @q = global i32* getelementptr inbounds ([5 x i32], [5 x i32]* @.compoundliteral, i32 0, i32 0), align 4 + // CHECK-LABEL: define i32 @_Z1fv() int f() { // CHECK: [[LVALUE:%[a-z0-9.]+]] = alloca @@ -38,20 +41,45 @@ int g() { return v[0]; } +// GCC's compound-literals-in-C++ extension lifetime-extends a compound literal +// (or a C++11 list-initialized temporary!) if: +// - it is at global scope +// - it has array type +// - it has a constant initializer + struct Z { int i[3]; }; int *p = (Z){ {1, 2, 3} }.i; // CHECK: define {{.*}}__cxx_global_var_init() -// CHECK: store i32* getelementptr inbounds (%struct.Z, %struct.Z* @.compoundliteral, i32 0, i32 0, i32 0), i32** @p +// CHECK: alloca %struct.Z +// CHECK: store i32* %{{.*}}, i32** @p +int *q = (int [5]){1, 2, 3, 4, 5}; +// (constant initialization, checked above) -int *PR21912_1 = (int []){}; +extern int n; +int *r = (int [5]){1, 2, 3, 4, 5} + n; // CHECK-LABEL: define {{.*}}__cxx_global_var_init.1() -// CHECK: store i32* getelementptr inbounds ([0 x i32], [0 x i32]* @.compoundliteral.2, i32 0, i32 0), i32** @PR21912_1 +// CHECK: %[[PTR:.*]] = getelementptr inbounds i32, i32* getelementptr inbounds ([5 x i32], [5 x i32]* @.compoundliteral.2, i32 0, i32 0), i32 % +// CHECK: store i32* %[[PTR]], i32** @r + +int *PR21912_1 = (int []){} + n; +// CHECK-LABEL: define {{.*}}__cxx_global_var_init.3() +// CHECK: %[[PTR:.*]] = getelementptr inbounds i32, i32* getelementptr inbounds ([0 x i32], [0 x i32]* @.compoundliteral.4, i32 0, i32 0), i32 % +// CHECK: store i32* %[[PTR]], i32** @PR21912_1 union PR21912Ty { long long l; double d; }; -union PR21912Ty *PR21912_2 = (union PR21912Ty[]){{.d = 2.0}, {.l = 3}}; -// CHECK-LABEL: define {{.*}}__cxx_global_var_init.3() -// CHECK: store %union.PR21912Ty* getelementptr inbounds ([2 x %union.PR21912Ty], [2 x %union.PR21912Ty]* bitcast (<{ { double }, %union.PR21912Ty }>* @.compoundliteral.4 to [2 x %union.PR21912Ty]*), i32 0, i32 0), %union.PR21912Ty** @PR21912_2 +union PR21912Ty *PR21912_2 = (union PR21912Ty[]){{.d = 2.0}, {.l = 3}} + n; +// CHECK-LABEL: define {{.*}}__cxx_global_var_init.5() +// CHECK: %[[PTR:.*]] = getelementptr inbounds %union.PR21912Ty, %union.PR21912Ty* getelementptr inbounds ([2 x %union.PR21912Ty], [2 x %union.PR21912Ty]* bitcast (<{ { double }, %union.PR21912Ty }>* @.compoundliteral.6 to [2 x %union.PR21912Ty]*), i32 0, i32 0), i32 % +// CHECK: store %union.PR21912Ty* %[[PTR]], %union.PR21912Ty** @PR21912_2, align 4 + +// This compound literal should have local scope. +int computed_with_lambda = [] { + int *array = (int[]) { 1, 3, 5, 7 }; + return array[0]; +}(); +// CHECK-LABEL: define internal i32 @{{.*}}clEv +// CHECK: alloca [4 x i32] diff --git a/test/CodeGenCXX/const-init-cxx11.cpp b/test/CodeGenCXX/const-init-cxx11.cpp index 0c2193fb07f2..c4962bc08ad6 100644 --- a/test/CodeGenCXX/const-init-cxx11.cpp +++ b/test/CodeGenCXX/const-init-cxx11.cpp @@ -343,13 +343,13 @@ namespace VirtualMembers { constexpr E() : B(3), c{'b','y','e'} {} char c[3]; }; - // CHECK: @_ZN14VirtualMembers1eE = global { i8**, double, i32, i8**, double, [5 x i8], i16, i8**, double, [5 x i8], [3 x i8] } { i8** getelementptr inbounds ([11 x i8*], [11 x i8*]* @_ZTVN14VirtualMembers1EE, i32 0, i32 2), double 1.000000e+00, i32 64, i8** getelementptr inbounds ([11 x i8*], [11 x i8*]* @_ZTVN14VirtualMembers1EE, i32 0, i32 5), double 2.000000e+00, [5 x i8] c"hello", i16 5, i8** getelementptr inbounds ([11 x i8*], [11 x i8*]* @_ZTVN14VirtualMembers1EE, i32 0, i32 9), double 3.000000e+00, [5 x i8] c"world", [3 x i8] c"bye" } + // CHECK: @_ZN14VirtualMembers1eE = global { i8**, double, i32, i8**, double, [5 x i8], i16, i8**, double, [5 x i8], [3 x i8] } { i8** getelementptr inbounds ({ [3 x i8*], [4 x i8*], [4 x i8*] }, { [3 x i8*], [4 x i8*], [4 x i8*] }* @_ZTVN14VirtualMembers1EE, i32 0, inrange i32 0, i32 2), double 1.000000e+00, i32 64, i8** getelementptr inbounds ({ [3 x i8*], [4 x i8*], [4 x i8*] }, { [3 x i8*], [4 x i8*], [4 x i8*] }* @_ZTVN14VirtualMembers1EE, i32 0, inrange i32 1, i32 2), double 2.000000e+00, [5 x i8] c"hello", i16 5, i8** getelementptr inbounds ({ [3 x i8*], [4 x i8*], [4 x i8*] }, { [3 x i8*], [4 x i8*], [4 x i8*] }* @_ZTVN14VirtualMembers1EE, i32 0, inrange i32 2, i32 2), double 3.000000e+00, [5 x i8] c"world", [3 x i8] c"bye" } E e; struct nsMemoryImpl { virtual void f(); }; - // CHECK: @_ZN14VirtualMembersL13sGlobalMemoryE = internal global { i8** } { i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN14VirtualMembers12nsMemoryImplE, i32 0, i32 2) } + // CHECK: @_ZN14VirtualMembersL13sGlobalMemoryE = internal global { i8** } { i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTVN14VirtualMembers12nsMemoryImplE, i32 0, inrange i32 0, i32 2) } __attribute__((used)) static nsMemoryImpl sGlobalMemory; @@ -360,7 +360,7 @@ namespace VirtualMembers { T t; }; - // CHECK: @_ZN14VirtualMembers1tE = global { i8**, i32 } { i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN14VirtualMembers13TemplateClassIiEE, i32 0, i32 2), i32 42 } + // CHECK: @_ZN14VirtualMembers1tE = global { i8**, i32 } { i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTVN14VirtualMembers13TemplateClassIiEE, i32 0, inrange i32 0, i32 2), i32 42 } TemplateClass<int> t; } diff --git a/test/CodeGenCXX/constructor-destructor-return-this.cpp b/test/CodeGenCXX/constructor-destructor-return-this.cpp index 9d47d1706bbe..164fda3c1c38 100644 --- a/test/CodeGenCXX/constructor-destructor-return-this.cpp +++ b/test/CodeGenCXX/constructor-destructor-return-this.cpp @@ -111,7 +111,7 @@ D::~D() { } // CHECKIOS5-LABEL: define %class.D* @_ZN1DD1Ev(%class.D* %this) // CHECKMS-LABEL: define x86_thiscallcc %class.D* @"\01??0D@@QAE@XZ"(%class.D* returned %this, i32 %is_most_derived) -// CHECKMS-LABEL: define x86_thiscallcc void @"\01??1D@@UAE@XZ"(%class.D*) +// CHECKMS-LABEL: define x86_thiscallcc void @"\01??1D@@UAE@XZ"(%class.D* %this) class E { public: diff --git a/test/CodeGenCXX/constructor-init.cpp b/test/CodeGenCXX/constructor-init.cpp index c78534a218de..fe15ccf8fef5 100644 --- a/test/CodeGenCXX/constructor-init.cpp +++ b/test/CodeGenCXX/constructor-init.cpp @@ -95,14 +95,14 @@ namespace InitVTable { // CHECK-LABEL: define void @_ZN10InitVTable1BC2Ev(%"struct.InitVTable::B"* %this) unnamed_addr // CHECK: [[T0:%.*]] = bitcast [[B:%.*]]* [[THIS:%.*]] to i32 (...)*** - // CHECK-NEXT: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN10InitVTable1BE, i32 0, i32 2) to i32 (...)**), i32 (...)*** [[T0]] + // CHECK-NEXT: store i32 (...)** bitcast (i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTVN10InitVTable1BE, i32 0, inrange i32 0, i32 2) to i32 (...)**), i32 (...)*** [[T0]] // CHECK: [[VTBL:%.*]] = load i32 ([[B]]*)**, i32 ([[B]]*)*** {{%.*}} // CHECK-NEXT: [[FNP:%.*]] = getelementptr inbounds i32 ([[B]]*)*, i32 ([[B]]*)** [[VTBL]], i64 0 // CHECK-NEXT: [[FN:%.*]] = load i32 ([[B]]*)*, i32 ([[B]]*)** [[FNP]] // CHECK-NEXT: [[ARG:%.*]] = call i32 [[FN]]([[B]]* [[THIS]]) // CHECK-NEXT: call void @_ZN10InitVTable1AC2Ei({{.*}}* {{%.*}}, i32 [[ARG]]) // CHECK-NEXT: [[T0:%.*]] = bitcast [[B]]* [[THIS]] to i32 (...)*** - // CHECK-NEXT: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN10InitVTable1BE, i32 0, i32 2) to i32 (...)**), i32 (...)*** [[T0]] + // CHECK-NEXT: store i32 (...)** bitcast (i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTVN10InitVTable1BE, i32 0, inrange i32 0, i32 2) to i32 (...)**), i32 (...)*** [[T0]] // CHECK-NEXT: ret void B::B() : A(foo()) {} @@ -110,7 +110,7 @@ namespace InitVTable { // CHECK: [[ARG:%.*]] = add nsw i32 {{%.*}}, 5 // CHECK-NEXT: call void @_ZN10InitVTable1AC2Ei({{.*}}* {{%.*}}, i32 [[ARG]]) // CHECK-NEXT: [[T0:%.*]] = bitcast [[B]]* {{%.*}} to i32 (...)*** - // CHECK-NEXT: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN10InitVTable1BE, i32 0, i32 2) to i32 (...)**), i32 (...)*** [[T0]] + // CHECK-NEXT: store i32 (...)** bitcast (i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTVN10InitVTable1BE, i32 0, inrange i32 0, i32 2) to i32 (...)**), i32 (...)*** [[T0]] // CHECK-NEXT: ret void B::B(int x) : A(x + 5) {} } @@ -207,20 +207,17 @@ namespace PR10720 { // CHECK-PR10720-LABEL: define linkonce_odr void @_ZN7PR107205pair2C2ERKS0_ // CHECK-PR10720-NOT: ret - // CHECK-PR10720: load - // CHECK-PR10720: icmp ult - // CHECK-PR10720-NEXT: br i1 // CHECK-PR10720: call void @_ZN7PR107201XC1ERKS0_ - // CHECK-PR10720-NEXT: br label + // CHECK-PR10720: icmp eq + // CHECK-PR10720-NEXT: br i1 // CHECK-PR10720: ret void // CHECK-PR10720-LABEL: define linkonce_odr void @_ZN7PR107205pair2C2EOS0_ // CHECK-PR10720-NOT: ret // CHECK-PR10720: load - // CHECK-PR10720: icmp ult - // CHECK-PR10720-NEXT: br i1 // CHECK-PR10720: call void @_ZN7PR107201XC1EOS0_ - // CHECK-PR10720-NEXT: br label + // CHECK-PR10720: icmp eq + // CHECK-PR10720-NEXT: br i1 // CHECK-PR10720: ret void pair2(pair2&&) = default; diff --git a/test/CodeGenCXX/copy-constructor-elim-2.cpp b/test/CodeGenCXX/copy-constructor-elim-2.cpp index c263b7ebf952..26b6b4851f5a 100644 --- a/test/CodeGenCXX/copy-constructor-elim-2.cpp +++ b/test/CodeGenCXX/copy-constructor-elim-2.cpp @@ -74,3 +74,23 @@ namespace PR12139 { return a.value; } } + +namespace ElidableCallIsNotCopyCtor { + struct A { A(const A&); }; + struct B : A { + B(B&); + B(A); + B(int); + }; + void f() { + // Here, we construct via B(int) then B(A). The B(A) construction is + // elidable, but we don't have an AST representation for the case where we + // must elide not only a constructor call but also some argument + // conversions, so we don't elide it. + // CHECK-LABEL: define void @_ZN25ElidableCallIsNotCopyCtor1fEv( + // CHECK: call {{.*}} @_ZN25ElidableCallIsNotCopyCtor1BC1Ei( + // CHECK: call {{.*}} @_ZN25ElidableCallIsNotCopyCtor1AC1ERKS0_( + // CHECK: call {{.*}} @_ZN25ElidableCallIsNotCopyCtor1BC1ENS_1AE( + B b = 0; + } +} diff --git a/test/CodeGenCXX/copy-constructor-synthesis-2.cpp b/test/CodeGenCXX/copy-constructor-synthesis-2.cpp index 9790ca882c6b..9d7e18e80f67 100644 --- a/test/CodeGenCXX/copy-constructor-synthesis-2.cpp +++ b/test/CodeGenCXX/copy-constructor-synthesis-2.cpp @@ -24,4 +24,4 @@ struct A { virtual void a(); }; A x(A& y) { return y; } // CHECK: define linkonce_odr {{.*}} @_ZN1AC1ERKS_(%struct.A* {{.*}}%this, %struct.A* dereferenceable({{[0-9]+}})) unnamed_addr -// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTV1A, i32 0, i32 2) to i32 (...)**) +// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTV1A, i32 0, inrange i32 0, i32 2) to i32 (...)**) diff --git a/test/CodeGenCXX/copy-constructor-synthesis.cpp b/test/CodeGenCXX/copy-constructor-synthesis.cpp index 4928c61488e9..5a2cc1440f74 100644 --- a/test/CodeGenCXX/copy-constructor-synthesis.cpp +++ b/test/CodeGenCXX/copy-constructor-synthesis.cpp @@ -166,7 +166,7 @@ void f(B b1) { // CHECK-LABEL: define linkonce_odr void @_ZN12rdar138169401AC2ERKS0_( // CHECK: [[THIS:%.*]] = load [[A]]*, [[A]]** // CHECK-NEXT: [[T0:%.*]] = bitcast [[A]]* [[THIS]] to i32 (...)*** -// CHECK-NEXT: store i32 (...)** bitcast (i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @_ZTVN12rdar138169401AE, i32 0, i32 2) to i32 (...)**), i32 (...)*** [[T0]] +// CHECK-NEXT: store i32 (...)** bitcast (i8** getelementptr inbounds ({ [4 x i8*] }, { [4 x i8*] }* @_ZTVN12rdar138169401AE, i32 0, inrange i32 0, i32 2) to i32 (...)**), i32 (...)*** [[T0]] // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[A]], [[A]]* [[THIS]], i32 0, i32 1 // CHECK-NEXT: [[OTHER:%.*]] = load [[A]]*, [[A]]** // CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds [[A]], [[A]]* [[OTHER]], i32 0, i32 1 diff --git a/test/CodeGenCXX/ctor-dtor-alias.cpp b/test/CodeGenCXX/ctor-dtor-alias.cpp index 018e958aab53..6826ee5796ca 100644 --- a/test/CodeGenCXX/ctor-dtor-alias.cpp +++ b/test/CodeGenCXX/ctor-dtor-alias.cpp @@ -1,6 +1,6 @@ // RUN: %clang_cc1 %s -triple i686-linux -emit-llvm -o - -mconstructor-aliases | FileCheck --check-prefix=NOOPT %s -// RUN: %clang_cc1 %s -triple i686-linux -emit-llvm -o - -mconstructor-aliases -O1 -disable-llvm-optzns > %t +// RUN: %clang_cc1 %s -triple i686-linux -emit-llvm -o - -mconstructor-aliases -O1 -disable-llvm-passes > %t // RUN: FileCheck --check-prefix=CHECK1 --input-file=%t %s // RUN: FileCheck --check-prefix=CHECK2 --input-file=%t %s // RUN: FileCheck --check-prefix=CHECK3 --input-file=%t %s @@ -8,7 +8,7 @@ // RUN: FileCheck --check-prefix=CHECK5 --input-file=%t %s // RUN: FileCheck --check-prefix=CHECK6 --input-file=%t %s -// RUN: %clang_cc1 %s -triple i686-pc-windows-gnu -emit-llvm -o - -mconstructor-aliases -O1 -disable-llvm-optzns | FileCheck --check-prefix=COFF %s +// RUN: %clang_cc1 %s -triple i686-pc-windows-gnu -emit-llvm -o - -mconstructor-aliases -O1 -disable-llvm-passes | FileCheck --check-prefix=COFF %s namespace test1 { // Test that we produce the apropriate comdats when creating aliases to @@ -172,7 +172,7 @@ void zed() { } } -// CHECK5: @_ZTV1C = linkonce_odr unnamed_addr constant [4 x i8*] [{{[^@]*}}@_ZTI1C {{[^@]*}}@_ZN1CD2Ev {{[^@]*}}@_ZN1CD0Ev {{[^@]*}}] +// CHECK5: @_ZTV1C = linkonce_odr unnamed_addr constant { [4 x i8*] } {{[^@]*}}@_ZTI1C {{[^@]*}}@_ZN1CD2Ev {{[^@]*}}@_ZN1CD0Ev {{[^@]*}}] // r194296 replaced C::~C with B::~B without emitting the later. class A { diff --git a/test/CodeGenCXX/cxx11-exception-spec.cpp b/test/CodeGenCXX/cxx11-exception-spec.cpp index 6a3a394e047a..fbff07802676 100644 --- a/test/CodeGenCXX/cxx11-exception-spec.cpp +++ b/test/CodeGenCXX/cxx11-exception-spec.cpp @@ -121,7 +121,7 @@ void j() { } // CHECK: attributes [[NONE]] = { {{.*}} } -// CHECK: attributes [[NUW]] = { nounwind{{.*}} } +// CHECK: attributes [[NUW]] = { noinline nounwind{{.*}} } // CHECK: attributes [[NUW2]] = { nounwind{{.*}} } diff --git a/test/CodeGenCXX/cxx11-noreturn.cpp b/test/CodeGenCXX/cxx11-noreturn.cpp index b876bb9661ba..58a5a377133a 100644 --- a/test/CodeGenCXX/cxx11-noreturn.cpp +++ b/test/CodeGenCXX/cxx11-noreturn.cpp @@ -7,4 +7,4 @@ int g(); while (g()) {} } -// CHECK: attributes [[NR]] = { noreturn nounwind{{.*}} } +// CHECK: attributes [[NR]] = { noinline noreturn nounwind{{.*}} } diff --git a/test/CodeGenCXX/cxx1y-initializer-aggregate.cpp b/test/CodeGenCXX/cxx1y-initializer-aggregate.cpp index 50629b590562..6d0ae8a09e65 100644 --- a/test/CodeGenCXX/cxx1y-initializer-aggregate.cpp +++ b/test/CodeGenCXX/cxx1y-initializer-aggregate.cpp @@ -51,8 +51,8 @@ C n{}; // CHECK: store i32 0, i32* getelementptr inbounds ({{.*}} @a, i32 0, i32 0) // CHECK: store i8* {{.*}} @[[STR_A]]{{.*}}, i8** getelementptr inbounds ({{.*}} @a, i32 0, i32 1) -// CHECK: load i32, i32* getelementptr inbounds ({{.*}} @a, i32 0, i32 0) // CHECK: load i8*, i8** getelementptr inbounds ({{.*}} @a, i32 0, i32 1) +// CHECK: load i32, i32* getelementptr inbounds ({{.*}} @a, i32 0, i32 0) // CHECK: getelementptr inbounds i8, i8* %{{.*}}, {{.*}} %{{.*}} // CHECK: store i8 %{{.*}}, i8* getelementptr inbounds ({{.*}} @a, i32 0, i32 2) // CHECK: call i32 @_ZN1A1fEv({{.*}} @a) diff --git a/test/CodeGenCXX/cxx1y-variable-template-linkage.cpp b/test/CodeGenCXX/cxx1y-variable-template-linkage.cpp index 8c0b8c22096d..bc775568aaf1 100644 --- a/test/CodeGenCXX/cxx1y-variable-template-linkage.cpp +++ b/test/CodeGenCXX/cxx1y-variable-template-linkage.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -std=c++1y -O1 -disable-llvm-optzns %s -o - | FileCheck %s -check-prefix=CHECKA -check-prefix=CHECK -// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -std=c++1y -O1 -disable-llvm-optzns -fcxx-exceptions %s -o - | FileCheck %s -check-prefix=CHECKB -check-prefix=CHECK +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -std=c++1y -O1 -disable-llvm-passes %s -o - | FileCheck %s -check-prefix=CHECKA -check-prefix=CHECK +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -std=c++1y -O1 -disable-llvm-passes -fcxx-exceptions %s -o - | FileCheck %s -check-prefix=CHECKB -check-prefix=CHECK // expected-no-diagnostics // The variable template specialization x<Foo> generated in each file diff --git a/test/CodeGenCXX/cxx1z-aligned-allocation.cpp b/test/CodeGenCXX/cxx1z-aligned-allocation.cpp new file mode 100644 index 000000000000..437597d963b0 --- /dev/null +++ b/test/CodeGenCXX/cxx1z-aligned-allocation.cpp @@ -0,0 +1,206 @@ +// Check that delete exprs call aligned (de)allocation functions if +// -faligned-allocation is passed in both C++11 and C++14. +// RUN: %clang_cc1 -std=c++11 -fexceptions -fsized-deallocation -faligned-allocation %s -emit-llvm -triple x86_64-linux-gnu -o - | FileCheck %s +// RUN: %clang_cc1 -std=c++14 -fexceptions -fsized-deallocation -faligned-allocation %s -emit-llvm -triple x86_64-linux-gnu -o - | FileCheck %s +// RUN: %clang_cc1 -std=c++1z -fexceptions -fsized-deallocation %s -emit-llvm -triple x86_64-linux-gnu -o - | FileCheck %s + +// Check that we don't used aligned (de)allocation without -faligned-allocation or C++1z. +// RUN: %clang_cc1 -std=c++14 -DUNALIGNED -fexceptions %s -emit-llvm -triple x86_64-linux-gnu -o - | FileCheck %s --check-prefix=CHECK-UNALIGNED +// RUN: %clang_cc1 -std=c++1z -DUNALIGNED -fexceptions -fno-aligned-allocation %s -emit-llvm -triple x86_64-linux-gnu -o - | FileCheck %s --check-prefix=CHECK-UNALIGNED + +// CHECK-UNALIGNED-NOT: _Znwm_St11align_val_t +// CHECK-UNALIGNED-NOT: _Znam_St11align_val_t +// CHECK-UNALIGNED-NOT: _ZdlPv_St11align_val_t +// CHECK-UNALIGNED-NOT: _ZdaPv_St11align_val_t +// CHECK-UNALIGNED-NOT: _ZdlPvm_St11align_val_t +// CHECK-UNALIGNED-NOT: _ZdaPvm_St11align_val_t + +typedef decltype(sizeof(0)) size_t; +namespace std { enum class align_val_t : size_t {}; } + +#define OVERALIGNED alignas(__STDCPP_DEFAULT_NEW_ALIGNMENT__ * 2) + +// Global new and delete. +// ====================== +struct OVERALIGNED A { A(); int n[128]; }; + +// CHECK-LABEL: define {{.*}} @_Z2a0v() +// CHECK: %[[ALLOC:.*]] = call i8* @_ZnwmSt11align_val_t(i64 512, i64 32) +// CHECK: call void @_ZdlPvSt11align_val_t(i8* %[[ALLOC]], i64 32) +void *a0() { return new A; } + +// CHECK-LABEL: define {{.*}} @_Z2a1l( +// CHECK: %[[ALLOC:.*]] = call i8* @_ZnamSt11align_val_t(i64 %{{.*}}, i64 32) +// No array cookie. +// CHECK-NOT: store +// CHECK: invoke void @_ZN1AC1Ev( +// CHECK: call void @_ZdaPvSt11align_val_t(i8* %[[ALLOC]], i64 32) +void *a1(long n) { return new A[n]; } + +// CHECK-LABEL: define {{.*}} @_Z2a2P1A( +// CHECK: call void @_ZdlPvmSt11align_val_t(i8* %{{.*}}, i64 512, i64 32) #9 +void a2(A *p) { delete p; } + +// CHECK-LABEL: define {{.*}} @_Z2a3P1A( +// CHECK: call void @_ZdaPvSt11align_val_t(i8* %{{.*}}, i64 32) #9 +void a3(A *p) { delete[] p; } + + +// Class-specific usual new and delete. +// ==================================== +struct OVERALIGNED B { + B(); + // These are just a distraction. We should ignore them. + void *operator new(size_t); + void operator delete(void*, size_t); + void operator delete[](void*, size_t); + + void *operator new(size_t, std::align_val_t); + void operator delete(void*, std::align_val_t); + void operator delete[](void*, std::align_val_t); + + int n[128]; +}; + +// CHECK-LABEL: define {{.*}} @_Z2b0v() +// CHECK: %[[ALLOC:.*]] = call i8* @_ZN1BnwEmSt11align_val_t(i64 512, i64 32) +// CHECK: call void @_ZN1BdlEPvSt11align_val_t(i8* %[[ALLOC]], i64 32) +void *b0() { return new B; } + +// CHECK-LABEL: define {{.*}} @_Z2b1l( +// CHECK: %[[ALLOC:.*]] = call i8* @_ZnamSt11align_val_t(i64 %{{.*}}, i64 32) +// No array cookie. +// CHECK-NOT: store +// CHECK: invoke void @_ZN1BC1Ev( +// CHECK: call void @_ZN1BdaEPvSt11align_val_t(i8* %[[ALLOC]], i64 32) +void *b1(long n) { return new B[n]; } + +// CHECK-LABEL: define {{.*}} @_Z2b2P1B( +// CHECK: call void @_ZN1BdlEPvSt11align_val_t(i8* %{{.*}}, i64 32) +void b2(B *p) { delete p; } + +// CHECK-LABEL: define {{.*}} @_Z2b3P1B( +// CHECK: call void @_ZN1BdaEPvSt11align_val_t(i8* %{{.*}}, i64 32) +void b3(B *p) { delete[] p; } + +struct OVERALIGNED C { + C(); + void *operator new[](size_t, std::align_val_t); + void operator delete[](void*, size_t, std::align_val_t); + + // It doesn't matter that we have an unaligned operator delete[] that doesn't + // want the size. What matters is that the aligned one does. + void operator delete[](void*); +}; + +// This one has an array cookie. +// CHECK-LABEL: define {{.*}} @_Z2b4l( +// CHECK: call {{.*}} @llvm.umul.with.overflow{{.*}}i64 32 +// CHECK: call {{.*}} @llvm.uadd.with.overflow{{.*}}i64 32 +// CHECK: %[[ALLOC:.*]] = call i8* @_ZN1CnaEmSt11align_val_t(i64 %{{.*}}, i64 32) +// CHECK: store +// CHECK: call void @_ZN1CC1Ev( +// +// Note, we're still calling a placement allocation function, and there is no +// matching placement operator delete. =( +// FIXME: This seems broken. +// CHECK-NOT: call void @_ZN1CdaEPvmSt11align_val_t( +#ifndef UNALIGNED +void *b4(long n) { return new C[n]; } +#endif + +// CHECK-LABEL: define {{.*}} @_Z2b5P1C( +// CHECK: mul i64{{.*}} 32 +// CHECK: add i64{{.*}} 32 +// CHECK: call void @_ZN1CdaEPvmSt11align_val_t( +void b5(C *p) { delete[] p; } + + +// Global placement new. +// ===================== + +struct Q { int n; } q; +void *operator new(size_t, Q); +void *operator new(size_t, std::align_val_t, Q); +void operator delete(void*, Q); +void operator delete(void*, std::align_val_t, Q); + +// CHECK-LABEL: define {{.*}} @_Z2c0v( +// CHECK: %[[ALLOC:.*]] = call i8* @_ZnwmSt11align_val_t1Q(i64 512, i64 32, i32 % +// CHECK: call void @_ZdlPvSt11align_val_t1Q(i8* %[[ALLOC]], i64 32, i32 % +void *c0() { return new (q) A; } + + +// Class-specific placement new. +// ============================= + +struct OVERALIGNED D { + D(); + void *operator new(size_t, Q); + void *operator new(size_t, std::align_val_t, Q); + void operator delete(void*, Q); + void operator delete(void*, std::align_val_t, Q); +}; + +// CHECK-LABEL: define {{.*}} @_Z2d0v( +// CHECK: %[[ALLOC:.*]] = call i8* @_ZN1DnwEmSt11align_val_t1Q(i64 32, i64 32, i32 % +// CHECK: call void @_ZN1DdlEPvSt11align_val_t1Q(i8* %[[ALLOC]], i64 32, i32 % +void *d0() { return new (q) D; } + + +// Calling aligned new with placement syntax. +// ========================================== + +#ifndef UNALIGNED +// CHECK-LABEL: define {{.*}} @_Z2e0v( +// CHECK: %[[ALLOC:.*]] = call i8* @_ZnwmSt11align_val_t(i64 512, i64 5) +// CHECK: call void @_ZdlPvSt11align_val_t(i8* %[[ALLOC]], i64 5) +void *e0() { return new (std::align_val_t(5)) A; } + +// CHECK-LABEL: define {{.*}} @_Z2e1v( +// CHECK: %[[ALLOC:.*]] = call i8* @_ZN1BnwEmSt11align_val_t(i64 512, i64 5) +// CHECK: call void @_ZN1BdlEPvSt11align_val_t(i8* %[[ALLOC]], i64 5) +void *e1() { return new (std::align_val_t(5)) B; } +#endif + +// Variadic placement/non-placement allocation functions. +// ====================================================== + +struct OVERALIGNED F { + F(); + void *operator new(size_t, ...); + void operator delete(void*, ...); + int n[128]; +}; + +// CHECK-LABEL: define {{.*}} @_Z2f0v( +// CHECK: %[[ALLOC:.*]] = call i8* (i64, ...) @_ZN1FnwEmz(i64 512, i64 32) +// Non-placement allocation function, uses normal deallocation lookup which +// cares about whether a parameter has type std::align_val_t. +// CHECK: call void (i8*, ...) @_ZN1FdlEPvz(i8* %[[ALLOC]]) +void *f0() { return new F; } + +// CHECK-LABEL: define {{.*}} @_Z2f1v( +// CHECK: %[[ALLOC:.*]] = call i8* (i64, ...) @_ZN1FnwEmz(i64 512, i64 32, i32 % +// Placement allocation function, uses placement deallocation matching, which +// passes same arguments and therefore includes alignment. +// CHECK: call void (i8*, ...) @_ZN1FdlEPvz(i8* %[[ALLOC]], i64 32, i32 % +void *f1() { return new (q) F; } + +struct OVERALIGNED G { + G(); + void *operator new(size_t, std::align_val_t, ...); + void operator delete(void*, std::align_val_t, ...); + int n[128]; +}; +#ifndef UNALIGNED +// CHECK-LABEL: define {{.*}} @_Z2g0v +// CHECK: %[[ALLOC:.*]] = call i8* (i64, i64, ...) @_ZN1GnwEmSt11align_val_tz(i64 512, i64 32) +// CHECK: call void (i8*, i64, ...) @_ZN1GdlEPvSt11align_val_tz(i8* %[[ALLOC]], i64 32) +void *g0() { return new G; } + +// CHECK-LABEL: define {{.*}} @_Z2g1v +// CHECK: %[[ALLOC:.*]] = call i8* (i64, i64, ...) @_ZN1GnwEmSt11align_val_tz(i64 512, i64 32, i32 % +// CHECK: call void (i8*, i64, ...) @_ZN1GdlEPvSt11align_val_tz(i8* %[[ALLOC]], i64 32, i32 % +void *g1() { return new (q) G; } +#endif diff --git a/test/CodeGenCXX/cxx1z-constexpr-if.cpp b/test/CodeGenCXX/cxx1z-constexpr-if.cpp index 80a397f51e9a..14695363b331 100644 --- a/test/CodeGenCXX/cxx1z-constexpr-if.cpp +++ b/test/CodeGenCXX/cxx1z-constexpr-if.cpp @@ -2,7 +2,15 @@ void should_be_used_1(); void should_be_used_2(); +void should_be_used_3(); void should_not_be_used(); + +struct A { + constexpr explicit operator bool() const { + return true; + } +}; + void f() { if constexpr (false) should_not_be_used(); @@ -15,7 +23,12 @@ void f() { goto foo; foo: should_not_be_used(); } + if constexpr (A()) + should_be_used_3(); + else + should_not_be_used(); } // CHECK: should_be_used_1 // CHECK: should_be_used_2 +// CHECK: should_be_used_3 diff --git a/test/CodeGenCXX/cxx1z-copy-omission.cpp b/test/CodeGenCXX/cxx1z-copy-omission.cpp new file mode 100644 index 000000000000..234e4b12589c --- /dev/null +++ b/test/CodeGenCXX/cxx1z-copy-omission.cpp @@ -0,0 +1,81 @@ +// RUN: %clang_cc1 -std=c++1z -emit-llvm -triple x86_64-linux-gnu -o - %s | FileCheck %s + +struct A { + A(int); + A(A&&); + A(const A&); + ~A(); + + int arr[10]; +}; + +A f(); +void h(); + +// CHECK-LABEL: define {{.*}} @_Z1gv( +void g() { + // CHECK: %[[A:.*]] = alloca + // CHECK-NOT: alloca + // CHECK-NOT: call + // CHECK: call {{.*}} @_Z1fv({{.*}}* sret %[[A]]) + A a = A( A{ f() } ); + // CHECK-NOT: call + + // CHECK: call void @_Z1hv( + h(); + // CHECK-NOT: call + + // CHECK: call void @_ZN1AD1Ev({{.*}}* %[[A]]) + // CHECK-NOT: call + // CHECK-LABEL: } +} + +void f(A); + +// CHECK-LABEL: define {{.*}} @_Z1hv( +void h() { + // CHECK: %[[A:.*]] = alloca + // CHECK-NOT: alloca + // CHECK-NOT: call + + // CHECK: call {{.*}} @_Z1fv({{.*}}* sret %[[A]]) + // CHECK-NOT: call + // CHECK: call {{.*}} @_Z1f1A({{.*}}* %[[A]]) + f(f()); + // CHECK-NOT: call + // CHECK: call void @_ZN1AD1Ev({{.*}}* %[[A]]) + + // CHECK: call void @_Z1hv( + h(); + + // CHECK-NOT: call + // CHECK-LABEL: } +} + +// We still pass classes with trivial copy/move constructors and destructors in +// registers, even if the copy is formally omitted. +struct B { + B(int); + int n; +}; + +B fB(); +void fB(B); + +// CHECK-LABEL: define {{.*}} @_Z1iv( +void i() { + // CHECK: %[[B:.*]] = alloca + // CHECK-NOT: alloca + // CHECK-NOT: call + + // CHECK: %[[B_N:.*]] = call i32 @_Z2fBv() + // CHECK-NOT: call + // CHECK: store i32 %[[B_N]], + // CHECK-NOT: call + // CHECK: %[[B_N:.*]] = load i32 + // CHECK-NOT: call + // CHECK: call void @_Z2fB1B(i32 %[[B_N]]) + fB(fB()); + + // CHECK-LABEL: } +} diff --git a/test/CodeGenCXX/cxx1z-decomposition.cpp b/test/CodeGenCXX/cxx1z-decomposition.cpp new file mode 100644 index 000000000000..b9212006053b --- /dev/null +++ b/test/CodeGenCXX/cxx1z-decomposition.cpp @@ -0,0 +1,118 @@ +// RUN: %clang_cc1 -std=c++1z -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck %s + +namespace std { + using size_t = decltype(sizeof(0)); + template<typename> struct tuple_size; + template<size_t, typename> struct tuple_element; +} + +struct Y { int n; }; +struct X { X(); X(Y); X(const X&); ~X(); }; + +struct A { int a : 13; bool b; }; + +struct B {}; +template<> struct std::tuple_size<B> { enum { value = 2 }; }; +template<> struct std::tuple_element<0,B> { using type = X; }; +template<> struct std::tuple_element<1,B> { using type = const int&; }; +template<int N> auto get(B) { + if constexpr (N == 0) + return Y(); + else + return 0.0; +} + +using C = int[2]; + +typedef int D __attribute__((ext_vector_type(2))); + +using E = _Complex int; + +template<typename T> T &make(); + +// CHECK: @_ZDC2a12a2E = global {{.*}} zeroinitializer, align 4 +auto [a1, a2] = make<A>(); +// CHECK: @_ZDC2b12b2E = global {{.*}} zeroinitializer, align 1 +// CHECK: @b1 = global {{.*}}* null, align 8 +// CHECK: @_ZGR2b1_ = internal global {{.*}} zeroinitializer, align 1 +// CHECK: @b2 = global i32* null, align 8 +// CHECK: @_ZGR2b2_ = internal global i32 0, align 4 +auto [b1, b2] = make<B>(); +// CHECK: @_ZDC2c12c2E = global [2 x i32]* null, align 8 +auto &[c1, c2] = make<C>(); +// CHECK: @_ZDC2d12d2E = global <2 x i32> zeroinitializer, align 8 +auto [d1, d2] = make<D>(); +// CHECK: @_ZDC2e12e2E = global { i32, i32 } zeroinitializer, align 4 +auto [e1, e2] = make<E>(); + +// CHECK: call {{.*}}* @_Z4makeI1AERT_v() +// CHECK: call {{.*}}memcpy{{.*}}@_ZDC2a12a2E + +// CHECK: @_Z4makeI1BERT_v() +// CHECK: call i32 @_Z3getILi0EEDa1B() +// CHECK: call void @_ZN1XC1E1Y({{.*}}* @_ZGR2b1_, i32 +// CHECK: call i32 @__cxa_atexit({{.*}}@_ZN1XD1Ev{{.*}}@_ZGR2b1_ +// CHECK: store {{.*}}* @_ZGR2b1_, +// +// CHECK: call double @_Z3getILi1EEDa1B() +// CHECK: fptosi double %{{.*}} to i32 +// CHECK: store i32 %{{.*}}, i32* @_ZGR2b2_ +// CHECK: store i32* @_ZGR2b2_, i32** @b2 + +// CHECK: call {{.*}}* @_Z4makeIA2_iERT_v() +// CHECK: store {{.*}}, [2 x i32]** @_ZDC2c12c2E + +// CHECK: call {{.*}}* @_Z4makeIDv2_iERT_v() +// CHECK: store {{.*}}, <2 x i32>* @_ZDC2d12d2E, align 8 + +// CHECK: call {{.*}}* @_Z4makeICiERT_v() +// CHECK: store i32 %{{.*}}, i32* getelementptr inbounds ({ i32, i32 }, { i32, i32 }* @_ZDC2e12e2E, i32 0, i32 0) +// CHECK: store i32 %{{.*}}, i32* getelementptr inbounds ({ i32, i32 }, { i32, i32 }* @_ZDC2e12e2E, i32 0, i32 1) + +// CHECK: define i32 @_Z12test_globalsv() +int test_globals() { + return a2 + b2 + c2 + d2 + e2; + // CHECK: load i8, i8* getelementptr inbounds (%struct.A, %struct.A* @_ZDC2a12a2E, i32 0, i32 1) + // + // CHECK: %[[b2:.*]] = load i32*, i32** @b2 + // CHECK: load i32, i32* %[[b2]] + // + // CHECK: %[[c1c2:.*]] = load [2 x i32]*, [2 x i32]** @_ZDC2c12c2E + // CHECK: %[[c2:.*]] = getelementptr inbounds [2 x i32], [2 x i32]* %[[c1c2]], i64 0, i64 1 + // CHECK: load i32, i32* %[[c2]] + // + // CHECK: %[[d1d2:.*]] = load <2 x i32>, <2 x i32>* @_ZDC2d12d2E + // CHECK: extractelement <2 x i32> %[[d1d2]], i32 1 + // + // CHECK: load i32, i32* getelementptr inbounds ({ i32, i32 }, { i32, i32 }* @_ZDC2e12e2E, i32 0, i32 1) +} + +// CHECK: define i32 @_Z11test_localsv() +int test_locals() { + auto [b1, b2] = make<B>(); + + // CHECK: @_Z4makeI1BERT_v() + // CHECK: call i32 @_Z3getILi0EEDa1B() + // CHECK: call void @_ZN1XC1E1Y({{.*}}* %[[b1:.*]], i32 + // + // CHECK: call double @_Z3getILi1EEDa1B() + // CHECK: %[[cvt:.*]] = fptosi double %{{.*}} to i32 + // CHECK: store i32 %[[cvt]], i32* %[[b2:.*]], + // CHECK: store i32* %[[b2]], i32** %[[b2ref:.*]], + + return b2; + // CHECK: %[[b2:.*]] = load i32*, i32** %[[b2ref]] + // CHECK: load i32, i32* %[[b2]] + + // CHECK: call {{.*}}@_ZN1XD1Ev({{.*}}%[[b1]]) +} + +// CHECK: define void @_Z13test_bitfieldR1A( +void test_bitfield(A &a) { + auto &[a1, a2] = a; + a1 = 5; + // CHECK: load i16, i16* %[[BITFIELD:.*]], + // CHECK: and i16 %{{.*}}, -8192 + // CHECK: or i16 %{{.*}}, 5 + // CHECK: store i16 %{{.*}}, i16* %[[BITFIELD]], +} diff --git a/test/CodeGenCXX/cxx1z-eval-order.cpp b/test/CodeGenCXX/cxx1z-eval-order.cpp new file mode 100644 index 000000000000..1106719a4748 --- /dev/null +++ b/test/CodeGenCXX/cxx1z-eval-order.cpp @@ -0,0 +1,271 @@ +// RUN: %clang_cc1 -std=c++1z %s -emit-llvm -o - -triple %itanium_abi_triple | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-ITANIUM +// RUN: %clang_cc1 -std=c++1z %s -emit-llvm -o - -triple i686-windows | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-WINDOWS +// RUN: %clang_cc1 -std=c++1z %s -emit-llvm -o - -triple x86_64-windows | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-WINDOWS + +struct B; +struct A { + A(); + A(const A&); + + void operator[](B b); + + int a_member_f(B); +}; +struct B { + B(); + ~B(); +}; + +struct C { + operator int *(); + A *operator->(); + void operator->*(A); + friend void operator->*(C, B); + + friend void operator<<(C, B); + friend void operator>>(C, B); + void operator<<(A); + void operator>>(A); + + void operator=(A); + void operator+=(A); + friend void operator+=(C, B); + + void operator,(A); + friend void operator,(C, B); + + void operator&&(A); + void operator||(A); + friend void operator&&(C, B); + friend void operator||(C, B); +}; + +A make_a(); +A *make_a_ptr(); +int A::*make_mem_ptr_a(); +void (A::*make_mem_fn_ptr_a())(); +B make_b(); +C make_c(); +void side_effect(); + +void callee(A); +void (*get_f())(A); + + +// CHECK-LABEL: define {{.*}}@{{.*}}postfix_before_args{{.*}}( +void postfix_before_args() { + // CHECK: call {{.*}}@{{.*}}get_f{{.*}}( + // CHECK-ITANIUM: call {{.*}}@_ZN1AC1Ev( + // CHECK-WINDOWS: call {{.*}}@"\01??0A@@Q{{AE|EAA}}@XZ"( + // CHECK: call {{.*}}%{{.*}}( + get_f()(A{}); + + // CHECK: call {{.*}}@{{.*}}side_effect{{.*}}( + // CHECK-ITANIUM: call {{.*}}@_ZN1AC1Ev( + // CHECK-WINDOWS: call {{.*}}@"\01??0A@@Q{{AE|EAA}}@XZ"( + // CHECK: call {{.*}}@{{.*}}callee{{.*}}( + (side_effect(), callee)(A{}); +// CHECK: } +} + + +// CHECK-LABEL: define {{.*}}@{{.*}}dot_lhs_before_rhs{{.*}}( +void dot_lhs_before_rhs() { + // CHECK: call {{.*}}@{{.*}}make_a{{.*}}( + // CHECK: call {{.*}}@{{.*}}make_b{{.*}}( + // CHECK: call {{.*}}@{{.*}}a_member_f{{.*}}( + make_a().a_member_f(make_b()); + + // CHECK: call {{.*}}@{{.*}}make_a_ptr{{.*}}( + // CHECK: call {{.*}}@{{.*}}make_b{{.*}}( + // CHECK: call {{.*}}@{{.*}}a_member_f{{.*}}( + make_a_ptr()->a_member_f(make_b()); + + // CHECK: call {{.*}}@{{.*}}make_c{{.*}}( + // CHECK: call {{.*}}@{{.*}}make_b{{.*}}( + // CHECK: call {{.*}}@{{.*}}a_member_f{{.*}}( + make_c()->a_member_f(make_b()); +// CHECK: } +} + + +// CHECK-LABEL: define {{.*}}@{{.*}}array_lhs_before_rhs{{.*}}( +void array_lhs_before_rhs() { + int (&get_arr())[10]; + extern int get_index(); + + // CHECK: call {{.*}}@{{.*}}get_arr{{.*}}( + // CHECK: call {{.*}}@{{.*}}get_index{{.*}}( + get_arr()[get_index()] = 0; + + // CHECK: call {{.*}}@{{.*}}get_index{{.*}}( + // CHECK: call {{.*}}@{{.*}}get_arr{{.*}}( + get_index()[get_arr()] = 0; + + // CHECK: call {{.*}}@{{.*}}make_a{{.*}}( + // CHECK: call {{.*}}@{{.*}}make_b{{.*}}( + // CHECK: call + make_a()[make_b()]; + + // CHECK: call {{.*}}@{{.*}}make_c{{.*}}( + // CHECK: call {{.*}}@{{.*}}get_index{{.*}}( + // CHECK: call + make_c()[get_index()] = 0; + + // CHECK: call {{.*}}@{{.*}}get_index{{.*}}( + // CHECK: call {{.*}}@{{.*}}make_c{{.*}}( + // CHECK: call + get_index()[make_c()] = 0; +// CHECK: } +} + + +void *operator new(decltype(sizeof(0)), C); + +// CHECK-LABEL: define {{.*}}@{{.*}}alloc_before_init{{.*}}( +void alloc_before_init() { + struct Q { Q(A) {} }; + // CHECK-ITANIUM: call {{.*}}@_Znw{{.*}}( + // CHECK-WINDOWS: call {{.*}}@"\01??2@YAP{{EAX_K|AXI}}@Z"( + // CHECK: call {{.*}}@{{.*}}make_a{{.*}}( + delete new Q(make_a()); + + // CHECK: call {{.*}}@{{.*}}make_c{{.*}}( + // CHECK: call {{.*}}@{{.*}}make_a{{.*}}( + new (make_c()) Q(make_a()); +// CHECK: } +} + + +// CHECK-LABEL: define {{.*}}@{{.*}}dotstar_lhs_before_rhs{{.*}}( +int dotstar_lhs_before_rhs() { + // CHECK: call {{.*}}@{{.*}}make_a{{.*}}( + // CHECK: call {{.*}}@{{.*}}make_mem_ptr_a{{.*}}( + int a = make_a().*make_mem_ptr_a(); + + // CHECK: call {{.*}}@{{.*}}make_a_ptr{{.*}}( + // CHECK: call {{.*}}@{{.*}}make_mem_ptr_a{{.*}}( + int b = make_a_ptr()->*make_mem_ptr_a(); + + // CHECK: call {{.*}}@{{.*}}make_c{{.*}}( + // CHECK: call {{.*}}@{{.*}}make_a{{.*}}( + make_c()->*make_a(); + + // FIXME: For MS ABI, the order of destruction of parameters here will not be + // reverse construction order (parameters are destroyed left-to-right in the + // callee). That sadly seems unavoidable; the rules are not implementable as + // specified. If we changed parameter destruction order for these functions + // to right-to-left, we could make the destruction order match for all cases + // other than indirect calls, but we can't completely avoid the problem. + // + // CHECK: call {{.*}}@{{.*}}make_c{{.*}}( + // CHECK: call {{.*}}@{{.*}}make_b{{.*}}( + make_c()->*make_b(); + + // CHECK: call {{.*}}@{{.*}}make_a{{.*}}( + // CHECK: call {{.*}}@{{.*}}make_mem_fn_ptr_a{{.*}}( + // CHECK: call + (make_a().*make_mem_fn_ptr_a())(); + + // CHECK: call {{.*}}@{{.*}}make_a_ptr{{.*}}( + // CHECK: call {{.*}}@{{.*}}make_mem_fn_ptr_a{{.*}}( + // CHECK: call + (make_a_ptr()->*make_mem_fn_ptr_a())(); + + return a + b; +// CHECK: } +} + + +// CHECK-LABEL: define {{.*}}@{{.*}}assign_rhs_before_lhs{{.*}}( +void assign_rhs_before_lhs() { + extern int &lhs_ref(), rhs(); + + // CHECK: call {{.*}}@{{.*}}rhs{{.*}}( + // CHECK: call {{.*}}@{{.*}}lhs_ref{{.*}}( + lhs_ref() = rhs(); + + // CHECK: call {{.*}}@{{.*}}rhs{{.*}}( + // CHECK: call {{.*}}@{{.*}}lhs_ref{{.*}}( + lhs_ref() += rhs(); + + // CHECK: call {{.*}}@{{.*}}rhs{{.*}}( + // CHECK: call {{.*}}@{{.*}}lhs_ref{{.*}}( + lhs_ref() %= rhs(); + + // CHECK: call {{.*}}@{{.*}}make_a{{.*}}( + // CHECK: call {{.*}}@{{.*}}make_c{{.*}}( + make_c() = make_a(); + + // CHECK: call {{.*}}@{{.*}}make_a{{.*}}( + // CHECK: call {{.*}}@{{.*}}make_c{{.*}}( + make_c() += make_a(); + + // CHECK: call {{.*}}@{{.*}}make_b{{.*}}( + // CHECK: call {{.*}}@{{.*}}make_c{{.*}}( + make_c() += make_b(); +// CHECK: } +} + +// CHECK-LABEL: define {{.*}}@{{.*}}shift_lhs_before_rhs{{.*}}( +void shift_lhs_before_rhs() { + extern int lhs(), rhs(); + + // CHECK: call {{.*}}@{{.*}}lhs{{.*}}( + // CHECK: call {{.*}}@{{.*}}rhs{{.*}}( + (void)(lhs() << rhs()); + + // CHECK: call {{.*}}@{{.*}}lhs{{.*}}( + // CHECK: call {{.*}}@{{.*}}rhs{{.*}}( + (void)(lhs() >> rhs()); + + // CHECK: call {{.*}}@{{.*}}make_c{{.*}}( + // CHECK: call {{.*}}@{{.*}}make_a{{.*}}( + make_c() << make_a(); + + // CHECK: call {{.*}}@{{.*}}make_c{{.*}}( + // CHECK: call {{.*}}@{{.*}}make_a{{.*}}( + make_c() >> make_a(); + + // FIXME: This is not correct for Windows ABIs, see above. + // CHECK: call {{.*}}@{{.*}}make_c{{.*}}( + // CHECK: call {{.*}}@{{.*}}make_b{{.*}}( + make_c() << make_b(); + + // CHECK: call {{.*}}@{{.*}}make_c{{.*}}( + // CHECK: call {{.*}}@{{.*}}make_b{{.*}}( + make_c() >> make_b(); +// CHECK: } +} + +// CHECK-LABEL: define {{.*}}@{{.*}}comma_lhs_before_rhs{{.*}}( +void comma_lhs_before_rhs() { + // CHECK: call {{.*}}@{{.*}}make_c{{.*}}( + // CHECK: call {{.*}}@{{.*}}make_a{{.*}}( + make_c() , make_a(); + + // FIXME: This is not correct for Windows ABIs, see above. + // CHECK: call {{.*}}@{{.*}}make_c{{.*}}( + // CHECK: call {{.*}}@{{.*}}make_b{{.*}}( + make_c() , make_b(); +} + +// CHECK-LABEL: define {{.*}}@{{.*}}andor_lhs_before_rhs{{.*}}( +void andor_lhs_before_rhs() { + // CHECK: call {{.*}}@{{.*}}make_c{{.*}}( + // CHECK: call {{.*}}@{{.*}}make_a{{.*}}( + make_c() && make_a(); + + // CHECK: call {{.*}}@{{.*}}make_c{{.*}}( + // CHECK: call {{.*}}@{{.*}}make_a{{.*}}( + make_c() || make_a(); + + // FIXME: This is not correct for Windows ABIs, see above. + // CHECK: call {{.*}}@{{.*}}make_c{{.*}}( + // CHECK: call {{.*}}@{{.*}}make_b{{.*}}( + make_c() && make_b(); + + // CHECK: call {{.*}}@{{.*}}make_c{{.*}}( + // CHECK: call {{.*}}@{{.*}}make_b{{.*}}( + make_c() || make_b(); +} diff --git a/test/CodeGenCXX/cxx1z-noexcept-function-type.cpp b/test/CodeGenCXX/cxx1z-noexcept-function-type.cpp new file mode 100644 index 000000000000..d2d06fbd2654 --- /dev/null +++ b/test/CodeGenCXX/cxx1z-noexcept-function-type.cpp @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -fexceptions -fcxx-exceptions -std=c++1z -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s + +// CHECK-LABEL: define {{.*}} @_Z11builtin_newm( +// CHECK: call {{.*}} @_Znwm( +void *builtin_new(unsigned long n) { return __builtin_operator_new(n); } + +// CHECK-LABEL: define {{.*}} @_Z14builtin_deletePv( +// CHECK: call {{.*}} @_ZdlPv( +void builtin_delete(void *p) { return __builtin_operator_delete(p); } diff --git a/test/CodeGenCXX/debug-info-access.cpp b/test/CodeGenCXX/debug-info-access.cpp index 41b7f71fcecb..82f29ea4d38a 100644 --- a/test/CodeGenCXX/debug-info-access.cpp +++ b/test/CodeGenCXX/debug-info-access.cpp @@ -39,6 +39,6 @@ private: // CHECK-SAME: flags: DIFlagPrototyped, void free() {} +U u; A a; B b; -U u; diff --git a/test/CodeGenCXX/debug-info-alias.cpp b/test/CodeGenCXX/debug-info-alias.cpp index 90476439e782..8c3f8447de69 100644 --- a/test/CodeGenCXX/debug-info-alias.cpp +++ b/test/CodeGenCXX/debug-info-alias.cpp @@ -14,8 +14,6 @@ bar } // CHECK: !DIGlobalVariable(name: "bi",{{.*}} type: [[BINT:![0-9]+]] -// CHECK: [[BINT]] = !DIDerivedType(tag: DW_TAG_typedef, name: "bar<int>" -// CHECK-SAME: line: 42, x::bar<int> bi; // CHECK: !DIGlobalVariable(name: "bf",{{.*}} type: [[BFLOAT:![0-9]+]] // CHECK: [[BFLOAT]] = !DIDerivedType(tag: DW_TAG_typedef, name: "bar<float>" @@ -37,3 +35,6 @@ tv<int> *tvp; using v = void; // CHECK: !DIDerivedType(tag: DW_TAG_typedef, name: "v" v *vp; + +// CHECK: [[BINT]] = !DIDerivedType(tag: DW_TAG_typedef, name: "bar<int>" +// CHECK-SAME: line: 42, diff --git a/test/CodeGenCXX/debug-info-anon-namespace.cpp b/test/CodeGenCXX/debug-info-anon-namespace.cpp index 4e3e08af2b74..79298deaf8b1 100644 --- a/test/CodeGenCXX/debug-info-anon-namespace.cpp +++ b/test/CodeGenCXX/debug-info-anon-namespace.cpp @@ -19,8 +19,9 @@ int *b2 = &a2; // PS4: [[NS:![0-9]+]] = !DINamespace +// PS4: [[CU:![0-9]+]] = distinct !DICompileUnit // PS4: [[NS2:![0-9]+]] = !DINamespace -// PS4: !DIImportedEntity(tag: DW_TAG_imported_module, scope: !0, entity: [[NS]]) +// PS4: !DIImportedEntity(tag: DW_TAG_imported_module, scope: [[CU]], entity: [[NS]]) // PS4: !DIImportedEntity(tag: DW_TAG_imported_module, scope: [[NS]], entity: [[NS2]], line: {{[0-9]+}}) // NON-PS4-NOT: !DIImportedEntity diff --git a/test/CodeGenCXX/debug-info-anon-union-vars.cpp b/test/CodeGenCXX/debug-info-anon-union-vars.cpp index b844d429447b..61b3c7c0526c 100644 --- a/test/CodeGenCXX/debug-info-anon-union-vars.cpp +++ b/test/CodeGenCXX/debug-info-anon-union-vars.cpp @@ -45,8 +45,8 @@ void instantiate(int x) { } // CHECK: !DIGlobalVariable(name: "c",{{.*}} file: [[FILE:.*]], line: 6,{{.*}} isLocal: true, isDefinition: true -// CHECK: [[FILE]] = !DIFile(filename: "{{.*}}debug-info-anon-union-vars.cpp", // CHECK: !DIGlobalVariable(name: "d",{{.*}} file: [[FILE]], line: 6,{{.*}} isLocal: true, isDefinition: true +// CHECK: [[FILE]] = !DIFile(filename: "{{.*}}debug-info-anon-union-vars.cpp", // CHECK: !DIGlobalVariable(name: "a",{{.*}} file: [[FILE]], line: 6,{{.*}} isLocal: true, isDefinition: true // CHECK: !DIGlobalVariable(name: "b",{{.*}} file: [[FILE]], line: 6,{{.*}} isLocal: true, isDefinition: true // CHECK: !DIGlobalVariable(name: "result", {{.*}} isLocal: false, isDefinition: true diff --git a/test/CodeGenCXX/debug-info-calling-conventions.cpp b/test/CodeGenCXX/debug-info-calling-conventions.cpp index 51d801e35ef6..db7fbd23405d 100644 --- a/test/CodeGenCXX/debug-info-calling-conventions.cpp +++ b/test/CodeGenCXX/debug-info-calling-conventions.cpp @@ -8,7 +8,7 @@ void A::thiscallcc() {} // CHECK: !DISubprogram(name: "thiscallcc", {{.*}} type: ![[thiscallty:[^,]*]], {{.*}}) // CHECK: ![[thiscallty]] = !DISubroutineType(cc: DW_CC_BORLAND_thiscall, types: ![[thisargs:[^,)]*]]) // CHECK: ![[thisargs]] = !{null, ![[thisptrty:[^,}]*]]} -// CHECK: ![[thisptrty]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !{{.*}}, size: 32, align: 32, flags: DIFlagArtificial | DIFlagObjectPointer) +// CHECK: ![[thisptrty]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !{{.*}}, size: 32, flags: DIFlagArtificial | DIFlagObjectPointer) void cdeclcc() {} void __fastcall fastcallcc() {} diff --git a/test/CodeGenCXX/debug-info-class-nolimit.cpp b/test/CodeGenCXX/debug-info-class-nolimit.cpp index ce47f9fa495a..0b3b38dd17b1 100644 --- a/test/CodeGenCXX/debug-info-class-nolimit.cpp +++ b/test/CodeGenCXX/debug-info-class-nolimit.cpp @@ -1,8 +1,26 @@ -// RUN: %clang_cc1 -triple x86_64-unk-unk -debug-info-kind=standalone -o - -emit-llvm %s | FileCheck %s -// On Darwin, "full" debug info is the default, so really these tests are -// identical, as cc1 no longer chooses the effective value of DebugInfoKind. // RUN: %clang_cc1 -triple x86_64-apple-darwin -debug-info-kind=standalone -o - -emit-llvm %s | FileCheck %s +// We had a bug in -fstandalone-debug where UnicodeString would not be completed +// when it was required to be complete. This orginally manifested as an +// assertion in CodeView emission on Windows with some dllexport stuff, but it's +// more general than that. + +struct UnicodeString; +UnicodeString *force_fwd_decl; +struct UnicodeString { +private: + virtual ~UnicodeString(); +}; +struct UseCompleteType { + UseCompleteType(); + ~UseCompleteType(); + UnicodeString currencySpcAfterSym[1]; +}; +UseCompleteType require_complete; +// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "UnicodeString" +// CHECK-NOT: DIFlagFwdDecl +// CHECK-SAME: ){{$}} + namespace rdar14101097_1 { // see also PR16214 // Check that we emit debug info for the definition of a struct if the // definition is available, even if it's used via a pointer wrapped in a diff --git a/test/CodeGenCXX/debug-info-class.cpp b/test/CodeGenCXX/debug-info-class.cpp index d03c0845dd6b..d572eef68abf 100644 --- a/test/CodeGenCXX/debug-info-class.cpp +++ b/test/CodeGenCXX/debug-info-class.cpp @@ -122,6 +122,7 @@ int main(int argc, char **argv) { // CHECK: [[C_DTOR]] = !DISubprogram(name: "~C" // CHECK: [[D:![0-9]+]] = !DICompositeType(tag: DW_TAG_structure_type, name: "D" +// CHECK-NOT: size: // CHECK-SAME: DIFlagFwdDecl // CHECK-SAME: identifier: "_ZTS1D" // CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "E" diff --git a/test/CodeGenCXX/debug-info-codeview-injected-class.cpp b/test/CodeGenCXX/debug-info-codeview-injected-class.cpp new file mode 100644 index 000000000000..b421b2bf8bd9 --- /dev/null +++ b/test/CodeGenCXX/debug-info-codeview-injected-class.cpp @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 %s -std=c++11 -triple=i686-pc-windows-msvc -debug-info-kind=limited -gcodeview -emit-llvm -o - | FileCheck %s + +// The injected class names in this test were accidentally making it into our +// nested class record debug info. Make sure they don't appear there. + +// PR28790 + +struct A { + const char *m_fn1(); + template <typename> class B; + template <typename> class C; + template <typename FunctionIdT> class C<B<FunctionIdT>>; +}; +const char *A::m_fn1() { return nullptr; } + +// CHECK: ![[A:[^ ]*]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "A", +// CHECK-SAME: elements: ![[elements:[0-9]+]] + +// CHECK: ![[elements]] = !{![[m_fn1:[0-9]+]]} + +// CHECK: ![[m_fn1]] = !DISubprogram(name: "m_fn1", diff --git a/test/CodeGenCXX/debug-info-cxx1y.cpp b/test/CodeGenCXX/debug-info-cxx1y.cpp index 36b3e09180c6..403424e2d6a8 100644 --- a/test/CodeGenCXX/debug-info-cxx1y.cpp +++ b/test/CodeGenCXX/debug-info-cxx1y.cpp @@ -3,9 +3,6 @@ // CHECK: imports: [[IMPS:![0-9]*]] // CHECK: [[EMPTY:![0-9]*]] = !{} -// CHECK: [[FOO:![0-9]+]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "foo", -// CHECK-SAME: elements: [[EMPTY]] - // CHECK: [[IMPS]] = !{[[IMP:![0-9]*]]} // CHECK: [[IMP]] = !DIImportedEntity( // CHECK-SAME: entity: [[F3:![0-9]*]] @@ -15,6 +12,9 @@ // CHECK: [[TYPE_LIST]] = !{[[INT:![0-9]*]]} // CHECK: [[INT]] = !DIBasicType(name: "int" +// CHECK: [[FOO:![0-9]+]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "foo", +// CHECK-SAME: elements: [[EMPTY]] + // FIXME: The context of this definition should be the CU/file scope, not the class. // CHECK: !DISubprogram(name: "func", {{.*}} scope: [[FOO]] // CHECK-SAME: type: [[SUBROUTINE_TYPE]] diff --git a/test/CodeGenCXX/debug-info-dllimport-base-class.cpp b/test/CodeGenCXX/debug-info-dllimport-base-class.cpp new file mode 100644 index 000000000000..855ecaaa4c90 --- /dev/null +++ b/test/CodeGenCXX/debug-info-dllimport-base-class.cpp @@ -0,0 +1,53 @@ +// RUN: %clang_cc1 -triple i386-pc-windows -emit-llvm -gcodeview -debug-info-kind=limited -fms-compatibility %s -x c++ -o - | FileCheck %s + +// Ensure we emit debug info for the full definition of base classes that will +// be imported from a DLL. Otherwise, the debugger wouldn't be able to show the +// members. + +// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "ImportedAfterCompletion", +// CHECK-NOT: DIFlagFwdDecl +// CHECK-SAME: ){{$}} + +// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "OutOfLineCtor", +// CHECK-SAME: DIFlagFwdDecl +// CHECK-SAME: ){{$}} + +// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "ImportedBase", +// CHECK-NOT: DIFlagFwdDecl +// CHECK-SAME: ){{$}} + +// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "ImportedMethod", +// CHECK-NOT: DIFlagFwdDecl +// CHECK-SAME: ){{$}} + + +struct ImportedAfterCompletion; +ImportedAfterCompletion *force_fwd_decl; +struct __declspec(dllimport) ImportedAfterCompletion { + virtual ~ImportedAfterCompletion(); +}; + +struct OutOfLineCtor { + OutOfLineCtor(); + virtual void Foo(); +}; + +struct __declspec(dllimport) ImportedBase { + ImportedBase(); + virtual void Foo(); +}; + +struct DerivedFromImported : public ImportedBase {}; + +struct ImportedMethod { + ImportedMethod(); + virtual void Foo(); + static void __declspec(dllimport) create(); +}; + +int main() { + ImportedAfterCompletion c; + OutOfLineCtor o; + DerivedFromImported d; + ImportedMethod m; +} diff --git a/test/CodeGenCXX/debug-info-dup-fwd-decl.cpp b/test/CodeGenCXX/debug-info-dup-fwd-decl.cpp index f7a2cfe7bae6..3b23ebf7dedc 100644 --- a/test/CodeGenCXX/debug-info-dup-fwd-decl.cpp +++ b/test/CodeGenCXX/debug-info-dup-fwd-decl.cpp @@ -19,6 +19,6 @@ protected: Test t; -// CHECK: !DIDerivedType(tag: DW_TAG_pointer_type // CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "data" +// CHECK: !DIDerivedType(tag: DW_TAG_pointer_type // CHECK-NOT: !DICompositeType(tag: DW_TAG_structure_type, name: "data" diff --git a/test/CodeGenCXX/debug-info-enum-class.cpp b/test/CodeGenCXX/debug-info-enum-class.cpp index 44daf412d3ac..b615d5b09626 100644 --- a/test/CodeGenCXX/debug-info-enum-class.cpp +++ b/test/CodeGenCXX/debug-info-enum-class.cpp @@ -13,7 +13,7 @@ D d; // CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "A" // CHECK-SAME: line: 3 // CHECK-SAME: baseType: ![[INT:[0-9]+]] -// CHECK-SAME: size: 32, align: 32 +// CHECK-SAME: size: 32 // CHECK-NOT: offset: // CHECK-NOT: flags: // CHECK-SAME: ){{$}} @@ -21,7 +21,7 @@ D d; // CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "B" // CHECK-SAME: line: 4 // CHECK-SAME: baseType: ![[ULONG:[0-9]+]] -// CHECK-SAME: size: 64, align: 64 +// CHECK-SAME: size: 64 // CHECK-NOT: offset: // CHECK-NOT: flags: // CHECK-SAME: ){{$}} @@ -29,7 +29,7 @@ D d; // CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "C" // CHECK-SAME: line: 5 // CHECK-NOT: baseType: -// CHECK-SAME: size: 32, align: 32 +// CHECK-SAME: size: 32 // CHECK-NOT: offset: // CHECK-NOT: flags: // CHECK-SAME: ){{$}} @@ -91,7 +91,7 @@ void f2(E) { // CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "D" // CHECK-SAME: line: 6 -// CHECK-SAME: size: 16, align: 16 +// CHECK-SAME: size: 16 // CHECK-NOT: offset: // CHECK-SAME: flags: DIFlagFwdDecl diff --git a/test/CodeGenCXX/debug-info-flex-member.cpp b/test/CodeGenCXX/debug-info-flex-member.cpp deleted file mode 100644 index 8dcdaeb935d0..000000000000 --- a/test/CodeGenCXX/debug-info-flex-member.cpp +++ /dev/null @@ -1,9 +0,0 @@ -// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited -triple x86_64-apple-darwin %s -o - | FileCheck %s - -// CHECK: !DISubrange(count: -1) - -struct StructName { - int member[]; -}; - -struct StructName SN; diff --git a/test/CodeGenCXX/debug-info-global.cpp b/test/CodeGenCXX/debug-info-global.cpp index 795602380d20..5abc050431d1 100644 --- a/test/CodeGenCXX/debug-info-global.cpp +++ b/test/CodeGenCXX/debug-info-global.cpp @@ -15,7 +15,8 @@ int f1() { // CHECK: [[GLOBALS]] = !{[[CNST:![0-9]*]]} -// CHECK: [[CNST]] = distinct !DIGlobalVariable(name: "cnst", -// CHECK-SAME: scope: [[NS:![0-9]*]] +// CHECK: [[CNST]] = !DIGlobalVariableExpression(var: [[CNSTV:.*]], expr: +// CHECK: [[CNSTV]] = distinct !DIGlobalVariable(name: "cnst", +// CHECK-SAME: scope: [[NS:![0-9]*]] // CHECK: [[NS]] = !DINamespace(name: "ns" diff --git a/test/CodeGenCXX/debug-info-indirect-field-decl.cpp b/test/CodeGenCXX/debug-info-indirect-field-decl.cpp index 70b233cac4dc..126e1f6bd1b8 100644 --- a/test/CodeGenCXX/debug-info-indirect-field-decl.cpp +++ b/test/CodeGenCXX/debug-info-indirect-field-decl.cpp @@ -11,13 +11,13 @@ struct Bar { // CHECK: !DIDerivedType(tag: DW_TAG_member, scope: // CHECK-SAME: line: [[@LINE+4]] // CHECK-SAME: baseType: ![[UNION:[0-9]+]] - // CHECK-SAME: size: 32, align: 32, offset: 32 + // CHECK-SAME: size: 32, offset: 32 // CHECK: ![[UNION]] = distinct !DICompositeType(tag: DW_TAG_union_type,{{.*}} identifier: "_ZTSN3BarUt_E") union { // CHECK: !DIDerivedType(tag: DW_TAG_member, name: "i2", // CHECK-SAME: line: [[@LINE+5]] // CHECK-SAME: baseType: ![[INT]] - // CHECK-SAME: size: 32, align: 32 + // CHECK-SAME: size: 32 // CHECK-NOT: offset: // CHECK-SAME: ){{$}} int i2; diff --git a/test/CodeGenCXX/debug-info-line-if.cpp b/test/CodeGenCXX/debug-info-line-if.cpp index b3f9c32e0911..41770b135619 100644 --- a/test/CodeGenCXX/debug-info-line-if.cpp +++ b/test/CodeGenCXX/debug-info-line-if.cpp @@ -53,15 +53,19 @@ int main() { // CHECK-DAG: [[DBG3]] = !DILocation(line: 300, scope: !{{.*}}) // CHECK-DAG: [[DBG4]] = !DILocation(line: 401, scope: !{{.*}}) - // CHECK-DAG: [[L1]] = distinct !{[[L1]], [[LDBG1:![0-9]*]]} - // CHECK-DAG: [[LDBG1]] = !DILocation(line: 100, scope: !{{.*}}) + // CHECK-DAG: [[L1]] = distinct !{[[L1]], [[SLDBG1:![0-9]*]], [[ELDBG1:![0-9]*]]} + // CHECK-DAG: [[SLDBG1]] = !DILocation(line: 100, scope: !{{.*}}) + // CHECK-DAG: [[ELDBG1]] = !DILocation(line: 104, scope: !{{.*}}) - // CHECK-DAG: [[L2]] = distinct !{[[L2]], [[LDBG2:![0-9]*]]} - // CHECK-DAG: [[LDBG2]] = !DILocation(line: 200, scope: !{{.*}}) + // CHECK-DAG: [[L2]] = distinct !{[[L2]], [[SLDBG2:![0-9]*]], [[ELDBG2:![0-9]*]]} + // CHECK-DAG: [[SLDBG2]] = !DILocation(line: 200, scope: !{{.*}}) + // CHECK-DAG: [[ELDBG2]] = !DILocation(line: 204, scope: !{{.*}}) - // CHECK-DAG: [[L3]] = distinct !{[[L3]], [[LDBG3:![0-9]*]]} - // CHECK-DAG: [[LDBG3]] = !DILocation(line: 300, scope: !{{.*}}) + // CHECK-DAG: [[L3]] = distinct !{[[L3]], [[SLDBG3:![0-9]*]], [[ELDBG3:![0-9]*]]} + // CHECK-DAG: [[SLDBG3]] = !DILocation(line: 300, scope: !{{.*}}) + // CHECK-DAG: [[ELDBG3]] = !DILocation(line: 304, scope: !{{.*}}) - // CHECK-DAG: [[L4]] = distinct !{[[L4]], [[LDBG4:![0-9]*]]} - // CHECK-DAG: [[LDBG4]] = !DILocation(line: 401, scope: !{{.*}}) + // CHECK-DAG: [[L4]] = distinct !{[[L4]], [[SLDBG4:![0-9]*]], [[ELDBG4:![0-9]*]]} + // CHECK-DAG: [[SLDBG4]] = !DILocation(line: 401, scope: !{{.*}}) + // CHECK-DAG: [[ELDBG4]] = !DILocation(line: 405, scope: !{{.*}}) } diff --git a/test/CodeGenCXX/debug-info-line.cpp b/test/CodeGenCXX/debug-info-line.cpp index 11653040109c..a1c4ef9eea25 100644 --- a/test/CodeGenCXX/debug-info-line.cpp +++ b/test/CodeGenCXX/debug-info-line.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -w -debug-info-kind=line-tables-only -std=c++11 -fexceptions -fcxx-exceptions -S -emit-llvm %s -o - -triple %itanium_abi_triple | FileCheck %s -// RUN: %clang_cc1 -w -debug-info-kind=line-tables-only -std=c++11 -fexceptions -fcxx-exceptions -S -emit-llvm %s -o - -triple i686-linux-gnu | FileCheck %s +// RUN: %clang_cc1 -w -debug-info-kind=line-tables-only -std=c++11 -fexceptions -fcxx-exceptions -S -mllvm -no-discriminators -emit-llvm %s -o - -triple %itanium_abi_triple | FileCheck %s +// RUN: %clang_cc1 -w -debug-info-kind=line-tables-only -std=c++11 -fexceptions -fcxx-exceptions -S -mllvm -no-discriminators -emit-llvm %s -o - -triple i686-linux-gnu | FileCheck %s int &src(); int *sink(); diff --git a/test/CodeGenCXX/debug-info-loops.cpp b/test/CodeGenCXX/debug-info-loops.cpp new file mode 100644 index 000000000000..69948ea0f880 --- /dev/null +++ b/test/CodeGenCXX/debug-info-loops.cpp @@ -0,0 +1,49 @@ +// RUN: %clang -g -gcolumn-info -std=c++11 -S -emit-llvm %s -o - | FileCheck %s +extern int v[2]; +int a = 0, b = 0; +int main() { +#line 100 + for (int x : v) { + if (x) + ++b; + else + ++a; + } + + // CHECK: br label {{.*}}, !dbg [[DBG1:![0-9]*]], !llvm.loop [[L1:![0-9]*]] + +#line 200 + while (a) + if (b) + ++b; + else + ++a; + // CHECK: br label {{.*}}, !dbg [[DBG2:![0-9]*]], !llvm.loop [[L2:![0-9]*]] + +#line 300 + for (unsigned i = 0; i < 100; i++) { + a++; + for (int y : v) + ++b; + } + + // CHECK: br label {{.*}}, !dbg [[DBG3:![0-9]*]], !llvm.loop [[L3:![0-9]*]] + // CHECK: br label {{.*}}, !dbg [[DBG3:![0-9]*]], !llvm.loop [[L4:![0-9]*]] + + + // CHECK-DAG: [[L1]] = distinct !{[[L1]], [[SLDBG1:![0-9]*]], [[ELDBG1:![0-9]*]]} + // CHECK-DAG: [[SLDBG1]] = !DILocation(line: 100, column: 3, scope: !{{.*}}) + // CHECK-DAG: [[ELDBG1]] = !DILocation(line: 105, column: 3, scope: !{{.*}}) + + // CHECK-DAG: [[L2]] = distinct !{[[L2]], [[SLDBG2:![0-9]*]], [[ELDBG2:![0-9]*]]} + // CHECK-DAG: [[SLDBG2]] = !DILocation(line: 200, column: 3, scope: !{{.*}}) + // CHECK-DAG: [[ELDBG2]] = !DILocation(line: 204, column: 9, scope: !{{.*}}) + + // CHECK-DAG: [[L3]] = distinct !{[[L3]], [[SLDBG3:![0-9]*]], [[ELDBG3:![0-9]*]]} + // CHECK-DAG: [[SLDBG3]] = !DILocation(line: 302, column: 5, scope: !{{.*}}) + // CHECK-DAG: [[ELDBG3]] = !DILocation(line: 303, column: 9, scope: !{{.*}}) + // + // CHECK-DAG: [[L4]] = distinct !{[[L4]], [[SLDBG4:![0-9]*]], [[ELDBG4:![0-9]*]]} + // CHECK-DAG: [[SLDBG4]] = !DILocation(line: 300, column: 3, scope: !{{.*}}) + // CHECK-DAG: [[ELDBG4]] = !DILocation(line: 304, column: 3, scope: !{{.*}}) +} diff --git a/test/CodeGenCXX/debug-info-method.cpp b/test/CodeGenCXX/debug-info-method.cpp index 73d8b928269a..e0f9a284f2cf 100644 --- a/test/CodeGenCXX/debug-info-method.cpp +++ b/test/CodeGenCXX/debug-info-method.cpp @@ -1,10 +1,10 @@ // RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -std=c++11 -debug-info-kind=limited %s -o - | FileCheck %s +// CHECK: !DIDerivedType(tag: DW_TAG_ptr_to_member_type // CHECK: ![[A:[0-9]+]] = distinct !DICompositeType(tag: DW_TAG_class_type, name: "A",{{.*}} identifier: "_ZTS1A") // CHECK: !DISubprogram(name: "foo", linkageName: "_ZN1A3fooEiS_3$_0" // CHECK-SAME: DIFlagProtected // CHECK: ![[THISTYPE:[0-9]+]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[A]] // CHECK-SAME: DIFlagArtificial -// CHECK: !DIDerivedType(tag: DW_TAG_ptr_to_member_type // CHECK: !DIDerivedType(tag: DW_TAG_ptr_to_member_type, baseType: ![[MEMFUNTYPE:[0-9]+]] // CHECK: ![[MEMFUNTYPE]] = !DISubroutineType({{(cc: DW_CC_BORLAND_thiscall, )?}}types: ![[MEMFUNARGS:[0-9]+]]) // CHECK: ![[MEMFUNARGS]] = {{.*}}, ![[THISTYPE]], diff --git a/test/CodeGenCXX/debug-info-ms-abi.cpp b/test/CodeGenCXX/debug-info-ms-abi.cpp index a146ce94176e..1bf8bab5f41c 100644 --- a/test/CodeGenCXX/debug-info-ms-abi.cpp +++ b/test/CodeGenCXX/debug-info-ms-abi.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -triple=i686-pc-windows-msvc -debug-info-kind=limited -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -triple=i686-pc-windows-msvc -debug-info-kind=limited -gcodeview -emit-llvm -o - | FileCheck %s // Tests that certain miscellaneous features work in the MS ABI. @@ -11,20 +11,30 @@ struct Foo { Foo f; Foo::Nested n; +// CHECK: ![[Nested:[0-9]+]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Nested", +// CHECK-SAME: identifier: ".?AUNested@Foo@@" + // CHECK: ![[Foo:[^ ]*]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Foo", +// CHECK-SAME: elements: ![[elements:[0-9]+]] // CHECK-SAME: identifier: ".?AUFoo@@" -// CHECK: !DISubprogram(name: "f", +// CHECK: ![[elements]] = !{![[vshape:[0-9]+]], ![[vptr:[0-9]+]], ![[Nested]], ![[f:[0-9]+]], ![[g:[0-9]+]], ![[h:[0-9]+]]} + +// CHECK: ![[vshape]] = !DIDerivedType(tag: DW_TAG_pointer_type, name: "__vtbl_ptr_type", baseType: null, size: 96) + +// CHECK: ![[vptr]] = !DIDerivedType(tag: DW_TAG_member, name: "_vptr$Foo", +// CHECK-SAME: baseType: ![[vptr_ty:[0-9]+]], + +// CHECK: ![[vptr_ty]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[vshape]], size: 32 + +// CHECK: ![[f]] = !DISubprogram(name: "f", // CHECK-SAME: containingType: ![[Foo]], virtuality: DW_VIRTUALITY_virtual, virtualIndex: 0, // CHECK-SAME: flags: DIFlagPrototyped | DIFlagIntroducedVirtual, -// CHECK: !DISubprogram(name: "g", +// CHECK: ![[g]] = !DISubprogram(name: "g", // CHECK-SAME: containingType: ![[Foo]], virtuality: DW_VIRTUALITY_virtual, virtualIndex: 1, // CHECK-SAME: flags: DIFlagPrototyped | DIFlagIntroducedVirtual, -// CHECK: !DISubprogram(name: "h", +// CHECK: ![[h]] = !DISubprogram(name: "h", // CHECK-SAME: containingType: ![[Foo]], virtuality: DW_VIRTUALITY_virtual, virtualIndex: 2, // CHECK-SAME: flags: DIFlagPrototyped | DIFlagIntroducedVirtual, - -// CHECK: distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Nested", -// CHECK-SAME: identifier: ".?AUNested@Foo@@" diff --git a/test/CodeGenCXX/debug-info-ms-anonymous-tag.cpp b/test/CodeGenCXX/debug-info-ms-anonymous-tag.cpp index cef1eb8c5a09..5e2cb2190f0d 100644 --- a/test/CodeGenCXX/debug-info-ms-anonymous-tag.cpp +++ b/test/CodeGenCXX/debug-info-ms-anonymous-tag.cpp @@ -4,7 +4,6 @@ typedef struct { } test1; test1 gv1; -// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "test1" struct { } test2; @@ -18,3 +17,5 @@ test3 gv3; void *use_test3 = &gv3; // CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "<unnamed-type-test3>" + +// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "test1" diff --git a/test/CodeGenCXX/debug-info-ms-bitfields.cpp b/test/CodeGenCXX/debug-info-ms-bitfields.cpp index 07d4c0c6c78a..e42330143bba 100644 --- a/test/CodeGenCXX/debug-info-ms-bitfields.cpp +++ b/test/CodeGenCXX/debug-info-ms-bitfields.cpp @@ -7,4 +7,4 @@ struct S { short x : 8; } s; -// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "x", {{.*}}, size: 8, align: 16, offset: 16, flags: DIFlagBitField, extraData: i64 8) +// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "x", {{.*}}, size: 8, offset: 16, flags: DIFlagBitField, extraData: i64 8) diff --git a/test/CodeGenCXX/debug-info-ms-ptr-to-member.cpp b/test/CodeGenCXX/debug-info-ms-ptr-to-member.cpp index 4b9f2a146896..1f4c90484b89 100644 --- a/test/CodeGenCXX/debug-info-ms-ptr-to-member.cpp +++ b/test/CodeGenCXX/debug-info-ms-ptr-to-member.cpp @@ -23,7 +23,6 @@ int Incomplete::**ppmd; void (Incomplete::**ppmf)(); // CHECK: distinct !DIGlobalVariable(name: "pmd_a", {{.*}} type: ![[pmd_a:[^, ]*]], {{.*}}) -// CHECK: ![[pmd_a]] = !DIDerivedType(tag: DW_TAG_ptr_to_member_type, baseType: !{{.*}}, size: 32, flags: DIFlagSingleInheritance, {{.*}}) // CHECK: distinct !DIGlobalVariable(name: "pmd_b", {{.*}} type: ![[pmd_b:[^, ]*]], {{.*}}) // CHECK: ![[pmd_b]] = !DIDerivedType(tag: DW_TAG_ptr_to_member_type, baseType: !{{.*}}, size: 32, flags: DIFlagMultipleInheritance, {{.*}}) // CHECK: distinct !DIGlobalVariable(name: "pmd_c", {{.*}} type: ![[pmd_c:[^, ]*]], {{.*}}) @@ -45,8 +44,10 @@ void (Incomplete::**ppmf)(); // CHECK-SAME: ){{$}} // CHECK: distinct !DIGlobalVariable(name: "ppmd", {{.*}} type: ![[ppmd:[^, ]*]], {{.*}}) -// CHECK: ![[ppmd]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[ppmd2:[^ ]*]], size: 64, align: 64) +// CHECK: ![[ppmd]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[ppmd2:[^ ]*]], size: 64) // CHECK: ![[ppmd2]] = !DIDerivedType(tag: DW_TAG_ptr_to_member_type, baseType: !{{[0-9]*}}, extraData: !{{[0-9]*}}){{$}} // CHECK: distinct !DIGlobalVariable(name: "ppmf", {{.*}} type: ![[ppmf:[^, ]*]], {{.*}}) -// CHECK: ![[ppmf]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[ppmf2:[^ ]*]], size: 64, align: 64) +// CHECK: ![[ppmf]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[ppmf2:[^ ]*]], size: 64) // CHECK: ![[ppmf2]] = !DIDerivedType(tag: DW_TAG_ptr_to_member_type, baseType: !{{[0-9]*}}, extraData: !{{[0-9]*}}){{$}} + +// CHECK: ![[pmd_a]] = !DIDerivedType(tag: DW_TAG_ptr_to_member_type, baseType: !{{.*}}, size: 32, flags: DIFlagSingleInheritance, {{.*}}) diff --git a/test/CodeGenCXX/debug-info-ms-vbase.cpp b/test/CodeGenCXX/debug-info-ms-vbase.cpp new file mode 100644 index 000000000000..3de3a751cba1 --- /dev/null +++ b/test/CodeGenCXX/debug-info-ms-vbase.cpp @@ -0,0 +1,68 @@ +// RUN: %clang_cc1 %s -triple=i686-pc-windows-msvc -debug-info-kind=limited -gcodeview -emit-llvm -o - | FileCheck %s + +// Tests virtual bases in the MS ABI. + +// CHECK: ![[NoPrimaryBase:[0-9]+]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "NoPrimaryBase", +// CHECK-SAME: elements: ![[elements:[0-9]+]] + +// CHECK: ![[elements]] = !{![[NoPrimaryBase_base:[0-9]+]]} + +// CHECK: ![[NoPrimaryBase_base]] = !DIDerivedType(tag: DW_TAG_inheritance, scope: ![[NoPrimaryBase]], +// CHECK-SAME: baseType: ![[HasVirtualMethod:[0-9]+]], offset: 4, flags: DIFlagVirtual) + +// CHECK: ![[HasVirtualMethod]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "HasVirtualMethod" + +// CHECK: ![[HasPrimaryBase:[0-9]+]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "HasPrimaryBase", +// CHECK-SAME: elements: ![[elements:[0-9]+]] + +// CHECK: ![[elements]] = !{![[SecondaryVTable_base:[0-9]+]], ![[HasVirtualMethod_base:[0-9]+]], ![[vshape:[0-9]+]]} + +// CHECK: ![[SecondaryVTable_base]] = !DIDerivedType(tag: DW_TAG_inheritance, scope: ![[HasPrimaryBase]], +// CHECK-SAME: baseType: ![[SecondaryVTable:[0-9]+]], offset: 4, flags: DIFlagVirtual) + +// CHECK: ![[SecondaryVTable]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "SecondaryVTable" + +// CHECK: ![[HasVirtualMethod_base]] = !DIDerivedType(tag: DW_TAG_inheritance, scope: ![[HasPrimaryBase]], baseType: ![[HasVirtualMethod]]) + +// CHECK: ![[HasIndirectVirtualBase:[0-9]+]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "HasIndirectVirtualBase" +// CHECK-SAME: elements: ![[elements:[0-9]+]] + +// CHECK: !DIDerivedType(tag: DW_TAG_inheritance, scope: ![[HasIndirectVirtualBase]], baseType: ![[HasPrimaryBase]] +// CHECK-NOT: DIFlagIndirectVirtualBase +// CHECK-SAME: ) + +// CHECK: !DIDerivedType(tag: DW_TAG_inheritance, scope: ![[HasIndirectVirtualBase]], baseType: ![[SecondaryVTable]] +// CHECK-SAME: flags: +// CHECK-SAME: DIFlagIndirectVirtualBase + +// CHECK: ![[DynamicNoVFPtr:[0-9]+]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "DynamicNoVFPtr", +// CHECK-SAME: elements: ![[elements:[0-9]+]] + +// CHECK: ![[elements]] = !{![[POD_base:[0-9]+]]} + +// CHECK: ![[POD_base]] = !DIDerivedType(tag: DW_TAG_inheritance, scope: ![[DynamicNoVFPtr]], +// CHECK-SAME: baseType: ![[POD:[0-9]+]], offset: 4, flags: DIFlagVirtual) + +// CHECK: ![[POD]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "POD" + +struct POD { int pod; }; + +struct DynamicNoVFPtr : virtual POD { }; + +DynamicNoVFPtr dynamic_no_vfptr; + +struct HasVirtualMethod { virtual void f(); }; + +struct NoPrimaryBase : virtual HasVirtualMethod { }; + +NoPrimaryBase no_primary_base; + +struct SecondaryVTable { virtual void g(); }; + +struct HasPrimaryBase : virtual SecondaryVTable, HasVirtualMethod { }; + +HasPrimaryBase has_primary_base; + +struct HasIndirectVirtualBase : public HasPrimaryBase {}; + +HasIndirectVirtualBase has_indirect_virtual_base; diff --git a/test/CodeGenCXX/debug-info-namespace.cpp b/test/CodeGenCXX/debug-info-namespace.cpp index 060a5cea636c..c75c40766a37 100644 --- a/test/CodeGenCXX/debug-info-namespace.cpp +++ b/test/CodeGenCXX/debug-info-namespace.cpp @@ -1,6 +1,6 @@ -// RUN: %clang_cc1 -debug-info-kind=limited -S -emit-llvm %s -o - | FileCheck %s -// RUN: %clang_cc1 -debug-info-kind=line-tables-only -S -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-GMLT %s -// RUN: %clang_cc1 -debug-info-kind=standalone -S -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-NOLIMIT %s +// RUN: %clang_cc1 -std=c++11 -debug-info-kind=limited -S -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -std=c++11 -debug-info-kind=line-tables-only -S -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-GMLT %s +// RUN: %clang_cc1 -std=c++11 -debug-info-kind=standalone -S -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-NOLIMIT %s namespace A { #line 1 "foo.cpp" @@ -49,14 +49,15 @@ using B::i; namespace B { int var_fwd = i; } +inline namespace I { +int var_i; +} } void B::func_fwd() {} // This should work even if 'i' and 'func' were declarations & not definitions, // but it doesn't yet. -// CHECK: [[CU:![0-9]+]] = distinct !DICompileUnit( -// CHECK-SAME: imports: [[MODULES:![0-9]*]] // CHECK: [[I:![0-9]+]] = distinct !DIGlobalVariable(name: "i",{{.*}} scope: [[NS:![0-9]+]], // CHECK: [[NS]] = !DINamespace(name: "B", scope: [[CTXT:![0-9]+]], file: [[FOOCPP:![0-9]+]], line: 1) // CHECK: [[FOOCPP]] = !DIFile(filename: "foo.cpp" @@ -65,6 +66,10 @@ void B::func_fwd() {} // CHECK: [[VAR_FWD:![0-9]+]] = distinct !DIGlobalVariable(name: "var_fwd",{{.*}} scope: [[NS]], // CHECK-SAME: line: 44 // CHECK-SAME: isDefinition: true +// CHECK: distinct !DIGlobalVariable(name: "var_i",{{.*}} scope: [[INLINE:![0-9]+]], +// CHECK: [[INLINE]] = !DINamespace(name: "I", scope: [[CTXT]], file: [[FOOCPP]], line: 46, exportSymbols: true) +// CHECK: [[CU:![0-9]+]] = distinct !DICompileUnit( +// CHECK-SAME: imports: [[MODULES:![0-9]*]] // CHECK: [[MODULES]] = !{[[M1:![0-9]+]], [[M2:![0-9]+]], [[M3:![0-9]+]], [[M4:![0-9]+]], [[M5:![0-9]+]], [[M6:![0-9]+]], [[M7:![0-9]+]], [[M8:![0-9]+]], [[M9:![0-9]+]], [[M10:![0-9]+]], [[M11:![0-9]+]], [[M12:![0-9]+]], [[M13:![0-9]+]], [[M14:![0-9]+]], [[M15:![0-9]+]], [[M16:![0-9]+]], [[M17:![0-9]+]]} // CHECK: [[M1]] = !DIImportedEntity(tag: DW_TAG_imported_module, scope: [[CTXT]], entity: [[NS]], line: 15) @@ -101,7 +106,7 @@ void B::func_fwd() {} // CHECK-SAME: scope: [[NS]], file: [[FOOCPP]], line: 9 // CHECK: [[M15]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[FUNC]], entity: [[VAR_FWD:![0-9]+]] // CHECK: [[M16]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[FUNC]], entity: [[FUNC_FWD:![0-9]+]] -// CHECK: [[FUNC_FWD]] = distinct !DISubprogram(name: "func_fwd",{{.*}} line: 47,{{.*}} isDefinition: true +// CHECK: [[FUNC_FWD]] = distinct !DISubprogram(name: "func_fwd",{{.*}} line: 50,{{.*}} isDefinition: true // CHECK: [[M17]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[CTXT]], entity: [[I]] // CHECK-GMLT: [[CU:![0-9]+]] = distinct !DICompileUnit( diff --git a/test/CodeGenCXX/debug-info-rvalue-ref.cpp b/test/CodeGenCXX/debug-info-rvalue-ref.cpp index edb93ae46cda..de0f65ad9a02 100644 --- a/test/CodeGenCXX/debug-info-rvalue-ref.cpp +++ b/test/CodeGenCXX/debug-info-rvalue-ref.cpp @@ -8,5 +8,5 @@ void foo (int &&i) printf("%d\n", i); } -// CHECK: !DIDerivedType(tag: DW_TAG_rvalue_reference_type, baseType: ![[INT:[0-9]+]], size: 64, align: 64) +// CHECK: !DIDerivedType(tag: DW_TAG_rvalue_reference_type, baseType: ![[INT:[0-9]+]], size: 64) // CHECK: ![[INT]] = !DIBasicType(name: "int" diff --git a/test/CodeGenCXX/debug-info-static-member.cpp b/test/CodeGenCXX/debug-info-static-member.cpp index ed8ae015cfc3..c777ccb2aba2 100644 --- a/test/CodeGenCXX/debug-info-static-member.cpp +++ b/test/CodeGenCXX/debug-info-static-member.cpp @@ -3,6 +3,10 @@ // RUN: %clangxx -target x86_64-unknown-unknown -g -std=c++11 %s -emit-llvm -S -o - | FileCheck %s // PR14471 +// CHECK: @_ZN1C1aE = global i32 4, align 4, !dbg [[A:![0-9]+]] +// CHECK: @_ZN1C1bE = global i32 2, align 4, !dbg [[B:![0-9]+]] +// CHECK: @_ZN1C1cE = global i32 1, align 4, !dbg [[C:![0-9]+]] + enum X { Y }; @@ -28,6 +32,10 @@ public: // why the definition of "a" comes before the declarations while // "b" and "c" come after. +// CHECK: [[A]] = !DIGlobalVariableExpression(var: [[AV:.*]]) +// CHECK: [[AV]] = distinct !DIGlobalVariable(name: "a", +// CHECK-SAME: declaration: ![[DECL_A:[0-9]+]]) +// // CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "X"{{.*}}, identifier: "_ZTS1X") // CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "anon_static_decl_struct" // CHECK: !DIDerivedType(tag: DW_TAG_member, name: "anon_static_decl_var" @@ -36,16 +44,24 @@ public: // CHECK-SAME: ){{$}} // CHECK: !DIDerivedType(tag: DW_TAG_member, name: "static_decl_templ_var" -// CHECK: !DIGlobalVariable(name: "a", {{.*}}variable: i32* @_ZN1C1aE, declaration: ![[DECL_A:[0-9]+]]) int C::a = 4; -// CHECK: ![[DECL_A]] = !DIDerivedType(tag: DW_TAG_member, name: "a" +// CHECK: [[B]] = !DIGlobalVariableExpression(var: [[BV:.*]]) +// CHECK: [[BV]] = distinct !DIGlobalVariable(name: "b", +// CHECK-SAME: declaration: ![[DECL_B:[0-9]+]]) +// CHECK: ![[DECL_B]] = !DIDerivedType(tag: DW_TAG_member, name: "b" // CHECK-NOT: size: // CHECK-NOT: align: // CHECK-NOT: offset: -// CHECK-SAME: flags: DIFlagStaticMember) +// CHECK-SAME: flags: DIFlagProtected | DIFlagStaticMember) // // CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "C"{{.*}}, identifier: "_ZTS1C") // +// CHECK: ![[DECL_A]] = !DIDerivedType(tag: DW_TAG_member, name: "a" +// CHECK-NOT: size: +// CHECK-NOT: align: +// CHECK-NOT: offset: +// CHECK-SAME: flags: DIFlagStaticMember) +// // CHECK: !DIDerivedType(tag: DW_TAG_member, name: "const_a" // CHECK-NOT: size: // CHECK-NOT: align: @@ -53,12 +69,6 @@ int C::a = 4; // CHECK-SAME: flags: DIFlagStaticMember, // CHECK-SAME: extraData: i1 true) -// CHECK: ![[DECL_B:[0-9]+]] = !DIDerivedType(tag: DW_TAG_member, name: "b" -// CHECK-NOT: size: -// CHECK-NOT: align: -// CHECK-NOT: offset: -// CHECK-SAME: flags: DIFlagProtected | DIFlagStaticMember) -// // CHECK: !DIDerivedType(tag: DW_TAG_member, name: "const_b" // CHECK-NOT: size: // CHECK-NOT: align: @@ -82,9 +92,9 @@ int C::a = 4; // CHECK: !DIDerivedType(tag: DW_TAG_member, name: "x_a" // CHECK-SAME: flags: DIFlagPublic | DIFlagStaticMember) -// CHECK: !DIGlobalVariable(name: "b", {{.*}}variable: i32* @_ZN1C1bE, declaration: ![[DECL_B]]) int C::b = 2; -// CHECK: !DIGlobalVariable(name: "c", {{.*}}variable: i32* @_ZN1C1cE, declaration: ![[DECL_C]]) +// CHECK: [[C]] = !DIGlobalVariableExpression(var: [[CV:.*]]) +// CHECK: [[CV]] = distinct !DIGlobalVariable(name: "c", {{.*}} declaration: ![[DECL_C]]) int C::c = 1; int main() diff --git a/test/CodeGenCXX/debug-info-template-explicit-specialization.cpp b/test/CodeGenCXX/debug-info-template-explicit-specialization.cpp index 08146c25263b..c8d8a1de855d 100644 --- a/test/CodeGenCXX/debug-info-template-explicit-specialization.cpp +++ b/test/CodeGenCXX/debug-info-template-explicit-specialization.cpp @@ -22,9 +22,6 @@ struct b { }; extern template class b<int>; b<int> bi; -// CHECK: DICompositeType(tag: DW_TAG_structure_type, name: "b<int>" -// CHECK-NOT: DIFlagFwdDecl -// CHECK-SAME: ){{$}} template <typename T> struct c { @@ -116,3 +113,7 @@ template <> struct k<int>; template struct k<int>; // CHECK-NOT: !DICompositeType(tag: DW_TAG_structure_type, name: "k<int>" + +// CHECK: DICompositeType(tag: DW_TAG_structure_type, name: "b<int>" +// CHECK-NOT: DIFlagFwdDecl +// CHECK-SAME: ){{$}} diff --git a/test/CodeGenCXX/debug-info-template-member.cpp b/test/CodeGenCXX/debug-info-template-member.cpp index 88f024b59abf..2b840745ffeb 100644 --- a/test/CodeGenCXX/debug-info-template-member.cpp +++ b/test/CodeGenCXX/debug-info-template-member.cpp @@ -1,5 +1,7 @@ // RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited -triple x86_64-apple-darwin %s -o - | FileCheck %s +// CHECK: @x = global %"struct.outer<foo>::inner" zeroinitializer, align 4, !dbg [[X:![0-9]+]] + struct MyClass { template <int i> int add(int j) { return i + j; @@ -17,9 +19,9 @@ inline int add3(int x) { } // The compile unit pulls in the global variables first. -// CHECK: !DIGlobalVariable(name: "x", -// CHECK-SAME: type: ![[OUTER_FOO_INNER_ID:[0-9]+]] -// CHECK-SAME: variable: %"struct.outer<foo>::inner"* @x +// CHECK: [[X]] = !DIGlobalVariableExpression(var: [[XV:.*]]) +// CHECK: [[XV]] = distinct !DIGlobalVariable(name: "x", +// CHECK-SAME: type: ![[OUTER_FOO_INNER_ID:[0-9]+]] // CHECK: ![[OUTER_FOO_INNER_ID:[0-9]*]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "inner"{{.*}}, identifier: // CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "foo" @@ -38,7 +40,7 @@ inline int add3(int x) { // CHECK: [[C_MEM]] = !{[[C_VPTR:![0-9]*]], [[C_FUNC:![0-9]*]]} // CHECK: [[C_VPTR]] = !DIDerivedType(tag: DW_TAG_member, name: "_vptr$MyClass" -// CHECK: [[C_FUNC]] = !DISubprogram(name: "func",{{.*}} line: 7, +// CHECK: [[C_FUNC]] = !DISubprogram(name: "func",{{.*}} line: 9, // CHECK: !DISubprogram(name: "add<2>" // CHECK-SAME: scope: [[C]] diff --git a/test/CodeGenCXX/debug-info-template-quals.cpp b/test/CodeGenCXX/debug-info-template-quals.cpp index 7a0d0d4a2755..cfee78d97493 100644 --- a/test/CodeGenCXX/debug-info-template-quals.cpp +++ b/test/CodeGenCXX/debug-info-template-quals.cpp @@ -17,10 +17,10 @@ void foo (const char *c) { // CHECK: [[P:![0-9]*]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: [[CON:![0-9]*]] // CHECK: [[CON]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: [[CH:![0-9]*]] -// CHECK: [[CH]] = !DIBasicType(name: "char", size: 8, align: 8, encoding: DW_ATE_signed_char) +// CHECK: [[CH]] = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char) // CHECK: [[BS:.*]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "basic_string<char>" // CHECK-SAME: line: 4 -// CHECK-SAME: size: 8, align: 8 +// CHECK-SAME: size: 8 // CHECK: [[TYPE:![0-9]*]] = !DISubroutineType(types: [[ARGS:.*]]) // CHECK: [[ARGS]] = !{!{{.*}}, !{{.*}}, [[P]], [[R:.*]]} diff --git a/test/CodeGenCXX/debug-info-template.cpp b/test/CodeGenCXX/debug-info-template.cpp index d35bb70fa713..54fac0b36eec 100644 --- a/test/CodeGenCXX/debug-info-template.cpp +++ b/test/CodeGenCXX/debug-info-template.cpp @@ -1,5 +1,9 @@ // RUN: %clang -S -emit-llvm -target x86_64-unknown_unknown -g %s -o - -std=c++11 | FileCheck %s +// CHECK: @tci = global %"struct.TC<unsigned int, 2, &glb, &foo::e, &foo::f, &foo::g, 1, 2, 3>::nested" zeroinitializer, align 1, !dbg [[TCI:![0-9]+]] +// CHECK: @tcn = global %struct.TC zeroinitializer, align 1, !dbg [[TCN:![0-9]+]] +// CHECK: @nn = global %struct.NN zeroinitializer, align 1, !dbg [[NN:![0-9]+]] + // CHECK: !DICompileUnit( // CHECK: [[EMPTY:![0-9]*]] = !{} @@ -18,13 +22,12 @@ struct TC { }; }; -// CHECK: [[INT:![0-9]+]] = !DIBasicType(name: "int" int glb; void func(); -// CHECK: !DIGlobalVariable(name: "tci", -// CHECK-SAME: type: ![[TCNESTED:[0-9]+]] -// CHECK-SAME: variable: %"struct.TC<unsigned int, 2, &glb, &foo::e, &foo::f, &foo::g, 1, 2, 3>::nested"* @tci +// CHECK: [[TCI]] = !DIGlobalVariableExpression(var: [[TCIV:.*]]) +// CHECK: [[TCIV]] = distinct !DIGlobalVariable(name: "tci", +// CHECK-SAME: type: ![[TCNESTED:[0-9]+]] // CHECK: ![[TCNESTED]] ={{.*}}!DICompositeType(tag: DW_TAG_structure_type, name: "nested", // CHECK-SAME: scope: ![[TC:[0-9]+]], @@ -39,7 +42,8 @@ TC 2, // CHECK: [[TCARG3]] = !DITemplateValueParameter(name: "x", type: [[CINTPTR:![0-9]*]], value: i32* @glb) // CHECK: [[CINTPTR]] = !DIDerivedType(tag: DW_TAG_pointer_type, {{.*}}baseType: [[CINT:![0-9]+]] -// CHECK: [[CINT]] = !DIDerivedType(tag: DW_TAG_const_type, {{.*}}baseType: [[INT]] +// CHECK: [[CINT]] = !DIDerivedType(tag: DW_TAG_const_type, {{.*}}baseType: [[INT:![0-9]+]] +// CHECK: [[INT]] = !DIBasicType(name: "int" &glb, // CHECK: [[TCARG4]] = !DITemplateValueParameter(name: "a", type: [[MEMINTPTR:![0-9]*]], value: i64 8) // CHECK: [[MEMINTPTR]] = !DIDerivedType(tag: DW_TAG_ptr_to_member_type, {{.*}}baseType: [[INT]], {{.*}}extraData: ![[FOO:[0-9]+]]) @@ -59,7 +63,7 @@ TC // CHECK: [[FARG1]] = !DIDerivedType(tag: DW_TAG_pointer_type, // CHECK-SAME: baseType: ![[FOO]] // CHECK-NOT: line: -// CHECK-SAME: size: 64, align: 64 +// CHECK-SAME: size: 64 // CHECK-NOT: offset: 0 // CHECK-SAME: DIFlagArtificial // CHECK: [[FUNTYPE:![0-9]*]] = !DISubroutineType(types: [[FUNARGS:![0-9]*]]) @@ -80,9 +84,9 @@ TC // CHECK: [[TCARG7_3]] = !DITemplateValueParameter(type: [[INT]], value: i32 3) 3>::nested tci; -// CHECK: !DIGlobalVariable(name: "tcn" -// CHECK-SAME: type: ![[TCNT:[0-9]+]] -// CHECK-SAME: variable: %struct.TC* @tcn +// CHECK: [[TCN]] = !DIGlobalVariableExpression(var: [[TCNV:.*]]) +// CHECK: [[TCNV]] = distinct !DIGlobalVariable(name: "tcn" +// CHECK-SAME: type: ![[TCNT:[0-9]+]] TC // CHECK: ![[TCNT]] ={{.*}}!DICompositeType(tag: DW_TAG_structure_type, name: "TC<int, -3, nullptr, nullptr, nullptr, nullptr>" // CHECK-SAME: templateParams: [[TCNARGS:![0-9]*]] @@ -121,9 +125,9 @@ template <template <typename> class tmpl, int &lvr, int &&rvr> struct NN { }; -// CHECK: !DIGlobalVariable(name: "nn" -// CHECK-SAME: type: ![[NNT:[0-9]+]] -// CHECK-SAME: variable: %struct.NN* @nn +// CHECK: [[NN]] = !DIGlobalVariableExpression(var: [[NNV:.*]]) +// CHECK: [[NNV]] = distinct !DIGlobalVariable(name: "nn" +// CHECK-SAME: type: ![[NNT:[0-9]+]] // FIXME: these parameters should probably be rendered as 'glb' rather than // '&glb', since they're references, not pointers. @@ -150,7 +154,7 @@ PaddingAtEnd PaddedObj = {}; // CHECK-SAME: templateParams: [[PTOARGS:![0-9]*]] // CHECK: [[PTOARGS]] = !{[[PTOARG1:![0-9]*]]} // CHECK: [[PTOARG1]] = !DITemplateValueParameter(type: [[CONST_PADDINGATEND_PTR:![0-9]*]], value: %struct.PaddingAtEnd* @PaddedObj) -// CHECK: [[CONST_PADDINGATEND_PTR]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[PADDINGATEND]], size: 64, align: 64) +// CHECK: [[CONST_PADDINGATEND_PTR]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[PADDINGATEND]], size: 64) template <PaddingAtEnd *> struct PaddingAtEndTemplate { }; diff --git a/test/CodeGenCXX/debug-info-thunk-msabi.cpp b/test/CodeGenCXX/debug-info-thunk-msabi.cpp new file mode 100644 index 000000000000..5c705ac0ac13 --- /dev/null +++ b/test/CodeGenCXX/debug-info-thunk-msabi.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 %s -triple i386-pc-windows-msvc19.0.0 -emit-llvm \ +// RUN: -debug-info-kind=line-tables-only -fms-extensions -o - | FileCheck %s +class __declspec(dllexport) A { + A(int * = new int) {} +}; +// CHECK: define {{.*}}void @"\01??_FA@@AAEXXZ" +// CHECK-SAME: !dbg ![[SP:[0-9]+]] +// CHECK-NOT: {{ret }} +// CHECK: call x86_thiscallcc %class.A* @"\01??0A@@AAE@PAH@Z" +// CHECK-SAME: !dbg ![[DBG:[0-9]+]] +// CHECK: ret void, !dbg +// +// CHECK: ![[SP]] = distinct !DISubprogram( +// CHECK-SAME: line: 4 +// CHECK-SAME: isDefinition: true +// CHECK-SAME: DIFlagArtificial +// CHECK-SAME: ){{$}} +// +// CHECK: ![[DBG]] = !DILocation(line: 0 diff --git a/test/CodeGenCXX/debug-info-thunk.cpp b/test/CodeGenCXX/debug-info-thunk.cpp index cd00ec937318..f7d16f493256 100644 --- a/test/CodeGenCXX/debug-info-thunk.cpp +++ b/test/CodeGenCXX/debug-info-thunk.cpp @@ -13,8 +13,17 @@ struct C : A, B { }; void C::f() { } - -// CHECK: !DISubprogram(linkageName: "_ZThn{{[48]}}_N1C1fEv" +// CHECK: define {{.*}}void @_ZThn{{[48]}}_N1C1fEv +// CHECK-SAME: !dbg ![[SP:[0-9]+]] +// CHECK-NOT: {{ret }} +// CHECK: = load{{.*}} !dbg ![[DBG:[0-9]+]] +// CHECK-NOT: {{ret }} +// CHECK: ret void, !dbg ![[DBG]] +// +// CHECK: ![[SP]] = distinct !DISubprogram(linkageName: "_ZThn{{[48]}}_N1C1fEv" // CHECK-SAME: line: 15 // CHECK-SAME: isDefinition: true +// CHECK-SAME: DIFlagArtificial // CHECK-SAME: ){{$}} +// +// CHECK: ![[DBG]] = !DILocation(line: 0 diff --git a/test/CodeGenCXX/debug-info-union.cpp b/test/CodeGenCXX/debug-info-union.cpp index 19e67418f9dc..cffe6e961cd4 100644 --- a/test/CodeGenCXX/debug-info-union.cpp +++ b/test/CodeGenCXX/debug-info-union.cpp @@ -12,7 +12,7 @@ E e; // CHECK: !DICompositeType(tag: DW_TAG_union_type, name: "E" // CHECK-SAME: line: 3 -// CHECK-SAME: size: 32, align: 32 +// CHECK-SAME: size: 32 // CHECK-NOT: offset: // CHECK-SAME: {{$}} // CHECK: !DISubprogram(name: "bb"{{.*}}, line: 6 diff --git a/test/CodeGenCXX/debug-info-uuid.cpp b/test/CodeGenCXX/debug-info-uuid.cpp index a304f37078b6..70b205ad0993 100644 --- a/test/CodeGenCXX/debug-info-uuid.cpp +++ b/test/CodeGenCXX/debug-info-uuid.cpp @@ -1,6 +1,18 @@ // RUN: %clang_cc1 -emit-llvm -fms-extensions -triple=x86_64-pc-win32 -debug-info-kind=limited %s -o - -std=c++11 | FileCheck %s // RUN: %clang_cc1 -emit-llvm -fms-extensions -triple=x86_64-unknown-unknown -debug-info-kind=limited %s -o - -std=c++11 2>&1 | FileCheck %s --check-prefix=CHECK-ITANIUM +// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "tmpl_guid2<__uuidof(uuid)>" +// CHECK-SAME: templateParams: [[TGI2ARGS:![0-9]*]] +// CHECK: [[TGI2ARGS]] = !{[[TGI2ARG1:![0-9]*]]} +// CHECK: [[TGI2ARG1]] = !DITemplateValueParameter( +// CHECK-SAME: type: [[CONST_GUID_REF:![0-9]*]] +// CHECK-SAME: value: { i32, i16, i16, [8 x i8] }* @_GUID_12345678_1234_1234_1234_1234567890ab +// CHECK: [[CONST_GUID_REF]] = !DIDerivedType(tag: DW_TAG_reference_type, +// CHECK-SAME: baseType: [[CONST_GUID:![0-9]*]] +// CHECK: [[CONST_GUID]] = !DIDerivedType(tag: DW_TAG_const_type +// CHECK-SAME: baseType: [[GUID:![0-9]*]] +// CHECK: [[GUID]] = !DICompositeType(tag: DW_TAG_structure_type, name: "_GUID" + // CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "tmpl_guid<&__uuidof(uuid)>" // CHECK-SAME: templateParams: [[TGIARGS:![0-9]*]] // CHECK: [[TGIARGS]] = !{[[TGIARG1:![0-9]*]]} @@ -10,24 +22,11 @@ // CHECK: [[CONST_GUID_PTR]] = !DIDerivedType(tag: DW_TAG_pointer_type // CHECK-SAME: baseType: [[CONST_GUID:![0-9]*]] // CHECK-SAME: size: 64 -// CHECK-SAME: align: 64 -// CHECK: [[CONST_GUID]] = !DIDerivedType(tag: DW_TAG_const_type -// CHECK-SAME: baseType: [[GUID:![0-9]*]] -// CHECK: [[GUID]] = !DICompositeType(tag: DW_TAG_structure_type, name: "_GUID" - -// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "tmpl_guid2<__uuidof(uuid)>" -// CHECK-SAME: templateParams: [[TGI2ARGS:![0-9]*]] -// CHECK: [[TGI2ARGS]] = !{[[TGI2ARG1:![0-9]*]]} -// CHECK: [[TGI2ARG1]] = !DITemplateValueParameter( -// CHECK-SAME: type: [[CONST_GUID_REF:![0-9]*]] -// CHECK-SAME: value: { i32, i16, i16, [8 x i8] }* @_GUID_12345678_1234_1234_1234_1234567890ab -// CHECK: [[CONST_GUID_REF]] = !DIDerivedType(tag: DW_TAG_reference_type, -// CHECK-SAME: baseType: [[CONST_GUID:![0-9]*]] -// CHECK-ITANIUM: !DICompositeType(tag: DW_TAG_structure_type, name: "tmpl_guid<&__uuidof(uuid)>" -// CHECK-ITANIUM-SAME: identifier: "_ZTS9tmpl_guidIXadu8__uuidoft4uuidEE" // CHECK-ITANIUM: !DICompositeType(tag: DW_TAG_structure_type, name: "tmpl_guid2<__uuidof(uuid)>" // CHECK-ITANIUM-SAME: identifier: "_ZTS10tmpl_guid2IXu8__uuidoft4uuidEE" +// CHECK-ITANIUM: !DICompositeType(tag: DW_TAG_structure_type, name: "tmpl_guid<&__uuidof(uuid)>" +// CHECK-ITANIUM-SAME: identifier: "_ZTS9tmpl_guidIXadu8__uuidoft4uuidEE" struct _GUID; template <const _GUID *> diff --git a/test/CodeGenCXX/debug-info-vla.cpp b/test/CodeGenCXX/debug-info-vla.cpp new file mode 100644 index 000000000000..88f3a3f55dab --- /dev/null +++ b/test/CodeGenCXX/debug-info-vla.cpp @@ -0,0 +1,20 @@ +// RUN: %clang -target x86_64-unknown-unknown -fverbose-asm -g -O0 -S -emit-llvm %s -o - -std=c++11 | FileCheck %s + + +void f(int m) { + int x[3][m]; +} + +int (*fp)(int[][*]) = nullptr; + +// CHECK: !DICompositeType(tag: DW_TAG_array_type, +// CHECK-NOT: size: +// CHECK-SAME: elements: [[ELEM_TYPE:![0-9]+]] +// CHECK: [[ELEM_TYPE]] = !{[[NOCOUNT:.*]]} +// CHECK: [[NOCOUNT]] = !DISubrange(count: -1) +// +// CHECK: !DICompositeType(tag: DW_TAG_array_type, +// CHECK-NOT: size: +// CHECK-SAME: elements: [[ELEM_TYPE:![0-9]+]] +// CHECK: [[ELEM_TYPE]] = !{[[THREE:.*]], [[NOCOUNT]]} +// CHECK: [[THREE]] = !DISubrange(count: 3) diff --git a/test/CodeGenCXX/debug-info-windows-dtor.cpp b/test/CodeGenCXX/debug-info-windows-dtor.cpp index e5a51abae68b..8eb744a61bc7 100644 --- a/test/CodeGenCXX/debug-info-windows-dtor.cpp +++ b/test/CodeGenCXX/debug-info-windows-dtor.cpp @@ -19,4 +19,4 @@ template struct AB<int>; // CHECK: define // CHECK: [[THUNK_VEC_DEL_DTOR]] = distinct !DISubprogram -// CHECK: [[THUNK_LOC]] = !DILocation(line: 15, scope: [[THUNK_VEC_DEL_DTOR]]) +// CHECK: [[THUNK_LOC]] = !DILocation(line: 0, scope: [[THUNK_VEC_DEL_DTOR]]) diff --git a/test/CodeGenCXX/debug-info-zero-length-arrays.cpp b/test/CodeGenCXX/debug-info-zero-length-arrays.cpp index dc7558aa3935..9f8eab624b40 100644 --- a/test/CodeGenCXX/debug-info-zero-length-arrays.cpp +++ b/test/CodeGenCXX/debug-info-zero-length-arrays.cpp @@ -10,7 +10,6 @@ A a; // CHECK-SAME: baseType: [[ARRAY_TYPE:![0-9]+]] // CHECK: [[ARRAY_TYPE]] = !DICompositeType(tag: DW_TAG_array_type, // CHECK-NOT: size: -// CHECK-SAME: align: 32 // CHECK-SAME: elements: [[ELEM_TYPE:![0-9]+]] // CHECK: [[ELEM_TYPE]] = !{[[SUBRANGE:.*]]} // CHECK: [[SUBRANGE]] = !DISubrange(count: -1) diff --git a/test/CodeGenCXX/debug-info.cpp b/test/CodeGenCXX/debug-info.cpp index 2e8d5fd5f137..9575a5129e3d 100644 --- a/test/CodeGenCXX/debug-info.cpp +++ b/test/CodeGenCXX/debug-info.cpp @@ -1,14 +1,16 @@ // RUN: %clang_cc1 -triple x86_64-none-linux-gnu -emit-llvm -debug-info-kind=limited %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=BOTH // RUN: %clang_cc1 -triple i686-pc-windows-msvc -emit-llvm -debug-info-kind=limited %s -o - | FileCheck %s --check-prefix=MSVC --check-prefix=BOTH +// CHECK: @_ZN6pr96081xE = global [3 x i8]* null, align 8, !dbg [[X:![0-9]+]] + // CHECK: define void @_ZN7pr147634funcENS_3fooE // CHECK: call void @llvm.dbg.declare({{.*}}, metadata ![[F:[0-9]+]], metadata ![[EXPR:[0-9]+]]) // !llvm.dbg.cu pulls in globals and their types first. // CHECK-NOT: !DIGlobalVariable(name: "c" -// CHECK: !DIGlobalVariable(name: "x", linkageName: "_ZN6pr96081xE" -// CHECK-SAME: type: [[INCARRAYPTR:![0-9]*]] -// CHECK-SAME: variable: [3 x i8]** @_ZN6pr96081xE +// CHECK: [[X]] = !DIGlobalVariableExpression(var: [[XV:!.*]]) +// CHECK: [[XV]] = distinct !DIGlobalVariable(name: "x", linkageName: "_ZN6pr96081xE" +// CHECK-SAME: type: [[INCARRAYPTR:![0-9]*]] // CHECK: [[INCARRAYPTR]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: [[INCARRAY:![0-9]+]] // CHECK: [[INCARRAY]] = !DICompositeType(tag: DW_TAG_array_type // CHECK-NOT: line: @@ -67,8 +69,8 @@ namespace VirtualBase { struct A { int a; }; struct B : virtual A { int b; }; // BOTH: ![[VBASE_B:[0-9]+]] ={{.*}}!DICompositeType(tag: DW_TAG_structure_type, name: "B",{{.*}} line: [[@LINE-1]], -// MSVC-SAME: size: 96, align: 32 -// CHECK-SAME: size: 128, align: 64, +// MSVC-SAME: size: 96 +// CHECK-SAME: size: 128, // BOTH-NOT: offset: // BOTH-NOT: DIFlagFwdDecl // BOTH-SAME: elements: [[VBASE_B_DEF:![0-9]+]] diff --git a/test/CodeGenCXX/debug-lambda-expressions.cpp b/test/CodeGenCXX/debug-lambda-expressions.cpp index b01f770bdd97..1717fc468656 100644 --- a/test/CodeGenCXX/debug-lambda-expressions.cpp +++ b/test/CodeGenCXX/debug-lambda-expressions.cpp @@ -15,6 +15,12 @@ struct D { D(); D(const D&); int x; }; int d(int x) { D y[10]; return [x,y] { return y[x].x; }(); } // Randomness for file. -- 6 + +// VAR: +// CHECK: !DIGlobalVariable(name: "var" +// CHECK-SAME: line: [[VAR_LINE:[0-9]+]] +// CHECK-SAME: type: ![[VAR_T:[0-9]+]] + // CHECK: [[FILE:.*]] = !DIFile(filename: "{{.*}}debug-lambda-expressions.cpp", // CVAR: @@ -26,10 +32,6 @@ int d(int x) { D y[10]; return [x,y] { return y[x].x; }(); } // CHECK-SAME: elements: ![[CVAR_ARGS:[0-9]+]] // CHECK: ![[CVAR_ARGS]] = !{!{{[0-9]+}}} -// VAR: -// CHECK: !DIGlobalVariable(name: "var" -// CHECK-SAME: line: [[VAR_LINE:[0-9]+]] -// CHECK-SAME: type: ![[VAR_T:[0-9]+]] // CHECK: ![[VAR_T]] = distinct !DICompositeType(tag: DW_TAG_class_type // CHECK-SAME: line: [[VAR_LINE]], // CHECK-SAME: elements: ![[VAR_ARGS:[0-9]+]] diff --git a/test/CodeGenCXX/debug-lambda-this.cpp b/test/CodeGenCXX/debug-lambda-this.cpp index 4af3d81983b2..eecbac6520ac 100644 --- a/test/CodeGenCXX/debug-lambda-this.cpp +++ b/test/CodeGenCXX/debug-lambda-this.cpp @@ -13,10 +13,10 @@ int D::d(int x) { } // CHECK: ![[D:[0-9]+]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "D", -// CHECK: ![[POINTER:.*]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[D]], size: 64, align: 64) +// CHECK: ![[POINTER:.*]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[D]], size: 64) // CHECK: !DIDerivedType(tag: DW_TAG_member, name: "this", // CHECK-SAME: line: 11 // CHECK-SAME: baseType: ![[POINTER]] -// CHECK-SAME: size: 64, align: 64 +// CHECK-SAME: size: 64 // CHECK-NOT: offset: 0 // CHECK-SAME: ){{$}} diff --git a/test/CodeGenCXX/default-arg-temps.cpp b/test/CodeGenCXX/default-arg-temps.cpp index 6a7f43a51287..f7b46818e39d 100644 --- a/test/CodeGenCXX/default-arg-temps.cpp +++ b/test/CodeGenCXX/default-arg-temps.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin9 | FileCheck %s +// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple=x86_64-apple-darwin9 | FileCheck %s struct T { T(); @@ -71,3 +71,10 @@ namespace test1 { D d; } + +namespace test2 { + // CHECK: define linkonce_odr void @_ZN5test21AIiED2Ev( + template <typename T> struct A { A() {} ~A() {} }; + template <typename> void f(const A<int> & = {}) {} + void g() { f<int>(); } +} diff --git a/test/CodeGenCXX/derived-to-base.cpp b/test/CodeGenCXX/derived-to-base.cpp index c69b45630ef6..3bd5e35615ac 100644 --- a/test/CodeGenCXX/derived-to-base.cpp +++ b/test/CodeGenCXX/derived-to-base.cpp @@ -46,4 +46,4 @@ namespace test3 { } } -// CHECK: attributes [[NUW]] = { nounwind{{.*}} } +// CHECK: attributes [[NUW]] = { noinline nounwind{{.*}} } diff --git a/test/CodeGenCXX/destructors.cpp b/test/CodeGenCXX/destructors.cpp index d6aabee58b9e..b082908b2c94 100644 --- a/test/CodeGenCXX/destructors.cpp +++ b/test/CodeGenCXX/destructors.cpp @@ -1,11 +1,16 @@ -// RUN: %clang_cc1 %s -triple x86_64-apple-darwin10 -emit-llvm -o - -mconstructor-aliases -fcxx-exceptions -fexceptions -O1 -disable-llvm-optzns > %t +// RUN: %clang_cc1 %s -triple x86_64-apple-darwin10 -emit-llvm -o - -mconstructor-aliases -fcxx-exceptions -fexceptions -O1 -disable-llvm-passes -std=c++03 > %t // RUN: FileCheck --check-prefix=CHECK1 --input-file=%t %s // RUN: FileCheck --check-prefix=CHECK2 --input-file=%t %s // RUN: FileCheck --check-prefix=CHECK3 --input-file=%t %s -// RUN: FileCheck --check-prefix=CHECK4 --input-file=%t %s -// RUN: FileCheck --check-prefix=CHECK5 --input-file=%t %s -// RUN: %clang_cc1 %s -triple x86_64-apple-darwin10 -emit-llvm -o - -fcxx-exceptions -fexceptions -O1 -disable-llvm-optzns -std=c++11 > %t2 -// RUN: FileCheck --check-prefix=CHECK6 --input-file=%t2 %s +// RUN: FileCheck --check-prefixes=CHECK4,CHECK4v03 --input-file=%t %s +// RUN: FileCheck --check-prefixes=CHECK5,CHECK5v03 --input-file=%t %s +// RUN: %clang_cc1 %s -triple x86_64-apple-darwin10 -emit-llvm -o - -mconstructor-aliases -fcxx-exceptions -fexceptions -O1 -disable-llvm-passes -std=c++11 > %t2 +// RUN: FileCheck --check-prefix=CHECK1 --input-file=%t2 %s +// RUN: FileCheck --check-prefix=CHECK2v11 --input-file=%t2 %s +// RUN: FileCheck --check-prefix=CHECK3 --input-file=%t2 %s +// RUN: FileCheck --check-prefixes=CHECK4,CHECK4v11 --input-file=%t2 %s +// RUN: FileCheck --check-prefixes=CHECK5,CHECK5v11 --input-file=%t2 %s +// RUN: FileCheck --check-prefix=CHECK6 --input-file=%t2 %s // REQUIRES: asserts struct A { @@ -98,6 +103,12 @@ namespace test0 { // CHECK2: invoke void @_ZN5test04BaseD2Ev // CHECK2: unwind label [[BASE_UNWIND:%[a-zA-Z0-9.]+]] +// In C++11, the destructors are often known not to throw. +// CHECK2v11-LABEL: @_ZN5test01AD1Ev = alias {{.*}} @_ZN5test01AD2Ev +// CHECK2v11-LABEL: define void @_ZN5test01AD2Ev(%"struct.test0::A"* %this) unnamed_addr +// CHECK2v11: call void @_ZN5test06MemberD1Ev +// CHECK2v11: call void @_ZN5test04BaseD2Ev + struct B : Base, virtual VBase { Member M; ~B(); @@ -111,6 +122,10 @@ namespace test0 { // CHECK2: invoke void @_ZN5test04BaseD2Ev // CHECK2: unwind label [[BASE_UNWIND:%[a-zA-Z0-9.]+]] +// CHECK2v11-LABEL: define void @_ZN5test01BD2Ev(%"struct.test0::B"* %this, i8** %vtt) unnamed_addr +// CHECK2v11: call void @_ZN5test06MemberD1Ev +// CHECK2v11: call void @_ZN5test04BaseD2Ev + // CHECK2-LABEL: define void @_ZN5test01BD1Ev(%"struct.test0::B"* %this) unnamed_addr // CHECK2: invoke void @_ZN5test06MemberD1Ev // CHECK2: unwind label [[MEM_UNWIND:%[a-zA-Z0-9.]+]] @@ -118,6 +133,11 @@ namespace test0 { // CHECK2: unwind label [[BASE_UNWIND:%[a-zA-Z0-9.]+]] // CHECK2: invoke void @_ZN5test05VBaseD2Ev // CHECK2: unwind label [[VBASE_UNWIND:%[a-zA-Z0-9.]+]] + +// CHECK2v11-LABEL: define void @_ZN5test01BD1Ev(%"struct.test0::B"* %this) unnamed_addr +// CHECK2v11: call void @_ZN5test06MemberD1Ev +// CHECK2v11: call void @_ZN5test04BaseD2Ev +// CHECK2v11: call void @_ZN5test05VBaseD2Ev } // Test base-class aliasing. @@ -189,19 +209,22 @@ namespace test3 { } // CHECK4-LABEL: define internal void @_ZN5test312_GLOBAL__N_11CD2Ev(%"struct.test3::(anonymous namespace)::C"* %this) unnamed_addr - // CHECK4: invoke void @_ZN5test31BD2Ev( + // CHECK4v03: invoke void @_ZN5test31BD2Ev( + // CHECK4v11: call void @_ZN5test31BD2Ev( // CHECK4: call void @_ZN5test31AD2Ev( // CHECK4: ret void // CHECK4-LABEL: define internal void @_ZN5test312_GLOBAL__N_11DD0Ev(%"struct.test3::(anonymous namespace)::D"* %this) unnamed_addr - // CHECK4-SAME: personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) - // CHECK4: invoke void {{.*}} @_ZN5test312_GLOBAL__N_11CD2Ev + // CHECK4v03-SAME: personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) + // CHECK4v03: invoke void {{.*}} @_ZN5test312_GLOBAL__N_11CD2Ev + // CHECK4v11: call void {{.*}} @_ZN5test312_GLOBAL__N_11CD2Ev // CHECK4: call void @_ZdlPv({{.*}}) [[NUW:#[0-9]+]] // CHECK4: ret void - // CHECK4: landingpad { i8*, i32 } - // CHECK4-NEXT: cleanup - // CHECK4: call void @_ZdlPv({{.*}}) [[NUW]] - // CHECK4: resume { i8*, i32 } + // CHECK4v03: landingpad { i8*, i32 } + // CHECK4v03-NEXT: cleanup + // CHECK4v03: call void @_ZdlPv({{.*}}) [[NUW]] + // CHECK4v03: resume { i8*, i32 } + // CHECK4v11-NOT: landingpad // CHECK4-LABEL: define internal void @_ZThn8_N5test312_GLOBAL__N_11DD1Ev( // CHECK4: getelementptr inbounds i8, i8* {{.*}}, i64 -8 @@ -214,14 +237,15 @@ namespace test3 { // CHECK4: ret void // CHECK4-LABEL: define internal void @_ZN5test312_GLOBAL__N_11CD0Ev(%"struct.test3::(anonymous namespace)::C"* %this) unnamed_addr - // CHECK4-SAME: personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) - // CHECK4: invoke void @_ZN5test312_GLOBAL__N_11CD2Ev( + // CHECK4v03-SAME: personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) + // CHECK4v03: invoke void @_ZN5test312_GLOBAL__N_11CD2Ev( + // CHECK4v11: call void @_ZN5test312_GLOBAL__N_11CD2Ev( // CHECK4: call void @_ZdlPv({{.*}}) [[NUW]] // CHECK4: ret void - // CHECK4: landingpad { i8*, i32 } - // CHECK4-NEXT: cleanup - // CHECK4: call void @_ZdlPv({{.*}}) [[NUW]] - // CHECK4: resume { i8*, i32 } + // CHECK4v03: landingpad { i8*, i32 } + // CHECK4v03-NEXT: cleanup + // CHECK4v03: call void @_ZdlPv({{.*}}) [[NUW]] + // CHECK4v03: resume { i8*, i32 } // CHECK4-LABEL: define internal void @_ZThn8_N5test312_GLOBAL__N_11CD1Ev( // CHECK4: getelementptr inbounds i8, i8* {{.*}}, i64 -8 @@ -282,8 +306,8 @@ namespace test5 { // CHECK5-LABEL: define void @_ZN5test53fooEv() // CHECK5: [[ELEMS:%.*]] = alloca [5 x [[A:%.*]]], align - // CHECK5-NEXT: [[EXN:%.*]] = alloca i8* - // CHECK5-NEXT: [[SEL:%.*]] = alloca i32 + // CHECK5v03-NEXT: [[EXN:%.*]] = alloca i8* + // CHECK5v03-NEXT: [[SEL:%.*]] = alloca i32 // CHECK5-NEXT: [[PELEMS:%.*]] = bitcast [5 x [[A]]]* [[ELEMS]] to i8* // CHECK5-NEXT: call void @llvm.lifetime.start(i64 5, i8* [[PELEMS]]) // CHECK5-NEXT: [[BEGIN:%.*]] = getelementptr inbounds [5 x [[A]]], [5 x [[A]]]* [[ELEMS]], i32 0, i32 0 @@ -291,19 +315,22 @@ namespace test5 { // CHECK5-NEXT: br label // CHECK5: [[POST:%.*]] = phi [[A]]* [ [[END]], {{%.*}} ], [ [[ELT:%.*]], {{%.*}} ] // CHECK5-NEXT: [[ELT]] = getelementptr inbounds [[A]], [[A]]* [[POST]], i64 -1 - // CHECK5-NEXT: invoke void @_ZN5test51AD1Ev([[A]]* [[ELT]]) + // CHECK5v03-NEXT: invoke void @_ZN5test51AD1Ev([[A]]* [[ELT]]) + // CHECK5v11-NEXT: call void @_ZN5test51AD1Ev([[A]]* [[ELT]]) // CHECK5: [[T0:%.*]] = icmp eq [[A]]* [[ELT]], [[BEGIN]] // CHECK5-NEXT: br i1 [[T0]], // CHECK5: call void @llvm.lifetime.end // CHECK5-NEXT: ret void // lpad - // CHECK5: [[EMPTY:%.*]] = icmp eq [[A]]* [[BEGIN]], [[ELT]] - // CHECK5-NEXT: br i1 [[EMPTY]] - // CHECK5: [[AFTER:%.*]] = phi [[A]]* [ [[ELT]], {{%.*}} ], [ [[CUR:%.*]], {{%.*}} ] - // CHECK5-NEXT: [[CUR:%.*]] = getelementptr inbounds [[A]], [[A]]* [[AFTER]], i64 -1 - // CHECK5-NEXT: invoke void @_ZN5test51AD1Ev([[A]]* [[CUR]]) - // CHECK5: [[DONE:%.*]] = icmp eq [[A]]* [[CUR]], [[BEGIN]] - // CHECK5-NEXT: br i1 [[DONE]], + // CHECK5v03: [[EMPTY:%.*]] = icmp eq [[A]]* [[BEGIN]], [[ELT]] + // CHECK5v03-NEXT: br i1 [[EMPTY]] + // CHECK5v03: [[AFTER:%.*]] = phi [[A]]* [ [[ELT]], {{%.*}} ], [ [[CUR:%.*]], {{%.*}} ] + // CHECK5v03-NEXT: [[CUR:%.*]] = getelementptr inbounds [[A]], [[A]]* [[AFTER]], i64 -1 + // CHECK5v03-NEXT: invoke void @_ZN5test51AD1Ev([[A]]* [[CUR]]) + // CHECK5v03: [[DONE:%.*]] = icmp eq [[A]]* [[CUR]], [[BEGIN]] + // CHECK5v03-NEXT: br i1 [[DONE]], + // CHECK5v11-NOT: landingpad + // CHECK5v11: } void foo() { A elems[5]; } @@ -334,25 +361,34 @@ namespace test6 { C::~C() { opaque(); } // CHECK5-LABEL: define void @_ZN5test61CD2Ev(%"struct.test6::C"* %this, i8** %vtt) unnamed_addr // CHECK5: invoke void @_ZN5test66opaqueEv - // CHECK5: invoke void @_ZN5test61AD1Ev - // CHECK5: invoke void @_ZN5test61AD1Ev - // CHECK5: invoke void @_ZN5test61AD1Ev - // CHECK5: invoke void @_ZN5test61BILj1EED2Ev + // CHECK5v03: invoke void @_ZN5test61AD1Ev + // CHECK5v03: invoke void @_ZN5test61AD1Ev + // CHECK5v03: invoke void @_ZN5test61AD1Ev + // CHECK5v03: invoke void @_ZN5test61BILj1EED2Ev + // CHECK5v11: call void @_ZN5test61AD1Ev + // CHECK5v11: call void @_ZN5test61AD1Ev + // CHECK5v11: call void @_ZN5test61AD1Ev + // CHECK5v11: call void @_ZN5test61BILj1EED2Ev // CHECK5: call void @_ZN5test61BILj0EED2Ev // CHECK5: ret void - // CHECK5: invoke void @_ZN5test61AD1Ev - // CHECK5: invoke void @_ZN5test61AD1Ev - // CHECK5: invoke void @_ZN5test61AD1Ev - // CHECK5: invoke void @_ZN5test61BILj1EED2Ev - // CHECK5: invoke void @_ZN5test61BILj0EED2Ev + // CHECK5v03: invoke void @_ZN5test61AD1Ev + // CHECK5v03: invoke void @_ZN5test61AD1Ev + // CHECK5v03: invoke void @_ZN5test61AD1Ev + // CHECK5v03: invoke void @_ZN5test61BILj1EED2Ev + // CHECK5v03: invoke void @_ZN5test61BILj0EED2Ev // CHECK5-LABEL: define void @_ZN5test61CD1Ev(%"struct.test6::C"* %this) unnamed_addr - // CHECK5: invoke void @_ZN5test61CD2Ev - // CHECK5: invoke void @_ZN5test61BILj3EED2Ev - // CHECK5: call void @_ZN5test61BILj2EED2Ev - // CHECK5: ret void - // CHECK5: invoke void @_ZN5test61BILj3EED2Ev - // CHECK5: invoke void @_ZN5test61BILj2EED2Ev + // CHECK5v03: invoke void @_ZN5test61CD2Ev + // CHECK5v03: invoke void @_ZN5test61BILj3EED2Ev + // CHECK5v03: call void @_ZN5test61BILj2EED2Ev + // CHECK5v03: ret void + // CHECK5v03: invoke void @_ZN5test61BILj3EED2Ev + // CHECK5v03: invoke void @_ZN5test61BILj2EED2Ev + + // CHECK5v11: call void @_ZN5test61CD2Ev + // CHECK5v11: call void @_ZN5test61BILj3EED2Ev + // CHECK5v11: call void @_ZN5test61BILj2EED2Ev + // CHECK5v11: ret void } // PR 9197 @@ -369,7 +405,8 @@ namespace test7 { // Verify that this doesn't get emitted as an alias // CHECK5-LABEL: define void @_ZN5test71BD2Ev( - // CHECK5: invoke void @_ZN5test71DD1Ev( + // CHECK5v03: invoke void @_ZN5test71DD1Ev( + // CHECK5v11: call void @_ZN5test71DD1Ev( // CHECK5: call void @_ZN5test71AD2Ev( B::~B() {} } @@ -394,7 +431,8 @@ namespace test8 { // CHECK5: call void @_ZN5test81AC1Ev([[A]]* [[X]]) // CHECK5-NEXT: br label // CHECK5: invoke void @_ZN5test81AC1Ev([[A]]* [[Y]]) - // CHECK5: invoke void @_ZN5test81AD1Ev([[A]]* [[Y]]) + // CHECK5v03: invoke void @_ZN5test81AD1Ev([[A]]* [[Y]]) + // CHECK5v11: call void @_ZN5test81AD1Ev([[A]]* [[Y]]) // CHECK5-NOT: switch // CHECK5: invoke void @_ZN5test83dieEv() // CHECK5: unreachable diff --git a/test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp b/test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp index 193ee5f80406..b90620ab600f 100644 --- a/test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp +++ b/test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp @@ -225,3 +225,19 @@ namespace Test9 { return -static_cast<RA&>(*x); } } + +namespace Test10 { + struct A { + virtual int f(); + }; + + struct B : A { + int f() final; + }; + + // CHECK-LABEL: define i32 @_ZN6Test101fEPNS_1BE + int f(B *b) { + // CHECK: call i32 @_ZN6Test101B1fEv + return static_cast<A *>(b)->f(); + } +} diff --git a/test/CodeGenCXX/devirtualize-virtual-function-calls.cpp b/test/CodeGenCXX/devirtualize-virtual-function-calls.cpp index 911ddeedd236..b4c39f3fcff5 100644 --- a/test/CodeGenCXX/devirtualize-virtual-function-calls.cpp +++ b/test/CodeGenCXX/devirtualize-virtual-function-calls.cpp @@ -1,8 +1,11 @@ -// RUN: %clang_cc1 %s -triple armv7-none-eabi -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -std=c++98 %s -triple armv7-none-eabi -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -std=c++11 %s -triple armv7-none-eabi -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -std=c++1z %s -triple armv7-none-eabi -emit-llvm -o - | FileCheck %s struct A { virtual void f(); virtual void f_const() const; + virtual void g(); A h(); }; @@ -37,6 +40,64 @@ void f(A a, A *ap, A& ar) { (a).f(); } +struct D : A { virtual void g(); }; +struct XD { D d; }; + +D gd(); + +void fd(D d, XD xd, D *p) { + // CHECK: call void @_ZN1A1fEv(%struct.A* + d.f(); + + // CHECK: call void @_ZN1D1gEv(%struct.D* + d.g(); + + // CHECK: call void @_ZN1A1fEv + D().f(); + + // CHECK: call void @_ZN1D1gEv + D().g(); + + // CHECK: call void @_ZN1A1fEv + gd().f(); + + // CHECK: call void @_ZNK1A7f_constEv + d.f_const(); + + // CHECK: call void @_ZN1A1fEv + (d).f(); + + // CHECK: call void @_ZN1A1fEv + (true, d).f(); + + // CHECK: call void @_ZN1D1gEv + (true, d).g(); + + // CHECK: call void @_ZN1A1fEv + xd.d.f(); + + // CHECK: call void @_ZN1A1fEv + XD().d.f(); + + // CHECK: call void @_ZN1A1fEv + D XD::*mp; + (xd.*mp).f(); + + // CHECK: call void @_ZN1D1gEv + (xd.*mp).g(); + + // Can't devirtualize this; we have no guarantee that p points to a D here, + // due to the "single object is considered to be an array of one element" + // rule. + // CHECK: call void % + p[0].f(); + + // FIXME: We can devirtualize this, by C++1z [expr.add]/6 (if the array + // element type and the pointee type are not similar, behavior is undefined). + // CHECK: call void % + p[1].f(); +} + struct B { virtual void f(); ~B(); @@ -100,3 +161,37 @@ namespace test4 { p->fish.eat(); } } + +// Do not devirtualize to pure virtual function calls. +namespace test5 { + struct X { + virtual void f() = 0; + }; + struct Y {}; + // CHECK-LABEL: define {{.*}} @_ZN5test51f + void f(Y &y, X Y::*p) { + // CHECK-NOT: call {{.*}} @_ZN5test51X1fEv + // CHECK: call void % + (y.*p).f(); + }; + + struct Z final { + virtual void f() = 0; + }; + // CHECK-LABEL: define {{.*}} @_ZN5test51g + void g(Z &z) { + // CHECK-NOT: call {{.*}} @_ZN5test51Z1fEv + // CHECK: call void % + z.f(); + } + + struct Q { + virtual void f() final = 0; + }; + // CHECK-LABEL: define {{.*}} @_ZN5test51h + void h(Q &q) { + // CHECK-NOT: call {{.*}} @_ZN5test51Q1fEv + // CHECK: call void % + q.f(); + } +} diff --git a/test/CodeGenCXX/dllexport.cpp b/test/CodeGenCXX/dllexport.cpp index 7cef7c2d127e..eb9ca79b7b40 100644 --- a/test/CodeGenCXX/dllexport.cpp +++ b/test/CodeGenCXX/dllexport.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -std=c++1y -fno-threadsafe-statics -fms-extensions -O1 -mconstructor-aliases -disable-llvm-optzns -o - %s -w -fms-compatibility-version=19.00 | FileCheck --check-prefix=MSC --check-prefix=M32 -check-prefix=MSVC2015 -check-prefix=M32MSVC2015 %s -// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -std=c++1y -fno-threadsafe-statics -fms-extensions -O1 -mconstructor-aliases -disable-llvm-optzns -o - %s -w -fms-compatibility-version=18.00 | FileCheck --check-prefix=MSC --check-prefix=M32 -check-prefix=MSVC2013 -check-prefix=M32MSVC2013 %s +// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -std=c++1y -fno-threadsafe-statics -fms-extensions -O1 -mconstructor-aliases -disable-llvm-passes -o - %s -w -fms-compatibility-version=19.00 | FileCheck --check-prefix=MSC --check-prefix=M32 -check-prefix=MSVC2015 -check-prefix=M32MSVC2015 %s +// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -std=c++1y -fno-threadsafe-statics -fms-extensions -O1 -mconstructor-aliases -disable-llvm-passes -o - %s -w -fms-compatibility-version=18.00 | FileCheck --check-prefix=MSC --check-prefix=M32 -check-prefix=MSVC2013 -check-prefix=M32MSVC2013 %s // RUN: %clang_cc1 -triple x86_64-windows-msvc -emit-llvm -std=c++1y -fno-threadsafe-statics -fms-extensions -O0 -o - %s -w -fms-compatibility-version=19.00 | FileCheck --check-prefix=MSC --check-prefix=M64 -check-prefix=MSVC2015 -check-prefix=M64MSVC2015 %s // RUN: %clang_cc1 -triple x86_64-windows-msvc -emit-llvm -std=c++1y -fno-threadsafe-statics -fms-extensions -O0 -o - %s -w -fms-compatibility-version=18.00 | FileCheck --check-prefix=MSC --check-prefix=M64 -check-prefix=MSVC2013 -check-prefix=M64MSVC2013 %s @@ -612,9 +612,9 @@ void W::foo() {} // Copy ctor: // M32-DAG: define weak_odr dllexport x86_thiscallcc %struct.W* @"\01??0W@@QAE@ABU0@@Z" // vftable: -// M32-DAG: [[W_VTABLE:@.*]] = private unnamed_addr constant [2 x i8*] [i8* bitcast (%rtti.CompleteObjectLocator* @"\01??_R4W@@6B@" to i8*), i8* bitcast (void (%struct.W*)* @"\01?foo@W@@UAEXXZ" to i8*)], comdat($"\01??_7W@@6B@") -// M32-DAG: @"\01??_7W@@6B@" = dllexport unnamed_addr alias i8*, getelementptr inbounds ([2 x i8*], [2 x i8*]* [[W_VTABLE]], i32 0, i32 1) -// G32-DAG: @_ZTV1W = dllexport unnamed_addr constant [3 x i8*] [i8* null, i8* bitcast ({ i8*, i8* }* @_ZTI1W to i8*), i8* bitcast (void (%struct.W*)* @_ZN1W3fooEv to i8*)] +// M32-DAG: [[W_VTABLE:@.*]] = private unnamed_addr constant { [2 x i8*] } { [2 x i8*] [i8* bitcast (%rtti.CompleteObjectLocator* @"\01??_R4W@@6B@" to i8*), i8* bitcast (void (%struct.W*)* @"\01?foo@W@@UAEXXZ" to i8*)] }, comdat($"\01??_7W@@6B@") +// M32-DAG: @"\01??_7W@@6B@" = dllexport unnamed_addr alias i8*, getelementptr inbounds ({ [2 x i8*] }, { [2 x i8*] }* [[W_VTABLE]], i32 0, i32 0, i32 1) +// G32-DAG: @_ZTV1W = dllexport unnamed_addr constant { [3 x i8*] } { [3 x i8*] [i8* null, i8* bitcast ({ i8*, i8* }* @_ZTI1W to i8*), i8* bitcast (void (%struct.W*)* @_ZN1W3fooEv to i8*)] } struct __declspec(dllexport) X : public virtual W {}; // vbtable: @@ -771,6 +771,13 @@ USEMEMFUNC(ExplicitInstantiationDeclExportedDefTemplate<int>, f); // M32-DAG: define weak_odr dllexport x86_thiscallcc %struct.ExplicitInstantiationDeclExportedDefTemplate* @"\01??0?$ExplicitInstantiationDeclExportedDefTemplate@H@@QAE@XZ" // G32-DAG: define weak_odr x86_thiscallcc void @_ZN44ExplicitInstantiationDeclExportedDefTemplateIiE1fEv +template <typename T> struct ImplicitInstantiationExplicitInstantiationDefExportedTemplate { void f() {} }; +ImplicitInstantiationExplicitInstantiationDefExportedTemplate<int> ImplicitInstantiationExplicitInstantiationDefExportedTemplateInstance; +template class __declspec(dllexport) ImplicitInstantiationExplicitInstantiationDefExportedTemplate<int>; +USEMEMFUNC(ImplicitInstantiationExplicitInstantiationDefExportedTemplate<int>, f); +// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?f@?$ImplicitInstantiationExplicitInstantiationDefExportedTemplate@H@@QAEXXZ" +// G32-DAG: define weak_odr x86_thiscallcc void @_ZN61ImplicitInstantiationExplicitInstantiationDefExportedTemplateIiE1fEv + namespace { struct InternalLinkageType {}; } struct __declspec(dllexport) PR23308 { void f(InternalLinkageType*); diff --git a/test/CodeGenCXX/dllimport-members.cpp b/test/CodeGenCXX/dllimport-members.cpp index 1fed1bf0acf1..19d9e1dfe7b6 100644 --- a/test/CodeGenCXX/dllimport-members.cpp +++ b/test/CodeGenCXX/dllimport-members.cpp @@ -44,7 +44,7 @@ void useSpecials() { } // Used to force non-trivial special members. -struct ForceNonTrivial { +struct __declspec(dllimport) ForceNonTrivial { ForceNonTrivial(); ~ForceNonTrivial(); ForceNonTrivial(const ForceNonTrivial&); diff --git a/test/CodeGenCXX/dllimport-rtti.cpp b/test/CodeGenCXX/dllimport-rtti.cpp index 4baee50fcff3..91e747ae1c15 100644 --- a/test/CodeGenCXX/dllimport-rtti.cpp +++ b/test/CodeGenCXX/dllimport-rtti.cpp @@ -1,11 +1,11 @@ -// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -std=c++1y -fms-extensions -O1 -disable-llvm-optzns -o - %s | FileCheck %s --check-prefix=MSVC -// RUN: %clang_cc1 -triple i686-windows-gnu -emit-llvm -std=c++1y -fms-extensions -O1 -disable-llvm-optzns -o - %s | FileCheck %s --check-prefix=GNU +// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -std=c++1y -fms-extensions -O1 -disable-llvm-passes -o - %s | FileCheck %s --check-prefix=MSVC +// RUN: %clang_cc1 -triple i686-windows-gnu -emit-llvm -std=c++1y -fms-extensions -O1 -disable-llvm-passes -o - %s | FileCheck %s --check-prefix=GNU struct __declspec(dllimport) S { virtual void f() {} } s; -// MSVC: [[VF_S:.*]] = private unnamed_addr constant [2 x i8*] -// MSVC-DAG: @"\01??_SS@@6B@" = unnamed_addr alias i8*, getelementptr inbounds ([2 x i8*], [2 x i8*]* [[VF_S]], i32 0, i32 1) +// MSVC: [[VF_S:.*]] = private unnamed_addr constant { [2 x i8*] } +// MSVC-DAG: @"\01??_SS@@6B@" = unnamed_addr alias i8*, getelementptr inbounds ({ [2 x i8*] }, { [2 x i8*] }* [[VF_S]], i32 0, i32 0, i32 1) // MSVC-DAG: @"\01??_R0?AUS@@@8" = linkonce_odr // MSVC-DAG: @"\01??_R1A@?0A@EA@S@@8" = linkonce_odr // MSVC-DAG: @"\01??_R2S@@8" = linkonce_odr diff --git a/test/CodeGenCXX/dllimport.cpp b/test/CodeGenCXX/dllimport.cpp index aff240f28769..4ec14b72109f 100644 --- a/test/CodeGenCXX/dllimport.cpp +++ b/test/CodeGenCXX/dllimport.cpp @@ -2,8 +2,8 @@ // RUN: %clang_cc1 -triple x86_64-windows-msvc -fno-rtti -fno-threadsafe-statics -fms-extensions -emit-llvm -std=c++1y -O0 -o - %s -DMSABI -w | FileCheck --check-prefix=MSC --check-prefix=M64 %s // RUN: %clang_cc1 -triple i686-windows-gnu -fno-rtti -fno-threadsafe-statics -fms-extensions -emit-llvm -std=c++1y -O0 -o - %s -w | FileCheck --check-prefix=GNU --check-prefix=G32 %s // RUN: %clang_cc1 -triple x86_64-windows-gnu -fno-rtti -fno-threadsafe-statics -fms-extensions -emit-llvm -std=c++1y -O0 -o - %s -w | FileCheck --check-prefix=GNU --check-prefix=G64 %s -// RUN: %clang_cc1 -triple i686-windows-msvc -fno-rtti -fno-threadsafe-statics -fms-extensions -fms-compatibility-version=18.00 -emit-llvm -std=c++1y -O1 -disable-llvm-optzns -o - %s -DMSABI -w | FileCheck --check-prefix=MO1 --check-prefix=M18 %s -// RUN: %clang_cc1 -triple i686-windows-msvc -fno-rtti -fno-threadsafe-statics -fms-extensions -fms-compatibility-version=19.00 -emit-llvm -std=c++1y -O1 -disable-llvm-optzns -o - %s -DMSABI -w | FileCheck --check-prefix=MO1 --check-prefix=M19 %s +// RUN: %clang_cc1 -triple i686-windows-msvc -fno-rtti -fno-threadsafe-statics -fms-extensions -fms-compatibility-version=18.00 -emit-llvm -std=c++1y -O1 -disable-llvm-passes -o - %s -DMSABI -w | FileCheck --check-prefix=MO1 --check-prefix=M18 %s +// RUN: %clang_cc1 -triple i686-windows-msvc -fno-rtti -fno-threadsafe-statics -fms-extensions -fms-compatibility-version=19.00 -emit-llvm -std=c++1y -O1 -disable-llvm-passes -o - %s -DMSABI -w | FileCheck --check-prefix=MO1 --check-prefix=M19 %s // RUN: %clang_cc1 -triple i686-windows-gnu -fno-rtti -fno-threadsafe-statics -fms-extensions -emit-llvm -std=c++1y -O1 -o - %s -w | FileCheck --check-prefix=GO1 %s // CHECK-NOT doesn't play nice with CHECK-DAG, so use separate run lines. @@ -347,6 +347,17 @@ __declspec(dllimport) inline int *ReferencingImportedDelete() { delete (int*)nul // MO1-DAG: define available_externally dllimport i32* @"\01?ReferencingImportedDelete@@YAPAHXZ" USE(ReferencingImportedNew) USE(ReferencingImportedDelete) +struct ClassWithDtor { ~ClassWithDtor() {} }; +struct __declspec(dllimport) ClassWithNonDllImportField { ClassWithDtor t; }; +struct __declspec(dllimport) ClassWithNonDllImportBase : public ClassWithDtor { }; +USECLASS(ClassWithNonDllImportField); +USECLASS(ClassWithNonDllImportBase); +// MO1-DAG: declare dllimport x86_thiscallcc void @"\01??1ClassWithNonDllImportBase@@QAE@XZ"(%struct.ClassWithNonDllImportBase*) +// MO1-DAG: declare dllimport x86_thiscallcc void @"\01??1ClassWithNonDllImportField@@QAE@XZ"(%struct.ClassWithNonDllImportField*) +struct ClassWithCtor { ClassWithCtor() {} }; +struct __declspec(dllimport) ClassWithNonDllImportFieldWithCtor { ClassWithCtor t; }; +USECLASS(ClassWithNonDllImportFieldWithCtor); +// MO1-DAG: declare dllimport x86_thiscallcc %struct.ClassWithNonDllImportFieldWithCtor* @"\01??0ClassWithNonDllImportFieldWithCtor@@QAE@XZ"(%struct.ClassWithNonDllImportFieldWithCtor* returned) // A dllimport function with a TLS variable must not be available_externally. __declspec(dllimport) inline void FunctionWithTLSVar() { static __thread int x = 42; } @@ -620,15 +631,15 @@ USEMEMFUNC(V, foo) struct __declspec(dllimport) W { virtual void foo() {} }; USECLASS(W) // vftable: -// MO1-DAG: @"\01??_SW@@6B@" = linkonce_odr unnamed_addr constant [1 x i8*] [i8* bitcast (void (%struct.W*)* @"\01?foo@W@@UAEXXZ" to i8*)] -// GO1-DAG: @_ZTV1W = available_externally dllimport unnamed_addr constant [3 x i8*] [i8* null, i8* null, i8* bitcast (void (%struct.W*)* @_ZN1W3fooEv to i8*)] +// MO1-DAG: @"\01??_SW@@6B@" = linkonce_odr unnamed_addr constant { [1 x i8*] } { [1 x i8*] [i8* bitcast (void (%struct.W*)* @"\01?foo@W@@UAEXXZ" to i8*)] } +// GO1-DAG: @_ZTV1W = available_externally dllimport unnamed_addr constant { [3 x i8*] } { [3 x i8*] [i8* null, i8* null, i8* bitcast (void (%struct.W*)* @_ZN1W3fooEv to i8*)] } struct __declspec(dllimport) KeyFuncClass { constexpr KeyFuncClass() {} virtual void foo(); }; extern constexpr KeyFuncClass keyFuncClassVar = {}; -// G32-DAG: @_ZTV12KeyFuncClass = external dllimport unnamed_addr constant [3 x i8*] +// G32-DAG: @_ZTV12KeyFuncClass = external dllimport unnamed_addr constant { [3 x i8*] } struct __declspec(dllimport) X : public virtual W {}; USECLASS(X) @@ -658,7 +669,7 @@ namespace Vtordisp { // Don't dllimport the vtordisp. // MO1-DAG: define linkonce_odr x86_thiscallcc void @"\01?f@?$C@H@Vtordisp@@$4PPPPPPPM@A@AEXXZ" - class Base { + class __declspec(dllimport) Base { virtual void f() {} }; template <typename T> @@ -734,7 +745,7 @@ namespace PR21355 { // S::~S is a key function, so we would ordinarily emit a strong definition for // the vtable. However, S is imported, so the vtable should be too. - // GNU-DAG: @_ZTVN7PR213551SE = available_externally dllimport unnamed_addr constant [4 x i8*] + // GNU-DAG: @_ZTVN7PR213551SE = available_externally dllimport unnamed_addr constant { [4 x i8*] } } namespace PR21366 { @@ -756,7 +767,7 @@ namespace PR27319 { }; extern template struct __declspec(dllimport) A<int>; void f() { new A<int>(); } - // MO1-DAG: @"\01??_S?$A@H@PR27319@@6B@" = linkonce_odr unnamed_addr constant [1 x i8*] + // MO1-DAG: @"\01??_S?$A@H@PR27319@@6B@" = linkonce_odr unnamed_addr constant { [1 x i8*] } } // MS ignores DLL attributes on partial specializations. diff --git a/test/CodeGenCXX/empty-classes.cpp b/test/CodeGenCXX/empty-classes.cpp index e27a961e123a..5727d5918291 100644 --- a/test/CodeGenCXX/empty-classes.cpp +++ b/test/CodeGenCXX/empty-classes.cpp @@ -96,3 +96,24 @@ namespace rdar20621065 { // Type checked at the top of the file. B b; }; + +// This test used to crash when CGRecordLayout::getNonVirtualBaseLLVMFieldNo was called. +namespace record_layout { +struct X0 { + int x[0]; +}; + +template<typename> +struct X2 : X0 { +}; + +template<typename> +struct X3 : X2<int> { + X3() : X2<int>() {} +}; + + +void test0() { + X3<int>(); +} +} diff --git a/test/CodeGenCXX/enable_if.cpp b/test/CodeGenCXX/enable_if.cpp index e17695b413b6..4e7707aaeed9 100644 --- a/test/CodeGenCXX/enable_if.cpp +++ b/test/CodeGenCXX/enable_if.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-pc-linux-gnu| FileCheck %s +// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-pc-linux-gnu | FileCheck %s // Test address-of overloading logic int test5(int); diff --git a/test/CodeGenCXX/exceptions-seh.cpp b/test/CodeGenCXX/exceptions-seh.cpp index 589bc2265760..7a11a1e50582 100644 --- a/test/CodeGenCXX/exceptions-seh.cpp +++ b/test/CodeGenCXX/exceptions-seh.cpp @@ -2,7 +2,7 @@ // RUN: -o - -mconstructor-aliases -fcxx-exceptions -fexceptions | \ // RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CXXEH // RUN: %clang_cc1 -std=c++11 -fblocks -fms-extensions %s -triple=x86_64-windows-msvc -emit-llvm \ -// RUN: -o - -mconstructor-aliases -O1 -disable-llvm-optzns | \ +// RUN: -o - -mconstructor-aliases -O1 -disable-llvm-passes | \ // RUN: FileCheck %s --check-prefix=CHECK --check-prefix=NOCXX extern "C" unsigned long _exception_code(); diff --git a/test/CodeGenCXX/explicit-instantiation.cpp b/test/CodeGenCXX/explicit-instantiation.cpp index 7e00d78e4834..fb5711878764 100644 --- a/test/CodeGenCXX/explicit-instantiation.cpp +++ b/test/CodeGenCXX/explicit-instantiation.cpp @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -emit-llvm -triple i686-pc-linux-gnu -std=c++1y -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NO-OPT -// RUN: %clang_cc1 -emit-llvm -triple i686-pc-linux-gnu -std=c++1y -O3 -disable-llvm-optzns -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-OPT +// RUN: %clang_cc1 -emit-llvm -triple i686-pc-linux-gnu -std=c++1y -O3 -disable-llvm-passes -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-OPT // RUN: %clang_cc1 -emit-llvm -triple i686-pc-win32 -std=c++1y -o - %s | FileCheck %s --check-prefix=CHECK-MS // This check logically is attached to 'template int S<int>::i;' below. diff --git a/test/CodeGenCXX/global-dtor-no-atexit.cpp b/test/CodeGenCXX/global-dtor-no-atexit.cpp index 9860412b1bda..862194126ba8 100644 --- a/test/CodeGenCXX/global-dtor-no-atexit.cpp +++ b/test/CodeGenCXX/global-dtor-no-atexit.cpp @@ -43,4 +43,4 @@ void func() { static A a1, a2; } -// CHECK: attributes [[NUW]] = { nounwind{{.*}} } +// CHECK: attributes [[NUW]] = { noinline nounwind{{.*}} } diff --git a/test/CodeGenCXX/global-init.cpp b/test/CodeGenCXX/global-init.cpp index e806af9eacb4..291b43cac0a0 100644 --- a/test/CodeGenCXX/global-init.cpp +++ b/test/CodeGenCXX/global-init.cpp @@ -18,9 +18,6 @@ struct D { ~D(); }; // CHECK: @__dso_handle = external global i8 // CHECK: @c = global %struct.C zeroinitializer, align 8 -// It's okay if we ever implement the IR-generation optimization to remove this. -// CHECK: @_ZN5test3L3varE = internal constant i8* getelementptr inbounds ([7 x i8], [7 x i8]* - // PR6205: The casts should not require global initializers // CHECK: @_ZN6PR59741cE = external global %"struct.PR5974::C" // CHECK: @_ZN6PR59741aE = global %"struct.PR5974::A"* getelementptr inbounds (%"struct.PR5974::C", %"struct.PR5974::C"* @_ZN6PR59741cE, i32 0, i32 0) @@ -171,6 +168,8 @@ namespace test7 { const int b3 = B().n; // CHECK-NOT: @_ZN5test7L2c1E + // CHECK: call void @llvm.memset{{.*}} @_ZN5test7L2c1E + // CHECK-NOT: @_ZN5test7L2c1E // CHECK: @_ZN5test7L2c2E // CHECK-NOT: @_ZN5test7L2c3E // CHECK: @_ZN5test7L2c4E @@ -205,8 +204,8 @@ namespace test7 { // rdar://problem/8090834: this should be nounwind // CHECK-NOEXC: define internal void @_GLOBAL__sub_I_global_init.cpp() [[NUW:#[0-9]+]] section "__TEXT,__StaticInit,regular,pure_instructions" { -// CHECK-NOEXC: attributes [[NUW]] = { nounwind{{.*}} } +// CHECK-NOEXC: attributes [[NUW]] = { noinline nounwind{{.*}} } // PR21811: attach the appropriate attribute to the global init function // CHECK-FP: define internal void @_GLOBAL__sub_I_global_init.cpp() [[NUX:#[0-9]+]] section "__TEXT,__StaticInit,regular,pure_instructions" { -// CHECK-FP: attributes [[NUX]] = { nounwind {{.*}}"no-frame-pointer-elim-non-leaf"{{.*}} } +// CHECK-FP: attributes [[NUX]] = { noinline nounwind {{.*}}"no-frame-pointer-elim-non-leaf"{{.*}} } diff --git a/test/CodeGenCXX/implicit-copy-constructor.cpp b/test/CodeGenCXX/implicit-copy-constructor.cpp index d0224131c4da..3f8665aa3b4d 100644 --- a/test/CodeGenCXX/implicit-copy-constructor.cpp +++ b/test/CodeGenCXX/implicit-copy-constructor.cpp @@ -48,12 +48,14 @@ void f(D d) { // CHECK: call void @_ZN1BC2ERS_ // CHECK: {{call void @llvm.memcpy.p0i8.p0i8.i64.*i64 28}} // CHECK: call void @_ZN1BC1ERS_ -// CHECK: br -// CHECK: {{icmp ult.*, 2}} -// CHECK: {{icmp ult.*, 3}} +// CHECK: br label // CHECK: call void @_ZN1AC1Ev // CHECK: call void @_ZN1CC1ERS_1A // CHECK: call void @_ZN1AD1Ev +// CHECK: {{icmp eq.*, 3}} +// CHECK: br i1 +// CHECK: {{icmp eq.*, 2}} +// CHECK: br i1 // CHECK: {{call void @llvm.memcpy.p0i8.p0i8.i64.*i64 300}} // CHECK: ret void diff --git a/test/CodeGenCXX/init-invariant.cpp b/test/CodeGenCXX/init-invariant.cpp index 71eb7dd73492..815287c8e116 100644 --- a/test/CodeGenCXX/init-invariant.cpp +++ b/test/CodeGenCXX/init-invariant.cpp @@ -1,12 +1,12 @@ // RUN: %clang_cc1 -triple i686-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-O0 // RUN: %clang_cc1 -triple i686-linux-gnu -emit-llvm %s -O1 -o - | FileCheck %s -// Check that we add an llvm.invariant.start to mark when a global becomes +// Check that we add an llvm.invariant.start.p0i8 to mark when a global becomes // read-only. If globalopt can fold the initializer, it will then mark the // variable as constant. // Do not produce markers at -O0. -// CHECK-O0-NOT: llvm.invariant.start +// CHECK-O0-NOT: llvm.invariant.start.p0i8 struct A { A(); @@ -42,19 +42,19 @@ void e() { } // CHECK: call void @_ZN1AC1Ev({{.*}}* nonnull @a) -// CHECK: call {{.*}}@llvm.invariant.start(i64 4, i8* bitcast ({{.*}} @a to i8*)) +// CHECK: call {{.*}}@llvm.invariant.start.p0i8(i64 4, i8* bitcast ({{.*}} @a to i8*)) // CHECK: call void @_ZN1BC1Ev({{.*}}* nonnull @b) -// CHECK-NOT: call {{.*}}@llvm.invariant.start(i64 4, i8* bitcast ({{.*}} @b to i8*)) +// CHECK-NOT: call {{.*}}@llvm.invariant.start.p0i8(i64 4, i8* bitcast ({{.*}} @b to i8*)) // CHECK: call void @_ZN1CC1Ev({{.*}}* nonnull @c) -// CHECK-NOT: call {{.*}}@llvm.invariant.start(i64 4, i8* bitcast ({{.*}} @c to i8*)) +// CHECK-NOT: call {{.*}}@llvm.invariant.start.p0i8(i64 4, i8* bitcast ({{.*}} @c to i8*)) // CHECK: call i32 @_Z1fv( // CHECK: store {{.*}}, i32* @d -// CHECK: call {{.*}}@llvm.invariant.start(i64 4, i8* bitcast ({{.*}} @d to i8*)) +// CHECK: call {{.*}}@llvm.invariant.start.p0i8(i64 4, i8* bitcast ({{.*}} @d to i8*)) // CHECK-LABEL: define void @_Z1ev( // CHECK: call void @_ZN1AC1Ev(%struct.A* nonnull @_ZZ1evE1a) -// CHECK: call {{.*}}@llvm.invariant.start(i64 4, i8* {{.*}}bitcast ({{.*}} @_ZZ1evE1a to i8*)) +// CHECK: call {{.*}}@llvm.invariant.start.p0i8(i64 4, i8* {{.*}}bitcast ({{.*}} @_ZZ1evE1a to i8*)) // CHECK-NOT: llvm.invariant.end diff --git a/test/CodeGenCXX/inline-dllexport-member.cpp b/test/CodeGenCXX/inline-dllexport-member.cpp index 2160f32e0b4f..66ef459bd80b 100644 --- a/test/CodeGenCXX/inline-dllexport-member.cpp +++ b/test/CodeGenCXX/inline-dllexport-member.cpp @@ -1,11 +1,13 @@ // RUN: %clang_cc1 -triple i686-windows-win32 -fms-extensions -debug-info-kind=limited -emit-llvm %s -o - \ // RUN: | FileCheck %s +// CHECK: @"\01?ui@s@@2IB" = weak_odr dllexport constant i32 0, comdat, align 4, !dbg [[UI:![0-9]+]] + struct __declspec(dllexport) s { static const unsigned int ui = 0; }; -// CHECK: ![[SCOPE:[0-9]+]] = distinct !DICompileUnit( -// CHECK: !DIGlobalVariable(name: "ui", linkageName: "\01?ui@s@@2IB", scope: ![[SCOPE]], -// CHECK-SAME: variable: i32* @"\01?ui@s@@2IB" +// CHECK: [[UI]] = !DIGlobalVariableExpression(var: [[UIV:.*]]) +// CHECK: [[UIV]] = distinct !DIGlobalVariable(name: "ui", linkageName: "\01?ui@s@@2IB", scope: ![[SCOPE:[0-9]+]], +// CHECK: ![[SCOPE]] = distinct !DICompileUnit( diff --git a/test/CodeGenCXX/inline-hint.cpp b/test/CodeGenCXX/inline-hint.cpp index 9c14032f9f69..c4de751ba76e 100644 --- a/test/CodeGenCXX/inline-hint.cpp +++ b/test/CodeGenCXX/inline-hint.cpp @@ -1,6 +1,6 @@ -// RUN: %clang_cc1 %s -std=c++11 -triple=x86_64-linux -finline-functions -emit-llvm -disable-llvm-optzns -o - | FileCheck %s --check-prefix=CHECK --check-prefix=SUITABLE -// RUN: %clang_cc1 %s -std=c++11 -triple=x86_64-linux -finline-hint-functions -emit-llvm -disable-llvm-optzns -o - | FileCheck %s --check-prefix=CHECK --check-prefix=HINTED -// RUN: %clang_cc1 %s -std=c++11 -triple=x86_64-linux -fno-inline -emit-llvm -disable-llvm-optzns -o - | FileCheck %s --check-prefix=CHECK --check-prefix=NOINLINE +// RUN: %clang_cc1 %s -std=c++11 -triple=x86_64-linux -O2 -finline-functions -emit-llvm -disable-llvm-passes -o - | FileCheck %s --check-prefix=CHECK --check-prefix=SUITABLE +// RUN: %clang_cc1 %s -std=c++11 -triple=x86_64-linux -O2 -finline-hint-functions -emit-llvm -disable-llvm-passes -o - | FileCheck %s --check-prefix=CHECK --check-prefix=HINTED +// RUN: %clang_cc1 %s -std=c++11 -triple=x86_64-linux -O2 -fno-inline -emit-llvm -disable-llvm-passes -o - | FileCheck %s --check-prefix=CHECK --check-prefix=NOINLINE // Force non-trivial implicit constructors/destructors/operators for B by having explicit ones for A struct A { diff --git a/test/CodeGenCXX/invariant.group-for-vptrs.cpp b/test/CodeGenCXX/invariant.group-for-vptrs.cpp index ca737ee23fb4..5c763538088b 100644 --- a/test/CodeGenCXX/invariant.group-for-vptrs.cpp +++ b/test/CodeGenCXX/invariant.group-for-vptrs.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple=x86_64-pc-linux-gnu -emit-llvm %s -fstrict-vtable-pointers -O1 -o - -disable-llvm-optzns | FileCheck %s +// RUN: %clang_cc1 -triple=x86_64-pc-linux-gnu -emit-llvm %s -fstrict-vtable-pointers -O1 -o - -disable-llvm-passes | FileCheck %s struct A { virtual void foo(); @@ -23,7 +23,7 @@ void testExternallyVisible() { // CHECK: load {{.*}} !invariant.group ![[A_MD]] a2->foo(); } -// CHECK-LABEL: } +// CHECK-LABEL: {{^}}} namespace { @@ -52,7 +52,7 @@ void testInternallyVisible(bool p) { // Checking A::A() // CHECK-LABEL: define linkonce_odr void @_ZN1AC2Ev( // CHECK: store {{.*}}, !invariant.group ![[A_MD]] -// CHECK-LABEL: } +// CHECK-LABEL: {{^}}} // Checking D::D() // CHECK-LABEL: define linkonce_odr void @_ZN1DC2Ev( diff --git a/test/CodeGenCXX/key-function-vtable.cpp b/test/CodeGenCXX/key-function-vtable.cpp index f6aa16e51a97..028017c176ad 100644 --- a/test/CodeGenCXX/key-function-vtable.cpp +++ b/test/CodeGenCXX/key-function-vtable.cpp @@ -44,8 +44,8 @@ inline void X1::f() { } void use_X1() { X1 x1; } // CHECK-DAG: @_ZTV2X1 = linkonce_odr unnamed_addr constant -// CHECK-DAG: @_ZTV5testa = unnamed_addr constant [3 x i8*] [i8* null -// CHECK-DAG: @_ZTV5testc = linkonce_odr unnamed_addr constant [3 x i8*] [i8* null -// CHECK-DAG: @_ZTV5testb = linkonce_odr unnamed_addr constant [3 x i8*] [i8* null -// CHECK-DAG: @_ZTV5teste = linkonce_odr unnamed_addr constant [3 x i8*] [i8* null -// CHECK-DAG: @_ZTVN12_GLOBAL__N_15testgE = internal unnamed_addr constant [3 x i8*] [i8* null +// CHECK-DAG: @_ZTV5testa = unnamed_addr constant { [3 x i8*] } { [3 x i8*] [i8* null +// CHECK-DAG: @_ZTV5testc = linkonce_odr unnamed_addr constant { [3 x i8*] } { [3 x i8*] [i8* null +// CHECK-DAG: @_ZTV5testb = linkonce_odr unnamed_addr constant { [3 x i8*] } { [3 x i8*] [i8* null +// CHECK-DAG: @_ZTV5teste = linkonce_odr unnamed_addr constant { [3 x i8*] } { [3 x i8*] [i8* null +// CHECK-DAG: @_ZTVN12_GLOBAL__N_15testgE = internal unnamed_addr constant { [3 x i8*] } { [3 x i8*] [i8* null diff --git a/test/CodeGenCXX/lambda-expressions.cpp b/test/CodeGenCXX/lambda-expressions.cpp index f59d360314e4..2c625daaf831 100644 --- a/test/CodeGenCXX/lambda-expressions.cpp +++ b/test/CodeGenCXX/lambda-expressions.cpp @@ -54,12 +54,14 @@ int c(int x) { return [&x]{return x;}(); } // CHECK: ret i32 struct D { D(); D(const D&); int x; }; -int d(int x) { D y[10]; [x,y] { return y[x].x; }(); } +int d(int x) { D y[10]; return [x,y] { return y[x].x; }(); } // CHECK-LABEL: define i32 @_Z1di // CHECK: call void @_ZN1DC1Ev -// CHECK: icmp ult i64 %{{.*}}, 10 +// CHECK: br label // CHECK: call void @_ZN1DC1ERKS_ +// CHECK: icmp eq i64 %{{.*}}, 10 +// CHECK: br i1 // CHECK: call i32 @"_ZZ1diENK3$_4clEv" // CHECK-LABEL: define internal i32 @"_ZZ1diENK3$_4clEv" // CHECK: load i32, i32* @@ -67,7 +69,7 @@ int d(int x) { D y[10]; [x,y] { return y[x].x; }(); } // CHECK: ret i32 struct E { E(); E(const E&); ~E(); int x; }; -int e(E a, E b, bool cond) { [a,b,cond](){ return (cond ? a : b).x; }(); } +int e(E a, E b, bool cond) { return [a,b,cond](){ return (cond ? a : b).x; }(); } // CHECK-LABEL: define i32 @_Z1e1ES_b // CHECK: call void @_ZN1EC1ERKS_ // CHECK: invoke void @_ZN1EC1ERKS_ @@ -116,6 +118,72 @@ int *PR22071_fun() { return [&] { return &y; }(); } +namespace pr28595 { + struct Temp { + Temp(); + ~Temp() noexcept(false); + }; + struct A { + A(); + A(const A &a, const Temp &temp = Temp()); + ~A(); + }; + + void after_init() noexcept; + + // CHECK-LABEL: define void @_ZN7pr285954testEv() + void test() { + // CHECK: %[[SRC:.*]] = alloca [3 x [5 x %[[A:.*]]]], align 1 + A array[3][5]; + + // Skip over the initialization loop. + // CHECK: call {{.*}}after_init + after_init(); + + // CHECK: %[[DST_0:.*]] = getelementptr {{.*}} [3 x [5 x %[[A]]]]* %[[DST:.*]], i64 0, i64 0 + // CHECK: br label + // CHECK: %[[I:.*]] = phi i64 [ 0, %{{.*}} ], [ %[[I_NEXT:.*]], {{.*}} ] + // CHECK: %[[DST_I:.*]] = getelementptr {{.*}} [5 x %[[A]]]* %[[DST_0]], i64 %[[I]] + // CHECK: %[[SRC_I:.*]] = getelementptr {{.*}} [3 x [5 x %[[A]]]]* %[[SRC]], i64 0, i64 %[[I]] + // + // CHECK: %[[DST_I_0:.*]] = getelementptr {{.*}} [5 x %[[A]]]* %[[DST_I]], i64 0, i64 0 + // CHECK: br label + // CHECK: %[[J:.*]] = phi i64 [ 0, %{{.*}} ], [ %[[J_NEXT:.*]], {{.*}} ] + // CHECK: %[[DST_I_J:.*]] = getelementptr {{.*}} %[[A]]* %[[DST_I_0]], i64 %[[J]] + // CHECK: %[[DST_0_0:.*]] = bitcast [5 x %[[A]]]* %[[DST_0]] to %[[A]]* + // CHECK: %[[SRC_I_J:.*]] = getelementptr {{.*}} [5 x %[[A]]]* %[[SRC_I]], i64 0, i64 %[[J]] + // + // CHECK: invoke void @_ZN7pr285954TempC1Ev + // CHECK: invoke void @_ZN7pr285951AC1ERKS0_RKNS_4TempE + // CHECK: invoke void @_ZN7pr285954TempD1Ev + // + // CHECK: add nuw i64 %[[J]], 1 + // CHECK: icmp eq + // CHECK: br i1 + // + // CHECK: add nuw i64 %[[I]], 1 + // CHECK: icmp eq + // CHECK: br i1 + // + // CHECK: ret void + // + // CHECK: landingpad + // CHECK: landingpad + // CHECK: br label %[[CLEANUP:.*]]{{$}} + // CHECK: landingpad + // CHECK: invoke void @_ZN7pr285954TempD1Ev + // CHECK: br label %[[CLEANUP]] + // + // CHECK: [[CLEANUP]]: + // CHECK: icmp eq %[[A]]* %[[DST_0_0]], %[[DST_I_J]] + // CHECK: %[[T0:.*]] = phi %[[A]]* + // CHECK: %[[T1:.*]] = getelementptr inbounds %[[A]], %[[A]]* %[[T0]], i64 -1 + // CHECK: call void @_ZN7pr285951AD1Ev(%[[A]]* %[[T1]]) + // CHECK: icmp eq %[[A]]* %[[T1]], %[[DST_0_0]] + (void) [array]{}; + } +} + // CHECK-LABEL: define internal void @"_ZZ1e1ES_bEN3$_5D2Ev" // CHECK-LABEL: define internal i32 @"_ZZ1fvEN3$_68__invokeEii" @@ -126,9 +194,9 @@ int *PR22071_fun() { // CHECK-NEXT: call i32 @"_ZZ1fvENK3$_6clEii" // CHECK-NEXT: ret i32 -// CHECK-LABEL: define internal void @"_ZZ1hvEN4$_108__invokeEv"(%struct.A* noalias sret %agg.result) {{.*}} { +// CHECK-LABEL: define internal void @"_ZZ1hvEN4$_118__invokeEv"(%struct.A* noalias sret %agg.result) {{.*}} { // CHECK-NOT: = -// CHECK: call void @"_ZZ1hvENK4$_10clEv"(%struct.A* sret %agg.result, +// CHECK: call void @"_ZZ1hvENK4$_11clEv"(%struct.A* sret %agg.result, // CHECK-NEXT: ret void struct A { ~A(); }; void h() { diff --git a/test/CodeGenCXX/linkage.cpp b/test/CodeGenCXX/linkage.cpp index 60e53c6444e2..69b426269ccd 100644 --- a/test/CodeGenCXX/linkage.cpp +++ b/test/CodeGenCXX/linkage.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -std=c++11 -O1 -disable-llvm-optzns %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -std=c++11 -O1 -disable-llvm-passes %s -o - | FileCheck %s namespace test1 { // CHECK-DAG: define linkonce_odr void @_ZN5test11fIZNS_1gEvE1SEEvT_( diff --git a/test/CodeGenCXX/main-norecurse.cpp b/test/CodeGenCXX/main-norecurse.cpp index 0f3640260962..a98677ce6f59 100644 --- a/test/CodeGenCXX/main-norecurse.cpp +++ b/test/CodeGenCXX/main-norecurse.cpp @@ -5,4 +5,4 @@ int main(int argc, char **argv) { return 1; } -// CHECK: attributes #0 = { norecurse{{.*}} } +// CHECK: attributes #0 = { noinline norecurse{{.*}} } diff --git a/test/CodeGenCXX/mangle-abi-tag.cpp b/test/CodeGenCXX/mangle-abi-tag.cpp index 385a16f26a51..a653ff42228a 100644 --- a/test/CodeGenCXX/mangle-abi-tag.cpp +++ b/test/CodeGenCXX/mangle-abi-tag.cpp @@ -203,3 +203,32 @@ void f18_test() { } // A18::operator A[abi:A][abi:B]() but GCC adds the same tags twice! // CHECK-DAG: define linkonce_odr {{.+}} @_ZN3A18cv1AB1AB1BEv( + +namespace N19 { + class A {}; + class __attribute__((abi_tag("B"))) B {}; + class D {}; + class F {}; + + template<typename T, B F(T, D)> + class C {}; + + B foo(A, D); +} +void f19_test(N19::C<N19::A, &N19::foo>, N19::F, N19::D) { +} +// f19_test(N19::C<N19::A, &N19::foo[abi:B]>, N19::F, N19::D) +// CHECK-DAG: define void @_Z8f19_testN3N191CINS_1AEXadL_ZNS_3fooB1BES1_NS_1DEEEEENS_1FES2_( + +namespace pr30440 { + +template<class F> void g(F); +template<class ...A> auto h(A ...a)->decltype (g (0, g < a > (a) ...)) { +} +// CHECK-DAG: define {{.*}} @_ZN7pr304401hIJEEEDTcl1gLi0Espcl1gIL_ZZNS_1hEDpT_E1aEEfp_EEES2_( + +void pr30440_test () { + h(); +} + +} diff --git a/test/CodeGenCXX/mangle-exception-spec.cpp b/test/CodeGenCXX/mangle-exception-spec.cpp new file mode 100644 index 000000000000..15f7a8b6cb50 --- /dev/null +++ b/test/CodeGenCXX/mangle-exception-spec.cpp @@ -0,0 +1,49 @@ +// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple=x86_64-apple-darwin9 -Wno-dynamic-exception-spec | FileCheck %s --check-prefix CHECK --check-prefix CHECK-CXX11 +// RUN: %clang_cc1 -std=c++1z -emit-llvm %s -o - -triple=x86_64-apple-darwin9 -Wno-dynamic-exception-spec | FileCheck %s --check-prefix CHECK --check-prefix CHECK-CXX17 + +// CHECK: define {{.*}} @_Z1aPFivE( +void a(int() throw(int, float)) {} +// CHECK-CXX11: define {{.*}} @_Z1bPFivE( +// CHECK-CXX17: define {{.*}} @_Z1bPDoFivE( +void b(int() noexcept) {} +// CHECK-CXX11: define {{.*}} @_Z1cPFivE( +// CHECK-CXX17: define {{.*}} @_Z1cPDoFivE( +void c(int() throw()) {} +// CHECK: define {{.*}} @_Z1dPFivE( +void d(int() noexcept(false)) {} +// CHECK-CXX11: define {{.*}} @_Z1ePFivE( +// CHECK-CXX17: define {{.*}} @_Z1ePDoFivE( +void e(int() noexcept(true)) {} + +template<bool B> void f(int() noexcept(B)) {} +// CHECK: define {{.*}} @_Z1fILb0EEvPDOT_EFivE( +template void f<false>(int()); +// CHECK: define {{.*}} @_Z1fILb1EEvPDOT_EFivE( +template void f<true>(int() noexcept); + +template<typename...T> void g(int() throw(T...)) {} +// CHECK: define {{.*}} @_Z1gIJEEvPDwDpT_EFivE( +template void g<>(int() noexcept); +// CHECK: define {{.*}} @_Z1gIJfEEvPDwDpT_EFivE( +template void g<float>(int()); + +// We consider the exception specifications in parameter and return type here +// to be different. +template<typename...T> auto h(int() throw(int, T...)) -> int (*)() throw(T..., int) { return nullptr; } +// CHECK: define {{.*}} @_Z1hIJEEPDwDpT_iEFivEPDwiS1_EFivE( +template auto h<>(int()) -> int (*)(); +// CHECK: define {{.*}} @_Z1hIJfEEPDwDpT_iEFivEPDwiS1_EFivE( +template auto h<float>(int()) -> int (*)(); + +// FIXME: The C++11 manglings here are wrong; they should be the same as the +// C++17 manglings. +// The mangler mishandles substitutions for instantiation-dependent types that +// differ only in type sugar that is not relevant for mangling. (In this case, +// the types differ in presence/absence of ParenType nodes under the pointer.) +template<typename...T> auto i(int() throw(int, T...)) -> int (*)() throw(int, T...) { return nullptr; } +// CHECK-CXX11: define {{.*}} @_Z1iIJEEPDwiDpT_EFivEPS2_( +// CHECK-CXX17: define {{.*}} @_Z1iIJEEPDwiDpT_EFivES3_( +template auto i<>(int()) -> int (*)(); +// CHECK-CXX11: define {{.*}} @_Z1iIJfEEPDwiDpT_EFivEPS2_( +// CHECK-CXX17: define {{.*}} @_Z1iIJfEEPDwiDpT_EFivES3_( +template auto i<float>(int()) -> int (*)(); diff --git a/test/CodeGenCXX/mangle-lambdas.cpp b/test/CodeGenCXX/mangle-lambdas.cpp index 051cfdc3a221..15987ebe46bd 100644 --- a/test/CodeGenCXX/mangle-lambdas.cpp +++ b/test/CodeGenCXX/mangle-lambdas.cpp @@ -173,6 +173,16 @@ namespace PR12123 { // CHECK-LABEL: define linkonce_odr dereferenceable({{[0-9]+}}) %"struct.PR12123::A"* @_ZZN7PR121231B1fERKSt9type_infoEd_NKUlvE_clEv +// CHECK-LABEL: define {{.*}} @_Z{{[0-9]*}}testVarargsLambdaNumberingv( +inline int testVarargsLambdaNumbering() { + // CHECK: testVarargsLambdaNumberingvE{{.*}}UlzE_ + auto a = [](...) { static int n; return ++n; }; + // CHECK: testVarargsLambdaNumberingvE{{.*}}UlvE_ + auto b = []() { static int n; return ++n; }; + return a() + b(); +} +int k = testVarargsLambdaNumbering(); + // Check linkage of the various lambdas. // CHECK-LABEL: define linkonce_odr i32 @_ZZ11inline_funciENKUlvE_clEv // CHECK: ret i32 1 diff --git a/test/CodeGenCXX/mangle-ms-cxx11.cpp b/test/CodeGenCXX/mangle-ms-cxx11.cpp index 8e2577b03e26..819b0d9c9d0d 100644 --- a/test/CodeGenCXX/mangle-ms-cxx11.cpp +++ b/test/CodeGenCXX/mangle-ms-cxx11.cpp @@ -318,3 +318,32 @@ void unaligned_foo8_S::unaligned_foo8() volatile __unaligned {} // CHECK-DAG: @"\01?unaligned_foo8@unaligned_foo8_S@@QFCEXXZ" +namespace PR31197 { +struct A { + // CHECK-DAG: define linkonce_odr x86_thiscallcc i32* @"\01??R<lambda_1>@x@A@PR31197@@QBE@XZ"( + int *x = []() { + static int white; + // CHECK-DAG: @"\01?white@?1???R<lambda_1>@x@A@PR31197@@QBE@XZ@4HA" + return &white; + }(); + // CHECK-DAG: define linkonce_odr x86_thiscallcc i32* @"\01??R<lambda_1>@y@A@PR31197@@QBE@XZ"( + int *y = []() { + static int black; + // CHECK-DAG: @"\01?black@?1???R<lambda_1>@y@A@PR31197@@QBE@XZ@4HA" + return &black; + }(); + using FPtrTy = void(void); + static void default_args(FPtrTy x = [] {}, FPtrTy y = [] {}, int z = [] { return 1; }() + [] { return 2; }()) {} + // CHECK-DAG: @"\01??R<lambda_1_1>@?0??default_args@A@PR31197@@SAXP6AXXZ0H@Z@QBE@XZ"( + // CHECK-DAG: @"\01??R<lambda_1_2>@?0??default_args@A@PR31197@@SAXP6AXXZ0H@Z@QBE@XZ"( + // CHECK-DAG: @"\01??R<lambda_2_1>@?0??default_args@A@PR31197@@SAXP6AXXZ0H@Z@QBE@XZ"( + // CHECK-DAG: @"\01??R<lambda_3_1>@?0??default_args@A@PR31197@@SAXP6AXXZ0H@Z@QBE@XZ"( +}; +A a; + +int call_it = (A::default_args(), 1); +} + +enum { enumerator }; +void f(decltype(enumerator)) {} +// CHECK-DAG: define void @"\01?f@@YAXW4<unnamed-enum-enumerator>@@@Z"( diff --git a/test/CodeGenCXX/mangle-unnamed.cpp b/test/CodeGenCXX/mangle-unnamed.cpp index a62bdd5393c4..43b7bd79537d 100644 --- a/test/CodeGenCXX/mangle-unnamed.cpp +++ b/test/CodeGenCXX/mangle-unnamed.cpp @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin10 | FileCheck %s +// RUN: %clang_cc1 -std=c++98 -emit-llvm %s -o - -triple=x86_64-apple-darwin10 | FileCheck %s +// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple=x86_64-apple-darwin10 | FileCheck %s struct S { virtual ~S() { } diff --git a/test/CodeGenCXX/mangle.cpp b/test/CodeGenCXX/mangle.cpp index 5d757102ed25..3a94071294d3 100644 --- a/test/CodeGenCXX/mangle.cpp +++ b/test/CodeGenCXX/mangle.cpp @@ -1111,3 +1111,17 @@ void fn(T, __underlying_type(T)) {} template void fn<E>(E, __underlying_type(E)); // CHECK-LABEL: @_ZN6test552fnINS_1EEEEvT_U3eutS2_ } + +namespace test56 { + struct A { A *operator->(); int n; } a; + template<int N> void f(decltype(a->n + N)) {} + // CHECK-LABEL: @_ZN6test561fILi0EEEvDTplptL_ZNS_1aEE1nT_E + template void f<0>(int); +} + +namespace test57 { + struct X { template <int N> int f(); } x; + template<int N> void f(decltype(x.f<0>() + N)) {} + // CHECK-LABEL: @_ZN6test571fILi0EEEvDTplcldtL_ZNS_1xEE1fIXLi0EEEET_E + template void f<0>(int); +} diff --git a/test/CodeGenCXX/microsoft-abi-array-cookies.cpp b/test/CodeGenCXX/microsoft-abi-array-cookies.cpp index 9ef1879ce5f2..146a6c8eda06 100644 --- a/test/CodeGenCXX/microsoft-abi-array-cookies.cpp +++ b/test/CodeGenCXX/microsoft-abi-array-cookies.cpp @@ -68,4 +68,4 @@ struct S { void delete_s(S *s) { delete[] s; } } -// CHECK: attributes [[NUW]] = { nounwind{{.*}} } +// CHECK: attributes [[NUW]] = { noinline nounwind{{.*}} } diff --git a/test/CodeGenCXX/microsoft-abi-constexpr-vs-inheritance.cpp b/test/CodeGenCXX/microsoft-abi-constexpr-vs-inheritance.cpp index 319f39c3ff48..6972dacd774f 100644 --- a/test/CodeGenCXX/microsoft-abi-constexpr-vs-inheritance.cpp +++ b/test/CodeGenCXX/microsoft-abi-constexpr-vs-inheritance.cpp @@ -7,7 +7,7 @@ struct A { }; A a(42); -// CHECK: @"\01?a@@3UA@@A" = global { [1 x i8*]*, i32 } { [1 x i8*]* @"\01??_7A@@6B@", i32 42 }, align 4 +// CHECK: @"\01?a@@3UA@@A" = global { { [1 x i8*] }*, i32 } { { [1 x i8*] }* @"\01??_7A@@6B@", i32 42 }, align 4 struct B { constexpr B(int y) : y(y) {} @@ -20,4 +20,4 @@ struct C : A, B { }; C c; -// CHECK: @"\01?c@@3UC@@A" = global { [1 x i8*]*, i32, [1 x i8*]*, i32 } { [1 x i8*]* @"\01??_7C@@6BA@@@", i32 777, [1 x i8*]* @"\01??_7C@@6BB@@@", i32 13 } +// CHECK: @"\01?c@@3UC@@A" = global { { [1 x i8*] }*, i32, { [1 x i8*] }*, i32 } { { [1 x i8*] }* @"\01??_7C@@6BA@@@", i32 777, { [1 x i8*] }* @"\01??_7C@@6BB@@@", i32 13 } diff --git a/test/CodeGenCXX/microsoft-abi-eh-catch.cpp b/test/CodeGenCXX/microsoft-abi-eh-catch.cpp index ac1321efeae2..6e18b92e0f41 100644 --- a/test/CodeGenCXX/microsoft-abi-eh-catch.cpp +++ b/test/CodeGenCXX/microsoft-abi-eh-catch.cpp @@ -1,6 +1,6 @@ // RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple=x86_64-pc-windows-msvc \ // RUN: -mconstructor-aliases -fexceptions -fcxx-exceptions \ -// RUN: -O1 -disable-llvm-optzns \ +// RUN: -O1 -disable-llvm-passes \ // RUN: | FileCheck -check-prefix WIN64 %s extern "C" void might_throw(); diff --git a/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp b/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp index 004dc45652e4..79ac1e12173b 100644 --- a/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp +++ b/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fexceptions -fcxx-exceptions -fno-rtti | FileCheck -check-prefix WIN32 -check-prefix WIN32-O0 %s -// RUN: %clang_cc1 -std=c++11 -emit-llvm -O3 -disable-llvm-optzns %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fexceptions -fcxx-exceptions -fno-rtti | FileCheck -check-prefix WIN32 -check-prefix WIN32-O3 -check-prefix WIN32-LIFETIME %s +// RUN: %clang_cc1 -std=c++11 -emit-llvm -O3 -disable-llvm-passes %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fexceptions -fcxx-exceptions -fno-rtti | FileCheck -check-prefix WIN32 -check-prefix WIN32-O3 -check-prefix WIN32-LIFETIME %s struct A { A(); @@ -278,3 +278,38 @@ void f() { // WIN32-LIFETIME: %[[bc2:.*]] = bitcast %"struct.lifetime_marker::C"* %[[c]] to i8* // WIN32-LIFETIME: call void @llvm.lifetime.end(i64 1, i8* %[[bc2]]) } + +struct class_2 { + class_2(); + virtual ~class_2(); +}; +struct class_1 : virtual class_2 { + class_1(){throw "Unhandled exception";} + virtual ~class_1() {} +}; +struct class_0 : class_1 { + class_0() ; + virtual ~class_0() {} +}; + +class_0::class_0() { + // WIN32: define x86_thiscallcc %struct.class_0* @"\01??0class_0@@QAE@XZ"(%struct.class_0* returned %this, i32 %is_most_derived) + // WIN32: store i32 %is_most_derived, i32* %[[IS_MOST_DERIVED_VAR:.*]], align 4 + // WIN32: %[[IS_MOST_DERIVED_VAL:.*]] = load i32, i32* %[[IS_MOST_DERIVED_VAR]] + // WIN32: %[[SHOULD_CALL_VBASE_CTORS:.*]] = icmp ne i32 %[[IS_MOST_DERIVED_VAL]], 0 + // WIN32: br i1 %[[SHOULD_CALL_VBASE_CTORS]], label %[[INIT_VBASES:.*]], label %[[SKIP_VBASES:.*]] + // WIN32: [[INIT_VBASES]] + // WIN32: br label %[[SKIP_VBASES]] + // WIN32: [[SKIP_VBASES]] +// ehcleanup: + // WIN32: %[[CLEANUPPAD:.*]] = cleanuppad within none [] + // WIN32-NEXT: bitcast %{{.*}}* %{{.*}} to i8* + // WIN32-NEXT: getelementptr inbounds i8, i8* %{{.*}}, i{{.*}} {{.}} + // WIN32-NEXT: bitcast i8* %{{.*}} to %{{.*}}* + // WIN32-NEXT: %[[SHOULD_CALL_VBASE_DTOR:.*]] = icmp ne i32 %[[IS_MOST_DERIVED_VAL]], 0 + // WIN32-NEXT: br i1 %[[SHOULD_CALL_VBASE_DTOR]], label %[[DTOR_VBASE:.*]], label %[[SKIP_VBASE:.*]] + // WIN32: [[DTOR_VBASE]] + // WIN32-NEXT: call x86_thiscallcc void @"\01??1class_2@@UAE@XZ" + // WIN32: br label %[[SKIP_VBASE]] + // WIN32: [[SKIP_VBASE]] +} diff --git a/test/CodeGenCXX/microsoft-abi-extern-template.cpp b/test/CodeGenCXX/microsoft-abi-extern-template.cpp index de46d5b5c37c..c69b4f5b8d86 100644 --- a/test/CodeGenCXX/microsoft-abi-extern-template.cpp +++ b/test/CodeGenCXX/microsoft-abi-extern-template.cpp @@ -1,11 +1,11 @@ -// RUN: %clang_cc1 -fno-rtti-data -O1 -disable-llvm-optzns %s -emit-llvm -o - -triple x86_64-windows-msvc | FileCheck %s +// RUN: %clang_cc1 -fno-rtti-data -O1 -disable-llvm-passes %s -emit-llvm -o - -triple x86_64-windows-msvc | FileCheck %s // Even though Foo<int> has an extern template declaration, we have to emit our // own copy the vftable when emitting the available externally constructor. -// CHECK: @"\01??_7?$Foo@H@@6B@" = linkonce_odr unnamed_addr constant [1 x i8*] [ +// CHECK: @"\01??_7?$Foo@H@@6B@" = linkonce_odr unnamed_addr constant { [1 x i8*] } { [1 x i8*] [ // CHECK-SAME: i8* bitcast (i8* (%struct.Foo*, i32)* @"\01??_G?$Foo@H@@UEAAPEAXI@Z" to i8*) -// CHECK-SAME: ], comdat +// CHECK-SAME: ] }, comdat // CHECK-LABEL: define %struct.Foo* @"\01?f@@YAPEAU?$Foo@H@@XZ"() // CHECK: call %struct.Foo* @"\01??0?$Foo@H@@QEAA@XZ"(%struct.Foo* %{{.*}}) diff --git a/test/CodeGenCXX/microsoft-abi-multiple-nonvirtual-inheritance.cpp b/test/CodeGenCXX/microsoft-abi-multiple-nonvirtual-inheritance.cpp index 34cb85ec28d1..f9db2680e336 100644 --- a/test/CodeGenCXX/microsoft-abi-multiple-nonvirtual-inheritance.cpp +++ b/test/CodeGenCXX/microsoft-abi-multiple-nonvirtual-inheritance.cpp @@ -150,35 +150,35 @@ void emit_ctors() { Left l; // CHECK: define {{.*}} @"\01??0Left@@QAE@XZ" // CHECK-NOT: getelementptr - // CHECK: store i32 (...)** bitcast ([1 x i8*]* @"\01??_7Left@@6B@" to i32 (...)**) + // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @"\01??_7Left@@6B@" to i32 (...)**) // CHECK: ret Right r; // CHECK: define {{.*}} @"\01??0Right@@QAE@XZ" // CHECK-NOT: getelementptr - // CHECK: store i32 (...)** bitcast ([1 x i8*]* @"\01??_7Right@@6B@" to i32 (...)**) + // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @"\01??_7Right@@6B@" to i32 (...)**) // CHECK: ret ChildOverride co; // CHECK: define {{.*}} @"\01??0ChildOverride@@QAE@XZ" // CHECK: %[[THIS:.*]] = load %struct.ChildOverride*, %struct.ChildOverride** // CHECK: %[[VFPTR:.*]] = bitcast %struct.ChildOverride* %[[THIS]] to i32 (...)*** - // CHECK: store i32 (...)** bitcast ([1 x i8*]* @"\01??_7ChildOverride@@6BLeft@@@" to i32 (...)**), i32 (...)*** %[[VFPTR]] + // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @"\01??_7ChildOverride@@6BLeft@@@" to i32 (...)**), i32 (...)*** %[[VFPTR]] // CHECK: %[[THIS_i8:.*]] = bitcast %struct.ChildOverride* %[[THIS]] to i8* // CHECK: %[[VFPTR_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_i8]], i32 4 // CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VFPTR_i8]] to i32 (...)*** - // CHECK: store i32 (...)** bitcast ([1 x i8*]* @"\01??_7ChildOverride@@6BRight@@@" to i32 (...)**), i32 (...)*** %[[VFPTR]] + // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @"\01??_7ChildOverride@@6BRight@@@" to i32 (...)**), i32 (...)*** %[[VFPTR]] // CHECK: ret GrandchildOverride gc; // CHECK: define {{.*}} @"\01??0GrandchildOverride@@QAE@XZ" // CHECK: %[[THIS:.*]] = load %struct.GrandchildOverride*, %struct.GrandchildOverride** // CHECK: %[[VFPTR:.*]] = bitcast %struct.GrandchildOverride* %[[THIS]] to i32 (...)*** - // CHECK: store i32 (...)** bitcast ([1 x i8*]* @"\01??_7GrandchildOverride@@6BLeft@@@" to i32 (...)**), i32 (...)*** %[[VFPTR]] + // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @"\01??_7GrandchildOverride@@6BLeft@@@" to i32 (...)**), i32 (...)*** %[[VFPTR]] // CHECK: %[[THIS_i8:.*]] = bitcast %struct.GrandchildOverride* %[[THIS]] to i8* // CHECK: %[[VFPTR_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_i8]], i32 4 // CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VFPTR_i8]] to i32 (...)*** - // CHECK: store i32 (...)** bitcast ([1 x i8*]* @"\01??_7GrandchildOverride@@6BRight@@@" to i32 (...)**), i32 (...)*** %[[VFPTR]] + // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @"\01??_7GrandchildOverride@@6BRight@@@" to i32 (...)**), i32 (...)*** %[[VFPTR]] // CHECK: ret } diff --git a/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp b/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp index f7dc52406740..7eea41c8712e 100644 --- a/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp +++ b/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp @@ -1,6 +1,7 @@ -// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-linux | FileCheck -check-prefix LINUX %s -// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fno-rtti | FileCheck -check-prefix WIN32 %s -// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-pc-win32 -mconstructor-aliases -fno-rtti | FileCheck -check-prefix WIN64 %s +// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple=i386-pc-linux | FileCheck -check-prefix LINUX %s +// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fno-rtti | FileCheck -check-prefix WIN32 %s +// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple=thumb-pc-win32 -mconstructor-aliases -fno-rtti | FileCheck -check-prefix WOA %s +// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple=x86_64-pc-win32 -mconstructor-aliases -fno-rtti | FileCheck -check-prefix WIN64 %s struct Empty {}; @@ -92,6 +93,9 @@ SmallWithCtor small_with_ctor_return() { return SmallWithCtor(); } // LINUX-LABEL: define void @_Z22small_with_ctor_returnv(%struct.SmallWithCtor* noalias sret %agg.result) // WIN32: define void @"\01?small_with_ctor_return@@YA?AUSmallWithCtor@@XZ"(%struct.SmallWithCtor* noalias sret %agg.result) // WIN64: define void @"\01?small_with_ctor_return@@YA?AUSmallWithCtor@@XZ"(%struct.SmallWithCtor* noalias sret %agg.result) +// FIXME: The 'sret' mark here doesn't seem to be enough to convince LLVM to +// preserve the hidden sret pointer in R0 across the function. +// WOA: define arm_aapcs_vfpcc void @"\01?small_with_ctor_return@@YA?AUSmallWithCtor@@XZ"(%struct.SmallWithCtor* noalias sret %agg.result) SmallWithVftable small_with_vftable_return() { return SmallWithVftable(); } // LINUX-LABEL: define void @_Z25small_with_vftable_returnv(%struct.SmallWithVftable* noalias sret %agg.result) @@ -102,6 +106,7 @@ MediumWithCopyCtor medium_with_copy_ctor_return() { return MediumWithCopyCtor(); // LINUX-LABEL: define void @_Z28medium_with_copy_ctor_returnv(%struct.MediumWithCopyCtor* noalias sret %agg.result) // WIN32: define void @"\01?medium_with_copy_ctor_return@@YA?AUMediumWithCopyCtor@@XZ"(%struct.MediumWithCopyCtor* noalias sret %agg.result) // WIN64: define void @"\01?medium_with_copy_ctor_return@@YA?AUMediumWithCopyCtor@@XZ"(%struct.MediumWithCopyCtor* noalias sret %agg.result) +// WOA: define arm_aapcs_vfpcc void @"\01?medium_with_copy_ctor_return@@YA?AUMediumWithCopyCtor@@XZ"(%struct.MediumWithCopyCtor* noalias sret %agg.result) // Returning a large struct that doesn't fit into a register. Big big_return() { return Big(); } @@ -114,22 +119,26 @@ void small_arg(Small s) {} // LINUX-LABEL: define void @_Z9small_arg5Small(i32 %s.0) // WIN32: define void @"\01?small_arg@@YAXUSmall@@@Z"(i32 %s.0) // WIN64: define void @"\01?small_arg@@YAXUSmall@@@Z"(i32 %s.coerce) +// WOA: define arm_aapcs_vfpcc void @"\01?small_arg@@YAXUSmall@@@Z"([1 x i32] %s.coerce) void medium_arg(Medium s) {} // LINUX-LABEL: define void @_Z10medium_arg6Medium(i32 %s.0, i32 %s.1) // WIN32: define void @"\01?medium_arg@@YAXUMedium@@@Z"(i32 %s.0, i32 %s.1) // WIN64: define void @"\01?medium_arg@@YAXUMedium@@@Z"(i64 %s.coerce) +// WOA: define arm_aapcs_vfpcc void @"\01?medium_arg@@YAXUMedium@@@Z"([2 x i32] %s.coerce) void small_arg_with_ctor(SmallWithCtor s) {} // LINUX-LABEL: define void @_Z19small_arg_with_ctor13SmallWithCtor(%struct.SmallWithCtor* byval align 4 %s) // WIN32: define void @"\01?small_arg_with_ctor@@YAXUSmallWithCtor@@@Z"(i32 %s.0) // WIN64: define void @"\01?small_arg_with_ctor@@YAXUSmallWithCtor@@@Z"(i32 %s.coerce) +// WOA: define arm_aapcs_vfpcc void @"\01?small_arg_with_ctor@@YAXUSmallWithCtor@@@Z"([1 x i32] %s.coerce) // FIXME: We could coerce to a series of i32s here if we wanted to. void multibyte_arg(Multibyte s) {} // LINUX-LABEL: define void @_Z13multibyte_arg9Multibyte(%struct.Multibyte* byval align 4 %s) // WIN32: define void @"\01?multibyte_arg@@YAXUMultibyte@@@Z"(%struct.Multibyte* byval align 4 %s) // WIN64: define void @"\01?multibyte_arg@@YAXUMultibyte@@@Z"(i32 %s.coerce) +// WOA: define arm_aapcs_vfpcc void @"\01?multibyte_arg@@YAXUMultibyte@@@Z"([1 x i32] %s.coerce) void packed_arg(Packed s) {} // LINUX-LABEL: define void @_Z10packed_arg6Packed(%struct.Packed* byval align 4 %s) @@ -145,6 +154,11 @@ void small_arg_with_dtor(SmallWithDtor s) {} // WIN64: call void @"\01??1SmallWithDtor@@QEAA@XZ" // WIN64: } +// FIXME: MSVC incompatible! +// WOA: define arm_aapcs_vfpcc void @"\01?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(%struct.SmallWithDtor* %s) {{.*}} { +// WOA: call arm_aapcs_vfpcc void @"\01??1SmallWithDtor@@QAA@XZ"(%struct.SmallWithDtor* %s) +// WOA: } + void call_small_arg_with_dtor() { small_arg_with_dtor(SmallWithDtor()); } @@ -211,6 +225,7 @@ void medium_arg_with_copy_ctor(MediumWithCopyCtor s) {} // LINUX-LABEL: define void @_Z25medium_arg_with_copy_ctor18MediumWithCopyCtor(%struct.MediumWithCopyCtor* %s) // WIN32: define void @"\01?medium_arg_with_copy_ctor@@YAXUMediumWithCopyCtor@@@Z"(<{ %struct.MediumWithCopyCtor }>* inalloca) // WIN64: define void @"\01?medium_arg_with_copy_ctor@@YAXUMediumWithCopyCtor@@@Z"(%struct.MediumWithCopyCtor* %s) +// WOA: define arm_aapcs_vfpcc void @"\01?medium_arg_with_copy_ctor@@YAXUMediumWithCopyCtor@@@Z"(%struct.MediumWithCopyCtor* %s) void big_arg(Big s) {} // LINUX-LABEL: define void @_Z7big_arg3Big(%struct.Big* byval align 4 %s) @@ -386,3 +401,30 @@ void fn2(FnPtr1 a, SmallWithDtor b) { fn1(a, b); }; // WIN32: %[[addr:[^ ]*]] = bitcast {}** %[[gep2]] to void [[dst_ty]]* // WIN32: store void [[dst_ty]] %[[a2]], void [[dst_ty]]* %[[addr]], align 4 // WIN32: call void @"\01?fn1@@YAXP6AXUForwardDeclare1@@@ZUSmallWithDtor@@@Z"([[argmem_ty]]* inalloca %[[argmem]]) + +namespace pr30293 { +// Virtual methods living in a secondary vtable take i8* as their 'this' +// parameter because the 'this' parameter on entry points to the secondary +// vptr. We used to have a bug where we didn't apply this rule consistently, +// and it would cause assertion failures when used with inalloca. +struct A { + virtual void f(); +}; +struct B { + virtual void __cdecl h(SmallWithDtor); +}; +struct C final : A, B { + void g(); + void __cdecl h(SmallWithDtor); + void f(); +}; +void C::g() { return h(SmallWithDtor()); } + +// WIN32-LABEL: define x86_thiscallcc void @"\01?g@C@pr30293@@QAEXXZ"(%"struct.pr30293::C"* %this) +// WIN32: call x86_thiscallcc %struct.SmallWithDtor* @"\01??0SmallWithDtor@@QAE@XZ" +// WIN32: call void @"\01?h@C@pr30293@@UAAXUSmallWithDtor@@@Z"(<{ i8*, %struct.SmallWithDtor }>* inalloca %{{[^,)]*}}) +// WIN32: declare void @"\01?h@C@pr30293@@UAAXUSmallWithDtor@@@Z"(<{ i8*, %struct.SmallWithDtor }>* inalloca) + +// WIN64-LABEL: define void @"\01?g@C@pr30293@@QEAAXXZ"(%"struct.pr30293::C"* %this) +// WIN64: declare void @"\01?h@C@pr30293@@UEAAXUSmallWithDtor@@@Z"(i8*, i32) +} diff --git a/test/CodeGenCXX/microsoft-abi-structors-alias.cpp b/test/CodeGenCXX/microsoft-abi-structors-alias.cpp index 08df374f2fc9..4eb757af3f8b 100644 --- a/test/CodeGenCXX/microsoft-abi-structors-alias.cpp +++ b/test/CodeGenCXX/microsoft-abi-structors-alias.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 -fno-rtti -mconstructor-aliases -O1 -disable-llvm-optzns | FileCheck %s +// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 -fno-rtti -mconstructor-aliases -O1 -disable-llvm-passes | FileCheck %s namespace test1 { template <typename T> class A { diff --git a/test/CodeGenCXX/microsoft-abi-structors.cpp b/test/CodeGenCXX/microsoft-abi-structors.cpp index a576f0c3d7e3..6397eeb7313f 100644 --- a/test/CodeGenCXX/microsoft-abi-structors.cpp +++ b/test/CodeGenCXX/microsoft-abi-structors.cpp @@ -77,7 +77,7 @@ void check_vftable_offset() { C c; // The vftable pointer should point at the beginning of the vftable. // CHECK: [[THIS_PTR:%[0-9]+]] = bitcast %"struct.basic::C"* {{.*}} to i32 (...)*** -// CHECK: store i32 (...)** bitcast ([2 x i8*]* @"\01??_7C@basic@@6B@" to i32 (...)**), i32 (...)*** [[THIS_PTR]] +// CHECK: store i32 (...)** bitcast ({ [2 x i8*] }* @"\01??_7C@basic@@6B@" to i32 (...)**), i32 (...)*** [[THIS_PTR]] } void call_complete_dtor(C *obj_ptr) { @@ -196,7 +196,7 @@ struct E : virtual C { int e; }; struct F : D, E { ~F(); int f; }; F::~F() { -// CHECK-LABEL: define x86_thiscallcc void @"\01??1F@test2@@UAE@XZ"(%"struct.test2::F"*) +// CHECK-LABEL: define x86_thiscallcc void @"\01??1F@test2@@UAE@XZ"(%"struct.test2::F"*{{[^,]*}}) // Do an adjustment from C vbase subobject to F as though F was the // complete type. // CHECK: getelementptr inbounds i8, i8* %{{.*}}, i32 -20 diff --git a/test/CodeGenCXX/microsoft-abi-vftables.cpp b/test/CodeGenCXX/microsoft-abi-vftables.cpp index 0c9b58bbb4d4..968955f4ee1b 100644 --- a/test/CodeGenCXX/microsoft-abi-vftables.cpp +++ b/test/CodeGenCXX/microsoft-abi-vftables.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 %s -fno-rtti -triple=i386-pc-win32 -fms-extensions -emit-llvm -o - -O1 -disable-llvm-optzns | FileCheck %s -check-prefix=NO-RTTI -// RUN: %clang_cc1 %s -triple=i386-pc-win32 -fms-extensions -emit-llvm -o - -O1 -disable-llvm-optzns | FileCheck %s -check-prefix=RTTI +// RUN: %clang_cc1 %s -fno-rtti -triple=i386-pc-win32 -fms-extensions -emit-llvm -o - -O1 -disable-llvm-passes | FileCheck %s -check-prefix=NO-RTTI +// RUN: %clang_cc1 %s -triple=i386-pc-win32 -fms-extensions -emit-llvm -o - -O1 -disable-llvm-passes | FileCheck %s -check-prefix=RTTI // RTTI-DAG: $"\01??_7S@@6B@" = comdat largest // RTTI-DAG: $"\01??_7V@@6B@" = comdat largest @@ -8,38 +8,38 @@ struct S { virtual ~S(); } s; -// RTTI-DAG: [[VTABLE_S:@.*]] = private unnamed_addr constant [2 x i8*] [i8* bitcast ({{.*}} @"\01??_R4S@@6B@" to i8*), i8* bitcast ({{.*}} @"\01??_GS@@UAEPAXI@Z" to i8*)], comdat($"\01??_7S@@6B@") -// RTTI-DAG: @"\01??_7S@@6B@" = unnamed_addr alias i8*, getelementptr inbounds ([2 x i8*], [2 x i8*]* [[VTABLE_S]], i32 0, i32 1) +// RTTI-DAG: [[VTABLE_S:@.*]] = private unnamed_addr constant { [2 x i8*] } { [2 x i8*] [i8* bitcast ({{.*}} @"\01??_R4S@@6B@" to i8*), i8* bitcast ({{.*}} @"\01??_GS@@UAEPAXI@Z" to i8*)] }, comdat($"\01??_7S@@6B@") +// RTTI-DAG: @"\01??_7S@@6B@" = unnamed_addr alias i8*, getelementptr inbounds ({ [2 x i8*] }, { [2 x i8*] }* [[VTABLE_S]], i32 0, i32 0, i32 1) -// NO-RTTI-DAG: @"\01??_7S@@6B@" = linkonce_odr unnamed_addr constant [1 x i8*] [i8* bitcast ({{.*}} @"\01??_GS@@UAEPAXI@Z" to i8*)] +// NO-RTTI-DAG: @"\01??_7S@@6B@" = linkonce_odr unnamed_addr constant { [1 x i8*] } { [1 x i8*] [i8* bitcast ({{.*}} @"\01??_GS@@UAEPAXI@Z" to i8*)] } struct __declspec(dllimport) U { virtual ~U(); } u; -// RTTI-DAG: [[VTABLE_U:@.*]] = private unnamed_addr constant [2 x i8*] [i8* bitcast ({{.*}} @"\01??_R4U@@6B@" to i8*), i8* bitcast ({{.*}} @"\01??_GU@@UAEPAXI@Z" to i8*)] -// RTTI-DAG: @"\01??_SU@@6B@" = unnamed_addr alias i8*, getelementptr inbounds ([2 x i8*], [2 x i8*]* [[VTABLE_U]], i32 0, i32 1) +// RTTI-DAG: [[VTABLE_U:@.*]] = private unnamed_addr constant { [2 x i8*] } { [2 x i8*] [i8* bitcast ({{.*}} @"\01??_R4U@@6B@" to i8*), i8* bitcast ({{.*}} @"\01??_GU@@UAEPAXI@Z" to i8*)] } +// RTTI-DAG: @"\01??_SU@@6B@" = unnamed_addr alias i8*, getelementptr inbounds ({ [2 x i8*] }, { [2 x i8*] }* [[VTABLE_U]], i32 0, i32 0, i32 1) -// NO-RTTI-DAG: @"\01??_SU@@6B@" = linkonce_odr unnamed_addr constant [1 x i8*] [i8* bitcast ({{.*}} @"\01??_GU@@UAEPAXI@Z" to i8*)] +// NO-RTTI-DAG: @"\01??_SU@@6B@" = linkonce_odr unnamed_addr constant { [1 x i8*] } { [1 x i8*] [i8* bitcast ({{.*}} @"\01??_GU@@UAEPAXI@Z" to i8*)] } struct __declspec(dllexport) V { virtual ~V(); } v; -// RTTI-DAG: [[VTABLE_V:@.*]] = private unnamed_addr constant [2 x i8*] [i8* bitcast ({{.*}} @"\01??_R4V@@6B@" to i8*), i8* bitcast ({{.*}} @"\01??_GV@@UAEPAXI@Z" to i8*)], comdat($"\01??_7V@@6B@") -// RTTI-DAG: @"\01??_7V@@6B@" = dllexport unnamed_addr alias i8*, getelementptr inbounds ([2 x i8*], [2 x i8*]* [[VTABLE_V]], i32 0, i32 1) +// RTTI-DAG: [[VTABLE_V:@.*]] = private unnamed_addr constant { [2 x i8*] } { [2 x i8*] [i8* bitcast ({{.*}} @"\01??_R4V@@6B@" to i8*), i8* bitcast ({{.*}} @"\01??_GV@@UAEPAXI@Z" to i8*)] }, comdat($"\01??_7V@@6B@") +// RTTI-DAG: @"\01??_7V@@6B@" = dllexport unnamed_addr alias i8*, getelementptr inbounds ({ [2 x i8*] }, { [2 x i8*] }* [[VTABLE_V]], i32 0, i32 0, i32 1) -// NO-RTTI-DAG: @"\01??_7V@@6B@" = weak_odr dllexport unnamed_addr constant [1 x i8*] [i8* bitcast ({{.*}} @"\01??_GV@@UAEPAXI@Z" to i8*)] +// NO-RTTI-DAG: @"\01??_7V@@6B@" = weak_odr dllexport unnamed_addr constant { [1 x i8*] } { [1 x i8*] [i8* bitcast ({{.*}} @"\01??_GV@@UAEPAXI@Z" to i8*)] } namespace { struct W { virtual ~W() {} } w; } -// RTTI-DAG: [[VTABLE_W:@.*]] = private unnamed_addr constant [2 x i8*] [i8* bitcast ({{.*}} @"\01??_R4W@?A@@6B@" to i8*), i8* bitcast ({{.*}} @"\01??_GW@?A@@UAEPAXI@Z" to i8*)] -// RTTI-DAG: @"\01??_7W@?A@@6B@" = internal unnamed_addr alias i8*, getelementptr inbounds ([2 x i8*], [2 x i8*]* [[VTABLE_W]], i32 0, i32 1) +// RTTI-DAG: [[VTABLE_W:@.*]] = private unnamed_addr constant { [2 x i8*] } { [2 x i8*] [i8* bitcast ({{.*}} @"\01??_R4W@?A@@6B@" to i8*), i8* bitcast ({{.*}} @"\01??_GW@?A@@UAEPAXI@Z" to i8*)] } +// RTTI-DAG: @"\01??_7W@?A@@6B@" = internal unnamed_addr alias i8*, getelementptr inbounds ({ [2 x i8*] }, { [2 x i8*] }* [[VTABLE_W]], i32 0, i32 0, i32 1) -// NO-RTTI-DAG: @"\01??_7W@?A@@6B@" = internal unnamed_addr constant [1 x i8*] [i8* bitcast ({{.*}} @"\01??_GW@?A@@UAEPAXI@Z" to i8*)] +// NO-RTTI-DAG: @"\01??_7W@?A@@6B@" = internal unnamed_addr constant { [1 x i8*] } { [1 x i8*] [i8* bitcast ({{.*}} @"\01??_GW@?A@@UAEPAXI@Z" to i8*)] } struct X {}; template <class> struct Y : virtual X { @@ -49,7 +49,7 @@ template <class> struct Y : virtual X { extern template class Y<int>; template Y<int>::Y(); -// RTTI-DAG: [[VTABLE_Y:@.*]] = private unnamed_addr constant [2 x i8*] [i8* bitcast (%rtti.CompleteObjectLocator* @"\01??_R4?$Y@H@@6B@" to i8*), i8* bitcast (i8* (%struct.Y*, i32)* @"\01??_G?$Y@H@@UAEPAXI@Z" to i8*)], comdat($"\01??_7?$Y@H@@6B@") -// RTTI-DAG: @"\01??_7?$Y@H@@6B@" = unnamed_addr alias i8*, getelementptr inbounds ([2 x i8*], [2 x i8*]* [[VTABLE_Y]], i32 0, i32 1) +// RTTI-DAG: [[VTABLE_Y:@.*]] = private unnamed_addr constant { [2 x i8*] } { [2 x i8*] [i8* bitcast (%rtti.CompleteObjectLocator* @"\01??_R4?$Y@H@@6B@" to i8*), i8* bitcast (i8* (%struct.Y*, i32)* @"\01??_G?$Y@H@@UAEPAXI@Z" to i8*)] }, comdat($"\01??_7?$Y@H@@6B@") +// RTTI-DAG: @"\01??_7?$Y@H@@6B@" = unnamed_addr alias i8*, getelementptr inbounds ({ [2 x i8*] }, { [2 x i8*] }* [[VTABLE_Y]], i32 0, i32 0, i32 1) -// NO-RTTI-DAG: @"\01??_7?$Y@H@@6B@" = linkonce_odr unnamed_addr constant [1 x i8*] [i8* bitcast (i8* (%struct.Y*, i32)* @"\01??_G?$Y@H@@UAEPAXI@Z" to i8*)], comdat +// NO-RTTI-DAG: @"\01??_7?$Y@H@@6B@" = linkonce_odr unnamed_addr constant { [1 x i8*] } { [1 x i8*] [i8* bitcast (i8* (%struct.Y*, i32)* @"\01??_G?$Y@H@@UAEPAXI@Z" to i8*)] }, comdat diff --git a/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp b/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp index 480ae8cfbbec..416aefa6b715 100644 --- a/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp +++ b/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp @@ -33,7 +33,7 @@ B::B() { // CHECK: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8* // CHECK: %[[VFPTR_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_i8]], i32 %{{.*}} // CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VFPTR_i8]] to i32 (...)*** - // CHECK: store i32 (...)** bitcast ([3 x i8*]* @"\01??_7B@@6B@" to i32 (...)**), i32 (...)*** %[[VFPTR]] + // CHECK: store i32 (...)** bitcast ({ [3 x i8*] }* @"\01??_7B@@6B@" to i32 (...)**), i32 (...)*** %[[VFPTR]] // Initialize vtorDisp: // CHECK: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8* @@ -66,7 +66,7 @@ B::~B() { // CHECK: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8* // CHECK: %[[VFPTR_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_i8]], i32 %{{.*}} // CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VFPTR_i8]] to i32 (...)*** - // CHECK: store i32 (...)** bitcast ([3 x i8*]* @"\01??_7B@@6B@" to i32 (...)**), i32 (...)*** %[[VFPTR]] + // CHECK: store i32 (...)** bitcast ({ [3 x i8*] }* @"\01??_7B@@6B@" to i32 (...)**), i32 (...)*** %[[VFPTR]] // Initialize vtorDisp: // CHECK: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8* @@ -245,9 +245,9 @@ struct D : virtual A, virtual B, virtual C { D::D() { // CHECK-LABEL: define x86_thiscallcc %"struct.multiple_vbases::D"* @"\01??0D@multiple_vbases@@QAE@XZ" // Just make sure we emit 3 vtordisps after initializing vfptrs. - // CHECK: store i32 (...)** bitcast ([1 x i8*]* @"\01??_7D@multiple_vbases@@6BA@1@@" to i32 (...)**), i32 (...)*** %{{.*}} - // CHECK: store i32 (...)** bitcast ([1 x i8*]* @"\01??_7D@multiple_vbases@@6BB@1@@" to i32 (...)**), i32 (...)*** %{{.*}} - // CHECK: store i32 (...)** bitcast ([1 x i8*]* @"\01??_7D@multiple_vbases@@6BC@1@@" to i32 (...)**), i32 (...)*** %{{.*}} + // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @"\01??_7D@multiple_vbases@@6BA@1@@" to i32 (...)**), i32 (...)*** %{{.*}} + // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @"\01??_7D@multiple_vbases@@6BB@1@@" to i32 (...)**), i32 (...)*** %{{.*}} + // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @"\01??_7D@multiple_vbases@@6BC@1@@" to i32 (...)**), i32 (...)*** %{{.*}} // ... // CHECK: store i32 %{{.*}}, i32* %{{.*}} // CHECK: store i32 %{{.*}}, i32* %{{.*}} @@ -283,7 +283,7 @@ struct D : virtual Z, B, C { } d; D::~D() { - // CHECK-LABEL: define x86_thiscallcc void @"\01??1D@diamond@@UAE@XZ"(%"struct.diamond::D"*) + // CHECK-LABEL: define x86_thiscallcc void @"\01??1D@diamond@@UAE@XZ"(%"struct.diamond::D"*{{.*}}) // CHECK: %[[ARG_i8:.*]] = bitcast %"struct.diamond::D"* %{{.*}} to i8* // CHECK: %[[THIS_i8:.*]] = getelementptr inbounds i8, i8* %[[ARG_i8]], i32 -24 // CHECK: %[[THIS:.*]] = bitcast i8* %[[THIS_i8]] to %"struct.diamond::D"* @@ -397,7 +397,7 @@ C::~C() { // CHECK-NOT: getelementptr // CHECK-NOT: bitcast // CHECK: %[[VFPTR_i8:.*]] = bitcast %"struct.test4::C"* %{{.*}} to i32 (...)*** - // CHECK: store i32 (...)** bitcast ([1 x i8*]* @"\01??_7C@test4@@6BB@1@@" to i32 (...)**), i32 (...)*** %[[VFPTR_i8]] + // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @"\01??_7C@test4@@6BB@1@@" to i32 (...)**), i32 (...)*** %[[VFPTR_i8]] foo(this); // CHECK: ret @@ -432,7 +432,7 @@ E::~E() { // CHECK-NOT: getelementptr // CHECK-NOT: bitcast // CHECK: %[[VFPTR_i8:.*]] = bitcast %"struct.test4::E"* %{{.*}} to i32 (...)*** - // CHECK: store i32 (...)** bitcast ([1 x i8*]* @"\01??_7E@test4@@6BD@1@@" to i32 (...)**), i32 (...)*** %[[VFPTR_i8]] + // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @"\01??_7E@test4@@6BD@1@@" to i32 (...)**), i32 (...)*** %[[VFPTR_i8]] foo(this); } diff --git a/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-this-adjustment.cpp b/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-this-adjustment.cpp index aaee39c51db6..b97c432f5e02 100644 --- a/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-this-adjustment.cpp +++ b/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-this-adjustment.cpp @@ -177,3 +177,26 @@ void fop(C &c) { } } + +namespace pr30293 { +struct NonTrivial { + ~NonTrivial(); + int x; +}; +struct A { virtual void f(); }; +struct B { virtual void __cdecl g(NonTrivial); }; +struct C final : A, B { + void f() override; + void __cdecl g(NonTrivial) override; +}; +C *whatsthis; +void C::f() { g(NonTrivial()); } +void C::g(NonTrivial o) { + whatsthis = this; +} + +// BITCODE-LABEL: define void @"\01?g@C@pr30293@@UAAXUNonTrivial@2@@Z"(<{ i8*, %"struct.pr30293::NonTrivial" }>* inalloca) +// BITCODE: %[[this1:[^ ]*]] = load i8*, i8** %[[thisaddr:[^ ]*]], align 4 +// BITCODE-NEXT: %[[this2:[^ ]*]] = getelementptr inbounds i8, i8* %[[this1]], i32 -4 +// BITCODE-NEXT: store i8* %[[this2]], i8** %[[thisaddr]], align 4 +} diff --git a/test/CodeGenCXX/microsoft-abi-vtables-return-thunks.cpp b/test/CodeGenCXX/microsoft-abi-vtables-return-thunks.cpp index d22344840c19..2bf7da58ea9c 100644 --- a/test/CodeGenCXX/microsoft-abi-vtables-return-thunks.cpp +++ b/test/CodeGenCXX/microsoft-abi-vtables-return-thunks.cpp @@ -26,7 +26,7 @@ J::J() {} // VFTABLES-NEXT: [return adjustment (to type 'struct test1::C *'): 0 non-virtual] // VFTABLES-NEXT: 2 | test1::D *test1::J::foo() -// GLOBALS-LABEL: @"\01??_7J@test1@@6B@" = linkonce_odr unnamed_addr constant [3 x i8*] +// GLOBALS-LABEL: @"\01??_7J@test1@@6B@" = linkonce_odr unnamed_addr constant { [3 x i8*] } // GLOBALS: @"\01?foo@J@test1@@QAEPAUB@2@XZ" // GLOBALS: @"\01?foo@J@test1@@QAEPAUC@2@XZ" // GLOBALS: @"\01?foo@J@test1@@UAEPAUD@2@XZ" @@ -44,7 +44,7 @@ K::K() {} // Only B to C requires adjustment, but we get 3 thunks in K's vftable, two of // which are trivial. -// GLOBALS-LABEL: @"\01??_7K@test1@@6B@" = linkonce_odr unnamed_addr constant [4 x i8*] +// GLOBALS-LABEL: @"\01??_7K@test1@@6B@" = linkonce_odr unnamed_addr constant { [4 x i8*] } // GLOBALS: @"\01?foo@K@test1@@QAEPAUB@2@XZ" // GLOBALS: @"\01?foo@K@test1@@QAEPAUC@2@XZ" // GLOBALS: @"\01?foo@K@test1@@QAEPAUD@2@XZ" @@ -90,7 +90,7 @@ J::J() {} // VFTABLES-NEXT: [return adjustment (to type 'struct test2::B *'): 4 non-virtual] // VFTABLES-NEXT: 1 | test2::D *test2::J::foo() -// GLOBALS-LABEL: @"\01??_7J@test2@@6B@" = linkonce_odr unnamed_addr constant [2 x i8*] +// GLOBALS-LABEL: @"\01??_7J@test2@@6B@" = linkonce_odr unnamed_addr constant { [2 x i8*] } K::K() {} @@ -101,7 +101,7 @@ K::K() {} // VFTABLES-NEXT: [return adjustment (to type 'struct test2::D *'): 0 non-virtual] // VFTABLES-NEXT: 2 | test2::E *test2::K::foo() -// GLOBALS-LABEL: @"\01??_7K@test2@@6B@" = linkonce_odr unnamed_addr constant [3 x i8*] +// GLOBALS-LABEL: @"\01??_7K@test2@@6B@" = linkonce_odr unnamed_addr constant { [3 x i8*] } } @@ -124,7 +124,7 @@ struct C : virtual A, B { C::C() {} -// GLOBALS-LABEL: @"\01??_7C@pr20479@@6B@" = linkonce_odr unnamed_addr constant [2 x i8*] +// GLOBALS-LABEL: @"\01??_7C@pr20479@@6B@" = linkonce_odr unnamed_addr constant { [2 x i8*] } // GLOBALS: @"\01?f@B@pr20479@@QAEPAUA@2@XZ" // GLOBALS: @"\01?f@B@pr20479@@UAEPAU12@XZ" } @@ -151,7 +151,7 @@ struct C : virtual A, virtual B { C::C() {} -// GLOBALS-LABEL: @"\01??_7C@pr21073@@6B@" = linkonce_odr unnamed_addr constant [2 x i8*] +// GLOBALS-LABEL: @"\01??_7C@pr21073@@6B@" = linkonce_odr unnamed_addr constant { [2 x i8*] } // GLOBALS: @"\01?f@B@pr21073@@WPPPPPPPI@AEPAUA@2@XZ" // GLOBALS: @"\01?f@B@pr21073@@WPPPPPPPI@AEPAU12@XZ" } @@ -168,7 +168,7 @@ D::D() {} // VFTABLES-NEXT: [return adjustment (to type 'struct pr21073_2::A *'): vbase #1, 0 non-virtual] // VFTABLES-NEXT: 1 | pr21073_2::C *pr21073_2::C::foo() -// GLOBALS-LABEL: @"\01??_7D@pr21073_2@@6B@" = {{.*}} constant [2 x i8*] +// GLOBALS-LABEL: @"\01??_7D@pr21073_2@@6B@" = {{.*}} constant { [2 x i8*] } // GLOBALS: @"\01?foo@C@pr21073_2@@QAEPAUA@2@XZ" // GLOBALS: @"\01?foo@C@pr21073_2@@UAEPAU12@XZ" } @@ -196,7 +196,7 @@ D::D() {} // VFTABLES-NEXT: [return adjustment (to type 'struct test3::D *'): 0 non-virtual] // VFTABLES-NEXT: [this adjustment: vtordisp at -4, 0 non-virtual] -// GLOBALS-LABEL: @"\01??_7D@test3@@6B@" = {{.*}} constant [3 x i8*] +// GLOBALS-LABEL: @"\01??_7D@test3@@6B@" = {{.*}} constant { [3 x i8*] } // GLOBALS: @"\01?fn@D@test3@@$4PPPPPPPM@A@AEPAUA@2@XZ" // GLOBALS: @"\01?fn@D@test3@@$4PPPPPPPM@A@AEPAUB@2@XZ" // GLOBALS: @"\01?fn@D@test3@@$4PPPPPPPM@A@AEPAU12@XZ" diff --git a/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp b/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp index aa39d6de615a..738c15d89d21 100644 --- a/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp +++ b/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp @@ -19,7 +19,7 @@ struct A { int ia; }; A a; -// EMITS-VFTABLE-DAG: @"\01??_7A@@6B@" = linkonce_odr unnamed_addr constant [3 x i8*] +// EMITS-VFTABLE-DAG: @"\01??_7A@@6B@" = linkonce_odr unnamed_addr constant { [3 x i8*] } void use(A *obj) { obj->f(); } struct B : A { @@ -39,7 +39,7 @@ struct B : A { virtual void j(); }; B b; -// EMITS-VFTABLE-DAG: @"\01??_7B@@6B@" = linkonce_odr unnamed_addr constant [5 x i8*] +// EMITS-VFTABLE-DAG: @"\01??_7B@@6B@" = linkonce_odr unnamed_addr constant { [5 x i8*] } void use(B *obj) { obj->f(); } struct C { @@ -69,7 +69,7 @@ struct D { virtual ~D(); }; D d; -// EMITS-VFTABLE-DAG: @"\01??_7D@@6B@" = linkonce_odr unnamed_addr constant [2 x i8*] +// EMITS-VFTABLE-DAG: @"\01??_7D@@6B@" = linkonce_odr unnamed_addr constant { [2 x i8*] } void use(D *obj) { obj->f(); } struct E : A { @@ -107,7 +107,7 @@ struct F : A { virtual ~F(); }; F f; -// EMITS-VFTABLE-DAG: @"\01??_7F@@6B@" = linkonce_odr unnamed_addr constant [5 x i8*] +// EMITS-VFTABLE-DAG: @"\01??_7F@@6B@" = linkonce_odr unnamed_addr constant { [5 x i8*] } void use(F *obj) { obj->i(); } struct G : E { @@ -295,7 +295,7 @@ struct S { // CHECK-NEXT: 0 | void S::f() [deleted] virtual void f() = delete; S(); - // EMITS-VFTABLE-DAG: @"\01??_7S@@6B@" = linkonce_odr unnamed_addr constant [1 x i8*] [i8* bitcast (void ()* @_purecall to i8*)] + // EMITS-VFTABLE-DAG: @"\01??_7S@@6B@" = linkonce_odr unnamed_addr constant { [1 x i8*] } { [1 x i8*] [i8* bitcast (void ()* @_purecall to i8*)] } }; S::S() {} diff --git a/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp b/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp index 83f8114bae99..342a584182cc 100644 --- a/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp +++ b/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp @@ -771,7 +771,7 @@ struct A { }; struct __declspec(dllexport) B : virtual A { virtual void f() = 0; - // MANGLING-DAG: @"\01??_7B@Test13@@6B@" = weak_odr dllexport unnamed_addr constant [1 x i8*] [i8* bitcast (void ()* @_purecall to i8*)] + // MANGLING-DAG: @"\01??_7B@Test13@@6B@" = weak_odr dllexport unnamed_addr constant { [1 x i8*] } { [1 x i8*] [i8* bitcast (void ()* @_purecall to i8*)] } }; } @@ -788,8 +788,8 @@ C::C() {} // CHECK-LABEL: VFTable for 'pr21031_1::B' in 'pr21031_1::C' (1 entry) // CHECK-NEXT: 0 | void pr21031_1::B::g() -// MANGLING-DAG: @"\01??_7C@pr21031_1@@6BB@1@@" = {{.*}} constant [1 x i8*] -// MANGLING-DAG: @"\01??_7C@pr21031_1@@6B@" = {{.*}} constant [1 x i8*] +// MANGLING-DAG: @"\01??_7C@pr21031_1@@6BB@1@@" = {{.*}} constant { [1 x i8*] } +// MANGLING-DAG: @"\01??_7C@pr21031_1@@6B@" = {{.*}} constant { [1 x i8*] } } namespace pr21031_2 { @@ -804,8 +804,8 @@ C::C() {} // CHECK-LABEL: VFTable for 'pr21031_2::A' in 'pr21031_2::B' in 'pr21031_2::C' (1 entry) // CHECK-NEXT: 0 | void pr21031_2::A::f() -// MANGLING-DAG: @"\01??_7C@pr21031_2@@6BA@1@@" = {{.*}} constant [1 x i8*] -// MANGLING-DAG: @"\01??_7C@pr21031_2@@6BB@1@@" = {{.*}} constant [1 x i8*] +// MANGLING-DAG: @"\01??_7C@pr21031_2@@6BA@1@@" = {{.*}} constant { [1 x i8*] } +// MANGLING-DAG: @"\01??_7C@pr21031_2@@6BB@1@@" = {{.*}} constant { [1 x i8*] } } namespace pr21062_1 { @@ -818,7 +818,7 @@ D::D() {} // CHECK-LABEL: VFTable for 'pr21062_1::A' in 'pr21062_1::D' (1 entry) // CHECK-NEXT: 0 | void pr21062_1::A::f() -// MANGLING-DAG: @"\01??_7D@pr21062_1@@6B@" = {{.*}} constant [1 x i8*] +// MANGLING-DAG: @"\01??_7D@pr21062_1@@6B@" = {{.*}} constant { [1 x i8*] } } namespace pr21062_2 { @@ -831,7 +831,7 @@ D::D() {} // CHECK-LABEL: VFTable for 'pr21062_2::A' in 'pr21062_2::D' (1 entry) // CHECK-NEXT: 0 | void pr21062_2::A::f() -// MANGLING-DAG: @"\01??_7D@pr21062_2@@6B@" = {{.*}} constant [1 x i8*] +// MANGLING-DAG: @"\01??_7D@pr21062_2@@6B@" = {{.*}} constant { [1 x i8*] } } namespace pr21064 { @@ -843,5 +843,5 @@ D::D() {} // CHECK-LABEL: VFTable for 'pr21064::B' in 'pr21064::C' in 'pr21064::D' (1 entry) // CHECK-NEXT: 0 | void pr21064::B::f() -// MANGLING-DAG: @"\01??_7D@pr21064@@6B@" = {{.*}} constant [1 x i8*] +// MANGLING-DAG: @"\01??_7D@pr21064@@6B@" = {{.*}} constant { [1 x i8*] } } diff --git a/test/CodeGenCXX/microsoft-interface.cpp b/test/CodeGenCXX/microsoft-interface.cpp index 8f4670a6946a..5f3a94a494b7 100644 --- a/test/CodeGenCXX/microsoft-interface.cpp +++ b/test/CodeGenCXX/microsoft-interface.cpp @@ -17,7 +17,7 @@ int fn() { return s.test(); } -// CHECK: @_ZTV1S = linkonce_odr unnamed_addr constant [3 x i8*] [i8* null, i8* bitcast ({ i8*, i8*, i8* }* @_ZTI1S to i8*), i8* bitcast (i32 (%struct.S*)* @_ZN1S4testEv to i8*)] +// CHECK: @_ZTV1S = linkonce_odr unnamed_addr constant { [3 x i8*] } { [3 x i8*] [i8* null, i8* bitcast ({ i8*, i8*, i8* }* @_ZTI1S to i8*), i8* bitcast (i32 (%struct.S*)* @_ZN1S4testEv to i8*)] } // CHECK-LABEL: define i32 @_Z2fnv() // CHECK: call x86_thiscallcc void @_ZN1SC1Ev(%struct.S* %s) @@ -31,10 +31,10 @@ int fn() { // CHECK-LABEL: define linkonce_odr x86_thiscallcc void @_ZN1SC2Ev(%struct.S* %this) // CHECK: call x86_thiscallcc void @_ZN1IC2Ev(%__interface.I* %{{[.0-9A-Z_a-z]+}}) -// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTV1S, i32 0, i32 2) to i32 (...)**), i32 (...)*** %{{[.0-9A-Z_a-z]+}} +// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTV1S, i32 0, inrange i32 0, i32 2) to i32 (...)**), i32 (...)*** %{{[.0-9A-Z_a-z]+}} // CHECK-LABEL: define linkonce_odr x86_thiscallcc void @_ZN1IC2Ev(%__interface.I* %this) -// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTV1I, i32 0, i32 2) to i32 (...)**), i32 (...)*** %{{[.0-9A-Z_a-z]+}} +// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTV1I, i32 0, inrange i32 0, i32 2) to i32 (...)**), i32 (...)*** %{{[.0-9A-Z_a-z]+}} // CHECK-LABEL: define linkonce_odr x86_thiscallcc i32 @_ZN1I4testEv(%__interface.I* %this) // CHECK: ret i32 1 diff --git a/test/CodeGenCXX/microsoft-no-rtti-data.cpp b/test/CodeGenCXX/microsoft-no-rtti-data.cpp index 68fdf0586c0d..05255909ced3 100644 --- a/test/CodeGenCXX/microsoft-no-rtti-data.cpp +++ b/test/CodeGenCXX/microsoft-no-rtti-data.cpp @@ -2,7 +2,7 @@ // vftable shouldn't have RTTI data in it. // CHECK-NOT: @"\01??_R4S@@6B@" -// CHECK: @"\01??_7S@@6B@" = linkonce_odr unnamed_addr constant [1 x i8*] [i8* bitcast ({{.*}} @"\01??_GS@@UAEPAXI@Z" to i8*)], comdat +// CHECK: @"\01??_7S@@6B@" = linkonce_odr unnamed_addr constant { [1 x i8*] } { [1 x i8*] [i8* bitcast ({{.*}} @"\01??_GS@@UAEPAXI@Z" to i8*)] }, comdat struct type_info; namespace std { using ::type_info; } diff --git a/test/CodeGenCXX/microsoft-uuidof.cpp b/test/CodeGenCXX/microsoft-uuidof.cpp index 62e4b880ad46..9b4ff68d9aa8 100644 --- a/test/CodeGenCXX/microsoft-uuidof.cpp +++ b/test/CodeGenCXX/microsoft-uuidof.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -emit-llvm %s -o - -DDEFINE_GUID -triple=i386-pc-linux -fms-extensions | FileCheck %s --check-prefix=CHECK-DEFINE-GUID +// RUN: %clang_cc1 -emit-llvm %s -o - -DDEFINE_GUID -DBRACKET_ATTRIB -triple=i386-pc-linux -fms-extensions | FileCheck %s --check-prefix=CHECK-DEFINE-GUID // RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-linux -fms-extensions | FileCheck %s // RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-pc-linux -fms-extensions | FileCheck %s --check-prefix=CHECK-64 // RUN: %clang_cc1 -emit-llvm %s -o - -DDEFINE_GUID -DWRONG_GUID -triple=i386-pc-linux -fms-extensions | FileCheck %s --check-prefix=CHECK-DEFINE-WRONG-GUID @@ -17,10 +18,17 @@ struct _GUID { #endif typedef struct _GUID GUID; +#ifdef BRACKET_ATTRIB +[uuid(12345678-1234-1234-1234-1234567890aB)] struct S1 { } s1; +[uuid(87654321-4321-4321-4321-ba0987654321)] struct S2 { }; +[uuid({12345678-1234-1234-1234-1234567890ac})] struct Curly; +[uuid({12345678-1234-1234-1234-1234567890ac})] struct Curly; +#else struct __declspec(uuid("12345678-1234-1234-1234-1234567890aB")) S1 { } s1; struct __declspec(uuid("87654321-4321-4321-4321-ba0987654321")) S2 { }; struct __declspec(uuid("{12345678-1234-1234-1234-1234567890ac}")) Curly; struct __declspec(uuid("{12345678-1234-1234-1234-1234567890ac}")) Curly; +#endif #ifdef DEFINE_GUID // Make sure we can properly generate code when the UUID has curly braces on it. diff --git a/test/CodeGenCXX/modules-ts.cppm b/test/CodeGenCXX/modules-ts.cppm new file mode 100644 index 000000000000..da3bcb2174a7 --- /dev/null +++ b/test/CodeGenCXX/modules-ts.cppm @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -fmodules-ts -std=c++1z -triple=x86_64-linux-gnu -emit-module-interface %s -o %t.pcm +// RUN: %clang_cc1 -fmodules-ts -std=c++1z -triple=x86_64-linux-gnu %t.pcm -emit-llvm -o - | FileCheck %s + +module FooBar; + +export { + // CHECK-LABEL: define i32 @_Z1fv( + int f() { return 0; } +} + +// FIXME: Emit global variables and their initializers with this TU. +// Emit an initialization function that other TUs can call, with guard variable. + +// FIXME: Mangle non-exported symbols so they don't collide with +// non-exported symbols from other modules? + +// FIXME: Formally-internal-linkage symbols that are used from an exported +// symbol need a mangled name and external linkage. + +// FIXME: const-qualified variables don't have implicit internal linkage when owned by a module. diff --git a/test/CodeGenCXX/ms-inline-asm-return.cpp b/test/CodeGenCXX/ms-inline-asm-return.cpp index 1219c617ddc7..51671c0bcdaa 100644 --- a/test/CodeGenCXX/ms-inline-asm-return.cpp +++ b/test/CodeGenCXX/ms-inline-asm-return.cpp @@ -50,8 +50,8 @@ char f_i8() { bool f_i1() { __asm { - mov eax, 1 - mov edx, 1 + mov eax, 1L + mov edx, 1U } } // CHECK-LABEL: define zeroext i1 @f_i1() @@ -80,12 +80,12 @@ struct EightChars { }; EightChars f_s8() { __asm { - mov eax, 0x01010101 - mov edx, 0x01010101 + mov eax, 01010101h + mov edx, 01010101b } } // CHECK-LABEL: define i64 @f_s8() -// CHECK: %[[r:[^ ]*]] = call i64 asm sideeffect inteldialect "mov eax, $$0x01010101\0A\09mov edx, $$0x01010101", "=A,~{eax},{{.*}}" +// CHECK: %[[r:[^ ]*]] = call i64 asm sideeffect inteldialect "mov eax, $$01010101h\0A\09mov edx, $$01010101b", "=A,~{eax},{{.*}}" // CHECK: store i64 %[[r]], i64* %{{.*}} // CHECK: %[[r_i64:[^ ]*]] = load i64, i64* %{{.*}} // CHECK: ret i64 %[[r_i64]] diff --git a/test/CodeGenCXX/ms-thread_local.cpp b/test/CodeGenCXX/ms-thread_local.cpp index c29473fd6fca..5183ab5c32e1 100644 --- a/test/CodeGenCXX/ms-thread_local.cpp +++ b/test/CodeGenCXX/ms-thread_local.cpp @@ -26,3 +26,8 @@ A f() { (void)b; return c; } + +// CHECK: !llvm.module.flags = !{{{.*}}} +// CHECK: !{{[0-9]+}} = !{i32 6, !"Linker Options", ![[link_opts:[0-9]+]]} +// CHECK: ![[link_opts]] = !{![[dyn_tls_init:[0-9]+]]} +// CHECK: ![[dyn_tls_init]] = !{!"/include:___dyn_tls_init@12"} diff --git a/test/CodeGenCXX/naked.cpp b/test/CodeGenCXX/naked.cpp new file mode 100644 index 000000000000..34f22b3636b5 --- /dev/null +++ b/test/CodeGenCXX/naked.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-windows -emit-llvm %s -o - | FileCheck %s + +class TestNaked { +public: + void NakedFunction(); +}; + +__attribute__((naked)) void TestNaked::NakedFunction() { + // CHECK-LABEL: define {{(x86_thiscallcc )?}}void @ + // CHECK: call void asm sideeffect + asm(""); +} diff --git a/test/CodeGenCXX/new-array-init.cpp b/test/CodeGenCXX/new-array-init.cpp index 602f93c34f01..0429ae770bc8 100644 --- a/test/CodeGenCXX/new-array-init.cpp +++ b/test/CodeGenCXX/new-array-init.cpp @@ -1,5 +1,8 @@ // RUN: %clang_cc1 -std=c++11 -triple i386-unknown-unknown %s -emit-llvm -o - | FileCheck %s +// CHECK: @[[ABC4:.*]] = {{.*}} constant [4 x i8] c"abc\00" +// CHECK: @[[ABC15:.*]] = {{.*}} constant [15 x i8] c"abc\00\00\00\00 + // CHECK-LABEL: define void @_Z2fni void fn(int n) { // CHECK: icmp ult i{{32|64}} %{{[^ ]+}}, 3 @@ -11,13 +14,6 @@ void fn(int n) { new int[n] { 1, 2, 3 }; } -// CHECK-LABEL: define void @_Z15const_underflowv -void const_underflow() { - // CHECK-NOT: icmp ult i{{32|64}} %{{[^ ]+}}, 3 - // CHECK: call i8* @_Zna{{.}}(i{{32|64}} -1) - new int[2] { 1, 2, 3 }; -} - // CHECK-LABEL: define void @_Z11const_exactv void const_exact() { // CHECK-NOT: icmp ult i{{32|64}} %{{[^ ]+}}, 3 @@ -46,3 +42,77 @@ void check_array_value_init() { // CHECK: icmp eq // CHECK: br i1 } + +// CHECK-LABEL: define void @_Z15string_nonconsti +void string_nonconst(int n) { + // CHECK: icmp slt i{{32|64}} %{{[^ ]+}}, 4 + // FIXME: Conditionally throw an exception rather than passing -1 to alloc function + // CHECK: select + // CHECK: %[[PTR:.*]] = call i8* @_Zna{{.}}(i{{32|64}} + // CHECK: call void @llvm.memcpy{{.*}}(i8* %[[PTR]], i8* getelementptr inbounds ([4 x i8], [4 x i8]* @[[ABC4]], i32 0, i32 0), i32 4, + // CHECK: %[[REST:.*]] = getelementptr inbounds i8, i8* %[[PTR]], i32 4 + // CHECK: %[[RESTSIZE:.*]] = sub {{.*}}, 4 + // CHECK: call void @llvm.memset{{.*}}(i8* %[[REST]], i8 0, i{{32|64}} %[[RESTSIZE]], + new char[n] { "abc" }; +} + +// CHECK-LABEL: define void @_Z12string_exactv +void string_exact() { + // CHECK-NOT: icmp + // CHECK: %[[PTR:.*]] = call i8* @_Zna{{.}}(i{{32|64}} 4) + // CHECK: call void @llvm.memcpy{{.*}}(i8* %[[PTR]], i8* getelementptr inbounds ([4 x i8], [4 x i8]* @[[ABC4]], i32 0, i32 0), i32 4, + // CHECK-NOT: memset + new char[4] { "abc" }; +} + +// CHECK-LABEL: define void @_Z17string_sufficientv +void string_sufficient() { + // CHECK-NOT: icmp + // CHECK: %[[PTR:.*]] = call i8* @_Zna{{.}}(i{{32|64}} 15) + // FIXME: For very large arrays, it would be preferable to emit a small copy and a memset. + // CHECK: call void @llvm.memcpy{{.*}}(i8* %[[PTR]], i8* getelementptr inbounds ([15 x i8], [15 x i8]* @[[ABC15]], i32 0, i32 0), i32 15, + // CHECK-NOT: memset + new char[15] { "abc" }; +} + +// CHECK-LABEL: define void @_Z10aggr_exactv +void aggr_exact() { + // CHECK-NOT: icmp + // CHECK: %[[MEM:.*]] = call i8* @_Zna{{.}}(i{{32|64}} 16) + // CHECK: %[[PTR0:.*]] = bitcast i8* %[[MEM]] to %[[AGGR:.*]]* + // CHECK: %[[FIELD:.*]] = getelementptr inbounds %[[AGGR]], %[[AGGR]]* %[[PTR0]], i32 0, i32 0{{$}} + // CHECK: store i32 1, i32* %[[FIELD]] + // CHECK: %[[FIELD:.*]] = getelementptr inbounds %[[AGGR]], %[[AGGR]]* %[[PTR0]], i32 0, i32 1{{$}} + // CHECK: store i32 2, i32* %[[FIELD]] + // CHECK: %[[PTR1:.*]] = getelementptr inbounds %[[AGGR]], %[[AGGR]]* %[[PTR0]], i32 1{{$}} + // CHECK: %[[FIELD:.*]] = getelementptr inbounds %[[AGGR]], %[[AGGR]]* %[[PTR1]], i32 0, i32 0{{$}} + // CHECK: store i32 3, i32* %[[FIELD]] + // CHECK: %[[FIELD:.*]] = getelementptr inbounds %[[AGGR]], %[[AGGR]]* %[[PTR1]], i32 0, i32 1{{$}} + // CHECK: store i32 0, i32* %[[FIELD]] + // CHECK-NOT: store + // CHECK-NOT: memset + struct Aggr { int a, b; }; + new Aggr[2] { 1, 2, 3 }; +} + +// CHECK-LABEL: define void @_Z15aggr_sufficienti +void aggr_sufficient(int n) { + // CHECK: icmp ult i32 %{{.*}}, 2 + // CHECK: %[[MEM:.*]] = call i8* @_Zna{{.}}( + // CHECK: %[[PTR0:.*]] = bitcast i8* %[[MEM]] to %[[AGGR:.*]]* + // CHECK: %[[FIELD:.*]] = getelementptr inbounds %[[AGGR]], %[[AGGR]]* %[[PTR0]], i32 0, i32 0{{$}} + // CHECK: store i32 1, i32* %[[FIELD]] + // CHECK: %[[FIELD:.*]] = getelementptr inbounds %[[AGGR]], %[[AGGR]]* %[[PTR0]], i32 0, i32 1{{$}} + // CHECK: store i32 2, i32* %[[FIELD]] + // CHECK: %[[PTR1:.*]] = getelementptr inbounds %[[AGGR]], %[[AGGR]]* %[[PTR0]], i32 1{{$}} + // CHECK: %[[FIELD:.*]] = getelementptr inbounds %[[AGGR]], %[[AGGR]]* %[[PTR1]], i32 0, i32 0{{$}} + // CHECK: store i32 3, i32* %[[FIELD]] + // CHECK: %[[FIELD:.*]] = getelementptr inbounds %[[AGGR]], %[[AGGR]]* %[[PTR1]], i32 0, i32 1{{$}} + // CHECK: store i32 0, i32* %[[FIELD]] + // CHECK: %[[PTR2:.*]] = getelementptr inbounds %[[AGGR]], %[[AGGR]]* %[[PTR1]], i32 1{{$}} + // CHECK: %[[REMAIN:.*]] = sub i32 {{.*}}, 16 + // CHECK: %[[MEM:.*]] = bitcast %[[AGGR]]* %[[PTR2]] to i8* + // CHECK: call void @llvm.memset{{.*}}(i8* %[[MEM]], i8 0, i32 %[[REMAIN]], + struct Aggr { int a, b; }; + new Aggr[n] { 1, 2, 3 }; +} diff --git a/test/CodeGenCXX/no-exceptions.cpp b/test/CodeGenCXX/no-exceptions.cpp index ceb3b8e80396..b970ef2c5a27 100644 --- a/test/CodeGenCXX/no-exceptions.cpp +++ b/test/CodeGenCXX/no-exceptions.cpp @@ -11,4 +11,4 @@ void f() throw (int) { // CHECK: ret void } -// CHECK: attributes [[NUW]] = { nounwind{{.*}} } +// CHECK: attributes [[NUW]] = { noinline nounwind{{.*}} } diff --git a/test/CodeGenCXX/nrvo.cpp b/test/CodeGenCXX/nrvo.cpp index 8744d141dddc..d02206abae50 100644 --- a/test/CodeGenCXX/nrvo.cpp +++ b/test/CodeGenCXX/nrvo.cpp @@ -1,5 +1,6 @@ // RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm -O1 -o - %s | FileCheck %s -// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm -O1 -fcxx-exceptions -fexceptions -o - %s | FileCheck --check-prefix=CHECK-EH %s +// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm -O1 -fcxx-exceptions -fexceptions -std=c++03 -o - %s | FileCheck --check-prefixes=CHECK-EH,CHECK-EH-03 %s +// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm -O1 -fcxx-exceptions -fexceptions -std=c++11 -o - %s | FileCheck --check-prefixes=CHECK-EH,CHECK-EH-11 %s // Test code generation for the named return value optimization. class X { @@ -91,16 +92,18 @@ X test2(bool B) { // -> %eh.cleanup // %lpad1: landing pad for return copy ctors, EH cleanup for 'y' - // CHECK-EH: invoke {{.*}} @_ZN1XD1Ev + // CHECK-EH-03: invoke {{.*}} @_ZN1XD1Ev // -> %eh.cleanup, %terminate.lpad + // CHECK-EH-11: call {{.*}} @_ZN1XD1Ev // %if.end: returning 'y' // CHECK-EH: invoke {{.*}} @_ZN1XC1ERKS_ // -> %cleanup, %lpad1 // %cleanup: normal cleanup for 'y' - // CHECK-EH: invoke {{.*}} @_ZN1XD1Ev + // CHECK-EH-03: invoke {{.*}} @_ZN1XD1Ev // -> %invoke.cont11, %lpad + // CHECK-EH-11: call {{.*}} @_ZN1XD1Ev // %invoke.cont11: normal cleanup for 'x' // CHECK-EH: call void @llvm.lifetime.end @@ -109,19 +112,20 @@ X test2(bool B) { // CHECK-EH-NEXT: ret void // %eh.cleanup: EH cleanup for 'x' - // CHECK-EH: invoke {{.*}} @_ZN1XD1Ev + // CHECK-EH-03: invoke {{.*}} @_ZN1XD1Ev // -> %invoke.cont17, %terminate.lpad + // CHECK-EH-11: call {{.*}} @_ZN1XD1Ev // %invoke.cont17: rethrow block for %eh.cleanup. // This really should be elsewhere in the function. // CHECK-EH: resume { i8*, i32 } // %terminate.lpad: terminate landing pad. - // CHECK-EH: [[T0:%.*]] = landingpad { i8*, i32 } - // CHECK-EH-NEXT: catch i8* null - // CHECK-EH-NEXT: [[T1:%.*]] = extractvalue { i8*, i32 } [[T0]], 0 - // CHECK-EH-NEXT: call void @__clang_call_terminate(i8* [[T1]]) [[NR_NUW:#[0-9]+]] - // CHECK-EH-NEXT: unreachable + // CHECK-EH-03: [[T0:%.*]] = landingpad { i8*, i32 } + // CHECK-EH-03-NEXT: catch i8* null + // CHECK-EH-03-NEXT: [[T1:%.*]] = extractvalue { i8*, i32 } [[T0]], 0 + // CHECK-EH-03-NEXT: call void @__clang_call_terminate(i8* [[T1]]) [[NR_NUW:#[0-9]+]] + // CHECK-EH-03-NEXT: unreachable } @@ -178,11 +182,11 @@ X test6() { return a; // CHECK: [[A:%.*]] = alloca [[X:%.*]], align 8 // CHECK-NEXT: [[PTR:%.*]] = getelementptr inbounds %class.X, %class.X* [[A]], i32 0, i32 0 - // CHECK-NEXT: call void @llvm.lifetime.start(i64 1, i8* [[PTR]]) + // CHECK-NEXT: call void @llvm.lifetime.start(i64 1, i8* nonnull [[PTR]]) // CHECK-NEXT: call {{.*}} @_ZN1XC1Ev([[X]]* nonnull [[A]]) // CHECK-NEXT: call {{.*}} @_ZN1XC1ERKS_([[X]]* {{%.*}}, [[X]]* nonnull dereferenceable({{[0-9]+}}) [[A]]) // CHECK-NEXT: call {{.*}} @_ZN1XD1Ev([[X]]* nonnull [[A]]) - // CHECK-NEXT: call void @llvm.lifetime.end(i64 1, i8* [[PTR]]) + // CHECK-NEXT: call void @llvm.lifetime.end(i64 1, i8* nonnull [[PTR]]) // CHECK-NEXT: ret void } @@ -217,4 +221,4 @@ Y<int> test9() { // CHECK-LABEL: define linkonce_odr void @_ZN1YIiE1fEv // CHECK: tail call {{.*}} @_ZN1YIiEC1Ev -// CHECK-EH: attributes [[NR_NUW]] = { noreturn nounwind } +// CHECK-EH-03: attributes [[NR_NUW]] = { noreturn nounwind } diff --git a/test/CodeGenCXX/optnone-class-members.cpp b/test/CodeGenCXX/optnone-class-members.cpp index 751f3dd2bf08..70e3ee76e60a 100644 --- a/test/CodeGenCXX/optnone-class-members.cpp +++ b/test/CodeGenCXX/optnone-class-members.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 < %s -triple %itanium_abi_triple -fms-extensions -emit-llvm -x c++ | FileCheck %s +// RUN: %clang_cc1 < %s -triple %itanium_abi_triple -fms-extensions -O2 -disable-llvm-optzns -emit-llvm -x c++ | FileCheck %s // Test attribute 'optnone' on methods: // -- member functions; diff --git a/test/CodeGenCXX/optnone-def-decl.cpp b/test/CodeGenCXX/optnone-def-decl.cpp index 0240189c5089..4008bbe685f3 100644 --- a/test/CodeGenCXX/optnone-def-decl.cpp +++ b/test/CodeGenCXX/optnone-def-decl.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -triple %itanium_abi_triple -fms-extensions -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -triple %itanium_abi_triple -fms-extensions -O2 -disable-llvm-optzns -emit-llvm -o - | FileCheck %s // Test optnone on both function declarations and function definitions. // Verify also that we don't generate invalid IR functions with diff --git a/test/CodeGenCXX/partial-destruction.cpp b/test/CodeGenCXX/partial-destruction.cpp index 4097fbfaa19c..a5a2f40eb071 100644 --- a/test/CodeGenCXX/partial-destruction.cpp +++ b/test/CodeGenCXX/partial-destruction.cpp @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - -fcxx-exceptions -fexceptions | FileCheck %s +// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - -fcxx-exceptions -fexceptions -std=c++03 | FileCheck %s -check-prefixes=CHECK,CHECKv03 +// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - -fcxx-exceptions -fexceptions -std=c++11 | FileCheck %s -check-prefixes=CHECK,CHECKv11 // Test IR generation for partial destruction of aggregates. @@ -45,7 +46,8 @@ namespace test0 { // CHECK-NEXT: br label // CHECK: [[ED_AFTER:%.*]] = phi [[A]]* [ [[ED_END]], {{%.*}} ], [ [[ED_CUR:%.*]], {{%.*}} ] // CHECK-NEXT: [[ED_CUR]] = getelementptr inbounds [[A]], [[A]]* [[ED_AFTER]], i64 -1 - // CHECK-NEXT: invoke void @_ZN5test01AD1Ev([[A]]* [[ED_CUR]]) + // CHECKv03-NEXT: invoke void @_ZN5test01AD1Ev([[A]]* [[ED_CUR]]) + // CHECKv11-NEXT: call void @_ZN5test01AD1Ev([[A]]* [[ED_CUR]]) // CHECK: [[T0:%.*]] = icmp eq [[A]]* [[ED_CUR]], [[ED_BEGIN]] // CHECK-NEXT: br i1 [[T0]], // CHECK: ret void @@ -58,7 +60,8 @@ namespace test0 { // CHECK-NEXT: br i1 [[T0]], // CHECK: [[E_AFTER:%.*]] = phi [[A]]* [ [[PARTIAL_END]], {{%.*}} ], [ [[E_CUR:%.*]], {{%.*}} ] // CHECK-NEXT: [[E_CUR]] = getelementptr inbounds [[A]], [[A]]* [[E_AFTER]], i64 -1 - // CHECK-NEXT: invoke void @_ZN5test01AD1Ev([[A]]* [[E_CUR]]) + // CHECKv03-NEXT: invoke void @_ZN5test01AD1Ev([[A]]* [[E_CUR]]) + // CHECKv11-NEXT: call void @_ZN5test01AD1Ev([[A]]* [[E_CUR]]) // CHECK: [[T0:%.*]] = icmp eq [[A]]* [[E_CUR]], [[E_BEGIN]] // CHECK-NEXT: br i1 [[T0]], @@ -73,20 +76,21 @@ namespace test0 { // FIXME: There's some really bad block ordering here which causes // the partial destroy for the primary normal destructor to fall // within the primary EH destructor. - // CHECK: landingpad { i8*, i32 } - // CHECK-NEXT: cleanup - // CHECK: [[T0:%.*]] = icmp eq [[A]]* [[ED_BEGIN]], [[ED_CUR]] - // CHECK-NEXT: br i1 [[T0]] - // CHECK: [[EDD_AFTER:%.*]] = phi [[A]]* [ [[ED_CUR]], {{%.*}} ], [ [[EDD_CUR:%.*]], {{%.*}} ] - // CHECK-NEXT: [[EDD_CUR]] = getelementptr inbounds [[A]], [[A]]* [[EDD_AFTER]], i64 -1 - // CHECK-NEXT: invoke void @_ZN5test01AD1Ev([[A]]* [[EDD_CUR]]) - // CHECK: [[T0:%.*]] = icmp eq [[A]]* [[EDD_CUR]], [[ED_BEGIN]] - // CHECK-NEXT: br i1 [[T0]] + // CHECKv03: landingpad { i8*, i32 } + // CHECKv03-NEXT: cleanup + // CHECKv03: [[T0:%.*]] = icmp eq [[A]]* [[ED_BEGIN]], [[ED_CUR]] + // CHECKv03-NEXT: br i1 [[T0]] + // CHECKv03: [[EDD_AFTER:%.*]] = phi [[A]]* [ [[ED_CUR]], {{%.*}} ], [ [[EDD_CUR:%.*]], {{%.*}} ] + // CHECKv03-NEXT: [[EDD_CUR]] = getelementptr inbounds [[A]], [[A]]* [[EDD_AFTER]], i64 -1 + // CHECKv03-NEXT: invoke void @_ZN5test01AD1Ev([[A]]* [[EDD_CUR]]) + // CHECKv03: [[T0:%.*]] = icmp eq [[A]]* [[EDD_CUR]], [[ED_BEGIN]] + // CHECKv03-NEXT: br i1 [[T0]] // Back to the primary EH destructor. // CHECK: [[E_AFTER:%.*]] = phi [[A]]* [ [[E_END]], {{%.*}} ], [ [[E_CUR:%.*]], {{%.*}} ] // CHECK-NEXT: [[E_CUR]] = getelementptr inbounds [[A]], [[A]]* [[E_AFTER]], i64 -1 - // CHECK-NEXT: invoke void @_ZN5test01AD1Ev([[A]]* [[E_CUR]]) + // CHECKv03-NEXT: invoke void @_ZN5test01AD1Ev([[A]]* [[E_CUR]]) + // CHECKv11-NEXT: call void @_ZN5test01AD1Ev([[A]]* [[E_CUR]]) // CHECK: [[T0:%.*]] = icmp eq [[A]]* [[E_CUR]], [[E0]] // CHECK-NEXT: br i1 [[T0]], @@ -120,8 +124,10 @@ namespace test1 { // CHECK-NEXT: cleanup // CHECK: landingpad { i8*, i32 } // CHECK-NEXT: cleanup - // CHECK: invoke void @_ZN5test11AD1Ev([[A]]* [[Y]]) - // CHECK: invoke void @_ZN5test11AD1Ev([[A]]* [[X]]) + // CHECKv03: invoke void @_ZN5test11AD1Ev([[A]]* [[Y]]) + // CHECKv03: invoke void @_ZN5test11AD1Ev([[A]]* [[X]]) + // CHECKv11: call void @_ZN5test11AD1Ev([[A]]* [[Y]]) + // CHECKv11: call void @_ZN5test11AD1Ev([[A]]* [[X]]) } namespace test2 { @@ -153,7 +159,8 @@ namespace test2 { // CHECK-NEXT: br i1 [[EMPTY]], // CHECK: [[PAST:%.*]] = phi [[A]]* [ [[CUR]], {{%.*}} ], [ [[DEL:%.*]], {{%.*}} ] // CHECK-NEXT: [[DEL]] = getelementptr inbounds [[A]], [[A]]* [[PAST]], i64 -1 - // CHECK-NEXT: invoke void @_ZN5test21AD1Ev([[A]]* [[DEL]]) + // CHECKv03-NEXT: invoke void @_ZN5test21AD1Ev([[A]]* [[DEL]]) + // CHECKv11-NEXT: call void @_ZN5test21AD1Ev([[A]]* [[DEL]]) // CHECK: [[T0:%.*]] = icmp eq [[A]]* [[DEL]], [[BEGIN]] // CHECK-NEXT: br i1 [[T0]], } diff --git a/test/CodeGenCXX/pr24097.cpp b/test/CodeGenCXX/pr24097.cpp index 122bf88506d3..cdf78d20cbda 100644 --- a/test/CodeGenCXX/pr24097.cpp +++ b/test/CodeGenCXX/pr24097.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -triple=x86_64-pc-linux -fvisibility hidden -emit-llvm -O1 -disable-llvm-optzns -o - | FileCheck %s +// RUN: %clang_cc1 %s -triple=x86_64-pc-linux -fvisibility hidden -emit-llvm -O1 -disable-llvm-passes -o - | FileCheck %s struct Filter { virtual void Foo(); diff --git a/test/CodeGenCXX/pr30731.cpp b/test/CodeGenCXX/pr30731.cpp new file mode 100644 index 000000000000..078f21ceda4f --- /dev/null +++ b/test/CodeGenCXX/pr30731.cpp @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -triple i386-pc-win32 -emit-llvm -flto -std=c++11 -o - %s | FileCheck %s + +struct A { + virtual ~A(); +}; + +struct B {}; + +struct C { + virtual void f(); +}; + +struct S : A, virtual B, C { + void f() override; +}; + +void f(S* s) { s->f(); } + +// CHECK-LABEL: define void @"\01?f@@YAXPAUS@@@Z" +// CHECK: call +// CHECK: ret void diff --git a/test/CodeGenCXX/pragma-loop-distribute.cpp b/test/CodeGenCXX/pragma-loop-distribute.cpp new file mode 100644 index 000000000000..a6925593b818 --- /dev/null +++ b/test/CodeGenCXX/pragma-loop-distribute.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 -emit-llvm -o - %s | FileCheck %s + +void while_test(int *List, int Length, int *List2, int Length2) { + // CHECK: define {{.*}} @_Z10while_test + int i = 0; + +#pragma clang loop distribute(enable) + while (i < Length) { + // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_1:.*]] + List[i] = i * 2; + i++; + } + + i = 0; + while (i < Length2) { + // CHECK-NOT: br label {{.*}}, !llvm.loop + List2[i] = i * 2; + i++; + } +} + +// CHECK: ![[LOOP_1]] = distinct !{![[LOOP_1]], ![[DISTRIBUTE_ENABLE:.*]]} +// CHECK: ![[DISTRIBUTE_ENABLE]] = !{!"llvm.loop.distribute.enable", i1 true} diff --git a/test/CodeGenCXX/pragma-loop-safety.cpp b/test/CodeGenCXX/pragma-loop-safety.cpp index 393f0a3e43fe..c6ce82737d0b 100644 --- a/test/CodeGenCXX/pragma-loop-safety.cpp +++ b/test/CodeGenCXX/pragma-loop-safety.cpp @@ -10,12 +10,12 @@ void vectorize_test(int *List, int Length) { #pragma clang loop vectorize(assume_safety) interleave(disable) unroll(disable) for (int i = 0; i < Length; i++) { // CHECK: [[RHIV1:.+]] = load i32, i32* [[IV1]], {{.*}}!llvm.mem.parallel_loop_access ![[LOOP1_ID]] - // CHECK-NEXT: [[CALC1:.+]] = mul nsw i32[[RHIV1]], 2 - // CHECK-NEXT: [[SIV1:.+]] = load i32, i32* [[IV1]]{{.*}}!llvm.mem.parallel_loop_access ![[LOOP1_ID]] - // CHECK-NEXT: [[INDEX1:.+]] = sext i32[[SIV1]] to i64 - // CHECK-NEXT: [[ARRAY1:.+]] = load i32*, i32** [[LIST1:.*]], {{.*}}!llvm.mem.parallel_loop_access ![[LOOP1_ID]] - // CHECK-NEXT: [[PTR1:.+]] = getelementptr inbounds i32, i32*[[ARRAY1]], i64[[INDEX1]] - // CHECK-NEXT: store i32[[CALC1]], i32*[[PTR1]], {{.*}}!llvm.mem.parallel_loop_access ![[LOOP1_ID]] + // CHECK-DAG: [[CALC1:.+]] = mul nsw i32[[RHIV1]], 2 + // CHECK-DAG: [[SIV1:.+]] = load i32, i32* [[IV1]]{{.*}}!llvm.mem.parallel_loop_access ![[LOOP1_ID]] + // CHECK-DAG: [[INDEX1:.+]] = sext i32[[SIV1]] to i64 + // CHECK-DAG: [[ARRAY1:.+]] = load i32*, i32** [[LIST1:.*]], {{.*}}!llvm.mem.parallel_loop_access ![[LOOP1_ID]] + // CHECK-DAG: [[PTR1:.+]] = getelementptr inbounds i32, i32*[[ARRAY1]], i64[[INDEX1]] + // CHECK: store i32[[CALC1]], i32*[[PTR1]], {{.*}}!llvm.mem.parallel_loop_access ![[LOOP1_ID]] // CHECK-NEXT: br label [[LOOP1_INC:[^,]+]] List[i] = i * 2; @@ -33,12 +33,12 @@ void interleave_test(int *List, int Length) { #pragma clang loop interleave(assume_safety) vectorize(disable) unroll(disable) for (int i = 0; i < Length; i++) { // CHECK: [[RHIV2:.+]] = load i32, i32* [[IV2]], {{.*}}!llvm.mem.parallel_loop_access ![[LOOP2_ID]] - // CHECK-NEXT: [[CALC2:.+]] = mul nsw i32[[RHIV2]], 2 - // CHECK-NEXT: [[SIV2:.+]] = load i32, i32* [[IV2]]{{.*}}!llvm.mem.parallel_loop_access ![[LOOP2_ID]] - // CHECK-NEXT: [[INDEX2:.+]] = sext i32[[SIV2]] to i64 - // CHECK-NEXT: [[ARRAY2:.+]] = load i32*, i32** [[LIST2:.*]], {{.*}}!llvm.mem.parallel_loop_access ![[LOOP2_ID]] - // CHECK-NEXT: [[PTR2:.+]] = getelementptr inbounds i32, i32*[[ARRAY2]], i64[[INDEX2]] - // CHECK-NEXT: store i32[[CALC2]], i32*[[PTR2]], {{.*}}!llvm.mem.parallel_loop_access ![[LOOP2_ID]] + // CHECK-DAG: [[CALC2:.+]] = mul nsw i32[[RHIV2]], 2 + // CHECK-DAG: [[SIV2:.+]] = load i32, i32* [[IV2]]{{.*}}!llvm.mem.parallel_loop_access ![[LOOP2_ID]] + // CHECK-DAG: [[INDEX2:.+]] = sext i32[[SIV2]] to i64 + // CHECK-DAG: [[ARRAY2:.+]] = load i32*, i32** [[LIST2:.*]], {{.*}}!llvm.mem.parallel_loop_access ![[LOOP2_ID]] + // CHECK-DAG: [[PTR2:.+]] = getelementptr inbounds i32, i32*[[ARRAY2]], i64[[INDEX2]] + // CHECK: store i32[[CALC2]], i32*[[PTR2]], {{.*}}!llvm.mem.parallel_loop_access ![[LOOP2_ID]] // CHECK-NEXT: br label [[LOOP2_INC:[^,]+]] List[i] = i * 2; diff --git a/test/CodeGenCXX/predefined-expr-cxx14.cpp b/test/CodeGenCXX/predefined-expr-cxx14.cpp index 1f035757dea9..dd531e3112b6 100644 --- a/test/CodeGenCXX/predefined-expr-cxx14.cpp +++ b/test/CodeGenCXX/predefined-expr-cxx14.cpp @@ -17,8 +17,8 @@ // CHECK-DAG: @__func__._ZN24ClassInTopLevelNamespace25topLevelNamespaceFunctionEv = private unnamed_addr constant [26 x i8] c"topLevelNamespaceFunction\00" // CHECK-DAG: @__PRETTY_FUNCTION__._ZN24ClassInTopLevelNamespace25topLevelNamespaceFunctionEv = private unnamed_addr constant [60 x i8] c"auto *ClassInTopLevelNamespace::topLevelNamespaceFunction()\00" -// CHECK-DAG: @__func__.___ZN16ClassBlockConstrD2Ev_block_invoke = private unnamed_addr constant [41 x i8] c"___ZN16ClassBlockConstrD2Ev_block_invoke\00" -// CHECK-DAG: @__func__.___ZN16ClassBlockConstrC2Ev_block_invoke = private unnamed_addr constant [41 x i8] c"___ZN16ClassBlockConstrC2Ev_block_invoke\00" +// CHECK-DAG: @__func__.___ZN16ClassBlockConstrD2Ev_block_invoke = private unnamed_addr constant [31 x i8] c"~ClassBlockConstr_block_invoke\00" +// CHECK-DAG: @__func__.___ZN16ClassBlockConstrC2Ev_block_invoke = private unnamed_addr constant [30 x i8] c"ClassBlockConstr_block_invoke\00" int printf(const char * _Format, ...); diff --git a/test/CodeGenCXX/reference-cast.cpp b/test/CodeGenCXX/reference-cast.cpp index 02498a36a180..54faa6488116 100644 --- a/test/CodeGenCXX/reference-cast.cpp +++ b/test/CodeGenCXX/reference-cast.cpp @@ -193,4 +193,4 @@ namespace PR10650 { // CHECK: store i64 } -// CHECK: attributes [[NUW]] = { nounwind{{.*}} } +// CHECK: attributes [[NUW]] = { noinline nounwind{{.*}} } diff --git a/test/CodeGenCXX/regcall.cpp b/test/CodeGenCXX/regcall.cpp new file mode 100644 index 000000000000..0cc6ad009324 --- /dev/null +++ b/test/CodeGenCXX/regcall.cpp @@ -0,0 +1,97 @@ +// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -std=c++11 %s -o - | FileCheck -check-prefix=CHECK-LIN -check-prefix=CHECK-LIN64 %s +// RUN: %clang_cc1 -triple i386-linux-gnu -emit-llvm -std=c++11 %s -o - | FileCheck -check-prefix=CHECK-LIN -check-prefix=CHECK-LIN32 %s +// RUN: %clang_cc1 -triple x86_64-windows-msvc -emit-llvm -std=c++11 %s -o - -DWIN_TEST | FileCheck -check-prefix=CHECK-WIN64 %s +// RUN: %clang_cc1 -triple i386-windows-msvc -emit-llvm -std=c++11 %s -o - -DWIN_TEST | FileCheck -check-prefix=CHECK-WIN32 %s + +int __regcall foo(int i); + +int main() +{ + int p = 0, _data; + auto lambda = [&](int parameter) -> int { + _data = foo(parameter); + return _data; + }; + return lambda(p); +} +// CHECK-LIN: call x86_regcallcc {{.+}} @_Z15__regcall3__foo +// CHECK-WIN64: call x86_regcallcc {{.+}} @"\01?foo@@YwHH@Z" +// CHECK-WIN32: call x86_regcallcc {{.+}} @"\01?foo@@YwHH@Z" + +int __regcall foo (int i){ + return i; +} +// CHECK-LIN: define x86_regcallcc {{.+}}@_Z15__regcall3__foo +// CHECK-WIN64: define x86_regcallcc {{.+}}@"\01?foo@@YwHH@Z" +// CHECK-WIN32: define x86_regcallcc {{.+}}@"\01?foo@@YwHH@Z" + +// used to give a body to test_class functions +static int x = 0; +class test_class { + int a; +public: +#ifndef WIN_TEST + __regcall +#endif + test_class(){++x;} + // CHECK-LIN-DAG: define linkonce_odr x86_regcallcc void @_ZN10test_classC1Ev + // CHECK-LIN-DAG: define linkonce_odr x86_regcallcc void @_ZN10test_classC2Ev + // Windows ignores calling convention on constructor/destructors. + // CHECK-WIN64-DAG: define linkonce_odr %class.test_class* @"\01??0test_class@@QEAA@XZ" + // CHECK-WIN32-DAG: define linkonce_odr x86_thiscallcc %class.test_class* @"\01??0test_class@@QAE@XZ" + +#ifndef WIN_TEST + __regcall +#endif + ~test_class(){--x;} + // CHECK-LIN-DAG: define linkonce_odr x86_regcallcc void @_ZN10test_classD2Ev + // CHECK-LIN-DAG: define linkonce_odr x86_regcallcc void @_ZN10test_classD1Ev + // Windows ignores calling convention on constructor/destructors. + // CHECK-WIN64-DAG: define linkonce_odr void @"\01??_Dtest_class@@QEAA@XZ" + // CHECK-WIN32-DAG: define linkonce_odr x86_thiscallcc void @"\01??_Dtest_class@@QAE@XZ" + + test_class& __regcall operator+=(const test_class&){ + return *this; + } + // CHECK-LIN-DAG: define linkonce_odr x86_regcallcc dereferenceable(4) %class.test_class* @_ZN10test_classpLERKS_ + // CHECK-WIN64-DAG: define linkonce_odr x86_regcallcc dereferenceable(4) %class.test_class* @"\01??Ytest_class@@QEAwAEAV0@AEBV0@@Z" + // CHECK-WIN32-DAG: define linkonce_odr x86_regcallcc dereferenceable(4) %class.test_class* @"\01??Ytest_class@@QAwAAV0@ABV0@@Z" + void __regcall do_thing(){} + // CHECK-LIN-DAG: define linkonce_odr x86_regcallcc void @_ZN10test_class20__regcall3__do_thingEv + // CHECK-WIN64-DAG: define linkonce_odr x86_regcallcc void @"\01?do_thing@test_class@@QEAwXXZ" + // CHECK-WIN32-DAG: define linkonce_odr x86_regcallcc void @"\01?do_thing@test_class@@QAwXXZ" + + template<typename T> + void __regcall tempFunc(T i){} + // CHECK-LIN-DAG: define linkonce_odr x86_regcallcc void @_ZN10test_class20__regcall3__tempFuncIiEEvT_ + // CHECK-WIN64-DAG: define linkonce_odr x86_regcallcc void @"\01??$freeTempFunc@H@@YwXH@Z" + // CHECK-WIN32-DAG: define linkonce_odr x86_regcallcc void @"\01??$freeTempFunc@H@@YwXH@Z" +}; + +bool __regcall operator ==(const test_class&, const test_class&){ --x; return false;} +// CHECK-LIN-DAG: define x86_regcallcc zeroext i1 @_ZeqRK10test_classS1_ +// CHECK-WIN64-DAG: define x86_regcallcc zeroext i1 @"\01??8@Yw_NAEBVtest_class@@0@Z" +// CHECK-WIN32-DAG: define x86_regcallcc zeroext i1 @"\01??8@Yw_NABVtest_class@@0@Z" + +test_class __regcall operator""_test_class (unsigned long long) { ++x; return test_class{};} +// CHECK-LIN64-DAG: define x86_regcallcc %class.test_class @_Zli11_test_classy(i64) +// CHECK-LIN32-DAG: define x86_regcallcc void @_Zli11_test_classy(%class.test_class* inreg noalias sret %agg.result, i64) +// CHECK-WIN64-DAG: \01??__K_test_class@@Yw?AVtest_class@@_K@Z" +// CHECK-WIN32-DAG: \01??__K_test_class@@Yw?AVtest_class@@_K@Z" + +template<typename T> +void __regcall freeTempFunc(T i){} +// CHECK-LIN-DAG: define linkonce_odr x86_regcallcc void @_Z24__regcall3__freeTempFuncIiEvT_ +// CHECK-WIN64-DAG: define linkonce_odr x86_regcallcc void @"\01??$freeTempFunc@H@@YwXH@Z" +// CHECK-WIN32-DAG: define linkonce_odr x86_regcallcc void @"\01??$freeTempFunc@H@@YwXH@Z" + +// class to force generation of functions +void force_gen() { + test_class t; + test_class t2 = 12_test_class; + t += t2; + auto t3 = 100_test_class; + t3.tempFunc(1); + freeTempFunc(1); + t3.do_thing(); +} diff --git a/test/CodeGenCXX/rtti-mingw64.cpp b/test/CodeGenCXX/rtti-mingw64.cpp new file mode 100644 index 000000000000..818b11b64bc5 --- /dev/null +++ b/test/CodeGenCXX/rtti-mingw64.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -triple x86_64-windows-gnu %s -emit-llvm -o - | FileCheck %s +struct A { int a; }; +struct B : virtual A { int b; }; +B b; + +// CHECK: @_ZTI1B = linkonce_odr constant { i8*, i8*, i32, i32, i8*, i64 } +// CHECK-SAME: i8* bitcast (i8** getelementptr inbounds (i8*, i8** @_ZTVN10__cxxabiv121__vmi_class_type_infoE, i64 2) to i8*), +// CHECK-SAME: i8* getelementptr inbounds ([3 x i8], [3 x i8]* @_ZTS1B, i32 0, i32 0), +// CHECK-SAME: i32 0, +// CHECK-SAME: i32 1, +// CHECK-SAME: i8* bitcast ({ i8*, i8* }* @_ZTI1A to i8*), +// This i64 is important, it should be an i64, not an i32. +// CHECK-SAME: i64 -6141 }, comdat diff --git a/test/CodeGenCXX/rtti-qualfn.cpp b/test/CodeGenCXX/rtti-qualfn.cpp new file mode 100644 index 000000000000..329cd50547ab --- /dev/null +++ b/test/CodeGenCXX/rtti-qualfn.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -std=c++1z -I%S %s -triple x86_64-linux-gnu -emit-llvm -o - -fcxx-exceptions | FileCheck %s + +#include "typeinfo" + +struct A {}; + +// CHECK-DAG: @_ZTIFvvE = linkonce_odr constant { i8*, i8* } { i8* bitcast (i8** getelementptr inbounds (i8*, i8** @_ZTVN10__cxxabiv120__function_type_infoE, i64 2) to i8*), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @_ZTSFvvE, i32 0, i32 0) }, comdat +// CHECK-DAG: @_ZTIPDoFvvE = linkonce_odr constant { i8*, i8*, i32, i8* } { i8* bitcast (i8** getelementptr inbounds (i8*, i8** @_ZTVN10__cxxabiv119__pointer_type_infoE, i64 2) to i8*), i8* getelementptr inbounds ([8 x i8], [8 x i8]* @_ZTSPDoFvvE, i32 0, i32 0), i32 64, i8* bitcast ({ i8*, i8* }* @_ZTIFvvE to i8*) }, comdat +auto &ti_noexcept_ptr = typeid(void (A::*)() noexcept); +// CHECK-DAG: @_ZTIM1ADoFvvE = linkonce_odr constant { i8*, i8*, i32, i8*, i8* } { i8* bitcast (i8** getelementptr inbounds (i8*, i8** @_ZTVN10__cxxabiv129__pointer_to_member_type_infoE, i64 2) to i8*), i8* getelementptr inbounds ([10 x i8], [10 x i8]* @_ZTSM1ADoFvvE, i32 0, i32 0), i32 64, i8* bitcast ({ i8*, i8* }* @_ZTIFvvE to i8*), i8* bitcast ({ i8*, i8* }* @_ZTI1A to i8*) }, comdat +auto &ti_noexcept_memptr = typeid(void (A::*)() noexcept); + +// CHECK-LABEL: define void @_Z1fv( +__attribute__((noreturn)) void f() noexcept { + // CHECK: call void @__cxa_throw({{.*}}@_ZTIPDoFvvE + throw f; +} + +// CHECK-LABEL: define void @_Z1gM1ADoFvvE( +void g(__attribute__((noreturn)) void (A::*p)() noexcept) { + // CHECK: call void @__cxa_throw({{.*}}@_ZTIM1ADoFvvE + throw p; +} diff --git a/test/CodeGenCXX/runtime-dllstorage.cpp b/test/CodeGenCXX/runtime-dllstorage.cpp new file mode 100644 index 000000000000..76c002c0e407 --- /dev/null +++ b/test/CodeGenCXX/runtime-dllstorage.cpp @@ -0,0 +1,158 @@ +// RUN: %clang_cc1 -triple i686-windows-msvc -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-MS -check-prefix CHECK-MS-DYNAMIC +// RUN: %clang_cc1 -triple i686-windows-msvc -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -flto-visibility-public-std -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-MS -check-prefix CHECK-MS-STATIC + +// RUN: %clang_cc1 -triple i686-windows-itanium -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-IA -check-prefix CHECK-DYNAMIC-IA -check-prefix CHECK-DYNAMIC-NODECL-IA -check-prefix CHECK-DYANMIC-IA-CXA-ATEXIT +// RUN: %clang_cc1 -triple i686-windows-itanium -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -flto-visibility-public-std -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-IA -check-prefix CHECK-STATIC-IA -check-prefix CHECK-STATIC-NODECL-IA -check-prefix CHECK-IA-STATIC-CXA-ATEXIT +// RUN: %clang_cc1 -triple i686-windows-itanium -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -DIMPORT_DECLARATIONS -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-IA -check-prefix CHECK-DYNAMIC-IA -check-prefix CHECK-DYNAMIC-IMPORT-IA -check-prefix CHECK-DYANMIC-IA-CXA-ATEXIT +// RUN: %clang_cc1 -triple i686-windows-itanium -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -flto-visibility-public-std -DIMPORT_DECLARATIONS -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-IA -check-prefix CHECK-STATIC-IA -check-prefix CHECK-STATIC-IMPORT-IA -check-prefix CHECK-IA-STATIC-CXA-ATEXIT +// RUN: %clang_cc1 -triple i686-windows-itanium -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -DEXPORT_DECLARATIONS -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-IA -check-prefix CHECK-DYNAMIC-IA -check-prefix CHECK-DYANMIC-IA-CXA-ATEXIT +// RUN: %clang_cc1 -triple i686-windows-itanium -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -flto-visibility-public-std -DEXPORT_DECLARATIONS -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-IA -check-prefix CHECK-STATIC-IA -check-prefix CHECK-IA-STATIC-CXA-ATEXIT +// RUN: %clang_cc1 -triple i686-windows-itanium -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -DDECL -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-IA -check-prefix CHECK-DYNAMIC-IA -check-prefix CHECK-DYNAMIC-DECL-IA -check-prefix CHECK-DYANMIC-IA-CXA-ATEXIT +// RUN: %clang_cc1 -triple i686-windows-itanium -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -flto-visibility-public-std -DDECL -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-IA -check-prefix CHECK-STATIC-IA -check-prefix CHECK-STATIC-DECL-IA -check-prefix CHECK-IA-STATIC-CXA-ATEXIT +// %clang_cc1 -triple i686-windows-itanium -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -fno-use-cxa-atexit -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-IA -check-prefix CHECK-DYNAMIC-IA -check-prefix CHECK-DYNAMIC-IA-ATEXIT +// %clang_cc1 -triple i686-windows-itanium -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -fno-use-cxa-atexit -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-IA -check-prefix CHECK-STATIC-IA -check-prefix CHECK-STATIC-IA-ATEXIT + +// RUN: %clang_cc1 -triple i686-windows-gnu -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-IA -check-prefix CHECK-DYNAMIC-IA +// RUN: %clang_cc1 -triple i686-windows-gnu -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -flto-visibility-public-std -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-IA -check-prefix CHECK-STATIC-IA +// RUN: %clang_cc1 -triple i686-windows-cygnus -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-IA -check-prefix CHECK-DYNAMIC-IA +// RUN: %clang_cc1 -triple i686-windows-cygnus -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -flto-visibility-public-std -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-IA -check-prefix CHECK-STATIC-IA + +#if defined(IMPORT_DECLARATIONS) +namespace __cxxabiv1 { +extern "C" { +__declspec(dllimport) void __cxa_guard_acquire(unsigned long long *); +__declspec(dllimport) unsigned char *__cxa_allocate_exception(unsigned long); +} +extern "C" __declspec(dllimport) void __cxa_guard_release(unsigned long long *); +} +namespace std { +__declspec(dllimport) __declspec(noreturn) void terminate(); +} +#elif defined(EXPORT_DECLARATIONS) +namespace __cxxabiv1 { +extern "C" { +__declspec(dllexport) void __cxa_guard_acquire(unsigned long long *); +__declspec(dllexport) unsigned char *__cxa_allocate_exception(unsigned long); +} +extern "C" void __declspec(dllexport) __cxa_guard_release(unsigned long long *); +} +namespace std { +__declspec(dllexport) __declspec(noreturn) void terminate(); +} +#elif defined(DECL) +namespace __cxxabiv1 { +extern "C" unsigned char *__cxa_allocate_exception(unsigned long); +} +namespace std { +__declspec(noreturn) void terminate(); +} +#else +namespace std { +__declspec(noreturn) void terminate(); +} +#endif + +struct s { + s() = default; + s(unsigned char) { throw 0; } + int m() const; +}; + +struct t { + ~t(); + int m() const; +}; + +struct u { + ~u(); +}; + +s o; +thread_local t t; +u v; +__declspec(thread) s q; + +void __declspec(noinline) f() { + throw 0; +} + +void g(); +void __declspec(noinline) h() { + try { + g(); + } catch (const int &) { + return; + } catch (...) { + throw; + } +} + +void i() { + s r(static_cast<unsigned char>('\t')); +} + +int j() { + static thread_local struct t v; + static struct t *w = new struct t; + return w->m() ? v.m() : w->m(); +} + +void k() noexcept { + g(); +} + +void l() { + std::terminate(); +} + +// CHECK-MS-DAG: @_Init_thread_epoch = external thread_local global i32 +// CHECK-MS-DAG: declare i32 @__tlregdtor(void ()*) +// CHECK-MS-DAG: declare i32 @atexit(void ()*) +// CHECK-MS-DYNAMIC-DAG: declare dllimport {{.*}} void @_CxxThrowException +// CHECK-MS-STATIC-DAG: declare {{.*}} void @_CxxThrowException +// CHECK-MS-DAG: declare noalias i8* @"\01??2@YAPAXI@Z" +// CHECK-MS-DAG: declare void @_Init_thread_header(i32*) +// CHECK-MS-DAG: declare void @_Init_thread_footer(i32*) + +// CHECK-IA-DAG: declare i32 @__gxx_personality_v0(...) +// CHECK-IA-DAG: define linkonce_odr hidden void @__clang_call_terminate(i8*) + +// CHECK-DYNAMIC-IA-DAG: declare dllimport i32 @__cxa_thread_atexit(void (i8*)*, i8*, i8*) +// CHECK-DYNAMIC-IA-DAG: declare dllimport i32 @__cxa_atexit(void (i8*)*, i8*, i8*) +// CHECK-DYNAMIC-IA-DECL-DAG: declare i8* @__cxa_allocate_exception(i32) +// CHECK-DYNAMIC-IA-NODECL-DAG: declare dllimport i8* @__cxa_allocate_exception(i32) +// CHECK-DYNAMIC-IA-IMPORT-DAG: declare dllimport i8* @__cxa_allocate_exception(i32) +// CHECK-DYNAMIC-IA-EXPORT-DAG: declare dllimport i8* @__cxa_allocate_exception(i32) +// CHECK-DYNAMIC-IA-DAG: declare dllimport void @__cxa_throw(i8*, i8*, i8*) +// CHECK-DYNAMIC-DECL-IA-DAG: declare dllimport i32 @__cxa_guard_acquire(i64*) +// CHECK-DYNAMIC-NODECL-IA-DAG: declare dllimport i32 @__cxa_guard_acquire(i64*) +// CHECK-DYNAMIC-IMPORT-IA-DAG: declare dllimport i32 @__cxa_guard_acquire(i64*) +// CHECK-DYNAMIC-EXPORT-IA-DAG: declare dllexport i32 @__cxa_guard_acquire(i64*) +// CHECK-IA-DAG: declare noalias i8* @_Znwj(i32) +// CHECK-DYNAMIC-DECL-IA-DAG: declare dllimport void @__cxa_guard_release(i64*) +// CHECK-DYNAMIC-NODECL-IA-DAG: declare dllimport void @__cxa_guard_release(i64*) +// CHECK-DYNAMIC-IMPORT-IA-DAG: declare dllimport void @__cxa_guard_release(i64*) +// CHECK-DYNAMIC-EXPORT-IA-DAG: declare dllimport void @__cxa_guard_release(i64*) +// CHECK-DYANMIC-IA-DAG: declare dllimport void @_ZSt9terminatev() +// CHECK-DYNAMIC-NODECL-IA-DAG: declare void @_ZSt9terminatev() +// CHECK-DYNAMIC-IMPORT-IA-DAG: declare dllimport void @_ZSt9terminatev() +// CHECK-DYNAMIC-EXPORT-IA-DAG: declare dllexport void @_ZSt9terminatev() + +// CHECK-STATIC-IA-DAG: declare i32 @__cxa_thread_atexit(void (i8*)*, i8*, i8*) +// CHECK-STATIC-IA-DAG: declare i32 @__cxa_atexit(void (i8*)*, i8*, i8*) +// CHECK-STATIC-IA-DAG: declare i8* @__cxa_allocate_exception(i32) +// CHECK-STATIC-IA-DAG: declare void @__cxa_throw(i8*, i8*, i8*) +// CHECK-STATIC-DECL-IA-DAG: declare i32 @__cxa_guard_acquire(i64*) +// CHECK-STATIC-NODECL-IA-DAG: declare i32 @__cxa_guard_acquire(i64*) +// CHECK-STATIC-IMPORT-IA-DAG: declare i32 @__cxa_guard_acquire(i64*) +// CHECK-STATIC-EXPORT-IA-DAG: declare i32 @__cxa_guard_acquire(i64*) +// CHECK-IA-DAG: declare noalias i8* @_Znwj(i32) +// CHECK-STATIC-DECL-IA-DAG: declare void @__cxa_guard_release(i64*) +// CHECK-STATIC-NODECL-IA-DAG: declare void @__cxa_guard_release(i64*) +// CHECK-STATIC-IMPORT-IA-DAG: declare void @__cxa_guard_release(i64*) +// CHECK-STATIC-EXPORT-IA-DAG: declare void @__cxa_guard_release(i64*) +// CHECK-STATIC-IA-DAG: declare void @_ZSt9terminatev() +// CHECK-STATIC-NODECL-IA-DAG: declare void @_ZSt9terminatev() +// CHECK-STATIC-IMPORT-IA-DAG: declare void @_ZSt9terminatev() +// CHECK-STATIC-EXPORT-IA-DAG: declare dllexport void @_ZSt9terminatev() + diff --git a/test/CodeGenCXX/sanitize-dtor-bit-field.cpp b/test/CodeGenCXX/sanitize-dtor-bit-field.cpp index d4497f6aac0b..19c46ba64a98 100644 --- a/test/CodeGenCXX/sanitize-dtor-bit-field.cpp +++ b/test/CodeGenCXX/sanitize-dtor-bit-field.cpp @@ -1,6 +1,6 @@ // Test -fsanitize-memory-use-after-dtor -// RUN: %clang_cc1 -O0 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s -// RUN: %clang_cc1 -O1 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -O0 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-passes -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -O1 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-passes -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s // 24 bytes total struct Packed { diff --git a/test/CodeGenCXX/sanitize-dtor-derived-class.cpp b/test/CodeGenCXX/sanitize-dtor-derived-class.cpp index f3134711824d..618096aeebd7 100644 --- a/test/CodeGenCXX/sanitize-dtor-derived-class.cpp +++ b/test/CodeGenCXX/sanitize-dtor-derived-class.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s -// RUN: %clang_cc1 -O1 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-passes -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -O1 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-passes -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s // Base dtor poisons members // Complete dtor poisons vtable ptr after destroying members and diff --git a/test/CodeGenCXX/sanitize-dtor-tail-call.cpp b/test/CodeGenCXX/sanitize-dtor-tail-call.cpp index de2fd8c75c88..d6f5719c8bf3 100644 --- a/test/CodeGenCXX/sanitize-dtor-tail-call.cpp +++ b/test/CodeGenCXX/sanitize-dtor-tail-call.cpp @@ -1,6 +1,6 @@ // Test -fsanitize-memory-use-after-dtor -// RUN: %clang_cc1 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s -// RUN: %clang_cc1 -O1 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-passes -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -O1 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-passes -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s struct Simple { int x_; diff --git a/test/CodeGenCXX/sanitize-dtor-trivial.cpp b/test/CodeGenCXX/sanitize-dtor-trivial.cpp index 39f580af97e7..9e328c0a2895 100644 --- a/test/CodeGenCXX/sanitize-dtor-trivial.cpp +++ b/test/CodeGenCXX/sanitize-dtor-trivial.cpp @@ -1,6 +1,6 @@ // Test -fsanitize-memory-use-after-dtor -// RUN: %clang_cc1 -O0 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s -// RUN: %clang_cc1 -O1 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -O0 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-passes -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -O1 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-passes -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s // TODO Success pending on resolution of issue: // https://github.com/google/sanitizers/issues/596 diff --git a/test/CodeGenCXX/sanitize-dtor-vtable.cpp b/test/CodeGenCXX/sanitize-dtor-vtable.cpp index 78be7949c32c..2318ef0d8003 100644 --- a/test/CodeGenCXX/sanitize-dtor-vtable.cpp +++ b/test/CodeGenCXX/sanitize-dtor-vtable.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -O0 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s -// RUN: %clang_cc1 -O1 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -O0 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-passes -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -O1 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-passes -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s class A { public: diff --git a/test/CodeGenCXX/skip-vtable-pointer-initialization.cpp b/test/CodeGenCXX/skip-vtable-pointer-initialization.cpp index 4734c02bc52e..83a2d617e878 100644 --- a/test/CodeGenCXX/skip-vtable-pointer-initialization.cpp +++ b/test/CodeGenCXX/skip-vtable-pointer-initialization.cpp @@ -11,7 +11,7 @@ struct A { }; // CHECK-LABEL: define void @_ZN5Test11AD2Ev -// CHECK-NOT: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN5Test11AE, i64 0, i64 2) to i32 (...)**), i32 (...)*** +// CHECK-NOT: store i32 (...)** bitcast (i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTVN5Test11AE, i64 0, i64 2) to i32 (...)**), i32 (...)*** A::~A() { } @@ -27,7 +27,7 @@ struct A { }; // CHECK-LABEL: define void @_ZN5Test21AD2Ev -// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN5Test21AE, i32 0, i32 2) to i32 (...)**), i32 (...)*** +// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTVN5Test21AE, i32 0, inrange i32 0, i32 2) to i32 (...)**), i32 (...)*** A::~A() { f(); } @@ -50,7 +50,7 @@ struct A { }; // CHECK-LABEL: define void @_ZN5Test31AD2Ev -// CHECK-NOT: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN5Test31AE, i32 0, i32 2) to i32 (...)**), i32 (...)*** +// CHECK-NOT: store i32 (...)** bitcast (i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTVN5Test31AE, i32 0, inrange i32 0, i32 2) to i32 (...)**), i32 (...)*** A::~A() { } @@ -76,7 +76,7 @@ struct A { }; // CHECK-LABEL: define void @_ZN5Test41AD2Ev -// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN5Test41AE, i32 0, i32 2) to i32 (...)**), i32 (...)*** +// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTVN5Test41AE, i32 0, inrange i32 0, i32 2) to i32 (...)**), i32 (...)*** A::~A() { } @@ -100,7 +100,7 @@ struct A { }; // CHECK-LABEL: define void @_ZN5Test51AD2Ev -// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN5Test51AE, i32 0, i32 2) to i32 (...)**), i32 (...)*** +// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTVN5Test51AE, i32 0, inrange i32 0, i32 2) to i32 (...)**), i32 (...)*** A::~A() { } @@ -128,7 +128,7 @@ struct A { }; // CHECK-LABEL: define void @_ZN5Test61AD2Ev -// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN5Test61AE, i32 0, i32 2) to i32 (...)**), i32 (...)*** +// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTVN5Test61AE, i32 0, inrange i32 0, i32 2) to i32 (...)**), i32 (...)*** A::~A() { } @@ -154,7 +154,7 @@ struct A { }; // CHECK-LABEL: define void @_ZN5Test71AD2Ev -// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN5Test71AE, i32 0, i32 2) to i32 (...)**), i32 (...)*** +// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTVN5Test71AE, i32 0, inrange i32 0, i32 2) to i32 (...)**), i32 (...)*** A::~A() { } @@ -180,7 +180,7 @@ struct A { }; // CHECK-LABEL: define void @_ZN5Test81AD2Ev -// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN5Test81AE, i32 0, i32 2) to i32 (...)**), i32 (...)*** +// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTVN5Test81AE, i32 0, inrange i32 0, i32 2) to i32 (...)**), i32 (...)*** A::~A() { } diff --git a/test/CodeGenCXX/stack-reuse-miscompile.cpp b/test/CodeGenCXX/stack-reuse-miscompile.cpp index 63d15fd1e8c9..3b860a573955 100644 --- a/test/CodeGenCXX/stack-reuse-miscompile.cpp +++ b/test/CodeGenCXX/stack-reuse-miscompile.cpp @@ -1,4 +1,4 @@ -// RUN: %clang -S -target armv7l-unknown-linux-gnueabihf -emit-llvm -O1 -mllvm -disable-llvm-optzns -S %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple armv7l-unknown-linux-gnueabihf -emit-llvm -O1 -disable-llvm-passes -std=c++03 %s -o - | FileCheck %s // This test should not to generate llvm.lifetime.start/llvm.lifetime.end for // f function because all temporary objects in this function are used for the diff --git a/test/CodeGenCXX/stack-reuse.cpp b/test/CodeGenCXX/stack-reuse.cpp index d6340ef2c10b..8325604391ae 100644 --- a/test/CodeGenCXX/stack-reuse.cpp +++ b/test/CodeGenCXX/stack-reuse.cpp @@ -132,8 +132,8 @@ void large_auto_object() { int large_combiner_test(S_large s) { // CHECK-LABEL: define i32 @large_combiner_test -// CHECK: [[T1:%.*]] = alloca %struct.Combiner // CHECK: [[T2:%.*]] = alloca %struct.Combiner +// CHECK: [[T1:%.*]] = alloca %struct.Combiner // CHECK: [[T3:%.*]] = call %struct.Combiner* @_ZN8CombinerC1E7S_large(%struct.Combiner* nonnull [[T1]], [9 x i32] %s.coerce) // CHECK: call void @_ZN8Combiner1fEv(%struct.Combiner* nonnull sret [[T2]], %struct.Combiner* nonnull [[T1]]) // CHECK: [[T4:%.*]] = getelementptr inbounds %struct.Combiner, %struct.Combiner* [[T2]], i32 0, i32 0, i32 0, i32 0 diff --git a/test/CodeGenCXX/strict-vtable-pointers.cpp b/test/CodeGenCXX/strict-vtable-pointers.cpp index 33f63994d7c0..21f85b1c5772 100644 --- a/test/CodeGenCXX/strict-vtable-pointers.cpp +++ b/test/CodeGenCXX/strict-vtable-pointers.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -fstrict-vtable-pointers -disable-llvm-optzns -O2 -emit-llvm -o %t.ll +// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -fstrict-vtable-pointers -disable-llvm-passes -O2 -emit-llvm -o %t.ll // RUN: FileCheck --check-prefix=CHECK-CTORS %s < %t.ll // RUN: FileCheck --check-prefix=CHECK-NEW %s < %t.ll // RUN: FileCheck --check-prefix=CHECK-DTORS %s < %t.ll @@ -54,7 +54,7 @@ struct DynamicFrom2Virtuals : // CHECK-NEW-LABEL: define void @_Z12LocalObjectsv() // CHECK-NEW-NOT: @llvm.invariant.group.barrier( -// CHECK-NEW-LABEL: } +// CHECK-NEW-LABEL: {{^}}} void LocalObjects() { DynamicBase1 DB; DB.foo(); @@ -82,12 +82,12 @@ void LocalObjects() { struct DynamicFromVirtualStatic1; // CHECK-CTORS-LABEL: define linkonce_odr void @_ZN25DynamicFromVirtualStatic1C1Ev // CHECK-CTORS-NOT: @llvm.invariant.group.barrier( -// CHECK-CTORS-LABEL: } +// CHECK-CTORS-LABEL: {{^}}} struct DynamicFrom2Virtuals; // CHECK-CTORS-LABEL: define linkonce_odr void @_ZN20DynamicFrom2VirtualsC1Ev // CHECK-CTORS: call i8* @llvm.invariant.group.barrier( -// CHECK-CTORS-LABEL: } +// CHECK-CTORS-LABEL: {{^}}} // CHECK-NEW-LABEL: define void @_Z9Pointers1v() @@ -97,7 +97,7 @@ struct DynamicFrom2Virtuals; // CHECK-NEW: %[[THIS3:.*]] = call i8* @llvm.invariant.group.barrier(i8* %[[THIS2:.*]]) // CHECK-NEW: %[[THIS4:.*]] = bitcast i8* %[[THIS3]] to %[[DynamicDerived:.*]]* // CHECK-NEW: call void @_ZN14DynamicDerivedC1Ev(%[[DynamicDerived:.*]]* %[[THIS4]]) -// CHECK-NEW-LABEL: } +// CHECK-NEW-LABEL: {{^}}} void Pointers1() { DynamicBase1 *DB = new DynamicBase1; DB->foo(); @@ -113,7 +113,7 @@ void Pointers1() { // CHECK-NEW: call void @_ZN14DynamicDerivedC1Ev( // CHECK-NEW: call i8* @llvm.invariant.group.barrier( // CHECK-NEW: call void @_ZN12DynamicBase1C1Ev( -// CHECK-NEW-LABEL: } +// CHECK-NEW-LABEL: {{^}}} void HackingObjects() { DynamicBase1 DB; DB.foo(); @@ -132,7 +132,7 @@ void HackingObjects() { struct DynamicBase1; // CHECK-CTORS-LABEL: define linkonce_odr void @_ZN12DynamicBase1C2Ev( // CHECK-CTORS-NOT: call i8* @llvm.invariant.group.barrier( -// CHECK-CTORS-LABEL: } +// CHECK-CTORS-LABEL: {{^}}} struct DynamicDerived; @@ -147,7 +147,7 @@ struct DynamicDerived; // CHECK-CTORS: %[[THIS5:.*]] = bitcast %struct.DynamicDerived* %[[THIS0]] to i32 (...)*** // CHECK-CTORS: store {{.*}} %[[THIS5]] -// CHECK-CTORS-LABEL: } +// CHECK-CTORS-LABEL: {{^}}} struct DynamicDerivedMultiple; // CHECK-CTORS-LABEL: define linkonce_odr void @_ZN22DynamicDerivedMultipleC2Ev( @@ -166,49 +166,49 @@ struct DynamicDerivedMultiple; // CHECK-CTORS: %[[THIS10:.*]] = bitcast %struct.DynamicDerivedMultiple* %[[THIS0]] to i32 (...)*** -// CHECK-CTORS: store {{.*}} @_ZTV22DynamicDerivedMultiple, i32 0, i32 2) {{.*}} %[[THIS10]] +// CHECK-CTORS: store {{.*}} @_ZTV22DynamicDerivedMultiple, i32 0, inrange i32 0, i32 2) {{.*}} %[[THIS10]] // CHECK-CTORS: %[[THIS11:.*]] = bitcast %struct.DynamicDerivedMultiple* %[[THIS0]] to i8* // CHECK-CTORS: %[[THIS_ADD:.*]] = getelementptr inbounds i8, i8* %[[THIS11]], i64 16 // CHECK-CTORS: %[[THIS12:.*]] = bitcast i8* %[[THIS_ADD]] to i32 (...)*** -// CHECK-CTORS: store {{.*}} @_ZTV22DynamicDerivedMultiple, i32 0, i32 6) {{.*}} %[[THIS12]] -// CHECK-CTORS-LABEL: } +// CHECK-CTORS: store {{.*}} @_ZTV22DynamicDerivedMultiple, i32 0, inrange i32 1, i32 2) {{.*}} %[[THIS12]] +// CHECK-CTORS-LABEL: {{^}}} struct DynamicFromStatic; // CHECK-CTORS-LABEL: define linkonce_odr void @_ZN17DynamicFromStaticC2Ev( // CHECK-CTORS-NOT: @llvm.invariant.group.barrier( -// CHECK-CTORS-LABEL: } +// CHECK-CTORS-LABEL: {{^}}} /** DTORS **/ // CHECK-DTORS-LABEL: define linkonce_odr void @_ZN10StaticBaseD2Ev( // CHECK-DTORS-NOT: call i8* @llvm.invariant.group.barrier( -// CHECK-DTORS-LABEL: } +// CHECK-DTORS-LABEL: {{^}}} // CHECK-DTORS-LABEL: define linkonce_odr void @_ZN25DynamicFromVirtualStatic2D2Ev( // CHECK-DTORS-NOT: invariant.barrier -// CHECK-DTORS-LABEL: } +// CHECK-DTORS-LABEL: {{^}}} // CHECK-DTORS-LABEL: define linkonce_odr void @_ZN17DynamicFromStaticD2Ev // CHECK-DTORS-NOT: call i8* @llvm.invariant.group.barrier( -// CHECK-DTORS-LABEL: } +// CHECK-DTORS-LABEL: {{^}}} // CHECK-DTORS-LABEL: define linkonce_odr void @_ZN22DynamicDerivedMultipleD2Ev( // CHECK-DTORS-LABEL: define linkonce_odr void @_ZN12DynamicBase2D2Ev( // CHECK-DTORS: call i8* @llvm.invariant.group.barrier( -// CHECK-DTORS-LABEL: } +// CHECK-DTORS-LABEL: {{^}}} // CHECK-DTORS-LABEL: define linkonce_odr void @_ZN12DynamicBase1D2Ev // CHECK-DTORS: call i8* @llvm.invariant.group.barrier( -// CHECK-DTORS-LABEL: } +// CHECK-DTORS-LABEL: {{^}}} // CHECK-DTORS-LABEL: define linkonce_odr void @_ZN14DynamicDerivedD2Ev // CHECK-DTORS-NOT: call i8* @llvm.invariant.group.barrier( -// CHECK-DTORS-LABEL: } +// CHECK-DTORS-LABEL: {{^}}} // CHECK-LINK-REQ: !llvm.module.flags = !{![[FIRST:.*]], ![[SEC:.*]]{{.*}}} diff --git a/test/CodeGenCXX/template-instantiation.cpp b/test/CodeGenCXX/template-instantiation.cpp index 90b8099f0a26..3d0ce234371f 100644 --- a/test/CodeGenCXX/template-instantiation.cpp +++ b/test/CodeGenCXX/template-instantiation.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -O1 -disable-llvm-optzns -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -O1 -disable-llvm-passes -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s // CHECK: @_ZN7PR100011xE = global // CHECK-NOT: @_ZN7PR100014kBarE = external global i32 diff --git a/test/CodeGenCXX/temporaries.cpp b/test/CodeGenCXX/temporaries.cpp index c537124c468c..bad51ba353cd 100644 --- a/test/CodeGenCXX/temporaries.cpp +++ b/test/CodeGenCXX/temporaries.cpp @@ -779,6 +779,36 @@ namespace MultipleExtension { } } +namespace ArrayAccess { + struct A { A(int); ~A(); }; + void g(); + void f() { + using T = A[3]; + + // CHECK: call void @_ZN11ArrayAccess1AC1Ei({{.*}}, i32 1 + // CHECK-NOT: @_ZN11ArrayAccess1AD + // CHECK: call void @_ZN11ArrayAccess1AC1Ei({{.*}}, i32 2 + // CHECK-NOT: @_ZN11ArrayAccess1AD + // CHECK: call void @_ZN11ArrayAccess1AC1Ei({{.*}}, i32 3 + // CHECK-NOT: @_ZN11ArrayAccess1AD + A &&a = T{1, 2, 3}[1]; + + // CHECK: call void @_ZN11ArrayAccess1AC1Ei({{.*}}, i32 4 + // CHECK-NOT: @_ZN11ArrayAccess1AD + // CHECK: call void @_ZN11ArrayAccess1AC1Ei({{.*}}, i32 5 + // CHECK-NOT: @_ZN11ArrayAccess1AD + // CHECK: call void @_ZN11ArrayAccess1AC1Ei({{.*}}, i32 6 + // CHECK-NOT: @_ZN11ArrayAccess1AD + A &&b = 2[T{4, 5, 6}]; + + // CHECK: call void @_ZN11ArrayAccess1gEv( + g(); + + // CHECK: call void @_ZN11ArrayAccess1AD + // CHECK: call void @_ZN11ArrayAccess1AD + } +} + namespace PR14130 { struct S { S(int); }; struct U { S &&s; }; diff --git a/test/CodeGenCXX/threadsafe-statics.cpp b/test/CodeGenCXX/threadsafe-statics.cpp index 9aecc2d0db68..7cb7003fc0ca 100644 --- a/test/CodeGenCXX/threadsafe-statics.cpp +++ b/test/CodeGenCXX/threadsafe-statics.cpp @@ -22,6 +22,6 @@ void g() { // NO-TSS-NOT: call void @__cxa_guard_release // NO-TSS: ret void -// WITH-TSS: attributes [[NUW]] = { nounwind{{.*}} } +// WITH-TSS: attributes [[NUW]] = { noinline nounwind{{.*}} } -// NO-TSS: attributes [[NUW]] = { nounwind{{.*}} } +// NO-TSS: attributes [[NUW]] = { noinline nounwind{{.*}} } diff --git a/test/CodeGenCXX/thunks.cpp b/test/CodeGenCXX/thunks.cpp index 3a598b90afe1..26e166c7bf4c 100644 --- a/test/CodeGenCXX/thunks.cpp +++ b/test/CodeGenCXX/thunks.cpp @@ -1,9 +1,5 @@ -// RUN: %clang_cc1 %s -triple=x86_64-pc-linux-gnu -munwind-tables -emit-llvm -o %t -// RUN: %clang_cc1 %s -triple=x86_64-pc-linux-gnu -munwind-tables -emit-llvm -o %t.opt -O1 -disable-llvm-optzns -// RUN: FileCheck %s < %t -// RUN: FileCheck %s < %t.opt -// RUN: FileCheck --check-prefix=CHECK-NONOPT %s < %t -// RUN: FileCheck --check-prefix=CHECK-OPT %s < %t.opt +// RUN: %clang_cc1 %s -triple=x86_64-pc-linux-gnu -munwind-tables -emit-llvm -o - | FileCheck --check-prefix=CHECK --check-prefix=CHECK-NONOPT %s +// RUN: %clang_cc1 %s -triple=x86_64-pc-linux-gnu -munwind-tables -emit-llvm -o - -O1 -disable-llvm-passes | FileCheck --check-prefix=CHECK --check-prefix=CHECK-OPT %s namespace Test1 { @@ -405,4 +401,5 @@ D::~D() {} // CHECK-OPT-LABEL: define linkonce_odr void @_ZN6Test101C3fooEv // CHECK-OPT-LABEL: define linkonce_odr void @_ZThn8_N6Test101C3fooEv -// CHECK: attributes [[NUW]] = { nounwind uwtable{{.*}} } +// CHECK-NONOPT: attributes [[NUW]] = { noinline nounwind uwtable{{.*}} } +// CHECK-OPT: attributes [[NUW]] = { nounwind uwtable{{.*}} } diff --git a/test/CodeGenCXX/ubsan-devirtualized-calls.cpp b/test/CodeGenCXX/ubsan-devirtualized-calls.cpp new file mode 100644 index 000000000000..bc8861aa8314 --- /dev/null +++ b/test/CodeGenCXX/ubsan-devirtualized-calls.cpp @@ -0,0 +1,81 @@ +// RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -emit-llvm -fsanitize=vptr %s -o - | FileCheck %s + +struct Base1 { + virtual void f1() {} +}; + +struct Base2 { + virtual void f1() {} +}; + +struct Derived1 final : Base1 { + void f1() override {} +}; + +struct Derived2 final : Base1, Base2 { + void f1() override {} +}; + +struct Derived3 : Base1 { + void f1() override /* nofinal */ {} +}; + +struct Derived4 final : Base1 { + void f1() override final {} +}; + +// CHECK: [[UBSAN_TI_DERIVED1_1:@[0-9]+]] = private unnamed_addr global {{.*}} i8* bitcast {{.*}} @_ZTI8Derived1 to i8* +// CHECK: [[UBSAN_TI_DERIVED2_1:@[0-9]+]] = private unnamed_addr global {{.*}} i8* bitcast {{.*}} @_ZTI8Derived2 to i8* +// CHECK: [[UBSAN_TI_DERIVED2_2:@[0-9]+]] = private unnamed_addr global {{.*}} i8* bitcast {{.*}} @_ZTI8Derived2 to i8* +// CHECK: [[UBSAN_TI_DERIVED3:@[0-9]+]] = private unnamed_addr global {{.*}} i8* bitcast {{.*}} @_ZTI8Derived3 to i8* +// CHECK: [[UBSAN_TI_BASE1:@[0-9]+]] = private unnamed_addr global {{.*}} i8* bitcast {{.*}} @_ZTI5Base1 to i8* +// CHECK: [[UBSAN_TI_DERIVED4_1:@[0-9]+]] = private unnamed_addr global {{.*}} i8* bitcast {{.*}} @_ZTI8Derived4 to i8* +// CHECK: [[UBSAN_TI_DERIVED4_2:@[0-9]+]] = private unnamed_addr global {{.*}} i8* bitcast {{.*}} @_ZTI8Derived4 to i8* + +// CHECK-LABEL: define void @_Z2t1v +void t1() { + Derived1 d1; + static_cast<Base1 *>(&d1)->f1(); //< Devirt Base1::f1 to Derived1::f1. + // CHECK: %[[D1:[0-9]+]] = ptrtoint %struct.Derived1* %d1 to i{{[0-9]+}}, !nosanitize + // CHECK-NEXT: call void @__ubsan_handle_dynamic_type_cache{{[_a-z]*}}({{.*}} [[UBSAN_TI_DERIVED1_1]] {{.*}}, i{{[0-9]+}} %[[D1]] +} + +// CHECK-LABEL: define void @_Z2t2v +void t2() { + Derived2 d2; + static_cast<Base1 *>(&d2)->f1(); //< Devirt Base1::f1 to Derived2::f1. + // CHECK: %[[D2_1:[0-9]+]] = ptrtoint %struct.Derived2* %d2 to i{{[0-9]+}}, !nosanitize + // CHECK-NEXT: call void @__ubsan_handle_dynamic_type_cache{{[_a-z]*}}({{.*}} [[UBSAN_TI_DERIVED2_1]] {{.*}}, i{{[0-9]+}} %[[D2_1]] +} + +// CHECK-LABEL: define void @_Z2t3v +void t3() { + Derived2 d2; + static_cast<Base2 *>(&d2)->f1(); //< Devirt Base2::f1 to Derived2::f1. + // CHECK: %[[D2_2:[0-9]+]] = ptrtoint %struct.Derived2* %d2 to i{{[0-9]+}}, !nosanitize + // CHECK-NEXT: call void @__ubsan_handle_dynamic_type_cache{{[_a-z]*}}({{.*}} [[UBSAN_TI_DERIVED2_2]] {{.*}}, i{{[0-9]+}} %[[D2_2]] +} + +// CHECK-LABEL: define void @_Z2t4v +void t4() { + Base1 p; + Derived3 *badp = static_cast<Derived3 *>(&p); //< Check that &p isa Derived3. + // CHECK: %[[P1:[0-9]+]] = ptrtoint %struct.Derived3* {{%[0-9]+}} to i{{[0-9]+}}, !nosanitize + // CHECK-NEXT: call void @__ubsan_handle_dynamic_type_cache{{[_a-z]*}}({{.*}} [[UBSAN_TI_DERIVED3]] {{.*}}, i{{[0-9]+}} %[[P1]] + + static_cast<Base1 *>(badp)->f1(); //< No devirt, test 'badp isa Base1'. + // CHECK: %[[BADP1:[0-9]+]] = ptrtoint %struct.Base1* {{%[0-9]+}} to i{{[0-9]+}}, !nosanitize + // CHECK-NEXT: call void @__ubsan_handle_dynamic_type_cache{{[_a-z]*}}({{.*}} [[UBSAN_TI_BASE1]] {{.*}}, i{{[0-9]+}} %[[BADP1]] +} + +// CHECK-LABEL: define void @_Z2t5v +void t5() { + Base1 p; + Derived4 *badp = static_cast<Derived4 *>(&p); //< Check that &p isa Derived4. + // CHECK: %[[P1:[0-9]+]] = ptrtoint %struct.Derived4* {{%[0-9]+}} to i{{[0-9]+}}, !nosanitize + // CHECK-NEXT: call void @__ubsan_handle_dynamic_type_cache{{[_a-z]*}}({{.*}} [[UBSAN_TI_DERIVED4_1]] {{.*}}, i{{[0-9]+}} %[[P1]] + + static_cast<Base1 *>(badp)->f1(); //< Devirt Base1::f1 to Derived4::f1. + // CHECK: %[[BADP1:[0-9]+]] = ptrtoint %struct.Derived4* {{%[0-9]+}} to i{{[0-9]+}}, !nosanitize + // CHECK-NEXT: call void @__ubsan_handle_dynamic_type_cache{{[_a-z]*}}({{.*}} [[UBSAN_TI_DERIVED4_2]] {{.*}}, i{{[0-9]+}} %[[BADP1]] +} diff --git a/test/CodeGenCXX/ubsan-vtable-checks.cpp b/test/CodeGenCXX/ubsan-vtable-checks.cpp new file mode 100644 index 000000000000..80af77d4ea6d --- /dev/null +++ b/test/CodeGenCXX/ubsan-vtable-checks.cpp @@ -0,0 +1,40 @@ +// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-linux -emit-llvm -fsanitize=null %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NULL --check-prefix=ITANIUM +// RUN: %clang_cc1 -std=c++11 -triple x86_64-windows -emit-llvm -fsanitize=null %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NULL --check-prefix=MSABI +// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-linux -emit-llvm -fsanitize=vptr %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-VPTR --check-prefix=ITANIUM +// RUN: %clang_cc1 -std=c++11 -triple x86_64-windows -emit-llvm -fsanitize=vptr %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-VPTR --check-prefix=MSABI +struct T { + virtual ~T() {} + virtual int v() { return 1; } +}; + +struct U : T { + ~U(); + virtual int v() { return 2; } +}; + +U::~U() {} + +// ITANIUM: define i32 @_Z5get_vP1T +// MSABI: define i32 @"\01?get_v +int get_v(T* t) { + // First, we check that vtable is not loaded before a type check. + // CHECK-NULL-NOT: load {{.*}} (%struct.T*{{.*}})**, {{.*}} (%struct.T*{{.*}})*** + // CHECK-NULL: [[UBSAN_CMP_RES:%[0-9]+]] = icmp ne %struct.T* %{{[_a-z0-9]+}}, null + // CHECK-NULL-NEXT: br i1 [[UBSAN_CMP_RES]], label %{{.*}}, label %{{.*}} + // CHECK-NULL: call void @__ubsan_handle_type_mismatch_abort + // Second, we check that vtable is actually loaded once the type check is done. + // CHECK-NULL: load {{.*}} (%struct.T*{{.*}})**, {{.*}} (%struct.T*{{.*}})*** + return t->v(); +} + +// ITANIUM: define void @_Z9delete_itP1T +// MSABI: define void @"\01?delete_it +void delete_it(T *t) { + // First, we check that vtable is not loaded before a type check. + // CHECK-VPTR-NOT: load {{.*}} (%struct.T*{{.*}})**, {{.*}} (%struct.T*{{.*}})*** + // CHECK-VPTR: br i1 {{.*}} label %{{.*}} + // CHECK-VPTR: call void @__ubsan_handle_dynamic_type_cache_miss_abort + // Second, we check that vtable is actually loaded once the type check is done. + // CHECK-VPTR: load {{.*}} (%struct.T*{{.*}})**, {{.*}} (%struct.T*{{.*}})*** + delete t; +} diff --git a/test/CodeGenCXX/uncopyable-args.cpp b/test/CodeGenCXX/uncopyable-args.cpp index c1d284a74185..307a5cf11b6b 100644 --- a/test/CodeGenCXX/uncopyable-args.cpp +++ b/test/CodeGenCXX/uncopyable-args.cpp @@ -204,3 +204,77 @@ void bar() { // WIN64-LABEL: declare void @"\01?foo@two_copy_ctors@@YAXUB@1@@Z"(%"struct.two_copy_ctors::B"*) } + +namespace definition_only { +struct A { + A(); + A(A &&o); + void *p; +}; +void *foo(A a) { return a.p; } +// WIN64-LABEL: define i8* @"\01?foo@definition_only@@YAPEAXUA@1@@Z"(%"struct.definition_only::A"* +} + +namespace deleted_by_member { +struct B { + B(); + B(B &&o); + void *p; +}; +struct A { + A(); + B b; +}; +void *foo(A a) { return a.b.p; } +// WIN64-LABEL: define i8* @"\01?foo@deleted_by_member@@YAPEAXUA@1@@Z"(%"struct.deleted_by_member::A"* +} + +namespace deleted_by_base { +struct B { + B(); + B(B &&o); + void *p; +}; +struct A : B { + A(); +}; +void *foo(A a) { return a.p; } +// WIN64-LABEL: define i8* @"\01?foo@deleted_by_base@@YAPEAXUA@1@@Z"(%"struct.deleted_by_base::A"* +} + +namespace deleted_by_member_copy { +struct B { + B(); + B(const B &o) = delete; + void *p; +}; +struct A { + A(); + B b; +}; +void *foo(A a) { return a.b.p; } +// WIN64-LABEL: define i8* @"\01?foo@deleted_by_member_copy@@YAPEAXUA@1@@Z"(%"struct.deleted_by_member_copy::A"* +} + +namespace deleted_by_base_copy { +struct B { + B(); + B(const B &o) = delete; + void *p; +}; +struct A : B { + A(); +}; +void *foo(A a) { return a.p; } +// WIN64-LABEL: define i8* @"\01?foo@deleted_by_base_copy@@YAPEAXUA@1@@Z"(%"struct.deleted_by_base_copy::A"* +} + +namespace explicit_delete { +struct A { + A(); + A(const A &o) = delete; + void *p; +}; +// WIN64-LABEL: define i8* @"\01?foo@explicit_delete@@YAPEAXUA@1@@Z"(%"struct.explicit_delete::A"* +void *foo(A a) { return a.p; } +} diff --git a/test/CodeGenCXX/value-init.cpp b/test/CodeGenCXX/value-init.cpp index 735dc6163990..fc4e0d3a55e0 100644 --- a/test/CodeGenCXX/value-init.cpp +++ b/test/CodeGenCXX/value-init.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -triple x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -std=c++98 %s -triple x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s struct A { virtual ~A(); @@ -315,6 +315,14 @@ namespace PR20256 { // CHECK: } } +// CHECK-LABEL: define {{.*}}@_Z20explicitly_defaultedv +int explicitly_defaulted() { + struct A { A() = default; int n; }; + // CHECK: call void @llvm.memset + A a = A(); + return a.n; +} // CHECK-LABEL: } + // CHECK-LABEL: define linkonce_odr void @_ZN8zeroinit2X3IiEC2Ev(%"struct.zeroinit::X3"* %this) unnamed_addr // CHECK: call void @llvm.memset.p0i8.i64 // CHECK-NEXT: call void @_ZN8zeroinit2X2IiEC2Ev diff --git a/test/CodeGenCXX/virtual-base-cast.cpp b/test/CodeGenCXX/virtual-base-cast.cpp index 554e80d3cf21..b2f2b4f2b319 100644 --- a/test/CodeGenCXX/virtual-base-cast.cpp +++ b/test/CodeGenCXX/virtual-base-cast.cpp @@ -82,4 +82,4 @@ BB* d() { return y; } // MSVC: add nsw i32 4, %[[offset]] // MSVC: } -// CHECK: attributes [[NUW]] = { nounwind{{.*}} } +// CHECK: attributes [[NUW]] = { noinline nounwind{{.*}} } diff --git a/test/CodeGenCXX/virtual-destructor-calls.cpp b/test/CodeGenCXX/virtual-destructor-calls.cpp index e13adfcc85cf..2e63daac31de 100644 --- a/test/CodeGenCXX/virtual-destructor-calls.cpp +++ b/test/CodeGenCXX/virtual-destructor-calls.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin10 -mconstructor-aliases -O1 -disable-llvm-optzns | FileCheck %s +// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin10 -mconstructor-aliases -O1 -disable-llvm-passes | FileCheck %s struct Member { ~Member(); diff --git a/test/CodeGenCXX/virtual-function-calls.cpp b/test/CodeGenCXX/virtual-function-calls.cpp index 0a6fc6b3f284..22944d94ca88 100644 --- a/test/CodeGenCXX/virtual-function-calls.cpp +++ b/test/CodeGenCXX/virtual-function-calls.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 %s -triple %itanium_abi_triple -std=c++11 -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -triple %itanium_abi_triple -std=c++11 -emit-llvm -o - -fstrict-vtable-pointers -O1 | FileCheck --check-prefix=CHECK-INVARIANT %s // PR5021 namespace PR5021 { @@ -42,10 +43,14 @@ namespace VirtualNoreturn { [[noreturn]] virtual void f(); }; - // CHECK: @_ZN15VirtualNoreturn1f + // CHECK-LABEL: @_ZN15VirtualNoreturn1f + // CHECK-INVARIANT-LABEL: define void @_ZN15VirtualNoreturn1f void f(A *p) { p->f(); // CHECK: call {{.*}}void %{{[^#]*$}} // CHECK-NOT: unreachable + // CHECK-INVARIANT: load {{.*}} !invariant.load ![[EMPTY_NODE:[0-9]+]] } } + +// CHECK-INVARIANT: ![[EMPTY_NODE]] = !{} diff --git a/test/CodeGenCXX/visibility-inlines-hidden.cpp b/test/CodeGenCXX/visibility-inlines-hidden.cpp index 7c0757b2829a..6ea234807ec2 100644 --- a/test/CodeGenCXX/visibility-inlines-hidden.cpp +++ b/test/CodeGenCXX/visibility-inlines-hidden.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple i386-unknown-unknown -std=c++11 -fvisibility-inlines-hidden -emit-llvm -o - %s -O2 -disable-llvm-optzns | FileCheck %s +// RUN: %clang_cc1 -triple i386-unknown-unknown -std=c++11 -fvisibility-inlines-hidden -emit-llvm -o - %s -O2 -disable-llvm-passes | FileCheck %s // The trickery with optimization in the run line is to get IR // generation to emit available_externally function bodies, but not diff --git a/test/CodeGenCXX/vla-lambda-capturing.cpp b/test/CodeGenCXX/vla-lambda-capturing.cpp index 44b6a2506d14..5081f1447d27 100644 --- a/test/CodeGenCXX/vla-lambda-capturing.cpp +++ b/test/CodeGenCXX/vla-lambda-capturing.cpp @@ -125,11 +125,11 @@ int main() { // CHECK: [[SIZE2:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[SIZE2_REF]] // CHECK: [[SIZE1_REF:%.+]] = getelementptr inbounds [[CAP_TYPE3]], [[CAP_TYPE3]]* [[THIS]], i{{[0-9]+}} 0, i{{[0-9]+}} 2 // CHECK: [[SIZE1:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[SIZE1_REF]] +// CHECK: [[BUFFER1_ADDR_REF:%.+]] = getelementptr inbounds [[CAP_TYPE3]], [[CAP_TYPE3]]* [[THIS]], i{{[0-9]+}} 0, i{{[0-9]+}} 3 +// CHECK: [[BUFFER1_ADDR:%.+]] = load [[INTPTR_T]]*, [[INTPTR_T]]** [[BUFFER1_ADDR_REF]] // CHECK: [[N_ADDR_REF:%.+]] = getelementptr inbounds [[CAP_TYPE3]], [[CAP_TYPE3]]* [[THIS]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 // CHECK: [[N_ADDR:%.+]] = load [[INTPTR_T]]*, [[INTPTR_T]]** [[N_ADDR_REF]] // CHECK: [[N:%.+]] = load [[INTPTR_T]], [[INTPTR_T]]* [[N_ADDR]] -// CHECK: [[BUFFER1_ADDR_REF:%.+]] = getelementptr inbounds [[CAP_TYPE3]], [[CAP_TYPE3]]* [[THIS]], i{{[0-9]+}} 0, i{{[0-9]+}} 3 -// CHECK: [[BUFFER1_ADDR:%.+]] = load [[INTPTR_T]]*, [[INTPTR_T]]** [[BUFFER1_ADDR_REF]] // CHECK: [[ELEM_OFFSET:%.+]] = mul {{.*}} i{{[0-9]+}} [[N]], [[SIZE1]] // CHECK: [[ELEM_ADDR:%.+]] = getelementptr inbounds [[INTPTR_T]], [[INTPTR_T]]* [[BUFFER1_ADDR]], i{{[0-9]+}} [[ELEM_OFFSET]] // CHECK: [[SIZEOF:%.+]] = mul {{.*}} i{{[0-9]+}} {{[0-9]+}}, [[SIZE1]] diff --git a/test/CodeGenCXX/vtable-align.cpp b/test/CodeGenCXX/vtable-align.cpp index f1f10c07df2d..1b82cbc085c9 100644 --- a/test/CodeGenCXX/vtable-align.cpp +++ b/test/CodeGenCXX/vtable-align.cpp @@ -9,6 +9,6 @@ struct A { void A::f() {} -// CHECK-32: @_ZTV1A = unnamed_addr constant [5 x i8*] [i8* null, i8* bitcast ({ i8*, i8* }* @_ZTI1A to i8*), i8* bitcast (void (%struct.A*)* @_ZN1A1fEv to i8*), i8* bitcast (void (%struct.A*)* @_ZN1A1gEv to i8*), i8* bitcast (void (%struct.A*)* @_ZN1A1hEv to i8*)], align 4 +// CHECK-32: @_ZTV1A = unnamed_addr constant { [5 x i8*] } { [5 x i8*] [i8* null, i8* bitcast ({ i8*, i8* }* @_ZTI1A to i8*), i8* bitcast (void (%struct.A*)* @_ZN1A1fEv to i8*), i8* bitcast (void (%struct.A*)* @_ZN1A1gEv to i8*), i8* bitcast (void (%struct.A*)* @_ZN1A1hEv to i8*)] }, align 4 -// CHECK-64: @_ZTV1A = unnamed_addr constant [5 x i8*] [i8* null, i8* bitcast ({ i8*, i8* }* @_ZTI1A to i8*), i8* bitcast (void (%struct.A*)* @_ZN1A1fEv to i8*), i8* bitcast (void (%struct.A*)* @_ZN1A1gEv to i8*), i8* bitcast (void (%struct.A*)* @_ZN1A1hEv to i8*)], align 8 +// CHECK-64: @_ZTV1A = unnamed_addr constant { [5 x i8*] } { [5 x i8*] [i8* null, i8* bitcast ({ i8*, i8* }* @_ZTI1A to i8*), i8* bitcast (void (%struct.A*)* @_ZN1A1fEv to i8*), i8* bitcast (void (%struct.A*)* @_ZN1A1gEv to i8*), i8* bitcast (void (%struct.A*)* @_ZN1A1hEv to i8*)] }, align 8 diff --git a/test/CodeGenCXX/vtable-assume-load.cpp b/test/CodeGenCXX/vtable-assume-load.cpp index 819b09d70e3d..b0857c29c654 100644 --- a/test/CodeGenCXX/vtable-assume-load.cpp +++ b/test/CodeGenCXX/vtable-assume-load.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 %s -triple x86_64-apple-darwin10 -emit-llvm -o %t.ll -O1 -disable-llvm-optzns -fms-extensions -fstrict-vtable-pointers -// RUN: %clang_cc1 %s -triple i686-pc-win32 -emit-llvm -o %t.ms.ll -O1 -disable-llvm-optzns -fms-extensions -fstrict-vtable-pointers +// RUN: %clang_cc1 %s -triple x86_64-apple-darwin10 -emit-llvm -o %t.ll -O1 -disable-llvm-passes -fms-extensions -fstrict-vtable-pointers +// RUN: %clang_cc1 %s -triple i686-pc-win32 -emit-llvm -o %t.ms.ll -O1 -disable-llvm-passes -fms-extensions -fstrict-vtable-pointers // FIXME: Assume load should not require -fstrict-vtable-pointers // RUN: FileCheck --check-prefix=CHECK1 --input-file=%t.ll %s @@ -27,9 +27,9 @@ void g(A *a) { a->foo(); } // CHECK1-LABEL: define void @_ZN5test14fooAEv() // CHECK1: call void @_ZN5test11AC1Ev(%"struct.test1::A"* // CHECK1: %[[VTABLE:.*]] = load i8**, i8*** %{{.*}} -// CHECK1: %[[CMP:.*]] = icmp eq i8** %[[VTABLE]], getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN5test11AE, i32 0, i32 2) +// CHECK1: %[[CMP:.*]] = icmp eq i8** %[[VTABLE]], getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTVN5test11AE, i32 0, inrange i32 0, i32 2) // CHECK1: call void @llvm.assume(i1 %[[CMP]]) -// CHECK1-LABEL: } +// CHECK1-LABEL: {{^}}} void fooA() { A a; @@ -39,9 +39,9 @@ void fooA() { // CHECK1-LABEL: define void @_ZN5test14fooBEv() // CHECK1: call void @_ZN5test11BC1Ev(%"struct.test1::B"* %{{.*}}) // CHECK1: %[[VTABLE:.*]] = load i8**, i8*** %{{.*}} -// CHECK1: %[[CMP:.*]] = icmp eq i8** %[[VTABLE]], getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN5test11BE, i32 0, i32 2) +// CHECK1: %[[CMP:.*]] = icmp eq i8** %[[VTABLE]], getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTVN5test11BE, i32 0, inrange i32 0, i32 2) // CHECK1: call void @llvm.assume(i1 %[[CMP]]) -// CHECK1-LABEL: } +// CHECK1-LABEL: {{^}}} void fooB() { B b; @@ -50,7 +50,7 @@ void fooB() { // there should not be any assumes in the ctor that calls base ctor // CHECK1-LABEL: define linkonce_odr void @_ZN5test11BC2Ev(%"struct.test1::B"* // CHECK1-NOT: @llvm.assume( -// CHECK1-LABEL: } +// CHECK1-LABEL: {{^}}} } namespace test2 { struct A { @@ -73,18 +73,18 @@ void h(B *b) { b->bar(); } // CHECK2-LABEL: define void @_ZN5test24testEv() // CHECK2: call void @_ZN5test21CC1Ev(%"struct.test2::C"* // CHECK2: %[[VTABLE:.*]] = load i8**, i8*** {{.*}} -// CHECK2: %[[CMP:.*]] = icmp eq i8** %[[VTABLE]], getelementptr inbounds ([6 x i8*], [6 x i8*]* @_ZTVN5test21CE, i32 0, i32 2) +// CHECK2: %[[CMP:.*]] = icmp eq i8** %[[VTABLE]], getelementptr inbounds ({ [3 x i8*], [3 x i8*] }, { [3 x i8*], [3 x i8*] }* @_ZTVN5test21CE, i32 0, inrange i32 0, i32 2) // CHECK2: call void @llvm.assume(i1 %[[CMP]]) // CHECK2: %[[V2:.*]] = bitcast %"struct.test2::C"* %{{.*}} to i8* // CHECK2: %[[ADD_PTR:.*]] = getelementptr inbounds i8, i8* %[[V2]], i64 8 // CHECK2: %[[V3:.*]] = bitcast i8* %[[ADD_PTR]] to i8*** // CHECK2: %[[VTABLE2:.*]] = load i8**, i8*** %[[V3]] -// CHECK2: %[[CMP2:.*]] = icmp eq i8** %[[VTABLE2]], getelementptr inbounds ([6 x i8*], [6 x i8*]* @_ZTVN5test21CE, i32 0, i32 5) +// CHECK2: %[[CMP2:.*]] = icmp eq i8** %[[VTABLE2]], getelementptr inbounds ({ [3 x i8*], [3 x i8*] }, { [3 x i8*], [3 x i8*] }* @_ZTVN5test21CE, i32 0, inrange i32 1, i32 2) // CHECK2: call void @llvm.assume(i1 %[[CMP2]]) // CHECK2: call void @_ZN5test21gEPNS_1AE( -// CHECK2-LABEL: } +// CHECK2-LABEL: {{^}}} void test() { C c; @@ -111,7 +111,7 @@ void g(B *a) { a->foo(); } // CHECK3-LABEL: define void @_ZN5test34testEv() // CHECK3: call void @_ZN5test31CC1Ev(%"struct.test3::C"* -// CHECK3: %[[CMP:.*]] = icmp eq i8** %{{.*}}, getelementptr inbounds ([4 x i8*], [4 x i8*]* @_ZTVN5test31CE, i32 0, i32 3) +// CHECK3: %[[CMP:.*]] = icmp eq i8** %{{.*}}, getelementptr inbounds ({ [4 x i8*] }, { [4 x i8*] }* @_ZTVN5test31CE, i32 0, inrange i32 0, i32 3) // CHECK3: call void @llvm.assume(i1 %[[CMP]]) // CHECK3-LABLEL: } void test() { @@ -140,13 +140,13 @@ void g(C *c) { c->foo(); } // CHECK4-LABEL: define void @_ZN5test44testEv() // CHECK4: call void @_ZN5test41CC1Ev(%"struct.test4::C"* // CHECK4: %[[VTABLE:.*]] = load i8**, i8*** %{{.*}} -// CHECK4: %[[CMP:.*]] = icmp eq i8** %[[VTABLE]], getelementptr inbounds ([5 x i8*], [5 x i8*]* @_ZTVN5test41CE, i32 0, i32 4) +// CHECK4: %[[CMP:.*]] = icmp eq i8** %[[VTABLE]], getelementptr inbounds ({ [5 x i8*] }, { [5 x i8*] }* @_ZTVN5test41CE, i32 0, inrange i32 0, i32 4) // CHECK4: call void @llvm.assume(i1 %[[CMP]] // CHECK4: %[[VTABLE2:.*]] = load i8**, i8*** %{{.*}} -// CHECK4: %[[CMP2:.*]] = icmp eq i8** %[[VTABLE2]], getelementptr inbounds ([5 x i8*], [5 x i8*]* @_ZTVN5test41CE, i32 0, i32 4) +// CHECK4: %[[CMP2:.*]] = icmp eq i8** %[[VTABLE2]], getelementptr inbounds ({ [5 x i8*] }, { [5 x i8*] }* @_ZTVN5test41CE, i32 0, inrange i32 0, i32 4) // CHECK4: call void @llvm.assume(i1 %[[CMP2]]) -// CHECK4-LABEL: } +// CHECK4-LABEL: {{^}}} void test() { C c; @@ -166,7 +166,7 @@ void g(S &s) { s.foo(); } // CHECK-MS-LABEL: define void @"\01?test@testMS@@YAXXZ"() // CHECK-MS: call x86_thiscallcc %"struct.testMS::S"* @"\01??0S@testMS@@QAE@XZ"( // CHECK-MS-NOT: @llvm.assume -// CHECK-MS-LABEL: } +// CHECK-MS-LABEL: {{^}}} void test() { S s; @@ -196,7 +196,7 @@ struct B : A { // CHECK6-LABEL: call void @_ZN5test61BC1Ev( // CHECK6-NOT: call void @llvm.assume( -// CHECK6-LABEL: } +// CHECK6-LABEL: {{^}}} void g() { A *a = new A; B *b = new B; @@ -216,7 +216,7 @@ void A::foo() {} // CHECK7-LABEL: define void @_ZN5test71gEv() // CHECK7: call void @_ZN5test71AC1Ev( // CHECK7: call void @llvm.assume( -// CHECK7-LABEL: } +// CHECK7-LABEL: {{^}}} void g() { A *a = new A(); a->bar(); @@ -259,7 +259,7 @@ struct E : A { // CHECK8-LABEL: define void @_ZN5test81bEv() // CHECK8: call void @llvm.assume( -// CHECK8-LABEL: } +// CHECK8-LABEL: {{^}}} void b() { B b; b.bar(); @@ -270,7 +270,7 @@ void b() { // defined here) it would be correct to refer to it. // CHECK8-LABEL: define void @_ZN5test81cEv() // CHECK8-NOT: call void @llvm.assume( -// CHECK8-LABEL: } +// CHECK8-LABEL: {{^}}} void c() { C c; c.bar(); @@ -279,7 +279,7 @@ void c() { // FIXME: We could generate assumption loads here. // CHECK8-LABEL: define void @_ZN5test81dEv() // CHECK8-NOT: call void @llvm.assume( -// CHECK8-LABEL: } +// CHECK8-LABEL: {{^}}} void d() { D d; d.bar(); @@ -287,7 +287,7 @@ void d() { // CHECK8-LABEL: define void @_ZN5test81eEv() // CHECK8: call void @llvm.assume( -// CHECK8-LABEL: } +// CHECK8-LABEL: {{^}}} void e() { E e; e.bar(); diff --git a/test/CodeGenCXX/vtable-available-externally.cpp b/test/CodeGenCXX/vtable-available-externally.cpp index f38d177666e6..ae81959a75e9 100644 --- a/test/CodeGenCXX/vtable-available-externally.cpp +++ b/test/CodeGenCXX/vtable-available-externally.cpp @@ -1,5 +1,5 @@ // RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -emit-llvm -o %t -// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -O2 -disable-llvm-optzns -emit-llvm -o %t.opt +// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -O2 -disable-llvm-passes -emit-llvm -o %t.opt // RUN: FileCheck --check-prefix=CHECK-TEST1 %s < %t // RUN: FileCheck --check-prefix=CHECK-TEST2 %s < %t // RUN: FileCheck --check-prefix=CHECK-TEST5 %s < %t diff --git a/test/CodeGenCXX/vtable-layout.cpp b/test/CodeGenCXX/vtable-layout.cpp index ca5384d6e031..4a47e3c9d2e8 100644 --- a/test/CodeGenCXX/vtable-layout.cpp +++ b/test/CodeGenCXX/vtable-layout.cpp @@ -1919,6 +1919,8 @@ namespace Test40 { virtual int i(int); virtual int i(); }; + // Force C's vtable to be generated. + int C::f() { return 1; } class D : C {}; diff --git a/test/CodeGenCXX/vtable-linkage.cpp b/test/CodeGenCXX/vtable-linkage.cpp index 0b556d10c3e8..c4ebf75b999a 100644 --- a/test/CodeGenCXX/vtable-linkage.cpp +++ b/test/CodeGenCXX/vtable-linkage.cpp @@ -1,6 +1,10 @@ // RUN: %clang_cc1 %s -triple=x86_64-pc-linux -emit-llvm -o %t -// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -disable-llvm-optzns -O3 -emit-llvm -o %t.opt +// RUN: %clang_cc1 %s -triple=x86_64-pc-linux -emit-llvm -std=c++03 -o %t.03 +// RUN: %clang_cc1 %s -triple=x86_64-pc-linux -emit-llvm -std=c++11 -o %t.11 +// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -disable-llvm-passes -O3 -emit-llvm -o %t.opt // RUN: FileCheck %s < %t +// RUN: FileCheck %s < %t.03 +// RUN: FileCheck %s < %t.11 // RUN: FileCheck --check-prefix=CHECK-OPT %s < %t.opt namespace { @@ -33,6 +37,11 @@ void D::f() { } static struct : D { } e; +// Force 'e' to be constructed and therefore have a vtable defined. +void use_e() { + e.f(); +} + // The destructor is the key function. template<typename T> struct E { diff --git a/test/CodeGenCXX/vtable-pointer-initialization.cpp b/test/CodeGenCXX/vtable-pointer-initialization.cpp index 130a55cf6218..49c8de4ea4f5 100644 --- a/test/CodeGenCXX/vtable-pointer-initialization.cpp +++ b/test/CodeGenCXX/vtable-pointer-initialization.cpp @@ -21,13 +21,13 @@ struct A : Base { // CHECK-LABEL: define void @_ZN1AC2Ev(%struct.A* %this) unnamed_addr // CHECK: call void @_ZN4BaseC2Ev( -// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTV1A, i32 0, i32 2) to i32 (...)**) +// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTV1A, i32 0, inrange i32 0, i32 2) to i32 (...)**) // CHECK: call void @_ZN5FieldC1Ev( // CHECK: ret void A::A() { } // CHECK-LABEL: define void @_ZN1AD2Ev(%struct.A* %this) unnamed_addr -// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTV1A, i32 0, i32 2) to i32 (...)**) +// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTV1A, i32 0, inrange i32 0, i32 2) to i32 (...)**) // CHECK: call void @_ZN5FieldD1Ev( // CHECK: call void @_ZN4BaseD2Ev( // CHECK: ret void @@ -49,12 +49,12 @@ void f() { B b; } // CHECK-LABEL: define linkonce_odr void @_ZN1BC2Ev(%struct.B* %this) unnamed_addr // CHECK: call void @_ZN4BaseC2Ev( -// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTV1B, i32 0, i32 2) to i32 (...)**) +// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTV1B, i32 0, inrange i32 0, i32 2) to i32 (...)**) // CHECK: call void @_ZN5FieldC1Ev // CHECK: ret void // CHECK-LABEL: define linkonce_odr void @_ZN1BD2Ev(%struct.B* %this) unnamed_addr -// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTV1B, i32 0, i32 2) to i32 (...)**) +// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTV1B, i32 0, inrange i32 0, i32 2) to i32 (...)**) // CHECK: call void @_ZN5FieldD1Ev( // CHECK: call void @_ZN4BaseD2Ev( // CHECK: ret void diff --git a/test/CodeGenCXX/vtt-layout.cpp b/test/CodeGenCXX/vtt-layout.cpp index 7ff93dd451c9..a5f7802577c8 100644 --- a/test/CodeGenCXX/vtt-layout.cpp +++ b/test/CodeGenCXX/vtt-layout.cpp @@ -78,11 +78,12 @@ namespace Test6 { } } -// CHECK: @_ZTTN5Test11BE = unnamed_addr constant [1 x i8*] [i8* bitcast (i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @_ZTVN5Test11BE, i32 0, i32 3) to i8*)] -// CHECK: @_ZTVN5Test51AE = unnamed_addr constant [4 x i8*] [i8* null, i8* bitcast ({ i8*, i8* }* @_ZTIN5Test51AE to i8*), i8* bitcast (void ()* @__cxa_pure_virtual to i8*), i8* bitcast (void (%"struct.Test5::A"*)* @_ZN5Test51A6anchorEv to i8*)] -// CHECK: @_ZTVN5Test61AE = unnamed_addr constant [4 x i8*] [i8* null, i8* bitcast ({ i8*, i8* }* @_ZTIN5Test61AE to i8*), i8* bitcast (void ()* @__cxa_deleted_virtual to i8*), i8* bitcast (void (%"struct.Test6::A"*)* @_ZN5Test61A6anchorEv to i8*)] -// CHECK: @_ZTTN5Test21CE = linkonce_odr unnamed_addr constant [2 x i8*] [i8* bitcast (i8** getelementptr inbounds ([5 x i8*], [5 x i8*]* @_ZTVN5Test21CE, i32 0, i32 4) to i8*), i8* bitcast (i8** getelementptr inbounds ([5 x i8*], [5 x i8*]* @_ZTVN5Test21CE, i32 0, i32 4) to i8*)] -// CHECK: @_ZTTN5Test31DE = linkonce_odr unnamed_addr constant [13 x i8*] [i8* bitcast (i8** getelementptr inbounds ([19 x i8*], [19 x i8*]* @_ZTVN5Test31DE, i32 0, i32 5) to i8*), i8* bitcast (i8** getelementptr inbounds ([7 x i8*], [7 x i8*]* @_ZTCN5Test31DE0_NS_2C1E, i32 0, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ([7 x i8*], [7 x i8*]* @_ZTCN5Test31DE0_NS_2C1E, i32 0, i32 6) to i8*), i8* bitcast (i8** getelementptr inbounds ([14 x i8*], [14 x i8*]* @_ZTCN5Test31DE16_NS_2C2E, i32 0, i32 6) to i8*), i8* bitcast (i8** getelementptr inbounds ([14 x i8*], [14 x i8*]* @_ZTCN5Test31DE16_NS_2C2E, i32 0, i32 6) to i8*), i8* bitcast (i8** getelementptr inbounds ([14 x i8*], [14 x i8*]* @_ZTCN5Test31DE16_NS_2C2E, i32 0, i32 10) to i8*), i8* bitcast (i8** getelementptr inbounds ([14 x i8*], [14 x i8*]* @_ZTCN5Test31DE16_NS_2C2E, i32 0, i32 13) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*], [19 x i8*]* @_ZTVN5Test31DE, i32 0, i32 15) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*], [19 x i8*]* @_ZTVN5Test31DE, i32 0, i32 11) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*], [19 x i8*]* @_ZTVN5Test31DE, i32 0, i32 11) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*], [19 x i8*]* @_ZTVN5Test31DE, i64 1, i32 0) to i8*), i8* bitcast (i8** getelementptr inbounds ([7 x i8*], [7 x i8*]* @_ZTCN5Test31DE64_NS_2V2E, i32 0, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ([7 x i8*], [7 x i8*]* @_ZTCN5Test31DE64_NS_2V2E, i32 0, i32 6) to i8*)] -// CHECK: @_ZTTN5Test41DE = linkonce_odr unnamed_addr constant [19 x i8*] [i8* bitcast (i8** getelementptr inbounds ([25 x i8*], [25 x i8*]* @_ZTVN5Test41DE, i32 0, i32 6) to i8*), i8* bitcast (i8** getelementptr inbounds ([11 x i8*], [11 x i8*]* @_ZTCN5Test41DE0_NS_2C1E, i32 0, i32 4) to i8*), i8* bitcast (i8** getelementptr inbounds ([11 x i8*], [11 x i8*]* @_ZTCN5Test41DE0_NS_2C1E, i32 0, i32 7) to i8*), i8* bitcast (i8** getelementptr inbounds ([11 x i8*], [11 x i8*]* @_ZTCN5Test41DE0_NS_2C1E, i32 0, i32 10) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*], [19 x i8*]* @_ZTCN5Test41DE16_NS_2C2E, i32 0, i32 7) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*], [19 x i8*]* @_ZTCN5Test41DE16_NS_2C2E, i32 0, i32 7) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*], [19 x i8*]* @_ZTCN5Test41DE16_NS_2C2E, i32 0, i32 12) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*], [19 x i8*]* @_ZTCN5Test41DE16_NS_2C2E, i32 0, i32 15) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*], [19 x i8*]* @_ZTCN5Test41DE16_NS_2C2E, i32 0, i32 18) to i8*), i8* bitcast (i8** getelementptr inbounds ([25 x i8*], [25 x i8*]* @_ZTVN5Test41DE, i32 0, i32 17) to i8*), i8* bitcast (i8** getelementptr inbounds ([25 x i8*], [25 x i8*]* @_ZTVN5Test41DE, i32 0, i32 20) to i8*), i8* bitcast (i8** getelementptr inbounds ([25 x i8*], [25 x i8*]* @_ZTVN5Test41DE, i32 0, i32 13) to i8*), i8* bitcast (i8** getelementptr inbounds ([25 x i8*], [25 x i8*]* @_ZTVN5Test41DE, i32 0, i32 13) to i8*), i8* bitcast (i8** getelementptr inbounds ([25 x i8*], [25 x i8*]* @_ZTVN5Test41DE, i64 1, i32 0) to i8*), i8* bitcast (i8** getelementptr inbounds ([7 x i8*], [7 x i8*]* @_ZTCN5Test41DE40_NS_2V1E, i32 0, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ([7 x i8*], [7 x i8*]* @_ZTCN5Test41DE40_NS_2V1E, i32 0, i32 6) to i8*), i8* bitcast (i8** getelementptr inbounds ([11 x i8*], [11 x i8*]* @_ZTCN5Test41DE72_NS_2V2E, i32 0, i32 4) to i8*), i8* bitcast (i8** getelementptr inbounds ([11 x i8*], [11 x i8*]* @_ZTCN5Test41DE72_NS_2V2E, i32 0, i32 7) to i8*), i8* bitcast (i8** getelementptr inbounds ([11 x i8*], [11 x i8*]* @_ZTCN5Test41DE72_NS_2V2E, i32 0, i32 10) to i8*)] +// CHECK: @_ZTTN5Test11BE = unnamed_addr constant [1 x i8*] [i8* bitcast (i8** getelementptr inbounds ({ [4 x i8*] }, { [4 x i8*] }* @_ZTVN5Test11BE, i32 0, inrange i32 0, i32 3) to i8*)] +// CHECK: @_ZTVN5Test51AE = unnamed_addr constant { [4 x i8*] } { [4 x i8*] [i8* null, i8* bitcast ({ i8*, i8* }* @_ZTIN5Test51AE to i8*), i8* bitcast (void ()* @__cxa_pure_virtual to i8*), i8* bitcast (void (%"struct.Test5::A"*)* @_ZN5Test51A6anchorEv to i8*)] } +// CHECK: @_ZTVN5Test61AE = unnamed_addr constant { [4 x i8*] } { [4 x i8*] [i8* null, i8* bitcast ({ i8*, i8* }* @_ZTIN5Test61AE to i8*), i8* bitcast (void ()* @__cxa_deleted_virtual to i8*), i8* bitcast (void (%"struct.Test6::A"*)* @_ZN5Test61A6anchorEv to i8*)] } +// CHECK: @_ZTTN5Test21CE = linkonce_odr unnamed_addr constant [2 x i8*] [i8* bitcast (i8** getelementptr inbounds ({ [5 x i8*] }, { [5 x i8*] }* @_ZTVN5Test21CE, i32 0, inrange i32 0, i32 4) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [5 x i8*] }, { [5 x i8*] }* @_ZTVN5Test21CE, i32 0, inrange i32 0, i32 4) to i8*)] +// CHECK: @_ZTTN5Test31DE = linkonce_odr unnamed_addr constant [13 x i8*] [i8* bitcast (i8** getelementptr inbounds ({ [5 x i8*], [7 x i8*], [4 x i8*], [3 x i8*] }, { [5 x i8*], [7 x i8*], [4 x i8*], [3 x i8*] }* @_ZTVN5Test31DE, i32 0, inrange i32 0, i32 5) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [3 x i8*], [4 x i8*] }, { [3 x i8*], [4 x i8*] }* @_ZTCN5Test31DE0_NS_2C1E, i32 0, inrange i32 0, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [3 x i8*], [4 x i8*] }, { [3 x i8*], [4 x i8*] }* @_ZTCN5Test31DE0_NS_2C1E, i32 0, inrange i32 1, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [7 x i8*], [3 x i8*], [4 x i8*] }, { [7 x i8*], [3 x i8*], [4 x i8*] }* @_ZTCN5Test31DE16_NS_2C2E, i32 0, inrange i32 0, i32 6) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [7 x i8*], [3 x i8*], [4 x i8*] }, { [7 x i8*], [3 x i8*], [4 x i8*] }* @_ZTCN5Test31DE16_NS_2C2E, i32 0, inrange i32 0, i32 6) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [7 x i8*], [3 x i8*], [4 x i8*] }, { [7 x i8*], [3 x i8*], [4 x i8*] }* @_ZTCN5Test31DE16_NS_2C2E, i32 0, inrange i32 1, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [7 x i8*], [3 x i8*], [4 x i8*] }, { [7 x i8*], [3 x i8*], [4 x i8*] }* @_ZTCN5Test31DE16_NS_2C2E, i32 0, inrange i32 2, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [5 x i8*], [7 x i8*], [4 x i8*], [3 x i8*] }, { [5 x i8*], [7 x i8*], [4 x i8*], [3 x i8*] }* @_ZTVN5Test31DE, i32 0, inrange i32 2, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [5 x i8*], [7 x i8*], [4 x i8*], [3 x i8*] }, { [5 x i8*], [7 x i8*], [4 x i8*], [3 x i8*] }* @_ZTVN5Test31DE, i32 0, inrange i32 1, i32 6) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [5 x i8*], [7 x i8*], [4 x i8*], [3 x i8*] }, { [5 x i8*], [7 x i8*], [4 x i8*], [3 x i8*] }* @_ZTVN5Test31DE, i32 0, inrange i32 1, i32 6) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [5 x i8*], [7 x i8*], [4 x i8*], [3 x i8*] }, { [5 x i8*], [7 x i8*], [4 x i8*], [3 x i8*] }* @_ZTVN5Test31DE, i32 0, inrange i32 3, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [3 x i8*], [4 x i8*] }, { [3 x i8*], [4 x i8*] }* @_ZTCN5Test31DE64_NS_2V2E, i32 0, inrange i32 0, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [3 x i8*], [4 x i8*] }, { [3 x i8*], [4 x i8*] }* @_ZTCN5Test31DE64_NS_2V2E, i32 0, inrange i32 1, i32 3) to i8*)] +// CHECK: @_ZTVN5Test41DE = linkonce_odr unnamed_addr constant { [6 x i8*], [8 x i8*], [3 x i8*], [4 x i8*], [4 x i8*] } { [6 x i8*] [i8* inttoptr (i64 72 to i8*), i8* inttoptr (i64 16 to i8*), i8* inttoptr (i64 56 to i8*), i8* inttoptr (i64 40 to i8*), i8* null, i8* bitcast ({ i8*, i8*, i32, i32, i8*, i64, i8*, i64, i8*, i64 }* @_ZTIN5Test41DE to i8*)], [8 x i8*] [i8* inttoptr (i64 40 to i8*), i8* inttoptr (i64 24 to i8*), i8* inttoptr (i64 56 to i8*), i8* null, i8* null, i8* inttoptr (i64 -16 to i8*), i8* bitcast ({ i8*, i8*, i32, i32, i8*, i64, i8*, i64, i8*, i64 }* @_ZTIN5Test41DE to i8*), i8* bitcast (void (%"class.Test4::V3"*)* @_ZN5Test42V31gEv to i8*)], [3 x i8*] [i8* inttoptr (i64 16 to i8*), i8* inttoptr (i64 -40 to i8*), i8* bitcast ({ i8*, i8*, i32, i32, i8*, i64, i8*, i64, i8*, i64 }* @_ZTIN5Test41DE to i8*)], [4 x i8*] [i8* null, i8* inttoptr (i64 -56 to i8*), i8* bitcast ({ i8*, i8*, i32, i32, i8*, i64, i8*, i64, i8*, i64 }* @_ZTIN5Test41DE to i8*), i8* bitcast (void (%"class.Test4::A2"*)* @_ZN5Test42A21fEv to i8*)], [4 x i8*] [i8* inttoptr (i64 -16 to i8*), i8* inttoptr (i64 -32 to i8*), i8* inttoptr (i64 -72 to i8*), i8* bitcast ({ i8*, i8*, i32, i32, i8*, i64, i8*, i64, i8*, i64 }* @_ZTIN5Test41DE to i8*)] } +// CHECK: @_ZTTN5Test41DE = linkonce_odr unnamed_addr constant [19 x i8*] [i8* bitcast (i8** getelementptr inbounds ({ [6 x i8*], [8 x i8*], [3 x i8*], [4 x i8*], [4 x i8*] }, { [6 x i8*], [8 x i8*], [3 x i8*], [4 x i8*], [4 x i8*] }* @_ZTVN5Test41DE, i32 0, inrange i32 0, i32 6) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [4 x i8*], [3 x i8*], [4 x i8*] }, { [4 x i8*], [3 x i8*], [4 x i8*] }* @_ZTCN5Test41DE0_NS_2C1E, i32 0, inrange i32 0, i32 4) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [4 x i8*], [3 x i8*], [4 x i8*] }, { [4 x i8*], [3 x i8*], [4 x i8*] }* @_ZTCN5Test41DE0_NS_2C1E, i32 0, inrange i32 1, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [4 x i8*], [3 x i8*], [4 x i8*] }, { [4 x i8*], [3 x i8*], [4 x i8*] }* @_ZTCN5Test41DE0_NS_2C1E, i32 0, inrange i32 2, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [8 x i8*], [4 x i8*], [3 x i8*], [4 x i8*] }, { [8 x i8*], [4 x i8*], [3 x i8*], [4 x i8*] }* @_ZTCN5Test41DE16_NS_2C2E, i32 0, inrange i32 0, i32 7) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [8 x i8*], [4 x i8*], [3 x i8*], [4 x i8*] }, { [8 x i8*], [4 x i8*], [3 x i8*], [4 x i8*] }* @_ZTCN5Test41DE16_NS_2C2E, i32 0, inrange i32 0, i32 7) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [8 x i8*], [4 x i8*], [3 x i8*], [4 x i8*] }, { [8 x i8*], [4 x i8*], [3 x i8*], [4 x i8*] }* @_ZTCN5Test41DE16_NS_2C2E, i32 0, inrange i32 1, i32 4) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [8 x i8*], [4 x i8*], [3 x i8*], [4 x i8*] }, { [8 x i8*], [4 x i8*], [3 x i8*], [4 x i8*] }* @_ZTCN5Test41DE16_NS_2C2E, i32 0, inrange i32 2, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [8 x i8*], [4 x i8*], [3 x i8*], [4 x i8*] }, { [8 x i8*], [4 x i8*], [3 x i8*], [4 x i8*] }* @_ZTCN5Test41DE16_NS_2C2E, i32 0, inrange i32 3, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [6 x i8*], [8 x i8*], [3 x i8*], [4 x i8*], [4 x i8*] }, { [6 x i8*], [8 x i8*], [3 x i8*], [4 x i8*], [4 x i8*] }* @_ZTVN5Test41DE, i32 0, inrange i32 2, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [6 x i8*], [8 x i8*], [3 x i8*], [4 x i8*], [4 x i8*] }, { [6 x i8*], [8 x i8*], [3 x i8*], [4 x i8*], [4 x i8*] }* @_ZTVN5Test41DE, i32 0, inrange i32 3, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [6 x i8*], [8 x i8*], [3 x i8*], [4 x i8*], [4 x i8*] }, { [6 x i8*], [8 x i8*], [3 x i8*], [4 x i8*], [4 x i8*] }* @_ZTVN5Test41DE, i32 0, inrange i32 1, i32 7) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [6 x i8*], [8 x i8*], [3 x i8*], [4 x i8*], [4 x i8*] }, { [6 x i8*], [8 x i8*], [3 x i8*], [4 x i8*], [4 x i8*] }* @_ZTVN5Test41DE, i32 0, inrange i32 1, i32 7) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [6 x i8*], [8 x i8*], [3 x i8*], [4 x i8*], [4 x i8*] }, { [6 x i8*], [8 x i8*], [3 x i8*], [4 x i8*], [4 x i8*] }* @_ZTVN5Test41DE, i32 0, inrange i32 4, i32 4) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [3 x i8*], [4 x i8*] }, { [3 x i8*], [4 x i8*] }* @_ZTCN5Test41DE40_NS_2V1E, i32 0, inrange i32 0, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [3 x i8*], [4 x i8*] }, { [3 x i8*], [4 x i8*] }* @_ZTCN5Test41DE40_NS_2V1E, i32 0, inrange i32 1, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [4 x i8*], [3 x i8*], [4 x i8*] }, { [4 x i8*], [3 x i8*], [4 x i8*] }* @_ZTCN5Test41DE72_NS_2V2E, i32 0, inrange i32 0, i32 4) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [4 x i8*], [3 x i8*], [4 x i8*] }, { [4 x i8*], [3 x i8*], [4 x i8*] }* @_ZTCN5Test41DE72_NS_2V2E, i32 0, inrange i32 1, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [4 x i8*], [3 x i8*], [4 x i8*] }, { [4 x i8*], [3 x i8*], [4 x i8*] }* @_ZTCN5Test41DE72_NS_2V2E, i32 0, inrange i32 2, i32 3) to i8*)] // CHECK: declare void @__cxa_pure_virtual() unnamed_addr // CHECK: declare void @__cxa_deleted_virtual() unnamed_addr diff --git a/test/CodeGenCXX/wasm-args-returns.cpp b/test/CodeGenCXX/wasm-args-returns.cpp index 2b80430014d0..24adc8e08761 100644 --- a/test/CodeGenCXX/wasm-args-returns.cpp +++ b/test/CodeGenCXX/wasm-args-returns.cpp @@ -14,7 +14,7 @@ struct one_field { double d; }; test(one_field); -// CHECK: define double @_Z7forward9one_field(double %{{.*}}) +// CHECK: define double @_Z7forward9one_field(double returned %{{.*}}) // // CHECK: define void @_Z14test_one_fieldv() // CHECK: %[[call:.*]] = tail call double @_Z13def_one_fieldv() @@ -89,7 +89,7 @@ struct one_bitfield { int d:3; }; test(one_bitfield); -// CHECK: define i32 @_Z7forward12one_bitfield(i32 %{{.*}}) +// CHECK: define i32 @_Z7forward12one_bitfield(i32 returned %{{.*}}) // // CHECK: define void @_Z17test_one_bitfieldv() // CHECK: %[[call:.*]] = tail call i32 @_Z16def_one_bitfieldv() diff --git a/test/CodeGenCXX/windows-implicit-dllexport-template-specialization.cpp b/test/CodeGenCXX/windows-implicit-dllexport-template-specialization.cpp new file mode 100644 index 000000000000..c2f2a0773e90 --- /dev/null +++ b/test/CodeGenCXX/windows-implicit-dllexport-template-specialization.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -std=c++11 -triple i686-windows -fdeclspec -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-MS +// RUN: %clang_cc1 -std=c++11 -triple i686-windows-itanium -fdeclspec -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-IA + +template <typename> +struct s {}; + +template <typename T_> +class t : s<T_> {}; + +extern template class t<char>; +template class __declspec(dllexport) t<char>; + +// CHECK-MS: dllexport {{.*}} @"\01??4?$t@D@@QAEAAV0@ABV0@@Z" +// CHECK-MS: dllexport {{.*}} @"\01??4?$s@D@@QAEAAU0@ABU0@@Z" + +// CHECK-IA: dllexport {{.*}} @_ZN1tIcEaSERKS0_ +// CHECK-IA: dllexport {{.*}} @_ZN1sIcEaSERKS0_ + diff --git a/test/CodeGenCXX/windows-itanium-dllexport.cpp b/test/CodeGenCXX/windows-itanium-dllexport.cpp new file mode 100644 index 000000000000..92cca2444287 --- /dev/null +++ b/test/CodeGenCXX/windows-itanium-dllexport.cpp @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 -emit-llvm -triple i686-windows-itanium -fdeclspec %s -o - | FileCheck %s + +struct __declspec(dllexport) s { + void f() {} +}; + +// CHECK: define {{.*}} dllexport {{.*}} @_ZN1saSERKS_ +// CHECK: define {{.*}} dllexport {{.*}} @_ZN1s1fEv + +template <class T> +class c { + void f() {} +}; + +template class __declspec(dllexport) c<int>; + +// CHECK: define {{.*}} dllexport {{.*}} @_ZN1cIiEaSERKS0_ +// CHECK: define {{.*}} dllexport {{.*}} @_ZN1cIiE1fEv + +extern template class c<char>; +template class __declspec(dllexport) c<char>; + +// CHECK: define {{.*}} dllexport {{.*}} @_ZN1cIcEaSERKS0_ +// CHECK: define {{.*}} dllexport {{.*}} @_ZN1cIcE1fEv + +c<double> g; +template class __declspec(dllexport) c<double>; + +// CHECK: define {{.*}} dllexport {{.*}} @_ZN1cIdEaSERKS0_ +// CHECK: define {{.*}} dllexport {{.*}} @_ZN1cIdE1fEv diff --git a/test/CodeGenCXX/windows-itanium-type-info.cpp b/test/CodeGenCXX/windows-itanium-type-info.cpp new file mode 100644 index 000000000000..ad89318f599e --- /dev/null +++ b/test/CodeGenCXX/windows-itanium-type-info.cpp @@ -0,0 +1,40 @@ +// RUN: %clang_cc1 -triple i686-windows-itanium -fdeclspec -fcxx-exceptions -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple i686-windows-itanium -fdeclspec -fcxx-exceptions -fno-rtti -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-EH-IMPORT + +namespace __cxxabiv1 { +class __declspec(dllexport) __fundamental_type_info { +public: + virtual ~__fundamental_type_info(); +}; + +__fundamental_type_info::~__fundamental_type_info() {} +} + +struct __declspec(dllimport) base { + virtual void method(); +}; +struct __declspec(dllexport) derived : base { + virtual ~derived(); +}; +derived::~derived() { + method(); +} + +void f() { + throw base(); +} + +// CHECK-DAG: @_ZTIi = dllexport constant +// CHECK-DAG: @_ZTSi = dllexport constant + +// CHECK-DAG: @_ZTI7derived = dllexport constant +// CHECK-DAG: @_ZTS7derived = dllexport constant +// CHECK-DAG: @_ZTV7derived = dllexport unnamed_addr constant + +// CHECK-DAG: @_ZTI4base = external dllimport constant +// CHECK-DAG: @_ZTS4base = external dllimport constant +// CHECK-NOT: @_ZTV4base = external dllimport constant + +// CHECK-EH-IMPORT: @_ZTS4base = linkonce_odr constant +// CHECK-EH-IMPORT: @_ZTI4base = linkonce_odr constant + |
