This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[gfortran] Fix PR 16485: Private entities from different modulescollide


We don't ensure that entities from different modules don't collide, e.g.
   module a
    private
   contains
    subroutine b
    end subroutine
   end
   module b
    private
   contains
    subroutine b
    end subroutine b
   end
would yield an assembler error if both modules were contained in one
file, and a linker error otherwise.

I'm sure there's a way in gcc to protect local symbols from a against
local symbols from b without name mangling, as something like this is
needed in C, e..g
  void e() { static int b; }
  void f() { static int b; }
faces the same problem. But I didn't find the necessary means when
looking cursorily through gcc's manual. Instead I decided to mangle the
names of private symbols in the same way as we do for public symbols.
This is achieved by the hunk to module.c, the function set_module_name
is ported from g95, which already implements this.

As an additional enhancement, this prevents private symbols from slowing
link times: currently set TREE_PUBLIC also on symbols from modules. This
is prevented by the hunk to trans-decl.c. Since I didn't know if this
works only by chance, if not zeroing it explicitly, I chose to add a
branch to the exisiting if.

Finally, the hunk to parse.c makes sure that all private contained
procedures are marked private, even if they are set so implicitly,
thereby making sure that the hunk in trans-decl.c can do its evil work.
With this fix the compiler should be able to optimize away private
procedures that are not used, or always are inlined when used, but I did
not verify that this happens.

- Tobi

2004-07-13  Tobias Schlueter  <tobias.schlueter@physik.uni-muenchen.de>

	PR fortran/16485
	* parse.c (parse_contained): Make sure that private procedures
	from modules have ACCESS_PRIVATE set.
	* module.c (set_module_name): New function.
	(write_symbol): Don't fill in module name.
	(write_symbol0): Call set_module_name for all symbols.
	* trans-decl.c (gfc_buld_function_decl): set TREE_PUBLIC to
	zero for private subroutines.

Index: parse.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fortran/parse.c,v
retrieving revision 1.13
diff -u -p -r1.13 parse.c
--- parse.c     11 Jul 2004 23:00:05 -0000      1.13
+++ parse.c     13 Jul 2004 17:01:37 -0000
@@ -2202,6 +2202,8 @@ parse_contained (int module)
              by other module functions.  */
           sym->attr.contained = 1;
          sym->attr.referenced = 1;
+         if (module && sym->attr.access == ACCESS_UNKNOWN)
+           sym->attr.access = parent_ns->default_access;

           /* Fix up any sibling functions that refer to this one.  */
           gfc_fixup_sibling_symbols (sym, gfc_current_ns);
Index: module.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fortran/module.c,v
retrieving revision 1.12
diff -u -p -r1.12 module.c
--- module.c    11 Jul 2004 13:04:32 -0000      1.12
+++ module.c    13 Jul 2004 17:01:40 -0000
@@ -3182,6 +3182,45 @@ write_common (gfc_symtree *st)
 }


+/* Decide on the module name of this symbol.
+   Procedures that are not module procedures of this module and aren't
+   generic don't get a module name.  */
+
+static void
+set_module_name (gfc_symbol * sym)
+{
+  gfc_namespace *ns;
+
+  if (sym->module[0] != '\0')
+    return;
+
+  if (sym->attr.dummy)
+    return;
+
+  if (sym->attr.flavor == FL_PROCEDURE
+      && sym->attr.proc != PROC_MODULE)
+    {
+      for (ns = sym->ns->contained; ns; ns = ns->sibling)
+       if (ns->proc_name == sym)
+         break;
+
+      /* At this point, the symbol is an external procedure that does
+        not live in a module.  Symbols without modules are not matched
+        globally by the module read subroutine, but these need to be,
+        even though they are not in a module.  We stick them into a
+        "module" with an otherwise illegal name. */
+
+      if (ns == NULL)
+       {
+         strcpy (sym->module, "(global)");
+         return;
+       }
+    }
+
+  strcpy (sym->module, module_name);
+}
+
+
 /* Write a symbol to the module.  */

 static void
@@ -3194,9 +3233,6 @@ write_symbol (int n, gfc_symbol * sym)
   mio_integer (&n);
   mio_internal_string (sym->name);

-  if (sym->module[0] == '\0')
-    strcpy (sym->module, module_name);
-
   mio_internal_string (sym->module);
   mio_pointer_ref (&sym->ns);

@@ -3222,6 +3258,7 @@ write_symbol0 (gfc_symtree * st)
   write_symbol0 (st->right);

   sym = st->n.sym;
+  set_module_name (sym);

   if (sym->attr.flavor == FL_PROCEDURE && sym->attr.generic
       && !sym->attr.subroutine && !sym->attr.function)
Index: trans-decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fortran/trans-decl.c,v
retrieving revision 1.22
diff -u -p -r1.22 trans-decl.c
--- trans-decl.c        12 Jul 2004 01:23:36 -0000      1.22
+++ trans-decl.c        13 Jul 2004 17:01:40 -0000
@@ -1049,7 +1049,9 @@ gfc_build_function_decl (gfc_symbol * sy

   /* This specifies if a function is globaly addressable, ie. it is
      the opposite of declaring static in C.  */
-  if (DECL_CONTEXT (fndecl) == NULL_TREE || attr.external)
+  if (attr.access == ACCESS_PRIVATE)
+    TREE_PUBLIC (fndecl) = 0;
+  else if (DECL_CONTEXT (fndecl) == NULL_TREE || attr.external)
     TREE_PUBLIC (fndecl) = 1;

   /* TREE_STATIC means the function body is defined here.  */





Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]