diff options
author | Douglas Gregor <dgregor@apple.com> | 2010-04-29 00:18:15 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2010-04-29 00:18:15 +0000 |
commit | cc8a5d5f90bbbbcb46f342117b851b7e07ec34f1 (patch) | |
tree | a75f28ed6bd4b72e7830bdd531451f25fc68159c /lib/AST/ExprConstant.cpp | |
parent | 6e45cbcba1807c01ce2fc9a768ebfffafcffa22d (diff) |
Teach __builtin_offsetof to compute the offsets of members of base
classes, since we only warn (not error) on offsetof() for non-POD
types. We store the base path within the OffsetOfExpr itself, then
evaluate the offsets within the constant evaluator.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@102571 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/AST/ExprConstant.cpp')
-rw-r--r-- | lib/AST/ExprConstant.cpp | 34 |
1 files changed, 29 insertions, 5 deletions
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 7233518d58..1c2b76eede 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -1414,17 +1414,41 @@ bool IntExprEvaluator::VisitOffsetOfExpr(const OffsetOfExpr *E) { if (*Field == MemberDecl) break; } - if (i < RL.getFieldCount()) - Result += CharUnits::fromQuantity( - RL.getFieldOffset(i) / Info.Ctx.getCharWidth()); - else - return false; + assert(i < RL.getFieldCount() && "offsetof field in wrong type"); + Result += CharUnits::fromQuantity( + RL.getFieldOffset(i) / Info.Ctx.getCharWidth()); CurrentType = MemberDecl->getType().getNonReferenceType(); break; } case OffsetOfExpr::OffsetOfNode::Identifier: llvm_unreachable("dependent __builtin_offsetof"); + return false; + + case OffsetOfExpr::OffsetOfNode::Base: { + CXXBaseSpecifier *BaseSpec = ON.getBase(); + if (BaseSpec->isVirtual()) + return false; + + // Find the layout of the class whose base we are looking into. + const RecordType *RT = CurrentType->getAs<RecordType>(); + if (!RT) + return false; + RecordDecl *RD = RT->getDecl(); + const ASTRecordLayout &RL = Info.Ctx.getASTRecordLayout(RD); + + // Find the base class itself. + CurrentType = BaseSpec->getType(); + const RecordType *BaseRT = CurrentType->getAs<RecordType>(); + if (!BaseRT) + return false; + + // Add the offset to the base. + Result += CharUnits::fromQuantity( + RL.getBaseClassOffset(cast<CXXRecordDecl>(BaseRT->getDecl())) + / Info.Ctx.getCharWidth()); + break; + } } } return Success(Result.getQuantity(), E); |