Hi all, the attached patch allows type-bound procedures to be passed actual arguments to dummy procedures. When doing this, on has to transform the expression such that the corresponding procedure pointer from the vtab is used.
The patch is regtested on x86_64-unknown-linux-gnu. Ok for trunk? Cheers, Janus 2015-01-03 Janus Weil <ja...@gcc.gnu.org> PR fortran/63552 * primary.c (gfc_match_varspec): Handle type-bound procedures as actual argument to dummy procedure. 2015-01-03 Janus Weil <ja...@gcc.gnu.org> PR fortran/63552 * gfortran.dg/typebound_proc_34.f90: New.
Index: gcc/fortran/primary.c =================================================================== --- gcc/fortran/primary.c (Revision 219159) +++ gcc/fortran/primary.c (Arbeitskopie) @@ -1826,6 +1826,7 @@ gfc_match_varspec (gfc_expr *primary, int equiv_fl gfc_ref *substring, *tail; gfc_component *component; gfc_symbol *sym = primary->symtree->n.sym; + gfc_symbol *dt = NULL; match m; bool unknown; @@ -1929,7 +1930,7 @@ gfc_match_varspec (gfc_expr *primary, int equiv_fl || gfc_match_char ('%') != MATCH_YES) goto check_substring; - sym = sym->ts.u.derived; + dt = sym->ts.u.derived; for (;;) { @@ -1942,8 +1943,8 @@ gfc_match_varspec (gfc_expr *primary, int equiv_fl if (m != MATCH_YES) return MATCH_ERROR; - if (sym->f2k_derived) - tbp = gfc_find_typebound_proc (sym, &t, name, false, &gfc_current_locus); + if (dt->f2k_derived) + tbp = gfc_find_typebound_proc (dt, &t, name, false, &gfc_current_locus); else tbp = NULL; @@ -1950,6 +1951,7 @@ gfc_match_varspec (gfc_expr *primary, int equiv_fl if (tbp) { gfc_symbol* tbp_sym; + gfc_actual_arglist *actual = NULL; if (!t) return MATCH_ERROR; @@ -1967,37 +1969,48 @@ gfc_match_varspec (gfc_expr *primary, int equiv_fl else tbp_sym = tbp->n.tb->u.specific->n.sym; - primary->expr_type = EXPR_COMPCALL; - primary->value.compcall.tbp = tbp->n.tb; - primary->value.compcall.name = tbp->name; - primary->value.compcall.ignore_pass = 0; - primary->value.compcall.assign = 0; - primary->value.compcall.base_object = NULL; - gcc_assert (primary->symtree->n.sym->attr.referenced); if (tbp_sym) primary->ts = tbp_sym->ts; else gfc_clear_ts (&primary->ts); - m = gfc_match_actual_arglist (tbp->n.tb->subroutine, - &primary->value.compcall.actual); + m = gfc_match_actual_arglist (tbp->n.tb->subroutine, &actual); if (m == MATCH_ERROR) return MATCH_ERROR; - if (m == MATCH_NO) + if (m == MATCH_YES || sub_flag) { - if (sub_flag) - primary->value.compcall.actual = NULL; - else - { - gfc_error ("Expected argument list at %C"); - return MATCH_ERROR; - } + primary->expr_type = EXPR_COMPCALL; + primary->value.compcall.tbp = tbp->n.tb; + primary->value.compcall.name = tbp->name; + primary->value.compcall.ignore_pass = 0; + primary->value.compcall.assign = 0; + primary->value.compcall.base_object = NULL; + primary->value.compcall.actual = actual; + gcc_assert (primary->symtree->n.sym->attr.referenced); } + else if (!matching_actual_arglist) + { + gfc_error ("Expected argument list at %C"); + return MATCH_ERROR; + } + else if (sym->ts.type == BT_CLASS) + { + gfc_add_vptr_component (primary); + gfc_add_component_ref (primary, name); + } + else if (sym->ts.type == BT_DERIVED) + { + gfc_symtree *symtree; + gfc_symbol *vtab = gfc_find_derived_vtab (dt); + gfc_find_sym_tree (vtab->name, NULL, 1, &symtree); + primary->symtree = symtree; + gfc_add_component_ref (primary, name); + } break; } - component = gfc_find_component (sym, name, false, false); + component = gfc_find_component (dt, name, false, false); if (component == NULL) return MATCH_ERROR; @@ -2005,7 +2018,7 @@ gfc_match_varspec (gfc_expr *primary, int equiv_fl tail->type = REF_COMPONENT; tail->u.c.component = component; - tail->u.c.sym = sym; + tail->u.c.sym = dt; primary->ts = component->ts; @@ -2058,12 +2071,12 @@ gfc_match_varspec (gfc_expr *primary, int equiv_fl || gfc_match_char ('%') != MATCH_YES) break; - sym = component->ts.u.derived; + dt = component->ts.u.derived; } check_substring: unknown = false; - if (primary->ts.type == BT_UNKNOWN && sym->attr.flavor != FL_DERIVED) + if (primary->ts.type == BT_UNKNOWN && !dt) { if (gfc_get_default_type (sym->name, sym->ns)->type == BT_CHARACTER) {
! { dg-do run } ! ! PR 63552: [OOP] Type-bound procedures rejected as actual argument to dummy procedure ! ! Contributed by Tobias Burnus <bur...@gcc.gnu.org> module m type t contains procedure, nopass :: tbp => f end type contains pure integer function f(a,b) integer, intent(in) :: a,b f = a + b end function end module program test use m integer :: a class(t), allocatable :: x type(t) :: y call sub(f) call sub(x%tbp) call sub(y%tbp) contains subroutine sub(arg) procedure(f) :: arg if (f(1,2)/=3) call abort end subroutine end ! { dg-final { cleanup-modules "m" } }