aboutsummaryrefslogtreecommitdiff
path: root/gcc/go
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@google.com>2012-12-03 03:25:18 +0000
committerIan Lance Taylor <iant@google.com>2012-12-03 03:25:18 +0000
commita5ca8a3201f8c03c48e85c068ed4e5431381a4ce (patch)
tree4f1a38beb547fc41b31fa8d28e24b825fdc69ad6 /gcc/go
parent2774b986d01f2e4adf371266be98d016815625f1 (diff)
compiler: Fix nil func panics, constant type conversions.
git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@194064 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/go')
-rw-r--r--gcc/go/gofrontend/expressions.cc157
-rw-r--r--gcc/go/gofrontend/expressions.h4
2 files changed, 98 insertions, 63 deletions
diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc
index 571aa024457..5fee25650b0 100644
--- a/gcc/go/gofrontend/expressions.cc
+++ b/gcc/go/gofrontend/expressions.cc
@@ -2965,46 +2965,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);
}
}
@@ -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,
fn, nargs, args);
delete[] args;
@@ -9272,6 +9235,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;
@@ -14229,7 +14210,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_)
@@ -14282,6 +14263,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);
@@ -14296,7 +14300,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;
@@ -14315,46 +14319,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 7bc42424bc1..eb4406dc9eb 100644
--- a/gcc/go/gofrontend/expressions.h
+++ b/gcc/go/gofrontend/expressions.h
@@ -2224,10 +2224,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