Bug 29400 - constant arrays as intrinsic arguments lead to ICE
Summary: constant arrays as intrinsic arguments lead to ICE
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: fortran (show other bugs)
Version: 4.2.0
: P3 normal
Target Milestone: ---
Assignee: Paul Thomas
URL:
Keywords: ice-on-valid-code, wrong-code
Depends on:
Blocks:
 
Reported: 2006-10-09 11:53 UTC by Francois-Xavier Coudert
Modified: 2007-05-08 13:02 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail: 4.1.2 4.2.0 4.3.0
Last reconfirmed: 2007-05-07 08:59:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Francois-Xavier Coudert 2006-10-09 11:53:32 UTC
I found that bug while reducing PR29391, so it might be related (but I doubt it).

$ cat a6.f90 
  integer,parameter :: i(1,1) = 0

  write(*,*) lbound(any(i==1,2)), ubound(any(i==1,2))
  write(*,*) lbound(count(i==1,2)), ubound(count(i==1,2))
  write(*,*) lbound(matmul(i,i))
end
$ gfortran a6.f90 && ./a.out
Operating system error: Cannot allocate memory
Memory allocation failed

If I remove the line with matmul, I get another error:

$ gfortran a6.f90 && ./a.out
           0           1
           0           1
zsh: segmentation fault  ./a.out
Comment 1 Francois-Xavier Coudert 2006-10-09 12:36:31 UTC
The generated code for:
  integer,parameter :: i(1,1) = 0
  integer :: j(1)
  j = lbound(any(i==1,2))
  end
is weird:

MAIN__ ()
{
  int4 j[1];

  _gfortran_set_std (70, 127, 0);
  {
    int8 S.0;

    S.0 = 1;
    while (1)
      {
        if (S.0 > 1) goto L.1; else (void) 0;
        {
          struct array1_logical4 atmp.1;
          int8 C.1248 = 2;
          logical4 C.1247 = 0;

          atmp.1.dtype = 273;
          atmp.1.data = 0B;
          atmp.1.offset = 0;
          _gfortran_any_l4 (&atmp.1, &C.1247, &C.1248);
          j[NON_LVALUE_EXPR <S.0> + -1] = (int4) atmp.1.dim[S.0 - 1].lbound;
          _gfortran_internal_free (atmp.1.data);
        }
        S.0 = S.0 + 1;
      }
    L.1:;
  }
}

Why are we passing a pointer to a logical4 as a second argument to _gfortran_any_l4, and not an array descriptor.
Comment 2 Francois-Xavier Coudert 2006-10-09 12:44:16 UTC
And while I'm there, a few possibly related bugs:

$ cat pr29400-2.f90 
  integer,parameter :: i(1,1) = 0
  logical :: l(2)
  l = any(i==1,2)
  end
$ gfortran pr29400-2.f90 && ./a.out
Fortran runtime error: rank of return array incorrect
$ cat pr29400-3.f90 
  integer,parameter :: i(1,1) = 0
  logical :: l
  l = any(i==1)
  end
$ gfortran pr29400-3.f90 && ./a.out
pr29400-3.f90: In function ‘MAIN__’:
pr29400-3.f90:1: internal compiler error: in gfc_conv_intrinsic_anyall, at fortran/trans-intrinsic.c:1339
Comment 3 Francois-Xavier Coudert 2007-02-06 12:25:46 UTC
> $ cat pr29400-3.f90 
>   integer,parameter :: i(1,1) = 0
>   logical :: l
>   l = any(i==1)
>   end
> $ gfortran pr29400-3.f90 && ./a.out
> pr29400-3.f90: In function ‘MAIN__’:
> pr29400-3.f90:1: internal compiler error: in gfc_conv_intrinsic_anyall, at
> fortran/trans-intrinsic.c:1339

Same thing happens for count. We try to walk the constant, and it doesn't work (we fail on the next assert). dot_product works, while seemingly doing the same thing, maybe we can borrow from it...
Comment 4 Francois-Xavier Coudert 2007-02-06 13:41:57 UTC
I was wrong: the bug basically happens for all intrinsics which gfc_walk_expr one of their arguments and then simply assert that the ss != gfc_ss_terminator. This is a wrong thing to do for constant arguments. I audited all the intrinsics to find out which I could lead to an ICE, and here's the complete list:

  integer,parameter :: i(1,1) = 0, j(2) = 42
  logical :: l

!  print *, maxloc(j+j,mask=(j==2))

  print *, size(j+j)
  print *, minval(j+j)
  print *, minval(j,mask=(j==2))
  print *, maxval(j+j)
  print *, maxval(j,mask=(j==2))
  print *, sum(j,mask=j==2)
  print *, sum(j+j)
  print *, product(j+j)
  print *, ubound(j+j)
  print *, lbound(j+j)
  print *, dot_product(j+j,j)
  print *, dot_product(j,j+j)
  print *, count(i==1)
  print *, any(i==1)
  print *, all(i==1)

  end

I couldn't make maxloc/minloc ICE, although I'm pretty sure there should be a way to get it.
Comment 5 Paul Thomas 2007-05-07 08:59:00 UTC
(In reply to comment #4)

FX,

  integer,parameter :: i(1,1) = reshape ((/0/),(/1,1/))
!  integer,parameter :: i(1,1) = 1
  integer :: j(1)
  j = lbound(any(i==1,2))
  print *, j
  end

works correctly, so it is the initializer that is wrong.  In fact, this is one and the same as PR29397.  My fix for that did not mend this PR until I added the shape expressions.  Then, even your great long test in comment#4 works correctly.

I'll do a regtest and submit later today.

Cheers

Paul
Comment 6 Paul Thomas 2007-05-08 12:58:35 UTC
Subject: Bug 29400

Author: pault
Date: Tue May  8 11:58:25 2007
New Revision: 124541

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=124541
Log:
2007-05-08  Paul Thomas  <pault@gcc.gnu.org>

	PR fortran/29397
	PR fortran/29400
	* decl.c (add_init_expr_to_sym): Expand a scalar initializer
	for a parameter array into an array expression with the right
	shape.
	* array.c (spec_dimen_size): Remove static attribute.
	* gfortran.h : Prototype for spec_dimen_size.

2007-05-08  Paul Thomas  <pault@gcc.gnu.org>

	PR fortran/29397
	* gfortran.dg/parameter_array_init_1.f90: New test.

	PR fortran/29400
	* gfortran.dg/parameter_array_init_2.f90: New test.

Added:
    trunk/gcc/testsuite/gfortran.dg/parameter_array_init_1.f90
    trunk/gcc/testsuite/gfortran.dg/parameter_array_init_2.f90
Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/array.c
    trunk/gcc/fortran/decl.c
    trunk/gcc/fortran/gfortran.h
    trunk/gcc/testsuite/ChangeLog

Comment 7 Paul Thomas 2007-05-08 13:02:07 UTC
Fixed on trunk

Paul