On Mon, 17 Dec 2018 at 23:05, Iain Buclaw <ibuc...@gdcproject.org> wrote:
>
> On Wed, 28 Nov 2018 at 23:46, Iain Buclaw <ibuc...@gdcproject.org> wrote:
> >
> > On Wed, 28 Nov 2018 at 22:32, Johannes Pfau <johannesp...@gmail.com> wrote:
> > >
> > > Next version, addresses the review comments.
> > >
> > > Tested at https://github.com/D-Programming-GDC/GDC/pull/768
> > > ---
> > > gcc/d/ChangeLog:
> > >
> > > 2018-11-28  Johannes Pfau  <johannesp...@gmail.com>
> > >
> > >         * expr.cc (ExprVisitor::visit(IdentityExp)): Add support for 
> > > complex types.
> > >         (build_float_identity): New function.
> > >
> > > gcc/testsuite/ChangeLog:
> > >
> > > 2018-11-28  Johannes Pfau  <johannesp...@gmail.com>
> > >
> > >         * gdc.dg/runnable.d: Test IdentityExp for complex types.
> > >
> > >
> > >  gcc/d/expr.cc                   | 40 ++++++++++++++++++++++++---------
> > >  gcc/testsuite/gdc.dg/runnable.d | 22 ++++++++++++++++++
> > >  2 files changed, 51 insertions(+), 11 deletions(-)
> > >
> >
> > As I've said before, looks reasonable to me.  Thanks.
> >
>
> I'll send a supplementary patch, and commit both together.
>

Committed to trunk along with patch that handles creal fields.

Bootstrapped and regression tested on x86_64-linux-gnu.

-- 
Iain
---
gcc/d/ChangeLog:

2019-01-20  Iain Buclaw  <ibuc...@gdcproject.org>

    * d-codegen.cc (identity_compare_p): Return false if seen built-in
    type with padding.
    (build_float_identity): Moved here from expr.cc.
    (lower_struct_comparison): Handle real and complex types.
    * d-tree.h (build_float_identity): New.
    * expr.cc (build_float_identity): Move to d-codegen.cc.

gcc/testsuite/ChangeLog:

2019-01-20  Iain Buclaw  <ibuc...@gdcproject.org>

    * gdc.dg/runnable.d: Add more tests for comparing complex types.

---
diff --git a/gcc/d/d-codegen.cc b/gcc/d/d-codegen.cc
index 7ca0acffcc4..58c8257c63c 100644
--- a/gcc/d/d-codegen.cc
+++ b/gcc/d/d-codegen.cc
@@ -798,15 +798,21 @@ identity_compare_p (StructDeclaration *sd)
   for (size_t i = 0; i < sd->fields.dim; i++)
     {
       VarDeclaration *vd = sd->fields[i];
+      Type *tb = vd->type->toBasetype ();
 
       /* Check inner data structures.  */
-      if (vd->type->ty == Tstruct)
+      if (tb->ty == Tstruct)
 	{
-	  TypeStruct *ts = (TypeStruct *) vd->type;
+	  TypeStruct *ts = (TypeStruct *) tb;
 	  if (!identity_compare_p (ts->sym))
 	    return false;
 	}
 
+      /* Check for types that may have padding.  */
+      if ((tb->ty == Tcomplex80 || tb->ty == Tfloat80 || tb->ty == Timaginary80)
+	  && Target::realpad != 0)
+	return false;
+
       if (offset <= vd->offset)
 	{
 	  /* There's a hole in the struct.  */
@@ -824,6 +830,20 @@ identity_compare_p (StructDeclaration *sd)
   return true;
 }
 
+/* Build a floating-point identity comparison between T1 and T2, ignoring any
+   excessive padding in the type.  CODE is EQ_EXPR or NE_EXPR comparison.  */
+
+tree
+build_float_identity (tree_code code, tree t1, tree t2)
+{
+  tree tmemcmp = builtin_decl_explicit (BUILT_IN_MEMCMP);
+  tree size = size_int (TYPE_PRECISION (TREE_TYPE (t1)) / BITS_PER_UNIT);
+
+  tree result = build_call_expr (tmemcmp, 3, build_address (t1),
+				 build_address (t2), size);
+  return build_boolop (code, result, integer_zero_node);
+}
+
 /* Lower a field-by-field equality expression between T1 and T2 of type SD.
    CODE is the EQ_EXPR or NE_EXPR comparison.  */
 
@@ -859,29 +879,45 @@ lower_struct_comparison (tree_code code, StructDeclaration *sd,
   for (size_t i = 0; i < sd->fields.dim; i++)
     {
       VarDeclaration *vd = sd->fields[i];
+      Type *type = vd->type->toBasetype ();
       tree sfield = get_symbol_decl (vd);
 
       tree t1ref = component_ref (t1, sfield);
       tree t2ref = component_ref (t2, sfield);
       tree tcmp;
 
-      if (vd->type->ty == Tstruct)
+      if (type->ty == Tstruct)
 	{
 	  /* Compare inner data structures.  */
-	  StructDeclaration *decl = ((TypeStruct *) vd->type)->sym;
+	  StructDeclaration *decl = ((TypeStruct *) type)->sym;
 	  tcmp = lower_struct_comparison (code, decl, t1ref, t2ref);
 	}
+      else if (type->ty != Tvector && type->isintegral ())
+	{
+	  /* Integer comparison, no special handling required.  */
+	  tcmp = build_boolop (code, t1ref, t2ref);
+	}
+      else if (type->ty != Tvector && type->isfloating ())
+	{
+	  /* Floating-point comparison, don't compare padding in type.  */
+	  if (!type->iscomplex ())
+	    tcmp = build_float_identity (code, t1ref, t2ref);
+	  else
+	    {
+	      tree req = build_float_identity (code, real_part (t1ref),
+					       real_part (t2ref));
+	      tree ieq = build_float_identity (code, imaginary_part (t1ref),
+					       imaginary_part (t2ref));
+
+	      tcmp = build_boolop (tcode, req, ieq);
+	    }
+	}
       else
 	{
-	  tree stype = build_ctype (vd->type);
+	  tree stype = build_ctype (type);
 	  opt_scalar_int_mode mode = int_mode_for_mode (TYPE_MODE (stype));
 
-	  if (vd->type->ty != Tvector && vd->type->isintegral ())
-	    {
-	      /* Integer comparison, no special handling required.  */
-	      tcmp = build_boolop (code, t1ref, t2ref);
-	    }
-	  else if (mode.exists ())
+	  if (mode.exists ())
 	    {
 	      /* Compare field bits as their corresponding integer type.
 		    *((T*) &t1) == *((T*) &t2)  */
diff --git a/gcc/d/d-tree.h b/gcc/d/d-tree.h
index 6ffb0f32a1f..0b3c5eddedd 100644
--- a/gcc/d/d-tree.h
+++ b/gcc/d/d-tree.h
@@ -522,6 +522,7 @@ extern tree d_mark_addressable (tree);
 extern tree d_mark_used (tree);
 extern tree d_mark_read (tree);
 extern bool identity_compare_p (StructDeclaration *);
+extern tree build_float_identity (tree_code, tree, tree);
 extern tree build_struct_comparison (tree_code, StructDeclaration *,
 				     tree, tree);
 extern tree build_array_struct_comparison (tree_code, StructDeclaration *,
diff --git a/gcc/d/expr.cc b/gcc/d/expr.cc
index a1f7c262dc8..4bfdde5a29a 100644
--- a/gcc/d/expr.cc
+++ b/gcc/d/expr.cc
@@ -43,20 +43,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "d-tree.h"
 
 
-/* Build a floating-point identity comparison between T1 and T2, ignoring any
-   excessive padding in the type.  CODE is EQ_EXPR or NE_EXPR comparison.  */
-
-static tree
-build_float_identity (tree_code code, tree t1, tree t2)
-{
-  tree tmemcmp = builtin_decl_explicit (BUILT_IN_MEMCMP);
-  tree size = size_int (TYPE_PRECISION (TREE_TYPE (t1)) / BITS_PER_UNIT);
-
-  tree result = build_call_expr (tmemcmp, 3, build_address (t1),
-				 build_address (t2), size);
-  return build_boolop (code, result, integer_zero_node);
-}
-
 /* Implements the visitor interface to build the GCC trees of all Expression
    AST classes emitted from the D Front-end.
    All visit methods accept one parameter E, which holds the frontend AST
diff --git a/gcc/testsuite/gdc.dg/runnable.d b/gcc/testsuite/gdc.dg/runnable.d
index 65c71e86292..e36a2585027 100644
--- a/gcc/testsuite/gdc.dg/runnable.d
+++ b/gcc/testsuite/gdc.dg/runnable.d
@@ -1553,6 +1553,26 @@ void test309()
     assert(!(f1 is f3));
     assert(!(f2 is f3));
     assert(!(f1 !is f4));
+
+    struct CReal
+    {
+        creal value;
+    }
+
+    CReal s1 = CReal(+0.0 + 0.0i);
+    CReal s2 = CReal(+0.0 - 0.0i);
+    CReal s3 = CReal(-0.0 + 0.0i);
+    CReal s4 = CReal(+0.0 + 0.0i);
+
+    assert(s1 !is s2);
+    assert(s1 !is s3);
+    assert(s2 !is s3);
+    assert(s1 is s4);
+
+    assert(!(s1 is s2));
+    assert(!(s1 is s3));
+    assert(!(s2 is s3));
+    assert(!(s1 !is s4));
 }
 
 /******************************************/

Reply via email to