From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: 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 A7C613858D28 for ; Mon, 6 Dec 2021 21:44:11 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org A7C613858D28 Received: from mail-qt1-f197.google.com (mail-qt1-f197.google.com [209.85.160.197]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-429-5WHzaeIpNeWfPVwsddCEKg-1; Mon, 06 Dec 2021 16:44:09 -0500 X-MC-Unique: 5WHzaeIpNeWfPVwsddCEKg-1 Received: by mail-qt1-f197.google.com with SMTP id h8-20020a05622a170800b002acc8656e05so14279421qtk.7 for ; Mon, 06 Dec 2021 13:44:09 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:message-id:date:mime-version:user-agent:subject :content-language:to:cc:references:from:in-reply-to :content-transfer-encoding; bh=MlM1IiZ570ab1w1Cst/p76mcTFr3gZHqJxn5JHeJmoQ=; b=ivcO4F28NMsgVDmcINr7LyaPZQqjQekQUZLC8m+rGEkXsFThmPhH4Mr38D5w4i7Hbh /LBV7BjqVMu6+W83fVpGilnMAAUgwanWj19fCe7hqqwtp3HbqCofoKh54ta1EB1SFTuB TFgT48yMosoYvp5+FAA6997ofrjSWRTyYO5Llld/9KBcWLMNtlMRc3Zg1D/CRLHR5hgt 2qqlp/oa6ulFQOU24OMKUSvBWoGXSbyFCb6E4/5Rbm9ULBxLZKNjhfLrwSzV0+LCYSyE l9QzEpc28l51yX5zl0RZFbzb25dcp5q0VPqn9V19uhlaWl9O8hSVyCsdlhI6ezNEV7cL yKBg== X-Gm-Message-State: AOAM531frsYKsFvHxL+CHdq1rT/rNpnI8HGq6Z3TXNaXnbcJWEmuzoVN b15z7yZqOb4bB1A8AkpOfBWGBYdzE6JRHTqK6NLeHz+bBoAAeXuJJpzdObM6YPBJlBZfk8zBUhs Hff1rymlgXtcjaOuXVA== X-Received: by 2002:a05:622a:308:: with SMTP id q8mr42784011qtw.463.1638827049045; Mon, 06 Dec 2021 13:44:09 -0800 (PST) X-Google-Smtp-Source: ABdhPJx3u+4vKZyp+4oNxGYXBVBOwdyqNG5KUjiRsDW4JEfoPOBq1cp4mdKt8DlnA7jrJjq5r0gL1Q== X-Received: by 2002:a05:622a:308:: with SMTP id q8mr42783984qtw.463.1638827048685; Mon, 06 Dec 2021 13:44:08 -0800 (PST) Received: from [192.168.1.149] (130-44-159-43.s15913.c3-0.arl-cbr1.sbo-arl.ma.cable.rcncustomer.com. [130.44.159.43]) by smtp.gmail.com with ESMTPSA id m9sm7034318qkn.59.2021.12.06.13.44.07 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Mon, 06 Dec 2021 13:44:07 -0800 (PST) Message-ID: <7a01a476-8057-9f23-44f0-6a8b3531709b@redhat.com> Date: Mon, 6 Dec 2021 16:44:06 -0500 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Thunderbird/91.3.2 Subject: Re: [PATCH v2] c++: Handle auto(x) in parameter-declaration-clause [PR103401] To: Marek Polacek Cc: GCC Patches References: <20211201151614.1497902-1-polacek@redhat.com> <3b09ccaa-c6e0-903a-1f85-3e5183bb4eb0@redhat.com> <39eac2d9-dcb1-b6df-c381-88d862f333f5@redhat.com> From: Jason Merrill In-Reply-To: X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Language: en-US Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit X-Spam-Status: No, score=-14.1 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, NICE_REPLY_A, 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-List-Received-Date: Mon, 06 Dec 2021 21:44:13 -0000 On 12/3/21 19:44, Marek Polacek wrote: > On Thu, Dec 02, 2021 at 12:56:38PM -0500, Jason Merrill wrote: >> On 12/2/21 10:27, Marek Polacek wrote: >>> On Wed, Dec 01, 2021 at 11:24:58PM -0500, Jason Merrill wrote: >>>> On 12/1/21 10:16, Marek Polacek wrote: >>>>> In C++23, auto(x) is valid, so decltype(auto(x)) should also be valid, >>>>> so >>>>> >>>>> void f(decltype(auto(0))); >>>>> >>>>> should be just as >>>>> >>>>> void f(int); >>>>> >>>>> but currently, everytime we see 'auto' in a parameter-declaration-clause, >>>>> we try to synthesize_implicit_template_parm for it, creating a new template >>>>> parameter list. The code above actually has us calling s_i_t_p twice; >>>>> once from cp_parser_decltype_expr -> cp_parser_postfix_expression which >>>>> fails and then again from cp_parser_decltype_expr -> cp_parser_expression. >>>>> So it looks like we have f and we accept ill-formed code. >>>>> >>>>> So we need to be more careful about synthesizing the implicit template >>>>> parameter. cp_parser_postfix_expression looked like a sensible place. >>>> >>>> Does this cover other uses of auto in decltype, such as >>>> >>>> void f(decltype(new auto{0})); >>> >>> Yes: the clearing of auto_is_implicit_function_template_parm_p will happen here >>> too. >>> >>> However, I'm noticing this: >>> >>> void f1(decltype(new auto{0})); >>> void f2(decltype(new int{0})); >>> >>> void >>> g () >>> { >>> int i; >>> void f3(decltype(new auto{0})); >>> void f4(decltype(new int{0})); >>> f1 (&i); // error: no matching function for call to f1(int*) >>> // couldn't deduce template parameter auto:1 >>> f2 (&i); >>> f3 (&i); >>> f4 (&i); >>> } >>> I think the error we issue is bogus. (My patch doesn't change this. clang++ >>> accepts.) Should I file a PR (and investigate)? >> >> That certainly suggests that auto_is_implicit_function_template_parm_p isn't >> getting cleared soon enough for f1. > > Exactly right. > >>>> ? Should we adjust this flag in cp_parser_decltype along with all the other >>>> flags? >>> >>> I think that's possible, but wouldn't cover auto in default arguments, or array >>> bounds. >> >> I guess cp_parser_sizeof_operand would need the same change. >> >> Do we currently handle auto in default arguments wrong? Ah, I see that we >> currently set auto_is_... for the whole parameter declaration clause, rather >> than just for the decl-specifier-seq of parameters as the standard >> specifies: >> >> "A placeholder-type-specifier of the form type-constraint opt auto can be >> used as a decl-specifier of the decl-specifier-seq of a >> parameter-declaration of a function declaration or lambda-expression...." > > Thanks. How about this then? The patch gives the rationale. > > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk? > > -- >8 -- > In C++23, auto(x) is valid, so decltype(auto(x)) should also be valid, > so > > void f(decltype(auto(0))); > > should be just as > > void f(int); > > but currently, everytime we see 'auto' in a parameter-declaration-clause, > we try to synthesize_implicit_template_parm for it, creating a new template > parameter list. The code above actually has us calling s_i_t_p twice; > once from cp_parser_decltype_expr -> cp_parser_postfix_expression which > fails and then again from cp_parser_decltype_expr -> cp_parser_expression. > So it looks like we have f and we accept ill-formed code. > > This shows that we need to be more careful about synthesizing the > implicit template parameter. [dcl.spec.auto.general] says that "A > placeholder-type-specifier of the form type-constraintopt auto can be > used as a decl-specifier of the decl-specifier-seq of a > parameter-declaration of a function declaration or lambda-expression..." > so this patch turns off auto_is_... after we've parsed the decl-specifier-seq. > > That doesn't quite cut yet though, because we also need to handle an > auto nested in the decl-specifier: > > void f(decltype(new auto{0})); > > therefore the cp_parser_decltype change. > > The second hunk broke lambda-generic-85713-2.C but I think the error we > issue with this patch is in fact correct, and clang++ agrees. > > The r11-1913 change is OK: we need to make sure that we see '(auto)' after > decltype to go ahead with 'decltype(auto)'. > > PR c++/103401 > > gcc/cp/ChangeLog: > > * parser.c (cp_parser_decltype): Clear > auto_is_implicit_function_template_parm_p. > (cp_parser_parameter_declaration): Clear > auto_is_implicit_function_template_parm_p after parsing the > decl-specifier-seq. > > gcc/testsuite/ChangeLog: > > * g++.dg/cpp1y/lambda-generic-85713-2.C: Add dg-error. > * g++.dg/cpp23/auto-fncast7.C: New test. > * g++.dg/cpp23/auto-fncast8.C: New test. > * g++.dg/cpp23/auto-fncast9.C: New test. > --- > gcc/cp/parser.c | 19 +++++++++++ > .../g++.dg/cpp1y/lambda-generic-85713-2.C | 2 +- > gcc/testsuite/g++.dg/cpp23/auto-fncast7.C | 9 +++++ > gcc/testsuite/g++.dg/cpp23/auto-fncast8.C | 34 +++++++++++++++++++ > gcc/testsuite/g++.dg/cpp23/auto-fncast9.C | 17 ++++++++++ > 5 files changed, 80 insertions(+), 1 deletion(-) > create mode 100644 gcc/testsuite/g++.dg/cpp23/auto-fncast7.C > create mode 100644 gcc/testsuite/g++.dg/cpp23/auto-fncast8.C > create mode 100644 gcc/testsuite/g++.dg/cpp23/auto-fncast9.C > > diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c > index 55e6a1a8b3a..7508def0750 100644 > --- a/gcc/cp/parser.c > +++ b/gcc/cp/parser.c > @@ -16432,6 +16432,16 @@ cp_parser_decltype (cp_parser *parser) > = parser->greater_than_is_operator_p; > parser->greater_than_is_operator_p = true; > > + /* Don't synthesize an implicit template type parameter here. This > + could happen with C++23 code like > + > + void f(decltype(new auto{0})); > + > + where we want to deduce the auto right away so that the parameter > + is of type 'int *'. */ > + auto cleanup = make_temp_override > + (parser->auto_is_implicit_function_template_parm_p, false); Please also make this change to cp_parser_sizeof_operand, and add tests involving sizeof/alignof in array bounds. OK with that change. > /* Do not actually evaluate the expression. */ > ++cp_unevaluated_operand; > > @@ -24668,6 +24678,15 @@ cp_parser_parameter_declaration (cp_parser *parser, > &decl_specifiers, > &declares_class_or_enum); > > + /* [dcl.spec.auto.general]: "A placeholder-type-specifier of the form > + type-constraint opt auto can be used as a decl-specifier of the > + decl-specifier-seq of a parameter-declaration of a function declaration > + or lambda-expression..." but we must not synthesize an implicit template > + type parameter in its declarator. That is, in "void f(auto[auto{10}]);" > + we want to synthesize only the first auto. */ > + auto cleanup = make_temp_override > + (parser->auto_is_implicit_function_template_parm_p, false); > + > /* Complain about missing 'typename' or other invalid type names. */ > if (!decl_specifiers.any_type_specifiers_p > && cp_parser_parse_and_diagnose_invalid_type_name (parser)) > diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-generic-85713-2.C b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-85713-2.C > index 8fb8dfdeaf0..dbc9e8c732c 100644 > --- a/gcc/testsuite/g++.dg/cpp1y/lambda-generic-85713-2.C > +++ b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-85713-2.C > @@ -2,6 +2,6 @@ > // { dg-do compile { target c++14 } } > > auto l4 = [](auto v, auto (&array (int)) [5]) -> int { return v + array[0]; }; > -auto l5 = [](auto v, auto (&array (auto)) [5]) -> int { return v + array[0]; }; > +auto l5 = [](auto v, auto (&array (auto)) [5]) -> int { return v + array[0]; }; // { dg-error ".auto. parameter not permitted in this context" } > auto l6 = [](auto v, auto (&array (int int)) [5]) -> int { return v + array[0]; }; // { dg-error "two or more data types" } > auto l7 = [](auto v, auto (&array (int auto)) [5]) -> int { return v + array[0]; }; // { dg-error "two or more data types" } > diff --git a/gcc/testsuite/g++.dg/cpp23/auto-fncast7.C b/gcc/testsuite/g++.dg/cpp23/auto-fncast7.C > new file mode 100644 > index 00000000000..763164f3e5b > --- /dev/null > +++ b/gcc/testsuite/g++.dg/cpp23/auto-fncast7.C > @@ -0,0 +1,9 @@ > +// PR c++/103401 > +// { dg-do compile { target c++23 } } > + > +void f(decltype(auto(0))) { } > + > +int main() > +{ > + f(0); // { dg-error "no matching function" } > +} > diff --git a/gcc/testsuite/g++.dg/cpp23/auto-fncast8.C b/gcc/testsuite/g++.dg/cpp23/auto-fncast8.C > new file mode 100644 > index 00000000000..4cf078ee989 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/cpp23/auto-fncast8.C > @@ -0,0 +1,34 @@ > +// PR c++/103401 > +// { dg-do compile { target c++23 } } > + > +void f1 (decltype(auto(0))); > +void f2 (decltype(auto{0})); > +void f3 (int = auto(42)); > +void f4 (int = auto{42}); > +void f5 (decltype(auto(0)) = auto(42)); > +void f6 (auto (x)); > +void f7 (int[auto(10)]); > +void f8 (int[auto{10}]); > +void f9 (auto[auto{10}]); > +void f10 (auto); > +void f11 (int x, decltype(x) y); > + > +void > +g () > +{ > + f1 (1); > + f2 (1); > + f3 (); > + f3 (1); > + f4 (); > + f4 (1); > + f5 (); > + f5 (1); > + f6 ('a'); > + int a[10]; > + f7 (&a[0]); > + f8 (&a[0]); > + f9 (&a[0]); > + f10 (1); > + f11 (1, 2); > +} > 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..12a0dcece75 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/cpp23/auto-fncast9.C > @@ -0,0 +1,17 @@ > +// PR c++/103401 > +// { dg-do compile { target c++23 } } > + > +void f1(decltype(new auto{0})); > +void f2(decltype(new int{0})); > + > +void > +g () > +{ > + int i; > + void f3(decltype(new auto{0})); > + void f4(decltype(new int{0})); > + f1 (&i); > + f2 (&i); > + f3 (&i); > + f4 (&i); > +} > > base-commit: bf548ce3e67276aa429b462cf41e68891fdf40c2 >