From ac6c481d5734d0aea887d1d598da10dc2c9910cd Mon Sep 17 00:00:00 2001 From: amylaar Date: Tue, 17 Feb 1998 10:26:44 +0000 Subject: [PATCH] * rtl.h (force_line_numbers, restore_line_number_status): Declare. * emit-rtl.c (force_line_numbers, restore_line_number_status): New functions. * stmt.c (struct nesting): Replace seenlabel with line_number_status. (expand_start_case): Adjust to this change. (check_seenlabel): New function. (pushcase, pushcase_range, expand_endcase): Use it. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@18031 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/emit-rtl.c | 22 ++++++++++++ gcc/rtl.h | 5 +++ gcc/stmt.c | 105 +++++++++++++++++++++++++-------------------------------- 3 files changed, 72 insertions(+), 60 deletions(-) diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c index 739ca53fde1..3da217ced04 100644 --- a/gcc/emit-rtl.c +++ b/gcc/emit-rtl.c @@ -3457,3 +3457,25 @@ init_emit_once (line_numbers) pic_offset_table_rtx = gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM); #endif } + +/* Query and clear/ restore no_line_numbers. This is used by the + switch / case handling in stmt.c to give proper line numbers in + warnings about unreachable code. */ + +int +force_line_numbers () +{ + int old = no_line_numbers; + + no_line_numbers = 0; + if (old) + force_next_line_note (); + return old; +} + +void +restore_line_number_status (old_value) + int old_value; +{ + no_line_numbers = old_value; +} diff --git a/gcc/rtl.h b/gcc/rtl.h index f75ca1b3984..81094753792 100644 --- a/gcc/rtl.h +++ b/gcc/rtl.h @@ -1147,6 +1147,11 @@ extern void reorder_insns_with_line_notes PROTO ((rtx, rtx, rtx)); extern void emit_insn_after_with_line_notes PROTO ((rtx, rtx, rtx)); extern enum rtx_code classify_insn PROTO ((rtx)); extern rtx emit PROTO ((rtx)); +/* Query and clear/ restore no_line_numbers. This is used by the + switch / case handling in stmt.c to give proper line numbers in + warnings about unreachable code. */ +int force_line_numbers PROTO((void)); +void restore_line_number_status PROTO((int old_value)); /* In insn-emit.c */ extern void add_clobbers PROTO ((rtx, int)); diff --git a/gcc/stmt.c b/gcc/stmt.c index 42ebecbb4e4..57caad79ca9 100644 --- a/gcc/stmt.c +++ b/gcc/stmt.c @@ -316,8 +316,10 @@ struct nesting int num_ranges; /* Name of this kind of statement, for warnings. */ char *printname; - /* Nonzero if a case label has been seen in this case stmt. */ - char seenlabel; + /* Used to save no_line_numbers till we see the first case label. + We set this to -1 when we see the first case label in this + case statement. */ + int line_number_status; } case_stmt; } data; }; @@ -3759,7 +3761,7 @@ expand_start_case (exit_flag, expr, type, printname) thiscase->data.case_stmt.default_label = 0; thiscase->data.case_stmt.num_ranges = 0; thiscase->data.case_stmt.printname = printname; - thiscase->data.case_stmt.seenlabel = 0; + thiscase->data.case_stmt.line_number_status = force_line_numbers (); case_stack = thiscase; nesting_stack = thiscase; @@ -3822,6 +3824,41 @@ case_index_expr_type () return 0; } +static void +check_seenlabel () +{ + /* If this is the first label, warn if any insns have been emitted. */ + if (case_stack->data.case_stmt.line_number_status >= 0) + { + rtx insn; + + restore_line_number_status + (case_stack->data.case_stmt.line_number_status); + case_stack->data.case_stmt.line_number_status = -1; + + for (insn = case_stack->data.case_stmt.start; + insn; + insn = NEXT_INSN (insn)) + { + if (GET_CODE (insn) == CODE_LABEL) + break; + if (GET_CODE (insn) != NOTE + && (GET_CODE (insn) != INSN || GET_CODE (PATTERN (insn)) != USE)) + { + do + insn = PREV_INSN (insn); + while (GET_CODE (insn) != NOTE || NOTE_LINE_NUMBER (insn) < 0); + + warning_with_file_and_line (NOTE_SOURCE_FILE(insn), + NOTE_LINE_NUMBER(insn), + "unreachable code at beginning of %s", + case_stack->data.case_stmt.printname); + break; + } + } + } +} + /* Accumulate one case or default label inside a case or switch statement. VALUE is the value of the case (a null pointer, for a default label). The function CONVERTER, when applied to arguments T and V, @@ -3858,6 +3895,8 @@ pushcase (value, converter, label, duplicate) index_type = TREE_TYPE (case_stack->data.case_stmt.index_expr); nominal_type = case_stack->data.case_stmt.nominal_type; + check_seenlabel (); + /* If the index is erroneous, avoid more problems: pretend to succeed. */ if (index_type == error_mark_node) return 0; @@ -3866,27 +3905,6 @@ pushcase (value, converter, label, duplicate) if (value != 0) value = (*converter) (nominal_type, value); - /* If this is the first label, warn if any insns have been emitted. */ - if (case_stack->data.case_stmt.seenlabel == 0) - { - rtx insn; - for (insn = case_stack->data.case_stmt.start; - insn; - insn = NEXT_INSN (insn)) - { - if (GET_CODE (insn) == CODE_LABEL) - break; - if (GET_CODE (insn) != NOTE - && (GET_CODE (insn) != INSN || GET_CODE (PATTERN (insn)) != USE)) - { - warning ("unreachable code at beginning of %s", - case_stack->data.case_stmt.printname); - break; - } - } - } - case_stack->data.case_stmt.seenlabel = 1; - /* Fail if this value is out of range for the actual type of the index (which may be narrower than NOMINAL_TYPE). */ if (value != 0 && ! int_fits_type_p (value, index_type)) @@ -3943,26 +3961,7 @@ pushcase_range (value1, value2, converter, label, duplicate) if (index_type == error_mark_node) return 0; - /* If this is the first label, warn if any insns have been emitted. */ - if (case_stack->data.case_stmt.seenlabel == 0) - { - rtx insn; - for (insn = case_stack->data.case_stmt.start; - insn; - insn = NEXT_INSN (insn)) - { - if (GET_CODE (insn) == CODE_LABEL) - break; - if (GET_CODE (insn) != NOTE - && (GET_CODE (insn) != INSN || GET_CODE (PATTERN (insn)) != USE)) - { - warning ("unreachable code at beginning of %s", - case_stack->data.case_stmt.printname); - break; - } - } - } - case_stack->data.case_stmt.seenlabel = 1; + check_seenlabel (); /* Convert VALUEs to type in which the comparisons are nominally done and replace any unspecified value with the corresponding bound. */ @@ -4613,6 +4612,8 @@ expand_end_case (orig_index) do_pending_stack_adjust (); + check_seenlabel (); + /* An ERROR_MARK occurs for various reasons including invalid data type. */ if (index_type != error_mark_node) { @@ -4625,22 +4626,6 @@ expand_end_case (orig_index) && TREE_CODE (index_expr) != INTEGER_CST) check_for_full_enumeration_handling (TREE_TYPE (orig_index)); - /* If this is the first label, warn if any insns have been emitted. */ - if (thiscase->data.case_stmt.seenlabel == 0) - { - rtx insn; - for (insn = get_last_insn (); - insn != case_stack->data.case_stmt.start; - insn = PREV_INSN (insn)) - if (GET_CODE (insn) != NOTE - && (GET_CODE (insn) != INSN || GET_CODE (PATTERN (insn))!= USE)) - { - warning ("unreachable code at beginning of %s", - case_stack->data.case_stmt.printname); - break; - } - } - /* If we don't have a default-label, create one here, after the body of the switch. */ if (thiscase->data.case_stmt.default_label == 0) -- 2.11.0