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)
+               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);
-- 
2.33.0.rc1

Reply via email to