{"id":2229966,"url":"http://patchwork.ozlabs.org/api/1.1/patches/2229966/?format=json","web_url":"http://patchwork.ozlabs.org/project/gcc/patch/20260429003833.1373414-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":"<20260429003833.1373414-1-feedabl3@gmail.com>","date":"2026-04-29T00:07:15","name":"[v5] c++/reflection: ICE on member function template splicing [PR124794]","commit_ref":null,"pull_url":null,"state":"new","archived":false,"hash":"26e5053b9aefa9724a38615bed34e48eaab405d0","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/20260429003833.1373414-1-feedabl3@gmail.com/mbox/","series":[{"id":501966,"url":"http://patchwork.ozlabs.org/api/1.1/series/501966/?format=json","web_url":"http://patchwork.ozlabs.org/project/gcc/list/?series=501966","date":"2026-04-29T00:07:15","name":"[v5] c++/reflection: ICE on member function template splicing [PR124794]","version":5,"mbox":"http://patchwork.ozlabs.org/series/501966/mbox/"}],"comments":"http://patchwork.ozlabs.org/api/patches/2229966/comments/","check":"pending","checks":"http://patchwork.ozlabs.org/api/patches/2229966/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=HwzlXYZj;\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=HwzlXYZj","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.49"],"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 4g4z391Z88z1xvV\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 29 Apr 2026 10:39:27 +1000 (AEST)","from vm01.sourceware.org (localhost [127.0.0.1])\n\tby sourceware.org (Postfix) with ESMTP id 70A874BB58D2\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 29 Apr 2026 00:39:24 +0000 (GMT)","from mail-wm1-f49.google.com (mail-wm1-f49.google.com\n [209.85.128.49])\n by sourceware.org (Postfix) with ESMTPS id 2A79C4BB24D7\n for <gcc-patches@gcc.gnu.org>; Wed, 29 Apr 2026 00:38:54 +0000 (GMT)","by mail-wm1-f49.google.com with SMTP id\n 5b1f17b1804b1-4838c15e3cbso109985085e9.3\n for <gcc-patches@gcc.gnu.org>; Tue, 28 Apr 2026 17:38:54 -0700 (PDT)","from 7a38 ([2a02:8308:900b:fc00::2690])\n by smtp.gmail.com with ESMTPSA id\n 5b1f17b1804b1-48a7bc79ab4sm20007995e9.9.2026.04.28.17.38.51\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Tue, 28 Apr 2026 17:38:52 -0700 (PDT)"],"DKIM-Filter":["OpenDKIM Filter v2.11.0 sourceware.org 70A874BB58D2","OpenDKIM Filter v2.11.0 sourceware.org 2A79C4BB24D7"],"DMARC-Filter":"OpenDMARC Filter v1.4.2 sourceware.org 2A79C4BB24D7","ARC-Filter":"OpenARC Filter v1.0.0 sourceware.org 2A79C4BB24D7","ARC-Seal":"i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1777423134; cv=none;\n b=XiyJ48Fblz2qDpQGb0IwCku2ynSg78ylFzO3K5bc5atJdy/i554D7uDgWWseBiG4ywrRw51Vqpug3WV6SrpmLr1dTmjRP5BysDCuTJf1g1pZVJa0lSrmWU48P46kqdFFSl4qN2/07rgZBUnrqCTrSG8SNH4gW+Upf9eMu0nn+Qk=","ARC-Message-Signature":"i=1; a=rsa-sha256; d=sourceware.org; s=key;\n t=1777423134; c=relaxed/simple;\n bh=Rs3+xW5fa9lIft+CTeK/qwFzIvazXxu/q/9Vzav6SdA=;\n h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version;\n b=Ob7vweTfeCuNZG7cXT3/19rLYrYCT2ItJzendQgNz14eMQIThScx1dTW1IOeiUFn3Wu8e4hyWTvmhXF5fPCYzQHY1LsHHPcj2HqxQFOHnpV80MSpJi+KdxhM99Qph5dzHBdNInFgY96nN+4XocaWR5qCRSKjl+CgS0Thvj/nAJI=","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=1777423133; x=1778027933; 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=ysTs0qbf4FmaQ2ogWEc/bt+WZft3QpzB+GVRzQz4HTc=;\n b=HwzlXYZjftazC95N4ORE6bQmrMkF6azDU5ClLDZhS2N5rfaWMqmKE1n4H0djX6IH+R\n ekRwAhl8rjZKgJa6m0/aEM0ekahwThx4zgb90gUbd28jQmJhEsaLk7WQCnWq8Q++lFYK\n 6OF1f/grn+NIQwhbaqBO2vSMoHR60al2sYXmo7zGvE57Cjm2mXXLhKETw+pVrQIB0nvF\n zrCu4dkvu+hT6YfqPxaMHI6x2BSKSlkN1g8WRkvE1Xf9lwEbnjV3gyKLDz2XNNlpkh3R\n GrpvfNBu9evfANMo4Uz21LMfzgBlTscw57lOz2SM62fNemfKeSmuhezOdslRZTXAzhl0\n blYQ==","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1777423133; x=1778027933;\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=ysTs0qbf4FmaQ2ogWEc/bt+WZft3QpzB+GVRzQz4HTc=;\n b=tMW0cnT7cXanky5zZQ7DRHSlSSJiigCDv0fk33h6ZLaNB3ww0Xu//Y2ci5+TsDLnQc\n dj6C4UnU/cBAFPEFJcrTCaMebwQ7SRmEPz/Ti5EjnhGuDPE1rfoeNFGSjvYaMYX8sOor\n xbdlNgpeVrdaZ2Hy3q2V0RGMa7NzhehANedXrZZcH5jwVZl0/eN9t6lZOL7K2Mz4Xm2g\n nwjbPjpO/w5H33cBLAedzzqPA9eP2+DLktmalXTUwtfxRdpvJSKQe0SGS72rPmyCUkvj\n orrfHlKeL8A74jLna1W7tJUs82Du2J4F5OcBEf40VuZ28Wi915brCR21n+e2PbxEwP1T\n bGFA==","X-Gm-Message-State":"AOJu0YwNLJ+Hxdam+XDhXB7RHZQd2NZrxlBjjGYLiJ0U6/A6iAflaQ+K\n MT26F/JmZ9n/75kQtYnheG4dsKvQJ94pxSDKH84Ro7bfPWF6NFDEcEd2WpcZ0A==","X-Gm-Gg":"AeBDieuJEvKXsiaxJ0WDhLhhA/yOkt2AA0axg2svt9voNMQRKue8Yipy+SKHj95YFPT\n x2l9AH4wR/nIScN7g1oSFXbXRwqEfB5B322c5coDSdt0ix9Q/vYwhANJ+XjRyFBld9peGbHPd3w\n 9UzdEGu5VPzCXlvSW3PA1mw4fR10VcRyBrsICxJwDxJcE8U2KrwCwjpgky4FlPE+Nu8GwbpMhWF\n Y+ehY47zKx/HRc908nxSp8BVRsSJpRDrSWQKTW2voEB6RlcaXIwCOHJft93juZb3ztwO11p+uzM\n 8WXv45wDtmm0z2PeqKA4lCGQuLEnsMVZnqCF2Y8Zi1bjsc53+KqltvFTVZLgopTPPRmt8x8fEV4\n GBRHyNGOoetzkwPpRp2lT5BxvNIpRq7bzptQcqPWBQR5yckVctIvYbzlD3Fim7xkzaooBCZZcyy\n FpBOGA5TeLYHY+lPmbHRg=","X-Received":"by 2002:a05:600c:8b54:b0:48a:5339:ef0e with SMTP id\n 5b1f17b1804b1-48a77ae5405mr89483715e9.3.1777423132741;\n Tue, 28 Apr 2026 17:38:52 -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 v5] c++/reflection: ICE on member function template splicing\n [PR124794]","Date":"Wed, 29 Apr 2026 03:07:15 +0300","Message-ID":"<20260429003833.1373414-1-feedabl3@gmail.com>","X-Mailer":"git-send-email 2.54.0","In-Reply-To":"<5ce36acd-2cd3-4bc0-9b98-1f63ca240704@gmail.com>","References":"<5ce36acd-2cd3-4bc0-9b98-1f63ca240704@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":"Please note the new test (splice14.C), new paragraph in the commit msg,\nand a new issue being fixed.\n\n>>     (tsubst_expr): Defer to tsubst_splice_expr when thetemplate part of\n>>     TEMPLATE_ID_EXPR is a SPLICE_EXPR\n>>     * reflect.cc (check_splice_expr): Add handling for BASELINKs\n>\n>I still think MAYBE_BASELINK_FUNCTIONS or maybe_get_first_fn at the top of check_splice_expr can replace changing multiple places in the function.  Nothing in this function is interested in a BASELINK.\n\nAlright, you win: after realizing I also want to handle TEMPLATE_ID_EXPR\nthere too, stripping stuff at the top seems very reasonable now.\nmaybe_get_first_fn doesn't exactly work, though, anymore: we also want\nto strip TEMPLATE_ID_EXPRs off of types and variables, too.\n\n>>>> The inform_tree_category call doesn't need maybe_get_first_fn because\n>>>> it already does it, and only the get_template_info check needs to strip\n>>>> BASELINKs.\n>>>\n>>> The tricky thing here is that it gets the location first, an only after that strips, so the location of the BASELINK(at the callsite) and not of the entity gets emitted in the end. \n>>\n>> It does currently, but is there any reason for that?  Why not move taking the location to after the strip?\n>>\n>> Jason \n>\n>I don't see a reason for that either, I can try moving that and see if tests start failing.\n\nAfter stripping stuff at the top, this is unnecessary (but still possible).\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\ncheck_splice_expr now also accepts TEMPLATE_ID_EXPRs in tsubst_splice_expr;\nthis is uniform with cp_parser_splice_expression, and required in order to\nhandle `template[:dep:]<>` where `dep` does not reflect a template.\n\n\tPR c++/124794\n\tPR c++/125069\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 the template 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\t* g++.dg/reflect/splice14.C: New test.\n---\n gcc/cp/parser.cc                        | 21 +++++---\n gcc/cp/pt.cc                            | 49 ++++++++++++++---\n gcc/cp/reflect.cc                       | 14 +++--\n gcc/testsuite/g++.dg/reflect/member19.C | 18 -------\n gcc/testsuite/g++.dg/reflect/splice13.C | 70 +++++++++++++++++++++++++\n gcc/testsuite/g++.dg/reflect/splice14.C | 34 ++++++++++++\n 6 files changed, 170 insertions(+), 36 deletions(-)\n create mode 100644 gcc/testsuite/g++.dg/reflect/splice13.C\n create mode 100644 gcc/testsuite/g++.dg/reflect/splice14.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..ff39a2f2d3f 100644\n--- a/gcc/cp/pt.cc\n+++ b/gcc/cp/pt.cc\n@@ -16926,7 +16926,34 @@ 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 op = tsubst_expr (TREE_OPERAND (t, 0), args, complain, in_decl);\n+  tree template_id = NULL_TREE;\n+  auto apply_template = [&](tree templ)\n+    {\n+      if (!template_id)\n+\treturn templ;\n+      template_id = copy_node (template_id);\n+      tree ret = template_id;\n+\n+      /* follow the example of lookup_template_function, but for all\n+\t templates. */\n+      if (BASELINK_P (templ))\n+\t{\n+\t  ret = copy_node (templ);\n+\t  BASELINK_FUNCTIONS (ret) = template_id;\n+\t  templ = BASELINK_FUNCTIONS (templ);\n+\t}\n+      TREE_OPERAND (template_id, 0) = templ;\n+      return ret;\n+    };\n+\n+  if (TREE_CODE (t) == TEMPLATE_ID_EXPR)\n+    {\n+      template_id = t;\n+      t = TREE_OPERAND (t, 0);\n+    }\n+\n+  tree op = tsubst_expr (TREE_OPERAND (t, 0), args,\n+\t\t\t (complain & ~tf_no_name_lookup), in_decl);\n   if (op == error_mark_node)\n     return error_mark_node;\n   op = splice (op);\n@@ -16944,8 +16971,12 @@ tsubst_splice_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)\n \tSET_SPLICE_EXPR_TEMPLATE_P (op, true);\n       if (SPLICE_EXPR_TARGS_P (t))\n \tSET_SPLICE_EXPR_TARGS_P (op, true);\n-      return op;\n+      return apply_template (op);\n     }\n+\n+  /* We have to form a template-id for checking too */\n+  op = apply_template (op);\n+\n   if (SPLICE_EXPR_EXPRESSION_P (t)\n       && !check_splice_expr (input_location, UNKNOWN_LOCATION, op,\n \t\t\t     SPLICE_EXPR_ADDRESS_P (t),\n@@ -16955,6 +16986,11 @@ 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+  /* For the template-id case, we have to substitute only after checking, to\n+     reject the case where the template part is a type.  */\n+  if (template_id)\n+    op = tsubst_expr (op, args, complain, in_decl);\n+\n   if (SPLICE_EXPR_ADDRESS_P (t))\n     {\n       if (BASELINK_P (op))\n@@ -21449,11 +21485,12 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)\n \ttree object;\n \ttree templ = TREE_OPERAND (t, 0);\n \ttree targs = TREE_OPERAND (t, 1);\n+\ttsubst_flags_t complain_lookup = complain | no_name_lookup_flag;\n \n-\tif (no_name_lookup_flag)\n-\t  templ = tsubst_name (templ, args, complain, in_decl);\n-\telse\n-\t  templ = tsubst_expr (templ, args, complain, in_decl);\n+\tif (TREE_CODE (templ) == SPLICE_EXPR)\n+\t  return tsubst_splice_expr (t, args, complain_lookup, in_decl);\n+\n+\ttempl = tsubst_expr (templ, args, complain_lookup, in_decl);\n \n \tif (targs)\n \t  targs = tsubst_template_args (targs, args, complain, in_decl);\ndiff --git a/gcc/cp/reflect.cc b/gcc/cp/reflect.cc\nindex b36c4be4273..bbe4bf03c47 100644\n--- a/gcc/cp/reflect.cc\n+++ b/gcc/cp/reflect.cc\n@@ -8962,6 +8962,12 @@ check_splice_expr (location_t loc, location_t start_loc, tree t,\n \t\t   bool address_p, bool member_access_p, bool template_p,\n \t\t   bool targs_p, bool complain_p)\n {\n+  t = MAYBE_BASELINK_FUNCTIONS (t);\n+  tree expr = t;\n+  if (TREE_CODE (t) == TEMPLATE_ID_EXPR)\n+    t = TREE_OPERAND (t, 0);\n+  t = OVL_FIRST (t);\n+\n   /* We may not have gotten an expression.  */\n   if (TREE_CODE (t) == TYPE_DECL\n       || TREE_CODE (t) == NAMESPACE_DECL\n@@ -8997,7 +9003,7 @@ check_splice_expr (location_t loc, location_t start_loc, tree t,\n   /* [expr.prim.splice]/2 For a splice-expression of the form\n      splice-specifier, the expression is ill-formed if it is:  */\n   /* -- a constructor or a destructor  */\n-  if (TREE_CODE (t) == FUNCTION_DECL\n+  if (TREE_CODE (STRIP_TEMPLATE (t)) == FUNCTION_DECL\n       && (DECL_CONSTRUCTOR_P (t) || DECL_DESTRUCTOR_P (t)))\n     {\n       if (complain_p)\n@@ -9036,7 +9042,7 @@ check_splice_expr (location_t loc, location_t start_loc, tree t,\n     }\n \n   if (member_access_p\n-      && !valid_splice_for_member_access_p (t, /*decls_only_p=*/false))\n+      && !valid_splice_for_member_access_p (expr, /*decls_only_p=*/false))\n     {\n       if (complain_p)\n \terror_at (loc, \"cannot use %qE to access a class member\", t);\n@@ -9134,8 +9140,8 @@ 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   || TREE_CODE (t) == TEMPLATE_ID_EXPR\n+\t\t\t   || get_template_info (expr)\n+\t\t\t   || TREE_CODE (expr) == TEMPLATE_ID_EXPR\n \t\t\t   || variable_template_p (t)\n \t\t\t   || dependent_splice_p (t));\n     }\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..f72e3f83373\n--- /dev/null\n+++ b/gcc/testsuite/g++.dg/reflect/splice13.C\n@@ -0,0 +1,70 @@\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{\n+  template <class T> void f(T);\n+  void g(int);\n+};\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+template <auto r> void (C::*tp0n)(int) = &template[:r:]<int>; // { dg-error \"no matches converting function\" }\n+template <auto r> void (C::*tp1n)(int) = template[:r:]<int>; // { dg-error \"cannot implicitly reference a class member\" }\n+template <auto r> void (C::*tp2n)(int) = &template[:r:]; // { dg-error \"expected a reflection of a function template\" }\n+template <auto r> void (C::*tp3n)(int) = template[:r:]; // { dg-error \"cannot implicitly reference a class member\" }\n+/* tp4u and tp5u intentionally omitted as they are not applicable in a template context */\n+template <auto r> void (C::*tp6n)(int) = &[:r:];\n+template <auto r> void (C::*tp7n)(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+    tp0n<^^C::g>,\n+    tp1n<^^C::g>,\n+    tp2n<^^C::g>,\n+    tp3n<^^C::g>,\n+    tp6n<^^C::g>,\n+    tp7n<^^C::g>,\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 }\ndiff --git a/gcc/testsuite/g++.dg/reflect/splice14.C b/gcc/testsuite/g++.dg/reflect/splice14.C\nnew file mode 100644\nindex 00000000000..a3eb13c5f69\n--- /dev/null\n+++ b/gcc/testsuite/g++.dg/reflect/splice14.C\n@@ -0,0 +1,34 @@\n+// PR c++/125069\n+// { dg-do compile { target c++26 } }\n+// { dg-additional-options \"-freflection -Wno-error=missing-template-keyword\" }\n+\n+#include <meta>\n+struct x{ x(auto); };\n+\n+constexpr auto ac = std::meta::access_context::unchecked();\n+\n+template<auto r>\n+constexpr auto t = (\n+  [:r:],  // { dg-error \"cannot use constructor or destructor\" }\n+  &[:r:],  // { dg-error \"cannot use constructor or destructor\" }\n+  template [:r:], // { dg-error \"cannot use constructor or destructor\" }\n+  &template [:r:], // { dg-error \"cannot use constructor or destructor\" }\n+  template [:r:]<int>, // { dg-error \"cannot use constructor or destructor\" }\n+  &template [:r:]<int>, // { dg-error \"cannot use constructor or destructor\" }\n+  1);\n+\n+\n+int main() {\n+  constexpr auto r = members_of(^^x, ac)[0];\n+\n+  t<r>;\n+\n+  [:r:];  // { dg-error \"cannot use constructor or destructor\" }\n+  &[:r:];  // { dg-error \"cannot use constructor or destructor\" }\n+  [:r:]<int>; // { dg-error \"cannot use constructor or destructor\" }\n+  &[:r:]<int>; // { dg-error \"cannot use constructor or destructor\" }\n+  template [:r:]; // { dg-error \"cannot use constructor or destructor\" }\n+  &template [:r:]; // { dg-error \"cannot use constructor or destructor\" }\n+  template [:r:]<int>; // { dg-error \"cannot use constructor or destructor\" }\n+  &template [:r:]<int>; // { dg-error \"cannot use constructor or destructor\" }\n+}\n","prefixes":["v5"]}