Commit db3015e9 by Ian Lance Taylor

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
parent ce8bdcef
a63e173b20baa1a48470dd31a1fb1f2704b37011 3f8feb4f905535448833a14e4f5c83f682087749
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.
...@@ -4567,6 +4567,7 @@ Binary_expression::eval_integer(Operator op, const Numeric_constant* left_nc, ...@@ -4567,6 +4567,7 @@ Binary_expression::eval_integer(Operator op, const Numeric_constant* left_nc,
if (mpz_sizeinbase(val, 2) > 0x100000) if (mpz_sizeinbase(val, 2) > 0x100000)
{ {
error_at(location, "constant addition overflow"); error_at(location, "constant addition overflow");
nc->set_invalid();
mpz_set_ui(val, 1); mpz_set_ui(val, 1);
} }
break; break;
...@@ -4575,6 +4576,7 @@ Binary_expression::eval_integer(Operator op, const Numeric_constant* left_nc, ...@@ -4575,6 +4576,7 @@ Binary_expression::eval_integer(Operator op, const Numeric_constant* left_nc,
if (mpz_sizeinbase(val, 2) > 0x100000) if (mpz_sizeinbase(val, 2) > 0x100000)
{ {
error_at(location, "constant subtraction overflow"); error_at(location, "constant subtraction overflow");
nc->set_invalid();
mpz_set_ui(val, 1); mpz_set_ui(val, 1);
} }
break; break;
...@@ -4589,6 +4591,7 @@ Binary_expression::eval_integer(Operator op, const Numeric_constant* left_nc, ...@@ -4589,6 +4591,7 @@ Binary_expression::eval_integer(Operator op, const Numeric_constant* left_nc,
if (mpz_sizeinbase(val, 2) > 0x100000) if (mpz_sizeinbase(val, 2) > 0x100000)
{ {
error_at(location, "constant multiplication overflow"); error_at(location, "constant multiplication overflow");
nc->set_invalid();
mpz_set_ui(val, 1); mpz_set_ui(val, 1);
} }
break; break;
...@@ -4598,6 +4601,7 @@ Binary_expression::eval_integer(Operator op, const Numeric_constant* left_nc, ...@@ -4598,6 +4601,7 @@ Binary_expression::eval_integer(Operator op, const Numeric_constant* left_nc,
else else
{ {
error_at(location, "division by zero"); error_at(location, "division by zero");
nc->set_invalid();
mpz_set_ui(val, 0); mpz_set_ui(val, 0);
} }
break; break;
...@@ -4607,6 +4611,7 @@ Binary_expression::eval_integer(Operator op, const Numeric_constant* left_nc, ...@@ -4607,6 +4611,7 @@ Binary_expression::eval_integer(Operator op, const Numeric_constant* left_nc,
else else
{ {
error_at(location, "division by zero"); error_at(location, "division by zero");
nc->set_invalid();
mpz_set_ui(val, 0); mpz_set_ui(val, 0);
} }
break; break;
...@@ -4618,6 +4623,7 @@ Binary_expression::eval_integer(Operator op, const Numeric_constant* left_nc, ...@@ -4618,6 +4623,7 @@ Binary_expression::eval_integer(Operator op, const Numeric_constant* left_nc,
else else
{ {
error_at(location, "shift count overflow"); error_at(location, "shift count overflow");
nc->set_invalid();
mpz_set_ui(val, 1); mpz_set_ui(val, 1);
} }
break; break;
...@@ -4629,6 +4635,7 @@ Binary_expression::eval_integer(Operator op, const Numeric_constant* left_nc, ...@@ -4629,6 +4635,7 @@ Binary_expression::eval_integer(Operator op, const Numeric_constant* left_nc,
if (mpz_cmp_ui(right_val, shift) != 0) if (mpz_cmp_ui(right_val, shift) != 0)
{ {
error_at(location, "shift count overflow"); error_at(location, "shift count overflow");
nc->set_invalid();
mpz_set_ui(val, 1); mpz_set_ui(val, 1);
} }
else else
...@@ -4723,6 +4730,7 @@ Binary_expression::eval_float(Operator op, const Numeric_constant* left_nc, ...@@ -4723,6 +4730,7 @@ Binary_expression::eval_float(Operator op, const Numeric_constant* left_nc,
else else
{ {
error_at(location, "division by zero"); error_at(location, "division by zero");
nc->set_invalid();
mpfr_set_ui(val, 0, GMP_RNDN); mpfr_set_ui(val, 0, GMP_RNDN);
} }
break; break;
...@@ -4787,6 +4795,7 @@ Binary_expression::eval_complex(Operator op, const Numeric_constant* left_nc, ...@@ -4787,6 +4795,7 @@ Binary_expression::eval_complex(Operator op, const Numeric_constant* left_nc,
if (mpc_cmp_si(right_val, 0) == 0) if (mpc_cmp_si(right_val, 0) == 0)
{ {
error_at(location, "division by zero"); error_at(location, "division by zero");
nc->set_invalid();
mpc_set_ui(val, 0, MPC_RNDNN); mpc_set_ui(val, 0, MPC_RNDNN);
break; break;
} }
...@@ -4849,7 +4858,14 @@ Binary_expression::do_lower(Gogo* gogo, Named_object*, ...@@ -4849,7 +4858,14 @@ Binary_expression::do_lower(Gogo* gogo, Named_object*,
Numeric_constant nc; Numeric_constant nc;
if (!Binary_expression::eval_constant(op, &left_nc, &right_nc, if (!Binary_expression::eval_constant(op, &left_nc, &right_nc,
location, &nc)) location, &nc))
return this; {
if (nc.is_invalid())
{
go_assert(saw_errors());
return Expression::make_error(location);
}
return this;
}
return nc.expression(location); return nc.expression(location);
} }
} }
...@@ -15189,7 +15205,7 @@ Numeric_constant::set_type(Type* type, bool issue_error, Location loc) ...@@ -15189,7 +15205,7 @@ Numeric_constant::set_type(Type* type, bool issue_error, Location loc)
bool bool
Numeric_constant::check_int_type(Integer_type* type, bool issue_error, Numeric_constant::check_int_type(Integer_type* type, bool issue_error,
Location location) const Location location)
{ {
mpz_t val; mpz_t val;
switch (this->classification_) switch (this->classification_)
...@@ -15203,7 +15219,11 @@ Numeric_constant::check_int_type(Integer_type* type, bool issue_error, ...@@ -15203,7 +15219,11 @@ Numeric_constant::check_int_type(Integer_type* type, bool issue_error,
if (!mpfr_integer_p(this->u_.float_val)) if (!mpfr_integer_p(this->u_.float_val))
{ {
if (issue_error) 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; return false;
} }
mpz_init(val); mpz_init(val);
...@@ -15215,7 +15235,10 @@ Numeric_constant::check_int_type(Integer_type* type, bool issue_error, ...@@ -15215,7 +15235,10 @@ Numeric_constant::check_int_type(Integer_type* type, bool issue_error,
|| !mpfr_zero_p(mpc_imagref(this->u_.complex_val))) || !mpfr_zero_p(mpc_imagref(this->u_.complex_val)))
{ {
if (issue_error) if (issue_error)
error_at(location, "complex constant truncated to integer"); {
error_at(location, "complex constant truncated to integer");
this->set_invalid();
}
return false; return false;
} }
mpz_init(val); mpz_init(val);
...@@ -15253,7 +15276,10 @@ Numeric_constant::check_int_type(Integer_type* type, bool issue_error, ...@@ -15253,7 +15276,10 @@ Numeric_constant::check_int_type(Integer_type* type, bool issue_error,
} }
if (!ret && issue_error) if (!ret && issue_error)
error_at(location, "integer constant overflow"); {
error_at(location, "integer constant overflow");
this->set_invalid();
}
return ret; return ret;
} }
...@@ -15281,7 +15307,10 @@ Numeric_constant::check_float_type(Float_type* type, bool issue_error, ...@@ -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 (!mpfr_zero_p(mpc_imagref(this->u_.complex_val)))
{ {
if (issue_error) if (issue_error)
error_at(location, "complex constant truncated to float"); {
this->set_invalid();
error_at(location, "complex constant truncated to float");
}
return false; return false;
} }
mpfr_init_set(val, mpc_realref(this->u_.complex_val), GMP_RNDN); 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, ...@@ -15344,7 +15373,10 @@ Numeric_constant::check_float_type(Float_type* type, bool issue_error,
mpfr_clear(val); mpfr_clear(val);
if (!ret && issue_error) if (!ret && issue_error)
error_at(location, "floating point constant overflow"); {
error_at(location, "floating point constant overflow");
this->set_invalid();
}
return ret; return ret;
} }
...@@ -15399,7 +15431,10 @@ Numeric_constant::check_complex_type(Complex_type* type, bool issue_error, ...@@ -15399,7 +15431,10 @@ Numeric_constant::check_complex_type(Complex_type* type, bool issue_error,
&& mpfr_get_exp(mpc_realref(val)) > max_exp) && mpfr_get_exp(mpc_realref(val)) > max_exp)
{ {
if (issue_error) if (issue_error)
error_at(location, "complex real part overflow"); {
error_at(location, "complex real part overflow");
this->set_invalid();
}
ret = false; ret = false;
} }
...@@ -15409,7 +15444,10 @@ Numeric_constant::check_complex_type(Complex_type* type, bool issue_error, ...@@ -15409,7 +15444,10 @@ Numeric_constant::check_complex_type(Complex_type* type, bool issue_error,
&& mpfr_get_exp(mpc_imagref(val)) > max_exp) && mpfr_get_exp(mpc_imagref(val)) > max_exp)
{ {
if (issue_error) if (issue_error)
error_at(location, "complex imaginary part overflow"); {
error_at(location, "complex imaginary part overflow");
this->set_invalid();
}
ret = false; ret = false;
} }
...@@ -15455,6 +15493,9 @@ Numeric_constant::expression(Location loc) const ...@@ -15455,6 +15493,9 @@ Numeric_constant::expression(Location loc) const
return Expression::make_float(&this->u_.float_val, this->type_, loc); return Expression::make_float(&this->u_.float_val, this->type_, loc);
case NC_COMPLEX: case NC_COMPLEX:
return Expression::make_complex(&this->u_.complex_val, this->type_, loc); return Expression::make_complex(&this->u_.complex_val, this->type_, loc);
case NC_INVALID:
go_assert(saw_errors());
return Expression::make_error(loc);
default: default:
go_unreachable(); go_unreachable();
} }
......
...@@ -3460,6 +3460,11 @@ class Numeric_constant ...@@ -3460,6 +3460,11 @@ class Numeric_constant
void void
set_complex(Type*, const mpc_t); set_complex(Type*, const mpc_t);
// Mark numeric constant as invalid.
void
set_invalid()
{ this->classification_ = NC_INVALID; }
// Classifiers. // Classifiers.
bool bool
is_int() const is_int() const
...@@ -3477,6 +3482,10 @@ class Numeric_constant ...@@ -3477,6 +3482,10 @@ class Numeric_constant
is_complex() const is_complex() const
{ return this->classification_ == Numeric_constant::NC_COMPLEX; } { 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 // Value retrievers. These will initialize the values as well as
// set them. GET_INT is only valid if IS_INT returns true, and // set them. GET_INT is only valid if IS_INT returns true, and
// likewise respectively. // likewise respectively.
...@@ -3554,7 +3563,7 @@ class Numeric_constant ...@@ -3554,7 +3563,7 @@ class Numeric_constant
mpfr_to_unsigned_long(const mpfr_t fval, unsigned long *val) const; mpfr_to_unsigned_long(const mpfr_t fval, unsigned long *val) const;
bool bool
check_int_type(Integer_type*, bool, Location) const; check_int_type(Integer_type*, bool, Location);
bool bool
check_float_type(Float_type*, bool, Location); check_float_type(Float_type*, bool, Location);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment