diff options
Diffstat (limited to 'contrib/gcc/cp/friend.c')
-rw-r--r-- | contrib/gcc/cp/friend.c | 50 |
1 files changed, 31 insertions, 19 deletions
diff --git a/contrib/gcc/cp/friend.c b/contrib/gcc/cp/friend.c index 441be67..9280a09 100644 --- a/contrib/gcc/cp/friend.c +++ b/contrib/gcc/cp/friend.c @@ -30,7 +30,7 @@ Boston, MA 02111-1307, USA. */ /* Friend data structures are described in cp-tree.h. */ -/* Returns non-zero if SUPPLICANT is a friend of TYPE. */ +/* Returns nonzero if SUPPLICANT is a friend of TYPE. */ int is_friend (type, supplicant) @@ -64,6 +64,10 @@ is_friend (type, supplicant) if (supplicant == TREE_VALUE (friends)) return 1; + /* We haven't completed the instantiation yet. */ + if (TREE_CODE (supplicant) == TEMPLATE_DECL) + return 1; + /* Temporarily, we are more lenient to deal with nested friend functions, for which there can be more than one FUNCTION_DECL, despite being the @@ -114,7 +118,7 @@ is_friend (type, supplicant) else context = NULL_TREE; - /* A namespace is not friend to anybody. */ + /* A namespace is not friend to anybody. */ if (context && TREE_CODE (context) == NAMESPACE_DECL) context = NULL_TREE; @@ -159,6 +163,9 @@ add_friend (type, decl) return; } } + + maybe_add_class_template_decl_list (type, decl, /*friend_p=*/1); + TREE_VALUE (list) = tree_cons (error_mark_node, decl, TREE_VALUE (list)); return; @@ -166,6 +173,8 @@ add_friend (type, decl) list = TREE_CHAIN (list); } + maybe_add_class_template_decl_list (type, decl, /*friend_p=*/1); + DECL_FRIENDLIST (typedecl) = tree_cons (DECL_NAME (decl), build_tree_list (error_mark_node, decl), DECL_FRIENDLIST (typedecl)); @@ -198,24 +207,25 @@ make_friend_class (type, friend_type) return; } - if (CLASS_TYPE_P (friend_type) - && CLASSTYPE_TEMPLATE_SPECIALIZATION (friend_type) - && uses_template_parms (friend_type)) - { - /* [temp.friend] - - Friend declarations shall not declare partial - specializations. */ - error ("partial specialization `%T' declared `friend'", - friend_type); - return; - } - if (processing_template_decl > template_class_depth (type)) /* If the TYPE is a template then it makes sense for it to be friends with itself; this means that each instantiation is friends with all other instantiations. */ - is_template_friend = 1; + { + if (CLASS_TYPE_P (friend_type) + && CLASSTYPE_TEMPLATE_SPECIALIZATION (friend_type) + && uses_template_parms (friend_type)) + { + /* [temp.friend] + Friend declarations shall not declare partial + specializations. */ + error ("partial specialization `%T' declared `friend'", + friend_type); + return; + } + + is_template_friend = 1; + } else if (same_type_p (type, friend_type)) { pedwarn ("class `%T' is implicitly friends with itself", @@ -230,7 +240,7 @@ make_friend_class (type, friend_type) A friend of a class or class template can be a function or class template, a specialization of a function template or class template, or an ordinary (nontemplate) function or - class. */ + class. */ if (!is_template_friend) ;/* ok */ else if (TREE_CODE (friend_type) == TYPENAME_TYPE) @@ -267,6 +277,8 @@ make_friend_class (type, friend_type) TREE_VALUE (classes), type); else { + maybe_add_class_template_decl_list (type, friend_type, /*friend_p=*/1); + CLASSTYPE_FRIEND_CLASSES (type) = tree_cons (NULL_TREE, friend_type, CLASSTYPE_FRIEND_CLASSES (type)); if (is_template_friend) @@ -396,14 +408,14 @@ do_friend (ctype, declarator, decl, parmdecls, attrlist, /* This must be a local class, so pushdecl will be ok, and insert an unqualified friend into the local scope (rather than the containing namespace scope, which the - next choice will do). */ + next choice will do). */ decl = pushdecl (decl); else { /* We can't use pushdecl, as we might be in a template class specialization, and pushdecl will insert an unqualified friend decl into the template parameter - scope, rather than the namespace containing it. */ + scope, rather than the namespace containing it. */ tree ns = decl_namespace_context (decl); push_nested_namespace (ns); |