Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > b5e52bbfb4bb11a6cbed452927fba979 > files > 51

gcc-4.1.2-50.el5.src.rpm

2007-02-17  Paul Thomas  <pault@gcc.gnu.org>

	PR fortran/30554
	* module.c (find_symtree_for_symbol): New function to return
	a symtree that is not a "unique symtree" given a symbol.
	(read_module): Do not automatically set pointer_info to
	referenced, if the symbol has a namespace, because this
	inhibits the generation of a unique symtree.  Recycle the
	symtree if possible by calling find_symtree_for_symbol. If a
	symbol is excluded by an ONLY clause, check to see if there is
	a symtree already loaded. If so, attach the symtree to the
	pointer_info.

	* gfortran.dg/used_dummy_types_6.f90: New test.
	* gfortran.dg/used_dummy_types_7.f90: New test..

--- gcc/fortran/module.c	(revision 122073)
+++ gcc/fortran/module.c	(revision 122074)
@@ -3241,6 +3241,31 @@ read_cleanup (pointer_info * p)
 }
 
 
+/* Given a root symtree node and a symbol, try to find a symtree that
+   references the symbol that is not a unique name.  */
+
+static gfc_symtree *
+find_symtree_for_symbol (gfc_symtree *st, gfc_symbol *sym)
+{
+  gfc_symtree *s = NULL;
+
+  if (st == NULL)
+    return s;
+
+  s = find_symtree_for_symbol (st->right, sym);
+  if (s != NULL)
+    return s;
+  s = find_symtree_for_symbol (st->left, sym);
+  if (s != NULL)
+    return s;
+
+  if (st->n.sym == sym && !check_unique_name (st->name))
+    return st;
+
+  return s;
+}
+
+
 /* Read a module file.  */
 
 static void
@@ -3251,7 +3276,7 @@ read_module (void)
   char name[GFC_MAX_SYMBOL_LEN + 1];
   gfc_intrinsic_op i;
   int ambiguous, j, nuse, symbol;
-  pointer_info *info;
+  pointer_info *info, *q;
   gfc_use_rename *u;
   gfc_symtree *st;
   gfc_symbol *sym;
@@ -3301,8 +3326,27 @@ read_module (void)
 	continue;
 
       info->u.rsym.state = USED;
-      info->u.rsym.referenced = 1;
       info->u.rsym.sym = sym;
+
+      /* Some symbols do not have a namespace (eg. formal arguments),
+	 so the automatic "unique symtree" mechanism must be suppressed
+	 by marking them as referenced.  */
+      q = get_integer (info->u.rsym.ns);
+      if (q->u.pointer == NULL)
+	{
+	  info->u.rsym.referenced = 1;
+	  continue;
+	}
+
+      /* If possible recycle the symtree that references the symbol.
+	 If a symtree is not found and the module does not import one,
+	 a unique-name symtree is found by read_cleanup.  */
+      st = find_symtree_for_symbol (gfc_current_ns->sym_root, sym);
+      if (st != NULL)
+	{
+	  info->u.rsym.symtree = st;
+	  info->u.rsym.referenced = 1;
+	}
     }
 
   mio_rparen ();
@@ -3332,15 +3376,22 @@ read_module (void)
 	  /* Get the jth local name for this symbol.  */
 	  p = find_use_name_n (name, &j);
 
-	  /* Skip symtree nodes not in an ONLY clause.  */
+	  /* Skip symtree nodes not in an ONLY clause, unless there
+	     is an existing symtree loaded from another USE
+	     statement.  */
 	  if (p == NULL)
-	    continue;
+	    {
+	      st = gfc_find_symtree (gfc_current_ns->sym_root, name);
+	      if (st != NULL)
+		info->u.rsym.symtree = st;
+	      continue;
+	    }
 
-	  /* Check for ambiguous symbols.  */
 	  st = gfc_find_symtree (gfc_current_ns->sym_root, p);
 
 	  if (st != NULL)
 	    {
+	      /* Check for ambiguous symbols.  */
 	      if (st->n.sym != info->u.rsym.sym)
 		st->ambiguous = 1;
 	      info->u.rsym.symtree = st;
--- gcc/testsuite/gfortran.dg/used_dummy_types_6.f90	(revision 0)
+++ gcc/testsuite/gfortran.dg/used_dummy_types_6.f90	(revision 122074)
@@ -0,0 +1,47 @@
+! { dg-do compile }
+! Tests the fix for PR30554, the USE statements in potential_energy
+! would cause a segfault because the pointer_info for nfree coming
+! from constraint would not find the existing symtree coming directly
+! from atom.
+!
+! The last two modules came up subsequently to the original fix.  The
+! PRIVATE statement caused a revival of the original problem.  This
+! was tracked down to an interaction between the symbols being set
+! referenced during module read and the application of the access
+! attribute.
+!
+! Contributed by Tobias Burnus <burnus@gcc.gnu.org>
+
+MODULE ATOMS
+INTEGER :: NFREE = 0
+END MODULE ATOMS
+
+MODULE CONSTRAINT
+USE ATOMS, ONLY: NFREE
+CONTAINS
+   SUBROUTINE ENERGY_CONSTRAINT ( HESSIAN )
+   REAL , DIMENSION(1:(3*NFREE*(3*NFREE+1))/2):: HESSIAN
+   END SUBROUTINE ENERGY_CONSTRAINT
+END MODULE CONSTRAINT
+
+MODULE POTENTIAL_ENERGY
+USE ATOMS
+USE CONSTRAINT,         ONLY : ENERGY_CONSTRAINT
+END MODULE POTENTIAL_ENERGY
+
+MODULE P_CONSTRAINT
+USE ATOMS, ONLY: NFREE
+PRIVATE
+PUBLIC :: ENERGY_CONSTRAINT
+CONTAINS
+   SUBROUTINE ENERGY_CONSTRAINT ( HESSIAN )
+   REAL , DIMENSION(1:(3*NFREE*(3*NFREE+1))/2):: HESSIAN
+   END SUBROUTINE ENERGY_CONSTRAINT
+END MODULE P_CONSTRAINT
+
+MODULE P_POTENTIAL_ENERGY
+USE ATOMS
+USE CONSTRAINT,         ONLY : ENERGY_CONSTRAINT
+END MODULE P_POTENTIAL_ENERGY
+
+! { dg-final { cleanup-modules "atoms constraint potential_energy p_constraint p_potential_energy" } }
--- gcc/testsuite/gfortran.dg/used_dummy_types_7.f90	(revision 0)
+++ gcc/testsuite/gfortran.dg/used_dummy_types_7.f90	(revision 122074)
@@ -0,0 +1,45 @@
+! { dg-do compile }
+! This tests a patch for a regression caused by the second part of
+! the fix for PR30554.  The linked derived types dummy_atom and
+! dummy_atom_list caused a segment fault because they do not have
+! a namespace.
+!
+! Contributed by Daniel Franke <franke.daniel@gmail.com>
+! 
+MODULE types
+TYPE :: dummy_atom_list
+  TYPE(dummy_atom), DIMENSION(:), POINTER :: table => null()
+END TYPE
+
+TYPE :: dummy_atom
+  TYPE(dummy_atom_private), POINTER :: p => null()
+END TYPE
+
+TYPE :: dummy_atom_private
+  INTEGER                     :: id
+END TYPE
+END MODULE
+
+MODULE atom
+USE types, ONLY: dummy_atom
+INTERFACE
+  SUBROUTINE dummy_atom_insert_symmetry_mate(this, other)
+    USE types, ONLY: dummy_atom
+    TYPE(dummy_atom), INTENT(inout) :: this
+    TYPE(dummy_atom), INTENT(in)    :: other
+  END SUBROUTINE
+END INTERFACE
+END MODULE
+
+MODULE list
+INTERFACE
+  SUBROUTINE dummy_atom_list_insert(this, atom)
+    USE types, ONLY: dummy_atom_list
+    USE atom, ONLY: dummy_atom
+
+    TYPE(dummy_atom_list), INTENT(inout) :: this
+    TYPE(dummy_atom), INTENT(in)         :: atom
+  END SUBROUTINE
+END INTERFACE
+END MODULE
+! { dg-final { cleanup-modules "atom types list" } }