diff options
| author | Anders Carlsson <andersca@mac.com> | 2009-10-15 00:51:46 +0000 |
|---|---|---|
| committer | Anders Carlsson <andersca@mac.com> | 2009-10-15 00:51:46 +0000 |
| commit | 66413c29d395e69219302025203434558e462617 (patch) | |
| tree | d84e56d8744822d3b571dd5d2330e11978db4907 /clang/lib/CodeGen | |
| parent | 63dce025449eecf17678ce1c5b6fac4a1b582e9e (diff) | |
| download | bcm5719-llvm-66413c29d395e69219302025203434558e462617.tar.gz bcm5719-llvm-66413c29d395e69219302025203434558e462617.zip | |
Handle
struct A { };
struct B : A { };
void f() {
const A& a = B();
}
correctly. (This now does the offset conversion if necessary and calls the destructor when a goes out of scope).
llvm-svn: 84162
Diffstat (limited to 'clang/lib/CodeGen')
| -rw-r--r-- | clang/lib/CodeGen/CGExpr.cpp | 48 |
1 files changed, 45 insertions, 3 deletions
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 2834dfeb780..01a057f6745 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -78,6 +78,26 @@ RValue CodeGenFunction::EmitAnyExprToTemp(const Expr *E, RValue CodeGenFunction::EmitReferenceBindingToExpr(const Expr* E, QualType DestType, bool IsInitializer) { + if (const CXXExprWithTemporaries *TE = dyn_cast<CXXExprWithTemporaries>(E)) { + // If we shouldn't destroy the temporaries, just emit the + // child expression. + if (!TE->shouldDestroyTemporaries()) + return EmitReferenceBindingToExpr(TE->getSubExpr(), DestType, + IsInitializer); + + // Keep track of the current cleanup stack depth. + unsigned OldNumLiveTemporaries = LiveTemporaries.size(); + + RValue RV = EmitReferenceBindingToExpr(TE->getSubExpr(), DestType, + IsInitializer); + + // Pop temporaries. + while (LiveTemporaries.size() > OldNumLiveTemporaries) + PopCXXTemporary(); + + return RV; + } + RValue Val; if (E->isLvalue(getContext()) == Expr::LV_Valid) { // Emit the expr as an lvalue. @@ -86,9 +106,21 @@ RValue CodeGenFunction::EmitReferenceBindingToExpr(const Expr* E, return RValue::get(LV.getAddress()); Val = EmitLoadOfLValue(LV, E->getType()); } else { - // FIXME: Initializers don't work with casts yet. For example - // const A& a = B(); - // if B inherits from A. + const CXXRecordDecl *BaseClassDecl = 0; + const CXXRecordDecl *DerivedClassDecl = 0; + + if (const CastExpr *CE = + dyn_cast<CastExpr>(E->IgnoreParenNoopCasts(getContext()))) { + if (CE->getCastKind() == CastExpr::CK_DerivedToBase) { + E = CE->getSubExpr(); + + BaseClassDecl = + cast<CXXRecordDecl>(CE->getType()->getAs<RecordType>()->getDecl()); + DerivedClassDecl = + cast<CXXRecordDecl>(E->getType()->getAs<RecordType>()->getDecl()); + } + } + Val = EmitAnyExprToTemp(E, /*IsAggLocVolatile=*/false, IsInitializer); @@ -106,6 +138,16 @@ RValue CodeGenFunction::EmitReferenceBindingToExpr(const Expr* E, } } } + + // Check if need to perform the derived-to-base cast. + if (BaseClassDecl) { + llvm::Value *Derived = Val.getAggregateAddr(); + + llvm::Value *Base = + GetAddressCXXOfBaseClass(Derived, DerivedClassDecl, BaseClassDecl, + /*NullCheckValue=*/false); + return RValue::get(Base); + } } if (Val.isAggregate()) { |

