weird F2003 pointer error

I'm trying to convert my OpenKIM model as QUIP potential code to the
new API and F2003 pointers. I have a routine which I'm going to
register as a get_neigh method. I'm using a kim buffer to store some
data that needs to be communicated. Relevant source is below. When I
try to compile it, I get the following errors:


  p_neigh_list = c_loc(buf%neigh_list)


Error: Argument 'buf' to 'c_loc' at (1) must be an associated scalar POINTER


  p_neigh_rij = c_loc(buf%neigh_rij)


Error: Argument 'buf' to 'c_loc' at (1) must be an associated scalar POINTER

I have no idea why those calls to c_loc are invalid. This is with
gfortran 4.8.2 on OS X.

Any ideas?


!!!!! start of code !!!!!!!

type quip_kim_buffer

  integer :: kim_iterator_current_i = -1

  type(Atoms), pointer :: kim_at => null()

  integer(c_int), pointer :: neigh_list(:slight_smile: => null()

  real(c_double), pointer :: neigh_rij(:,:slight_smile: => null()

end type quip_kim_buffer

function quip_neighbour_iterator(pkim, iterator_mode, request, atom,
nneigh, p_neigh_list, p_neigh_rij) bind(c) result(outval)

  type(c_ptr) :: pkim

  integer(c_int) :: iterator_mode, request, atom, nneigh

  type(c_ptr) :: p_neigh_list

  type(c_ptr) :: p_neigh_rij

  integer(c_int) :: outval ! result

  type(quip_kim_buffer), pointer :: buf; type(c_ptr) :: p_buf

  integer :: kim_error

  integer :: ji

  real(dp) :: drij(3)

  p_buf = kim_api_get_model_buffer(pkim, kim_error)

  if (kim_error < KIM_STATUS_OK) then

    call system_abort("quip_neighbor_iterator failed to get kim buffer
with error "//kim_error)


  call c_f_pointer(p_buf, buf)

  if (iterator_mode == 1) then ! locator mode

    if (request < 1 .or. request > buf%kim_at%N) then




    atom = request

  else if (iterator_mode == 0) then ! iterator mode

    if (request == 0) then

       buf%kim_iterator_current_i = 1



    else if (request == 1) then

      if (buf%kim_iterator_current_i > buf%kim_at%N) then




      atom = buf%kim_iterator_current_i

      buf%kim_iterator_current_i = buf%kim_iterator_current_i + 1

    else ! other iterator requests




  else ! other mode




  nneigh = n_neighbours(buf%kim_at, atom)

  if (associated(buf%neigh_list)) then

    if (size(buf%neigh_list) < nneigh) deallocate(buf%neigh_list)


  if (.not. associated(buf%neigh_list)) allocate(buf%neigh_list(nneigh))

  if (associated(buf%neigh_rij)) then

    if (size(buf%neigh_rij,2) < nneigh) deallocate(buf%neigh_rij)


  if (.not. associated(buf%neigh_rij)) allocate(buf%neigh_rij(3,nneigh))

  p_neigh_list = c_loc(buf%neigh_list)

  p_neigh_rij = c_loc(buf%neigh_rij)

  do ji=1, nneigh

      buf%neigh_list(ji) = neighbour(buf%kim_at, atom, ji, diff = drij)

      buf%neigh_rij(1:3,ji) = drij

  end do

  outval = KIM_STATUS_OK

end function quip_neighbour_iterator

I also don't see anything wrong, but I have two suggestions to try:

1) Maybe? the derived type can only contain interoperable things.?. So you might try removing the kim_at and see if it still complains.

2) it might work if you ask for the c_loc of the first element of the array instead of the "whole array":

   p_neigh_list = c_loc(buf%neigh_list(1))
   p_neigh_rij = c_loc(buf%neigh_rij(1,1))

Although it doesn't seem like you should need to do this, it might work. (I don't know enought about Fortran to know if this is proper, or only acceptable, or bad practice....)


Hi Noam,

I think


should work. There is a nasty bug in older gfortran versions that lead to a segfault of the compiler if you omited the index. Bug was apparently just fixed in gcc 4.9. See here:

This suggestion worked, and thanks also to Lars for pointing it out as well. The definition of c_loc in sec seems to allow it, and example C.10.2.1 definitely does c_loc(allocatable_array), not c_loc(allocatable_array(1)), which would make me think that my original syntax should be allowed. Then again, it is only 11 years after the date of the standard, so who could expect a full implementation?