This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[C++ PATCH] Implement member class of class template as templatefriend
- From: Kriang Lerdsuwanakij <lerdsuwa at users dot sourceforge dot net>
- To: <gcc-patches at gcc dot gnu dot org>
- Date: Mon, 6 Sep 2004 23:06:08 +0700 (ICT)
- Subject: [C++ PATCH] Implement member class of class template as templatefriend
- Reply-to: <lerdsuwa at users dot sourceforge dot net>
Hi
This patch completes the implementation of template friend described in
14.5.3/6. Now nested class of class template is also handled:
template <class T> struct A {
struct B {};
};
class C {
template <class T> friend class A<T>::B;
};
These are the major changes:
- 'make_friend_class' is heavily modified to handle such template friend.
It is always passed to make_friend_class as TYPENAME_TYPE from the
parser. Depending on situations, TYPENAME_TYPE may be created to
support codes like:
template <class T> class C {
template <T *t> friend class A<t>::B; // A<t> depending on T
};
or UNBOUND_CLASS_TEMPLATE for codes like:
template <class T> class C {
template <T *t> template <class U> friend class A<t>::B;
// B is a member class
// template
};
Nevertheless, they are ended up a TEMPLATE_DECL after the enclosing
class C<T> is fully substituted. This is handled by the changes in
'instantiate_class_template'.
- The support of friend class is added to 'is_specialization_of_friend'.
Previously only friend function is supported.
- A parameter is added to 'make_unbound_class_template'. This is used
to catch type mismatch for the UNBOUND_CLASS_TEMPLATE case above.
For example, the actual A<t>::B may be declared as:
template <int *t> struct A<t> {
template <class U, class V> struct B {}; // 2 template parameters
};
Tested on i686-pc-linux-gnu. OK for mainline?
--Kriang
2004-09-06 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
* decl.c (make_unbound_class_template): Add PARM_LIST parameter.
* cp-tree.h (make_unbound_class_template): Adjust prototype.
* parser.c (cp_parser_lookup_name): Adjust call to
make_unbound_class_template.
(cp_parser_single_declaration): Handle member class of class
template as template friend parsing correctly.
* friend.c (is_friend): Call is_specialization_of_friend for
template friend class.
(make_friend_class): Handle member class of class template as
template friend.
* pt.c (is_specialization_of_friend): Likewise.
(instantiate_class_template): Likewise.
(tsubst): Adjust call to make_unbound_class_template.
2004-09-06 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
* g++.dg/template/memfriend9.C: New test.
* g++.dg/template/memfriend10.C: Likewise.
* g++.dg/template/memfriend11.C: Likewise.
* g++.dg/template/memfriend12.C: Likewise.
* g++.dg/template/memfriend13.C: Likewise.
* g++.dg/template/memfriend14.C: Likewise.
* g++.dg/template/memfriend15.C: Likewise.
* g++.dg/template/memfriend16.C: Likewise.
* g++.dg/template/memfriend17.C: Likewise.
* g++.old-deja/g++.pt/friend44.C: Remove bogus error.
diff -cprN gcc-main-save/gcc/cp/cp-tree.h gcc-main-new/gcc/cp/cp-tree.h
*** gcc-main-save/gcc/cp/cp-tree.h Sat Aug 28 16:06:17 2004
--- gcc-main-new/gcc/cp/cp-tree.h Sun Aug 29 22:15:51 2004
*************** extern tree define_label (location_t,
*** 3736,3742 ****
extern void check_goto (tree);
extern void define_case_label (void);
extern tree make_typename_type (tree, tree, tsubst_flags_t);
! extern tree make_unbound_class_template (tree, tree, tsubst_flags_t);
extern tree check_for_out_of_scope_variable (tree);
extern tree build_library_fn (tree, tree);
extern tree build_library_fn_ptr (const char *, tree);
--- 3736,3742 ----
extern void check_goto (tree);
extern void define_case_label (void);
extern tree make_typename_type (tree, tree, tsubst_flags_t);
! extern tree make_unbound_class_template (tree, tree, tree, tsubst_flags_t);
extern tree check_for_out_of_scope_variable (tree);
extern tree build_library_fn (tree, tree);
extern tree build_library_fn_ptr (const char *, tree);
diff -cprN gcc-main-save/gcc/cp/decl.c gcc-main-new/gcc/cp/decl.c
*** gcc-main-save/gcc/cp/decl.c Sat Aug 28 16:06:18 2004
--- gcc-main-new/gcc/cp/decl.c Sun Aug 29 23:02:57 2004
*************** make_typename_type (tree context, tree n
*** 2686,2699 ****
return build_typename_type (context, name, fullname);
}
! /* Resolve `CONTEXT::template NAME'. Returns an appropriate type,
! unless an error occurs, in which case error_mark_node is returned.
! If we locate a TYPE_DECL, we return that, rather than the _TYPE it
! corresponds to. If COMPLAIN zero, don't complain about any errors
! that occur. */
tree
! make_unbound_class_template (tree context, tree name, tsubst_flags_t complain)
{
tree t;
tree d;
--- 2686,2703 ----
return build_typename_type (context, name, fullname);
}
! /* Resolve `CONTEXT::template NAME'. Returns a TEMPLATE_DECL if the name
! can be resolved or an UNBOUND_CLASS_TEMPLATE, unless an error occurs,
! in which case error_mark_node is returned.
!
! If PARM_LIST is non-NULL, also make sure that the template parameter
! list of TEMPLATE_DECL matches.
!
! If COMPLAIN zero, don't complain about any errors that occur. */
tree
! make_unbound_class_template (tree context, tree name, tree parm_list,
! tsubst_flags_t complain)
{
tree t;
tree d;
*************** make_unbound_class_template (tree contex
*** 2720,2725 ****
--- 2724,2737 ----
return error_mark_node;
}
+ if (parm_list
+ && !comp_template_parms (DECL_TEMPLATE_PARMS (tmpl), parm_list))
+ {
+ if (complain & tf_error)
+ error ("template parameter not match");
+ return error_mark_node;
+ }
+
if (complain & tf_error)
perform_or_defer_access_check (TYPE_BINFO (context), tmpl);
*************** make_unbound_class_template (tree contex
*** 2737,2742 ****
--- 2749,2755 ----
TYPE_STUB_DECL (TREE_TYPE (d)) = d;
DECL_CONTEXT (d) = FROB_CONTEXT (context);
DECL_ARTIFICIAL (d) = 1;
+ DECL_TEMPLATE_PARMS (d) = parm_list;
return t;
}
diff -cprN gcc-main-save/gcc/cp/friend.c gcc-main-new/gcc/cp/friend.c
*** gcc-main-save/gcc/cp/friend.c Sun Jul 11 21:47:16 2004
--- gcc-main-new/gcc/cp/friend.c Sun Aug 29 23:50:03 2004
*************** is_friend (tree type, tree supplicant)
*** 92,98 ****
tree t = TREE_VALUE (list);
if (TREE_CODE (t) == TEMPLATE_DECL ?
! is_specialization_of (TYPE_MAIN_DECL (supplicant), t) :
same_type_p (supplicant, t))
return 1;
}
--- 92,98 ----
tree t = TREE_VALUE (list);
if (TREE_CODE (t) == TEMPLATE_DECL ?
! is_specialization_of_friend (TYPE_MAIN_DECL (supplicant), t) :
same_type_p (supplicant, t))
return 1;
}
*************** void
*** 197,203 ****
make_friend_class (tree type, tree friend_type, bool complain)
{
tree classes;
! int is_template_friend;
if (! IS_AGGR_TYPE (friend_type))
{
--- 197,227 ----
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 (! IS_AGGR_TYPE (friend_type))
{
*************** make_friend_class (tree type, tree frien
*** 205,211 ****
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. */
--- 229,235 ----
return;
}
! if (friend_depth)
/* 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. */
*************** make_friend_class (tree type, tree frien
*** 221,228 ****
friend_type);
return;
}
-
- is_template_friend = 1;
}
else if (same_type_p (type, friend_type))
{
--- 245,250 ----
*************** make_friend_class (tree type, tree frien
*** 231,238 ****
type);
return;
}
- else
- is_template_friend = 0;
/* [temp.friend]
--- 253,258 ----
*************** make_friend_class (tree type, tree frien
*** 240,252 ****
class template, a specialization of a function template or
class template, or an ordinary (nontemplate) function or
class. */
! if (!is_template_friend)
;/* ok */
else if (TREE_CODE (friend_type) == TYPENAME_TYPE)
{
! /* template <class T> friend typename S<T>::X; */
! error ("typename type `%#T' declared `friend'", friend_type);
! return;
}
else if (TREE_CODE (friend_type) == TEMPLATE_TYPE_PARM)
{
--- 260,331 ----
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 `%T' declared `friend'",
! friend_type);
! return;
! }
! else
! {
! /* We will figure this out later. */
! bool template_member_p = false;
!
! tree ctype = TYPE_CONTEXT (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,
! TYPE_IDENTIFIER (friend_type),
! current_template_parms,
! tf_error);
! else
! friend_type
! = make_typename_type (ctype, TYPE_IDENTIFIER (friend_type),
! tf_error);
! }
! else
! {
! decl = lookup_member (ctype, TYPE_IDENTIFIER (friend_type),
! 0, true);
! if (!decl)
! {
! error ("cannot find `%T'", friend_type);
! return;
! }
! if (template_member_p && !DECL_CLASS_TEMPLATE_P (decl))
! {
! error ("cannot find template `%T'", friend_type);
! return;
! }
! if (!template_member_p && (TREE_CODE (decl) != TYPE_DECL
! || !CLASS_TYPE_P (TREE_TYPE (decl))))
! {
! error ("cannot find type `%T'", friend_type);
! return;
! }
!
! friend_type = CLASSTYPE_TI_TEMPLATE (TREE_TYPE (decl));
! }
! }
}
else if (TREE_CODE (friend_type) == TEMPLATE_TYPE_PARM)
{
*************** make_friend_class (tree type, tree frien
*** 260,269 ****
error ("`%#T' is not a template", friend_type);
return;
}
!
! if (is_template_friend)
friend_type = CLASSTYPE_TI_TEMPLATE (friend_type);
/* See if it is already a friend. */
for (classes = CLASSTYPE_FRIEND_CLASSES (type);
classes;
--- 339,351 ----
error ("`%#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;
*************** make_friend_class (tree type, tree frien
*** 299,305 ****
CLASSTYPE_FRIEND_CLASSES (type)
= tree_cons (NULL_TREE, friend_type, CLASSTYPE_FRIEND_CLASSES (type));
! if (is_template_friend)
friend_type = TREE_TYPE (friend_type);
if (!uses_template_parms (type))
CLASSTYPE_BEFRIENDING_CLASSES (friend_type)
--- 381,387 ----
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)
diff -cprN gcc-main-save/gcc/cp/parser.c gcc-main-new/gcc/cp/parser.c
*** gcc-main-save/gcc/cp/parser.c Sat Aug 28 16:06:19 2004
--- gcc-main-new/gcc/cp/parser.c Sun Aug 29 22:15:20 2004
*************** cp_parser_lookup_name (cp_parser *parser
*** 14235,14241 ****
/*complain=*/1));
else if (is_template)
decl = make_unbound_class_template (parser->scope,
! name,
/*complain=*/1);
else
decl = build_nt (SCOPE_REF, parser->scope, name);
--- 14228,14234 ----
/*complain=*/1));
else if (is_template)
decl = make_unbound_class_template (parser->scope,
! name, NULL_TREE,
/*complain=*/1);
else
decl = build_nt (SCOPE_REF, parser->scope, name);
*************** cp_parser_single_declaration (cp_parser*
*** 14997,15002 ****
--- 14990,15010 ----
if (cp_parser_declares_only_class_p (parser))
{
decl = shadow_tag (&decl_specifiers);
+
+ /* In this case:
+
+ struct C {
+ friend template <typename T> struct A<T>::B;
+ };
+
+ A<T>::B will be represented by a TYPENAME_TYPE, and
+ therefore not recognized by shadow_tag. */
+ if (friend_p && *friend_p
+ && !decl
+ && decl_specifiers.type
+ && TYPE_P (decl_specifiers.type))
+ decl = decl_specifiers.type;
+
if (decl && decl != error_mark_node)
decl = TYPE_NAME (decl);
else
diff -cprN gcc-main-save/gcc/cp/pt.c gcc-main-new/gcc/cp/pt.c
*** gcc-main-save/gcc/cp/pt.c Sat Aug 28 16:06:19 2004
--- gcc-main-new/gcc/cp/pt.c Sun Sep 5 19:34:52 2004
*************** is_specialization_of_friend (tree decl,
*** 906,912 ****
bool need_template = true;
int template_depth;
! gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
/* For [temp.friend/6] when FRIEND is an ordinary member function
of a template class, we want to check if DECL is a specialization
--- 906,913 ----
bool need_template = true;
int template_depth;
! gcc_assert (TREE_CODE (decl) == FUNCTION_DECL
! || TREE_CODE (decl) == TYPE_DECL);
/* For [temp.friend/6] when FRIEND is an ordinary member function
of a template class, we want to check if DECL is a specialization
*************** is_specialization_of_friend (tree decl,
*** 915,930 ****
&& DECL_TEMPLATE_INFO (friend)
&& !DECL_USE_TEMPLATE (friend))
{
friend = DECL_TI_TEMPLATE (friend);
need_template = false;
}
/* There is nothing to do if this is not a template friend. */
if (TREE_CODE (friend) != TEMPLATE_DECL)
! return 0;
if (is_specialization_of (decl, friend))
! return 1;
/* [temp.friend/6]
A member of a class template may be declared to be a friend of a
--- 916,935 ----
&& DECL_TEMPLATE_INFO (friend)
&& !DECL_USE_TEMPLATE (friend))
{
+ /* We want a TEMPLATE_DECL for `is_specialization_of'. */
friend = DECL_TI_TEMPLATE (friend);
need_template = false;
}
+ else if (TREE_CODE (friend) == TEMPLATE_DECL
+ && !PRIMARY_TEMPLATE_P (friend))
+ need_template = false;
/* There is nothing to do if this is not a template friend. */
if (TREE_CODE (friend) != TEMPLATE_DECL)
! return false;
if (is_specialization_of (decl, friend))
! return true;
/* [temp.friend/6]
A member of a class template may be declared to be a friend of a
*************** is_specialization_of_friend (tree decl,
*** 953,969 ****
CLASSTYPE_TI_TEMPLATE (DECL_CONTEXT (friend))))
{
/* Next, we check the members themselves. In order to handle
! a few tricky cases like
template <class T> friend void A<T>::g(T t);
template <class T> template <T t> friend void A<T>::h();
! we need to figure out what ARGS is (corresponding to `T' in above
! examples) from DECL for later processing. */
tree context = DECL_CONTEXT (decl);
tree args = NULL_TREE;
int current_depth = 0;
while (current_depth < template_depth)
{
if (CLASSTYPE_TEMPLATE_INFO (context))
--- 958,982 ----
CLASSTYPE_TI_TEMPLATE (DECL_CONTEXT (friend))))
{
/* Next, we check the members themselves. In order to handle
! a few tricky cases, such as when FRIEND's are
template <class T> friend void A<T>::g(T t);
template <class T> template <T t> friend void A<T>::h();
! and DECL's are
!
! void A<int>::g(int);
! template <int> void A<int>::h();
!
! we need to figure out ARGS, the template arguments from
! the context of DECL. This is required for template substitution
! of `T' in the function parameter of `g' and template parameter
! of `h' in the above examples. Here ARGS corresponds to `int'. */
tree context = DECL_CONTEXT (decl);
tree args = NULL_TREE;
int current_depth = 0;
+
while (current_depth < template_depth)
{
if (CLASSTYPE_TEMPLATE_INFO (context))
*************** is_specialization_of_friend (tree decl,
*** 990,996 ****
is_template = DECL_TEMPLATE_INFO (decl)
&& PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (decl));
if (need_template ^ is_template)
! return 0;
else if (is_template)
{
/* If both are templates, check template parameter list. */
--- 1003,1009 ----
is_template = DECL_TEMPLATE_INFO (decl)
&& PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (decl));
if (need_template ^ is_template)
! return false;
else if (is_template)
{
/* If both are templates, check template parameter list. */
*************** is_specialization_of_friend (tree decl,
*** 1000,1006 ****
if (!comp_template_parms
(DECL_TEMPLATE_PARMS (DECL_TI_TEMPLATE (decl)),
friend_parms))
! return 0;
decl_type = TREE_TYPE (DECL_TI_TEMPLATE (decl));
}
--- 1013,1019 ----
if (!comp_template_parms
(DECL_TEMPLATE_PARMS (DECL_TI_TEMPLATE (decl)),
friend_parms))
! return false;
decl_type = TREE_TYPE (DECL_TI_TEMPLATE (decl));
}
*************** is_specialization_of_friend (tree decl,
*** 1010,1020 ****
friend_type = tsubst_function_type (TREE_TYPE (friend), args,
tf_none, NULL_TREE);
if (friend_type == error_mark_node)
! return 0;
/* Check if return types match. */
if (!same_type_p (TREE_TYPE (decl_type), TREE_TYPE (friend_type)))
! return 0;
/* Check if function parameter types match, ignoring the
`this' parameter. */
--- 1023,1033 ----
friend_type = tsubst_function_type (TREE_TYPE (friend), args,
tf_none, NULL_TREE);
if (friend_type == error_mark_node)
! return false;
/* Check if return types match. */
if (!same_type_p (TREE_TYPE (decl_type), TREE_TYPE (friend_type)))
! return false;
/* Check if function parameter types match, ignoring the
`this' parameter. */
*************** is_specialization_of_friend (tree decl,
*** 1024,1034 ****
friend_args_type = TREE_CHAIN (friend_args_type);
if (DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
decl_args_type = TREE_CHAIN (decl_args_type);
! if (compparms (decl_args_type, friend_args_type))
! return 1;
}
}
! return 0;
}
/* Register the specialization SPEC as a specialization of TMPL with
--- 1037,1082 ----
friend_args_type = TREE_CHAIN (friend_args_type);
if (DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
decl_args_type = TREE_CHAIN (decl_args_type);
!
! return compparms (decl_args_type, friend_args_type);
! }
! else
! {
! /* DECL is a TYPE_DECL */
! bool is_template;
! tree decl_type = TREE_TYPE (decl);
!
! /* Make sure that both DECL and FRIEND are templates or
! non-templates. */
! is_template
! = CLASSTYPE_TEMPLATE_INFO (decl_type)
! && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (decl_type));
!
! if (need_template ^ is_template)
! return false;
! else if (is_template)
! {
! tree friend_parms;
! /* If both are templates, check the name of the two
! TEMPLATE_DECL's first because is_friend didn't. */
! if (DECL_NAME (CLASSTYPE_TI_TEMPLATE (decl_type))
! != DECL_NAME (friend))
! return false;
!
! /* Now check template parameter list. */
! friend_parms
! = tsubst_template_parms (DECL_TEMPLATE_PARMS (friend),
! args, tf_none);
! return comp_template_parms
! (DECL_TEMPLATE_PARMS (CLASSTYPE_TI_TEMPLATE (decl_type)),
! friend_parms);
! }
! else
! return (DECL_NAME (decl)
! == DECL_NAME (friend));
}
}
! return false;
}
/* Register the specialization SPEC as a specialization of TMPL with
*************** instantiate_class_template (tree type)
*** 5662,5676 ****
/* Build new CLASSTYPE_FRIEND_CLASSES. */
tree friend_type = t;
! tree new_friend_type;
if (TREE_CODE (friend_type) == TEMPLATE_DECL)
! new_friend_type = tsubst_friend_class (friend_type, args);
else if (uses_template_parms (friend_type))
! new_friend_type = tsubst (friend_type, args,
! tf_error | tf_warning, NULL_TREE);
else if (CLASSTYPE_USE_TEMPLATE (friend_type))
! new_friend_type = friend_type;
else
{
tree ns = decl_namespace_context (TYPE_MAIN_DECL (friend_type));
--- 5710,5746 ----
/* Build new CLASSTYPE_FRIEND_CLASSES. */
tree friend_type = t;
! bool adjust_processing_template_decl = false;
if (TREE_CODE (friend_type) == TEMPLATE_DECL)
! {
! friend_type = tsubst_friend_class (friend_type, args);
! adjust_processing_template_decl = true;
! }
! else if (TREE_CODE (friend_type) == UNBOUND_CLASS_TEMPLATE)
! {
! friend_type = tsubst (friend_type, args,
! tf_error | tf_warning, NULL_TREE);
! if (TREE_CODE (friend_type) == TEMPLATE_DECL)
! friend_type = TREE_TYPE (friend_type);
! adjust_processing_template_decl = true;
! }
! else if (TREE_CODE (friend_type) == TYPENAME_TYPE)
! {
! friend_type = tsubst (friend_type, args,
! tf_error | tf_warning, NULL_TREE);
! /* Bump processing_template_decl for correct
! dependent_type_p calculation. */
! ++processing_template_decl;
! if (dependent_type_p (friend_type))
! adjust_processing_template_decl = true;
! --processing_template_decl;
! }
else if (uses_template_parms (friend_type))
! friend_type = tsubst (friend_type, args,
! tf_error | tf_warning, NULL_TREE);
else if (CLASSTYPE_USE_TEMPLATE (friend_type))
! friend_type = friend_type;
else
{
tree ns = decl_namespace_context (TYPE_MAIN_DECL (friend_type));
*************** instantiate_class_template (tree type)
*** 5678,5689 ****
/* The call to xref_tag_from_type does injection for friend
classes. */
push_nested_namespace (ns);
! new_friend_type =
xref_tag_from_type (friend_type, NULL_TREE, 1);
pop_nested_namespace (ns);
}
! if (TREE_CODE (friend_type) == TEMPLATE_DECL)
/* Trick make_friend_class into realizing that the friend
we're adding is a template, not an ordinary class. It's
important that we use make_friend_class since it will
--- 5748,5759 ----
/* The call to xref_tag_from_type does injection for friend
classes. */
push_nested_namespace (ns);
! friend_type =
xref_tag_from_type (friend_type, NULL_TREE, 1);
pop_nested_namespace (ns);
}
! if (adjust_processing_template_decl)
/* Trick make_friend_class into realizing that the friend
we're adding is a template, not an ordinary class. It's
important that we use make_friend_class since it will
*************** instantiate_class_template (tree type)
*** 5691,5701 ****
information. */
++processing_template_decl;
! if (new_friend_type != error_mark_node)
! make_friend_class (type, new_friend_type,
! /*complain=*/false);
! if (TREE_CODE (friend_type) == TEMPLATE_DECL)
--processing_template_decl;
}
else
--- 5761,5770 ----
information. */
++processing_template_decl;
! if (friend_type != error_mark_node)
! make_friend_class (type, friend_type, /*complain=*/false);
! if (adjust_processing_template_decl)
--processing_template_decl;
}
else
*************** tsubst (tree t, tree args, tsubst_flags_
*** 7241,7251 ****
tree ctx = tsubst_aggr_type (TYPE_CONTEXT (t), args, complain,
in_decl, /*entering_scope=*/1);
tree name = TYPE_IDENTIFIER (t);
if (ctx == error_mark_node || name == error_mark_node)
return error_mark_node;
! return make_unbound_class_template (ctx, name, complain);
}
case INDIRECT_REF:
--- 7310,7323 ----
tree ctx = tsubst_aggr_type (TYPE_CONTEXT (t), args, complain,
in_decl, /*entering_scope=*/1);
tree name = TYPE_IDENTIFIER (t);
+ tree parm_list = DECL_TEMPLATE_PARMS (TYPE_NAME (t));
if (ctx == error_mark_node || name == error_mark_node)
return error_mark_node;
! if (parm_list)
! parm_list = tsubst_template_parms (parm_list, args, complain);
! return make_unbound_class_template (ctx, name, parm_list, complain);
}
case INDIRECT_REF:
diff -cprN gcc-main-save/gcc/testsuite/g++.dg/template/memfriend10.C gcc-main-new/gcc/testsuite/g++.dg/template/memfriend10.C
*** gcc-main-save/gcc/testsuite/g++.dg/template/memfriend10.C Thu Jan 1 07:00:00 1970
--- gcc-main-new/gcc/testsuite/g++.dg/template/memfriend10.C Sat Sep 4 21:39:28 2004
***************
*** 0 ****
--- 1,71 ----
+ // { dg-do compile }
+
+ // Copyright (C) 2004 Free Software Foundation
+ // Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+
+ // Nested class template of class template as friend
+
+ template <class T> struct A
+ {
+ template <class U> struct B
+ {
+ void f();
+ };
+ };
+
+ class C {
+ int i;
+ template <class T> template <class U> friend struct A<T>::B;
+ };
+
+ template <class T> struct A<T*>
+ {
+ template <class U> struct B
+ {
+ void f();
+ };
+ };
+
+ template <> struct A<char>
+ {
+ template <class U> struct B
+ {
+ void f();
+ };
+ };
+
+ template <class T> template <class U> void A<T>::B<U>::f()
+ {
+ C c;
+ c.i = 0;
+ }
+
+ template <class T> template <class U> void A<T*>::B<U>::f()
+ {
+ C c;
+ c.i = 0;
+ }
+
+ template <class U> void A<char>::B<U>::f()
+ {
+ C c;
+ c.i = 0;
+ }
+
+ template <> void A<char>::B<int>::f()
+ {
+ C c;
+ c.i = 0;
+ }
+
+ int main()
+ {
+ A<int>::B<int> b1;
+ b1.f();
+ A<int *>::B<int> b2;
+ b2.f();
+ A<char>::B<char> b3;
+ b3.f();
+ A<char>::B<int> b4;
+ b4.f();
+ }
diff -cprN gcc-main-save/gcc/testsuite/g++.dg/template/memfriend11.C gcc-main-new/gcc/testsuite/g++.dg/template/memfriend11.C
*** gcc-main-save/gcc/testsuite/g++.dg/template/memfriend11.C Thu Jan 1 07:00:00 1970
--- gcc-main-new/gcc/testsuite/g++.dg/template/memfriend11.C Sat Sep 4 21:40:57 2004
***************
*** 0 ****
--- 1,73 ----
+ // { dg-do compile }
+
+ // Copyright (C) 2004 Free Software Foundation
+ // Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+
+ // Nest class template of class template as friend
+
+ template<class T> struct A
+ {
+ template <T t> struct B
+ {
+ void f();
+ };
+ };
+
+ class C {
+ int i;
+ template<class T> template <T t> friend struct A<T>::B;
+ };
+
+ template<class T> struct A<T*>
+ {
+ template <T* t> struct B
+ {
+ void f();
+ };
+ };
+
+ template<> struct A<char>
+ {
+ template <char t> struct B
+ {
+ void f();
+ };
+ };
+
+ template<class T> template <T t> void A<T>::B<t>::f()
+ {
+ C c;
+ c.i = 0;
+ }
+
+ template<class T> template <T* t> void A<T*>::B<t>::f()
+ {
+ C c;
+ c.i = 0;
+ }
+
+ template <char t> void A<char>::B<t>::f()
+ {
+ C c;
+ c.i = 0;
+ }
+
+ template <> void A<char>::B<'b'>::f()
+ {
+ C c;
+ c.i = 0;
+ }
+
+ int d2 = 0;
+
+ int main()
+ {
+ A<int>::B<0> b1;
+ b1.f();
+ A<int *>::B<&d2> b2;
+ b2.f();
+ A<char>::B<'a'> b3;
+ b3.f();
+ A<char>::B<'b'> b4;
+ b4.f();
+ }
diff -cprN gcc-main-save/gcc/testsuite/g++.dg/template/memfriend12.C gcc-main-new/gcc/testsuite/g++.dg/template/memfriend12.C
*** gcc-main-save/gcc/testsuite/g++.dg/template/memfriend12.C Thu Jan 1 07:00:00 1970
--- gcc-main-new/gcc/testsuite/g++.dg/template/memfriend12.C Sat Sep 4 21:40:59 2004
***************
*** 0 ****
--- 1,63 ----
+ // { dg-do compile }
+
+ // Copyright (C) 2004 Free Software Foundation
+ // Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+
+ // Nested class of class template as friend
+
+ template<class T> struct A
+ {
+ struct B
+ {
+ void f();
+ };
+ };
+
+ template <class U> class C {
+ int i;
+ template<class T> friend struct A<T>::B;
+ };
+
+ template<class T> struct A<T*>
+ {
+ struct B
+ {
+ void f();
+ };
+ };
+
+ template<> struct A<char>
+ {
+ struct B
+ {
+ void f();
+ };
+ };
+
+ template<class T> void A<T>::B::f()
+ {
+ C<int> c;
+ c.i = 0;
+ }
+
+ template<class T> void A<T*>::B::f()
+ {
+ C<int> c;
+ c.i = 0;
+ }
+
+ void A<char>::B::f()
+ {
+ C<int> c;
+ c.i = 0;
+ }
+
+ int main()
+ {
+ A<int>::B b1;
+ b1.f();
+ A<int *>::B b2;
+ b2.f();
+ A<char>::B b3;
+ b3.f();
+ }
diff -cprN gcc-main-save/gcc/testsuite/g++.dg/template/memfriend13.C gcc-main-new/gcc/testsuite/g++.dg/template/memfriend13.C
*** gcc-main-save/gcc/testsuite/g++.dg/template/memfriend13.C Thu Jan 1 07:00:00 1970
--- gcc-main-new/gcc/testsuite/g++.dg/template/memfriend13.C Sat Sep 4 21:41:00 2004
***************
*** 0 ****
--- 1,71 ----
+ // { dg-do compile }
+
+ // Copyright (C) 2004 Free Software Foundation
+ // Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+
+ // Nested class template of class template as friend
+
+ template <class T> struct A
+ {
+ template <class U> struct B
+ {
+ void f();
+ };
+ };
+
+ template <class V> class C {
+ int i;
+ template <class T> template <class U> friend struct A<T>::B;
+ };
+
+ template <class T> struct A<T*>
+ {
+ template <class U> struct B
+ {
+ void f();
+ };
+ };
+
+ template <> struct A<char>
+ {
+ template <class U> struct B
+ {
+ void f();
+ };
+ };
+
+ template <class T> template <class U> void A<T>::B<U>::f()
+ {
+ C<int> c;
+ c.i = 0;
+ }
+
+ template <class T> template <class U> void A<T*>::B<U>::f()
+ {
+ C<int> c;
+ c.i = 0;
+ }
+
+ template <class U> void A<char>::B<U>::f()
+ {
+ C<int> c;
+ c.i = 0;
+ }
+
+ template <> void A<char>::B<int>::f()
+ {
+ C<int> c;
+ c.i = 0;
+ }
+
+ int main()
+ {
+ A<int>::B<int> b1;
+ b1.f();
+ A<int *>::B<int> b2;
+ b2.f();
+ A<char>::B<char> b3;
+ b3.f();
+ A<char>::B<int> b4;
+ b4.f();
+ }
diff -cprN gcc-main-save/gcc/testsuite/g++.dg/template/memfriend14.C gcc-main-new/gcc/testsuite/g++.dg/template/memfriend14.C
*** gcc-main-save/gcc/testsuite/g++.dg/template/memfriend14.C Thu Jan 1 07:00:00 1970
--- gcc-main-new/gcc/testsuite/g++.dg/template/memfriend14.C Sat Sep 4 21:41:02 2004
***************
*** 0 ****
--- 1,73 ----
+ // { dg-do compile }
+
+ // Copyright (C) 2004 Free Software Foundation
+ // Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+
+ // Nest class template of class template as friend
+
+ template<class T> struct A
+ {
+ template <T t> struct B
+ {
+ void f();
+ };
+ };
+
+ template <class U> class C {
+ int i;
+ template<class T> template <T t> friend struct A<T>::B;
+ };
+
+ template<class T> struct A<T*>
+ {
+ template <T* t> struct B
+ {
+ void f();
+ };
+ };
+
+ template<> struct A<char>
+ {
+ template <char t> struct B
+ {
+ void f();
+ };
+ };
+
+ template<class T> template <T t> void A<T>::B<t>::f()
+ {
+ C<int> c;
+ c.i = 0;
+ }
+
+ template<class T> template <T* t> void A<T*>::B<t>::f()
+ {
+ C<int> c;
+ c.i = 0;
+ }
+
+ template <char t> void A<char>::B<t>::f()
+ {
+ C<int> c;
+ c.i = 0;
+ }
+
+ template <> void A<char>::B<'b'>::f()
+ {
+ C<int> c;
+ c.i = 0;
+ }
+
+ int d2 = 0;
+
+ int main()
+ {
+ A<int>::B<0> b1;
+ b1.f();
+ A<int *>::B<&d2> b2;
+ b2.f();
+ A<char>::B<'a'> b3;
+ b3.f();
+ A<char>::B<'b'> b4;
+ b4.f();
+ }
diff -cprN gcc-main-save/gcc/testsuite/g++.dg/template/memfriend15.C gcc-main-new/gcc/testsuite/g++.dg/template/memfriend15.C
*** gcc-main-save/gcc/testsuite/g++.dg/template/memfriend15.C Thu Jan 1 07:00:00 1970
--- gcc-main-new/gcc/testsuite/g++.dg/template/memfriend15.C Sat Sep 4 22:34:12 2004
***************
*** 0 ****
--- 1,34 ----
+ // { dg-do compile }
+
+ // Copyright (C) 2004 Free Software Foundation
+ // Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+
+ // Nested class of class template as friend
+
+ template<class T> struct A
+ {
+ struct B1
+ {
+ };
+ struct B2
+ {
+ void f();
+ };
+ };
+
+ class C {
+ int i; // { dg-error "private" }
+ template<class T> friend struct A<T>::B1;
+ };
+
+ template<class T> void A<T>::B2::f()
+ {
+ C c;
+ c.i = 0; // { dg-error "context" }
+ }
+
+ int main()
+ {
+ A<int>::B2 b1;
+ b1.f(); // { dg-error "instantiated" }
+ }
diff -cprN gcc-main-save/gcc/testsuite/g++.dg/template/memfriend16.C gcc-main-new/gcc/testsuite/g++.dg/template/memfriend16.C
*** gcc-main-save/gcc/testsuite/g++.dg/template/memfriend16.C Thu Jan 1 07:00:00 1970
--- gcc-main-new/gcc/testsuite/g++.dg/template/memfriend16.C Sat Sep 4 22:34:14 2004
***************
*** 0 ****
--- 1,34 ----
+ // { dg-do compile }
+
+ // Copyright (C) 2004 Free Software Foundation
+ // Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+
+ // Nested class of class template as friend
+
+ template<class T> struct A
+ {
+ template <class U> struct B1
+ {
+ };
+ template <class U> struct B2
+ {
+ void f();
+ };
+ };
+
+ class C {
+ int i; // { dg-error "private" }
+ template<class T> template <class U> friend struct A<T>::B1;
+ };
+
+ template<class T> template <class U> void A<T>::B2<U>::f()
+ {
+ C c;
+ c.i = 0; // { dg-error "context" }
+ }
+
+ int main()
+ {
+ A<int>::B2<int> b1;
+ b1.f(); // { dg-error "instantiated" }
+ }
diff -cprN gcc-main-save/gcc/testsuite/g++.dg/template/memfriend17.C gcc-main-new/gcc/testsuite/g++.dg/template/memfriend17.C
*** gcc-main-save/gcc/testsuite/g++.dg/template/memfriend17.C Thu Jan 1 07:00:00 1970
--- gcc-main-new/gcc/testsuite/g++.dg/template/memfriend17.C Sat Sep 4 23:07:20 2004
***************
*** 0 ****
--- 1,46 ----
+ // { dg-do compile }
+
+ // Origin: Giovanni Bajo <giovannibajo@libero.it>
+
+ // PR c++/13495: Nested class as template friend.
+
+ template<typename T>
+ class A{
+ public:
+ class B
+ {
+ void func1(void);
+ void func2(void);
+ };
+ };
+
+ template<typename Q>
+ class F1
+ {
+ friend class A<Q>::B;
+ enum { foo = 0 }; // { dg-error "private" }
+ };
+
+ template<typename Q>
+ class F2
+ {
+ template<typename T>
+ friend class A<T>::B;
+ enum { foo = 0 };
+ };
+
+ template <typename T>
+ void A<T>::B::func1(void)
+ {
+ (void)F1<T>::foo;
+ (void)F2<T>::foo;
+ }
+
+ template <typename T>
+ void A<T>::B::func2(void)
+ {
+ (void)F1<T*>::foo; // { dg-error "context" }
+ (void)F2<T*>::foo;
+ }
+
+ template class A<int>; // { dg-error "instantiated" }
diff -cprN gcc-main-save/gcc/testsuite/g++.dg/template/memfriend9.C gcc-main-new/gcc/testsuite/g++.dg/template/memfriend9.C
*** gcc-main-save/gcc/testsuite/g++.dg/template/memfriend9.C Thu Jan 1 07:00:00 1970
--- gcc-main-new/gcc/testsuite/g++.dg/template/memfriend9.C Sat Sep 4 21:39:20 2004
***************
*** 0 ****
--- 1,63 ----
+ // { dg-do compile }
+
+ // Copyright (C) 2004 Free Software Foundation
+ // Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+
+ // Nested class of class template as friend
+
+ template<class T> struct A
+ {
+ struct B
+ {
+ void f();
+ };
+ };
+
+ class C {
+ int i;
+ template<class T> friend struct A<T>::B;
+ };
+
+ template<class T> struct A<T*>
+ {
+ struct B
+ {
+ void f();
+ };
+ };
+
+ template<> struct A<char>
+ {
+ struct B
+ {
+ void f();
+ };
+ };
+
+ template<class T> void A<T>::B::f()
+ {
+ C c;
+ c.i = 0;
+ }
+
+ template<class T> void A<T*>::B::f()
+ {
+ C c;
+ c.i = 0;
+ }
+
+ void A<char>::B::f()
+ {
+ C c;
+ c.i = 0;
+ }
+
+ int main()
+ {
+ A<int>::B b1;
+ b1.f();
+ A<int *>::B b2;
+ b2.f();
+ A<char>::B b3;
+ b3.f();
+ }
diff -cprN gcc-main-save/gcc/testsuite/g++.old-deja/g++.pt/friend44.C gcc-main-new/gcc/testsuite/g++.old-deja/g++.pt/friend44.C
*** gcc-main-save/gcc/testsuite/g++.old-deja/g++.pt/friend44.C Sat Nov 22 13:45:04 2003
--- gcc-main-new/gcc/testsuite/g++.old-deja/g++.pt/friend44.C Sun Aug 29 19:25:37 2004
***************
*** 1,4 ****
! // { dg-do run }
// Test that template friends referring to class template members are
// respected.
--- 1,4 ----
! // { dg-do compile }
// Test that template friends referring to class template members are
// respected.
*************** class B
*** 15,21 ****
{
template <class T> friend int A<T>::f (T);
template <class T> friend struct A<T>::AI;
! int a; // { dg-bogus "" "" { xfail *-*-* } }
public:
B(): a(0) { }
};
--- 15,21 ----
{
template <class T> friend int A<T>::f (T);
template <class T> friend struct A<T>::AI;
! int a;
public:
B(): a(0) { }
};
*************** template <class T> int A<T>::f (T)
*** 29,35 ****
template <class T> int A<T>::AI::f (T)
{
B b;
! return b.a; // { dg-bogus "" "" { xfail *-*-* } }
}
int main ()
--- 29,35 ----
template <class T> int A<T>::AI::f (T)
{
B b;
! return b.a;
}
int main ()