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;

Reply via email to