re PR go/78763 (go1: internal compiler error: in do_get_backend, at go/gofrontend...
authorIan Lance Taylor <ian@gcc.gnu.org>
Thu, 15 Dec 2016 22:47:43 +0000 (22:47 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Thu, 15 Dec 2016 22:47:43 +0000 (22:47 +0000)
PR go/78763
    compiler: call determine_types even for constant expressions

    We need to call determine_types even for constant expressions, since a
    constant expression may include code like unsafe.Sizeof(0).  Something
    needs to determine the type of the untyped 0, and that should be the
    determine_types pass.

    Implementing that triggered a compiler crash on test/const1.go because
    it permitted some erroneous constants to make it all the way to the
    backend.  Catch that case by checking whether we get a constant
    overflow error, and marking the expression invalid if we do.  This is
    a good change in any case, as previously we reported the same constant
    overflow error multiple times, and now we only report it once.

    Fixes GCC PR 78763.

    Reviewed-on: https://go-review.googlesource.com/34496

From-SVN: r243729

gcc/go/gofrontend/MERGE
gcc/go/gofrontend/expressions.cc
gcc/go/gofrontend/expressions.h

index 1303ad5412a8c5e7fd0e9768b105b4231a12b32c..4a5f6d295ddb5545c103d02dcf32af3fb7dd9b4b 100644 (file)
@@ -1,4 +1,4 @@
-5eb55901861f360c2c2ff70f14a8315694934c97
+e807c1deec1e7114bc4757b6193510fdae13e75f
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
index a9337bda6b1c6fad53e566040d3a93ef2b91776b..2022c4749b3ebcf8c2b275ce15c52100e305366a 100644 (file)
@@ -3738,8 +3738,12 @@ Unary_expression::do_lower(Gogo*, Named_object*, Statement_inserter*, int)
       if (expr->numeric_constant_value(&nc))
        {
          Numeric_constant result;
-         if (Unary_expression::eval_constant(op, &nc, loc, &result))
+         bool issued_error;
+         if (Unary_expression::eval_constant(op, &nc, loc, &result,
+                                             &issued_error))
            return result.expression(loc);
+         else if (issued_error)
+           return Expression::make_error(this->location());
        }
     }
 
@@ -3900,12 +3904,15 @@ Unary_expression::do_is_static_initializer() const
 }
 
 // Apply unary opcode OP to UNC, setting NC.  Return true if this
-// could be done, false if not.  Issue errors for overflow.
+// could be done, false if not.  On overflow, issues an error and sets
+// *ISSUED_ERROR.
 
 bool
 Unary_expression::eval_constant(Operator op, const Numeric_constant* unc,
-                               Location location, Numeric_constant* nc)
+                               Location location, Numeric_constant* nc,
+                               bool* issued_error)
 {
+  *issued_error = false;
   switch (op)
     {
     case OPERATOR_PLUS:
@@ -4050,7 +4057,12 @@ Unary_expression::eval_constant(Operator op, const Numeric_constant* unc,
   mpz_clear(uval);
   mpz_clear(val);
 
-  return nc->set_type(unc->type(), true, location);
+  if (!nc->set_type(unc->type(), true, location))
+    {
+      *issued_error = true;
+      return false;
+    }
+  return true;
 }
 
 // Return the integral constant value of a unary expression, if it has one.
@@ -4061,8 +4073,9 @@ Unary_expression::do_numeric_constant_value(Numeric_constant* nc) const
   Numeric_constant unc;
   if (!this->expr_->numeric_constant_value(&unc))
     return false;
+  bool issued_error;
   return Unary_expression::eval_constant(this->op_, &unc, this->location(),
-                                        nc);
+                                        nc, &issued_error);
 }
 
 // Return the type of a unary expression.
@@ -4737,13 +4750,15 @@ Binary_expression::compare_complex(const Numeric_constant* left_nc,
 
 // Apply binary opcode OP to LEFT_NC and RIGHT_NC, setting NC.  Return
 // true if this could be done, false if not.  Issue errors at LOCATION
-// as appropriate.
+// as appropriate, and sets *ISSUED_ERROR if it did.
 
 bool
 Binary_expression::eval_constant(Operator op, Numeric_constant* left_nc,
                                 Numeric_constant* right_nc,
-                                Location location, Numeric_constant* nc)
+                                Location location, Numeric_constant* nc,
+                                bool* issued_error)
 {
+  *issued_error = false;
   switch (op)
     {
     case OPERATOR_OROR:
@@ -4792,7 +4807,11 @@ Binary_expression::eval_constant(Operator op, Numeric_constant* left_nc,
     r = Binary_expression::eval_integer(op, left_nc, right_nc, location, nc);
 
   if (r)
-    r = nc->set_type(type, true, location);
+    {
+      r = nc->set_type(type, true, location);
+      if (!r)
+       *issued_error = true;
+    }
 
   return r;
 }
@@ -5115,9 +5134,15 @@ Binary_expression::do_lower(Gogo* gogo, Named_object*,
        else
          {
            Numeric_constant nc;
+           bool issued_error;
            if (!Binary_expression::eval_constant(op, &left_nc, &right_nc,
-                                                 location, &nc))
+                                                 location, &nc,
+                                                 &issued_error))
+             {
+               if (issued_error)
+                 return Expression::make_error(location);
                 return this;
+             }
            return nc.expression(location);
          }
       }
@@ -5458,8 +5483,9 @@ Binary_expression::do_numeric_constant_value(Numeric_constant* nc) const
   Numeric_constant right_nc;
   if (!this->right_->numeric_constant_value(&right_nc))
     return false;
+  bool issued_error;
   return Binary_expression::eval_constant(this->op_, &left_nc, &right_nc,
-                                         this->location(), nc);
+                                         this->location(), nc, &issued_error);
 }
 
 // Note that the value is being discarded.
@@ -5558,7 +5584,12 @@ Binary_expression::do_determine_type(const Type_context* context)
 
   Type_context subcontext(*context);
 
-  if (is_comparison)
+  if (is_constant_expr)
+    {
+      subcontext.type = NULL;
+      subcontext.may_be_abstract = true;
+    }
+  else if (is_comparison)
     {
       // In a comparison, the context does not determine the types of
       // the operands.
@@ -5600,8 +5631,7 @@ Binary_expression::do_determine_type(const Type_context* context)
        subcontext.type = subcontext.type->make_non_abstract_type();
     }
 
-  if (!is_constant_expr)
-    this->left_->determine_type(&subcontext);
+  this->left_->determine_type(&subcontext);
 
   if (is_shift_op)
     {
@@ -5621,8 +5651,7 @@ Binary_expression::do_determine_type(const Type_context* context)
       subcontext.may_be_abstract = false;
     }
 
-  if (!is_constant_expr)
-    this->right_->determine_type(&subcontext);
+  this->right_->determine_type(&subcontext);
 
   if (is_comparison)
     {
index 98e21151cc602fb8674eed774706dd2c665e1624..e088100e056e6504293043fe5260aeb40be4ab81 100644 (file)
@@ -1775,10 +1775,11 @@ class Unary_expression : public Expression
   }
 
   // Apply unary opcode OP to UNC, setting NC.  Return true if this
-  // could be done, false if not.  Issue errors for overflow.
+  // could be done, false if not.  On overflow, issues an error and
+  // sets *ISSUED_ERROR.
   static bool
   eval_constant(Operator op, const Numeric_constant* unc,
-               Location, Numeric_constant* nc);
+               Location, Numeric_constant* nc, bool *issued_error);
 
   static Expression*
   do_import(Import*);
@@ -1893,11 +1894,11 @@ class Binary_expression : public Expression
 
   // Apply binary opcode OP to LEFT_NC and RIGHT_NC, setting NC.
   // Return true if this could be done, false if not.  Issue errors at
-  // LOCATION as appropriate.
+  // LOCATION as appropriate, and sets *ISSUED_ERROR if it did.
   static bool
   eval_constant(Operator op, Numeric_constant* left_nc,
                Numeric_constant* right_nc, Location location,
-               Numeric_constant* nc);
+               Numeric_constant* nc, bool* issued_error);
 
   // Compare constants LEFT_NC and RIGHT_NC according to OP, setting
   // *RESULT.  Return true if this could be done, false if not.  Issue