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) + if (cp_parser_maybe_adjust_declarator_for_dguide (parser, + declarator)) + ctor_dtor_or_conv_p = 1; if (declares_class_or_enum & 2) cp_parser_check_for_definition_in_return_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