Created attachment 44019 [details] fortran source file to demonstrate the bug A call to a pure function from inside a pure function crashes the compilation with this message internal compiler error: Segmentation fault the same code has been compiling regularly with gfortran up to 6.2 while it is failing in 6.4 and 7.3 versions I attach a sample source file
Reduce test case. module fox_m_fsys_format implicit none integer, parameter :: dp=8 interface leng module procedure str_real_dp_fmt_len end interface contains pure function str_real_dp_fmt_len(x, fmt) result(n) real(dp), intent(in) :: x character(len=10), intent(in) :: fmt integer :: n if (.not.checkFmt(fmt)) then n = 0 return end if end function str_real_dp_fmt_len function str_real_dp_fmt(x, fmt) result(s) real(dp), intent(in) :: x character(len=10), intent(in) :: fmt character(len=leng(x, fmt)) :: s end function str_real_dp_fmt function checkFmt(fmt) result(good) character(len=10), intent(in) :: fmt logical good good = .true. end function checkFmt end module fox_m_fsys_format
The code compiles with 6.4.0 and 7.3.0, but not with 6.4.1, 7.3.1, 8.0.1 and trunk (9.0). This is likely r258347 for gcc8, r258367 for gcc7, and r258368 for gcc6.
On Wed, Apr 25, 2018 at 11:33:34PM +0000, dominiq at lps dot ens.fr wrote: > The code compiles with 6.4.0 and 7.3.0, but not with 6.4.1, 7.3.1, > 8.0.1 and trunk (9.0). This is likely r258347 for gcc8, r258367 > for gcc7, and r258368 for gcc6. Bummer. Don't know how to fix this one. Workaround is to move checkFmt() to above its first use in another function.
a quick and dirty workaround is to move all the routines in the "leng" interface at the bottom of the file. But some compilers do not accept this code as valid. A better solution is to move the leng subroutines in a module by their own and import the interface.
On Thu, Apr 26, 2018 at 08:03:35AM +0000, mail at pietrodelugas dot it wrote: > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85526 > > --- Comment #4 from Pietro Delugas <mail at pietrodelugas dot it> --- > a quick and dirty workaround is to move all the routines in the "leng" > interface at the bottom of the file. But some compilers do not accept > this code as valid. > > A better solution is to move the leng subroutines in a module by > their own and import the interface. > With your original code, move checkFMT() to right after the CONTAINS statement. The code then compiles. No other functions need to move.
On Thu, Apr 26, 2018 at 12:54:05AM +0000, sgk at troutmask dot apl.washington.edu wrote: > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85526 > > --- Comment #3 from Steve Kargl <sgk at troutmask dot apl.washington.edu> --- > On Wed, Apr 25, 2018 at 11:33:34PM +0000, dominiq at lps dot ens.fr wrote: > > The code compiles with 6.4.0 and 7.3.0, but not with 6.4.1, 7.3.1, > > 8.0.1 and trunk (9.0). This is likely r258347 for gcc8, r258367 > > for gcc7, and r258368 for gcc6. > > Bummer. > > Don't know how to fix this one. > > Workaround is to move checkFmt() to above its first use > in another function. > Well, I understand the problem a bit now. In decl.c (lines 3229 to 3248), we have /* If gfortran ends up here, then the len may be reducible to a constant. Try to do that here. If it does not reduce, simply assign len to the charlen. */ if (len && len->expr_type != EXPR_CONSTANT) { gfc_expr *e; e = gfc_copy_expr (len); gfc_reduce_init_expr (e); if (e->expr_type == EXPR_CONSTANT) { gfc_replace_expr (len, e); if (mpz_cmp_si (len->value.integer, 0) < 0) mpz_set_ui (len->value.integer, 0); } else { gfc_free_expr (e); } cl->length = len; } 'gfc_reduce_init_expr (e)' is causing the symbol checkFmt, which has not previously been seen, to be committed to the current namespace before the symbol has been resolved. So, checkFmt() doesn't have a proper type and gfortran cannot set it when she finally parses the function. During the translation, checkFmt is implicitly typed, which can be gleaned from 0x6ce630 gfc_conv_expr(gfc_se*, gfc_expr*) ../../gcc8/gcc/fortran/trans-expr.c:7918 0x6d0967 gfc_conv_expr_val(gfc_se*, gfc_expr*) <-- from stepping in gdb ../../gcc8/gcc/fortran/trans-expr.c:7975 0x6fed87 gfc_trans_if_1 ../../gcc8/gcc/fortran/trans-stmt.c:1427 0x70715a gfc_trans_if(gfc_code*) What needs to be done is that symbols in the gfc_current_ns must be save before the call to 'gfc_reduce_init_expr (e)'. If reduction fails, then the old symbols need to be restored in the gfc_current_ns and any new symbols added by 'gfc_reduce_init_expr (e)' need to be removed. Unfortunately, I don't know how to do this.
This is actually a duplicate of PR 85138. Comment #6 should be added to that PR. *** This bug has been marked as a duplicate of bug 85138 ***