diff mbox

[Fortran,pr66911,gcc-5,v1] ICE on allocate character with source as a derived type component

Message ID 20160403173357.1a2b03b7@vepi2
State New
Headers show

Commit Message

Andre Vehreschild April 3, 2016, 3:33 p.m. UTC
Hi all,

attached patch fixes the ICE when using a deferred length char array as
source= expression in an allocate for complicated source= expressions.
Before the patch the compiler was relying on having the string length
available in the ts of the expression, but when the expression is
sufficiently complicated it is not set there. In trunk the problem does
not arise, because the source= expression is evaluated in more cases.
In gcc-5 this is not available without doing a major rewrite of the
allocate() statement's conv-routine. Therefore this small portion of
extra code reliably does the trick and takes the string_length from the
se.string_length now.

Bootstrapped and regtested ok on x86_64-linux-gnu/F23. Ok for
gcc-5-branch?

Regards,
	Andre

Comments

Jerry DeLisle April 3, 2016, 7:22 p.m. UTC | #1
On 04/03/2016 08:33 AM, Andre Vehreschild wrote:
> Hi all,
> 
> attached patch fixes the ICE when using a deferred length char array as
> source= expression in an allocate for complicated source= expressions.
> Before the patch the compiler was relying on having the string length
> available in the ts of the expression, but when the expression is
> sufficiently complicated it is not set there. In trunk the problem does
> not arise, because the source= expression is evaluated in more cases.
> In gcc-5 this is not available without doing a major rewrite of the
> allocate() statement's conv-routine. Therefore this small portion of
> extra code reliably does the trick and takes the string_length from the
> se.string_length now.
> 
> Bootstrapped and regtested ok on x86_64-linux-gnu/F23. Ok for
> gcc-5-branch?
> 
> Regards,
> 	Andre
> 

Yes, OK

Thanks for your work.

Jerry
diff mbox

Patch

diff --git a/gcc/fortran/trans-stmt.c b/gcc/fortran/trans-stmt.c
index b33bad7..25c2a0c 100644
--- a/gcc/fortran/trans-stmt.c
+++ b/gcc/fortran/trans-stmt.c
@@ -5536,14 +5536,23 @@  gfc_trans_allocate (gfc_code * code)
 	  if (expr3_len == NULL_TREE
 	      && code->expr3->ts.type == BT_CHARACTER)
 	    {
+	      gfc_init_se (&se, NULL);
 	      if (code->expr3->ts.u.cl
 		  && code->expr3->ts.u.cl->length)
 		{
-		  gfc_init_se (&se, NULL);
 		  gfc_conv_expr (&se, code->expr3->ts.u.cl->length);
 		  gfc_add_block_to_block (&block, &se.pre);
 		  expr3_len = gfc_evaluate_now (se.expr, &block);
 		}
+	      else
+		{
+		  /* The string_length is not set in the symbol, which prevents
+		     it being set in the ts.  Deduce it by converting expr3.  */
+		  gfc_conv_expr (&se, code->expr3);
+		  gfc_add_block_to_block (&block, &se.pre);
+		  gcc_assert (se.string_length);
+		  expr3_len = gfc_evaluate_now (se.string_length, &block);
+		}
 	      gcc_assert (expr3_len);
 	    }
 	  /* For character arrays only the kind's size is needed, because
diff --git a/gcc/testsuite/gfortran.dg/deferred_character_16.f90 b/gcc/testsuite/gfortran.dg/deferred_character_16.f90
new file mode 100644
index 0000000..27fb112
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/deferred_character_16.f90
@@ -0,0 +1,24 @@ 
+! { dg-do run }
+
+program truc
+implicit none
+
+type t_env_table
+    character(len=:), allocatable :: key
+end type
+
+type(t_env_table), dimension(:), allocatable :: environment_table
+
+character(len=:), allocatable :: s
+
+allocate(environment_table(1))
+environment_table(1)%key='tt'
+
+allocate(s, source=environment_table(1)%key)
+
+if ( .not. allocated(s) ) call abort()
+if ( s /= "tt" ) call abort()
+if ( len(s) /= 2 ) call abort()
+!print *, 's:"', s, '" derived:"',environment_table(1)%key,'"'
+
+end program