summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2014-01-11 01:24:05 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2014-01-11 01:24:05 +0000
commit454b4af0b0bb4234c0c2f56b935323c17043c447 (patch)
tree5b2d447128f2ae9d4e004684fa1495413f2f62a1
parent55d3a0c3d4777d8bbb5c5ddc735d5d61b328a2b2 (diff)
downloadbcm5719-llvm-454b4af0b0bb4234c0c2f56b935323c17043c447.tar.gz
bcm5719-llvm-454b4af0b0bb4234c0c2f56b935323c17043c447.zip
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. llvm-svn: 198991
-rw-r--r--clang/lib/CodeGen/CGStmt.cpp3
-rw-r--r--clang/test/CodeGenCXX/no-elide-constructors.cpp35
2 files changed, 37 insertions, 1 deletions
diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp
index b18ff09015a..83b5fa9228a 100644
--- a/clang/lib/CodeGen/CGStmt.cpp
+++ b/clang/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/clang/test/CodeGenCXX/no-elide-constructors.cpp b/clang/test/CodeGenCXX/no-elide-constructors.cpp
new file mode 100644
index 00000000000..ecb350f43ec
--- /dev/null
+++ b/clang/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;
+}
OpenPOWER on IntegriCloud