compiler: Fix nil func panics, constant type conversions.
From-SVN: r194064
This commit is contained in:
parent
9b8a401725
commit
405c87c4d3
|
@ -2965,46 +2965,6 @@ Type_conversion_expression::do_lower(Gogo*, Named_object*,
|
||||||
{
|
{
|
||||||
if (!nc.set_type(type, true, location))
|
if (!nc.set_type(type, true, location))
|
||||||
return Expression::make_error(location);
|
return Expression::make_error(location);
|
||||||
|
|
||||||
// Don't simply convert to or from a float or complex type
|
|
||||||
// with a different size. That may change the value.
|
|
||||||
Type* vtype = val->type();
|
|
||||||
if (vtype->is_abstract())
|
|
||||||
;
|
|
||||||
else if (type->float_type() != NULL)
|
|
||||||
{
|
|
||||||
if (vtype->float_type() != NULL)
|
|
||||||
{
|
|
||||||
if (type->float_type()->bits() != vtype->float_type()->bits())
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
else if (vtype->complex_type() != NULL)
|
|
||||||
{
|
|
||||||
if (type->float_type()->bits() * 2
|
|
||||||
!= vtype->complex_type()->bits())
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (type->complex_type() != NULL)
|
|
||||||
{
|
|
||||||
if (vtype->complex_type() != NULL)
|
|
||||||
{
|
|
||||||
if (type->complex_type()->bits()
|
|
||||||
!= vtype->complex_type()->bits())
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
else if (vtype->float_type() != NULL)
|
|
||||||
{
|
|
||||||
if (type->complex_type()->bits()
|
|
||||||
!= vtype->float_type()->bits() * 2)
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (vtype->float_type() != NULL)
|
|
||||||
return this;
|
|
||||||
else if (vtype->complex_type() != NULL)
|
|
||||||
return this;
|
|
||||||
|
|
||||||
return nc.expression(location);
|
return nc.expression(location);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9239,6 +9199,9 @@ Call_expression::do_get_tree(Translate_context* context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (func == NULL)
|
||||||
|
fn = save_expr(fn);
|
||||||
|
|
||||||
tree ret = build_call_array(excess_type != NULL_TREE ? excess_type : rettype,
|
tree ret = build_call_array(excess_type != NULL_TREE ? excess_type : rettype,
|
||||||
fn, nargs, args);
|
fn, nargs, args);
|
||||||
delete[] args;
|
delete[] args;
|
||||||
|
@ -9272,6 +9235,24 @@ Call_expression::do_get_tree(Translate_context* context)
|
||||||
if (this->results_ != NULL)
|
if (this->results_ != NULL)
|
||||||
ret = this->set_results(context, ret);
|
ret = this->set_results(context, ret);
|
||||||
|
|
||||||
|
// We can't unwind the stack past a call to nil, so we need to
|
||||||
|
// insert an explicit check so that the panic can be recovered.
|
||||||
|
if (func == NULL)
|
||||||
|
{
|
||||||
|
tree compare = fold_build2_loc(location.gcc_location(), EQ_EXPR,
|
||||||
|
boolean_type_node, fn,
|
||||||
|
fold_convert_loc(location.gcc_location(),
|
||||||
|
TREE_TYPE(fn),
|
||||||
|
null_pointer_node));
|
||||||
|
tree crash = build3_loc(location.gcc_location(), COND_EXPR,
|
||||||
|
void_type_node, compare,
|
||||||
|
gogo->runtime_error(RUNTIME_ERROR_NIL_DEREFERENCE,
|
||||||
|
location),
|
||||||
|
NULL_TREE);
|
||||||
|
ret = fold_build2_loc(location.gcc_location(), COMPOUND_EXPR,
|
||||||
|
TREE_TYPE(ret), crash, ret);
|
||||||
|
}
|
||||||
|
|
||||||
this->tree_ = ret;
|
this->tree_ = ret;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -14229,7 +14210,7 @@ Numeric_constant::check_int_type(Integer_type* type, bool issue_error,
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Numeric_constant::check_float_type(Float_type* type, bool issue_error,
|
Numeric_constant::check_float_type(Float_type* type, bool issue_error,
|
||||||
Location location) const
|
Location location)
|
||||||
{
|
{
|
||||||
mpfr_t val;
|
mpfr_t val;
|
||||||
switch (this->classification_)
|
switch (this->classification_)
|
||||||
|
@ -14282,6 +14263,29 @@ Numeric_constant::check_float_type(Float_type* type, bool issue_error,
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = exp <= max_exp;
|
ret = exp <= max_exp;
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
// Round the constant to the desired type.
|
||||||
|
mpfr_t t;
|
||||||
|
mpfr_init(t);
|
||||||
|
switch (type->bits())
|
||||||
|
{
|
||||||
|
case 32:
|
||||||
|
mpfr_set_prec(t, 24);
|
||||||
|
break;
|
||||||
|
case 64:
|
||||||
|
mpfr_set_prec(t, 53);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
go_unreachable();
|
||||||
|
}
|
||||||
|
mpfr_set(t, val, GMP_RNDN);
|
||||||
|
mpfr_set(val, t, GMP_RNDN);
|
||||||
|
mpfr_clear(t);
|
||||||
|
|
||||||
|
this->set_float(type, val);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mpfr_clear(val);
|
mpfr_clear(val);
|
||||||
|
@ -14296,7 +14300,7 @@ Numeric_constant::check_float_type(Float_type* type, bool issue_error,
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Numeric_constant::check_complex_type(Complex_type* type, bool issue_error,
|
Numeric_constant::check_complex_type(Complex_type* type, bool issue_error,
|
||||||
Location location) const
|
Location location)
|
||||||
{
|
{
|
||||||
if (type->is_abstract())
|
if (type->is_abstract())
|
||||||
return true;
|
return true;
|
||||||
|
@ -14315,46 +14319,77 @@ Numeric_constant::check_complex_type(Complex_type* type, bool issue_error,
|
||||||
}
|
}
|
||||||
|
|
||||||
mpfr_t real;
|
mpfr_t real;
|
||||||
|
mpfr_t imag;
|
||||||
switch (this->classification_)
|
switch (this->classification_)
|
||||||
{
|
{
|
||||||
case NC_INT:
|
case NC_INT:
|
||||||
case NC_RUNE:
|
case NC_RUNE:
|
||||||
mpfr_init_set_z(real, this->u_.int_val, GMP_RNDN);
|
mpfr_init_set_z(real, this->u_.int_val, GMP_RNDN);
|
||||||
|
mpfr_init_set_ui(imag, 0, GMP_RNDN);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NC_FLOAT:
|
case NC_FLOAT:
|
||||||
mpfr_init_set(real, this->u_.float_val, GMP_RNDN);
|
mpfr_init_set(real, this->u_.float_val, GMP_RNDN);
|
||||||
|
mpfr_init_set_ui(imag, 0, GMP_RNDN);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NC_COMPLEX:
|
case NC_COMPLEX:
|
||||||
if (!mpfr_nan_p(this->u_.complex_val.imag)
|
|
||||||
&& !mpfr_inf_p(this->u_.complex_val.imag)
|
|
||||||
&& !mpfr_zero_p(this->u_.complex_val.imag))
|
|
||||||
{
|
|
||||||
if (mpfr_get_exp(this->u_.complex_val.imag) > max_exp)
|
|
||||||
{
|
|
||||||
if (issue_error)
|
|
||||||
error_at(location, "complex imaginary part overflow");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mpfr_init_set(real, this->u_.complex_val.real, GMP_RNDN);
|
mpfr_init_set(real, this->u_.complex_val.real, GMP_RNDN);
|
||||||
|
mpfr_init_set(imag, this->u_.complex_val.imag, GMP_RNDN);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
go_unreachable();
|
go_unreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ret;
|
bool ret = true;
|
||||||
if (mpfr_nan_p(real) || mpfr_inf_p(real) || mpfr_zero_p(real))
|
if (!mpfr_nan_p(real)
|
||||||
ret = true;
|
&& !mpfr_inf_p(real)
|
||||||
else
|
&& !mpfr_zero_p(real)
|
||||||
ret = mpfr_get_exp(real) <= max_exp;
|
&& mpfr_get_exp(real) > max_exp)
|
||||||
|
{
|
||||||
|
if (issue_error)
|
||||||
|
error_at(location, "complex real part overflow");
|
||||||
|
ret = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mpfr_nan_p(imag)
|
||||||
|
&& !mpfr_inf_p(imag)
|
||||||
|
&& !mpfr_zero_p(imag)
|
||||||
|
&& mpfr_get_exp(imag) > max_exp)
|
||||||
|
{
|
||||||
|
if (issue_error)
|
||||||
|
error_at(location, "complex imaginary part overflow");
|
||||||
|
ret = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
// Round the constant to the desired type.
|
||||||
|
mpfr_t t;
|
||||||
|
mpfr_init(t);
|
||||||
|
switch (type->bits())
|
||||||
|
{
|
||||||
|
case 64:
|
||||||
|
mpfr_set_prec(t, 24);
|
||||||
|
break;
|
||||||
|
case 128:
|
||||||
|
mpfr_set_prec(t, 53);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
go_unreachable();
|
||||||
|
}
|
||||||
|
mpfr_set(t, real, GMP_RNDN);
|
||||||
|
mpfr_set(real, t, GMP_RNDN);
|
||||||
|
mpfr_set(t, imag, GMP_RNDN);
|
||||||
|
mpfr_set(imag, t, GMP_RNDN);
|
||||||
|
mpfr_clear(t);
|
||||||
|
|
||||||
|
this->set_complex(type, real, imag);
|
||||||
|
}
|
||||||
|
|
||||||
mpfr_clear(real);
|
mpfr_clear(real);
|
||||||
|
mpfr_clear(imag);
|
||||||
if (!ret && issue_error)
|
|
||||||
error_at(location, "complex real part overflow");
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2224,10 +2224,10 @@ class Numeric_constant
|
||||||
check_int_type(Integer_type*, bool, Location) const;
|
check_int_type(Integer_type*, bool, Location) const;
|
||||||
|
|
||||||
bool
|
bool
|
||||||
check_float_type(Float_type*, bool, Location) const;
|
check_float_type(Float_type*, bool, Location);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
check_complex_type(Complex_type*, bool, Location) const;
|
check_complex_type(Complex_type*, bool, Location);
|
||||||
|
|
||||||
// The kinds of constants.
|
// The kinds of constants.
|
||||||
enum Classification
|
enum Classification
|
||||||
|
|
Loading…
Reference in New Issue