aboutsummaryrefslogtreecommitdiff
path: root/gcc/fortran/interface.c
diff options
context:
space:
mode:
authorJerry DeLisle <jvdelisle@gcc.gnu.org>2007-11-14 00:59:09 +0000
committerJerry DeLisle <jvdelisle@gcc.gnu.org>2007-11-14 00:59:09 +0000
commit6cc309c9234d18f69b2c70ec0220becf3b0f58f5 (patch)
treec296e0620442c1d321dbe2b55bcada779f15b955 /gcc/fortran/interface.c
parent7cbb9e290262fc10104e673248332e1a889ac1b4 (diff)
downloadgcc-6cc309c9234d18f69b2c70ec0220becf3b0f58f5.zip
gcc-6cc309c9234d18f69b2c70ec0220becf3b0f58f5.tar.gz
gcc-6cc309c9234d18f69b2c70ec0220becf3b0f58f5.tar.bz2
re PR fortran/33162 (INTRINSIC functions as ACTUAL argument)
2007-11-11 Jerry DeLisle <jvdelisle@gcc.gnu.org> PR fortran/33162 * decl.c (match_procedure_decl): Remove TODO and allow intrinsics in PROCEDURE declarations. Set attr.untyped to allow the interface to be resolved later where the symbol type will be set. * interface.c (compare_intr_interfaces): Remove static from pointer declarations. Add type and kind checks for dummy function arguments. (compare_actual_formal_intr): New function to compare an actual argument with an intrinsic function. (gfc_procedures_use): Add check for interface that points to an intrinsic function, use the new function. * resolve.c (resolve_specific_f0): Resolve the intrinsic interface. (resolve_specific_s0): Ditto. From-SVN: r130168
Diffstat (limited to 'gcc/fortran/interface.c')
-rw-r--r--gcc/fortran/interface.c79
1 files changed, 77 insertions, 2 deletions
diff --git a/gcc/fortran/interface.c b/gcc/fortran/interface.c
index 7f6406a..650cd21 100644
--- a/gcc/fortran/interface.c
+++ b/gcc/fortran/interface.c
@@ -977,13 +977,25 @@ compare_interfaces (gfc_symbol *s1, gfc_symbol *s2, int generic_flag)
static int
compare_intr_interfaces (gfc_symbol *s1, gfc_symbol *s2)
{
- static gfc_formal_arglist *f, *f1;
- static gfc_intrinsic_arg *fi, *f2;
+ gfc_formal_arglist *f, *f1;
+ gfc_intrinsic_arg *fi, *f2;
gfc_intrinsic_sym *isym;
if (s1->attr.function != s2->attr.function
|| s1->attr.subroutine != s2->attr.subroutine)
return 0; /* Disagreement between function/subroutine. */
+
+ /* If the arguments are functions, check type and kind. */
+
+ if (s1->attr.dummy && s1->attr.function && s2->attr.function)
+ {
+ if (s1->ts.type != s2->ts.type)
+ return 0;
+ if (s1->ts.kind != s2->ts.kind)
+ return 0;
+ if (s1->attr.if_source == IFSRC_DECL)
+ return 1;
+ }
isym = gfc_find_function (s2->name);
@@ -1024,6 +1036,55 @@ compare_intr_interfaces (gfc_symbol *s1, gfc_symbol *s2)
}
+/* Compare an actual argument list with an intrinsic argument list. */
+
+static int
+compare_actual_formal_intr (gfc_actual_arglist **ap, gfc_symbol *s2)
+{
+ gfc_actual_arglist *a;
+ gfc_intrinsic_arg *fi, *f2;
+ gfc_intrinsic_sym *isym;
+
+ isym = gfc_find_function (s2->name);
+
+ /* This should already have been checked in
+ resolve.c (resolve_actual_arglist). */
+ gcc_assert (isym);
+
+ f2 = isym->formal;
+
+ /* Special case. */
+ if (*ap == NULL && f2 == NULL)
+ return 1;
+
+ /* First scan through the actual argument list and check the intrinsic. */
+ fi = f2;
+ for (a = *ap; a; a = a->next)
+ {
+ if (fi == NULL)
+ return 0;
+ if ((fi->ts.type != a->expr->ts.type)
+ || (fi->ts.kind != a->expr->ts.kind))
+ return 0;
+ fi = fi->next;
+ }
+
+ /* Now scan through the intrinsic argument list and check the formal. */
+ a = *ap;
+ for (fi = f2; fi; fi = fi->next)
+ {
+ if (a == NULL)
+ return 0;
+ if ((fi->ts.type != a->expr->ts.type)
+ || (fi->ts.kind != a->expr->ts.kind))
+ return 0;
+ a = a->next;
+ }
+
+ return 1;
+}
+
+
/* Given a pointer to an interface pointer, remove duplicate
interfaces and make sure that all symbols are either functions or
subroutines. Returns nonzero if something goes wrong. */
@@ -2225,6 +2286,20 @@ gfc_procedure_use (gfc_symbol *sym, gfc_actual_arglist **ap, locus *where)
gfc_warning ("Procedure '%s' called with an implicit interface at %L",
sym->name, where);
+ if (sym->interface && sym->interface->attr.intrinsic)
+ {
+ gfc_intrinsic_sym *isym;
+ isym = gfc_find_function (sym->interface->name);
+ if (isym != NULL)
+ {
+ if (compare_actual_formal_intr (ap, sym->interface))
+ return;
+ gfc_error ("Type/rank mismatch in argument '%s' at %L",
+ sym->name, where);
+ return;
+ }
+ }
+
if (sym->attr.if_source == IFSRC_UNKNOWN
|| !compare_actual_formal (ap, sym->formal, 0,
sym->attr.elemental, where))