2017-08-26 09:04:35 +08:00
|
|
|
// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=NEWABI
|
|
|
|
// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown -fclang-abi-compat=4.0 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=OLDABI
|
|
|
|
// RUN: %clang_cc1 -std=c++11 -triple x86_64-scei-ps4 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=OLDABI
|
PR19668, PR23034: Fix handling of move constructors and deleted copy
constructors when deciding whether classes should be passed indirectly.
This fixes ABI differences between Clang and GCC:
* Previously, Clang ignored the move constructor when making this
determination. It now takes the move constructor into account, per
https://github.com/itanium-cxx-abi/cxx-abi/pull/17 (this change may
seem recent, but the ABI change was agreed on the Itanium C++ ABI
list a long time ago).
* Previously, Clang's behavior when the copy constructor was deleted
was unstable -- depending on whether the lazy declaration of the
copy constructor had been triggered, you might get different behavior.
We now eagerly declare the copy constructor whenever its deletedness
is unclear, and ignore deleted copy/move constructors when looking for
a trivial such constructor.
This also fixes an ABI difference between Clang and MSVC:
* If the copy constructor would be implicitly deleted (but has not been
lazily declared yet), for instance because the class has an rvalue
reference member, we would pass it directly. We now pass such a class
indirectly, matching MSVC.
Based on a patch by Vassil Vassilev, which was based on a patch by Bernd
Schmidt, which was based on a patch by Reid Kleckner!
This is a re-commit of r310401, which was reverted in r310464 due to ARM
failures (which should now be fixed).
llvm-svn: 310983
2017-08-16 09:49:53 +08:00
|
|
|
// RUN: %clang_cc1 -std=c++11 -triple x86_64-windows-msvc -emit-llvm -o - %s -fms-compatibility -fms-compatibility-version=18 | FileCheck %s -check-prefix=WIN64 -check-prefix=WIN64-18
|
|
|
|
// RUN: %clang_cc1 -std=c++11 -triple x86_64-windows-msvc -emit-llvm -o - %s -fms-compatibility -fms-compatibility-version=19 | FileCheck %s -check-prefix=WIN64 -check-prefix=WIN64-19
|
2014-05-15 00:02:09 +08:00
|
|
|
|
|
|
|
namespace trivial {
|
|
|
|
// Trivial structs should be passed directly.
|
|
|
|
struct A {
|
|
|
|
void *p;
|
|
|
|
};
|
|
|
|
void foo(A);
|
|
|
|
void bar() {
|
|
|
|
foo({});
|
|
|
|
}
|
|
|
|
// CHECK-LABEL: define void @_ZN7trivial3barEv()
|
|
|
|
// CHECK: alloca %"struct.trivial::A"
|
2015-02-28 05:19:58 +08:00
|
|
|
// CHECK: load i8*, i8**
|
2014-05-15 00:02:09 +08:00
|
|
|
// CHECK: call void @_ZN7trivial3fooENS_1AE(i8* %{{.*}})
|
|
|
|
// CHECK-LABEL: declare void @_ZN7trivial3fooENS_1AE(i8*)
|
|
|
|
|
|
|
|
// WIN64-LABEL: declare void @"\01?foo@trivial@@YAXUA@1@@Z"(i64)
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace default_ctor {
|
|
|
|
struct A {
|
|
|
|
A();
|
|
|
|
void *p;
|
|
|
|
};
|
|
|
|
void foo(A);
|
|
|
|
void bar() {
|
|
|
|
// Core issue 1590. We can pass this type in registers, even though C++
|
|
|
|
// normally doesn't permit copies when using braced initialization.
|
|
|
|
foo({});
|
|
|
|
}
|
|
|
|
// CHECK-LABEL: define void @_ZN12default_ctor3barEv()
|
|
|
|
// CHECK: alloca %"struct.default_ctor::A"
|
|
|
|
// CHECK: call void @_Z{{.*}}C1Ev(
|
2015-02-28 05:19:58 +08:00
|
|
|
// CHECK: load i8*, i8**
|
2014-05-15 00:02:09 +08:00
|
|
|
// CHECK: call void @_ZN12default_ctor3fooENS_1AE(i8* %{{.*}})
|
|
|
|
// CHECK-LABEL: declare void @_ZN12default_ctor3fooENS_1AE(i8*)
|
|
|
|
|
|
|
|
// WIN64-LABEL: declare void @"\01?foo@default_ctor@@YAXUA@1@@Z"(i64)
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace move_ctor {
|
|
|
|
// The presence of a move constructor implicitly deletes the trivial copy ctor
|
|
|
|
// and means that we have to pass this struct by address.
|
|
|
|
struct A {
|
|
|
|
A();
|
|
|
|
A(A &&o);
|
|
|
|
void *p;
|
|
|
|
};
|
|
|
|
void foo(A);
|
|
|
|
void bar() {
|
|
|
|
foo({});
|
|
|
|
}
|
PR19668, PR23034: Fix handling of move constructors and deleted copy
constructors when deciding whether classes should be passed indirectly.
This fixes ABI differences between Clang and GCC:
* Previously, Clang ignored the move constructor when making this
determination. It now takes the move constructor into account, per
https://github.com/itanium-cxx-abi/cxx-abi/pull/17 (this change may
seem recent, but the ABI change was agreed on the Itanium C++ ABI
list a long time ago).
* Previously, Clang's behavior when the copy constructor was deleted
was unstable -- depending on whether the lazy declaration of the
copy constructor had been triggered, you might get different behavior.
We now eagerly declare the copy constructor whenever its deletedness
is unclear, and ignore deleted copy/move constructors when looking for
a trivial such constructor.
This also fixes an ABI difference between Clang and MSVC:
* If the copy constructor would be implicitly deleted (but has not been
lazily declared yet), for instance because the class has an rvalue
reference member, we would pass it directly. We now pass such a class
indirectly, matching MSVC.
Based on a patch by Vassil Vassilev, which was based on a patch by Bernd
Schmidt, which was based on a patch by Reid Kleckner!
This is a re-commit of r310401, which was reverted in r310464 due to ARM
failures (which should now be fixed).
llvm-svn: 310983
2017-08-16 09:49:53 +08:00
|
|
|
// CHECK-LABEL: define void @_ZN9move_ctor3barEv()
|
|
|
|
// CHECK: call void @_Z{{.*}}C1Ev(
|
|
|
|
// CHECK-NOT: call
|
2017-08-26 09:04:35 +08:00
|
|
|
// NEWABI: call void @_ZN9move_ctor3fooENS_1AE(%"struct.move_ctor::A"* %{{.*}})
|
|
|
|
// OLDABI: call void @_ZN9move_ctor3fooENS_1AE(i8* %{{.*}})
|
|
|
|
// NEWABI-LABEL: declare void @_ZN9move_ctor3fooENS_1AE(%"struct.move_ctor::A"*)
|
|
|
|
// OLDABI-LABEL: declare void @_ZN9move_ctor3fooENS_1AE(i8*)
|
2014-05-15 00:02:09 +08:00
|
|
|
|
|
|
|
// WIN64-LABEL: declare void @"\01?foo@move_ctor@@YAXUA@1@@Z"(%"struct.move_ctor::A"*)
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace all_deleted {
|
|
|
|
struct A {
|
|
|
|
A();
|
|
|
|
A(const A &o) = delete;
|
|
|
|
A(A &&o) = delete;
|
|
|
|
void *p;
|
|
|
|
};
|
|
|
|
void foo(A);
|
|
|
|
void bar() {
|
|
|
|
foo({});
|
|
|
|
}
|
PR19668, PR23034: Fix handling of move constructors and deleted copy
constructors when deciding whether classes should be passed indirectly.
This fixes ABI differences between Clang and GCC:
* Previously, Clang ignored the move constructor when making this
determination. It now takes the move constructor into account, per
https://github.com/itanium-cxx-abi/cxx-abi/pull/17 (this change may
seem recent, but the ABI change was agreed on the Itanium C++ ABI
list a long time ago).
* Previously, Clang's behavior when the copy constructor was deleted
was unstable -- depending on whether the lazy declaration of the
copy constructor had been triggered, you might get different behavior.
We now eagerly declare the copy constructor whenever its deletedness
is unclear, and ignore deleted copy/move constructors when looking for
a trivial such constructor.
This also fixes an ABI difference between Clang and MSVC:
* If the copy constructor would be implicitly deleted (but has not been
lazily declared yet), for instance because the class has an rvalue
reference member, we would pass it directly. We now pass such a class
indirectly, matching MSVC.
Based on a patch by Vassil Vassilev, which was based on a patch by Bernd
Schmidt, which was based on a patch by Reid Kleckner!
This is a re-commit of r310401, which was reverted in r310464 due to ARM
failures (which should now be fixed).
llvm-svn: 310983
2017-08-16 09:49:53 +08:00
|
|
|
// CHECK-LABEL: define void @_ZN11all_deleted3barEv()
|
|
|
|
// CHECK: call void @_Z{{.*}}C1Ev(
|
|
|
|
// CHECK-NOT: call
|
2017-08-26 09:04:35 +08:00
|
|
|
// NEWABI: call void @_ZN11all_deleted3fooENS_1AE(%"struct.all_deleted::A"* %{{.*}})
|
|
|
|
// OLDABI: call void @_ZN11all_deleted3fooENS_1AE(i8* %{{.*}})
|
|
|
|
// NEWABI-LABEL: declare void @_ZN11all_deleted3fooENS_1AE(%"struct.all_deleted::A"*)
|
|
|
|
// OLDABI-LABEL: declare void @_ZN11all_deleted3fooENS_1AE(i8*)
|
2014-05-15 00:02:09 +08:00
|
|
|
|
|
|
|
// WIN64-LABEL: declare void @"\01?foo@all_deleted@@YAXUA@1@@Z"(%"struct.all_deleted::A"*)
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace implicitly_deleted {
|
|
|
|
struct A {
|
|
|
|
A();
|
|
|
|
A &operator=(A &&o);
|
|
|
|
void *p;
|
|
|
|
};
|
|
|
|
void foo(A);
|
|
|
|
void bar() {
|
|
|
|
foo({});
|
|
|
|
}
|
PR19668, PR23034: Fix handling of move constructors and deleted copy
constructors when deciding whether classes should be passed indirectly.
This fixes ABI differences between Clang and GCC:
* Previously, Clang ignored the move constructor when making this
determination. It now takes the move constructor into account, per
https://github.com/itanium-cxx-abi/cxx-abi/pull/17 (this change may
seem recent, but the ABI change was agreed on the Itanium C++ ABI
list a long time ago).
* Previously, Clang's behavior when the copy constructor was deleted
was unstable -- depending on whether the lazy declaration of the
copy constructor had been triggered, you might get different behavior.
We now eagerly declare the copy constructor whenever its deletedness
is unclear, and ignore deleted copy/move constructors when looking for
a trivial such constructor.
This also fixes an ABI difference between Clang and MSVC:
* If the copy constructor would be implicitly deleted (but has not been
lazily declared yet), for instance because the class has an rvalue
reference member, we would pass it directly. We now pass such a class
indirectly, matching MSVC.
Based on a patch by Vassil Vassilev, which was based on a patch by Bernd
Schmidt, which was based on a patch by Reid Kleckner!
This is a re-commit of r310401, which was reverted in r310464 due to ARM
failures (which should now be fixed).
llvm-svn: 310983
2017-08-16 09:49:53 +08:00
|
|
|
// CHECK-LABEL: define void @_ZN18implicitly_deleted3barEv()
|
|
|
|
// CHECK: call void @_Z{{.*}}C1Ev(
|
|
|
|
// CHECK-NOT: call
|
2017-08-26 09:04:35 +08:00
|
|
|
// NEWABI: call void @_ZN18implicitly_deleted3fooENS_1AE(%"struct.implicitly_deleted::A"* %{{.*}})
|
|
|
|
// OLDABI: call void @_ZN18implicitly_deleted3fooENS_1AE(i8* %{{.*}})
|
|
|
|
// NEWABI-LABEL: declare void @_ZN18implicitly_deleted3fooENS_1AE(%"struct.implicitly_deleted::A"*)
|
|
|
|
// OLDABI-LABEL: declare void @_ZN18implicitly_deleted3fooENS_1AE(i8*)
|
PR19668, PR23034: Fix handling of move constructors and deleted copy
constructors when deciding whether classes should be passed indirectly.
This fixes ABI differences between Clang and GCC:
* Previously, Clang ignored the move constructor when making this
determination. It now takes the move constructor into account, per
https://github.com/itanium-cxx-abi/cxx-abi/pull/17 (this change may
seem recent, but the ABI change was agreed on the Itanium C++ ABI
list a long time ago).
* Previously, Clang's behavior when the copy constructor was deleted
was unstable -- depending on whether the lazy declaration of the
copy constructor had been triggered, you might get different behavior.
We now eagerly declare the copy constructor whenever its deletedness
is unclear, and ignore deleted copy/move constructors when looking for
a trivial such constructor.
This also fixes an ABI difference between Clang and MSVC:
* If the copy constructor would be implicitly deleted (but has not been
lazily declared yet), for instance because the class has an rvalue
reference member, we would pass it directly. We now pass such a class
indirectly, matching MSVC.
Based on a patch by Vassil Vassilev, which was based on a patch by Bernd
Schmidt, which was based on a patch by Reid Kleckner!
This is a re-commit of r310401, which was reverted in r310464 due to ARM
failures (which should now be fixed).
llvm-svn: 310983
2017-08-16 09:49:53 +08:00
|
|
|
|
|
|
|
// In MSVC 2013, the copy ctor is not deleted by a move assignment. In MSVC 2015, it is.
|
|
|
|
// WIN64-18-LABEL: declare void @"\01?foo@implicitly_deleted@@YAXUA@1@@Z"(i64
|
|
|
|
// WIN64-19-LABEL: declare void @"\01?foo@implicitly_deleted@@YAXUA@1@@Z"(%"struct.implicitly_deleted::A"*)
|
2014-05-15 00:02:09 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
namespace one_deleted {
|
|
|
|
struct A {
|
|
|
|
A();
|
|
|
|
A(A &&o) = delete;
|
|
|
|
void *p;
|
|
|
|
};
|
|
|
|
void foo(A);
|
|
|
|
void bar() {
|
|
|
|
foo({});
|
|
|
|
}
|
PR19668, PR23034: Fix handling of move constructors and deleted copy
constructors when deciding whether classes should be passed indirectly.
This fixes ABI differences between Clang and GCC:
* Previously, Clang ignored the move constructor when making this
determination. It now takes the move constructor into account, per
https://github.com/itanium-cxx-abi/cxx-abi/pull/17 (this change may
seem recent, but the ABI change was agreed on the Itanium C++ ABI
list a long time ago).
* Previously, Clang's behavior when the copy constructor was deleted
was unstable -- depending on whether the lazy declaration of the
copy constructor had been triggered, you might get different behavior.
We now eagerly declare the copy constructor whenever its deletedness
is unclear, and ignore deleted copy/move constructors when looking for
a trivial such constructor.
This also fixes an ABI difference between Clang and MSVC:
* If the copy constructor would be implicitly deleted (but has not been
lazily declared yet), for instance because the class has an rvalue
reference member, we would pass it directly. We now pass such a class
indirectly, matching MSVC.
Based on a patch by Vassil Vassilev, which was based on a patch by Bernd
Schmidt, which was based on a patch by Reid Kleckner!
This is a re-commit of r310401, which was reverted in r310464 due to ARM
failures (which should now be fixed).
llvm-svn: 310983
2017-08-16 09:49:53 +08:00
|
|
|
// CHECK-LABEL: define void @_ZN11one_deleted3barEv()
|
|
|
|
// CHECK: call void @_Z{{.*}}C1Ev(
|
|
|
|
// CHECK-NOT: call
|
2017-08-26 09:04:35 +08:00
|
|
|
// NEWABI: call void @_ZN11one_deleted3fooENS_1AE(%"struct.one_deleted::A"* %{{.*}})
|
|
|
|
// OLDABI: call void @_ZN11one_deleted3fooENS_1AE(i8* %{{.*}})
|
|
|
|
// NEWABI-LABEL: declare void @_ZN11one_deleted3fooENS_1AE(%"struct.one_deleted::A"*)
|
|
|
|
// OLDABI-LABEL: declare void @_ZN11one_deleted3fooENS_1AE(i8*)
|
2014-05-15 00:02:09 +08:00
|
|
|
|
|
|
|
// WIN64-LABEL: declare void @"\01?foo@one_deleted@@YAXUA@1@@Z"(%"struct.one_deleted::A"*)
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace copy_defaulted {
|
|
|
|
struct A {
|
|
|
|
A();
|
|
|
|
A(const A &o) = default;
|
|
|
|
A(A &&o) = delete;
|
|
|
|
void *p;
|
|
|
|
};
|
|
|
|
void foo(A);
|
|
|
|
void bar() {
|
|
|
|
foo({});
|
|
|
|
}
|
|
|
|
// CHECK-LABEL: define void @_ZN14copy_defaulted3barEv()
|
|
|
|
// CHECK: call void @_Z{{.*}}C1Ev(
|
2015-02-28 05:19:58 +08:00
|
|
|
// CHECK: load i8*, i8**
|
2014-05-15 00:02:09 +08:00
|
|
|
// CHECK: call void @_ZN14copy_defaulted3fooENS_1AE(i8* %{{.*}})
|
|
|
|
// CHECK-LABEL: declare void @_ZN14copy_defaulted3fooENS_1AE(i8*)
|
|
|
|
|
|
|
|
// WIN64-LABEL: declare void @"\01?foo@copy_defaulted@@YAXUA@1@@Z"(i64)
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace move_defaulted {
|
|
|
|
struct A {
|
|
|
|
A();
|
|
|
|
A(const A &o) = delete;
|
|
|
|
A(A &&o) = default;
|
|
|
|
void *p;
|
|
|
|
};
|
|
|
|
void foo(A);
|
|
|
|
void bar() {
|
|
|
|
foo({});
|
|
|
|
}
|
|
|
|
// CHECK-LABEL: define void @_ZN14move_defaulted3barEv()
|
|
|
|
// CHECK: call void @_Z{{.*}}C1Ev(
|
2015-02-28 05:19:58 +08:00
|
|
|
// CHECK: load i8*, i8**
|
2014-05-15 00:02:09 +08:00
|
|
|
// CHECK: call void @_ZN14move_defaulted3fooENS_1AE(i8* %{{.*}})
|
|
|
|
// CHECK-LABEL: declare void @_ZN14move_defaulted3fooENS_1AE(i8*)
|
|
|
|
|
|
|
|
// WIN64-LABEL: declare void @"\01?foo@move_defaulted@@YAXUA@1@@Z"(%"struct.move_defaulted::A"*)
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace trivial_defaulted {
|
|
|
|
struct A {
|
|
|
|
A();
|
|
|
|
A(const A &o) = default;
|
|
|
|
void *p;
|
|
|
|
};
|
|
|
|
void foo(A);
|
|
|
|
void bar() {
|
|
|
|
foo({});
|
|
|
|
}
|
|
|
|
// CHECK-LABEL: define void @_ZN17trivial_defaulted3barEv()
|
|
|
|
// CHECK: call void @_Z{{.*}}C1Ev(
|
2015-02-28 05:19:58 +08:00
|
|
|
// CHECK: load i8*, i8**
|
2014-05-15 00:02:09 +08:00
|
|
|
// CHECK: call void @_ZN17trivial_defaulted3fooENS_1AE(i8* %{{.*}})
|
|
|
|
// CHECK-LABEL: declare void @_ZN17trivial_defaulted3fooENS_1AE(i8*)
|
|
|
|
|
|
|
|
// WIN64-LABEL: declare void @"\01?foo@trivial_defaulted@@YAXUA@1@@Z"(i64)
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace two_copy_ctors {
|
|
|
|
struct A {
|
|
|
|
A();
|
|
|
|
A(const A &) = default;
|
|
|
|
A(const A &, int = 0);
|
|
|
|
void *p;
|
|
|
|
};
|
|
|
|
struct B : A {};
|
|
|
|
|
|
|
|
void foo(B);
|
|
|
|
void bar() {
|
|
|
|
foo({});
|
|
|
|
}
|
PR19668, PR23034: Fix handling of move constructors and deleted copy
constructors when deciding whether classes should be passed indirectly.
This fixes ABI differences between Clang and GCC:
* Previously, Clang ignored the move constructor when making this
determination. It now takes the move constructor into account, per
https://github.com/itanium-cxx-abi/cxx-abi/pull/17 (this change may
seem recent, but the ABI change was agreed on the Itanium C++ ABI
list a long time ago).
* Previously, Clang's behavior when the copy constructor was deleted
was unstable -- depending on whether the lazy declaration of the
copy constructor had been triggered, you might get different behavior.
We now eagerly declare the copy constructor whenever its deletedness
is unclear, and ignore deleted copy/move constructors when looking for
a trivial such constructor.
This also fixes an ABI difference between Clang and MSVC:
* If the copy constructor would be implicitly deleted (but has not been
lazily declared yet), for instance because the class has an rvalue
reference member, we would pass it directly. We now pass such a class
indirectly, matching MSVC.
Based on a patch by Vassil Vassilev, which was based on a patch by Bernd
Schmidt, which was based on a patch by Reid Kleckner!
This is a re-commit of r310401, which was reverted in r310464 due to ARM
failures (which should now be fixed).
llvm-svn: 310983
2017-08-16 09:49:53 +08:00
|
|
|
// CHECK-LABEL: define void @_ZN14two_copy_ctors3barEv()
|
|
|
|
// CHECK: call void @_Z{{.*}}C1Ev(
|
2017-08-26 09:04:35 +08:00
|
|
|
// NEWABI: call void @_ZN14two_copy_ctors3fooENS_1BE(%"struct.two_copy_ctors::B"* %{{.*}})
|
|
|
|
// OLDABI: call void @_ZN14two_copy_ctors3fooENS_1BE(%"struct.two_copy_ctors::B"* byval
|
|
|
|
// NEWABI-LABEL: declare void @_ZN14two_copy_ctors3fooENS_1BE(%"struct.two_copy_ctors::B"*)
|
|
|
|
// OLDABI-LABEL: declare void @_ZN14two_copy_ctors3fooENS_1BE(%"struct.two_copy_ctors::B"* byval
|
2014-05-15 00:02:09 +08:00
|
|
|
|
|
|
|
// WIN64-LABEL: declare void @"\01?foo@two_copy_ctors@@YAXUB@1@@Z"(%"struct.two_copy_ctors::B"*)
|
|
|
|
}
|
2016-11-22 08:21:43 +08:00
|
|
|
|
|
|
|
namespace definition_only {
|
|
|
|
struct A {
|
|
|
|
A();
|
|
|
|
A(A &&o);
|
|
|
|
void *p;
|
|
|
|
};
|
|
|
|
void *foo(A a) { return a.p; }
|
2017-08-26 09:04:35 +08:00
|
|
|
// NEWABI-LABEL: define i8* @_ZN15definition_only3fooENS_1AE(%"struct.definition_only::A"*
|
|
|
|
// OLDABI-LABEL: define i8* @_ZN15definition_only3fooENS_1AE(i8*
|
2016-11-22 08:43:30 +08:00
|
|
|
// WIN64-LABEL: define i8* @"\01?foo@definition_only@@YAPEAXUA@1@@Z"(%"struct.definition_only::A"*
|
2016-11-22 08:21:43 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
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; }
|
2017-08-26 09:04:35 +08:00
|
|
|
// NEWABI-LABEL: define i8* @_ZN17deleted_by_member3fooENS_1AE(%"struct.deleted_by_member::A"*
|
|
|
|
// OLDABI-LABEL: define i8* @_ZN17deleted_by_member3fooENS_1AE(i8*
|
2016-11-22 08:43:30 +08:00
|
|
|
// WIN64-LABEL: define i8* @"\01?foo@deleted_by_member@@YAPEAXUA@1@@Z"(%"struct.deleted_by_member::A"*
|
2016-11-22 08:21:43 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
namespace deleted_by_base {
|
|
|
|
struct B {
|
|
|
|
B();
|
|
|
|
B(B &&o);
|
|
|
|
void *p;
|
|
|
|
};
|
|
|
|
struct A : B {
|
|
|
|
A();
|
|
|
|
};
|
|
|
|
void *foo(A a) { return a.p; }
|
2017-08-26 09:04:35 +08:00
|
|
|
// NEWABI-LABEL: define i8* @_ZN15deleted_by_base3fooENS_1AE(%"struct.deleted_by_base::A"*
|
|
|
|
// OLDABI-LABEL: define i8* @_ZN15deleted_by_base3fooENS_1AE(i8*
|
2016-11-22 08:43:30 +08:00
|
|
|
// 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; }
|
2017-08-26 09:04:35 +08:00
|
|
|
// NEWABI-LABEL: define i8* @_ZN22deleted_by_member_copy3fooENS_1AE(%"struct.deleted_by_member_copy::A"*
|
|
|
|
// OLDABI-LABEL: define i8* @_ZN22deleted_by_member_copy3fooENS_1AE(i8*
|
2016-11-22 08:43:30 +08:00
|
|
|
// 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; }
|
2017-08-26 09:04:35 +08:00
|
|
|
// NEWABI-LABEL: define i8* @_ZN20deleted_by_base_copy3fooENS_1AE(%"struct.deleted_by_base_copy::A"*
|
|
|
|
// OLDABI-LABEL: define i8* @_ZN20deleted_by_base_copy3fooENS_1AE(i8*
|
2016-11-22 08:43:30 +08:00
|
|
|
// WIN64-LABEL: define i8* @"\01?foo@deleted_by_base_copy@@YAPEAXUA@1@@Z"(%"struct.deleted_by_base_copy::A"*
|
2016-11-22 08:21:43 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
namespace explicit_delete {
|
|
|
|
struct A {
|
|
|
|
A();
|
|
|
|
A(const A &o) = delete;
|
|
|
|
void *p;
|
|
|
|
};
|
2017-08-26 09:04:35 +08:00
|
|
|
// NEWABI-LABEL: define i8* @_ZN15explicit_delete3fooENS_1AE(%"struct.explicit_delete::A"*
|
|
|
|
// OLDABI-LABEL: define i8* @_ZN15explicit_delete3fooENS_1AE(i8*
|
2016-11-22 08:43:30 +08:00
|
|
|
// WIN64-LABEL: define i8* @"\01?foo@explicit_delete@@YAPEAXUA@1@@Z"(%"struct.explicit_delete::A"*
|
2016-11-22 08:21:43 +08:00
|
|
|
void *foo(A a) { return a.p; }
|
|
|
|
}
|
PR19668, PR23034: Fix handling of move constructors and deleted copy
constructors when deciding whether classes should be passed indirectly.
This fixes ABI differences between Clang and GCC:
* Previously, Clang ignored the move constructor when making this
determination. It now takes the move constructor into account, per
https://github.com/itanium-cxx-abi/cxx-abi/pull/17 (this change may
seem recent, but the ABI change was agreed on the Itanium C++ ABI
list a long time ago).
* Previously, Clang's behavior when the copy constructor was deleted
was unstable -- depending on whether the lazy declaration of the
copy constructor had been triggered, you might get different behavior.
We now eagerly declare the copy constructor whenever its deletedness
is unclear, and ignore deleted copy/move constructors when looking for
a trivial such constructor.
This also fixes an ABI difference between Clang and MSVC:
* If the copy constructor would be implicitly deleted (but has not been
lazily declared yet), for instance because the class has an rvalue
reference member, we would pass it directly. We now pass such a class
indirectly, matching MSVC.
Based on a patch by Vassil Vassilev, which was based on a patch by Bernd
Schmidt, which was based on a patch by Reid Kleckner!
This is a re-commit of r310401, which was reverted in r310464 due to ARM
failures (which should now be fixed).
llvm-svn: 310983
2017-08-16 09:49:53 +08:00
|
|
|
|
|
|
|
namespace implicitly_deleted_copy_ctor {
|
|
|
|
struct A {
|
|
|
|
// No move ctor due to copy assignment.
|
|
|
|
A &operator=(const A&);
|
|
|
|
// Deleted copy ctor due to rvalue ref member.
|
|
|
|
int &&ref;
|
|
|
|
};
|
2017-08-26 09:04:35 +08:00
|
|
|
// NEWABI-LABEL: define {{.*}} @_ZN28implicitly_deleted_copy_ctor3fooENS_1AE(%"struct.implicitly_deleted_copy_ctor::A"*
|
|
|
|
// OLDABI-LABEL: define {{.*}} @_ZN28implicitly_deleted_copy_ctor3fooENS_1AE(i32*
|
PR19668, PR23034: Fix handling of move constructors and deleted copy
constructors when deciding whether classes should be passed indirectly.
This fixes ABI differences between Clang and GCC:
* Previously, Clang ignored the move constructor when making this
determination. It now takes the move constructor into account, per
https://github.com/itanium-cxx-abi/cxx-abi/pull/17 (this change may
seem recent, but the ABI change was agreed on the Itanium C++ ABI
list a long time ago).
* Previously, Clang's behavior when the copy constructor was deleted
was unstable -- depending on whether the lazy declaration of the
copy constructor had been triggered, you might get different behavior.
We now eagerly declare the copy constructor whenever its deletedness
is unclear, and ignore deleted copy/move constructors when looking for
a trivial such constructor.
This also fixes an ABI difference between Clang and MSVC:
* If the copy constructor would be implicitly deleted (but has not been
lazily declared yet), for instance because the class has an rvalue
reference member, we would pass it directly. We now pass such a class
indirectly, matching MSVC.
Based on a patch by Vassil Vassilev, which was based on a patch by Bernd
Schmidt, which was based on a patch by Reid Kleckner!
This is a re-commit of r310401, which was reverted in r310464 due to ARM
failures (which should now be fixed).
llvm-svn: 310983
2017-08-16 09:49:53 +08:00
|
|
|
// WIN64-LABEL: define {{.*}} @"\01?foo@implicitly_deleted_copy_ctor@@YAAEAHUA@1@@Z"(%"struct.implicitly_deleted_copy_ctor::A"*
|
|
|
|
int &foo(A a) { return a.ref; }
|
|
|
|
|
|
|
|
struct B {
|
|
|
|
// Passed direct: has non-deleted trivial copy ctor.
|
|
|
|
B &operator=(const B&);
|
|
|
|
int &ref;
|
|
|
|
};
|
|
|
|
int &foo(B b) { return b.ref; }
|
|
|
|
// CHECK-LABEL: define {{.*}} @_ZN28implicitly_deleted_copy_ctor3fooENS_1BE(i32*
|
|
|
|
// WIN64-LABEL: define {{.*}} @"\01?foo@implicitly_deleted_copy_ctor@@YAAEAHUB@1@@Z"(i64
|
|
|
|
|
|
|
|
struct X { X(const X&); };
|
|
|
|
struct Y { Y(const Y&) = default; };
|
|
|
|
|
|
|
|
union C {
|
|
|
|
C &operator=(const C&);
|
|
|
|
// Passed indirect: copy ctor deleted due to variant member with nontrivial copy ctor.
|
|
|
|
X x;
|
|
|
|
int n;
|
|
|
|
};
|
|
|
|
int foo(C c) { return c.n; }
|
|
|
|
// CHECK-LABEL: define {{.*}} @_ZN28implicitly_deleted_copy_ctor3fooENS_1CE(%"union.implicitly_deleted_copy_ctor::C"*
|
|
|
|
// WIN64-LABEL: define {{.*}} @"\01?foo@implicitly_deleted_copy_ctor@@YAHTC@1@@Z"(%"union.implicitly_deleted_copy_ctor::C"*
|
|
|
|
|
|
|
|
struct D {
|
|
|
|
D &operator=(const D&);
|
|
|
|
// Passed indirect: copy ctor deleted due to variant member with nontrivial copy ctor.
|
|
|
|
union {
|
|
|
|
X x;
|
|
|
|
int n;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
int foo(D d) { return d.n; }
|
|
|
|
// CHECK-LABEL: define {{.*}} @_ZN28implicitly_deleted_copy_ctor3fooENS_1DE(%"struct.implicitly_deleted_copy_ctor::D"*
|
|
|
|
// WIN64-LABEL: define {{.*}} @"\01?foo@implicitly_deleted_copy_ctor@@YAHUD@1@@Z"(%"struct.implicitly_deleted_copy_ctor::D"*
|
|
|
|
|
|
|
|
union E {
|
|
|
|
// Passed direct: has non-deleted trivial copy ctor.
|
|
|
|
E &operator=(const E&);
|
|
|
|
Y y;
|
|
|
|
int n;
|
|
|
|
};
|
|
|
|
int foo(E e) { return e.n; }
|
|
|
|
// CHECK-LABEL: define {{.*}} @_ZN28implicitly_deleted_copy_ctor3fooENS_1EE(i32
|
|
|
|
// WIN64-LABEL: define {{.*}} @"\01?foo@implicitly_deleted_copy_ctor@@YAHTE@1@@Z"(i32
|
|
|
|
|
|
|
|
struct F {
|
|
|
|
// Passed direct: has non-deleted trivial copy ctor.
|
|
|
|
F &operator=(const F&);
|
|
|
|
union {
|
|
|
|
Y y;
|
|
|
|
int n;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
int foo(F f) { return f.n; }
|
|
|
|
// CHECK-LABEL: define {{.*}} @_ZN28implicitly_deleted_copy_ctor3fooENS_1FE(i32
|
|
|
|
// WIN64-LABEL: define {{.*}} @"\01?foo@implicitly_deleted_copy_ctor@@YAHUF@1@@Z"(i32
|
|
|
|
}
|