Commit 36e87c23 by Paolo Carlini Committed by Paolo Carlini

re PR c++/63985 (Accepts invalid range-based for declaration)

/cp
2014-12-04  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/63985
	* parser.c (cp_parser_for_init_statement): Reject invalid declarations
	in range-based for loops.

/testsuite
2014-12-04  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/63985
	* g++.dg/cpp0x/range-for29.C: New.

From-SVN: r219054
parent 03267abb
2014-12-24 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/63985
* parser.c (cp_parser_init_declarator): Add location_t* parameter.
(cp_parser_simple_declaration): Provide proper diagnostic for
multiple declarations and initializers in range-based for loops.
(cp_parser_single_declaration): Adjust call.
2014-12-20 Jason Merrill <jason@redhat.com> 2014-12-20 Jason Merrill <jason@redhat.com>
PR c++/64359 PR c++/64359
......
...@@ -2124,7 +2124,8 @@ static tree cp_parser_decltype ...@@ -2124,7 +2124,8 @@ static tree cp_parser_decltype
/* Declarators [gram.dcl.decl] */ /* Declarators [gram.dcl.decl] */
static tree cp_parser_init_declarator static tree cp_parser_init_declarator
(cp_parser *, cp_decl_specifier_seq *, vec<deferred_access_check, va_gc> *, bool, bool, int, bool *, tree *); (cp_parser *, cp_decl_specifier_seq *, vec<deferred_access_check, va_gc> *,
bool, bool, int, bool *, tree *, location_t *);
static cp_declarator *cp_parser_declarator static cp_declarator *cp_parser_declarator
(cp_parser *, cp_parser_declarator_kind, int *, bool *, bool, bool); (cp_parser *, cp_parser_declarator_kind, int *, bool *, bool, bool);
static cp_declarator *cp_parser_direct_declarator static cp_declarator *cp_parser_direct_declarator
...@@ -11454,6 +11455,8 @@ cp_parser_simple_declaration (cp_parser* parser, ...@@ -11454,6 +11455,8 @@ cp_parser_simple_declaration (cp_parser* parser,
cp_decl_specifier_seq decl_specifiers; cp_decl_specifier_seq decl_specifiers;
int declares_class_or_enum; int declares_class_or_enum;
bool saw_declarator; bool saw_declarator;
location_t comma_loc = UNKNOWN_LOCATION;
location_t init_loc = UNKNOWN_LOCATION;
if (maybe_range_for_decl) if (maybe_range_for_decl)
*maybe_range_for_decl = NULL_TREE; *maybe_range_for_decl = NULL_TREE;
...@@ -11528,12 +11531,16 @@ cp_parser_simple_declaration (cp_parser* parser, ...@@ -11528,12 +11531,16 @@ cp_parser_simple_declaration (cp_parser* parser,
if (saw_declarator) if (saw_declarator)
{ {
/* If we are processing next declarator, coma is expected */ /* If we are processing next declarator, comma is expected */
token = cp_lexer_peek_token (parser->lexer); token = cp_lexer_peek_token (parser->lexer);
gcc_assert (token->type == CPP_COMMA); gcc_assert (token->type == CPP_COMMA);
cp_lexer_consume_token (parser->lexer); cp_lexer_consume_token (parser->lexer);
if (maybe_range_for_decl) if (maybe_range_for_decl)
*maybe_range_for_decl = error_mark_node; {
*maybe_range_for_decl = error_mark_node;
if (comma_loc == UNKNOWN_LOCATION)
comma_loc = token->location;
}
} }
else else
saw_declarator = true; saw_declarator = true;
...@@ -11545,7 +11552,8 @@ cp_parser_simple_declaration (cp_parser* parser, ...@@ -11545,7 +11552,8 @@ cp_parser_simple_declaration (cp_parser* parser,
/*member_p=*/false, /*member_p=*/false,
declares_class_or_enum, declares_class_or_enum,
&function_definition_p, &function_definition_p,
maybe_range_for_decl); maybe_range_for_decl,
&init_loc);
/* If an error occurred while parsing tentatively, exit quickly. /* If an error occurred while parsing tentatively, exit quickly.
(That usually happens when in the body of a function; each (That usually happens when in the body of a function; each
statement is treated as a declaration-statement until proven statement is treated as a declaration-statement until proven
...@@ -11631,7 +11639,15 @@ cp_parser_simple_declaration (cp_parser* parser, ...@@ -11631,7 +11639,15 @@ cp_parser_simple_declaration (cp_parser* parser,
/* Consume the `;'. */ /* Consume the `;'. */
if (!maybe_range_for_decl) if (!maybe_range_for_decl)
cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON); cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
else if (cp_lexer_next_token_is (parser->lexer, CPP_COLON))
{
if (init_loc != UNKNOWN_LOCATION)
error_at (init_loc, "initializer in range-based %<for%> loop");
if (comma_loc != UNKNOWN_LOCATION)
error_at (comma_loc,
"multiple declarations in range-based %<for%> loop");
}
done: done:
pop_deferring_access_checks (); pop_deferring_access_checks ();
...@@ -16842,7 +16858,12 @@ cp_parser_asm_definition (cp_parser* parser) ...@@ -16842,7 +16858,12 @@ cp_parser_asm_definition (cp_parser* parser)
parsed declaration if it is an uninitialized single declarator not followed parsed declaration if it is an uninitialized single declarator not followed
by a `;', or to error_mark_node otherwise. Either way, the trailing `;', by a `;', or to error_mark_node otherwise. Either way, the trailing `;',
if present, will not be consumed. If returned, this declarator will be if present, will not be consumed. If returned, this declarator will be
created with SD_INITIALIZED but will not call cp_finish_decl. */ created with SD_INITIALIZED but will not call cp_finish_decl.
If INIT_LOC is not NULL, and *INIT_LOC is equal to UNKNOWN_LOCATION,
and there is an initializer, the pointed location_t is set to the
location of the '=' or `(', or '{' in C++11 token introducing the
initializer. */
static tree static tree
cp_parser_init_declarator (cp_parser* parser, cp_parser_init_declarator (cp_parser* parser,
...@@ -16852,7 +16873,8 @@ cp_parser_init_declarator (cp_parser* parser, ...@@ -16852,7 +16873,8 @@ cp_parser_init_declarator (cp_parser* parser,
bool member_p, bool member_p,
int declares_class_or_enum, int declares_class_or_enum,
bool* function_definition_p, bool* function_definition_p,
tree* maybe_range_for_decl) tree* maybe_range_for_decl,
location_t* init_loc)
{ {
cp_token *token = NULL, *asm_spec_start_token = NULL, cp_token *token = NULL, *asm_spec_start_token = NULL,
*attributes_start_token = NULL; *attributes_start_token = NULL;
...@@ -16875,6 +16897,7 @@ cp_parser_init_declarator (cp_parser* parser, ...@@ -16875,6 +16897,7 @@ cp_parser_init_declarator (cp_parser* parser,
tree pushed_scope = NULL_TREE; tree pushed_scope = NULL_TREE;
bool range_for_decl_p = false; bool range_for_decl_p = false;
bool saved_default_arg_ok_p = parser->default_arg_ok_p; bool saved_default_arg_ok_p = parser->default_arg_ok_p;
location_t tmp_init_loc = UNKNOWN_LOCATION;
/* Gather the attributes that were provided with the /* Gather the attributes that were provided with the
decl-specifiers. */ decl-specifiers. */
...@@ -17041,6 +17064,9 @@ cp_parser_init_declarator (cp_parser* parser, ...@@ -17041,6 +17064,9 @@ cp_parser_init_declarator (cp_parser* parser,
initialization_kind = token->type; initialization_kind = token->type;
if (maybe_range_for_decl) if (maybe_range_for_decl)
*maybe_range_for_decl = error_mark_node; *maybe_range_for_decl = error_mark_node;
tmp_init_loc = token->location;
if (init_loc && *init_loc == UNKNOWN_LOCATION)
*init_loc = tmp_init_loc;
if (token->type == CPP_EQ if (token->type == CPP_EQ
&& function_declarator_p (declarator)) && function_declarator_p (declarator))
...@@ -17063,7 +17089,8 @@ cp_parser_init_declarator (cp_parser* parser, ...@@ -17063,7 +17089,8 @@ cp_parser_init_declarator (cp_parser* parser,
range_for_decl_p = true; range_for_decl_p = true;
else else
{ {
cp_parser_error (parser, "expected initializer"); if (!maybe_range_for_decl)
cp_parser_error (parser, "expected initializer");
return error_mark_node; return error_mark_node;
} }
} }
...@@ -17135,7 +17162,6 @@ cp_parser_init_declarator (cp_parser* parser, ...@@ -17135,7 +17162,6 @@ cp_parser_init_declarator (cp_parser* parser,
{ {
if (function_declarator_p (declarator)) if (function_declarator_p (declarator))
{ {
cp_token *initializer_start_token = cp_lexer_peek_token (parser->lexer);
if (initialization_kind == CPP_EQ) if (initialization_kind == CPP_EQ)
initializer = cp_parser_pure_specifier (parser); initializer = cp_parser_pure_specifier (parser);
else else
...@@ -17144,8 +17170,7 @@ cp_parser_init_declarator (cp_parser* parser, ...@@ -17144,8 +17170,7 @@ cp_parser_init_declarator (cp_parser* parser,
know what the user intended, so just silently know what the user intended, so just silently
consume the initializer. */ consume the initializer. */
if (decl != error_mark_node) if (decl != error_mark_node)
error_at (initializer_start_token->location, error_at (tmp_init_loc, "initializer provided for function");
"initializer provided for function");
cp_parser_skip_to_closing_parenthesis (parser, cp_parser_skip_to_closing_parenthesis (parser,
/*recovering=*/true, /*recovering=*/true,
/*or_comma=*/false, /*or_comma=*/false,
...@@ -23726,7 +23751,7 @@ cp_parser_single_declaration (cp_parser* parser, ...@@ -23726,7 +23751,7 @@ cp_parser_single_declaration (cp_parser* parser,
member_p, member_p,
declares_class_or_enum, declares_class_or_enum,
&function_definition_p, &function_definition_p,
NULL); NULL, NULL);
/* 7.1.1-1 [dcl.stc] /* 7.1.1-1 [dcl.stc]
......
2014-12-24 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/63985
* g++.dg/cpp0x/range-for29.C: New.
2014-12-22 John David Anglin <danglin@gcc.gnu.org> 2014-12-22 John David Anglin <danglin@gcc.gnu.org>
* gcc.dg/pr55023.c: New file. * gcc.dg/pr55023.c: New file.
......
// PR c++/63985
// { dg-require-effective-target c++11 }
void foo()
{
int arr;
for (int i = 5: arr) // { dg-error "initializer in range-based" }
;
for (int i, j: arr) // { dg-error "multiple declarations in range-based" }
;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment