[PATCH] c++: recognize class-scope non-template dguides [PR79501]

Jason Merrill jason@redhat.com
Wed Aug 11 17:32:28 GMT 2021


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.

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



More information about the Gcc-patches mailing list