]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Revert "c++: reorganize friend template matching [PR91618]"
authorJason Merrill <jason@redhat.com>
Wed, 3 May 2023 18:16:00 +0000 (14:16 -0400)
committerJason Merrill <jason@redhat.com>
Wed, 3 May 2023 19:23:46 +0000 (15:23 -0400)
This patch was just a cleanup after the actual bugfix, so let's revert it on
the branch.

PR c++/109649

This reverts commit e9d2adc17d0dbe46db67e1b618dea888d5c7aca3.

gcc/cp/decl.cc
gcc/cp/decl2.cc
gcc/cp/friend.cc

index 71d33d2b7a4d266b1e91bb335fdbe5594ed14c70..5fe4c53523dc9975b49fc786493d620de8b2b28b 100644 (file)
@@ -14428,6 +14428,15 @@ grokdeclarator (const cp_declarator *declarator,
                cplus_decl_attributes (&decl, *attrlist, 0);
                *attrlist = NULL_TREE;
 
+               if (template_class_depth (current_class_type) == 0)
+                 {
+                   decl = check_explicit_specialization
+                     (unqualified_id, decl, template_count,
+                      2 * funcdef_flag + 4);
+                   if (decl == error_mark_node)
+                     return error_mark_node;
+                 }
+
                tree scope = ctype ? ctype : in_namespace;
                decl = do_friend (scope, unqualified_id, decl,
                                  flags, funcdef_flag);
index 9594be4092c3c00fddc9d4c6da5931ea3b7e8792..1dd3c2b13bc219a836318f2ff5bfd670707ae1db 100644 (file)
@@ -853,9 +853,14 @@ check_classfn (tree ctype, tree function, tree template_parms)
         is replaced with the specialization chosen by deduction from the
         friend declaration or discarded if deduction fails."
 
-        So tell check_explicit_specialization to look for a match.  */
+        So ask check_explicit_specialization to find a matching template.  */
       SET_DECL_IMPLICIT_INSTANTIATION (function);
-      matched = function;
+      tree spec = check_explicit_specialization (DECL_NAME (function),
+                                                function, /* tcount */0,
+                                                /* friend flag */4,
+                                                /* attrlist */NULL_TREE);
+      if (spec != error_mark_node)
+       matched = spec;
     }
 
   if (!matched)
index b36de2b20bba9f945299566c68b2e2af069bcb2e..4d546b4fef79e9dbf3b5c534da7388349e2a81e8 100644 (file)
@@ -521,7 +521,6 @@ do_friend (tree scope, tree declarator, tree decl,
     error ("friend declaration %qD may not have virt-specifiers",
           decl);
 
-  tree orig_declarator = declarator;
   if (TREE_CODE (declarator) == TEMPLATE_ID_EXPR)
     {
       declarator = TREE_OPERAND (declarator, 0);
@@ -529,33 +528,32 @@ do_friend (tree scope, tree declarator, tree decl,
        declarator = OVL_NAME (declarator);
     }
 
-  /* CLASS_TEMPLATE_DEPTH counts the number of template headers for
-     the enclosing class.  FRIEND_DEPTH counts the number of template
-     headers used for this friend declaration.  TEMPLATE_MEMBER_P is
-     true if a template header in FRIEND_DEPTH is intended for
-     DECLARATOR.  For example, the code
-
-     template <class T> struct A {
-       template <class U> struct B {
-        template <class V> template <class W>
-          friend void C<V>::f(W);
-       };
-     };
-
-     will eventually give the following results
-
-     1. CLASS_TEMPLATE_DEPTH equals 2 (for `T' and `U').
-     2. FRIEND_DEPTH equals 2 (for `V' and `W').
-     3. CTYPE_DEPTH equals 1 (for `V').
-     4. TEMPLATE_MEMBER_P is true (for `W').  */
-
-  int class_template_depth = template_class_depth (current_class_type);
-  int friend_depth = current_template_depth - class_template_depth;
-  int ctype_depth = num_template_headers_for_class (ctype);
-  bool template_member_p = friend_depth > ctype_depth;
-
   if (ctype)
     {
+      /* CLASS_TEMPLATE_DEPTH counts the number of template headers for
+        the enclosing class.  FRIEND_DEPTH counts the number of template
+        headers used for this friend declaration.  TEMPLATE_MEMBER_P is
+        true if a template header in FRIEND_DEPTH is intended for
+        DECLARATOR.  For example, the code
+
+          template <class T> struct A {
+            template <class U> struct B {
+              template <class V> template <class W>
+                friend void C<V>::f(W);
+            };
+          };
+
+        will eventually give the following results
+
+        1. CLASS_TEMPLATE_DEPTH equals 2 (for `T' and `U').
+        2. FRIEND_DEPTH equals 2 (for `V' and `W').
+        3. TEMPLATE_MEMBER_P is true (for `W').  */
+
+      int class_template_depth = template_class_depth (current_class_type);
+      int friend_depth = current_template_depth - class_template_depth;
+      /* We will figure this out later.  */
+      bool template_member_p = false;
+
       tree cname = TYPE_NAME (ctype);
       if (TREE_CODE (cname) == TYPE_DECL)
        cname = DECL_NAME (cname);
@@ -566,6 +564,13 @@ do_friend (tree scope, tree declarator, tree decl,
 
       grokclassfn (ctype, decl, flags);
 
+      if (friend_depth)
+       {
+         if (!uses_template_parms_level (ctype, class_template_depth
+                                                + friend_depth))
+           template_member_p = true;
+       }
+
       /* A nested class may declare a member of an enclosing class
         to be a friend, so we do lookup here even if CTYPE is in
         the process of being defined.  */
@@ -594,6 +599,9 @@ do_friend (tree scope, tree declarator, tree decl,
               || (class_template_depth && friend_depth))
              && decl && TREE_CODE (decl) == FUNCTION_DECL)
            decl = DECL_TI_TEMPLATE (decl);
+
+         if (decl)
+           add_friend (current_class_type, decl, /*complain=*/true);
        }
       else
        error ("member %qD declared as friend before type %qT defined",
@@ -602,6 +610,7 @@ do_friend (tree scope, tree declarator, tree decl,
   else
     {
       /* Namespace-scope friend function.  */
+      int is_friend_template = PROCESSING_REAL_TEMPLATE_DECL_P ();
 
       if (funcdef_flag)
        SET_DECL_FRIEND_CONTEXT (decl, current_class_type);
@@ -612,11 +621,12 @@ do_friend (tree scope, tree declarator, tree decl,
             arguments before push_template_decl adds a reference to
             the containing template class.  */
          int warn = (warn_nontemplate_friend
-                     && ! funcdef_flag && ! friend_depth
+                     && ! funcdef_flag && ! is_friend_template
                      && current_template_parms
                      && uses_template_parms (decl));
 
-         if (friend_depth || class_template_depth)
+         if (is_friend_template
+             || template_class_depth (current_class_type) != 0)
            /* We can't call pushdecl for a template class, since in
               general, such a declaration depends on template
               parameters.  Instead, we call pushdecl when the class
@@ -656,26 +666,14 @@ do_friend (tree scope, tree declarator, tree decl,
                }
            }
        }
-    }
 
-  if (decl == error_mark_node)
-    return error_mark_node;
-
-  if (!class_template_depth && DECL_IMPLICIT_INSTANTIATION (decl))
-    /* "[if no non-template match is found,] each remaining function template
-       is replaced with the specialization chosen by deduction from the
-       friend declaration or discarded if deduction fails."
-
-       set_decl_namespace or check_classfn set DECL_IMPLICIT_INSTANTIATION to
-       indicate that we need a template match, so ask
-       check_explicit_specialization to find one.  */
-    decl = (check_explicit_specialization
-           (orig_declarator, decl, ctype_depth,
-            2 * funcdef_flag + 4));
-
-  add_friend (current_class_type,
-             (!ctype && friend_depth) ? DECL_TI_TEMPLATE (decl) : decl,
-             /*complain=*/true);
+      if (decl == error_mark_node)
+       return error_mark_node;
+
+      add_friend (current_class_type,
+                 is_friend_template ? DECL_TI_TEMPLATE (decl) : decl,
+                 /*complain=*/true);
+    }
 
   return decl;
 }