Bug 26257 - internal compiler error: Segmentation fault, on function call with assumed shape array parameter
Summary: internal compiler error: Segmentation fault, on function call with assumed sh...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: fortran (show other bugs)
Version: 4.2.0
: P3 normal
Target Milestone: 4.1.1
Assignee: Not yet assigned to anyone
URL:
Keywords: ice-on-valid-code
Depends on:
Blocks: Fortran_character
  Show dependency treegraph
 
Reported: 2006-02-13 14:15 UTC by Jos de Kloe
Modified: 2006-04-12 01:23 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2006-02-13 14:40:58


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Jos de Kloe 2006-02-13 14:15:23 UTC
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
Comment 1 Andrew Pinski 2006-02-13 14:40:58 UTC
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
Comment 2 Paul Thomas 2006-02-13 22:17:34 UTC
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
Comment 3 Paul Thomas 2006-02-28 16:00:14 UTC
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&#9500;®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
Comment 4 patchapp@dberlin.org 2006-02-28 19:45:20 UTC
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
Comment 5 Paul Thomas 2006-03-09 05:52:10 UTC
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

Comment 6 Paul Thomas 2006-04-11 04:40:37 UTC
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

Comment 7 Paul Thomas 2006-04-11 04:42:38 UTC
Sorry, I forgot about closing out this one on 4.1.

Fixed on trunk and 4.1.

Paul