aboutsummaryrefslogtreecommitdiff
path: root/lib/AST/ExprConstant.cpp
diff options
context:
space:
mode:
authorAnders Carlsson <andersca@mac.com>2010-10-31 20:41:46 +0000
committerAnders Carlsson <andersca@mac.com>2010-10-31 20:41:46 +0000
commit5c5a764fcd256df6f6cfbce5cdd2a2dfb2c45e95 (patch)
tree83a012face3ac7a9c9e9d6a6c0dfce46c65e8fe7 /lib/AST/ExprConstant.cpp
parent739830d278b0a174edc59edcfedaecec53d36e3f (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.cpp36
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))