From e206fecaac29f559f4990312b875604eb1ce3ef3 Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Mon, 15 Aug 2022 17:51:03 +0200 Subject: 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. --- gcc/d/d-codegen.cc | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) (limited to 'gcc/d/d-codegen.cc') diff --git a/gcc/d/d-codegen.cc b/gcc/d/d-codegen.cc index d02da1f..aa6bc9e 100644 --- a/gcc/d/d-codegen.cc +++ b/gcc/d/d-codegen.cc @@ -1588,6 +1588,32 @@ complex_expr (tree type, tree re, tree im) type, re, im); } +/* Build a two-field record TYPE representing the complex expression EXPR. */ + +tree +underlying_complex_expr (tree type, tree expr) +{ + gcc_assert (list_length (TYPE_FIELDS (type)) == 2); + + expr = d_save_expr (expr); + + /* Build a constructor from the real and imaginary parts. */ + if (COMPLEX_FLOAT_TYPE_P (TREE_TYPE (expr)) && + (!INDIRECT_REF_P (expr) + || !CONVERT_EXPR_CODE_P (TREE_CODE (TREE_OPERAND (expr, 0))))) + { + vec *ve = NULL; + CONSTRUCTOR_APPEND_ELT (ve, TYPE_FIELDS (type), + real_part (expr)); + CONSTRUCTOR_APPEND_ELT (ve, TREE_CHAIN (TYPE_FIELDS (type)), + imaginary_part (expr)); + return build_constructor (type, ve); + } + + /* Replace type in the reinterpret cast with a cast to the record type. */ + return build_vconvert (type, expr); +} + /* Cast EXP (which should be a pointer) to TYPE* and then indirect. The back-end requires this cast in many cases. */ @@ -2214,6 +2240,14 @@ d_build_call (TypeFunction *tf, tree callable, tree object, build_address (targ)); } + /* Complex types are exposed as special types with an underlying + struct representation, if we are passing the native type to a + function that accepts the library-defined version, then ensure + it is properly reinterpreted as the underlying struct type. */ + if (COMPLEX_FLOAT_TYPE_P (TREE_TYPE (targ)) + && arg->type->isTypeStruct ()) + targ = underlying_complex_expr (build_ctype (arg->type), targ); + /* Type `noreturn` is a terminator, as no other arguments can possibly be evaluated after it. */ if (TREE_TYPE (targ) == noreturn_type_node) -- cgit v1.1