aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/go/gofrontend/MERGE2
-rw-r--r--gcc/go/gofrontend/expressions.cc42
-rw-r--r--gcc/go/gofrontend/expressions.h11
3 files changed, 49 insertions, 6 deletions
diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE
index f55daf7..cd1a396 100644
--- a/gcc/go/gofrontend/MERGE
+++ b/gcc/go/gofrontend/MERGE
@@ -1,4 +1,4 @@
-5364d15082de77d2759a01f254208d4cb4f579e3
+b3a0b068f7fa2d65ba781271b2c0479d103b7d7b
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/expressions.cc b/gcc/go/gofrontend/expressions.cc
index 50574c2..ebe1b36 100644
--- a/gcc/go/gofrontend/expressions.cc
+++ b/gcc/go/gofrontend/expressions.cc
@@ -6287,8 +6287,21 @@ Binary_expression::lower_array_comparison(Gogo* gogo,
args->push_back(this->operand_address(inserter, this->left_));
args->push_back(this->operand_address(inserter, this->right_));
- Expression* ret = Expression::make_call(func, args, false, loc);
-
+ Call_expression* ce = Expression::make_call(func, args, false, loc);
+
+ // Record that this is a call to a generated equality function. We
+ // need to do this because a comparison returns an abstract boolean
+ // type, but the function necessarily returns "bool". The
+ // difference shows up in code like
+ // type mybool bool
+ // var b mybool = [10]string{} == [10]string{}
+ // The comparison function returns "bool", but since a comparison
+ // has an abstract boolean type we need an implicit conversion to
+ // "mybool". The implicit conversion is inserted in
+ // Call_expression::do_flatten.
+ ce->set_is_equal_function();
+
+ Expression* ret = ce;
if (this->op_ == OPERATOR_NOTEQ)
ret = Expression::make_unary(OPERATOR_NOT, ret, loc);
@@ -11163,6 +11176,13 @@ Call_expression::do_flatten(Gogo* gogo, Named_object*,
return ret;
}
+ // Add an implicit conversion to a boolean type, if needed. See the
+ // comment in Binary_expression::lower_array_comparison.
+ if (this->is_equal_function_
+ && this->type_ != NULL
+ && this->type_ != Type::lookup_bool_type())
+ return Expression::make_cast(this->type_, this, this->location());
+
return this;
}
@@ -11938,7 +11958,7 @@ Call_expression::do_type()
// parameter types to set the types of the arguments.
void
-Call_expression::do_determine_type(const Type_context*)
+Call_expression::do_determine_type(const Type_context* context)
{
if (!this->determining_types())
return;
@@ -11985,6 +12005,22 @@ Call_expression::do_determine_type(const Type_context*)
(*pa)->determine_type_no_context();
}
}
+
+ // If this is a call to a generated equality function, we determine
+ // the type based on the context. See the comment in
+ // Binary_expression::lower_array_comparison.
+ if (this->is_equal_function_
+ && !context->may_be_abstract
+ && context->type != NULL
+ && context->type->is_boolean_type()
+ && context->type != Type::lookup_bool_type())
+ {
+ go_assert(this->type_ == NULL
+ || this->type_ == Type::lookup_bool_type()
+ || this->type_ == context->type
+ || this->type_->is_error());
+ this->type_ = context->type;
+ }
}
// Called when determining types for a Call_expression. Return true
diff --git a/gcc/go/gofrontend/expressions.h b/gcc/go/gofrontend/expressions.h
index d297523..259eeb6 100644
--- a/gcc/go/gofrontend/expressions.h
+++ b/gcc/go/gofrontend/expressions.h
@@ -2326,8 +2326,8 @@ class Call_expression : public Expression
fn_(fn), args_(args), type_(NULL), call_(NULL), call_temp_(NULL)
, expected_result_count_(0), is_varargs_(is_varargs),
varargs_are_lowered_(false), types_are_determined_(false),
- is_deferred_(false), is_concurrent_(false), issued_error_(false),
- is_multi_value_arg_(false), is_flattened_(false)
+ is_deferred_(false), is_concurrent_(false), is_equal_function_(false),
+ issued_error_(false), is_multi_value_arg_(false), is_flattened_(false)
{ }
// The function to call.
@@ -2408,6 +2408,11 @@ class Call_expression : public Expression
set_is_concurrent()
{ this->is_concurrent_ = true; }
+ // Note that this is a call to a generated equality function.
+ void
+ set_is_equal_function()
+ { this->is_equal_function_ = true; }
+
// We have found an error with this call expression; return true if
// we should report it.
bool
@@ -2545,6 +2550,8 @@ class Call_expression : public Expression
bool is_deferred_;
// True if the call is an argument to a go statement.
bool is_concurrent_;
+ // True if this is a call to a generated equality function.
+ bool is_equal_function_;
// True if we reported an error about a mismatch between call
// results and uses. This is to avoid producing multiple errors
// when there are multiple Call_result_expressions.