Created attachment 41446 [details] Test Case Trying to compile the testcase with "-O" produces invalid code, while compiling it without leads to a segfault. gcc@dcm-linux:~/pr/35339> gfortran -O z5.f90 gcc@dcm-linux:~/pr/35339> ./a.out c foo bar xyzzy ca xyzzy gcc@dcm-linux:~/pr/35339> gfortran z5.f90 gcc@dcm-linux:~/pr/35339> ./a.out Program received signal SIGSEGV: Segmentation fault - invalid memory reference. Backtrace for this error: #0 0x7f37dee45adf in ??? #1 0x7f37dee97d15 in ??? #2 0x7f37dfb03a50 in read_default_char1 at ../../../trunk/libgfortran/io/read.c:429 #3 0x7f37dfb0809c in formatted_transfer_scalar_read at ../../../trunk/libgfortran/io/transfer.c:1591 #4 0x7f37dfb08f2c in formatted_transfer at ../../../trunk/libgfortran/io/transfer.c:2270 #5 0x400cb3 in ??? #6 0x400e43 in ??? #7 0x7f37dee31469 in ??? #8 0x400909 in ??? at ../sysdeps/x86_64/start.S:120 #9 0xffffffffffffffff in ??? Segmentation fault (core dumped)
1. write also fails (no surprise there) 2. ca is OK, ca(1:3) is not. $ cat u.f90 program main implicit none integer:: i integer, parameter:: N = 10 character(len=:), dimension(:),allocatable:: ca character(len=50):: buffer allocate(character(len=N):: ca(3)) buffer = "foo bar xyzzy" ca(1) = "foo" ca(2) = "bar" ca(3) = "xyzzy" write (*, '(3A5)') ca write (*, '(3A5)') ca(1:3) end program $ gfortran u.f90 && ./a.out foo bar xyzzy Program received signal SIGSEGV: Segmentation fault - invalid memory reference. Backtrace for this error: #0 0x7f38e528406f in ??? #1 0x7f38e5384440 in ??? #2 0x7f38e5eeb67c in formatted_transfer_scalar_write at ../../../gcc-7/libgfortran/io/transfer.c:2059 #3 0x7f38e5eeb81c in formatted_transfer at ../../../gcc-7/libgfortran/io/transfer.c:2279 #4 0x400d03 in ??? #5 0x400d55 in ??? #6 0x7f38e526f540 in ??? #7 0x400839 in ??? at ../sysdeps/x86_64/start.S:120 #8 0xffffffffffffffff in ??? Speicherzugriffsfehler (Speicherabzug geschrieben)
The dtype is messed up. Breaking at _gfortran_transfer_array for the test case in cmment #1 shows Breakpoint 1, _gfortran_transfer_array (dtp=0x7fffffffd910, desc=0x7fffffffdaf0, kind=1, charlen=10) at ../../../gcc-7/libgfortran/io/transfer.c:2409 2409 if ((dtp->common.flags & IOPARM_LIBRETURN_MASK) != IOPARM_LIBRETURN_OK) (gdb) p *desc $3 = {base_addr = 0x605ff0 "foo bar xyzzy ", offset = 18446744073709551615, dtype = 689, dim = {{_stride = 1, lower_bound = 1, _ubound = 3}, {_stride = 8241976683187367782, lower_bound = 2340036147838197792, _ubound = 2314885530818453536}, {_stride = 2314885530818453536, lower_bound = 2314885530818453536, _ubound = 2314885530818453536}, {_stride = 8224, lower_bound = 44024187392, _ubound = 140737488346016}, {_stride = 0, lower_bound = 4196368, _ubound = 140737488346240}, {_stride = 140737488346016, lower_bound = 4197718, _ubound = 140737488346248}, {_stride = 4294967296, lower_bound = 4197728, _ubound = 140737336403265}}} (gdb) c Continuing. foo bar xyzzy Breakpoint 1, _gfortran_transfer_array (dtp=0x7fffffffd910, desc=0x7fffffffd8e0, kind=1, charlen=10) at ../../../gcc-7/libgfortran/io/transfer.c:2409 2409 if ((dtp->common.flags & IOPARM_LIBRETURN_MASK) != IOPARM_LIBRETURN_OK) (gdb) p *desc $4 = {base_addr = 0x605ff0 "foo bar xyzzy ", offset = 0, dtype = -60931979599, dim = {{_stride = 1, lower_bound = 1, _ubound = 3}, {_stride = 25769807872, lower_bound = 4198108, _ubound = 13}, {_stride = 0, lower_bound = 0, _ubound = 0}, {_stride = 0, lower_bound = 0, _ubound = 0}, {_stride = 4198114, lower_bound = 5, _ubound = 0}, {_stride = 0, lower_bound = 0, _ubound = 0}, {_stride = 0, lower_bound = 0, _ubound = 0}}}
Really strange - the tree dumps look OK at first glance. D.3543 = (sizetype) NON_LVALUE_EXPR <.ca>; and later on parm.3.dtype = ((integer(kind=8)) SAVE_EXPR <D.3543> << 6) + 49; parm.3.dim[0].lbound = 1; parm.3.dim[0].ubound = 3; parm.3.dim[0].stride = 1; parm.3.data = (void *) &(*(character(kind=1)[0:][1:.ca] * restrict) ca.data)[1 - ca.dim[0].lbound]; parm.3.offset = 0; _gfortran_transfer_array_write (&dt_parm.2, &parm.3, 1, .ca); What am I missing?
(In reply to Thomas Koenig from comment #3) > Really strange - the tree dumps look OK at first glance. > Maybe missing something in a backend declaration?
The code is correctly compiled if I replace character(len=:), dimension(:),allocatable:: ca with character(len=N), dimension(:),allocatable:: ca or read (buffer, '(3A5)') ca(1:3) with read (buffer, '(3A5)') ca It could be related to pr68241.
If this patch is fixed, please remember to remove the extra check in frontend-passes.c (traverse_io_block). Just grep for 80945.
Still fails with current trunk. Code from comment#1, somewhat simplified: program main implicit none integer:: i integer, parameter:: N = 10 character(len=:), dimension(:),allocatable:: ca allocate(character(len=N):: ca(3)) ca(1) = "foo" ca(2) = "bar" ca(3) = "xyzzy" write (*, '(3A5)') ca(1:3) end program This yields on gcc110: foo foo foo Looking at the tree dump, we see MAIN__ () { integer(kind=8) .ca; struct array01_unknown ca; bitsizetype D.2078; sizetype D.2079; D.2078 = (bitsizetype) (sizetype) NON_LVALUE_EXPR <.ca> * 8; D.2079 = (sizetype) NON_LVALUE_EXPR <.ca>; and later { integer(kind=4) overflow.0; .ca = 10; ca.dtype = {.elem_len=(unsigned long) SAVE_EXPR <(sizetype) NON_LVALUE_EXPR <.ca>>, .rank=1, .type=6}; ... _gfortran_st_write (&dt_parm.1); { struct array01_unknown parm.2; parm.2.dtype = {.elem_len=(unsigned long) SAVE_EXPR <D.2079>, .rank=1, .type=6}; parm.2.dim[0].lbound = 1; parm.2.dim[0].ubound = 3; parm.2.dim[0].stride = 1; parm.2.data = (void *) &(*(character(kind=1)[0:][1:.ca] * restrict) ca.data)[1 - ca.dim[0].lbound]; parm.2.offset = ca.offset; _gfortran_transfer_array_write (&dt_parm.1, &parm.2, 1, .ca); so the dtype gets its elem_len from the uninitialized copy of .ca instead of the correctly initialized value later. Paul, does this ring any bells?
Hi Thomas, It doesn't just ring bells, it lets off sirens and sets the marching bands to marching! I can only find rather old sources on the web but I seem to remember that the new dtype generation uses gfc_get_element_type , which makes use of GFC_TYPE_ARRAY_DATAPTR_TYPE. If this latter does not get reset with each reallocation it would be the source of the trouble. I'll try to take a look tonight, although the 14th February might prevail :-) Paul On 13 February 2018 at 21:18, tkoenig at gcc dot gnu.org <gcc-bugzilla@gcc.gnu.org> wrote: > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80945 > > --- Comment #7 from Thomas Koenig <tkoenig at gcc dot gnu.org> --- > Still fails with current trunk. > > Code from comment#1, somewhat simplified: > > program main > implicit none > integer:: i > integer, parameter:: N = 10 > character(len=:), dimension(:),allocatable:: ca > allocate(character(len=N):: ca(3)) > ca(1) = "foo" > ca(2) = "bar" > ca(3) = "xyzzy" > write (*, '(3A5)') ca(1:3) > end program > > This yields on gcc110: > > foo foo foo > > Looking at the tree dump, we see > > MAIN__ () > { > integer(kind=8) .ca; > struct array01_unknown ca; > bitsizetype D.2078; > sizetype D.2079; > > D.2078 = (bitsizetype) (sizetype) NON_LVALUE_EXPR <.ca> * 8; > D.2079 = (sizetype) NON_LVALUE_EXPR <.ca>; > > and later > > { > integer(kind=4) overflow.0; > > .ca = 10; > ca.dtype = {.elem_len=(unsigned long) SAVE_EXPR <(sizetype) NON_LVALUE_EXPR > <.ca>>, .rank=1, .type=6}; > > ... > > _gfortran_st_write (&dt_parm.1); > { > struct array01_unknown parm.2; > > parm.2.dtype = {.elem_len=(unsigned long) SAVE_EXPR <D.2079>, .rank=1, > .type=6}; > parm.2.dim[0].lbound = 1; > parm.2.dim[0].ubound = 3; > parm.2.dim[0].stride = 1; > parm.2.data = (void *) &(*(character(kind=1)[0:][1:.ca] * restrict) > ca.data)[1 - ca.dim[0].lbound]; > parm.2.offset = ca.offset; > _gfortran_transfer_array_write (&dt_parm.1, &parm.2, 1, .ca); > > so the dtype gets its elem_len from the uninitialized copy of .ca > instead of the correctly initialized value later. > > Paul, does this ring any bells? > > -- > You are receiving this mail because: > You are on the CC list for the bug.
Created attachment 43438 [details] A demo patch for the PR This does the job but sucks stylistically. I will sort out something better. It does regtest fine, though :-) It also fixes: program main implicit none integer:: i integer, parameter:: N = 10 character(len=:), dimension(:),allocatable:: ca character(len=:), dimension(:,:),allocatable:: cb allocate(character(len=N) :: ca(3)) ca(1) = "foo" ca(2) = "bar" ca(3) = "xyzzy" write (*, '(3A5)') ca(1:3) allocate(character(len=N) :: cb(3,2)) cb(1,1) = "foo" cb(2,1) = "bar" cb(3,1) = "xyzzy" write (*, '(3A5)') cb(1:3,1) ! Hence the assignment of the rank! end program Paul
Author: pault Date: Sun Feb 18 08:59:06 2018 New Revision: 257788 URL: https://gcc.gnu.org/viewcvs?rev=257788&root=gcc&view=rev Log: 2018-02-18 Paul Thomas <pault@gcc.gnu.org> PR fortran/80945 * trans-array.c (gfc_conv_expr_descriptor): Set parmtype from the typenode in the case of deferred length characters. 2018-02-18 Paul Thomas <pault@gcc.gnu.org> PR fortran/80945 * gfortran.dg/associate_35.f90: Remove error, add stop n's and change to run. Added: trunk/gcc/testsuite/gfortran.dg/deferred_character_19.f90 Modified: trunk/gcc/fortran/ChangeLog trunk/gcc/fortran/trans-array.c trunk/gcc/testsuite/ChangeLog
Author: tkoenig Date: Mon Feb 19 18:21:45 2018 New Revision: 257814 URL: https://gcc.gnu.org/viewcvs?rev=257814&root=gcc&view=rev Log: 2018-02-19 Thomas Koenig <tkoenig@gcc.gnu.org> PR fortran/35339 * frontend-passes.c (traverse_io_block): Remove workaround for PR 80945. 2018-02-19 Thomas Koenig <tkoenig@gcc.gnu.org> PR fortran/35339 * gfortran.dg/implied_do_io_4.f90: New test. Added: trunk/gcc/testsuite/gfortran.dg/implied_do_io_4.f90 Modified: trunk/gcc/fortran/ChangeLog trunk/gcc/fortran/frontend-passes.c trunk/gcc/testsuite/ChangeLog
Fixed?
Fixed on trunk. Thanks for the report. Paul and Thomas