Summary: | [8/9 regression] ICE with generic function | ||
---|---|---|---|
Product: | gcc | Reporter: | Andrew Benson <abensonca> |
Component: | fortran | Assignee: | kargls |
Status: | RESOLVED FIXED | ||
Severity: | normal | CC: | kargls, pault, tkoenig |
Priority: | P4 | Keywords: | ice-on-invalid-code |
Version: | 8.0.1 | ||
Target Milestone: | 6.5 | ||
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 |
Bug Depends on: | 85996 | ||
Bug Blocks: |
Description
Andrew Benson
2018-03-31 03:30:02 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 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. (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 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. (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. 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 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... 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.
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. *** Bug 85526 has been marked as a duplicate of this bug. *** (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. GCC 8.1 has been released. 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 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 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 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 Fixed on trunk and 6, 7, and 8 branches. |