represent the start and end of scope which a local jump is not allowed to cross as a jump barrier, moving this logic out into a function allows for defer statements to use the same codepath
gcc/c/ChangeLog: * c-decl.cc (struct c_jump_barrier): New structure. (struct c_spot_bindings): Adjust. (set_spot_bindings): Likewise. (c_binding_adjust_jump_barrier): New function. (c_bindings_start_stmt_expr): Adjust. (c_bindings_end_stmt_expr): Likewise. (lookup_label_for_goto): Likewise. (check_earlier_gotos): Likewise. (c_release_switch_bindings): Likewise. (c_check_switch_jump_warnings): Likewise. Signed-off-by: Anna (navi) Figueiredo Gomes <n...@vlhl.dev> --- gcc/c/c-decl.cc | 72 +++++++++++++++++++++++++------------------------ 1 file changed, 37 insertions(+), 35 deletions(-) diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc index 7850365f35c..56ca3078226 100644 --- a/gcc/c/c-decl.cc +++ b/gcc/c/c-decl.cc @@ -379,6 +379,16 @@ c_tree_size (enum tree_code code) scopes are popped, we update these structures and gather the decls that matter at that time. */ +struct GTY(()) c_jump_barrier { + /* The number of barriers that have started since this label or goto + statement was defined. This is zero if we are at the same barrier. + It is positive if we are in a barrier that started since this spot. + If it goes negative, it is reset to zero and .left is set to true. */ + int count; + /* Whether we started in a barrier but are no longer in it. */ + bool left; +}; + struct GTY(()) c_spot_bindings { /* The currently open scope which holds bindings defined when the label was defined or the goto statement was found. */ @@ -387,16 +397,7 @@ struct GTY(()) c_spot_bindings { of the label or goto. This lets us look at older or newer bindings in the scope, as appropriate. */ struct c_binding *bindings_in_scope; - /* The number of statement expressions that have started since this - label or goto statement was defined. This is zero if we are at - the same statement expression level. It is positive if we are in - a statement expression started since this spot. It is negative - if this spot was in a statement expression and we have left - it. */ - int stmt_exprs; - /* Whether we started in a statement expression but are no longer in - it. This is set to true if stmt_exprs ever goes negative. */ - bool left_stmt_expr; + struct c_jump_barrier stmt_exprs; }; /* This structure is used to keep track of bindings seen when a goto @@ -983,8 +984,8 @@ set_spot_bindings (struct c_spot_bindings *p, bool defining) p->scope = NULL; p->bindings_in_scope = NULL; } - p->stmt_exprs = 0; - p->left_stmt_expr = false; + p->stmt_exprs.count = 0; + p->stmt_exprs.left = false; } /* Update spot bindings P as we pop out of SCOPE. Return true if we @@ -1603,6 +1604,18 @@ finish_underspecified_init (tree name, unsigned int prev_state) /* Adjust the bindings for the start of a statement expression. */ +static void +c_binding_adjust_jump_barrier (struct c_spot_bindings *binding, bool start) +{ + struct c_jump_barrier *barrier = &binding->stmt_exprs; + barrier->count += start ? 1 : -1; + if (barrier->count < 0) + { + barrier->count = 0; + barrier->left = true; + } +} + void c_bindings_start_stmt_expr (struct c_spot_bindings* switch_bindings) { @@ -1624,14 +1637,15 @@ c_bindings_start_stmt_expr (struct c_spot_bindings* switch_bindings) if (TREE_CODE (b->decl) != LABEL_DECL) continue; label_vars = b->u.label; - ++label_vars->label_bindings.stmt_exprs; + + c_binding_adjust_jump_barrier (&label_vars->label_bindings, true); FOR_EACH_VEC_SAFE_ELT (label_vars->gotos, ix, g) - ++g->goto_bindings.stmt_exprs; + c_binding_adjust_jump_barrier (&g->goto_bindings, true); } } if (switch_bindings != NULL) - ++switch_bindings->stmt_exprs; + c_binding_adjust_jump_barrier (switch_bindings, true); } /* Adjust the bindings for the end of a statement expression. */ @@ -1657,28 +1671,16 @@ c_bindings_end_stmt_expr (struct c_spot_bindings *switch_bindings) if (TREE_CODE (b->decl) != LABEL_DECL) continue; label_vars = b->u.label; - --label_vars->label_bindings.stmt_exprs; - if (label_vars->label_bindings.stmt_exprs < 0) - { - label_vars->label_bindings.left_stmt_expr = true; - label_vars->label_bindings.stmt_exprs = 0; - } + c_binding_adjust_jump_barrier (&label_vars->label_bindings, false); FOR_EACH_VEC_SAFE_ELT (label_vars->gotos, ix, g) - { - --g->goto_bindings.stmt_exprs; - if (g->goto_bindings.stmt_exprs < 0) - { - g->goto_bindings.left_stmt_expr = true; - g->goto_bindings.stmt_exprs = 0; - } - } + c_binding_adjust_jump_barrier (&g->goto_bindings, false); } } if (switch_bindings != NULL) { - --switch_bindings->stmt_exprs; - gcc_assert (switch_bindings->stmt_exprs >= 0); + c_binding_adjust_jump_barrier (switch_bindings, defer, false); + gcc_assert (switch_bindings->stmt_exprs.count >= 0); } } @@ -4149,7 +4151,7 @@ lookup_label_for_goto (location_t loc, tree name) FOR_EACH_VEC_SAFE_ELT (label_vars->decls_in_scope, ix, decl) warn_about_goto (loc, label, decl); - if (label_vars->label_bindings.left_stmt_expr) + if (label_vars->label_bindings.stmt_exprs.left) { auto_diagnostic_group d; error_at (loc, "jump into statement expression"); @@ -4240,7 +4242,7 @@ check_earlier_gotos (tree label, struct c_label_vars* label_vars) } } - if (g->goto_bindings.stmt_exprs > 0) + if (g->goto_bindings.stmt_exprs.count > 0) { auto_diagnostic_group d; error_at (g->loc, "jump into statement expression"); @@ -4331,7 +4333,7 @@ c_get_switch_bindings (void) void c_release_switch_bindings (struct c_spot_bindings *bindings) { - gcc_assert (bindings->stmt_exprs == 0 && !bindings->left_stmt_expr); + gcc_assert (bindings->stmt_exprs.count == 0 && !bindings->stmt_exprs.left); XDELETE (bindings); } @@ -4395,7 +4397,7 @@ c_check_switch_jump_warnings (struct c_spot_bindings *switch_bindings, } } - if (switch_bindings->stmt_exprs > 0) + if (switch_bindings->stmt_exprs.count > 0) { saw_error = true; auto_diagnostic_group d; -- 2.49.1