From: ian Date: Mon, 3 Dec 2012 03:26:07 +0000 (+0000) Subject: compiler: Fix nil func panics, constant type conversions. X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=commitdiff_plain;h=30a15d848b166d3d7f195b32cd553e0b71015a26 compiler: Fix nil func panics, constant type conversions. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/gcc-4_7-branch@194065 138bc75d-0d04-0410-961f-82ee72b054a4 --- diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc index e20de21de90..5358a7dc987 100644 --- a/gcc/go/gofrontend/expressions.cc +++ b/gcc/go/gofrontend/expressions.cc @@ -2970,46 +2970,6 @@ Type_conversion_expression::do_lower(Gogo*, Named_object*, { if (!nc.set_type(type, true, 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); } } @@ -9235,6 +9195,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, fn, nargs, args); delete[] args; @@ -9268,6 +9231,24 @@ Call_expression::do_get_tree(Translate_context* context) if (this->results_ != NULL) 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; return ret; @@ -14119,7 +14100,7 @@ Numeric_constant::check_int_type(Integer_type* type, bool issue_error, bool Numeric_constant::check_float_type(Float_type* type, bool issue_error, - Location location) const + Location location) { mpfr_t val; switch (this->classification_) @@ -14172,6 +14153,29 @@ Numeric_constant::check_float_type(Float_type* type, bool issue_error, } 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); @@ -14186,7 +14190,7 @@ Numeric_constant::check_float_type(Float_type* type, bool issue_error, bool Numeric_constant::check_complex_type(Complex_type* type, bool issue_error, - Location location) const + Location location) { if (type->is_abstract()) return true; @@ -14205,46 +14209,77 @@ Numeric_constant::check_complex_type(Complex_type* type, bool issue_error, } mpfr_t real; + mpfr_t imag; switch (this->classification_) { case NC_INT: case NC_RUNE: mpfr_init_set_z(real, this->u_.int_val, GMP_RNDN); + mpfr_init_set_ui(imag, 0, GMP_RNDN); break; case NC_FLOAT: mpfr_init_set(real, this->u_.float_val, GMP_RNDN); + mpfr_init_set_ui(imag, 0, GMP_RNDN); break; 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(imag, this->u_.complex_val.imag, GMP_RNDN); break; default: go_unreachable(); } - bool ret; - if (mpfr_nan_p(real) || mpfr_inf_p(real) || mpfr_zero_p(real)) - ret = true; - else - ret = mpfr_get_exp(real) <= max_exp; + bool ret = true; + if (!mpfr_nan_p(real) + && !mpfr_inf_p(real) + && !mpfr_zero_p(real) + && mpfr_get_exp(real) > max_exp) + { + if (issue_error) + error_at(location, "complex real part overflow"); + ret = false; + } - mpfr_clear(real); + 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 && issue_error) - error_at(location, "complex real part overflow"); + 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(imag); return ret; } diff --git a/gcc/go/gofrontend/expressions.h b/gcc/go/gofrontend/expressions.h index eea141fe776..63769dcfa33 100644 --- a/gcc/go/gofrontend/expressions.h +++ b/gcc/go/gofrontend/expressions.h @@ -2219,10 +2219,10 @@ class Numeric_constant check_int_type(Integer_type*, bool, Location) const; bool - check_float_type(Float_type*, bool, Location) const; + check_float_type(Float_type*, bool, Location); bool - check_complex_type(Complex_type*, bool, Location) const; + check_complex_type(Complex_type*, bool, Location); // The kinds of constants. enum Classification