The following code lets gfortran crash: module chtest contains function chararray2string(chararray) result(text) character(len=1), dimension(:) :: chararray ! input character(len=size(chararray)) :: text ! output integer :: n, i text(:) = ' ' n = size(chararray) DO i=1,n text(i:i) = chararray(i) END DO end function chararray2string end module chtest program TestStringTools use chtest implicit none character(len=50) :: txt character(len=1), dimension(50) :: chararr ! init and print txt(:) = ' ' chararr(1:3) = (/'A','B','C'/) ! convert to a string and print txt = chararray2string(chararr) print *,"trim(txt) = [",trim(txt),"]" end program TestStringTools when compiled with: >gfortran Test.F90 -o chtest I get the following response: Test.F90: In function ‘MAIN__’: Test.F90:22: internal compiler error: Segmentation fault Please submit a full bug report, with preprocessed source if appropriate. See <URL:http://gcc.gnu.org/bugs.html> for instructions. > Commenting out the following line removes the problem: txt = chararray2string(chararr) I used the following gfortran version: >gfortran -v Using built-in specs. Target: i386-linux Configured with: ../gcc/configure --prefix=/tmp/gfortran-20060212/irun --enable-languages=c,fortran --host=i386-linux --with-gmp=/tmp/gfortran-20060212/gfortran_libs Thread model: posix gcc version 4.2.0 20060212 (experimental) best regards, Jos de Kloe
Confirmed, reduced testcase: module chtest contains function chararray2string(chararray) result(text) character(len=1), dimension(:) :: chararray ! input character(len=size(chararray)) :: text ! output end function chararray2string end module chtest program TestStringTools use chtest character(len=50) :: txt character(len=1), dimension(50) :: chararr txt = chararray2string(chararr) end program TestStringTools
This is a module related problem; the same function works fine when internal. program TestStringTools character(len=50) :: txt character(len=1), dimension(50) :: chararr txt = chararray2string(chararr) contains function chararray2string(chararray) result(text) character(len=1), dimension(:) :: chararray ! input character(len=size(chararray)) :: text ! output do i = 1,size(chararray,1) text(i:i) = chararray (i) end do end function chararray2string end program TestStringTools Paul
Jos, You have made my day on two levels: First, your idea that the code is "letting" gfortran crash means that we are making real progress; ie. gfortran crashing is no longer its natural state! Second this was quite a diverting little problem to solve. As I remarked below, it is due to the function being use associated - the segfault occurs via the route gfc_conv_intrinsic_size => gfc_conv_expr_descriptor => gfc_build_addr_expr, which is needed to calculate the potential offset between the full array and the argumant to SIZE that is assumed to be an array section. However, seen from the main program, the address of a dummy argument of a module procedure is not the most readily available thing in the world - in fact, it has already gone out of scope. Happily, SIZE does not need the offset or the data, come to that. Thus a patch in which we check that the symbol belongs to a namespace before trying to cause segfaults, judiciously deposited in gfc_conv_expr_descriptor, does the job. This patch appears below, together with a testsuite version of the reduced testcase. I need to think about whether this patch is "correct" or whether it might not be better to ensure that a symbol is generated in MAIN corresponding to chararray. I'll sleep on it and decide tomorrow. Paul Thomas $ svn diff gcc/fortran/trans-array.c Index: gcc/fortran/trans-array.c =================================================================== --- gcc/fortran/trans-array.c (r├®vision 111471) +++ gcc/fortran/trans-array.c (copie de travail) @@ -3789,9 +3789,12 @@ tree offset; int full; gfc_ref *ref; + gfc_symbol *sym; - gcc_assert (ss != gfc_ss_terminator); - + gcc_assert (ss != gfc_ss_terminator); + + sym = expr->expr_type == EXPR_VARIABLE ? expr->symtree->n.sym : NULL; + /* TODO: Pass constant array constructors without a temporary. */ /* Special case things we know we can pass easily. */ switch (expr->expr_type) @@ -4142,14 +4145,17 @@ dim++; } + + if (!(sym && !sym->ns && !se->direct_byref)) + { + /* Point the data pointer at the first element in the section. */ + tmp = gfc_conv_array_data (desc); + tmp = build_fold_indirect_ref (tmp); + tmp = gfc_build_array_ref (tmp, offset); + offset = gfc_build_addr_expr (gfc_array_dataptr_type (desc), tmp); + gfc_conv_descriptor_data_set (&loop.pre, parm, offset); + } - /* Point the data pointer at the first element in the section. */ - tmp = gfc_conv_array_data (desc); - tmp = build_fold_indirect_ref (tmp); - tmp = gfc_build_array_ref (tmp, offset); - offset = gfc_build_addr_expr (gfc_array_dataptr_type (desc), tmp); - gfc_conv_descriptor_data_set (&loop.pre, parm, offset); - if (se->direct_byref) { /* Set the offset. */ ! { dg-do run } ! Test the fix for PR26257, in which the implicit reference to ! chararray in the main program call of chararray2string would ! cause a segfault in gfc_build_addr_expr. ! ! Based on the reduced testcase in the PR. module chtest contains function chararray2string(chararray) result(text) character(len=1), dimension(:) :: chararray ! input character(len=size(chararray, 1)) :: text ! output do i = 1,size(chararray,1) text(i:i) = chararray (i) end do end function chararray2string end module chtest program TestStringTools use chtest character(len=52) :: txt character(len=1), dimension(52) :: chararr = & (/(char(i+64),char(i+96), i = 1,26)/) txt = chararray2string(chararr) if (txt .ne. "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz") & call abort () end program TestStringTools
Subject: Bug number PR26257 A patch for this bug has been added to the patch tracker. The mailing list url for the patch is http://gcc.gnu.org/ml/gcc-patches/2006-02/msg02069.html
Subject: Bug 26257 Author: pault Date: Thu Mar 9 05:52:06 2006 New Revision: 111860 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=111860 Log: 2006-03-09 Paul Thomas <pault@gcc.gnu.org> PR fortran/26257 * trans-array.c (gfc_conv_expr_descriptor): Exclude calculation of the offset and data when se->data_not_needed is set. * trans.h: Include the data_not_need bit in gfc_se. * trans-intrinsic.c (gfc_conv_intrinsic_size): Set it for SIZE. 2006-03-09 Paul Thomas <pault@gcc.gnu.org> * PR fortran/26257 gfortran.dg/auto_char_len_3.f90: New test Added: trunk/gcc/testsuite/gfortran.dg/auto_char_len_3.f90 Modified: trunk/gcc/fortran/ChangeLog trunk/gcc/fortran/trans-array.c trunk/gcc/fortran/trans-intrinsic.c trunk/gcc/fortran/trans.h trunk/gcc/testsuite/ChangeLog
Subject: Bug 26257 Author: pault Date: Tue Apr 11 04:40:33 2006 New Revision: 112848 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=112848 Log: 2006-04-11 Paul Thomas <pault@gcc.gnu.org> PR fortran/26257 * trans-array.c (gfc_conv_expr_descriptor): Exclude calculation of the offset and data when se->data_not_needed is set. * trans.h: Include the data_not_need bit in gfc_se. * trans-intrinsic.c (gfc_conv_intrinsic_size): Set it for SIZE. 2006-04-11 Paul Thomas <pault@gcc.gnu.org> * PR fortran/26257 gfortran.dg/auto_char_len_3.f90: New test Added: branches/gcc-4_1-branch/gcc/testsuite/gfortran.dg/auto_char_len_3.f90 Modified: branches/gcc-4_1-branch/gcc/fortran/ChangeLog branches/gcc-4_1-branch/gcc/fortran/trans-array.c branches/gcc-4_1-branch/gcc/fortran/trans-intrinsic.c branches/gcc-4_1-branch/gcc/fortran/trans.h branches/gcc-4_1-branch/gcc/testsuite/ChangeLog
Sorry, I forgot about closing out this one on 4.1. Fixed on trunk and 4.1. Paul