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 <[email protected]>
---
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.51.0