diff options
author | Jason Merrill <jason@redhat.com> | 2011-09-24 22:26:01 -0400 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2011-09-24 22:26:01 -0400 |
commit | eb02633818a908b78e8fc0939be2e4774ed840c6 (patch) | |
tree | 4ed25f3377c184a6d3a1db8397675121388b3ccc /gcc/cp | |
parent | 0e5f8a598de1c8dc44fb59c6d0ea0dcd557f695a (diff) | |
download | gcc-eb02633818a908b78e8fc0939be2e4774ed840c6.zip gcc-eb02633818a908b78e8fc0939be2e4774ed840c6.tar.gz gcc-eb02633818a908b78e8fc0939be2e4774ed840c6.tar.bz2 |
Handle deferred parsing of NSDMIs.
* parser.h (cp_unparsed_functions_entry): Add nsdmis field.
* parser.c (unparsed_nsdmis, cp_parser_save_nsdmi): New.
(cp_parser_late_parse_one_default_arg): Split out from
cp_parser_late_parsing_default_args.
(cp_parser_late_parsing_nsdmi): New.
(push_unparsed_function_queues): Set it.
(cp_parser_parameter_declaration): Save the '=' token.
(cp_parser_template_parameter): Likewise.
(cp_parser_default_argument): Call cp_parser_initializer
rather than cp_parser_initializer_clause.
(cp_parser_class_specifier_1): Parse unparsed_nsdmis.
(cp_parser_member_declaration): Handle nsdmis.
* decl2.c (grokfield): Handle DEFAULT_ARG for a function.
From-SVN: r179156
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 15 | ||||
-rw-r--r-- | gcc/cp/decl.c | 2 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 2 | ||||
-rw-r--r-- | gcc/cp/parser.c | 196 | ||||
-rw-r--r-- | gcc/cp/parser.h | 4 |
5 files changed, 174 insertions, 45 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 7881e1f..f1496b6 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,20 @@ 2011-09-24 Jason Merrill <jason@redhat.com> + Handle deferred parsing of NSDMIs. + * parser.h (cp_unparsed_functions_entry): Add nsdmis field. + * parser.c (unparsed_nsdmis, cp_parser_save_nsdmi): New. + (cp_parser_late_parse_one_default_arg): Split out from + cp_parser_late_parsing_default_args. + (cp_parser_late_parsing_nsdmi): New. + (push_unparsed_function_queues): Set it. + (cp_parser_parameter_declaration): Save the '=' token. + (cp_parser_template_parameter): Likewise. + (cp_parser_default_argument): Call cp_parser_initializer + rather than cp_parser_initializer_clause. + (cp_parser_class_specifier_1): Parse unparsed_nsdmis. + (cp_parser_member_declaration): Handle nsdmis. + * decl2.c (grokfield): Handle DEFAULT_ARG for a function. + Implement C++11 non-static data member initializers. * cp-tree.h (enum cpp_warn_str): Add CPP0X_NSDMI. * error.c (maybe_warn_cpp0x): Handle it. diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 661cc5e..45bf6a1 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -6077,7 +6077,7 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p, /* Just store non-static data member initializers for later. */ if (init && TREE_CODE (decl) == FIELD_DECL) - DECL_INITIAL (decl) = digest_init_flags (TREE_TYPE (decl), init, flags); + DECL_INITIAL (decl) = init; /* Take care of TYPE_DECLs up front. */ if (TREE_CODE (decl) == TYPE_DECL) diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 1e06280..6e5f7cc 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -902,6 +902,8 @@ grokfield (const cp_declarator *declarator, DECL_DECLARED_INLINE_P (value) = 1; } } + else if (TREE_CODE (init) == DEFAULT_ARG) + error ("invalid initializer for member function %qD", value); else if (TREE_CODE (TREE_TYPE (value)) == METHOD_TYPE) { if (integer_zerop (init)) diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index bd46af3..2dbe866 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -1486,6 +1486,8 @@ cp_parser_context_new (cp_parser_context* next) VEC_last (cp_unparsed_functions_entry, parser->unparsed_queues)->funs_with_default_args #define unparsed_funs_with_definitions \ VEC_last (cp_unparsed_functions_entry, parser->unparsed_queues)->funs_with_definitions +#define unparsed_nsdmis \ + VEC_last (cp_unparsed_functions_entry, parser->unparsed_queues)->nsdmis static void push_unparsed_function_queues (cp_parser *parser) @@ -1494,6 +1496,7 @@ push_unparsed_function_queues (cp_parser *parser) parser->unparsed_queues, NULL); unparsed_funs_with_default_args = NULL; unparsed_funs_with_definitions = make_tree_vector (); + unparsed_nsdmis = NULL; } static void @@ -1936,12 +1939,18 @@ static tree cp_parser_functional_cast (cp_parser *, tree); static tree cp_parser_save_member_function_body (cp_parser *, cp_decl_specifier_seq *, cp_declarator *, tree); +static tree cp_parser_save_nsdmi + (cp_parser *); static tree cp_parser_enclosed_template_argument_list (cp_parser *); static void cp_parser_save_default_args (cp_parser *, tree); static void cp_parser_late_parsing_for_member (cp_parser *, tree); +static tree cp_parser_late_parse_one_default_arg + (cp_parser *, tree, tree, tree); +static void cp_parser_late_parsing_nsdmi + (cp_parser *, tree); static void cp_parser_late_parsing_default_args (cp_parser *, tree); static tree cp_parser_sizeof_operand @@ -11343,9 +11352,7 @@ cp_parser_template_parameter (cp_parser* parser, bool *is_non_type, user may try to do so, so we'll parse them and give an appropriate diagnostic here. */ - /* Consume the `='. */ cp_token *start_token = cp_lexer_peek_token (parser->lexer); - cp_lexer_consume_token (parser->lexer); /* Find the name of the parameter pack. */ id_declarator = parameter_declarator->declarator; @@ -16323,9 +16330,6 @@ cp_parser_parameter_declaration (cp_parser *parser, /* If the next token is `=', then process a default argument. */ if (cp_lexer_next_token_is (parser->lexer, CPP_EQ)) { - /* Consume the `='. */ - cp_lexer_consume_token (parser->lexer); - /* If we are defining a class, then the tokens that make up the default argument must be saved and processed later. */ if (!template_parm_p && at_class_scope_p () @@ -16535,7 +16539,7 @@ cp_parser_default_argument (cp_parser *parser, bool template_parm_p) tree default_argument = NULL_TREE; bool saved_greater_than_is_operator_p; bool saved_local_variables_forbidden_p; - bool non_constant_p; + bool non_constant_p, is_direct_init; /* Make sure that PARSER->GREATER_THAN_IS_OPERATOR_P is set correctly. */ @@ -16549,7 +16553,7 @@ cp_parser_default_argument (cp_parser *parser, bool template_parm_p) if (template_parm_p) push_deferring_access_checks (dk_no_deferred); default_argument - = cp_parser_initializer_clause (parser, &non_constant_p); + = cp_parser_initializer (parser, &is_direct_init, &non_constant_p); if (BRACE_ENCLOSED_INITIALIZER_P (default_argument)) maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS); if (template_parm_p) @@ -17265,7 +17269,7 @@ cp_parser_class_specifier_1 (cp_parser* parser) there is no need to delay the parsing of `A::B::f'. */ if (--parser->num_classes_being_defined == 0) { - tree fn; + tree decl; tree class_type = NULL_TREE; tree pushed_scope = NULL_TREE; unsigned ix; @@ -17284,7 +17288,7 @@ cp_parser_class_specifier_1 (cp_parser* parser) FOR_EACH_VEC_ELT (cp_default_arg_entry, unparsed_funs_with_default_args, ix, e) { - fn = e->decl; + decl = e->decl; /* If there are default arguments that have not yet been processed, take care of them now. */ if (class_type != e->class_type) @@ -17295,18 +17299,31 @@ cp_parser_class_specifier_1 (cp_parser* parser) pushed_scope = push_scope (class_type); } /* Make sure that any template parameters are in scope. */ - maybe_begin_member_template_processing (fn); + maybe_begin_member_template_processing (decl); /* Parse the default argument expressions. */ - cp_parser_late_parsing_default_args (parser, fn); + cp_parser_late_parsing_default_args (parser, decl); /* Remove any template parameters from the symbol table. */ maybe_end_member_template_processing (); } + VEC_truncate (cp_default_arg_entry, unparsed_funs_with_default_args, 0); + /* Now parse any NSDMIs. */ + FOR_EACH_VEC_ELT (tree, unparsed_nsdmis, ix, decl) + { + if (class_type != DECL_CONTEXT (decl)) + { + if (pushed_scope) + pop_scope (pushed_scope); + class_type = DECL_CONTEXT (decl); + pushed_scope = push_scope (class_type); + } + cp_parser_late_parsing_nsdmi (parser, decl); + } + VEC_truncate (tree, unparsed_nsdmis, 0); if (pushed_scope) pop_scope (pushed_scope); - VEC_truncate (cp_default_arg_entry, unparsed_funs_with_default_args, 0); /* Now parse the body of the functions. */ - FOR_EACH_VEC_ELT (tree, unparsed_funs_with_definitions, ix, fn) - cp_parser_late_parsing_for_member (parser, fn); + FOR_EACH_VEC_ELT (tree, unparsed_funs_with_definitions, ix, decl) + cp_parser_late_parsing_for_member (parser, decl); VEC_truncate (tree, unparsed_funs_with_definitions, 0); } @@ -18185,8 +18202,14 @@ cp_parser_member_declaration (cp_parser* parser) constant-initializer. When we call `grokfield', it will perform more stringent semantics checks. */ initializer_token_start = cp_lexer_peek_token (parser->lexer); - if (function_declarator_p (declarator)) + if (function_declarator_p (declarator) + || (decl_specifiers.type + && TREE_CODE (decl_specifiers.type) == TYPE_DECL + && (TREE_CODE (TREE_TYPE (decl_specifiers.type)) + == FUNCTION_TYPE))) initializer = cp_parser_pure_specifier (parser); + else if (decl_specifiers.storage_class != sc_static) + initializer = cp_parser_save_nsdmi (parser); else if (cxx_dialect >= cxx0x) { bool nonconst; @@ -18206,7 +18229,10 @@ cp_parser_member_declaration (cp_parser* parser) && !function_declarator_p (declarator)) { bool x; - initializer = cp_parser_initializer (parser, &x, &x); + if (decl_specifiers.storage_class != sc_static) + initializer = cp_parser_save_nsdmi (parser); + else + initializer = cp_parser_initializer (parser, &x, &x); } /* Otherwise, there is no initializer. */ else @@ -18292,6 +18318,11 @@ cp_parser_member_declaration (cp_parser* parser) if (TREE_CODE (decl) == FUNCTION_DECL) cp_parser_save_default_args (parser, decl); + else if (TREE_CODE (decl) == FIELD_DECL + && !DECL_C_BIT_FIELD (decl) + && DECL_INITIAL (decl)) + /* Add DECL to the queue of NSDMI to be parsed later. */ + VEC_safe_push (tree, gc, unparsed_nsdmis, decl); } if (assume_semicolon) @@ -20539,6 +20570,30 @@ cp_parser_save_member_function_body (cp_parser* parser, return fn; } +/* Save the tokens that make up the in-class initializer for a non-static + data member. Returns a DEFAULT_ARG. */ + +static tree +cp_parser_save_nsdmi (cp_parser* parser) +{ + /* Save away the tokens that make up the body of the + function. */ + cp_token *first = parser->lexer->next_token; + cp_token *last; + tree node; + + cp_parser_cache_group (parser, CPP_CLOSE_PAREN, /*depth=*/0); + + last = parser->lexer->next_token; + + node = make_node (DEFAULT_ARG); + DEFARG_TOKENS (node) = cp_token_cache_new (first, last); + DEFARG_INSTANTIATIONS (node) = NULL; + + return node; +} + + /* Parse a template-argument-list, as well as the trailing ">" (but not the opening ">"). See cp_parser_template_argument_list for the return value. */ @@ -20744,6 +20799,83 @@ cp_parser_save_default_args (cp_parser* parser, tree decl) } } +/* DEFAULT_ARG contains the saved tokens for the initializer of DECL, + which is either a FIELD_DECL or PARM_DECL. Parse it and return + the result. For a PARM_DECL, PARMTYPE is the corresponding type + from the parameter-type-list. */ + +static tree +cp_parser_late_parse_one_default_arg (cp_parser *parser, tree decl, + tree default_arg, tree parmtype) +{ + cp_token_cache *tokens; + tree parsed_arg; + bool dummy; + + /* Push the saved tokens for the default argument onto the parser's + lexer stack. */ + tokens = DEFARG_TOKENS (default_arg); + cp_parser_push_lexer_for_tokens (parser, tokens); + + start_lambda_scope (decl); + + /* Parse the default argument. */ + parsed_arg = cp_parser_initializer (parser, &dummy, &dummy); + if (BRACE_ENCLOSED_INITIALIZER_P (parsed_arg)) + maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS); + + finish_lambda_scope (); + + if (!processing_template_decl) + { + /* In a non-template class, check conversions now. In a template, + we'll wait and instantiate these as needed. */ + if (TREE_CODE (decl) == PARM_DECL) + parsed_arg = check_default_argument (parmtype, parsed_arg); + else + { + int flags = LOOKUP_IMPLICIT; + if (BRACE_ENCLOSED_INITIALIZER_P (parsed_arg) + && CONSTRUCTOR_IS_DIRECT_INIT (parsed_arg)) + flags = LOOKUP_NORMAL; + parsed_arg = digest_init_flags (TREE_TYPE (decl), parsed_arg, flags); + } + } + + /* If the token stream has not been completely used up, then + there was extra junk after the end of the default + argument. */ + if (!cp_lexer_next_token_is (parser->lexer, CPP_EOF)) + { + if (TREE_CODE (decl) == PARM_DECL) + cp_parser_error (parser, "expected %<,%>"); + else + cp_parser_error (parser, "expected %<;%>"); + } + + /* Revert to the main lexer. */ + cp_parser_pop_lexer (parser); + + return parsed_arg; +} + +/* FIELD is a non-static data member with an initializer which we saved for + later; parse it now. */ + +static void +cp_parser_late_parsing_nsdmi (cp_parser *parser, tree field) +{ + tree def; + + push_unparsed_function_queues (parser); + def = cp_parser_late_parse_one_default_arg (parser, field, + DECL_INITIAL (field), + NULL_TREE); + pop_unparsed_function_queues (parser); + + DECL_INITIAL (field) = def; +} + /* FN is a FUNCTION_DECL which may contains a parameter with an unparsed DEFAULT_ARG. Parse the default args now. This function assumes that the current scope is the scope in which the default @@ -20753,7 +20885,6 @@ static void cp_parser_late_parsing_default_args (cp_parser *parser, tree fn) { bool saved_local_variables_forbidden_p; - bool non_constant_p; tree parm, parmdecl; /* While we're parsing the default args, we might (due to the @@ -20775,7 +20906,6 @@ cp_parser_late_parsing_default_args (cp_parser *parser, tree fn) parm = TREE_CHAIN (parm), parmdecl = DECL_CHAIN (parmdecl)) { - cp_token_cache *tokens; tree default_arg = TREE_PURPOSE (parm); tree parsed_arg; VEC(tree,gc) *insts; @@ -20790,25 +20920,14 @@ cp_parser_late_parsing_default_args (cp_parser *parser, tree fn) already declared with default arguments. */ continue; - /* Push the saved tokens for the default argument onto the parser's - lexer stack. */ - tokens = DEFARG_TOKENS (default_arg); - cp_parser_push_lexer_for_tokens (parser, tokens); - - start_lambda_scope (parmdecl); - - /* Parse the assignment-expression. */ - parsed_arg = cp_parser_initializer_clause (parser, &non_constant_p); + parsed_arg + = cp_parser_late_parse_one_default_arg (parser, parmdecl, + default_arg, + TREE_VALUE (parm)); if (parsed_arg == error_mark_node) { - cp_parser_pop_lexer (parser); continue; } - if (BRACE_ENCLOSED_INITIALIZER_P (parsed_arg)) - maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS); - - if (!processing_template_decl) - parsed_arg = check_default_argument (TREE_VALUE (parm), parsed_arg); TREE_PURPOSE (parm) = parsed_arg; @@ -20816,17 +20935,6 @@ cp_parser_late_parsing_default_args (cp_parser *parser, tree fn) for (insts = DEFARG_INSTANTIATIONS (default_arg), ix = 0; VEC_iterate (tree, insts, ix, copy); ix++) TREE_PURPOSE (copy) = parsed_arg; - - finish_lambda_scope (); - - /* If the token stream has not been completely used up, then - there was extra junk after the end of the default - argument. */ - if (!cp_lexer_next_token_is (parser->lexer, CPP_EOF)) - cp_parser_error (parser, "expected %<,%>"); - - /* Revert to the main lexer. */ - cp_parser_pop_lexer (parser); } pop_defarg_context (); diff --git a/gcc/cp/parser.h b/gcc/cp/parser.h index 33582fb..e08c0b4 100644 --- a/gcc/cp/parser.h +++ b/gcc/cp/parser.h @@ -169,6 +169,10 @@ typedef struct GTY(()) cp_unparsed_functions_entry_d { /* Functions with defintions that require post-processing. Functions appear in this list in declaration order. */ VEC(tree,gc) *funs_with_definitions; + + /* Non-static data members with initializers that require post-processing. + FIELD_DECLs appear in this list in declaration order. */ + VEC(tree,gc) *nsdmis; } cp_unparsed_functions_entry; DEF_VEC_O(cp_unparsed_functions_entry); |