compiler: fix computation of Offsetof.

The implied offsets must be taken into account
when the selector involves anonymous fields.

From-SVN: r200098
This commit is contained in:
Ian Lance Taylor 2013-06-14 17:59:48 +00:00
parent 24244e4deb
commit 51b08adabf
3 changed files with 37 additions and 12 deletions

View file

@ -7279,19 +7279,31 @@ Builtin_call_expression::do_numeric_constant_value(Numeric_constant* nc) const
Field_reference_expression* farg = arg->field_reference_expression();
if (farg == NULL)
return false;
Expression* struct_expr = farg->expr();
Type* st = struct_expr->type();
if (st->struct_type() == NULL)
return false;
if (st->named_type() != NULL)
st->named_type()->convert(this->gogo_);
unsigned int offset;
if (!st->struct_type()->backend_field_offset(this->gogo_,
farg->field_index(),
&offset))
return false;
unsigned int total_offset = 0;
while (true)
{
Expression* struct_expr = farg->expr();
Type* st = struct_expr->type();
if (st->struct_type() == NULL)
return false;
if (st->named_type() != NULL)
st->named_type()->convert(this->gogo_);
unsigned int offset;
if (!st->struct_type()->backend_field_offset(this->gogo_,
farg->field_index(),
&offset))
return false;
total_offset += offset;
if (farg->implicit() && struct_expr->field_reference_expression() != NULL)
{
// Go up until we reach the original base.
farg = struct_expr->field_reference_expression();
continue;
}
break;
}
nc->set_unsigned_long(Type::lookup_integer_type("uintptr"),
static_cast<unsigned long>(offset));
static_cast<unsigned long>(total_offset));
return true;
}
else if (this->code_ == BUILTIN_REAL || this->code_ == BUILTIN_IMAG)

View file

@ -1860,6 +1860,15 @@ class Field_reference_expression : public Expression
field_index() const
{ return this->field_index_; }
// Return whether this node was implied by an anonymous field.
bool
implicit() const
{ return this->implicit_; }
void
set_implicit(bool implicit)
{ this->implicit_ = implicit; }
// Set the struct expression. This is used when parsing.
void
set_struct_expression(Expression* expr)
@ -1914,6 +1923,9 @@ class Field_reference_expression : public Expression
Expression* expr_;
// The zero-based index of the field we are retrieving.
unsigned int field_index_;
// Whether this node was emitted implicitly for an embedded field,
// that is, expr_ is not the expr_ of the original user node.
bool implicit_;
// Whether we have already emitted a fieldtrack call.
bool called_fieldtrack_;
};

View file

@ -4532,6 +4532,7 @@ Struct_type::field_reference_depth(Expression* struct_expr,
go_assert(sub != NULL);
}
sub->set_struct_expression(here);
sub->set_implicit(true);
}
else if (subdepth > found_depth)
delete sub;