This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix 9162
- From: Nathan Sidwell <nathan at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Cc: Mark Mitchell <mark at codesourcery dot com>
- Date: Wed, 02 Jul 2003 10:29:31 +0100
- Subject: [PATCH] Fix 9162
- Organization: Codesourcery LLC
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);
}