aboutsummaryrefslogtreecommitdiff
path: root/gcc/fortran/resolve.c
diff options
context:
space:
mode:
authorTobias Schlüter <tobi@gcc.gnu.org>2009-03-29 19:15:48 +0200
committerTobias Schlüter <tobi@gcc.gnu.org>2009-03-29 19:15:48 +0200
commitd80c695ff0da09ebbb0d7b4370396e36d4e58180 (patch)
tree932f0cbc2ec95ee8d7f4af821c8414255f18bcaa /gcc/fortran/resolve.c
parenteeae74a1a98590abc9eda18b198ff92f473f2e36 (diff)
downloadgcc-d80c695ff0da09ebbb0d7b4370396e36d4e58180.zip
gcc-d80c695ff0da09ebbb0d7b4370396e36d4e58180.tar.gz
gcc-d80c695ff0da09ebbb0d7b4370396e36d4e58180.tar.bz2
re PR fortran/38507 (Bogus Warning: Deleted feature: GOTO jumps to END of construct)
fortran/ PR fortran/38507 * gfortran.h (gfc_st_label): Fix comment. (gfc_exec_op): Add statement code EXEC_END_BLOCK for end of block. * parse.c (accept_statement): Use EXEC_END_BLOCK for END IF and END SELECT with labels. (check_do_closure): Fix formatting. (parse_do_block): Fix typo in error message. * resolve.c (code_stack): Remove tail member. Update comment to new use of reachable_labels. (reachable_labels): Rename to ... (find_reachable_labels): ... this. Overhaul. Update preceding comment. (resolve_branch): Fix comment preceding function. Rewrite. (resolve_code): Update call to find_reachable_labels. Add code to deal with EXEC_END_BLOCK. * st.c (gfc_free_statement): Add code to deal with EXEC_END_BLOCK. * trans.c (gfc_trans_code): Likewise. testsuite/ * do_4.f: New. * goto_2.f90: Correct expected warnings. * goto_4.f90: Likewise. * goto_5.f90: New. From-SVN: r145245
Diffstat (limited to 'gcc/fortran/resolve.c')
-rw-r--r--gcc/fortran/resolve.c70
1 files changed, 27 insertions, 43 deletions
diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c
index 1d6ee85..7f7a806 100644
--- a/gcc/fortran/resolve.c
+++ b/gcc/fortran/resolve.c
@@ -43,11 +43,12 @@ seq_type;
typedef struct code_stack
{
- struct gfc_code *head, *current, *tail;
+ struct gfc_code *head, *current;
struct code_stack *prev;
/* This bitmap keeps track of the targets valid for a branch from
- inside this block. */
+ inside this block except for END {IF|SELECT}s of enclosing
+ blocks. */
bitmap reachable_labels;
}
code_stack;
@@ -5978,11 +5979,10 @@ resolve_transfer (gfc_code *code)
/*********** Toplevel code resolution subroutines ***********/
/* Find the set of labels that are reachable from this block. We also
- record the last statement in each block so that we don't have to do
- a linear search to find the END DO statements of the blocks. */
+ record the last statement in each block. */
static void
-reachable_labels (gfc_code *block)
+find_reachable_labels (gfc_code *block)
{
gfc_code *c;
@@ -5991,14 +5991,13 @@ reachable_labels (gfc_code *block)
cs_base->reachable_labels = bitmap_obstack_alloc (&labels_obstack);
- /* Collect labels in this block. */
+ /* Collect labels in this block. We don't keep those corresponding
+ to END {IF|SELECT}, these are checked in resolve_branch by going
+ up through the code_stack. */
for (c = block; c; c = c->next)
{
- if (c->here)
+ if (c->here && c->op != EXEC_END_BLOCK)
bitmap_set_bit (cs_base->reachable_labels, c->here->value);
-
- if (!c->next && cs_base->prev)
- cs_base->prev->tail = c;
}
/* Merge with labels from parent block. */
@@ -6010,7 +6009,7 @@ reachable_labels (gfc_code *block)
}
}
-/* Given a branch to a label and a namespace, if the branch is conforming.
+/* Given a branch to a label, see if the branch is conforming.
The code node describes where the branch is located. */
static void
@@ -6049,46 +6048,30 @@ resolve_branch (gfc_st_label *label, gfc_code *code)
branching statement. The hard work has been done by setting up
the bitmap reachable_labels. */
- if (!bitmap_bit_p (cs_base->reachable_labels, label->value))
- {
- /* The label is not in an enclosing block, so illegal. This was
- allowed in Fortran 66, so we allow it as extension. No
- further checks are necessary in this case. */
- gfc_notify_std (GFC_STD_LEGACY, "Label at %L is not in the same block "
- "as the GOTO statement at %L", &label->where,
- &code->loc);
- return;
- }
+ if (bitmap_bit_p (cs_base->reachable_labels, label->value))
+ return;
- /* Step four: Make sure that the branching target is legal if
- the statement is an END {SELECT,IF}. */
+ /* Step four: If we haven't found the label in the bitmap, it may
+ still be the label of the END of the enclosing block, in which
+ case we find it by going up the code_stack. */
for (stack = cs_base; stack; stack = stack->prev)
if (stack->current->next && stack->current->next->here == label)
break;
- if (stack && stack->current->next->op == EXEC_NOP)
+ if (stack)
{
- gfc_notify_std (GFC_STD_F95_DEL, "Deleted feature: GOTO at %L jumps to "
- "END of construct at %L", &code->loc,
- &stack->current->next->loc);
- return; /* We know this is not an END DO. */
+ gcc_assert (stack->current->next->op == EXEC_END_BLOCK);
+ return;
}
- /* Step five: Make sure that we're not jumping to the end of a DO
- loop from within the loop. */
-
- for (stack = cs_base; stack; stack = stack->prev)
- if ((stack->current->op == EXEC_DO
- || stack->current->op == EXEC_DO_WHILE)
- && stack->tail->here == label && stack->tail->op == EXEC_NOP)
- {
- gfc_notify_std (GFC_STD_F95_DEL, "Deleted feature: GOTO at %L jumps "
- "to END of construct at %L", &code->loc,
- &stack->tail->loc);
- return;
-
- }
+ /* The label is not in an enclosing block, so illegal. This was
+ allowed in Fortran 66, so we allow it as extension. No
+ further checks are necessary in this case. */
+ gfc_notify_std (GFC_STD_LEGACY, "Label at %L is not in the same block "
+ "as the GOTO statement at %L", &label->where,
+ &code->loc);
+ return;
}
@@ -6669,7 +6652,7 @@ resolve_code (gfc_code *code, gfc_namespace *ns)
frame.head = code;
cs_base = &frame;
- reachable_labels (code);
+ find_reachable_labels (code);
for (; code; code = code->next)
{
@@ -6727,6 +6710,7 @@ resolve_code (gfc_code *code, gfc_namespace *ns)
switch (code->op)
{
case EXEC_NOP:
+ case EXEC_END_BLOCK:
case EXEC_CYCLE:
case EXEC_PAUSE:
case EXEC_STOP: