Hi,
This patch fixes PR124026.
Regstrapped on x86_64-linux-gnu, committed to mainline, and backported
to releases/gcc-13, gcc-14, and gcc-15.
Regards,
Iain.
---
PR d/124026
gcc/d/ChangeLog:
* expr.cc (ExprVisitor::visit (FuncExp *)): Always convert function
literal to a delegate if the expression expects one.
---
gcc/d/expr.cc | 24 ++++++++++++++----------
1 file changed, 14 insertions(+), 10 deletions(-)
diff --git a/gcc/d/expr.cc b/gcc/d/expr.cc
index d05a12d5d09..8c068b083e5 100644
--- a/gcc/d/expr.cc
+++ b/gcc/d/expr.cc
@@ -1871,27 +1871,31 @@ public:
/* Compile the declaration. */
build_lambda_tree (e->fd, e->type->toBasetype ());
- /* If nested, this will be a trampoline. */
- if (e->fd->isNested ())
- {
- tree func = build_address (get_symbol_decl (e->fd));
- tree object;
+ tree func = build_address (get_symbol_decl (e->fd));
+ Type *tb = e->type->toBasetype ();
- if (this->constp_)
+ /* If a delegate is expected, the literal will be inferred as a delegate
+ even if it accesses no variables from an enclosing function. */
+ if (tb->ty == TY::Tdelegate)
+ {
+ /* Static delegate variables have no context pointer. */
+ if (this->constp_ || !e->fd->isNested ())
{
- /* Static delegate variables have no context pointer. */
- object = null_pointer_node;
- this->result_ = build_method_call (func, object, e->fd->type);
+ this->result_ = build_method_call (func, null_pointer_node,
+ e->fd->type);
TREE_CONSTANT (this->result_) = 1;
}
else
{
- object = get_frame_for_symbol (e->fd);
+ gcc_assert (e->fd->isNested ());
+ tree object = get_frame_for_symbol (e->fd);
this->result_ = build_method_call (func, object, e->fd->type);
}
}
else
{
+ /* The function literal is a function pointer. */
+ gcc_assert (tb->ty == TY::Tpointer);
this->result_ = build_nop (build_ctype (e->type),
build_address (get_symbol_decl (e->fd)));
}
diff --git a/gcc/testsuite/gdc.dg/pr124026.d b/gcc/testsuite/gdc.dg/pr124026.d
new file mode 100644
index 00000000000..48a3e13eded
--- /dev/null
+++ b/gcc/testsuite/gdc.dg/pr124026.d
@@ -0,0 +1,21 @@
+// { dg-do compile }
+struct UDA
+{
+ int delegate() foo;
+}
+
+static UDA getUDA(alias S)()
+{
+ return __traits(getAttributes, S)[0];
+}
+
+struct S124026
+{
+ @UDA({ return 42; }) int a;
+}
+
+void f124026()
+{
+ S124026 m;
+ enum uda = getUDA!(m.a);
+}
--
2.43.0