[Patch, gfortran] PR26257 - Ping

Paul Thomas paulthomas2@wanadoo.fr
Mon Mar 6 19:48:00 GMT 2006


Paul Thomas wrote:

> Paul Thomas wrote:
>
> Ping!
>
> Original is found on http://gcc.gnu.org/ml/fortran/2006-02/msg00553.html.
>
> The patch has evolved slightly, although the principle is the same.  
> Instead of testsing for the symbol possessing a namespace, the caller 
> explicitly demands that the data and offset fields not be filled, 
> through a new bitfield in gfc_se.
>
> Again, regtested on FC3/Athlon.
>
> Paul
>
>> :ADDPATCH fortran:
>>
>> With reference to the attached testcase, the seg fault 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 actual argument of SIZE, which 
>> 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 provoke a segfault, judiciously deposited 
>> in gfc_conv_expr_descriptor, does the job.  This patch is attached, 
>> together with a testsuite version of the reduced PR testcase.
>>
>> Regtested on FC3/Athlon.
>>
>> OK for mainline and 4.1, when reopened?
>>
>> Paul
>>
>> 2006-02-29  Paul Thomas  <pault@gcc.gnu.org>
>>
>>    PR fortran/26257
>>    * trans-array.c (gfc_conv_expr_descriptor): Exclude calculation of 
>> the offset
>>    for arrays without a namespace - ie. module procedure dummies.
>>
>> 2006-02-29  Paul Thomas  <pault@gcc.gnu.org>
>>
>>    PR fortran/26257
>>    gfortran.dg/auto_char_len_3.f90: New test
>>
>>
>>
>> ------------------------------------------------------------------------
>>
>> Index: gcc/fortran/trans-array.c
>> ===================================================================
>> *** gcc/fortran/trans-array.c    (revision 111450)
>> --- gcc/fortran/trans-array.c    (working copy)
>> *************** gfc_conv_expr_descriptor (gfc_se * se, g
>> *** 3789,3797 ****
>> --- 3789,3800 ----
>>    tree offset;
>>    int full;
>>    gfc_ref *ref;
>> +   gfc_symbol *sym;
>>  
>>    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)
>> *************** gfc_conv_expr_descriptor (gfc_se * se, g
>> *** 4143,4154 ****
>>        dim++;
>>      }
>>  
>> !       /* 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)
>>      {
>> --- 4146,4160 ----
>>        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);
>> !     }
>>  
>>        if (se->direct_byref)
>>      {
>>  
>>
>> ------------------------------------------------------------------------
>>
>> ! { 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
>>  
>>
>
>------------------------------------------------------------------------
>
>Index: gcc/fortran/trans-array.c
>===================================================================
>*** gcc/fortran/trans-array.c	(revision 111642)
>--- gcc/fortran/trans-array.c	(working copy)
>*************** gfc_conv_expr_descriptor (gfc_se * se, g
>*** 4144,4157 ****
>  	  dim++;
>  	}
>  
>!       /* 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.  */
>  	  tmp = gfc_conv_descriptor_offset (parm);
>--- 4144,4162 ----
>  	  dim++;
>  	}
>  
>!       if (se->data_not_needed)
>! 	gfc_conv_descriptor_data_set (&loop.pre, parm, gfc_index_zero_node);
>!       else
>! 	{
>! 	  /* 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 && !se->data_not_needed)
>  	{
>  	  /* Set the offset.  */
>  	  tmp = gfc_conv_descriptor_offset (parm);
>Index: gcc/fortran/trans.h
>===================================================================
>*** gcc/fortran/trans.h	(revision 111642)
>--- gcc/fortran/trans.h	(working copy)
>*************** typedef struct gfc_se
>*** 67,72 ****
>--- 67,76 ----
>    /* Ignore absent optional arguments.  Used for some intrinsics.  */
>    unsigned ignore_optional:1;
>  
>+   /* When this is set the data and offset fields of the returned descriptor
>+      are NULL.  Used by intrinsic size.  */
>+   unsigned data_not_needed:1;
>+ 
>    /* Scalarization parameters.  */
>    struct gfc_se *parent;
>    struct gfc_ss *ss;
>Index: gcc/fortran/trans-intrinsic.c
>===================================================================
>*** gcc/fortran/trans-intrinsic.c	(revision 111642)
>--- gcc/fortran/trans-intrinsic.c	(working copy)
>*************** gfc_conv_intrinsic_size (gfc_se * se, gf
>*** 2405,2410 ****
>--- 2405,2411 ----
>    ss = gfc_walk_expr (actual->expr);
>    gcc_assert (ss != gfc_ss_terminator);
>    argse.want_pointer = 1;
>+   argse.data_not_needed = 1;
>    gfc_conv_expr_descriptor (&argse, actual->expr, ss);
>    gfc_add_block_to_block (&se->pre, &argse.pre);
>    gfc_add_block_to_block (&se->post, &argse.post);
>  
>




More information about the Fortran mailing list