Index: gcc/fortran/interface.c =================================================================== *** gcc/fortran/interface.c (revision 114148) --- gcc/fortran/interface.c (working copy) *************** compare_parameter (gfc_symbol * formal, *** 1123,1129 **** && !compare_type_rank (formal, actual->symtree->n.sym)) return 0; ! if (formal->attr.if_source == IFSRC_UNKNOWN) return 1; /* Assume match */ return compare_interfaces (formal, actual->symtree->n.sym, 0); --- 1123,1130 ---- && !compare_type_rank (formal, actual->symtree->n.sym)) return 0; ! if (formal->attr.if_source == IFSRC_UNKNOWN ! || actual->symtree->n.sym->attr.external) return 1; /* Assume match */ return compare_interfaces (formal, actual->symtree->n.sym, 0); *************** compare_actual_formal (gfc_actual_arglis *** 1177,1182 **** --- 1178,1184 ---- { gfc_actual_arglist **new, *a, *actual, temp; gfc_formal_arglist *f; + gfc_gsymbol *gsym; int i, n, na; bool rank_check; *************** compare_actual_formal (gfc_actual_arglis *** 1276,1281 **** --- 1278,1301 ---- return 0; } + /* Satisfy 12.4.1.2 by ensuring that a procedure actual argument is + provided for a procedure formal argument. */ + if (a->expr->ts.type != BT_PROCEDURE + && a->expr->expr_type == EXPR_VARIABLE + && f->sym->attr.flavor == FL_PROCEDURE) + { + gsym = gfc_find_gsymbol (gfc_gsym_root, + a->expr->symtree->n.sym->name); + if (gsym == NULL || (gsym->type != GSYM_FUNCTION + && gsym->type != GSYM_SUBROUTINE)) + { + if (where) + gfc_error ("Expected a procedure for argument '%s' at %L", + f->sym->name, &a->expr->where); + return 0; + } + } + if (f->sym->as && f->sym->as->type == AS_ASSUMED_SHAPE && a->expr->expr_type == EXPR_VARIABLE Index: gcc/testsuite/gfortran.dg/dummy_procedure_1.f90 =================================================================== *** gcc/testsuite/gfortran.dg/dummy_procedure_1.f90 (revision 0) --- gcc/testsuite/gfortran.dg/dummy_procedure_1.f90 (revision 0) *************** *** 0 **** --- 1,47 ---- + ! { dg-do compile } + ! Test the patch for PR25098, where passing a variable as an + ! actual argument to a formal argument that is a procedure + ! went undiagnosed. + ! + ! Based on contribution by Joost VandeVondele + ! + integer function y() + y = 1 + end + integer function z() + z = 1 + end + + module m1 + contains + subroutine s1(f) + interface + function f() + integer f + end function f + end interface + end subroutine s1 + end module m1 + + use m1 + external y + interface + function x() + integer x + end function x + end interface + + integer :: i, y, z + i=1 + call s1(i) ! { dg-error "Expected a procedure for argument" } + call s1(w) ! { dg-error "not allowed as an actual argument" } + call s1(x) ! explicit interface + call s1(y) ! declared external + call s1(z) ! already compiled + contains + integer function w() + w = 1 + end function w + end + + ! { dg-final { cleanup-modules "m1" } } Index: gcc/testsuite/gfortran.dg/dummy_procedure_2.f90 =================================================================== *** gcc/testsuite/gfortran.dg/dummy_procedure_2.f90 (revision 0) --- gcc/testsuite/gfortran.dg/dummy_procedure_2.f90 (revision 0) *************** *** 0 **** --- 1,33 ---- + ! { dg-do compile } + ! Checks the fix for the bug exposed in fixing PR25147 + ! + ! Contributed by Tobias Schlueter + ! + module integrator + interface + function integrate(f,xmin,xmax) + implicit none + interface + function f(x) + real(8) :: f,x + intent(in) :: x + end function f + end interface + real(8) :: xmin, xmax, integrate + end function integrate + end interface + end module integrator + + use integrator + call foo1 () + call foo2 () + contains + subroutine foo1 () + real(8) :: f ! This was not trapped: PR25147/25098 + print *,integrate (f,0d0,3d0) ! { dg-error "Expected a procedure" } + end subroutine foo1 + subroutine foo2 () + real(8), external :: g ! This would give an error, incorrectly. + print *,integrate (g,0d0,3d0) + end subroutine foo2 + end