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

Reply via email to