From 62afb87d9c466ab33767fad6d74133a4ad925f52 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Thu, 15 Dec 2016 22:47:43 +0000 Subject: [PATCH] re PR go/78763 (go1: internal compiler error: in do_get_backend, at go/gofrontend/expressions.cc:8352) 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 | 2 +- gcc/go/gofrontend/expressions.cc | 59 ++++++++++++++++++++++++-------- gcc/go/gofrontend/expressions.h | 9 ++--- 3 files changed, 50 insertions(+), 20 deletions(-) diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index 1303ad5412a..4a5f6d295dd 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -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. diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc index a9337bda6b1..2022c4749b3 100644 --- a/gcc/go/gofrontend/expressions.cc +++ b/gcc/go/gofrontend/expressions.cc @@ -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) { diff --git a/gcc/go/gofrontend/expressions.h b/gcc/go/gofrontend/expressions.h index 98e21151cc6..e088100e056 100644 --- a/gcc/go/gofrontend/expressions.h +++ b/gcc/go/gofrontend/expressions.h @@ -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 -- 2.30.2