OSDN Git Service

2007-12-21 Paul Thomas <pault@gcc.gnu.org>
authorpault <pault@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 21 Dec 2007 21:20:38 +0000 (21:20 +0000)
committerpault <pault@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 21 Dec 2007 21:20:38 +0000 (21:20 +0000)
PR fortran/34438
* trans-decl.c (gfc_finish_var_decl): Do not mark derived types
with default initializers as TREE_STATIC unless they are in the
main program scope.
(gfc_get_symbol_decl): Pass derived types with a default
initializer to gfc_defer_symbol_init.
(init_default_dt): Apply default initializer to a derived type.
(init_intent_out_dt): Call init_default_dt.
(gfc_trans_deferred_vars): Ditto.

* module.c (read_module): Check sym->module is there before
using it in a string comparison.

2007-12-21  Paul Thomas  <pault@gcc.gnu.org>

PR fortran/34438
* gfortran.dg/default_initialization_3.f90: New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@131124 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/fortran/ChangeLog
gcc/fortran/module.c
gcc/fortran/trans-decl.c
gcc/testsuite/ChangeLog
gcc/testsuite/gfortran.dg/default_initialization_3.f90 [new file with mode: 0644]

index 4701a2f..f90a077 100644 (file)
@@ -1,3 +1,18 @@
+2007-12-21  Paul Thomas  <pault@gcc.gnu.org>
+
+       PR fortran/34438
+       * trans-decl.c (gfc_finish_var_decl): Do not mark derived types
+       with default initializers as TREE_STATIC unless they are in the
+       main program scope.
+       (gfc_get_symbol_decl): Pass derived types with a default
+       initializer to gfc_defer_symbol_init.
+       (init_default_dt): Apply default initializer to a derived type.
+       (init_intent_out_dt): Call init_default_dt.
+       (gfc_trans_deferred_vars): Ditto.
+
+       * module.c (read_module): Check sym->module is there before
+       using it in a string comparison.
+
 2007-12-20  Tobias Burnus  <burnus@net-b.de>
 
        PR fortran/34482
index 9cb082a..f3c54b7 100644 (file)
@@ -3732,6 +3732,7 @@ read_module (void)
              if (st && only_flag
                     && !st->n.sym->attr.use_only
                     && !st->n.sym->attr.use_rename
+                    && st->n.sym->module
                     && strcmp (st->n.sym->module, module_name) == 0)
                st->name = gfc_get_string ("hidden.%s", name);
 
index 876219f..f97870c 100644 (file)
@@ -517,8 +517,15 @@ gfc_finish_var_decl (tree decl, gfc_symbol * sym)
       TREE_STATIC (decl) = 1;
     }
 
-  if ((sym->attr.save || sym->attr.data || sym->value)
-      && !sym->attr.use_assoc)
+  /* Derived types are a bit peculiar because of the possibility of
+     a default initializer; this must be applied each time the variable
+     comes into scope it therefore need not be static.  These variables
+     are SAVE_NONE but have an initializer.  Otherwise explicitly
+     intitialized variables are SAVE_IMPLICIT and explicitly saved are
+     SAVE_EXPLICIT.  */
+  if (!sym->attr.use_assoc
+       && (sym->attr.save != SAVE_NONE || sym->attr.data
+             || (sym->value && sym->ns->proc_name->attr.is_main_program)))
     TREE_STATIC (decl) = 1;
 
   if (sym->attr.volatile_)
@@ -995,6 +1002,14 @@ gfc_get_symbol_decl (gfc_symbol * sym)
 
   if (sym->ts.type == BT_DERIVED && sym->ts.derived->attr.alloc_comp)
     gfc_defer_symbol_init (sym);
+  /* This applies a derived type default initializer.  */
+  else if (sym->ts.type == BT_DERIVED
+            && sym->attr.save == SAVE_NONE
+            && !sym->attr.data
+            && !sym->attr.allocatable
+            && (sym->value && !sym->ns->proc_name->attr.is_main_program)
+            && !sym->attr.use_assoc)
+    gfc_defer_symbol_init (sym);
 
   gfc_finish_var_decl (decl, sym);
 
@@ -2572,43 +2587,53 @@ gfc_trans_vla_type_sizes (gfc_symbol *sym, stmtblock_t *body)
 }
 
 
-/* Initialize INTENT(OUT) derived type dummies.  */
+/* Initialize a derived type by building an lvalue from the symbol
+   and using trans_assignment to do the work.  */
 static tree
-init_intent_out_dt (gfc_symbol * proc_sym, tree body)
+init_default_dt (gfc_symbol * sym, tree body)
 {
   stmtblock_t fnblock;
-  gfc_formal_arglist *f;
-  gfc_expr *tmpe;
+  gfc_expr *e;
   tree tmp;
   tree present;
 
   gfc_init_block (&fnblock);
-
-  for (f = proc_sym->formal; f; f = f->next)
+  gcc_assert (!sym->attr.allocatable);
+  gfc_set_sym_referenced (sym);
+  e = gfc_lval_expr_from_sym (sym);
+  tmp = gfc_trans_assignment (e, sym->value, false);
+  if (sym->attr.dummy)
     {
-      if (f->sym && f->sym->attr.intent == INTENT_OUT
-           && f->sym->ts.type == BT_DERIVED
-           && !f->sym->ts.derived->attr.alloc_comp
-           && f->sym->value)
-       {
-         gcc_assert (!f->sym->attr.allocatable);
-         gfc_set_sym_referenced (f->sym);
-         tmpe = gfc_lval_expr_from_sym (f->sym);
-         tmp = gfc_trans_assignment (tmpe, f->sym->value, false);
-
-         present = gfc_conv_expr_present (f->sym);
-         tmp = build3 (COND_EXPR, TREE_TYPE (tmp), present,
-                       tmp, build_empty_stmt ());
-         gfc_add_expr_to_block (&fnblock, tmp);
-         gfc_free_expr (tmpe);
-       }
+      present = gfc_conv_expr_present (sym);
+      tmp = build3 (COND_EXPR, TREE_TYPE (tmp), present,
+                   tmp, build_empty_stmt ());
     }
-
+  gfc_add_expr_to_block (&fnblock, tmp);
+  gfc_free_expr (e);
   gfc_add_expr_to_block (&fnblock, body);
   return gfc_finish_block (&fnblock);
 }
 
 
+/* Initialize INTENT(OUT) derived type dummies.  */
+static tree
+init_intent_out_dt (gfc_symbol * proc_sym, tree body)
+{
+  stmtblock_t fnblock;
+  gfc_formal_arglist *f;
+
+  gfc_init_block (&fnblock);
+  for (f = proc_sym->formal; f; f = f->next)
+    if (f->sym && f->sym->attr.intent == INTENT_OUT
+         && f->sym->ts.type == BT_DERIVED
+         && !f->sym->ts.derived->attr.alloc_comp
+         && f->sym->value)
+      body = init_default_dt (f->sym, body);
+
+  gfc_add_expr_to_block (&fnblock, body);
+  return gfc_finish_block (&fnblock);
+}
+
 
 /* Generate function entry and exit code, and add it to the function body.
    This includes:
@@ -2698,6 +2723,11 @@ gfc_trans_deferred_vars (gfc_symbol * proc_sym, tree fnbody)
                      seen_trans_deferred_array = true;
                      fnbody = gfc_trans_deferred_array (sym, fnbody);
                    }
+                 else if (sym->ts.type == BT_DERIVED
+                            && sym->value
+                            && !sym->attr.data
+                            && sym->attr.save == SAVE_NONE)
+                   fnbody = init_default_dt (sym, fnbody);
 
                  gfc_get_backend_locus (&loc);
                  gfc_set_backend_locus (&sym->declared_at);
@@ -2753,6 +2783,11 @@ gfc_trans_deferred_vars (gfc_symbol * proc_sym, tree fnbody)
          fnbody = gfc_trans_assign_aux_var (sym, fnbody);
          gfc_set_backend_locus (&loc);
        }
+      else if (sym->ts.type == BT_DERIVED
+                && sym->value
+                && !sym->attr.data
+                && sym->attr.save == SAVE_NONE)
+       fnbody = init_default_dt (sym, fnbody);
       else
        gcc_unreachable ();
     }
index a703188..3e4d2db 100644 (file)
@@ -1,3 +1,8 @@
+2007-12-21  Paul Thomas  <pault@gcc.gnu.org>
+
+       PR fortran/34438
+       * gfortran.dg/default_initialization_3.f90: New test.
+
 2007-12-21  Richard Sandiford  <rsandifo@nildram.co.uk>
 
        * gcc.target/mips/mips.exp (setup_mips_tests): Fix _MIPS_SIM
diff --git a/gcc/testsuite/gfortran.dg/default_initialization_3.f90 b/gcc/testsuite/gfortran.dg/default_initialization_3.f90
new file mode 100644 (file)
index 0000000..4365198
--- /dev/null
@@ -0,0 +1,108 @@
+! { dg-do run }
+! Test the fix for PR34438, in which default initializers
+! forced the derived type to be static; ie. initialized once
+! during the lifetime of the programme.  Instead, they should
+! be initialized each time they come into scope.
+!
+! Contributed by Sven Buijssen <sven.buijssen@math.uni-dortmund.de>
+! Third test is from  Dominique Dhumieres <dominiq@lps.ens.fr>
+!
+module demo
+   type myint
+     integer :: bar = 42
+   end type myint
+end module demo
+
+! As the name implies, this was the original testcase
+! provided by the contributor....
+subroutine original
+  use demo
+  integer val1 (6)
+  integer val2 (6)
+  call recfunc (1)
+  if (any (val1 .ne. (/1, 2, 3, 1, 2, 3/))) call abort ()
+  if (any (val2 .ne. (/1, 2, 3, 4, 4, 4/))) call abort ()
+contains
+
+  recursive subroutine recfunc (ivalue)
+    integer, intent(in) :: ivalue
+    type(myint) :: foo1
+    type(myint) :: foo2 = myint (99)
+    foo1%bar = ivalue
+    foo2%bar = ivalue
+    if (ivalue .le. 3) then
+      val1(ivalue) = foo1%bar
+      val2(ivalue) = foo2%bar
+      call recfunc (ivalue + 1)
+      val1(ivalue + 3) = foo1%bar
+      val2(ivalue + 3) = foo2%bar
+    endif
+  end subroutine recfunc
+end subroutine original
+
+! ...who came up with this one too.
+subroutine func (ivalue, retval1, retval2)
+  use demo
+  integer, intent(in) :: ivalue
+  type(myint) :: foo1
+  type(myint) :: foo2 = myint (77)
+  type(myint) :: retval1
+  type(myint) :: retval2
+  retval1 = foo1
+  retval2 = foo2
+  foo1%bar = 999
+  foo2%bar = 999
+end subroutine func
+
+subroutine other
+  use demo
+  interface
+    subroutine func(ivalue, rv1, rv2)
+      use demo
+      integer, intent(in) :: ivalue
+      type(myint) :: foo, rv1, rv2
+   end subroutine func
+  end interface
+  type(myint) :: val1, val2
+  call func (1, val1, val2)
+  if ((val1%bar .ne. 42) .or. (val2%bar .ne. 77)) call abort ()
+  call func (2, val1, val2)
+  if ((val1%bar .ne. 42) .or. (val2%bar .ne. 999)) call abort ()
+
+end subroutine other
+
+MODULE M1
+  TYPE T1
+    INTEGER :: i=7
+  END TYPE T1
+CONTAINS
+  FUNCTION F1(d1) RESULT(res)
+    INTEGER :: res
+    TYPE(T1), INTENT(OUT) :: d1
+    TYPE(T1), INTENT(INOUT) :: d2
+    res=d1%i
+    d1%i=0
+    RETURN
+  ENTRY   E1(d2) RESULT(res)
+    res=d2%i
+    d2%i=0
+  END FUNCTION F1
+END MODULE M1
+
+! This tests the fix of a regression caused by the first version
+! of the patch.
+subroutine dominique ()
+  USE M1
+  TYPE(T1) :: D1
+  D1=T1(3)
+  if (F1(D1) .ne. 7) call abort ()
+  D1=T1(3)
+  if (E1(D1) .ne. 3) call abort ()
+END
+
+! Run both tests.
+  call original
+  call other
+  call dominique
+end
+! { dg-final { cleanup-modules "demo M1" } }