This patch to the Go frontend checks for negative numbers with very
small magnitudes that will round to negative zero, and forces 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.  This fixes golang.org/issue/12621.
Bootstrapped and ran Go testsuite on x86_64-pc-linux-gnu.  Committed
to mainline.

Ian
Index: gcc/go/gofrontend/MERGE
===================================================================
--- gcc/go/gofrontend/MERGE     (revision 257379)
+++ gcc/go/gofrontend/MERGE     (working copy)
@@ -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.
Index: gcc/go/gofrontend/expressions.cc
===================================================================
--- gcc/go/gofrontend/expressions.cc    (revision 257379)
+++ gcc/go/gofrontend/expressions.cc    (working copy)
@@ -16158,10 +16158,16 @@ Numeric_constant::set_float(Type* type,
   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
   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.
Index: gcc/go/gofrontend/expressions.h
===================================================================
--- gcc/go/gofrontend/expressions.h     (revision 257379)
+++ gcc/go/gofrontend/expressions.h     (working copy)
@@ -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
   {

Reply via email to