aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/CGExpr.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2010-07-15 18:04:13 +0000
committerDouglas Gregor <dgregor@apple.com>2010-07-15 18:04:13 +0000
commit5467209f23097d5b0fc628c18aaa85e73d386598 (patch)
treec2fefa1bef840cf3e33150dd17a8e796ec47f42d /lib/CodeGen/CGExpr.cpp
parent24978863d13e12278799df62edaa2ddf33ff2fba (diff)
Teach CodeGenFunction::EmitCastLValue() to handle casts to an lvalue
that involve binding a reference to a pure rvalue temporary (e.g., not a class temporary), by creating a new temporary and copying the result there. Fixes PR6024. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@108431 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGExpr.cpp')
-rw-r--r--lib/CodeGen/CGExpr.cpp55
1 files changed, 43 insertions, 12 deletions
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
index 43bab9fece..94fb086b4c 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/lib/CodeGen/CGExpr.cpp
@@ -1749,8 +1749,48 @@ CodeGenFunction::EmitConditionalOperatorLValue(const ConditionalOperator* E) {
/// cast from scalar to union.
LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
switch (E->getCastKind()) {
- default:
+ case CastExpr::CK_ToVoid:
return EmitUnsupportedLValue(E, "unexpected cast lvalue");
+
+ case CastExpr::CK_NoOp:
+ if (E->getSubExpr()->getType()->isRecordType() ||
+ E->getSubExpr()->isLvalue(getContext()) == Expr::LV_Valid) {
+ LValue LV = EmitLValue(E->getSubExpr());
+ if (LV.isPropertyRef()) {
+ QualType QT = E->getSubExpr()->getType();
+ RValue RV = EmitLoadOfPropertyRefLValue(LV, QT);
+ assert(!RV.isScalar() && "EmitCastLValue - scalar cast of property ref");
+ llvm::Value *V = RV.getAggregateAddr();
+ return LValue::MakeAddr(V, MakeQualifiers(QT));
+ }
+ return LV;
+ }
+ // Fall through to synthesize a temporary.
+
+ case CastExpr::CK_Unknown:
+ case CastExpr::CK_BitCast:
+ case CastExpr::CK_ArrayToPointerDecay:
+ case CastExpr::CK_FunctionToPointerDecay:
+ case CastExpr::CK_NullToMemberPointer:
+ case CastExpr::CK_IntegralToPointer:
+ case CastExpr::CK_PointerToIntegral:
+ case CastExpr::CK_VectorSplat:
+ case CastExpr::CK_IntegralCast:
+ case CastExpr::CK_IntegralToFloating:
+ case CastExpr::CK_FloatingToIntegral:
+ case CastExpr::CK_FloatingCast:
+ case CastExpr::CK_DerivedToBaseMemberPointer:
+ case CastExpr::CK_BaseToDerivedMemberPointer:
+ case CastExpr::CK_MemberPointerToBoolean:
+ case CastExpr::CK_AnyPointerToBlockPointerCast: {
+ // These casts only produce lvalues when we're binding a reference to a
+ // temporary realized from a (converted) pure rvalue. Emit the expression
+ // as a value, copy it into a temporary, and return an lvalue referring to
+ // that temporary.
+ llvm::Value *V = CreateMemTemp(E->getType(), "ref.temp");
+ EmitAnyExprToMem(E, V, false, false);
+ return LValue::MakeAddr(V, MakeQualifiers(E->getType()));
+ }
case CastExpr::CK_Dynamic: {
LValue LV = EmitLValue(E->getSubExpr());
@@ -1760,17 +1800,6 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
MakeQualifiers(E->getType()));
}
- case CastExpr::CK_NoOp: {
- LValue LV = EmitLValue(E->getSubExpr());
- if (LV.isPropertyRef()) {
- QualType QT = E->getSubExpr()->getType();
- RValue RV = EmitLoadOfPropertyRefLValue(LV, QT);
- assert(!RV.isScalar() && "EmitCastLValue - scalar cast of property ref");
- llvm::Value *V = RV.getAggregateAddr();
- return LValue::MakeAddr(V, MakeQualifiers(QT));
- }
- return LV;
- }
case CastExpr::CK_ConstructorConversion:
case CastExpr::CK_UserDefinedConversion:
case CastExpr::CK_AnyPointerToObjCPointerCast:
@@ -1826,6 +1855,8 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
return LValue::MakeAddr(V, MakeQualifiers(E->getType()));
}
}
+
+ llvm_unreachable("Unhandled lvalue cast kind?");
}
LValue CodeGenFunction::EmitNullInitializationLValue(