diff mbox

[Fortran,(RFC)] PR49110/51055 Assignment to alloc. deferred-length character vars

Message ID 4FB136B3.30804@net-b.de
State New
Headers show

Commit Message

Tobias Burnus May 14, 2012, 4:45 p.m. UTC
Dear Paul,

On 05/14/2012 03:31 PM, Paul Richard Thomas wrote:
> OK for trunk - just a wee typo to correct:

Fixed. Thanks for the review! I have now committed the attached patch as 
Rev. 187472.

Tobias
diff mbox

Patch

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

	PR fortran/49110
	PR fortran/51055
	PR fortran/53329
	* trans-expr.c (gfc_trans_assignment_1): Fix allocation
	handling for assignment of function results to allocatable
	deferred-length strings.
	* trans-decl.c (gfc_create_string_length): For deferred-length
	module variables, include module name in the assembler name.
	(gfc_get_symbol_decl): Don't override the assembler name.

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

	PR fortran/49110
	PR fortran/51055
	PR fortran/53329
	* gfortran.dg/deferred_type_param_4.f90: New.
	* gfortran.dg/deferred_type_param_6.f90: New.

diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c
index b03d393..1354ad0 100644
--- a/gcc/fortran/trans-decl.c
+++ b/gcc/fortran/trans-decl.c
@@ -1087,11 +1087,14 @@  gfc_create_string_length (gfc_symbol * sym)
   if (sym->ts.u.cl->backend_decl == NULL_TREE)
     {
       tree length;
-      char name[GFC_MAX_MANGLED_SYMBOL_LEN + 2];
+      const char *name;
 
       /* Also prefix the mangled name.  */
-      strcpy (&name[1], sym->name);
-      name[0] = '.';
+      if (sym->module)
+	name = gfc_get_string (".__%s_MOD_%s", sym->module, sym->name);
+      else
+	name = gfc_get_string (".%s", sym->name);
+
       length = build_decl (input_location,
 			   VAR_DECL, get_identifier (name),
 			   gfc_charlen_type_node);
@@ -1101,6 +1104,13 @@  gfc_create_string_length (gfc_symbol * sym)
 	gfc_defer_symbol_init (sym);
 
       sym->ts.u.cl->backend_decl = length;
+
+      if (sym->attr.save || sym->ns->proc_name->attr.flavor == FL_MODULE)
+	TREE_STATIC (length) = 1;
+
+      if (sym->ns->proc_name->attr.flavor == FL_MODULE
+	  && (sym->attr.access != ACCESS_PRIVATE || sym->attr.public_used))
+	TREE_PUBLIC (length) = 1;
     }
 
   gcc_assert (sym->ts.u.cl->backend_decl != NULL_TREE);
@@ -1402,17 +1412,6 @@  gfc_get_symbol_decl (gfc_symbol * sym)
 
       if (TREE_CODE (length) != INTEGER_CST)
 	{
-	  char name[GFC_MAX_MANGLED_SYMBOL_LEN + 2];
-
-	  if (sym->module)
-	    {
-	      /* Also prefix the mangled name for symbols from modules.  */
-	      strcpy (&name[1], sym->name);
-	      name[0] = '.';
-	      strcpy (&name[1],
-		      IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (length)));
-	      gfc_set_decl_assembler_name (decl, get_identifier (name));
-	    }
 	  gfc_finish_var_decl (length, sym);
 	  gcc_assert (!sym->value);
 	}
diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c
index 81562d2..9d48a09 100644
--- a/gcc/fortran/trans-expr.c
+++ b/gcc/fortran/trans-expr.c
@@ -7005,13 +7005,14 @@  gfc_trans_assignment_1 (gfc_expr * expr1, gfc_expr * expr2, bool init_flag,
       gfc_add_expr_to_block (&loop.post, tmp);
     }
 
-  /* For a deferred character length function, the function call must
-     happen before the (re)allocation of the lhs, otherwise the character
-     length of the result is not known.  */
-  def_clen_func = (((expr2->expr_type == EXPR_FUNCTION)
-			   || (expr2->expr_type == EXPR_COMPCALL)
-			   || (expr2->expr_type == EXPR_PPC))
-		       && expr2->ts.deferred);
+  /* When assigning a character function result to a deferred-length variable,
+     the function call must happen before the (re)allocation of the lhs -
+     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)
--- /dev/null	2012-05-14 08:15:48.907781309 +0200
+++ gcc/gcc/testsuite/gfortran.dg/deferred_type_param_6.f90	2012-05-11 12:18:46.000000000 +0200
@@ -0,0 +1,33 @@ 
+! { dg-do run }
+!
+! PR fortran/51055
+! PR fortran/49110
+!
+
+subroutine test()
+  implicit none
+  integer :: i = 5
+  character(len=:), allocatable :: s1
+  call sub(s1, i)
+  if (len(s1) /= 5) call abort()
+  if (s1 /= "ZZZZZ") call abort()
+contains
+  subroutine sub(str,j)
+    character(len=:), allocatable :: str
+    integer :: j
+    str = REPEAT("Z",j)
+    if (len(str) /= 5) call abort()
+    if (str /= "ZZZZZ") call abort()
+  end subroutine sub
+end subroutine test
+
+program a
+ character(len=:),allocatable :: s
+ integer :: j=2
+ s = repeat ('x', j)
+ if (len(repeat(' ',j)) /= 2) call abort()
+ if (repeat('y',j) /= "yy") call abort()
+ if (len(s) /= 2) call abort()
+ if (s /= "xx") call abort()
+ call test()
+end program a
--- /dev/null	2012-05-14 08:15:48.907781309 +0200
+++ gcc/gcc/testsuite/gfortran.dg/deferred_type_param_4.f90	2012-05-11 12:22:30.000000000 +0200
@@ -0,0 +1,33 @@ 
+! { dg-do run }
+!
+! PR fortran/51055
+! PR fortran/49110
+!
+!
+program test
+  implicit none
+  character(len=:), allocatable :: str
+  integer :: i
+  i = 5
+  str = f()
+  call printIt ()
+  i = 7
+  str = repeat('X', i)
+  call printIt ()
+contains
+  function f()
+    character(len=i) :: f
+    f = '1234567890'
+  end function f
+  subroutine printIt
+!    print *, len(str)
+!    print '(3a)', '>',str,'<'
+    if (i == 5) then
+      if (str /= "12345" .or. len(str) /= 5) call abort ()
+    else if (i == 7) then
+      if (str /= "XXXXXXX" .or. len(str) /= 7) call abort ()
+    else
+      call abort ()
+    end if
+  end subroutine
+end