This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [gfortran] restrictions on recursive procedures
François-Xavier,
:REVIEWMAIL:
That's correct; I had to look up who gets to be declared RECURSIVE. I
had never encountered such a thing as a recursive procedure with
multiple entries and would not like to meet one in the dark!
For those that are curious, this is what I found in the standard:
12.5.2.2 Function subprogram
....snip....
The prefix-spec RECURSIVE shall be present if the function directly or indirectly invokes itself or a
function defined by an ENTRY statement in the same subprogram. Similarly, RECURSIVE shall be
present if a function defined by an ENTRY statement in the subprogram directly or indirectly
invokes itself, another function defined by an ENTRY statement in that subprogram, or the
function defined by the FUNCTION statement.
12.5.2.3 Subroutine subprogram
....snip....
says the same as for functions
12.5.2.5 ENTRY statement
....snip....
The keyword RECURSIVE is not used in an ENTRY statement. Instead, the presence or absence of
RECURSIVE in the initial SUBROUTINE or FUNCTION statement controls whether the procedure
defined by an ENTRY statement is permitted to reference itself.
I need to think about various of the conditions that you apply before
okaying this patch; I think that it is sufficient (and necessary?) to
check that the namespaces are the same and that one of them has entries.
This suggestion was very bad in that it causes a goodly number of
regressions. Thus, your patch, slightly spruced up (in the eyes of this
beholder, at least) has the day - please see the attached, which
regtests on FC5/Athlon1700. In addition, I request that you either
incorporate the following test in the existing one, changing it to f90
of course, or commit it as an extra. (I have to admit I was surprised to
begin with that it works correctly!)
! { dg-do compile }
! PR fortran/26551
function func2()
integer func2
func2 = 42
return
entry c() result (foo)
foo = barbar()
return
entry b() result (bar)
bar = 12
return
contains
function barbar ()
barbar = b () ! { dg-error "is not declared as RECURSIVE" }
end function barbar
end function
OK to commit.
Many thanks!
Paul
Index: gcc/fortran/resolve.c
===================================================================
*** gcc/fortran/resolve.c (revision 113673)
--- gcc/fortran/resolve.c (working copy)
*************** resolve_function (gfc_expr * expr)
*** 1377,1382 ****
--- 1377,1406 ----
}
}
+ /* Functions without the RECURSIVE attribution are not allowed to
+ * call themselves. */
+ if (expr->value.function.esym && !expr->value.function.esym->attr.recursive)
+ {
+ gfc_symbol *esym, *proc;
+ esym = expr->value.function.esym;
+ proc = gfc_current_ns->proc_name;
+ if (esym == proc)
+ {
+ gfc_error ("Function '%s' at %L cannot call itself, as it is not "
+ "RECURSIVE", name, &expr->where);
+ t = FAILURE;
+ }
+
+ if (esym->attr.entry && esym->ns->entries && proc->ns->entries
+ && esym->ns->entries->sym == proc->ns->entries->sym)
+ {
+ gfc_error ("Call to ENTRY '%s' at %L is recursive, but function "
+ "'%s' is not declared as RECURSIVE",
+ esym->name, &expr->where, esym->ns->entries->sym->name);
+ t = FAILURE;
+ }
+ }
+
/* Character lengths of use associated functions may contains references to
symbols not referenced from the current program unit otherwise. Make sure
those symbols are marked as referenced. */
*************** resolve_call (gfc_code * c)
*** 1626,1631 ****
--- 1650,1679 ----
&& !c->symtree->n.sym->attr.use_assoc)
resolve_global_procedure (c->symtree->n.sym, &c->loc, 1);
+ /* Subroutines without the RECURSIVE attribution are not allowed to
+ * call themselves. */
+ if (c->symtree && c->symtree->n.sym && !c->symtree->n.sym->attr.recursive)
+ {
+ gfc_symbol *csym, *proc;
+ csym = c->symtree->n.sym;
+ proc = gfc_current_ns->proc_name;
+ if (csym == proc)
+ {
+ gfc_error ("SUBROUTINE '%s' at %L cannot call itself, as it is not "
+ "RECURSIVE", csym->name, &c->loc);
+ t = FAILURE;
+ }
+
+ if (csym->attr.entry && csym->ns->entries && proc->ns->entries
+ && csym->ns->entries->sym == proc->ns->entries->sym)
+ {
+ gfc_error ("Call to ENTRY '%s' at %L is recursive, but subroutine "
+ "'%s' is not declared as RECURSIVE",
+ csym->name, &c->loc, csym->ns->entries->sym->name);
+ t = FAILURE;
+ }
+ }
+
/* Switch off assumed size checking and do this again for certain kinds
of procedure, once the procedure itself is resolved. */
need_full_assumed_size++;