public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [C++] My unreviewed patch
@ 2004-10-17 14:48 Kriang Lerdsuwanakij
  2004-10-18 17:51 ` Nathan Sidwell
  0 siblings, 1 reply; 13+ messages in thread
From: Kriang Lerdsuwanakij @ 2004-10-17 14:48 UTC (permalink / raw)
  To: gcc-patches

Hi

The following patch of mine is still not reviewed:

  http://gcc.gnu.org/ml/gcc-patches/2004-09/msg00557.html

It implements a missing friend feature (mentioned in section
14.5.3/6) I intended to have in GCC 4.0.

Thanks

--Kriang

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [C++] My unreviewed patch
  2004-10-17 14:48 [C++] My unreviewed patch Kriang Lerdsuwanakij
@ 2004-10-18 17:51 ` Nathan Sidwell
  2004-10-18 19:02   ` Gabriel Dos Reis
  0 siblings, 1 reply; 13+ messages in thread
From: Nathan Sidwell @ 2004-10-18 17:51 UTC (permalink / raw)
  To: lerdsuwa; +Cc: gcc-patches

Kriang Lerdsuwanakij wrote:
> Hi
> 
> The following patch of mine is still not reviewed:
> 
>   http://gcc.gnu.org/ml/gcc-patches/2004-09/msg00557.html
> 
> It implements a missing friend feature (mentioned in section
> 14.5.3/6) I intended to have in GCC 4.0.

Looks ok apart from some issues with the diagnostic text.  Can
you use the new %qD and related quoted printing formatters?



+       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;
+ 	}

Something with more context would be better
    cp_error "template parameters do not match template"
    cp_error_at "declared here", tmpl
It's a pity we can't actuall print out the mismatching template
parameters.

! 	      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;
! 		}

These would be better as something like
	"%qT is not a member of %qT", friend_type, ctype
that way the user gets a clue as to where the compiler was looking.

ok with those changes. If you want to run the diagnostics by me, feel
free to do so.

nathan

-- 
Nathan Sidwell    ::   http://www.codesourcery.com   ::     CodeSourcery LLC
nathan@codesourcery.com    ::     http://www.planetfall.pwp.blueyonder.co.uk


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [C++] My unreviewed patch
  2004-10-18 17:51 ` Nathan Sidwell
@ 2004-10-18 19:02   ` Gabriel Dos Reis
  2004-10-18 19:08     ` Nathan Sidwell
  0 siblings, 1 reply; 13+ messages in thread
From: Gabriel Dos Reis @ 2004-10-18 19:02 UTC (permalink / raw)
  To: Nathan Sidwell; +Cc: lerdsuwa, gcc-patches

Nathan Sidwell <nathan@codesourcery.com> writes:

| Kriang Lerdsuwanakij wrote:
| > Hi
| > The following patch of mine is still not reviewed:
| >   http://gcc.gnu.org/ml/gcc-patches/2004-09/msg00557.html
| > It implements a missing friend feature (mentioned in section
| > 14.5.3/6) I intended to have in GCC 4.0.
| 
| Looks ok apart from some issues with the diagnostic text.  Can
| you use the new %qD and related quoted printing formatters?
| 
| 
| 
| +       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;
| + 	}
| 
| Something with more context would be better
|     cp_error "template parameters do not match template"
|     cp_error_at "declared here", tmpl
| It's a pity we can't actuall print out the mismatching template
| parameters.

Why can't we?

-- Gaby

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [C++] My unreviewed patch
  2004-10-18 19:02   ` Gabriel Dos Reis
@ 2004-10-18 19:08     ` Nathan Sidwell
  2004-10-18 20:05       ` Gabriel Dos Reis
  0 siblings, 1 reply; 13+ messages in thread
From: Nathan Sidwell @ 2004-10-18 19:08 UTC (permalink / raw)
  To: Gabriel Dos Reis; +Cc: lerdsuwa, gcc-patches

Gabriel Dos Reis wrote:
> Nathan Sidwell <nathan@codesourcery.com> writes:

> | It's a pity we can't actuall print out the mismatching template
> | parameters.
> 
> Why can't we?
> 
> -- Gaby
It's  a tree_list, and we don't dump those (do we?).

nathan
-- 
Nathan Sidwell    ::   http://www.codesourcery.com   ::     CodeSourcery LLC
nathan@codesourcery.com    ::     http://www.planetfall.pwp.blueyonder.co.uk


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [C++] My unreviewed patch
  2004-10-18 19:08     ` Nathan Sidwell
@ 2004-10-18 20:05       ` Gabriel Dos Reis
  2004-10-18 20:18         ` Gabriel Dos Reis
  0 siblings, 1 reply; 13+ messages in thread
From: Gabriel Dos Reis @ 2004-10-18 20:05 UTC (permalink / raw)
  To: Nathan Sidwell; +Cc: lerdsuwa, gcc-patches

Nathan Sidwell <nathan@codesourcery.com> writes:

| Gabriel Dos Reis wrote:
| > Nathan Sidwell <nathan@codesourcery.com> writes:
| 
| > | It's a pity we can't actuall print out the mismatching template
| > | parameters.
| > Why can't we?
| > -- Gaby
| It's  a tree_list, and we don't dump those (do we?).

We don't currently dump template argument list, but we could -- it is
no different from the way we currently dump tree_list for function
arguments. 

-- Gaby

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [C++] My unreviewed patch
  2004-10-18 20:05       ` Gabriel Dos Reis
@ 2004-10-18 20:18         ` Gabriel Dos Reis
  0 siblings, 0 replies; 13+ messages in thread
From: Gabriel Dos Reis @ 2004-10-18 20:18 UTC (permalink / raw)
  To: Nathan Sidwell; +Cc: lerdsuwa, gcc-patches

Gabriel Dos Reis <gdr@cs.tamu.edu> writes:

| Nathan Sidwell <nathan@codesourcery.com> writes:
| 
| | Gabriel Dos Reis wrote:
| | > Nathan Sidwell <nathan@codesourcery.com> writes:
| | 
| | > | It's a pity we can't actuall print out the mismatching template
| | > | parameters.
| | > Why can't we?
| | > -- Gaby
| | It's  a tree_list, and we don't dump those (do we?).
| 
| We don't currently dump template argument list, but we could -- it is
| no different from the way we currently dump tree_list for function
| arguments. 

I mean we could leverage cp/error.c:dump_template_argument_list().
We just need a format specifier for that.

-- Gaby

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [C++] My unreviewed patch
  2004-10-20 18:15 ` Giovanni Bajo
  2004-10-21 12:10   ` Kriang Lerdsuwanakij
  2004-10-21 12:11   ` Kriang Lerdsuwanakij
@ 2004-10-21 12:36   ` Kriang Lerdsuwanakij
  2 siblings, 0 replies; 13+ messages in thread
From: Kriang Lerdsuwanakij @ 2004-10-21 12:36 UTC (permalink / raw)
  To: Giovanni Bajo; +Cc: gcc-patches

Giovanni Bajo wrote

 >>Tue Oct 19 22:58:28 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.
 >>
 >>
 >
 >Why? Didn't this use to be a run testcase?
 >
Thanks, I've fixed the typos in memfriend11.C and memfriend14.C testcases.
Regarding the friend44.C test above, access checking problems are caught
during compile time.  And because it failed with bogus error message and
never compiled nor ran, we don't lose anything changing it to compilation-only
test.

--Kriang




^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [C++] My unreviewed patch
  2004-10-20 18:15 ` Giovanni Bajo
  2004-10-21 12:10   ` Kriang Lerdsuwanakij
@ 2004-10-21 12:11   ` Kriang Lerdsuwanakij
  2004-10-21 12:36   ` Kriang Lerdsuwanakij
  2 siblings, 0 replies; 13+ messages in thread
From: Kriang Lerdsuwanakij @ 2004-10-21 12:11 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-patches

Giovanni Bajo wrote

 > Tue Oct 19 22:58:28 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.
 >
 >
 > Why? Didn't this use to be a run testcase?

Thanks, I've fixed the typos in memfriend11.C and memfriend14.C testcases.
Regarding the friend44.C test above, access checking problems are caught
during compile time.  And because it failed with bogus error message and
never compiled nor ran, we don't lose anything changing it to compilation-only test.

--Kriang



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [C++] My unreviewed patch
  2004-10-20 18:15 ` Giovanni Bajo
@ 2004-10-21 12:10   ` Kriang Lerdsuwanakij
  2004-10-21 12:11   ` Kriang Lerdsuwanakij
  2004-10-21 12:36   ` Kriang Lerdsuwanakij
  2 siblings, 0 replies; 13+ messages in thread
From: Kriang Lerdsuwanakij @ 2004-10-21 12:10 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-patches

Giovanni Bajo wrote

 > Tue Oct 19 22:58:28 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.
 >
 >
 > Why? Didn't this use to be a run testcase?

Thanks, I've fixed the typos in memfriend11.C and memfriend14.C testcases.
Regarding the friend44.C test above, access checking problems are caught
during compile time.  And because it failed with bogus error message and
never compiled nor ran, we don't lose anything changing it to compilation-only test.

--Kriang



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [C++] My unreviewed patch
  2004-10-20 12:09 Kriang Lerdsuwanakij
  2004-10-20 13:41 ` Nathan Sidwell
@ 2004-10-20 18:15 ` Giovanni Bajo
  2004-10-21 12:10   ` Kriang Lerdsuwanakij
                     ` (2 more replies)
  1 sibling, 3 replies; 13+ messages in thread
From: Giovanni Bajo @ 2004-10-20 18:15 UTC (permalink / raw)
  To: lerdsuwa; +Cc: gcc-patches

Kriang Lerdsuwanakij wrote:

> 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 Tue Oct
19
> 22:58:28 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

Typo, "nested".



> 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
> Tue Oct 19 22:58:28 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.
>

Why? Didn't this use to be a run testcase?

Thanks for fixing this!

Giovanni Bajo

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [C++] My unreviewed patch
  2004-10-20 12:09 Kriang Lerdsuwanakij
@ 2004-10-20 13:41 ` Nathan Sidwell
  2004-10-20 18:15 ` Giovanni Bajo
  1 sibling, 0 replies; 13+ messages in thread
From: Nathan Sidwell @ 2004-10-20 13:41 UTC (permalink / raw)
  To: lerdsuwa; +Cc: gcc-patches

Kriang Lerdsuwanakij wrote:

> This is the version I'm testing and will commit when all the 
> tests are finished.  These are the relevant chunk of patch
> involving dianostics:
> 
> ! 	      decl = lookup_member (ctype, name, 0, true);
> ! 	      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);
> ! 		  cp_error_at ("%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);
> ! 		  cp_error_at ("%qD declared here", decl);
> ! 		  return;
> ! 		}
Looks good.


> which is better than the following
> 
>   mf1.C:6: error: 'typename C<T>::X' is not a member of 'C<T>'
>   etc
> 
> in my opinion.
yes, I agree.

Thanks!

nathan

-- 
Nathan Sidwell    ::   http://www.codesourcery.com   ::     CodeSourcery LLC
nathan@codesourcery.com    ::     http://www.planetfall.pwp.blueyonder.co.uk


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [C++] My unreviewed patch
@ 2004-10-20 12:09 Kriang Lerdsuwanakij
  2004-10-20 13:41 ` Nathan Sidwell
  2004-10-20 18:15 ` Giovanni Bajo
  0 siblings, 2 replies; 13+ messages in thread
From: Kriang Lerdsuwanakij @ 2004-10-20 12:09 UTC (permalink / raw)
  To: gcc-patches, nathan


Nathan Sidwell <nathan@codesourcery.com> writes:

| Looks ok apart from some issues with the diagnostic text.  Can
| you use the new %qD and related quoted printing formatters?
| 

This is the version I'm testing and will commit when all the 
tests are finished.  These are the relevant chunk of patch
involving dianostics:

! 	      decl = lookup_member (ctype, name, 0, true);
! 	      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);
! 		  cp_error_at ("%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);
! 		  cp_error_at ("%qD declared here", decl);
! 		  return;
! 		}

I tweaked the error messages a bit from what you suggested.
For the following code:

  template <class T> class C {
    template <class U> class Y {};
    class Z {};
  };
  class D {
    template <class T> friend class C<T>::X;
    template <class T> friend class C<T>::Y;
    template <class T> template <class U> friend class C<T>::Z;
  };

It produces error messages as:

  mf1.C:6: error: 'X' is not a member of 'C<T>'
  mf1.C:7: error: 'Y' is not a nested class of 'C<T>'
  mf1.C:2: error: 'template<class T> template<class U> class C<T>::Y' declared here
  mf1.C:8: error: 'Z' is not a member class template of 'C<T>'
  mf1.C:3: error: 'class C<T>::Z' declared here

which is better than the following

  mf1.C:6: error: 'typename C<T>::X' is not a member of 'C<T>'
  etc

in my opinion.

--Kriang


2004-10-20  Kriang Lerdsuwanakij  <lerdsuwa@users.sourceforge.net>

	PR c++/13495
	* 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-10-20  Kriang Lerdsuwanakij  <lerdsuwa@users.sourceforge.net>

	PR c++/13495
	* 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	Tue Oct 19 18:43:59 2004
--- gcc-main-new/gcc/cp/cp-tree.h	Tue Oct 19 22:58:28 2004
*************** extern tree define_label			(location_t, 
*** 3689,3695 ****
  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);
--- 3689,3695 ----
  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	Tue Oct 19 18:43:59 2004
--- gcc-main-new/gcc/cp/decl.c	Tue Oct 19 23:09:36 2004
*************** make_typename_type (tree context, tree n
*** 2730,2743 ****
    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;
--- 2730,2747 ----
    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
*** 2763,2768 ****
--- 2767,2783 ----
  	  return error_mark_node;
  	}
  
+       if (parm_list
+ 	  && !comp_template_parms (DECL_TEMPLATE_PARMS (tmpl), parm_list))
+ 	{
+ 	  if (complain & tf_error)
+ 	    {
+ 	      error ("template parameters do not match template");
+ 	      cp_error_at ("%qD declared here", tmpl);
+ 	    }
+ 	  return error_mark_node;
+ 	}
+ 
        if (complain & tf_error)
  	perform_or_defer_access_check (TYPE_BINFO (context), tmpl);
  
*************** make_unbound_class_template (tree contex
*** 2780,2785 ****
--- 2795,2801 ----
    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	Tue Oct 12 22:48:26 2004
--- gcc-main-new/gcc/cp/friend.c	Wed Oct 20 18:05:52 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 %q#T declared %<friend%>", friend_type);
!       return;
      }
    else if (TREE_CODE (friend_type) == TEMPLATE_TYPE_PARM)
      {
--- 260,334 ----
       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, tf_error);
! 	    }
! 	  else
! 	    {
! 	      decl = lookup_member (ctype, name, 0, true);
! 	      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);
! 		  cp_error_at ("%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);
! 		  cp_error_at ("%qD declared here", decl);
! 		  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 ("%q#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;
--- 342,354 ----
        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;
*************** make_friend_class (tree type, tree frien
*** 297,303 ****
  
        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)
--- 382,388 ----
  
        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	Tue Oct 19 18:43:59 2004
--- gcc-main-new/gcc/cp/parser.c	Tue Oct 19 22:58:28 2004
*************** cp_parser_lookup_name (cp_parser *parser
*** 14237,14243 ****
  						  /*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);
--- 14237,14243 ----
  						  /*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*
*** 14926,14931 ****
--- 14926,14946 ----
        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	Tue Oct 19 18:44:00 2004
--- gcc-main-new/gcc/cp/pt.c	Tue Oct 19 22:58:28 2004
*************** is_specialization_of_friend (tree decl, 
*** 939,945 ****
    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
--- 939,946 ----
    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, 
*** 948,963 ****
        && 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
--- 949,968 ----
        && 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, 
*** 986,1002 ****
  			       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))
--- 991,1015 ----
  			       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, 
*** 1023,1029 ****
  	  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.  */
--- 1036,1042 ----
  	  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, 
*** 1033,1039 ****
  	      if (!comp_template_parms
  		     (DECL_TEMPLATE_PARMS (DECL_TI_TEMPLATE (decl)),
  		      friend_parms))
! 		return 0;
  
  	      decl_type = TREE_TYPE (DECL_TI_TEMPLATE (decl));
  	    }
--- 1046,1052 ----
  	      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, 
*** 1043,1053 ****
  	  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.  */
--- 1056,1066 ----
  	  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, 
*** 1057,1067 ****
  	    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
--- 1070,1115 ----
  	    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)
*** 5691,5705 ****
  	      /* 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));
--- 5739,5775 ----
  	      /* 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)
*** 5707,5718 ****
  		  /* 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
--- 5777,5788 ----
  		  /* 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)
*** 5720,5730 ****
  		   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
--- 5790,5799 ----
  		   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_
*** 7283,7293 ****
  	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:
--- 7352,7365 ----
  	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	Tue Oct 19 22:58: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	Tue Oct 19 22:58:28 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	Tue Oct 19 22:58:28 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	Tue Oct 19 22:58: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();
+   };
+ };
+ 
+ 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	Tue Oct 19 22:58:28 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	Tue Oct 19 22:58:28 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	Tue Oct 19 22:58:28 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	Tue Oct 19 22:58:28 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	Tue Oct 19 22:58:28 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	Tue Oct 19 22:58:28 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 ()

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [C++] My unreviewed patch
@ 2003-07-19 16:54 Kriang Lerdsuwanakij
  0 siblings, 0 replies; 13+ messages in thread
From: Kriang Lerdsuwanakij @ 2003-07-19 16:54 UTC (permalink / raw)
  To: gcc-patches

Hi

Aside from a few patches I sent earlier, I have one more
unreviewed patch left.  This one doesn't need any update.
It removes a chunk of code that relaxs access checking which
I no longer think it's necessary.

  http://gcc.gnu.org/ml/gcc-patches/2003-06/msg01740.html

Thank you

--Kriang


^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2004-10-21 12:11 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-10-17 14:48 [C++] My unreviewed patch Kriang Lerdsuwanakij
2004-10-18 17:51 ` Nathan Sidwell
2004-10-18 19:02   ` Gabriel Dos Reis
2004-10-18 19:08     ` Nathan Sidwell
2004-10-18 20:05       ` Gabriel Dos Reis
2004-10-18 20:18         ` Gabriel Dos Reis
  -- strict thread matches above, loose matches on Subject: below --
2004-10-20 12:09 Kriang Lerdsuwanakij
2004-10-20 13:41 ` Nathan Sidwell
2004-10-20 18:15 ` Giovanni Bajo
2004-10-21 12:10   ` Kriang Lerdsuwanakij
2004-10-21 12:11   ` Kriang Lerdsuwanakij
2004-10-21 12:36   ` Kriang Lerdsuwanakij
2003-07-19 16:54 Kriang Lerdsuwanakij

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).