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