From 2a3b37c3b9f09fe9b020294debf96d0298d7be70 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Wed, 15 Dec 2010 18:33:34 +0000 Subject: [PATCH] Use a different identity function for Types in hash tables. From-SVN: r167866 --- gcc/go/gofrontend/types.cc | 40 ++++++++++++++++++++++++++++++-------- gcc/go/gofrontend/types.h | 8 +++++++- 2 files changed, 39 insertions(+), 9 deletions(-) diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc index 5a75a0bc8cf..1579f179aa7 100644 --- a/gcc/go/gofrontend/types.cc +++ b/gcc/go/gofrontend/types.cc @@ -393,6 +393,38 @@ Type::are_identical(const Type* t1, const Type* t2, std::string* reason) } } +// Return true if two types are identical when it comes to storing +// them in a hash table. This differs from Type::are_identical with +// regard to how we handle error types. We want to treat error types +// as identical to other types when it comes to reporting +// compatibility errors, but we want to treat them as different when +// it comes to storing them in a hash table. + +bool +Type::are_identical_for_hash_table(const Type* t1, const Type *t2) +{ + if (t1 == NULL || t2 == NULL) + return t1 == t2; + + t1 = t1->forwarded(); + t2 = t2->forwarded(); + + if (t1 == t2) + return true; + + // Undefined forward declarations are only equal to themselves. + if (t1->forward_declaration_type() != NULL + || t2->forward_declaration_type() != NULL) + return false; + + // The error type is only equal to the error type. + if (t1->is_error_type() || t2->is_error_type()) + return t1->is_error_type() && t2->is_error_type(); + + // Otherwise we can use the usual identity check. + return Type::are_identical(t1, t2, NULL); +} + // Return true if it's OK to have a binary operation with types LHS // and RHS. This is not used for shifts or comparisons. @@ -810,14 +842,6 @@ Type::get_tree(Gogo* gogo) tree t = this->get_tree_without_hash(gogo); - // Don't store errors in the hash table. This type might be a - // pointer to an error type or something like that. Since error - // types are identical to everything else, that could cause us to - // return error_mark_node for pointers to any type, which will then - // confuse us later. - if (t == error_mark_node) - return error_mark_node; - if (ins.first->second == NULL_TREE) ins.first->second = t; else diff --git a/gcc/go/gofrontend/types.h b/gcc/go/gofrontend/types.h index 3f1b8ba7817..43a2708547c 100644 --- a/gcc/go/gofrontend/types.h +++ b/gcc/go/gofrontend/types.h @@ -508,6 +508,12 @@ class Type static bool are_identical(const Type* lhs, const Type* rhs, std::string* reason); + // Return true if two types are identical when it comes to putting + // them in a hash table. This differs from are_identical only in + // how error types are handled. + static bool + are_identical_for_hash_table(const Type*, const Type*); + // Return true if two types are compatible for use in a binary // operation, other than a shift, comparison, or channel send. This // is an equivalence relation. @@ -1104,7 +1110,7 @@ class Type_identical public: bool operator()(const Type* t1, const Type* t2) const - { return Type::are_identical(t1, t2, NULL); } + { return Type::are_identical_for_hash_table(t1, t2); } }; // An identifier with a type.