aboutsummaryrefslogtreecommitdiff
path: root/gcc/go/gofrontend/expressions.cc
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2013-06-14 17:59:48 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2013-06-14 17:59:48 +0000
commit51b08adabf40a7922771ff4e0c36c8680c082825 (patch)
tree0578244ff530b3ebc00aed42fca943c03feb3d58 /gcc/go/gofrontend/expressions.cc
parent24244e4debd3261c8237d15d940fd10df5b0005a (diff)
downloadgcc-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.cc36
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)