[PATCH] fortran: Fix DO CONCURRENT nested-in-block iterator counting [PR123943]

Christopher Albert <[email protected]>
Newsgroups gmane.comp.gcc.patches,gmane.comp.gcc.fortran
Message-ID <[email protected]>
Fix iterator-depth pre-counting in gfc_resolve_forall for nested
DO CONCURRENT/FORALL constructs inside block arms (e.g. IF/ELSE,
SELECT CASE).  The previous logic only scanned a flat next-chain,
which could undercount and trigger an ICE assertion.

Add a regression test based on a reduced testcase from Harald Anlauf.
Adjust wording in one comment to avoid GNU-style checker complaints.

	PR fortran/123943

Co-authored-by: Harald Anlauf <[email protected]>
Signed-off-by: Christopher Albert <[email protected]>
---
 gcc/fortran/resolve.cc                 | 53 +++++++++++++++++---------
 gcc/testsuite/gfortran.dg/pr123943.f90 | 48 +++++++++++++++++++++++
 2 files changed, 83 insertions(+), 18 deletions(-)
 create mode 100644 gcc/testsuite/gfortran.dg/pr123943.f90

diff --git a/gcc/fortran/resolve.cc b/gcc/fortran/resolve.cc
index e5b36234d7e..d98c2d65476 100644
--- a/gcc/fortran/resolve.cc
+++ b/gcc/fortran/resolve.cc
@@ -12433,33 +12433,50 @@ gfc_resolve_forall_body (gfc_code *code, int nvar, gfc_expr **var_expr)
    nested forall constructs. This is used to allocate the needed memory
    in gfc_resolve_forall.  */
 
+static int gfc_count_forall_iterators (gfc_code *code);
+
+/* Return the deepest nested FORALL/DO CONCURRENT iterator count in CODE's
+   next-chain, descending into block arms such as IF/ELSE branches.  */
+
+static int
+gfc_max_forall_iterators_in_chain (gfc_code *code)
+{
+  int max_iters = 0;
+
+  for (gfc_code *c = code; c; c = c->next)
+    {
+      int sub_iters = 0;
+
+      if (c->op == EXEC_FORALL || c->op == EXEC_DO_CONCURRENT)
+	sub_iters = gfc_count_forall_iterators (c);
+      else if (c->block)
+	for (gfc_code *b = c->block; b; b = b->block)
+	  {
+	    int arm_iters = gfc_max_forall_iterators_in_chain (b->next);
+	    if (arm_iters > sub_iters)
+	      sub_iters = arm_iters;
+	  }
+
+      if (sub_iters > max_iters)
+	max_iters = sub_iters;
+    }
+
+  return max_iters;
+}
+
+
 static int
 gfc_count_forall_iterators (gfc_code *code)
 {
-  int max_iters, sub_iters, current_iters;
+  int current_iters = 0;
   gfc_forall_iterator *fa;
 
   gcc_assert (code->op == EXEC_FORALL || code->op == EXEC_DO_CONCURRENT);
-  max_iters = 0;
-  current_iters = 0;
 
   for (fa = code->ext.concur.forall_iterator; fa; fa = fa->next)
-    current_iters ++;
-
-  code = code->block->next;
-
-  while (code)
-    {
-      if (code->op == EXEC_FORALL || code->op == EXEC_DO_CONCURRENT)
-        {
-          sub_iters = gfc_count_forall_iterators (code);
-          if (sub_iters > max_iters)
-            max_iters = sub_iters;
-        }
-      code = code->next;
-    }
+    current_iters++;
 
-  return current_iters + max_iters;
+  return current_iters + gfc_max_forall_iterators_in_chain (code->block->next);
 }
 
 
diff --git a/gcc/testsuite/gfortran.dg/pr123943.f90 b/gcc/testsuite/gfortran.dg/pr123943.f90
new file mode 100644
index 00000000000..6d6461317c2
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr123943.f90
@@ -0,0 +1,48 @@
+! { dg-do compile }
+! PR fortran/123943
+!
+! Nested DO CONCURRENT in block constructs must not ICE in gfc_resolve_forall.
+! Reduced testcase by Harald Anlauf <[email protected]>
+
+subroutine nested_in_if
+  implicit none
+  integer :: k, l
+
+  do concurrent (k = 1:5)
+    if (k == 3) then
+      do concurrent (l = 1:4)
+      end do
+    end if
+  end do
+end subroutine nested_in_if
+
+
+subroutine nested_in_if_else
+  implicit none
+  integer :: k, l
+
+  do concurrent (k = 1:5)
+    if (k == 3) then
+      do concurrent (l = 1:4)
+      end do
+    else
+      do concurrent (l = 1:2)
+      end do
+    end if
+  end do
+end subroutine nested_in_if_else
+
+
+subroutine nested_in_select_case
+  implicit none
+  integer :: k, l
+
+  do concurrent (k = 1:5)
+    select case (k)
+    case (3)
+      do concurrent (l = 1:4)
+      end do
+    case default
+    end select
+  end do
+end subroutine nested_in_select_case
-- 
2.53.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.