diff options
author | Jerry DeLisle <jvdelisle@gcc.gnu.org> | 2007-11-14 00:59:09 +0000 |
---|---|---|
committer | Jerry DeLisle <jvdelisle@gcc.gnu.org> | 2007-11-14 00:59:09 +0000 |
commit | 6cc309c9234d18f69b2c70ec0220becf3b0f58f5 (patch) | |
tree | c296e0620442c1d321dbe2b55bcada779f15b955 /gcc/fortran/interface.c | |
parent | 7cbb9e290262fc10104e673248332e1a889ac1b4 (diff) | |
download | gcc-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.c | 79 |
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)) |