2003-11-24 Eric Christopher <echristo@redhat.com>
authorechristo <echristo@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 24 Nov 2003 20:12:06 +0000 (20:12 +0000)
committerechristo <echristo@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 24 Nov 2003 20:12:06 +0000 (20:12 +0000)
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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@73887 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/c-decl.c
gcc/c-parse.in
gcc/c-semantics.c
gcc/c-tree.h

index 29159e8..fe2752e 100644 (file)
@@ -1,3 +1,19 @@
+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.
index 61fcae0..16cf655 100644 (file)
@@ -126,6 +126,10 @@ static GTY(()) struct stmt_tree_s c_stmt_tree;
 
 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;
@@ -425,13 +429,13 @@ void
 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;
@@ -440,9 +444,9 @@ objc_mark_locals_volatile (void *enclosing_blk)
       /* Do not climb up past the current function.  */
       if (scope->function_body)
        break;
-    }  
-}     
-  
+    }
+}
+
 /* Nonzero if we are currently in the global scope.  */
 
 int
@@ -1677,7 +1681,7 @@ pushdecl (tree x)
     DECL_CONTEXT (x) = current_file_decl;
   else
     DECL_CONTEXT (x) = current_function_decl;
-  
+
   if (name)
     {
       tree old;
@@ -1718,7 +1722,7 @@ pushdecl (tree x)
          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);
            }
@@ -2250,7 +2254,7 @@ c_init_decl_processing (void)
   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 ();
 
@@ -4637,7 +4641,7 @@ get_parm_info (int void_at_end)
        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)));
@@ -5088,23 +5092,23 @@ finish_struct (tree t, tree fieldlist, tree attributes)
         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;
@@ -5119,7 +5123,7 @@ finish_struct (tree t, tree fieldlist, tree attributes)
           }
       }
   }
-  
+
   for (x = TYPE_MAIN_VARIANT (t); x; x = TYPE_NEXT_VARIANT (x))
     {
       TYPE_FIELDS (x) = TYPE_FIELDS (t);
@@ -5438,6 +5442,8 @@ start_function (tree declspecs, tree declarator, tree attributes)
   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;
@@ -6251,20 +6257,6 @@ check_for_loop_decls (void)
     }
 }
 \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.  */
 
@@ -6277,6 +6269,8 @@ c_push_function_context (struct function *f)
 
   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;
@@ -6303,6 +6297,8 @@ c_pop_function_context (struct function *f)
 
   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;
@@ -6510,7 +6506,7 @@ merge_translation_unit_decls (void)
   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);
@@ -6551,7 +6547,7 @@ merge_translation_unit_decls (void)
                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;
@@ -6585,10 +6581,10 @@ merge_translation_unit_decls (void)
        {
          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);
@@ -6603,7 +6599,7 @@ void
 c_write_global_declarations(void)
 {
   tree link;
-  
+
   for (link = current_file_decl; link; link = TREE_CHAIN (link))
     {
       tree globals = BLOCK_VARS (DECL_INITIAL (link));
@@ -6611,16 +6607,16 @@ c_write_global_declarations(void)
       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);
     }
@@ -6633,7 +6629,7 @@ c_reset_state (void)
 {
   tree link;
   tree file_scope_decl;
-  
+
   /* Pop the global scope.  */
   if (current_scope != global_scope)
       current_scope = global_scope;
index 22bab99..d58b1ef 100644 (file)
@@ -257,6 +257,9 @@ do {                                                                        \
 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;
@@ -2053,12 +2056,12 @@ pushlevel:  /* empty */
        ;
 
 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);
                }
         ;
 
@@ -2202,6 +2205,7 @@ do_stmt_start:
          DO
                { stmt_count++;
                  compstmt_count++;
+                 c_in_iteration_stmt++;
                  $<ttype>$
                    = add_stmt (build_stmt (DO_STMT, NULL_TREE,
                                            NULL_TREE));
@@ -2212,7 +2216,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 ($$));
+                 c_in_iteration_stmt--; }
        ;
 
 /* The forced readahead in here is because we might be at the end of a
@@ -2295,12 +2300,14 @@ select_or_iter_stmt:
                 { 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); }
@@ -2318,14 +2325,18 @@ select_or_iter_stmt:
                    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:
@@ -2348,9 +2359,21 @@ 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++;
@@ -2397,18 +2420,18 @@ stmt:
                { $$ = 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 (); }
@@ -2425,18 +2448,18 @@ objc_try_catch_stmt:
 
 
 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++; }
@@ -3689,7 +3712,7 @@ _yylex (void)
     case CPP_STRING:
     case CPP_WSTRING:
       return STRING;
-      
+
     case CPP_OBJC_STRING:
       return OBJC_STRING;
 
index a3e1b45..f3c61b4 100644 (file)
@@ -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 3ba4953..f04e7b4 100644 (file)
@@ -44,12 +44,12 @@ struct lang_identifier GTY(())
 
 /* 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;
 };
@@ -106,7 +106,7 @@ struct lang_decl GTY(())
 /* 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.
@@ -152,6 +152,22 @@ struct lang_type GTY(())
 #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);