get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/1.1/patches/2221254/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "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"
    ]
}