Bug 50269 - Wrongly rejects element of assumed-shape array in C_LOC
Summary: Wrongly rejects element of assumed-shape array in C_LOC
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: fortran (show other bugs)
Version: 4.7.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: rejects-valid
Depends on:
Blocks: 53945
  Show dependency treegraph
 
Reported: 2011-09-01 19:38 UTC by Tobias Burnus
Modified: 2013-04-04 07:41 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2013-04-02 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Tobias Burnus 2011-09-01 19:38:38 UTC
Reported by Ian Bush in comp.lang.fortran, http://groups.google.com/group/comp.lang.fortran/browse_thread/thread/71338937cf348f26


     b = c_loc( aa( 1 ) )
                1
Error: Assumed-shape array 'aa' at (1) cannot be an argument to the procedure 'c_loc' because it is not C interoperable



Program gf
   Use iso_c_binding
   Real( c_double ), Dimension( 1:10 ), Target :: a
   Call test( a )
Contains
   Subroutine test( aa )
     Real( c_double ), Dimension( : ), Target :: aa
     Type( c_ptr ), Pointer :: b
     b = c_loc( aa( 1 ) )
   End Subroutine test
End Program gf
Comment 1 kargls 2011-09-01 20:24:42 UTC
This allows the code to compile, but one then gets a segfault
or the right answer depending on memory layout.  I think
trans-expr.c(conv_isocbinding_procedure) needs to be updated
as well, but don't know what needs to be done (yet).

Index: resolve.c
===================================================================
--- resolve.c   (revision 178329)
+++ resolve.c   (working copy)
@@ -2809,7 +2809,8 @@ gfc_iso_c_func_interface (gfc_symbol *sy
                         interoperable.  */
                      if (args_sym && args_sym->attr.dimension)
                        {
-                         if (args_sym->as->type == AS_ASSUMED_SHAPE)
+                         if (args_sym->as->type == AS_ASSUMED_SHAPE
+                             && args->expr->ref->u.ar.type != AR_ELEMENT)
                            {
                              gfc_error ("Assumed-shape array '%s' at %L "
                                         "cannot be an argument to the "


troutmask:sgk[215] gfc4x -o z foo.f90 && ./z
 Calling test()
c_loc(aa)  = 140737488344288
troutmask:sgk[216] gfc4x -o z foo.f90 && ./z
Segmentation fault (core dumped)

program gf
   use iso_c_binding
   real(c_double), dimension(1:10), target :: a
!   a = 42
!   print *, 'Calling test()'
   call test(a)
   contains
      subroutine test(aa)
        real(c_double), dimension(:), target :: aa
        type(c_ptr), pointer :: b
        b = c_loc(aa(1))
        print '(A,I0)', 'c_loc(aa)  = ', b
      end subroutine test
end program gf
Comment 2 Tobias Burnus 2011-09-01 21:10:05 UTC
(In reply to comment #1)
> This allows the code to compile, but one then gets a segfault
> or the right answer depending on memory layout.  I think
> trans-expr.c(conv_isocbinding_procedure) needs to be updated
> as well, but don't know what needs to be done (yet).

It might be that it accesses the descriptor instead of desc.data.


> -                         if (args_sym->as->type == AS_ASSUMED_SHAPE)
> +                         if (args_sym->as->type == AS_ASSUMED_SHAPE
> +                             && args->expr->ref->u.ar.type != AR_ELEMENT)
>                             {
>                               gfc_error ("Assumed-shape array '%s' at %L "
>                                          "cannot be an argument to the "

I think one should use the opportunity to update it to Fortran 2008, which allows also assumed/deferred-shape arrays - if they are contiguous:

F2008, 15.2.3.6 C LOC (X):

"Argument. X shall have either the POINTER or TARGET attribute. It shall not be a coindexed object. It shall either be a variable with interoperable type and kind type parameters, or be a scalar, nonpolymorphic variable with no length type parameters. If it is allocatable, it shall be allocated. If it is a pointer, it shall be associated. If it is an array, it shall be contiguous and have nonzero size. It shall not be a zero-length string."


Note: It talks about "contiguous" and not "simply contiguous", which means that it is not compile-time checkable (unless strides are used or a vector index). I think there is also a coindexed check missing.


Fortran 2003 had in 15.1.2.5 C LOC (X):

"Argument. X shall either
 (1) have interoperable type and type parameters and be
   (a) a variable that has the TARGET attribute and is interoperable,
   (b) an allocated allocatable variable that has the TARGET attribute
       and is not an array of zero size, or
   (c) an associated scalar pointer, or
 (2) be a nonpolymorphic scalar, have no length type parameters, and be
   (a) a nonallocatable, nonpointer variable that has the TARGET attribute,
   (b) an allocated allocatable variable that has the TARGET attribute, or
   (c) an associated pointer."
Comment 3 Tobias Burnus 2013-03-25 15:53:57 UTC
Author: burnus
Date: Mon Mar 25 15:40:26 2013
New Revision: 197053

URL: http://gcc.gnu.org/viewcvs?rev=197053&root=gcc&view=rev
Log:
2013-03-25  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/47034
        PR fortran/49023
        PR fortran/50269
        PR fortran/50612
        PR fortran/52426
        PR fortran/54263
        PR fortran/55343
        PR fortran/55444
        PR fortran/55574
        PR fortran/56079
        PR fortran/56378
        * check.c (gfc_var_strlen): Properly handle 0-sized string.
        (gfc_check_c_sizeof): Use is_c_interoperable, add checks.
        (is_c_interoperable, gfc_check_c_associated, gfc_check_c_f_pointer,
        gfc_check_c_f_procpointer, gfc_check_c_funloc, gfc_check_c_loc): New
        functions.
        * expr.c (check_inquiry): Add c_sizeof, compiler_version and
        compiler_options.
        (gfc_check_pointer_assign): Refine function result check.
        gfortran.h (gfc_isym_id): Add GFC_ISYM_C_ASSOCIATED,
        GFC_ISYM_C_F_POINTER, GFC_ISYM_C_F_PROCPOINTER, GFC_ISYM_C_FUNLOC,
        GFC_ISYM_C_LOC.
        (iso_fortran_env_symbol, iso_c_binding_symbol): Handle
        NAMED_SUBROUTINE.
        (generate_isocbinding_symbol): Update prototype.
        (get_iso_c_sym): Remove.
        (gfc_isym_id_by_intmod, gfc_isym_id_by_intmod_sym): New prototypes.
        * intrinsic.c (gfc_intrinsic_subroutine_by_id): New function.
        (gfc_intrinsic_sub_interface): Use it.
        (add_functions, add_subroutines): Add missing C-binding intrinsics.
        (gfc_intrinsic_func_interface): Add special case for c_loc.
        gfc_isym_id_by_intmod, gfc_isym_id_by_intmod_sym): New functions.
        (gfc_intrinsic_func_interface, gfc_intrinsic_sub_interface): Use them.
        * intrinsic.h (gfc_check_c_associated, gfc_check_c_f_pointer,
        gfc_check_c_f_procpointer, gfc_check_c_funloc, gfc_check_c_loc,
        gfc_resolve_c_loc, gfc_resolve_c_funloc): New prototypes.
        * iresolve.c (gfc_resolve_c_loc, gfc_resolve_c_funloc): New
        functions.
        * iso-c-binding.def: Split PROCEDURE into NAMED_SUBROUTINE and
        NAMED_FUNCTION.
        * iso-fortran-env.def: Add NAMED_SUBROUTINE for completeness.
        * module.c (create_intrinsic_function): Support subroutines and
        derived-type results.
        (use_iso_fortran_env_module): Update calls.
        (import_iso_c_binding_module): Ditto; update calls to
        generate_isocbinding_symbol.
        * resolve.c (find_arglists): Skip for intrinsic symbols.
        (gfc_resolve_intrinsic): Find intrinsic subs via id.
        (is_scalar_expr_ptr, gfc_iso_c_func_interface,
        set_name_and_label, gfc_iso_c_sub_interface): Remove.
        (resolve_function, resolve_specific_s0): Remove calls to those.
        (resolve_structure_cons): Fix handling.
        * symbol.c (gen_special_c_interop_ptr): Update c_ptr/c_funptr
        generation.
        (gen_cptr_param, gen_fptr_param, gen_shape_param,
        build_formal_args, get_iso_c_sym): Remove.
        (std_for_isocbinding_symbol): Handle NAMED_SUBROUTINE.
        (generate_isocbinding_symbol): Support hidden symbols and
        using c_ptr/c_funptr symtrees for nullptr defs.
        * target-memory.c (gfc_target_encode_expr): Fix handling
        of c_ptr/c_funptr.
        * trans-expr.c (conv_isocbinding_procedure): Remove.
        (gfc_conv_procedure_call): Remove call to it.
        (gfc_trans_subcomponent_assign, gfc_conv_expr): Update handling
        of c_ptr/c_funptr.
        * trans-intrinsic.c (conv_isocbinding_function,
        conv_isocbinding_subroutine): New.
        (gfc_conv_intrinsic_function, gfc_conv_intrinsic_subroutine):
        Call them.
        * trans-io.c (transfer_expr): Fix handling of c_ptr/c_funptr.
        * trans-types.c (gfc_typenode_for_spec,
        gfc_get_derived_type): Ditto.
        (gfc_init_c_interop_kinds): Handle NAMED_SUBROUTINE.

2013-03-25  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/47034
        PR fortran/49023
        PR fortran/50269
        PR fortran/50612
        PR fortran/52426
        PR fortran/54263
        PR fortran/55343
        PR fortran/55444
        PR fortran/55574
        PR fortran/56079
        PR fortran/56378
        * gfortran.dg/c_assoc_2.f03: Update dg-error wording.
        * gfortran.dg/c_f_pointer_shape_test.f90: Ditto.
        * gfortran.dg/c_f_pointer_shape_tests_3.f03: Ditto.
        * gfortran.dg/c_f_pointer_tests_5.f90: Ditto.
        * gfortran.dg/c_funloc_tests_2.f03: Ditto.
        * gfortran.dg/c_funloc_tests_5.f03: Ditto.
        * gfortran.dg/c_funloc_tests_6.f90: Ditto.
        * gfortran.dg/c_loc_tests_10.f03: Add -std=f2008.
        * gfortran.dg/c_loc_tests_11.f03: Ditto, update dg-error.
        * gfortran.dg/c_loc_tests_16.f90: Ditto.
        * gfortran.dg/c_loc_tests_4.f03: Ditto.
        * gfortran.dg/c_loc_tests_15.f90: Update dg-error wording.
        * gfortran.dg/c_loc_tests_3.f03: Valid since F2003 TC5.
        * gfortran.dg/c_loc_tests_8.f03: Ditto.
        * gfortran.dg/c_ptr_tests_14.f90: Update scan-tree-dump-times.
        * gfortran.dg/c_ptr_tests_15.f90: Ditto.
        * gfortran.dg/c_sizeof_1.f90: Fix invalid code.
        * gfortran.dg/iso_c_binding_init_expr.f03: Update dg-error wording.
        * gfortran.dg/pr32601_1.f03: Ditto.
        * gfortran.dg/storage_size_2.f08: Remove dg-error.
        * gfortran.dg/blockdata_7.f90: New.
        * gfortran.dg/c_assoc_4.f90: New.
        * gfortran.dg/c_f_pointer_tests_6.f90: New.
        * gfortran.dg/c_f_pointer_tests_7.f90: New.
        * gfortran.dg/c_funloc_tests_8.f90: New.
        * gfortran.dg/c_loc_test_17.f90: New.
        * gfortran.dg/c_loc_test_18.f90: New.
        * gfortran.dg/c_loc_test_19.f90: New.
        * gfortran.dg/c_loc_test_20.f90: New.
        * gfortran.dg/c_sizeof_5.f90: New.
        * gfortran.dg/iso_c_binding_rename_3.f90: New.
        * gfortran.dg/transfer_resolve_2.f90: New.
        * gfortran.dg/transfer_resolve_3.f90: New.
        * gfortran.dg/transfer_resolve_4.f90: New.
        * gfortran.dg/pr32601.f03: Update dg-error.
        * gfortran.dg/c_ptr_tests_13.f03: Update dg-error.
        * gfortran.dg/c_ptr_tests_9.f03: Fix test case.


Added:
    trunk/gcc/testsuite/gfortran.dg/blockdata_7.f90
    trunk/gcc/testsuite/gfortran.dg/c_assoc_4.f90
    trunk/gcc/testsuite/gfortran.dg/c_f_pointer_tests_6.f90
    trunk/gcc/testsuite/gfortran.dg/c_f_pointer_tests_7.f90
    trunk/gcc/testsuite/gfortran.dg/c_funloc_tests_8.f90
    trunk/gcc/testsuite/gfortran.dg/c_loc_test_17.f90
    trunk/gcc/testsuite/gfortran.dg/c_loc_test_18.f90
    trunk/gcc/testsuite/gfortran.dg/c_loc_test_19.f90
    trunk/gcc/testsuite/gfortran.dg/c_loc_test_20.f90
    trunk/gcc/testsuite/gfortran.dg/c_loc_tests_17.f90
    trunk/gcc/testsuite/gfortran.dg/c_sizeof_5.f90
    trunk/gcc/testsuite/gfortran.dg/iso_c_binding_rename_3.f90
    trunk/gcc/testsuite/gfortran.dg/transfer_resolve_2.f90
    trunk/gcc/testsuite/gfortran.dg/transfer_resolve_3.f90
    trunk/gcc/testsuite/gfortran.dg/transfer_resolve_4.f90
Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/check.c
    trunk/gcc/fortran/expr.c
    trunk/gcc/fortran/gfortran.h
    trunk/gcc/fortran/intrinsic.c
    trunk/gcc/fortran/intrinsic.h
    trunk/gcc/fortran/iresolve.c
    trunk/gcc/fortran/iso-c-binding.def
    trunk/gcc/fortran/iso-fortran-env.def
    trunk/gcc/fortran/module.c
    trunk/gcc/fortran/resolve.c
    trunk/gcc/fortran/symbol.c
    trunk/gcc/fortran/target-memory.c
    trunk/gcc/fortran/trans-expr.c
    trunk/gcc/fortran/trans-intrinsic.c
    trunk/gcc/fortran/trans-io.c
    trunk/gcc/fortran/trans-types.c
    trunk/gcc/testsuite/ChangeLog
    trunk/gcc/testsuite/gfortran.dg/c_assoc_2.f03
    trunk/gcc/testsuite/gfortran.dg/c_f_pointer_shape_test.f90
    trunk/gcc/testsuite/gfortran.dg/c_f_pointer_shape_tests_3.f03
    trunk/gcc/testsuite/gfortran.dg/c_f_pointer_tests_5.f90
    trunk/gcc/testsuite/gfortran.dg/c_funloc_tests_2.f03
    trunk/gcc/testsuite/gfortran.dg/c_funloc_tests_5.f03
    trunk/gcc/testsuite/gfortran.dg/c_funloc_tests_6.f90
    trunk/gcc/testsuite/gfortran.dg/c_loc_tests_10.f03
    trunk/gcc/testsuite/gfortran.dg/c_loc_tests_11.f03
    trunk/gcc/testsuite/gfortran.dg/c_loc_tests_15.f90
    trunk/gcc/testsuite/gfortran.dg/c_loc_tests_16.f90
    trunk/gcc/testsuite/gfortran.dg/c_loc_tests_3.f03
    trunk/gcc/testsuite/gfortran.dg/c_loc_tests_4.f03
    trunk/gcc/testsuite/gfortran.dg/c_loc_tests_8.f03
    trunk/gcc/testsuite/gfortran.dg/c_ptr_tests_13.f03
    trunk/gcc/testsuite/gfortran.dg/c_ptr_tests_14.f90
    trunk/gcc/testsuite/gfortran.dg/c_ptr_tests_15.f90
    trunk/gcc/testsuite/gfortran.dg/c_ptr_tests_9.f03
    trunk/gcc/testsuite/gfortran.dg/c_sizeof_1.f90
    trunk/gcc/testsuite/gfortran.dg/iso_c_binding_init_expr.f03
    trunk/gcc/testsuite/gfortran.dg/pr32601.f03
    trunk/gcc/testsuite/gfortran.dg/pr32601_1.f03
    trunk/gcc/testsuite/gfortran.dg/storage_size_2.f08
Comment 4 Tobias Burnus 2013-03-25 17:49:21 UTC
FIXED on the 4.9 trunk.
Comment 5 Rich Townsend 2013-04-01 15:30:54 UTC
(In reply to comment #4)
> FIXED on the 4.9 trunk.

Is this going to be ported back to earlier releases? It's kind of a biggie for me...
Comment 6 Rich Townsend 2013-04-01 22:24:35 UTC
(In reply to comment #4)
> FIXED on the 4.9 trunk.

Are we sure? When running the code example given in comment #1, I get a segfault.

Moreover, the following subroutine won't compile when using the '-std=f2008' flag:

subroutine test_contig (a)
  use ISO_C_BINDING
  real, intent(in), contiguous, target :: a(:)
  type(C_PTR) :: b
  b = C_LOC(a)
end subroutine test_contig

The error message is:

test_contig.f90:9.12:

  b = C_LOC(a)
            1
Error: TS 29113: Noninteroperable array at (1) as argument to C_LOC: Only explicit-size and assumed-size arrays are interoperable

My understanding of the F2008 standard is that assumed-shape arrays with the contiguous attribute are interoperable -- hence, I'm not sure this error message is correct. If I change the std flag to f2008ts, then the routine compiles OK; but the TS extension shouldn't be required here.

gfortran -v:

Using built-in specs.
COLLECT_GCC=/Applications/madsdk/bin/gfortran.exec
COLLECT_LTO_WRAPPER=/Applications/madsdk/libexec/gcc/x86_64-apple-darwin11.4.2/4.9.0/lto-wrapper
Target: x86_64-apple-darwin11.4.2
Configured with: ./configure CC='gcc -D_FORTIFY_SOURCE=0' --build=x86_64-apple-darwin11.4.2 --prefix=/Applications/madsdk --with-gmp=/Applications/madsdk --with-mpfr=/Applications/madsdk --with-mpc=/Applications/madsdk --enable-languages=c,c++,fortran --disable-multilib
Thread model: posix
gcc version 4.9.0 20130401 (experimental) (GCC)
Comment 7 Tobias Burnus 2013-04-02 07:52:26 UTC
REOPEN

(In reply to comment #5)
> Is this going to be ported back to earlier releases? It's kind of a biggie for
> me...

Probably not - it is a rather large change - and, hence, it might cause regressions.


(In reply to comment #6)
> Are we sure? When running the code example given in comment #1, I get a
> segfault.

Yes, something seems to be still broken.


> Moreover, the following subroutine won't compile when using the '-std=f2008'
> flag:
>   real, intent(in), contiguous, target :: a(:)
>   b = C_LOC(a)
> 
> The error message is:
> test_contig.f90:9.12:
>   b = C_LOC(a)
>             1
> Error: TS 29113: Noninteroperable array at (1) as argument to C_LOC: Only
> explicit-size and assumed-size arrays are interoperable
> 
> My understanding of the F2008 standard is that assumed-shape arrays with the
> contiguous attribute are interoperable


Well, Fortran 2008 has:

"A Fortran variable that is a named array is interoperable if and only if its type and type parameters are interoperable, it is not a coarray, it is of explicit shape or assumed size, and if it is of type character its length is not
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
assumed or declared by an expression that is not a constant expression."
("15.3.6 Interoperability of array variables")


Thus, it is definitely not interoperable. But the real question is whether it is permitted for C_LOC. From "15.2.3.6 C_LOC(X)":

"Argument. X shall have either the POINTER or TARGET attribute. It shall not be a coindexed object. It shall either be a variable with interoperable type and kind type parameters, or be a scalar, nonpolymorphic variable with no length type parameters. If it is allocatable, it shall be allocated. If it is a pointer, it shall be associated. If it is an array, it shall be contiguous and have nonzero size. It shall not be a zero-length string."



I think the crucial part is: "with interoperable type and kind type parameter" - which is different to the other intrinsics, which require "an interoperable data entity". Thus, it seems to be permitted in C_LOC.


Thanks for testing.
Comment 8 Tobias Burnus 2013-04-02 13:28:00 UTC
(In reply to comment #7)
> (In reply to comment #6)
> > Are we sure? When running the code example given in comment #1, I get a
> > segfault.
> Yes, something seems to be still broken.

Actually, the compiler generates the correct code. The problem with the test case of comment 0 and comment 1 is that "b" is a pointer but never allocated.

It works if one either removes "pointer" from the declaration of "b" or adds an "allocate(b)".
Comment 9 Tobias Burnus 2013-04-04 07:37:01 UTC
Author: burnus
Date: Thu Apr  4 07:22:24 2013
New Revision: 197468

URL: http://gcc.gnu.org/viewcvs?rev=197468&root=gcc&view=rev
Log:
2013-04-04  Tobias Burnus  <burnus@net-b.de>

        PR fortran/50269
        * gcc/fortran/check.c (is_c_interoperable,
        gfc_check_c_loc): Correct c_loc array checking
        for Fortran 2003 and Fortran 2008.

2013-04-04  Tobias Burnus  <burnus@net-b.de>

        PR fortran/50269
        * gfortran.dg/c_loc_test_21.f90: New.
        * gfortran.dg/c_loc_test_19.f90: Update dg-error.
        * gfortran.dg/c_loc_tests_10.f03: Update dg-error.
        * gfortran.dg/c_loc_tests_11.f03: Update dg-error.
        * gfortran.dg/c_loc_tests_4.f03: Update dg-error.
        * gfortran.dg/c_loc_tests_16.f90:  Update dg-error.


Added:
    trunk/gcc/testsuite/gfortran.dg/c_loc_test_21.f90
Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/check.c
    trunk/gcc/testsuite/ChangeLog
    trunk/gcc/testsuite/gfortran.dg/c_loc_test_19.f90
    trunk/gcc/testsuite/gfortran.dg/c_loc_tests_10.f03
    trunk/gcc/testsuite/gfortran.dg/c_loc_tests_11.f03
    trunk/gcc/testsuite/gfortran.dg/c_loc_tests_16.f90
    trunk/gcc/testsuite/gfortran.dg/c_loc_tests_4.f03
Comment 10 Tobias Burnus 2013-04-04 07:41:20 UTC
FIXED on the 4.9 trunk.

I have now updated some constraint checks, hopefully, -std=f2003/f2008/f2008ts are now handled correctly.


Missing is a check whether the argument is not contiguous. But that's tracked elsewhere. (Note: The standard does not demand simply contiguous but only contiguous arrays - thus, the compiler can only reject simple-to-detect noncontiguous arrays.)