[Patch, Fortran] C Binding - module+intrinsic cleanup+bug fixes
Mikael Morin
mikael.morin@sfr.fr
Sat Mar 23 21:41:00 GMT 2013
Hello,
Le 23/03/2013 10:59, Tobias Burnus a écrit :
> Dear all,
>
> initially, I only wanted to allow assumed-rank arrays with C_LOC, even if I played with the idea to cleanup the intrinsic handling of the ISO_C_Binding module for quite some time. But Mikael rejected a hacky version.
>
Did I? Never mind, the rejection proves fruitful in the end. :-)
>
> The main change of this patch is to move all the special handling of the intrinsics from symbol.c to the normal intrinsics code in intrinsic.{c,h}, check.c, iresolve.c and trans-intrinsics.c. That also implied to do some larger changes to module.c. Additionally, I rewrote all the constraint checks from scratch, based on the Fortran 2003, 2008 and TS29113 standards - and fixed the fallout. Finally, I looked through the bugreports mentioning those intrinsics - and fixed some remaing issues (some were already fixed, either by this patch or since at least GCC 4.6).
>
> 2013-03-22 Tobias Burnus <burnus@net-b.de>
>
> PR fortran/38536
> PR fortran/38813
> PR fortran/38894
> PR fortran/39288
> PR fortran/40963
> PR fortran/45824
> PR fortran/47023
> PR fortran/49023
> PR fortran/50269
> PR fortran/50612
> PR fortran/52426
> PR fortran/54263
> PR fortran/55343
> PR fortran/55444
> PR fortran/56079
> PR fortran/56378
Really impressive. You can also add PR 55574 to the list (test case
attached).
There is one thing in the patch I'm uncomfortable with, namely:
> @@ -4192,7 +4245,11 @@ gfc_intrinsic_sub_interface (gfc_code *c, int
error_flag)
>
> name = c->symtree->n.sym->name;
>
> - isym = gfc_find_subroutine (name);
> + if (c->symtree->n.sym->intmod_sym_id)
> + isym = gfc_intrinsic_subroutine_by_id ((gfc_isym_id)
> + c->symtree->n.sym->intmod_sym_id);
Err... an iso_c_binding_symbol id is a different thing from a
gfc_isym_id id; isn't it?
After investigating further, it seems that create_intrinsic_function
sets the intmod_sym_id field to the gfc_isym_id id (even without your
patch).
This is confusing because the non-procedure symbols use as intmod_sym_id
a ISOCBINDING_* id, whereas procedures use a GFC_ISYM_* id.
I don't know how it ends up working, but I suggest the following change:
- store the ISOCBINDING_* id in intmod_sym_id
- retrieve the corresponding GFC_ISYM_* when needed (like above) using
c_interop_kinds_table[...->intmod_sym_id].value
By the way, create_intrinsic_function could certainly be simplified if
it was called from generate_isocbinding_symbol.
Otherwise, looks good. The usual nits below.
Mikael
> diff --git a/gcc/fortran/check.c b/gcc/fortran/check.c
> index 0e71b95..28172fc 100644
> --- a/gcc/fortran/check.c
> +++ b/gcc/fortran/check.c
> @@ -693,12 +693,15 @@ gfc_var_strlen (const gfc_expr *a)
> {
> long start_a, end_a;
>
> + if (!ra->u.ss.start || !ra->u.ss.end)
> + return -1;
> +
This is a bit conservative (though not wrong); ra->u.ss.start == NULL at
least doesn't prevent string length evaluation.
> @@ -3621,17 +3624,389 @@ gfc_check_sizeof (gfc_expr *arg)
> }
>
>
> +/* Check whether an expression is interoperable. If all_len_okay is true,
> + all length-type parameters (for character) are allowed. Required for
> + C_LOC (cf. Fortran 2003corr5 or Fortran 2008). */
Could you add a comment about MSG?
Something like:
"when returning false, MSG is set to a string telling why the expression
is not interoperable, which can be used in diagnostics"
I think full sentences should be used for MSG, to avoid getting
confusing messages like the following (and to help translation):
"'foo' argument of 'bar' intrinsic at (1) must be an interoperable data
entity: deferred-length string"
thus:
"expression shall not be a deferred-length string"
instead of
"deferred-length string"
same for "Extension to use non-C_Bool-kind LOGICAL", "Extension:
Non-C_CHAR-kind CHARACTER"
[...]
> +gfc_try
> +gfc_check_c_associated (gfc_expr *c_ptr_1, gfc_expr *c_ptr_2)
> +{
> + if (c_ptr_1->ts.type != BT_DERIVED
> + || (c_ptr_1->ts.u.derived->intmod_sym_id != ISOCBINDING_PTR
> + && c_ptr_1->ts.u.derived->intmod_sym_id != ISOCBINDING_FUNPTR))
You should also check ...->from_intmod; just in case there is a vicious
user using a symbol (from a non-iso_c_binding intrinsic module) with the
same id as C_FUN/C_FUNPTR. ;-)
There are several instances of this with c_associated, c_f_pointer, etc.
> diff --git a/gcc/fortran/module.c b/gcc/fortran/module.c
> index 1b38555..8a92386 100644
> --- a/gcc/fortran/module.c
> +++ b/gcc/fortran/module.c
> @@ -5695,20 +5767,60 @@ import_iso_c_binding_module (void)
> {
> #define NAMED_FUNCTION(a,b,c,d) \
> case a: \
> + if (a == ISOCBINDING_LOC) \
> + create_intrinsic_function (u->local_name[0] \
> + ? u->local_name : u->use_name, \
> + (gfc_isym_id) c, \
> + iso_c_module_name, \
> + INTMOD_ISO_C_BINDING, false, \
> + c_ptr->n.sym); \
> + else if (a == ISOCBINDING_FUNLOC) \
> + create_intrinsic_function (u->local_name[0] \
> + ? u->local_name : u->use_name, \
> + (gfc_isym_id) c, \
> + iso_c_module_name, \
> + INTMOD_ISO_C_BINDING, false, \
> + c_funptr->n.sym); \
> + else \
> + create_intrinsic_function (u->local_name[0] \
> + ? u->local_name : u->use_name, \
> + (gfc_isym_id) c, \
> + iso_c_module_name, \
> + INTMOD_ISO_C_BINDING, false, NULL); \
> + break;
Could you simplify it a bit like this:
if (a == ISOCBINDING_LOC)
return_type = c_ptr->n.sym;
else if (a == ISOCBINDING_FUNLOC)
return_type = c_funptr->n.sym;
else
return_type = NULL;
create_intrinsic_function (..., return_type);
> default:
> - generate_isocbinding_symbol (iso_c_module_name,
> - (iso_c_binding_symbol) i,
> - u->local_name[0] ? u->local_name
> - : u->use_name);
> + if (i == ISOCBINDING_NULL_PTR)
> + generate_isocbinding_symbol (iso_c_module_name,
> + (iso_c_binding_symbol) i,
> + u->local_name[0]
> + ? u->local_name : u->use_name,
> + c_ptr, false);
> + else if (i == ISOCBINDING_NULL_FUNPTR)
> + generate_isocbinding_symbol (iso_c_module_name,
> + (iso_c_binding_symbol) i,
> + u->local_name[0]
> + ? u->local_name : u->use_name,
> + c_funptr, false);
> + else
> + generate_isocbinding_symbol (iso_c_module_name,
> + (iso_c_binding_symbol) i,
> + u->local_name[0]
> + ? u->local_name : u->use_name,
> + NULL, false);
Ditto here...
> @@ -5754,16 +5863,47 @@ import_iso_c_binding_module (void)
> {
> #define NAMED_FUNCTION(a,b,c,d) \
> case a: \
> + if (a == ISOCBINDING_LOC) \
> + create_intrinsic_function (b, (gfc_isym_id) c, \
> + iso_c_module_name, \
> + INTMOD_ISO_C_BINDING, false, \
> + c_ptr->n.sym); \
> + else if (a == ISOCBINDING_FUNLOC) \
> + create_intrinsic_function (b, (gfc_isym_id) c, \
> + iso_c_module_name, \
> + INTMOD_ISO_C_BINDING, false, \
> + c_funptr->n.sym); \
> + else \
> + create_intrinsic_function (b, (gfc_isym_id) c, \
> + iso_c_module_name, \
> + INTMOD_ISO_C_BINDING, false, \
> + NULL); \
> + break;
...and here...
> default:
> - generate_isocbinding_symbol (iso_c_module_name,
> - (iso_c_binding_symbol) i, NULL);
> + if (i == ISOCBINDING_NULL_PTR)
> + generate_isocbinding_symbol (iso_c_module_name,
> + (iso_c_binding_symbol) i, NULL,
> + c_ptr, false);
> + else if (i == ISOCBINDING_NULL_FUNPTR)
> + generate_isocbinding_symbol (iso_c_module_name,
> + (iso_c_binding_symbol) i, NULL,
> + c_funptr, false);
> + else
> + generate_isocbinding_symbol (iso_c_module_name,
> + (iso_c_binding_symbol) i, NULL,
> + NULL, false);
... and here.
> diff --git a/gcc/testsuite/gfortran.dg/blockdata_7.f90 b/gcc/testsuite/gfortran.dg/blockdata_7.f90
> new file mode 100644
> index 0000000..16329c3
> --- /dev/null
> +++ b/gcc/testsuite/gfortran.dg/blockdata_7.f90
> @@ -0,0 +1,16 @@
> +! { dg-compile }
dg-do compile
> diff --git a/gcc/testsuite/gfortran.dg/c_f_pointer_tests_6.f90 b/gcc/testsuite/gfortran.dg/c_f_pointer_tests_6.f90
> new file mode 100644
> index 0000000..19393c8
> --- /dev/null
> +++ b/gcc/testsuite/gfortran.dg/c_f_pointer_tests_6.f90
> @@ -0,0 +1,43 @@
> +! { dg-compile }
dg-do compile
-------------- next part --------------
! { dg-do compile }
!
! PR fortran/55574
! The following code used to be accepted because C_LOC pulls in C_PTR
! implicitly.
!
! Contributed by Valery Weber <valeryweber@hotmail.com>
!
program aaaa
use iso_c_binding, only : c_loc
integer, target :: i
type(C_PTR) :: f_ptr ! { dg-error "being used before it is defined" }
f_ptr=c_loc(i) ! { dg-error "Can't convert" }
end program aaaa
More information about the Fortran
mailing list