Bug 27096

Summary: Automatic charlen pointer array result produces and ICE
Product: gcc Reporter: Paul Thomas <pault>
Component: fortranAssignee: Paul Thomas <pault>
Status: RESOLVED FIXED    
Severity: normal CC: debian-gcc, gcc-bugs, krange
Priority: P3    
Version: 4.2.0   
Target Milestone: 4.2.0   
Host: Target:
Build: Known to work:
Known to fail: Last reconfirmed: 2006-04-09 22:03:04

Description Paul Thomas 2006-04-09 21:56:58 UTC
As part of the continuing crusade to get tonto compiled:

character(10), dimension (2) :: inp
inp = "abcdefghij"
inp = join_1(inp)
print *, inp
contains
function join_1(self) result(res)
character(len=*), dimension(:) :: self
character(len=len(self)), dimension(:), pointer :: res
allocate (res(2))
res = self
end function
end

produces

test2.f90: In function ‘join_1’:
test2.f90:1: internal compiler error: in gfc_trans_deferred_array, at fortran/trans-array.c:4394

If I override the ICE by returning and finishing the block, I get the most peculiar code:

join_1 (__result, .__result, self, _self)
{
int4 ..__result;
int4 ubound.0;
int4 stride.1;
int4 offset.2;
int4 size.3;
char[0:D.939][1:_self] * self.0;
bit_size_type D.934;
<unnamed type> D.935;
bit_size_type D.937;
<unnamed type> D.938;
int4 D.939;
bit_size_type D.940;
<unnamed type> D.941;

{
int4 D.936;

D.936 = self->dim[0].stride;
stride.1 = D.936 == 0 ? 1 : D.936;
self.0 = (char[0:D.939][1:_self] *) (char[0:][1:_self] *) self->data;
ubound.0 = self->dim[0].ubound - self->dim[0].lbound + 1;
size.3 = stride.1 * NON_LVALUE_EXPR <ubound.0>;
offset.2 = -stride.1;
D.937 = (bit_size_type) (<unnamed type>) _self * 8;
D.938 = (<unnamed type>) _self;
D.939 = size.3 - 1;
D.940 = (bit_size_type) (<unnamed type>) _self * (bit_size_type) (<unnamed type>) size.3 * 8;
D.941 = (<unnamed type>) _self * (<unnamed type>) size.3;
}
..__result = _self;
D.934 = (bit_size_type) (<unnamed type>) ..__result * 8;
D.935 = (<unnamed type>) ..__result;
}
 
Paul
Comment 1 Andrew Pinski 2006-04-09 22:03:04 UTC
Confirmed.
Comment 2 Paul Thomas 2006-04-10 14:19:59 UTC
The peculiar code turns out to be a result of the way in which I kludged my way past the ICE.  In sorting the out, I found that there is a double fault:

The implicit result version of the above....

  character(10), dimension (2) :: inp
  inp = "abcdefghij"
  inp = join_1(inp)
  print *, inp
contains
  function join_1(self)
    character(len=*), dimension(:) :: self
    character(len=len(self)), dimension(:), pointer :: join_1
    allocate (join_1(2))
    join_1 = self
  end function
end

compiles but hits the runtime error:

Fortran runtime error: Attempt to allocate negative amount of memory.  Possible
integer overflow.

I must check that this is not an existing PR.

A double patch is on its way.

Paul


Comment 3 Paul Thomas 2006-04-10 14:48:46 UTC
A patch (not regtested yet, nor tested on tonto) and testcase for this and PR25597:

Index: gcc/fortran/trans-decl.c
===================================================================
--- gcc/fortran/trans-decl.c	(révision 112529)
+++ gcc/fortran/trans-decl.c	(copie de travail)
@@ -2536,6 +2536,12 @@
 	{
 	  tree result = TREE_VALUE (current_fake_result_decl);
 	  fnbody = gfc_trans_dummy_array_bias (proc_sym, result, fnbody);
+
+	  /* An automatic character length, pointer array result.  */
+	  if (proc_sym->ts.type == BT_CHARACTER
+		&& TREE_CODE (proc_sym->ts.cl->backend_decl) == VAR_DECL)
+	    fnbody = gfc_trans_dummy_character (proc_sym, proc_sym->ts.cl,
+						fnbody);
 	}
       else if (proc_sym->ts.type == BT_CHARACTER)
 	{
Index: gcc/fortran/trans-array.c
===================================================================
--- gcc/fortran/trans-array.c	(révision 112529)
+++ gcc/fortran/trans-array.c	(copie de travail)
@@ -4385,7 +4385,14 @@
 
   /* Get the descriptor type.  */
   type = TREE_TYPE (sym->backend_decl);
-  gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
+  if (!GFC_DESCRIPTOR_TYPE_P (type))
+    {
+      /* If the backend_decl is not a descriptor, we must have a pointer
+	 to one.  */
+      descriptor = build_fold_indirect_ref (sym->backend_decl);
+      type = TREE_TYPE (descriptor);
+      gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
+    }
 
   /* NULLIFY the data pointer.  */
   gfc_conv_descriptor_data_set (&fnblock, descriptor, null_pointer_node);


! { dg-do run }
! Tests the fixes for PR25597 and PR27096.
!
! This test combines the PR testcases.
!
  character(10), dimension (2) :: implicit_result
  character(10), dimension (2) :: explicit_result
  character(10), dimension (2) :: source
  source = "abcdefghij"
  explicit_result = join_1(source)
  if (any (explicit_result .ne. source)) call abort () 

  implicit_result = reallocate_hnv (source, size(source, 1), LEN (source))
  if (any (implicit_result .ne. source)) call abort () 

contains

! This function would cause an ICE in gfc_trans_deferred_array.
  function join_1(self) result(res)
    character(len=*), dimension(:) :: self
    character(len=len(self)), dimension(:), pointer :: res
    allocate (res(2))
    res = self
  end function

! This function originally ICEd and latterly caused a runtime error.
  FUNCTION reallocate_hnv(p, n, LEN)
    CHARACTER(LEN=LEN), DIMENSION(:), POINTER :: reallocate_hnv
    character(*), dimension(:) :: p
    ALLOCATE (reallocate_hnv(n))
    reallocate_hnv = p
  END FUNCTION reallocate_hnv

end


Paul
Comment 4 Paul Thomas 2006-04-16 03:45:34 UTC
Subject: Bug 27096

Author: pault
Date: Sun Apr 16 03:45:24 2006
New Revision: 112981

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=112981
Log:
2006-04-16  Paul Thomas  <pault@gcc.gnu.org>

	PR fortran/26822
	* intrinsic.c (add_functions): Mark LOGICAL as elemental.

	PR fortran/26787
	* expr.c (gfc_check_assign): Extend scope of error to include
	assignments to a procedure in the main program or, from a
	module or internal procedure that is not that represented by
	the lhs symbol. Use VARIABLE rather than l-value in message.

	PR fortran/27096
	* trans-array.c (gfc_trans_deferred_array): If the backend_decl
	is not a descriptor, dereference and then test and use the type.

	PR fortran/25597
	* trans-decl.c (gfc_trans_deferred_vars): Check if an array
	result, is also automatic character length.  If so, process
	the character length.

	PR fortran/18803
	PR fortran/25669
	PR fortran/26834
	* trans_intrinsic.c (gfc_walk_intrinsic_bound): Set
	data.info.dimen for bound intrinsics.
	* trans_array.c (gfc_conv_ss_startstride): Pick out LBOUND and
	UBOUND intrinsics and supply their shape information to the ss
	and the loop.

	PR fortran/27124
	* trans_expr.c (gfc_trans_function_call):  Add a new block, post,
	in to which all the argument post blocks are put.  Add this block
	to se->pre after a byref call or to se->post, otherwise.

2006-04-16  Paul Thomas  <pault@gcc.gnu.org>

	PR fortran/26787
	* gfortran.dg/proc_assign_1.f90: New test.
	* gfortran.dg/procedure_lvalue.f90: Change message.
	* gfortran.dg/namelist_4.f90: Add new error.

	PR fortran/27096
	* gfortran.dg/auto_pointer_array_result_1.f90

	PR fortran/27089
	* gfortran.dg/specification_type_resolution_1.f90

	PR fortran/18803
	PR fortran/25669
	PR fortran/26834
	* gfortran.dg/bounds_temporaries_1.f90: New test.

	PR fortran/27124
	* gfortran.dg/array_return_value_1.f90: New test.



Added:
    trunk/gcc/testsuite/gfortran.dg/array_return_value_1.f90
    trunk/gcc/testsuite/gfortran.dg/auto_char_pointer_array_result_1.f90
    trunk/gcc/testsuite/gfortran.dg/auto_pointer_array_result_1.f90
    trunk/gcc/testsuite/gfortran.dg/bounds_temporaries_1.f90
    trunk/gcc/testsuite/gfortran.dg/proc_assign_1.f90
    trunk/gcc/testsuite/gfortran.dg/specification_type_resolution_1.f90
Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/expr.c
    trunk/gcc/fortran/intrinsic.c
    trunk/gcc/fortran/resolve.c
    trunk/gcc/fortran/trans-array.c
    trunk/gcc/fortran/trans-decl.c
    trunk/gcc/fortran/trans-expr.c
    trunk/gcc/fortran/trans-intrinsic.c
    trunk/gcc/testsuite/ChangeLog
    trunk/gcc/testsuite/gfortran.dg/namelist_4.f90
    trunk/gcc/testsuite/gfortran.dg/procedure_lvalue.f90

Comment 5 Paul Thomas 2006-04-22 15:47:19 UTC
trunk and 4.1 have diverged too far, especially in characters, for the fix to work on 4.1.  I started trying to make up the difference but it is just too much to be worthwhile.

I am marking this as fixed on trunk.

Paul
Comment 6 Andrew Pinski 2006-09-25 22:47:14 UTC
*** Bug 29228 has been marked as a duplicate of this bug. ***