[D] Fix identity comparison for structs with complex float fields.
authorIain Buclaw <ibuclaw@gdcproject.org>
Sun, 20 Jan 2019 12:55:38 +0000 (12:55 +0000)
committerIain Buclaw <ibuclaw@gcc.gnu.org>
Sun, 20 Jan 2019 12:55:38 +0000 (12:55 +0000)
gcc/d/ChangeLog:

2019-01-20  Iain Buclaw  <ibuclaw@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  <ibuclaw@gdcproject.org>

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

From-SVN: r268104

gcc/d/ChangeLog
gcc/d/d-codegen.cc
gcc/d/d-tree.h
gcc/d/expr.cc
gcc/testsuite/ChangeLog
gcc/testsuite/gdc.dg/runnable.d

index f062ff8f24fc2bafe59d1bc6242efb90a777150f..aa3bb7f90417ff5b4161f179932f05c8f4941fa1 100644 (file)
@@ -1,3 +1,12 @@
+2019-01-20  Iain Buclaw  <ibuclaw@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.
+
 2019-01-20  Johannes Pfau  <johannespfau@gmail.com>
 
        * expr.cc (build_float_identity): New function.
index 7ca0acffcc417bcc61694f0e1df6eba0e1f5d628..58c8257c63c508725d24e90dd961f74c0e64db2f 100644 (file)
@@ -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)  */
index 6ffb0f32a1f77c9094588c2b0ac0e2ea2283778a..0b3c5eddedd6e2ded70a95e9f70c2633116185d0 100644 (file)
@@ -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 *,
index a1f7c262dc8f2a93557a9b2a30d66ebaac3606a4..4bfdde5a29ab22246223c61d7e813529272ea207 100644 (file)
@@ -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
index de3a3c428d220b4a14b9eaf6f0a80fc4388765aa..853224023fd1711326502294c411ea5c9a62df5e 100644 (file)
@@ -1,3 +1,7 @@
+2019-01-20  Iain Buclaw  <ibuclaw@gdcproject.org>
+
+       * gdc.dg/runnable.d: Add more tests for comparing complex types.
+
 2019-01-20  Johannes Pfau  <johannespfau@gmail.com>
 
        * gdc.dg/runnable.d: Add tests for comparing complex types.
index 65c71e86292cb632c9a0eb91f944c4237d7d4133..e36a25850270738f6ee189c294d24c52c1b5d1a5 100644 (file)
@@ -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));
 }
 
 /******************************************/