diff options
author | Sandra Loosemore <sandra@codesourcery.com> | 2020-09-19 07:32:35 -0700 |
---|---|---|
committer | Sandra Loosemore <sandra@codesourcery.com> | 2020-09-19 13:54:16 -0700 |
commit | 3696a50beeb73f4ded8a584e76ee16f0bde109b9 (patch) | |
tree | 547aae764865eb453ea15100d01ddd72cae15773 /gcc/c/c-parser.c | |
parent | a85e5696a31cac8c14dde14f031e76480205f8a0 (diff) | |
download | gcc-3696a50beeb73f4ded8a584e76ee16f0bde109b9.zip gcc-3696a50beeb73f4ded8a584e76ee16f0bde109b9.tar.gz gcc-3696a50beeb73f4ded8a584e76ee16f0bde109b9.tar.bz2 |
Change C front end to emit structured loop and switch tree nodes.
2020-08-12 Sandra Loosemore <sandra@codesourcery.com>
gcc/c
* c-decl.c (c_break_label, c_cont_label): Delete, and replace
with...
(in_statement): New.
(start_function): Adjust for above change.
(c_push_function_context, c_pop_function_context): Likewise.
* c-lang.h (struct language_function): Likewise.
* c-objc-common.h (LANG_HOOKS_BLOCK_MAY_FALLTHRU): Define.
* c-parser.c (objc_foreach_break_label, objc_foreach_continue_label):
New.
(c_parser_statement_after_labels): Adjust calls to c_finish_bc_stmt.
(c_parser_switch_statement): Adjust break/switch context handling
and calls to renamed functions.
(c_parser_while_statement): Adjust break/switch context handling and
build a WHILE_STMT.
(c_parser_do_statement): Ditto, with DO_STMT respectively.
(c_parser_for_statement): Ditto, with FOR_STMT respectively.
(c_parser_omp_for_loop): Adjust break/switch context handling.
* c-tree.h (c_break_label, c_cont_label): Delete.
(IN_SWITCH_STMT, IN_ITERATION_STMT): Define.
(IN_OMP_BLOCK, IN_OMP_FOR, IN_OBJC_FOREACH): Define.
(in_statement, switch_statement_break_seen_p): Declare.
(c_start_case, c_finish_case): Renamed to...
(c_start_switch, c_finish_switch).
(c_finish_bc_stmt): Adjust arguments.
* c-typeck.c (build_function_call_vec): Don't try to print
statements with %qE format.
(struct c_switch): Rename switch_expr field to switch_stmt.
Add break_stmt_seen_p field.
(c_start_case): Rename to c_start_switch. Build a SWITCH_STMT
instead of a SWITCH_EXPR. Update for changes to struct c_switch.
(do_case): Update for changes to struct c_switch.
(c_finish_case): Rename to c_finish_switch. Update for changes to
struct c_switch and change of representation from SWITCH_EXPR to
SWITCH_STMT.
(c_finish_loop): Delete.
(c_finish_bc_stmt): Update to reflect changes to break/continue
state representation. Build a BREAK_STMT or CONTINUE_STMT instead
of a GOTO_EXPR except for objc foreach loops.
gcc/objc
* objc-act.c (objc_start_method_definition): Update to reflect
changes to break/continue state bookkeeping in C front end.
gcc/testsuite/
* gcc.dg/gomp/block-7.c: Update expected error message wording.
Diffstat (limited to 'gcc/c/c-parser.c')
-rw-r--r-- | gcc/c/c-parser.c | 125 |
1 files changed, 60 insertions, 65 deletions
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c index a8bc301..2e6775a 100644 --- a/gcc/c/c-parser.c +++ b/gcc/c/c-parser.c @@ -1479,6 +1479,9 @@ struct oacc_routine_data { location_t loc; }; +/* Used for parsing objc foreach statements. */ +static tree objc_foreach_break_label, objc_foreach_continue_label; + static bool c_parser_nth_token_starts_std_attributes (c_parser *, unsigned int); static tree c_parser_std_attribute_specifier_sequence (c_parser *); @@ -6221,11 +6224,11 @@ c_parser_statement_after_labels (c_parser *parser, bool *if_p, goto expect_semicolon; case RID_CONTINUE: c_parser_consume_token (parser); - stmt = c_finish_bc_stmt (loc, &c_cont_label, false); + stmt = c_finish_bc_stmt (loc, objc_foreach_continue_label, false); goto expect_semicolon; case RID_BREAK: c_parser_consume_token (parser); - stmt = c_finish_bc_stmt (loc, &c_break_label, true); + stmt = c_finish_bc_stmt (loc, objc_foreach_break_label, true); goto expect_semicolon; case RID_RETURN: c_parser_consume_token (parser); @@ -6627,7 +6630,8 @@ static void c_parser_switch_statement (c_parser *parser, bool *if_p) { struct c_expr ce; - tree block, expr, body, save_break; + tree block, expr, body; + unsigned char save_in_statement; location_t switch_loc = c_parser_peek_token (parser)->location; location_t switch_cond_loc; gcc_assert (c_parser_next_token_is_keyword (parser, RID_SWITCH)); @@ -6653,9 +6657,9 @@ c_parser_switch_statement (c_parser *parser, bool *if_p) expr = error_mark_node; ce.original_type = error_mark_node; } - c_start_case (switch_loc, switch_cond_loc, expr, explicit_cast_p); - save_break = c_break_label; - c_break_label = NULL_TREE; + c_start_switch (switch_loc, switch_cond_loc, expr, explicit_cast_p); + save_in_statement = in_statement; + in_statement |= IN_SWITCH_STMT; location_t loc_after_labels; bool open_brace_p = c_parser_peek_token (parser)->type == CPP_OPEN_BRACE; body = c_parser_c99_block_statement (parser, if_p, &loc_after_labels); @@ -6663,16 +6667,8 @@ c_parser_switch_statement (c_parser *parser, bool *if_p) if (!open_brace_p && c_parser_peek_token (parser)->type != CPP_SEMICOLON) warn_for_multistatement_macros (loc_after_labels, next_loc, switch_loc, RID_SWITCH); - if (c_break_label) - { - location_t here = c_parser_peek_token (parser)->location; - tree t = build1 (LABEL_EXPR, void_type_node, c_break_label); - SET_EXPR_LOCATION (t, here); - SWITCH_BREAK_LABEL_P (c_break_label) = 1; - append_to_statement_list_force (t, &body); - } - c_finish_case (body, ce.original_type); - c_break_label = save_break; + c_finish_switch (body, ce.original_type); + in_statement = save_in_statement; add_stmt (c_end_compound_stmt (switch_loc, block, flag_isoc99)); c_parser_maybe_reclassify_token (parser); } @@ -6690,7 +6686,8 @@ static void c_parser_while_statement (c_parser *parser, bool ivdep, unsigned short unroll, bool *if_p) { - tree block, cond, body, save_break, save_cont; + tree block, cond, body; + unsigned char save_in_statement; location_t loc; gcc_assert (c_parser_next_token_is_keyword (parser, RID_WHILE)); token_indent_info while_tinfo @@ -6709,10 +6706,8 @@ c_parser_while_statement (c_parser *parser, bool ivdep, unsigned short unroll, build_int_cst (integer_type_node, annot_expr_unroll_kind), build_int_cst (integer_type_node, unroll)); - save_break = c_break_label; - c_break_label = NULL_TREE; - save_cont = c_cont_label; - c_cont_label = NULL_TREE; + save_in_statement = in_statement; + in_statement = IN_ITERATION_STMT; token_indent_info body_tinfo = get_token_indent_info (c_parser_peek_token (parser)); @@ -6720,8 +6715,7 @@ c_parser_while_statement (c_parser *parser, bool ivdep, unsigned short unroll, location_t loc_after_labels; bool open_brace = c_parser_next_token_is (parser, CPP_OPEN_BRACE); body = c_parser_c99_block_statement (parser, if_p, &loc_after_labels); - c_finish_loop (loc, loc, cond, UNKNOWN_LOCATION, NULL, body, - c_break_label, c_cont_label, true); + add_stmt (build_stmt (loc, WHILE_STMT, cond, body)); add_stmt (c_end_compound_stmt (loc, block, flag_isoc99)); c_parser_maybe_reclassify_token (parser); @@ -6733,8 +6727,7 @@ c_parser_while_statement (c_parser *parser, bool ivdep, unsigned short unroll, warn_for_multistatement_macros (loc_after_labels, next_tinfo.location, while_tinfo.location, RID_WHILE); - c_break_label = save_break; - c_cont_label = save_cont; + in_statement = save_in_statement; } /* Parse a do statement (C90 6.6.5, C99 6.8.5, C11 6.8.5). @@ -6746,7 +6739,8 @@ c_parser_while_statement (c_parser *parser, bool ivdep, unsigned short unroll, static void c_parser_do_statement (c_parser *parser, bool ivdep, unsigned short unroll) { - tree block, cond, body, save_break, save_cont, new_break, new_cont; + tree block, cond, body; + unsigned char save_in_statement; location_t loc; gcc_assert (c_parser_next_token_is_keyword (parser, RID_DO)); c_parser_consume_token (parser); @@ -6756,17 +6750,11 @@ c_parser_do_statement (c_parser *parser, bool ivdep, unsigned short unroll) "suggest braces around empty body in %<do%> statement"); block = c_begin_compound_stmt (flag_isoc99); loc = c_parser_peek_token (parser)->location; - save_break = c_break_label; - c_break_label = NULL_TREE; - save_cont = c_cont_label; - c_cont_label = NULL_TREE; + save_in_statement = in_statement; + in_statement = IN_ITERATION_STMT; body = c_parser_c99_block_statement (parser, NULL); c_parser_require_keyword (parser, RID_WHILE, "expected %<while%>"); - new_break = c_break_label; - c_break_label = save_break; - new_cont = c_cont_label; - c_cont_label = save_cont; - location_t cond_loc = c_parser_peek_token (parser)->location; + in_statement = save_in_statement; cond = c_parser_paren_condition (parser); if (ivdep && cond != error_mark_node) cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond, @@ -6780,8 +6768,8 @@ c_parser_do_statement (c_parser *parser, bool ivdep, unsigned short unroll) build_int_cst (integer_type_node, unroll)); if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>")) c_parser_skip_to_end_of_block_or_statement (parser); - c_finish_loop (loc, cond_loc, cond, UNKNOWN_LOCATION, NULL, body, - new_break, new_cont, false); + + add_stmt (build_stmt (loc, DO_STMT, cond, body)); add_stmt (c_end_compound_stmt (loc, block, flag_isoc99)); } @@ -6848,15 +6836,15 @@ static void c_parser_for_statement (c_parser *parser, bool ivdep, unsigned short unroll, bool *if_p) { - tree block, cond, incr, save_break, save_cont, body; + tree block, cond, incr, body; + unsigned char save_in_statement; + tree save_objc_foreach_break_label, save_objc_foreach_continue_label; /* The following are only used when parsing an ObjC foreach statement. */ tree object_expression; /* Silence the bogus uninitialized warning. */ tree collection_expression = NULL; location_t loc = c_parser_peek_token (parser)->location; location_t for_loc = loc; - location_t cond_loc = UNKNOWN_LOCATION; - location_t incr_loc = UNKNOWN_LOCATION; bool is_foreach_statement = false; gcc_assert (c_parser_next_token_is_keyword (parser, RID_FOR)); token_indent_info for_tinfo @@ -6966,7 +6954,6 @@ c_parser_for_statement (c_parser *parser, bool ivdep, unsigned short unroll, gcc_assert (!parser->objc_could_be_foreach_context); if (!is_foreach_statement) { - cond_loc = c_parser_peek_token (parser)->location; if (c_parser_next_token_is (parser, CPP_SEMICOLON)) { if (ivdep) @@ -7007,7 +6994,7 @@ c_parser_for_statement (c_parser *parser, bool ivdep, unsigned short unroll, /* Parse the increment expression (the third expression in a for-statement). In the case of a foreach-statement, this is the expression that follows the 'in'. */ - loc = incr_loc = c_parser_peek_token (parser)->location; + loc = c_parser_peek_token (parser)->location; if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) { if (is_foreach_statement) @@ -7033,10 +7020,17 @@ c_parser_for_statement (c_parser *parser, bool ivdep, unsigned short unroll, } parens.skip_until_found_close (parser); } - save_break = c_break_label; - c_break_label = NULL_TREE; - save_cont = c_cont_label; - c_cont_label = NULL_TREE; + save_in_statement = in_statement; + if (is_foreach_statement) + { + in_statement = IN_OBJC_FOREACH; + save_objc_foreach_break_label = objc_foreach_break_label; + save_objc_foreach_continue_label = objc_foreach_continue_label; + objc_foreach_break_label = create_artificial_label (loc); + objc_foreach_continue_label = create_artificial_label (loc); + } + else + in_statement = IN_ITERATION_STMT; token_indent_info body_tinfo = get_token_indent_info (c_parser_peek_token (parser)); @@ -7047,11 +7041,12 @@ c_parser_for_statement (c_parser *parser, bool ivdep, unsigned short unroll, if (is_foreach_statement) objc_finish_foreach_loop (for_loc, object_expression, - collection_expression, body, c_break_label, - c_cont_label); + collection_expression, body, + objc_foreach_break_label, + objc_foreach_continue_label); else - c_finish_loop (for_loc, cond_loc, cond, incr_loc, incr, body, - c_break_label, c_cont_label, true); + add_stmt (build_stmt (for_loc, FOR_STMT, NULL_TREE, cond, incr, + body, NULL_TREE)); add_stmt (c_end_compound_stmt (for_loc, block, flag_isoc99 || c_dialect_objc ())); c_parser_maybe_reclassify_token (parser); @@ -7064,8 +7059,12 @@ c_parser_for_statement (c_parser *parser, bool ivdep, unsigned short unroll, warn_for_multistatement_macros (loc_after_labels, next_tinfo.location, for_tinfo.location, RID_FOR); - c_break_label = save_break; - c_cont_label = save_cont; + in_statement = save_in_statement; + if (is_foreach_statement) + { + objc_foreach_break_label = save_objc_foreach_break_label; + objc_foreach_continue_label = save_objc_foreach_continue_label; + } } /* Parse an asm statement, a GNU extension. This is a full-blown asm @@ -18038,7 +18037,8 @@ static tree c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code, tree clauses, tree *cclauses, bool *if_p) { - tree decl, cond, incr, save_break, save_cont, body, init, stmt, cl; + tree decl, cond, incr, body, init, stmt, cl; + unsigned char save_in_statement; tree declv, condv, incrv, initv, ret = NULL_TREE; tree pre_body = NULL_TREE, this_pre_body; tree ordered_cl = NULL_TREE; @@ -18106,6 +18106,11 @@ c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code, for_loc = c_parser_peek_token (parser)->location; c_parser_consume_token (parser); + /* Forbid break/continue in the loop initializer, condition, and + increment expressions. */ + save_in_statement = in_statement; + in_statement = IN_OMP_BLOCK; + for (i = 0; i < count; i++) { int bracecount = 0; @@ -18279,10 +18284,7 @@ c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code, if (nbraces) if_p = NULL; - save_break = c_break_label; - c_break_label = size_one_node; - save_cont = c_cont_label; - c_cont_label = NULL_TREE; + in_statement = IN_OMP_FOR; body = push_stmt_list (); if (inscan) @@ -18296,16 +18298,9 @@ c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code, } else add_stmt (c_parser_c99_block_statement (parser, if_p)); - if (c_cont_label) - { - tree t = build1 (LABEL_EXPR, void_type_node, c_cont_label); - SET_EXPR_LOCATION (t, loc); - add_stmt (t); - } body = pop_stmt_list (body); - c_break_label = save_break; - c_cont_label = save_cont; + in_statement = save_in_statement; while (nbraces) { |