aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2010-05-22 05:17:18 +0000
committerDouglas Gregor <dgregor@apple.com>2010-05-22 05:17:18 +0000
commit2d6b0e94db30c0e2754d270753c6f75478e451bf (patch)
tree789d9601397ddcd59cd006e9e0c5cabfa5c2edc9 /lib/CodeGen
parent5e30b8bf56c41fcfec63ae82ddd461c99f3c4221 (diff)
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
Diffstat (limited to 'lib/CodeGen')
-rw-r--r--lib/CodeGen/CGExpr.cpp26
-rw-r--r--lib/CodeGen/CGExprAgg.cpp8
2 files changed, 27 insertions, 7 deletions
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<SubobjectAdjustment, 2> Adjustments;
do {
- if (const CastExpr *CE
- = dyn_cast<CastExpr>(E->IgnoreParenNoopCasts(getContext()))) {
- if (CE->getCastKind() == CastExpr::CK_DerivedToBase) {
+ if (const ParenExpr *PE = dyn_cast<ParenExpr>(E)) {
+ E = PE->getSubExpr();
+ continue;
+ }
+
+ if (const CastExpr *CE = dyn_cast<CastExpr>(E)) {
+ if ((CE->getCastKind() == CastExpr::CK_DerivedToBase ||
+ CE->getCastKind() == CastExpr::CK_UncheckedDerivedToBase) &&
+ E->getType()->isRecordType()) {
E = CE->getSubExpr();
CXXRecordDecl *Derived
= cast<CXXRecordDecl>(E->getType()->getAs<RecordType>()->getDecl());
@@ -221,9 +227,12 @@ RValue CodeGenFunction::EmitReferenceBindingToExpr(const Expr* E,
Derived));
continue;
}
- } else if (const MemberExpr *ME
- = dyn_cast<MemberExpr>(
- E->IgnoreParenNoopCasts(getContext()))) {
+
+ if (CE->getCastKind() == CastExpr::CK_NoOp) {
+ E = CE->getSubExpr();
+ continue;
+ }
+ } else if (const MemberExpr *ME = dyn_cast<MemberExpr>(E)) {
if (ME->getBase()->isLvalue(getContext()) != Expr::LV_Valid &&
ME->getBase()->getType()->isRecordType()) {
if (FieldDecl *Field = dyn_cast<FieldDecl>(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);
diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp
index aa32bb8d8d..7b0c316c9d 100644
--- a/lib/CodeGen/CGExprAgg.cpp
+++ b/lib/CodeGen/CGExprAgg.cpp
@@ -216,6 +216,14 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) {
break;
}
+ case CastExpr::CK_DerivedToBase:
+ case CastExpr::CK_BaseToDerived:
+ case CastExpr::CK_UncheckedDerivedToBase: {
+ assert(0 && "cannot perform hierarchy conversion in EmitAggExpr: "
+ "should have been unpacked before we got here");
+ break;
+ }
+
// FIXME: Remove the CK_Unknown check here.
case CastExpr::CK_Unknown:
case CastExpr::CK_NoOp: