This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: PATCH: RFA Fix C/13014
On Sun, 2003-11-16 at 23:38, Jason Merrill wrote:
> Alternately, you could add your in_*_stmt flags to cfun.
Ended up adding it to lang_decl instead like so...
Bootstrapped on x86-linux, regtested on the same. Joseph: I think your
testcase would be a good addition to the testsuite. Would you care to
check it in?
OK?
-eric
--
Eric Christopher <echristo@redhat.com>
2003-11-17 Eric Christopher <echristo@redhat.com>
PR C/13014
* c-tree.h (lang_decl): New variables: in_iteration_statement,
in_case_stmt.
* c-parse.in (in_iteration_stmt_ptr, in_case_stmt_ptr): Defines
to above.
(do_stmt_start, select_or_iter_stmt, stmt): Use. Return NULL_TREE
for bad code. Move errors here...
* c-semantics.c (genrtl_break_stmt, genrtl_continue_stmt):
... from here. Change previous errors to abort.
Index: c-parse.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-parse.in,v
retrieving revision 1.188
diff -u -p -w -r1.188 c-parse.in
--- c-parse.in 24 Oct 2003 15:30:30 -0000 1.188
+++ c-parse.in 18 Nov 2003 02:10:11 -0000
@@ -257,6 +257,11 @@ do { \
static int stmt_count;
static int compstmt_count;
+#define in_iteration_stmt_ptr \
+ DECL_LANG_SPECIFIC (current_function_decl)->in_iteration_stmt
+#define in_case_stmt_ptr \
+ DECL_LANG_SPECIFIC (current_function_decl)->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;
@@ -2202,6 +2207,7 @@ do_stmt_start:
DO
{ stmt_count++;
compstmt_count++;
+ in_iteration_stmt_ptr++;
$<ttype>$
= add_stmt (build_stmt (DO_STMT, NULL_TREE,
NULL_TREE));
@@ -2212,7 +2218,8 @@ do_stmt_start:
DO_COND ($<ttype>$) = error_mark_node; }
c99_block_lineno_labeled_stmt WHILE
{ $$ = $<ttype>2;
- RECHAIN_STMTS ($$, DO_BODY ($$)); }
+ RECHAIN_STMTS ($$, DO_BODY ($$));
+ in_iteration_stmt_ptr--; }
;
/* The forced readahead in here is because we might be at the end of a
@@ -2295,12 +2302,14 @@ select_or_iter_stmt:
{ stmt_count++;
$<ttype>$ = c_begin_while_stmt (); }
'(' expr ')'
- { $4 = c_common_truthvalue_conversion ($4);
+ { in_iteration_stmt_ptr++;
+ $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)); }
+ { in_iteration_stmt_ptr--;
+ RECHAIN_STMTS ($<ttype>6, WHILE_BODY ($<ttype>6)); }
| do_stmt_start
'(' expr ')' ';'
{ DO_COND ($1) = c_common_truthvalue_conversion ($3); }
@@ -2318,14 +2327,18 @@ select_or_iter_stmt:
FOR_COND ($<ttype>2)
= c_common_truthvalue_conversion ($6); }
xexpr ')'
- { FOR_EXPR ($<ttype>2) = $9; }
+ { in_iteration_stmt_ptr++;
+ 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));
+ in_iteration_stmt_ptr--;}
| SWITCH '(' expr ')'
{ stmt_count++;
- $<ttype>$ = c_start_case ($3); }
+ $<ttype>$ = c_start_case ($3);
+ in_case_stmt_ptr++; }
c99_block_lineno_labeled_stmt
- { c_finish_case (); }
+ { c_finish_case ();
+ in_case_stmt_ptr--; }
;
for_init_stmt:
@@ -2348,9 +2361,21 @@ stmt:
$$ = NULL_TREE; }
| BREAK ';'
{ stmt_count++;
+ if (!(in_iteration_stmt_ptr || in_case_stmt_ptr))
+ {
+ error ("break statement not within loop or switch");
+ $$ = NULL_TREE;
+ }
+ else
$$ = add_stmt (build_break_stmt ()); }
| CONTINUE ';'
{ stmt_count++;
+ if (!in_iteration_stmt_ptr)
+ {
+ error ("continue statement not within a loop");
+ $$ = NULL_TREE;
+ }
+ else
$$ = add_stmt (build_continue_stmt ()); }
| RETURN ';'
{ stmt_count++;
Index: c-semantics.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-semantics.c,v
retrieving revision 1.73
diff -u -p -w -r1.73 c-semantics.c
--- c-semantics.c 7 Oct 2003 22:10:37 -0000 1.73
+++ c-semantics.c 18 Nov 2003 02:10:12 -0000
@@ -592,7 +592,7 @@ genrtl_break_stmt (void)
{
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. */
@@ -610,7 +610,7 @@ genrtl_continue_stmt (void)
{
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. */
Index: c-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-tree.h,v
retrieving revision 1.134
diff -u -p -w -r1.134 c-tree.h
--- c-tree.h 12 Nov 2003 19:52:08 -0000 1.134
+++ c-tree.h 18 Nov 2003 02:10:12 -0000
@@ -62,6 +62,8 @@ struct lang_decl GTY(())
This is a list of any SAVE_EXPRs that need to be evaluated to
compute those sizes. */
tree pending_sizes;
+ int in_iteration_stmt;
+ int in_case_stmt;
};
/* Macros for access to language-specific slots in an identifier. */