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

Reply via email to