summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>2012-08-31 02:50:08 +0000
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>2012-08-31 02:50:08 +0000
commitabcd2504cabc450b2eb467a4918270ed4f97d70a (patch)
tree424314c23f47f26c9a20d19dc68f81690672bb2e
parentce61b1b3b9c052593eeb616e4c7caff2f8668dd2 (diff)
downloadgcc-abcd2504cabc450b2eb467a4918270ed4f97d70a.tar.gz
* 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@190828 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/cp/ChangeLog7
-rw-r--r--gcc/cp/decl.c12
-rw-r--r--gcc/cp/friend.c5
-rw-r--r--gcc/cp/parser.c4
-rw-r--r--gcc/cp/pt.c9
5 files changed, 31 insertions, 6 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index f334778cfbe..fc49329ed0d 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,12 @@
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
main_tmpl parameter.
(more_specialized_class): Add main_tmpl parameter.
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 19485fc712c..c909dea1775 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -11484,9 +11484,10 @@ check_elaborated_type_specifier (enum tag_types tag_code,
type, tag_name (tag_code));
return error_mark_node;
}
- /* Accept bound template template parameters. */
+ /* Accept template template parameters. */
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]
@@ -11574,7 +11575,9 @@ lookup_and_check_tag (enum tag_types tag_code, tree name,
else
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);
if (decl && TREE_CODE (decl) == TYPE_DECL)
@@ -11679,6 +11682,9 @@ xref_tag_1 (enum tag_types tag_code, tree name,
&& template_class_depth (current_class_type)
&& template_header_p)
{
+ if (TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM)
+ return t;
+
/* Since SCOPE is not TS_CURRENT, we are not looking at a
definition of this tag. Since, in addition, we are currently
processing a (member) template declaration of a template
diff --git a/gcc/cp/friend.c b/gcc/cp/friend.c
index d0cbaedc581..d4548ff7ad6 100644
--- a/gcc/cp/friend.c
+++ b/gcc/cp/friend.c
@@ -224,7 +224,8 @@ make_friend_class (tree type, tree friend_type, bool complain)
int class_template_depth = template_class_depth (type);
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
(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)
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 */
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 0f897c96f07..091a96728ad 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -21240,7 +21240,9 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
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),
/*complain=*/true);
}
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 792e9d131e7..6506a6719d8 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -8152,6 +8152,12 @@ tsubst_friend_class (tree friend_tmpl, tree args)
tree tmpl;
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);
if (context != global_namespace)
@@ -8736,7 +8742,8 @@ instantiate_class_template_1 (tree type)
}
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. */