Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/1.1/patches/2221254/?format=api
{ "id": 2221254, "url": "http://patchwork.ozlabs.org/api/1.1/patches/2221254/?format=api", "web_url": "http://patchwork.ozlabs.org/project/gcc/patch/adat_NaPJs-bKBVb@redhat.com/", "project": { "id": 17, "url": "http://patchwork.ozlabs.org/api/1.1/projects/17/?format=api", "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": "<adat_NaPJs-bKBVb@redhat.com>", "date": "2026-04-08T19:35:24", "name": "[v2] c++/reflection: reject invalid template splice [PR123998]", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "f803a20c379b404447c553d0c7f5f9b14e1f7930", "submitter": { "id": 14370, "url": "http://patchwork.ozlabs.org/api/1.1/people/14370/?format=api", "name": "Marek Polacek", "email": "polacek@redhat.com" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/gcc/patch/adat_NaPJs-bKBVb@redhat.com/mbox/", "series": [ { "id": 499227, "url": "http://patchwork.ozlabs.org/api/1.1/series/499227/?format=api", "web_url": "http://patchwork.ozlabs.org/project/gcc/list/?series=499227", "date": "2026-04-08T19:35:24", "name": "[v2] c++/reflection: reject invalid template splice [PR123998]", "version": 2, "mbox": "http://patchwork.ozlabs.org/series/499227/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/2221254/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/2221254/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 (1024-bit key;\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=WksJCvIs;\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 (1024-bit key,\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=WksJCvIs", "sourceware.org; dmarc=pass (p=quarantine dis=none)\n header.from=redhat.com", "sourceware.org; spf=pass smtp.mailfrom=redhat.com", "server2.sourceware.org;\n arc=none smtp.remote-ip=170.10.133.124" ], "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 4frfPq5FwDz1yCv\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 09 Apr 2026 09:27:54 +1000 (AEST)", "from vm01.sourceware.org (localhost [127.0.0.1])\n\tby sourceware.org (Postfix) with ESMTP id 8EA474BA2E14\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 8 Apr 2026 23:27:50 +0000 (GMT)", "from us-smtp-delivery-124.mimecast.com\n (us-smtp-delivery-124.mimecast.com [170.10.133.124])\n by sourceware.org (Postfix) with ESMTP id 8F3164BA2E06\n for <gcc-patches@gcc.gnu.org>; Wed, 8 Apr 2026 23:27:14 +0000 (GMT)", "from mail-qk1-f199.google.com (mail-qk1-f199.google.com\n [209.85.222.199]) by relay.mimecast.com with ESMTP with STARTTLS\n (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id\n us-mta-567-H_ycHS6bONiXMnWArnUI-Q-1; Wed, 08 Apr 2026 15:35:29 -0400", "by mail-qk1-f199.google.com with SMTP id\n af79cd13be357-8d4c2906fdfso15017385a.2\n for <gcc-patches@gcc.gnu.org>; Wed, 08 Apr 2026 12:35:29 -0700 (PDT)", "from redhat.com ([2603:7000:9500:10::1db4])\n by smtp.gmail.com with ESMTPSA id\n af79cd13be357-8d2a8c22d0esm1835643085a.41.2026.04.08.12.35.26\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Wed, 08 Apr 2026 12:35:26 -0700 (PDT)" ], "DKIM-Filter": [ "OpenDKIM Filter v2.11.0 sourceware.org 8EA474BA2E14", "OpenDKIM Filter v2.11.0 sourceware.org 8F3164BA2E06" ], "DMARC-Filter": "OpenDMARC Filter v1.4.2 sourceware.org 8F3164BA2E06", "ARC-Filter": "OpenARC Filter v1.0.0 sourceware.org 8F3164BA2E06", "ARC-Seal": "i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1775690834; cv=none;\n b=gFRxoyFmQSYVzRQoH9umYw71XA3l2+XLRD3ZjVCv3jnEyvAFBesRAL3i2wRaFqz+lRKNcW+VS6U6sFe9eae5OiXvRDPN0g5pfti5ymDbBZQu4sjsarFxGRbyozBuhFmwCVy+NfMrduWjQa7chmobKHKXCOjjzXkJLTONtGiWSRs=", "ARC-Message-Signature": "i=1; a=rsa-sha256; d=sourceware.org; s=key;\n t=1775690834; c=relaxed/simple;\n bh=hHk5WZl/zGsfQqwZWKPjFW2rbZfRxep475dEpb++Gys=;\n h=DKIM-Signature:Date:From:To:Subject:Message-ID:MIME-Version;\n b=POlb0JeFV9w37jo/2/pvOPgw4eD1LCLHvRl1W7RwFKPHaOs8BtmgL8o3F888g8aZiWM5rjRUm5TND0GV+lNMKn69H31GWH6EU32l3ITpaHdQpPtHDUXUgYHCL6NYRWcoUiHDceSqkQu8EQC83eEtevR5hXemPjq8xbOkGHU0ros=", "ARC-Authentication-Results": "i=1; server2.sourceware.org", "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n s=mimecast20190719; t=1775690834;\n h=from:from:reply-to:subject:subject:date:date:message-id:message-id:\n to:to:cc:cc:mime-version:mime-version:content-type:content-type:\n in-reply-to:in-reply-to:references:references;\n bh=udR1U7YhE354dpqEagzq2elVm8/a0FJIA+GgplSOKNo=;\n b=WksJCvIsYho1YgTO7sElaNUsfGl14dmh6ra48+uhbBZ+t67z6lTZ5Gba21kVYFybK0vsaE\n XctQW+6BYzXbPut8mpcAsOgyZR8fHY69c2K1SPWp2dFHkTJKfT/csXE6M1By0VAoKurD3L\n 7zGgEl5Sk7p2Vk/5wKhiMOnphpmtjlM=", "X-MC-Unique": "H_ycHS6bONiXMnWArnUI-Q-1", "X-Mimecast-MFC-AGG-ID": "H_ycHS6bONiXMnWArnUI-Q_1775676928", "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1775676928; x=1776281728;\n h=user-agent:in-reply-to:content-disposition:mime-version:references\n :message-id:subject:cc:to:from:date:x-gm-gg:x-gm-message-state:from\n :to:cc:subject:date:message-id:reply-to;\n bh=udR1U7YhE354dpqEagzq2elVm8/a0FJIA+GgplSOKNo=;\n b=nBlf5ezs7VIOAIA2amsJgZqbeotEKG/JKQYm0rE41s/nF1bjL3WOfIMPoaWSSdVP4S\n Z8SaWBgi6PGUfzrCyyEirn8lKf5+P4K/qYRb9XZQNIHrLUuK1KvWLcbyPCasi7eTc5nr\n mdfG7s6dgqNs7QHD1+nUOgmjeGw1mrOsFh2w9fwBtfpFM6cSA6vzCgRMGmPMEqdOg8Ys\n MnSljeMPzxhxz0HCdqi5wzInTDKWL0vgqJpf7DWI7KUYIOLHF7KRYpLpFJZH5/q8xzUV\n 8aAxo4fLcBAnbhv6rg4jZOVAbI46gReikO01TaPPVyNd8FxqFSoSLveMMVuYyYax7XB5\n kgwQ==", "X-Gm-Message-State": "AOJu0YyIEExVSr1LjAm9zLPJtr2I/henYwOmmv5UH+HS/hp8c669buQ0\n 7Guk8za3ITIejJ/8R3p8z48poPesLOKo+OtkVRA7EfLFLuf8+xoz++yT1lSZa3uJ4Heq1CHr1M6\n NrB+A+NNvl/H1PVqeqrT+JfHoy/k1/LgeGYsSIs/Yy2/WCbcQ8Dehk49nq6s=", "X-Gm-Gg": "AeBDies3Gn0AOzjPg/CSryXYA8tlZMiIAb0vWAB8F9cWCmjp/+nNelbTfBsx3xJUf8S\n tQldHMExXg87DVpJjwaY4lCwRvj3/AXVO8c/DfnZT+iaQc9tixTEmDKRzcT2W9lclqcfwBDqFtf\n m4OvKIIGNtjg9PMSPyP7bXw2s7hxyNK0bjnliz2n2Rf6sG6SSNblEEmd7Lk6XPRTv5HeNJ1Z9eD\n u/ZtkemykuG1KMo2jhZTqiu7fZ0SeC5UjnFD0DVQ0kmQ9w89L/pgFuNrCGMXcHy8+z32gAPl7hl\n dg9h0G48ajiGCGlpLw11vFfd66L9c9N5nYOyfOliRTTKTfMewjFQ+b2bkjfzSXGXbBCT9aQMenJ\n /4Q==", "X-Received": [ "by 2002:a05:620a:462c:b0:8d6:874c:a762 with SMTP id\n af79cd13be357-8d6874ca9c4mr2388232685a.54.1775676928017;\n Wed, 08 Apr 2026 12:35:28 -0700 (PDT)", "by 2002:a05:620a:462c:b0:8d6:874c:a762 with SMTP id\n af79cd13be357-8d6874ca9c4mr2388225885a.54.1775676927224;\n Wed, 08 Apr 2026 12:35:27 -0700 (PDT)" ], "Date": "Wed, 8 Apr 2026 15:35:24 -0400", "From": "Marek Polacek <polacek@redhat.com>", "To": "Jason Merrill <jason@redhat.com>", "Cc": "GCC Patches <gcc-patches@gcc.gnu.org>, Jakub Jelinek <jakub@redhat.com>", "Subject": "[PATCH v2] c++/reflection: reject invalid template splice [PR123998]", "Message-ID": "<adat_NaPJs-bKBVb@redhat.com>", "References": "<20260320205155.212366-1-polacek@redhat.com>\n <735f0b6a-be78-4608-b8cf-e6293a254d5c@redhat.com>", "MIME-Version": "1.0", "In-Reply-To": "<735f0b6a-be78-4608-b8cf-e6293a254d5c@redhat.com>", "User-Agent": "Mutt/2.3.1 (2026-03-20)", "X-Mimecast-Spam-Score": "0", "X-Mimecast-MFC-PROC-ID": "P8foPk8Awg5e945V4HW48YE059ABqaWEDADGkGxUiXA_1775676928", "X-Mimecast-Originator": "redhat.com", "Content-Type": "text/plain; charset=us-ascii", "Content-Disposition": "inline", "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": "On Thu, Apr 02, 2026 at 05:41:38PM -0400, Jason Merrill wrote:\n> On 3/20/26 4:51 PM, Marek Polacek wrote:\n> > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?\n> > \n> > -- >8 --\n> > When we have \"template [:R:]\" without template arguments, the\n> > splice has to designate a function template. E.g.,\n> > \n> > void foo (int);\n> > template [: ^^foo :] (0); // invalid\n> > \n> > We check this in cp_parser_splice_expression. But when the splice\n> > is dependent, we don't check it when instantiating, thus missing\n> > the error in\n> > \n> > template [: N == 0 ? ^^foo : ^^:: :] (0);\n> > \n> > This patch introduces SPLICE_EXPR_TEMPLATE_P, and moves the checking\n> > into check_splice_expr.\n> > \n> > \tPR c++/123998\n> > \n> > gcc/cp/ChangeLog:\n> > \n> > \t* cp-tree.h (SPLICE_EXPR_TEMPLATE_P): Define.\n> > \t(SET_SPLICE_EXPR_TEMPLATE_P): Define.\n> > \t(check_splice_expr): Adjust.\n> > \t* parser.cc (cp_parser_splice_expression): Do\n> > \tSET_SPLICE_EXPR_TEMPLATE_P. Adjust the call to check_splice_expr.\n> > \tMove the template_p checking into check_splice_expr.\n> > \t* pt.cc (tsubst_splice_expr): Do SET_SPLICE_EXPR_TEMPLATE_P.\n> > \tAdjust the call to check_splice_expr.\n> > \t* reflect.cc (eval_constant_of): Adjust the call to\n> > \tcheck_splice_expr.\n> > \t(check_splice_expr): Two new bool parameters. Add the template_p\n> > \tchecking from cp_parser_splice_expression. Allow\n> > \tvariable_template_p in the assert.\n> > \n> > gcc/testsuite/ChangeLog:\n> > \n> > \t* g++.dg/reflect/splice5.C: Adjust dg-error.\n> > ---\n> > gcc/cp/cp-tree.h | 14 +++++++--\n> > gcc/cp/parser.cc | 40 +++++++-------------------\n> > gcc/cp/pt.cc | 7 ++++-\n> > gcc/cp/reflect.cc | 40 +++++++++++++++++++++++---\n> > gcc/testsuite/g++.dg/reflect/splice5.C | 7 ++---\n> > 5 files changed, 67 insertions(+), 41 deletions(-)\n> > \n> > diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h\n> > index ea3cb049785..e31f47b92af 100644\n> > --- a/gcc/cp/cp-tree.h\n> > +++ b/gcc/cp/cp-tree.h\n> > @@ -522,6 +522,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];\n> > TARGET_EXPR_ELIDING_P (in TARGET_EXPR)\n> > IF_STMT_VACUOUS_INIT_P (IF_STMT)\n> > TYPENAME_IS_RESOLVING_P (in TYPENAME_TYPE)\n> > + SPLICE_EXPR_TEMPLATE_P (in SPLICE_EXPR)\n> > 4: IDENTIFIER_MARKED (IDENTIFIER_NODEs)\n> > TREE_HAS_CONSTRUCTOR (in INDIRECT_REF, SAVE_EXPR, CONSTRUCTOR,\n> > \t CALL_EXPR, or FIELD_DECL).\n> > @@ -1979,6 +1980,15 @@ enum reflect_kind : addr_space_t {\n> > (SPLICE_EXPR_ADDRESS_P (TREE_CODE (NODE) == SPLICE_EXPR \\\n> > \t\t\t ? NODE : TREE_OPERAND (NODE, 0)) = (VAL))\n> > +/* True if this SPLICE_EXPR was decorated with 'template'. */\n> > +#define SPLICE_EXPR_TEMPLATE_P(NODE) \\\n> > + TREE_LANG_FLAG_3 (SPLICE_EXPR_CHECK (NODE))\n> > +\n> > +/* Helper macro to set SPLICE_EXPR_TEMPLATE_P. */\n> > +#define SET_SPLICE_EXPR_TEMPLATE_P(NODE, VAL) \\\n> > + (SPLICE_EXPR_TEMPLATE_P (TREE_CODE (NODE) == SPLICE_EXPR \\\n> > +\t\t\t ? NODE : TREE_OPERAND (NODE, 0)) = (VAL))\n> > +\n> > /* The expression in question for a SPLICE_SCOPE. */\n> > #define SPLICE_SCOPE_EXPR(NODE) \\\n> > (TYPE_VALUES_RAW (SPLICE_SCOPE_CHECK (NODE)))\n> > @@ -9414,8 +9424,8 @@ extern bool consteval_only_p (tree) ATTRIBUTE_PURE;\n> > extern bool compare_reflections (tree, tree) ATTRIBUTE_PURE;\n> > extern bool valid_splice_type_p (const_tree) ATTRIBUTE_PURE;\n> > extern bool valid_splice_scope_p (const_tree) ATTRIBUTE_PURE;\n> > -extern bool check_splice_expr (location_t, location_t, tree, bool, bool, bool)\n> > - ATTRIBUTE_PURE;\n> > +extern bool check_splice_expr (location_t, location_t, tree, bool, bool, bool,\n> > +\t\t\t bool, bool) ATTRIBUTE_PURE;\n> > extern tree make_splice_scope (tree, bool);\n> > extern bool dependent_splice_p (const_tree) ATTRIBUTE_PURE;\n> > extern tree reflection_mangle_prefix (tree, char [3]);\n> > diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc\n> > index 8d88dc9c312..cca2edc1e47 100644\n> > --- a/gcc/cp/parser.cc\n> > +++ b/gcc/cp/parser.cc\n> > @@ -6313,6 +6313,7 @@ cp_parser_splice_expression (cp_parser *parser, bool template_p,\n> > SET_SPLICE_EXPR_EXPRESSION_P (t);\n> > SET_SPLICE_EXPR_MEMBER_ACCESS_P (t, member_access_p);\n> > SET_SPLICE_EXPR_ADDRESS_P (t, address_p);\n> > + SET_SPLICE_EXPR_TEMPLATE_P (t, template_p);\n> > return t;\n> > }\n> > @@ -6325,38 +6326,17 @@ cp_parser_splice_expression (cp_parser *parser, bool template_p,\n> > /* Make sure this splice-expression produces an expression. */\n> > if (!check_splice_expr (loc, expr.get_start (), t, address_p,\n> > -\t\t\t member_access_p, /*complain=*/true))\n> > +\t\t\t member_access_p, template_p, targs_p,\n> > +\t\t\t /*complain=*/true))\n> > return error_mark_node;\n> > - if (template_p)\n> > - {\n> > - /* [expr.prim.splice] For a splice-expression of the form template\n> > -\t splice-specifier, the splice-specifier shall designate a function\n> > -\t template. */\n> > - if (!targs_p\n> > -\t && !really_overloaded_fn (t)\n> \n> Can we switch to using a different function name for testing for a\n> reflection of a function template, even if it just returns\n> really_overloaded_fn? This can be a later patch.\n\nSure. For 16 or 17?\n\n> > -\t && !dependent_splice_p (t))\n> > -\t{\n> > -\t auto_diagnostic_group d;\n> > -\t error_at (loc, \"expected a reflection of a function template\");\n> > -\t inform_tree_category (t);\n> > -\t return error_mark_node;\n> > -\t}\n> > - /* [expr.prim.splice] For a splice-expression of the form\n> > -\t template splice-specialization-specifier, the splice-specifier of the\n> > -\t splice-specialization-specifier shall designate a template. Since\n> > -\t we would have already complained, just check that we have a template. */\n> > - gcc_checking_assert (really_overloaded_fn (t)\n> > -\t\t\t || get_template_info (t)\n> > -\t\t\t || TREE_CODE (t) == TEMPLATE_ID_EXPR\n> > -\t\t\t || dependent_splice_p (t));\n> > - }\n> > - else if (/* No 'template' but there were template arguments? */\n> > -\t (targs_p\n> > -\t /* No 'template' but the splice-specifier designates a function\n> > -\t template? */\n> > -\t || really_overloaded_fn (t))\n> > -\t && warning_enabled_at (loc, OPT_Wmissing_template_keyword))\n> > + if (!template_p\n> > + /* No 'template' but there were template arguments? */\n> > + && (targs_p\n> > +\t /* No 'template' but the splice-specifier designates a function\n> > +\t template? */\n> > +\t || really_overloaded_fn (t))\n> > + && warning_enabled_at (loc, OPT_Wmissing_template_keyword))\n> > /* Were 'template' present, this would be valid code, so keep going. */\n> > missing_template_diag (loc, diagnostics::kind::pedwarn);\n> > diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc\n> > index 020a70c1112..913331c7b94 100644\n> > --- a/gcc/cp/pt.cc\n> > +++ b/gcc/cp/pt.cc\n> > @@ -16810,13 +16810,18 @@ tsubst_splice_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)\n> > \tSET_SPLICE_EXPR_MEMBER_ACCESS_P (op, true);\n> > if (SPLICE_EXPR_ADDRESS_P (t))\n> > \tSET_SPLICE_EXPR_ADDRESS_P (op, true);\n> > + if (SPLICE_EXPR_TEMPLATE_P (t))\n> > +\tSET_SPLICE_EXPR_TEMPLATE_P (op, true);\n> > return op;\n> > }\n> > + const bool targs_p = (TREE_CODE (t) == TEMPLATE_ID_EXPR\n> > +\t\t\t|| variable_template_p (op));\n> \n> Why || variable_template_p? Can't you have a variable template reflection\n> without targs?\n\nI was trying to avoid adding SPLICE_EXPR_TARGS_P but it's probably not\ngoing to work too well. And the == TEMPLATE_ID_EXPR check can never\nbe true.\n\nSo this patch adds SPLICE_EXPR_TARGS_P so that we can check we're\ncoming from [:R:]<args> in the SPLICE_EXPR. With that, I had to\nadd an error for DECL_TYPE_TEMPLATE_P in check_splice_expr to avoid\ncrashing in crash11.C.\n\nBootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?\n\n-- >8 --\nWhen we have \"template [:R:]\" without template arguments, the\nsplice has to designate a function template. E.g.,\n\n void foo (int);\n template [: ^^foo :] (0); // invalid\n\nWe check this in cp_parser_splice_expression. But when the splice\nis dependent, we don't check it when instantiating, thus missing\nthe error in\n\n template [: N == 0 ? ^^foo : ^^:: :] (0);\n\nThis patch introduces SPLICE_EXPR_TEMPLATE_P and SPLICE_EXPR_TARGS_P,\nand moves the checking into check_splice_expr. It also adds a missing\ncheck for DECL_TYPE_TEMPLATE_P in case we have a splice-expression of\nthe form template splice-specialization-specifier.\n\n\tPR c++/123998\n\ngcc/cp/ChangeLog:\n\n\t* cp-tree.h (SPLICE_EXPR_TEMPLATE_P): Define.\n\t(SET_SPLICE_EXPR_TEMPLATE_P): Define.\n\t(SPLICE_EXPR_TARGS_P): Define.\n\t(SET_SPLICE_EXPR_TARGS_P): Define.\n\t(check_splice_expr): Adjust.\n\t* parser.cc (cp_parser_splice_expression): Do\n\tSET_SPLICE_EXPR_TEMPLATE_P and SET_SPLICE_EXPR_TARGS_P. Adjust\n\tthe call to check_splice_expr. Move the template_p checking into\n\tcheck_splice_expr.\n\t* pt.cc (tsubst_splice_expr): Do SET_SPLICE_EXPR_TEMPLATE_P and\n\tSET_SPLICE_EXPR_TARGS_P. Adjust the call to check_splice_expr.\n\t* reflect.cc (eval_constant_of): Adjust the call to\n\tcheck_splice_expr.\n\t(check_splice_expr): Two new bool parameters. Add the template_p\n\tchecking from cp_parser_splice_expression. Allow\n\tvariable_template_p in the assert. Add a check for\n\tDECL_TYPE_TEMPLATE_P.\n\ngcc/testsuite/ChangeLog:\n\n\t* g++.dg/reflect/crash11.C: Adjust dg-error.\n\t* g++.dg/reflect/splice5.C: Likewise.\n---\n gcc/cp/cp-tree.h | 24 +++++++++++-\n gcc/cp/parser.cc | 41 ++++++--------------\n gcc/cp/pt.cc | 6 +++\n gcc/cp/reflect.cc | 53 ++++++++++++++++++++++++--\n gcc/testsuite/g++.dg/reflect/crash11.C | 4 +-\n gcc/testsuite/g++.dg/reflect/splice5.C | 7 ++--\n 6 files changed, 93 insertions(+), 42 deletions(-)\n\n\nbase-commit: 6be9db000810a44c5b6b5af320723b3af175bb8a", "diff": "diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h\nindex 1ea3319c37b..1080203ac8a 100644\n--- a/gcc/cp/cp-tree.h\n+++ b/gcc/cp/cp-tree.h\n@@ -522,6 +522,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];\n TARGET_EXPR_ELIDING_P (in TARGET_EXPR)\n IF_STMT_VACUOUS_INIT_P (IF_STMT)\n TYPENAME_IS_RESOLVING_P (in TYPENAME_TYPE)\n+ SPLICE_EXPR_TEMPLATE_P (in SPLICE_EXPR)\n 4: IDENTIFIER_MARKED (IDENTIFIER_NODEs)\n TREE_HAS_CONSTRUCTOR (in INDIRECT_REF, SAVE_EXPR, CONSTRUCTOR,\n \t CALL_EXPR, or FIELD_DECL).\n@@ -533,6 +534,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];\n TARGET_EXPR_INTERNAL_P (in TARGET_EXPR)\n CONTRACT_CONST (in ASSERTION_, PRECONDITION_, POSTCONDITION_STMT)\n DECL_HAS_DEFAULT_ARGUMENT_P (in PARM_DECL)\n+ SPLICE_EXPR_TARGS_P (in SPLICE_EXPR)\n 5: IDENTIFIER_VIRTUAL_P (in IDENTIFIER_NODE)\n FUNCTION_RVALUE_QUALIFIED (in FUNCTION_TYPE, METHOD_TYPE)\n CALL_EXPR_REVERSE_ARGS (in CALL_EXPR, AGGR_INIT_EXPR)\n@@ -1979,6 +1981,24 @@ enum reflect_kind : addr_space_t {\n (SPLICE_EXPR_ADDRESS_P (TREE_CODE (NODE) == SPLICE_EXPR \\\n \t\t\t ? NODE : TREE_OPERAND (NODE, 0)) = (VAL))\n \n+/* True if this SPLICE_EXPR was decorated with 'template'. */\n+#define SPLICE_EXPR_TEMPLATE_P(NODE) \\\n+ TREE_LANG_FLAG_3 (SPLICE_EXPR_CHECK (NODE))\n+\n+/* Helper macro to set SPLICE_EXPR_TEMPLATE_P. */\n+#define SET_SPLICE_EXPR_TEMPLATE_P(NODE, VAL) \\\n+ (SPLICE_EXPR_TEMPLATE_P (TREE_CODE (NODE) == SPLICE_EXPR \\\n+\t\t\t ? NODE : TREE_OPERAND (NODE, 0)) = (VAL))\n+\n+/* True if this SPLICE_EXPR has template arguments. */\n+#define SPLICE_EXPR_TARGS_P(NODE) \\\n+ TREE_LANG_FLAG_4 (SPLICE_EXPR_CHECK (NODE))\n+\n+/* Helper macro to set SPLICE_EXPR_TARGS_P. */\n+#define SET_SPLICE_EXPR_TARGS_P(NODE, VAL) \\\n+ (SPLICE_EXPR_TARGS_P (TREE_CODE (NODE) == SPLICE_EXPR \\\n+\t\t\t? NODE : TREE_OPERAND (NODE, 0)) = (VAL))\n+\n /* The expression in question for a SPLICE_SCOPE. */\n #define SPLICE_SCOPE_EXPR(NODE) \\\n (TYPE_VALUES_RAW (SPLICE_SCOPE_CHECK (NODE)))\n@@ -9416,8 +9436,8 @@ extern bool consteval_only_p (tree) ATTRIBUTE_PURE;\n extern bool compare_reflections (tree, tree) ATTRIBUTE_PURE;\n extern bool valid_splice_type_p (const_tree) ATTRIBUTE_PURE;\n extern bool valid_splice_scope_p (const_tree) ATTRIBUTE_PURE;\n-extern bool check_splice_expr (location_t, location_t, tree, bool, bool, bool)\n- ATTRIBUTE_PURE;\n+extern bool check_splice_expr (location_t, location_t, tree, bool, bool, bool,\n+\t\t\t bool, bool) ATTRIBUTE_PURE;\n extern tree make_splice_scope (tree, bool);\n extern bool dependent_splice_p (const_tree) ATTRIBUTE_PURE;\n extern tree reflection_mangle_prefix (tree, char [3]);\ndiff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc\nindex bbebc125765..fe27a15a283 100644\n--- a/gcc/cp/parser.cc\n+++ b/gcc/cp/parser.cc\n@@ -6318,6 +6318,8 @@ cp_parser_splice_expression (cp_parser *parser, bool template_p,\n SET_SPLICE_EXPR_EXPRESSION_P (t);\n SET_SPLICE_EXPR_MEMBER_ACCESS_P (t, member_access_p);\n SET_SPLICE_EXPR_ADDRESS_P (t, address_p);\n+ SET_SPLICE_EXPR_TEMPLATE_P (t, template_p);\n+ SET_SPLICE_EXPR_TARGS_P (t, targs_p);\n return t;\n }\n \n@@ -6330,38 +6332,17 @@ cp_parser_splice_expression (cp_parser *parser, bool template_p,\n \n /* Make sure this splice-expression produces an expression. */\n if (!check_splice_expr (loc, expr.get_start (), t, address_p,\n-\t\t\t member_access_p, /*complain=*/true))\n+\t\t\t member_access_p, template_p, targs_p,\n+\t\t\t /*complain=*/true))\n return error_mark_node;\n \n- if (template_p)\n- {\n- /* [expr.prim.splice] For a splice-expression of the form template\n-\t splice-specifier, the splice-specifier shall designate a function\n-\t template. */\n- if (!targs_p\n-\t && !really_overloaded_fn (t)\n-\t && !dependent_splice_p (t))\n-\t{\n-\t auto_diagnostic_group d;\n-\t error_at (loc, \"expected a reflection of a function template\");\n-\t inform_tree_category (t);\n-\t return error_mark_node;\n-\t}\n- /* [expr.prim.splice] For a splice-expression of the form\n-\t template splice-specialization-specifier, the splice-specifier of the\n-\t splice-specialization-specifier shall designate a template. Since\n-\t we would have already complained, just check that we have a template. */\n- gcc_checking_assert (really_overloaded_fn (t)\n-\t\t\t || get_template_info (t)\n-\t\t\t || TREE_CODE (t) == TEMPLATE_ID_EXPR\n-\t\t\t || dependent_splice_p (t));\n- }\n- else if (/* No 'template' but there were template arguments? */\n-\t (targs_p\n-\t /* No 'template' but the splice-specifier designates a function\n-\t template? */\n-\t || really_overloaded_fn (t))\n-\t && warning_enabled_at (loc, OPT_Wmissing_template_keyword))\n+ if (!template_p\n+ /* No 'template' but there were template arguments? */\n+ && (targs_p\n+\t /* No 'template' but the splice-specifier designates a function\n+\t template? */\n+\t || really_overloaded_fn (t))\n+ && warning_enabled_at (loc, OPT_Wmissing_template_keyword))\n /* Were 'template' present, this would be valid code, so keep going. */\n missing_template_diag (loc, diagnostics::kind::pedwarn);\n \ndiff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc\nindex c10ca09cdb1..18aec7ebb56 100644\n--- a/gcc/cp/pt.cc\n+++ b/gcc/cp/pt.cc\n@@ -16833,12 +16833,18 @@ tsubst_splice_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)\n \tSET_SPLICE_EXPR_MEMBER_ACCESS_P (op, true);\n if (SPLICE_EXPR_ADDRESS_P (t))\n \tSET_SPLICE_EXPR_ADDRESS_P (op, true);\n+ if (SPLICE_EXPR_TEMPLATE_P (t))\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 }\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 \t\t\t SPLICE_EXPR_MEMBER_ACCESS_P (t),\n+\t\t\t SPLICE_EXPR_TEMPLATE_P (t),\n+\t\t\t SPLICE_EXPR_TARGS_P (t),\n \t\t\t (complain & tf_error)))\n return error_mark_node;\n \ndiff --git a/gcc/cp/reflect.cc b/gcc/cp/reflect.cc\nindex 78d48db29ba..8925bf49465 100644\n--- a/gcc/cp/reflect.cc\n+++ b/gcc/cp/reflect.cc\n@@ -2752,6 +2752,8 @@ eval_constant_of (location_t loc, const constexpr_ctx *ctx, tree r,\n else if (!check_splice_expr (loc, UNKNOWN_LOCATION, r,\n \t\t\t /*address_p=*/false,\n \t\t\t /*member_access_p=*/false,\n+\t\t\t /*template_p=*/false,\n+\t\t\t /*targs_p=*/false,\n \t\t\t /*complain_p=*/false)\n \t /* One cannot query the value of a function template.\n \t ??? But if [:^^X:] where X is a template is OK, should we\n@@ -8812,13 +8814,15 @@ check_consteval_only_fn (tree decl)\n \n /* Check if T is a valid result of splice-expression. ADDRESS_P is true if\n we are taking the address of the splice. MEMBER_ACCESS_P is true if this\n- splice is used in foo.[: bar :] or foo->[: bar :] context. COMPLAIN_P is\n- true if any errors should be emitted. Returns true is no problems are\n- found, false otherwise. */\n+ splice is used in foo.[: bar :] or foo->[: bar :] context. TEMPLATE_P is\n+ true if the splice-expression was preceded by 'template'. TARGS_P is true\n+ if there were template arguments. COMPLAIN_P is true if any errors should\n+ be emitted. Returns true is no problems are found, false otherwise. */\n \n bool\n check_splice_expr (location_t loc, location_t start_loc, tree t,\n-\t\t bool address_p, bool member_access_p, bool complain_p)\n+\t\t bool address_p, bool member_access_p, bool template_p,\n+\t\t bool targs_p, bool complain_p)\n {\n /* We may not have gotten an expression. */\n if (TREE_CODE (t) == TYPE_DECL\n@@ -8949,6 +8953,47 @@ check_splice_expr (location_t loc, location_t start_loc, tree t,\n return false;\n }\n \n+ if (template_p)\n+ {\n+ /* [expr.prim.splice] For a splice-expression of the form template\n+\t splice-specifier, the splice-specifier shall designate a function\n+\t template. */\n+ if (!targs_p)\n+\t{\n+\t if (!really_overloaded_fn (t) && !dependent_splice_p (t))\n+\t {\n+\t if (complain_p)\n+\t\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}\n+\t return false;\n+\t }\n+\t}\n+ /* [expr.prim.splice] For a splice-expression of the form\n+\t template splice-specialization-specifier, the splice-specifier of the\n+\t splice-specialization-specifier shall designate a template. The\n+\t template should be a function template or a variable template. */\n+ else if (DECL_TYPE_TEMPLATE_P (t))\n+\t{\n+\t if (complain_p)\n+\t {\n+\t auto_diagnostic_group d;\n+\t error_at (loc, \"expected a reflection of a function or variable \"\n+\t\t\t\"template\");\n+\t inform_tree_category (t);\n+\t }\n+\t return false;\n+\t}\n+ gcc_checking_assert (really_overloaded_fn (t)\n+\t\t\t || get_template_info (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));\n+ }\n+\n return true;\n }\n \ndiff --git a/gcc/testsuite/g++.dg/reflect/crash11.C b/gcc/testsuite/g++.dg/reflect/crash11.C\nindex 3aef5d0b2fe..1d8e78994c2 100644\n--- a/gcc/testsuite/g++.dg/reflect/crash11.C\n+++ b/gcc/testsuite/g++.dg/reflect/crash11.C\n@@ -12,8 +12,8 @@ template<typename T, auto R>\n void\n g ()\n {\n- template [: R :]<int> c0; // { dg-error \"not a function template|expected\" }\n- template [: T::r :]<int> c1; // { dg-error \"not a function template|expected\" }\n+ template [: R :]<int> c0; // { dg-error \"function or variable template|expected\" }\n+ template [: T::r :]<int> c1; // { dg-error \"function or variable template|expected\" }\n }\n \n void\ndiff --git a/gcc/testsuite/g++.dg/reflect/splice5.C b/gcc/testsuite/g++.dg/reflect/splice5.C\nindex 4f0d2fe6134..96d3192eb55 100644\n--- a/gcc/testsuite/g++.dg/reflect/splice5.C\n+++ b/gcc/testsuite/g++.dg/reflect/splice5.C\n@@ -25,10 +25,9 @@ template <int N>\n void\n qux (S &s)\n {\n- // TODO: We don't reject this one.\n- template [: N == 0 ? ^^foo : ^^:: :] (0);\t// { dg-error \"reflection 'foo' not usable in a template splice\" \"\" { xfail *-*-* } }\n- template [: N == 0 ? ^^bar : ^^:: :] (0);\t// { dg-message \"only function templates are allowed here\" \"\" { xfail *-*-* } .-1 }\n- s.template [: N == 0 ? ^^S::foo : ^^:: :] (0); // { dg-error \"reflection 'foo' not usable in a template splice\" \"\" { xfail *-*-* } }\n+ template [: N == 0 ? ^^foo : ^^:: :] (0);\t// { dg-error \"expected a reflection of a function template\" }\n+ template [: N == 0 ? ^^bar : ^^:: :] (0);\n+ s.template [: N == 0 ? ^^S::foo : ^^:: :] (0); // { dg-error \"expected a reflection of a function template\" }\n s.template [: N == 0 ? ^^S::bar : ^^:: :] (0);\n }\n \n", "prefixes": [ "v2" ] }