From e13e48e70711cf7328c91eedf04ad4771dc9a002 Mon Sep 17 00:00:00 2001 From: Eric Christopher Date: Mon, 24 Nov 2003 20:12:06 +0000 Subject: [PATCH] re PR c/13014 (if shortcut misses required diagnostics) 2003-11-24 Eric Christopher 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. From-SVN: r73887 --- gcc/ChangeLog | 18 ++++++++++- gcc/c-decl.c | 76 ++++++++++++++++++++++------------------------- gcc/c-parse.in | 63 ++++++++++++++++++++++++++------------- gcc/c-semantics.c | 4 +-- gcc/c-tree.h | 24 ++++++++++++--- 5 files changed, 118 insertions(+), 67 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 29159e82446..fe2752e692e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,19 @@ +2003-11-24 Eric Christopher + + 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 * fold-const.c (fold): Do not return early when optimizing COMPONENT_REF @@ -204,7 +220,7 @@ * 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. diff --git a/gcc/c-decl.c b/gcc/c-decl.c index 61fcae0111a..16cf655b8b4 100644 --- a/gcc/c-decl.c +++ b/gcc/c-decl.c @@ -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) } } -/* 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; diff --git a/gcc/c-parse.in b/gcc/c-parse.in index 22bab99077a..d58b1ef6bbe 100644 --- a/gcc/c-parse.in +++ b/gcc/c-parse.in @@ -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++; $$ = add_stmt (build_stmt (DO_STMT, NULL_TREE, NULL_TREE)); @@ -2212,7 +2216,8 @@ do_stmt_start: DO_COND ($$) = error_mark_node; } c99_block_lineno_labeled_stmt WHILE { $$ = $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++; $$ = 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), $2); $$ = add_stmt ($2); } c99_block_lineno_labeled_stmt - { RECHAIN_STMTS ($6, WHILE_BODY ($6)); } + { c_in_iteration_stmt--; + RECHAIN_STMTS ($6, WHILE_BODY ($6)); } | do_stmt_start '(' expr ')' ';' { DO_COND ($1) = c_common_truthvalue_conversion ($3); } @@ -2318,14 +2325,18 @@ select_or_iter_stmt: FOR_COND ($2) = c_common_truthvalue_conversion ($6); } xexpr ')' - { FOR_EXPR ($2) = $9; } + { c_in_iteration_stmt++; + FOR_EXPR ($2) = $9; } c99_block_lineno_labeled_stmt - { RECHAIN_STMTS ($2, FOR_BODY ($2)); } + { RECHAIN_STMTS ($2, FOR_BODY ($2)); + c_in_iteration_stmt--;} | SWITCH '(' expr ')' { stmt_count++; - $$ = c_start_case ($3); } + $$ = 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; diff --git a/gcc/c-semantics.c b/gcc/c-semantics.c index a3e1b45343c..f3c61b42c35 100644 --- a/gcc/c-semantics.c +++ b/gcc/c-semantics.c @@ -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. */ diff --git a/gcc/c-tree.h b/gcc/c-tree.h index 3ba495395b2..f04e7b4edfa 100644 --- a/gcc/c-tree.h +++ b/gcc/c-tree.h @@ -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; +}; + /* in c-parse.in */ extern void c_parse_init (void);