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.

So let's tag them 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.
This commit is contained in:
Patrick Palka 2021-08-11 15:59:22 -04:00
parent 6186708312
commit 7e39d1a15f
2 changed files with 54 additions and 19 deletions

View File

@ -22078,6 +22078,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.
@ -22254,25 +22285,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);
@ -26956,6 +26975,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,

View File

@ -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);