aboutsummaryrefslogtreecommitdiff
path: root/gcc/fortran/parse.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/fortran/parse.c')
-rw-r--r--gcc/fortran/parse.c95
1 files changed, 91 insertions, 4 deletions
diff --git a/gcc/fortran/parse.c b/gcc/fortran/parse.c
index 8950b6a..caea16b 100644
--- a/gcc/fortran/parse.c
+++ b/gcc/fortran/parse.c
@@ -426,6 +426,7 @@ decode_statement (void)
match (NULL, gfc_match_critical, ST_CRITICAL);
match (NULL, gfc_match_select, ST_SELECT_CASE);
match (NULL, gfc_match_select_type, ST_SELECT_TYPE);
+ match (NULL, gfc_match_select_rank, ST_SELECT_RANK);
/* General statement matching: Instead of testing every possible
statement, we eliminate most possibilities by peeking at the
@@ -546,6 +547,7 @@ decode_statement (void)
break;
case 'r':
+ match ("rank", gfc_match_rank_is, ST_RANK);
match ("read", gfc_match_read, ST_READ);
match ("return", gfc_match_return, ST_RETURN);
match ("rewind", gfc_match_rewind, ST_REWIND);
@@ -1537,7 +1539,7 @@ next_statement (void)
#define case_exec_markers case ST_DO: case ST_FORALL_BLOCK: \
case ST_IF_BLOCK: case ST_BLOCK: case ST_ASSOCIATE: \
case ST_WHERE_BLOCK: case ST_SELECT_CASE: case ST_SELECT_TYPE: \
- case ST_OMP_PARALLEL: \
+ case ST_SELECT_RANK: case ST_OMP_PARALLEL: \
case ST_OMP_PARALLEL_SECTIONS: case ST_OMP_SECTIONS: case ST_OMP_ORDERED: \
case ST_OMP_CRITICAL: case ST_OMP_MASTER: case ST_OMP_SINGLE: \
case ST_OMP_DO: case ST_OMP_PARALLEL_DO: case ST_OMP_ATOMIC: \
@@ -2077,12 +2079,18 @@ gfc_ascii_statement (gfc_statement st)
case ST_SELECT_TYPE:
p = "SELECT TYPE";
break;
+ case ST_SELECT_RANK:
+ p = "SELECT RANK";
+ break;
case ST_TYPE_IS:
p = "TYPE IS";
break;
case ST_CLASS_IS:
p = "CLASS IS";
break;
+ case ST_RANK:
+ p = "RANK";
+ break;
case ST_SEQUENCE:
p = "SEQUENCE";
break;
@@ -4179,7 +4187,7 @@ parse_select_block (void)
reject_statement ();
}
- /* At this point, we're got a nonempty select block. */
+ /* At this point, we've got a nonempty select block. */
cp = new_level (cp);
*cp = new_st;
@@ -4263,7 +4271,7 @@ parse_select_type_block (void)
reject_statement ();
}
- /* At this point, we're got a nonempty select block. */
+ /* At this point, we've got a nonempty select block. */
cp = new_level (cp);
*cp = new_st;
@@ -4306,6 +4314,81 @@ done:
}
+/* Parse a SELECT RANK construct. */
+
+static void
+parse_select_rank_block (void)
+{
+ gfc_statement st;
+ gfc_code *cp;
+ gfc_state_data s;
+
+ gfc_current_ns = new_st.ext.block.ns;
+ accept_statement (ST_SELECT_RANK);
+
+ cp = gfc_state_stack->tail;
+ push_state (&s, COMP_SELECT_RANK, gfc_new_block);
+
+ /* Make sure that the next statement is a RANK IS or RANK DEFAULT. */
+ for (;;)
+ {
+ st = next_statement ();
+ if (st == ST_NONE)
+ unexpected_eof ();
+ if (st == ST_END_SELECT)
+ /* Empty SELECT CASE is OK. */
+ goto done;
+ if (st == ST_RANK)
+ break;
+
+ gfc_error ("Expected RANK or RANK DEFAULT "
+ "following SELECT RANK at %C");
+
+ reject_statement ();
+ }
+
+ /* At this point, we've got a nonempty select block. */
+ cp = new_level (cp);
+ *cp = new_st;
+
+ accept_statement (st);
+
+ do
+ {
+ st = parse_executable (ST_NONE);
+ switch (st)
+ {
+ case ST_NONE:
+ unexpected_eof ();
+
+ case ST_RANK:
+ cp = new_level (gfc_state_stack->head);
+ *cp = new_st;
+ gfc_clear_new_st ();
+
+ accept_statement (st);
+ /* Fall through */
+
+ case ST_END_SELECT:
+ break;
+
+ /* Can't have an executable statement because of
+ parse_executable(). */
+ default:
+ unexpected_statement (st);
+ break;
+ }
+ }
+ while (st != ST_END_SELECT);
+
+done:
+ pop_state ();
+ accept_statement (st);
+ gfc_current_ns = gfc_current_ns->parent;
+ select_type_pop ();
+}
+
+
/* Given a symbol, make sure it is not an iteration variable for a DO
statement. This subroutine is called when the symbol is seen in a
context that causes it to become redefined. If the symbol is an
@@ -5360,6 +5443,10 @@ parse_executable (gfc_statement st)
parse_select_type_block ();
break;
+ case ST_SELECT_RANK:
+ parse_select_rank_block ();
+ break;
+
case ST_DO:
parse_do_block ();
if (check_do_closure () == 1)
@@ -6410,7 +6497,7 @@ done:
if (flag_dump_fortran_global)
gfc_dump_global_symbols (stdout);
-
+
gfc_end_source_files ();
return true;