This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[Patch, fortran] PR27269 and PR27324 - Module equivalences
- From: Paul dot Thomas at jet dot uk (Paul Thomas)
- To: fortran at gcc dot gnu dot org, gcc-patches at gnu dot org
- Date: Fri, 28 Apr 2006 10:10:43 +0100
- Subject: [Patch, fortran] PR27269 and PR27324 - Module equivalences
:ADDPATCH fortran:
This patch fixes PR27269 which causes a segfault in trying to process
module b of the testcase, with an unused equivalence from module a. In
the course of developing the patch, PR27324 was uncovered, which
produces an assembler error when module equivalences have a member with
an initializer.
PR27269 requires modifications to module.c(load_equiv) to recognise that
members of an equivalence group are not used. This is detected by the
absence of a symtree for the variable. To reach this stage, the
expression has been read and a fixup entry generated in mio_expr_ref.
To prevent this latter from happening and to allow the expression to be
freed in load_equiv, a flag in_load_equiv has been added. To summarise,
the equivalence is read as usual, except that the absence of a symtree
does not produce a fixup entry. Subsequently, the absence of a symtree
is used to trigger the deletion of the equivalence and the associated
expressions.
PR27234 is fixed in trans_common.c by inverting the order of the calls
to finish_equivalences and gfc_commit_symbols. This is necessary because
module equivalences are represented in gfc_common_ns as symtree/symbol
entries, like common blocks. Without the call to gfc_commit_symbols,
these symbols were being deleted because they were still marked as
temporary.
Regtested on Cygwin_NT/Athlon_M
OK for trunk and 4.1?
Paul
2006-04-28 Paul Thomas <pault@gcc.gnu.org>
PR fortran/27269
* module.c: Add static flag in_load_equiv.
(mio_expr_ref): Return if no symtree and in_load_equiv.
(load_equiv): If any of the equivalence members have no symtree, free
the equivalence and the associated expressions.
PR fortran/27324
* trans-common.c (gfc_trans_common): Invert the order of calls to
finish equivalences and gfc_commit_symbols.
2006-04-28 Paul Thomas <pault@gcc.gnu.org>
PR fortran/27269
PR fortran/27324
* gfortran.dg/module_equivalence_2.f90: New test.
Index: gcc/fortran/module.c
===================================================================
--- gcc/fortran/module.c (révision 113192)
+++ gcc/fortran/module.c (copie de travail)
@@ -182,8 +182,11 @@
static pointer_info *pi_root;
static int symbol_number; /* Counter for assigning symbol numbers */
+/* Tells mio_expr_ref not to load unused equivalence members. */
+static bool in_load_equiv;
+
/*****************************************************************/
/* Pointer/integer conversion. Pointers between structures are stored
@@ -2135,6 +2138,11 @@
{
require_atom (ATOM_INTEGER);
p = get_integer (atom_int);
+
+ /* An unused equivalence member; bail out. */
+ if (in_load_equiv && p->u.rsym.symtree == NULL)
+ return;
+
if (p->type == P_UNKNOWN)
p->type = P_SYMBOL;
@@ -3008,14 +3016,18 @@
mio_rparen();
}
-/* load_equiv()-- Load equivalences. */
+/* load_equiv()-- Load equivalences. The flag in_load_equiv informs
+ mio_expr_ref of this so that unused variables are not loaded and
+ so that the expression can be safely freed.*/
static void
load_equiv(void)
{
- gfc_equiv *head, *tail, *end;
+ gfc_equiv *head, *tail, *end, *eq;
+ bool unused;
mio_lparen();
+ in_load_equiv = true;
end = gfc_current_ns->equiv;
while(end != NULL && end->next != NULL)
@@ -3039,16 +3051,40 @@
mio_expr(&tail->expr);
}
+ /* Unused variables have no symtree. */
+ unused = false;
+ for (eq = head; eq; eq = eq->eq)
+ {
+ if (!(eq && eq->expr && eq->expr->symtree))
+ {
+ unused = true;
+ break;
+ }
+ }
+
+ if (unused)
+ {
+ for (eq = head; eq; eq = head)
+ {
+ head = eq->eq;
+ gfc_free_expr (eq->expr);
+ gfc_free (eq);
+ }
+ }
+
if (end == NULL)
gfc_current_ns->equiv = head;
else
end->next = head;
- end = head;
+ if (head != NULL)
+ end = head;
+
mio_rparen();
}
mio_rparen();
+ in_load_equiv = false;
}
/* Recursive function to traverse the pointer_info tree and load a
Index: gcc/fortran/trans-common.c
===================================================================
--- gcc/fortran/trans-common.c (révision 113192)
+++ gcc/fortran/trans-common.c (copie de travail)
@@ -1057,9 +1057,10 @@
/* 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);
+
+ /* Commit the newly created symbols for common blocks and module
+ equivalences. */
+ gfc_commit_symbols ();
}
! { dg-do run }
! Tests the fix for PR27269 and PR27324.
! The former caused a segfault in trying to process
! module b, with an unused equivalence in a. The latter
! produced an assembler error due to multiple declarations
! for a module equivalence, when one of the variables was
! initialized, as M in module a.
!
module a
integer, parameter :: dp = selected_real_kind (10)
real(dp) :: reM, M = 1.77d0
equivalence (M, reM)
end module a
module b
use a, only : dp
end module b
use a
use b
if (reM .ne. 1.77d0) call abort ()
reM = 0.57d1
if (M .ne. 0.57d1) call abort ()
end