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
This commit is contained in:
Anders Carlsson 2009-10-15 00:51:46 +00:00
parent 63dce02544
commit 66413c29d3
2 changed files with 53 additions and 4 deletions

View File

@ -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()) {

View File

@ -1,4 +1,4 @@
// RUN: clang-cc -verify -emit-llvm -o %t %s
// RUN: clang-cc -verify -emit-llvm -o - %s | FileCheck %s
void t1() {
extern int& a;
@ -100,3 +100,10 @@ void f(A* a) {
void *foo = 0;
void * const & kFoo = foo;
struct D : C { D(); ~D(); };
void h() {
// CHECK: call void @_ZN1DD1Ev
const C& c = D();
}