Bug 85138 - [8/9 regression] ICE with generic function
Summary: [8/9 regression] ICE with generic function
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: fortran (show other bugs)
Version: 8.0.1
: P4 normal
Target Milestone: 6.5
Assignee: kargls
URL:
Keywords: ice-on-invalid-code
: 85526 (view as bug list)
Depends on: 85996
Blocks:
  Show dependency treegraph
 
Reported: 2018-03-31 03:30 UTC by Andrew Benson
Modified: 2018-06-09 18:38 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Known to work: 6.4.0, 7.3.0
Known to fail: 8.0.1
Last reconfirmed: 2018-03-31 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Andrew Benson 2018-03-31 03:30:02 UTC
The following (reduced from a much larger module) causes an ICE with gfortran 8.0.1 r258983:

module fox_m_fsys_format
  interface len
     module procedure str_real_sp_len, str_real_sp_fmt_len
  end interface
contains
  pure function str_real_sp_fmt_len(x, fmt) result(n)
    real, intent(in) :: x
    character(len=*), intent(in) :: fmt
    if (.not.checkFmt(fmt)) then
    endif
  end function str_real_sp_fmt_len
  pure function str_real_sp_len(x) result(n)
    real, intent(in) :: x
    n = len(x, "")
  end function str_real_sp_len
  function str_real_dp_matrix(xa) result(s)
    real, intent(in) :: xa
    character(len=len(xa)) :: s
  end function str_real_dp_matrix
end module fox_m_fsys_format

$ gfortran -v
Using built-in specs.
COLLECT_GCC=gfortran
COLLECT_LTO_WRAPPER=/home/abenson/Galacticus/Tools/libexec/gcc/x86_64-pc-linux-gnu/8.0.1/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: ../gcc-trunk/configure --prefix=/home/abenson/Galacticus/Tools --enable-languages=c,c++,fort
an --disable-multilib
Thread model: posix
gcc version 8.0.1 20180330 (experimental) (GCC)

$ gfortran -c tmp3.F90
tmp3.F90:9:0:

     if (.not.checkFmt(fmt)) then

internal compiler error: in gfc_typenode_for_spec, at fortran/trans-types.c:1157
0x5ee3b2 gfc_typenode_for_spec(gfc_typespec*, int)
        ../../gcc-trunk/gcc/fortran/trans-types.c:1157
0x889d77 gfc_conv_unary_op
        ../../gcc-trunk/gcc/fortran/trans-expr.c:2802
0x887060 gfc_conv_expr_op
        ../../gcc-trunk/gcc/fortran/trans-expr.c:3317
0x887060 gfc_conv_expr(gfc_se*, gfc_expr*)
        ../../gcc-trunk/gcc/fortran/trans-expr.c:7918
0x889cc7 gfc_conv_expr_val(gfc_se*, gfc_expr*)
        ../../gcc-trunk/gcc/fortran/trans-expr.c:7975
0x8c00d7 gfc_trans_if_1
        ../../gcc-trunk/gcc/fortran/trans-stmt.c:1427
0x8c8dba gfc_trans_if(gfc_code*)
        ../../gcc-trunk/gcc/fortran/trans-stmt.c:1464
0x84ca37 trans_code
        ../../gcc-trunk/gcc/fortran/trans.c:1916
0x878a2d gfc_generate_function_code(gfc_namespace*)
        ../../gcc-trunk/gcc/fortran/trans-decl.c:6507
0x850cc1 gfc_generate_module_code(gfc_namespace*)
        ../../gcc-trunk/gcc/fortran/trans.c:2222
0x80333b translate_all_program_units
        ../../gcc-trunk/gcc/fortran/parse.c:6108
0x80333b gfc_parse_file()
        ../../gcc-trunk/gcc/fortran/parse.c:6324
0x849b8f gfc_be_parse_file
        ../../gcc-trunk/gcc/fortran/f95-lang.c:204
Please submit a full bug report,
with preprocessed source if appropriate.
Please include the complete backtrace with any bug report.
See <https://gcc.gnu.org/bugs/> for instructions.
Comment 1 Paul Thomas 2018-03-31 07:37:17 UTC
Confirmed as a regression in 8-branch.

Earlier branches give

     if (.not.checkFmt(fmt)) then
             1
Error: Reference to impure function ‘checkfmt’ at (1) within a PURE procedure

Adding:
  interface
     pure logical function checkFmt(arg)
        character(len = *), intent(in) :: arg
     end function
  end interface

makes the problem go away.

Paul
Comment 2 Dominique d'Humieres 2018-03-31 08:24:27 UTC
Up to revision r258235 (2018-03-04) compiling the test gave the error

     if (.not.checkFmt(fmt)) then
             1
Error: Reference to impure function 'checkfmt' at (1) within a PURE procedure

After revision r258362 (2018-03-08) I get the ICE. This has been back ported to 7.3.1.

In this range I see only r258281, r258305, and r258347, but r258305 has not been back ported.
Comment 3 Paul Thomas 2018-03-31 10:53:52 UTC
(In reply to Dominique d'Humieres from comment #2)
> Up to revision r258235 (2018-03-04) compiling the test gave the error
> 
>      if (.not.checkFmt(fmt)) then
>              1
> Error: Reference to impure function 'checkfmt' at (1) within a PURE procedure
> 
> After revision r258362 (2018-03-08) I get the ICE. This has been back ported
> to 7.3.1.
> 
> In this range I see only r258281, r258305, and r258347, but r258305 has not
> been back ported.

Bizarrely it is r258347 that is the trigger. It has been backported without any ill effects.

Paul
Comment 4 Andrew Benson 2018-04-01 02:42:01 UTC
A related but possibly different ICE:


module fox_m_fsys_format
  interface len
    module procedure str_real_dp_len, str_real_dp_fmt_len
  end interface
contains
  pure function str_real_dp_fmt_len(x, fmt) result(n)
    real, intent(in) :: x
    character(len=*), intent(in) :: fmt
    if (.not.checkFmt(fmt)) then
    endif
  end function str_real_dp_fmt_len
  pure function str_real_dp_len(x) result(n)
    real, intent(in) :: x
  end function str_real_dp_len
  pure function str_real_dp_array_len(xa) result(n)
    real, dimension(:), intent(in) :: xa
  end function str_real_dp_array_len
  pure function str_real_dp_array_fmt_len(xa, fmt) result(n)
    real, dimension(:), intent(in) :: xa
    character(len=*), intent(in) :: fmt
  end function str_real_dp_array_fmt_len
  pure function str_real_dp_fmt(x, fmt) result(s)
    real, intent(in) :: x
    character(len=*), intent(in) :: fmt
    character(len=len(x, fmt)) :: s
  end function str_real_dp_fmt
  pure function checkFmt(fmt) result(good)
    character(len=*), intent(in) :: fmt
    logical :: good
  end function checkFmt
end module fox_m_fsys_format


$ gfortran -c  tmp6.F90

     if (.not.checkFmt(fmt)) then

internal compiler error: Segmentation fault
0xd2f4cf crash_signal
        ../../gcc-trunk/gcc/toplev.c:325
0x7f434bb321ef ???
        /data001/abenson/Galacticus/Tools/glibc-2.12.1/signal/../sysdeps/unix/sysv/linux/x86_64/sigaction.c:0
0x881660 gfc_conv_procedure_call(gfc_se*, gfc_symbol*, gfc_actual_arglist*, gfc_expr*, vec<tree_node*, va_gc,
vl_embed>*)
        ../../gcc-trunk/gcc/fortran/trans-expr.c:4890
0x886eaa gfc_conv_expr(gfc_se*, gfc_expr*)
        ../../gcc-trunk/gcc/fortran/trans-expr.c:7922
0x889cc7 gfc_conv_expr_val(gfc_se*, gfc_expr*)
        ../../gcc-trunk/gcc/fortran/trans-expr.c:7975
0x889d61 gfc_conv_unary_op
        ../../gcc-trunk/gcc/fortran/trans-expr.c:2799
0x887060 gfc_conv_expr_op
        ../../gcc-trunk/gcc/fortran/trans-expr.c:3317
0x887060 gfc_conv_expr(gfc_se*, gfc_expr*)
        ../../gcc-trunk/gcc/fortran/trans-expr.c:7918
0x889cc7 gfc_conv_expr_val(gfc_se*, gfc_expr*)
        ../../gcc-trunk/gcc/fortran/trans-expr.c:7975
0x8c00d7 gfc_trans_if_1
        ../../gcc-trunk/gcc/fortran/trans-stmt.c:1427
0x8c8dba gfc_trans_if(gfc_code*)
        ../../gcc-trunk/gcc/fortran/trans-stmt.c:1464
0x84ca37 trans_code
        ../../gcc-trunk/gcc/fortran/trans.c:1916
0x878a2d gfc_generate_function_code(gfc_namespace*)
        ../../gcc-trunk/gcc/fortran/trans-decl.c:6507
0x850cc1 gfc_generate_module_code(gfc_namespace*)
        ../../gcc-trunk/gcc/fortran/trans.c:2222
0x80333b translate_all_program_units
        ../../gcc-trunk/gcc/fortran/parse.c:6108
0x80333b gfc_parse_file()
        ../../gcc-trunk/gcc/fortran/parse.c:6324
0x849b8f gfc_be_parse_file
        ../../gcc-trunk/gcc/fortran/f95-lang.c:204
Please submit a full bug report,
with preprocessed source if appropriate.
Please include the complete backtrace with any bug report.
See <https://gcc.gnu.org/bugs/> for instructions.
Comment 5 kargls 2018-04-01 16:31:57 UTC
(In reply to Paul Thomas from comment #3)
> (In reply to Dominique d'Humieres from comment #2)
> > Up to revision r258235 (2018-03-04) compiling the test gave the error
> > 
> >      if (.not.checkFmt(fmt)) then
> >              1
> > Error: Reference to impure function 'checkfmt' at (1) within a PURE procedure
> > 
> > After revision r258362 (2018-03-08) I get the ICE. This has been back ported
> > to 7.3.1.
> > 
> > In this range I see only r258281, r258305, and r258347, but r258305 has not
> > been back ported.
> 
> Bizarrely it is r258347 that is the trigger. It has been backported without
> any ill effects.
>

It's probably not bizarre when a user does something like overloading
the name of an intrinsic subprogram and then tries to use it in a
specification statement.  Something that the contributor of r258347
and of very little brain would never do.  The simple fix is to not
be too clever.

   interface length
      module procedure alen, blen  ! renamed to shorter symbols for debugging
   end interface

      function str_real_dp_matrix(xa) result(s)
         real, intent(in) :: xa
         character(len=length(xa)) :: s
      end function str_real_dp_matrix

% gfc -c a.f90
a.f90:12:18:

          if (.not.checkFmt(fmt)) then
                  1
Error: Reference to impure function 'checkfmt' at (1) within a PURE procedure

If I had to guess the gfc_reduce_init_expr() in r258347 is
disabling the reporting of errors at some point when
len=len(xa) is being reduced.
Comment 6 Dominique d'Humieres 2018-04-01 19:54:47 UTC
The following variant gives the same ICE

module fox_m_fsys_format
  interface mylen
     module procedure str_real_sp_len, str_real_sp_fmt_len
  end interface
contains
  pure function str_real_sp_fmt_len(x, fmt) result(n)
    real, intent(in) :: x
    character(len=*), intent(in) :: fmt
    if (.not.checkFmt()) then
    endif
  end function str_real_sp_fmt_len
  pure function str_real_sp_len(x) result(n)
    real, intent(in) :: x
    n = mylen(x, "")
  end function str_real_sp_len
  function str_real_dp_matrix(xa) result(s)
    real, intent(in) :: xa
    character(len=mylen(xa)) :: s
  end function str_real_dp_matrix
end module fox_m_fsys_format
Comment 7 Thomas Koenig 2018-04-02 17:50:30 UTC
First, I have renamed the function "len" to "llen" in the original
test case to avoid confusion with the intrinsic.

The problem seems to be that, at the entry of pure_function(),
there are different opinions about purity:

(gdb) p e->symtree->n.sym->name
$6 = 0x7ffff743b078 "llen"
(gdb) p e->symtree->n.sym->attr.pure
$7 = 0
(gdb) p e->value.function
$8 = {actual = 0x2515700, name = 0x7ffff7438a80 "str_real_sp_fmt_len", isym = 0x0, esym = 0x2581200}
(gdb) p e->value.function.esym->attr.pure
$9 = 1

(Why this problem is exposed by Steve's patch, I have no idea).

Investigating further...
Comment 8 kargl@troutmask.apl.washington.edu 2018-04-02 17:55:16 UTC
On Mon, Apr 02, 2018 at 05:50:30PM +0000, tkoenig at gcc dot gnu.org wrote:
> 
> --- Comment #7 from Thomas Koenig <tkoenig at gcc dot gnu.org> ---
> First, I have renamed the function "len" to "llen" in the original
> test case to avoid confusion with the intrinsic.
> 
> The problem seems to be that, at the entry of pure_function(),
> there are different opinions about purity:
> 
> (gdb) p e->symtree->n.sym->name
> $6 = 0x7ffff743b078 "llen"
> (gdb) p e->symtree->n.sym->attr.pure
> $7 = 0
> (gdb) p e->value.function
> $8 = {actual = 0x2515700, name = 0x7ffff7438a80 "str_real_sp_fmt_len", isym =
> 0x0, esym = 0x2581200}
> (gdb) p e->value.function.esym->attr.pure
> $9 = 1
> 
> (Why this problem is exposed by Steve's patch, I have no idea).
> 

I don't have time to look, but if the gfc_reduce_init_expr() is
now being invoked from my patch I suspect that you either have
e->symtree->n.sym->attr.pure overwriting e->value.function.esym->attr.pure
or vice versa.
Comment 9 Thomas Koenig 2018-04-02 18:20:14 UTC
OK, so I am beginning to understand...

Part of the problem seems that, in check_pure_function,

      else if (gfc_pure (NULL))
	{
	  gfc_error ("Reference to impure function %qs at %L "
		     "within a PURE procedure", name, &e->where);
	  return false;
	}

is checking the current namespace for PUREness; this seems not
to be initialized when gfc_reduce_init_expr (which in turn calls
gfc_resolve_expr) is called.
Comment 10 kargls 2018-04-27 23:29:27 UTC
*** Bug 85526 has been marked as a duplicate of this bug. ***
Comment 11 kargls 2018-04-27 23:31:40 UTC
(In reply to kargl from comment #10)
> *** Bug 85526 has been marked as a duplicate of this bug. ***

Comment #6 in the duplicate provides additional information.
Reprodcued here.



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 12 Jakub Jelinek 2018-05-02 10:08:55 UTC
GCC 8.1 has been released.
Comment 13 kargls 2018-06-09 15:48:45 UTC
Author: kargl
Date: Sat Jun  9 15:47:40 2018
New Revision: 261362

URL: https://gcc.gnu.org/viewcvs?rev=261362&root=gcc&view=rev
Log:
2018-06-09  Steven G. Kargl  <kargl@gcc.gnu.org>

	PR fortran/85138
	PR fortran/85996
	PR fortran/86051
	* decl.c (gfc_match_char_spec): Use private namespace in attempt to
	reduce a charlen to a constant.

2018-06-09  Steven G. Kargl  <kargl@gcc.gnu.org>

	PR fortran/85138
	PR fortran/85996
	PR fortran/86051
	* gfortran.dg/pr85138_1.f90: New test.
	* gfortran.dg/pr85138_2.f90: Ditto.
	* gfortran.dg/pr85996.f90: Ditto.

Added:
    trunk/gcc/testsuite/gfortran.dg/pr85138_1.f90
    trunk/gcc/testsuite/gfortran.dg/pr85138_2.f90
    trunk/gcc/testsuite/gfortran.dg/pr85996.f90
Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/decl.c
    trunk/gcc/testsuite/ChangeLog
Comment 14 kargls 2018-06-09 18:09:32 UTC
Author: kargl
Date: Sat Jun  9 18:09:00 2018
New Revision: 261370

URL: https://gcc.gnu.org/viewcvs?rev=261370&root=gcc&view=rev
Log:
2018-06-09  Steven G. Kargl  <kargl@gcc.gnu.org>

	PR fortran/85138
	PR fortran/85996
	PR fortran/86051
	* decl.c (gfc_match_char_spec): Use private namespace in attempt to
	reduce a charlen to a constant.

2018-06-09  Steven G. Kargl  <kargl@gcc.gnu.org>

	PR fortran/85138
	PR fortran/85996
	PR fortran/86051
	* gfortran.dg/pr85138_1.f90: New test.
	* gfortran.dg/pr85138_2.f90: Ditto.
	* gfortran.dg/pr85996.f90: Ditto.

Added:
    branches/gcc-8-branch/gcc/testsuite/gfortran.dg/pr85138_1.f90
    branches/gcc-8-branch/gcc/testsuite/gfortran.dg/pr85138_2.f90
    branches/gcc-8-branch/gcc/testsuite/gfortran.dg/pr85996.f90
Modified:
    branches/gcc-8-branch/gcc/fortran/ChangeLog
    branches/gcc-8-branch/gcc/fortran/decl.c
    branches/gcc-8-branch/gcc/testsuite/ChangeLog
Comment 15 kargls 2018-06-09 18:30:12 UTC
Author: kargl
Date: Sat Jun  9 18:29:40 2018
New Revision: 261371

URL: https://gcc.gnu.org/viewcvs?rev=261371&root=gcc&view=rev
Log:
2018-06-09  Steven G. Kargl  <kargl@gcc.gnu.org>

	PR fortran/85138
	PR fortran/85996
	PR fortran/86051
	* decl.c (gfc_match_char_spec): Use private namespace in attempt to
	reduce a charlen to a constant.

2018-06-09  Steven G. Kargl  <kargl@gcc.gnu.org>

	PR fortran/85138
	PR fortran/85996
	PR fortran/86051
	* gfortran.dg/pr85138_1.f90: New test.
	* gfortran.dg/pr85138_2.f90: Ditto.
	* gfortran.dg/pr85996.f90: Ditto.

Added:
    branches/gcc-7-branch/gcc/testsuite/gfortran.dg/pr85138_1.f90
    branches/gcc-7-branch/gcc/testsuite/gfortran.dg/pr85138_2.f90
    branches/gcc-7-branch/gcc/testsuite/gfortran.dg/pr85996.f90
Modified:
    branches/gcc-7-branch/gcc/fortran/ChangeLog
    branches/gcc-7-branch/gcc/fortran/decl.c
    branches/gcc-7-branch/gcc/testsuite/ChangeLog
Comment 16 kargls 2018-06-09 18:36:30 UTC
Author: kargl
Date: Sat Jun  9 18:35:58 2018
New Revision: 261372

URL: https://gcc.gnu.org/viewcvs?rev=261372&root=gcc&view=rev
Log:
2018-06-09  Steven G. Kargl  <kargl@gcc.gnu.org>

	PR fortran/85138
	PR fortran/85996
	PR fortran/86051
	* decl.c (gfc_match_char_spec): Use private namespace in attempt to
	reduce a charlen to a constant.

2018-06-09  Steven G. Kargl  <kargl@gcc.gnu.org>

	PR fortran/85138
	PR fortran/85996
	PR fortran/86051
	* gfortran.dg/pr85138_1.f90: New test.
	* gfortran.dg/pr85138_2.f90: Ditto.
	* gfortran.dg/pr85996.f90: Ditto.

Added:
    branches/gcc-6-branch/gcc/testsuite/gfortran.dg/pr85138_1.f90
    branches/gcc-6-branch/gcc/testsuite/gfortran.dg/pr85138_2.f90
    branches/gcc-6-branch/gcc/testsuite/gfortran.dg/pr85996.f90
Modified:
    branches/gcc-6-branch/gcc/fortran/ChangeLog
    branches/gcc-6-branch/gcc/fortran/decl.c
    branches/gcc-6-branch/gcc/testsuite/ChangeLog
Comment 17 kargls 2018-06-09 18:38:12 UTC
Fixed on trunk and 6, 7, and 8 branches.