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);