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 | d17020676106cd77cd35d263c5549b605dad0225 (patch) | |
| tree | 0c226b716d4557190e486e71f490f08cbad50d14 /clang/lib/AST/ExprConstant.cpp | |
| parent | a5a8f76cea106a8d766bd6d9351fd0f51ef46a2f (diff) | |
| download | bcm5719-llvm-d17020676106cd77cd35d263c5549b605dad0225.tar.gz bcm5719-llvm-d17020676106cd77cd35d263c5549b605dad0225.zip | |
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
Diffstat (limited to 'clang/lib/AST/ExprConstant.cpp')
| -rw-r--r-- | clang/lib/AST/ExprConstant.cpp | 34 |
1 files changed, 29 insertions, 5 deletions
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<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); |

