]> granicus.if.org Git - clang/commitdiff
PR12208: Under -fno-elide-constructors, don't forget to actually copy an NRVO
authorRichard Smith <richard-llvm@metafoo.co.uk>
Sat, 11 Jan 2014 01:24:05 +0000 (01:24 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Sat, 11 Jan 2014 01:24:05 +0000 (01:24 +0000)
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

lib/CodeGen/CGStmt.cpp
test/CodeGenCXX/no-elide-constructors.cpp [new file with mode: 0644]

index b18ff09015aa8228ef8e1abed956b2c3d8ec4a9e..83b5fa9228a07bee2bfd28580b3f72ca71be0041 100644 (file)
@@ -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 (file)
index 0000000..ecb350f
--- /dev/null
@@ -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;
+}