diff options
author | Janus Weil <janus@gcc.gnu.org> | 2012-07-31 20:32:41 +0200 |
---|---|---|
committer | Janus Weil <janus@gcc.gnu.org> | 2012-07-31 20:32:41 +0200 |
commit | 0e8d854eb8bbfc44c1fd9d2fa6e07514d2932e0e (patch) | |
tree | 9616650ee31fffec962f6770ab78c4b7b3506558 /gcc | |
parent | ab6d55ef6209019d4268546aa030928b72f59b49 (diff) | |
download | gcc-0e8d854eb8bbfc44c1fd9d2fa6e07514d2932e0e.zip gcc-0e8d854eb8bbfc44c1fd9d2fa6e07514d2932e0e.tar.gz gcc-0e8d854eb8bbfc44c1fd9d2fa6e07514d2932e0e.tar.bz2 |
re PR fortran/42418 (PROCEDURE: Rejects interface which is both specific and generic procedure)
2012-07-31 Janus Weil <janus@gcc.gnu.org>
PR fortran/42418
* decl.c (match_procedure_interface): Move some checks to
'resolve_procedure_interface'. Set flavor if appropriate.
* expr.c (gfc_check_pointer_assign): Cleanup of 'gfc_is_intrinsic'.
* intrinsic.c (gfc_is_intrinsic): Additional checks for attributes which
identify a procedure as being non-intrinsic.
* resolve.c (resolve_procedure_interface): Checks moved here from
'match_procedure_interface'. Minor cleanup.
(resolve_formal_arglist,resolve_symbol): Cleanup of
'resolve_procedure_interface'
(resolve_actual_arglist,is_external_proc): Cleanup of
'gfc_is_intrinsic'.
2012-07-31 Janus Weil <janus@gcc.gnu.org>
PR fortran/42418
* gfortran.dg/proc_decl_29.f90: New.
From-SVN: r190017
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/fortran/ChangeLog | 15 | ||||
-rw-r--r-- | gcc/fortran/decl.c | 33 | ||||
-rw-r--r-- | gcc/fortran/expr.c | 2 | ||||
-rw-r--r-- | gcc/fortran/intrinsic.c | 13 | ||||
-rw-r--r-- | gcc/fortran/resolve.c | 65 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gfortran.dg/proc_decl_29.f90 | 30 |
7 files changed, 111 insertions, 52 deletions
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 7eb4db4..08dce7f 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,5 +1,20 @@ 2012-07-31 Janus Weil <janus@gcc.gnu.org> + PR fortran/42418 + * decl.c (match_procedure_interface): Move some checks to + 'resolve_procedure_interface'. Set flavor if appropriate. + * expr.c (gfc_check_pointer_assign): Cleanup of 'gfc_is_intrinsic'. + * intrinsic.c (gfc_is_intrinsic): Additional checks for attributes which + identify a procedure as being non-intrinsic. + * resolve.c (resolve_procedure_interface): Checks moved here from + 'match_procedure_interface'. Minor cleanup. + (resolve_formal_arglist,resolve_symbol): Cleanup of + 'resolve_procedure_interface' + (resolve_actual_arglist,is_external_proc): Cleanup of + 'gfc_is_intrinsic'. + +2012-07-31 Janus Weil <janus@gcc.gnu.org> + PR fortran/54134 * dependency.c (gfc_dep_compare_expr): Check if arguments are NULL. diff --git a/gcc/fortran/decl.c b/gcc/fortran/decl.c index 39c0493..083326e 100644 --- a/gcc/fortran/decl.c +++ b/gcc/fortran/decl.c @@ -4792,41 +4792,20 @@ match_procedure_interface (gfc_symbol **proc_if) gfc_current_ns = old_ns; *proc_if = st->n.sym; - /* Various interface checks. */ if (*proc_if) { (*proc_if)->refs++; /* Resolve interface if possible. That way, attr.procedure is only set if it is declared by a later procedure-declaration-stmt, which is - invalid per C1212. */ + invalid per F08:C1216 (cf. resolve_procedure_interface). */ while ((*proc_if)->ts.interface) *proc_if = (*proc_if)->ts.interface; - if ((*proc_if)->generic) - { - gfc_error ("Interface '%s' at %C may not be generic", - (*proc_if)->name); - return MATCH_ERROR; - } - if ((*proc_if)->attr.proc == PROC_ST_FUNCTION) - { - gfc_error ("Interface '%s' at %C may not be a statement function", - (*proc_if)->name); - return MATCH_ERROR; - } - /* Handle intrinsic procedures. */ - if (!((*proc_if)->attr.external || (*proc_if)->attr.use_assoc - || (*proc_if)->attr.if_source == IFSRC_IFBODY) - && (gfc_is_intrinsic ((*proc_if), 0, gfc_current_locus) - || gfc_is_intrinsic ((*proc_if), 1, gfc_current_locus))) - (*proc_if)->attr.intrinsic = 1; - if ((*proc_if)->attr.intrinsic - && !gfc_intrinsic_actual_ok ((*proc_if)->name, 0)) - { - gfc_error ("Intrinsic procedure '%s' not allowed " - "in PROCEDURE statement at %C", (*proc_if)->name); - return MATCH_ERROR; - } + if ((*proc_if)->attr.flavor == FL_UNKNOWN + && (*proc_if)->ts.type == BT_UNKNOWN + && gfc_add_flavor (&(*proc_if)->attr, FL_PROCEDURE, + (*proc_if)->name, NULL) == FAILURE) + return MATCH_ERROR; } got_ts: diff --git a/gcc/fortran/expr.c b/gcc/fortran/expr.c index f43bc6f..3a3ba9a 100644 --- a/gcc/fortran/expr.c +++ b/gcc/fortran/expr.c @@ -3426,8 +3426,6 @@ gfc_check_pointer_assign (gfc_expr *lvalue, gfc_expr *rvalue) /* Check for intrinsics. */ gfc_symbol *sym = rvalue->symtree->n.sym; if (!sym->attr.intrinsic - && !(sym->attr.contained || sym->attr.use_assoc - || sym->attr.external || sym->attr.if_source == IFSRC_IFBODY) && (gfc_is_intrinsic (sym, 0, sym->declared_at) || gfc_is_intrinsic (sym, 1, sym->declared_at))) { diff --git a/gcc/fortran/intrinsic.c b/gcc/fortran/intrinsic.c index dbfadb4..60c68fe 100644 --- a/gcc/fortran/intrinsic.c +++ b/gcc/fortran/intrinsic.c @@ -902,9 +902,9 @@ gfc_intrinsic_actual_ok (const char *name, const bool subroutine_flag) } -/* Given a symbol, find out if it is (and is to be treated) an intrinsic. If - it's name refers to an intrinsic but this intrinsic is not included in the - selected standard, this returns FALSE and sets the symbol's external +/* Given a symbol, find out if it is (and is to be treated as) an intrinsic. + If its name refers to an intrinsic, but this intrinsic is not included in + the selected standard, this returns FALSE and sets the symbol's external attribute. */ bool @@ -913,10 +913,13 @@ gfc_is_intrinsic (gfc_symbol* sym, int subroutine_flag, locus loc) gfc_intrinsic_sym* isym; const char* symstd; - /* If INTRINSIC/EXTERNAL state is already known, return. */ + /* If INTRINSIC attribute is already known, return. */ if (sym->attr.intrinsic) return true; - if (sym->attr.external) + + /* Check for attributes which prevent the symbol from being INTRINSIC. */ + if (sym->attr.external || sym->attr.contained + || sym->attr.if_source == IFSRC_IFBODY) return false; if (subroutine_flag) diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c index dcce3f5..a6dd0da 100644 --- a/gcc/fortran/resolve.c +++ b/gcc/fortran/resolve.c @@ -146,24 +146,58 @@ static void resolve_symbol (gfc_symbol *sym); static gfc_try resolve_procedure_interface (gfc_symbol *sym) { - if (sym->ts.interface == sym) + gfc_symbol *ifc = sym->ts.interface; + + if (!ifc) + return SUCCESS; + + /* Several checks for F08:C1216. */ + if (ifc == sym) { gfc_error ("PROCEDURE '%s' at %L may not be used as its own interface", sym->name, &sym->declared_at); return FAILURE; } - if (sym->ts.interface->attr.procedure) + if (ifc->attr.procedure) { gfc_error ("Interface '%s', used by procedure '%s' at %L, is declared " - "in a later PROCEDURE statement", sym->ts.interface->name, + "in a later PROCEDURE statement", ifc->name, sym->name, &sym->declared_at); return FAILURE; } + if (ifc->generic) + { + /* For generic interfaces, check if there is + a specific procedure with the same name. */ + gfc_interface *gen = ifc->generic; + while (gen && strcmp (gen->sym->name, ifc->name) != 0) + gen = gen->next; + if (!gen) + { + gfc_error ("Interface '%s' at %L may not be generic", + ifc->name, &sym->declared_at); + return FAILURE; + } + } + if (ifc->attr.proc == PROC_ST_FUNCTION) + { + gfc_error ("Interface '%s' at %L may not be a statement function", + ifc->name, &sym->declared_at); + return FAILURE; + } + if (gfc_is_intrinsic (ifc, 0, ifc->declared_at) + || gfc_is_intrinsic (ifc, 1, ifc->declared_at)) + ifc->attr.intrinsic = 1; + if (ifc->attr.intrinsic && !gfc_intrinsic_actual_ok (ifc->name, 0)) + { + gfc_error ("Intrinsic procedure '%s' not allowed in " + "PROCEDURE statement at %L", ifc->name, &sym->declared_at); + return FAILURE; + } /* Get the attributes from the interface (now resolved). */ - if (sym->ts.interface->attr.if_source || sym->ts.interface->attr.intrinsic) + if (ifc->attr.if_source || ifc->attr.intrinsic) { - gfc_symbol *ifc = sym->ts.interface; resolve_symbol (ifc); if (ifc->attr.intrinsic) @@ -212,10 +246,10 @@ resolve_procedure_interface (gfc_symbol *sym) return FAILURE; } } - else if (sym->ts.interface->name[0] != '\0') + else if (ifc->name[0] != '\0') { gfc_error ("Interface '%s' of procedure '%s' at %L must be explicit", - sym->ts.interface->name, sym->name, &sym->declared_at); + ifc->name, sym->name, &sym->declared_at); return FAILURE; } @@ -273,9 +307,9 @@ resolve_formal_arglist (gfc_symbol *proc) &proc->declared_at); continue; } - else if (sym->attr.procedure && sym->ts.interface - && sym->attr.if_source != IFSRC_DECL) - resolve_procedure_interface (sym); + else if (sym->attr.procedure && sym->attr.if_source != IFSRC_DECL + && resolve_procedure_interface (sym) == FAILURE) + return; if (sym->attr.if_source != IFSRC_UNKNOWN) resolve_formal_arglist (sym); @@ -1672,10 +1706,7 @@ resolve_actual_arglist (gfc_actual_arglist *arg, procedure_type ptype, /* If a procedure is not already determined to be something else check if it is intrinsic. */ - if (!sym->attr.intrinsic - && !(sym->attr.external || sym->attr.use_assoc - || sym->attr.if_source == IFSRC_IFBODY) - && gfc_is_intrinsic (sym, sym->attr.subroutine, e->where)) + if (gfc_is_intrinsic (sym, sym->attr.subroutine, e->where)) sym->attr.intrinsic = 1; if (sym->attr.proc == PROC_ST_FUNCTION) @@ -2601,8 +2632,7 @@ static bool is_external_proc (gfc_symbol *sym) { if (!sym->attr.dummy && !sym->attr.contained - && !(sym->attr.intrinsic - || gfc_is_intrinsic (sym, sym->attr.subroutine, sym->declared_at)) + && !gfc_is_intrinsic (sym, sym->attr.subroutine, sym->declared_at) && sym->attr.proc != PROC_ST_FUNCTION && !sym->attr.proc_pointer && !sym->attr.use_assoc @@ -12516,8 +12546,7 @@ resolve_symbol (gfc_symbol *sym) if (sym->attr.external && sym->ts.type != BT_UNKNOWN && !sym->attr.function) gfc_add_function (&sym->attr, sym->name, &sym->declared_at); - if (sym->attr.procedure && sym->ts.interface - && sym->attr.if_source != IFSRC_DECL + if (sym->attr.procedure && sym->attr.if_source != IFSRC_DECL && resolve_procedure_interface (sym) == FAILURE) return; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 00c8b70..e210d00 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2012-07-31 Janus Weil <janus@gcc.gnu.org> + + PR fortran/42418 + * gfortran.dg/proc_decl_29.f90: New. + 2012-07-31 Dehao Chen <dehao@google.com> * gcc.dg/predict-7.c: New test. diff --git a/gcc/testsuite/gfortran.dg/proc_decl_29.f90 b/gcc/testsuite/gfortran.dg/proc_decl_29.f90 new file mode 100644 index 0000000..6a92118 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/proc_decl_29.f90 @@ -0,0 +1,30 @@ +! { dg-do compile } +! +! PR 42418: PROCEDURE: Rejects interface which is both specific and generic procedure +! +! Contributed by Tobias Burnus <burnus@gcc.gnu.org> + + interface gen + procedure gen + end interface + + procedure(gen) :: p1 + procedure(gen2) :: p2 ! { dg-error "may not be generic" } + procedure(sf) :: p3 ! { dg-error "may not be a statement function" } + procedure(char) :: p4 + + interface gen2 + procedure char + end interface + + sf(x) = x**2 ! { dg-warning "Obsolescent feature" } + +contains + + subroutine gen + end subroutine + + subroutine char + end subroutine + +end |