aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorIain Buclaw <ibuclaw@gdcproject.org>2019-01-20 12:55:38 +0000
committerIain Buclaw <ibuclaw@gcc.gnu.org>2019-01-20 12:55:38 +0000
commit5bdebb51a649d04569324f4f1124d5e64a3cbff7 (patch)
tree420e7c58ae557015dac5d880c91f9f924489f3aa /gcc
parent70d87497e760dca94ef78e4e936f6d461f36e80d (diff)
downloadgcc-5bdebb51a649d04569324f4f1124d5e64a3cbff7.zip
gcc-5bdebb51a649d04569324f4f1124d5e64a3cbff7.tar.gz
gcc-5bdebb51a649d04569324f4f1124d5e64a3cbff7.tar.bz2
[D] Fix identity comparison for structs with complex float fields.
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/d/ChangeLog9
-rw-r--r--gcc/d/d-codegen.cc58
-rw-r--r--gcc/d/d-tree.h1
-rw-r--r--gcc/d/expr.cc14
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gdc.dg/runnable.d20
6 files changed, 81 insertions, 25 deletions
diff --git a/gcc/d/ChangeLog b/gcc/d/ChangeLog
index f062ff8..aa3bb7f 100644
--- a/gcc/d/ChangeLog
+++ b/gcc/d/ChangeLog
@@ -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.
diff --git a/gcc/d/d-codegen.cc b/gcc/d/d-codegen.cc
index 7ca0acf..58c8257 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 6ffb0f3..0b3c5ed 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 a1f7c26..4bfdde5 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/ChangeLog b/gcc/testsuite/ChangeLog
index de3a3c4..8532240 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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.
diff --git a/gcc/testsuite/gdc.dg/runnable.d b/gcc/testsuite/gdc.dg/runnable.d
index 65c71e8..e36a258 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));
}
/******************************************/