diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2016-12-06 23:52:28 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2016-12-06 23:52:28 +0000 |
commit | 9d208e19f424c4a10afbd6d391cd3cbe49a1d6d4 (patch) | |
tree | 04fc1ea37b0d9a65a64d5309cd4b3fac12f4648b /test/CodeGenCXX/cxx1z-copy-omission.cpp | |
parent | 31a3f52040e75efea0e486ddc168b604947451fe (diff) |
[c++17] P0135R1: Guaranteed copy elision.
When an object of class type is initialized from a prvalue of the same type
(ignoring cv qualifications), use the prvalue to initialize the object directly
instead of inserting a redundant elidable call to a copy constructor.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@288866 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test/CodeGenCXX/cxx1z-copy-omission.cpp')
-rw-r--r-- | test/CodeGenCXX/cxx1z-copy-omission.cpp | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/test/CodeGenCXX/cxx1z-copy-omission.cpp b/test/CodeGenCXX/cxx1z-copy-omission.cpp new file mode 100644 index 0000000000..234e4b1258 --- /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: } +} |