aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIain Buclaw <ibuclaw@gdcproject.org>2024-03-10 17:49:06 +0100
committerIain Buclaw <ibuclaw@gdcproject.org>2024-03-10 19:06:11 +0100
commita84b98c62d90bf9e8b01038f624a62725e6a44db (patch)
treeb67edf44624f2abe1af29df34ddec6b0fd441bce
parent8fe27ed193d60f6cd8b34761858a720c95eabbdb (diff)
downloadgcc-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.cc25
-rw-r--r--gcc/testsuite/gdc.dg/pr112285.d13
-rw-r--r--gcc/testsuite/gdc.dg/pr112290.d15
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;
+}