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  <bur...@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


! { 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 <valerywe...@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

Reply via email to