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 | 122f88d481971b68d05ba12395c3b73ab4b31ab3 (patch) | |
| tree | c59ee8196c104634ee39555cc8b9d97ee5d75b5c /clang/test/CodeGenCXX | |
| parent | 2187bb8a89cdbe529ee222bf56d1b7415337cb20 (diff) | |
| download | bcm5719-llvm-122f88d481971b68d05ba12395c3b73ab4b31ab3.tar.gz bcm5719-llvm-122f88d481971b68d05ba12395c3b73ab4b31ab3.zip | |
[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.
llvm-svn: 288866
Diffstat (limited to 'clang/test/CodeGenCXX')
| -rw-r--r-- | clang/test/CodeGenCXX/cxx1z-copy-omission.cpp | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/clang/test/CodeGenCXX/cxx1z-copy-omission.cpp b/clang/test/CodeGenCXX/cxx1z-copy-omission.cpp new file mode 100644 index 00000000000..234e4b12589 --- /dev/null +++ b/clang/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: } +} |

