Commit 8db1028e by Nathan Sidwell Committed by Nathan Sidwell

re PR c++/9162 ([New parser] Problem with default argument in a friend function)

cp:
	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.
testsuite:
	PR c++/9162
	* g++.dg/parse/defarg4.C: New.

From-SVN: r68886
parent 58eabcb1
2003-07-03 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.
2003-07-03 Kaveh R. Ghazi <ghazi@caip.rutgers.edu> 2003-07-03 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* class.c (add_method, check_field_decl): Fix format specifier. * class.c (add_method, check_field_decl): Fix format specifier.
......
...@@ -10779,9 +10779,6 @@ grokdeclarator (tree declarator, ...@@ -10779,9 +10779,6 @@ grokdeclarator (tree declarator,
declarator = TREE_OPERAND (declarator, 0); declarator = TREE_OPERAND (declarator, 0);
/* FIXME: This is where default args should be fully
processed. */
arg_types = grokparms (inner_parms); arg_types = grokparms (inner_parms);
if (declarator && flags == DTOR_FLAG) if (declarator && flags == DTOR_FLAG)
...@@ -11536,30 +11533,24 @@ grokdeclarator (tree declarator, ...@@ -11536,30 +11533,24 @@ grokdeclarator (tree declarator,
/* Friends are treated specially. */ /* Friends are treated specially. */
if (ctype == current_class_type) if (ctype == current_class_type)
warning ("member functions are implicitly friends of their class"); warning ("member functions are implicitly friends of their class");
else else if (decl && DECL_NAME (decl))
{ {
tree t = NULL_TREE; if (template_class_depth (current_class_type) == 0)
if (decl && DECL_NAME (decl)) {
{ decl = check_explicit_specialization
if (template_class_depth (current_class_type) == 0) (declarator, decl, template_count,
{ 2 * (funcdef_flag != 0) + 4);
decl if (decl == error_mark_node)
= check_explicit_specialization return error_mark_node;
(declarator, decl, }
template_count, 2 * (funcdef_flag != 0) + 4);
if (decl == error_mark_node) decl = do_friend (ctype, declarator, decl,
return error_mark_node; last_function_parms, *attrlist,
} flags, quals, funcdef_flag);
return decl;
t = do_friend (ctype, declarator, decl, }
last_function_parms, *attrlist, else
flags, quals, funcdef_flag); return void_type_node;
}
if (t && funcdef_flag)
return t;
return void_type_node;
}
} }
/* Structure field. It may not be a function, except for C++ */ /* Structure field. It may not be a function, except for C++ */
......
...@@ -889,8 +889,14 @@ grokfield (tree declarator, tree declspecs, tree init, tree asmspec_tree, ...@@ -889,8 +889,14 @@ grokfield (tree declarator, tree declspecs, tree init, tree asmspec_tree,
} }
/* Pass friendly classes back. */ /* Pass friendly classes back. */
if (TREE_CODE (value) == VOID_TYPE) if (value == void_type_node)
return 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 if (DECL_NAME (value) != NULL_TREE
&& IDENTIFIER_POINTER (DECL_NAME (value))[0] == '_' && IDENTIFIER_POINTER (DECL_NAME (value))[0] == '_'
......
...@@ -306,10 +306,7 @@ make_friend_class (type, friend_type) ...@@ -306,10 +306,7 @@ make_friend_class (type, friend_type)
} }
} }
/* Main friend processor. This is large, and for modularity purposes, /* Main friend processor.
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. CTYPE is the class this friend belongs to.
......
...@@ -1295,16 +1295,20 @@ typedef struct cp_parser GTY(()) ...@@ -1295,16 +1295,20 @@ typedef struct cp_parser GTY(())
issued as an error message if a type is defined. */ issued as an error message if a type is defined. */
const char *type_definition_forbidden_message; const char *type_definition_forbidden_message;
/* A TREE_LIST of queues of functions whose bodies have been lexed, /* A list of lists. The outer list is a stack, used for member
but may not have been parsed. These functions are friends of functions of local classes. At each level there are two sub-list,
members defined within a class-specification; they are not one on TREE_VALUE and one on TREE_PURPOSE. Each of those
procssed until the class is complete. The active queue is at the sub-lists has a FUNCTION_DECL or TEMPLATE_DECL on their
front of the list. TREE_VALUE's. The functions are chained in reverse declaration
order.
Within each queue, functions appear in the reverse order that
they appeared in the source. Each TREE_VALUE is a The TREE_PURPOSE sublist contains those functions with default
FUNCTION_DECL of TEMPLATE_DECL corresponding to a member arguments that need post processing, and the TREE_VALUE sublist
function. */ 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; tree unparsed_functions_queues;
/* The number of classes whose definitions are currently in /* The number of classes whose definitions are currently in
...@@ -1679,6 +1683,8 @@ static tree cp_parser_single_declaration ...@@ -1679,6 +1683,8 @@ static tree cp_parser_single_declaration
(cp_parser *, bool, bool *); (cp_parser *, bool, bool *);
static tree cp_parser_functional_cast static tree cp_parser_functional_cast
(cp_parser *, tree); (cp_parser *, tree);
static void cp_parser_save_default_args
(cp_parser *, tree);
static void cp_parser_late_parsing_for_member static void cp_parser_late_parsing_for_member
(cp_parser *, tree); (cp_parser *, tree);
static void cp_parser_late_parsing_default_args static void cp_parser_late_parsing_default_args
...@@ -9735,10 +9741,14 @@ cp_parser_init_declarator (cp_parser* parser, ...@@ -9735,10 +9741,14 @@ cp_parser_init_declarator (cp_parser* parser,
/* For an in-class declaration, use `grokfield' to create the /* For an in-class declaration, use `grokfield' to create the
declaration. */ declaration. */
if (member_p) if (member_p)
decl = grokfield (declarator, decl_specifiers, {
initializer, /*asmspec=*/NULL_TREE, decl = grokfield (declarator, decl_specifiers,
initializer, /*asmspec=*/NULL_TREE,
/*attributes=*/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 /* Finish processing the declaration. But, skip friend
declarations. */ declarations. */
if (!friend_p && decl) if (!friend_p && decl)
...@@ -11031,6 +11041,9 @@ cp_parser_function_definition (cp_parser* parser, bool* friend_p) ...@@ -11031,6 +11041,9 @@ cp_parser_function_definition (cp_parser* parser, bool* friend_p)
return error_mark_node; return error_mark_node;
} }
/* Remember it, if there default args to post process. */
cp_parser_save_default_args (parser, fn);
/* Create a token cache. */ /* Create a token cache. */
cache = cp_token_cache_new (); cache = cp_token_cache_new ();
/* Save away the tokens that make up the body of the /* Save away the tokens that make up the body of the
...@@ -11505,14 +11518,9 @@ cp_parser_class_specifier (cp_parser* parser) ...@@ -11505,14 +11518,9 @@ cp_parser_class_specifier (cp_parser* parser)
there is no need to delay the parsing of `A::B::f'. */ there is no need to delay the parsing of `A::B::f'. */
if (--parser->num_classes_being_defined == 0) if (--parser->num_classes_being_defined == 0)
{ {
tree last_scope = NULL_TREE;
tree queue_entry; tree queue_entry;
tree fn; 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. /* In a first pass, parse default arguments to the functions.
Then, in a second pass, parse the bodies of the functions. Then, in a second pass, parse the bodies of the functions.
This two-phased approach handles cases like: This two-phased approach handles cases like:
...@@ -11523,13 +11531,13 @@ cp_parser_class_specifier (cp_parser* parser) ...@@ -11523,13 +11531,13 @@ cp_parser_class_specifier (cp_parser* parser)
}; };
*/ */
for (queue_entry = TREE_VALUE (parser->unparsed_functions_queues); for (TREE_PURPOSE (parser->unparsed_functions_queues)
queue_entry; = nreverse (TREE_PURPOSE (parser->unparsed_functions_queues));
queue_entry = TREE_CHAIN (queue_entry)) (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); 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. */ /* Make sure that any template parameters are in scope. */
maybe_begin_member_template_processing (fn); maybe_begin_member_template_processing (fn);
/* If there are default arguments that have not yet been processed, /* If there are default arguments that have not yet been processed,
...@@ -11539,24 +11547,19 @@ cp_parser_class_specifier (cp_parser* parser) ...@@ -11539,24 +11547,19 @@ cp_parser_class_specifier (cp_parser* parser)
maybe_end_member_template_processing (); maybe_end_member_template_processing ();
} }
/* Now parse the body of the functions. */ /* Now parse the body of the functions. */
while (TREE_VALUE (parser->unparsed_functions_queues)) 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. */ /* Figure out which function we need to process. */
queue_entry = TREE_VALUE (parser->unparsed_functions_queues);
fn = TREE_VALUE (queue_entry); fn = TREE_VALUE (queue_entry);
/* Parse the function. */ /* Parse the function. */
cp_parser_late_parsing_for_member (parser, fn); 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. */ /* Put back any saved access checks. */
...@@ -12268,13 +12271,8 @@ cp_parser_member_declaration (cp_parser* parser) ...@@ -12268,13 +12271,8 @@ cp_parser_member_declaration (cp_parser* parser)
if (!friend_p) if (!friend_p)
finish_member_declaration (decl); 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) if (TREE_CODE (decl) == FUNCTION_DECL)
TREE_VALUE (parser->unparsed_functions_queues) cp_parser_save_default_args (parser, decl);
= tree_cons (NULL_TREE, decl,
TREE_VALUE (parser->unparsed_functions_queues));
} }
} }
} }
...@@ -14129,6 +14127,27 @@ cp_parser_late_parsing_for_member (cp_parser* parser, tree member_function) ...@@ -14129,6 +14127,27 @@ cp_parser_late_parsing_for_member (cp_parser* parser, tree member_function)
= TREE_CHAIN (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 /* FN is a FUNCTION_DECL which may contains a parameter with an
unparsed DEFAULT_ARG. Parse the default args now. */ unparsed DEFAULT_ARG. Parse the default args now. */
......
2003-07-03 Nathan Sidwell <nathan@codesourcery.com>
PR c++/9162
* g++.dg/parse/defarg4.C: New.
2003-07-03 Roger Sayle <roger@eyesopen.com> 2003-07-03 Roger Sayle <roger@eyesopen.com>
PR target/10700 PR target/10700
......
// { dg-do compile }
// Copyright (C) 2003 Free Software Foundation, Inc.
// Contributed by Nathan Sidwell 3 Jul 2003 <nathan@codesourcery.com>
// PR c++ 9162. default args got left unprocessed
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);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment