At first this PR looked as if it was going to be one of those horrible typebound procedure/operator tangles. However, it turned out that this was entirely down to the attempt to extract the specific procedure for the ASSOCIATE name during parsing. Returning NULL before expression resolution fixed the problem.
Regtests fine - OK for mainline? I am inclined to backport, since the fix is both simple and, at worst, defers the ICE. OK? Paul
Change.Logs
Description: Binary data
diff --git a/gcc/fortran/interface.cc b/gcc/fortran/interface.cc index f74fbf0f6e5..d08f683498d 100644 --- a/gcc/fortran/interface.cc +++ b/gcc/fortran/interface.cc @@ -4781,6 +4781,13 @@ matching_typebound_op (gfc_expr** tb_base, gfc_actual_arglist* argcopy; bool matches; + /* If expression matching comes here during parsing, eg. when + parsing ASSOCIATE, generic TBPs have not yet been resolved + and g->specific will not have been set. Wait for expression + resolution by returning NULL. */ + if (!g->specific && !gfc_current_ns->resolved) + return NULL; + gcc_assert (g->specific); if (g->specific->error) continue; diff --git a/gcc/testsuite/gfortran.dg/associate_75.f90 b/gcc/testsuite/gfortran.dg/associate_75.f90 new file mode 100644 index 00000000000..c7c461a5cb6 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/associate_75.f90 @@ -0,0 +1,50 @@ +! { dg-do run } +! +! Test fix for PR121060. +! +! Contributed by Damian Rouson <damian@archaeologic.codes> +! +module subdomain_m + implicit none + + type subdomain_t + real :: s_ = 99. + contains + generic :: operator(.laplacian.) => laplacian + procedure laplacian + end type + +contains + + function laplacian(rhs) + class(subdomain_t), intent(in) :: rhs + type(subdomain_t) laplacian + laplacian%s_ = rhs%s_ + 42 + end function + +end module + + use subdomain_m + implicit none + + type operands_t + real :: s_ + end type + + type(subdomain_t) phi + type(operands_t) operands + + associate(laplacian_phi => .laplacian. phi) ! ICE because specific not found. + operands = approximates(laplacian_phi%s_) + end associate + + if (int (operands%s_) /= 42) stop 1 +contains + + function approximates(actual) + real actual + type(operands_t) approximates + approximates%s_ = actual - 99 + end function + +end