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>
* class.c (add_method, check_field_decl): Fix format specifier.
......
......@@ -10779,9 +10779,6 @@ grokdeclarator (tree declarator,
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)
......@@ -11536,31 +11533,25 @@ grokdeclarator (tree declarator,
/* 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))
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);
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,
decl = do_friend (ctype, declarator, decl,
last_function_parms, *attrlist,
flags, quals, funcdef_flag);
return decl;
}
if (t && funcdef_flag)
return t;
else
return void_type_node;
}
}
/* 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,
}
/* Pass friendly classes back. */
if (TREE_CODE (value) == VOID_TYPE)
return void_type_node;
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] == '_'
......
......@@ -306,10 +306,7 @@ make_friend_class (type, friend_type)
}
}
/* 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.
/* Main friend processor.
CTYPE is the class this friend belongs to.
......
......@@ -1295,16 +1295,20 @@ typedef struct cp_parser GTY(())
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. */
/* 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
......@@ -1679,6 +1683,8 @@ static tree cp_parser_single_declaration
(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
......@@ -9735,9 +9741,13 @@ cp_parser_init_declarator (cp_parser* parser,
/* 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. */
......@@ -11031,6 +11041,9 @@ cp_parser_function_definition (cp_parser* parser, bool* friend_p)
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
......@@ -11505,14 +11518,9 @@ cp_parser_class_specifier (cp_parser* parser)
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:
......@@ -11523,13 +11531,13 @@ cp_parser_class_specifier (cp_parser* parser)
};
*/
for (queue_entry = TREE_VALUE (parser->unparsed_functions_queues);
queue_entry;
queue_entry = TREE_CHAIN (queue_entry))
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);
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,
......@@ -11539,24 +11547,19 @@ cp_parser_class_specifier (cp_parser* parser)
maybe_end_member_template_processing ();
}
/* 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. */
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. */
......@@ -12268,13 +12271,8 @@ cp_parser_member_declaration (cp_parser* parser)
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));
cp_parser_save_default_args (parser, decl);
}
}
}
......@@ -14129,6 +14127,27 @@ cp_parser_late_parsing_for_member (cp_parser* parser, tree member_function)
= 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
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>
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