[cfe-commits] r124453 - in /cfe/trunk: lib/CodeGen/CGExpr.cpp test/CodeGenCXX/rvalue-references.cpp

Douglas Gregor dgregor at apple.com
Thu Jan 27 15:22:05 PST 2011


Author: dgregor
Date: Thu Jan 27 17:22:05 2011
New Revision: 124453

URL: http://llvm.org/viewvc/llvm-project?rev=124453&view=rev
Log:
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.

Modified:
    cfe/trunk/lib/CodeGen/CGExpr.cpp
    cfe/trunk/test/CodeGenCXX/rvalue-references.cpp

Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=124453&r1=124452&r2=124453&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExpr.cpp Thu Jan 27 17:22:05 2011
@@ -1772,11 +1772,12 @@
   }
 
   case CK_NoOp:
-    if (!E->getSubExpr()->isRValue() || E->getType()->isRecordType())
+  case CK_LValueToRValue:
+    if (!E->getSubExpr()->Classify(getContext()).isPRValue() 
+        || E->getType()->isRecordType())
       return EmitLValue(E->getSubExpr());
     // Fall through to synthesize a temporary.
 
-  case CK_LValueToRValue:
   case CK_BitCast:
   case CK_ArrayToPointerDecay:
   case CK_FunctionToPointerDecay:

Modified: cfe/trunk/test/CodeGenCXX/rvalue-references.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/rvalue-references.cpp?rev=124453&r1=124452&r2=124453&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/rvalue-references.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/rvalue-references.cpp Thu Jan 27 17:22:05 2011
@@ -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
+}





More information about the cfe-commits mailing list