forked from OSchip/llvm-project
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
This commit is contained in:
parent
63dce02544
commit
66413c29d3
|
@ -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()) {
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue