From: Richard Smith Date: Sat, 11 Jan 2014 01:24:05 +0000 (+0000) Subject: PR12208: Under -fno-elide-constructors, don't forget to actually copy an NRVO X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=daffa2c523921ffdd333be145e7f0f77cd02f39c;p=clang PR12208: Under -fno-elide-constructors, don't forget to actually copy an NRVO variable to the return slot. Patch by David Wiberg, with test case alterations by me. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@198991 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp index b18ff09015..83b5fa9228 100644 --- a/lib/CodeGen/CGStmt.cpp +++ b/lib/CodeGen/CGStmt.cpp @@ -871,7 +871,8 @@ void CodeGenFunction::EmitReturnStmt(const ReturnStmt &S) { // FIXME: Clean this up by using an LValue for ReturnTemp, // EmitStoreThroughLValue, and EmitAnyExpr. - if (S.getNRVOCandidate() && S.getNRVOCandidate()->isNRVOVariable()) { + if (getLangOpts().ElideConstructors && + S.getNRVOCandidate() && S.getNRVOCandidate()->isNRVOVariable()) { // Apply the named return value optimization for this return statement, // which means doing nothing: the appropriate result has already been // constructed into the NRVO variable. diff --git a/test/CodeGenCXX/no-elide-constructors.cpp b/test/CodeGenCXX/no-elide-constructors.cpp new file mode 100644 index 0000000000..ecb350f43e --- /dev/null +++ b/test/CodeGenCXX/no-elide-constructors.cpp @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 -std=c++98 -triple i386-unknown-unknown -fno-elide-constructors -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-CXX98 +// RUN: %clang_cc1 -std=c++11 -triple i386-unknown-unknown -fno-elide-constructors -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-CXX11 +// RUN: %clang_cc1 -std=c++98 -triple i386-unknown-unknown -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-CXX98-ELIDE +// RUN: %clang_cc1 -std=c++11 -triple i386-unknown-unknown -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-CXX11-ELIDE + +// Reduced from PR12208 +class X { +public: + X(); + X(const X&); +#if __cplusplus >= 201103L + X(X&&); +#endif + ~X(); +}; + +// CHECK-LABEL: define void @_Z4Testv( +X Test() +{ + X x; + + // Check that the copy constructor for X is called with result variable as + // sret argument. + // CHECK-CXX98: call void @_ZN1XC1ERKS_( + // CHECK-CXX11: call void @_ZN1XC1EOS_( + // CHECK-CXX98-ELIDE-NOT: call void @_ZN1XC1ERKS_( + // CHECK-CXX11-ELIDE-NOT: call void @_ZN1XC1EOS_( + + // Make sure that the destructor for X is called. + // FIXME: This call is present even in the -ELIDE runs, but is guarded by a + // branch that is never taken in those cases. We could generate better IR + // here. + // CHECK: call void @_ZN1XD1Ev( + return x; +}