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]

[PATCH] Fix 9162


Hi,
this patch fixes 9162 where we were leaving unprocessed default args lying
about.

I had to change grokdeclarator to return any friend function decls it
processed, so they could be remembered by the parser. Also you'll
see I split unparsed_functions_queue into two chains, one for function
bodies and one for default args - should speed things up a bit.

booted and tested on i686-pc-linux-gnu, ok?

nathan
--
Nathan Sidwell    ::   http://www.codesourcery.com   ::     CodeSourcery LLC
         The voices in my head said this was stupid too
nathan@codesourcery.com    ::     http://www.planetfall.pwp.blueyonder.co.uk

2003-07-02  Nathan Sidwell  <nathan@codesourcery.com>

	PR c++/9162
	* decl.c (grokdeclarator): Return friend decls, not
	void_type_node.
	* decl2.c (grokfield): Alter friend decl check.
	* parser.c (struct cp_parser): Document default_arg chain on
	unparsed_functions_queue.
	(cp_parser_save_default_args): New.
	(cp_parser_init_declarator, cp_parser_function_definition,
	cp_parser_member_declaration): Call it.
	(cp_parser_class_specifier): Remove unused variable. Alter
	processing of unparsed_functions_queue.

Index: cp/decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl.c,v
retrieving revision 1.1074
diff -c -3 -p -r1.1074 decl.c
*** cp/decl.c	28 Jun 2003 00:30:29 -0000	1.1074
--- cp/decl.c	1 Jul 2003 08:40:27 -0000
*************** grokdeclarator (tree declarator,
*** 10773,10781 ****
  
  	    declarator = TREE_OPERAND (declarator, 0);
  
- 	    /* FIXME: This is where default args should be fully
- 	       processed.  */
- 
  	    arg_types = grokparms (inner_parms);
  
  	    if (declarator && flags == DTOR_FLAG)
--- 10772,10777 ----
*************** grokdeclarator (tree declarator,
*** 11529,11558 ****
  	    /* Friends are treated specially.  */
  	    if (ctype == current_class_type)
  	      warning ("member functions are implicitly friends of their class");
!  	    else
!  	      {
!  		tree t = NULL_TREE;
!  		if (decl && DECL_NAME (decl))
!  		  {
!  		    if (template_class_depth (current_class_type) == 0)
!  		      {
!  			decl
!  			  = check_explicit_specialization
!  			  (declarator, decl,
!  			   template_count, 2 * (funcdef_flag != 0) + 4);
!  			if (decl == error_mark_node)
!  			  return error_mark_node;
!  		      }
! 		    
!  		    t = do_friend (ctype, declarator, decl,
!  				   last_function_parms, *attrlist,
! 				   flags, quals, funcdef_flag);
!  		  }
!  		if (t && funcdef_flag)
!  		  return t;
!   
!  		return void_type_node;
!  	      }
  	  }
  
  	/* Structure field.  It may not be a function, except for C++ */
--- 11525,11548 ----
  	    /* Friends are treated specially.  */
  	    if (ctype == current_class_type)
  	      warning ("member functions are implicitly friends of their class");
!  	    else if (decl && DECL_NAME (decl))
! 	      {
! 		if (template_class_depth (current_class_type) == 0)
! 		  {
! 		    decl = check_explicit_specialization
! 		      (declarator, decl, template_count,
! 		       2 * (funcdef_flag != 0) + 4);
! 		    if (decl == error_mark_node)
! 		      return error_mark_node;
! 		  }
! 		
! 		decl = do_friend (ctype, declarator, decl,
! 				  last_function_parms, *attrlist,
! 				  flags, quals, funcdef_flag);
! 		return decl;
! 	      }
! 	    else
! 	      return void_type_node;
  	  }
  
  	/* Structure field.  It may not be a function, except for C++ */
Index: cp/decl2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl2.c,v
retrieving revision 1.633
diff -c -3 -p -r1.633 decl2.c
*** cp/decl2.c	1 Jul 2003 07:17:02 -0000	1.633
--- cp/decl2.c	1 Jul 2003 08:40:36 -0000
*************** grokfield (tree declarator, tree declspe
*** 887,894 ****
      }
  
    /* Pass friendly classes back.  */
!   if (TREE_CODE (value) == VOID_TYPE)
!     return void_type_node;
  
    if (DECL_NAME (value) != NULL_TREE
        && IDENTIFIER_POINTER (DECL_NAME (value))[0] == '_'
--- 887,900 ----
      }
  
    /* Pass friendly classes back.  */
!   if (value == void_type_node)
!     return value;
! 
!   /* Pass friend decls back. */
!   if ((TREE_CODE (value) == FUNCTION_DECL
!        || TREE_CODE (value) == TEMPLATE_DECL)
!       && DECL_CONTEXT (value) != current_class_type)
!     return value;
  
    if (DECL_NAME (value) != NULL_TREE
        && IDENTIFIER_POINTER (DECL_NAME (value))[0] == '_'
Index: cp/friend.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/friend.c,v
retrieving revision 1.83
diff -c -3 -p -r1.83 friend.c
*** cp/friend.c	24 Jun 2003 15:40:02 -0000	1.83
--- cp/friend.c	1 Jul 2003 08:40:37 -0000
*************** make_friend_class (type, friend_type)
*** 306,315 ****
      }
  }
  
! /* Main friend processor.  This is large, and for modularity purposes,
!    has been removed from grokdeclarator.  It returns `void_type_node'
!    to indicate that something happened, though a FIELD_DECL is
!    not returned.
  
     CTYPE is the class this friend belongs to.
  
--- 306,312 ----
      }
  }
  
! /* Main friend processor. 
  
     CTYPE is the class this friend belongs to.
  
Index: cp/parser.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/parser.c,v
retrieving revision 1.69
diff -c -3 -p -r1.69 parser.c
*** cp/parser.c	30 Jun 2003 18:55:06 -0000	1.69
--- cp/parser.c	1 Jul 2003 08:41:09 -0000
*************** typedef struct cp_parser GTY(())
*** 1295,1310 ****
       issued as an error message if a type is defined.  */
    const char *type_definition_forbidden_message;
  
!   /* A TREE_LIST of queues of functions whose bodies have been lexed,
!      but may not have been parsed.  These functions are friends of
!      members defined within a class-specification; they are not
!      procssed until the class is complete.  The active queue is at the
!      front of the list.
! 
!      Within each queue, functions appear in the reverse order that
!      they appeared in the source.  Each TREE_VALUE is a
!      FUNCTION_DECL of TEMPLATE_DECL corresponding to a member
!      function.  */
    tree unparsed_functions_queues;
  
    /* The number of classes whose definitions are currently in
--- 1295,1314 ----
       issued as an error message if a type is defined.  */
    const char *type_definition_forbidden_message;
  
!   /* A list of lists. The outer list is a stack, used for member
!      functions of local classes. At each level there are two sub-list,
!      one on TREE_VALUE and one on TREE_PURPOSE. Each of those
!      sub-lists has a FUNCTION_DECL or TEMPLATE_DECL on their
!      TREE_VALUE's. The functions are chained in reverse declaration
!      order.
! 
!      The TREE_PURPOSE sublist contains those functions with default
!      arguments that need post processing, and the TREE_VALUE sublist
!      contains those functions with definitions that need post
!      processing.
! 
!      These lists can only be processed once the outermost class being
!      defined is complete. */
    tree unparsed_functions_queues;
  
    /* The number of classes whose definitions are currently in
*************** static tree cp_parser_single_declaration
*** 1679,1684 ****
--- 1683,1690 ----
    (cp_parser *, bool, bool *);
  static tree cp_parser_functional_cast
    (cp_parser *, tree);
+ static void cp_parser_save_default_args
+   (cp_parser *, tree);
  static void cp_parser_late_parsing_for_member
    (cp_parser *, tree);
  static void cp_parser_late_parsing_default_args
*************** cp_parser_init_declarator (cp_parser* pa
*** 9735,9744 ****
    /* For an in-class declaration, use `grokfield' to create the
       declaration.  */
    if (member_p)
!     decl = grokfield (declarator, decl_specifiers,
! 		      initializer, /*asmspec=*/NULL_TREE,
  			/*attributes=*/NULL_TREE);
! 
    /* Finish processing the declaration.  But, skip friend
       declarations.  */
    if (!friend_p && decl)
--- 9740,9753 ----
    /* For an in-class declaration, use `grokfield' to create the
       declaration.  */
    if (member_p)
!     {
!       decl = grokfield (declarator, decl_specifiers,
! 			initializer, /*asmspec=*/NULL_TREE,
  			/*attributes=*/NULL_TREE);
!       if (decl && TREE_CODE (decl) == FUNCTION_DECL)
! 	cp_parser_save_default_args (parser, decl);
!     }
!   
    /* Finish processing the declaration.  But, skip friend
       declarations.  */
    if (!friend_p && decl)
*************** cp_parser_function_definition (cp_parser
*** 11031,11036 ****
--- 11040,11048 ----
  	  return error_mark_node;
  	}
  
+       /* Remember it, if there default args to post process.  */
+       cp_parser_save_default_args (parser, fn);
+       
        /* Create a token cache.  */
        cache = cp_token_cache_new ();
        /* Save away the tokens that make up the body of the 
*************** cp_parser_class_specifier (cp_parser* pa
*** 11505,11518 ****
       there is no need to delay the parsing of `A::B::f'.  */
    if (--parser->num_classes_being_defined == 0) 
      {
-       tree last_scope = NULL_TREE;
        tree queue_entry;
        tree fn;
  
-       /* Reverse the queue, so that we process it in the order the
- 	 functions were declared.  */
-       TREE_VALUE (parser->unparsed_functions_queues)
- 	= nreverse (TREE_VALUE (parser->unparsed_functions_queues));
        /* In a first pass, parse default arguments to the functions.
  	 Then, in a second pass, parse the bodies of the functions.
  	 This two-phased approach handles cases like:
--- 11517,11525 ----
*************** cp_parser_class_specifier (cp_parser* pa
*** 11523,11535 ****
              };
  
           */
!       for (queue_entry = TREE_VALUE (parser->unparsed_functions_queues);
! 	   queue_entry;
! 	   queue_entry = TREE_CHAIN (queue_entry))
  	{
  	  fn = TREE_VALUE (queue_entry);
- 	  if (DECL_FUNCTION_TEMPLATE_P (fn))
- 	    fn = DECL_TEMPLATE_RESULT (fn);
  	  /* Make sure that any template parameters are in scope.  */
  	  maybe_begin_member_template_processing (fn);
  	  /* If there are default arguments that have not yet been processed,
--- 11530,11542 ----
              };
  
           */
!       for (TREE_PURPOSE (parser->unparsed_functions_queues)
! 	     = nreverse (TREE_PURPOSE (parser->unparsed_functions_queues));
! 	   (queue_entry = TREE_PURPOSE (parser->unparsed_functions_queues));
! 	   TREE_PURPOSE (parser->unparsed_functions_queues)
! 	     = TREE_CHAIN (TREE_PURPOSE (parser->unparsed_functions_queues)))
  	{
  	  fn = TREE_VALUE (queue_entry);
  	  /* Make sure that any template parameters are in scope.  */
  	  maybe_begin_member_template_processing (fn);
  	  /* If there are default arguments that have not yet been processed,
*************** cp_parser_class_specifier (cp_parser* pa
*** 11539,11562 ****
  	  maybe_end_member_template_processing ();
  	}
        /* Now parse the body of the functions.  */
!       while (TREE_VALUE (parser->unparsed_functions_queues))
! 
  	{
  	  /* Figure out which function we need to process.  */
- 	  queue_entry = TREE_VALUE (parser->unparsed_functions_queues);
  	  fn = TREE_VALUE (queue_entry);
  
  	  /* Parse the function.  */
  	  cp_parser_late_parsing_for_member (parser, fn);
- 
- 	  TREE_VALUE (parser->unparsed_functions_queues)
- 	    = TREE_CHAIN (TREE_VALUE (parser->unparsed_functions_queues));
  	}
  
-       /* If LAST_SCOPE is non-NULL, then we have pushed scopes one
- 	 more time than we have popped, so me must pop here.  */
-       if (last_scope)
- 	pop_scope (last_scope);
      }
  
    /* Put back any saved access checks.  */
--- 11546,11564 ----
  	  maybe_end_member_template_processing ();
  	}
        /* Now parse the body of the functions.  */
!       for (TREE_VALUE (parser->unparsed_functions_queues)
! 	     = nreverse (TREE_VALUE (parser->unparsed_functions_queues));
! 	   (queue_entry = TREE_VALUE (parser->unparsed_functions_queues));
! 	   TREE_VALUE (parser->unparsed_functions_queues)
! 	     = TREE_CHAIN (TREE_VALUE (parser->unparsed_functions_queues)))
  	{
  	  /* Figure out which function we need to process.  */
  	  fn = TREE_VALUE (queue_entry);
  
  	  /* Parse the function.  */
  	  cp_parser_late_parsing_for_member (parser, fn);
  	}
  
      }
  
    /* Put back any saved access checks.  */
*************** cp_parser_member_declaration (cp_parser*
*** 12268,12280 ****
  	      if (!friend_p)
  		finish_member_declaration (decl);
  
- 	      /* If DECL is a function, we must return
- 		 to parse it later.  (Even though there is no definition,
- 		 there might be default arguments that need handling.)  */
  	      if (TREE_CODE (decl) == FUNCTION_DECL)
! 		TREE_VALUE (parser->unparsed_functions_queues)
! 		  = tree_cons (NULL_TREE, decl, 
! 			       TREE_VALUE (parser->unparsed_functions_queues));
  	    }
  	}
      }
--- 12267,12274 ----
  	      if (!friend_p)
  		finish_member_declaration (decl);
  
  	      if (TREE_CODE (decl) == FUNCTION_DECL)
! 		cp_parser_save_default_args (parser, decl);
  	    }
  	}
      }
*************** cp_parser_late_parsing_for_member (cp_pa
*** 14127,14132 ****
--- 14117,14143 ----
    /* Restore the queue.  */
    parser->unparsed_functions_queues 
      = TREE_CHAIN (parser->unparsed_functions_queues);
+ }
+ 
+ /* If DECL contains any default args, remeber it on the unparsed
+    functions queue.  */
+ 
+ static void
+ cp_parser_save_default_args (cp_parser* parser, tree decl)
+ {
+   tree probe;
+ 
+   for (probe = TYPE_ARG_TYPES (TREE_TYPE (decl));
+        probe;
+        probe = TREE_CHAIN (probe))
+     if (TREE_PURPOSE (probe))
+       {
+ 	TREE_PURPOSE (parser->unparsed_functions_queues)
+ 	  = tree_cons (NULL_TREE, decl, 
+ 		       TREE_PURPOSE (parser->unparsed_functions_queues));
+ 	break;
+       }
+   return;
  }
  
  /* FN is a FUNCTION_DECL which may contains a parameter with an
struct S {
  friend int foo (int = 100);
};
int i = foo ();

struct R
{
  template <typename T> R (T, int = 0);
};

int Foo ()
{
  R s (1);
}

template <typename T> struct Q
{
  int Foo (T, int = 0);
};

int Foo (Q<int> *s)
{
  s->Foo (1);
}

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