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. -- >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); -- 2.33.0.rc1