compiler: Mark erroneous constants as invalid.
When the compiler failed to evaluate a numeric constant because because it was erroneous, there was no way for parent nodes to discover the error and lower themselves into error nodes. This patch now uses the NC_INVALID enumerator to mark numeric constants with a known, reported error. Fixes golang/go#11541. Reviewed-on: https://go-review.googlesource.com/13904 From-SVN: r227420
This commit is contained in:
parent
ce8bdcefc5
commit
db3015e9e3
3 changed files with 61 additions and 11 deletions
|
@ -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.
|
||||
|
|
|
@ -4567,6 +4567,7 @@ Binary_expression::eval_integer(Operator op, const Numeric_constant* left_nc,
|
|||
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 op, const Numeric_constant* left_nc,
|
|||
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 op, const Numeric_constant* left_nc,
|
|||
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 op, const Numeric_constant* left_nc,
|
|||
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 op, const Numeric_constant* left_nc,
|
|||
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 op, const Numeric_constant* left_nc,
|
|||
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 op, const Numeric_constant* left_nc,
|
|||
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 op, const Numeric_constant* left_nc,
|
|||
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 op, const Numeric_constant* left_nc,
|
|||
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, Named_object*,
|
|||
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, bool issue_error, Location loc)
|
|||
|
||||
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_type* type, bool issue_error,
|
|||
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_type* type, bool issue_error,
|
|||
|| !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_type* type, bool issue_error,
|
|||
}
|
||||
|
||||
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_type* type, bool issue_error,
|
|||
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_type* type, bool issue_error,
|
|||
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(Complex_type* type, bool issue_error,
|
|||
&& 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(Complex_type* type, bool issue_error,
|
|||
&& 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 loc) const
|
|||
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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Reference in a new issue