From 51b08adabf40a7922771ff4e0c36c8680c082825 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Fri, 14 Jun 2013 17:59:48 +0000 Subject: compiler: fix computation of Offsetof. The implied offsets must be taken into account when the selector involves anonymous fields. From-SVN: r200098 --- gcc/go/gofrontend/expressions.cc | 36 ++++++++++++++++++++++++------------ gcc/go/gofrontend/expressions.h | 12 ++++++++++++ gcc/go/gofrontend/types.cc | 1 + 3 files changed, 37 insertions(+), 12 deletions(-) (limited to 'gcc') diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc index 9abd224..afc1832 100644 --- a/gcc/go/gofrontend/expressions.cc +++ b/gcc/go/gofrontend/expressions.cc @@ -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(offset)); + static_cast(total_offset)); return true; } else if (this->code_ == BUILTIN_REAL || this->code_ == BUILTIN_IMAG) diff --git a/gcc/go/gofrontend/expressions.h b/gcc/go/gofrontend/expressions.h index af178de..36f4c0d 100644 --- a/gcc/go/gofrontend/expressions.h +++ b/gcc/go/gofrontend/expressions.h @@ -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_; }; diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc index 7694982..4fbb162 100644 --- a/gcc/go/gofrontend/types.cc +++ b/gcc/go/gofrontend/types.cc @@ -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; -- cgit v1.1