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 | |
| 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
| -rw-r--r-- | clang/lib/CodeGen/CGExpr.cpp | 63 | ||||
| -rw-r--r-- | clang/test/CodeGenCXX/derived-to-base.cpp | 16 |
2 files changed, 58 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()); + } + } } //===--------------------------------------------------------------------===// diff --git a/clang/test/CodeGenCXX/derived-to-base.cpp b/clang/test/CodeGenCXX/derived-to-base.cpp new file mode 100644 index 0000000..63492d6 --- /dev/null +++ b/clang/test/CodeGenCXX/derived-to-base.cpp @@ -0,0 +1,16 @@ +// RUN: clang-cc -emit-llvm %s -o - +struct A { + void f(); + + int a; +}; + +struct B : A { + double b; +}; + +void f() { + B b; + + b.f(); +} |
