diff options
| author | Anders Carlsson <andersca@mac.com> | 2009-09-12 16:16:49 +0000 |
|---|---|---|
| committer | Anders Carlsson <andersca@mac.com> | 2009-09-12 16:16:49 +0000 |
| commit | d95f9608abeb8f6f144a4234427d504aee8bf908 (patch) | |
| tree | 10225f9f8a2d7c0a3aac43a3bd9c6aa16a60a1bc /clang/lib | |
| parent | 882b798a50cc54440698a204c6dd8c0d07d5f317 (diff) | |
| download | llvm-d95f9608abeb8f6f144a4234427d504aee8bf908.zip llvm-d95f9608abeb8f6f144a4234427d504aee8bf908.tar.gz llvm-d95f9608abeb8f6f144a4234427d504aee8bf908.tar.bz2 | |
Handle CK_DerivedToBase when emitting lvalue casts.
llvm-svn: 81614
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/CodeGen/CGExpr.cpp | 63 |
1 files changed, 42 insertions, 21 deletions
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 1141dd6..92e8782 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -1153,30 +1153,51 @@ LValue CodeGenFunction::EmitConditionalOperator(const ConditionalOperator* E) { /// all the reasons that casts are permitted with aggregate result, including /// noop aggregate casts, and cast from scalar to union. LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) { - // If this is an aggregate-to-aggregate cast, just use the input's address as - // the lvalue. - if (E->getCastKind() == CastExpr::CK_NoOp || - E->getCastKind() == CastExpr::CK_ConstructorConversion || - E->getCastKind() == CastExpr::CK_UserDefinedConversion) + switch (E->getCastKind()) { + default: + // If this is an lvalue cast, treat it as a no-op. + // FIXME: We shouldn't need to check for this explicitly! + if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) + if (ICE->isLvalueCast()) + return EmitLValue(E->getSubExpr()); + + assert(0 && "Unhandled cast!"); + + case CastExpr::CK_NoOp: + case CastExpr::CK_ConstructorConversion: + case CastExpr::CK_UserDefinedConversion: return EmitLValue(E->getSubExpr()); + + case CastExpr::CK_DerivedToBase: { + const RecordType *DerivedClassTy = + E->getSubExpr()->getType()->getAs<RecordType>(); + CXXRecordDecl *DerivedClassDecl = + cast<CXXRecordDecl>(DerivedClassTy->getDecl()); + + const RecordType *BaseClassTy = E->getType()->getAs<RecordType>(); + CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseClassTy->getDecl()); + + LValue LV = EmitLValue(E->getSubExpr()); + + // Perform the derived-to-base conversion + llvm::Value *Base = + GetAddressCXXOfBaseClass(LV.getAddress(), DerivedClassDecl, + BaseClassDecl, /*NullCheckValue=*/false); + + return LValue::MakeAddr(Base, E->getType().getCVRQualifiers(), + getContext().getObjCGCAttrKind(E->getType()), + E->getType().getAddressSpace()); + } - // If this is an lvalue cast, treat it as a no-op. - // FIXME: We shouldn't need to check for this explicitly! - if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) - if (ICE->isLvalueCast()) - return EmitLValue(E->getSubExpr()); - - // Otherwise, we must have a cast from scalar to union. - assert(E->getCastKind() == CastExpr::CK_ToUnion && - "Expected scalar-to-union cast"); - - // Casts are only lvalues when the source and destination types are the same. - llvm::Value *Temp = CreateTempAlloca(ConvertType(E->getType())); - EmitAnyExpr(E->getSubExpr(), Temp, false); + case CastExpr::CK_ToUnion: { + llvm::Value *Temp = CreateTempAlloca(ConvertType(E->getType())); + EmitAnyExpr(E->getSubExpr(), Temp, false); - return LValue::MakeAddr(Temp, E->getType().getCVRQualifiers(), - getContext().getObjCGCAttrKind(E->getType()), - E->getType().getAddressSpace()); + return LValue::MakeAddr(Temp, E->getType().getCVRQualifiers(), + getContext().getObjCGCAttrKind(E->getType()), + E->getType().getAddressSpace()); + } + } } //===--------------------------------------------------------------------===// |
