| ! { 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 |