Hi All, The "fix" for PR84674 caused this regression.
The diagnostics that I had used for PR117763 allowed me to find a much better fix for PR84674 and so this patch reverts the chunk in resolve.cc. The chunk in class.cc works because non_overridable typebound procedures, whose parent is abstract, do not have the 'overridden' field set. This caused an immediate return from 'add_proc_comp' and this led to viable typebound procedures being rejected. The fix checks the vtype component for a specific typebound procedure that is abstract and uses this to suppress the immediate return. I tested not adding the initialization expression if the specific is abstract but, although this version regression tested OK, decided to keep the patch as minimal as possible. OK for mainline and, after a decent interval, to backport the chunk in class.cc to the branches affected by PR84674? Regards Paul Fortran: Fix non_overridable typebound proc problems [PR84674/117768]. 2024-11-27 Paul Thomas <pa...@gcc.gnu.org> gcc/fortran/ChangeLog PR fortran/84674 * class.cc (add_proc_comp): If the component points to a tbp that is abstract, do not return since the new version is more likely to be usable. PR fortran/117768 * resolve.cc (resolve_fl_derived): Remove the condition that rejected a completely empty derived type extension. gcc/testsuite/ChangeLog PR fortran/117768 * gfortran.dg/pr117768.f90: New test.
diff --git a/gcc/fortran/class.cc b/gcc/fortran/class.cc index 59ac0d97e08..64a0e726eeb 100644 --- a/gcc/fortran/class.cc +++ b/gcc/fortran/class.cc @@ -884,11 +884,21 @@ static void add_proc_comp (gfc_symbol *vtype, const char *name, gfc_typebound_proc *tb) { gfc_component *c; - + bool is_abstract = false; c = gfc_find_component (vtype, name, true, true, NULL); - if (tb->non_overridable && !tb->overridden && c) + /* If the present component typebound proc is abstract, the new version + should unconditionally be tested if it is a suitable replacement. */ + if (c && c->tb && c->tb->u.specific + && c->tb->u.specific->n.sym->attr.abstract) + is_abstract = true; + + /* Pass on the new tb being not overridable if a component is found and + either there is not an overridden specific or the present component + tb is abstract. This ensures that possible, viable replacements are + loaded. */ + if (tb->non_overridable && !tb->overridden && !is_abstract && c) return; if (c == NULL) diff --git a/gcc/fortran/resolve.cc b/gcc/fortran/resolve.cc index 0d3845f9ce3..afed8db7852 100644 --- a/gcc/fortran/resolve.cc +++ b/gcc/fortran/resolve.cc @@ -3229,8 +3229,8 @@ static bool check_pure_function (gfc_expr *e) const char *name = NULL; code_stack *stack; bool saw_block = false; - - /* A BLOCK construct within a DO CONCURRENT construct leads to + + /* A BLOCK construct within a DO CONCURRENT construct leads to gfc_do_concurrent_flag = 0 when the check for an impure function occurs. Check the stack to see if the source code has a nested BLOCK construct. */ @@ -16305,10 +16305,6 @@ resolve_fl_derived (gfc_symbol *sym) && sym->ns->proc_name && sym->ns->proc_name->attr.flavor == FL_MODULE && sym->attr.access != ACCESS_PRIVATE - && !(sym->attr.extension - && sym->attr.zero_comp - && !sym->f2k_derived->tb_sym_root - && !sym->f2k_derived->tb_uop_root) && !(sym->attr.vtype || sym->attr.pdt_template)) { gfc_symbol *vtab = gfc_find_derived_vtab (sym); diff --git a/gcc/testsuite/gfortran.dg/pr117768.f90 b/gcc/testsuite/gfortran.dg/pr117768.f90 new file mode 100644 index 00000000000..f9cf46421c1 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/pr117768.f90 @@ -0,0 +1,76 @@ +! { dg-do compile } +! +! Fix a regession caused by the first patch for PR84674. +! +! Contributed by Juergen Reuter <juergen.reu...@desy.de> +! +module m1 + implicit none + private + public :: t1 + type, abstract :: t1 + end type t1 +end module m1 + +module t_base + use m1, only: t1 + implicit none + private + public :: t_t + type, abstract :: t_t + contains + procedure (t_out), deferred :: output + end type t_t + + abstract interface + subroutine t_out (t, handle) + import + class(t_t), intent(inout) :: t + class(t1), intent(inout), optional :: handle + end subroutine t_out + end interface + +end module t_base + + +module t_ascii + use m1, only: t1 + use t_base + implicit none + private + + type, abstract, extends (t_t) :: t1_t + contains + procedure :: output => t_ascii_output + end type t1_t + type, extends (t1_t) :: t2_t + end type t2_t + type, extends (t1_t) :: t3_t + logical :: verbose = .true. + end type t3_t + + interface + module subroutine t_ascii_output & + (t, handle) + class(t1_t), intent(inout) :: t + class(t1), intent(inout), optional :: handle + end subroutine t_ascii_output + end interface +end module t_ascii + +submodule (t_ascii) t_ascii_s + implicit none +contains + module subroutine t_ascii_output & + (t, handle) + class(t1_t), intent(inout) :: t + class(t1), intent(inout), optional :: handle + select type (t) + type is (t3_t) + type is (t2_t) + class default + return + end select + end subroutine t_ascii_output +end submodule t_ascii_s +