From 2370bdbb0b29b14401d8508d846c0e01c64d82fc Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Sun, 26 Apr 2020 23:39:32 +0200 Subject: d: Fix ICE in assign_temp, at function.c:984 (PR94777) Named arguments were being passed around by invisible reference, just not variadic arguments. There is a need to de-duplicate the routines that handle declaration/parameter promotion and reference checking. However for now, the parameter helper functions have just been renamed to parameter_reference_p and parameter_type, to make it more clear that it is the Parameter equivalent to declaration_reference_p and declaration_type. On writing the tests, a forward-reference bug was discovered on x86_64 during va_list type semantic. This was due to fields not having their parent set-up correctly. gcc/d/ChangeLog: PR d/94777 * d-builtins.cc (build_frontend_type): Set parent for generated fields of built-in types. * d-codegen.cc (argument_reference_p): Rename to ... (parameter_reference_p): ... this. (type_passed_as): Rename to ... (parameter_type): ... this. Make TREE_ADDRESSABLE types restrict. (d_build_call): Move handling of non-POD types here from ... * d-convert.cc (convert_for_argument): ... here. * d-tree.h (argument_reference_p): Rename declaration to ... (parameter_reference_p): ... this. (type_passed_as): Rename declaration to ... (parameter_type): ... this. * types.cc (TypeVisitor::visit (TypeFunction *)): Update caller. gcc/testsuite/ChangeLog: PR d/94777 * gdc.dg/pr94777a.d: New test. * gdc.dg/pr94777b.d: New test. --- gcc/d/ChangeLog | 17 +++++++++++++++++ gcc/d/d-builtins.cc | 1 + gcc/d/d-codegen.cc | 32 +++++++++++++++++++++++++++++--- gcc/d/d-convert.cc | 19 ++----------------- gcc/d/d-tree.h | 4 ++-- gcc/d/types.cc | 2 +- 6 files changed, 52 insertions(+), 23 deletions(-) (limited to 'gcc/d') diff --git a/gcc/d/ChangeLog b/gcc/d/ChangeLog index ab3028d..3b5fc12 100644 --- a/gcc/d/ChangeLog +++ b/gcc/d/ChangeLog @@ -1,3 +1,20 @@ +2020-04-27 Iain Buclaw + + PR d/94777 + * d-builtins.cc (build_frontend_type): Set parent for generated + fields of built-in types. + * d-codegen.cc (argument_reference_p): Rename to ... + (parameter_reference_p): ... this. + (type_passed_as): Rename to ... + (parameter_type): ... this. Make TREE_ADDRESSABLE types restrict. + (d_build_call): Move handling of non-POD types here from ... + * d-convert.cc (convert_for_argument): ... here. + * d-tree.h (argument_reference_p): Rename declaration to ... + (parameter_reference_p): ... this. + (type_passed_as): Rename declaration to ... + (parameter_type): ... this. + * types.cc (TypeVisitor::visit (TypeFunction *)): Update caller. + 2020-04-26 Iain Buclaw * decl.cc (get_symbol_decl): Set DECL_DECLARED_INLINE_P or diff --git a/gcc/d/d-builtins.cc b/gcc/d/d-builtins.cc index cb8f43a..a5654a6 100644 --- a/gcc/d/d-builtins.cc +++ b/gcc/d/d-builtins.cc @@ -253,6 +253,7 @@ build_frontend_type (tree type) = Identifier::idPool (IDENTIFIER_POINTER (DECL_NAME (field))); VarDeclaration *vd = VarDeclaration::create (Loc (), ftype, fident, NULL); + vd->parent = sdecl; vd->offset = tree_to_uhwi (DECL_FIELD_OFFSET (field)); vd->semanticRun = PASSsemanticdone; vd->csym = field; diff --git a/gcc/d/d-codegen.cc b/gcc/d/d-codegen.cc index 8dc1ab2..12c6f13 100644 --- a/gcc/d/d-codegen.cc +++ b/gcc/d/d-codegen.cc @@ -172,7 +172,7 @@ declaration_type (Declaration *decl) Return TRUE if parameter ARG is a reference type. */ bool -argument_reference_p (Parameter *arg) +parameter_reference_p (Parameter *arg) { Type *tb = arg->type->toBasetype (); @@ -186,7 +186,7 @@ argument_reference_p (Parameter *arg) /* Returns the real type for parameter ARG. */ tree -type_passed_as (Parameter *arg) +parameter_type (Parameter *arg) { /* Lazy parameters are converted to delegates. */ if (arg->storageClass & STClazy) @@ -207,9 +207,18 @@ type_passed_as (Parameter *arg) tree type = build_ctype (arg->type); /* Parameter is passed by reference. */ - if (TREE_ADDRESSABLE (type) || argument_reference_p (arg)) + if (parameter_reference_p (arg)) return build_reference_type (type); + /* Pass non-POD structs by invisible reference. */ + if (TREE_ADDRESSABLE (type)) + { + type = build_reference_type (type); + /* There are no other pointer to this temporary. */ + type = build_qualified_type (type, TYPE_QUAL_RESTRICT); + } + + /* Front-end has already taken care of type promotions. */ return type; } @@ -1954,6 +1963,23 @@ d_build_call (TypeFunction *tf, tree callable, tree object, targ = build2 (COMPOUND_EXPR, TREE_TYPE (t), targ, t); } + /* Parameter is a struct passed by invisible reference. */ + if (TREE_ADDRESSABLE (TREE_TYPE (targ))) + { + Type *t = arg->type->toBasetype (); + gcc_assert (t->ty == Tstruct); + StructDeclaration *sd = ((TypeStruct *) t)->sym; + + /* Nested structs also have ADDRESSABLE set, but if the type has + neither a copy constructor nor a destructor available, then we + need to take care of copying its value before passing it. */ + if (arg->op == TOKstructliteral || (!sd->postblit && !sd->dtor)) + targ = force_target_expr (targ); + + targ = convert (build_reference_type (TREE_TYPE (targ)), + build_address (targ)); + } + vec_safe_push (args, targ); } } diff --git a/gcc/d/d-convert.cc b/gcc/d/d-convert.cc index 9ee149b..e2921ec 100644 --- a/gcc/d/d-convert.cc +++ b/gcc/d/d-convert.cc @@ -672,25 +672,10 @@ convert_for_argument (tree expr, Parameter *arg) if (!POINTER_TYPE_P (TREE_TYPE (expr))) return build_address (expr); } - else if (argument_reference_p (arg)) + else if (parameter_reference_p (arg)) { /* Front-end shouldn't automatically take the address. */ - return convert (type_passed_as (arg), build_address (expr)); - } - else if (TREE_ADDRESSABLE (TREE_TYPE (expr))) - { - /* Type is a struct passed by invisible reference. */ - Type *t = arg->type->toBasetype (); - gcc_assert (t->ty == Tstruct); - StructDeclaration *sd = ((TypeStruct *) t)->sym; - - /* Nested structs also have ADDRESSABLE set, but if the type has - neither a copy constructor nor a destructor available, then we - need to take care of copying its value before passing it. */ - if (!sd->postblit && !sd->dtor) - expr = force_target_expr (expr); - - return convert (type_passed_as (arg), build_address (expr)); + return convert (parameter_type (arg), build_address (expr)); } return expr; diff --git a/gcc/d/d-tree.h b/gcc/d/d-tree.h index 89feb9e..48587d9 100644 --- a/gcc/d/d-tree.h +++ b/gcc/d/d-tree.h @@ -504,8 +504,8 @@ extern tree d_decl_context (Dsymbol *); extern tree copy_aggregate_type (tree); extern bool declaration_reference_p (Declaration *); extern tree declaration_type (Declaration *); -extern bool argument_reference_p (Parameter *); -extern tree type_passed_as (Parameter *); +extern bool parameter_reference_p (Parameter *); +extern tree parameter_type (Parameter *); extern tree build_integer_cst (dinteger_t, tree = d_int_type); extern tree build_float_cst (const real_t &, Type *); extern tree d_array_length (tree); diff --git a/gcc/d/types.cc b/gcc/d/types.cc index f6ae574..59a90b4 100644 --- a/gcc/d/types.cc +++ b/gcc/d/types.cc @@ -720,7 +720,7 @@ public: for (size_t i = 0; i < n_args; i++) { - tree type = type_passed_as (Parameter::getNth (t->parameters, i)); + tree type = parameter_type (Parameter::getNth (t->parameters, i)); fnparams = chainon (fnparams, build_tree_list (0, type)); } } -- cgit v1.1