aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@codesourcery.com>2003-07-03 16:10:52 +0000
committerNathan Sidwell <nathan@gcc.gnu.org>2003-07-03 16:10:52 +0000
commit8db1028ebab32f0d725be8dc886a6aa335d81575 (patch)
treececd1124ba5e8aecaff532002a217533915f83ea /gcc/cp
parent58eabcb1e9b9e16550757ba6b744148d20a7457f (diff)
downloadgcc-8db1028ebab32f0d725be8dc886a6aa335d81575.zip
gcc-8db1028ebab32f0d725be8dc886a6aa335d81575.tar.gz
gcc-8db1028ebab32f0d725be8dc886a6aa335d81575.tar.bz2
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
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog14
-rw-r--r--gcc/cp/decl.c45
-rw-r--r--gcc/cp/decl2.c10
-rw-r--r--gcc/cp/friend.c5
-rw-r--r--gcc/cp/parser.c97
5 files changed, 99 insertions, 72 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index c0b47dc..f75b8ac 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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.
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 732ada2..219c659 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 faa36f5..ab29aee 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 0a0e82c..e458a14 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 3654adb..6155af4 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. */