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]

[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

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