Hi!

The following testcase is incorrectly rejected.
While when parsing the splice expressions outside of templates we call
finish_id_expression -> finish_id_expression_1 -> convert_from_reference,
in tsubst_splice_expr that doesn't happen and so build_x_array_ref is
called with the PARM_DECLs of REFERENCE_TYPE rather than INDIRECT_REFs
of those.

The following patch adds the convert_from_reference call.
The "&& (TREE_TYPE (t) == NULL_TREE || !TYPE_REF_P (TREE_TYPE (t)))"
part is maybe not needed, I only see build_nt (SPLICE_EXPR, refl);
as creating SPLICE_EXPRs and am not aware (but haven't searched hard)
whether their type is ever changed.
The !TYPE_P (op) part is to prevent ICE on reflect/members_of14.C testcase,
where f<typename [:type_of(mem):]>(); apparently results in
tsubst_splice_expr having op of FUNCTION_TYPE.  Perhaps the condition
ought to be
  else if (SPLICE_EXPR_EXPRESSION_P (t))
    op = convert_from_reference (op);

In any case, bootstrapped/regtested on x86_64-linux and i686-linux
successfully.

2026-09-10  Jakub Jelinek  <[email protected]>

        PR c++/127276
        * pt.cc (tsubst_splice_expr): Call convert_from_reference if not
        member access and op isn't a type.

        * g++.dg/reflect/pr127276.C: New test.

--- a/gcc/cp/pt.cc      2026-09-08 22:18:28.000000000 +0200
+++ b/gcc/cp/pt.cc      2026-09-09 16:42:48.315435696 +0200
@@ -17173,6 +17173,11 @@ tsubst_splice_expr (tree t, tree args, t
      certain kind of entities.  */
   if (SPLICE_EXPR_MEMBER_ACCESS_P (t))
     gcc_assert (valid_splice_for_member_access_p (op, /*decls_only_p=*/false));
+  else if (!TYPE_P (op)
+          && (TREE_TYPE (t) == NULL_TREE || !TYPE_REF_P (TREE_TYPE (t))))
+    /* If the original type was a reference, we'll be wrapped in
+       the appropriate INDIRECT_REF.  */
+    op = convert_from_reference (op);
 
   return op;
 }
--- a/gcc/testsuite/g++.dg/reflect/pr127276.C   2026-09-09 16:50:57.263203336 
+0200
+++ b/gcc/testsuite/g++.dg/reflect/pr127276.C   2026-09-09 16:50:38.326445643 
+0200
@@ -0,0 +1,34 @@
+// PR c++/127276
+// { dg-do compile { target c++26 } }
+// { dg-additional-options "-freflection" }
+
+struct A {
+  constexpr int &operator[] (int x) { return a[x]; };
+  int a[2];
+};
+
+constexpr int
+foo (A &x, int y)
+{
+  return [: ^^x :][ [: ^^y :] ];
+}
+
+template <typename T>
+constexpr int
+bar (T &x, int y)
+{
+  return [: ^^x :][ [: ^^y :] ];
+}
+
+constexpr bool
+baz ()
+{
+  A a = { 2, 3 };
+  if (foo (a, 0) != 2 || foo (a, 1) != 3)
+    return false;
+  if (bar (a, 0) != 2 || bar (a, 1) != 3)
+    return false;
+  return true;
+}
+
+static_assert (baz ());

        Jakub

Reply via email to