Bug 43591 - PPC: internal compiler error: in gfc_traverse_expr, at fortran/expr.c:3604
Summary: PPC: internal compiler error: in gfc_traverse_expr, at fortran/expr.c:3604
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: fortran (show other bugs)
Version: 4.5.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: ice-on-invalid-code, ice-on-valid-code
Depends on:
Blocks:
 
Reported: 2010-03-30 17:18 UTC by Thorsten Ohl
Modified: 2010-05-19 07:24 UTC (History)
4 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail: 4.5.0
Last reconfirmed: 2010-04-01 12:28:49


Attachments
program that triggers the bug (36.46 KB, application/x-tar)
2010-03-30 17:21 UTC, Thorsten Ohl
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Thorsten Ohl 2010-03-30 17:18:33 UTC
When compiling the attached sources, I get

Using built-in specs.
COLLECT_GCC=gfortran
COLLECT_LTO_WRAPPER=/archive/ohl/tools64/libexec/gcc/x86_64-unknown-linux-gnu/4.5.0/lto-wrapper
Target: x86_64-unknown-linux-gnu
Configured with: /home/ohl/archive/gcc/svn/configure --prefix=/archive/ohl/tools64/ --enable-languages=c,c++,fortran
Thread model: posix
gcc version 4.5.0 20100330 (experimental) (GCC) 
ward.f90:79:0: internal compiler error: in gfc_traverse_expr, at fortran/expr.c:3604
Please submit a full bug report,
with preprocessed source if appropriate.
See <http://gcc.gnu.org/bugs.html> for instructions.
Comment 1 Thorsten Ohl 2010-03-30 17:21:49 UTC
Created attachment 20261 [details]
program that triggers the bug
Comment 2 Joost VandeVondele 2010-03-30 17:58:35 UTC
confirmed. 
Comment 3 Dominique d'Humieres 2010-03-30 18:29:54 UTC
Reduced test:

module ward_lib

  implicit none

  type omega_procedures
     procedure(number_particles_out), nopass, pointer :: number_particles_out => NULL()
     procedure(number_flavor_states), nopass, pointer :: number_flavor_states => NULL()
  end type omega_procedures

contains

  subroutine quantum_numbers2 (physical, unphysical)
    type(omega_procedures), intent(in) :: physical, unphysical
    integer, dimension(physical%number_particles_out(), &
         physical%number_flavor_states()) :: table_flavor_states

  end subroutine quantum_numbers2

end module ward_lib
Comment 4 Dominique d'Humieres 2010-03-30 19:55:20 UTC
Further reduced test that does not give an ICE, but several errors:

[macbook] f90/bug% cat pr43591_red_1.f90
module ward_lib

  implicit none

  type omega_procedures
     procedure(number_particles_out), nopass, pointer :: number_particles_out => NULL()
  end type omega_procedures

contains

  subroutine quantum_numbers2 ()
!    type(omega_procedures), intent(in) :: physical
    integer, dimension(physical%number_particles_out()) &
         :: table_flavor_states

  end subroutine quantum_numbers2

end module ward_lib
[macbook] f90/bug% gfc pr43591_red_1.f90
pr43591_red_1.f90:14.31:

    integer, dimension(physical%number_particles_out()) &
                               1
Error: Expected another dimension in array declaration at (1)
pr43591_red_1.f90:7.35:

     procedure(number_particles_out), nopass, pointer :: number_particles_out =
                                   1
Error: Symbol 'number_particles_out' at (1) has no IMPLICIT type
pr43591_red_1.f90:7.77:

   procedure(number_particles_out), nopass, pointer :: number_particles_out => 
                                                                           1  
Error: Interface 'number_particles_out' of procedure pointer component 'number_particles_out' at (1) must be explicit

If uncomment the commented line I get an ICE:

#0  fancy_abort (file=0x100974ce0 "../../p_work/gcc/fortran/expr.c", line=3604, function=0x1009f4d80 "gfc_traverse_expr") at ../../p_work/gcc/diagnostic.c:762
#1  0x000000010002b86f in gfc_traverse_expr (expr=0x141815840, sym=0x0, func=0x100026480 <expr_check_typed_help>, f=0) at ../../p_work/gcc/fortran/expr.c:3604
#2  0x000000010002c5e7 in gfc_expr_check_typed (e=0x141815840, ns=0x142078600, strict=<value temporarily unavailable, due to optimizations>) at ../../p_work/gcc/fortran/expr.c:3767
#3  0x00000001000069f5 in gfc_match_array_spec (asp=0x100c8f140) at ../../p_work/gcc/fortran/array.c:310
#4  0x0000000100018bcf in match_attr_spec () at ../../p_work/gcc/fortran/decl.c:3044
#5  0x000000010001d137 in gfc_match_data_decl () at ../../p_work/gcc/fortran/decl.c:3730
#6  0x0000000100062f22 in match_word (str=<value temporarily unavailable, due to optimizations>, subr=0x10001d0d0 <gfc_match_data_decl>, old_locus=0x7fff5fbfd380) at ../../p_work/gcc/fortran/parse.c:65
#7  0x00000001000637ad in decode_statement () at ../../p_work/gcc/fortran/parse.c:283
#8  0x0000000100064dd5 in next_statement () at ../../p_work/gcc/fortran/parse.c:715
#9  0x000000010006613c in parse_spec (st=<value temporarily unavailable, due to optimizations>) at ../../p_work/gcc/fortran/parse.c:2549
#10 0x000000010006838d in parse_progunit (st=ST_ARITHMETIC_IF) at ../../p_work/gcc/fortran/parse.c:3758
#11 0x0000000100068708 in parse_contained (module=1) at ../../p_work/gcc/fortran/parse.c:3698
#12 0x0000000100069c8a in gfc_parse_file () at ../../p_work/gcc/fortran/parse.c:3953
#13 0x00000001000a291c in gfc_be_parse_file (set_yydebug=<value temporarily unavailable, due to optimizations>) at ../../p_work/gcc/fortran/f95-lang.c:239
#14 0x00000001006d6b5a in toplev_main (argc=2, argv=0x7fff5fbfd9e8) at ../../p_work/gcc/toplev.c:1053
#15 0x00000001000019e4 in start ()

Although gfortran should not give an ICE, I have doubts about the validity of the code.
Comment 5 Tobias Burnus 2010-04-01 09:26:30 UTC
(In reply to comment #3)
> Reduced test:
[...]
(In reply to comment #4)
> Further reduced test that does not give an ICE, but several errors:
> Although gfortran should not give an ICE, I have doubts about the validity of
> the code.

Well, using
  type omega_procedures
     procedure(number_particles_out), nopass, pointer :: number_particles_out => NULL()
  end type omega_procedures

is definitely wrong: You tell that the procedure pointer has the interface of itself. By itself, gfortran also properly diagnoses this:

Error: Interface 'number_particles_out' of procedure pointer component 'number_particles_out' at (1) must be explicit

But seemingly, this resolution comes too late - the ICE happens earlier. That's definitely an ICE-on-invalid-code bug.

 * * *

However, if I compile the real, 7479 line program with ifort, I do not get any error message. I try now to reduce - using delta - the big program, under the constraint that it still compiles without any error with ifort. Let's see where that leads to.
Cf. http://gcc.gnu.org/wiki/A_guide_to_testcase_reduction
Comment 6 Thorsten Ohl 2010-04-01 11:47:26 UTC
(In reply to comment #5)

> Well, using
>   type omega_procedures
>      procedure(number_particles_out), nopass, pointer :: number_particles_out
> => NULL()
>   end type omega_procedures
> 
> is definitely wrong: You tell that the procedure pointer has the interface of
> itself.

But that's not the problem:

module m
  implicit none
  type t
     procedure(p1_type), nopass, pointer :: p1 => NULL()
     procedure(p2_type), nopass, pointer :: p2 => NULL()
  end type t
contains
  subroutine proc (t1, t2)
    type(t), intent(in) :: t1, t2
    integer, dimension(t1%p1(), t2%p2()) :: table
  end subroutine proc
end module m

produces the same error.

What is invaild about the code is that t1%p1() and t2%p2() are not initialization expressions.  Everthing works fine, when the tables are allocatable.

BTW: gfortran produces correct code for the variant when the procedures are not procedure pointers.  I stumpled over this OCE when rewriting some code.
Comment 7 Dominique d'Humieres 2010-04-01 12:17:14 UTC
(In reply to comment #6)
> What is invaild about the code is that t1%p1() and t2%p2() are not
> initialization expressions.  Everthing works fine, when the tables are
> allocatable.

That was the origin of my question about the validity of the code.

> BTW: gfortran produces correct code for the variant when the procedures are not
> procedure pointers.  I stumpled over this OCE when rewriting some code.

Why would this make the code valid?
Comment 8 Tobias Burnus 2010-04-01 12:28:49 UTC
(In reply to comment #6)
> But that's not the problem:
>   type t
>      procedure(p1_type), nopass, pointer :: p1 => NULL()
>      procedure(p2_type), nopass, pointer :: p2 => NULL()

That's not valid either as you have not defined "p1_type" - replacing it by INTEGER should work, though.  -- Well, it actually does not as specification expressions need to be PURE.

 * * *

Daniel, Janus: What do you think about the following incomplete patch? It needs some extra handling as, e.g., the PURE check fails for the procedure pointer (it works for the type-bound procedure) and maybe one should insert an assert that it is really a function and not a subroutine and things like that, but otherwise it seems to work.

Test case:
!----------------------------
module m
  implicit none
  type t
     procedure(p1_type), nopass, pointer :: p1 => NULL()
  contains
     procedure, nopass :: tbp => p1_type
  end type t
contains
  subroutine proc (t1, t2)
    type(t), intent(in) :: t1, t2
    integer, dimension(t1%p1(), t2%tbp()) :: table
  end subroutine proc
  pure function p1_type()
   integer :: p1_type
   p1_type = 42
  end function p1_type
end module m
!----------------------------

Index: expr.c
===================================================================
--- expr.c      (revision 157899)
+++ expr.c      (working copy)
@@ -3559,6 +3559,8 @@ gfc_traverse_expr (gfc_expr *expr, gfc_s

   switch (expr->expr_type)
     {
+    case EXPR_PPC:
+    case EXPR_COMPCALL:
     case EXPR_FUNCTION:
       for (args = expr->value.function.actual; args; args = args->next)
        {
Comment 9 Tobias Burnus 2010-04-01 12:36:49 UTC
(In reply to comment #7)
> (In reply to comment #6)
> > What is invaild about the code is that t1%p1() and t2%p2() are not
> > initialization expressions.  Everthing works fine, when the tables are
> > allocatable.
> 
> That was the origin of my question about the validity of the code.

What you have is called an "automatic (explicit) array", which does not need to have initialization expressions for bounds but just specification expressions:

5.3.8.2 Explicit-shape array
R516   explicit-shape-spec   is   [ lower-bound : ] upper-bound
R517   lower-bound  is  specification-expr
R518   upper-bound  is  specification-expr
C531 (R516) An explicit-shape-spec whose bounds are not constant expressions shall appear only in a subprogram, derived type denition, BLOCK construct, or interface body.

7.1.11 Specification expression
[...]
A function is a specification function if it is a pure function, is not a standard intrinsic function, is not an internal function, is not a statement function, and does not have a dummy procedure argument.
Comment 10 Thorsten Ohl 2010-04-01 12:45:17 UTC
(In reply to comment #8)
> That's not valid either as you have not defined "p1_type" - replacing it by
> INTEGER should work, though.  -- Well, it actually does not as specification
> expressions need to be PURE.

Doesn't help

module m
  implicit none
  type t
     procedure(p1_type), nopass, pointer :: p1 => NULL()
     procedure(p2_type), nopass, pointer :: p2 => NULL()
  end type t
  abstract interface
    pure function p1_type () result (n)
      integer :: n
    end function p1_type
    pure function p2_type () result (n)
      integer :: n
    end function p2_type
  end interface
contains
  subroutine proc (t1, t2)
    type(t), intent(in) :: t1, t2
    integer, dimension(t1%p1(), t2%p2()) :: table
  end subroutine proc
end module m

(The abstract interface is in the original bug report, but was removed in Dominiques's reduction).
Comment 11 Dominique d'Humieres 2010-04-01 15:57:21 UTC
The patch in comment #8 fixes the ICEs for the various reduced tests, however for the original code I get

ward.f90:405.19:

end module ward_lib
                   1
Internal Error at (1):
gfc_is_constant_expr(): Unknown expression type
Comment 12 Tobias Burnus 2010-04-06 20:58:38 UTC
(In reply to comment #11)
> Internal Error at (1):
> gfc_is_constant_expr(): Unknown expression type

Try the following patch; however, as written in comment 8 the PURE attribute is lost somewhere thus the patch is not sufficient.

Index: gcc/fortran/expr.c
===================================================================
--- gcc/fortran/expr.c  (Revision 158016)
+++ gcc/fortran/expr.c
@@ -782,6 +782,8 @@ gfc_is_constant_expr (gfc_expr *e)
       break;
 
     case EXPR_FUNCTION:
+    case EXPR_PPC:
+    case EXPR_COMPCALL:
       /* Specification functions are constant.  */
       if (check_specification_function (e) == MATCH_YES)
        {
@@ -3560,6 +3562,8 @@ gfc_traverse_expr (gfc_expr *expr, gfc_s
 
   switch (expr->expr_type)
     {
+    case EXPR_PPC:
+    case EXPR_COMPCALL:
     case EXPR_FUNCTION:
       for (args = expr->value.function.actual; args; args = args->next)
        {
Comment 13 Tobias Burnus 2010-04-07 09:38:26 UTC
I somehow miss the setting of
  expr->value.function.esym and thus expr->value.function.esym->attr
for PPC in resolve.c (e.g. in resolve_expr_ppc). Contrary to resolve_compcall, where on has:
  e->value.function.esym = target->n.sym;
(Setting it is not trivial as esym is gfc_symbol while the PPC is a component.)

Clearly, e->value.function.esym != NULL as otherwise one would never reach the PURE check in expr.c's external_spec_function but segfault:
  f = e->value.function.esym;
  if (!f->attr.pure && !f->attr.elemental)

In any case, e->value.function.esym->attr does not seem to be correctly set.
Comment 14 Tobias Burnus 2010-04-07 10:20:40 UTC
Looked at the wrong check. The following (lightly tested) should work:

Index: gcc/fortran/expr.c
===================================================================
--- gcc/fortran/expr.c  (revision 158042)
+++ gcc/fortran/expr.c  (working copy)
@@ -782,6 +782,8 @@ gfc_is_constant_expr (gfc_expr *e)
       break;

     case EXPR_FUNCTION:
+    case EXPR_PPC:
+    case EXPR_COMPCALL:
       /* Specification functions are constant.  */
       if (check_specification_function (e) == MATCH_YES)
        {
@@ -2808,6 +2810,7 @@ check_restricted (gfc_expr *e)
 gfc_try
 gfc_specification_expr (gfc_expr *e)
 {
+  gfc_component *comp;

   if (e == NULL)
     return SUCCESS;
@@ -2822,7 +2825,9 @@ gfc_specification_expr (gfc_expr *e)
   if (e->expr_type == EXPR_FUNCTION
          && !e->value.function.isym
          && !e->value.function.esym
-         && !gfc_pure (e->symtree->n.sym))
+         && !gfc_pure (e->symtree->n.sym)
+         && (!gfc_is_proc_ptr_comp (e, &comp)
+             || !comp-> attr.pure))
     {
       gfc_error ("Function '%s' at %L must be PURE",
                 e->symtree->n.sym->name, &e->where);
@@ -3560,6 +3565,8 @@ gfc_traverse_expr (gfc_expr *expr, gfc_s

   switch (expr->expr_type)
     {
+    case EXPR_PPC:
+    case EXPR_COMPCALL:
     case EXPR_FUNCTION:
       for (args = expr->value.function.actual; args; args = args->next)
        {
Comment 15 Dominique d'Humieres 2010-04-08 07:48:46 UTC
With the patch in comment #14, the test in comment #1 compiles and gives:

 evt=  234, flv=  1, col=  2, hel=  3, -0.122E-13 + i* 0.675E-14 ~ 0.267E-02
 evt=  234, flv=  1, col=  2, hel=  6, -0.122E-13 + i*-0.675E-14 ~ 0.267E-02
 evt=  289, flv=  1, col=  2, hel=  3, -0.161E-12 + i* 0.292E-12 ~ 0.446E-01
 evt=  289, flv=  1, col=  2, hel=  6, -0.161E-12 + i*-0.292E-12 ~ 0.446E-01
 evt=  380, flv=  1, col=  2, hel=  3,  0.102E-11 + i*-0.568E-13 ~ 0.817E-01
 evt=  380, flv=  1, col=  2, hel=  4, -0.383E-12 + i* 0.213E-13 ~ 0.817E-01
 evt=  380, flv=  1, col=  2, hel=  5, -0.383E-12 + i*-0.213E-13 ~ 0.817E-01
 evt=  380, flv=  1, col=  2, hel=  6,  0.102E-11 + i* 0.568E-13 ~ 0.817E-01
 evt=  380, flv=  1, col=  5, hel=  3, -0.108E-11 + i* 0.710E-12 ~ 0.217E+00
 evt=  380, flv=  1, col=  5, hel=  6, -0.108E-11 + i*-0.710E-12 ~ 0.217E+00
          10  failures in        40000  attempts
STOP 1

Regtested without failure.
Comment 16 Tobias Burnus 2010-04-10 14:25:12 UTC
Subject: Bug 43591

Author: burnus
Date: Sat Apr 10 14:24:46 2010
New Revision: 158191

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=158191
Log:
2010-04-10  Tobias Burnus  <burnus@net-b.de>

        PR fortran/43591
        * expr.c (gfc_is_constant_expr, gfc_traverse_expr): Handle
        proc-pointers and type-bound procedures.
        (gfc_specification_expr): Check proc-pointers for pureness.

2010-04-10  Tobias Burnus  <burnus@net-b.de>

        PR fortran/43591
        * gfortran.dg/spec_expr_6.f90: New test.


Added:
    trunk/gcc/testsuite/gfortran.dg/spec_expr_6.f90
Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/expr.c
    trunk/gcc/testsuite/ChangeLog

Comment 17 Tobias Burnus 2010-04-10 14:27:01 UTC
Fixed on the trunk (4.6). Planned to be committed also to GCC 4.5.1.

Patch: http://gcc.gnu.org/ml/fortran/2010-04/msg00093.html

Thanks for the bug report!
Comment 18 Daniel Franke 2010-05-18 22:36:35 UTC
(In reply to comment #17)
> Fixed on the trunk (4.6). Planned to be committed also to GCC 4.5.1.

Patch was applied to trunk about 6 weeks ago - how are the backporting plans?
Comment 19 Tobias Burnus 2010-05-19 07:22:20 UTC
Subject: Bug 43591

Author: burnus
Date: Wed May 19 07:22:00 2010
New Revision: 159556

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=159556
Log:
2010-05-19  Tobias Burnus  <burnus@net-b.de>

        PR fortran/43591
        * expr.c (gfc_is_constant_expr, gfc_traverse_expr): Handle
        proc-pointers and type-bound procedures.
        (gfc_specification_expr): Check proc-pointers for pureness.

2010-05-19  Tobias Burnus  <burnus@net-b.de>

        PR fortran/43591
        * gfortran.dg/spec_expr_6.f90: New test.


Added:
    branches/gcc-4_5-branch/gcc/testsuite/gfortran.dg/spec_expr_6.f90
Modified:
    branches/gcc-4_5-branch/gcc/fortran/ChangeLog
    branches/gcc-4_5-branch/gcc/fortran/expr.c
    branches/gcc-4_5-branch/gcc/testsuite/ChangeLog

Comment 20 Tobias Burnus 2010-05-19 07:24:01 UTC
(In reply to comment #18)
> Patch was applied to trunk about 6 weeks ago - how are the backporting plans?
Thanks for the reminder!

Thorsten: Thanks for the bug report.

As I do not intent to backport it to 4.4.x: Close as FIXED.