[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