+2003-11-24 Eric Christopher <echristo@redhat.com>
+
+ PR C/13014
+ * c-decl.c (c_in_iteration_stmt, c_in_case_stmt): New.
+ (start_function): Use.
+ (c_push_function_context): Ditto.
+ (c-pop_function_context): Ditto.
+ (language_function): Move...
+ * c-tree.h: ... here. Add x_in_iteration_stmt, and
+ x_in_case_stmt.
+ * c-parse.in (do_stmt_start, select_or_iter_stmt, stmt): Use
+ c_in_iteration_stmt, c_in_case_stmt for parser state. Move
+ check for valid break or continue statment here...
+ * c-semantics.c (genrtl_break_stmt, genrtl_continue_stmt): From
+ here. Change original errors to abort.
+
2003-11-24 Jan Hubicka <jh@suse.cz>
* fold-const.c (fold): Do not return early when optimizing COMPONENT_REF
* calls.c (expand_call): Allocate new temp in pass1.
(store_one_arg): If PARALLEL, calculate excess using mode size of
- rtvec elt.
+ rtvec elt.
* expr.c (emit_push_insn): If PARALLEL, calculate offset using
mode size of rtvec elt.
* function.c (assign_parms): Use parm in register, if available.
static GTY(()) tree c_scope_stmt_stack;
+/* State saving variables. */
+int c_in_iteration_stmt;
+int c_in_case_stmt;
+
/* A list of external DECLs that appeared at block scope when there was
some other global meaning for that identifier. */
static GTY(()) tree truly_local_externals;
objc_mark_locals_volatile (void *enclosing_blk)
{
struct c_scope *scope;
-
- for (scope = current_scope;
+
+ for (scope = current_scope;
scope && scope != enclosing_blk;
scope = scope->outer)
{
tree decl;
-
+
for (decl = scope->names; decl; decl = TREE_CHAIN (decl))
{
DECL_REGISTER (decl) = 0;
/* Do not climb up past the current function. */
if (scope->function_body)
break;
- }
-}
-
+ }
+}
+
/* Nonzero if we are currently in the global scope. */
int
DECL_CONTEXT (x) = current_file_decl;
else
DECL_CONTEXT (x) = current_function_decl;
-
+
if (name)
{
tree old;
tree ext = any_external_decl (name);
if (ext)
{
- if (duplicate_decls (x, ext, scope != global_scope,
+ if (duplicate_decls (x, ext, scope != global_scope,
false))
x = copy_node (ext);
}
tree endlink;
tree ptr_ftype_void, ptr_ftype_ptr;
location_t save_loc = input_location;
-
+
/* Adds some ggc roots, and reserved words for c-parse.in. */
c_parse_init ();
default: abort ();
}
- if (TREE_PURPOSE (decl))
+ if (TREE_PURPOSE (decl))
/* The first %s will be one of 'struct', 'union', or 'enum'. */
warning ("\"%s %s\" declared inside parameter list",
keyword, IDENTIFIER_POINTER (TREE_PURPOSE (decl)));
tree *field_array;
struct lang_type *space;
struct sorted_fields_type *space2;
-
+
len += list_length (x);
-
+
/* Use the same allocation policy here that make_node uses, to
ensure that this lives as long as the rest of the struct decl.
All decls in an inline function need to be saved. */
-
+
space = ggc_alloc (sizeof (struct lang_type));
space2 = ggc_alloc (sizeof (struct sorted_fields_type) + len * sizeof (tree));
-
+
len = 0;
space->s = space2;
field_array = &space2->elts[0];
for (x = fieldlist; x; x = TREE_CHAIN (x))
{
field_array[len++] = x;
-
+
/* If there is anonymous struct or union, break out of the loop. */
if (DECL_NAME (x) == NULL)
break;
}
}
}
-
+
for (x = TYPE_MAIN_VARIANT (t); x; x = TYPE_NEXT_VARIANT (x))
{
TYPE_FIELDS (x) = TYPE_FIELDS (t);
current_function_returns_abnormally = 0;
warn_about_return_type = 0;
current_extern_inline = 0;
+ c_in_iteration_stmt = 0;
+ c_in_case_stmt = 0;
/* Don't expand any sizes in the return type of the function. */
immediate_size_expand = 0;
}
}
\f
-/* Save and restore the variables in this file and elsewhere
- that keep track of the progress of compilation of the current function.
- Used for nested functions. */
-
-struct language_function GTY(())
-{
- struct c_language_function base;
- int returns_value;
- int returns_null;
- int returns_abnormally;
- int warn_about_return_type;
- int extern_inline;
-};
-
/* Save and reinitialize the variables
used during compilation of a C function. */
p->base.x_stmt_tree = c_stmt_tree;
p->base.x_scope_stmt_stack = c_scope_stmt_stack;
+ p->x_in_iteration_stmt = c_in_iteration_stmt;
+ p->x_in_case_stmt = c_in_case_stmt;
p->returns_value = current_function_returns_value;
p->returns_null = current_function_returns_null;
p->returns_abnormally = current_function_returns_abnormally;
c_stmt_tree = p->base.x_stmt_tree;
c_scope_stmt_stack = p->base.x_scope_stmt_stack;
+ c_in_iteration_stmt = p->x_in_iteration_stmt;
+ c_in_case_stmt = p->x_in_case_stmt;
current_function_returns_value = p->returns_value;
current_function_returns_null = p->returns_null;
current_function_returns_abnormally = p->returns_abnormally;
tree decl;
htab_t link_hash_table;
tree block;
-
+
/* Create the BLOCK that poplevel would have created, but don't
actually call poplevel since that's expensive. */
block = make_node (BLOCK);
DECL_EXTERNAL (decl) = 1;
else if (DECL_COMMON (old_decl) || DECL_ONE_ONLY (old_decl))
DECL_EXTERNAL (old_decl) = 1;
-
+
if (DECL_EXTERNAL (decl))
{
DECL_INITIAL (decl) = NULL_TREE;
{
tree global_decl;
global_decl = htab_find (link_hash_table, decl);
-
+
if (! global_decl)
continue;
-
+
/* Print any appropriate error messages, and partially merge
the decls. */
(void) duplicate_decls (decl, global_decl, true, true);
c_write_global_declarations(void)
{
tree link;
-
+
for (link = current_file_decl; link; link = TREE_CHAIN (link))
{
tree globals = BLOCK_VARS (DECL_INITIAL (link));
tree *vec = xmalloc (sizeof (tree) * len);
int i;
tree decl;
-
+
/* Process the decls in the order they were written. */
for (i = 0, decl = globals; i < len; i++, decl = TREE_CHAIN (decl))
vec[i] = decl;
-
+
wrapup_global_declarations (vec, len);
-
+
check_global_declarations (vec, len);
-
+
/* Clean up. */
free (vec);
}
{
tree link;
tree file_scope_decl;
-
+
/* Pop the global scope. */
if (current_scope != global_scope)
current_scope = global_scope;
static int stmt_count;
static int compstmt_count;
+extern int c_in_iteration_stmt;
+extern int c_in_case_stmt;
+
/* Input location of the end of the body of last simple_if;
used by the stmt-rule immediately after simple_if returns. */
static location_t if_stmt_locus;
;
poplevel: /* empty */
- {
+ {
@@ifobjc
if (c_dialect_objc ())
objc_clear_super_receiver ();
@@end_ifobjc
- $$ = add_scope_stmt (/*begin_p=*/0, /*partial_p=*/0);
+ $$ = add_scope_stmt (/*begin_p=*/0, /*partial_p=*/0);
}
;
DO
{ stmt_count++;
compstmt_count++;
+ c_in_iteration_stmt++;
$<ttype>$
= add_stmt (build_stmt (DO_STMT, NULL_TREE,
NULL_TREE));
DO_COND ($<ttype>$) = error_mark_node; }
c99_block_lineno_labeled_stmt WHILE
{ $$ = $<ttype>2;
- RECHAIN_STMTS ($$, DO_BODY ($$)); }
+ RECHAIN_STMTS ($$, DO_BODY ($$));
+ c_in_iteration_stmt--; }
;
/* The forced readahead in here is because we might be at the end of a
{ stmt_count++;
$<ttype>$ = c_begin_while_stmt (); }
'(' expr ')'
- { $4 = c_common_truthvalue_conversion ($4);
+ { c_in_iteration_stmt++;
+ $4 = c_common_truthvalue_conversion ($4);
c_finish_while_stmt_cond
(c_common_truthvalue_conversion ($4), $<ttype>2);
$<ttype>$ = add_stmt ($<ttype>2); }
c99_block_lineno_labeled_stmt
- { RECHAIN_STMTS ($<ttype>6, WHILE_BODY ($<ttype>6)); }
+ { c_in_iteration_stmt--;
+ RECHAIN_STMTS ($<ttype>6, WHILE_BODY ($<ttype>6)); }
| do_stmt_start
'(' expr ')' ';'
{ DO_COND ($1) = c_common_truthvalue_conversion ($3); }
FOR_COND ($<ttype>2)
= c_common_truthvalue_conversion ($6); }
xexpr ')'
- { FOR_EXPR ($<ttype>2) = $9; }
+ { c_in_iteration_stmt++;
+ FOR_EXPR ($<ttype>2) = $9; }
c99_block_lineno_labeled_stmt
- { RECHAIN_STMTS ($<ttype>2, FOR_BODY ($<ttype>2)); }
+ { RECHAIN_STMTS ($<ttype>2, FOR_BODY ($<ttype>2));
+ c_in_iteration_stmt--;}
| SWITCH '(' expr ')'
{ stmt_count++;
- $<ttype>$ = c_start_case ($3); }
+ $<ttype>$ = c_start_case ($3);
+ c_in_case_stmt++; }
c99_block_lineno_labeled_stmt
- { c_finish_case (); }
+ { c_finish_case ();
+ c_in_case_stmt--; }
;
for_init_stmt:
$$ = NULL_TREE; }
| BREAK ';'
{ stmt_count++;
+ if (!(c_in_iteration_stmt || c_in_case_stmt))
+ {
+ error ("break statement not within loop or switch");
+ $$ = NULL_TREE;
+ }
+ else
$$ = add_stmt (build_break_stmt ()); }
| CONTINUE ';'
{ stmt_count++;
+ if (!c_in_iteration_stmt)
+ {
+ error ("continue statement not within a loop");
+ $$ = NULL_TREE;
+ }
+ else
$$ = add_stmt (build_continue_stmt ()); }
| RETURN ';'
{ stmt_count++;
{ $$ = NULL_TREE; }
@@ifobjc
| AT_THROW expr ';'
- { stmt_count++;
- $$ = objc_build_throw_stmt ($2);
+ { stmt_count++;
+ $$ = objc_build_throw_stmt ($2);
}
| AT_THROW ';'
- { stmt_count++;
- $$ = objc_build_throw_stmt (NULL_TREE);
+ { stmt_count++;
+ $$ = objc_build_throw_stmt (NULL_TREE);
}
- | objc_try_catch_stmt
+ | objc_try_catch_stmt
{ objc_build_finally_prologue (); }
objc_finally_block
{ $$ = objc_build_try_catch_finally_stmt ($1, $3); }
- | AT_SYNCHRONIZED '(' expr ')'
+ | AT_SYNCHRONIZED '(' expr ')'
{ objc_build_synchronized_prologue ($3); }
compstmt
{ $$ = objc_build_synchronized_epilogue (); }
objc_try_stmt:
- AT_TRY
+ AT_TRY
{ objc_build_try_prologue (); }
- compstmt
+ compstmt
;
-
+
objc_catch_list:
objc_catch_list objc_catch_block
| objc_catch_block
;
objc_catch_block:
- AT_CATCH '(' parm ')'
+ AT_CATCH '(' parm ')'
{ objc_build_catch_stmt ($3); }
compstmt
{ stmt_count++; }
case CPP_STRING:
case CPP_WSTRING:
return STRING;
-
+
case CPP_OBJC_STRING:
return OBJC_STRING;
{
emit_line_note (input_location);
if ( ! expand_exit_something ())
- error ("break statement not within loop or switch");
+ abort ();
}
/* Build a continue statement node and return it. */
{
emit_line_note (input_location);
if (! expand_continue_loop (0))
- error ("continue statement not within a loop");
+ abort ();
}
/* Generate the RTL for T, which is a SCOPE_STMT. */
/* The resulting tree type. */
-union lang_tree_node
+union lang_tree_node
GTY((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"),
chain_next ("TREE_CODE (&%h.generic) == INTEGER_TYPE ? (union lang_tree_node *)TYPE_NEXT_VARIANT (&%h.generic) : (union lang_tree_node *)TREE_CHAIN (&%h.generic)")))
{
- union tree_node GTY ((tag ("0"),
- desc ("tree_node_structure (&%h)")))
+ union tree_node GTY ((tag ("0"),
+ desc ("tree_node_structure (&%h)")))
generic;
struct lang_identifier GTY ((tag ("1"))) identifier;
};
/* In a RECORD_TYPE, a sorted array of the fields of the type. */
struct lang_type GTY(())
{
- struct sorted_fields_type * GTY ((reorder ("resort_sorted_fields"))) s;
+ struct sorted_fields_type * GTY ((reorder ("resort_sorted_fields"))) s;
};
/* Record whether a type or decl was written with nonconstant size.
#define KEEP_YES 1
#define KEEP_MAYBE 2
+/* Save and restore the variables in this file and elsewhere
+ that keep track of the progress of compilation of the current function.
+ Used for nested functions. */
+
+struct language_function GTY(())
+{
+ struct c_language_function base;
+ int returns_value;
+ int returns_null;
+ int returns_abnormally;
+ int warn_about_return_type;
+ int extern_inline;
+ int x_in_iteration_stmt;
+ int x_in_case_stmt;
+};
+
\f
/* in c-parse.in */
extern void c_parse_init (void);