diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2019-01-15 20:32:39 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2019-01-15 20:32:39 +0000 |
commit | 6a0c8e77f289a5c2e1b1ad0f2c8a5c5105f599a6 (patch) | |
tree | ed17062ac88ccb7fdf858eb98d80b5880065061a /gcc | |
parent | a81a6d58367e63f3c7314eb793002e5feb379428 (diff) | |
download | gcc-6a0c8e77f289a5c2e1b1ad0f2c8a5c5105f599a6.zip gcc-6a0c8e77f289a5c2e1b1ad0f2c8a5c5105f599a6.tar.gz gcc-6a0c8e77f289a5c2e1b1ad0f2c8a5c5105f599a6.tar.bz2 |
compiler, runtime: panic on uncomparable map key, even if map is empty
This ports https://golang.org/cl/155918 from the master repo.
runtime: panic on uncomparable map key, even if map is empty
Reorg map flags a bit so we don't need any extra space for the extra flag.
This is a pre-req for updating libgo to the Go 1.12beta2 release.
Reviewed-on: https://go-review.googlesource.com/c/157858
From-SVN: r267950
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/go/gofrontend/MERGE | 2 | ||||
-rw-r--r-- | gcc/go/gofrontend/types.cc | 62 | ||||
-rw-r--r-- | gcc/go/gofrontend/types.h | 22 |
3 files changed, 61 insertions, 25 deletions
diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index ab0a2bd4..4d76c54 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -1,4 +1,4 @@ -0d64279c01a37b2579c0c62ca4f2c3e3f81de07c +87005025fcd0d7e7908b3aae7062b52cb80eb0f3 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 509be44..5a45bb2 100644 --- a/gcc/go/gofrontend/types.cc +++ b/gcc/go/gofrontend/types.cc @@ -5839,6 +5839,25 @@ Struct_type::do_needs_key_update() return false; } +// Return whether computing the hash value of an instance of this +// struct type might panic. + +bool +Struct_type::do_hash_might_panic() +{ + const Struct_field_list* fields = this->fields_; + if (fields == NULL) + return false; + for (Struct_field_list::const_iterator pf = fields->begin(); + pf != fields->end(); + ++pf) + { + if (pf->type()->hash_might_panic()) + return true; + } + return false; +} + // Return whether this struct type is permitted to be in the heap. bool @@ -7979,21 +7998,18 @@ Map_type::make_map_type_descriptor_type() Type* ptdt = Type::make_type_descriptor_ptr_type(); Type* uint8_type = Type::lookup_integer_type("uint8"); Type* uint16_type = Type::lookup_integer_type("uint16"); - Type* bool_type = Type::lookup_bool_type(); + Type* uint32_type = Type::lookup_integer_type("uint32"); Struct_type* sf = - Type::make_builtin_struct_type(11, + Type::make_builtin_struct_type(8, "", tdt, "key", ptdt, "elem", ptdt, "bucket", ptdt, "keysize", uint8_type, - "indirectkey", bool_type, "valuesize", uint8_type, - "indirectvalue", bool_type, "bucketsize", uint16_type, - "reflexivekey", bool_type, - "needkeyupdate", bool_type); + "flags", uint32_type); ret = Type::make_builtin_named_type("MapType", sf); } @@ -8011,6 +8027,7 @@ Map_type::do_type_descriptor(Gogo* gogo, Named_type* name) Type* mtdt = Map_type::make_map_type_descriptor_type(); Type* uint8_type = Type::lookup_integer_type("uint8"); Type* uint16_type = Type::lookup_integer_type("uint16"); + Type* uint32_type = Type::lookup_integer_type("uint32"); int64_t keysize; if (!this->key_type_->backend_type_size(gogo, &keysize)) @@ -8078,11 +8095,6 @@ Map_type::do_type_descriptor(Gogo* gogo, Named_type* name) vals->push_back(Expression::make_integer_int64(keysize, uint8_type, bloc)); ++p; - go_assert(p->is_field_name("indirectkey")); - vals->push_back(Expression::make_boolean(keysize > Map_type::max_key_size, - bloc)); - - ++p; go_assert(p->is_field_name("valuesize")); if (valsize > Map_type::max_val_size) vals->push_back(Expression::make_integer_int64(ptrsize, uint8_type, bloc)); @@ -8090,24 +8102,26 @@ Map_type::do_type_descriptor(Gogo* gogo, Named_type* name) vals->push_back(Expression::make_integer_int64(valsize, uint8_type, bloc)); ++p; - go_assert(p->is_field_name("indirectvalue")); - vals->push_back(Expression::make_boolean(valsize > Map_type::max_val_size, - bloc)); - - ++p; go_assert(p->is_field_name("bucketsize")); vals->push_back(Expression::make_integer_int64(bucketsize, uint16_type, bloc)); ++p; - go_assert(p->is_field_name("reflexivekey")); - vals->push_back(Expression::make_boolean(this->key_type_->is_reflexive(), - bloc)); - - ++p; - go_assert(p->is_field_name("needkeyupdate")); - vals->push_back(Expression::make_boolean(this->key_type_->needs_key_update(), - bloc)); + go_assert(p->is_field_name("flags")); + // As with the other fields, the flag bits must match the reflect + // and runtime packages. + unsigned long flags = 0; + if (keysize > Map_type::max_key_size) + flags |= 1; + if (valsize > Map_type::max_val_size) + flags |= 2; + if (this->key_type_->is_reflexive()) + flags |= 4; + if (this->key_type_->needs_key_update()) + flags |= 8; + if (this->key_type_->hash_might_panic()) + flags |= 16; + vals->push_back(Expression::make_integer_ul(flags, uint32_type, bloc)); ++p; go_assert(p == fields->end()); diff --git a/gcc/go/gofrontend/types.h b/gcc/go/gofrontend/types.h index 9d79941..cc92471 100644 --- a/gcc/go/gofrontend/types.h +++ b/gcc/go/gofrontend/types.h @@ -635,6 +635,12 @@ class Type needs_key_update() { return this->do_needs_key_update(); } + // Return whether the hash function of this type might panic. This + // is only called for types used as a key in a map type. + bool + hash_might_panic() + { return this->do_hash_might_panic(); } + // Whether the type is permitted in the heap. bool in_heap() @@ -1074,6 +1080,10 @@ class Type { return false; } virtual bool + do_hash_might_panic() + { return false; } + + virtual bool do_in_heap() { return true; } @@ -2601,6 +2611,9 @@ class Struct_type : public Type do_needs_key_update(); bool + do_hash_might_panic(); + + bool do_in_heap(); unsigned int @@ -2779,6 +2792,10 @@ class Array_type : public Type { return this->element_type_->needs_key_update(); } bool + do_hash_might_panic() + { return this->length_ != NULL && this->element_type_->hash_might_panic(); } + + bool do_in_heap() { return this->length_ == NULL || this->element_type_->in_heap(); } @@ -3170,6 +3187,11 @@ class Interface_type : public Type do_needs_key_update() { return true; } + // Hashing an unhashable type stored in an interface might panic. + bool + do_hash_might_panic() + { return true; } + unsigned int do_hash_for_method(Gogo*, int) const; |