When producing IR for a lvalue-to-rvalue cast *as an lvalue*, only
non-class prvalues actually require the realization of a
temporary. For everything else, we already have an lvalue (or class
prvalue) in the subexpression.

Note: we're missing some move elision in this case. I'll tackle that next.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@124453 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/test/CodeGenCXX/rvalue-references.cpp b/test/CodeGenCXX/rvalue-references.cpp
index 693e143..a7c74ae 100644
--- a/test/CodeGenCXX/rvalue-references.cpp
+++ b/test/CodeGenCXX/rvalue-references.cpp
@@ -34,3 +34,55 @@
 // CHECK-NEXT: store i32 {{.*}}, i32*
 // CHECK-NEXT: ret i32*
 int &&f2() { return static_cast<int&&>(getIntPRValue()); }
+
+bool ok;
+
+class C
+{
+   int* state_;
+
+   C(const C&) = delete;
+   C& operator=(const C&) = delete;
+public:
+  C(int state) : state_(new int(state)) { }
+  
+  C(C&& a) {
+    state_ = a.state_; 
+    a.state_ = 0;
+  }
+
+  ~C() {
+    delete state_; 
+    state_ = 0;
+  }
+};
+
+C test();
+
+// CHECK: define void @_Z15elide_copy_initv
+void elide_copy_init() {
+  ok = false;
+  // FIXME: We're doing an extra move here, when we shouldn't be!
+  // CHECK: call void @_Z4testv(%class.C* sret %ref.tmp)
+  // CHECK: call void @_ZN1CC1EOS_(%class.C* %a, %class.C* %ref.tmp)
+  // CHECK: call void @_ZN1CD1Ev(%class.C* %ref.tmp)
+  C a = test();
+  // CHECK: call void @_ZN1CD1Ev(%class.C* %a)
+  // CHECK: ret void
+}
+
+// CHECK: define void @_Z16test_move_returnv
+C test_move_return() {
+  // CHECK: call void @_ZN1CC1Ei
+  C a1(3);
+  // CHECK: call void @_ZN1CC1Ei
+  C a2(4);
+  if (ok)
+    // CHECK: call void @_ZN1CC1EOS_
+    return a1;
+  // CHECK: call void @_ZN1CC1EOS_
+  return a2;
+  // CHECK: call void @_ZN1CD1Ev
+  // CHECK: call void @_ZN1CD1Ev
+  //CHECK:  ret void
+}