{"id":2229077,"url":"http://patchwork.ozlabs.org/api/1.1/patches/2229077/?format=json","web_url":"http://patchwork.ozlabs.org/project/gcc/patch/20260427182331.85714-1-feedabl3@gmail.com/","project":{"id":17,"url":"http://patchwork.ozlabs.org/api/1.1/projects/17/?format=json","name":"GNU Compiler Collection","link_name":"gcc","list_id":"gcc-patches.gcc.gnu.org","list_email":"gcc-patches@gcc.gnu.org","web_url":null,"scm_url":null,"webscm_url":null},"msgid":"<20260427182331.85714-1-feedabl3@gmail.com>","date":"2026-04-27T18:14:57","name":"[v4] c++/reflection: ICE on member function template splicing [PR124794]","commit_ref":null,"pull_url":null,"state":"new","archived":false,"hash":"f996f2ba7d5494cd506ebd1111201fe06bb260df","submitter":{"id":92146,"url":"http://patchwork.ozlabs.org/api/1.1/people/92146/?format=json","name":"feedable","email":"feedabl3@gmail.com"},"delegate":null,"mbox":"http://patchwork.ozlabs.org/project/gcc/patch/20260427182331.85714-1-feedabl3@gmail.com/mbox/","series":[{"id":501702,"url":"http://patchwork.ozlabs.org/api/1.1/series/501702/?format=json","web_url":"http://patchwork.ozlabs.org/project/gcc/list/?series=501702","date":"2026-04-27T18:14:57","name":"[v4] c++/reflection: ICE on member function template splicing [PR124794]","version":4,"mbox":"http://patchwork.ozlabs.org/series/501702/mbox/"}],"comments":"http://patchwork.ozlabs.org/api/patches/2229077/comments/","check":"pending","checks":"http://patchwork.ozlabs.org/api/patches/2229077/checks/","tags":{},"headers":{"Return-Path":"<gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org>","X-Original-To":["incoming@patchwork.ozlabs.org","gcc-patches@gcc.gnu.org"],"Delivered-To":["patchwork-incoming@legolas.ozlabs.org","gcc-patches@gcc.gnu.org"],"Authentication-Results":["legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256\n header.s=20251104 header.b=oE3RwurZ;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org\n (client-ip=2620:52:6:3111::32; helo=vm01.sourceware.org;\n envelope-from=gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org;\n receiver=patchwork.ozlabs.org)","sourceware.org;\n\tdkim=pass (2048-bit key,\n unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256\n header.s=20251104 header.b=oE3RwurZ","sourceware.org;\n dmarc=pass (p=none dis=none) header.from=gmail.com","sourceware.org; spf=pass smtp.mailfrom=gmail.com","server2.sourceware.org;\n arc=none smtp.remote-ip=209.85.128.47"],"Received":["from vm01.sourceware.org (vm01.sourceware.org\n [IPv6:2620:52:6:3111::32])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4g4BmT6jc2z1yHv\n\tfor <incoming@patchwork.ozlabs.org>; Tue, 28 Apr 2026 04:24:24 +1000 (AEST)","from vm01.sourceware.org (localhost [127.0.0.1])\n\tby sourceware.org (Postfix) with ESMTP id 9B41E4BAD15D\n\tfor <incoming@patchwork.ozlabs.org>; Mon, 27 Apr 2026 18:24:22 +0000 (GMT)","from mail-wm1-f47.google.com (mail-wm1-f47.google.com\n [209.85.128.47])\n by sourceware.org (Postfix) with ESMTPS id 9D84B4BAD152\n for <gcc-patches@gcc.gnu.org>; Mon, 27 Apr 2026 18:23:49 +0000 (GMT)","by mail-wm1-f47.google.com with SMTP id\n 5b1f17b1804b1-488ad135063so96618805e9.0\n for <gcc-patches@gcc.gnu.org>; Mon, 27 Apr 2026 11:23:49 -0700 (PDT)","from 7a38.moduleworks.com ([2a02:8308:900b:fc00::2690])\n by smtp.gmail.com with ESMTPSA id\n 5b1f17b1804b1-48a773a88e8sm6020645e9.3.2026.04.27.11.23.47\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Mon, 27 Apr 2026 11:23:47 -0700 (PDT)"],"DKIM-Filter":["OpenDKIM Filter v2.11.0 sourceware.org 9B41E4BAD15D","OpenDKIM Filter v2.11.0 sourceware.org 9D84B4BAD152"],"DMARC-Filter":"OpenDMARC Filter v1.4.2 sourceware.org 9D84B4BAD152","ARC-Filter":"OpenARC Filter v1.0.0 sourceware.org 9D84B4BAD152","ARC-Seal":"i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1777314229; cv=none;\n b=Tagw3j9ZjtTwqDYNTqMXlb/xrw0DQlsVdKWpD6NBNmN53Trg0hhlXJULAgUwR+/CAS7CVOuUTKSt0wiUtF6I1w0VgUTmfH4OGr3eKJRs6wETUdKDu1cc+izmroRVJa/o+xC05YBrlvnphb1IhLPfZ4AJVXsyYtfB7F+e6aWBxts=","ARC-Message-Signature":"i=1; a=rsa-sha256; d=sourceware.org; s=key;\n t=1777314229; c=relaxed/simple;\n bh=5UNYwG3xUqFR0dLpF1SP72hbvxG9LD6yWDu7BI/qFZQ=;\n h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version;\n b=aYufzFmL3D4Kb30lH92nlFGEa4DGkm3pRB1k3rAo6syxLRQrRGiQ/jyJdBmoNLTXAWduLaEj9kCSUY4DWg/1XqNxQKdPdp1ZgY/rMUV/u8J8lveN9jZaC81DN0TubY8rCrceHgWRkKqqXGzaCI3OeCllmSMkRwTTNE1cbnxBhHg=","ARC-Authentication-Results":"i=1; server2.sourceware.org","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=gmail.com; s=20251104; t=1777314228; x=1777919028; darn=gcc.gnu.org;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:cc:to:from:from:to:cc:subject:date\n :message-id:reply-to;\n bh=USNTEVuxptWbni4LuSnHav5fmobV+n0TP0sEJDD9RMk=;\n b=oE3RwurZuuQu1t91rmKqHuwIbBX1aUeF0Tm9WgMJEqEASyf0QM1ZiZ11G9/GjslUaj\n cvZIjmCGokVc+5+7IvJ9xH21Uh5T0zUqNWgmxaEsu9HQrRYzBQ8OzC2ADj73IG9zPyvh\n 1NZ/fei6iLNPPFJnjHtHXHRQeHEPTKFMezkHW2RaEIlZzklb/zFR3183JWjFk3of9Nvr\n 1efp9L+DnLaCirgnKSHHYWP1lyyLUJBw4X/DnNqc36seuCV/f/CszuVMBCa127SkZDIn\n v76XEywqnJtnxsTkzf63mC2/3elioIlRA0rJpAuRoc7uCXlvltTBa51fwSpvyVj7PKgp\n QOjw==","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1777314228; x=1777919028;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from\n :to:cc:subject:date:message-id:reply-to;\n bh=USNTEVuxptWbni4LuSnHav5fmobV+n0TP0sEJDD9RMk=;\n b=Jy21Vd+7wn3RkcH7WOwChY3Y26ajs9770yRRxjFII5sXZ0eZdNW0tHZOE5UcG3s7W9\n gmBBLvZbaLjsBINxGxhK8Xx63U6wegaebJ7P8ypmI/gT8ZWIpQBvMpYdKzv+/eaxziMb\n CAT+tadTJP3rVhJ8Qwl9sW0M7JYqv0Fc9YwByp1/A5t29t9C+oEDKf2js6IYUtk4XQZS\n 0G6J0p4OO69EXEPAVhP55fVvXWIaxDS6ibsowd2k1M42YqH7OeKN2mWOlqsnZtGi2WvL\n utUqNNVtJ7fYFew9VpC2nJgwiIElMs3sj5evkqYbNBJ+Y2iqy77/U1HVWOF0lN7t0cWW\n 7ONQ==","X-Gm-Message-State":"AOJu0YwzYuJaFhLY3zDMOHM8/6rDmTNFd/tx2SVXAJg16xWSO/ma5Tk0\n 3imZ5u2Zv1tGkv6iBy+CAFvJ4eV4ZC0Rilr8YuifQv5eojtJw7B4uSzmHNcx2Q==","X-Gm-Gg":"AeBDietYmtWhdDt/19WIiflAxpeKJREXisnPjCZqYpwyMbEURGqhm/RFSKbqjFV/OSS\n HXG9eq3Xc9zGQG6E6KtNAkVk+B3GpHYw8uK5QhORsU1TKQHSa5CSh+nZQy5miaME3kmBP5SbyYn\n htsTHcoBUrvyBUNsCU1tlHiMGXaiZQRPdC41oJ0DCbgB+T5+x3mlLL6xve0m0zwF23c8/jL0Htr\n W41rQf2pjFJvqvt6BXemHBLbkhZCKjb9EIgZLSWXcg5TzMFQFgeTrlcGMw4LGFNH31USU/1YQep\n OGjuWz2vfpMxokOx+4CqN/MLCtMpSyedWscQKw0ZsD5Cmoy80TUPzmTyURihTrZUPEysFUx/YJc\n 82Q6eBhF406gWL+DQk9PcHqvqm454szTtrKjU6pPaa8h+5x+52TkCluYAqCcep0gvOtcQYHJuUp\n jWUyoSAQxMa1XI43Fs3fNgSR73zyJcPQ==","X-Received":"by 2002:a05:600c:a316:b0:489:1ba8:5bf0 with SMTP id\n 5b1f17b1804b1-48a76f85a78mr4533115e9.21.1777314227976;\n Mon, 27 Apr 2026 11:23:47 -0700 (PDT)","From":"feedable <feedabl3@gmail.com>","To":"gcc-patches@gcc.gnu.org","Cc":"Jason Merrill <jason@redhat.com>, Marek Polacek <polacek@redhat.com>,\n feedable <feedabl3@gmail.com>","Subject":"[PATCH v4] c++/reflection: ICE on member function template splicing\n [PR124794]","Date":"Mon, 27 Apr 2026 21:14:57 +0300","Message-ID":"<20260427182331.85714-1-feedabl3@gmail.com>","X-Mailer":"git-send-email 2.54.0","In-Reply-To":"<834e4d1f-cad9-4e33-bde4-cfaf768a8271@gmail.com>","References":"<834e4d1f-cad9-4e33-bde4-cfaf768a8271@gmail.com>","MIME-Version":"1.0","Content-Transfer-Encoding":"8bit","X-BeenThere":"gcc-patches@gcc.gnu.org","X-Mailman-Version":"2.1.30","Precedence":"list","List-Id":"Gcc-patches mailing list <gcc-patches.gcc.gnu.org>","List-Unsubscribe":"<https://gcc.gnu.org/mailman/options/gcc-patches>,\n <mailto:gcc-patches-request@gcc.gnu.org?subject=unsubscribe>","List-Archive":"<https://gcc.gnu.org/pipermail/gcc-patches/>","List-Post":"<mailto:gcc-patches@gcc.gnu.org>","List-Help":"<mailto:gcc-patches-request@gcc.gnu.org?subject=help>","List-Subscribe":"<https://gcc.gnu.org/mailman/listinfo/gcc-patches>,\n <mailto:gcc-patches-request@gcc.gnu.org?subject=subscribe>","Errors-To":"gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org"},"content":">>>>>> +          else if (BASELINK_P (expr))\n>>>>>> +        expr  = build_baselink (access_path, BASELINK_BINFO (expr),\n>>>>\n>>>> Extra space before =.  Also I guess BASELINK_ACCESS_BINFO instead of\n>>>> BASELINK_BINFO?\n>>>\n>>> We want to use access_path (relative to the actual object_type) in place of\n>>> BASELINK_ACCESS_BINFO, but indeed the access path should be the second\n>>> argument rather than the first in both this call and the existing one.\n>>\n>> If I understand correctly, access_path is the endpoint of the search, so it\n>> should go into BASELINK_BINFO, and it's the object type that should go\n>> into BASELINK_ACCESS_BINFO (in both cases, actually), since it's the\n>> place where we started the search.\n>\n>Ah, true.\n\nApparently, the start would actually correspond to the time when we got\nthe reflection in the first place (as we are essentially performing\nx.C::m, but with C::m being spliced); so obtaining the access binfo from the\nreflection here is correct.\n\n>>>>>> It might also make sense to move the template arguments\n>>>>>> inside the SPLICE_EXPR so that we have them available in\n>>>>>> tsubst_splice_expr. This seems reasonable since they are\n>>>>>> part of the splice*specifier.\n>>>>>\n>>>>> Another option would be to detect a TEMPLATE_ID_EXPR where the\n>>>>> template part is a SPLICE_EXPR, and forward that to\n>>>>> tsubst_splice_expr as a TEMPLATE_ID_EXPR, instead of creating\n>>>>> another node type or expanding the SPLICE_EXPR.\n>>>>\n>>>> Sure, that would also work.\n>\n>I'd prefer this: tsubst already does something like this for\n>a TEMPLATE_ID_EXPR with SPLICE_EXPR.\n\nThe case of tsubst is a little different, as I understand it: the\nstructure there is basically splice-scope(template-id(splice-expr,\nargs)); and only the splice-expr part will be in the tsubst_splice_expr,\nand that will expand into a type, on which no processing has to be done.\nBut tsubst_expr here would forward the template-id itself, and handle\nthat within.\n\n-- >8 --\n\ncp_parser_splice_expression is stripping BASELINKs before resolving the expr;\nchecks if the result is a BASELINK after that (by which point it never is).\nTo fix it, stop stripping the BASELINK, add handling to check_splice_expr\ninstead.\n\nIn cp_parser_splice_specifier, the additional template param parsing fails to\ndetect that the reflection is a template if it's wrapped in a BASELINKs, and\ndecides not to parse the splice-specialization-specifier if the 'template'\nkeyword is missing. Grab the data from the reflection instead.\n\nDuring template isntantiation, we blindly substitute the template part of a\nTEMPLATE_ID_EXPR, even if it's a SPLICE_EXPR. This, in turn, substitutes the\nSPLICE_EXPR as-if it had no template arguments and finishes up the expression,\nwhich interferes with later processing by TEMPLATE_ID_EXPR.\nTo fix, we defer such TEMPLATE_ID_EXPRs to tsubst_splice_expr, which itself\nperforms the substitution of a TEMPLATE_ID_EXPR and finishes up the expression.\n\n\tPR c++/124794\n\ngcc/cp/ChangeLog:\n\n\t* parser.cc (cp_parser_splice_specifier): Do not strip BASELINKs\n\t(cp_parser_splice_expression): Add parsing for member function template\n\tspecializations without the \"template\" keyword\n\t* pt.cc (tsubst_splice_expr): Handle TEMPLATE_ID_EXPR where the template\n\tpart is a SPLICE_EXPR\n\t(tsubst_expr): Defer to tsubst_splice_expr when thetemplate part of\n\tTEMPLATE_ID_EXPR is a SPLICE_EXPR\n\t* reflect.cc (check_splice_expr): Add handling for BASELINKs\n\ngcc/testsuite/ChangeLog:\n\n\t* g++.dg/reflect/member19.C: Enable tests.\n\t* g++.dg/reflect/splice13.C: New test.\n---\n gcc/cp/parser.cc                        | 21 ++++++----\n gcc/cp/pt.cc                            | 20 +++++++++\n gcc/cp/reflect.cc                       | 21 +++++-----\n gcc/testsuite/g++.dg/reflect/member19.C | 18 ---------\n gcc/testsuite/g++.dg/reflect/splice13.C | 54 +++++++++++++++++++++++++\n 5 files changed, 98 insertions(+), 36 deletions(-)\n create mode 100644 gcc/testsuite/g++.dg/reflect/splice13.C","diff":"diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc\nindex 9f2641f2ab2..4daba6c0260 100644\n--- a/gcc/cp/parser.cc\n+++ b/gcc/cp/parser.cc\n@@ -6179,6 +6179,8 @@ cp_parser_splice_specifier (cp_parser *parser, bool template_p = false,\n   /* Get the reflected operand.  */\n   expr = splice (expr);\n \n+  tree expr_real = maybe_get_first_fn (expr);\n+\n   /* If the next token is a <, it could be a splice-specialization-specifier.\n      But we need to handle \"[:r:] < 42\" where the < doesn't start a template\n      argument list.  [temp.names]/3: A < is interpreted as the delimiter of\n@@ -6190,30 +6192,34 @@ cp_parser_splice_specifier (cp_parser *parser, bool template_p = false,\n       /* As a courtesy to the user, if there is a < after a template\n \t name, parse the construct as an s-s-s and warn about the missing\n \t 'template'; it can't be anything else.  */\n-      && (template_p\n-\t  || typename_p\n-\t  || TREE_CODE (OVL_FIRST (expr)) == TEMPLATE_DECL))\n+      && (template_p || typename_p || TREE_CODE (expr_real) == TEMPLATE_DECL))\n     {\n       /* For member access splice-specialization-specifier, try to wrap\n \t non-dependent splice for function template into a BASELINK so\n \t that cp_parser_template_id can handle it.  */\n       if (object_type\n-\t  && DECL_FUNCTION_TEMPLATE_P (OVL_FIRST (expr))\n+\t  && reflection_function_template_p (expr_real)\n \t  && !dependent_type_p (object_type))\n \t{\n-\t  tree scope = DECL_CONTEXT (OVL_FIRST (expr));\n+\t  tree scope = DECL_CONTEXT (expr_real);\n \t  if (scope && CLASS_TYPE_P (scope))\n \t    {\n \t      tree access_path = lookup_base (object_type, scope, ba_unique,\n \t\t\t\t\t      NULL, tf_warning_or_error);\n \t      if (access_path == error_mark_node)\n \t\texpr = error_mark_node;\n+\t      else if (BASELINK_P (expr))\n+\t\texpr = build_baselink (access_path,\n+\t\t\t\t       BASELINK_ACCESS_BINFO (expr),\n+\t\t\t\t       BASELINK_FUNCTIONS (expr),\n+\t\t\t\t       BASELINK_OPTYPE (expr));\n \t      else\n \t\texpr\n \t\t  = build_baselink (access_path, TYPE_BINFO (object_type),\n \t\t\t\t    expr,\n-\t\t\t\t    IDENTIFIER_CONV_OP_P (OVL_NAME (expr))\n-\t\t\t\t    ? TREE_TYPE (OVL_NAME (expr)) : NULL_TREE);\n+\t\t\t\t    IDENTIFIER_CONV_OP_P (OVL_NAME (expr_real))\n+\t\t\t\t    ? TREE_TYPE (OVL_NAME (expr_real))\n+\t\t\t\t    : NULL_TREE);\n \t    }\n \t}\n       /* Let cp_parser_template_id parse the template arguments.  */\n@@ -6316,7 +6322,6 @@ cp_parser_splice_expression (cp_parser *parser, bool template_p,\n   tree t = expr.get_value ();\n   STRIP_ANY_LOCATION_WRAPPER (t);\n   tree unresolved = t;\n-  t = MAYBE_BASELINK_FUNCTIONS (t);\n   t = resolve_nondeduced_context (t, tf_warning_or_error);\n \n   if (dependent_splice_p (t))\ndiff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc\nindex 2cf14e2c801..89ddd782005 100644\n--- a/gcc/cp/pt.cc\n+++ b/gcc/cp/pt.cc\n@@ -16926,6 +16926,13 @@ tsubst_splice_scope (tree t, tree args, tsubst_flags_t complain, tree in_decl)\n static tree\n tsubst_splice_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)\n {\n+  tree template_id = NULL_TREE;\n+  if (TREE_CODE (t) == TEMPLATE_ID_EXPR)\n+    {\n+      template_id = copy_node (t);\n+      t = TREE_OPERAND (t, 0);\n+    }\n+\n   tree op = tsubst_expr (TREE_OPERAND (t, 0), args, complain, in_decl);\n   if (op == error_mark_node)\n     return error_mark_node;\n@@ -16955,6 +16962,16 @@ tsubst_splice_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)\n \t\t\t     (complain & tf_error)))\n     return error_mark_node;\n \n+  if (template_id)\n+    {\n+      TREE_OPERAND (template_id, 0) = op;\n+      /* Send the unresolved expr, just like we do in\n+\tcp_parser_splice_expression. */\n+      if (SPLICE_EXPR_MEMBER_ACCESS_P (t))\n+\treturn template_id;\n+      op = tsubst_expr (template_id, args, complain, in_decl);\n+    }\n+\n   if (SPLICE_EXPR_ADDRESS_P (t))\n     {\n       if (BASELINK_P (op))\n@@ -21450,6 +21467,9 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)\n \ttree templ = TREE_OPERAND (t, 0);\n \ttree targs = TREE_OPERAND (t, 1);\n \n+\tif (TREE_CODE (templ) == SPLICE_EXPR)\n+\t  return tsubst_splice_expr (t, args, complain, in_decl);\n+\n \tif (no_name_lookup_flag)\n \t  templ = tsubst_name (templ, args, complain, in_decl);\n \telse\ndiff --git a/gcc/cp/reflect.cc b/gcc/cp/reflect.cc\nindex b36c4be4273..528adc747de 100644\n--- a/gcc/cp/reflect.cc\n+++ b/gcc/cp/reflect.cc\n@@ -9016,15 +9016,16 @@ check_splice_expr (location_t loc, location_t start_loc, tree t,\n   /* Class members may not be implicitly referenced through a splice.\n      But taking the address is fine, and so is class member access a la\n      foo.[: ^^S::bar :].  */\n-  if (!address_p\n-      && !member_access_p\n-      && DECL_P (t)\n-      && DECL_NONSTATIC_MEMBER_P (t))\n+  if (!address_p && !member_access_p)\n     {\n-      if (complain_p)\n-\terror_at (loc, \"cannot implicitly reference a class member %qD \"\n-\t\t  \"through a splice\", t);\n-      return false;\n+      tree r = maybe_get_first_fn (t);\n+      if (DECL_P (r) && DECL_NONSTATIC_MEMBER_P (r))\n+\t{\n+\t  if (complain_p)\n+\t    error_at (loc, \"cannot implicitly reference a class member %qD \"\n+\t\t      \"through a splice\", r);\n+\t  return false;\n+\t}\n     }\n \n   /* One can't access a class template or alias template with . or ->.  */\n@@ -9113,7 +9114,7 @@ check_splice_expr (location_t loc, location_t start_loc, tree t,\n \t\t  auto_diagnostic_group d;\n \t\t  error_at (loc, \"expected a reflection of a function \"\n \t\t\t    \"template\");\n-\t\t  inform_tree_category (t);\n+\t\t  inform_tree_category (maybe_get_first_fn (t));\n \t\t}\n \t      return false;\n \t    }\n@@ -9134,7 +9135,7 @@ check_splice_expr (location_t loc, location_t start_loc, tree t,\n \t  return false;\n \t}\n       gcc_checking_assert (reflection_function_template_p (t)\n-\t\t\t   || get_template_info (t)\n+\t\t\t   || get_template_info (MAYBE_BASELINK_FUNCTIONS (t))\n \t\t\t   || TREE_CODE (t) == TEMPLATE_ID_EXPR\n \t\t\t   || variable_template_p (t)\n \t\t\t   || dependent_splice_p (t));\ndiff --git a/gcc/testsuite/g++.dg/reflect/member19.C b/gcc/testsuite/g++.dg/reflect/member19.C\nindex 8523ee55215..765b456a1f2 100644\n--- a/gcc/testsuite/g++.dg/reflect/member19.C\n+++ b/gcc/testsuite/g++.dg/reflect/member19.C\n@@ -92,28 +92,19 @@ baz ()\n   static_assert (s.a <43> == 43);\n   static_assert (s.template [:members_of (^^A, uctx)[0]:] <44> == 44);\n   static_assert (s.template [:members_of (^^A, uctx)[0]:] <45> == 45);\n-#if 0\n-  // TODO: This doesn't work yet.\n   static_assert (s.template [:^^A::a:] <44> == 44);\n   static_assert (s.template [:^^A::a:] <45> == 45);\n-#endif\n   constexpr T t;\n   static_assert (t.a <42> == 142);\n   static_assert (t.a <43> == 143);\n   static_assert (t.template [:members_of (^^A, uctx)[0]:] <44> == 44);\n   static_assert (t.template [:members_of (^^A, uctx)[0]:] <45> == 45);\n-#if 0\n-  // TODO: This doesn't work yet.\n   static_assert (t.template [:^^A::a:] <44> == 44);\n   static_assert (t.template [:^^A::a:] <45> == 45);\n-#endif\n   static_assert (t.template [:members_of (^^B, uctx)[0]:] <44> == 144);\n   static_assert (t.template [:members_of (^^B, uctx)[0]:] <45> == 145);\n-#if 0\n-  // TODO: This doesn't work yet.\n   static_assert (t.template [:^^B::a:] <44> == 144);\n   static_assert (t.template [:^^B::a:] <45> == 145);\n-#endif\n }\n \n template <typename A, typename B>\n@@ -125,28 +116,19 @@ qux ()\n   static_assert (s.template a <43> == 43);\n   static_assert (s.template [:members_of (^^A, uctx)[0]:] <44> == 44);\n   static_assert (s.template [:members_of (^^A, uctx)[0]:] <45> == 45);\n-#if 0\n-  // TODO: This doesn't work yet.\n   static_assert (s.template [:^^A::a:] <44> == 44);\n   static_assert (s.template [:^^A::a:] <45> == 45);\n-#endif\n   constexpr B t;\n   static_assert (t.template a <42> == 142);\n   static_assert (t.template a <43> == 143);\n   static_assert (t.template [:members_of (^^A, uctx)[0]:] <44> == 44);\n   static_assert (t.template [:members_of (^^A, uctx)[0]:] <45> == 45);\n-#if 0\n-  // TODO: This doesn't work yet.\n   static_assert (t.template [:^^A::a:] <44> == 44);\n   static_assert (t.template [:^^A::a:] <45> == 45);\n-#endif\n   static_assert (t.template [:members_of (^^B, uctx)[0]:] <44> == 144);\n   static_assert (t.template [:members_of (^^B, uctx)[0]:] <45> == 145);\n-#if 0\n-  // TODO: This doesn't work yet.\n   static_assert (t.template [:^^B::a:] <44> == 144);\n   static_assert (t.template [:^^B::a:] <45> == 145);\n-#endif\n }\n \n void\ndiff --git a/gcc/testsuite/g++.dg/reflect/splice13.C b/gcc/testsuite/g++.dg/reflect/splice13.C\nnew file mode 100644\nindex 00000000000..f432b50f812\n--- /dev/null\n+++ b/gcc/testsuite/g++.dg/reflect/splice13.C\n@@ -0,0 +1,54 @@\n+// PR c++/124794\n+// { dg-do compile { target c++26 } }\n+// { dg-additional-options \"-freflection -Wno-error=missing-template-keyword\" }\n+\n+struct C { template <class T> void f(T); };\n+\n+void (C::*p0)(int) = &template[:^^C::f:]<int>;\n+void (C::*p1)(int) = template[:^^C::f:]<int>; // { dg-error \"cannot implicitly reference a class member\" }\n+void (C::*p2)(int) = &template[:^^C::f:];\n+void (C::*p3)(int) = template[:^^C::f:]; // { dg-error \"cannot implicitly reference a class member\" }\n+void (C::*p4)(int) = &[:^^C::f:]<int>; // { dg-warning \"keyword before dependent template name\" }\n+void (C::*p5)(int) = [:^^C::f:]<int>; // { dg-error \"cannot implicitly reference a class member\" }\n+void (C::*p6)(int) = &[:^^C::f:]; // { dg-warning \"keyword before dependent template name\" }\n+void (C::*p7)(int) = [:^^C::f:]; // { dg-error \"cannot implicitly reference a class member\" }\n+\n+template <auto r> void (C::*tp0)(int) = &template[:r:]<int>;\n+template <auto r> void (C::*tp1)(int) = template[:r:]<int>; // { dg-error \"cannot implicitly reference a class member\" }\n+template <auto r> void (C::*tp2)(int) = &template[:r:];\n+template <auto r> void (C::*tp3)(int) = template[:r:]; // { dg-error \"cannot implicitly reference a class member\" }\n+/* tp4 and tp5 intentionally omitted as they are not applicable in a template context */\n+template <auto r> void (C::*tp6)(int) = &[:r:];\n+template <auto r> void (C::*tp7)(int) = [:r:]; // { dg-error \"cannot implicitly reference a class member\" }\n+\n+static_assert((\n+    tp0<^^C::f>,\n+    tp1<^^C::f>,\n+    tp2<^^C::f>,\n+    tp3<^^C::f>,\n+    tp6<^^C::f>,\n+    tp7<^^C::f>,\n+    true));\n+\n+struct Base1{\n+  template<class T>\n+  constexpr T f(T x) {\n+    return x;\n+  }\n+};\n+struct Base2: Base1 {\n+  template<class T>\n+  constexpr T g(T x) {\n+    return x;\n+  }\n+};\n+struct Base3: Base1, Base2 {}; // { dg-warning \"inaccessible\" }\n+\n+static_assert(Base1{}.[:^^Base1::f:](4) == 4); // { dg-warning \"keyword before dependent template name\" }\n+static_assert(Base1{}.[:^^Base1::f:]<int>(13) == 13); // { dg-warning \"keyword before dependent template name\" }\n+static_assert(Base3{}.[:^^Base2::g:](42) == 42); // { dg-warning \"keyword before dependent template name\" }\n+static_assert(Base3{}.[:^^Base2::g:]<int>(67) == 67); // { dg-warning \"keyword before dependent template name\" }\n+constexpr int invalid1 = Base3{}.[:^^Base2::f:]; // { dg-error \"cannot resolve overloaded function\" }\n+// { dg-warning \"keyword before dependent template name\" \"\" { target *-*-* } .-1 }\n+constexpr int invalid2 = Base3{}.[:^^Base1::f:]; // { dg-error \"cannot resolve overloaded function\" }\n+// { dg-warning \"keyword before dependent template name\" \"\" { target *-*-* } .-1 }\n","prefixes":["v4"]}