This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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.  */



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]