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


Reply via email to