diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2013-06-14 17:59:48 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2013-06-14 17:59:48 +0000 |
commit | 51b08adabf40a7922771ff4e0c36c8680c082825 (patch) | |
tree | 0578244ff530b3ebc00aed42fca943c03feb3d58 /gcc/go/gofrontend/expressions.cc | |
parent | 24244e4debd3261c8237d15d940fd10df5b0005a (diff) | |
download | gcc-51b08adabf40a7922771ff4e0c36c8680c082825.zip gcc-51b08adabf40a7922771ff4e0c36c8680c082825.tar.gz gcc-51b08adabf40a7922771ff4e0c36c8680c082825.tar.bz2 |
compiler: fix computation of Offsetof.
The implied offsets must be taken into account
when the selector involves anonymous fields.
From-SVN: r200098
Diffstat (limited to 'gcc/go/gofrontend/expressions.cc')
-rw-r--r-- | gcc/go/gofrontend/expressions.cc | 36 |
1 files changed, 24 insertions, 12 deletions
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<unsigned long>(offset)); + static_cast<unsigned long>(total_offset)); return true; } else if (this->code_ == BUILTIN_REAL || this->code_ == BUILTIN_IMAG) |