diff mbox

Go patch committed: mark erroneous constants as invalid

Message ID CAOyqgcVDw4YFTY4C8dSY0aS1YA+qSJXGGWh_bn5Buox2h5h+tQ@mail.gmail.com
State New
Headers show

Commit Message

Ian Lance Taylor Sept. 2, 2015, 8:52 p.m. UTC
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
diff mbox

Patch

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);