From: Jason Merrill Date: Wed, 3 May 2023 18:16:00 +0000 (-0400) Subject: Revert "c++: reorganize friend template matching [PR91618]" X-Git-Tag: releases/gcc-13.2.0~326 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=6138e862038180c7cfb94d6c120bd0b76da382ae;p=thirdparty%2Fgcc.git Revert "c++: reorganize friend template matching [PR91618]" 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. --- diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc index 71d33d2b7a4d..5fe4c53523dc 100644 --- a/gcc/cp/decl.cc +++ b/gcc/cp/decl.cc @@ -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); diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc index 9594be4092c3..1dd3c2b13bc2 100644 --- a/gcc/cp/decl2.cc +++ b/gcc/cp/decl2.cc @@ -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) diff --git a/gcc/cp/friend.cc b/gcc/cp/friend.cc index b36de2b20bba..4d546b4fef79 100644 --- a/gcc/cp/friend.cc +++ b/gcc/cp/friend.cc @@ -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 struct A { - template struct B { - template template - friend void C::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 struct A { + template struct B { + template template + friend void C::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; }