From d17020676106cd77cd35d263c5549b605dad0225 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Thu, 29 Apr 2010 00:18:15 +0000 Subject: 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. llvm-svn: 102571 --- clang/lib/AST/ExprConstant.cpp | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) (limited to 'clang/lib/AST/ExprConstant.cpp') diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 7233518d58c..1c2b76eede6 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/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(); + 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(); + if (!BaseRT) + return false; + + // Add the offset to the base. + Result += CharUnits::fromQuantity( + RL.getBaseClassOffset(cast(BaseRT->getDecl())) + / Info.Ctx.getCharWidth()); + break; + } } } return Success(Result.getQuantity(), E); -- cgit v1.2.3