! { dg-do run } ! ! PR fortran/99171 ! ! Check dummy procedure arguments, especially optional ones ! module m use iso_c_binding implicit none (type, external) integer :: cnt integer :: cnt2 contains subroutine proc() cnt = cnt + 1 end subroutine subroutine proc2() cnt2 = cnt2 + 1 end subroutine subroutine check(my_proc) procedure(proc) :: my_proc cnt = 42 call my_proc() if (cnt /= 43) stop 1 !$omp parallel call my_proc() !$omp end parallel if (cnt <= 43) stop 2 end subroutine check_opt(my_proc) procedure(proc), optional :: my_proc logical :: is_present is_present = present(my_proc) cnt = 55 if (present (my_proc)) then call my_proc() if (cnt /= 56) stop 3 endif !$omp parallel if (is_present .neqv. present (my_proc)) stop 4 if (present (my_proc)) then call my_proc() if (cnt <= 56) stop 5 end if !$omp end parallel if (is_present) then if (cnt <= 56) stop 6 else if (cnt /= 55) then stop 7 end if end subroutine check_ptr(my_proc) procedure(proc), pointer :: my_proc logical :: is_assoc integer :: mycnt is_assoc = associated (my_proc) cnt = 10 cnt2 = 20 if (associated (my_proc)) then call my_proc() if (cnt /= 11 .or. cnt2 /= 20) stop 8 endif !$omp parallel if (is_assoc .neqv. associated (my_proc)) stop 9 if (associated (my_proc)) then if (.not. associated (my_proc, proc)) stop 10 call my_proc() if (cnt <= 11 .or. cnt2 /= 20) stop 11 else if (cnt /= 10 .or. cnt2 /= 20) then stop 12 end if !$omp end parallel if (is_assoc .neqv. associated (my_proc)) stop 13 if (associated (my_proc)) then if (cnt <= 11 .or. cnt2 /= 20) stop 14 else if (is_assoc .and. (cnt /= 11 .or. cnt2 /= 20)) then stop 15 end if cnt = 30 cnt2 = 40 mycnt = 0 !$omp parallel shared(mycnt) !$omp critical my_proc => proc2 if (.not.associated (my_proc, proc2)) stop 17 mycnt = mycnt + 1 call my_proc() if (cnt2 /= 40 + mycnt .or. cnt /= 30) stop 18 !$omp end critical !$omp end parallel if (.not.associated (my_proc, proc2)) stop 19 if (cnt2 /= 40 + mycnt .or. cnt /= 30) stop 20 end subroutine check_ptr_opt(my_proc) procedure(proc), pointer, optional :: my_proc logical :: is_assoc, is_present integer :: mycnt is_assoc = .false. is_present = present(my_proc) cnt = 10 cnt2 = 20 if (present (my_proc)) then is_assoc = associated (my_proc) if (associated (my_proc)) then call my_proc() if (cnt /= 11 .or. cnt2 /= 20) stop 21 endif end if !$omp parallel if (is_present .neqv. present (my_proc)) stop 22 if (present (my_proc)) then if (is_assoc .neqv. associated (my_proc)) stop 23 if (associated (my_proc)) then if (.not. associated (my_proc, proc)) stop 24 call my_proc() if (cnt <= 11 .or. cnt2 /= 20) stop 25 else if (cnt /= 10 .or. cnt2 /= 20) then stop 26 end if end if !$omp end parallel if (present (my_proc)) then if (is_assoc .neqv. associated (my_proc)) stop 27 if (associated (my_proc)) then if (cnt <= 11 .or. cnt2 /= 20) stop 28 else if (is_assoc .and. (cnt /= 11 .or. cnt2 /= 20)) then stop 29 end if end if cnt = 30 cnt2 = 40 mycnt = 0 !$omp parallel shared(mycnt) if (is_present .neqv. present (my_proc)) stop 30 !$omp critical if (present (my_proc)) then my_proc => proc2 if (.not.associated (my_proc, proc2)) stop 31 mycnt = mycnt + 1 call my_proc() if (cnt2 /= 40 + mycnt .or. cnt /= 30) stop 32 end if !$omp end critical !$omp end parallel if (present (my_proc)) then if (.not.associated (my_proc, proc2)) stop 33 if (cnt2 /= 40 + mycnt .or. cnt /= 30) stop 34 end if end ! ---------------------- subroutine cfun_check(my_cfun) type(c_funptr) :: my_cfun procedure(proc), pointer :: pptr logical :: has_cfun has_cfun = c_associated (my_cfun) pptr => null() cnt = 42 call c_f_procpointer (my_cfun, pptr) if (has_cfun) then call pptr() if (cnt /= 43) stop 35 end if pptr => null() !$omp parallel if (has_cfun .neqv. c_associated (my_cfun)) stop 36 !$omp critical call c_f_procpointer (my_cfun, pptr) !$omp end critical if (has_cfun) then call pptr() if (cnt <= 43) stop 37 else if (associated (pptr)) stop 38 end if !$omp end parallel end subroutine cfun_check_opt(my_cfun) type(c_funptr), optional :: my_cfun procedure(proc), pointer :: pptr logical :: has_cfun, is_present has_cfun = .false. is_present = present (my_cfun) if (is_present) has_cfun = c_associated (my_cfun) cnt = 1 pptr => null() !$omp parallel if (is_present .neqv. present (my_cfun)) stop 39 if (is_present) then if (has_cfun .neqv. c_associated (my_cfun, c_funloc(proc))) stop 40 !$omp critical call c_f_procpointer (my_cfun, pptr) !$omp end critical if (has_cfun) then call pptr() if (cnt <= 1) stop 41 else if (associated (pptr)) stop 42 end if end if !$omp end parallel end subroutine cfun_check_ptr(my_cfun) type(c_funptr), pointer :: my_cfun procedure(proc), pointer :: pptr logical :: has_cfun, is_assoc has_cfun = .false. is_assoc = associated (my_cfun) if (is_assoc) has_cfun = c_associated (my_cfun) cnt = 1 pptr => null() !$omp parallel if (is_assoc .neqv. associated (my_cfun)) stop 43 if (is_assoc) then if (has_cfun .neqv. c_associated (my_cfun, c_funloc(proc))) stop 44 !$omp critical call c_f_procpointer (my_cfun, pptr) !$omp end critical if (has_cfun) then call pptr() if (cnt <= 1) stop 45 else if (associated (pptr)) stop 46 end if end if !$omp end parallel cnt = 42 cnt2 = 1 pptr => null() !$omp parallel if (is_assoc .neqv. associated (my_cfun)) stop 47 if (is_assoc) then !$omp critical my_cfun = c_funloc (proc2) call c_f_procpointer (my_cfun, pptr) !$omp end critical if (.not. associated (pptr, proc2)) stop 48 if (.not. c_associated (my_cfun, c_funloc(proc2))) stop 49 call pptr() if (cnt /= 42 .or. cnt2 <= 1) stop 50 end if !$omp end parallel if (is_assoc) then if (.not. associated (pptr, proc2)) stop 51 if (.not. c_associated (my_cfun, c_funloc(proc2))) stop 52 else if (associated (pptr)) stop 53 end if end subroutine cfun_check_ptr_opt (my_cfun) type(c_funptr), pointer, optional :: my_cfun procedure(proc), pointer :: pptr logical :: is_present, has_cfun, is_assoc has_cfun = .false. is_assoc = .false. is_present = present (my_cfun) if (is_present) then is_assoc = associated (my_cfun) if (is_assoc) has_cfun = c_associated (my_cfun) end if cnt = 1 pptr => null() !$omp parallel if (is_present .neqv. present (my_cfun)) stop 54 if (is_present) then if (is_assoc .neqv. associated (my_cfun)) stop 55 if (is_assoc) then if (has_cfun .neqv. c_associated (my_cfun, c_funloc(proc))) stop 56 !$omp critical call c_f_procpointer (my_cfun, pptr) !$omp end critical if (has_cfun) then call pptr() if (cnt <= 1) stop 57 else if (associated (pptr)) stop 58 end if end if end if !$omp end parallel cnt = 42 cnt2 = 1 pptr => null() !$omp parallel if (is_present .neqv. present (my_cfun)) stop 59 if (is_present) then if (is_assoc .neqv. associated (my_cfun)) stop 60 if (is_assoc) then !$omp critical my_cfun = c_funloc (proc2) call c_f_procpointer (my_cfun, pptr) !$omp end critical if (.not. associated (pptr, proc2)) stop 61 if (.not. c_associated (my_cfun, c_funloc(proc2))) stop 62 call pptr() if (cnt /= 42 .or. cnt2 <= 1) stop 63 end if end if !$omp end parallel if (is_present .and. is_assoc) then if (.not. associated (pptr, proc2)) stop 64 if (.not. c_associated (my_cfun, c_funloc(proc2))) stop 65 else if (associated (pptr)) stop 66 end if end end module m program main use m implicit none (type, external) procedure(proc), pointer :: pptr type(c_funptr), target :: cfun type(c_funptr), pointer :: cfun_ptr call check(proc) call check_opt() call check_opt(proc) pptr => null() call check_ptr(pptr) pptr => proc call check_ptr(pptr) call check_ptr_opt() pptr => null() call check_ptr_opt(pptr) pptr => proc call check_ptr_opt(pptr) ! ------------------- pptr => null() cfun = c_funloc (pptr) call cfun_check(cfun) cfun = c_funloc (proc) call cfun_check(cfun) call cfun_check_opt() cfun = c_funloc (pptr) call cfun_check_opt(cfun) cfun = c_funloc (proc) call cfun_check_opt(cfun) ! - - - - cfun_ptr => null() call cfun_check_ptr (cfun_ptr) cfun = c_funloc (proc) cfun_ptr => cfun call cfun_check_ptr (cfun_ptr) ! - - - - call cfun_check_ptr_opt () cfun_ptr => null() call cfun_check_ptr_opt (cfun_ptr) cfun = c_funloc (proc) cfun_ptr => cfun call cfun_check_ptr_opt (cfun_ptr) end program