aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/parser.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/parser.c')
-rw-r--r--gcc/cp/parser.c196
1 files changed, 152 insertions, 44 deletions
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 ();