Tobias Burnus wrote:
Note that the patch assumes that the function's result variable's length specification expression is completely known to the caller. I think that's always the case in gfortran - or is it not?

Thinking about it, I came to the conclusion has explicitly been designed such that it is known.

Note: The attached patch is required in addition to make sure that the variable has the correct name mangling and to ensure that the string length is TREE_PUBLIC() = 1, when needed.

The trans-expr.c part of the patch has been posted at http://gcc.gnu.org/ml/fortran/2012-05/msg00054.html


Compile ("-c") the following code - with the function commented or not and with PUBLIC and PRIVATE - and look resulting .o file via nm. It shouldn't show the "str" variable (and the length variable) if (and only) if it is private and not used in the function result expression. Result for the program as shown below:

0000000000000008 B .__m_MOD_str
0000000000000000 T __m_MOD_bar
0000000000000000 B __m_MOD_str


module m
!  character(len=:), PRIVATE, allocatable :: str
  character(len=:), PUBLIC, allocatable :: str
contains
  ! Note due to technical reasons (TBP, generic, cf. resolve.c),
  ! a "PRIVATE :: bar" still counts a publicly using "str".
  function bar()
    character(len=len(str)) :: str
  end function bar
end module m

Tobias
diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c
index b03d393..3c1118e 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);
@@ -1395,29 +1405,7 @@ gfc_get_symbol_decl (gfc_symbol * sym)
 
   gfc_finish_var_decl (decl, sym);
 
-  if (sym->ts.type == BT_CHARACTER)
-    {
-      /* Character variables need special handling.  */
-      gfc_allocate_lang_decl (decl);
-
-      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);
-	}
-    }
-  else if (sym->attr.subref_array_pointer)
+  if (sym->attr.subref_array_pointer)
     {
       /* We need the span for these beasts.  */
       gfc_allocate_lang_decl (decl);

Reply via email to