Hi all, attached are two patches one for trunk and one for the gcc-5-branch, which fix an ICE when BLOCK statements are not closed correctly (too many END BLOCKs). Unfortunately did the patch I tailored for gcc-5 not work on trunk.
GCC 5: The ICE is prevented by making sure that gfc_current_ns is not set to NULL, when too many closing END BLOCK statements are found. This may lead to gfortran be in the wrong namespace, but gfortran is already in error. Therefore this does not matter any more. We just need to exit cleanly. GCC 6/trunk: Here the ICE is prevented by making sure, that unnesting of BLOCK namespaces is only done, when the END encountered is not the one of a BLOCK. This prevents gfortran from removing a correctly initialized and for further analysis required namespace. Bootstrapped and regtested ok on x86_64-linux-gnu/F23. Ok for trunk and gcc-5-branch, respectively? Regards, Andre -- Andre Vehreschild * Email: vehre ad gmx dot de
diff --git a/gcc/fortran/decl.c b/gcc/fortran/decl.c index 2708413..adea3f3 100644 --- a/gcc/fortran/decl.c +++ b/gcc/fortran/decl.c @@ -6454,9 +6454,16 @@ cleanup: prev_ns = ns; ns = ns->sibling; } - - gfc_free_namespace (gfc_current_ns); - gfc_current_ns = parent_ns; + + if (parent_ns) + { + /* Free the current namespace only when the parent one exists. This + prevents an ICE when more END BLOCK then BLOCK statements are + present. It does not mean any further harm, because we already + have errored. */ + gfc_free_namespace (gfc_current_ns); + gfc_current_ns = parent_ns; + } } return MATCH_ERROR; diff --git a/gcc/testsuite/gfortran.dg/block_14.f08 b/gcc/testsuite/gfortran.dg/block_14.f08 new file mode 100644 index 0000000..4e5903b --- /dev/null +++ b/gcc/testsuite/gfortran.dg/block_14.f08 @@ -0,0 +1,21 @@ +! { dg-do compile } +! +! Contributed by Tobias Burnus <bur...@gcc.gnu.org> +! Check fix for PR62536 works as expected. + +function f2 (x) +implicit none + integer f2, x + block + block named ! { dg-error "Unclassifiable statement" } + integer a ! should be SAVEd + a = a + x ! should increment by y every time + f2 = a + end block named ! { dg-error "Syntax error in END BLOCK statement" } + end block ! { dg-error "Expected block name of " } + return +endfunction ! { dg-error "Expecting END BLOCK statement" } + +end ! { dg-error "END BLOCK statement expected" } +! { dg-excess-errors "Previous error cause unexpected end of file." } +
gcc/testsuite/ChangeLog: 2016-01-27 Andre Vehreschild <ve...@gcc.gnu.org> PR fortran/62536 * gfortran.dg/block_14.f08: New test. gcc/fortran/ChangeLog: 2016-01-27 Andre Vehreschild <ve...@gcc.gnu.org> PR fortran/62536 * decl.c: Prevent setting gfc_current_ns to NULL when block statement's nesting is incomplete. There is already an error conditon, so having gfc_current_ns pointing to an eventually wrong namespace does not matter that much.
diff --git a/gcc/fortran/decl.c b/gcc/fortran/decl.c index 7c0e011..df81369 100644 --- a/gcc/fortran/decl.c +++ b/gcc/fortran/decl.c @@ -6327,6 +6327,7 @@ gfc_match_end (gfc_statement *st) gfc_namespace *parent_ns, *ns, *prev_ns; gfc_namespace **nsp; bool abreviated_modproc_decl; + bool got_matching_end = false; old_loc = gfc_current_locus; if (gfc_match ("end") != MATCH_YES) @@ -6510,6 +6511,8 @@ gfc_match_end (gfc_statement *st) ? "END PROCEDURE" : gfc_ascii_statement(*st), &old_loc); goto cleanup; } + else + got_matching_end = true; old_loc = gfc_current_locus; /* If we're at the end, make sure a block name wasn't required. */ @@ -6581,7 +6584,7 @@ cleanup: /* If we are missing an END BLOCK, we created a half-ready namespace. Remove it from the parent namespace's sibling list. */ - while (state == COMP_BLOCK) + while (state == COMP_BLOCK && !got_matching_end) { parent_ns = gfc_current_ns->parent; @@ -6601,7 +6604,7 @@ cleanup: prev_ns = ns; ns = ns->sibling; } - + gfc_free_namespace (gfc_current_ns); gfc_current_ns = parent_ns; gfc_state_stack = gfc_state_stack->previous; diff --git a/gcc/testsuite/gfortran.dg/block_15.f08 b/gcc/testsuite/gfortran.dg/block_15.f08 new file mode 100644 index 0000000..fd1ca55 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/block_15.f08 @@ -0,0 +1,20 @@ +! { dg-do compile } +! +! Contributed by Tobias Burnus <bur...@gcc.gnu.org> +! Check fix for PR62536 works as expected. + +function f2 (x) +implicit none + integer f2, x + block + block named ! { dg-error "Unclassifiable statement" } + integer a ! should be SAVEd + a = a + x ! should increment by y every time + f2 = a + end block named ! { dg-error "Syntax error in END BLOCK statement" } + end block + return +endfunction + +end + diff --git a/gcc/testsuite/gfortran.dg/block_end_error_1.f90 b/gcc/testsuite/gfortran.dg/block_end_error_1.f90 index e7dcdfa..4bbe89b 100644 --- a/gcc/testsuite/gfortran.dg/block_end_error_1.f90 +++ b/gcc/testsuite/gfortran.dg/block_end_error_1.f90 @@ -6,5 +6,5 @@ subroutine s block end block named ! { dg-error "Syntax error in END BLOCK statement" } return -endsubroutine +endsubroutine ! { dg-error "Expecting END BLOCK statement" } ! { dg-prune-output "Unexpected end of file" }
gcc/fortran/ChangeLog: 2016-01-27 Andre Vehreschild <ve...@gcc.gnu.org> PR fortran/62536 * decl.c (gfc_match_end): Only unnest and remove BLOCK namespaces when the END encountered does not match a BLOCK's end. gcc/testsuite/ChangeLog: 2016-01-27 Andre Vehreschild <ve...@gcc.gnu.org> PR fortran/62536 * gfortran.dg/block_15.f08: New test. * gfortran.dg/block_end_error_1.f90: Need to catch additional error on incorrectly closed BLOCK.