Bug 85526 - [6/7/8/9 regression] ICE when calling a (pure) function from inside another pure function
Summary: [6/7/8/9 regression] ICE when calling a (pure) function from inside another p...
Status: RESOLVED DUPLICATE of bug 85138
Alias: None
Product: gcc
Classification: Unclassified
Component: fortran (show other bugs)
Version: 6.4.0
: P4 normal
Target Milestone: 6.5
Assignee: Not yet assigned to anyone
URL:
Keywords: ice-on-valid-code
Depends on:
Blocks:
 
Reported: 2018-04-25 21:49 UTC by Pietro Delugas
Modified: 2018-04-27 23:29 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Known to work: 6.4.0, 7.3.0
Known to fail: 6.4.1, 7.3.1, 8.0.1
Last reconfirmed: 2018-04-25 00:00:00


Attachments
fortran source file to demonstrate the bug (8.08 KB, text/plain)
2018-04-25 21:49 UTC, Pietro Delugas
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Pietro Delugas 2018-04-25 21:49:38 UTC
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
Comment 1 kargls 2018-04-25 23:09:23 UTC
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
Comment 2 Dominique d'Humieres 2018-04-25 23:33:34 UTC
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.
Comment 3 Steve Kargl 2018-04-26 00:54:05 UTC
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.
Comment 4 Pietro Delugas 2018-04-26 08:03:35 UTC
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.
Comment 5 Steve Kargl 2018-04-26 14:16:41 UTC
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.
Comment 6 Steve Kargl 2018-04-26 23:31:26 UTC
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.
Comment 7 kargls 2018-04-27 23:29:26 UTC
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 ***