[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