This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [Patch, Fortran] PR 39577 - fix -fcheck=recursion
- From: Tobias Burnus <burnus at net-b dot de>
- To: Dominique Dhumieres <dominiq at lps dot ens dot fr>
- Cc: fortran at gcc dot gnu dot org, gcc-patches at gcc dot gnu dot org
- Date: Sat, 04 Apr 2009 10:09:21 +0200
- Subject: Re: [Patch, Fortran] PR 39577 - fix -fcheck=recursion
- References: <20090403221056.CF95F3BAB9@mailhost.lps.ens.fr>
Dominique,
thanks for your testing.
Dominique Dhumieres wrote:
> I am not so sure because I don't really master 'recursive', 'entry', and
> interfaces. But, if the code above is standard conforming, then it is a
> false positive.
>
Neither am I; I think there are still a couple of bugs in gfortran with
ENTRY as it is only rarely used.
Your example(s) now work(s), the problem was that the entry-master
function does not have the recursive attribute only the entry procedures
themselves have. Attached is the updated patch, which regtests and
includes your last valid example.
Build and regtested on x86-64-linux.
OK for the trunk?
Tobias
2009-04-04 Tobias Burnus <burnus@net-b.de>
PR fortran/39577
* trans-decl.c (gfc_generate_function_code): Move recursive
check to the right position.
2009-04-04 Tobias Burnus <burnus@net-b.de>
PR fortran/39577
* gfortran.dg/recursive_check_8.f90: New.
* gfortran.dg/recursive_check_9.f90: New.
* gfortran.dg/recursive_check_10.f90: New.
* gfortran.dg/recursive_check_11.f90: New.
* gfortran.dg/recursive_check_12.f90: New.
* gfortran.dg/recursive_check_13.f90: New.
* gfortran.dg/recursive_check_14.f90: New.
Index: gcc/fortran/trans-decl.c
===================================================================
--- gcc/fortran/trans-decl.c (Revision 145531)
+++ gcc/fortran/trans-decl.c (Arbeitskopie)
@@ -3718,6 +3718,7 @@ gfc_generate_function_code (gfc_namespac
tree recurcheckvar = NULL;
gfc_symbol *sym;
int rank;
+ bool is_recursive;
sym = ns->proc_name;
@@ -3883,7 +3884,10 @@ gfc_generate_function_code (gfc_namespac
gfc_add_expr_to_block (&body, tmp);
}
- if ((gfc_option.rtcheck & GFC_RTCHECK_RECURSION) && !sym->attr.recursive)
+ is_recursive = sym->attr.recursive
+ || (sym->attr.entry_master
+ && sym->ns->entries->sym->attr.recursive);
+ if ((gfc_option.rtcheck & GFC_RTCHECK_RECURSION) && !is_recursive)
{
char * msg;
@@ -3953,6 +3957,13 @@ gfc_generate_function_code (gfc_namespac
gfc_add_expr_to_block (&block, tmp);
+ /* Reset recursion-check variable. */
+ if ((gfc_option.rtcheck & GFC_RTCHECK_RECURSION) && !is_recursive)
+ {
+ gfc_add_modify (&block, recurcheckvar, boolean_false_node);
+ recurcheckvar = NULL;
+ }
+
if (result == NULL_TREE)
{
/* TODO: move to the appropriate place in resolve.c. */
@@ -3975,11 +3986,16 @@ gfc_generate_function_code (gfc_namespac
}
}
else
- gfc_add_expr_to_block (&block, tmp);
+ {
+ gfc_add_expr_to_block (&block, tmp);
+ /* Reset recursion-check variable. */
+ if ((gfc_option.rtcheck & GFC_RTCHECK_RECURSION) && !is_recursive)
+ {
+ gfc_add_modify (&block, recurcheckvar, boolean_false_node);
+ recurcheckvar = NULL;
+ }
+ }
- /* Reset recursion-check variable. */
- if ((gfc_option.rtcheck & GFC_RTCHECK_RECURSION) && !sym->attr.recursive)
- gfc_add_modify (&block, recurcheckvar, boolean_false_node);
/* Add all the decls we created during processing. */
decl = saved_function_decls;
Index: gcc/testsuite/gfortran.dg/recursive_check_10.f90
===================================================================
--- gcc/testsuite/gfortran.dg/recursive_check_10.f90 (Revision 0)
+++ gcc/testsuite/gfortran.dg/recursive_check_10.f90 (Revision 0)
@@ -0,0 +1,25 @@
+! { dg-do run }
+! { dg-options "-fcheck=recursion" }
+!
+! PR fortran/39577
+!
+! OK - no recursion
+program test
+ integer :: i
+ i = f(.false.)
+ print *,i
+ i = f(.false.)
+ print *,i
+contains
+ integer function f(rec)
+ logical :: rec
+ if(rec) then
+ f = g()
+ else
+ f = 42
+ end if
+ end function f
+ integer function g()
+ g = f(.false.)
+ end function g
+end program test
Index: gcc/testsuite/gfortran.dg/recursive_check_11.f90
===================================================================
--- gcc/testsuite/gfortran.dg/recursive_check_11.f90 (Revision 0)
+++ gcc/testsuite/gfortran.dg/recursive_check_11.f90 (Revision 0)
@@ -0,0 +1,28 @@
+! { dg-do run }
+! { dg-options "-fcheck=recursion" }
+! { dg-shouldfail "Recursion check" }
+!
+! { dg-output "Fortran runtime error: Recursive call to nonrecursive procedure 'f'" }
+!
+! PR fortran/39577
+!
+! wrong - recursion
+program test
+ integer :: i
+ i = f(.false.)
+ print *,i
+ i = f(.true.)
+ print *,i
+contains
+ integer function f(rec)
+ logical :: rec
+ if(rec) then
+ f = g()
+ else
+ f = 42
+ end if
+ end function f
+ integer function g()
+ g = f(.false.)
+ end function g
+end program test
Index: gcc/testsuite/gfortran.dg/recursive_check_12.f90
===================================================================
--- gcc/testsuite/gfortran.dg/recursive_check_12.f90 (Revision 0)
+++ gcc/testsuite/gfortran.dg/recursive_check_12.f90 (Revision 0)
@@ -0,0 +1,29 @@
+! { dg-do run }
+! { dg-options "-fcheck=recursion" }
+!
+! PR fortran/39577
+!
+! OK - no recursion
+module m
+ implicit none
+contains
+ subroutine f(rec)
+ logical :: rec
+ if(rec) then
+ call h()
+ end if
+ return
+ entry g()
+ end subroutine f
+ subroutine h()
+ call f(.false.)
+ end subroutine h
+end module m
+
+program test
+ use m
+ implicit none
+ call f(.false.)
+ call f(.false.)
+end program test
+! { dg-final { cleanup-modules "m" } }
Index: gcc/testsuite/gfortran.dg/recursive_check_13.f90
===================================================================
--- gcc/testsuite/gfortran.dg/recursive_check_13.f90 (Revision 0)
+++ gcc/testsuite/gfortran.dg/recursive_check_13.f90 (Revision 0)
@@ -0,0 +1,32 @@
+! { dg-do run }
+! { dg-options "-fcheck=recursion" }
+! { dg-shouldfail "Recursion check" }
+!
+! { dg-output "Fortran runtime error: Recursive call to nonrecursive procedure 'master.0.f'" }
+!
+! PR fortran/39577
+!
+! invalid - recursion
+module m
+ implicit none
+contains
+ subroutine f(rec)
+ logical :: rec
+ if(rec) then
+ call h()
+ end if
+ return
+ entry g()
+ end subroutine f
+ subroutine h()
+ call f(.false.)
+ end subroutine h
+end module m
+
+program test
+ use m
+ implicit none
+ call f(.false.)
+ call f(.true.)
+end program test
+! { dg-final { cleanup-modules "m" } }
Index: gcc/testsuite/gfortran.dg/recursive_check_14.f90
===================================================================
--- gcc/testsuite/gfortran.dg/recursive_check_14.f90 (Revision 0)
+++ gcc/testsuite/gfortran.dg/recursive_check_14.f90 (Revision 0)
@@ -0,0 +1,40 @@
+! { dg-do run }
+! { dg-options "-fcheck=recursion" }
+!
+! PR fortran/39577
+!
+! Recursive but valid program
+! Contributed by Dominique Dhumieres
+!
+recursive function fac(i) result (res)
+ integer :: i, j, k, res
+ k = 1
+ goto 100
+entry bifac(i,j) result (res)
+ k = j
+100 continue
+ if (i < k) then
+ res = 1
+ else
+ res = i * bifac(i-k,k)
+ end if
+end function
+
+program test
+interface
+ recursive function fac(n) result (res)
+ integer :: res
+ integer :: n
+ end function fac
+ recursive function bifac(m,n) result (res)
+ integer :: m, n, res
+ end function bifac
+end interface
+
+ print *, fac(5)
+ print *, bifac(5,2)
+ print*, fac(6)
+ print *, bifac(6,2)
+ print*, fac(0)
+ print *, bifac(1,2)
+end program test
Index: gcc/testsuite/gfortran.dg/recursive_check_8.f90
===================================================================
--- gcc/testsuite/gfortran.dg/recursive_check_8.f90 (Revision 0)
+++ gcc/testsuite/gfortran.dg/recursive_check_8.f90 (Revision 0)
@@ -0,0 +1,22 @@
+! { dg-do run }
+! { dg-options "-fcheck=recursion" }
+!
+! PR fortran/39577
+!
+! OK - no recursion
+program test
+ call f(.false.)
+ call f(.false.)
+contains
+ subroutine f(rec)
+ logical :: rec
+ if(rec) then
+ call g()
+ end if
+ return
+ end subroutine f
+ subroutine g()
+ call f(.false.)
+ return
+ end subroutine g
+end program test
Index: gcc/testsuite/gfortran.dg/recursive_check_9.f90
===================================================================
--- gcc/testsuite/gfortran.dg/recursive_check_9.f90 (Revision 0)
+++ gcc/testsuite/gfortran.dg/recursive_check_9.f90 (Revision 0)
@@ -0,0 +1,25 @@
+! { dg-do run }
+! { dg-options "-fcheck=recursion" }
+! { dg-shouldfail "Recursion check" }
+!
+! { dg-output "Fortran runtime error: Recursive call to nonrecursive procedure 'f'" }
+!
+! PR fortran/39577
+!
+! Invalid - recursion
+program test
+ call f(.false.)
+ call f(.true.)
+contains
+ subroutine f(rec)
+ logical :: rec
+ if(rec) then
+ call g()
+ end if
+ return
+ end subroutine f
+ subroutine g()
+ call f(.false.)
+ return
+ end subroutine g
+end program test