compiler: rewrite Type::are_identical to use flags
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
This commit is contained in:
parent
28dd75a330
commit
0799a08b5c
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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()
|
||||
|
@ -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())
|
||||
|
@ -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())
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -563,30 +563,23 @@ 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,
|
||||
// Bit flags to pass to are_identical and friends.
|
||||
|
||||
// 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. 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,
|
||||
are_identical(const Type* lhs, const Type* rhs, int flags,
|
||||
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.
|
||||
@ -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);
|
||||
|
@ -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())
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user