To: J3 11-168 From: R. Bader, N. M. Maclaren Subject: Orthogonalizing CFI_establish Date: 2011 June 07 References: N1845, N1848, N1854 INTRODUCTION: There is a considerable overlap of functionality between CFI_establish and CFI_section; as the examples in N1845 show, this leads not only to a measure of uncertainty on which of the functions to use, but also has a potential for making it easy to write programs which violate the existing restrictions on the use of descriptors. Therefore, this paper suggests changes to CFI_establish which more clearly separate its functionality from that of CFI_section as well as CFI_setpointer: The use of CFI_establish() is limited to creating descriptors for Fortran objects within C which are (1) unallocated/disassociated ALLOCATABLE or POINTER objects of some specified rank and type, or (2) contiguous assumed shape arrays created from contiguous pre-existing C storage (of sufficient size). This is achieved by * replacing the dim argument by one describing the upper bounds. This covers case (2) above (the dim member of dv will be appropriately set up inside the function call). Note that case (1) will of course ignore this arguments, so NULL can then be passed for it. * adding the restriction that base_addr shall be the C address of a contiguous storage area of known type, unless it is NULL. This mostly prevents directly creating a C descriptor for an object passed from Fortran via a descriptor; the other functions deal with this situation as far as needed; also nonsensical rank changing is not possible any more. Finally, some edits are added which ensure that descriptors created inside C must be initialized with CFI_establish before other functions are used on them. Disadvantages: * General pointer rank/bounds remapping is not possible any more (but of course a Fortran subroutine can be written to do this). * Pointer association must be done by creating a disassociated pointer and invoking CFI_setpointer i.e., more function calls must be written (but then we're also orthogonal to CFI_setpointer). These changes make obsolete the need for adding a note as described in the reference to [14:43+] of N1845 in N1848. EDITS to N1854: [14:27-29] Delete "CFI_type_other or" and "If the type is CFI_type_other, elem_len shall be greater than zero and equal to the sizeof() of an element of the object." (In the context of allocation, elem_len is meant to deal with deferred length strings only.) [15:29] Replace "const CFI_dim_t dim[]" by "const CFI_index_t upper_bounds[]" [16:1] After "not NULL it shall be" insert " a pointer to a contiguous storage sequence which is" [16:12-13] Replace the paragraph by "/upper_bounds/ is ignored if the rank /r/ is not greater than zero or if base_addr is NULL. Otherwise, it shall point to an array with /r/ elements specifying the upper bounds of the described array." [16:15-16] Delete the sentence "If base_addr ... subobject of it". [16:17] After "disassociated pointer" add "; otherwise, it is for a contiguous assumed-shape array, or a contiguous non-pointer non-allocatable scalar." [16:21+] Add the following text: "NOTE 5.6+ CFI_establish must be used to initialize the space for a descriptor created inside C before calling either of CFI_allocate or CFI_setpointer on it, in order to set the rank, type and element length." [16:30-45] Replace text by: "Example 2: Given the Fortran type definition type, bind(c) :: t real(c_double) :: x complex(c_double_complex) :: y end type and a Fortran subprogram which has an assumed shape dummy argument of type t, the following code fragment creates a descriptor /a_fortran/ for an array of size 100 which can be used as the actual argument in an invocation of the subprogram from C: typedef struct {double x; double complex y;} t; t a_c[100]; CFI_CDESC_T(1) a_fortran; int ind; CFI_index_t upper_bound[1]; upper_bound[0] = 99; /* the lower bound is 0 */ ind = CFI_establish( (CFI_cdesc_t *) &a_fortran, a_c, CFI_attribute_assumed, CFI_type_other, sizeof(t), 1, upper_bound);" (apart from the interface change, the present text could be interpreted as producing a copy of a descriptor to a Fortran object - but CFI_section should be used for that purpose). [19:12] After "object.", add "Its /rank/ and /type/ members shall have the same values as that of /result/. If its type member is CFI_type_other, its /elem_len/ member shall have the same value as that of /result/." (This makes CFI_setpointer as safe as is possible in this context). EDITS for example A.2.2: [38:4] Replace "two C descriptors" by "the first C descriptor for an allocatable entity" [38:5] Replace "copies the base_addr ... second descriptor" by "constructs the second descriptor by invoking CFI_section with the value CFI_attribute_assumed for the attribute parameter," [38:11] Remove the declaration of dims [38:21] Replace "dims" by "NULL" (dims ignored for allocatable entity) [38:26-32] Replace invocation of CFI_establish by "CFI_section(desc_assum, desc_alloc, CFI_attribute_assumed, desc_alloc->dim);" [38:32+] Add text "After invocation of CFI_section, the lower bounds stored in the /dim/ member of /desc_assum/ will have the value 0 even if the corresponding entries in /desc_alloc/ have different values." (Note how the change avoids the need to specify rank and type redundantly but consistently, which could be a source of programming errors. The interface change does not force a programmer to use CFI_section here, but gently pushes her/him in that direction). EDITS for example A.2.3: This includes changes to some of the text, subsuming the reference to [38:49]-[39:4] of N1845 mentioned in part 3 of N1848. [39:13-19] Replace invocation of CFI_establish by "CFI_section( (CFI_cdesc_t *) &array, int_array, CFI_attribute_assumed, dims );" [37:26-31] Both paragraphs can be removed because the new interface forces the programmer to use CFI_section in this context, hence the discussion of descriptor corruption is superfluous. (One could add some words why the result cannot be a formal parameter, but it may be a better idea to put that into a NOTE accompanying the function description, or the - presently still missing - rules in 5.2.6). [40:2] Replace "CFI_dim_t dims[1]" by "CFI_index_t upper_bound[1];" [40:8-10] Replace definition of dims by "upper_bound[0] = ARRAY_SIZE - 1;" (Again, there is a simplification in use). [40:11] Remove comment (leftover from a much earlier version) [40:16] Replace "sizeof(int)" by "/* element length is ignored */ 0,". [40:18] Replace "dims" by "upper_bound" EDITS for example A.2.4: [40:36+] Insert the following statements: "CFI_CDESC_T(0) yp; int ind; /* make local yp point at y */ CFI_establish( (CFI_cdesc_t *) &yp, &y, CFI_attribute_pointer, CFI_type_int, /* elem_len is ignored */ 0, /* rank */ 0, /* upper bounds are ignored */ NULL);" [40:37-45] Replace condition and invocation of CFI_establish by "/* Pointer association of ip with yp */ ind = CFI_setpointer(ip, (CFI_cdesc_t *) &yp, NULL); if (ind != CFI_SUCCESS) { /* handle run time error */ }" [40:46+] Add text: "The restrictions on the use of CFI_establish prohibit direct modification of the incoming pointer entity ip by invoking that function on it." (This example becomes only slightly more complicated than before - but it was violating the rules before, so needed fixing in any case).