https://gcc.gnu.org/bugzilla/show_bug.cgi?id=124161

            Bug ID: 124161
           Summary: ICE in fold_convert_loc with submodule polymorphic TBP
                    dispatch
           Product: gcc
           Version: 15.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: fortran
          Assignee: unassigned at gcc dot gnu.org
          Reporter: zbeekman at gmail dot com
  Target Milestone: ---

Created attachment 63724
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=63724&action=edit
minimal reproducer fortran source file

ICE in fold_convert_loc with submodule polymorphic TBP dispatch (false positive
-Wmaybe-recursive)


SUMMARY
=======

GFortran 15 crashes with an internal compiler error when compiling a submodule
that implements a type-bound procedure (TBP) whose body calls a same-named TBP
via polymorphic dispatch on an allocatable class component.  I think that the
code is valid Fortran and compiles cleanly with GFortran 14.  A spurious
-Wmaybe-recursive warning is emitted immediately before the crash; the warning
is a false positive because the polymorphic call dispatches through an abstract
type to an unrelated concrete type -- it cannot recurse back to the outer
procedure.


COMPILER VERSIONS
=================

  Affected:   GNU Fortran (GCC) 15.2.0  -- ICE
  Unaffected: GNU Fortran (GCC) 14.3.0  -- clean compile, no warnings

PLATFORMS TESTED
================

16-inch, 2019 MacBook Pro
2.4 GHz 8-Core Intel Core i9
32 GB 2667 MHz DDR4

HOW TO REPRODUCE
================

Attach ice_minimal.f90 (single file, zero external dependencies) and run:

  gfortran -c ice_minimal.f90

NOTE: if -Werror is in effect the compiler exits on the spurious warning before
reaching the crash site; omit -Werror to observe the ICE.


ACTUAL RESULT
=============

  ice_minimal.f90:67:17:

     67 | submodule(outer_m) outer_impl
        |                 1
  Warning: Non-RECURSIVE procedure 'summary' at (1) is possibly calling itself
  recursively.  Declare it RECURSIVE or use '-frecursive'
  ice_minimal.f90:67:17:

     67 | submodule(outer_m) outer_impl
        |                 1
  internal compiler error: in fold_convert_loc, at fold-const.cc:2786
  Please submit a full bug report, with preprocessed source (by using
-freport-bug).

NOTE: `-freport-bug` doesn't change anything or produce additional output, I
think the ICE kills the process early.

EXPECTED RESULT
===============

Clean compilation with no warnings (as with GFortran 14).  The procedure
'summary' in the submodule is not recursive: the call self%component%summary()
dispatches through class(inner_t) to concrete_t%summary, which is a completely
unrelated type from outer_t%summary.


TRIGGER CONDITIONS
==================

I think all five conditions must be present to reproduce the ICE:

  1. An abstract type (inner_t) with a deferred TBP whose return type is a
     derived type containing an allocatable component.
  2. A concrete extension (concrete_t) implementing that deferred TBP.
  3. An outer type (outer_t) that holds a class(inner_t) allocatable component
     AND also has a TBP with the SAME NAME as the deferred TBP, declared as a
     module function with a result() clause (i.e. the result variable has a
     different name from the function).
  4. The outer module USEs the concrete type (concrete_t) -- this causes the
     concrete type's TBP to be encoded in the parent .smod file and visible
     when the submodule is compiled.
  5. A submodule implements the outer TBP by calling
     self%component%summary() via polymorphic dispatch.

Removing any one of these conditions prevents the ICE:

  - result() clause removed from outer function:  no warning, no ICE
  - USE of concrete_t removed from outer module:  no warning, no ICE
  - Return type changed to INTEGER (no allocatable component): no warning, no
ICE
  - Implementation moved from submodule to module contains: no warning, no ICE


FLAG BEHAVIOR
=============

  (no extra flags)       -Wmaybe-recursive warning fires, then ICE
  -w                     warning text suppressed, ICE still fires
  -Wno-maybe-recursive   warning NOT suppressed, ICE still fires
  -frecursive            warning suppressed, ICE still fires
  -Werror                compiler exits on warning-as-error; ICE masked


REPRODUCER SOURCE (ice_minimal.f90)
====================================

module inner_m
    implicit none
    type :: dt_t
        integer, allocatable :: val
    end type
    type, abstract :: inner_t
    contains
        procedure(summary_i), deferred :: summary
    end type
    abstract interface
        function summary_i(self)
            import :: inner_t, dt_t
            class(inner_t), intent(in) :: self
            type(dt_t) :: summary_i
        end function
    end interface
end module inner_m

module concrete_m
    use inner_m, only: inner_t, dt_t
    implicit none
    type, extends(inner_t) :: concrete_t
    contains
        procedure :: summary
    end type
contains
    function summary(self)
        class(concrete_t), intent(in) :: self
        type(dt_t) :: summary
    end function
end module concrete_m

module outer_m
    use inner_m, only: inner_t, dt_t
    use concrete_m, only: concrete_t
    implicit none
    type :: outer_t
        class(inner_t), allocatable :: component
    contains
        procedure :: summary
    end type
    interface
        module function summary(self) result(res)
            class(outer_t), intent(in) :: self
            type(dt_t) :: res
        end function
    end interface
end module outer_m

submodule(outer_m) outer_impl
contains
    module procedure summary
        res = self%component%summary()
    end procedure
end submodule outer_impl

Reply via email to