On Tuesday, February 10th, 2026 at 2:05 PM, Jason Merrill <[email protected]> 
wrote:

> 
> 

Snipped older discussions for brevity.

> > 
> > Here's a v2 of the patch, bootstrapped and tested on x86_64-pc-linux-gnu.
> > -- >8 --
> > In case of expressions like `&[:expr:]` where `expr` depends on a
> > template parameter, and the splice expression represents a `FIELD_DECL` or
> > a non-static member `FUNCTION_DECL`, that's exactly what we'd pass on.
> > However, `build_x_unary_op()` for these expressions is expecting an
> > `OFFSET_REF`. `OFFSET_REF` is also what gets passed to
> > `build_x_unary_op()` when templates are not involved.
> > 
> > There's also a difference between the template argument being a type and
> > using `members_of()` to get to the reflections of members (in which case
> > evaluating the `SPLICE_EXPR` returns a `FUNCTION_DECL` - `splice10.C`
> > test) and passing `^^T::member` as the template argument (in which case
> > evaluating the `SPLICE_EXPR` returns a `BASELINK` - `splice11.C`).
> > 
> > Signed-off-by: Boris Staletic [email protected]
> > 
> > PR c++/123660
> > PR c++/123661
> > 
> > gcc/cp/ChangeLog:
> > 
> > * pt.cc (tsubst_splice_expr): Handle pointers to non-static members
> > from splice expressions
> > 
> > gcc/testsuite/ChangeLog:
> > 
> > * g++.dg/reflect/splice10.C: New test.
> > * g++.dg/reflect/splice11.C: New test.
> > ---
> > gcc/cp/pt.cc | 14 ++++++++++++
> > gcc/testsuite/g++.dg/reflect/splice10.C | 28 ++++++++++++++++++++++++
> > gcc/testsuite/g++.dg/reflect/splice11.C | 29 +++++++++++++++++++++++++
> > 3 files changed, 71 insertions(+)
> > create mode 100644 gcc/testsuite/g++.dg/reflect/splice10.C
> > create mode 100644 gcc/testsuite/g++.dg/reflect/splice11.C
> > 
> > diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
> > index 049bbf07e0..0c0076c9a4 100644
> > --- a/gcc/cp/pt.cc
> > +++ b/gcc/cp/pt.cc
> > @@ -16755,6 +16755,20 @@ tsubst_splice_expr (tree t, tree args, 
> > tsubst_flags_t complain, tree in_decl)
> > op = splice (op);
> > if (op == error_mark_node)
> > return error_mark_node;
> > +
> > + if (SPLICE_EXPR_ADDRESS_P (t) && !TREE_STATIC (TREE_TYPE (op)))
> 
> 
> TREE_STATIC on a type isn't meaningful, the checks below are enough.

I thought that was fishy... You're right, everything works without that check.

> 
> > + {
> > + if (TREE_CODE (op) == BASELINK
> > + && TREE_CODE (TREE_TYPE (op)) == METHOD_TYPE)
> 
> 
> It shouldn't be necessary to check for METHOD_TYPE; any class member is
> suitable for passing to build_offset_ref. If the argument is static,
> it'll return it unchanged rather than actually build an OFFSET_REF.

If I drop the METHOD_TYPE check, I get an ICE in both splice10.C and splice11.C.
splice10.C ICEs when calling `build_offset_ref()` on a static member function 
(s::get_y).
splice11.C ICEs when calling `build_offset_ref()` on a free function (::f).

That's why I was initially looking for a way to do this only for non-static 
members.

In case of free functions in splice11.C, the ICE happens here:
https://gcc.gnu.org/git/?p=gcc.git;a=blob;f=gcc/cp/init.cc;h=437797fef0c637b5a7d988eee8f8b5c710bd2d11;hb=HEAD#l2428

In case of static member functions in splice10.C, we get a bit further, here's 
the traceback:

splice10.C: In instantiation of ‘constexpr auto test() [with T = s; long 
unsigned int I = 1]’:
required from here
splice10.C:25:27:
   25 | static_assert(test<s, 1uz>() == &s::get_y);
      |               ~~~~~~~~~~~~^~
splice10.C:21:10: internal compiler error: in build_ptrmem_type, at 
cp/decl.cc:12978
   21 |   return &[:members_of(^^T, ctx)[I]:];
      |          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
0x2a92a3f internal_error(char const*, ...)
        ../../gcc/diagnostic-global-context.cc:787
0xaff8c1 fancy_abort(char const*, int, char const*)
        ../../gcc/diagnostics/context.cc:1812
0x7b9b70 build_ptrmem_type(tree_node*, tree_node*)
        ../../gcc/cp/decl.cc:12978
0xe4b7a9 cp_build_addr_expr_1
        ../../gcc/cp/typeck.cc:7638
0xe4c728 cp_build_addr_expr_strict
        ../../gcc/cp/typeck.cc:7726
0xe4c728 build_x_unary_op(unsigned long, tree_code, cp_expr, tree_node*, int)
        ../../gcc/cp/typeck.cc:7318
0xd859b6 tsubst_expr(tree_node*, tree_node*, int, tree_node*)
        ../../gcc/cp/pt.cc:21470
0xdb36bf tsubst_stmt
        ../../gcc/cp/pt.cc:20614
0xdb49e3 tsubst_stmt
        ../../gcc/cp/pt.cc:19397
0xdb49a0 tsubst_stmt
        ../../gcc/cp/pt.cc:19387
0xdb50ed tsubst_stmt
        ../../gcc/cp/pt.cc:19808
0xdbc4a6 tsubst_stmt
        ../../gcc/cp/pt.cc:19373
0xdbc4a6 instantiate_body
        ../../gcc/cp/pt.cc:28418
0xdbd27c instantiate_decl(tree_node*, bool, bool)
        ../../gcc/cp/pt.cc:28711
0xc156e0 maybe_instantiate_decl(tree_node*)
        ../../gcc/cp/decl2.cc:6432
0xc156e0 maybe_instantiate_decl(tree_node*)
        ../../gcc/cp/decl2.cc:6420
0xc17587 mark_used(tree_node*, int)
        ../../gcc/cp/decl2.cc:6788
0xb17c1b build_over_call
        ../../gcc/cp/call.cc:11024
0xb2c405 build_new_function_call(tree_node*, vec<tree_node*, va_gc, 
vl_embed>**, int)
        ../../gcc/cp/call.cc:5310
0xdfbc09 finish_call_expr(tree_node*, vec<tree_node*, va_gc, vl_embed>**, bool, 
bool, int)
        ../../gcc/cp/semantics.cc:3542

Reply via email to