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 70B9C3857030 for ; Tue, 14 Nov 2023 02:26:45 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 70B9C3857030 Authentication-Results: sourceware.org; dmarc=pass (p=none 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 70B9C3857030 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1699928807; cv=none; b=BQHSQ1pGmKAMuoMc9bZwXrpJ8Y5eHJk56/EkYFgwCB5vWAYRjucDmp+cKaDgna+KDtzV7ZRD50iMhTyVu0JnS0ZBi/tF4u/CKZZXkhza5ezReWpInF5+YPjwG8PbmE05BgxOGf8jPvpZPhf8jhb3szlpKLwspYJ7zKMS4Vmt2J4= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1699928807; c=relaxed/simple; bh=EgDwO3s/gzwU6exHwaDAyOgJx7CH2GqyI0QEcBmeO0w=; h=DKIM-Signature:Message-ID:Date:MIME-Version:Subject:To:From; b=XLGK5hNG+OkjSgIiahjw6W8bqY00wORizmf3bsEBqqdtuA3NF5uM7UMU9x05R9//er3hzMnDfoi5n0yUDD9V5gIl/OxXFFebHhFk7F/Sj9rxZrJgKdXdfyeURxs8WXvD8snl3t7i4d8qPtymAbcUgihEDKhU+dsE0ry+KtxqJA8= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1699928805; 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: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=K14ee45lL+2pudZL95PLOsTAKVu4wv6nKL/RPMAKm9Y=; b=Bi7TUP4BnragjIDODYdYAvtvMeqQoNpeIMLuMDNJ05g42ZE5Ru8horzMiG0WJnFMtb5wnu laSXcX/n79EVb8IciXzVR+b3Vm+guD5q9t4yhJzuPuNXqrZC4iGeE+TJx5iZNoKGGbhRBt AKGkPaskMtE23iDClgqDF+pm+t0aM74= Received: from mail-qv1-f71.google.com (mail-qv1-f71.google.com [209.85.219.71]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-237-l8j0GiCkPrulSpWpaVf6eg-1; Mon, 13 Nov 2023 21:26:43 -0500 X-MC-Unique: l8j0GiCkPrulSpWpaVf6eg-1 Received: by mail-qv1-f71.google.com with SMTP id 6a1803df08f44-66d91b47f23so52575286d6.2 for ; Mon, 13 Nov 2023 18:26:43 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1699928803; x=1700533603; h=content-transfer-encoding:in-reply-to:from:references:cc:to :content-language:subject:user-agent:mime-version:date:message-id :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=K14ee45lL+2pudZL95PLOsTAKVu4wv6nKL/RPMAKm9Y=; b=Fd33ssFtj3hJr9n177jx55HtgQBso0q8rMlUh5JH5SPCyoYXz1FKCUlQXJekTcZLfO oboteBwMpzTNy5PruXvQhkt1+WBjZfQlXRBru4slexOBeZRLTF6F+H/oQymjI13R/H3H tbDub2amf5LwDE/QnFDoswSvcpa/BFxsOHBaTwyXOZi5xLj2UWckU7Cg38dNHrChDYaA y0AGavSDRW1mvWfR9u/ZXqXJDxQryM/ihfSR1xBmfeAwI5mLA9FN9ZJXtIE8h62CIuvp /NqTvwttYPF2B6im3cgQyZ6LThgfD+J6PUFiSqL0l4xpqMgftMlb+9bMOPuhsm3biuah LcaQ== X-Gm-Message-State: AOJu0YzgGXPPNC/4KeG/vOIMc0t2Yoedjvp0hGoiUdvLeRBJetyzeOAP NH9B0PcuXUSedY9xvB+SmSD1bFnylqZcSUHmBu64MowcyqHfr7S2QezD3b9K5v9DjrB0UaenqBS UV5EHhE198+vxi19ypw== X-Received: by 2002:ad4:530e:0:b0:66f:f810:9e2b with SMTP id y14-20020ad4530e000000b0066ff8109e2bmr965725qvr.52.1699928803033; Mon, 13 Nov 2023 18:26:43 -0800 (PST) X-Google-Smtp-Source: AGHT+IFXYK42D3fzp8NxCf9/vtt/JJ1bvzsE5Q4qnFfN42kUbvywTC+EKfxcSeX19iwLP62PHPYRVA== X-Received: by 2002:ad4:530e:0:b0:66f:f810:9e2b with SMTP id y14-20020ad4530e000000b0066ff8109e2bmr965711qvr.52.1699928802587; Mon, 13 Nov 2023 18:26:42 -0800 (PST) Received: from [192.168.1.108] (130-44-146-16.s12558.c3-0.arl-cbr1.sbo-arl.ma.cable.rcncustomer.com. [130.44.146.16]) by smtp.gmail.com with ESMTPSA id su7-20020a05620a4b4700b007756c8ce8f5sm2305059qkn.59.2023.11.13.18.26.41 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Mon, 13 Nov 2023 18:26:41 -0800 (PST) Message-ID: <5b947ae5-b4bb-4bf2-91b5-6dcace7b537d@redhat.com> Date: Mon, 13 Nov 2023 21:26:41 -0500 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: [PATCH v2] c++: fix parsing with auto(x) [PR112410] To: Marek Polacek Cc: GCC Patches References: <20231109195835.429291-1-polacek@redhat.com> <1c680274-040d-40d7-b998-b100084c0ba5@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=-12.3 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_H4,RCVD_IN_MSPIKE_WL,SPF_HELO_NONE,SPF_NONE,TXREP,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: On 11/10/23 20:13, Marek Polacek wrote: > On Thu, Nov 09, 2023 at 07:07:03PM -0500, Jason Merrill wrote: >> On 11/9/23 14:58, Marek Polacek wrote: >>> Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk? >>> >>> -- >8 -- >>> Here we are wrongly parsing >>> >>> int y(auto(42)); >>> >>> which uses the C++23 cast-to-prvalue feature, and initializes y to 42. >>> However, we were treating the auto as an implicit template parameter. >>> >>> Fixing the auto{42} case is easy, but when auto is followed by a (, >>> I found the fix to be much more involved. For instance, we cannot >>> use cp_parser_expression, because that can give hard errors. It's >>> also necessary to disambiguate 'auto(i)' as 'auto i', not a cast. >>> auto(), auto(int), auto(f)(int), auto(*), auto(i[]), auto(...), etc. >>> are all function declarations. We have to look at more than one >>> token to decide. >> >> Yeah, this is a most vexing parse problem. The code is synthesizing >> template parameters before we've resolved whether the auto is a >> decl-specifier or not. >> >>> In this fix, I'm (ab)using cp_parser_declarator, with member_p=false >>> so that it doesn't commit. But it handles even more complicated >>> cases as >>> >>> int fn (auto (*const **&f)(int) -> char); >> >> But it doesn't seem to handle the extremely vexing >> >> struct A { >> A(int,int); >> }; >> >> int main() >> { >> int a; >> A b(auto(a), 42); >> } > > Argh. This test should indeed be accepted and is currently rejected, > but it's a different problem: 'b' is at block scope and you can't > have a template there. But when I put it into a namespace scope, > it shows that my patch doesn't work correctly. I've added auto-fncast14.C > for the latter and opened c++/112482 for the block-scope problem. > >> I think we need to stop synthesizing immediately when we see RID_AUTO, and >> instead go back after we successfully parse a declaration and synthesize for >> any autos we saw along the way. :/ > > That seems very complicated :(. I had a different idea though; how > about the following patch? The idea is that if we see that parsing > the parameter-declaration-list didn't work, we undo what synthesize_ > did, and let cp_parser_initializer parse "(auto(42))", which should > succeed. I checked that after cp_finish_decl y is initialized to 42. Nice, that's much simpler. Do you also still need the changes to cp_parser_simple_type_specifier? > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk? > > -- >8 -- > Here we are wrongly parsing > > int y(auto(42)); > > which uses the C++23 cast-to-prvalue feature, and initializes y to 42. > However, we were treating the auto as an implicit template parameter. > > Fixing the auto{42} case is easy, but when auto is followed by a (, > I found the fix to be much more involved. For instance, we cannot > use cp_parser_expression, because that can give hard errors. It's > also necessary to disambiguate 'auto(i)' as 'auto i', not a cast. > auto(), auto(int), auto(f)(int), auto(*), auto(i[]), auto(...), etc. > are all function declarations. > > This patch rectifies that by undoing the implicit function template > modification. In the test above, we should notice that the parameter > list is ill-formed, and since we've synthesized an implicit template > parameter, we undo it by calling abort_fully_implicit_template. Then, > we'll parse the "(auto(42))" as an initializer. > > PR c++/112410 > > gcc/cp/ChangeLog: > > * parser.cc (cp_parser_simple_type_specifier): Disambiguate > between a variable and function declaration with auto. > (cp_parser_parameter_declaration_clause): Maybe call > abort_fully_implicit_template if it turned out the parameter list was > ill-formed. > > gcc/testsuite/ChangeLog: > > * g++.dg/cpp23/auto-fncast13.C: New test. > * g++.dg/cpp23/auto-fncast14.C: New test. > --- > gcc/cp/parser.cc | 27 +++++++++- > gcc/testsuite/g++.dg/cpp23/auto-fncast13.C | 61 ++++++++++++++++++++++ > gcc/testsuite/g++.dg/cpp23/auto-fncast14.C | 9 ++++ > 3 files changed, 96 insertions(+), 1 deletion(-) > create mode 100644 gcc/testsuite/g++.dg/cpp23/auto-fncast13.C > create mode 100644 gcc/testsuite/g++.dg/cpp23/auto-fncast14.C > > diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc > index 5116bcb78f6..947351b09b8 100644 > --- a/gcc/cp/parser.cc > +++ b/gcc/cp/parser.cc > @@ -19991,6 +19991,8 @@ cp_parser_simple_type_specifier (cp_parser* parser, > /* The 'auto' might be the placeholder return type for a function decl > with trailing return type. */ > bool have_trailing_return_fn_decl = false; > + /* Or it might be auto(x) or auto {x}. */ > + bool decay_copy = false; > > cp_parser_parse_tentatively (parser); > cp_lexer_consume_token (parser->lexer); > @@ -20008,6 +20010,11 @@ cp_parser_simple_type_specifier (cp_parser* parser, > /*consume_paren*/true); > continue; > } > + else if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE)) > + { > + decay_copy = true; > + break; > + } > > if (cp_lexer_next_token_is (parser->lexer, CPP_DEREF)) > { > @@ -20019,6 +20026,11 @@ cp_parser_simple_type_specifier (cp_parser* parser, > } > cp_parser_abort_tentative_parse (parser); > > + if (decay_copy) > + { > + type = error_mark_node; > + break; > + } > if (have_trailing_return_fn_decl) > { > type = make_auto (); > @@ -24973,7 +24985,20 @@ cp_parser_parameter_declaration_clause (cp_parser* parser, > parameter-declaration-list, then the entire > parameter-declaration-clause is erroneous. */ > if (parameters == error_mark_node) > - return NULL_TREE; > + { > + /* For code like > + int x(auto(42)); > + A a(auto(i), 42); > + we have synthesized an implicit template parameter and marked > + what we thought was a function as an implicit function template. > + But now, having seen the whole parameter list, we know it's not > + a function declaration, so undo that. */ > + if (parser->fully_implicit_function_template_p > + /* Don't do this for the inner (). */ > + && parser->default_arg_ok_p) > + abort_fully_implicit_template (parser); > + return NULL_TREE; > + } > > /* Peek at the next token. */ > token = cp_lexer_peek_token (parser->lexer); > diff --git a/gcc/testsuite/g++.dg/cpp23/auto-fncast13.C b/gcc/testsuite/g++.dg/cpp23/auto-fncast13.C > new file mode 100644 > index 00000000000..1bceffb70cf > --- /dev/null > +++ b/gcc/testsuite/g++.dg/cpp23/auto-fncast13.C > @@ -0,0 +1,61 @@ > +// PR c++/112410 > +// { dg-do compile { target c++23 } } > + > +int f1 (auto(int) -> char); > +int f2 (auto x); > +int f3 (auto); > +int f4 (auto(i)); > + > +int v1 (auto(42)); > +int v2 (auto{42}); > +int e1 (auto{i}); // { dg-error "not declared" } > +int i; > +int v3 (auto{i}); > +int v4 (auto(i + 1)); > +int v5 (auto(+i)); > +int v6 (auto(i = 4)); > + > +int f5 (auto(i)); > +int f6 (auto()); > +int f7 (auto(int)); > +int f8 (auto(f)(int)); > +int f9 (auto(...) -> char); > +// FIXME: ICEs (PR c++/89867) > +//int f10 (auto(__attribute__((unused)) i)); > +int f11 (auto((i))); > +int f12 (auto(i[])); > +int f13 (auto(*i)); > +int f14 (auto(*)); > + > +int e2 (auto{}); // { dg-error "invalid use of .auto." } > +int e3 (auto(i, i)); // { dg-error "invalid use of .auto." } > + > +char bar (int); > +char baz (); > +char qux (...); > + > +void > +g (int i) > +{ > + f1 (bar); > + f2 (42); > + f3 (42); > + f4 (42); > + f5 (42); > + f6 (baz); > + f7 (bar); > + f8 (bar); > + f9 (qux); > +// f10 (42); > + f11 (42); > + f12 (&i); > + f13 (&i); > + f14 (&i); > + > + v1 = 1; > + v2 = 2; > + v3 = 3; > + v4 = 4; > + v5 = 5; > + v6 = 6; > +} > diff --git a/gcc/testsuite/g++.dg/cpp23/auto-fncast14.C b/gcc/testsuite/g++.dg/cpp23/auto-fncast14.C > new file mode 100644 > index 00000000000..9e7a06c87d5 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/cpp23/auto-fncast14.C > @@ -0,0 +1,9 @@ > +// PR c++/112410 > +// { dg-do compile { target c++23 } } > + > +struct A { > + A(int,int); > +}; > + > +int a; > +A b1(auto(a), 42); > > base-commit: e0c1476d5d7c450b1b16a40364cea4e91237ea93