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]

Re: [PATCH,c++] convert cp_parser.unparsed_function_queues &co. to VECs


On Tue, Jun 08, 2010 at 02:03:37PM -0700, Nathan Froyd wrote:
> On Tue, Jun 08, 2010 at 11:57:40AM -0400, Jason Merrill wrote:
> > On 06/07/2010 02:14 PM, Nathan Froyd wrote:
> >> +typedef struct GTY(()) cp_default_arg_entry_d {
> >> +  /* The current_class_type when we parsed this arg.  */
> >> +  tree class_type;
> >> +
> >> +  /* The function decl itself.  */
> >> +  tree decl;
> >> +} cp_default_arg_entry;
> >
> > I don't think we need to store the class type, we can get it from the  
> > decl itself, i.e.
> >
> > ctype = DECL_FUNCTION_MEMBER_P (decl) ? DECL_CONTEXT (decl) :  
> > DECL_FRIEND_CONTEXT (decl)
> 
> Thanks for pointing that out.  I'll change things to use that and
> retest.

I tried the below, which I think implements your idea.  But
g++.old-deja/g++.other/defarg8.C fails with:

defarg8.C:15:30: error: the default argument for parameter 0 of 'static int AA::Baz(int)' has not yet been parsed

My C++-fu is weak, so I'm not quite sure what the problem is here.  It
sure would be nice to use a tree VEC for
unparsed_funs_with_default_args...but I don't know how to modify your
idea to make that happen.

-Nathan

	* parser.c (cp_unparsed_functions_entry): Declare.  Declare a VEC
	of it.
	(cp_parser) [unparsed_functions_queues]: Rename to unparsed_queues.
	Change type to a VEC.
	(unparsed_funs_with_default_args): Define.
	(unparsed_funs_with_definitions): Define.
	(push_unparsed_function_queues): New function.
	(cp_parser_new): Call it.
	(pop_unparsed_function_queues): New function.
	(cp_parser_class_specifier): Adjust processing of unparsed functions.
	(cp_parser_template_declaration_after_export): Use VEC_safe_push.
	(cp_parser_save_member_function_body): Likewise.
	(cp_parser_late_parsing_for_member): Call push_unparsed_function_queues
	and pop_unparsed_function_queues.
	(cp_parser_late_parsing_default_args): Likewise.
	(cp_parser_save_default_args): Use VEC_safe_push.

Index: parser.c
===================================================================
--- parser.c	(revision 160819)
+++ parser.c	(working copy)
@@ -1514,6 +1514,21 @@ cp_parser_context_new (cp_parser_context
   return context;
 }
 
+/* An entry in a stack for member functions of local classes.  */
+
+typedef struct GTY(()) cp_unparsed_functions_entry_d {
+  /* Functions with default arguments that require post-processing.
+     Functions appear in this list in declaration order.  */
+  VEC(tree,gc) *funs_with_default_args;
+
+  /* Functions with defintions that require post-processing.  Functions
+     appear in this list in declaration order.  */
+  VEC(tree,gc) *funs_with_definitions;
+} cp_unparsed_functions_entry;
+
+DEF_VEC_O(cp_unparsed_functions_entry);
+DEF_VEC_ALLOC_O(cp_unparsed_functions_entry,gc);
+
 /* The cp_parser structure represents the C++ parser.  */
 
 typedef struct GTY(()) cp_parser {
@@ -1640,21 +1655,10 @@ typedef struct GTY(()) cp_parser {
      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;
+  /* A stack used for member functions of local classes.  The lists
+     contained in an individual entry can only be processed once the
+     outermost class being defined is complete.  */
+  VEC(cp_unparsed_functions_entry,gc) *unparsed_queues;
 
   /* The number of classes whose definitions are currently in
      progress.  */
@@ -1665,6 +1669,30 @@ typedef struct GTY(()) cp_parser {
   unsigned num_template_parameter_lists;
 } cp_parser;
 
+/* Managing the unparsed function queues.  */
+
+#define unparsed_funs_with_default_args \
+  VEC_last (cp_unparsed_functions_entry, parser->unparsed_queues)->funs_with_default_args
+#define unparsed_funs_with_definitions \
+  VEC_last (cp_unparsed_functions_entry, parser->unparsed_queues)->funs_with_definitions
+
+static void
+push_unparsed_function_queues (cp_parser *parser)
+{
+  VEC_safe_push (cp_unparsed_functions_entry, gc,
+		 parser->unparsed_queues, NULL);
+  unparsed_funs_with_default_args = make_tree_vector ();
+  unparsed_funs_with_definitions = make_tree_vector ();
+}
+
+static void
+pop_unparsed_function_queues (cp_parser *parser)
+{
+  release_tree_vector (unparsed_funs_with_definitions);
+  release_tree_vector (unparsed_funs_with_default_args);
+  VEC_pop (cp_unparsed_functions_entry, parser->unparsed_queues);
+}
+
 /* Prototypes.  */
 
 /* Constructors and destructors.  */
@@ -3151,7 +3179,7 @@ cp_parser_new (void)
   parser->in_function_body = false;
 
   /* The unparsed function queue is empty.  */
-  parser->unparsed_functions_queues = build_tree_list (NULL_TREE, NULL_TREE);
+  push_unparsed_function_queues (parser);
 
   /* There are no classes being defined.  */
   parser->num_classes_being_defined = 0;
@@ -16248,10 +16276,10 @@ cp_parser_class_specifier (cp_parser* pa
      there is no need to delay the parsing of `A::B::f'.  */
   if (--parser->num_classes_being_defined == 0)
     {
-      tree queue_entry;
       tree fn;
       tree class_type = NULL_TREE;
       tree pushed_scope = NULL_TREE;
+      unsigned ix;
 
       /* In a first pass, parse default arguments to the functions.
 	 Then, in a second pass, parse the bodies of the functions.
@@ -16263,20 +16291,20 @@ cp_parser_class_specifier (cp_parser* pa
 	    };
 
 	 */
-      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);
+      for (ix = 0;
+	   VEC_iterate (tree, unparsed_funs_with_default_args, ix, fn);
+	   ix++)
+	{
+	  tree ctype = (DECL_FUNCTION_MEMBER_P (fn)
+			? DECL_CONTEXT (fn)
+			: DECL_FRIEND_CONTEXT (fn));
 	  /* If there are default arguments that have not yet been processed,
 	     take care of them now.  */
-	  if (class_type != TREE_PURPOSE (queue_entry))
+	  if (class_type != ctype)
 	    {
 	      if (pushed_scope)
 		pop_scope (pushed_scope);
-	      class_type = TREE_PURPOSE (queue_entry);
+	      class_type = ctype;
 	      pushed_scope = push_scope (class_type);
 	    }
 	  /* Make sure that any template parameters are in scope.  */
@@ -16288,18 +16316,13 @@ cp_parser_class_specifier (cp_parser* pa
 	}
       if (pushed_scope)
 	pop_scope (pushed_scope);
+      VEC_truncate (tree, unparsed_funs_with_default_args, 0);
       /* 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);
-	}
+      for (ix = 0;
+	   VEC_iterate (tree, unparsed_funs_with_definitions, ix, fn);
+	   ix++)
+	cp_parser_late_parsing_for_member (parser, fn);
+      VEC_truncate (tree, unparsed_funs_with_definitions, 0);
     }
 
   /* Put back any saved access checks.  */
@@ -19152,9 +19175,7 @@ cp_parser_template_declaration_after_exp
   if (member_p && decl
       && (TREE_CODE (decl) == FUNCTION_DECL
 	  || DECL_FUNCTION_TEMPLATE_P (decl)))
-    TREE_VALUE (parser->unparsed_functions_queues)
-      = tree_cons (NULL_TREE, decl,
-		   TREE_VALUE (parser->unparsed_functions_queues));
+    VEC_safe_push (tree, gc, unparsed_funs_with_definitions, decl);
 }
 
 /* Perform the deferred access checks from a template-parameter-list.
@@ -19424,9 +19445,7 @@ cp_parser_save_member_function_body (cp_
   DECL_INITIALIZED_IN_CLASS_P (fn) = 1;
 
   /* Add FN to the queue of functions to be parsed later.  */
-  TREE_VALUE (parser->unparsed_functions_queues)
-    = tree_cons (NULL_TREE, fn,
-		 TREE_VALUE (parser->unparsed_functions_queues));
+  VEC_safe_push (tree, gc, unparsed_funs_with_definitions, fn);
 
   return fn;
 }
@@ -19557,8 +19576,7 @@ cp_parser_late_parsing_for_member (cp_pa
      classes.  We want to handle them right away, but we don't want
      them getting mixed up with functions that are currently in the
      queue.  */
-  parser->unparsed_functions_queues
-    = tree_cons (NULL_TREE, NULL_TREE, parser->unparsed_functions_queues);
+  push_unparsed_function_queues (parser);
 
   /* Make sure that any template parameters are in scope.  */
   maybe_begin_member_template_processing (member_function);
@@ -19610,8 +19628,7 @@ cp_parser_late_parsing_for_member (cp_pa
   maybe_end_member_template_processing ();
 
   /* Restore the queue.  */
-  parser->unparsed_functions_queues
-    = TREE_CHAIN (parser->unparsed_functions_queues);
+  pop_unparsed_function_queues (parser);
 }
 
 /* If DECL contains any default args, remember it on the unparsed
@@ -19627,9 +19644,7 @@ cp_parser_save_default_args (cp_parser* 
        probe = TREE_CHAIN (probe))
     if (TREE_PURPOSE (probe))
       {
-	TREE_PURPOSE (parser->unparsed_functions_queues)
-	  = tree_cons (current_class_type, decl,
-		       TREE_PURPOSE (parser->unparsed_functions_queues));
+	VEC_safe_push (tree, gc, unparsed_funs_with_default_args, decl);
 	break;
       }
 }
@@ -19649,8 +19664,7 @@ cp_parser_late_parsing_default_args (cp_
      statement expression extension) encounter more classes.  We want
      to handle them right away, but we don't want them getting mixed
      up with default args that are currently in the queue.  */
-  parser->unparsed_functions_queues
-    = tree_cons (NULL_TREE, NULL_TREE, parser->unparsed_functions_queues);
+  push_unparsed_function_queues (parser);
 
   /* Local variable names (and the `this' keyword) may not appear
      in a default argument.  */
@@ -19722,8 +19736,7 @@ cp_parser_late_parsing_default_args (cp_
   parser->local_variables_forbidden_p = saved_local_variables_forbidden_p;
 
   /* Restore the queue.  */
-  parser->unparsed_functions_queues
-    = TREE_CHAIN (parser->unparsed_functions_queues);
+  pop_unparsed_function_queues (parser);
 }
 
 /* Parse the operand of `sizeof' (or a similar operator).  Returns


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