aboutsummaryrefslogtreecommitdiff
path: root/gcc/fortran/trans-decl.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/fortran/trans-decl.c')
-rw-r--r--gcc/fortran/trans-decl.c126
1 files changed, 102 insertions, 24 deletions
diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c
index a2172c3ddeb..4e778be34c5 100644
--- a/gcc/fortran/trans-decl.c
+++ b/gcc/fortran/trans-decl.c
@@ -342,39 +342,45 @@ gfc_get_label_decl (gfc_st_label * lp)
}
}
+/* Return the name of an identifier. */
-/* Convert a gfc_symbol to an identifier of the same name. */
-
-static tree
-gfc_sym_identifier (gfc_symbol * sym)
+static const char *
+sym_identifier (gfc_symbol *sym)
{
if (sym->attr.is_main_program && strcmp (sym->name, "main") == 0)
- return (get_identifier ("MAIN__"));
+ return "MAIN__";
else
- return (get_identifier (sym->name));
+ return sym->name;
}
-
-/* Construct mangled name from symbol name. */
+/* Convert a gfc_symbol to an identifier of the same name. */
static tree
-gfc_sym_mangled_identifier (gfc_symbol * sym)
+gfc_sym_identifier (gfc_symbol * sym)
{
- char name[GFC_MAX_MANGLED_SYMBOL_LEN + 1];
+ return get_identifier (sym_identifier (sym));
+}
+/* Construct mangled name from symbol name. */
+
+static const char *
+mangled_identifier (gfc_symbol *sym)
+{
+ static char name[GFC_MAX_MANGLED_SYMBOL_LEN + 1];
/* Prevent the mangling of identifiers that have an assigned
binding label (mainly those that are bind(c)). */
+
if (sym->attr.is_bind_c == 1 && sym->binding_label)
- return get_identifier (sym->binding_label);
+ return sym->binding_label;
if (!sym->fn_result_spec)
{
if (sym->module == NULL)
- return gfc_sym_identifier (sym);
+ return sym_identifier (sym);
else
{
snprintf (name, sizeof name, "__%s_MOD_%s", sym->module, sym->name);
- return get_identifier (name);
+ return name;
}
}
else
@@ -389,17 +395,40 @@ gfc_sym_mangled_identifier (gfc_symbol * sym)
sym->ns->proc_name->module,
sym->ns->proc_name->name,
sym->name);
- return get_identifier (name);
+ return name;
}
else
{
snprintf (name, sizeof name, "__%s_PROC_%s",
sym->ns->proc_name->name, sym->name);
- return get_identifier (name);
+ return name;
}
}
}
+/* Get mangled identifier, adding the symbol to the global table if
+ it is not yet already there. */
+
+static tree
+gfc_sym_mangled_identifier (gfc_symbol * sym)
+{
+ tree result;
+ gfc_gsymbol *gsym;
+ const char *name;
+
+ name = mangled_identifier (sym);
+ result = get_identifier (name);
+
+ gsym = gfc_find_gsymbol (gfc_gsym_root, name);
+ if (gsym == NULL)
+ {
+ gsym = gfc_get_gsymbol (name, false);
+ gsym->ns = sym->ns;
+ gsym->sym_name = sym->name;
+ }
+
+ return result;
+}
/* Construct mangled function name from symbol name. */
@@ -839,7 +868,7 @@ gfc_get_module_backend_decl (gfc_symbol *sym)
{
if (!gsym)
{
- gsym = gfc_get_gsymbol (sym->module);
+ gsym = gfc_get_gsymbol (sym->module, false);
gsym->type = GSYM_MODULE;
gsym->ns = gfc_get_namespace (NULL, 0);
}
@@ -1865,7 +1894,7 @@ gfc_get_symbol_decl (gfc_symbol * sym)
if (sym->attr.vtab
|| (sym->name[0] == '_' && strncmp ("__def_init", sym->name, 10) == 0))
- TREE_READONLY (decl) = 1;
+ DECL_ARTIFICIAL (decl) = 1;
return decl;
}
@@ -1905,6 +1934,22 @@ get_proc_pointer_decl (gfc_symbol *sym)
tree decl;
tree attributes;
+ if (sym->module || sym->fn_result_spec)
+ {
+ const char *name;
+ gfc_gsymbol *gsym;
+
+ name = mangled_identifier (sym);
+ gsym = gfc_find_gsymbol (gfc_gsym_root, name);
+ if (gsym != NULL)
+ {
+ gfc_symbol *s;
+ gfc_find_symbol (sym->name, gsym->ns, 0, &s);
+ if (s && s->backend_decl)
+ return s->backend_decl;
+ }
+ }
+
decl = sym->backend_decl;
if (decl)
return decl;
@@ -2002,9 +2047,22 @@ gfc_get_extern_function_decl (gfc_symbol * sym, gfc_actual_arglist *actual_args)
return get_proc_pointer_decl (sym);
/* See if this is an external procedure from the same file. If so,
- return the backend_decl. */
- gsym = gfc_find_gsymbol (gfc_gsym_root, sym->binding_label
- ? sym->binding_label : sym->name);
+ return the backend_decl. If we are looking at a BIND(C)
+ procedure and the symbol is not BIND(C), or vice versa, we
+ haven't found the right procedure. */
+
+ if (sym->binding_label)
+ {
+ gsym = gfc_find_gsymbol (gfc_gsym_root, sym->binding_label);
+ if (gsym && !gsym->bind_c)
+ gsym = NULL;
+ }
+ else
+ {
+ gsym = gfc_find_gsymbol (gfc_gsym_root, sym->name);
+ if (gsym && gsym->bind_c)
+ gsym = NULL;
+ }
if (gsym && !gsym->defined)
gsym = NULL;
@@ -2500,6 +2558,17 @@ create_function_arglist (gfc_symbol * sym)
TREE_READONLY (length) = 1;
gfc_finish_decl (length);
+ /* Marking the length DECL_HIDDEN_STRING_LENGTH will lead
+ to tail calls being disabled. Only do that if we
+ potentially have broken callers. */
+ if (flag_tail_call_workaround
+ && f->sym->ts.u.cl
+ && f->sym->ts.u.cl->length
+ && f->sym->ts.u.cl->length->expr_type == EXPR_CONSTANT
+ && (flag_tail_call_workaround == 2
+ || f->sym->ns->implicit_interface_calls))
+ DECL_HIDDEN_STRING_LENGTH (length) = 1;
+
/* Remember the passed value. */
if (!f->sym->ts.u.cl || f->sym->ts.u.cl->passed_length)
{
@@ -5655,9 +5724,11 @@ generate_local_decl (gfc_symbol * sym)
}
else if (warn_unused_dummy_argument)
{
- gfc_warning (OPT_Wunused_dummy_argument,
- "Unused dummy argument %qs at %L", sym->name,
- &sym->declared_at);
+ if (!sym->attr.artificial)
+ gfc_warning (OPT_Wunused_dummy_argument,
+ "Unused dummy argument %qs at %L", sym->name,
+ &sym->declared_at);
+
if (sym->backend_decl != NULL_TREE)
TREE_NO_WARNING(sym->backend_decl) = 1;
}
@@ -5749,7 +5820,14 @@ generate_local_decl (gfc_symbol * sym)
if (sym->ns && sym->ns->construct_entities)
{
- if (sym->attr.referenced)
+ /* Construction of the intrinsic modules within a BLOCK
+ construct, where ONLY and RENAMED entities are included,
+ seems to be bogus. This is a workaround that can be removed
+ if someone ever takes on the task to creating full-fledge
+ modules. See PR 69455. */
+ if (sym->attr.referenced
+ && sym->from_intmod != INTMOD_ISO_C_BINDING
+ && sym->from_intmod != INTMOD_ISO_FORTRAN_ENV)
gfc_get_symbol_decl (sym);
sym->mark = 1;
}