aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2018-02-05 15:28:59 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2018-02-05 15:28:59 +0000
commit354bbdb6bac8630e8f3e14d85ce9451eca8cf2a8 (patch)
treeb35c958fa28f08c28032e35dd056af7d988acc37
parent5f25b464a8e3935b9b1bd47e6b652e79d4824102 (diff)
downloadgcc-354bbdb6bac8630e8f3e14d85ce9451eca8cf2a8.zip
gcc-354bbdb6bac8630e8f3e14d85ce9451eca8cf2a8.tar.gz
gcc-354bbdb6bac8630e8f3e14d85ce9451eca8cf2a8.tar.bz2
compiler: avoid negative zero in float constants
Check for negative numbers with very small magnitudes that will round to negative zero, and force them to positive zero instead. This implements the spec clarification in https://golang.org/cl/14727. The test is in https://golang.org/cl/91895. Fixes golang/go#12621 Reviewed-on: https://go-review.googlesource.com/91915 From-SVN: r257390
-rw-r--r--gcc/go/gofrontend/MERGE2
-rw-r--r--gcc/go/gofrontend/expressions.cc52
-rw-r--r--gcc/go/gofrontend/expressions.h3
3 files changed, 54 insertions, 3 deletions
diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE
index 3588a8a..545b40f 100644
--- a/gcc/go/gofrontend/MERGE
+++ b/gcc/go/gofrontend/MERGE
@@ -1,4 +1,4 @@
-36594b69b94326014c331fe50a5a345ef4f8de16
+7eebd495df915ab87926b8dd88f554674cfdacea
The first line of this file holds the git revision number of the last
merge done from the gofrontend repository.
diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc
index 8555c05..03f8c68 100644
--- a/gcc/go/gofrontend/expressions.cc
+++ b/gcc/go/gofrontend/expressions.cc
@@ -16158,10 +16158,16 @@ Numeric_constant::set_float(Type* type, const mpfr_t val)
this->clear();
this->classification_ = NC_FLOAT;
this->type_ = type;
+
// Numeric constants do not have negative zero values, so remove
// them here. They also don't have infinity or NaN values, but we
// should never see them here.
- if (mpfr_zero_p(val))
+ int bits = 0;
+ if (type != NULL
+ && type->float_type() != NULL
+ && !type->float_type()->is_abstract())
+ bits = type->float_type()->bits();
+ if (Numeric_constant::is_float_zero(val, bits))
mpfr_init_set_ui(this->u_.float_val, 0, GMP_RNDN);
else
mpfr_init_set(this->u_.float_val, val, GMP_RNDN);
@@ -16175,8 +16181,50 @@ Numeric_constant::set_complex(Type* type, const mpc_t val)
this->clear();
this->classification_ = NC_COMPLEX;
this->type_ = type;
+
+ // Avoid negative zero as in set_float.
+ int bits = 0;
+ if (type != NULL
+ && type->complex_type() != NULL
+ && !type->complex_type()->is_abstract())
+ bits = type->complex_type()->bits() / 2;
+
+ mpfr_t real;
+ mpfr_init_set(real, mpc_realref(val), GMP_RNDN);
+ if (Numeric_constant::is_float_zero(real, bits))
+ mpfr_set_ui(real, 0, GMP_RNDN);
+
+ mpfr_t imag;
+ mpfr_init_set(imag, mpc_imagref(val), GMP_RNDN);
+ if (Numeric_constant::is_float_zero(imag, bits))
+ mpfr_set_ui(imag, 0, GMP_RNDN);
+
mpc_init2(this->u_.complex_val, mpc_precision);
- mpc_set(this->u_.complex_val, val, MPC_RNDNN);
+ mpc_set_fr_fr(this->u_.complex_val, real, imag, MPC_RNDNN);
+
+ mpfr_clear(real);
+ mpfr_clear(imag);
+}
+
+// Return whether VAL, at a precision of BITS, is zero. BITS may be
+// zero in which case it is ignored.
+
+bool
+Numeric_constant::is_float_zero(const mpfr_t val, int bits)
+{
+ if (mpfr_zero_p(val))
+ return true;
+ switch (bits)
+ {
+ case 0:
+ return false;
+ case 32:
+ return mpfr_get_flt(val, GMP_RNDN) == 0;
+ case 64:
+ return mpfr_get_d(val, GMP_RNDN) == 0;
+ default:
+ go_unreachable();
+ }
}
// Get an int value.
diff --git a/gcc/go/gofrontend/expressions.h b/gcc/go/gofrontend/expressions.h
index d16a284..3acaeb2 100644
--- a/gcc/go/gofrontend/expressions.h
+++ b/gcc/go/gofrontend/expressions.h
@@ -4220,6 +4220,9 @@ class Numeric_constant
bool
check_complex_type(Complex_type*, bool, Location);
+ static bool
+ is_float_zero(const mpfr_t, int bits);
+
// The kinds of constants.
enum Classification
{