public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* 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
@ 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
* [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-20 12:09 [C++] My unreviewed patch 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
  -- strict thread matches above, loose matches on Subject: below --
2004-10-17 14:48 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
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).