aboutsummaryrefslogtreecommitdiff
path: root/gcc/fortran
diff options
context:
space:
mode:
authorThomas Koenig <tkoenig@gcc.gnu.org>2019-02-18 18:28:58 +0000
committerThomas Koenig <tkoenig@gcc.gnu.org>2019-02-18 18:28:58 +0000
commit378f53c75232416c9171bcfb42a551371321bffe (patch)
treee1b9c5e9aba98b7ee97c1db32ec84d400da32f4e /gcc/fortran
parent7a247605d892747ccc9216ffc047c73bd688ac36 (diff)
downloadgcc-378f53c75232416c9171bcfb42a551371321bffe.zip
gcc-378f53c75232416c9171bcfb42a551371321bffe.tar.gz
gcc-378f53c75232416c9171bcfb42a551371321bffe.tar.bz2
re PR fortran/87689 (PowerPC64 ELFv2 function parameter passing violation)
2019-02-18 Thomas Koenig <tkoenig@gcc.gnu.org> PR fortran/87689 * trans-decl.c (gfc_get_extern_function_decl): Add argument actual_args and pass it through to gfc_get_function_type. * trans-expr.c (conv_function_val): Add argument actual_args and pass it on to gfc_get_extern_function_decl. (conv_procedure_call): Pass actual arguments to conv_function_val. * trans-types.c (get_formal_from_actual_arglist): New function. (gfc_get_function_type): Add argument actual_args. Generate formal args from actual args if necessary. * trans-types.h (gfc_get_function_type): Add optional argument. * trans.h (gfc_get_extern_function_decl): Add optional argument. 2019-02-18 Thomas Koenig <tkoenig@gcc.gnu.org> PR fortran/87689 * gfortran.dg/lto/20091028-1_0.f90: Add -Wno-lto-type-mismatch to options. * gfortran.dg/lto/20091028-2_0.f90: Likewise. * gfortran.dg/lto/pr87689_0.f: New file. * gfortran.dg/lto/pr87689_1.f: New file. From-SVN: r268992
Diffstat (limited to 'gcc/fortran')
-rw-r--r--gcc/fortran/ChangeLog14
-rw-r--r--gcc/fortran/trans-decl.c4
-rw-r--r--gcc/fortran/trans-expr.c7
-rw-r--r--gcc/fortran/trans-types.c51
-rw-r--r--gcc/fortran/trans-types.h2
-rw-r--r--gcc/fortran/trans.h3
6 files changed, 73 insertions, 8 deletions
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index a03cfd2..43eda8c 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,17 @@
+2019-02-18 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR fortran/87689
+ * trans-decl.c (gfc_get_extern_function_decl): Add argument
+ actual_args and pass it through to gfc_get_function_type.
+ * trans-expr.c (conv_function_val): Add argument actual_args
+ and pass it on to gfc_get_extern_function_decl.
+ (conv_procedure_call): Pass actual arguments to conv_function_val.
+ * trans-types.c (get_formal_from_actual_arglist): New function.
+ (gfc_get_function_type): Add argument actual_args. Generate
+ formal args from actual args if necessary.
+ * trans-types.h (gfc_get_function_type): Add optional argument.
+ * trans.h (gfc_get_extern_function_decl): Add optional argument.
+
2019-02-18 Martin Liska <mliska@suse.cz>
* decl.c (gfc_match_gcc_builtin): Add support for filtering
diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c
index 9a8f2d3..3604cfc 100644
--- a/gcc/fortran/trans-decl.c
+++ b/gcc/fortran/trans-decl.c
@@ -1962,7 +1962,7 @@ get_proc_pointer_decl (gfc_symbol *sym)
/* Get a basic decl for an external function. */
tree
-gfc_get_extern_function_decl (gfc_symbol * sym)
+gfc_get_extern_function_decl (gfc_symbol * sym, gfc_actual_arglist *actual_args)
{
tree type;
tree fndecl;
@@ -2135,7 +2135,7 @@ module_sym:
mangled_name = gfc_sym_mangled_function_id (sym);
}
- type = gfc_get_function_type (sym);
+ type = gfc_get_function_type (sym, actual_args);
fndecl = build_decl (input_location,
FUNCTION_DECL, name, type);
diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c
index e7c7591..a75f8a7 100644
--- a/gcc/fortran/trans-expr.c
+++ b/gcc/fortran/trans-expr.c
@@ -3895,7 +3895,8 @@ conv_base_obj_fcn_val (gfc_se * se, tree base_object, gfc_expr * expr)
static void
-conv_function_val (gfc_se * se, gfc_symbol * sym, gfc_expr * expr)
+conv_function_val (gfc_se * se, gfc_symbol * sym, gfc_expr * expr,
+ gfc_actual_arglist *actual_args)
{
tree tmp;
@@ -3913,7 +3914,7 @@ conv_function_val (gfc_se * se, gfc_symbol * sym, gfc_expr * expr)
else
{
if (!sym->backend_decl)
- sym->backend_decl = gfc_get_extern_function_decl (sym);
+ sym->backend_decl = gfc_get_extern_function_decl (sym, actual_args);
TREE_USED (sym->backend_decl) = 1;
@@ -6580,7 +6581,7 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
/* Generate the actual call. */
if (base_object == NULL_TREE)
- conv_function_val (se, sym, expr);
+ conv_function_val (se, sym, expr, args);
else
conv_base_obj_fcn_val (se, base_object, expr);
diff --git a/gcc/fortran/trans-types.c b/gcc/fortran/trans-types.c
index 1302d2a..2115db2 100644
--- a/gcc/fortran/trans-types.c
+++ b/gcc/fortran/trans-types.c
@@ -2970,9 +2970,54 @@ create_fn_spec (gfc_symbol *sym, tree fntype)
return build_type_attribute_variant (fntype, tmp);
}
+/* Helper function - if we do not find an interface for a procedure,
+ construct it from the actual arglist. Luckily, this can only
+ happen for call by reference, so the information we actually need
+ to provide (and which would be impossible to guess from the call
+ itself) is not actually needed. */
+
+static void
+get_formal_from_actual_arglist (gfc_symbol *sym, gfc_actual_arglist *actual_args)
+{
+ gfc_actual_arglist *a;
+ gfc_formal_arglist **f;
+ gfc_symbol *s;
+ char name[GFC_MAX_SYMBOL_LEN + 1];
+ static int var_num;
+
+ f = &sym->formal;
+ for (a = actual_args; a != NULL; a = a->next)
+ {
+ if (a->expr)
+ {
+ (*f) = gfc_get_formal_arglist ();
+ snprintf (name, GFC_MAX_SYMBOL_LEN, "_formal_%d", var_num ++);
+ gfc_get_symbol (name, NULL, &s);
+ if (a->expr->ts.type == BT_PROCEDURE)
+ {
+ s->attr.flavor = FL_PROCEDURE;
+ }
+ else
+ {
+ s->ts = a->expr->ts;
+ s->attr.flavor = FL_VARIABLE;
+ if (a->expr->rank > 0)
+ {
+ s->attr.dimension = 1;
+ s->as = gfc_get_array_spec ();
+ s->as->type = AS_ASSUMED_SIZE;
+ }
+ }
+ s->attr.dummy = 1;
+ s->attr.intent = INTENT_UNKNOWN;
+ (*f)->sym = s;
+ }
+ f = &((*f)->next);
+ }
+}
tree
-gfc_get_function_type (gfc_symbol * sym)
+gfc_get_function_type (gfc_symbol * sym, gfc_actual_arglist *actual_args)
{
tree type;
vec<tree, va_gc> *typelist = NULL;
@@ -3030,6 +3075,10 @@ gfc_get_function_type (gfc_symbol * sym)
vec_safe_push (typelist, build_pointer_type(gfc_charlen_type_node));
}
}
+ if (sym->backend_decl == error_mark_node && actual_args != NULL
+ && sym->formal == NULL && (sym->attr.proc == PROC_EXTERNAL
+ || sym->attr.proc == PROC_UNKNOWN))
+ get_formal_from_actual_arglist (sym, actual_args);
/* Build the argument types for the function. */
for (f = gfc_sym_get_dummy_args (sym); f; f = f->next)
diff --git a/gcc/fortran/trans-types.h b/gcc/fortran/trans-types.h
index 2952d11..7d591ba 100644
--- a/gcc/fortran/trans-types.h
+++ b/gcc/fortran/trans-types.h
@@ -88,7 +88,7 @@ tree gfc_sym_type (gfc_symbol *);
tree gfc_typenode_for_spec (gfc_typespec *, int c = 0);
int gfc_copy_dt_decls_ifequal (gfc_symbol *, gfc_symbol *, bool);
-tree gfc_get_function_type (gfc_symbol *);
+tree gfc_get_function_type (gfc_symbol *, gfc_actual_arglist *args = NULL);
tree gfc_type_for_size (unsigned, int);
tree gfc_type_for_mode (machine_mode, int);
diff --git a/gcc/fortran/trans.h b/gcc/fortran/trans.h
index 805ed76..7d46684 100644
--- a/gcc/fortran/trans.h
+++ b/gcc/fortran/trans.h
@@ -580,7 +580,8 @@ void gfc_merge_block_scope (stmtblock_t * block);
tree gfc_get_label_decl (gfc_st_label *);
/* Return the decl for an external function. */
-tree gfc_get_extern_function_decl (gfc_symbol *);
+tree gfc_get_extern_function_decl (gfc_symbol *,
+ gfc_actual_arglist *args = NULL);
/* Return the decl for a function. */
tree gfc_get_function_decl (gfc_symbol *);