This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH: Fix PR 9189
- From: Mark Mitchell <mark at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Mon, 6 Jan 2003 13:30:21 -0800
- Subject: C++ PATCH: Fix PR 9189
- Reply-to: mark at codesourcery dot com
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);
+ };