[PATCH] c++: recognize class-scope non-template dguides [PR79501]
Jason Merrill
jason@redhat.com
Wed Aug 11 18:47:45 GMT 2021
On 8/11/21 2:29 PM, Patrick Palka wrote:
> On Wed, 11 Aug 2021, Jason Merrill wrote:
>
>> On 8/9/21 1:16 PM, Patrick Palka wrote:
>>> It looks like we still don't recognize class-scope non-template
>>> deduction guides even after r12-2260. This is because deduction guides
>>> are handled in cp_parser_init_declarator after calling
>>> cp_parser_declarator, but in the class-scope non-template case we call
>>> cp_parser_declarator directly from cp_parser_member_declaration.
>>>
>>> This patch makes us handle deduction guides in cp_parser_member_declaration
>>> as well.
>>>
>>> Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
>>> trunk?
>>>
>>> PR c++/79501
>>>
>>> gcc/cp/ChangeLog:
>>>
>>> * parser.c (cp_parser_maybe_adjust_declarator_for_dguide): New,
>>> split out from ...
>>> (cp_parser_init_declarator): ... here.
>>> (cp_parser_member_declaration): Use it.
>>>
>>> gcc/testsuite/ChangeLog:
>>>
>>> * g++.dg/cpp1z/class-deduction98.C: New test.
>>> ---
>>> gcc/cp/parser.c | 54 +++++++++++++------
>>> .../g++.dg/cpp1z/class-deduction98.C | 10 ++++
>>> 2 files changed, 49 insertions(+), 15 deletions(-)
>>> create mode 100644 gcc/testsuite/g++.dg/cpp1z/class-deduction98.C
>>>
>>> diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
>>> index d4da25ca703..04fdeec32ab 100644
>>> --- a/gcc/cp/parser.c
>>> +++ b/gcc/cp/parser.c
>>> @@ -21869,6 +21869,30 @@ warn_about_ambiguous_parse (const
>>> cp_decl_specifier_seq *decl_specifiers,
>>> }
>>> }
>>> +/* If the function declarator DECLARATOR names a class template, adjust
>>> + it to name its deduction guides and return true. Otherwise return
>>> false. */
>>> +
>>> +static bool
>>> +cp_parser_maybe_adjust_declarator_for_dguide (cp_parser *parser,
>>> + cp_declarator *declarator)
>>> +{
>>> + gcc_assert (function_declarator_p (declarator));
>>> +
>>> + cp_declarator *id = get_id_declarator (declarator);
>>> + tree name = id->u.id.unqualified_name;
>>> + parser->scope = id->u.id.qualifying_scope;
>>> + tree tmpl = cp_parser_lookup_name_simple (parser, name, id->id_loc);
>>> + if (tmpl
>>> + && (DECL_CLASS_TEMPLATE_P (tmpl)
>>> + || DECL_TEMPLATE_TEMPLATE_PARM_P (tmpl)))
>>> + {
>>> + id->u.id.unqualified_name = dguide_name (tmpl);
>>> + id->u.id.sfk = sfk_deduction_guide;
>>> + return true;
>>> + }
>>> + return false;
>>> +}
>>> +
>>> /* Declarators [gram.dcl.decl] */
>>> /* Parse an init-declarator.
>>> @@ -22045,25 +22069,16 @@ cp_parser_init_declarator (cp_parser* parser,
>>> if (function_declarator_p (declarator))
>>> {
>>> - /* Handle C++17 deduction guides. */
>>> + /* Handle C++17 deduction guides. Note that class-scope
>>> + non-template deduction guides are handled in
>>> + cp_parser_member_declaration. */
>>> if (!decl_specifiers->type
>>> && !decl_specifiers->any_type_specifiers_p
>>> && ctor_dtor_or_conv_p <= 0
>>> && cxx_dialect >= cxx17)
>>> - {
>>> - cp_declarator *id = get_id_declarator (declarator);
>>> - tree name = id->u.id.unqualified_name;
>>> - parser->scope = id->u.id.qualifying_scope;
>>> - tree tmpl = cp_parser_lookup_name_simple (parser, name, id->id_loc);
>>> - if (tmpl
>>> - && (DECL_CLASS_TEMPLATE_P (tmpl)
>>> - || DECL_TEMPLATE_TEMPLATE_PARM_P (tmpl)))
>>> - {
>>> - id->u.id.unqualified_name = dguide_name (tmpl);
>>> - id->u.id.sfk = sfk_deduction_guide;
>>> - ctor_dtor_or_conv_p = 1;
>>> - }
>>> - }
>>> + if (cp_parser_maybe_adjust_declarator_for_dguide (parser,
>>> + declarator))
>>> + ctor_dtor_or_conv_p = 1;
>>> if (!member_p && !cp_parser_error_occurred (parser))
>>> warn_about_ambiguous_parse (decl_specifiers, declarator);
>>> @@ -26719,6 +26734,15 @@ cp_parser_member_declaration (cp_parser* parser)
>>> cp_lexer_consume_token (parser->lexer);
>>> goto out;
>>> }
>>> + /* Handle class-scope non-template C++17 deduction guides. */
>>> + if (function_declarator_p (declarator)
>>> + && !decl_specifiers.type
>>> + && !decl_specifiers.any_type_specifiers_p
>>> + && ctor_dtor_or_conv_p <= 0
>>> + && cxx_dialect >= cxx17)
>>
>> Looks like you could factor more of the tests into the new function.
>
> That works nicely, like so? Bootstrap and regtesting in progress.
OK.
> -- >8 --
>
> Subject: [PATCH] c++: recognize class-scope non-template dguides [PR79501]
>
> It looks like we still don't recognize class-scope non-template
> deduction guides even after r12-2260. This is because deduction guides
> are tagged as such in cp_parser_init_declarator after calling
> cp_parser_declarator, but in cp_parser_member_declaration we call
> cp_parser_declarator directly.
>
> This patch makes us handle deduction guides in cp_parser_member_declaration
> as well.
>
> PR c++/79501
>
> gcc/cp/ChangeLog:
>
> * parser.c (maybe_adjust_declarator_for_dguide): New, split out
> from ...
> (cp_parser_init_declarator): ... here.
> (cp_parser_member_declaration): Use it.
>
> gcc/testsuite/ChangeLog:
>
> * g++.dg/cpp1z/class-deduction98.C: New test.
> ---
> gcc/cp/parser.c | 63 +++++++++++++------
> .../g++.dg/cpp1z/class-deduction98.C | 10 +++
> 2 files changed, 54 insertions(+), 19 deletions(-)
> create mode 100644 gcc/testsuite/g++.dg/cpp1z/class-deduction98.C
>
> diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
> index b2ddfe4f181..27bb7178464 100644
> --- a/gcc/cp/parser.c
> +++ b/gcc/cp/parser.c
> @@ -22081,6 +22081,37 @@ warn_about_ambiguous_parse (const cp_decl_specifier_seq *decl_specifiers,
> }
> }
>
> +/* If DECLARATOR with DECL_SPECS is a function declarator that has
> + the form of a deduction guide, tag it as such. CTOR_DTOR_OR_CONV_P
> + has the same meaning as in cp_parser_declarator. */
> +
> +static void
> +cp_parser_maybe_adjust_declarator_for_dguide (cp_parser *parser,
> + cp_decl_specifier_seq *decl_specs,
> + cp_declarator *declarator,
> + int *ctor_dtor_or_conv_p)
> +{
> + if (cxx_dialect >= cxx17
> + && *ctor_dtor_or_conv_p <= 0
> + && !decl_specs->type
> + && !decl_specs->any_type_specifiers_p
> + && function_declarator_p (declarator))
> + {
> + cp_declarator *id = get_id_declarator (declarator);
> + tree name = id->u.id.unqualified_name;
> + parser->scope = id->u.id.qualifying_scope;
> + tree tmpl = cp_parser_lookup_name_simple (parser, name, id->id_loc);
> + if (tmpl
> + && (DECL_CLASS_TEMPLATE_P (tmpl)
> + || DECL_TEMPLATE_TEMPLATE_PARM_P (tmpl)))
> + {
> + id->u.id.unqualified_name = dguide_name (tmpl);
> + id->u.id.sfk = sfk_deduction_guide;
> + *ctor_dtor_or_conv_p = 1;
> + }
> + }
> +}
> +
> /* Declarators [gram.dcl.decl] */
>
> /* Parse an init-declarator.
> @@ -22257,25 +22288,13 @@ cp_parser_init_declarator (cp_parser* parser,
>
> if (function_declarator_p (declarator))
> {
> - /* Handle C++17 deduction guides. */
> - if (!decl_specifiers->type
> - && !decl_specifiers->any_type_specifiers_p
> - && ctor_dtor_or_conv_p <= 0
> - && cxx_dialect >= cxx17)
> - {
> - cp_declarator *id = get_id_declarator (declarator);
> - tree name = id->u.id.unqualified_name;
> - parser->scope = id->u.id.qualifying_scope;
> - tree tmpl = cp_parser_lookup_name_simple (parser, name, id->id_loc);
> - if (tmpl
> - && (DECL_CLASS_TEMPLATE_P (tmpl)
> - || DECL_TEMPLATE_TEMPLATE_PARM_P (tmpl)))
> - {
> - id->u.id.unqualified_name = dguide_name (tmpl);
> - id->u.id.sfk = sfk_deduction_guide;
> - ctor_dtor_or_conv_p = 1;
> - }
> - }
> + /* Handle C++17 deduction guides. Note that class-scope
> + non-template deduction guides are instead handled in
> + cp_parser_member_declaration. */
> + cp_parser_maybe_adjust_declarator_for_dguide (parser,
> + decl_specifiers,
> + declarator,
> + &ctor_dtor_or_conv_p);
>
> if (!member_p && !cp_parser_error_occurred (parser))
> warn_about_ambiguous_parse (decl_specifiers, declarator);
> @@ -26959,6 +26978,12 @@ cp_parser_member_declaration (cp_parser* parser)
> goto out;
> }
>
> + /* Handle class-scope non-template C++17 deduction guides. */
> + cp_parser_maybe_adjust_declarator_for_dguide (parser,
> + &decl_specifiers,
> + declarator,
> + &ctor_dtor_or_conv_p);
> +
> if (declares_class_or_enum & 2)
> cp_parser_check_for_definition_in_return_type
> (declarator, decl_specifiers.type,
> diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction98.C b/gcc/testsuite/g++.dg/cpp1z/class-deduction98.C
> new file mode 100644
> index 00000000000..bee0ce433ee
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction98.C
> @@ -0,0 +1,10 @@
> +// PR c++/79501
> +// { dg-do compile { target c++17 } }
> +
> +template<class T>
> +struct A {
> + template<class U> struct B { template<class V> B(V); };
> + B(T) -> B<T>;
> +};
> +
> +A<int>::B b(0);
>
More information about the Gcc-patches
mailing list