Bug 51434 - ICE with scalar init of an array parameter, used in DT default init with transfer
Summary: ICE with scalar init of an array parameter, used in DT default init with tran...
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: fortran (show other bugs)
Version: 4.5.2
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: ice-on-valid-code
Depends on:
Blocks:
 
Reported: 2011-12-06 06:06 UTC by Andy Nelson
Modified: 2013-11-25 01:12 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2012-06-23 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Andy Nelson 2011-12-06 06:06:08 UTC
The following code produces an internal compiler error on gfortran 4.5.2:


module testgfortran

use iso_c_binding


integer          , parameter :: lenname = 20
character(C_CHAR), parameter :: cdumchar(lenname) = ' '

type :: fsinfonames
   integer          :: namelen          = lenname
   character(C_CHAR):: raidnum(lenname) = transfer('raidnum             ',cdumchar)
end type 

end module testgfortran

well...it does, modulo the wordwrap damage that seems to appear above...
the 'raidnum' line should have as its ending portion:

raidnum(lenname) = transfer('raidnum             ',cdumchar)


which I hope doesn't get damaged too.

I type exactly:

gfortran testmod.f90

to get the error report of:

f951: internal compiler error: Segmentation fault
Please submit a full bug report,
with preprocessed source if appropriate.
See <http://gcc.gnu.org/bugs.html> for instructions.


gfortran -v gives me this:

Using built-in specs.
COLLECT_GCC=/opt/gcc/4.5.2/bin/../snos/bin/gfortran
COLLECT_LTO_WRAPPER=/opt/gcc/4.5.2/snos/libexec/gcc/x86_64-suse-linux/4.5.2/lto-wrapper
Target: x86_64-suse-linux
Configured with: ../xt-gcc-4.5.2/configure --prefix=/opt/gcc/4.5.2/snos --disable-nls --libdir=/opt/gcc/4.5.2/snos/lib --enable-languages=c,c++,fortran --with-gxx-include-dir=/opt/gcc/4.5.2/snos/include/g++ --with-slibdir=/opt/gcc/4.5.2/snos/lib --with-system-zlib --enable-shared --enable-__cxa_atexit x86_64-suse-linux --with-mpc=/opt/gcc/mpc/0.8.1 --with-mpfr=/opt/gcc/mpfr/2.4.2 --with-gmp=/opt/gcc/gmp/4.3.2 --with-sysroot=
Thread model: posix
gcc version 4.5.2 20101216 (Cray Inc.) (GCC)
Comment 1 kargl 2011-12-06 06:26:29 UTC
Reset Importance field to normal.  This field is usual normal for
fortran bugs.  The higher levels of importance are reserved for
bugs that break the ability to build gcc.

To avoid the word warp issue, you can also attach the
code to the pr via the web interface.

Can you explain what you think the code is doing, 
because I believe that it may not be doing what
you intend?
Comment 2 Steve Kargl 2011-12-06 06:31:17 UTC
On Tue, Dec 06, 2011 at 06:26:29AM +0000, kargl at gcc dot gnu.org wrote:
> 
> Can you explain what you think the code is doing, 
> because I believe that it may not be doing what
> you intend?
> 

I forgot to mention the ICE is present in trunk.
Slightly modified testcase.

module a
   use iso_c_binding
   integer, parameter :: n = 5
!
! ICE with next line
!  character(kind=c_char), parameter :: s(n) = 'a'
!
! Next two lines do not have an ICE.
!  character(c_char), parameter :: s(n) = ['a', 'b', 'c', 'd', 'e']
   character(kind=c_char), parameter :: s(n) = ['a', 'b', 'c', 'd', 'e']
   type b
      integer :: m = n
! All three lines work with the above to 'good' lines.
!     character(kind=c_char) :: t(n) = transfer('abc  ', s)
!     character(len=c_char) :: t(n) = transfer('abc  ', s)
      character(c_char) :: t(n) = transfer('abc  ', s)
   end type
end module a
Comment 3 Andy Nelson 2011-12-06 06:40:07 UTC
ok for priority modification. I don't know what the system is. This bug 'only'
breaks my code build, not any gcc build, so far as I know.

The code is trying to establish a storage area for a number of character
variable names which I can pass to C. Since C doesn't like character strings that
have lengths greater than one, I have to turn the strings that I have 
into arrays of character(len=1). Then when I pass them into a bind(c) routine
it goes over the boundary correctly. At least it seems to on intel and pgi
where I've tried this previously. The 'transfer' intrinsic is the mechanism
I'm using to set values for the character array (of which I provided only
one example...the actual fsinfonames type has more members). If I don't use
transfer, I have to do something like this, which is rather ugly:

character(c_char) :: raidnum(lenname) = (/ 'r','a','i','d','n','u','m',.....   /)


Is this what you thought I was trying to do? Is what I am trying to do actually
legal (would tend to think so atm, since pgi and intel don't have similar problems)?
Can you recommend a better way to solve this problem, besides redefining the C
standard to accept 'scalar' character strings longer than one character? 

Thanks,

Andy



On Dec 5, 2011, at 11:26 PM, kargl at gcc dot gnu.org wrote:

> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51434
> 
> kargl at gcc dot gnu.org changed:
> 
>           What    |Removed                     |Added
> ----------------------------------------------------------------------------
>                 CC|                            |kargl at gcc dot gnu.org
>           Severity|blocker                     |normal
> 
> --- Comment #1 from kargl at gcc dot gnu.org 2011-12-06 06:26:29 UTC ---
> Reset Importance field to normal.  This field is usual normal for
> fortran bugs.  The higher levels of importance are reserved for
> bugs that break the ability to build gcc.
> 
> To avoid the word warp issue, you can also attach the
> code to the pr via the web interface.
> 
> Can you explain what you think the code is doing, 
> because I believe that it may not be doing what
> you intend?
> 
> -- 
> Configure bugmail: http://gcc.gnu.org/bugzilla/userprefs.cgi?tab=email
> ------- You are receiving this mail because: -------
> You are on the CC list for the bug.
> You reported the bug.
Comment 4 Tobias Burnus 2011-12-06 08:53:24 UTC
Reduced test case. The TYPE is crucial - if "t" is just an initialization to a module variable, no ICE occurs.

character, parameter :: s(5) = 'a'
type b
  character :: t(5) = transfer('abc  ', s)  ! << ICE
end type
!type(b) :: x
!print *, x%t   ! shall print "abc  "
!print *, s     ! prints successfully "aaaaa"
end

==14250== Invalid read of size 8
==14250==    at 0x51A7CD: gfc_match_data_decl() (decl.c:1589)
==14250==    by 0x55F429: _ZL10match_wordPKcPF5matchvEP5locus.part.3 (parse.c:65)
==14250==    by 0x55FC39: decode_statement() (parse.c:283)

That's the line:
      else if (mpz_cmp (c->ts.u.cl->length->value.integer,
                        c->initializer->ts.u.cl->length->value.integer))
with
  c->initializer->ts.u.cl == NULL
Comment 5 Steve Kargl 2011-12-06 15:47:41 UTC
On Tue, Dec 06, 2011 at 06:40:07AM +0000, andy.nelson at lanl dot gov wrote:
> 
> character(c_char) :: raidnum(lenname) = &
> &  (/ 'r','a','i','d','n','u','m',.....  /)
> 
> Is this what you thought I was trying to do?
> Is what I am trying to do actually
> legal (would tend to think so atm, since pgi and intel don't have similar
> problems)?

What does 'character(c_char)' above declare?

What you have is an array of strings with each
string having a length of c_char.

R424 char-selector is length-selector
         or ( LEN = type-param-value ,
              KIND = scalar-int-initialization-expr )
         or ( type-param-value ,
              [ KIND = ] scalar-int-initialization-expr )
         or ( KIND = scalar-int-initialization-expr
              [ , LEN =type-param-value ] )

R425 length-selector is ( [ LEN = ] type-param-value )
         or * char-length [ , ]

Let nlen be the length and nknd the kind, you want to 
have one of the following forms:

character(len=nlen, kind=nknd) ...
character(nlen, kind=nknd) ...
character(len=nlen, nknd) ...
character(nlen, nknd) ...
character(kind=nknd) ...
character(kind=nknd, len=nlen) ...

For your case, nlen=1 and nknd=c_char.

As shown by Tobias, even if you fix your declarations, your
code will fail.

PS: I suspect yor code works with ifort and pgi because 
c_char is probably 1, default character kind is 1, and
these compilers only support a single character kind.  So,
you accidentally get want you want. 

PPS: Yes, I would use an ugly explicit array to do the
initializaton instead of transfer.  First, the explicit
array is clear and easy to understand.  Second, although
transfer should work, it is one ugly piece of code 
under the hood.
Comment 6 Steve Kargl 2011-12-06 15:59:17 UTC
On Tue, Dec 06, 2011 at 06:40:07AM +0000, andy.nelson at lanl dot gov wrote:
>
> Can you recommend a better way to solve this problem, besides redefining the C
> standard to accept 'scalar' character strings longer than one character? 
> 

Don't know if the code conforms to the C and Fortran standards,
but this appears to work.

% cat foo.c

#include <stdio.h>
void
foo(char *s)
{
   printf("%s\n", s);
}

% cat bar.f90

program bar
  use iso_c_binding
  character(len=5,kind=c_char) :: s
  interface
    subroutine foo(s) bind(c)
      use iso_c_binding
      character(len=1, kind=c_char) :: s
    end subroutine foo
  end interface
  s = 'abcd'
  call foo(s // char(0))
end program bar

% gcc46 -c foo.c
% gfortran46 -o z bar.f90 foo.c
% ./z
abcd 

It should be straight forward to modify your code.  The 
key is to null terminate the string you are passing into
the C routine, i.e., the char(0) above.
Comment 7 Andy Nelson 2011-12-06 22:25:00 UTC
Seems it doesn't work in general. My attempt at getting it to work (perhaps
messed up, but still an attempt) on intel generated an error about length not
being the same or some such, and that being a violation of the f03 standard
somewhere. Didn't investigate too deeply.

I'm now going forward with the array specification version

character(kind=C_CHAR) :: blah(10) = (/ 'b','l','a','h',...... /)

since it seems to work on the places I've tried it.

Any guess when this ICE might get some attention and into a release version?


Thanks for your help, and the pointer about the kind=C_CHAR things that 
I was not doing correctly. 

Andy

On Dec 6, 2011, at 8:59 AM, sgk at troutmask dot apl.washington.edu wrote:

> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51434
> 
> --- Comment #6 from Steve Kargl <sgk at troutmask dot apl.washington.edu> 2011-12-06 15:59:17 UTC ---
> On Tue, Dec 06, 2011 at 06:40:07AM +0000, andy.nelson at lanl dot gov wrote:
>> 
>> Can you recommend a better way to solve this problem, besides redefining the C
>> standard to accept 'scalar' character strings longer than one character? 
>> 
> 
> Don't know if the code conforms to the C and Fortran standards,
> but this appears to work.
> 
> % cat foo.c
> 
> #include <stdio.h>
> void
> foo(char *s)
> {
>   printf("%s\n", s);
> }
> 
> % cat bar.f90
> 
> program bar
>  use iso_c_binding
>  character(len=5,kind=c_char) :: s
>  interface
>    subroutine foo(s) bind(c)
>      use iso_c_binding
>      character(len=1, kind=c_char) :: s
>    end subroutine foo
>  end interface
>  s = 'abcd'
>  call foo(s // char(0))
> end program bar
> 
> % gcc46 -c foo.c
> % gfortran46 -o z bar.f90 foo.c
> % ./z
> abcd 
> 
> It should be straight forward to modify your code.  The 
> key is to null terminate the string you are passing into
> the C routine, i.e., the char(0) above.
> 
> -- 
> Configure bugmail: http://gcc.gnu.org/bugzilla/userprefs.cgi?tab=email
> ------- You are receiving this mail because: -------
> You are on the CC list for the bug.
> You reported the bug.
Comment 8 Steve Kargl 2011-12-07 02:17:48 UTC
On Tue, Dec 06, 2011 at 10:25:00PM +0000, andy.nelson at lanl dot gov wrote:
> 
> Any guess when this ICE might get some attention and into a release version?
> 

Unfortunately, the only guess is the bug will be fixed
when someone gets around to fixing it. :(  It comes 
down to too few developers and too many things to do
(e.g., fix bugs and implement new features) and too 
little time.

I breifly looked at the code path with gdb.  It seems to
be a problem with populating the first array.

This fails

integer, parameter :: n = 5
character(kind=c_char), parameter :: s(n) = 'a'
type b
  character(kind=c_char) :: t(n) = transfer(s, s,)
end type b 

because the scalar 'a' is not broadcasted over the array.

If one replaces the s(n) line with

character(kind=c_char), parameter :: s(n) = ['a', 'a', 'a', 'a', 'a']

then everything appears to work.  I haven't had time to
look at this any further.
Comment 9 Tobias Burnus 2011-12-07 11:44:48 UTC
(In reply to comment #7)
> Any guess when this ICE might get some attention and into a release version?

Well, as you can see from the discussion here, it does get attention.

But in general: Only regressions have a high priority. (Regression = something which worked before but stopped doing so. At least the code of comment 4 never worked in gfortran.) -- We try hard to fix also the other issues, but as the development is based on volunteers and there are many bugs and feature requests, it might take a while.

Release: The GCC development is now in the stabilization phase and GCC 4.7.0 will be presumably released around March next year. See http://gcc.gnu.org/ml/fortran/2011-12/msg00028.html (esp. the "Status" part in the forwarded email).


(In reply to comment #4)
> That's the line:
>       else if (mpz_cmp (c->ts.u.cl->length->value.integer,
>                         c->initializer->ts.u.cl->length->value.integer))
> with
>   c->initializer->ts.u.cl == NULL


Draft patch - one probably needs to do something similar for derived types.

--- a/gcc/fortran/decl.c
+++ b/gcc/fortran/decl.c
@@ -1500,6 +1500,8 @@ add_init_expr_to_sym (const char *name, gfc_expr **initp, locus *var_locus)
                                             &init->where);

              array->shape = gfc_get_shape (sym->as->rank);
+             if (init->ts.type == BT_CHARACTER)
+               array->ts.u.cl = init->ts.u.cl;
              for (n = 0; n < sym->as->rank; n++)
                spec_dimen_size (sym->as, n, &array->shape[n]);
Comment 10 Tobias Burnus 2011-12-07 15:31:11 UTC
(In reply to comment #9)
> Draft patch - one probably needs to do something similar for derived types.

The patch breaks the "Different CHARACTER lengths (%d/%d) in array constructor" diagnostic, e.g. gfortran.dg/bounds_check_array_ctor_3.f90.
Comment 11 Andy Nelson 2011-12-07 16:11:38 UTC
On Dec 6, 2011, at 7:17 PM, sgk at troutmask dot apl.washington.edu wrote:

> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51434
> 
> --- Comment #8 from Steve Kargl <sgk at troutmask dot apl.washington.edu> 2011-12-07 02:17:48 UTC ---
> On Tue, Dec 06, 2011 at 10:25:00PM +0000, andy.nelson at lanl dot gov wrote:
>> 
>> Any guess when this ICE might get some attention and into a release version?
>> 
> 
> Unfortunately, the only guess is the bug will be fixed
> when someone gets around to fixing it. :(  It comes 
> down to too few developers and too many things to do
> (e.g., fix bugs and implement new features) and too 
> little time.
> 

Sure. I didn't mean to imply any particular pressure. In the environment
I work in, it would be years before I see this fix even if it got fixed today,
so any particular time pressure is rather soft. Basically, for most of the codes 
that I work on and that pay my salary, I can't implement a feature or depend on
a bug not hitting me until the oldest machine we have is retired or upgraded past the 
implementation/fix of whatever it is that I need for some bit of code or other.

Thanks for the attention,

Andy
Comment 12 Tobias Burnus 2011-12-07 17:20:14 UTC
(In reply to comment #10)
> > Draft patch - one probably needs to do something similar for derived types.
> The patch breaks the "Different CHARACTER lengths (%d/%d) in array
> constructor" diagnostic, e.g. gfortran.dg/bounds_check_array_ctor_3.f90.

Actually, it does not - that was a left over from an earlier attempt (in expr.c's gfc_get_character_expr). The following should work, but is not regtested. I am not sure about the BT_DERIVED part; valid examples seem to work fine while the following invalid code ICEs in decl.c's build_struct. That's independent of the patch.

  type t
    character :: z
  end type t
  type(t), parameter :: s(5) = t('a')
  type b
      character :: y(5) = transfer('aaaaa', s)
    end type
  end

--- a/gcc/fortran/decl.c
+++ b/gcc/fortran/decl.c
@@ -1502,6 +1502,18 @@ add_init_expr_to_sym (const char *name, gfc_expr **initp, locus *var_locus)
              array->shape = gfc_get_shape (sym->as->rank);
              for (n = 0; n < sym->as->rank; n++)
                spec_dimen_size (sym->as, n, &array->shape[n]);
+             array->ts.is_c_interop = init->ts.is_c_interop;
+             if (init->ts.type == BT_CHARACTER)
+               {
+                 if (init->ts.u.cl->length == NULL)
+                   init->ts.u.cl->length
+                       = gfc_get_int_expr (gfc_default_integer_kind,
+                                           &init->where,
+                                           init->value.character.length);
+                 array->ts.u.cl = init->ts.u.cl;
+               }
+             else if (init->ts.type == BT_DERIVED)
+               array->ts.u.derived = init->ts.u.derived;

              init = array;
              mpz_clear (size);
Comment 13 Dominique d'Humieres 2012-06-23 21:56:00 UTC
(In reply to comment #12)
> Actually, it does not - that was a left over from an earlier attempt (in
> expr.c's gfc_get_character_expr). The following should work, but is not
> regtested. I am not sure about the BT_DERIVED part; valid examples seem to work
> fine while the following invalid code ICEs in decl.c's build_struct. That's
> independent of the patch.

Indeed even with the patch I get 

f951: internal compiler error: in build_struct, at fortran/decl.c:1620

Is the following variant 

  type t
    character :: z
  end type t
  type(t), parameter :: s(5) = t('a')
  type b
      character :: y(5) = transfer('aaaaa', s%z)
  end type
  type(b) :: zz
  print *, zz
  print *, s%z
  end

valid? Compiling it with/without the patch gives a segmentation fault. For the patched trunk of today, the backtrace is

#0  splay_tree_min (sp=0x1) at ../../work/libiberty/splay-tree.c:485
#1  0x0000000100013d8e in gfc_constructor_first (base=<value optimized out>) at ../../work/gcc/fortran/constructor.c:234
#2  0x000000010002fbac in simplify_const_ref (p=0x142314d00) at ../../work/gcc/fortran/expr.c:1276
#3  0x0000000100030012 in simplify_const_ref (p=0x142314920) at ../../work/gcc/fortran/expr.c:1653
#4  0x00000001000306fe in gfc_simplify_expr (p=0x142314920, type=0) at ../../work/gcc/fortran/expr.c:1917
#5  0x00000001000309ea in simplify_parameter_variable (p=0x142314560, type=0) at ../../work/gcc/fortran/expr.c:1782
#6  0x000000010002f2f8 in gfc_check_init_expr (e=0x142314560) at ../../work/gcc/fortran/expr.c:2515
#7  0x000000010002fa42 in check_init_expr_arguments (e=<value optimized out>) at ../../work/gcc/fortran/expr.c:2228
#8  0x000000010002f95e in gfc_check_init_expr (e=0x1423142b0) at ../../work/gcc/fortran/expr.c:2381
#9  0x000000010002fae8 in gfc_reduce_init_expr (expr=0x1423142b0) at ../../work/gcc/fortran/expr.c:2626
#10 0x0000000100030b8a in gfc_match_init_expr (result=0x7fff5fbfd308) at ../../work/gcc/fortran/expr.c:2665
#11 0x0000000100021be5 in gfc_match_data_decl () at ../../work/gcc/fortran/decl.c:2042
#12 0x000000010006e41a in match_word (subr=<value optimized out>, old_locus=0x7fff5fbfd3f0, str=<value optimized out>)
    at ../../work/gcc/fortran/parse.c:66
#13 0x000000010006ede4 in decode_statement () at ../../work/gcc/fortran/parse.c:331
#14 0x00000001000703c5 in next_statement () at ../../work/gcc/fortran/parse.c:778
#15 0x0000000100071ead in parse_spec (st=ST_DERIVED_DECL) at ../../work/gcc/fortran/parse.c:2093
#16 0x00000001000740f9 in parse_progunit (st=<value optimized out>) at ../../work/gcc/fortran/parse.c:4110
#17 0x000000010007507e in gfc_parse_file () at ../../work/gcc/fortran/parse.c:4585
#18 0x00000001000b4726 in gfc_be_parse_file () at ../../work/gcc/fortran/f95-lang.c:191
#19 0x000000010072c2af in compile_file () at ../../work/gcc/toplev.c:550
#20 0x000000010072e115 in toplev_main (argc=2, argv=0x7fff5fbfd7a0) at ../../work/gcc/toplev.c:1867
#21 0x0000000100001974 in start ()
Comment 14 Tobias Burnus 2012-06-25 13:28:34 UTC
(In reply to comment #13)
> Is the following variant 
...
> valid?

Looks valid - and with other compilers it does compile and run. What works in gfortran is the following, which yields a scalar RHS of "= 'a'":
  character :: y(5) = transfer('abced', s(1)%z)

While for s%z or s(:)%z or even s(1:1)%z, one gets a size-5 array on the RHS, namely "=['a','a','a','a','a']" (or with 'abcde' the array ['a','b','c','d','e']). That case is ICEing in gfortran.


From F2008, "13.7.168 TRANSFER (SOURCE, MOLD [, SIZE])":

"Result Characteristics. The result is of the same type and type parameters as MOLD.
Case (i): If MOLD is a scalar and SIZE is absent, the result is a scalar.
Case (ii): If MOLD is an array and SIZE is absent, the result is an array and of rank one. Its size is as small as possible such that its physical representation is not shorter than that of SOURCE.
Case (iii): If SIZE is present, the result is an array of rank one and size SIZE."
Comment 15 Dominique d'Humieres 2012-06-25 13:45:09 UTC
The following test 

  character(len=2), parameter :: z(5) = ['af', 'bg', 'ch', 'di', 'ej']
  type b
      character :: y(5) = transfer('zyxwvutsrq', z)
  end type
  type(b) :: zz
  print *, zz
  print *, z
  end

gives

 zxvtr
 afbgchdiej

when compiled with g95, but an ICE when compiled with gfortran

pr51434_3_db_4.f90:8:0: internal compiler error: in output_constructor_regular_field, at varasm.c:4768