Skip to content

Commit dc230a0

Browse files
committed
d: Fix internal compiler error: Segmentation fault at gimple-expr.cc:88
Because complex types are deprecated in the language, the new way to expose native complex types is by defining an enum with a basetype of a library-defined struct that is implicitly treated as-if it is native. As casts are not implicitly added by the front-end when downcasting from enum to its underlying type, we must insert an explicit cast during the code generation pass. PR d/106623 gcc/d/ChangeLog: * d-codegen.cc (underlying_complex_expr): New function. (d_build_call): Handle passing native complex objects as the library-defined equivalent. * d-tree.h (underlying_complex_expr): Declare. * expr.cc (ExprVisitor::visit (DotVarExp *)): Call underlying_complex_expr instead of build_vconvert. gcc/testsuite/ChangeLog: * gdc.dg/torture/pr106623.d: New test. (cherry picked from commit e206fec)
1 parent 0dd5036 commit dc230a0

File tree

4 files changed

+64
-1
lines changed

4 files changed

+64
-1
lines changed

gcc/d/d-codegen.cc

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1578,6 +1578,32 @@ complex_expr (tree type, tree re, tree im)
15781578
type, re, im);
15791579
}
15801580

1581+
/* Build a two-field record TYPE representing the complex expression EXPR. */
1582+
1583+
tree
1584+
underlying_complex_expr (tree type, tree expr)
1585+
{
1586+
gcc_assert (list_length (TYPE_FIELDS (type)) == 2);
1587+
1588+
expr = d_save_expr (expr);
1589+
1590+
/* Build a constructor from the real and imaginary parts. */
1591+
if (COMPLEX_FLOAT_TYPE_P (TREE_TYPE (expr)) &&
1592+
(!INDIRECT_REF_P (expr)
1593+
|| !CONVERT_EXPR_CODE_P (TREE_CODE (TREE_OPERAND (expr, 0)))))
1594+
{
1595+
vec <constructor_elt, va_gc> *ve = NULL;
1596+
CONSTRUCTOR_APPEND_ELT (ve, TYPE_FIELDS (type),
1597+
real_part (expr));
1598+
CONSTRUCTOR_APPEND_ELT (ve, TREE_CHAIN (TYPE_FIELDS (type)),
1599+
imaginary_part (expr));
1600+
return build_constructor (type, ve);
1601+
}
1602+
1603+
/* Replace type in the reinterpret cast with a cast to the record type. */
1604+
return build_vconvert (type, expr);
1605+
}
1606+
15811607
/* Cast EXP (which should be a pointer) to TYPE* and then indirect.
15821608
The back-end requires this cast in many cases. */
15831609

@@ -2204,6 +2230,14 @@ d_build_call (TypeFunction *tf, tree callable, tree object,
22042230
build_address (targ));
22052231
}
22062232

2233+
/* Complex types are exposed as special types with an underlying
2234+
struct representation, if we are passing the native type to a
2235+
function that accepts the library-defined version, then ensure
2236+
it is properly reinterpreted as the underlying struct type. */
2237+
if (COMPLEX_FLOAT_TYPE_P (TREE_TYPE (targ))
2238+
&& arg->type->isTypeStruct ())
2239+
targ = underlying_complex_expr (build_ctype (arg->type), targ);
2240+
22072241
/* Type `noreturn` is a terminator, as no other arguments can possibly
22082242
be evaluated after it. */
22092243
if (TREE_TYPE (targ) == noreturn_type_node)

gcc/d/d-tree.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -564,6 +564,7 @@ extern tree size_mult_expr (tree, tree);
564564
extern tree real_part (tree);
565565
extern tree imaginary_part (tree);
566566
extern tree complex_expr (tree, tree, tree);
567+
extern tree underlying_complex_expr (tree, tree);
567568
extern tree indirect_ref (tree, tree);
568569
extern tree build_deref (tree);
569570
extern tree build_array_index (tree, tree);

gcc/d/expr.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1911,7 +1911,7 @@ class ExprVisitor : public Visitor
19111911
underlying is really a complex type. */
19121912
if (e->e1->type->ty == TY::Tenum
19131913
&& e->e1->type->isTypeEnum ()->sym->isSpecial ())
1914-
object = build_vconvert (build_ctype (tb), object);
1914+
object = underlying_complex_expr (build_ctype (tb), object);
19151915

19161916
this->result_ = component_ref (object, get_symbol_decl (vd));
19171917
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106623
2+
// { dg-do compile }
3+
private struct _Complex(T) { T re; T im; }
4+
enum __c_complex_double : _Complex!double;
5+
6+
pragma(inline, true)
7+
ulong hashOf()(scope const double val)
8+
{
9+
return *cast(ulong*)&val;
10+
}
11+
12+
pragma(inline, true)
13+
ulong hashOf()(scope const _Complex!double val, ulong seed = 0)
14+
{
15+
return hashOf(val.re) + hashOf(val.im);
16+
}
17+
18+
pragma(inline, true)
19+
ulong hashOf()(__c_complex_double val, ulong seed = 0)
20+
{
21+
return hashOf(cast(_Complex!double) val, seed);
22+
}
23+
24+
ulong test106623()
25+
{
26+
__c_complex_double val;
27+
return hashOf(val);
28+
}

0 commit comments

Comments
 (0)