This patch by Chris Manghane avoids a compiler crash by marking
erroneous constants as invalid and turning them into error expressions
when seen.  This fixes https://golang.org/issue/11541 .  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 227395)
+++ gcc/go/gofrontend/MERGE     (working copy)
@@ -1,4 +1,4 @@
-a63e173b20baa1a48470dd31a1fb1f2704b37011
+3f8feb4f905535448833a14e4f5c83f682087749
 
 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 227395)
+++ gcc/go/gofrontend/expressions.cc    (working copy)
@@ -4567,6 +4567,7 @@ Binary_expression::eval_integer(Operator
       if (mpz_sizeinbase(val, 2) > 0x100000)
        {
          error_at(location, "constant addition overflow");
+          nc->set_invalid();
          mpz_set_ui(val, 1);
        }
       break;
@@ -4575,6 +4576,7 @@ Binary_expression::eval_integer(Operator
       if (mpz_sizeinbase(val, 2) > 0x100000)
        {
          error_at(location, "constant subtraction overflow");
+          nc->set_invalid();
          mpz_set_ui(val, 1);
        }
       break;
@@ -4589,6 +4591,7 @@ Binary_expression::eval_integer(Operator
       if (mpz_sizeinbase(val, 2) > 0x100000)
        {
          error_at(location, "constant multiplication overflow");
+          nc->set_invalid();
          mpz_set_ui(val, 1);
        }
       break;
@@ -4598,6 +4601,7 @@ Binary_expression::eval_integer(Operator
       else
        {
          error_at(location, "division by zero");
+          nc->set_invalid();
          mpz_set_ui(val, 0);
        }
       break;
@@ -4607,6 +4611,7 @@ Binary_expression::eval_integer(Operator
       else
        {
          error_at(location, "division by zero");
+          nc->set_invalid();
          mpz_set_ui(val, 0);
        }
       break;
@@ -4618,6 +4623,7 @@ Binary_expression::eval_integer(Operator
        else
          {
            error_at(location, "shift count overflow");
+            nc->set_invalid();
            mpz_set_ui(val, 1);
          }
        break;
@@ -4629,6 +4635,7 @@ Binary_expression::eval_integer(Operator
        if (mpz_cmp_ui(right_val, shift) != 0)
          {
            error_at(location, "shift count overflow");
+            nc->set_invalid();
            mpz_set_ui(val, 1);
          }
        else
@@ -4723,6 +4730,7 @@ Binary_expression::eval_float(Operator o
       else
        {
          error_at(location, "division by zero");
+          nc->set_invalid();
          mpfr_set_ui(val, 0, GMP_RNDN);
        }
       break;
@@ -4787,6 +4795,7 @@ Binary_expression::eval_complex(Operator
       if (mpc_cmp_si(right_val, 0) == 0)
        {
          error_at(location, "division by zero");
+          nc->set_invalid();
          mpc_set_ui(val, 0, MPC_RNDNN);
          break;
        }
@@ -4849,7 +4858,14 @@ Binary_expression::do_lower(Gogo* gogo,
            Numeric_constant nc;
            if (!Binary_expression::eval_constant(op, &left_nc, &right_nc,
                                                  location, &nc))
-             return this;
+              {
+                if (nc.is_invalid())
+                  {
+                    go_assert(saw_errors());
+                    return Expression::make_error(location);
+                  }
+                return this;
+              }
            return nc.expression(location);
          }
       }
@@ -15189,7 +15205,7 @@ Numeric_constant::set_type(Type* type, b
 
 bool
 Numeric_constant::check_int_type(Integer_type* type, bool issue_error,
-                                Location location) const
+                                Location location)
 {
   mpz_t val;
   switch (this->classification_)
@@ -15203,7 +15219,11 @@ Numeric_constant::check_int_type(Integer
       if (!mpfr_integer_p(this->u_.float_val))
        {
          if (issue_error)
-           error_at(location, "floating point constant truncated to integer");
+            {
+              error_at(location,
+                       "floating point constant truncated to integer");
+              this->set_invalid();
+            }
          return false;
        }
       mpz_init(val);
@@ -15215,7 +15235,10 @@ Numeric_constant::check_int_type(Integer
          || !mpfr_zero_p(mpc_imagref(this->u_.complex_val)))
        {
          if (issue_error)
-           error_at(location, "complex constant truncated to integer");
+            {
+              error_at(location, "complex constant truncated to integer");
+              this->set_invalid();
+            }
          return false;
        }
       mpz_init(val);
@@ -15253,7 +15276,10 @@ Numeric_constant::check_int_type(Integer
     }
 
   if (!ret && issue_error)
-    error_at(location, "integer constant overflow");
+    {
+      error_at(location, "integer constant overflow");
+      this->set_invalid();
+    }
 
   return ret;
 }
@@ -15281,7 +15307,10 @@ Numeric_constant::check_float_type(Float
       if (!mpfr_zero_p(mpc_imagref(this->u_.complex_val)))
        {
          if (issue_error)
-           error_at(location, "complex constant truncated to float");
+            {
+              this->set_invalid();
+              error_at(location, "complex constant truncated to float");
+            }
          return false;
        }
       mpfr_init_set(val, mpc_realref(this->u_.complex_val), GMP_RNDN);
@@ -15344,7 +15373,10 @@ Numeric_constant::check_float_type(Float
   mpfr_clear(val);
 
   if (!ret && issue_error)
-    error_at(location, "floating point constant overflow");
+    {
+      error_at(location, "floating point constant overflow");
+      this->set_invalid();
+    }
 
   return ret;
 } 
@@ -15399,7 +15431,10 @@ Numeric_constant::check_complex_type(Com
       && mpfr_get_exp(mpc_realref(val)) > max_exp)
     {
       if (issue_error)
-       error_at(location, "complex real part overflow");
+        {
+          error_at(location, "complex real part overflow");
+          this->set_invalid();
+        }
       ret = false;
     }
 
@@ -15409,7 +15444,10 @@ Numeric_constant::check_complex_type(Com
       && mpfr_get_exp(mpc_imagref(val)) > max_exp)
     {
       if (issue_error)
-       error_at(location, "complex imaginary part overflow");
+        {
+          error_at(location, "complex imaginary part overflow");
+          this->set_invalid();
+        }
       ret = false;
     }
 
@@ -15455,6 +15493,9 @@ Numeric_constant::expression(Location lo
       return Expression::make_float(&this->u_.float_val, this->type_, loc);
     case NC_COMPLEX:
       return Expression::make_complex(&this->u_.complex_val, this->type_, loc);
+    case NC_INVALID:
+      go_assert(saw_errors());
+      return Expression::make_error(loc);
     default:
       go_unreachable();
     }
Index: gcc/go/gofrontend/expressions.h
===================================================================
--- gcc/go/gofrontend/expressions.h     (revision 227299)
+++ gcc/go/gofrontend/expressions.h     (working copy)
@@ -3460,6 +3460,11 @@ class Numeric_constant
   void
   set_complex(Type*, const mpc_t);
 
+  // Mark numeric constant as invalid.
+  void
+  set_invalid()
+  { this->classification_ = NC_INVALID; }
+
   // Classifiers.
   bool
   is_int() const
@@ -3477,6 +3482,10 @@ class Numeric_constant
   is_complex() const
   { return this->classification_ == Numeric_constant::NC_COMPLEX; }
 
+  bool
+  is_invalid() const
+  { return this->classification_ == Numeric_constant::NC_INVALID; }
+
   // Value retrievers.  These will initialize the values as well as
   // set them.  GET_INT is only valid if IS_INT returns true, and
   // likewise respectively.
@@ -3554,7 +3563,7 @@ class Numeric_constant
   mpfr_to_unsigned_long(const mpfr_t fval, unsigned long *val) const;
 
   bool
-  check_int_type(Integer_type*, bool, Location) const;
+  check_int_type(Integer_type*, bool, Location);
 
   bool
   check_float_type(Float_type*, bool, Location);

Reply via email to