diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 1a6b28afcde..f3602064f96 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,13 @@ +2006-12-09 Paul Thomas + + PR fortran/29464 + * module.c (load_generic_interfaces): Add symbols for all the + local names of an interface. Share the interface amongst the + symbols. + * gfortran.h : Add generic_copy to symbol_attribute. + * symbol.c (free_symbol): Only free interface if generic_copy + is not set. + 2006-12-09 Paul Thomas PR fortran/29941 diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h index 3a3b680f88f..5e4b322aebf 100644 --- a/gcc/fortran/gfortran.h +++ b/gcc/fortran/gfortran.h @@ -486,7 +486,7 @@ typedef struct use_assoc:1; /* Symbol has been use-associated. */ unsigned in_namelist:1, in_common:1, in_equivalence:1; - unsigned function:1, subroutine:1, generic:1; + unsigned function:1, subroutine:1, generic:1, generic_copy:1; unsigned implicit_type:1; /* Type defined via implicit rules. */ unsigned untyped:1; /* No implicit type could be found. */ diff --git a/gcc/fortran/module.c b/gcc/fortran/module.c index 6956fc980c5..7c9c2b1ab3c 100644 --- a/gcc/fortran/module.c +++ b/gcc/fortran/module.c @@ -3024,6 +3024,8 @@ load_generic_interfaces (void) const char *p; char name[GFC_MAX_SYMBOL_LEN + 1], module[GFC_MAX_SYMBOL_LEN + 1]; gfc_symbol *sym; + gfc_interface *generic = NULL; + int n, i; mio_lparen (); @@ -3034,25 +3036,39 @@ load_generic_interfaces (void) mio_internal_string (name); mio_internal_string (module); - /* Decide if we need to load this one or not. */ - p = find_use_name (name); + n = number_use_names (name); + n = n ? n : 1; - if (p == NULL || gfc_find_symbol (p, NULL, 0, &sym)) + for (i = 1; i <= n; i++) { - while (parse_atom () != ATOM_RPAREN); - continue; + /* Decide if we need to load this one or not. */ + p = find_use_name_n (name, &i); + + if (p == NULL || gfc_find_symbol (p, NULL, 0, &sym)) + { + while (parse_atom () != ATOM_RPAREN); + continue; + } + + if (sym == NULL) + { + gfc_get_symbol (p, NULL, &sym); + + sym->attr.flavor = FL_PROCEDURE; + sym->attr.generic = 1; + sym->attr.use_assoc = 1; + } + if (i == 1) + { + mio_interface_rest (&sym->generic); + generic = sym->generic; + } + else + { + sym->generic = generic; + sym->attr.generic_copy = 1; + } } - - if (sym == NULL) - { - gfc_get_symbol (p, NULL, &sym); - - sym->attr.flavor = FL_PROCEDURE; - sym->attr.generic = 1; - sym->attr.use_assoc = 1; - } - - mio_interface_rest (&sym->generic); } mio_rparen (); diff --git a/gcc/fortran/symbol.c b/gcc/fortran/symbol.c index 228567bd5e8..7cb5e762de5 100644 --- a/gcc/fortran/symbol.c +++ b/gcc/fortran/symbol.c @@ -1971,7 +1971,8 @@ gfc_free_symbol (gfc_symbol * sym) gfc_free_namespace (sym->formal_ns); - gfc_free_interface (sym->generic); + if (!sym->attr.generic_copy) + gfc_free_interface (sym->generic); gfc_free_formal_arglist (sym->formal); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 761d53bb660..5204470816a 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2006-12-09 Paul Thomas + + PR fortran/29464 + * gfortran.dg/module_interface_2.f90: New test. + 2006-12-09 Paul Thomas PR fortran/29941 diff --git a/gcc/testsuite/gfortran.dg/module_interface_2.f90 b/gcc/testsuite/gfortran.dg/module_interface_2.f90 new file mode 100644 index 00000000000..1f9fde81edb --- /dev/null +++ b/gcc/testsuite/gfortran.dg/module_interface_2.f90 @@ -0,0 +1,31 @@ +! { dg-do compile } +! Tests the fix for PR29464, in which the second USE of the generic +! interface caused an error. +! +! Contributed by Vivek Rao +! +module foo_mod + implicit none + interface twice + module procedure twice_real + end interface twice +contains + real function twice_real(x) + real :: x + twice_real = 2*x + end function twice_real +end module foo_mod + + subroutine foobar () + use foo_mod, only: twice, twice + print *, twice (99.0) + end subroutine foobar + + program xfoo + use foo_mod, only: two => twice, dbl => twice + implicit none + call foobar () + print *, two (2.3) + print *, dbl (2.3) +end program xfoo +! { dg-final { cleanup-modules "foo_mod" } }