|
|
|
@ -1863,12 +1863,14 @@ static tree cp_parser_condition
|
|
|
|
|
(cp_parser *);
|
|
|
|
|
static tree cp_parser_iteration_statement
|
|
|
|
|
(cp_parser *);
|
|
|
|
|
static void cp_parser_for_init_statement
|
|
|
|
|
(cp_parser *);
|
|
|
|
|
static tree cp_parser_c_for
|
|
|
|
|
(cp_parser *);
|
|
|
|
|
static tree cp_parser_range_for
|
|
|
|
|
static bool cp_parser_for_init_statement
|
|
|
|
|
(cp_parser *, tree *decl);
|
|
|
|
|
static tree cp_parser_for
|
|
|
|
|
(cp_parser *);
|
|
|
|
|
static tree cp_parser_c_for
|
|
|
|
|
(cp_parser *, tree, tree);
|
|
|
|
|
static tree cp_parser_range_for
|
|
|
|
|
(cp_parser *, tree, tree, tree);
|
|
|
|
|
static tree cp_parser_jump_statement
|
|
|
|
|
(cp_parser *);
|
|
|
|
|
static void cp_parser_declaration_statement
|
|
|
|
@ -1888,7 +1890,7 @@ static void cp_parser_declaration
|
|
|
|
|
static void cp_parser_block_declaration
|
|
|
|
|
(cp_parser *, bool);
|
|
|
|
|
static void cp_parser_simple_declaration
|
|
|
|
|
(cp_parser *, bool);
|
|
|
|
|
(cp_parser *, bool, tree *);
|
|
|
|
|
static void cp_parser_decl_specifier_seq
|
|
|
|
|
(cp_parser *, cp_parser_flags, cp_decl_specifier_seq *, int *);
|
|
|
|
|
static tree cp_parser_storage_class_specifier_opt
|
|
|
|
@ -1938,7 +1940,7 @@ static tree cp_parser_decltype
|
|
|
|
|
/* Declarators [gram.dcl.decl] */
|
|
|
|
|
|
|
|
|
|
static tree cp_parser_init_declarator
|
|
|
|
|
(cp_parser *, cp_decl_specifier_seq *, VEC (deferred_access_check,gc)*, bool, bool, int, bool *);
|
|
|
|
|
(cp_parser *, cp_decl_specifier_seq *, VEC (deferred_access_check,gc)*, bool, bool, int, bool *, tree *);
|
|
|
|
|
static cp_declarator *cp_parser_declarator
|
|
|
|
|
(cp_parser *, cp_parser_declarator_kind, int *, bool *, bool);
|
|
|
|
|
static cp_declarator *cp_parser_direct_declarator
|
|
|
|
@ -8694,21 +8696,38 @@ cp_parser_condition (cp_parser* parser)
|
|
|
|
|
return cp_parser_expression (parser, /*cast_p=*/false, NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Parses a traditional for-statement until the closing ')', not included. */
|
|
|
|
|
/* Parses a for-statement or range-for-statement until the closing ')',
|
|
|
|
|
not included. */
|
|
|
|
|
|
|
|
|
|
static tree
|
|
|
|
|
cp_parser_c_for (cp_parser *parser)
|
|
|
|
|
cp_parser_for (cp_parser *parser)
|
|
|
|
|
{
|
|
|
|
|
/* Normal for loop */
|
|
|
|
|
tree stmt;
|
|
|
|
|
tree condition = NULL_TREE;
|
|
|
|
|
tree expression = NULL_TREE;
|
|
|
|
|
tree init, scope, decl;
|
|
|
|
|
bool is_range_for;
|
|
|
|
|
|
|
|
|
|
/* Begin the for-statement. */
|
|
|
|
|
stmt = begin_for_stmt ();
|
|
|
|
|
scope = begin_for_scope (&init);
|
|
|
|
|
|
|
|
|
|
/* Parse the initialization. */
|
|
|
|
|
cp_parser_for_init_statement (parser);
|
|
|
|
|
is_range_for = cp_parser_for_init_statement (parser, &decl);
|
|
|
|
|
|
|
|
|
|
if (is_range_for)
|
|
|
|
|
return cp_parser_range_for (parser, scope, init, decl);
|
|
|
|
|
else
|
|
|
|
|
return cp_parser_c_for (parser, scope, init);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static tree
|
|
|
|
|
cp_parser_c_for (cp_parser *parser, tree scope, tree init)
|
|
|
|
|
{
|
|
|
|
|
/* Normal for loop */
|
|
|
|
|
tree condition = NULL_TREE;
|
|
|
|
|
tree expression = NULL_TREE;
|
|
|
|
|
tree stmt;
|
|
|
|
|
|
|
|
|
|
stmt = begin_for_stmt (scope, init);
|
|
|
|
|
/* The for-init-statement has already been parsed in
|
|
|
|
|
cp_parser_for_init_statement, so no work is needed here. */
|
|
|
|
|
finish_for_init_stmt (stmt);
|
|
|
|
|
|
|
|
|
|
/* If there's a condition, process it. */
|
|
|
|
@ -8729,60 +8748,27 @@ cp_parser_c_for (cp_parser *parser)
|
|
|
|
|
/* Tries to parse a range-based for-statement:
|
|
|
|
|
|
|
|
|
|
range-based-for:
|
|
|
|
|
type-specifier-seq declarator : expression
|
|
|
|
|
decl-specifier-seq declarator : expression
|
|
|
|
|
|
|
|
|
|
If succesful, assigns to *DECL the DECLARATOR and to *EXPR the
|
|
|
|
|
expression. Note that the *DECL is returned unfinished, so
|
|
|
|
|
later you should call cp_finish_decl().
|
|
|
|
|
|
|
|
|
|
Returns TRUE iff a range-based for is parsed. */
|
|
|
|
|
The decl-specifier-seq declarator and the `:' are already parsed by
|
|
|
|
|
cp_parser_for_init_statement. If processing_template_decl it returns a
|
|
|
|
|
newly created RANGE_FOR_STMT; if not, it is converted to a
|
|
|
|
|
regular FOR_STMT. */
|
|
|
|
|
|
|
|
|
|
static tree
|
|
|
|
|
cp_parser_range_for (cp_parser *parser)
|
|
|
|
|
cp_parser_range_for (cp_parser *parser, tree scope, tree init, tree range_decl)
|
|
|
|
|
{
|
|
|
|
|
tree stmt, range_decl, range_expr;
|
|
|
|
|
cp_decl_specifier_seq type_specifiers;
|
|
|
|
|
cp_declarator *declarator;
|
|
|
|
|
const char *saved_message;
|
|
|
|
|
tree attributes, pushed_scope;
|
|
|
|
|
bool saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p;
|
|
|
|
|
tree stmt, range_expr;
|
|
|
|
|
|
|
|
|
|
parser->colon_corrects_to_scope_p = false;
|
|
|
|
|
cp_parser_parse_tentatively (parser);
|
|
|
|
|
/* New types are not allowed in the type-specifier-seq for a
|
|
|
|
|
range-based for loop. */
|
|
|
|
|
saved_message = parser->type_definition_forbidden_message;
|
|
|
|
|
parser->type_definition_forbidden_message
|
|
|
|
|
= G_("types may not be defined in range-based for loops");
|
|
|
|
|
/* Parse the type-specifier-seq. */
|
|
|
|
|
cp_parser_type_specifier_seq (parser, /*is_declaration==*/true,
|
|
|
|
|
/*is_trailing_return=*/false,
|
|
|
|
|
&type_specifiers);
|
|
|
|
|
/* Restore the saved message. */
|
|
|
|
|
parser->type_definition_forbidden_message = saved_message;
|
|
|
|
|
/* If all is well, we might be looking at a declaration. */
|
|
|
|
|
if (cp_parser_error_occurred (parser))
|
|
|
|
|
/* If the variable from a range-for is not actually used, GCC would issue
|
|
|
|
|
"unused variable" warnings, and the user could do little to prevent them.
|
|
|
|
|
So we always mark it as used. */
|
|
|
|
|
if (range_decl != error_mark_node)
|
|
|
|
|
{
|
|
|
|
|
cp_parser_abort_tentative_parse (parser);
|
|
|
|
|
stmt = NULL_TREE;
|
|
|
|
|
goto out;
|
|
|
|
|
TREE_USED (range_decl) = 1;
|
|
|
|
|
DECL_READ_P (range_decl) = 1;
|
|
|
|
|
}
|
|
|
|
|
/* Parse the declarator. */
|
|
|
|
|
declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
|
|
|
|
|
/*ctor_dtor_or_conv_p=*/NULL,
|
|
|
|
|
/*parenthesized_p=*/NULL,
|
|
|
|
|
/*member_p=*/false);
|
|
|
|
|
/* Parse the attributes. */
|
|
|
|
|
attributes = cp_parser_attributes_opt (parser);
|
|
|
|
|
/* The next token should be `:'. */
|
|
|
|
|
if (cp_lexer_next_token_is_not (parser->lexer, CPP_COLON))
|
|
|
|
|
cp_parser_simulate_error (parser);
|
|
|
|
|
|
|
|
|
|
/* Check if it is a range-based for */
|
|
|
|
|
if (!cp_parser_parse_definitely (parser))
|
|
|
|
|
return NULL_TREE;
|
|
|
|
|
|
|
|
|
|
cp_parser_require (parser, CPP_COLON, RT_COLON);
|
|
|
|
|
if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
|
|
|
|
|
{
|
|
|
|
|
bool expr_non_constant_p;
|
|
|
|
@ -8791,29 +8777,18 @@ cp_parser_range_for (cp_parser *parser)
|
|
|
|
|
else
|
|
|
|
|
range_expr = cp_parser_expression (parser, /*cast_p=*/false, NULL);
|
|
|
|
|
|
|
|
|
|
/* If in template, STMT is converted to a normal for-statements
|
|
|
|
|
/* If in template, STMT is converted to a normal for-statement
|
|
|
|
|
at instantiation. If not, it is done just ahead. */
|
|
|
|
|
if (processing_template_decl)
|
|
|
|
|
stmt = begin_range_for_stmt ();
|
|
|
|
|
{
|
|
|
|
|
stmt = begin_range_for_stmt (scope, init);
|
|
|
|
|
finish_range_for_decl (stmt, range_decl, range_expr);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
stmt = begin_for_stmt ();
|
|
|
|
|
|
|
|
|
|
/* Create the declaration. It must be after begin{,_range}_for_stmt(). */
|
|
|
|
|
range_decl = start_decl (declarator, &type_specifiers,
|
|
|
|
|
/*initialized_p=*/SD_INITIALIZED,
|
|
|
|
|
attributes, /*prefix_attributes=*/NULL_TREE,
|
|
|
|
|
&pushed_scope);
|
|
|
|
|
/* No scope allowed here */
|
|
|
|
|
pop_scope (pushed_scope);
|
|
|
|
|
|
|
|
|
|
if (TREE_CODE (stmt) == RANGE_FOR_STMT)
|
|
|
|
|
finish_range_for_decl (stmt, range_decl, range_expr);
|
|
|
|
|
else
|
|
|
|
|
/* Convert the range-based for loop into a normal for-statement. */
|
|
|
|
|
stmt = cp_convert_range_for (stmt, range_decl, range_expr);
|
|
|
|
|
|
|
|
|
|
out:
|
|
|
|
|
parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p;
|
|
|
|
|
{
|
|
|
|
|
stmt = begin_for_stmt (scope, init);
|
|
|
|
|
stmt = cp_convert_range_for (stmt, range_decl, range_expr);
|
|
|
|
|
}
|
|
|
|
|
return stmt;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -8854,63 +8829,71 @@ cp_convert_range_for (tree statement, tree range_decl, tree range_expr)
|
|
|
|
|
tree iter_type, begin_expr, end_expr;
|
|
|
|
|
tree condition, expression;
|
|
|
|
|
|
|
|
|
|
/* Find out the type deduced by the declaration
|
|
|
|
|
* `auto &&__range = range_expr' */
|
|
|
|
|
range_type = cp_build_reference_type (make_auto (), true);
|
|
|
|
|
range_type = do_auto_deduction (range_type, range_expr,
|
|
|
|
|
type_uses_auto (range_type));
|
|
|
|
|
|
|
|
|
|
/* Create the __range variable */
|
|
|
|
|
range_temp = build_decl (input_location, VAR_DECL,
|
|
|
|
|
get_identifier ("__for_range"), range_type);
|
|
|
|
|
TREE_USED (range_temp) = 1;
|
|
|
|
|
DECL_ARTIFICIAL (range_temp) = 1;
|
|
|
|
|
pushdecl (range_temp);
|
|
|
|
|
cp_finish_decl (range_temp, range_expr,
|
|
|
|
|
/*is_constant_init*/false, NULL_TREE,
|
|
|
|
|
LOOKUP_ONLYCONVERTING);
|
|
|
|
|
|
|
|
|
|
range_temp = convert_from_reference (range_temp);
|
|
|
|
|
|
|
|
|
|
if (TREE_CODE (TREE_TYPE (range_temp)) == ARRAY_TYPE)
|
|
|
|
|
{
|
|
|
|
|
/* If RANGE_TEMP is an array we will use pointer arithmetic */
|
|
|
|
|
iter_type = build_pointer_type (TREE_TYPE (TREE_TYPE (range_temp)));
|
|
|
|
|
begin_expr = range_temp;
|
|
|
|
|
end_expr
|
|
|
|
|
= build_binary_op (input_location, PLUS_EXPR,
|
|
|
|
|
range_temp,
|
|
|
|
|
array_type_nelts_top (TREE_TYPE (range_temp)), 0);
|
|
|
|
|
}
|
|
|
|
|
if (range_decl == error_mark_node || range_expr == error_mark_node)
|
|
|
|
|
/* If an error happened previously do nothing or else a lot of
|
|
|
|
|
unhelpful errors would be issued. */
|
|
|
|
|
begin_expr = end_expr = iter_type = error_mark_node;
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* If it is not an array, we must call begin(__range)/end__range() */
|
|
|
|
|
VEC(tree,gc) *vec;
|
|
|
|
|
/* Find out the type deduced by the declaration
|
|
|
|
|
* `auto &&__range = range_expr' */
|
|
|
|
|
range_type = cp_build_reference_type (make_auto (), true);
|
|
|
|
|
range_type = do_auto_deduction (range_type, range_expr,
|
|
|
|
|
type_uses_auto (range_type));
|
|
|
|
|
|
|
|
|
|
begin_expr = get_identifier ("begin");
|
|
|
|
|
vec = make_tree_vector ();
|
|
|
|
|
VEC_safe_push (tree, gc, vec, range_temp);
|
|
|
|
|
begin_expr = perform_koenig_lookup (begin_expr, vec,
|
|
|
|
|
/*include_std=*/true);
|
|
|
|
|
begin_expr = finish_call_expr (begin_expr, &vec, false, true,
|
|
|
|
|
tf_warning_or_error);
|
|
|
|
|
release_tree_vector (vec);
|
|
|
|
|
/* Create the __range variable */
|
|
|
|
|
range_temp = build_decl (input_location, VAR_DECL,
|
|
|
|
|
get_identifier ("__for_range"), range_type);
|
|
|
|
|
TREE_USED (range_temp) = 1;
|
|
|
|
|
DECL_ARTIFICIAL (range_temp) = 1;
|
|
|
|
|
pushdecl (range_temp);
|
|
|
|
|
cp_finish_decl (range_temp, range_expr,
|
|
|
|
|
/*is_constant_init*/false, NULL_TREE,
|
|
|
|
|
LOOKUP_ONLYCONVERTING);
|
|
|
|
|
|
|
|
|
|
end_expr = get_identifier ("end");
|
|
|
|
|
vec = make_tree_vector ();
|
|
|
|
|
VEC_safe_push (tree, gc, vec, range_temp);
|
|
|
|
|
end_expr = perform_koenig_lookup (end_expr, vec,
|
|
|
|
|
/*include_std=*/true);
|
|
|
|
|
end_expr = finish_call_expr (end_expr, &vec, false, true,
|
|
|
|
|
tf_warning_or_error);
|
|
|
|
|
release_tree_vector (vec);
|
|
|
|
|
range_temp = convert_from_reference (range_temp);
|
|
|
|
|
|
|
|
|
|
/* The unqualified type of the __begin and __end temporaries should
|
|
|
|
|
* be the same as required by the multiple auto declaration */
|
|
|
|
|
iter_type = cv_unqualified (TREE_TYPE (begin_expr));
|
|
|
|
|
if (!same_type_p (iter_type, cv_unqualified (TREE_TYPE (end_expr))))
|
|
|
|
|
error ("inconsistent begin/end types in range-based for: %qT and %qT",
|
|
|
|
|
TREE_TYPE (begin_expr), TREE_TYPE (end_expr));
|
|
|
|
|
if (TREE_CODE (TREE_TYPE (range_temp)) == ARRAY_TYPE)
|
|
|
|
|
{
|
|
|
|
|
/* If RANGE_TEMP is an array we will use pointer arithmetic */
|
|
|
|
|
iter_type = build_pointer_type (TREE_TYPE (TREE_TYPE (range_temp)));
|
|
|
|
|
begin_expr = range_temp;
|
|
|
|
|
end_expr
|
|
|
|
|
= build_binary_op (input_location, PLUS_EXPR,
|
|
|
|
|
range_temp,
|
|
|
|
|
array_type_nelts_top (TREE_TYPE (range_temp)),
|
|
|
|
|
0);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* If it is not an array, we must call begin(__range)/end__range() */
|
|
|
|
|
VEC(tree,gc) *vec;
|
|
|
|
|
|
|
|
|
|
begin_expr = get_identifier ("begin");
|
|
|
|
|
vec = make_tree_vector ();
|
|
|
|
|
VEC_safe_push (tree, gc, vec, range_temp);
|
|
|
|
|
begin_expr = perform_koenig_lookup (begin_expr, vec,
|
|
|
|
|
/*include_std=*/true);
|
|
|
|
|
begin_expr = finish_call_expr (begin_expr, &vec, false, true,
|
|
|
|
|
tf_warning_or_error);
|
|
|
|
|
release_tree_vector (vec);
|
|
|
|
|
|
|
|
|
|
end_expr = get_identifier ("end");
|
|
|
|
|
vec = make_tree_vector ();
|
|
|
|
|
VEC_safe_push (tree, gc, vec, range_temp);
|
|
|
|
|
end_expr = perform_koenig_lookup (end_expr, vec,
|
|
|
|
|
/*include_std=*/true);
|
|
|
|
|
end_expr = finish_call_expr (end_expr, &vec, false, true,
|
|
|
|
|
tf_warning_or_error);
|
|
|
|
|
release_tree_vector (vec);
|
|
|
|
|
|
|
|
|
|
/* The unqualified type of the __begin and __end temporaries should
|
|
|
|
|
* be the same as required by the multiple auto declaration */
|
|
|
|
|
iter_type = cv_unqualified (TREE_TYPE (begin_expr));
|
|
|
|
|
if (!same_type_p (iter_type, cv_unqualified (TREE_TYPE (end_expr))))
|
|
|
|
|
error ("inconsistent begin/end types in range-based for: %qT and %qT",
|
|
|
|
|
TREE_TYPE (begin_expr), TREE_TYPE (end_expr));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* The new for initialization statement */
|
|
|
|
@ -9039,12 +9022,7 @@ cp_parser_iteration_statement (cp_parser* parser)
|
|
|
|
|
/* Look for the `('. */
|
|
|
|
|
cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
|
|
|
|
|
|
|
|
|
|
if (cxx_dialect == cxx0x)
|
|
|
|
|
statement = cp_parser_range_for (parser);
|
|
|
|
|
else
|
|
|
|
|
statement = NULL_TREE;
|
|
|
|
|
if (statement == NULL_TREE)
|
|
|
|
|
statement = cp_parser_c_for (parser);
|
|
|
|
|
statement = cp_parser_for (parser);
|
|
|
|
|
|
|
|
|
|
/* Look for the `)'. */
|
|
|
|
|
cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
|
|
|
|
@ -9068,14 +9046,15 @@ cp_parser_iteration_statement (cp_parser* parser)
|
|
|
|
|
return statement;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Parse a for-init-statement.
|
|
|
|
|
/* Parse a for-init-statement or the declarator of a range-based-for.
|
|
|
|
|
Returns true if a range-based-for declaration is seen.
|
|
|
|
|
|
|
|
|
|
for-init-statement:
|
|
|
|
|
expression-statement
|
|
|
|
|
simple-declaration */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
cp_parser_for_init_statement (cp_parser* parser)
|
|
|
|
|
static bool
|
|
|
|
|
cp_parser_for_init_statement (cp_parser* parser, tree *decl)
|
|
|
|
|
{
|
|
|
|
|
/* If the next token is a `;', then we have an empty
|
|
|
|
|
expression-statement. Grammatically, this is also a
|
|
|
|
@ -9085,19 +9064,45 @@ cp_parser_for_init_statement (cp_parser* parser)
|
|
|
|
|
declaration. */
|
|
|
|
|
if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
|
|
|
|
|
{
|
|
|
|
|
bool is_range_for = false;
|
|
|
|
|
bool saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p;
|
|
|
|
|
|
|
|
|
|
parser->colon_corrects_to_scope_p = false;
|
|
|
|
|
|
|
|
|
|
/* We're going to speculatively look for a declaration, falling back
|
|
|
|
|
to an expression, if necessary. */
|
|
|
|
|
cp_parser_parse_tentatively (parser);
|
|
|
|
|
/* Parse the declaration. */
|
|
|
|
|
cp_parser_simple_declaration (parser,
|
|
|
|
|
/*function_definition_allowed_p=*/false);
|
|
|
|
|
/*function_definition_allowed_p=*/false,
|
|
|
|
|
decl);
|
|
|
|
|
parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p;
|
|
|
|
|
if (cp_lexer_next_token_is (parser->lexer, CPP_COLON))
|
|
|
|
|
{
|
|
|
|
|
/* It is a range-for, consume the ':' */
|
|
|
|
|
cp_lexer_consume_token (parser->lexer);
|
|
|
|
|
is_range_for = true;
|
|
|
|
|
if (cxx_dialect < cxx0x)
|
|
|
|
|
{
|
|
|
|
|
error_at (cp_lexer_peek_token (parser->lexer)->location,
|
|
|
|
|
"range-based-for loops are not allowed "
|
|
|
|
|
"in C++98 mode");
|
|
|
|
|
*decl = error_mark_node;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
/* The ';' is not consumed yet because we told
|
|
|
|
|
cp_parser_simple_declaration not to. */
|
|
|
|
|
cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
|
|
|
|
|
|
|
|
|
|
if (cp_parser_parse_definitely (parser))
|
|
|
|
|
return is_range_for;
|
|
|
|
|
/* If the tentative parse failed, then we shall need to look for an
|
|
|
|
|
expression-statement. */
|
|
|
|
|
if (cp_parser_parse_definitely (parser))
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* If we are here, it is an expression-statement. */
|
|
|
|
|
cp_parser_expression_statement (parser, NULL_TREE);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Parse a jump-statement.
|
|
|
|
@ -9584,7 +9589,8 @@ cp_parser_block_declaration (cp_parser *parser,
|
|
|
|
|
cp_parser_static_assert (parser, /*member_p=*/false);
|
|
|
|
|
/* Anything else must be a simple-declaration. */
|
|
|
|
|
else
|
|
|
|
|
cp_parser_simple_declaration (parser, !statement_p);
|
|
|
|
|
cp_parser_simple_declaration (parser, !statement_p,
|
|
|
|
|
/*maybe_range_for_decl*/NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Parse a simple-declaration.
|
|
|
|
@ -9597,16 +9603,25 @@ cp_parser_block_declaration (cp_parser *parser,
|
|
|
|
|
init-declarator-list , init-declarator
|
|
|
|
|
|
|
|
|
|
If FUNCTION_DEFINITION_ALLOWED_P is TRUE, then we also recognize a
|
|
|
|
|
function-definition as a simple-declaration. */
|
|
|
|
|
function-definition as a simple-declaration.
|
|
|
|
|
|
|
|
|
|
If MAYBE_RANGE_FOR_DECL is not NULL, the pointed tree will be set to the
|
|
|
|
|
parsed declaration if it is an uninitialized single declarator not followed
|
|
|
|
|
by a `;', or to error_mark_node otherwise. Either way, the trailing `;',
|
|
|
|
|
if present, will not be consumed. */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
cp_parser_simple_declaration (cp_parser* parser,
|
|
|
|
|
bool function_definition_allowed_p)
|
|
|
|
|
bool function_definition_allowed_p,
|
|
|
|
|
tree *maybe_range_for_decl)
|
|
|
|
|
{
|
|
|
|
|
cp_decl_specifier_seq decl_specifiers;
|
|
|
|
|
int declares_class_or_enum;
|
|
|
|
|
bool saw_declarator;
|
|
|
|
|
|
|
|
|
|
if (maybe_range_for_decl)
|
|
|
|
|
*maybe_range_for_decl = NULL_TREE;
|
|
|
|
|
|
|
|
|
|
/* Defer access checks until we know what is being declared; the
|
|
|
|
|
checks for names appearing in the decl-specifier-seq should be
|
|
|
|
|
done as if we were in the scope of the thing being declared. */
|
|
|
|
@ -9681,6 +9696,8 @@ cp_parser_simple_declaration (cp_parser* parser,
|
|
|
|
|
token = cp_lexer_peek_token (parser->lexer);
|
|
|
|
|
gcc_assert (token->type == CPP_COMMA);
|
|
|
|
|
cp_lexer_consume_token (parser->lexer);
|
|
|
|
|
if (maybe_range_for_decl)
|
|
|
|
|
*maybe_range_for_decl = error_mark_node;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
saw_declarator = true;
|
|
|
|
@ -9691,7 +9708,8 @@ cp_parser_simple_declaration (cp_parser* parser,
|
|
|
|
|
function_definition_allowed_p,
|
|
|
|
|
/*member_p=*/false,
|
|
|
|
|
declares_class_or_enum,
|
|
|
|
|
&function_definition_p);
|
|
|
|
|
&function_definition_p,
|
|
|
|
|
maybe_range_for_decl);
|
|
|
|
|
/* If an error occurred while parsing tentatively, exit quickly.
|
|
|
|
|
(That usually happens when in the body of a function; each
|
|
|
|
|
statement is treated as a declaration-statement until proven
|
|
|
|
@ -9721,13 +9739,15 @@ cp_parser_simple_declaration (cp_parser* parser,
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (maybe_range_for_decl && *maybe_range_for_decl == NULL_TREE)
|
|
|
|
|
*maybe_range_for_decl = decl;
|
|
|
|
|
/* The next token should be either a `,' or a `;'. */
|
|
|
|
|
token = cp_lexer_peek_token (parser->lexer);
|
|
|
|
|
/* If it's a `,', there are more declarators to come. */
|
|
|
|
|
if (token->type == CPP_COMMA)
|
|
|
|
|
/* will be consumed next time around */;
|
|
|
|
|
/* If it's a `;', we are done. */
|
|
|
|
|
else if (token->type == CPP_SEMICOLON)
|
|
|
|
|
else if (token->type == CPP_SEMICOLON || maybe_range_for_decl)
|
|
|
|
|
break;
|
|
|
|
|
/* Anything else is an error. */
|
|
|
|
|
else
|
|
|
|
@ -9765,7 +9785,8 @@ cp_parser_simple_declaration (cp_parser* parser,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Consume the `;'. */
|
|
|
|
|
cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
|
|
|
|
|
if (!maybe_range_for_decl)
|
|
|
|
|
cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
|
|
|
|
|
|
|
|
|
|
done:
|
|
|
|
|
pop_deferring_access_checks ();
|
|
|
|
@ -14378,7 +14399,13 @@ cp_parser_asm_definition (cp_parser* parser)
|
|
|
|
|
have been completely parsed.
|
|
|
|
|
|
|
|
|
|
FUNCTION_DEFINITION_P may be NULL if FUNCTION_DEFINITION_ALLOWED_P
|
|
|
|
|
is FALSE. */
|
|
|
|
|
is FALSE.
|
|
|
|
|
|
|
|
|
|
If MAYBE_RANGE_FOR_DECL is not NULL, the pointed tree will be set to the
|
|
|
|
|
parsed declaration if it is an uninitialized single declarator not followed
|
|
|
|
|
by a `;', or to error_mark_node otherwise. Either way, the trailing `;',
|
|
|
|
|
if present, will not be consumed. If returned, this declarator will be
|
|
|
|
|
created with SD_INITIALIZED but will not call cp_finish_decl. */
|
|
|
|
|
|
|
|
|
|
static tree
|
|
|
|
|
cp_parser_init_declarator (cp_parser* parser,
|
|
|
|
@ -14387,7 +14414,8 @@ cp_parser_init_declarator (cp_parser* parser,
|
|
|
|
|
bool function_definition_allowed_p,
|
|
|
|
|
bool member_p,
|
|
|
|
|
int declares_class_or_enum,
|
|
|
|
|
bool* function_definition_p)
|
|
|
|
|
bool* function_definition_p,
|
|
|
|
|
tree* maybe_range_for_decl)
|
|
|
|
|
{
|
|
|
|
|
cp_token *token = NULL, *asm_spec_start_token = NULL,
|
|
|
|
|
*attributes_start_token = NULL;
|
|
|
|
@ -14408,6 +14436,7 @@ cp_parser_init_declarator (cp_parser* parser,
|
|
|
|
|
int ctor_dtor_or_conv_p;
|
|
|
|
|
bool friend_p;
|
|
|
|
|
tree pushed_scope = NULL;
|
|
|
|
|
bool range_for_decl_p = false;
|
|
|
|
|
|
|
|
|
|
/* Gather the attributes that were provided with the
|
|
|
|
|
decl-specifiers. */
|
|
|
|
@ -14551,6 +14580,8 @@ cp_parser_init_declarator (cp_parser* parser,
|
|
|
|
|
{
|
|
|
|
|
is_initialized = SD_INITIALIZED;
|
|
|
|
|
initialization_kind = token->type;
|
|
|
|
|
if (maybe_range_for_decl)
|
|
|
|
|
*maybe_range_for_decl = error_mark_node;
|
|
|
|
|
|
|
|
|
|
if (token->type == CPP_EQ
|
|
|
|
|
&& function_declarator_p (declarator))
|
|
|
|
@ -14569,8 +14600,13 @@ cp_parser_init_declarator (cp_parser* parser,
|
|
|
|
|
if (token->type != CPP_COMMA
|
|
|
|
|
&& token->type != CPP_SEMICOLON)
|
|
|
|
|
{
|
|
|
|
|
cp_parser_error (parser, "expected initializer");
|
|
|
|
|
return error_mark_node;
|
|
|
|
|
if (maybe_range_for_decl && *maybe_range_for_decl != error_mark_node)
|
|
|
|
|
range_for_decl_p = true;
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
cp_parser_error (parser, "expected initializer");
|
|
|
|
|
return error_mark_node;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
is_initialized = SD_UNINITIALIZED;
|
|
|
|
|
initialization_kind = CPP_EOF;
|
|
|
|
@ -14603,7 +14639,8 @@ cp_parser_init_declarator (cp_parser* parser,
|
|
|
|
|
if (parser->in_unbraced_linkage_specification_p)
|
|
|
|
|
decl_specifiers->storage_class = sc_extern;
|
|
|
|
|
decl = start_decl (declarator, decl_specifiers,
|
|
|
|
|
is_initialized, attributes, prefix_attributes,
|
|
|
|
|
range_for_decl_p? SD_INITIALIZED : is_initialized,
|
|
|
|
|
attributes, prefix_attributes,
|
|
|
|
|
&pushed_scope);
|
|
|
|
|
/* Adjust location of decl if declarator->id_loc is more appropriate:
|
|
|
|
|
set, and decl wasn't merged with another decl, in which case its
|
|
|
|
@ -14717,7 +14754,7 @@ cp_parser_init_declarator (cp_parser* parser,
|
|
|
|
|
|
|
|
|
|
/* Finish processing the declaration. But, skip friend
|
|
|
|
|
declarations. */
|
|
|
|
|
if (!friend_p && decl && decl != error_mark_node)
|
|
|
|
|
if (!friend_p && decl && decl != error_mark_node && !range_for_decl_p)
|
|
|
|
|
{
|
|
|
|
|
cp_finish_decl (decl,
|
|
|
|
|
initializer, !is_non_constant_init,
|
|
|
|
@ -20071,7 +20108,8 @@ cp_parser_single_declaration (cp_parser* parser,
|
|
|
|
|
/*function_definition_allowed_p=*/true,
|
|
|
|
|
member_p,
|
|
|
|
|
declares_class_or_enum,
|
|
|
|
|
&function_definition_p);
|
|
|
|
|
&function_definition_p,
|
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
|
|
/* 7.1.1-1 [dcl.stc]
|
|
|
|
|
|
|
|
|
|