aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2019-01-15 20:32:39 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2019-01-15 20:32:39 +0000
commit6a0c8e77f289a5c2e1b1ad0f2c8a5c5105f599a6 (patch)
treeed17062ac88ccb7fdf858eb98d80b5880065061a /gcc
parenta81a6d58367e63f3c7314eb793002e5feb379428 (diff)
downloadgcc-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/MERGE2
-rw-r--r--gcc/go/gofrontend/types.cc62
-rw-r--r--gcc/go/gofrontend/types.h22
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;