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)
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)
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_;
};