compiler: rewrite Type::are_identical to use flags
authorIan Lance Taylor <ian@gcc.gnu.org>
Thu, 18 Oct 2018 22:55:34 +0000 (22:55 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Thu, 18 Oct 2018 22:55:34 +0000 (22:55 +0000)
    A single flags parameter replaces the Cmp_tags and errors_are_identical
    parameters. The existing behavior is unchanged.

    This is a simplification step for future work that will add a new flag.

    Reviewed-on: https://go-review.googlesource.com/c/143019

From-SVN: r265293

gcc/go/gofrontend/MERGE
gcc/go/gofrontend/escape.cc
gcc/go/gofrontend/expressions.cc
gcc/go/gofrontend/gogo.cc
gcc/go/gofrontend/statements.cc
gcc/go/gofrontend/types.cc
gcc/go/gofrontend/types.h
gcc/go/gofrontend/wb.cc

index fa708bceae7a35093471d4d44096d76625a9f807..a2cf0af0634e4105e85ef4add09de6099d55a82a 100644 (file)
@@ -1,4 +1,4 @@
-0494dc5737f0c89ad6f45e04e8313e4161678861
+84531ef21230307773daa438a50bf095edcdbf93
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
index d9dcc8993f4e7d492c3217722a6d24ce24b1dfb1..eb23c2dc4a0c21b7eacaf119216dc19d799edf2a 100644 (file)
@@ -2077,7 +2077,8 @@ Escape_analysis_assign::call(Call_expression* call)
       else
        {
          if (!Type::are_identical(fntype->receiver()->type(),
-                              (*p)->expr()->type(), true, NULL))
+                                  (*p)->expr()->type(), Type::COMPARE_TAGS,
+                                  NULL))
            {
              // This will be converted later, preemptively track it instead
              // of its conversion expression which will show up in a later pass.
@@ -2096,7 +2097,7 @@ Escape_analysis_assign::call(Call_expression* call)
           ++pn, ++p)
        {
          if (!Type::are_identical(pn->type(), (*p)->expr()->type(),
-                                  true, NULL))
+                                  Type::COMPARE_TAGS, NULL))
            {
              // This will be converted later, preemptively track it instead
              // of its conversion expression which will show up in a later pass.
index 91cc30e30b5e1c715c18c5b3bcdcb707ec7d0c29..0a6910ac87972a00d95f258efd08cf3524894508 100644 (file)
@@ -178,7 +178,10 @@ Expression::convert_for_assignment(Gogo*, Type* lhs_type,
       || rhs->is_error_expression())
     return Expression::make_error(location);
 
-  bool are_identical = Type::are_identical(lhs_type, rhs_type, false, NULL);
+  bool are_identical = Type::are_identical(lhs_type, rhs_type,
+                                          (Type::COMPARE_ERRORS
+                                           | Type::COMPARE_TAGS),
+                                          NULL);
   if (!are_identical && lhs_type->interface_type() != NULL)
     {
       if (rhs_type->interface_type() == NULL)
@@ -341,7 +344,9 @@ Expression::convert_interface_to_interface(Type *lhs_type, Expression* rhs,
                                            bool for_type_guard,
                                            Location location)
 {
-  if (Type::are_identical(lhs_type, rhs->type(), false, NULL))
+  if (Type::are_identical(lhs_type, rhs->type(),
+                         Type::COMPARE_ERRORS | Type::COMPARE_TAGS,
+                         NULL))
     return rhs;
 
   Interface_type* lhs_interface_type = lhs_type->interface_type();
@@ -3389,7 +3394,9 @@ Type_conversion_expression::do_is_static_initializer() const
   if (!this->expr_->is_static_initializer())
     return false;
 
-  if (Type::are_identical(type, expr_type, false, NULL))
+  if (Type::are_identical(type, expr_type,
+                         Type::COMPARE_ERRORS | Type::COMPARE_TAGS,
+                         NULL))
     return true;
 
   if (type->is_string_type() && expr_type->is_string_type())
@@ -3503,7 +3510,9 @@ Type_conversion_expression::do_get_backend(Translate_context* context)
   Btype* btype = type->get_backend(gogo);
   Location loc = this->location();
 
-  if (Type::are_identical(type, expr_type, false, NULL))
+  if (Type::are_identical(type, expr_type,
+                         Type::COMPARE_ERRORS | Type::COMPARE_TAGS,
+                         NULL))
     {
       Bexpression* bexpr = this->expr_->get_backend(context);
       return gogo->backend()->convert_expression(btype, bexpr, loc);
@@ -5433,7 +5442,10 @@ Binary_expression::lower_struct_comparison(Gogo* gogo,
   Struct_type* st2 = this->right_->type()->struct_type();
   if (st2 == NULL)
     return this;
-  if (st != st2 && !Type::are_identical(st, st2, false, NULL))
+  if (st != st2
+      && !Type::are_identical(st, st2,
+                             Type::COMPARE_ERRORS | Type::COMPARE_TAGS,
+                             NULL))
     return this;
   if (!Type::are_compatible_for_comparison(true, this->left_->type(),
                                           this->right_->type(), NULL))
@@ -5512,7 +5524,10 @@ Binary_expression::lower_array_comparison(Gogo* gogo,
   Array_type* at2 = this->right_->type()->array_type();
   if (at2 == NULL)
     return this;
-  if (at != at2 && !Type::are_identical(at, at2, false, NULL))
+  if (at != at2
+      && !Type::are_identical(at, at2,
+                             Type::COMPARE_ERRORS | Type::COMPARE_TAGS,
+                             NULL))
     return this;
   if (!Type::are_compatible_for_comparison(true, this->left_->type(),
                                           this->right_->type(), NULL))
@@ -6902,7 +6917,7 @@ Bound_method_expression::do_check_types(Gogo*)
                 ? this->expr_type_
                 : this->expr_->type());
   etype = etype->deref();
-  if (!Type::are_identical(rtype, etype, true, NULL))
+  if (!Type::are_identical(rtype, etype, Type::COMPARE_TAGS, NULL))
     this->report_error(_("method type does not match object type"));
 }
 
@@ -8404,7 +8419,9 @@ Builtin_call_expression::do_numeric_constant_value(Numeric_constant* nc) const
          && !rnc.type()->is_abstract()
          && inc.type() != NULL
          && !inc.type()->is_abstract()
-         && !Type::are_identical(rnc.type(), inc.type(), false, NULL))
+         && !Type::are_identical(rnc.type(), inc.type(),
+                                 Type::COMPARE_ERRORS | Type::COMPARE_TAGS,
+                                 NULL))
        return false;
 
       mpfr_t r;
@@ -8885,7 +8902,7 @@ Builtin_call_expression::do_check_types(Gogo*)
        if (arg2_type->is_slice_type())
          {
            Type* e2 = arg2_type->array_type()->element_type();
-           if (!Type::are_identical(e1, e2, true, NULL))
+           if (!Type::are_identical(e1, e2, Type::COMPARE_TAGS, NULL))
              this->report_error(_("element types must be the same"));
          }
        else if (arg2_type->is_string_type())
@@ -9023,7 +9040,8 @@ Builtin_call_expression::do_check_types(Gogo*)
                 || args->back()->type()->is_error())
          this->set_is_error();
        else if (!Type::are_identical(args->front()->type(),
-                                     args->back()->type(), true, NULL))
+                                     args->back()->type(),
+                                     Type::COMPARE_TAGS, NULL))
          this->report_error(_("complex arguments must have identical types"));
        else if (args->front()->type()->float_type() == NULL)
          this->report_error(_("complex arguments must have "
@@ -9935,7 +9953,8 @@ Call_expression::do_flatten(Gogo* gogo, Named_object*,
       for (; pa != this->args_->end(); ++pa, ++pp)
        {
          go_assert(pp != fntype->parameters()->end());
-         if (Type::are_identical(pp->type(), (*pa)->type(), true, NULL))
+         if (Type::are_identical(pp->type(), (*pa)->type(),
+                                 Type::COMPARE_TAGS, NULL))
            args->push_back(*pa);
          else
            {
@@ -11630,7 +11649,9 @@ Map_index_expression::do_flatten(Gogo* gogo, Named_object*,
       return Expression::make_error(loc);
     }
 
-  if (!Type::are_identical(mt->key_type(), this->index_->type(), false, NULL))
+  if (!Type::are_identical(mt->key_type(), this->index_->type(),
+                          Type::COMPARE_ERRORS | Type::COMPARE_TAGS,
+                          NULL))
     {
       if (this->index_->type()->interface_type() != NULL
          && !this->index_->is_variable())
@@ -15948,7 +15969,8 @@ Type*
 Conditional_expression::do_type()
 {
   Type* result_type = Type::make_void_type();
-  if (Type::are_identical(this->then_->type(), this->else_->type(), false,
+  if (Type::are_identical(this->then_->type(), this->else_->type(),
+                         Type::COMPARE_ERRORS | Type::COMPARE_TAGS,
                           NULL))
     result_type = this->then_->type();
   else if (this->then_->is_nil_expression()
index d07068d49ac5bf3da594900ebdc1b56f9a01af50..bfbf682fc113ef35ccf87ebf599af9c000a9c4b2 100644 (file)
@@ -6492,7 +6492,8 @@ Variable::flatten_init_expression(Gogo* gogo, Named_object* function,
       // If an interface conversion is needed, we need a temporary
       // variable.
       if (this->type_ != NULL
-         && !Type::are_identical(this->type_, this->init_->type(), false,
+         && !Type::are_identical(this->type_, this->init_->type(),
+                                 Type::COMPARE_ERRORS | Type::COMPARE_TAGS,
                                  NULL)
          && this->init_->type()->interface_type() != NULL
          && !this->init_->is_variable())
index 1df676f53c2c3886723d8dec9c7321259ba2f473..c35002df13ce4e7bf5f94614d1120e0517d3633e 100644 (file)
@@ -472,7 +472,9 @@ Temporary_statement::do_flatten(Gogo*, Named_object*, Block*,
 
   if (this->type_ != NULL
       && this->init_ != NULL
-      && !Type::are_identical(this->type_, this->init_->type(), false, NULL)
+      && !Type::are_identical(this->type_, this->init_->type(),
+                             Type::COMPARE_ERRORS | Type::COMPARE_TAGS,
+                             NULL)
       && this->init_->type()->interface_type() != NULL
       && !this->init_->is_variable())
     {
@@ -841,7 +843,8 @@ Assignment_statement::do_flatten(Gogo*, Named_object*, Block*,
 
   if (!this->lhs_->is_sink_expression()
       && !Type::are_identical(this->lhs_->type(), this->rhs_->type(),
-                             false, NULL)
+                             Type::COMPARE_ERRORS | Type::COMPARE_TAGS,
+                             NULL)
       && this->rhs_->type()->interface_type() != NULL
       && !this->rhs_->is_variable())
     {
@@ -4384,7 +4387,9 @@ Send_statement::do_flatten(Gogo*, Named_object*, Block*,
     }
 
   Type* element_type = this->channel_->type()->channel_type()->element_type();
-  if (!Type::are_identical(element_type, this->val_->type(), false, NULL)
+  if (!Type::are_identical(element_type, this->val_->type(),
+                          Type::COMPARE_ERRORS | Type::COMPARE_TAGS,
+                          NULL)
       && this->val_->type()->interface_type() != NULL
       && !this->val_->is_variable())
     {
index 573011a25658da72e110850c022ac2d746dfbe35..bb90e92716a772e910dbfaf1eecff2eb2e0903d9 100644 (file)
@@ -336,29 +336,17 @@ Type::do_traverse(Traverse*)
   return TRAVERSE_CONTINUE;
 }
 
-// Return whether two types are identical.  If ERRORS_ARE_IDENTICAL,
-// then return true for all erroneous types; this is used to avoid
-// cascading errors.  If REASON is not NULL, optionally set *REASON to
-// the reason the types are not identical.
+// Return whether two types are identical.  If REASON is not NULL,
+// optionally set *REASON to the reason the types are not identical.
 
 bool
-Type::are_identical(const Type* t1, const Type* t2, bool errors_are_identical,
+Type::are_identical(const Type* t1, const Type* t2, int flags,
                    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)
     {
       // Something is wrong.
-      return errors_are_identical ? true : t1 == t2;
+      return (flags & COMPARE_ERRORS) == 0 ? true : t1 == t2;
     }
 
   // Skip defined forward declarations.  Ignore aliases.
@@ -371,12 +359,12 @@ Type::are_identical_cmp_tags(const Type* t1, const Type* t2, Cmp_tags cmp_tags,
   // An undefined forward declaration is an error.
   if (t1->forward_declaration_type() != NULL
       || t2->forward_declaration_type() != NULL)
-    return errors_are_identical;
+    return (flags & COMPARE_ERRORS) == 0;
 
   // Avoid cascading errors with error types.
   if (t1->is_error_type() || t2->is_error_type())
     {
-      if (errors_are_identical)
+      if ((flags & COMPARE_ERRORS) == 0)
        return true;
       return t1->is_error_type() && t2->is_error_type();
     }
@@ -418,35 +406,26 @@ Type::are_identical_cmp_tags(const Type* t1, const Type* t2, Cmp_tags cmp_tags,
 
     case TYPE_FUNCTION:
       return t1->function_type()->is_identical(t2->function_type(),
-                                              false,
-                                              cmp_tags,
-                                              errors_are_identical,
-                                              reason);
+                                              false, flags, reason);
 
     case TYPE_POINTER:
-      return Type::are_identical_cmp_tags(t1->points_to(), t2->points_to(),
-                                         cmp_tags, errors_are_identical,
-                                         reason);
+      return Type::are_identical(t1->points_to(), t2->points_to(), flags,
+                                reason);
 
     case TYPE_STRUCT:
-      return t1->struct_type()->is_identical(t2->struct_type(), cmp_tags,
-                                            errors_are_identical);
+      return t1->struct_type()->is_identical(t2->struct_type(), flags);
 
     case TYPE_ARRAY:
-      return t1->array_type()->is_identical(t2->array_type(), cmp_tags,
-                                           errors_are_identical);
+      return t1->array_type()->is_identical(t2->array_type(), flags);
 
     case TYPE_MAP:
-      return t1->map_type()->is_identical(t2->map_type(), cmp_tags,
-                                         errors_are_identical);
+      return t1->map_type()->is_identical(t2->map_type(), flags);
 
     case TYPE_CHANNEL:
-      return t1->channel_type()->is_identical(t2->channel_type(), cmp_tags,
-                                             errors_are_identical);
+      return t1->channel_type()->is_identical(t2->channel_type(), flags);
 
     case TYPE_INTERFACE:
-      return t1->interface_type()->is_identical(t2->interface_type(), cmp_tags,
-                                               errors_are_identical);
+      return t1->interface_type()->is_identical(t2->interface_type(), flags);
 
     case TYPE_CALL_MULTIPLE_RESULT:
       if (reason != NULL)
@@ -464,7 +443,7 @@ Type::are_identical_cmp_tags(const Type* t1, const Type* t2, Cmp_tags cmp_tags,
 bool
 Type::are_compatible_for_binop(const Type* lhs, const Type* rhs)
 {
-  if (Type::are_identical(lhs, rhs, true, NULL))
+  if (Type::are_identical(lhs, rhs, Type::COMPARE_TAGS, NULL))
     return true;
 
   // A constant of abstract bool type may be mixed with any bool type.
@@ -675,7 +654,7 @@ Type::are_assignable(const Type* lhs, const Type* rhs, std::string* reason)
     return true;
 
   // Identical types are assignable.
-  if (Type::are_identical(lhs, rhs, true, reason))
+  if (Type::are_identical(lhs, rhs, Type::COMPARE_TAGS, reason))
     return true;
 
   // Ignore aliases, except for error messages.
@@ -688,7 +667,8 @@ Type::are_assignable(const Type* lhs, const Type* rhs, std::string* reason)
   // and either LHS or RHS is not a named type.
   if (((lhs->named_type() != NULL && rhs->named_type() == NULL)
        || (rhs->named_type() != NULL && lhs->named_type() == NULL))
-      && Type::are_identical(lhs->base(), rhs->base(), true, reason))
+      && Type::are_identical(lhs->base(), rhs->base(), Type::COMPARE_TAGS,
+                            reason))
     return true;
 
   // The types are assignable if LHS is an interface type and RHS
@@ -715,7 +695,7 @@ Type::are_assignable(const Type* lhs, const Type* rhs, std::string* reason)
       && (lhs->named_type() == NULL || rhs->named_type() == NULL)
       && Type::are_identical(lhs->channel_type()->element_type(),
                             rhs->channel_type()->element_type(),
-                            true,
+                            Type::COMPARE_TAGS,
                             reason))
     return true;
 
@@ -796,8 +776,7 @@ Type::are_convertible(const Type* lhs, const Type* rhs, std::string* reason)
   // The types are convertible if they have identical underlying
   // types, ignoring struct field tags.
   if ((lhs->named_type() != NULL || rhs->named_type() != NULL)
-      && Type::are_identical_cmp_tags(lhs->base(), rhs->base(), IGNORE_TAGS,
-                                     true, reason))
+      && Type::are_identical(lhs->base(), rhs->base(), 0, reason))
     return true;
 
   // The types are convertible if they are both unnamed pointer types
@@ -809,11 +788,9 @@ Type::are_convertible(const Type* lhs, const Type* rhs, std::string* reason)
       && rhs->points_to() != NULL
       && (lhs->points_to()->named_type() != NULL
          || rhs->points_to()->named_type() != NULL)
-      && Type::are_identical_cmp_tags(lhs->points_to()->base(),
-                                     rhs->points_to()->base(),
-                                     IGNORE_TAGS,
-                                     true,
-                                     reason))
+      && Type::are_identical(lhs->points_to()->base(),
+                            rhs->points_to()->base(),
+                            0, reason))
     return true;
 
   // Integer and floating point types are convertible to each other.
@@ -944,21 +921,21 @@ Type::copy_expressions()
 // Return a hash code for the type to be used for method lookup.
 
 unsigned int
-Type::hash_for_method(Gogo* gogo) const
+Type::hash_for_method(Gogo* gogo, int flags) const
 {
   if (this->named_type() != NULL && this->named_type()->is_alias())
-    return this->named_type()->real_type()->hash_for_method(gogo);
+    return this->named_type()->real_type()->hash_for_method(gogo, flags);
   unsigned int ret = 0;
   if (this->classification_ != TYPE_FORWARD)
     ret += this->classification_;
-  return ret + this->do_hash_for_method(gogo);
+  return ret + this->do_hash_for_method(gogo, flags);
 }
 
 // Default implementation of do_hash_for_method.  This is appropriate
 // for types with no subfields.
 
 unsigned int
-Type::do_hash_for_method(Gogo*) const
+Type::do_hash_for_method(Gogo*, int) const
 {
   return 0;
 }
@@ -2370,9 +2347,9 @@ Type::type_descriptor_constructor(Gogo* gogo, int runtime_type_kind,
   go_assert(p->is_field_name("hash"));
   unsigned int h;
   if (name != NULL)
-    h = name->hash_for_method(gogo);
+    h = name->hash_for_method(gogo, Type::COMPARE_TAGS);
   else
-    h = this->hash_for_method(gogo);
+    h = this->hash_for_method(gogo, Type::COMPARE_TAGS);
   vals->push_back(Expression::make_integer_ul(h, p->type(), bloc));
 
   ++p;
@@ -3980,7 +3957,7 @@ Integer_type::is_identical(const Integer_type* t) const
 // Hash code.
 
 unsigned int
-Integer_type::do_hash_for_method(Gogo*) const
+Integer_type::do_hash_for_method(Gogo*, int) const
 {
   return ((this->bits_ << 4)
          + ((this->is_unsigned_ ? 1 : 0) << 8)
@@ -4110,7 +4087,7 @@ Float_type::is_identical(const Float_type* t) const
 // Hash code.
 
 unsigned int
-Float_type::do_hash_for_method(Gogo*) const
+Float_type::do_hash_for_method(Gogo*, int) const
 {
   return (this->bits_ << 4) + ((this->is_abstract_ ? 1 : 0) << 8);
 }
@@ -4224,7 +4201,7 @@ Complex_type::is_identical(const Complex_type *t) const
 // Hash code.
 
 unsigned int
-Complex_type::do_hash_for_method(Gogo*) const
+Complex_type::do_hash_for_method(Gogo*, int) const
 {
   return (this->bits_ << 4) + ((this->is_abstract_ ? 1 : 0) << 8);
 }
@@ -4443,7 +4420,7 @@ bool
 Function_type::is_valid_redeclaration(const Function_type* t,
                                      std::string* reason) const
 {
-  if (!this->is_identical(t, false, COMPARE_TAGS, true, reason))
+  if (!this->is_identical(t, false, COMPARE_TAGS, reason))
     return false;
 
   // A redeclaration of a function is required to use the same names
@@ -4521,8 +4498,7 @@ Function_type::is_valid_redeclaration(const Function_type* t,
 
 bool
 Function_type::is_identical(const Function_type* t, bool ignore_receiver,
-                           Cmp_tags cmp_tags, bool errors_are_identical,
-                           std::string* reason) const
+                           int flags, std::string* reason) const
 {
   if (this->is_backend_function_type() != t->is_backend_function_type())
     return false;
@@ -4539,8 +4515,7 @@ Function_type::is_identical(const Function_type* t, bool ignore_receiver,
        }
       if (r1 != NULL)
        {
-         if (!Type::are_identical_cmp_tags(r1->type(), r2->type(), cmp_tags,
-                                           errors_are_identical, reason))
+         if (!Type::are_identical(r1->type(), r2->type(), flags, reason))
            {
              if (reason != NULL && !reason->empty())
                *reason = "receiver: " + *reason;
@@ -4575,8 +4550,7 @@ Function_type::is_identical(const Function_type* t, bool ignore_receiver,
              return false;
            }
 
-         if (!Type::are_identical_cmp_tags(p1->type(), p2->type(), cmp_tags,
-                                           errors_are_identical, NULL))
+         if (!Type::are_identical(p1->type(), p2->type(), flags, NULL))
            {
              if (reason != NULL)
                *reason = _("different parameter types");
@@ -4624,9 +4598,7 @@ Function_type::is_identical(const Function_type* t, bool ignore_receiver,
              return false;
            }
 
-         if (!Type::are_identical_cmp_tags(res1->type(), res2->type(),
-                                           cmp_tags, errors_are_identical,
-                                           NULL))
+         if (!Type::are_identical(res1->type(), res2->type(), flags, NULL))
            {
              if (reason != NULL)
                *reason = _("different result types");
@@ -4647,7 +4619,7 @@ Function_type::is_identical(const Function_type* t, bool ignore_receiver,
 // Hash code.
 
 unsigned int
-Function_type::do_hash_for_method(Gogo* gogo) const
+Function_type::do_hash_for_method(Gogo* gogo, int flags) const
 {
   unsigned int ret = 0;
   // We ignore the receiver type for hash codes, because we need to
@@ -4659,7 +4631,7 @@ Function_type::do_hash_for_method(Gogo* gogo) const
       for (Typed_identifier_list::const_iterator p = this->parameters_->begin();
           p != this->parameters_->end();
           ++p, ++shift)
-       ret += p->type()->hash_for_method(gogo) << shift;
+       ret += p->type()->hash_for_method(gogo, flags) << shift;
     }
   if (this->results_ != NULL)
     {
@@ -4667,7 +4639,7 @@ Function_type::do_hash_for_method(Gogo* gogo) const
       for (Typed_identifier_list::const_iterator p = this->results_->begin();
           p != this->results_->end();
           ++p, ++shift)
-       ret += p->type()->hash_for_method(gogo) << shift;
+       ret += p->type()->hash_for_method(gogo, flags) << shift;
     }
   if (this->is_varargs_)
     ret += 1;
@@ -4687,7 +4659,7 @@ Function_type::Results_hash::operator()(const Typed_identifier_list* t) const
     {
       hash <<= 2;
       hash = Type::hash_string(p->name(), hash);
-      hash += p->type()->hash_for_method(NULL);
+      hash += p->type()->hash_for_method(NULL, Type::COMPARE_TAGS);
     }
   return hash;
 }
@@ -4707,7 +4679,8 @@ Function_type::Results_equal::operator()(const Typed_identifier_list* a,
        ++pa, ++pb)
     {
       if (pa->name() != pb->name()
-         || !Type::are_identical(pa->type(), pb->type(), true, NULL))
+         || !Type::are_identical(pa->type(), pb->type(), Type::COMPARE_TAGS,
+                                 NULL))
        return false;
     }
   return true;
@@ -5269,9 +5242,9 @@ Pointer_type::do_traverse(Traverse* traverse)
 // Hash code.
 
 unsigned int
-Pointer_type::do_hash_for_method(Gogo* gogo) const
+Pointer_type::do_hash_for_method(Gogo* gogo, int flags) const
 {
-  return this->to_type_->hash_for_method(gogo) << 4;
+  return this->to_type_->hash_for_method(gogo, flags) << 4;
 }
 
 // Get the backend representation for a pointer type.
@@ -5723,8 +5696,7 @@ Struct_type::do_has_pointer() const
 // Whether this type is identical to T.
 
 bool
-Struct_type::is_identical(const Struct_type* t, Cmp_tags cmp_tags,
-                         bool errors_are_identical) const
+Struct_type::is_identical(const Struct_type* t, int flags) const
 {
   if (this->is_struct_incomparable_ != t->is_struct_incomparable_)
     return false;
@@ -5742,10 +5714,9 @@ Struct_type::is_identical(const Struct_type* t, Cmp_tags cmp_tags,
       if (pf1->field_name() != pf2->field_name())
        return false;
       if (pf1->is_anonymous() != pf2->is_anonymous()
-         || !Type::are_identical_cmp_tags(pf1->type(), pf2->type(), cmp_tags,
-                                          errors_are_identical, NULL))
+         || !Type::are_identical(pf1->type(), pf2->type(), flags, NULL))
        return false;
-      if (cmp_tags == COMPARE_TAGS)
+      if ((flags & Type::COMPARE_TAGS) != 0)
        {
          if (!pf1->has_tag())
            {
@@ -5876,7 +5847,7 @@ Struct_type::do_in_heap()
 // Hash code.
 
 unsigned int
-Struct_type::do_hash_for_method(Gogo* gogo) const
+Struct_type::do_hash_for_method(Gogo* gogo, int flags) const
 {
   unsigned int ret = 0;
   if (this->fields() != NULL)
@@ -5884,7 +5855,7 @@ Struct_type::do_hash_for_method(Gogo* gogo) const
       for (Struct_field_list::const_iterator pf = this->fields()->begin();
           pf != this->fields()->end();
           ++pf)
-       ret = (ret << 1) + pf->type()->hash_for_method(gogo);
+       ret = (ret << 1) + pf->type()->hash_for_method(gogo, flags);
     }
   ret <<= 2;
   if (this->is_struct_incomparable_)
@@ -6940,11 +6911,10 @@ Array_type::int_length(int64_t* plen)
 // Whether two array types are identical.
 
 bool
-Array_type::is_identical(const Array_type* t, Cmp_tags cmp_tags,
-                        bool errors_are_identical) const
+Array_type::is_identical(const Array_type* t, int flags) const
 {
-  if (!Type::are_identical_cmp_tags(this->element_type(), t->element_type(),
-                                   cmp_tags, errors_are_identical, NULL))
+  if (!Type::are_identical(this->element_type(), t->element_type(),
+                          flags, NULL))
     return false;
 
   if (this->is_array_incomparable_ != t->is_array_incomparable_)
@@ -7154,13 +7124,13 @@ Array_type::do_compare_is_identity(Gogo* gogo)
 // Array type hash code.
 
 unsigned int
-Array_type::do_hash_for_method(Gogo* gogo) const
+Array_type::do_hash_for_method(Gogo* gogo, int flags) const
 {
   unsigned int ret;
 
   // There is no very convenient way to get a hash code for the
   // length.
-  ret = this->element_type_->hash_for_method(gogo) + 1;
+  ret = this->element_type_->hash_for_method(gogo, flags) + 1;
   if (this->is_array_incomparable_)
     ret <<= 1;
   return ret;
@@ -7873,23 +7843,20 @@ Map_type::do_verify()
 // Whether two map types are identical.
 
 bool
-Map_type::is_identical(const Map_type* t, Cmp_tags cmp_tags,
-                      bool errors_are_identical) const
+Map_type::is_identical(const Map_type* t, int flags) const
 {
-  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));
+  return (Type::are_identical(this->key_type(), t->key_type(), flags, NULL)
+         && Type::are_identical(this->val_type(), t->val_type(), flags,
+                                NULL));
 }
 
 // Hash code.
 
 unsigned int
-Map_type::do_hash_for_method(Gogo* gogo) const
+Map_type::do_hash_for_method(Gogo* gogo, int flags) const
 {
-  return (this->key_type_->hash_for_method(gogo)
-         + this->val_type_->hash_for_method(gogo)
+  return (this->key_type_->hash_for_method(gogo, flags)
+         + this->val_type_->hash_for_method(gogo, flags)
          + 2);
 }
 
@@ -8386,7 +8353,7 @@ Channel_type::do_verify()
 // Hash code.
 
 unsigned int
-Channel_type::do_hash_for_method(Gogo* gogo) const
+Channel_type::do_hash_for_method(Gogo* gogo, int flags) const
 {
   unsigned int ret = 0;
   if (this->may_send_)
@@ -8394,18 +8361,17 @@ Channel_type::do_hash_for_method(Gogo* gogo) const
   if (this->may_receive_)
     ret += 2;
   if (this->element_type_ != NULL)
-    ret += this->element_type_->hash_for_method(gogo) << 2;
+    ret += this->element_type_->hash_for_method(gogo, flags) << 2;
   return ret << 3;
 }
 
 // Whether this type is the same as T.
 
 bool
-Channel_type::is_identical(const Channel_type* t, Cmp_tags cmp_tags,
-                          bool errors_are_identical) const
+Channel_type::is_identical(const Channel_type* t, int flags) const
 {
-  if (!Type::are_identical_cmp_tags(this->element_type(), t->element_type(),
-                                   cmp_tags, errors_are_identical, NULL))
+  if (!Type::are_identical(this->element_type(), t->element_type(), flags,
+                          NULL))
     return false;
   return (this->may_send_ == t->may_send_
          && this->may_receive_ == t->may_receive_);
@@ -8775,8 +8741,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, Cmp_tags cmp_tags,
-                            bool errors_are_identical) const
+Interface_type::is_identical(const Interface_type* t, int flags) const
 {
   // If methods have not been finalized, then we are asking whether
   // func redeclarations are the same.  This is an error, so for
@@ -8806,8 +8771,7 @@ Interface_type::is_identical(const Interface_type* t, Cmp_tags cmp_tags,
       if (p1 == this->all_methods_->end())
        break;
       if (p1->name() != p2->name()
-         || !Type::are_identical_cmp_tags(p1->type(), p2->type(), cmp_tags,
-                                          errors_are_identical, NULL))
+         || !Type::are_identical(p1->type(), p2->type(), flags, NULL))
        break;
     }
 
@@ -8863,7 +8827,8 @@ Interface_type::is_compatible_for_assign(const Interface_type* t,
        }
 
       std::string subreason;
-      if (!Type::are_identical(p->type(), m->type(), true, &subreason))
+      if (!Type::are_identical(p->type(), m->type(), Type::COMPARE_TAGS,
+                              &subreason))
        {
          if (reason != NULL)
            {
@@ -8891,7 +8856,7 @@ Interface_type::is_compatible_for_assign(const Interface_type* t,
 // Hash code.
 
 unsigned int
-Interface_type::do_hash_for_method(Gogo*) const
+Interface_type::do_hash_for_method(Gogo*, int) const
 {
   go_assert(this->methods_are_finalized_);
   unsigned int ret = 0;
@@ -9005,7 +8970,7 @@ 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, COMPARE_TAGS, true,
+      if (!p_fn_type->is_identical(m_fn_type, true, Type::COMPARE_TAGS,
                                   &subreason))
        {
          if (reason != NULL)
@@ -10427,7 +10392,7 @@ Named_type::do_needs_key_update()
 // hash on the name itself.
 
 unsigned int
-Named_type::do_hash_for_method(Gogo* gogo) const
+Named_type::do_hash_for_method(Gogo* gogo, int) const
 {
   if (this->is_error_)
     return 0;
index 85e7c51c302d3ad2187b21858d993a1968108cd4..9e3f2f36e3c00d8e105d5f1c00256a7cbf49a87e 100644 (file)
@@ -563,29 +563,22 @@ class Type
   verify()
   { return this->do_verify(); }
 
-  // Return true if two types are identical.  If ERRORS_ARE_IDENTICAL,
-  // returns that an erroneous type is identical to any other type;
-  // this is used to avoid cascading errors.  If this returns false,
-  // and REASON is not NULL, it may set *REASON.
-  static bool
-  are_identical(const Type* lhs, const Type* rhs, bool errors_are_identical,
-               std::string* reason);
+  // Bit flags to pass to are_identical and friends.
 
-  // An argument to are_identical_cmp_tags, indicating whether or not
-  // to compare struct field tags.
-  enum Cmp_tags {
-    COMPARE_TAGS,
-    IGNORE_TAGS
-  };
+  // Treat error types as their own distinct type.  Sometimes we
+  // ignore error types--treat them as identical to every other
+  // type--to avoid cascading errors.
+  static const int COMPARE_ERRORS = 1;
+
+  // Compare struct field tags when comparing structs.  We ignore
+  // struct field tags for purposes of type conversion.
+  static const int COMPARE_TAGS = 2;
 
-  // 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.
+  // Return true if two types are identical.  If this returns false,
+  // and REASON is not NULL, it may set *REASON.
   static bool
-  are_identical_cmp_tags(const Type* lhs, const Type* rhs,
-                        Cmp_tags, bool errors_are_identical,
-                        std::string* reason);
+  are_identical(const Type* lhs, const Type* rhs, int flags,
+               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
@@ -648,7 +641,7 @@ class Type
   // Types which are equivalent according to are_identical will have
   // the same hash code.
   unsigned int
-  hash_for_method(Gogo*) const;
+  hash_for_method(Gogo*, int) const;
 
   // Return the type classification.
   Type_classification
@@ -1082,7 +1075,7 @@ class Type
   { return true; }
 
   virtual unsigned int
-  do_hash_for_method(Gogo*) const;
+  do_hash_for_method(Gogo*, int) const;
 
   virtual Btype*
   do_get_backend(Gogo*) = 0;
@@ -1381,14 +1374,18 @@ class Type
   bool in_heap_;
 };
 
-// Type hash table operations.
+// Type hash table operations, treating aliases as identical to the
+// types that they alias.
 
 class Type_hash_identical
 {
  public:
   unsigned int
   operator()(const Type* type) const
-  { return type->hash_for_method(NULL); }
+  {
+    return type->hash_for_method(NULL,
+                                Type::COMPARE_ERRORS | Type::COMPARE_TAGS);
+  }
 };
 
 class Type_identical
@@ -1396,7 +1393,11 @@ class Type_identical
  public:
   bool
   operator()(const Type* t1, const Type* t2) const
-  { return Type::are_identical(t1, t2, false, NULL); }
+  {
+    return Type::are_identical(t1, t2,
+                              Type::COMPARE_ERRORS | Type::COMPARE_TAGS,
+                              NULL);
+  }
 };
 
 // An identifier with a type.
@@ -1724,7 +1725,7 @@ protected:
   { return true; }
 
   unsigned int
-  do_hash_for_method(Gogo*) const;
+  do_hash_for_method(Gogo*, int) const;
 
   Btype*
   do_get_backend(Gogo*);
@@ -1810,7 +1811,7 @@ class Float_type : public Type
   { return true; }
 
   unsigned int
-  do_hash_for_method(Gogo*) const;
+  do_hash_for_method(Gogo*, int) const;
 
   Btype*
   do_get_backend(Gogo*);
@@ -1888,7 +1889,7 @@ class Complex_type : public Type
   { return true; }
 
   unsigned int
-  do_hash_for_method(Gogo*) const;
+  do_hash_for_method(Gogo*, int) const;
 
   Btype*
   do_get_backend(Gogo*);
@@ -2036,8 +2037,8 @@ class Function_type : public Type
 
   // Whether this type is the same as T.
   bool
-  is_identical(const Function_type* t, bool ignore_receiver,
-              Cmp_tags, bool errors_are_identical, std::string*) const;
+  is_identical(const Function_type* t, bool ignore_receiver, int flags,
+              std::string*) const;
 
   // Record that this is a varargs function.
   void
@@ -2102,7 +2103,7 @@ class Function_type : public Type
   { return false; }
 
   unsigned int
-  do_hash_for_method(Gogo*) const;
+  do_hash_for_method(Gogo*, int) const;
 
   Btype*
   do_get_backend(Gogo*);
@@ -2231,7 +2232,7 @@ class Pointer_type : public Type
   { return true; }
 
   unsigned int
-  do_hash_for_method(Gogo*) const;
+  do_hash_for_method(Gogo*, int) const;
 
   Btype*
   do_get_backend(Gogo*);
@@ -2478,8 +2479,7 @@ class Struct_type : public Type
 
   // Whether this type is identical with T.
   bool
-  is_identical(const Struct_type* t, Cmp_tags,
-              bool errors_are_identical) const;
+  is_identical(const Struct_type* t, int) const;
 
   // Return whether NAME is a local field which is not exported.  This
   // is only used for better error reporting.
@@ -2498,7 +2498,7 @@ class Struct_type : public Type
   has_any_methods() const
   { return this->all_methods_ != NULL; }
 
-  // Return the methods for tihs type.  This should only be called
+  // Return the methods for this type.  This should only be called
   // after the finalize_methods pass.
   const Methods*
   methods() const
@@ -2590,7 +2590,7 @@ class Struct_type : public Type
   do_in_heap();
 
   unsigned int
-  do_hash_for_method(Gogo*) const;
+  do_hash_for_method(Gogo*, int) const;
 
   Btype*
   do_get_backend(Gogo*);
@@ -2684,8 +2684,7 @@ class Array_type : public Type
 
   // Whether this type is identical with T.
   bool
-  is_identical(const Array_type* t, Cmp_tags,
-              bool errors_are_identical) const;
+  is_identical(const Array_type* t, int) const;
 
   // Return an expression for the pointer to the values in an array.
   Expression*
@@ -2767,7 +2766,7 @@ class Array_type : public Type
   { return this->length_ == NULL || this->element_type_->in_heap(); }
 
   unsigned int
-  do_hash_for_method(Gogo*) const;
+  do_hash_for_method(Gogo*, int) const;
 
   Btype*
   do_get_backend(Gogo*);
@@ -2850,8 +2849,7 @@ class Map_type : public Type
 
   // Whether this type is identical with T.
   bool
-  is_identical(const Map_type* t, Cmp_tags,
-              bool errors_are_identical) const;
+  is_identical(const Map_type* t, int) const;
 
   // Import a map type.
   static Map_type*
@@ -2885,7 +2883,7 @@ class Map_type : public Type
   }
 
   unsigned int
-  do_hash_for_method(Gogo*) const;
+  do_hash_for_method(Gogo*, int) const;
 
   Btype*
   do_get_backend(Gogo*);
@@ -2970,8 +2968,7 @@ class Channel_type : public Type
 
   // Whether this type is identical with T.
   bool
-  is_identical(const Channel_type* t, Cmp_tags,
-              bool errors_are_identical) const;
+  is_identical(const Channel_type* t, int) const;
 
   // Import a channel type.
   static Channel_type*
@@ -3000,7 +2997,7 @@ class Channel_type : public Type
   { return true; }
 
   unsigned int
-  do_hash_for_method(Gogo*) const;
+  do_hash_for_method(Gogo*, int) const;
 
   Btype*
   do_get_backend(Gogo*);
@@ -3090,8 +3087,7 @@ 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, Cmp_tags,
-              bool errors_are_identical) const;
+  is_identical(const Interface_type* t, int) const;
 
   // Whether we can assign T to this type.  is_identical is known to
   // be false.
@@ -3151,7 +3147,7 @@ class Interface_type : public Type
   { return true; }
 
   unsigned int
-  do_hash_for_method(Gogo*) const;
+  do_hash_for_method(Gogo*, int) const;
 
   Btype*
   do_get_backend(Gogo*);
@@ -3476,7 +3472,7 @@ class Named_type : public Type
   { return this->in_heap_ && this->type_->in_heap(); }
 
   unsigned int
-  do_hash_for_method(Gogo*) const;
+  do_hash_for_method(Gogo*, int) const;
 
   Btype*
   do_get_backend(Gogo*);
@@ -3639,8 +3635,8 @@ class Forward_declaration_type : public Type
   { return this->real_type()->in_heap(); }
 
   unsigned int
-  do_hash_for_method(Gogo* gogo) const
-  { return this->real_type()->hash_for_method(gogo); }
+  do_hash_for_method(Gogo* gogo, int flags) const
+  { return this->real_type()->hash_for_method(gogo, flags); }
 
   Btype*
   do_get_backend(Gogo* gogo);
index 52db71046fe6827dbc8474f6903c8365187b6340..3f0a89f8ceb509bb5271903e298f2472759fe3e8 100644 (file)
@@ -777,7 +777,9 @@ Gogo::assign_with_write_barrier(Function* function, Block* enclosing,
   inserter->insert(lhs_temp);
   lhs = Expression::make_temporary_reference(lhs_temp, loc);
 
-  if (!Type::are_identical(type, rhs->type(), false, NULL)
+  if (!Type::are_identical(type, rhs->type(),
+                          Type::COMPARE_ERRORS | Type::COMPARE_TAGS,
+                          NULL)
       && rhs->type()->interface_type() != NULL
       && !rhs->is_variable())
     {