11-126
To: J3
From: Nick Maclaren
Subject: Interop TR: CFI_desc_t copying and ALLOCATABLE
Date: 2011 January 26
Reference: 10-251.pdf, 10-235, 11-122
1. Summary
----------
This issue was raised in 10-235, but there are no minutes of the
subgroup, so I do not know what happened and what decisions were taken.
Because of that, this merely raises issues and provides no edits.
In C, all structures are copyable in one of three ways[*]:
1) Explicit member-by-member copying. This is not possible for
CFI_desc_t, because vendors are allowed to have 'hidden' members.
2) Direct assignment of structure values to structure lvalues.
3) memcpy and friends.
10-251.pdf/N1838.pdf does not constrain this, therefore it is possible
for descriptors passed as arguments and, in most cases, that works.
However, there is a very serious problem with allocatable arguments,
because Fortran requires the allocation and deallocation of any one
associated variable to be reflected in all others [N1826 6.7.1.3 p3 and
6.7.3.2 p1].
If a descriptor is copied, the Fortran run-time system does not get an
opportunity to chain such descriptors, and this becomes unimplementable.
It cannot be solved by indirection, as some of the properties that
must be maintained are the bounds, which are in the descriptor itself.
As I said in 10-235, I attempted to think of wording within the design
of 10-251, and failed.
[*] This is not strictly correct, as volatile confuses the issue, but
that is not relevant here.
2. Example
----------
The Fortran standard requires the allocation in Joe to be reflected
in what the main program sees, and the following is required to print
10 and 5:
PROGRAM Main
INTERFACE
SUBROUTINE Fred (y)
REAL, ALLOCATABLE :: y(:)
END SUBROUTINE Fred
END INTERFACE
REAL, ALLOCATABLE :: x(:)
ALLOCATE(x(10))
PRINT *, SIZE(x)
CALL Fred(x)
PRINT *, SIZE(x)
END PROGRAM Main
SUBROUTINE Fred (y)
INTERFACE
SUBROUTINE Joe (z)
REAL, ALLOCATABLE :: z(:)
END SUBROUTINE Joe
END INTERFACE
REAL, ALLOCATABLE :: y(:)
CALL Joe(y)
END SUBROUTINE Fred
SUBROUTINE Joe (z)
REAL, ALLOCATABLE :: z(:)
DEALLOCATE(z)
ALLOCATE(z(5))
END SUBROUTINE Joe
Now, what if Fred were a BIND(C) function written in C, such as:
#include "ISO_Fortran_binding.h"
#include
void Fred (CFI_desc_t *y) {
size_t n = sizeof(CFI_desc_t)+y->rank*sizeof(CFI_dim_t);
CFI_desc_t *z = malloc(n);
memcpy(z,y,n);
Joe(z);
}
That is not going to work but is implicitly allowed by C and is not
forbidden by the TR. Furthermore, simply forbidding the copying of
descriptors is an unreasonable constraint on the use of non-allocatable
descriptors, not least because it forbids function arguments of type
CFI_desc_t.