From 69b6679cb3d40be670a7cb5df16343c567ae2fa0 Mon Sep 17 00:00:00 2001 From: nathan Date: Thu, 3 Jul 2003 16:10:52 +0000 Subject: [PATCH] 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@68886 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/cp/ChangeLog | 14 ++++++ gcc/cp/decl.c | 45 +++++++---------- gcc/cp/decl2.c | 10 +++- gcc/cp/friend.c | 5 +- gcc/cp/parser.c | 97 +++++++++++++++++++++--------------- gcc/testsuite/ChangeLog | 5 ++ gcc/testsuite/g++.dg/parse/defarg4.C | 31 ++++++++++++ 7 files changed, 135 insertions(+), 72 deletions(-) create mode 100644 gcc/testsuite/g++.dg/parse/defarg4.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index c0b47dc970b..f75b8ac4a4f 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,17 @@ +2003-07-03 Nathan Sidwell + + 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 * class.c (add_method, check_field_decl): Fix format specifier. diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 732ada291b4..219c65996fd 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -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++ */ diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index faa36f58b3c..ab29aeed45d 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.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] == '_' diff --git a/gcc/cp/friend.c b/gcc/cp/friend.c index 0a0e82c7fcd..e458a14bf1a 100644 --- a/gcc/cp/friend.c +++ b/gcc/cp/friend.c @@ -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. diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 3654adbe0a8..6155af404cd 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -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,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. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 70bc1834e9a..c158b78539d 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2003-07-03 Nathan Sidwell + + PR c++/9162 + * g++.dg/parse/defarg4.C: New. + 2003-07-03 Roger Sayle PR target/10700 diff --git a/gcc/testsuite/g++.dg/parse/defarg4.C b/gcc/testsuite/g++.dg/parse/defarg4.C new file mode 100644 index 00000000000..39d0a89904f --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/defarg4.C @@ -0,0 +1,31 @@ +// { dg-do compile } + +// Copyright (C) 2003 Free Software Foundation, Inc. +// Contributed by Nathan Sidwell 3 Jul 2003 + +// PR c++ 9162. default args got left unprocessed + +struct S { + friend int foo (int = 100); +}; +int i = foo (); + +struct R +{ + template R (T, int = 0); +}; + +int Foo () +{ + R s (1); +} + +template struct Q +{ + int Foo (T, int = 0); +}; + +int Foo (Q *s) +{ + s->Foo (1); +} -- 2.11.4.GIT