diff options
author | Iain Buclaw <ibuclaw@gdcproject.org> | 2024-03-10 17:49:06 +0100 |
---|---|---|
committer | Iain Buclaw <ibuclaw@gdcproject.org> | 2024-03-10 19:06:11 +0100 |
commit | a84b98c62d90bf9e8b01038f624a62725e6a44db (patch) | |
tree | b67edf44624f2abe1af29df34ddec6b0fd441bce | |
parent | 8fe27ed193d60f6cd8b34761858a720c95eabbdb (diff) | |
download | gcc-a84b98c62d90bf9e8b01038f624a62725e6a44db.zip gcc-a84b98c62d90bf9e8b01038f624a62725e6a44db.tar.gz gcc-a84b98c62d90bf9e8b01038f624a62725e6a44db.tar.bz2 |
d: Fix -fpreview=in ICEs with forward referenced parameter [PR112285]
The way that the target hook preferPassByRef is implemented, it relied
on the GCC "back-end" tree type to determine whether or not to use `ref'
ABI for D `in' parameters; e.g: prefer by value if it is expected that
the target will pass the type around in registers.
Building the GCC tree type depends on the AST type being complete - all
semantic processing is finished - but as this hook is called from the
front-end, this will not be the case for forward referenced or
self-referencing types.
The consensus in upstream is that `in' parameters should always be
implicitly `ref', but as the front-end does not yet support all types
being rvalue references, limit this just static arrays and structs.
PR d/112285
PR d/112290
gcc/d/ChangeLog:
* d-target.cc (Target::preferPassByRef): Return true for all static
array and struct types.
gcc/testsuite/ChangeLog:
* gdc.dg/pr112285.d: New test.
* gdc.dg/pr112290.d: New test.
-rw-r--r-- | gcc/d/d-target.cc | 25 | ||||
-rw-r--r-- | gcc/testsuite/gdc.dg/pr112285.d | 13 | ||||
-rw-r--r-- | gcc/testsuite/gdc.dg/pr112290.d | 15 |
3 files changed, 33 insertions, 20 deletions
diff --git a/gcc/d/d-target.cc b/gcc/d/d-target.cc index b9d1244..127b9d7 100644 --- a/gcc/d/d-target.cc +++ b/gcc/d/d-target.cc @@ -575,31 +575,16 @@ Target::supportsLinkerDirective (void) const } /* Decides whether an `in' parameter of the specified POD type PARAM_TYPE is to - be passed by reference or by valie. This is used only when compiling with + be passed by reference or by value. This is used only when compiling with `-fpreview=in' enabled. */ bool Target::preferPassByRef (Type *param_type) { - if (param_type->size () == SIZE_INVALID) + /* See note in Target::isReturnOnStack. */ + Type *tb = param_type->toBasetype (); + if (tb->size () == SIZE_INVALID) return false; - tree type = build_ctype (param_type); - - /* Prefer a `ref' if the type is an aggregate, and its size is greater than - its alignment. */ - if (AGGREGATE_TYPE_P (type) - && (!valid_constant_size_p (TYPE_SIZE_UNIT (type)) - || compare_tree_int (TYPE_SIZE_UNIT (type), TYPE_ALIGN (type)) > 0)) - return true; - - /* If the back-end is always going to pass this by invisible reference. */ - if (pass_by_reference (NULL, function_arg_info (type, true))) - return true; - - /* If returning the parameter means the caller will do RVO. */ - if (targetm.calls.return_in_memory (type, NULL_TREE)) - return true; - - return false; + return (tb->ty == TY::Tstruct || tb->ty == TY::Tsarray); } diff --git a/gcc/testsuite/gdc.dg/pr112285.d b/gcc/testsuite/gdc.dg/pr112285.d new file mode 100644 index 0000000..5ca100a --- /dev/null +++ b/gcc/testsuite/gdc.dg/pr112285.d @@ -0,0 +1,13 @@ +// { dg-do compile } +// { dg-additional-options "-fpreview=in" } +struct S112285 +{ +} + +class C112285 +{ + S112285 s; + void f112285(in C112285) + { + } +} diff --git a/gcc/testsuite/gdc.dg/pr112290.d b/gcc/testsuite/gdc.dg/pr112290.d new file mode 100644 index 0000000..7456fc2 --- /dev/null +++ b/gcc/testsuite/gdc.dg/pr112290.d @@ -0,0 +1,15 @@ +// { dg-do compile } +// { dg-additional-options "-fpreview=in" } +struct S112290a +{ + S112290b* p; + bool opEquals(in S112290a) + { + return p == p; + } +} + +struct S112290b +{ + string s; +} |