bool generic_lambda_fn_p (tree callop) { return (LAMBDA_FUNCTION_P (callop) && DECL_TEMPLATE_INFO (callop) && PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (callop))); }
void make_friend_class (tree type, tree friend_type, bool complain) { tree classes; /* 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, defined inside the `if' block for TYPENAME_TYPE case, 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 class C<V>::D; }; }; 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'). The friend is a template friend iff FRIEND_DEPTH is nonzero. */ int class_template_depth = template_class_depth (type); int friend_depth = processing_template_decl - class_template_depth; if (! MAYBE_CLASS_TYPE_P (friend_type) && TREE_CODE (friend_type) != TEMPLATE_TEMPLATE_PARM) { /* N1791: If the type specifier in a friend declaration designates a (possibly cv-qualified) class type, that class is declared as a friend; otherwise, the friend declaration is ignored. So don't complain in C++11 mode. */ if (cxx_dialect < cxx11) pedwarn (input_location, complain ? 0 : OPT_Wpedantic, "invalid type %qT declared %<friend%>", friend_type); return; } friend_type = cv_unqualified (friend_type); if (check_for_bare_parameter_packs (friend_type)) return; if (friend_depth) { /* [temp.friend] Friend declarations shall not declare partial specializations. */ if (CLASS_TYPE_P (friend_type) && CLASSTYPE_TEMPLATE_SPECIALIZATION (friend_type) && uses_template_parms (friend_type)) { error ("partial specialization %qT declared %<friend%>", friend_type); return; } if (TYPE_TEMPLATE_INFO (friend_type) && !PRIMARY_TEMPLATE_P (TYPE_TI_TEMPLATE (friend_type))) { error ("%qT is not a template", friend_type); inform (location_of (friend_type), "previous declaration here"); if (TYPE_CLASS_SCOPE_P (friend_type) && CLASSTYPE_TEMPLATE_INFO (TYPE_CONTEXT (friend_type)) && currently_open_class (TYPE_CONTEXT (friend_type))) inform (input_location, "perhaps you need explicit template " "arguments in your nested-name-specifier"); return; } } /* It makes sense for a template class to be friends with itself, that means the instantiations can be friendly. Other cases are not so meaningful. */ if (!friend_depth && same_type_p (type, friend_type)) { if (complain) warning (0, "class %qT is implicitly friends with itself", type); return; } /* [temp.friend] 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. */ if (!friend_depth) ;/* ok */ else if (TREE_CODE (friend_type) == TYPENAME_TYPE) { 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, tf_warning_or_error); 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); inform (DECL_SOURCE_LOCATION (decl), "%qD 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); inform (DECL_SOURCE_LOCATION (decl), "%qD declared here", decl); return; } friend_type = CLASSTYPE_TI_TEMPLATE (TREE_TYPE (decl)); } } } else if (TREE_CODE (friend_type) == TEMPLATE_TYPE_PARM) { /* template <class T> friend class T; */ error ("template parameter type %qT declared %<friend%>", friend_type); return; } else if (TREE_CODE (friend_type) == TEMPLATE_TEMPLATE_PARM) friend_type = TYPE_NAME (friend_type); else if (!CLASSTYPE_TEMPLATE_INFO (friend_type)) { /* template <class T> friend class A; where A is not a template */ error ("%q#T is not a template", friend_type); return; } else /* template <class T> friend class A; where A is a template */ friend_type = CLASSTYPE_TI_TEMPLATE (friend_type); if (friend_type == error_mark_node) return; /* See if it is already a friend. */ for (classes = CLASSTYPE_FRIEND_CLASSES (type); classes; classes = TREE_CHAIN (classes)) { tree probe = TREE_VALUE (classes); if (TREE_CODE (friend_type) == TEMPLATE_DECL) { if (friend_type == probe) { if (complain) warning (OPT_Wredundant_decls, "%qD is already a friend of %qT", probe, type); break; } } else if (TREE_CODE (probe) != TEMPLATE_DECL) { if (same_type_p (probe, friend_type)) { if (complain) warning (OPT_Wredundant_decls, "%qT is already a friend of %qT", probe, type); break; } } } if (!classes) { 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 (TREE_CODE (friend_type) == TEMPLATE_DECL) friend_type = TREE_TYPE (friend_type); if (!uses_template_parms (type)) CLASSTYPE_BEFRIENDING_CLASSES (friend_type) = tree_cons (NULL_TREE, type, CLASSTYPE_BEFRIENDING_CLASSES (friend_type)); } }