From eba55d501f7a2e4b95b7fedd3463424e403f2c54 Mon Sep 17 00:00:00 2001 From: Paul Thomas <pault@gcc.gnu.org> Date: Sat, 24 Nov 2007 10:17:26 +0000 Subject: [PATCH] re PR fortran/33541 (gfortran wrongly imports renamed-use-associated symbol unrenamed) 2007-11-24 Paul Thomas <pault@gcc.gnu.org> PR fortran/33541 * module.c (find_symtree_for_symbol): Move to new location. (find_symbol): New function. (load_generic_interfaces): Rework completely so that symtrees have the local name and symbols have the use name. Renamed generic interfaces exclude the use of the interface without an ONLY clause (11.3.2). (read_module): Implement 11.3.2 in the same way as for generic interfaces. 2007-11-24 Paul Thomas <pault@gcc.gnu.org> PR fortran/33541 * gfortran.dg/nested_modules_1.f90: Change the reference to FOO, forbidden by the standard, to a reference to W. * gfortran.dg/use_only_1.f90: New test. From-SVN: r130395 --- gcc/fortran/ChangeLog | 12 ++++++++++++ gcc/fortran/module.c | 168 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------------------- gcc/testsuite/ChangeLog | 7 +++++++ gcc/testsuite/gfortran.dg/nested_modules_1.f90 | 2 +- gcc/testsuite/gfortran.dg/use_only_1.f90 | 91 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 239 insertions(+), 41 deletions(-) create mode 100644 gcc/testsuite/gfortran.dg/use_only_1.f90 diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index e7c00b2..aedee5e 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,15 @@ +2007-11-24 Paul Thomas <pault@gcc.gnu.org> + + PR fortran/33541 + * module.c (find_symtree_for_symbol): Move to new location. + (find_symbol): New function. + (load_generic_interfaces): Rework completely so that symtrees + have the local name and symbols have the use name. Renamed + generic interfaces exclude the use of the interface without an + ONLY clause (11.3.2). + (read_module): Implement 11.3.2 in the same way as for generic + interfaces. + 2007-11-23 Christopher D. Rickett <crickett@lanl.gov> * trans-common.c (build_common_decl): Fix the alignment for diff --git a/gcc/fortran/module.c b/gcc/fortran/module.c index 00b9e25..5f03b49 100644 --- a/gcc/fortran/module.c +++ b/gcc/fortran/module.c @@ -3104,6 +3104,63 @@ mio_symbol (gfc_symbol *sym) /************************* Top level subroutines *************************/ +/* Given a root symtree node and a symbol, try to find a symtree that + references the symbol that is not a unique name. */ + +static gfc_symtree * +find_symtree_for_symbol (gfc_symtree *st, gfc_symbol *sym) +{ + gfc_symtree *s = NULL; + + if (st == NULL) + return s; + + s = find_symtree_for_symbol (st->right, sym); + if (s != NULL) + return s; + s = find_symtree_for_symbol (st->left, sym); + if (s != NULL) + return s; + + if (st->n.sym == sym && !check_unique_name (st->name)) + return st; + + return s; +} + + +/* A recursive function to look for a speficic symbol by name and by + module. Whilst several symtrees might point to one symbol, its + is sufficient for the purposes here than one exist. Note that + generic interfaces are distinguished. */ +static gfc_symtree * +find_symbol (gfc_symtree *st, const char *name, + const char *module, int generic) +{ + int c; + gfc_symtree *retval; + + if (st == NULL || st->n.sym == NULL) + return NULL; + + c = strcmp (name, st->n.sym->name); + if (c == 0 && st->n.sym->module + && strcmp (module, st->n.sym->module) == 0) + { + if ((!generic && !st->n.sym->attr.generic) + || (generic && st->n.sym->attr.generic)) + return st; + } + + retval = find_symbol (st->left, name, module, generic); + + if (retval == NULL) + retval = find_symbol (st->right, name, module, generic); + + return retval; +} + + /* Skip a list between balanced left and right parens. */ static void @@ -3219,41 +3276,79 @@ load_generic_interfaces (void) for (i = 1; i <= n; i++) { + gfc_symtree *st; /* Decide if we need to load this one or not. */ p = find_use_name_n (name, &i, false); - if (p == NULL || gfc_find_symbol (p, NULL, 0, &sym)) + st = find_symbol (gfc_current_ns->sym_root, + name, module_name, 1); + + if (!p || gfc_find_symbol (p, NULL, 0, &sym)) { - while (parse_atom () != ATOM_RPAREN); + /* Skip the specific names for these cases. */ + while (i == 1 && parse_atom () != ATOM_RPAREN); + continue; } - if (sym == NULL) + /* If the symbol exists already and is being USEd without being + in an ONLY clause, do not load a new symtree(11.3.2). */ + if (!only_flag && st) + sym = st->n.sym; + + if (!sym) { - gfc_get_symbol (p, NULL, &sym); + /* Make symtree inaccessible by renaming if the symbol has + been added by a USE statement without an ONLY(11.3.2). */ + if (st && !st->n.sym->attr.use_only && only_flag + && strcmp (st->n.sym->module, module_name) == 0) + st->name = gfc_get_string ("hidden.%s", name); + else if (st) + { + sym = st->n.sym; + if (strcmp (st->name, p) != 0) + { + st = gfc_new_symtree (&gfc_current_ns->sym_root, p); + st->n.sym = sym; + sym->refs++; + } + } - sym->attr.flavor = FL_PROCEDURE; - sym->attr.generic = 1; - sym->attr.use_assoc = 1; + /* Since we haven't found a valid generic interface, we had + better make one. */ + if (!sym) + { + gfc_get_symbol (p, NULL, &sym); + sym->name = gfc_get_string (name); + sym->module = gfc_get_string (module_name); + sym->attr.flavor = FL_PROCEDURE; + sym->attr.generic = 1; + sym->attr.use_assoc = 1; + } } else { /* Unless sym is a generic interface, this reference is ambiguous. */ - gfc_symtree *st; - p = p ? p : name; - st = gfc_find_symtree (gfc_current_ns->sym_root, p); - if (!sym->attr.generic - && sym->module != NULL - && strcmp(module, sym->module) != 0) + if (st == NULL) + st = gfc_find_symtree (gfc_current_ns->sym_root, p); + + sym = st->n.sym; + + if (st && !sym->attr.generic + && sym->module + && strcmp(module, sym->module)) st->ambiguous = 1; } + + sym->attr.use_only = only_flag; + if (i == 1) { mio_interface_rest (&sym->generic); generic = sym->generic; } - else + else if (!sym->generic) { sym->generic = generic; sym->attr.generic_copy = 1; @@ -3468,31 +3563,6 @@ read_cleanup (pointer_info *p) } -/* Given a root symtree node and a symbol, try to find a symtree that - references the symbol that is not a unique name. */ - -static gfc_symtree * -find_symtree_for_symbol (gfc_symtree *st, gfc_symbol *sym) -{ - gfc_symtree *s = NULL; - - if (st == NULL) - return s; - - s = find_symtree_for_symbol (st->right, sym); - if (s != NULL) - return s; - s = find_symtree_for_symbol (st->left, sym); - if (s != NULL) - return s; - - if (st->n.sym == sym && !check_unique_name (st->name)) - return st; - - return s; -} - - /* Read a module file. */ static void @@ -3609,7 +3679,7 @@ read_module (void) /* Skip symtree nodes not in an ONLY clause, unless there is an existing symtree loaded from another USE statement. */ - if (p == NULL) + if (p == NULL && only_flag) { st = gfc_find_symtree (gfc_current_ns->sym_root, name); if (st != NULL) @@ -3617,6 +3687,16 @@ read_module (void) continue; } + /* If a symbol of the same name and module exists already, + this symbol, which is not in an ONLY clause, must not be + added to the namespace(11.3.2). Note that find_symbol + only returns the first occurrence that it finds. */ + if (!only_flag + && strcmp (name, module_name) != 0 + && find_symbol (gfc_current_ns->sym_root, name, + module_name, 0)) + continue; + st = gfc_find_symtree (gfc_current_ns->sym_root, p); if (st != NULL) @@ -3628,6 +3708,14 @@ read_module (void) } else { + st = gfc_find_symtree (gfc_current_ns->sym_root, name); + + /* Make symtree inaccessible by renaming if the symbol has + been added by a USE statement without an ONLY(11.3.2). */ + if (st && !st->n.sym->attr.use_only && only_flag + && strcmp (st->n.sym->module, module_name) == 0) + st->name = gfc_get_string ("hidden.%s", name); + /* Create a symtree node in the current namespace for this symbol. */ st = check_unique_name (p) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 6c191d6..d83f28f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2007-11-24 Paul Thomas <pault@gcc.gnu.org> + + PR fortran/33541 + * gfortran.dg/nested_modules_1.f90: Change the reference to + FOO, forbidden by the standard, to a reference to W. + * gfortran.dg/use_only_1.f90: New test. + 2007-11-23 Tobias Burnus <burnus@net-b.de> PR fortran/34209 diff --git a/gcc/testsuite/gfortran.dg/nested_modules_1.f90 b/gcc/testsuite/gfortran.dg/nested_modules_1.f90 index 85a2483..a0bd963 100644 --- a/gcc/testsuite/gfortran.dg/nested_modules_1.f90 +++ b/gcc/testsuite/gfortran.dg/nested_modules_1.f90 @@ -35,7 +35,7 @@ use mod2 use mod0, only: w=>foo - FOO = (0.0d0, 1.0d0) + w = (0.0d0, 1.0d0) ! Was foo but this is forbidden (11.3.2) KANGA = (0.0d0, -1.0d0) ROBIN = (99.0d0, 99.0d0) call eyeore () diff --git a/gcc/testsuite/gfortran.dg/use_only_1.f90 b/gcc/testsuite/gfortran.dg/use_only_1.f90 new file mode 100644 index 0000000..30808fb --- /dev/null +++ b/gcc/testsuite/gfortran.dg/use_only_1.f90 @@ -0,0 +1,91 @@ +! { dg-do run } +! { dg-options "-O1" } +! Checks the fix for PR33541, in which a requirement of +! F95 11.3.2 was not being met: The local names 'x' and +! 'y' coming from the USE statements without an ONLY clause +! should not survive in the presence of the locally renamed +! versions. In fixing the PR, the same correction has been +! made to generic interfaces. +! +! Reported by Reported by John Harper in +! http://gcc.gnu.org/ml/fortran/2007-09/msg00397.html +! +MODULE xmod + integer(4) :: x = -666 + private foo, bar + interface xfoobar + module procedure foo, bar + end interface +contains + integer function foo () + foo = 42 + end function + integer function bar (a) + integer a + bar = a + end function +END MODULE xmod + +MODULE ymod + integer(4) :: y = -666 + private foo, bar + interface yfoobar + module procedure foo, bar + end interface +contains + integer function foo () + foo = 42 + end function + integer function bar (a) + integer a + bar = a + end function +END MODULE ymod + + integer function xfoobar () ! These function as defaults should... + xfoobar = 99 + end function + + integer function yfoobar () ! ...the rename works correctly. + yfoobar = 99 + end function + +PROGRAM test2uses + implicit integer(2) (a-z) + x = 666 ! These assignments generate implicitly typed + y = 666 ! local variables 'x' and 'y'. + call test1 + call test2 + call test3 +contains + subroutine test1 ! Test the fix of the original PR + USE xmod + USE xmod, ONLY: xrenamed => x + USE ymod, ONLY: yrenamed => y + USE ymod + implicit integer(2) (a-z) + if (kind(xrenamed) == kind(x)) call abort () + if (kind(yrenamed) == kind(y)) call abort () + end subroutine + + subroutine test2 ! Test the fix applies to generic interfaces + USE xmod + USE xmod, ONLY: xfoobar_renamed => xfoobar + USE ymod, ONLY: yfoobar_renamed => yfoobar + USE ymod + if (xfoobar_renamed (42) == xfoobar ()) call abort () + if (yfoobar_renamed (42) == yfoobar ()) call abort () + end subroutine + + subroutine test3 ! Check that USE_NAME == LOCAL_NAME is OK + USE xmod + USE xmod, ONLY: x => x, xfoobar => xfoobar + USE ymod, ONLY: y => y, yfoobar => yfoobar + USE ymod + if (kind (x) /= 4) call abort () + if (kind (y) /= 4) call abort () + if (xfoobar (77) /= 77_4) call abort () + if (yfoobar (77) /= 77_4) call abort () + end subroutine +END PROGRAM test2uses +! { dg-final { cleanup-modules "xmod ymod" } } -- libgit2 0.26.0