mirror of git://gcc.gnu.org/git/gcc.git
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:
parent
24244e4deb
commit
51b08adabf
|
|
@ -7279,19 +7279,31 @@ Builtin_call_expression::do_numeric_constant_value(Numeric_constant* nc) const
|
||||||
Field_reference_expression* farg = arg->field_reference_expression();
|
Field_reference_expression* farg = arg->field_reference_expression();
|
||||||
if (farg == NULL)
|
if (farg == NULL)
|
||||||
return false;
|
return false;
|
||||||
Expression* struct_expr = farg->expr();
|
unsigned int total_offset = 0;
|
||||||
Type* st = struct_expr->type();
|
while (true)
|
||||||
if (st->struct_type() == NULL)
|
{
|
||||||
return false;
|
Expression* struct_expr = farg->expr();
|
||||||
if (st->named_type() != NULL)
|
Type* st = struct_expr->type();
|
||||||
st->named_type()->convert(this->gogo_);
|
if (st->struct_type() == NULL)
|
||||||
unsigned int offset;
|
return false;
|
||||||
if (!st->struct_type()->backend_field_offset(this->gogo_,
|
if (st->named_type() != NULL)
|
||||||
farg->field_index(),
|
st->named_type()->convert(this->gogo_);
|
||||||
&offset))
|
unsigned int offset;
|
||||||
return false;
|
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"),
|
nc->set_unsigned_long(Type::lookup_integer_type("uintptr"),
|
||||||
static_cast<unsigned long>(offset));
|
static_cast<unsigned long>(total_offset));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (this->code_ == BUILTIN_REAL || this->code_ == BUILTIN_IMAG)
|
else if (this->code_ == BUILTIN_REAL || this->code_ == BUILTIN_IMAG)
|
||||||
|
|
|
||||||
|
|
@ -1860,6 +1860,15 @@ class Field_reference_expression : public Expression
|
||||||
field_index() const
|
field_index() const
|
||||||
{ return this->field_index_; }
|
{ 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.
|
// Set the struct expression. This is used when parsing.
|
||||||
void
|
void
|
||||||
set_struct_expression(Expression* expr)
|
set_struct_expression(Expression* expr)
|
||||||
|
|
@ -1914,6 +1923,9 @@ class Field_reference_expression : public Expression
|
||||||
Expression* expr_;
|
Expression* expr_;
|
||||||
// The zero-based index of the field we are retrieving.
|
// The zero-based index of the field we are retrieving.
|
||||||
unsigned int field_index_;
|
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.
|
// Whether we have already emitted a fieldtrack call.
|
||||||
bool called_fieldtrack_;
|
bool called_fieldtrack_;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -4532,6 +4532,7 @@ Struct_type::field_reference_depth(Expression* struct_expr,
|
||||||
go_assert(sub != NULL);
|
go_assert(sub != NULL);
|
||||||
}
|
}
|
||||||
sub->set_struct_expression(here);
|
sub->set_struct_expression(here);
|
||||||
|
sub->set_implicit(true);
|
||||||
}
|
}
|
||||||
else if (subdepth > found_depth)
|
else if (subdepth > found_depth)
|
||||||
delete sub;
|
delete sub;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue