aboutsummaryrefslogtreecommitdiff
path: root/gcc/fortran/parse.c
diff options
context:
space:
mode:
authorDaniel Kraft <d@domob.eu>2009-09-29 09:42:42 +0200
committerDaniel Kraft <domob@gcc.gnu.org>2009-09-29 09:42:42 +0200
commit9abe5e56e20294d899363abc8898d4fa6a72e2f7 (patch)
tree8bbc9942644ae27a9137a47480f2dfeeba5ab54c /gcc/fortran/parse.c
parent9b13eb8457f5b02769cfd6762c8885d58be80f78 (diff)
downloadgcc-9abe5e56e20294d899363abc8898d4fa6a72e2f7.zip
gcc-9abe5e56e20294d899363abc8898d4fa6a72e2f7.tar.gz
gcc-9abe5e56e20294d899363abc8898d4fa6a72e2f7.tar.bz2
re PR fortran/39626 (Correctly implement details of Fortran 2008 BLOCK construct)
2009-09-29 Daniel Kraft <d@domob.eu> PR fortran/39626 * gfortran.h (enum gfc_statement): Add ST_BLOCK and ST_END_BLOCK. (struct gfc_namespace): Convert flags to bit-fields and add flag `construct_entities' for use with BLOCK constructs. (enum gfc_exec_code): Add EXEC_BLOCK. (struct gfc_code): Add namespace field to union for EXEC_BLOCK. * match.h (gfc_match_block): New prototype. * parse.h (enum gfc_compile_state): Add COMP_BLOCK. * trans.h (gfc_process_block_locals): New prototype. (gfc_trans_deferred_vars): Made public, new prototype. * trans-stmt.h (gfc_trans_block_construct): New prototype. * decl.c (gfc_match_end): Handle END BLOCK correctly. (gfc_match_intent): Error if inside of BLOCK. (gfc_match_optional), (gfc_match_value): Ditto. * match.c (gfc_match_block): New routine. * parse.c (decode_statement): Handle BLOCK statement. (case_exec_markers): Add ST_BLOCK. (case_end): Add ST_END_BLOCK. (gfc_ascii_statement): Handle ST_BLOCK and ST_END_BLOCK. (parse_spec): Check for statements not allowed inside of BLOCK. (parse_block_construct): New routine. (parse_executable): Parse BLOCKs. (parse_progunit): Disallow CONTAINS in BLOCK constructs. * resolve.c (is_illegal_recursion): Find real container procedure and don't get confused by BLOCK constructs. (resolve_block_construct): New routine. (gfc_resolve_blocks), (resolve_code): Handle EXEC_BLOCK. * st.c (gfc_free_statement): Handle EXEC_BLOCK statements. * trans-decl.c (saved_local_decls): New static variable. (add_decl_as_local): New routine. (gfc_finish_var_decl): Add variable as local if inside BLOCK. (gfc_trans_deferred_vars): Make public. (gfc_process_block_locals): New routine. * trans-stmt.c (gfc_trans_block_construct): New routine. * trans.c (gfc_trans_code): Handle EXEC_BLOCK statements. 2009-09-29 Daniel Kraft <d@domob.eu> PR fortran/39626 * gfortran.dg/block_1.f08: New test. * gfortran.dg/block_2.f08: New test. * gfortran.dg/block_3.f90: New test. * gfortran.dg/block_4.f08: New test. * gfortran.dg/block_5.f08: New test. * gfortran.dg/block_6.f08: New test. * gfortran.dg/block_7.f08: New test. * gfortran.dg/block_8.f08: New test. From-SVN: r152266
Diffstat (limited to 'gcc/fortran/parse.c')
-rw-r--r--gcc/fortran/parse.c109
1 files changed, 98 insertions, 11 deletions
diff --git a/gcc/fortran/parse.c b/gcc/fortran/parse.c
index 93a6cfd..e6b5dbb 100644
--- a/gcc/fortran/parse.c
+++ b/gcc/fortran/parse.c
@@ -289,7 +289,7 @@ decode_statement (void)
gfc_undo_symbols ();
gfc_current_locus = old_locus;
- /* Check for the IF, DO, SELECT, WHERE and FORALL statements, which
+ /* Check for the IF, DO, SELECT, WHERE, FORALL and BLOCK statements, which
might begin with a block label. The match functions for these
statements are unusual in that their keyword is not seen before
the matcher is called. */
@@ -309,6 +309,7 @@ decode_statement (void)
gfc_undo_symbols ();
gfc_current_locus = old_locus;
+ match (NULL, gfc_match_block, ST_BLOCK);
match (NULL, gfc_match_do, ST_DO);
match (NULL, gfc_match_select, ST_SELECT_CASE);
@@ -933,7 +934,8 @@ next_statement (void)
/* Statements that mark other executable statements. */
-#define case_exec_markers case ST_DO: case ST_FORALL_BLOCK: case ST_IF_BLOCK: \
+#define case_exec_markers case ST_DO: case ST_FORALL_BLOCK: \
+ case ST_IF_BLOCK: case ST_BLOCK: \
case ST_WHERE_BLOCK: case ST_SELECT_CASE: 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: \
@@ -952,7 +954,8 @@ next_statement (void)
are detected in gfc_match_end(). */
#define case_end case ST_END_BLOCK_DATA: case ST_END_FUNCTION: \
- case ST_END_PROGRAM: case ST_END_SUBROUTINE
+ case ST_END_PROGRAM: case ST_END_SUBROUTINE: \
+ case ST_END_BLOCK
/* Push a new state onto the stack. */
@@ -1142,6 +1145,9 @@ gfc_ascii_statement (gfc_statement st)
case ST_BACKSPACE:
p = "BACKSPACE";
break;
+ case ST_BLOCK:
+ p = "BLOCK";
+ break;
case ST_BLOCK_DATA:
p = "BLOCK DATA";
break;
@@ -1190,6 +1196,9 @@ gfc_ascii_statement (gfc_statement st)
case ST_ELSEWHERE:
p = "ELSEWHERE";
break;
+ case ST_END_BLOCK:
+ p = "END BLOCK";
+ break;
case ST_END_BLOCK_DATA:
p = "END BLOCK DATA";
break;
@@ -2391,6 +2400,27 @@ parse_spec (gfc_statement st)
}
loop:
+
+ /* If we're inside a BLOCK construct, some statements are disallowed.
+ Check this here. Attribute declaration statements like INTENT, OPTIONAL
+ or VALUE are also disallowed, but they don't have a particular ST_*
+ key so we have to check for them individually in their matcher routine. */
+ if (gfc_current_state () == COMP_BLOCK)
+ switch (st)
+ {
+ case ST_IMPLICIT:
+ case ST_IMPLICIT_NONE:
+ case ST_NAMELIST:
+ case ST_COMMON:
+ case ST_EQUIVALENCE:
+ case ST_STATEMENT_FUNCTION:
+ gfc_error ("%s statement is not allowed inside of BLOCK at %C",
+ gfc_ascii_statement (st));
+ break;
+
+ default:
+ break;
+ }
/* If we find a statement that can not be followed by an IMPLICIT statement
(and thus we can expect to see none any further), type the function result
@@ -2908,6 +2938,58 @@ check_do_closure (void)
}
+/* Parse a series of contained program units. */
+
+static void parse_progunit (gfc_statement);
+
+
+/* Parse a BLOCK construct. */
+
+static void
+parse_block_construct (void)
+{
+ gfc_namespace* parent_ns;
+ gfc_namespace* my_ns;
+ gfc_state_data s;
+
+ gfc_notify_std (GFC_STD_F2008, "Fortran 2008: BLOCK construct at %C");
+
+ parent_ns = gfc_current_ns;
+ my_ns = gfc_get_namespace (parent_ns, 1);
+ my_ns->construct_entities = 1;
+
+ /* Give the BLOCK a symbol of flavor LABEL; this is later needed for correct
+ code generation (so it must not be NULL).
+ We set its recursive argument if our container procedure is recursive, so
+ that local variables are accordingly placed on the stack when it
+ will be necessary. */
+ if (gfc_new_block)
+ my_ns->proc_name = gfc_new_block;
+ else
+ {
+ gfc_try t;
+
+ gfc_get_symbol ("block@", my_ns, &my_ns->proc_name);
+ t = gfc_add_flavor (&my_ns->proc_name->attr, FL_LABEL,
+ my_ns->proc_name->name, NULL);
+ gcc_assert (t == SUCCESS);
+ }
+ my_ns->proc_name->attr.recursive = parent_ns->proc_name->attr.recursive;
+
+ new_st.op = EXEC_BLOCK;
+ new_st.ext.ns = my_ns;
+ accept_statement (ST_BLOCK);
+
+ push_state (&s, COMP_BLOCK, my_ns->proc_name);
+ gfc_current_ns = my_ns;
+
+ parse_progunit (ST_NONE);
+
+ gfc_current_ns = parent_ns;
+ pop_state ();
+}
+
+
/* Parse a DO loop. Note that the ST_CYCLE and ST_EXIT statements are
handled inside of parse_executable(), because they aren't really
loop statements. */
@@ -3301,6 +3383,10 @@ parse_executable (gfc_statement st)
return ST_IMPLIED_ENDDO;
break;
+ case ST_BLOCK:
+ parse_block_construct ();
+ break;
+
case ST_IF_BLOCK:
parse_if_block ();
break;
@@ -3359,11 +3445,6 @@ parse_executable (gfc_statement st)
}
-/* Parse a series of contained program units. */
-
-static void parse_progunit (gfc_statement);
-
-
/* Fix the symbols for sibling functions. These are incorrectly added to
the child namespace as the parser didn't know about this procedure. */
@@ -3545,7 +3626,7 @@ parse_contained (int module)
}
-/* Parse a PROGRAM, SUBROUTINE or FUNCTION unit. */
+/* Parse a PROGRAM, SUBROUTINE, FUNCTION unit or BLOCK construct. */
static void
parse_progunit (gfc_statement st)
@@ -3560,7 +3641,10 @@ parse_progunit (gfc_statement st)
unexpected_eof ();
case ST_CONTAINS:
- goto contains;
+ /* This is not allowed within BLOCK! */
+ if (gfc_current_state () != COMP_BLOCK)
+ goto contains;
+ break;
case_end:
accept_statement (st);
@@ -3584,7 +3668,10 @@ loop:
unexpected_eof ();
case ST_CONTAINS:
- goto contains;
+ /* This is not allowed within BLOCK! */
+ if (gfc_current_state () != COMP_BLOCK)
+ goto contains;
+ break;
case_end:
accept_statement (st);