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.

Reply via email to