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
This commit is contained in:
parent
58eabcb1e9
commit
8db1028eba
|
@ -1,3 +1,17 @@
|
|||
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,30 +11533,24 @@ 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))
|
||||
{
|
||||
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;
|
||||
}
|
||||
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++ */
|
||||
|
|
|
@ -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.
|
||||
/* 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.
|
||||
|
||||
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. */
|
||||
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,10 +9741,14 @@ 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,
|
||||
{
|
||||
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)
|
||||
|
@ -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. */
|
||||
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
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
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
// { 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);
|
||||
}
|
Loading…
Reference in New Issue