aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMikael Morin <mikael@gcc.gnu.org>2013-02-08 15:13:32 +0000
committerMikael Morin <mikael@gcc.gnu.org>2013-02-08 15:13:32 +0000
commit3434c119a309db4ff991d50b6ebe25a017b58cd7 (patch)
tree396927675c70a031f01648aeeee123668f8c7712 /gcc
parent600a5961b24faccf68ef5287fb3a6ed3c6b79224 (diff)
downloadgcc-3434c119a309db4ff991d50b6ebe25a017b58cd7.zip
gcc-3434c119a309db4ff991d50b6ebe25a017b58cd7.tar.gz
gcc-3434c119a309db4ff991d50b6ebe25a017b58cd7.tar.bz2
re PR fortran/54107 ([F03] Memory hog with abstract interface)
fortran/ PR fortran/54107 * trans-types.c (gfc_get_function_type): Change a NULL backend_decl to error_mark_node on entry. Detect recursive types. Build a variadic procedure type if the type is recursive. Restore the initial backend_decl. testsuite/ PR fortran/54107 * gfortran.dg/recursive_interface_2.f90: New test. From-SVN: r195890
Diffstat (limited to 'gcc')
-rw-r--r--gcc/fortran/ChangeLog8
-rw-r--r--gcc/fortran/trans-types.c32
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gfortran.dg/recursive_interface_2.f9022
4 files changed, 59 insertions, 8 deletions
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index a0a0e02..6505704 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,11 @@
+2013-02-08 Mikael Morin <mikael@gcc.gnu.org>
+
+ PR fortran/54107
+ * trans-types.c (gfc_get_function_type): Change a NULL backend_decl
+ to error_mark_node on entry. Detect recursive types. Build a variadic
+ procedure type if the type is recursive. Restore the initial
+ backend_decl.
+
2013-02-07 Tobias Burnus <burnus@net-b.de>
PR fortran/54339
diff --git a/gcc/fortran/trans-types.c b/gcc/fortran/trans-types.c
index 21aa75c..30561ee 100644
--- a/gcc/fortran/trans-types.c
+++ b/gcc/fortran/trans-types.c
@@ -2711,19 +2711,23 @@ gfc_get_function_type (gfc_symbol * sym)
gfc_formal_arglist *f;
gfc_symbol *arg;
int alternate_return;
- bool is_varargs = true;
+ bool is_varargs = true, recursive_type = false;
/* Make sure this symbol is a function, a subroutine or the main
program. */
gcc_assert (sym->attr.flavor == FL_PROCEDURE
|| sym->attr.flavor == FL_PROGRAM);
- if (sym->backend_decl)
- {
- if (sym->attr.proc_pointer)
- return TREE_TYPE (TREE_TYPE (sym->backend_decl));
- return TREE_TYPE (sym->backend_decl);
- }
+ /* To avoid recursing infinitely on recursive types, we use error_mark_node
+ so that they can be detected here and handled further down. */
+ if (sym->backend_decl == NULL)
+ sym->backend_decl = error_mark_node;
+ else if (sym->backend_decl == error_mark_node)
+ recursive_type = true;
+ else if (sym->attr.proc_pointer)
+ return TREE_TYPE (TREE_TYPE (sym->backend_decl));
+ else
+ return TREE_TYPE (sym->backend_decl);
alternate_return = 0;
typelist = NULL;
@@ -2775,6 +2779,13 @@ gfc_get_function_type (gfc_symbol * sym)
if (arg->attr.flavor == FL_PROCEDURE)
{
+ /* We don't know in the general case which argument causes
+ recursion. But we know that it is a procedure. So we give up
+ creating the procedure argument type list at the first
+ procedure argument. */
+ if (recursive_type)
+ goto arg_type_list_done;
+
type = gfc_get_function_type (arg);
type = build_pointer_type (type);
}
@@ -2828,6 +2839,11 @@ gfc_get_function_type (gfc_symbol * sym)
|| sym->attr.if_source != IFSRC_UNKNOWN)
is_varargs = false;
+arg_type_list_done:
+
+ if (!recursive_type && sym->backend_decl == error_mark_node)
+ sym->backend_decl = NULL_TREE;
+
if (alternate_return)
type = integer_type_node;
else if (!sym->attr.function || gfc_return_by_reference (sym))
@@ -2865,7 +2881,7 @@ gfc_get_function_type (gfc_symbol * sym)
else
type = gfc_sym_type (sym);
- if (is_varargs)
+ if (is_varargs || recursive_type)
type = build_varargs_function_type_vec (type, typelist);
else
type = build_function_type_vec (type, typelist);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index ae21e6b..60fc928 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2013-02-08 Mikael Morin <mikael@gcc.gnu.org>
+
+ PR fortran/54107
+ * gfortran.dg/recursive_interface_2.f90: New test.
+
2013-02-08 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/56250
diff --git a/gcc/testsuite/gfortran.dg/recursive_interface_2.f90 b/gcc/testsuite/gfortran.dg/recursive_interface_2.f90
new file mode 100644
index 0000000..9726a0e
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/recursive_interface_2.f90
@@ -0,0 +1,22 @@
+! { dg-do compile }
+!
+! PR fortran/54107
+! Recursive interfaces used to lead to an infinite recursion during
+! translation.
+
+module m
+ contains
+ subroutine foo (arg)
+ procedure(foo) :: arg
+ end subroutine
+ function foo2 (arg) result(r)
+ procedure(foo2) :: arg
+ procedure(foo2), pointer :: r
+ end function
+ subroutine bar (arg)
+ procedure(baz) :: arg
+ end subroutine
+ subroutine baz (arg)
+ procedure(bar) :: arg
+ end subroutine
+end module m