From patchwork Thu Dec 2 00:45:46 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Polacek X-Patchwork-Id: 48377 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 7683E3857C71 for ; Thu, 2 Dec 2021 00:46:25 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 7683E3857C71 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1638405985; bh=OwyF5bTVpTT+clVALPnUXR3SN9hqRnrwWDTNIZbeHOQ=; h=Date:To:Subject:References:In-Reply-To:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=Q/xs+ITGENF7tWLafv2fO6vyVyado1PjxyDwpxmD3AzcWjioWw56PArSZofnnH7MD Y1f9K7Tv7kD40MTxNXOtBZuufTx8UF/7bPQaKzAFm7qcMTVGFFTppir7F71pajHpBX xT6FzlkCM+fRTwxRBiivT7D0YWPx3srLJ/XOndkA= 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.129.124]) by sourceware.org (Postfix) with ESMTPS id 7FEDB3858414 for ; Thu, 2 Dec 2021 00:45:54 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 7FEDB3858414 Received: from mail-qt1-f200.google.com (mail-qt1-f200.google.com [209.85.160.200]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-243-eajuXu8cNJO2yvShQjQoEw-1; Wed, 01 Dec 2021 19:45:50 -0500 X-MC-Unique: eajuXu8cNJO2yvShQjQoEw-1 Received: by mail-qt1-f200.google.com with SMTP id v17-20020a05622a131100b002aea167e24aso34335334qtk.5 for ; Wed, 01 Dec 2021 16:45:50 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to:user-agent; bh=OwyF5bTVpTT+clVALPnUXR3SN9hqRnrwWDTNIZbeHOQ=; b=IQXM7h5GmMWySXEG8LxhspmvEr5W5IleTXulfLqstTQzN3mAtBtV+QGYTxlJ1ji4b2 ftbB+s7AuVE6kKInOfAbm7L/SepJ6c+BPf2/SWj4jVBHPJdRttfjQi29ruutsKgdlof7 Kz4KMovHi1XiwCOyWLt0isVIcPZrpc4IJ5zXTCHy3Fet1NCE+Vw90XG+lrnC62laHBrW lJ1onhrRQoI8/u2LvkLggdMzpOQYuo0D64CqUsD6gmkJ9TSt+CnRsHPc/1Y7VFW8aZ9W PSPAtiRdnjZ6fy1u6tROQHFIVKPg/inSETgJHxl2LkEshR7enbs1B1PV5aHqKlfX3ojW NaCw== X-Gm-Message-State: AOAM532IAURo40UHcjtG3g0QmREvyaQ9/huYooHEBbedOUf3eXL/wpXm sXrHEG+dRGBvL0HRrUXcXhhIALzL2drmYBlC4w8x5m0gqXJ0OSruDbfTMXeB84rM2cFedsaq7F2 G1WxD5p7KsLw8TRqDLQ== X-Received: by 2002:ac8:5906:: with SMTP id 6mr10650646qty.230.1638405949303; Wed, 01 Dec 2021 16:45:49 -0800 (PST) X-Google-Smtp-Source: ABdhPJyd4N0fPXq0iZqVYibbC7rWm9kJd0mgb7Chp0vAUxfhIghVdLXSfEMM5Xhhe7JWrwE1vp6K3w== X-Received: by 2002:ac8:5906:: with SMTP id 6mr10650627qty.230.1638405948993; Wed, 01 Dec 2021 16:45:48 -0800 (PST) Received: from redhat.com ([2601:184:4780:4310::aac2]) by smtp.gmail.com with ESMTPSA id c25sm1686733qkp.31.2021.12.01.16.45.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 01 Dec 2021 16:45:48 -0800 (PST) Date: Wed, 1 Dec 2021 19:45:46 -0500 To: Patrick Palka Subject: [PATCH v2] c++: ICE with auto(0) in requires-expression [PR103408] Message-ID: References: <20211201151629.1497940-1-polacek@redhat.com> MIME-Version: 1.0 In-Reply-To: User-Agent: Mutt/2.1.3 (2021-09-10) X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Disposition: inline X-Spam-Status: No, score=-13.2 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_LOW, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Marek Polacek via Gcc-patches From: Marek Polacek Reply-To: Marek Polacek Cc: GCC Patches Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" On Wed, Dec 01, 2021 at 12:17:47PM -0500, Patrick Palka wrote: > On Wed, Dec 1, 2021 at 10:26 AM Marek Polacek via Gcc-patches > wrote: > > > > Here we ICE on > > > > int f() requires (auto(0)); > > > > in do_auto_deduction when handling the auto: we're in a non-templated > > requires-expression which are parsed under processing_template_decl == 1 > > and empty current_template_parms, so 'current_template_args ()' will > > crash. This code is invalid as per "C++20 CA378: Remove non-templated > > constrained functions", but of course we shouldn't crash. > > FWIW it looks like we can trip over the same bug with valid code: > > static_assert(requires { auto(0); }); Right, I hadn't thought of this at all. So it's not just an ICE-on-invalid! > > Since in the scenario above it's expected that current_template_parms is > > null, I've just added a check, and let grokfndecl issue an error. > > I guess another approch would be to fake up a template parameter list > > before calling do_auto_deduction. > > > > For good measure, I've added several well-formed cases with auto(x) in > > a requires-expression. > > > > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk? > > > > PR c++/103408 > > > > gcc/cp/ChangeLog: > > > > * pt.c (do_auto_deduction): Check current_template_parms before > > current_template_args (). > > > > gcc/testsuite/ChangeLog: > > > > * g++.dg/cpp23/auto-fncast9.C: New test. > > --- > > gcc/cp/pt.c | 2 +- > > gcc/testsuite/g++.dg/cpp23/auto-fncast9.C | 27 +++++++++++++++++++++++ > > 2 files changed, 28 insertions(+), 1 deletion(-) > > create mode 100644 gcc/testsuite/g++.dg/cpp23/auto-fncast9.C > > > > diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c > > index f4b9d9673fb..012ca5d06c0 100644 > > --- a/gcc/cp/pt.c > > +++ b/gcc/cp/pt.c > > @@ -30041,7 +30041,7 @@ do_auto_deduction (tree type, tree init, tree auto_node, > > (but we still may have used them for constraint checking above). */; > > else if (context == adc_unify) > > targs = add_to_template_args (outer_targs, targs); > > - else if (processing_template_decl) > > + else if (processing_template_decl && current_template_parms) > > targs = add_to_template_args (current_template_args (), targs); > > return tsubst (type, targs, complain, NULL_TREE); > > Won't this mean the call to tsubst here will end up lowering the level > of the auto from 2 to 1 rather than replacing it with the actual > deduced type? Yes, exactly -- targs has depth 1 but the level of auto is 2. :( > It also looks like this approach doesn't handle static_assert(requires > { auto(auto(0)); }), probably due to this substitution issue. I guess > we could add a dummy level to 'targs' to work around this.. Thanks for pointing this out. Here's a v2 which uses a dummy level. The description hopefully explains what's going on here... Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk? -- >8 -- Here we ICE on int f() requires (auto(0)); in do_auto_deduction when handling the auto: we're in a non-templated requires-expression which are parsed under processing_template_decl == 1 and empty current_template_parms, so 'current_template_args ()' will crash. This code is invalid as per "C++20 CA378: Remove non-templated constrained functions", but of course we shouldn't crash. However, as Patrick pointed out, this is valid: static_assert(requires { auto(0); }); // #1 static_assert(requires { auto(auto(0)); }); // #2 To make #1 and #2 work, I'm playing games with faking up a dummy template parameter level to current_template_parms, which need elaborating a bit. autos are created with the level processing_template_decl + 1. When we call do_auto_deduction for the inner auto(0) in #2, the auto will therefore have level 2. type_unification_real in do_auto_deduction deduces targs to (TMPL_ARGS_DEPTH = 1), so the return tsubst (type, targs, complain, NULL_TREE); will only reduce the level of the auto to 1. So it remains undeduced, causing the "invalid use of auto" error. If I create the dummy template parameter level, then this at the end of do_auto_deduction else if (processing_template_decl) targs = add_to_template_args (current_template_args (), targs); transforms into <, int>, which has TMPL_ARGS_DEPTH = 2 and so the following tsubst actually replaces the auto with int, and things work. For good measure, I've added several well-formed cases with auto(x) in a requires-expression. PR c++/103408 gcc/cp/ChangeLog: * cp-tree.h (add_dummy_template_parameter_level): Declare. * pt.c (add_dummy_template_parameter_level): New function. (begin_template_parm_list): Use it. * semantics.c (finish_compound_literal): Call add_dummy_template_parameter_level if there are no template parameters. * typeck2.c (build_functional_cast_1): Likewise. gcc/testsuite/ChangeLog: * g++.dg/cpp23/auto-fncast9.C: New test. --- gcc/cp/cp-tree.h | 1 + gcc/cp/pt.c | 15 +++++++--- gcc/cp/semantics.c | 3 ++ gcc/cp/typeck2.c | 3 ++ gcc/testsuite/g++.dg/cpp23/auto-fncast9.C | 35 +++++++++++++++++++++++ 5 files changed, 53 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp23/auto-fncast9.C base-commit: 860c56b5bc356960a4d0445dadc43ceddbe3c7e2 diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 1ee2c57e83c..ad220980476 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -7174,6 +7174,7 @@ extern tree get_innermost_template_args (tree, int); extern void maybe_begin_member_template_processing (tree); extern void maybe_end_member_template_processing (void); extern tree finish_member_template_decl (tree); +extern void add_dummy_template_parameter_level (); extern void begin_template_parm_list (void); extern bool begin_specialization (void); extern void reset_specialization (void); diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index f4b9d9673fb..f1ef1dbde0f 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -689,6 +689,16 @@ strip_innermost_template_args (tree args, int extra_levels) return new_args; } +/* Add a dummy template parameter level to current_template_parms. */ + +void +add_dummy_template_parameter_level () +{ + current_template_parms = tree_cons (size_int (processing_template_decl), + make_tree_vec (0), + current_template_parms); +} + /* We've got a template header coming up; push to a new level for storing the parms. */ @@ -715,10 +725,7 @@ begin_template_parm_list (void) note_template_header (0); /* Add a dummy parameter level while we process the parameter list. */ - current_template_parms - = tree_cons (size_int (processing_template_decl), - make_tree_vec (0), - current_template_parms); + add_dummy_template_parameter_level (); } /* This routine is called when a specialization is declared. If it is diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index cd1956497f8..7e2179412b2 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -3143,6 +3143,9 @@ finish_compound_literal (tree type, tree compound_literal, pedwarn (input_location, OPT_Wc__23_extensions, "% only available with " "%<-std=c++2b%> or %<-std=gnu++2b%>"); + auto ctp = make_temp_override (current_template_parms); + if (processing_template_decl && !current_template_parms) + add_dummy_template_parameter_level (); type = do_auto_deduction (type, compound_literal, type, complain, adc_variable_type); if (type == error_mark_node) diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index 3fb651a02ba..af20315c9e4 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -2202,6 +2202,7 @@ build_functional_cast_1 (location_t loc, tree exp, tree parms, if (tree anode = type_uses_auto (type)) { tree init; + auto ctp = make_temp_override (current_template_parms); if (CLASS_PLACEHOLDER_TEMPLATE (anode)) init = parms; /* C++23 auto(x). */ @@ -2213,6 +2214,8 @@ build_functional_cast_1 (location_t loc, tree exp, tree parms, pedwarn (loc, OPT_Wc__23_extensions, "% only available with " "%<-std=c++2b%> or %<-std=gnu++2b%>"); + if (processing_template_decl && !current_template_parms) + add_dummy_template_parameter_level (); } else { diff --git a/gcc/testsuite/g++.dg/cpp23/auto-fncast9.C b/gcc/testsuite/g++.dg/cpp23/auto-fncast9.C new file mode 100644 index 00000000000..b92a5f7b320 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp23/auto-fncast9.C @@ -0,0 +1,35 @@ +// PR c++/103408 +// { dg-do compile { target c++23 } } + +int bad1() requires (auto(true)); // { dg-error "constraints on a non-templated function" } + +template +int f1() requires (auto(B)); + +template +struct S { T t; constexpr operator bool() { return true; } }; + +int bad2() requires (bool(S{1})); // { dg-error "constraints on a non-templated function" } +int bad3() requires (bool(S(1))); // { dg-error "constraints on a non-templated function" } + +template +int f2() requires (bool(S{N})); + +template +int f3() requires (bool(S(N))); + +void +g () +{ + f1(); + f2<42>(); + f3<42>(); +} + +static_assert(requires { auto(0); }); +static_assert(requires { auto(auto(0)); }); +static_assert(requires { auto(auto(auto(0))); }); + +static_assert(requires { auto{0}; }); +static_assert(requires { auto{auto{0}}; }); +static_assert(requires { auto{auto{auto{0}}}; });