Commit 091bffba by Jason Merrill Committed by Jason Merrill

friend.c (make_friend_class): Handle template template parameters.

	* friend.c (make_friend_class): Handle template template parameters.
	* parser.c (cp_parser_template_declaration_after_export): Likewise.
	* pt.c (tsubst_friend_class): Likewise.
	(instantiate_class_template_1): Likewise
	* decl.c (check_elaborated_type_specifier): Likewise.
	(lookup_and_check_tag): Likewise.

From-SVN: r190828
parent 5cb25c9c
2012-08-30 Jason Merrill <jason@redhat.com> 2012-08-30 Jason Merrill <jason@redhat.com>
* friend.c (make_friend_class): Handle template template parameters.
* parser.c (cp_parser_template_declaration_after_export): Likewise.
* pt.c (tsubst_friend_class): Likewise.
(instantiate_class_template_1): Likewise
* decl.c (check_elaborated_type_specifier): Likewise.
(lookup_and_check_tag): Likewise.
* pt.c (get_class_bindings): Call coerce_template_parms. Add * pt.c (get_class_bindings): Call coerce_template_parms. Add
main_tmpl parameter. main_tmpl parameter.
(more_specialized_class): Add main_tmpl parameter. (more_specialized_class): Add main_tmpl parameter.
......
...@@ -11484,9 +11484,10 @@ check_elaborated_type_specifier (enum tag_types tag_code, ...@@ -11484,9 +11484,10 @@ check_elaborated_type_specifier (enum tag_types tag_code,
type, tag_name (tag_code)); type, tag_name (tag_code));
return error_mark_node; return error_mark_node;
} }
/* Accept bound template template parameters. */ /* Accept template template parameters. */
else if (allow_template_p else if (allow_template_p
&& TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM) && (TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM
|| TREE_CODE (type) == TEMPLATE_TEMPLATE_PARM))
; ;
/* [dcl.type.elab] /* [dcl.type.elab]
...@@ -11574,7 +11575,9 @@ lookup_and_check_tag (enum tag_types tag_code, tree name, ...@@ -11574,7 +11575,9 @@ lookup_and_check_tag (enum tag_types tag_code, tree name,
else else
decl = lookup_type_scope (name, scope); decl = lookup_type_scope (name, scope);
if (decl && DECL_CLASS_TEMPLATE_P (decl)) if (decl
&& (DECL_CLASS_TEMPLATE_P (decl)
|| DECL_TEMPLATE_TEMPLATE_PARM_P (decl)))
decl = DECL_TEMPLATE_RESULT (decl); decl = DECL_TEMPLATE_RESULT (decl);
if (decl && TREE_CODE (decl) == TYPE_DECL) if (decl && TREE_CODE (decl) == TYPE_DECL)
...@@ -11679,6 +11682,9 @@ xref_tag_1 (enum tag_types tag_code, tree name, ...@@ -11679,6 +11682,9 @@ xref_tag_1 (enum tag_types tag_code, tree name,
&& template_class_depth (current_class_type) && template_class_depth (current_class_type)
&& template_header_p) && template_header_p)
{ {
if (TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM)
return t;
/* Since SCOPE is not TS_CURRENT, we are not looking at a /* Since SCOPE is not TS_CURRENT, we are not looking at a
definition of this tag. Since, in addition, we are currently definition of this tag. Since, in addition, we are currently
processing a (member) template declaration of a template processing a (member) template declaration of a template
......
...@@ -224,7 +224,8 @@ make_friend_class (tree type, tree friend_type, bool complain) ...@@ -224,7 +224,8 @@ make_friend_class (tree type, tree friend_type, bool complain)
int class_template_depth = template_class_depth (type); int class_template_depth = template_class_depth (type);
int friend_depth = processing_template_decl - class_template_depth; int friend_depth = processing_template_decl - class_template_depth;
if (! MAYBE_CLASS_TYPE_P (friend_type)) 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 /* N1791: If the type specifier in a friend declaration designates a
(possibly cv-qualified) class type, that class is declared as a (possibly cv-qualified) class type, that class is declared as a
...@@ -349,6 +350,8 @@ make_friend_class (tree type, tree friend_type, bool complain) ...@@ -349,6 +350,8 @@ make_friend_class (tree type, tree friend_type, bool complain)
error ("template parameter type %qT declared %<friend%>", friend_type); error ("template parameter type %qT declared %<friend%>", friend_type);
return; return;
} }
else if (TREE_CODE (friend_type) == TEMPLATE_TEMPLATE_PARM)
friend_type = TYPE_NAME (friend_type);
else if (!CLASSTYPE_TEMPLATE_INFO (friend_type)) else if (!CLASSTYPE_TEMPLATE_INFO (friend_type))
{ {
/* template <class T> friend class A; where A is not a template */ /* template <class T> friend class A; where A is not a template */
......
...@@ -21240,7 +21240,9 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p) ...@@ -21240,7 +21240,9 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
decl = finish_member_template_decl (decl); decl = finish_member_template_decl (decl);
} }
else if (friend_p && decl && TREE_CODE (decl) == TYPE_DECL) else if (friend_p && decl
&& (TREE_CODE (decl) == TYPE_DECL
|| DECL_TYPE_TEMPLATE_P (decl)))
make_friend_class (current_class_type, TREE_TYPE (decl), make_friend_class (current_class_type, TREE_TYPE (decl),
/*complain=*/true); /*complain=*/true);
} }
......
...@@ -8152,6 +8152,12 @@ tsubst_friend_class (tree friend_tmpl, tree args) ...@@ -8152,6 +8152,12 @@ tsubst_friend_class (tree friend_tmpl, tree args)
tree tmpl; tree tmpl;
tree context; tree context;
if (DECL_TEMPLATE_TEMPLATE_PARM_P (friend_tmpl))
{
tree t = tsubst (TREE_TYPE (friend_tmpl), args, tf_none, NULL_TREE);
return TREE_TYPE (t);
}
context = CP_DECL_CONTEXT (friend_tmpl); context = CP_DECL_CONTEXT (friend_tmpl);
if (context != global_namespace) if (context != global_namespace)
...@@ -8736,7 +8742,8 @@ instantiate_class_template_1 (tree type) ...@@ -8736,7 +8742,8 @@ instantiate_class_template_1 (tree type)
} }
else else
{ {
if (TYPE_P (t) || DECL_CLASS_TEMPLATE_P (t)) if (TYPE_P (t) || DECL_CLASS_TEMPLATE_P (t)
|| DECL_TEMPLATE_TEMPLATE_PARM_P (t))
{ {
/* Build new CLASSTYPE_FRIEND_CLASSES. */ /* Build new CLASSTYPE_FRIEND_CLASSES. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment