Change the AST generated for offsetof a bit so that it looks like a
normal expression, and change Evaluate and IRGen to evaluate it like a
normal expression. This simplifies the code significantly, and fixes
PR3396.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@65622 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index e309259..d0d14f2 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -1331,49 +1331,6 @@
return getCond()->getIntegerConstantExprValue(C) != 0;
}
-static int64_t evaluateOffsetOf(ASTContext& C, const Expr *E) {
- if (const MemberExpr *ME = dyn_cast<MemberExpr>(E)) {
- QualType Ty = ME->getBase()->getType();
-
- RecordDecl *RD = Ty->getAsRecordType()->getDecl();
- const ASTRecordLayout &RL = C.getASTRecordLayout(RD);
- if (FieldDecl *FD = dyn_cast<FieldDecl>(ME->getMemberDecl())) {
- // FIXME: This is linear time. And the fact that we're indexing
- // into the layout by position in the record means that we're
- // either stuck numbering the fields in the AST or we have to keep
- // the linear search (yuck and yuck).
- unsigned i = 0;
- for (RecordDecl::field_iterator Field = RD->field_begin(),
- FieldEnd = RD->field_end();
- Field != FieldEnd; (void)++Field, ++i) {
- if (*Field == FD)
- break;
- }
-
- return RL.getFieldOffset(i) + evaluateOffsetOf(C, ME->getBase());
- }
- } else if (const ArraySubscriptExpr *ASE = dyn_cast<ArraySubscriptExpr>(E)) {
- const Expr *Base = ASE->getBase();
-
- int64_t size = C.getTypeSize(ASE->getType());
- size *= ASE->getIdx()->getIntegerConstantExprValue(C).getSExtValue();
-
- return size + evaluateOffsetOf(C, Base);
- } else if (isa<CompoundLiteralExpr>(E))
- return 0;
-
- assert(0 && "Unknown offsetof subexpression!");
- return 0;
-}
-
-int64_t UnaryOperator::evaluateOffsetOf(ASTContext& C) const
-{
- assert(Opc == OffsetOf && "Unary operator not offsetof!");
-
- unsigned CharSize = C.Target.getCharWidth();
- return ::evaluateOffsetOf(C, cast<Expr>(Val)) / CharSize;
-}
-
void SizeOfAlignOfExpr::Destroy(ASTContext& C) {
// Override default behavior of traversing children. If this has a type
// operand and the type is a variable-length array, the child iteration
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index 4f55f8d..68818db 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -1064,8 +1064,16 @@
bool IntExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) {
// Special case unary operators that do not need their subexpression
// evaluated. offsetof/sizeof/alignof are all special.
- if (E->isOffsetOfOp())
- return Success(E->evaluateOffsetOf(Info.Ctx), E);
+ if (E->isOffsetOfOp()) {
+ // The AST for offsetof is defined in such a way that we can just
+ // directly Evaluate it as an l-value.
+ APValue LV;
+ if (!EvaluateLValue(E->getSubExpr(), LV, Info))
+ return false;
+ if (LV.getLValueBase())
+ return false;
+ return Success(LV.getLValueOffset(), E);
+ }
if (E->getOpcode() == UnaryOperator::LNot) {
// LNot's operand isn't necessarily an integer, so we handle it specially.
diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp
index 4468c79..7e25b46 100644
--- a/lib/AST/StmtPrinter.cpp
+++ b/lib/AST/StmtPrinter.cpp
@@ -724,7 +724,7 @@
}
bool StmtPrinter::PrintOffsetOfDesignator(Expr *E) {
- if (isa<CompoundLiteralExpr>(E)) {
+ if (isa<UnaryOperator>(E)) {
// Base case, print the type and comma.
OS << E->getType().getAsString() << ", ";
return true;