diff options
author | Paul Thomas <pault@gcc.gnu.org> | 2007-11-24 10:17:26 +0000 |
---|---|---|
committer | Paul Thomas <pault@gcc.gnu.org> | 2007-11-24 10:17:26 +0000 |
commit | eba55d501f7a2e4b95b7fedd3463424e403f2c54 (patch) | |
tree | 21ec542f34f69afb88c52c5d30f8758eca1c37d1 /gcc/fortran/module.c | |
parent | a298680ca5bbf7254b79e310e683c33baffa18af (diff) | |
download | gcc-eba55d501f7a2e4b95b7fedd3463424e403f2c54.zip gcc-eba55d501f7a2e4b95b7fedd3463424e403f2c54.tar.gz gcc-eba55d501f7a2e4b95b7fedd3463424e403f2c54.tar.bz2 |
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
Diffstat (limited to 'gcc/fortran/module.c')
-rw-r--r-- | gcc/fortran/module.c | 168 |
1 files changed, 128 insertions, 40 deletions
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) |