On Thu, Dec 15, 2016 at 2:47 PM, Ian Lance Taylor <i...@golang.org> wrote: > The Go frontend needs to call determine_types even for constant > expressions, which it was not doing. The problem is that 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. > > This fixes GCC PR 78763. > > Bootstrapped and ran Go testsuite on x86_64-pc-linux-gnu. Committed > to mainline.
In order to fix GCC PR 78763, I'd like to commit this patch to the GCC 6 branch. I've bootstrapped the test on x86_64-pc-linux-gnu, and verified that the Go tests continue to pass. OK for GCC 6 branch? Ian
Index: gcc/go/gofrontend/expressions.cc =================================================================== --- gcc/go/gofrontend/expressions.cc (revision 243728) +++ gcc/go/gofrontend/expressions.cc (working copy) @@ -3639,8 +3639,12 @@ 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()); } } @@ -3747,12 +3751,15 @@ } // 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: @@ -3897,7 +3904,12 @@ 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. @@ -3908,8 +3920,9 @@ 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. @@ -4539,13 +4552,15 @@ // 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: @@ -4594,7 +4609,11 @@ 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; } @@ -4917,9 +4936,15 @@ 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); } } @@ -5254,8 +5279,9 @@ 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. @@ -5354,8 +5380,13 @@ 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. subcontext.type = NULL; @@ -5396,8 +5427,7 @@ 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) { @@ -5417,8 +5447,7 @@ subcontext.may_be_abstract = false; } - if (!is_constant_expr) - this->right_->determine_type(&subcontext); + this->right_->determine_type(&subcontext); if (is_comparison) { Index: gcc/go/gofrontend/expressions.h =================================================================== --- gcc/go/gofrontend/expressions.h (revision 243728) +++ gcc/go/gofrontend/expressions.h (working copy) @@ -1633,10 +1633,11 @@ } // 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*); @@ -1755,11 +1756,11 @@ // 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