The following variant of proc_ptr_8.* fails at runtime: ! { dg-do run } ! { dg-additional-sources proc_ptr_8.c } MODULE X USE ISO_C_BINDING INTERFACE INTEGER(KIND=C_INT) FUNCTION mytype( a ) BIND(C) USE ISO_C_BINDING INTEGER(KIND=C_INT), VALUE :: a END FUNCTION SUBROUTINE init() BIND(C,name="init") END SUBROUTINE END INTERFACE TYPE(C_FUNPTR), BIND(C,name="funpointer") :: funpointer END MODULE X USE X PROCEDURE(mytype), POINTER :: ptype CALL init() call setpointer(ptype) if (ptype(3) /= 9) call abort() contains subroutine setpointer (p) PROCEDURE(mytype), POINTER :: p CALL C_F_PROCPOINTER(funpointer,p) end subroutine END ! { dg-final { cleanup-modules "X" } } /* Used by proc_ptr_8.f90. PR fortran/32580. */ int (*funpointer)(int); int f(int t) { return t*3; } void init() { funpointer=f; }
Side-note on C_F_PROCPOINTER: The manual claims that ... "Due to the currently lacking support of procedure pointers in GNU Fortran this function is not fully operable." ... which is a dirty lie.
Proposed fix: Index: gcc/fortran/trans-expr.c =================================================================== --- gcc/fortran/trans-expr.c (revision 154189) +++ gcc/fortran/trans-expr.c (working copy) @@ -2645,6 +2645,12 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * tmp = gfc_get_ppc_type (arg->next->expr->ref->u.c.component); else tmp = TREE_TYPE (arg->next->expr->symtree->n.sym->backend_decl); + + if (arg->next->expr->symtree->n.sym->attr.proc_pointer + && arg->next->expr->symtree->n.sym->attr.dummy) + fptrse.expr = build_fold_indirect_ref_loc (input_location, + fptrse.expr); + se->expr = fold_build2 (MODIFY_EXPR, tmp, fptrse.expr, fold_convert (tmp, cptrse.expr));
call setpointer(ptype) is being converted into: setpointer.1481 (); So inside MAIN__ we have: static void setpointer (integer(kind=4) (*<T3af>) (integer(kind=4))); setpointer (&ptype); That is wrong, unless I am missing a reference type somewhere. Plus inside setpointer I think: p = (integer(kind=4) (*<T3af>) (integer(kind=4)) *) funpointer; is incorrect, it should be: *p = funpointer;
Wrong buttons :).
(In reply to comment #3) > So inside MAIN__ we have: > static void setpointer (integer(kind=4) (*<T3af>) (integer(kind=4))); > setpointer (&ptype); > > That is wrong, unless I am missing a reference type somewhere. Yes, indeed the 'static' line is wrong. However, it does not seem to have any consequences. > Plus inside setpointer I think: > p = (integer(kind=4) (*<T3af>) (integer(kind=4)) *) funpointer; > > is incorrect, it should be: > *p = funpointer; Right, this is corrected by my patch in comment #2. With that patch, the dump shows: setpointer (integer(kind=4) (*<T3d4>) (integer(kind=4)) * p) { *p = (integer(kind=4) (*<T3d4>) (integer(kind=4))) funpointer; } MAIN__ () { extern void (*<T62>) (void) funpointer; integer(kind=4) (*<T3d4>) (integer(kind=4)) ptype; integer(kind=4) (*<T3d4>) (integer(kind=4)) ptype2; static void setpointer (integer(kind=4) (*<T3d4>) (integer(kind=4))); Here the 'setpointer' routine is ok, but again the static declaration is wrong.
Subject: Bug 42072 Author: janus Date: Wed Nov 18 13:24:54 2009 New Revision: 154292 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=154292 Log: 2009-11-18 Janus Weil <janus@gcc.gnu.org> PR fortran/42072 * trans-expr.c (gfc_conv_procedure_call): Handle procedure pointer dummies which are passed to C_F_PROCPOINTER. 2009-11-18 Janus Weil <janus@gcc.gnu.org> PR fortran/42072 * gfortran.dg/proc_ptr_8.f90: Extended. Modified: trunk/gcc/fortran/ChangeLog trunk/gcc/fortran/trans-expr.c trunk/gcc/testsuite/ChangeLog trunk/gcc/testsuite/gfortran.dg/proc_ptr_8.f90
The runtime problem and the obsolete comment in the manual are fixed now. So the only issue left is the wrong static declaration reported in comment #3.
(In reply to comment #7) > So the only issue left is the wrong static declaration reported in comment #3. This is now PR 42122. Closing this one.