diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 12 | ||||
-rw-r--r-- | gcc/cp/decl.c | 12 | ||||
-rw-r--r-- | gcc/cp/parser.c | 61 |
3 files changed, 66 insertions, 19 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 647bcd0..d8c54b0 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,17 @@ 2003-11-12 Mark Mitchell <mark@codesourcery.com> + * decl.c (finish_case_label): Do not check that we are within a + switch statement here. + * parser.c (struct cp_parser): Add in_iteration_statement_p and + in_switch_statement_p. + (cp_parser_new): Initialize them. + (cp_parser_labeled_statement): Check validity of case labels + here. + (cp_parser_selection_statement): Set in_switch_statement_p. + (cp_parser_iteration_statement): Set in_iteration_statement_p. + (cp_parser_jump_statement): Check validity of break/continue + statements here. + PR c++/12735 * cp-tree.h (duplicate_decls): Return a tree. * decl.c (duplicate_decls): Clarify documentation. Return diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 3894c7a..b1fd4f7 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -2433,18 +2433,6 @@ finish_case_label (tree low_value, tree high_value) tree cond, r; register struct cp_binding_level *p; - if (! switch_stack) - { - if (high_value) - error ("case label not within a switch statement"); - else if (low_value) - error ("case label `%E' not within a switch statement", - low_value); - else - error ("`default' label not within a switch statement"); - return NULL_TREE; - } - if (processing_template_decl) { tree label; diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index d08588f..5e24fd5 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -1230,6 +1230,14 @@ typedef struct cp_parser GTY(()) direct-declarator. */ bool in_declarator_p; + /* TRUE if we are presently parsing the body of an + iteration-statement. */ + bool in_iteration_statement_p; + + /* TRUE if we are presently parsing the body of a switch + statement. */ + bool in_switch_statement_p; + /* If non-NULL, then we are parsing a construct where new type definitions are not permitted. The string stored here will be issued as an error message if a type is defined. */ @@ -2118,6 +2126,12 @@ cp_parser_new (void) /* We are not processing a declarator. */ parser->in_declarator_p = false; + /* We are not in an iteration statement. */ + parser->in_iteration_statement_p = false; + + /* We are not in a switch statement. */ + parser->in_switch_statement_p = false; + /* The unparsed function queue is empty. */ parser->unparsed_functions_queues = build_tree_list (NULL_TREE, NULL_TREE); @@ -5228,7 +5242,7 @@ static tree cp_parser_labeled_statement (cp_parser* parser, bool in_statement_expr_p) { cp_token *token; - tree statement = NULL_TREE; + tree statement = error_mark_node; /* The next token should be an identifier. */ token = cp_lexer_peek_token (parser->lexer); @@ -5251,16 +5265,20 @@ cp_parser_labeled_statement (cp_parser* parser, bool in_statement_expr_p) expr = cp_parser_constant_expression (parser, /*allow_non_constant_p=*/false, NULL); - /* Create the label. */ - statement = finish_case_label (expr, NULL_TREE); + if (!parser->in_switch_statement_p) + error ("case label `%E' not within a switch statement", expr); + else + statement = finish_case_label (expr, NULL_TREE); } break; case RID_DEFAULT: /* Consume the `default' token. */ cp_lexer_consume_token (parser->lexer); - /* Create the label. */ - statement = finish_case_label (NULL_TREE, NULL_TREE); + if (!parser->in_switch_statement_p) + error ("case label not within a switch statement"); + else + statement = finish_case_label (NULL_TREE, NULL_TREE); break; default: @@ -5443,12 +5461,16 @@ cp_parser_selection_statement (cp_parser* parser) else { tree body; + bool in_switch_statement_p; /* Add the condition. */ finish_switch_cond (condition, statement); /* Parse the body of the switch-statement. */ + in_switch_statement_p = parser->in_switch_statement_p; + parser->in_switch_statement_p = true; body = cp_parser_implicitly_scoped_statement (parser); + parser->in_switch_statement_p = in_switch_statement_p; /* Now we're all done with the switch-statement. */ finish_switch_stmt (statement); @@ -5564,12 +5586,18 @@ cp_parser_iteration_statement (cp_parser* parser) cp_token *token; enum rid keyword; tree statement; + bool in_iteration_statement_p; + /* Peek at the next token. */ token = cp_parser_require (parser, CPP_KEYWORD, "iteration-statement"); if (!token) return error_mark_node; + /* Remember whether or not we are already within an iteration + statement. */ + in_iteration_statement_p = parser->in_iteration_statement_p; + /* See what kind of keyword it is. */ keyword = token->keyword; switch (keyword) @@ -5588,7 +5616,9 @@ cp_parser_iteration_statement (cp_parser* parser) /* Look for the `)'. */ cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"); /* Parse the dependent statement. */ + parser->in_iteration_statement_p = true; cp_parser_already_scoped_statement (parser); + parser->in_iteration_statement_p = in_iteration_statement_p; /* We're done with the while-statement. */ finish_while_stmt (statement); } @@ -5601,7 +5631,9 @@ cp_parser_iteration_statement (cp_parser* parser) /* Begin the do-statement. */ statement = begin_do_stmt (); /* Parse the body of the do-statement. */ + parser->in_iteration_statement_p = true; cp_parser_implicitly_scoped_statement (parser); + parser->in_iteration_statement_p = in_iteration_statement_p; finish_do_body (statement); /* Look for the `while' keyword. */ cp_parser_require_keyword (parser, RID_WHILE, "`while'"); @@ -5646,7 +5678,9 @@ cp_parser_iteration_statement (cp_parser* parser) cp_parser_require (parser, CPP_CLOSE_PAREN, "`;'"); /* Parse the body of the for-statement. */ + parser->in_iteration_statement_p = true; cp_parser_already_scoped_statement (parser); + parser->in_iteration_statement_p = in_iteration_statement_p; /* We're done with the for-statement. */ finish_for_stmt (statement); @@ -5727,12 +5761,25 @@ cp_parser_jump_statement (cp_parser* parser) switch (keyword) { case RID_BREAK: - statement = finish_break_stmt (); + if (!parser->in_switch_statement_p + && !parser->in_iteration_statement_p) + { + error ("break statement not within loop or switch"); + statement = error_mark_node; + } + else + statement = finish_break_stmt (); cp_parser_require (parser, CPP_SEMICOLON, "`;'"); break; case RID_CONTINUE: - statement = finish_continue_stmt (); + if (!parser->in_iteration_statement_p) + { + error ("continue statement not within a loop"); + statement = error_mark_node; + } + else + statement = finish_continue_stmt (); cp_parser_require (parser, CPP_SEMICOLON, "`;'"); break; |