Eliad
Eliad

Reputation: 926

impure function inside a DO CONCURRENT block

Impure functions are not allowed to be used inside DO CONCURRENT blocks:

  ! Not allowed
  do concurrent(i=0:10)
    y(i) = impure_func(i)
  end do

But gfortran (v12.2.0) allows this if the impure function is inside a BLOCK inside the DO CONCURRENT block:

  ! Allowed
  do concurrent(i=0:10)
    block
      y(i) = impure_func(i)
    end block
  end do

What I want to know is that

  1. Why is this allowed? Is this a bug for is it a feature?
  2. If it is not a gfortran bug, how are the side-effects of using an impure function inside a DO CONCURRENT block avoided. Does gfortran prevent parallelizations of such a block?

Upvotes: 2

Views: 99

Answers (1)

steve
steve

Reputation: 900

Unreported bugs typically go unfixed.

diff --git a/gcc/fortran/resolve.cc b/gcc/fortran/resolve.cc
index b8c908b51e9..1b98be205b4 100644
--- a/gcc/fortran/resolve.cc
+++ b/gcc/fortran/resolve.cc
@@ -3228,6 +3228,24 @@ pure_stmt_function (gfc_expr *e, gfc_symbol *sym)
 static bool check_pure_function (gfc_expr *e)
 {
   const char *name = NULL;
+  code_stack *stack;
+  bool saw_block = false;
+  
+  /* A BLOCK construct within a DO CONCURRENT construct leads to 
+     gfc_do_concurrent_flag = 0 when the check for an impure function
+     occurs.  Check the stack to see if the source code has a nested
+     BLOCK construct.  */
+  for (stack = cs_base; stack; stack = stack->prev)
+    {
+      if (stack->current->op == EXEC_BLOCK) saw_block = true;
+      if (saw_block && stack->current->op == EXEC_DO_CONCURRENT)
+   {
+     gfc_error ("Reference to impure function at %L inside a "
+            "DO CONCURRENT", &e->where);
+     return false;
+   }
+    }
+
   if (!gfc_pure_function (e, &name) && name)
     {
       if (forall_flag)

Upvotes: 3

Related Questions