gfortran version "gcc version 3.5.0 20040710 (experimental)" generates incorrect names for private functions inside modules, causing link-time collisions between same-named private functions from different modules: (this problem prevents this example from even assembling): [olchansk@tw15 gfortran_test]$ cat test_ldcollide.f90 module foo private contains subroutine sub end subroutine sub end module foo module bar private contains subroutine sub end subroutine sub end module bar [olchansk@tw15 gfortran_test]$ make test_ldcollide.o /triumfcs/trshare/olchansk/gcc-tree-ssa/install/bin/gfortran -x f95 -c -o test_ldcollide.o -O2 -g -Wall -Waliasing -Wline-truncation -Wsurprising -Wunused-labels -fPIC -ffixed-line-length-132 test_ldcollide.f90 /tmp/ccAzTdiq.s: Assembler messages: /tmp/ccAzTdiq.s:30: Error: symbol `sub_' is already defined make: *** [test_ldcollide.o] Error 1 K.O.
This change to module.c::write_symbol0() fixes the symbol collisions. My project now almost links, except for the missing "entry" symbols. Yay! Something silly is going on. This is how I understand this problem (feel free to laugh at me if I got it completly backwards). gfc_sym_mangled_function_id() depends on sym->module to create unique mangled names. However, private module subroutines arrive there with sym->module blank and mangling cannot happen. So, who sets sym->module? The only place I could find is in module.c::write_symbol(). Internal subroutines do not go through "write_symbol" and their sym->module remains blank. Fix to module.c::write_symbol0(): add lines marked "+" (no cvs diff this time, sorry). sym = st->n.sym; if (sym->attr.flavor == FL_PROCEDURE && sym->attr.generic && !sym->attr.subroutine && !sym->attr.function) return; + if (sym->attr.proc == PROC_MODULE && sym->module[0] == 0) + strcpy (sym->module, module_name); if (!check_access (sym->attr.access, sym->ns->default_access)) return; K.O.
Confirmed from a build which was updated about 2 hours ago.
There's another problem: splitting your testcase in two files gives an error at link time. I don't think there's any reason a private procedure should have global linkage. (Mangling names would help for this, but linking large projects would definitely be sped up by not creating these global symbols in the first place). [tobi@marktplatz tests]$ cat pr16485.f90 module foo private contains subroutine sub end subroutine sub end module foo [tobi@marktplatz tests]$ cat pr16485_2.f90 module bar private contains subroutine sub end subroutine sub end module bar end [tobi@marktplatz tests]$ gfortran pr16485.f90 pr16485_2.f90 /tmp/ccadlrBF.o(.text+0x0): In function `sub_': : multiple definition of `sub_' /tmp/ccWqd9At.o(.text+0x0): first defined here collect2: ld returned 1 exit status [tobi@marktplatz tests]$ The error message is also remarkably bad. Compiling and linking in separate steps fixes that: [tobi@marktplatz tests]$ gfortran pr16485.f90 -c [tobi@marktplatz tests]$ gfortran pr16485_2.f90 -c [tobi@marktplatz tests]$ gfortran pr16485.o pr16485_2.o pr16485_2.o(.text+0x0): In function `sub_': : multiple definition of `sub_' pr16485.o(.text+0x0): first defined here collect2: ld returned 1 exit status [tobi@marktplatz tests]$
Created attachment 6728 [details] Putative patch The attached patch fixes the problem if the modules are in two separate files. With my little knowledge of gcc's backend, I think the DECL_CONTEXT of a module procedure shouldn't be NULL, but a TRANSLATION_UNIT_DECL of the current module instead. Then setting TREE_PUBLIC(fndecl) = 0 should do the trick also in a single file.
Created attachment 6730 [details] Revised patch This is a revised version which also fixes the single file case. I'm not posting this to the list as I'm convinced that the real fix would be to introduce the necessary scoped. I tried calling pushlevel(0) and poplevel(1,0,0) in gfc_generate_module_code, but this didn't help.
Created attachment 6731 [details] Revised patch Unfortunately the above broke other assumptions, which were not checked in the testsuite so I didn't find them initially. Indeed, I think now that your approach is favorable, and I implemented it. The new routine in module.c is taken from g95 which had already implemented your suggestion.
Looks like I attached the second patch again, when I attached for the third time. Anyway, I've posted my current patch to the mailing list: http://gcc.gnu.org/ml/fortran/2004-07/msg00161.html
Updated patch here: http://gcc.gnu.org/ml/fortran/2004-09/msg00019.html
Subject: Bug 16485 CVSROOT: /cvs/gcc Module name: gcc Changes by: pbrook@gcc.gnu.org 2004-09-15 13:12:52 Modified files: gcc/fortran : ChangeLog module.c gcc/testsuite : ChangeLog Added files: gcc/testsuite/gfortran.dg: same_name_1.f90 Log message: 2004-09-15 Tobias Schlueter <tobias.schlueter@physik.uni-muenchen.de> PR fortran/16485 * module.c (write_symbol): Don't fill in module name here. (write_symbol0): Fill in here instead. testsuite/ * gfortran.dg/same_name_1.f90: New test. Patches: http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/fortran/ChangeLog.diff?cvsroot=gcc&r1=1.202&r2=1.203 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/fortran/module.c.diff?cvsroot=gcc&r1=1.15&r2=1.16 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/ChangeLog.diff?cvsroot=gcc&r1=1.4294&r2=1.4295 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gfortran.dg/same_name_1.f90.diff?cvsroot=gcc&r1=NONE&r2=1.1
Fixed.