+ if (TREE_CODE (TYPENAME_TYPE_FULLNAME (friend_type))
+ == TEMPLATE_ID_EXPR)
+ {
+ /* template <class U> friend class T::X<U>; */
+ /* [temp.friend]
+ Friend declarations shall not declare partial
+ specializations. */
+ error ("partial specialization %qT declared %<friend%>",
+ friend_type);
+ return;
+ }
+ else
+ {
+ /* We will figure this out later. */
+ bool template_member_p = false;
+
+ tree ctype = TYPE_CONTEXT (friend_type);
+ tree name = TYPE_IDENTIFIER (friend_type);
+ tree decl;
+
+ if (!uses_template_parms_level (ctype, class_template_depth
+ + friend_depth))
+ template_member_p = true;
+
+ if (class_template_depth)
+ {
+ /* We rely on tsubst_friend_class to check the
+ validity of the declaration later. */
+ if (template_member_p)
+ friend_type
+ = make_unbound_class_template (ctype,
+ name,
+ current_template_parms,
+ tf_error);
+ else
+ friend_type
+ = make_typename_type (ctype, name, class_type, tf_error);
+ }
+ else
+ {
+ decl = lookup_member (ctype, name, 0, true);
+ if (!decl)
+ {
+ error ("%qT is not a member of %qT", name, ctype);
+ return;
+ }
+ if (template_member_p && !DECL_CLASS_TEMPLATE_P (decl))
+ {
+ error ("%qT is not a member class template of %qT",
+ name, ctype);
+ error ("%q+D declared here", decl);
+ return;
+ }
+ if (!template_member_p && (TREE_CODE (decl) != TYPE_DECL
+ || !CLASS_TYPE_P (TREE_TYPE (decl))))
+ {
+ error ("%qT is not a nested class of %qT",
+ name, ctype);
+ error ("%q+D declared here", decl);
+ return;
+ }
+
+ friend_type = CLASSTYPE_TI_TEMPLATE (TREE_TYPE (decl));
+ }
+ }