https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78661
--- Comment #7 from janus at gcc dot gnu.org --- So, here is a corrected test for the polymorphic case: MODULE m IMPLICIT NONE TYPE :: t CHARACTER :: c CONTAINS PROCEDURE :: write_formatted GENERIC :: WRITE(FORMATTED) => write_formatted PROCEDURE :: read_formatted GENERIC :: READ(FORMATTED) => read_formatted END TYPE CONTAINS SUBROUTINE write_formatted(dtv, unit, iotype, v_list, iostat, iomsg) CLASS(t), INTENT(IN) :: dtv INTEGER, INTENT(IN) :: unit CHARACTER(*), INTENT(IN) :: iotype INTEGER, INTENT(IN) :: v_list(:) INTEGER, INTENT(OUT) :: iostat CHARACTER(*), INTENT(INOUT) :: iomsg WRITE (unit, "(A)", IOSTAT=iostat, IOMSG=iomsg) dtv%c END SUBROUTINE SUBROUTINE read_formatted(dtv, unit, iotype, v_list, iostat, iomsg) CLASS(t), INTENT(INOUT) :: dtv INTEGER, INTENT(IN) :: unit CHARACTER(*), INTENT(IN) :: iotype INTEGER, INTENT(IN) :: v_list(:) INTEGER, INTENT(OUT) :: iostat CHARACTER(*), INTENT(INOUT) :: iomsg READ (unit, "(A)", IOSTAT=iostat, IOMSG=iomsg) dtv%c END SUBROUTINE read_formatted END MODULE PROGRAM p USE m IMPLICIT NONE class(t), allocatable :: x NAMELIST /nml/ x x = t('a') WRITE (*, nml) END It currently prints (with my patch from comment 4, but probably also without): &NML X= / Apparently 'write_formatted' is not called. The dump for the non-poly version from comment 0/3 shows: _gfortran_st_set_nml_dtio_var (&dt_parm.3, x, &"x"[1]{lb: 1 sz: 1}, 0, 0, 40, write_formatted, (void *) &__vtab_m_T); But for the polymorphic version it has: _gfortran_st_set_nml_dtio_var (&dt_parm.3, &x, &"x"[1]{lb: 1 sz: 1}, 0, 0, 56, 0B, 0B); Neither the DTIO procedure nor the vtab is called. The DTIO procedure we need here is "x._vptr->write_formatted". Btw why do we actually pass the vtab in the first case?