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


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

[C++ PATCH] Fix PR 109


Hi,
This fixes bug 109 where we fail to grok type dependant friends such as
	friend void T::Foo ();
and
	friend class T::N;
where T is a template type parm.  The tsubst code deals with these fine,
it is the front end template parsing & checking which bails out.

grokdeclarator mustn't reject T::foo as a declarator name until it knows
it is not a friend. handle_class_head mustn't try and push into the scope
of T in 'class T::N' (because it hasn't got one), and push_template_decl_real
must deal with such contexts.

built & tested on i686-pc-linux-gnu, ok?

nathan
-- 
Dr Nathan Sidwell   ::   http://www.codesourcery.com   ::   CodeSourcery LLC
         'But that's a lie.' - 'Yes it is. What's your point?'
nathan@codesourcery.com : http://www.cs.bris.ac.uk/~nathan/ : nathan@acm.org
2001-12-18  Nathan Sidwell  <nathan@codesourcery.com>

	PR c++/109
	* decl.c (grokdeclarator): Allow friend declarations from
	dependant types.
	* decl2.c (handle_class_head): Don't push into template parm contexts.
	* parse.y (structsp): Don't pop from template parm contexts.
	* pt.c (push_template_decl_real): Template parm contexts are never
	being defined.

Index: cp/decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl.c,v
retrieving revision 1.843
diff -c -3 -p -r1.843 decl.c
*** decl.c	2001/12/18 03:35:26	1.843
--- decl.c	2001/12/19 09:48:49
*************** grokdeclarator (declarator, declspecs, d
*** 9601,9606 ****
--- 9601,9607 ----
    int explicit_char = 0;
    int defaulted_int = 0;
    int extern_langp = 0;
+   tree dependant_name = NULL_TREE;
    
    tree typedef_decl = NULL_TREE;
    const char *name;
*************** grokdeclarator (declarator, declspecs, d
*** 9842,9852 ****
  	      else if (TREE_CODE (cname) == TEMPLATE_TYPE_PARM
  		       || TREE_CODE (cname) == BOUND_TEMPLATE_TEMPLATE_PARM)
  		{
! 		  error ("`%T::%D' is not a valid declarator", cname,
! 			    TREE_OPERAND (decl, 1));
! 		  error ("  perhaps you want `typename %T::%D' to make it a type",
! 			    cname, TREE_OPERAND (decl, 1));
! 		  return void_type_node;
  		}
  	      else if (ctype == NULL_TREE)
  		ctype = cname;
--- 9843,9852 ----
  	      else if (TREE_CODE (cname) == TEMPLATE_TYPE_PARM
  		       || TREE_CODE (cname) == BOUND_TEMPLATE_TEMPLATE_PARM)
  		{
! 	  	  /* This might be declaring a member of a template
! 		     parm to be a friend.  */
! 		  ctype = cname;
! 		  dependant_name = TREE_OPERAND (decl, 1);
  		}
  	      else if (ctype == NULL_TREE)
  		ctype = cname;
*************** grokdeclarator (declarator, declspecs, d
*** 10330,10335 ****
--- 10330,10341 ----
    friendp = RIDBIT_SETP (RID_FRIEND, specbits);
    RIDBIT_RESET (RID_FRIEND, specbits);
  
+   if (dependant_name && !friendp)
+     {
+       error ("`%T::%D' is not a valid declarator", ctype, dependant_name);
+       return void_type_node;
+     }
+   
    /* Warn if two storage classes are given. Default to `auto'.  */
  
    if (RIDBIT_ANY_SET (specbits))
Index: cp/decl2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl2.c,v
retrieving revision 1.506
diff -c -3 -p -r1.506 decl2.c
*** decl2.c	2001/12/18 09:36:01	1.506
--- decl2.c	2001/12/19 09:48:50
*************** handle_class_head (aggr, scope, id)
*** 5167,5172 ****
--- 5167,5173 ----
       tree aggr, scope, id;
  {
    tree decl = NULL_TREE;
+   tree ctx;
  
    if (TREE_CODE (id) == TYPE_DECL)
      /* We must bash typedefs back to the main decl of the type. Otherwise
*************** handle_class_head (aggr, scope, id)
*** 5213,5219 ****
   
    /* Enter the SCOPE.  If this turns out not to be a definition, the
       parser must leave the scope.  */
!   push_scope (CP_DECL_CONTEXT (decl));
  
    /* If we see something like:
  
--- 5214,5223 ----
   
    /* Enter the SCOPE.  If this turns out not to be a definition, the
       parser must leave the scope.  */
!   ctx = CP_DECL_CONTEXT (decl);
!   if (TREE_CODE (ctx) != TEMPLATE_TYPE_PARM
!       && TREE_CODE (ctx) != BOUND_TEMPLATE_TEMPLATE_PARM)
!     push_scope (ctx);
  
    /* If we see something like:
  
Index: cp/parse.y
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/parse.y,v
retrieving revision 1.238
diff -c -3 -p -r1.238 parse.y
*** parse.y	2001/12/18 03:35:35	1.238
--- parse.y	2001/12/19 09:48:54
*************** structsp:
*** 2313,2319 ****
  	| class_head  %prec EMPTY
  		{
  		  if ($1.new_type_flag && $1.t != error_mark_node)
! 		    pop_scope (CP_DECL_CONTEXT (TYPE_MAIN_DECL ($1.t)));
  		  $$.new_type_flag = 0;
  		  if ($1.t == error_mark_node)
  		    $$.t = $1.t;
--- 2313,2326 ----
  	| class_head  %prec EMPTY
  		{
  		  if ($1.new_type_flag && $1.t != error_mark_node)
! 		    {
! 		      tree ctx = CP_DECL_CONTEXT (TYPE_MAIN_DECL ($1.t));
! 
! 		      if (TREE_CODE (ctx) != TEMPLATE_TYPE_PARM
! 			  && TREE_CODE (ctx) != BOUND_TEMPLATE_TEMPLATE_PARM)
! 			pop_scope (ctx);
! 		    }
! 
  		  $$.new_type_flag = 0;
  		  if ($1.t == error_mark_node)
  		    $$.t = $1.t;
Index: cp/pt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/pt.c,v
retrieving revision 1.566
diff -c -3 -p -r1.566 pt.c
*** pt.c	2001/12/18 14:13:44	1.566
--- pt.c	2001/12/19 09:48:56
*************** push_template_decl_real (decl, is_friend
*** 2570,2576 ****
  
    if (!ctx 
        || TREE_CODE (ctx) == FUNCTION_DECL
!       || TYPE_BEING_DEFINED (ctx)
        || (is_friend && !DECL_TEMPLATE_INFO (decl)))
      {
        if (DECL_LANG_SPECIFIC (decl)
--- 2570,2578 ----
  
    if (!ctx 
        || TREE_CODE (ctx) == FUNCTION_DECL
!       || (TREE_CODE (ctx) != TEMPLATE_TYPE_PARM
! 	  && TREE_CODE (ctx) != BOUND_TEMPLATE_TEMPLATE_PARM
! 	  && TYPE_BEING_DEFINED (ctx))
        || (is_friend && !DECL_TEMPLATE_INFO (decl)))
      {
        if (DECL_LANG_SPECIFIC (decl)
// { dg-do compile }

// Copyright (C) 2001 Free Software Foundation, Inc.
// Contributed by Nathan Sidwell 18 Dec 2001 <nathan@nathan@codesourcery.com>

// PR 109, dependant member friends

struct B
{
  static int foo ();
  struct N
  {
    static int bar ();
  };
};


template <class T>
class A
{
  friend int T::foo ();
  friend int T::N::bar ();
  
  private:
  static int m;
};

template <class T>
class C
{
  friend struct T::N;

  private:
  static int m;
};


int B::foo ()
{
  return A<B>::m;
}

int B::N::bar ()
{
  return A<B>::m + C<B>::m;
}

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