up searching for labels when popping scopes, particularly since
labels are normally only found at function scope. */
BOOL_BITFIELD has_label_bindings : 1;
+
+ /* True if we should issue a warning if a goto statement crosses any
+ of the bindings. We still need to check the list of bindings to
+ find the specific ones we need to warn about. This is true if
+ decl_jump_unsafe would return true for any of the bindings. This
+ is used to avoid looping over all the bindings unnecessarily. */
+ BOOL_BITFIELD has_jump_unsafe_decl : 1;
};
/* The scope currently in effect. */
return t;
}
\f
+/* Return true if we will want to say something if a goto statement
+ crosses DECL. */
+
+static bool
+decl_jump_unsafe (tree decl)
+{
+ if (decl == error_mark_node || TREE_TYPE (decl) == error_mark_node)
+ return false;
+
+ /* Always warn about crossing variably modified types. */
+ if ((TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == TYPE_DECL)
+ && variably_modified_type_p (TREE_TYPE (decl), NULL_TREE))
+ return true;
+
+ /* Otherwise, only warn if -Wgoto-misses-init and this is an
+ initialized automatic decl. */
+ if (warn_jump_misses_init
+ && TREE_CODE (decl) == VAR_DECL
+ && !TREE_STATIC (decl)
+ && DECL_INITIAL (decl) != NULL_TREE)
+ return true;
+
+ return false;
+}
+\f
void
c_print_identifier (FILE *file, tree node, int indent)
b->prev = scope->bindings;
scope->bindings = b;
+ if (decl_jump_unsafe (decl))
+ scope->has_jump_unsafe_decl = 1;
+
if (!name)
return;
p->left_stmt_expr = false;
}
-/* Return true if we will want to say something if a goto statement
- crosses DECL. */
-
-static bool
-decl_jump_unsafe (tree decl)
-{
- if (decl == error_mark_node || TREE_TYPE (decl) == error_mark_node)
- return false;
-
- /* Always warn about crossing variably modified types. */
- if ((TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == TYPE_DECL)
- && variably_modified_type_p (TREE_TYPE (decl), NULL_TREE))
- return true;
-
- /* Otherwise, only warn if -Wgoto-misses-init and this is an
- initialized automatic decl. */
- if (warn_jump_misses_init
- && TREE_CODE (decl) == VAR_DECL
- && !TREE_STATIC (decl)
- && DECL_INITIAL (decl) != NULL_TREE)
- return true;
-
- return false;
-}
-
/* Update spot bindings P as we pop out of SCOPE. Return true if we
should push decls for a label. */
{
struct c_label_vars *label_vars;
struct c_binding *b1;
+ bool hjud;
unsigned int ix;
struct c_goto_bindings *g;
label_vars = b->u.label;
b1 = label_vars->label_bindings.bindings_in_scope;
+ if (label_vars->label_bindings.scope == NULL)
+ hjud = false;
+ else
+ hjud = label_vars->label_bindings.scope->has_jump_unsafe_decl;
if (update_spot_bindings (scope, &label_vars->label_bindings))
{
/* This label is defined in this scope. */
- for (; b1 != NULL; b1 = b1->prev)
+ if (hjud)
{
- /* A goto from later in the function to this
- label will never see the initialization of
- B1, if any. Save it to issue a warning if
- needed. */
- if (decl_jump_unsafe (b1->decl))
- VEC_safe_push (tree, gc, label_vars->decls_in_scope,
- b1->decl);
+ for (; b1 != NULL; b1 = b1->prev)
+ {
+ /* A goto from later in the function to this
+ label will never see the initialization
+ of B1, if any. Save it to issue a
+ warning if needed. */
+ if (decl_jump_unsafe (b1->decl))
+ VEC_safe_push (tree, gc,
+ label_vars->decls_in_scope,
+ b1->decl);
+ }
}
}
/* We have a goto to this label. The goto is going forward. In
g->scope, the goto is going to skip any binding which was
defined after g->bindings_in_scope. */
- for (b = g->goto_bindings.scope->bindings;
- b != g->goto_bindings.bindings_in_scope;
- b = b->prev)
+ if (g->goto_bindings.scope->has_jump_unsafe_decl)
{
- if (decl_jump_unsafe (b->decl))
- warn_about_goto (g->loc, label, b->decl);
+ for (b = g->goto_bindings.scope->bindings;
+ b != g->goto_bindings.bindings_in_scope;
+ b = b->prev)
+ {
+ if (decl_jump_unsafe (b->decl))
+ warn_about_goto (g->loc, label, b->decl);
+ }
}
/* We also need to warn about decls defined in any scopes
scope = scope->outer)
{
gcc_assert (scope != NULL);
- if (scope == label_vars->label_bindings.scope)
- b = label_vars->label_bindings.bindings_in_scope;
- else
- b = scope->bindings;
- for (; b != NULL; b = b->prev)
+ if (scope->has_jump_unsafe_decl)
{
- if (decl_jump_unsafe (b->decl))
- warn_about_goto (g->loc, label, b->decl);
+ if (scope == label_vars->label_bindings.scope)
+ b = label_vars->label_bindings.bindings_in_scope;
+ else
+ b = scope->bindings;
+ for (; b != NULL; b = b->prev)
+ {
+ if (decl_jump_unsafe (b->decl))
+ warn_about_goto (g->loc, label, b->decl);
+ }
}
}
struct c_binding *b;
gcc_assert (scope != NULL);
+
+ if (!scope->has_jump_unsafe_decl)
+ continue;
+
for (b = scope->bindings; b != NULL; b = b->prev)
{
if (decl_jump_unsafe (b->decl))