Skip to content

Commit 3696a50

Browse files
Change C front end to emit structured loop and switch tree nodes.
2020-08-12 Sandra Loosemore <[email protected]> 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.
1 parent a85e569 commit 3696a50

File tree

8 files changed

+164
-250
lines changed

8 files changed

+164
-250
lines changed

gcc/c/c-decl.c

+7-11
Original file line numberDiff line numberDiff line change
@@ -112,9 +112,9 @@ struct obstack parser_obstack;
112112

113113
static GTY(()) struct stmt_tree_s c_stmt_tree;
114114

115-
/* State saving variables. */
116-
tree c_break_label;
117-
tree c_cont_label;
115+
/* Zero if we are not in an iteration or switch statement, otherwise
116+
a bitmask. See bitmask definitions in c-tree.h. */
117+
unsigned char in_statement;
118118

119119
/* A list of decls to be made automatically visible in each file scope. */
120120
static GTY(()) tree visible_builtins;
@@ -9163,10 +9163,8 @@ start_function (struct c_declspecs *declspecs, struct c_declarator *declarator,
91639163
warn_about_return_type = 0;
91649164
c_switch_stack = NULL;
91659165

9166-
/* Indicate no valid break/continue context by setting these variables
9167-
to some non-null, non-label value. We'll notice and emit the proper
9168-
error message in c_finish_bc_stmt. */
9169-
c_break_label = c_cont_label = size_zero_node;
9166+
/* Indicate no valid break/continue context. */
9167+
in_statement = 0;
91709168

91719169
decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, true, NULL,
91729170
&attributes, NULL, NULL, DEPRECATED_NORMAL);
@@ -10167,8 +10165,7 @@ c_push_function_context (void)
1016710165

1016810166
p->base.x_stmt_tree = c_stmt_tree;
1016910167
c_stmt_tree.x_cur_stmt_list = vec_safe_copy (c_stmt_tree.x_cur_stmt_list);
10170-
p->x_break_label = c_break_label;
10171-
p->x_cont_label = c_cont_label;
10168+
p->x_in_statement = in_statement;
1017210169
p->x_switch_stack = c_switch_stack;
1017310170
p->arg_info = current_function_arg_info;
1017410171
p->returns_value = current_function_returns_value;
@@ -10207,8 +10204,7 @@ c_pop_function_context (void)
1020710204

1020810205
c_stmt_tree = p->base.x_stmt_tree;
1020910206
p->base.x_stmt_tree.x_cur_stmt_list = NULL;
10210-
c_break_label = p->x_break_label;
10211-
c_cont_label = p->x_cont_label;
10207+
in_statement = p->x_in_statement;
1021210208
c_switch_stack = p->x_switch_stack;
1021310209
current_function_arg_info = p->arg_info;
1021410210
current_function_returns_value = p->returns_value;

gcc/c/c-lang.h

+1-2
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,7 @@ struct GTY(()) lang_decl {
5151

5252
struct GTY(()) language_function {
5353
struct c_language_function base;
54-
tree x_break_label;
55-
tree x_cont_label;
54+
unsigned char x_in_statement;
5655
struct c_switch * GTY((skip)) x_switch_stack;
5756
struct c_arg_info * GTY((skip)) arg_info;
5857
int returns_value;

gcc/c/c-objc-common.h

+2
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ along with GCC; see the file COPYING3. If not see
5656
#define LANG_HOOKS_TYPES_COMPATIBLE_P c_types_compatible_p
5757
#undef LANG_HOOKS_MISSING_NORETURN_OK_P
5858
#define LANG_HOOKS_MISSING_NORETURN_OK_P c_missing_noreturn_ok_p
59+
#undef LANG_HOOKS_BLOCK_MAY_FALLTHRU
60+
#define LANG_HOOKS_BLOCK_MAY_FALLTHRU c_block_may_fallthru
5961
#undef LANG_HOOKS_BUILTIN_FUNCTION
6062
#define LANG_HOOKS_BUILTIN_FUNCTION c_builtin_function
6163
#undef LANG_HOOKS_BUILTIN_FUNCTION_EXT_SCOPE

gcc/c/c-parser.c

+60-65
Original file line numberDiff line numberDiff line change
@@ -1479,6 +1479,9 @@ struct oacc_routine_data {
14791479
location_t loc;
14801480
};
14811481

1482+
/* Used for parsing objc foreach statements. */
1483+
static tree objc_foreach_break_label, objc_foreach_continue_label;
1484+
14821485
static bool c_parser_nth_token_starts_std_attributes (c_parser *,
14831486
unsigned int);
14841487
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,
62216224
goto expect_semicolon;
62226225
case RID_CONTINUE:
62236226
c_parser_consume_token (parser);
6224-
stmt = c_finish_bc_stmt (loc, &c_cont_label, false);
6227+
stmt = c_finish_bc_stmt (loc, objc_foreach_continue_label, false);
62256228
goto expect_semicolon;
62266229
case RID_BREAK:
62276230
c_parser_consume_token (parser);
6228-
stmt = c_finish_bc_stmt (loc, &c_break_label, true);
6231+
stmt = c_finish_bc_stmt (loc, objc_foreach_break_label, true);
62296232
goto expect_semicolon;
62306233
case RID_RETURN:
62316234
c_parser_consume_token (parser);
@@ -6627,7 +6630,8 @@ static void
66276630
c_parser_switch_statement (c_parser *parser, bool *if_p)
66286631
{
66296632
struct c_expr ce;
6630-
tree block, expr, body, save_break;
6633+
tree block, expr, body;
6634+
unsigned char save_in_statement;
66316635
location_t switch_loc = c_parser_peek_token (parser)->location;
66326636
location_t switch_cond_loc;
66336637
gcc_assert (c_parser_next_token_is_keyword (parser, RID_SWITCH));
@@ -6653,26 +6657,18 @@ c_parser_switch_statement (c_parser *parser, bool *if_p)
66536657
expr = error_mark_node;
66546658
ce.original_type = error_mark_node;
66556659
}
6656-
c_start_case (switch_loc, switch_cond_loc, expr, explicit_cast_p);
6657-
save_break = c_break_label;
6658-
c_break_label = NULL_TREE;
6660+
c_start_switch (switch_loc, switch_cond_loc, expr, explicit_cast_p);
6661+
save_in_statement = in_statement;
6662+
in_statement |= IN_SWITCH_STMT;
66596663
location_t loc_after_labels;
66606664
bool open_brace_p = c_parser_peek_token (parser)->type == CPP_OPEN_BRACE;
66616665
body = c_parser_c99_block_statement (parser, if_p, &loc_after_labels);
66626666
location_t next_loc = c_parser_peek_token (parser)->location;
66636667
if (!open_brace_p && c_parser_peek_token (parser)->type != CPP_SEMICOLON)
66646668
warn_for_multistatement_macros (loc_after_labels, next_loc, switch_loc,
66656669
RID_SWITCH);
6666-
if (c_break_label)
6667-
{
6668-
location_t here = c_parser_peek_token (parser)->location;
6669-
tree t = build1 (LABEL_EXPR, void_type_node, c_break_label);
6670-
SET_EXPR_LOCATION (t, here);
6671-
SWITCH_BREAK_LABEL_P (c_break_label) = 1;
6672-
append_to_statement_list_force (t, &body);
6673-
}
6674-
c_finish_case (body, ce.original_type);
6675-
c_break_label = save_break;
6670+
c_finish_switch (body, ce.original_type);
6671+
in_statement = save_in_statement;
66766672
add_stmt (c_end_compound_stmt (switch_loc, block, flag_isoc99));
66776673
c_parser_maybe_reclassify_token (parser);
66786674
}
@@ -6690,7 +6686,8 @@ static void
66906686
c_parser_while_statement (c_parser *parser, bool ivdep, unsigned short unroll,
66916687
bool *if_p)
66926688
{
6693-
tree block, cond, body, save_break, save_cont;
6689+
tree block, cond, body;
6690+
unsigned char save_in_statement;
66946691
location_t loc;
66956692
gcc_assert (c_parser_next_token_is_keyword (parser, RID_WHILE));
66966693
token_indent_info while_tinfo
@@ -6709,19 +6706,16 @@ c_parser_while_statement (c_parser *parser, bool ivdep, unsigned short unroll,
67096706
build_int_cst (integer_type_node,
67106707
annot_expr_unroll_kind),
67116708
build_int_cst (integer_type_node, unroll));
6712-
save_break = c_break_label;
6713-
c_break_label = NULL_TREE;
6714-
save_cont = c_cont_label;
6715-
c_cont_label = NULL_TREE;
6709+
save_in_statement = in_statement;
6710+
in_statement = IN_ITERATION_STMT;
67166711

67176712
token_indent_info body_tinfo
67186713
= get_token_indent_info (c_parser_peek_token (parser));
67196714

67206715
location_t loc_after_labels;
67216716
bool open_brace = c_parser_next_token_is (parser, CPP_OPEN_BRACE);
67226717
body = c_parser_c99_block_statement (parser, if_p, &loc_after_labels);
6723-
c_finish_loop (loc, loc, cond, UNKNOWN_LOCATION, NULL, body,
6724-
c_break_label, c_cont_label, true);
6718+
add_stmt (build_stmt (loc, WHILE_STMT, cond, body));
67256719
add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
67266720
c_parser_maybe_reclassify_token (parser);
67276721

@@ -6733,8 +6727,7 @@ c_parser_while_statement (c_parser *parser, bool ivdep, unsigned short unroll,
67336727
warn_for_multistatement_macros (loc_after_labels, next_tinfo.location,
67346728
while_tinfo.location, RID_WHILE);
67356729

6736-
c_break_label = save_break;
6737-
c_cont_label = save_cont;
6730+
in_statement = save_in_statement;
67386731
}
67396732

67406733
/* 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,
67466739
static void
67476740
c_parser_do_statement (c_parser *parser, bool ivdep, unsigned short unroll)
67486741
{
6749-
tree block, cond, body, save_break, save_cont, new_break, new_cont;
6742+
tree block, cond, body;
6743+
unsigned char save_in_statement;
67506744
location_t loc;
67516745
gcc_assert (c_parser_next_token_is_keyword (parser, RID_DO));
67526746
c_parser_consume_token (parser);
@@ -6756,17 +6750,11 @@ c_parser_do_statement (c_parser *parser, bool ivdep, unsigned short unroll)
67566750
"suggest braces around empty body in %<do%> statement");
67576751
block = c_begin_compound_stmt (flag_isoc99);
67586752
loc = c_parser_peek_token (parser)->location;
6759-
save_break = c_break_label;
6760-
c_break_label = NULL_TREE;
6761-
save_cont = c_cont_label;
6762-
c_cont_label = NULL_TREE;
6753+
save_in_statement = in_statement;
6754+
in_statement = IN_ITERATION_STMT;
67636755
body = c_parser_c99_block_statement (parser, NULL);
67646756
c_parser_require_keyword (parser, RID_WHILE, "expected %<while%>");
6765-
new_break = c_break_label;
6766-
c_break_label = save_break;
6767-
new_cont = c_cont_label;
6768-
c_cont_label = save_cont;
6769-
location_t cond_loc = c_parser_peek_token (parser)->location;
6757+
in_statement = save_in_statement;
67706758
cond = c_parser_paren_condition (parser);
67716759
if (ivdep && cond != error_mark_node)
67726760
cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
@@ -6780,8 +6768,8 @@ c_parser_do_statement (c_parser *parser, bool ivdep, unsigned short unroll)
67806768
build_int_cst (integer_type_node, unroll));
67816769
if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
67826770
c_parser_skip_to_end_of_block_or_statement (parser);
6783-
c_finish_loop (loc, cond_loc, cond, UNKNOWN_LOCATION, NULL, body,
6784-
new_break, new_cont, false);
6771+
6772+
add_stmt (build_stmt (loc, DO_STMT, cond, body));
67856773
add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
67866774
}
67876775

@@ -6848,15 +6836,15 @@ static void
68486836
c_parser_for_statement (c_parser *parser, bool ivdep, unsigned short unroll,
68496837
bool *if_p)
68506838
{
6851-
tree block, cond, incr, save_break, save_cont, body;
6839+
tree block, cond, incr, body;
6840+
unsigned char save_in_statement;
6841+
tree save_objc_foreach_break_label, save_objc_foreach_continue_label;
68526842
/* The following are only used when parsing an ObjC foreach statement. */
68536843
tree object_expression;
68546844
/* Silence the bogus uninitialized warning. */
68556845
tree collection_expression = NULL;
68566846
location_t loc = c_parser_peek_token (parser)->location;
68576847
location_t for_loc = loc;
6858-
location_t cond_loc = UNKNOWN_LOCATION;
6859-
location_t incr_loc = UNKNOWN_LOCATION;
68606848
bool is_foreach_statement = false;
68616849
gcc_assert (c_parser_next_token_is_keyword (parser, RID_FOR));
68626850
token_indent_info for_tinfo
@@ -6966,7 +6954,6 @@ c_parser_for_statement (c_parser *parser, bool ivdep, unsigned short unroll,
69666954
gcc_assert (!parser->objc_could_be_foreach_context);
69676955
if (!is_foreach_statement)
69686956
{
6969-
cond_loc = c_parser_peek_token (parser)->location;
69706957
if (c_parser_next_token_is (parser, CPP_SEMICOLON))
69716958
{
69726959
if (ivdep)
@@ -7007,7 +6994,7 @@ c_parser_for_statement (c_parser *parser, bool ivdep, unsigned short unroll,
70076994
/* Parse the increment expression (the third expression in a
70086995
for-statement). In the case of a foreach-statement, this is
70096996
the expression that follows the 'in'. */
7010-
loc = incr_loc = c_parser_peek_token (parser)->location;
6997+
loc = c_parser_peek_token (parser)->location;
70116998
if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
70126999
{
70137000
if (is_foreach_statement)
@@ -7033,10 +7020,17 @@ c_parser_for_statement (c_parser *parser, bool ivdep, unsigned short unroll,
70337020
}
70347021
parens.skip_until_found_close (parser);
70357022
}
7036-
save_break = c_break_label;
7037-
c_break_label = NULL_TREE;
7038-
save_cont = c_cont_label;
7039-
c_cont_label = NULL_TREE;
7023+
save_in_statement = in_statement;
7024+
if (is_foreach_statement)
7025+
{
7026+
in_statement = IN_OBJC_FOREACH;
7027+
save_objc_foreach_break_label = objc_foreach_break_label;
7028+
save_objc_foreach_continue_label = objc_foreach_continue_label;
7029+
objc_foreach_break_label = create_artificial_label (loc);
7030+
objc_foreach_continue_label = create_artificial_label (loc);
7031+
}
7032+
else
7033+
in_statement = IN_ITERATION_STMT;
70407034

70417035
token_indent_info body_tinfo
70427036
= 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,
70477041

70487042
if (is_foreach_statement)
70497043
objc_finish_foreach_loop (for_loc, object_expression,
7050-
collection_expression, body, c_break_label,
7051-
c_cont_label);
7044+
collection_expression, body,
7045+
objc_foreach_break_label,
7046+
objc_foreach_continue_label);
70527047
else
7053-
c_finish_loop (for_loc, cond_loc, cond, incr_loc, incr, body,
7054-
c_break_label, c_cont_label, true);
7048+
add_stmt (build_stmt (for_loc, FOR_STMT, NULL_TREE, cond, incr,
7049+
body, NULL_TREE));
70557050
add_stmt (c_end_compound_stmt (for_loc, block,
70567051
flag_isoc99 || c_dialect_objc ()));
70577052
c_parser_maybe_reclassify_token (parser);
@@ -7064,8 +7059,12 @@ c_parser_for_statement (c_parser *parser, bool ivdep, unsigned short unroll,
70647059
warn_for_multistatement_macros (loc_after_labels, next_tinfo.location,
70657060
for_tinfo.location, RID_FOR);
70667061

7067-
c_break_label = save_break;
7068-
c_cont_label = save_cont;
7062+
in_statement = save_in_statement;
7063+
if (is_foreach_statement)
7064+
{
7065+
objc_foreach_break_label = save_objc_foreach_break_label;
7066+
objc_foreach_continue_label = save_objc_foreach_continue_label;
7067+
}
70697068
}
70707069

70717070
/* Parse an asm statement, a GNU extension. This is a full-blown asm
@@ -18038,7 +18037,8 @@ static tree
1803818037
c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code,
1803918038
tree clauses, tree *cclauses, bool *if_p)
1804018039
{
18041-
tree decl, cond, incr, save_break, save_cont, body, init, stmt, cl;
18040+
tree decl, cond, incr, body, init, stmt, cl;
18041+
unsigned char save_in_statement;
1804218042
tree declv, condv, incrv, initv, ret = NULL_TREE;
1804318043
tree pre_body = NULL_TREE, this_pre_body;
1804418044
tree ordered_cl = NULL_TREE;
@@ -18106,6 +18106,11 @@ c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code,
1810618106
for_loc = c_parser_peek_token (parser)->location;
1810718107
c_parser_consume_token (parser);
1810818108

18109+
/* Forbid break/continue in the loop initializer, condition, and
18110+
increment expressions. */
18111+
save_in_statement = in_statement;
18112+
in_statement = IN_OMP_BLOCK;
18113+
1810918114
for (i = 0; i < count; i++)
1811018115
{
1811118116
int bracecount = 0;
@@ -18279,10 +18284,7 @@ c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code,
1827918284
if (nbraces)
1828018285
if_p = NULL;
1828118286

18282-
save_break = c_break_label;
18283-
c_break_label = size_one_node;
18284-
save_cont = c_cont_label;
18285-
c_cont_label = NULL_TREE;
18287+
in_statement = IN_OMP_FOR;
1828618288
body = push_stmt_list ();
1828718289

1828818290
if (inscan)
@@ -18296,16 +18298,9 @@ c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code,
1829618298
}
1829718299
else
1829818300
add_stmt (c_parser_c99_block_statement (parser, if_p));
18299-
if (c_cont_label)
18300-
{
18301-
tree t = build1 (LABEL_EXPR, void_type_node, c_cont_label);
18302-
SET_EXPR_LOCATION (t, loc);
18303-
add_stmt (t);
18304-
}
1830518301

1830618302
body = pop_stmt_list (body);
18307-
c_break_label = save_break;
18308-
c_cont_label = save_cont;
18303+
in_statement = save_in_statement;
1830918304

1831018305
while (nbraces)
1831118306
{

gcc/c/c-tree.h

+16-5
Original file line numberDiff line numberDiff line change
@@ -547,8 +547,19 @@ extern void gen_aux_info_record (tree, int, int, int);
547547
struct c_spot_bindings;
548548
class c_struct_parse_info;
549549
extern struct obstack parser_obstack;
550-
extern tree c_break_label;
551-
extern tree c_cont_label;
550+
/* Set to IN_ITERATION_STMT if parsing an iteration-statement,
551+
to IN_OMP_BLOCK if parsing OpenMP structured block and
552+
IN_OMP_FOR if parsing OpenMP loop. If parsing a switch statement,
553+
this is bitwise ORed with IN_SWITCH_STMT, unless parsing an
554+
iteration-statement, OpenMP block or loop within that switch. */
555+
#define IN_SWITCH_STMT 1
556+
#define IN_ITERATION_STMT 2
557+
#define IN_OMP_BLOCK 4
558+
#define IN_OMP_FOR 8
559+
#define IN_OBJC_FOREACH 16
560+
extern unsigned char in_statement;
561+
562+
extern bool switch_statement_break_seen_p;
552563

553564
extern bool global_bindings_p (void);
554565
extern tree pushdecl (tree);
@@ -714,8 +725,8 @@ extern void process_init_element (location_t, struct c_expr, bool,
714725
extern tree build_compound_literal (location_t, tree, tree, bool,
715726
unsigned int);
716727
extern void check_compound_literal_type (location_t, struct c_type_name *);
717-
extern tree c_start_case (location_t, location_t, tree, bool);
718-
extern void c_finish_case (tree, tree);
728+
extern tree c_start_switch (location_t, location_t, tree, bool);
729+
extern void c_finish_switch (tree, tree);
719730
extern tree build_asm_expr (location_t, tree, tree, tree, tree, tree, bool,
720731
bool);
721732
extern tree build_asm_stmt (bool, tree);
@@ -730,7 +741,7 @@ extern tree c_finish_stmt_expr (location_t, tree);
730741
extern tree c_process_expr_stmt (location_t, tree);
731742
extern tree c_finish_expr_stmt (location_t, tree);
732743
extern tree c_finish_return (location_t, tree, tree);
733-
extern tree c_finish_bc_stmt (location_t, tree *, bool);
744+
extern tree c_finish_bc_stmt (location_t, tree, bool);
734745
extern tree c_finish_goto_label (location_t, tree);
735746
extern tree c_finish_goto_ptr (location_t, tree);
736747
extern tree c_expr_to_decl (tree, bool *, bool *);

0 commit comments

Comments
 (0)