From 307ca54339bfce88e67f7e446ee4bbf5f1961eba Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Wed, 16 Nov 2016 14:47:28 +0000 Subject: [PATCH] compiler: separate incomparable types from comparable ones Otherwise we can accidentally and incorrectly mark an actual user type as incomparable. This fixes the gccgo version of https://golang.org/issue/17752. The test case for gccgo is https://golang.org/cl/33249. Reviewed-on: https://go-review.googlesource.com/33292 From-SVN: r242494 --- gcc/go/gofrontend/MERGE | 2 +- gcc/go/gofrontend/types.cc | 22 ++++++++++++++++++++-- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index 1fe9decbd3d..56ba8a56a0f 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -1,4 +1,4 @@ -eb716b515356166d3177e6244619be5901f31162 +31ff8c31d33c3e77cae4fd55445f12825eb92af5 The first line of this file holds the git revision number of the last merge done from the gofrontend repository. diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc index 1635709be2c..bc6e3c62838 100644 --- a/gcc/go/gofrontend/types.cc +++ b/gcc/go/gofrontend/types.cc @@ -4792,6 +4792,8 @@ bool Struct_type::is_identical(const Struct_type* t, bool errors_are_identical) const { + if (this->is_struct_incomparable_ != t->is_struct_incomparable_) + return false; const Struct_field_list* fields1 = this->fields(); const Struct_field_list* fields2 = t->fields(); if (fields1 == NULL || fields2 == NULL) @@ -4929,7 +4931,10 @@ Struct_type::do_hash_for_method(Gogo* gogo) const ++pf) ret = (ret << 1) + pf->type()->hash_for_method(gogo); } - return ret <<= 2; + ret <<= 2; + if (this->is_struct_incomparable_) + ret <<= 1; + return ret; } // Find the local field NAME. @@ -5659,6 +5664,9 @@ Struct_type::do_mangled_name(Gogo* gogo, std::string* ret) const } } + if (this->is_struct_incomparable_) + ret->push_back('x'); + ret->push_back('e'); } @@ -6052,6 +6060,9 @@ Array_type::is_identical(const Array_type* t, bool errors_are_identical) const errors_are_identical, NULL)) return false; + if (this->is_array_incomparable_ != t->is_array_incomparable_) + return false; + Expression* l1 = this->length(); Expression* l2 = t->length(); @@ -6216,9 +6227,14 @@ Array_type::do_compare_is_identity(Gogo* gogo) unsigned int Array_type::do_hash_for_method(Gogo* gogo) const { + unsigned int ret; + // There is no very convenient way to get a hash code for the // length. - return this->element_type_->hash_for_method(gogo) + 1; + ret = this->element_type_->hash_for_method(gogo) + 1; + if (this->is_array_incomparable_) + ret <<= 1; + return ret; } // Write the hash function for an array which can not use the identify @@ -6916,6 +6932,8 @@ Array_type::do_mangled_name(Gogo* gogo, std::string* ret) const ret->append(s); free(s); mpz_clear(val); + if (this->is_array_incomparable_) + ret->push_back('x'); } ret->push_back('e'); } -- 2.30.2