Found by James Van Buskirk at http://groups.google.com/group/comp.lang.fortran/browse_thread/thread/c8dd08d6da052499/ The following program gives an ICE in transfer; one may argue whether it is valid or not, but I would expect that it works on all systems. The crash occurs in: ==28354== at 0x477713: gfc_interpret_derived (target-memory.c:422) ==28354== by 0x4773DE: gfc_target_interpret_expr (target-memory.c:474) ==28354== by 0x46AA47: gfc_simplify_transfer (simplify.c:4103) ==28354== by 0x42A6A2: do_simplify (intrinsic.c:3186) which is: ptr = TREE_INT_CST_LOW (DECL_FIELD_OFFSET (cmp->backend_decl)); Using NAG f95 and ifort, it works and prints ".FALSE.". program bug2_transfer use ISO_C_BINDING implicit none type(C_PTR) C_NULL_PTR1 C_NULL_PTR1 = transfer(0_C_INTPTR_T, C_NULL_PTR1) ! write(*,'(a)') trim(merge('.TRUE. ','.FALSE.', & ! C_ASSOCIATED(C_NULL_PTR1))) end program bug2_transfer
Some debugging notes. While the following crashes C_NULL_PTR1 = transfer(0_C_INTPTR_T, C_NULL_PTR1) it works after replacing the constant by a variable. In gfc_simplify_transfer (for the constant expression), /* And read the buffer back into the new expression. */ gfc_target_interpret_expr (buffer, buffer_size, result); is called. Here, "result" is of the type(c_ptr), i.e. ts.type == BT_DERIVED. As it is not a real derived type calling gfc_interpret_derived fails (segfault); converting it into INTEGER works in principle, but it fails in the "C_NULL_PTR1 =" assignment step as one cannot assign an integer to a derived type.
Confirmed.
The ICE itself can be gotten rid of by setting the offset of the private field of our ISO_C derived types: Index: trans-types.c =================================================================== --- trans-types.c (revision 132578) +++ trans-types.c (working copy) @@ -1731,6 +1731,7 @@ get_identifier (derived->components->name), gfc_typenode_for_spec ( &(derived->components->ts))); + DECL_FIELD_OFFSET (derived->components->backend_decl) = size_int (0); derived->ts.kind = gfc_index_integer_kind; derived->ts.type = BT_INTEGER; (Independently of the rest, I think that fix is desirable.) However, with that fix, we now error out: C_NULL_PTR1 = transfer(0_C_INTPTR_T, C_NULL_PTR1) 1 Error: Can't convert INTEGER(4) to TYPE(c_ptr) at (1) The reason for that is that gfc_typenode_for_spec(), which is called from gfc_interpret_derived(), modifies the symbol itself to make it an integer: /* If we're dealing with either C_PTR or C_FUNPTR, we modified the type and kind to fit a (void *) and the basetype returned was a ptr_type_node. We need to pass up this new information to the symbol that was declared of type C_PTR or C_FUNPTR. */ I have always been wary of this course of actions (magically making the ISO_C_BINDING derived types into scalar integer variables), and in that case it is biting us hard. I have tried to work around this in target-memory.c by a custom-tailored fix: Index: target-memory.c =================================================================== --- target-memory.c (revision 132578) +++ target-memory.c (working copy) @@ -379,7 +379,21 @@ /* The attributes of the derived type need to be bolted to the floor. */ result->expr_type = EXPR_STRUCTURE; - type = gfc_typenode_for_spec (&result->ts); + /* FIXME -- This is more of a workaround than a real fix, please see + PR34199 for details. + For ISO_C_BINDING derived types, gfc_typenode_for_spec() will change + the symbol under our feet into an integer, which we don't want, so + we restore it. */ + if (result->ts.type == BT_DERIVED && result->ts.derived->attr.is_iso_c) + { + gfc_typespec ts; + ts = result->ts; + type = gfc_typenode_for_spec (&result->ts); + result->ts = ts; + } + else + type = gfc_typenode_for_spec (&result->ts); + cmp = result->ts.derived->components; /* Run through the derived type components. */ This in turn makes the derived type constructors go into trans-expr.c's gfc_conv_expr(), which does not deal with them. This is fixed with the following patchlet: Index: trans-expr.c =================================================================== --- trans-expr.c (revision 132578) +++ trans-expr.c (working copy) @@ -3517,14 +3517,19 @@ } /* We need to convert the expressions for the iso_c_binding derived types. - C_NULL_PTR and C_NULL_FUNPTR will be made EXPR_NULL, which evaluates to - null_pointer_node. C_PTR and C_FUNPTR are converted to match the - typespec for the C_PTR and C_FUNPTR symbols, which has already been - updated to be an integer with a kind equal to the size of a (void *). */ + C_NULL_PTR, C_NULL_FUNPTR and constants (coming, for example, from the + simplification of TRANSFER expressions) will be made EXPR_NULL, + which evaluates to null_pointer_node. C_PTR and C_FUNPTR are converted + to match the typespec for the C_PTR and C_FUNPTR symbols, which has + already been updated to be an integer with a kind equal to the size of + a (void *). */ if (expr->ts.type == BT_DERIVED && expr->ts.derived && expr->ts.derived->attr.is_iso_c) { - if (expr->symtree->n.sym->intmod_sym_id == ISOCBINDING_NULL_PTR + /* expr->expr_type == EXPR_STRUCTURE matches the constant derived + types. */ + if (expr->expr_type == EXPR_STRUCTURE + || expr->symtree->n.sym->intmod_sym_id == ISOCBINDING_NULL_PTR || expr->symtree->n.sym->intmod_sym_id == ISOCBINDING_NULL_FUNPTR) { /* Set expr_type to EXPR_NULL, which will result in Now, with all three patches, we can compile the testcase and run it fine. I'm not really satisfied with the patch to target-memory.c, as it is more a workaround than a patch. For that reason, I'm not assigning this to myself and will let the ISO_C_BINDING experts decide what course is most appropriate.
(In reply to comment #3) > Now, with all three patches, we can compile the testcase and run it fine. The three patches, together, regtest fine on x86_64-linux (both -m32 and -m64).
Further reports: They might show the same problem, or also different ones. I did not check them all: http://groups.google.com/group/comp.lang.fortran/browse_thread/thread/c553e0034bab977c * * * Patch by FX: http://gcc.gnu.org/ml/gcc-patches/2008-03/msg00546.html My review: http://gcc.gnu.org/ml/fortran/2008-03/msg00232.html
(In reply to comment #5) > Patch by FX: > http://gcc.gnu.org/ml/gcc-patches/2008-03/msg00546.html > > My review: > http://gcc.gnu.org/ml/fortran/2008-03/msg00232.html Your second point in the review is spot on, the patch is certainly not doing the right thing (the trans-expr.c part, at least) :( I've spent some time looking into other options, but this is all too confusing: I wonder if we shouldn't have made these derived types into structures all the way, instead of trying to morph things into pointer types when comes code generation.
Extracted from http://groups.google.com/group/comp.lang.fortran/browse_thread/thread/c553e0034bab977c the following code module bug1 use ISO_C_BINDING implicit none contains subroutine sub1(x) type(C_PTR) x write(*,'(z16.16)') transfer(x,0_C_INTPTR_T) end subroutine sub1 subroutine sub2(x) type(C_FUNPTR) x write(*,'(z16.16)') transfer(x,0_C_INTPTR_T) end subroutine sub2 subroutine sub3() bind(C) end subroutine sub3 end module bug1 program test use bug1 implicit none integer, target :: i type(C_FUNPTR) p p = C_FUNLOC(sub3) call sub1(C_LOC(i)) call sub2(C_FUNLOC(sub3)) ! Causes ICE call sub2(p) ! No ICE end program test gives with trunk and 4.3.2: pr34199_4.f90: In function 'test': pr34199_4.f90:23: internal compiler error: in expand_expr_addr_expr_1, at expr.c:6848
Extracted from http://groups.google.com/group/comp.lang.fortran/browse_thread/thread/c553e0034bab977c the following code module bug1 use ISO_C_BINDING implicit none contains subroutine sub1(x) type(C_PTR) x write(*,'(z16.16)') transfer(x,0_C_INTPTR_T) end subroutine sub1 subroutine sub2(x) type(C_FUNPTR) x write(*,'(z16.16)') transfer(x,0_C_INTPTR_T) end subroutine sub2 end module bug1 program test use bug1 implicit none call sub1(transfer(7_C_INTPTR_T,C_NULL_PTR)) call sub2(transfer(7_C_INTPTR_T,C_NULL_FUNPTR)) end program test gives with trunk and 4.3.2 pr34199_3.f90:7: internal compiler error: Bus error Please submit a full bug report,
Extracted from http://groups.google.com/group/comp.lang.fortran/browse_thread/thread/c553e0034bab977c the following code program bug2_transfer use ISO_C_BINDING implicit none type(C_PTR) C_NULL_PTR1 C_NULL_PTR1 = transfer(23454_C_INTPTR_T, C_NULL_PTR1) write(*,'(a)') trim(merge('.TRUE. ','.FALSE.', & C_ASSOCIATED(C_NULL_PTR1))) end program bug2_transfer gives with trunk and 4.3.2 f951: internal compiler error: Bus error Please submit a full bug report,
This PR seems to have been fixed at revision 168044 (likely r 168031). May be pr46974 was a duplicate of this PR. Could someone check this and close this PR if it is the case? TIA
Yes, looks as duplicate of PR 46974. *** This bug has been marked as a duplicate of bug 46974 ***