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 9189


This patch fixes the regression reported in PR 9189.

Tested on i686-pc-linux-gnu, applied on the mainline.

--
Mark Mitchell                   mark@codesourcery.com
CodeSourcery, LLC               http://www.codesourcery.com

2003-01-06  Mark Mitchell  <mark@codesourcery.com>

	PR c++/9189
	* parser.c (cp_parser): Remove default_arg_types.  Update
	documentation for unparsed_functions_queues.
	(cp_parser_late_parsing_default_args): Take a FUNCTION_DECL as the
	parameter.
	(cp_parser_new): Don't set parser->default_arg_types.
	(cp_parser_function_definition): Adjust usage of
	unparsed_funtions_queues.
	(cp_parser_class_specifier): Don't mess with
	parser->default_arg_types.  Handle default argument processing in
	a separate phase from function body processing.
	(cp_parser_template_declaration_after_export): Adjust usage of
	unparsed_functions_queues.
	(cp_parser_late_parsing_for_member): Do not handle default
	arguments.

2003-01-06  Mark Mitchell  <mark@codesourcery.com>

	PR c++/9189
	* g++.dg/parse/defarg3.C: New test.

Index: parser.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/parser.c,v
retrieving revision 1.17
diff -c -5 -p -r1.17 parser.c
*** parser.c	3 Jan 2003 02:11:55 -0000	1.17
--- parser.c	6 Jan 2003 21:15:16 -0000
*************** typedef struct cp_parser GTY(())
*** 1316,1341 ****
    /* If non-NULL, then we are parsing a construct where new type
       definitions are not permitted.  The string stored here will be
       issued as an error message if a type is defined.  */
    const char *type_definition_forbidden_message;
  
-   /* List of FUNCTION_TYPEs which contain unprocessed DEFAULT_ARGs
-      during class parsing, and are not FUNCTION_DECLs.  G++ has an
-      awkward extension allowing default args on pointers to functions
-      etc.  */
-   tree default_arg_types;
- 
    /* 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.  The TREE_PURPOSE of each node is
!      the class in which the function was defined or declared; the
!      TREE_VALUE is the FUNCTION_DECL itself.  */
    tree unparsed_functions_queues;
  
    /* The number of classes whose definitions are currently in
       progress.  */
    unsigned num_classes_being_defined;
--- 1316,1335 ----
    /* If non-NULL, then we are parsing a construct where new type
       definitions are not permitted.  The string stored here will be
       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
       progress.  */
    unsigned num_classes_being_defined;
*************** static tree cp_parser_single_declaration
*** 1717,1727 ****
  static tree cp_parser_functional_cast
    PARAMS ((cp_parser *, tree));
  static void cp_parser_late_parsing_for_member
    PARAMS ((cp_parser *, tree));
  static void cp_parser_late_parsing_default_args
!   (cp_parser *, tree, tree);
  static tree cp_parser_sizeof_operand
    PARAMS ((cp_parser *, enum rid));
  static bool cp_parser_declares_only_class_p
    PARAMS ((cp_parser *));
  static bool cp_parser_friend_p
--- 1711,1721 ----
  static tree cp_parser_functional_cast
    PARAMS ((cp_parser *, tree));
  static void cp_parser_late_parsing_for_member
    PARAMS ((cp_parser *, tree));
  static void cp_parser_late_parsing_default_args
!   (cp_parser *, tree);
  static tree cp_parser_sizeof_operand
    PARAMS ((cp_parser *, enum rid));
  static bool cp_parser_declares_only_class_p
    PARAMS ((cp_parser *));
  static bool cp_parser_friend_p
*************** cp_parser_new ()
*** 2490,2502 ****
    parser->in_unbraced_linkage_specification_p = false;
  
    /* We are not processing a declarator.  */
    parser->in_declarator_p = false;
  
-   /* There are no default args to process.  */
-   parser->default_arg_types = NULL;
- 
    /* The unparsed function queue is empty.  */
    parser->unparsed_functions_queues = build_tree_list (NULL_TREE, NULL_TREE);
  
    /* There are no classes being defined.  */
    parser->num_classes_being_defined = 0;
--- 2484,2493 ----
*************** cp_parser_function_definition (parser, f
*** 11208,11218 ****
        /* We're done with the inline definition.  */
        finish_method (fn);
  
        /* Add FN to the queue of functions to be parsed later.  */
        TREE_VALUE (parser->unparsed_functions_queues)
! 	= tree_cons (current_class_type, fn, 
  		     TREE_VALUE (parser->unparsed_functions_queues));
  
        return fn;
      }
  
--- 11199,11209 ----
        /* We're done with the inline definition.  */
        finish_method (fn);
  
        /* 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));
  
        return fn;
      }
  
*************** cp_parser_class_specifier (parser)
*** 11660,11692 ****
  
       there is no need to delay the parsing of `A::B::f'.  */
    if (--parser->num_classes_being_defined == 0) 
      {
        tree last_scope = NULL_TREE;
  
-       /* Process non FUNCTION_DECL related DEFAULT_ARGs.  */
-       for (parser->default_arg_types = nreverse (parser->default_arg_types);
- 	   parser->default_arg_types;
- 	   parser->default_arg_types = TREE_CHAIN (parser->default_arg_types))
- 	cp_parser_late_parsing_default_args
- 	  (parser, TREE_PURPOSE (parser->default_arg_types), NULL_TREE);
-       
        /* 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));
!       /* Loop through all of the functions.  */
        while (TREE_VALUE (parser->unparsed_functions_queues))
  
  	{
- 	  tree fn;
- 	  tree fn_scope;
- 	  tree queue_entry;
- 
  	  /* Figure out which function we need to process.  */
  	  queue_entry = TREE_VALUE (parser->unparsed_functions_queues);
- 	  fn_scope = TREE_PURPOSE (queue_entry);
  	  fn = TREE_VALUE (queue_entry);
  
  	  /* Parse the function.  */
  	  cp_parser_late_parsing_for_member (parser, fn);
  
--- 11651,11698 ----
  
       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:
! 	 
! 	    struct S { 
!               void f() { g(); } 
!               void g(int i = 3);
!             };
! 
!          */
!       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,
! 	     take care of them now.  */
! 	  cp_parser_late_parsing_default_args (parser, fn);
! 	  /* Remove any template parameters from the symbol table.  */
! 	  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);
  
*************** cp_parser_member_declaration (parser)
*** 12414,12424 ****
  	      /* 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 (current_class_type, decl, 
  			       TREE_VALUE (parser->unparsed_functions_queues));
  	    }
  	}
      }
  
--- 12420,12430 ----
  	      /* 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));
  	    }
  	}
      }
  
*************** cp_parser_template_declaration_after_exp
*** 14216,14226 ****
       arguments that need handling.)  */
    if (member_p && decl 
        && (TREE_CODE (decl) == FUNCTION_DECL
  	  || DECL_FUNCTION_TEMPLATE_P (decl)))
      TREE_VALUE (parser->unparsed_functions_queues)
!       = tree_cons (current_class_type, decl, 
  		   TREE_VALUE (parser->unparsed_functions_queues));
  }
  
  /* Parse a `decl-specifier-seq [opt] init-declarator [opt] ;' or
     `function-definition' sequence.  MEMBER_P is true, this declaration
--- 14222,14232 ----
       arguments that need handling.)  */
    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));
  }
  
  /* Parse a `decl-specifier-seq [opt] init-declarator [opt] ;' or
     `function-definition' sequence.  MEMBER_P is true, this declaration
*************** cp_parser_late_parsing_for_member (parse
*** 14362,14378 ****
      = tree_cons (NULL_TREE, NULL_TREE, parser->unparsed_functions_queues);
  
    /* Make sure that any template parameters are in scope.  */
    maybe_begin_member_template_processing (member_function);
  
-   /* If there are default arguments that have not yet been processed,
-      take care of them now.  */
-   cp_parser_late_parsing_default_args (parser, TREE_TYPE (member_function),
- 				       DECL_FUNCTION_MEMBER_P (member_function)
- 				       ? DECL_CONTEXT (member_function)
- 				       : NULL_TREE);
- 
    /* If the body of the function has not yet been parsed, parse it
       now.  */
    if (DECL_PENDING_INLINE_P (member_function))
      {
        tree function_scope;
--- 14368,14377 ----
*************** cp_parser_late_parsing_for_member (parse
*** 14422,14445 ****
    /* Restore the queue.  */
    parser->unparsed_functions_queues 
      = TREE_CHAIN (parser->unparsed_functions_queues);
  }
  
! /* TYPE is a FUNCTION_TYPE or METHOD_TYPE which contains a parameter
!    with an unparsed DEFAULT_ARG.  If non-NULL, SCOPE is the class in
!    whose context name lookups in the default argument should occur.
!    Parse the default args now.  */
  
  static void
! cp_parser_late_parsing_default_args (cp_parser *parser, tree type, tree scope)
  {
    cp_lexer *saved_lexer;
    cp_token_cache *tokens;
    bool saved_local_variables_forbidden_p;
    tree parameters;
!   
!   for (parameters = TYPE_ARG_TYPES (type);
         parameters;
         parameters = TREE_CHAIN (parameters))
      {
        if (!TREE_PURPOSE (parameters)
  	  || TREE_CODE (TREE_PURPOSE (parameters)) != DEFAULT_ARG)
--- 14421,14442 ----
    /* Restore the queue.  */
    parser->unparsed_functions_queues 
      = TREE_CHAIN (parser->unparsed_functions_queues);
  }
  
! /* FN is a FUNCTION_DECL which may contains a parameter with an
!    unparsed DEFAULT_ARG.  Parse the default args now.  */
  
  static void
! cp_parser_late_parsing_default_args (cp_parser *parser, tree fn)
  {
    cp_lexer *saved_lexer;
    cp_token_cache *tokens;
    bool saved_local_variables_forbidden_p;
    tree parameters;
! 
!   for (parameters = TYPE_ARG_TYPES (TREE_TYPE (fn));
         parameters;
         parameters = TREE_CHAIN (parameters))
      {
        if (!TREE_PURPOSE (parameters)
  	  || TREE_CODE (TREE_PURPOSE (parameters)) != DEFAULT_ARG)
*************** cp_parser_late_parsing_default_args (cp_
*** 14459,14472 ****
         /* Local variable names (and the `this' keyword) may not appear
       	  in a default argument.  */
        saved_local_variables_forbidden_p = parser->local_variables_forbidden_p;
        parser->local_variables_forbidden_p = true;
         /* Parse the assignment-expression.  */
!       if (scope)
! 	push_nested_class (scope, 1);
        TREE_PURPOSE (parameters) = cp_parser_assignment_expression (parser);
!       if (scope)
  	pop_nested_class ();
  
         /* Restore saved state.  */
        parser->lexer = saved_lexer;
        parser->local_variables_forbidden_p = saved_local_variables_forbidden_p;
--- 14456,14469 ----
         /* Local variable names (and the `this' keyword) may not appear
       	  in a default argument.  */
        saved_local_variables_forbidden_p = parser->local_variables_forbidden_p;
        parser->local_variables_forbidden_p = true;
         /* Parse the assignment-expression.  */
!       if (DECL_CONTEXT (fn))
! 	push_nested_class (DECL_CONTEXT (fn), 1);
        TREE_PURPOSE (parameters) = cp_parser_assignment_expression (parser);
!       if (DECL_CONTEXT (fn))
  	pop_nested_class ();
  
         /* Restore saved state.  */
        parser->lexer = saved_lexer;
        parser->local_variables_forbidden_p = saved_local_variables_forbidden_p;
*** /dev/null	Thu Apr 11 07:25:15 2002
--- testsuite/g++.dg/parse/defarg3.C	Mon Jan  6 12:30:37 2003
***************
*** 0 ****
--- 1,5 ----
+ struct A {
+     enum { value = 10 };
+     A() { f(); }
+     static int f(int i=value);
+ };


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