mirror of git://gcc.gnu.org/git/gcc.git
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
This commit is contained in:
parent
7cdb6e4c68
commit
62afb87d9c
|
|
@ -1,4 +1,4 @@
|
||||||
5eb55901861f360c2c2ff70f14a8315694934c97
|
e807c1deec1e7114bc4757b6193510fdae13e75f
|
||||||
|
|
||||||
The first line of this file holds the git revision number of the last
|
The first line of this file holds the git revision number of the last
|
||||||
merge done from the gofrontend repository.
|
merge done from the gofrontend repository.
|
||||||
|
|
|
||||||
|
|
@ -3738,8 +3738,12 @@ Unary_expression::do_lower(Gogo*, Named_object*, Statement_inserter*, int)
|
||||||
if (expr->numeric_constant_value(&nc))
|
if (expr->numeric_constant_value(&nc))
|
||||||
{
|
{
|
||||||
Numeric_constant result;
|
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);
|
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
|
// 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
|
bool
|
||||||
Unary_expression::eval_constant(Operator op, const Numeric_constant* unc,
|
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)
|
switch (op)
|
||||||
{
|
{
|
||||||
case OPERATOR_PLUS:
|
case OPERATOR_PLUS:
|
||||||
|
|
@ -4050,7 +4057,12 @@ Unary_expression::eval_constant(Operator op, const Numeric_constant* unc,
|
||||||
mpz_clear(uval);
|
mpz_clear(uval);
|
||||||
mpz_clear(val);
|
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.
|
// 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;
|
Numeric_constant unc;
|
||||||
if (!this->expr_->numeric_constant_value(&unc))
|
if (!this->expr_->numeric_constant_value(&unc))
|
||||||
return false;
|
return false;
|
||||||
|
bool issued_error;
|
||||||
return Unary_expression::eval_constant(this->op_, &unc, this->location(),
|
return Unary_expression::eval_constant(this->op_, &unc, this->location(),
|
||||||
nc);
|
nc, &issued_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the type of a unary expression.
|
// 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
|
// 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
|
// 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
|
bool
|
||||||
Binary_expression::eval_constant(Operator op, Numeric_constant* left_nc,
|
Binary_expression::eval_constant(Operator op, Numeric_constant* left_nc,
|
||||||
Numeric_constant* right_nc,
|
Numeric_constant* right_nc,
|
||||||
Location location, Numeric_constant* nc)
|
Location location, Numeric_constant* nc,
|
||||||
|
bool* issued_error)
|
||||||
{
|
{
|
||||||
|
*issued_error = false;
|
||||||
switch (op)
|
switch (op)
|
||||||
{
|
{
|
||||||
case OPERATOR_OROR:
|
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);
|
r = Binary_expression::eval_integer(op, left_nc, right_nc, location, nc);
|
||||||
|
|
||||||
if (r)
|
if (r)
|
||||||
r = nc->set_type(type, true, location);
|
{
|
||||||
|
r = nc->set_type(type, true, location);
|
||||||
|
if (!r)
|
||||||
|
*issued_error = true;
|
||||||
|
}
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
@ -5115,9 +5134,15 @@ Binary_expression::do_lower(Gogo* gogo, Named_object*,
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Numeric_constant nc;
|
Numeric_constant nc;
|
||||||
|
bool issued_error;
|
||||||
if (!Binary_expression::eval_constant(op, &left_nc, &right_nc,
|
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 this;
|
||||||
|
}
|
||||||
return nc.expression(location);
|
return nc.expression(location);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -5458,8 +5483,9 @@ Binary_expression::do_numeric_constant_value(Numeric_constant* nc) const
|
||||||
Numeric_constant right_nc;
|
Numeric_constant right_nc;
|
||||||
if (!this->right_->numeric_constant_value(&right_nc))
|
if (!this->right_->numeric_constant_value(&right_nc))
|
||||||
return false;
|
return false;
|
||||||
|
bool issued_error;
|
||||||
return Binary_expression::eval_constant(this->op_, &left_nc, &right_nc,
|
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.
|
// Note that the value is being discarded.
|
||||||
|
|
@ -5558,7 +5584,12 @@ Binary_expression::do_determine_type(const Type_context* context)
|
||||||
|
|
||||||
Type_context subcontext(*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
|
// In a comparison, the context does not determine the types of
|
||||||
// the operands.
|
// the operands.
|
||||||
|
|
@ -5600,8 +5631,7 @@ Binary_expression::do_determine_type(const Type_context* context)
|
||||||
subcontext.type = subcontext.type->make_non_abstract_type();
|
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)
|
if (is_shift_op)
|
||||||
{
|
{
|
||||||
|
|
@ -5621,8 +5651,7 @@ Binary_expression::do_determine_type(const Type_context* context)
|
||||||
subcontext.may_be_abstract = false;
|
subcontext.may_be_abstract = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_constant_expr)
|
this->right_->determine_type(&subcontext);
|
||||||
this->right_->determine_type(&subcontext);
|
|
||||||
|
|
||||||
if (is_comparison)
|
if (is_comparison)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1775,10 +1775,11 @@ class Unary_expression : public Expression
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply unary opcode OP to UNC, setting NC. Return true if this
|
// 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
|
static bool
|
||||||
eval_constant(Operator op, const Numeric_constant* unc,
|
eval_constant(Operator op, const Numeric_constant* unc,
|
||||||
Location, Numeric_constant* nc);
|
Location, Numeric_constant* nc, bool *issued_error);
|
||||||
|
|
||||||
static Expression*
|
static Expression*
|
||||||
do_import(Import*);
|
do_import(Import*);
|
||||||
|
|
@ -1893,11 +1894,11 @@ class Binary_expression : public Expression
|
||||||
|
|
||||||
// Apply binary opcode OP to LEFT_NC and RIGHT_NC, setting 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
|
// 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
|
static bool
|
||||||
eval_constant(Operator op, Numeric_constant* left_nc,
|
eval_constant(Operator op, Numeric_constant* left_nc,
|
||||||
Numeric_constant* right_nc, Location location,
|
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
|
// Compare constants LEFT_NC and RIGHT_NC according to OP, setting
|
||||||
// *RESULT. Return true if this could be done, false if not. Issue
|
// *RESULT. Return true if this could be done, false if not. Issue
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue