diff options
author | Anders Carlsson <andersca@mac.com> | 2010-10-31 20:41:46 +0000 |
---|---|---|
committer | Anders Carlsson <andersca@mac.com> | 2010-10-31 20:41:46 +0000 |
commit | 5c5a764fcd256df6f6cfbce5cdd2a2dfb2c45e95 (patch) | |
tree | 83a012face3ac7a9c9e9d6a6c0dfce46c65e8fe7 /lib/AST/ExprConstant.cpp | |
parent | 739830d278b0a174edc59edcfedaecec53d36e3f (diff) |
Teach the constant expr evaluator about derived-to-base casts when no virtual bases are involved. Fixes PR5974.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@117868 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/AST/ExprConstant.cpp')
-rw-r--r-- | lib/AST/ExprConstant.cpp | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 61f5b136ac..d23eac24d4 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -568,6 +568,42 @@ bool PointerExprEvaluator::VisitCastExpr(CastExpr* E) { case CK_AnyPointerToBlockPointerCast: return Visit(SubExpr); + case CK_DerivedToBase: + case CK_UncheckedDerivedToBase: { + LValue BaseLV; + if (!EvaluatePointer(E->getSubExpr(), BaseLV, Info)) + return false; + + // Now figure out the necessary offset to add to the baseLV to get from + // the derived class to the base class. + uint64_t Offset = 0; + + QualType Ty = E->getSubExpr()->getType(); + const CXXRecordDecl *DerivedDecl = + Ty->getAs<PointerType>()->getPointeeType()->getAsCXXRecordDecl(); + + for (CastExpr::path_const_iterator PathI = E->path_begin(), + PathE = E->path_end(); PathI != PathE; ++PathI) { + const CXXBaseSpecifier *Base = *PathI; + + // FIXME: If the base is virtual, we'd need to determine the type of the + // most derived class and we don't support that right now. + if (Base->isVirtual()) + return false; + + const CXXRecordDecl *BaseDecl = Base->getType()->getAsCXXRecordDecl(); + const ASTRecordLayout &Layout = Info.Ctx.getASTRecordLayout(DerivedDecl); + + Offset += Layout.getBaseClassOffset(BaseDecl); + DerivedDecl = BaseDecl; + } + + Result.Base = BaseLV.getLValueBase(); + Result.Offset = BaseLV.getLValueOffset() + + CharUnits::fromQuantity(Offset / Info.Ctx.getCharWidth()); + return true; + } + case CK_IntegralToPointer: { APValue Value; if (!EvaluateIntegerOrLValue(SubExpr, Value, Info)) |