|
|
3db796 |
From 109b1eeba24e5091bf3bdb6caedf7101a9dcaa6a Mon Sep 17 00:00:00 2001
|
|
|
3db796 |
From: Jim MacArthur <jim.macarthur@codethink.co.uk>
|
|
|
3db796 |
Date: Wed, 18 Nov 2015 11:50:41 +0000
|
|
|
3db796 |
Subject: [PATCH 16/23] Allow calls to intrinsics with smaller types than
|
|
|
3db796 |
specified
|
|
|
3db796 |
|
|
|
3db796 |
This feature is enabled by the `-std=extra-legacy` compiler flag.
|
|
|
3db796 |
---
|
|
|
3db796 |
|
|
|
3db796 |
0016-Allow-calls-to-intrinsics-with-smaller-types-than-sp.patch
|
|
|
3db796 |
|
|
|
3db796 |
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
|
|
|
3db796 |
index a32de3e..e222003 100644
|
|
|
3db796 |
--- a/gcc/fortran/gfortran.h
|
|
|
3db796 |
+++ b/gcc/fortran/gfortran.h
|
|
|
3db796 |
@@ -646,6 +646,8 @@ enum gfc_reverse
|
|
|
3db796 |
GFC_INHIBIT_REVERSE
|
|
|
3db796 |
};
|
|
|
3db796 |
|
|
|
3db796 |
+enum match_type { MATCH_EXACT, MATCH_PROMOTABLE, MATCH_INVALID };
|
|
|
3db796 |
+
|
|
|
3db796 |
/************************* Structures *****************************/
|
|
|
3db796 |
|
|
|
3db796 |
/* Used for keeping things in balanced binary trees. */
|
|
|
3db796 |
@@ -3251,7 +3253,7 @@ bool gfc_add_interface (gfc_symbol *);
|
|
|
3db796 |
gfc_interface *gfc_current_interface_head (void);
|
|
|
3db796 |
void gfc_set_current_interface_head (gfc_interface *);
|
|
|
3db796 |
gfc_symtree* gfc_find_sym_in_symtree (gfc_symbol*);
|
|
|
3db796 |
-bool gfc_arglist_matches_symbol (gfc_actual_arglist**, gfc_symbol*);
|
|
|
3db796 |
+bool gfc_arglist_matches_symbol (gfc_actual_arglist**, gfc_symbol*, enum match_type mtype);
|
|
|
3db796 |
bool gfc_check_operator_interface (gfc_symbol*, gfc_intrinsic_op, locus);
|
|
|
3db796 |
bool gfc_has_vector_subscript (gfc_expr*);
|
|
|
3db796 |
gfc_intrinsic_op gfc_equivalent_op (gfc_intrinsic_op);
|
|
|
3db796 |
diff --git a/gcc/fortran/interface.c b/gcc/fortran/interface.c
|
|
|
3db796 |
index 162f777..fc73e31 100644
|
|
|
3db796 |
--- a/gcc/fortran/interface.c
|
|
|
3db796 |
+++ b/gcc/fortran/interface.c
|
|
|
3db796 |
@@ -682,7 +682,7 @@ gfc_compare_derived_types (gfc_symbol *derived1, gfc_symbol *derived2)
|
|
|
3db796 |
/* Compare two typespecs, recursively if necessary. */
|
|
|
3db796 |
|
|
|
3db796 |
bool
|
|
|
3db796 |
-gfc_compare_types (gfc_typespec *ts1, gfc_typespec *ts2)
|
|
|
3db796 |
+gfc_compare_types_generic (gfc_typespec *ts1, gfc_typespec *ts2, enum match_type mtype)
|
|
|
3db796 |
{
|
|
|
3db796 |
/* See if one of the typespecs is a BT_VOID, which is what is being used
|
|
|
3db796 |
to allow the funcs like c_f_pointer to accept any pointer type.
|
|
|
3db796 |
@@ -721,12 +721,23 @@ gfc_compare_types (gfc_typespec *ts1, gfc_typespec *ts2)
|
|
|
3db796 |
return compare_union_types (ts1->u.derived, ts2->u.derived);
|
|
|
3db796 |
|
|
|
3db796 |
if (ts1->type != BT_DERIVED && ts1->type != BT_CLASS)
|
|
|
3db796 |
- return (ts1->kind == ts2->kind);
|
|
|
3db796 |
+ {
|
|
|
3db796 |
+ if (mtype == MATCH_PROMOTABLE)
|
|
|
3db796 |
+ return (ts1->kind >= ts2->kind);
|
|
|
3db796 |
+ else
|
|
|
3db796 |
+ return (ts1->kind == ts2->kind);
|
|
|
3db796 |
+ }
|
|
|
3db796 |
+
|
|
|
3db796 |
|
|
|
3db796 |
/* Compare derived types. */
|
|
|
3db796 |
return gfc_type_compatible (ts1, ts2);
|
|
|
3db796 |
}
|
|
|
3db796 |
|
|
|
3db796 |
+bool
|
|
|
3db796 |
+gfc_compare_types (gfc_typespec *ts1, gfc_typespec *ts2)
|
|
|
3db796 |
+{
|
|
|
3db796 |
+ return gfc_compare_types_generic (ts1, ts2, MATCH_EXACT);
|
|
|
3db796 |
+}
|
|
|
3db796 |
|
|
|
3db796 |
static bool
|
|
|
3db796 |
compare_type (gfc_symbol *s1, gfc_symbol *s2)
|
|
|
3db796 |
@@ -743,7 +754,9 @@ compare_type (gfc_symbol *s1, gfc_symbol *s2)
|
|
|
3db796 |
return gfc_compare_types (&s1->ts, &s2->ts) || s2->ts.type == BT_ASSUMED;
|
|
|
3db796 |
}
|
|
|
3db796 |
|
|
|
3db796 |
-
|
|
|
3db796 |
+/* Given two symbols that are formal arguments, compare their ranks
|
|
|
3db796 |
+ and types. Returns nonzero if they have the same rank and type,
|
|
|
3db796 |
+ zero otherwise. */
|
|
|
3db796 |
static bool
|
|
|
3db796 |
compare_rank (gfc_symbol *s1, gfc_symbol *s2)
|
|
|
3db796 |
{
|
|
|
3db796 |
@@ -2150,7 +2163,7 @@ argument_rank_mismatch (const char *name, locus *where,
|
|
|
3db796 |
|
|
|
3db796 |
static bool
|
|
|
3db796 |
compare_parameter (gfc_symbol *formal, gfc_expr *actual,
|
|
|
3db796 |
- int ranks_must_agree, int is_elemental, locus *where)
|
|
|
3db796 |
+ int ranks_must_agree, int is_elemental, locus *where, enum match_type mtype)
|
|
|
3db796 |
{
|
|
|
3db796 |
gfc_ref *ref;
|
|
|
3db796 |
bool rank_check, is_pointer;
|
|
|
3db796 |
@@ -2242,7 +2255,7 @@ compare_parameter (gfc_symbol *formal, gfc_expr *actual,
|
|
|
3db796 |
&& actual->ts.type != BT_HOLLERITH
|
|
|
3db796 |
&& formal->ts.type != BT_ASSUMED
|
|
|
3db796 |
&& !(formal->attr.ext_attr & (1 << EXT_ATTR_NO_ARG_CHECK))
|
|
|
3db796 |
- && !gfc_compare_types (&formal->ts, &actual->ts)
|
|
|
3db796 |
+ && !gfc_compare_types_generic (&formal->ts, &actual->ts, mtype)
|
|
|
3db796 |
&& !(formal->ts.type == BT_DERIVED && actual->ts.type == BT_CLASS
|
|
|
3db796 |
&& gfc_compare_derived_types (formal->ts.u.derived,
|
|
|
3db796 |
CLASS_DATA (actual)->ts.u.derived)))
|
|
|
3db796 |
@@ -2792,7 +2805,8 @@ is_procptr_result (gfc_expr *expr)
|
|
|
3db796 |
static bool
|
|
|
3db796 |
compare_actual_formal (gfc_actual_arglist **ap, gfc_formal_arglist *formal,
|
|
|
3db796 |
int ranks_must_agree, int is_elemental,
|
|
|
3db796 |
- bool in_statement_function, locus *where)
|
|
|
3db796 |
+ bool in_statement_function, locus *where,
|
|
|
3db796 |
+ enum match_type mtype)
|
|
|
3db796 |
{
|
|
|
3db796 |
gfc_actual_arglist **new_arg, *a, *actual;
|
|
|
3db796 |
gfc_formal_arglist *f;
|
|
|
3db796 |
@@ -2918,7 +2932,7 @@ compare_actual_formal (gfc_actual_arglist **ap, gfc_formal_arglist *formal,
|
|
|
3db796 |
}
|
|
|
3db796 |
|
|
|
3db796 |
if (!compare_parameter (f->sym, a->expr, ranks_must_agree,
|
|
|
3db796 |
- is_elemental, where))
|
|
|
3db796 |
+ is_elemental, where, mtype))
|
|
|
3db796 |
return false;
|
|
|
3db796 |
|
|
|
3db796 |
/* TS 29113, 6.3p2. */
|
|
|
3db796 |
@@ -3666,7 +3680,8 @@ gfc_procedure_use (gfc_symbol *sym, gfc_actual_arglist **ap, locus *where)
|
|
|
3db796 |
/* For a statement function, check that types and type parameters of actual
|
|
|
3db796 |
arguments and dummy arguments match. */
|
|
|
3db796 |
if (!compare_actual_formal (ap, dummy_args, 0, sym->attr.elemental,
|
|
|
3db796 |
- sym->attr.proc == PROC_ST_FUNCTION, where))
|
|
|
3db796 |
+ sym->attr.proc == PROC_ST_FUNCTION, where,
|
|
|
3db796 |
+ MATCH_PROMOTABLE))
|
|
|
3db796 |
return false;
|
|
|
3db796 |
|
|
|
3db796 |
if (!check_intents (dummy_args, *ap))
|
|
|
3db796 |
@@ -3715,7 +3730,8 @@ gfc_ppc_use (gfc_component *comp, gfc_actual_arglist **ap, locus *where)
|
|
|
3db796 |
}
|
|
|
3db796 |
|
|
|
3db796 |
if (!compare_actual_formal (ap, comp->ts.interface->formal, 0,
|
|
|
3db796 |
- comp->attr.elemental, false, where))
|
|
|
3db796 |
+ comp->attr.elemental, false, where,
|
|
|
3db796 |
+ MATCH_EXACT))
|
|
|
3db796 |
return;
|
|
|
3db796 |
|
|
|
3db796 |
check_intents (comp->ts.interface->formal, *ap);
|
|
|
3db796 |
@@ -3729,7 +3745,7 @@ gfc_ppc_use (gfc_component *comp, gfc_actual_arglist **ap, locus *where)
|
|
|
3db796 |
GENERIC resolution. */
|
|
|
3db796 |
|
|
|
3db796 |
bool
|
|
|
3db796 |
-gfc_arglist_matches_symbol (gfc_actual_arglist** args, gfc_symbol* sym)
|
|
|
3db796 |
+gfc_arglist_matches_symbol (gfc_actual_arglist** args, gfc_symbol* sym, enum match_type mtype)
|
|
|
3db796 |
{
|
|
|
3db796 |
gfc_formal_arglist *dummy_args;
|
|
|
3db796 |
bool r;
|
|
|
3db796 |
@@ -3740,7 +3756,7 @@ gfc_arglist_matches_symbol (gfc_actual_arglist** args, gfc_symbol* sym)
|
|
|
3db796 |
dummy_args = gfc_sym_get_dummy_args (sym);
|
|
|
3db796 |
|
|
|
3db796 |
r = !sym->attr.elemental;
|
|
|
3db796 |
- if (compare_actual_formal (args, dummy_args, r, !r, false, NULL))
|
|
|
3db796 |
+ if (compare_actual_formal (args, dummy_args, r, !r, false, NULL, mtype))
|
|
|
3db796 |
{
|
|
|
3db796 |
check_intents (dummy_args, *args);
|
|
|
3db796 |
if (warn_aliasing)
|
|
|
3db796 |
@@ -3766,7 +3782,8 @@ gfc_search_interface (gfc_interface *intr, int sub_flag,
|
|
|
3db796 |
locus null_expr_loc;
|
|
|
3db796 |
gfc_actual_arglist *a;
|
|
|
3db796 |
bool has_null_arg = false;
|
|
|
3db796 |
-
|
|
|
3db796 |
+ enum match_type mtypes[] = { MATCH_EXACT, MATCH_PROMOTABLE };
|
|
|
3db796 |
+ int i;
|
|
|
3db796 |
for (a = *ap; a; a = a->next)
|
|
|
3db796 |
if (a->expr && a->expr->expr_type == EXPR_NULL
|
|
|
3db796 |
&& a->expr->ts.type == BT_UNKNOWN)
|
|
|
3db796 |
@@ -3776,38 +3793,43 @@ gfc_search_interface (gfc_interface *intr, int sub_flag,
|
|
|
3db796 |
break;
|
|
|
3db796 |
}
|
|
|
3db796 |
|
|
|
3db796 |
- for (; intr; intr = intr->next)
|
|
|
3db796 |
+ for (i = 0; i < 2; i++)
|
|
|
3db796 |
{
|
|
|
3db796 |
- if (gfc_fl_struct (intr->sym->attr.flavor))
|
|
|
3db796 |
- continue;
|
|
|
3db796 |
- if (sub_flag && intr->sym->attr.function)
|
|
|
3db796 |
- continue;
|
|
|
3db796 |
- if (!sub_flag && intr->sym->attr.subroutine)
|
|
|
3db796 |
- continue;
|
|
|
3db796 |
-
|
|
|
3db796 |
- if (gfc_arglist_matches_symbol (ap, intr->sym))
|
|
|
3db796 |
+ for (; intr; intr = intr->next)
|
|
|
3db796 |
{
|
|
|
3db796 |
- if (has_null_arg && null_sym)
|
|
|
3db796 |
- {
|
|
|
3db796 |
- gfc_error ("MOLD= required in NULL() argument at %L: Ambiguity "
|
|
|
3db796 |
- "between specific functions %s and %s",
|
|
|
3db796 |
- &null_expr_loc, null_sym->name, intr->sym->name);
|
|
|
3db796 |
- return NULL;
|
|
|
3db796 |
- }
|
|
|
3db796 |
- else if (has_null_arg)
|
|
|
3db796 |
- {
|
|
|
3db796 |
- null_sym = intr->sym;
|
|
|
3db796 |
- continue;
|
|
|
3db796 |
- }
|
|
|
3db796 |
+ if (intr->sym->attr.flavor == FL_DERIVED)
|
|
|
3db796 |
+ continue;
|
|
|
3db796 |
+ if (gfc_fl_struct (intr->sym->attr.flavor))
|
|
|
3db796 |
+ continue;
|
|
|
3db796 |
+ if (sub_flag && intr->sym->attr.function)
|
|
|
3db796 |
+ continue;
|
|
|
3db796 |
+ if (!sub_flag && intr->sym->attr.subroutine)
|
|
|
3db796 |
+ continue;
|
|
|
3db796 |
|
|
|
3db796 |
- /* Satisfy 12.4.4.1 such that an elemental match has lower
|
|
|
3db796 |
- weight than a non-elemental match. */
|
|
|
3db796 |
- if (intr->sym->attr.elemental)
|
|
|
3db796 |
+ if (gfc_arglist_matches_symbol (ap, intr->sym, mtypes[i]))
|
|
|
3db796 |
{
|
|
|
3db796 |
- elem_sym = intr->sym;
|
|
|
3db796 |
- continue;
|
|
|
3db796 |
+ if (has_null_arg && null_sym)
|
|
|
3db796 |
+ {
|
|
|
3db796 |
+ gfc_error ("MOLD= required in NULL() argument at %L: Ambiguity "
|
|
|
3db796 |
+ "between specific functions %s and %s",
|
|
|
3db796 |
+ &null_expr_loc, null_sym->name, intr->sym->name);
|
|
|
3db796 |
+ return NULL;
|
|
|
3db796 |
+ }
|
|
|
3db796 |
+ else if (has_null_arg)
|
|
|
3db796 |
+ {
|
|
|
3db796 |
+ null_sym = intr->sym;
|
|
|
3db796 |
+ continue;
|
|
|
3db796 |
+ }
|
|
|
3db796 |
+
|
|
|
3db796 |
+ /* Satisfy 12.4.4.1 such that an elemental match has lower
|
|
|
3db796 |
+ weight than a non-elemental match. */
|
|
|
3db796 |
+ if (intr->sym->attr.elemental)
|
|
|
3db796 |
+ {
|
|
|
3db796 |
+ elem_sym = intr->sym;
|
|
|
3db796 |
+ continue;
|
|
|
3db796 |
+ }
|
|
|
3db796 |
+ return intr->sym;
|
|
|
3db796 |
}
|
|
|
3db796 |
- return intr->sym;
|
|
|
3db796 |
}
|
|
|
3db796 |
}
|
|
|
3db796 |
|
|
|
3db796 |
@@ -3942,7 +3964,7 @@ matching_typebound_op (gfc_expr** tb_base,
|
|
|
3db796 |
|
|
|
3db796 |
/* Check if this arglist matches the formal. */
|
|
|
3db796 |
argcopy = gfc_copy_actual_arglist (args);
|
|
|
3db796 |
- matches = gfc_arglist_matches_symbol (&argcopy, target);
|
|
|
3db796 |
+ matches = gfc_arglist_matches_symbol (&argcopy, target, MATCH_EXACT);
|
|
|
3db796 |
gfc_free_actual_arglist (argcopy);
|
|
|
3db796 |
|
|
|
3db796 |
/* Return if we found a match. */
|
|
|
3db796 |
diff --git a/gcc/fortran/intrinsic.c b/gcc/fortran/intrinsic.c
|
|
|
3db796 |
index 371f5b8..846492a 100644
|
|
|
3db796 |
--- a/gcc/fortran/intrinsic.c
|
|
|
3db796 |
+++ b/gcc/fortran/intrinsic.c
|
|
|
3db796 |
@@ -4229,6 +4229,16 @@ check_arglist (gfc_actual_arglist **ap, gfc_intrinsic_sym *sym,
|
|
|
3db796 |
if (ts.kind == 0)
|
|
|
3db796 |
ts.kind = actual->expr->ts.kind;
|
|
|
3db796 |
|
|
|
3db796 |
+ /* ts.kind is the argument spec. actual is what was passed. */
|
|
|
3db796 |
+
|
|
|
3db796 |
+ if (actual->expr->ts.kind < ts.kind
|
|
|
3db796 |
+ && ts.type == BT_INTEGER)
|
|
|
3db796 |
+ {
|
|
|
3db796 |
+ /* If it was OK to overwrite ts.kind in the previous case, it
|
|
|
3db796 |
+ should be fine here... */
|
|
|
3db796 |
+ ts.kind = actual->expr->ts.kind;
|
|
|
3db796 |
+ }
|
|
|
3db796 |
+
|
|
|
3db796 |
if (!gfc_compare_types (&ts, &actual->expr->ts))
|
|
|
3db796 |
{
|
|
|
3db796 |
if (error_flag)
|
|
|
3db796 |
diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c
|
|
|
3db796 |
index 33b441a..f82c298 100644
|
|
|
3db796 |
--- a/gcc/fortran/resolve.c
|
|
|
3db796 |
+++ b/gcc/fortran/resolve.c
|
|
|
3db796 |
@@ -6055,7 +6055,7 @@ resolve_typebound_generic_call (gfc_expr* e, const char **name)
|
|
|
3db796 |
&& gfc_sym_get_dummy_args (target) == NULL);
|
|
|
3db796 |
|
|
|
3db796 |
/* Check if this arglist matches the formal. */
|
|
|
3db796 |
- matches = gfc_arglist_matches_symbol (&args, target);
|
|
|
3db796 |
+ matches = gfc_arglist_matches_symbol (&args, target, MATCH_EXACT);
|
|
|
3db796 |
|
|
|
3db796 |
/* Clean up and break out of the loop if we've found it. */
|
|
|
3db796 |
gfc_free_actual_arglist (args);
|