This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[C++ PATCH] Implement member class of class template as templatefriend


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 ()


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]