The Go frontend code that handled array dimensions when generating reflection and mangling assumed that an array dimension would fit in an unsigned long. That is of course not true when a 32-bit host is cross-compiling to a 64-bit target. This patch fixes the problem. This was reported as GCC PR 65717. Bootstrapped and ran Go tests on x86_64-pc-linux-gnu, and also on a 32-bit Solaris host crossing to a 64-bit Solaris target. Committed to mainline. Could be committed to GCC 5 branch but I'm not sure whether the branch is open yet.
Ian
Index: gcc/go/gofrontend/MERGE =================================================================== --- gcc/go/gofrontend/MERGE (revision 231095) +++ gcc/go/gofrontend/MERGE (working copy) @@ -1,4 +1,4 @@ -81eb6a3f425b2158c67ee32c0cc973a72ce9d6be +c375f3bf470f94220149b486c947bb3eb57cde7d The first line of this file holds the git revision number of the last merge done from the gofrontend repository. Index: gcc/go/gofrontend/types.cc =================================================================== --- gcc/go/gofrontend/types.cc (revision 231095) +++ gcc/go/gofrontend/types.cc (working copy) @@ -6398,22 +6398,21 @@ Array_type::do_reflection(Gogo* gogo, st if (this->length_ != NULL) { Numeric_constant nc; - unsigned long val; - if (!this->length_->numeric_constant_value(&nc) - || nc.to_unsigned_long(&val) != Numeric_constant::NC_UL_VALID) + if (!this->length_->numeric_constant_value(&nc)) { - if (!this->issued_length_error_) - { - error_at(this->length_->location(), "invalid array length"); - this->issued_length_error_ = true; - } + go_assert(saw_errors()); + return; } - else + mpz_t val; + if (!nc.to_int(&val)) { - char buf[50]; - snprintf(buf, sizeof buf, "%lu", val); - ret->append(buf); + go_assert(saw_errors()); + return; } + char* s = mpz_get_str(NULL, 10, val); + ret->append(s); + free(s); + mpz_clear(val); } ret->push_back(']'); @@ -6544,22 +6543,21 @@ Array_type::do_mangled_name(Gogo* gogo, if (this->length_ != NULL) { Numeric_constant nc; - unsigned long val; - if (!this->length_->numeric_constant_value(&nc) - || nc.to_unsigned_long(&val) != Numeric_constant::NC_UL_VALID) + if (!this->length_->numeric_constant_value(&nc)) { - if (!this->issued_length_error_) - { - error_at(this->length_->location(), "invalid array length"); - this->issued_length_error_ = true; - } + go_assert(saw_errors()); + return; } - else + mpz_t val; + if (!nc.to_int(&val)) { - char buf[50]; - snprintf(buf, sizeof buf, "%lu", val); - ret->append(buf); + go_assert(saw_errors()); + return; } + char *s = mpz_get_str(NULL, 10, val); + ret->append(s); + free(s); + mpz_clear(val); } ret->push_back('e'); }