This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[Fortran] Fix gfortran.df/module_equivalence_1.f90 on HPUX
- From: Roger Sayle <roger at eyesopen dot com>
- To: fortran at gcc dot gnu dot org
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Sun, 30 Apr 2006 20:44:05 -0600 (MDT)
- Subject: [Fortran] Fix gfortran.df/module_equivalence_1.f90 on HPUX
The following patch addresses the failure of module_equivalence_1.f90
on PA/HPUX, but the underlying problem is present on all platforms,
though harmlessly latent on Linux (and others?).
The failure on PA/HPUX is caused by the assembler complaining about
duplicate .comm lines for the symbol test_equiv.eq.1. This failure
may be reproduced on other platforms by compiling module_equivalence_1.f90
and noticing that the symbol test_equiv.eq.1 is indeed emitted multiple
times in the assembly language output. On x86/Linux, we see
.comm my_common_,32,32
.comm test_equiv.eq.1_,16,16
.comm test_equiv.eq.1_,16,16
.comm test_equiv.eq.1_,16,16
Presumably gas on HPUX is stricter than gas on Linux.
After some investigation and much head scratching it appeared that the
reason was that trans-common.c:build_common_decl was creating multiple
DECLs for the same symbol. This was baffling because the logic in
that function uses a global "gfc_common_ns" namespace to keep track
of it's common block symbols, which looks like it should be resusing
a single gfc_symbol, and thereby avoiding any possibility of duplicates.
Eventually, I discovered that the gfortran front-end uses a commit or
rollback mechanism for symbol creation, and that recently created
gfc_symbols may be destroyed/revoked if they aren't explicitly committed.
This then pointed to the logic error, corrected below, where in the
function gfc_trans_common, it calls gfc_commit_symbols before calling
finish_equivalences, which may itself create symbols via create_common.
Unfortunately, none of these symbols (including the problematic
test_equiv.eq.1 described above) are guaranteed to be committed,
and may unintentionally be revoked by the next statements commit/rollback
decision. The fix is to simply move the call to gfc_commit_symbols in
gfc_trans_common after finish_equivalences, where it becomes the last
call in that function.
Unless, of course, I'm missing something and this duplicate declaration
logic is intentional (but non-portable)?
The following patch has been tested on x86_64-unknown-linux-gnu with a
full "make bootstrap", including gfortran, and tested with a top-level
"make -k check" with no new failures. Inspecting the assembler output
reveals that we now emit one ".comm" directive for test_equiv.eq.1
instead of the three lines we did previously.
Ok for mainline?
2006-04-30 Roger Sayle <roger@eyesopen.com>
* trans-common.c (gfc_trans_common): Call gfc_commit_symbols after
finish_equivalences to commit symbols created there.
Index: trans-common.c
===================================================================
*** trans-common.c (revision 113392)
--- trans-common.c (working copy)
*************** gfc_trans_common (gfc_namespace *ns)
*** 1057,1065 ****
/* Translate all named common blocks. */
gfc_traverse_symtree (ns->common_root, named_common);
- /* Commit the newly created symbols for common blocks. */
- gfc_commit_symbols ();
-
/* Translate local equivalence. */
finish_equivalences (ns);
}
--- 1057,1065 ----
/* Translate all named common blocks. */
gfc_traverse_symtree (ns->common_root, named_common);
/* Translate local equivalence. */
finish_equivalences (ns);
+
+ /* Commit the newly created symbols for common blocks. */
+ gfc_commit_symbols ();
}
Roger
--