This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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++;

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]