This patch by Chris Manghane changes the Go frontend to ignore the result context when determining the type of constant expressions. This fixes https://golang.org/issue/11566 . Bootstrapped and ran Go testsuite on x86_64-unknown-linux-gnu. Committed to mainline.
Ian
Index: gcc/go/gofrontend/MERGE =================================================================== --- gcc/go/gofrontend/MERGE (revision 227699) +++ gcc/go/gofrontend/MERGE (working copy) @@ -1,4 +1,4 @@ -aea4360ca9c37f8e929f177ae7e42593ee62aa79 +1d9d92ab09996d2f7795481d2876a21194502b89 The first line of this file holds the git revision number of the last merge done from the gofrontend repository. Index: gcc/go/gofrontend/expressions.cc =================================================================== --- gcc/go/gofrontend/expressions.cc (revision 227696) +++ gcc/go/gofrontend/expressions.cc (working copy) @@ -5307,6 +5307,14 @@ Binary_expression::do_determine_type(con || this->op_ == OPERATOR_GT || this->op_ == OPERATOR_GE); + // For constant expressions, the context of the result is not useful in + // determining the types of the operands. It is only legal to use abstract + // boolean, numeric, and string constants as operands where it is legal to + // use non-abstract boolean, numeric, and string constants, respectively. + // Any issues with the operation will be resolved in the check_types pass. + bool is_constant_expr = (this->left_->is_constant() + && this->right_->is_constant()); + Type_context subcontext(*context); if (is_comparison) @@ -5351,7 +5359,8 @@ Binary_expression::do_determine_type(con subcontext.type = subcontext.type->make_non_abstract_type(); } - this->left_->determine_type(&subcontext); + if (!is_constant_expr) + this->left_->determine_type(&subcontext); if (is_shift_op) { @@ -5371,7 +5380,8 @@ Binary_expression::do_determine_type(con subcontext.may_be_abstract = false; } - this->right_->determine_type(&subcontext); + if (!is_constant_expr) + this->right_->determine_type(&subcontext); if (is_comparison) { @@ -5396,7 +5406,8 @@ Binary_expression::check_operator_type(O { case OPERATOR_OROR: case OPERATOR_ANDAND: - if (!type->is_boolean_type()) + if (!type->is_boolean_type() + || !otype->is_boolean_type()) { error_at(location, "expected boolean type"); return false; @@ -5431,10 +5442,8 @@ Binary_expression::check_operator_type(O case OPERATOR_PLUS: case OPERATOR_PLUSEQ: - if (type->integer_type() == NULL - && type->float_type() == NULL - && type->complex_type() == NULL - && !type->is_string_type()) + if ((!type->is_numeric_type() && !type->is_string_type()) + || (!otype->is_numeric_type() && !otype->is_string_type())) { error_at(location, "expected integer, floating, complex, or string type"); @@ -5448,9 +5457,7 @@ Binary_expression::check_operator_type(O case OPERATOR_MULTEQ: case OPERATOR_DIV: case OPERATOR_DIVEQ: - if (type->integer_type() == NULL - && type->float_type() == NULL - && type->complex_type() == NULL) + if (!type->is_numeric_type() || !otype->is_numeric_type()) { error_at(location, "expected integer, floating, or complex type"); return false; @@ -5467,7 +5474,7 @@ Binary_expression::check_operator_type(O case OPERATOR_XOREQ: case OPERATOR_BITCLEAR: case OPERATOR_BITCLEAREQ: - if (type->integer_type() == NULL) + if (type->integer_type() == NULL || otype->integer_type() == NULL) { error_at(location, "expected integer type"); return false;