diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index f7e19d32bd6..2a4aa2dbb03 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -1,4 +1,4 @@ -ba68a42618d1e8516e38da093d3af731d7fd4f06 +369e1efe19adfc5393d2235992327f39360e0554 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 8d542de1b3c..053e71d6bfa 100644 --- a/gcc/go/gofrontend/types.cc +++ b/gcc/go/gofrontend/types.cc @@ -316,6 +316,16 @@ Type::do_traverse(Traverse*) bool Type::are_identical(const Type* t1, const Type* t2, bool errors_are_identical, std::string* reason) +{ + return Type::are_identical_cmp_tags(t1, t2, COMPARE_TAGS, + errors_are_identical, reason); +} + +// Like are_identical, but with a CMP_TAGS parameter. + +bool +Type::are_identical_cmp_tags(const Type* t1, const Type* t2, Cmp_tags cmp_tags, + bool errors_are_identical, std::string* reason) { if (t1 == NULL || t2 == NULL) { @@ -387,31 +397,33 @@ Type::are_identical(const Type* t1, const Type* t2, bool errors_are_identical, case TYPE_FUNCTION: return t1->function_type()->is_identical(t2->function_type(), false, + cmp_tags, errors_are_identical, reason); case TYPE_POINTER: - return Type::are_identical(t1->points_to(), t2->points_to(), - errors_are_identical, reason); + return Type::are_identical_cmp_tags(t1->points_to(), t2->points_to(), + cmp_tags, errors_are_identical, + reason); case TYPE_STRUCT: - return t1->struct_type()->is_identical(t2->struct_type(), + return t1->struct_type()->is_identical(t2->struct_type(), cmp_tags, errors_are_identical); case TYPE_ARRAY: - return t1->array_type()->is_identical(t2->array_type(), + return t1->array_type()->is_identical(t2->array_type(), cmp_tags, errors_are_identical); case TYPE_MAP: - return t1->map_type()->is_identical(t2->map_type(), + return t1->map_type()->is_identical(t2->map_type(), cmp_tags, errors_are_identical); case TYPE_CHANNEL: - return t1->channel_type()->is_identical(t2->channel_type(), + return t1->channel_type()->is_identical(t2->channel_type(), cmp_tags, errors_are_identical); case TYPE_INTERFACE: - return t1->interface_type()->is_identical(t2->interface_type(), + return t1->interface_type()->is_identical(t2->interface_type(), cmp_tags, errors_are_identical); case TYPE_CALL_MULTIPLE_RESULT: @@ -735,23 +747,26 @@ Type::are_convertible(const Type* lhs, const Type* rhs, std::string* reason) return true; // The types are convertible if they have identical underlying - // types. + // types, ignoring struct field tags. if ((lhs->named_type() != NULL || rhs->named_type() != NULL) - && Type::are_identical(lhs->base(), rhs->base(), true, reason)) + && Type::are_identical_cmp_tags(lhs->base(), rhs->base(), IGNORE_TAGS, + true, reason)) return true; // The types are convertible if they are both unnamed pointer types - // and their pointer base types have identical underlying types. + // and their pointer base types have identical underlying types, + // ignoring struct field tags. if (lhs->named_type() == NULL && rhs->named_type() == NULL && lhs->points_to() != NULL && rhs->points_to() != NULL && (lhs->points_to()->named_type() != NULL || rhs->points_to()->named_type() != NULL) - && Type::are_identical(lhs->points_to()->base(), - rhs->points_to()->base(), - true, - reason)) + && Type::are_identical_cmp_tags(lhs->points_to()->base(), + rhs->points_to()->base(), + IGNORE_TAGS, + true, + reason)) return true; // Integer and floating point types are convertible to each other. @@ -4502,7 +4517,7 @@ bool Function_type::is_valid_redeclaration(const Function_type* t, std::string* reason) const { - if (!this->is_identical(t, false, true, reason)) + if (!this->is_identical(t, false, COMPARE_TAGS, true, reason)) return false; // A redeclaration of a function is required to use the same names @@ -4580,7 +4595,7 @@ Function_type::is_valid_redeclaration(const Function_type* t, bool Function_type::is_identical(const Function_type* t, bool ignore_receiver, - bool errors_are_identical, + Cmp_tags cmp_tags, bool errors_are_identical, std::string* reason) const { if (!ignore_receiver) @@ -4595,8 +4610,8 @@ Function_type::is_identical(const Function_type* t, bool ignore_receiver, } if (r1 != NULL) { - if (!Type::are_identical(r1->type(), r2->type(), errors_are_identical, - reason)) + if (!Type::are_identical_cmp_tags(r1->type(), r2->type(), cmp_tags, + errors_are_identical, reason)) { if (reason != NULL && !reason->empty()) *reason = "receiver: " + *reason; @@ -4627,8 +4642,8 @@ Function_type::is_identical(const Function_type* t, bool ignore_receiver, return false; } - if (!Type::are_identical(p1->type(), p2->type(), - errors_are_identical, NULL)) + if (!Type::are_identical_cmp_tags(p1->type(), p2->type(), cmp_tags, + errors_are_identical, NULL)) { if (reason != NULL) *reason = _("different parameter types"); @@ -4672,8 +4687,9 @@ Function_type::is_identical(const Function_type* t, bool ignore_receiver, return false; } - if (!Type::are_identical(res1->type(), res2->type(), - errors_are_identical, NULL)) + if (!Type::are_identical_cmp_tags(res1->type(), res2->type(), + cmp_tags, errors_are_identical, + NULL)) { if (reason != NULL) *reason = _("different result types"); @@ -5803,7 +5819,7 @@ Struct_type::do_has_pointer() const // Whether this type is identical to T. bool -Struct_type::is_identical(const Struct_type* t, +Struct_type::is_identical(const Struct_type* t, Cmp_tags cmp_tags, bool errors_are_identical) const { if (this->is_struct_incomparable_ != t->is_struct_incomparable_) @@ -5822,20 +5838,23 @@ Struct_type::is_identical(const Struct_type* t, if (pf1->field_name() != pf2->field_name()) return false; if (pf1->is_anonymous() != pf2->is_anonymous() - || !Type::are_identical(pf1->type(), pf2->type(), - errors_are_identical, NULL)) + || !Type::are_identical_cmp_tags(pf1->type(), pf2->type(), cmp_tags, + errors_are_identical, NULL)) return false; - if (!pf1->has_tag()) + if (cmp_tags == COMPARE_TAGS) { - if (pf2->has_tag()) - return false; - } - else - { - if (!pf2->has_tag()) - return false; - if (pf1->tag() != pf2->tag()) - return false; + if (!pf1->has_tag()) + { + if (pf2->has_tag()) + return false; + } + else + { + if (!pf2->has_tag()) + return false; + if (pf1->tag() != pf2->tag()) + return false; + } } } if (pf2 != fields2->end()) @@ -7061,10 +7080,11 @@ Array_type::int_length(int64_t* plen) // Whether two array types are identical. bool -Array_type::is_identical(const Array_type* t, bool errors_are_identical) const +Array_type::is_identical(const Array_type* t, Cmp_tags cmp_tags, + bool errors_are_identical) const { - if (!Type::are_identical(this->element_type(), t->element_type(), - errors_are_identical, NULL)) + if (!Type::are_identical_cmp_tags(this->element_type(), t->element_type(), + cmp_tags, errors_are_identical, NULL)) return false; if (this->is_array_incomparable_ != t->is_array_incomparable_) @@ -7986,12 +8006,14 @@ Map_type::do_verify() // Whether two map types are identical. bool -Map_type::is_identical(const Map_type* t, bool errors_are_identical) const +Map_type::is_identical(const Map_type* t, Cmp_tags cmp_tags, + bool errors_are_identical) const { - return (Type::are_identical(this->key_type(), t->key_type(), - errors_are_identical, NULL) - && Type::are_identical(this->val_type(), t->val_type(), - errors_are_identical, NULL)); + return (Type::are_identical_cmp_tags(this->key_type(), t->key_type(), + cmp_tags, errors_are_identical, NULL) + && Type::are_identical_cmp_tags(this->val_type(), t->val_type(), + cmp_tags, errors_are_identical, + NULL)); } // Hash code. @@ -8510,11 +8532,11 @@ Channel_type::do_hash_for_method(Gogo* gogo) const // Whether this type is the same as T. bool -Channel_type::is_identical(const Channel_type* t, +Channel_type::is_identical(const Channel_type* t, Cmp_tags cmp_tags, bool errors_are_identical) const { - if (!Type::are_identical(this->element_type(), t->element_type(), - errors_are_identical, NULL)) + if (!Type::are_identical_cmp_tags(this->element_type(), t->element_type(), + cmp_tags, errors_are_identical, NULL)) return false; return (this->may_send_ == t->may_send_ && this->may_receive_ == t->may_receive_); @@ -8920,7 +8942,7 @@ Interface_type::is_unexported_method(Gogo* gogo, const std::string& name) const // Whether this type is identical with T. bool -Interface_type::is_identical(const Interface_type* t, +Interface_type::is_identical(const Interface_type* t, Cmp_tags cmp_tags, bool errors_are_identical) const { // If methods have not been finalized, then we are asking whether @@ -8951,8 +8973,8 @@ Interface_type::is_identical(const Interface_type* t, if (p1 == this->all_methods_->end()) break; if (p1->name() != p2->name() - || !Type::are_identical(p1->type(), p2->type(), - errors_are_identical, NULL)) + || !Type::are_identical_cmp_tags(p1->type(), p2->type(), cmp_tags, + errors_are_identical, NULL)) break; } @@ -9150,7 +9172,8 @@ Interface_type::implements_interface(const Type* t, std::string* reason) const Function_type* m_fn_type = m->type()->function_type(); go_assert(p_fn_type != NULL && m_fn_type != NULL); std::string subreason; - if (!p_fn_type->is_identical(m_fn_type, true, true, &subreason)) + if (!p_fn_type->is_identical(m_fn_type, true, COMPARE_TAGS, true, + &subreason)) { if (reason != NULL) { diff --git a/gcc/go/gofrontend/types.h b/gcc/go/gofrontend/types.h index bae7fd3a541..bfc0a8ba46a 100644 --- a/gcc/go/gofrontend/types.h +++ b/gcc/go/gofrontend/types.h @@ -568,6 +568,22 @@ class Type are_identical(const Type* lhs, const Type* rhs, bool errors_are_identical, std::string* reason); + // An argument to are_identical_cmp_tags, indicating whether or not + // to compare struct field tags. + enum Cmp_tags { + COMPARE_TAGS, + IGNORE_TAGS + }; + + // Return true if two types are identical. This is like the + // are_identical function, but also takes a CMP_TAGS argument + // indicating whether to compare struct tags. Otherwise the + // parameters are as for are_identical. + static bool + are_identical_cmp_tags(const Type* lhs, const Type* rhs, + Cmp_tags, bool errors_are_identical, + std::string* reason); + // 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. @@ -1899,7 +1915,7 @@ class Function_type : public Type // Whether this type is the same as T. bool is_identical(const Function_type* t, bool ignore_receiver, - bool errors_are_identical, std::string*) const; + Cmp_tags, bool errors_are_identical, std::string*) const; // Record that this is a varargs function. void @@ -2293,7 +2309,8 @@ class Struct_type : public Type // Whether this type is identical with T. bool - is_identical(const Struct_type* t, bool errors_are_identical) const; + is_identical(const Struct_type* t, Cmp_tags, + bool errors_are_identical) const; // Return whether NAME is a local field which is not exported. This // is only used for better error reporting. @@ -2495,7 +2512,8 @@ class Array_type : public Type // Whether this type is identical with T. bool - is_identical(const Array_type* t, bool errors_are_identical) const; + is_identical(const Array_type* t, Cmp_tags, + bool errors_are_identical) const; // Return an expression for the pointer to the values in an array. Expression* @@ -2656,7 +2674,8 @@ class Map_type : public Type // Whether this type is identical with T. bool - is_identical(const Map_type* t, bool errors_are_identical) const; + is_identical(const Map_type* t, Cmp_tags, + bool errors_are_identical) const; // Import a map type. static Map_type* @@ -2773,7 +2792,8 @@ class Channel_type : public Type // Whether this type is identical with T. bool - is_identical(const Channel_type* t, bool errors_are_identical) const; + is_identical(const Channel_type* t, Cmp_tags, + bool errors_are_identical) const; // Import a channel type. static Channel_type* @@ -2883,7 +2903,8 @@ class Interface_type : public Type // Whether this type is identical with T. REASON is as in // implements_interface. bool - is_identical(const Interface_type* t, bool errors_are_identical) const; + is_identical(const Interface_type* t, Cmp_tags, + bool errors_are_identical) const; // Whether we can assign T to this type. is_identical is known to // be false.