This is the mail archive of the fortran@gcc.gnu.org mailing list for the GNU Fortran project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Patch, Fortran] PR45170 - Fix deferred-length issue


This patch fixes an ordering problem with deferred string lengths. For

str = str2(:nn)

where "nn" is a something a tad more complicated than a local variable (e.g. a non-VALUE dummy argument), the result was wrong: the temporary variable with the string length was used before it was set.

The attached patch fixes the issue. However, I wonder whether the block should/could always be added.

Build and regtested on x86-64-linux.
OK for the trunk?

* * *

Remaining deferred-length issues:

- PR 47674: a = a(:n); reallocation messed up; "realloc" should be enough as the length has to be always <= previous length [memory content is then guaranteed to remain untouched]. Alternatively, a temporary is required
- PR 49954: String length is wrong for "array(:)(1:1)": It's wrongly the one of "array" instead of 1; there might be some extra issues.
- PR 50221: Some odd array assignment issues.
- PR 51976: Deferred-string components. Needs a hidden component for the string length. Tricky: expr->ts.u.cl->backend_decl is wrong as that points to the component - missing the component ref ("var->comp"). Similar to the issue of PR49954.


Tobias
2012-05-24  Tobias Burnus  <burnus@net-b.de>

	PR fortran/45170
	* trans-expr.c (gfc_trans_assignment_1): Fix handling of RHS
	string lengths for deferred-length LHS.
	(gfc_trans_scalar_assign): Remove superfluous gcc_assert.

2012-05-24  Tobias Burnus  <burnus@net-b.de>

	PR fortran/45170
	* gfortran.dg/deferred_type_param_7.f90: New.

diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c
index 9d48a09..ce915b6 100644
--- a/gcc/fortran/trans-expr.c
+++ b/gcc/fortran/trans-expr.c
@@ -6106,7 +6110,6 @@ gfc_trans_scalar_assign (gfc_se * lse, gfc_se * rse, gfc_typespec ts,
 
       if (rse->string_length != NULL_TREE)
 	{
-	  gcc_assert (rse->string_length != NULL_TREE);
 	  gfc_conv_string_parameter (rse);
 	  gfc_add_block_to_block (&block, &rse->pre);
 	  rlen = rse->string_length;
@@ -6891,7 +6897,6 @@ gfc_trans_assignment_1 (gfc_expr * expr1, gfc_expr * expr2, bool init_flag,
   stmtblock_t body;
   bool l_is_temp;
   bool scalar_to_array;
-  bool def_clen_func;
   tree string_length;
   int n;
 
@@ -7010,13 +7015,8 @@ gfc_trans_assignment_1 (gfc_expr * expr1, gfc_expr * expr2, bool init_flag,
      otherwise the character length of the result is not known.
      NOTE: This relies on having the exact dependence of the length type
      parameter available to the caller; gfortran saves it in the .mod files. */
-  def_clen_func = (expr2->expr_type == EXPR_FUNCTION
-		   || expr2->expr_type == EXPR_COMPCALL
-		   || expr2->expr_type == EXPR_PPC);
-  if (gfc_option.flag_realloc_lhs
-	&& expr2->ts.type == BT_CHARACTER
-	&& (def_clen_func || expr2->expr_type == EXPR_OP)
-	&& expr1->ts.deferred)
+  if (gfc_option.flag_realloc_lhs && expr2->ts.type == BT_CHARACTER
+      && expr1->ts.deferred)
     gfc_add_block_to_block (&block, &rse.pre);
 
   tmp = gfc_trans_scalar_assign (&lse, &rse, expr1->ts,
--- /dev/null	2012-05-24 07:57:26.555773053 +0200
+++ gcc/gcc/testsuite/gfortran.dg/deferred_type_param_7.f90	2012-05-24 15:18:26.000000000 +0200
@@ -0,0 +1,64 @@
+! { dg-do run }
+!
+! PR fortran/45170
+!
+! Contribued by Steve Kargl
+!
+
+PROGRAM helloworld
+  implicit none
+  character(:),allocatable::string
+  character(11), parameter :: cmpstring = "hello world"
+  real::rnd
+  integer :: i, cnt
+  do i = 1, 100
+     call random_number(rnd)
+     cnt = floor(12*rnd)
+
+     if (allocated (string) .and. mod(i, 3) == 0) deallocate (string)
+     call hello1 (cnt, string)
+     if (len(string) /= cnt .or. string /= cmpstring(1:cnt)) call abort ()
+
+     if (allocated (string) .and. mod(i, 5) == 0) deallocate (string)
+     call hello2 (cnt, string)
+     if (len(string) /= cnt .or. string /= cmpstring(1:cnt)) call abort ()
+
+     if (allocated (string) .and. mod(i, 7) == 0) deallocate (string)
+     call hello3 (cnt, string)
+     if (len(string) /= cnt .or. string /= cmpstring(1:cnt)) call abort ()
+
+     if (allocated (string) .and. mod(i, 9) == 0) deallocate (string)
+     call hello4 (cnt, string)
+     if (len(string) /= cnt .or. string /= cmpstring(1:cnt)) call abort ()
+
+!     print '(A,1X,I0)', '>' // string // '<', len(string)
+  end do
+contains
+  subroutine hello1 (n,string)
+    character(:),allocatable,intent(out)::string
+    integer,intent(in)::n
+    character(11)::helloworld="hello world"
+    string=helloworld(:n)                      ! Does not work.
+  end subroutine hello1
+
+  subroutine hello2 (n,string)
+    character(:),allocatable,intent(out)::string
+    integer,intent(in)::n
+    character(11)::helloworld="hello world"
+    string=(helloworld(:n))
+  end subroutine hello2
+
+  subroutine hello3 (n,string)
+    character(:),allocatable,intent(out)::string
+    integer,intent(in)::n
+    character(11)::helloworld="hello world"
+    allocate(string, source=helloworld(:n))
+  end subroutine hello3
+
+  subroutine hello4 (n,string)
+    character(:),allocatable,intent(out)::string
+    integer,intent(in)::n
+    character(11)::helloworld="hello world"
+    allocate(string, source=(helloworld(:n)))
+  end subroutine hello4
+end PROGRAM helloworld


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]