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

            Bug ID: 106790
           Summary: Weird SIGSEV using polymorphic routine with "select
                    type" and optimization (-O3)
           Product: gcc
           Version: 12.1.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: fortran
          Assignee: unassigned at gcc dot gnu.org
          Reporter: federico.perini at gmail dot com
  Target Milestone: ---

I'm getting a weird SIGSEV error when running the following code with full
optimization (-O3). Error happens if: 

- type guard ("select type") is is "type is", no segfault if "class is"
- the non-abstract derived type contains more than 1 scalar

I suspect something is wrong with the compiler trying to optimize out the code
in the main program (it's all constants). 

- Fails only on gfortran 11, 12. 
- Works on gfortran 7,8,9,10

Test it here: https://godbolt.org/z/qKPMvKnzf

Here is the minimum working example: 

module ttt
implicit none
    type, abstract :: t0
        contains
            procedure(merge), deferred :: mergeWith
            procedure(pprint), deferred :: print
    end type
    type,extends(t0) :: t
        integer :: from1,to1,face
        contains 
            procedure :: mergeWith => t_merge
            procedure :: print => link_print
    end type t

abstract interface
    pure subroutine merge(this,that)
        import t0
        class(t0), intent(inout) :: this
        class(t0), intent(in) :: that
    end subroutine merge
    function pprint(this) result(msg)
        import t0
        class(t0), intent(in) :: this
        character(len=:), allocatable :: msg
    end function pprint
end interface

contains

    function link_print(this) result(msg)
       class(t), intent(in) :: this
       character(len=:), allocatable :: msg
       character(len=1024) :: buffer
       integer :: lt

       write(buffer,1) this%to1,this%from1,this%face
       lt = len_trim(buffer)
       allocate(character(len=lt) :: msg)
       if (lt>0) msg(1:lt) = buffer(1:lt)

       1 format('to1=',i0,' from1=',i0,' face=',i0)
    end function link_print

pure subroutine t_merge(this,that)
class(t), intent(inout) :: this
class(t0), intent(in) :: that

       select type (ttype => that)

       type is (t) ! Does not SIGSEV if using "class is (t)"

           ! SIGSEV at any of the following lines
           ! Does not crash anymore if commenting any of them
           if (this%to1<0 .and. this%from1<0) then
              this%to1   = ttype%to1
              this%face = ttype%face
           end if

       end select

end subroutine t_merge
end module

program test_t
use ttt
implicit none

type(t) :: t1,t2


t1 = t(from1=123,to1=435,face=789)
t2 = t(from1=-1,to1=-1,face=-1)
call t1%mergeWith(t2)
print *, 't1=',t1%print(),' t2=',t2%print()

t1 = t(from1=123,to1=435,face=789)
t2 = t(from1=-1,to1=-1,face=-1)

! Crash here on -O3, apparently during the unrolling of constants
call t2%mergeWith(t1)
print *, 't1=',t1%print(),' t2=',t2%print()

end program


Thanks,
Federico

Reply via email to