From 2d6b0e94db30c0e2754d270753c6f75478e451bf Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Sat, 22 May 2010 05:17:18 +0000 Subject: Improve our handling of reference binding for subobjects of temporaries. There are actually several interrelated fixes here: - When converting an object to a base class, it's only an lvalue cast when the original object was an lvalue and we aren't casting pointer-to-derived to pointer-to-base. Previously, we were misclassifying derived-to-base casts of class rvalues as lvalues, causing various oddities (including problems with reference binding not extending the lifetimes of some temporaries). - Teach the code for emitting a reference binding how to look through no-op casts and parentheses directly, since Expr::IgnoreParenNoOpCasts is just plain wrong for this. Also, make sure that we properly look through multiple levels of indirection from the temporary object, but destroy the actual temporary object; this fixes the reference-binding issue mentioned above. - Teach Objective-C message sends to bind the result as a temporary when needed. This is actually John's change, but it triggered the reference-binding problem above, so it's included here. Now John can actually test his return-slot improvements. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@104434 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGExpr.cpp | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) (limited to 'lib/CodeGen/CGExpr.cpp') diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index 74e64e59a5..17d85dc9d9 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -211,9 +211,15 @@ RValue CodeGenFunction::EmitReferenceBindingToExpr(const Expr* E, llvm::SmallVector Adjustments; do { - if (const CastExpr *CE - = dyn_cast(E->IgnoreParenNoopCasts(getContext()))) { - if (CE->getCastKind() == CastExpr::CK_DerivedToBase) { + if (const ParenExpr *PE = dyn_cast(E)) { + E = PE->getSubExpr(); + continue; + } + + if (const CastExpr *CE = dyn_cast(E)) { + if ((CE->getCastKind() == CastExpr::CK_DerivedToBase || + CE->getCastKind() == CastExpr::CK_UncheckedDerivedToBase) && + E->getType()->isRecordType()) { E = CE->getSubExpr(); CXXRecordDecl *Derived = cast(E->getType()->getAs()->getDecl()); @@ -221,9 +227,12 @@ RValue CodeGenFunction::EmitReferenceBindingToExpr(const Expr* E, Derived)); continue; } - } else if (const MemberExpr *ME - = dyn_cast( - E->IgnoreParenNoopCasts(getContext()))) { + + if (CE->getCastKind() == CastExpr::CK_NoOp) { + E = CE->getSubExpr(); + continue; + } + } else if (const MemberExpr *ME = dyn_cast(E)) { if (ME->getBase()->isLvalue(getContext()) != Expr::LV_Valid && ME->getBase()->getType()->isRecordType()) { if (FieldDecl *Field = dyn_cast(ME->getMemberDecl())) { @@ -234,7 +243,10 @@ RValue CodeGenFunction::EmitReferenceBindingToExpr(const Expr* E, } } } - } while (false); + + // Nothing changed. + break; + } while (true); Val = EmitAnyExprToTemp(E, /*IsAggLocVolatile=*/false, IsInitializer); -- cgit v1.2.3-70-g09d2