fortrangfortran

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?

Solution

  • 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)