]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR fortran/25818 ([4.1 only] Problem with handling optional and entry master argum...
authorPaul Thomas <pault@gcc.gnu.org>
Fri, 22 Dec 2006 20:49:00 +0000 (20:49 +0000)
committerPaul Thomas <pault@gcc.gnu.org>
Fri, 22 Dec 2006 20:49:00 +0000 (20:49 +0000)
2006-12-22  Paul Thomas  <pault@gcc.gnu.org>

PR fortran/25818
* trans-array.c (gfc_trans_g77_array): If the variable is
optional or not always present, make the statement conditional
on presence of the argument.
* gfortran.h : Add symbol_attribute not_always_present.
* resolve.c (check_argument_lists): New function to check if
arguments are not present in all entries.

PR fortran/30084
* module.c (mio_component_ref): Move treatment of unique name
variables, during output, to fix_mio_expr.
(fix_mio_expr): New function that fixes defective expressions
before they are written to the module file.
(mio_expr): Call the new function.
(resolve_entries): Call check_argument_lists.

2006-12-22  Paul Thomas  <pault@gcc.gnu.org>

PR fortran/25818
* gfortran.dg/entry_array_specs_2.f: New test.

PR fortran/30084
* gfortran.dg/nested_modules_6.f90: New test.

From-SVN: r120155

gcc/fortran/ChangeLog
gcc/fortran/gfortran.h
gcc/fortran/module.c
gcc/fortran/resolve.c
gcc/fortran/trans-array.c
gcc/testsuite/ChangeLog
gcc/testsuite/gfortran.dg/entry_array_specs_2.f [new file with mode: 0644]
gcc/testsuite/gfortran.dg/nested_modules_6.f90 [new file with mode: 0644]

index d25f5bf15234019dd47e27f8b051d5c12b085da8..c47a3b85cbe733cc9f4171bd21bd9d733fa3b897 100644 (file)
@@ -1,3 +1,21 @@
+2006-12-22  Paul Thomas  <pault@gcc.gnu.org>
+
+       PR fortran/25818
+       * trans-array.c (gfc_trans_g77_array): If the variable is
+       optional or not always present, make the statement conditional
+       on presence of the argument.
+       * gfortran.h : Add symbol_attribute not_always_present.
+       * resolve.c (check_argument_lists): New function to check if
+       arguments are not present in all entries.
+
+       PR fortran/30084
+       * module.c (mio_component_ref): Move treatment of unique name
+       variables, during output, to fix_mio_expr.
+       (fix_mio_expr): New function that fixes defective expressions
+       before they are written to the module file.
+       (mio_expr): Call the new function.
+       (resolve_entries): Call check_argument_lists.
+
 2006-12-21  Roger Sayle  <roger@eyesopen.com>
 
        * trans-array.c (gfc_trans_create_temp_array): When the size is known
index 296004edbc85958a79ca1f5ddedfe550705411c2..62862977eeb1d5f0a2aa500cc3f78d09d8100900 100644 (file)
@@ -480,7 +480,7 @@ typedef struct
   /* Variable attributes.  */
   unsigned allocatable:1, dimension:1, external:1, intrinsic:1,
     optional:1, pointer:1, save:1, target:1, value:1, volatile_:1,
-    dummy:1, result:1, assign:1, threadprivate:1;
+    dummy:1, result:1, assign:1, threadprivate:1, not_always_present:1;
 
   unsigned data:1,             /* Symbol is named in a DATA statement.  */
     protected:1,               /* Symbol has been marked as protected.  */
index f54ef8e67cd0a460e12126f10a4f641808f0b295..dc138d3e5cacc2596e8f865eca9fc8eb2d1c09c7 100644 (file)
@@ -2194,27 +2194,9 @@ mio_symtree_ref (gfc_symtree ** stp)
 {
   pointer_info *p;
   fixup_t *f;
-  gfc_symtree * ns_st = NULL;
 
   if (iomode == IO_OUTPUT)
-    {
-      /* If this is a symtree for a symbol that came from a contained module
-        namespace, it has a unique name and we should look in the current
-        namespace to see if the required, non-contained symbol is available
-        yet. If so, the latter should be written.  */
-      if ((*stp)->n.sym && check_unique_name((*stp)->name))
-       ns_st = gfc_find_symtree (gfc_current_ns->sym_root,
-                                   (*stp)->n.sym->name);
-
-      /* On the other hand, if the existing symbol is the module name or the
-        new symbol is a dummy argument, do not do the promotion.  */
-      if (ns_st && ns_st->n.sym
-           && ns_st->n.sym->attr.flavor != FL_MODULE
-           && !(*stp)->n.sym->attr.dummy)
-       mio_symbol_ref (&ns_st->n.sym);
-      else
-       mio_symbol_ref (&(*stp)->n.sym);
-    }
+    mio_symbol_ref (&(*stp)->n.sym);
   else
     {
       require_atom (ATOM_INTEGER);
@@ -2554,6 +2536,48 @@ static const mstring intrinsics[] =
     minit (NULL, -1)
 };
 
+
+/* Remedy a couple of situations where the gfc_expr's can be defective.  */
+static void
+fix_mio_expr (gfc_expr *e)
+{
+  gfc_symtree *ns_st = NULL;
+  const char *fname;
+
+  if (iomode != IO_OUTPUT)
+    return;
+
+  if (e->symtree)
+    {
+      /* If this is a symtree for a symbol that came from a contained module
+        namespace, it has a unique name and we should look in the current
+        namespace to see if the required, non-contained symbol is available
+        yet. If so, the latter should be written.  */
+      if (e->symtree->n.sym && check_unique_name(e->symtree->name))
+       ns_st = gfc_find_symtree (gfc_current_ns->sym_root,
+                                   e->symtree->n.sym->name);
+
+      /* On the other hand, if the existing symbol is the module name or the
+        new symbol is a dummy argument, do not do the promotion.  */
+      if (ns_st && ns_st->n.sym
+           && ns_st->n.sym->attr.flavor != FL_MODULE
+           && !e->symtree->n.sym->attr.dummy)
+       e->symtree = ns_st;
+    }
+  else if (e->expr_type == EXPR_FUNCTION && e->value.function.name)
+    {
+      /* In some circumstances, a function used in an initialization
+        expression, in one use associated module, can fail to be
+        coupled to its symtree when used in a specification
+        expression in another module.  */
+      fname = e->value.function.esym ? e->value.function.esym->name :
+                                      e->value.function.isym->name;
+      e->symtree = gfc_find_symtree (gfc_current_ns->sym_root, fname);
+    }
+}
+
+
 /* Read and write expressions.  The form "()" is allowed to indicate a
    NULL expression.  */
 
@@ -2598,6 +2622,8 @@ mio_expr (gfc_expr ** ep)
   mio_typespec (&e->ts);
   mio_integer (&e->rank);
 
+  fix_mio_expr (e);
+
   switch (e->expr_type)
     {
     case EXPR_OP:
index 519d92ab9b7f138e7ba15824330964fd7a4a133a..eaa939debec6901ee29213fd2c666c89244c7bdc 100644 (file)
@@ -342,6 +342,33 @@ merge_argument_lists (gfc_symbol *proc, gfc_formal_arglist *new_args)
 }
 
 
+/* Flag the arguments that are not present in all entries.  */
+
+static void
+check_argument_lists (gfc_symbol *proc, gfc_formal_arglist *new_args)
+{
+  gfc_formal_arglist *f, *head;
+  head = new_args;
+
+  for (f = proc->formal; f; f = f->next)
+    {
+      if (f->sym == NULL)
+       continue;
+
+      for (new_args = head; new_args; new_args = new_args->next)
+       {
+         if (new_args->sym == f->sym)
+           break;
+       }
+
+      if (new_args)
+       continue;
+
+      f->sym->attr.not_always_present = 1;
+    }
+}
+
+
 /* Resolve alternate entry points.  If a symbol has multiple entry points we
    create a new master symbol for the main routine, and turn the existing
    symbol into an entry point.  */
@@ -541,6 +568,11 @@ resolve_entries (gfc_namespace * ns)
   for (el = ns->entries; el; el = el->next)
     merge_argument_lists (proc, el->sym->formal);
 
+  /* Check the master formal arguments for any that are not
+     present in all entry points.  */
+  for (el = ns->entries; el; el = el->next)
+    check_argument_lists (proc, el->sym->formal);
+
   /* Use the master function for the function body.  */
   ns->proc_name = proc;
 
index 56e69a3d43503673e6f6a782f8742096b7ba0083..10243fe5712fe8c778e4431be7a4d95635f5ab6d 100644 (file)
@@ -3767,6 +3767,7 @@ gfc_trans_g77_array (gfc_symbol * sym, tree body)
   locus loc;
   tree offset;
   tree tmp;
+  tree stmt;  
   stmtblock_t block;
 
   gfc_get_backend_locus (&loc);
@@ -3796,13 +3797,21 @@ gfc_trans_g77_array (gfc_symbol * sym, tree body)
       tmp = convert (TREE_TYPE (parm), GFC_DECL_SAVED_DESCRIPTOR (parm));
       gfc_add_modify_expr (&block, parm, tmp);
     }
-  tmp = gfc_finish_block (&block);
+  stmt = gfc_finish_block (&block);
 
   gfc_set_backend_locus (&loc);
 
   gfc_start_block (&block);
+
   /* Add the initialization code to the start of the function.  */
-  gfc_add_expr_to_block (&block, tmp);
+
+  if (sym->attr.optional || sym->attr.not_always_present)
+    {
+      tmp = gfc_conv_expr_present (sym);
+      stmt = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt ());
+    }
+  
+  gfc_add_expr_to_block (&block, stmt);
   gfc_add_expr_to_block (&block, body);
 
   return gfc_finish_block (&block);
index 5fc63cfc4357f98ac989011bc40a8d45adb13220..c452eb45f09989ed31f0b4578212ed66e5cd6d03 100644 (file)
@@ -1,3 +1,11 @@
+2006-12-22  Paul Thomas  <pault@gcc.gnu.org>
+
+       PR fortran/25818
+       * gfortran.dg/entry_array_specs_2.f: New test.
+
+       PR fortran/30084
+       * gfortran.dg/nested_modules_6.f90: New test.
+
 2006-12-22  Manuel Lopez-Ibanez  <manu@gcc.gnu.org>
 
        PR middle-end/7651
diff --git a/gcc/testsuite/gfortran.dg/entry_array_specs_2.f b/gcc/testsuite/gfortran.dg/entry_array_specs_2.f
new file mode 100644 (file)
index 0000000..ba4de31
--- /dev/null
@@ -0,0 +1,31 @@
+! { dg-do run }
+! Tests the patch for PR30025, aka 25818, in which the initialization
+! code for the array a, was causing a segfault in runtime for a call
+! to x, since n is missing.
+!
+! COntributed by Elizabeth Yip <elizabeth.l.yip@boeing.com>
+      program test_entry
+      common // j
+      real a(10)
+      a(1) = 999.
+      call x
+      if (j .ne. 1) call abort ()
+      call y(a,10)
+      if (j .ne. 2) call abort ()
+      stop
+      end 
+      subroutine x
+      common // j
+      real a(n)
+      j = 1
+      return
+      entry y(a,n)
+      call foo(a(1))
+      end
+      subroutine foo(a)
+      common // j
+      real a
+      j = 2
+      return
+      end
+
diff --git a/gcc/testsuite/gfortran.dg/nested_modules_6.f90 b/gcc/testsuite/gfortran.dg/nested_modules_6.f90
new file mode 100644 (file)
index 0000000..c967aaa
--- /dev/null
@@ -0,0 +1,35 @@
+! { dg-do compile }
+! Test the patch for PR30084 in which the reference to SIZE
+! in function diag caused a segfault in module.c.
+!
+! Contributed by Troban Trumsko <trumsko@yahoo.com>
+! and reduced by Steve Kargl <kargl@gcc.gnu.org>
+!
+module tao_random_numbers
+  integer, dimension(10) :: s_buffer
+  integer :: s_last = size (s_buffer)
+end module tao_random_numbers
+
+module linalg
+  contains
+  function diag (a) result (d)
+    real, dimension(:,:), intent(in) :: a
+    real, dimension(min(size(a,dim=1),size(a,dim=2))) :: d
+    integer :: i
+    do i = 1, min(size(a, dim = 1), size(a, dim = 2))
+       d(i) = a(i,i)
+    end do
+  end function diag
+end module linalg
+
+module vamp_rest
+  use tao_random_numbers
+  use linalg
+end module vamp_rest
+
+  use vamp_rest
+  real :: x(2, 2) = reshape ([1.,2.,3.,4.], [2,2]) ! { dg-warning "nonstandard" } 
+  print *, s_last
+  print *, diag (x)
+end
+! { dg-final { cleanup-modules "tao_random_numbers linalg vamp_rest" } }