Title: The ADDRESS attribute Submitted by: J3 (Aleksandar Donev, January 2004) Status: For Consideration References: J3/03-279r1 Basic Functionality: I propose that modifications be made to the Fortran standard to allow passing buffers to C IO/communication routines without explicitly using C_LOC. For this purpose, a new attribute, spelled ADDRESS in this proposal, is provided. It would only be compatible with a dummy argument of type TYPE(C_PTR). The C address of the actual argument is passed by value by the caller. The actual argument must be a valid argument for the C_LOC intrinsic, in particular, have the TARGET attribute. Here is an example: INTERFACE SUBROUTINE MPI_Send(buffer, count), BIND(C,"MPI_Send") TYPE(C_PTR), ADDRESS :: buffer ! New attribute INTEGER(C_INT), VALUE :: count END SUBROUTINE END INTERFACE ! Make this legal: REAL(C_FLOAT), DIMENSION(...), TARGET :: buffer CALL MPI_SEND(buffer,10) ! No need for C_LOC The above problem is similar to the one with "pass-by-value". Implementations used to deal with C interop with the %VAL intrinsic, so that one had to wrap a %VAL around any argument in a call that required pass-by-value. The present system in which the VALUE attribute is present in the interface and there is no difference at the call site is much better for the user and for code clarity. I am essentially proposing that a similar solution be implemented to the common problem of passing the address to an IO-type routine. Rationale: Many C libraries dealing with IO/communication, and in particular MPI, have "typeless" dummy arguments (typically for buffers). These are typically a void pointer in the C interface. Consider the following (simplified) C prototype: void MPI_Send(void * buffer, int count); and its Fortran equivalent: INTERFACE SUBROUTINE MPI_Send(buffer, count), BIND(C,"MPI_Send") TYPE(C_PTR), VALUE :: buffer INTEGER(C_INT), VALUE :: count END SUBROUTINE END INTERFACE The actual argument in C can be a pointer (C array) of any type, and an implicit conversion into a void pointer happens: float * buffer; buffer = malloc(...); MPI_Send(buffer,10); // Works in C Fortran has a very different system in which the types of the dummy and actual must match and no implicit conversion happens at the call point. Therefore, one cannot call the MPI_Send procedure with anything but a C pointer as an actual argument: REAL(C_FLOAT), DIMENSION(:), TARGET :: buffer CALL MPI_SEND(buffer,10) ! NOT OK in Fortran but the following is OK: CALL MPI_SEND(C_LOC(buffer),10) The rationale for the proposed solution is two fold: 1) It allows for easier interfacing to numerous existing libraries, including the existing Fortran interface to MPI (which is flawed as described above), from the user perspective. 2) It will allow one to reuse current codes, which use vendor extensions or simply non-conforming tricks to call MPI_SEND with different types. This is friendly to existing practices. Estimated Impact: This will have no cost for the implementations since many implementations already have a switch that basically lets one have type mismatches, and since the above change is really just a syntactic wrapper for something everyone already knows how to do: Just pass the memory address. Incorporating this into the standard is not entirely trivial. The proposed change will require that special provisions be made in argument association in the case when the dummy is a C pointer with the ADDRESS. Essentially what we would say is that it is as if the user had put a C_LOC in the call: ! This: CALL MPI_SEND(buffer,10) ! should be the same as: CALL MPI_SEND(C_LOC(buffer),10) Whether we relax the requirement that the actual be a TARGET (since the actual of C_LOC needs to) is a different matter. I would suggest that TARGET be required. If TARGET were optional, there are issues to consider here such as contiguity requirements and the provision for copy in/copy out (think Interp 125), as well as the risk of allowing pointers to be taken by the C procedure and abused, even in a legal program. I would like to say that, in some cases, one wants to make sure no copy in/copy out happens (such as asynchronous communication calls), and in Fortran using the TARGET attribute is the *only* way to ensure this (Interp 125). Detailed Specification: A dummy argument interoperable with a C pointer may have the ADDRESS attribute. The VALUE attribute is implied by the ADDRESS attribute, but may be duplicated. If the dummy argument has the ADDRESS attribute, the actual argument must be a valid actual argument for C_LOC. The value of the result of C_LOC applied to the actual argument, i.e., the C address of the actual argument, is associated with the dummy. History: Comment: Malcolm Cohen, Nihon NAG, Tokyo: This reminds me of a Kurt Hirchert suggestion to allow a TARGET actual to be passed to a POINTER dummy. This is analagous to passing an expression value to a dummy variable (no-one thinks we should have been limited to passing variables instead of values). This suggestion is very similar - one has (effectively) a POINTER VALUE dummy argument and wants a TARGET to turn into a POINTER. I think that Kurt's suggestion is much more attractive than just doing it for C interop. Furthermore, the idea of doing automatic coercions on argument association is completely foreign to Fortran. C has automatic conversions, which is the only reason you don't see typecasts everywhere on function references. I'm not sure that this is where I'd start adding them either. The argument that it uglifies the call to say CALL csub(C_LOC(my_var)) I find a bit unconvincing. It is even more ugly to say x = cpown(REAL(y1-y2,C_DOUBLE),INT(n+1,C_LONG)) but noone is suggesting we do anything about that! We already have a fully polymorphic pointer in Fortran, it's called CLASS(*). If we want to have one that is completely unsafe to use, perhaps TYPE(*) is a better way of spelling it than TYPE(C_PTR). Then a TYPE(*) dummy would interoperate with a (void *) C pointer. Finally, if we're going to have automatic conversions for TYPE(C_PTR) let's just have them. Drop the unnecessary syntax. If TYPE(C_PTR) is going to be magic, let's just make it magic and not have a special attribute "MAGIC" which is ***ONLY*** applicable to TYPE(C_PTR). SUMMARY: (1) I'd rather see an unsafe TYPE(*) added, with whatever operations necessary [perhaps just conversion to another pointer type, perhaps some I/O support]. (2) Should we not consider the Hirchert idea as well? (3) If we're really wedded to the idea of only doing this for C interop, drop the syntax. Just do it.