https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110547

            Bug ID: 110547
           Summary: Improper finalization calls with OpenMP tasks
           Product: gcc
           Version: 14.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: fortran
          Assignee: unassigned at gcc dot gnu.org
          Reporter: abensonca at gcc dot gnu.org
  Target Milestone: ---

Here's an example code (highly simplified from the actual code I'm working
on) that causes seemingly wrong behavior resulting in calling a destructor when
it should not be called:

module taskerMod

   type :: tasker
      integer :: depth=-1
    contains
      final     ::            taskerDestruct
      procedure :: compute => taskerCompute
   end type tasker

 contains

   subroutine taskerDestruct(self)
     !$ use :: OMP_Lib                                                          
     implicit none
     type(tasker), intent(inout) :: self

     write (0,*) "DESTRUCT FROM DEPTH ",self%depth !$ ," :
",omp_get_thread_num()                                                          
     return
   end subroutine taskerDestruct

   recursive subroutine taskerCompute(self)
     !$ use :: OMP_Lib                                                          
     implicit none
     class(tasker), intent(inout) :: self

     !$omp atomic
     self%depth=self%depth+1
     write (0,*) "DEPTH ",self%depth !$ ," : ",omp_get_thread_num()             
     if (self%depth < 3) then
        !$omp task untied                                                       
        call self%compute()
        !$omp end task                                                          
     end if
     return
   end subroutine taskerCompute

 end module taskerMod

 program testTasks
   use :: taskerMod
   implicit none
   type(tasker) :: tasker_

   tasker_=tasker(0)
   !$omp parallel                                                               
   !$omp single                                                                 
   !$omp taskgroup                                                              
   !$omp task untied                                                            
   call tasker_%compute()
   !$omp end task                                                               
   !$omp end taskgroup                                                          
   !$omp end single                                                             
   !$omp end parallel                                                           
 end program testTasks

Compiling without OpenMP results in the expected behavior:
$ gfortran test.F90
$ ./a.out
 DESTRUCT FROM DEPTH           -1
 DEPTH            1
 DEPTH            2
 DEPTH            3

There's a call to the finalizer for the tasker class (on assignment), and then
it simply reports the 3 levels of recursion that I've set it to go through.

But, if I compile with OpenMP and run just a single thread (the same problem
occurs with multiple threads also):
$ gfortran test.F90 -fopenmp
$ ./a.out
 DESTRUCT FROM DEPTH           -1
 DEPTH            1
 DEPTH            2
 DESTRUCT FROM DEPTH            2
 DEPTH            3
 DESTRUCT FROM DEPTH            3

I now see calls to the finalizer from the 2nd and 3rd recursive calls to the
taskerCompute function. Since self is intent(inout) to this function I
wouldn't expect it to be finalized.

This happens with versions 12.0.0, 13.0.1, and the current HEAD of the GCC git
repo. But, ifort, does not produce the extra finalizer calls when used to
compile the above with OpenMP.

Reply via email to