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] Support static coarrays with "automatic" cobounds


gfortran currently rejects:

subroutine foo(n)
   integer, SAVE :: foo(500)[n, *]

claiming that as SAVE does not work with automatic arrays. The latter is correct. ("C513 An automatic object shall not have the SAVE attribute.") However, I would argue that "foo" is not an automatic object and thus the code is valid: "An automatic data object is a nondummy data object with a type parameter or array bound that depends on the value of a specification-expr that is not a constant expression.". -- Note the "bound" not "cobound". Cf. "1.3.27 cobound: bound (limit) of a codimension" vs. "1.3.17 bound / array bound: limit of a dimension of an array".

(Obviously, the bounds need to be constant for a static array, but the cobounds are only "virtual": They just exist to calculate the image from the coarray index - and vice versa ("image_index()").)

The test program (cf. patch) also compiles with crayftn, but it is rejected by both g95 and ifort 12.0. I think that's a bug in g95 and ifort, but if possible: please cross check the standard to ensure that I did not misread it.

Build and regtested on x86-64-linux.
OK for the trunk?

Tobias
2011-05-30  Tobias Burnus  <burnus@net-b.de>

	PR fortran/18918
	* resolve.c (resolve_fl_variable): Handle static coarrays
	with non-constant cobounds.
	(resolve_symbol): Handle SAVE statement without arguments
	for coarrays.
	* trans-array.c (gfc_trans_array_cobounds): New function.
	(gfc_trans_array_bounds): Place code by call to it.
	* trans-array.h (gfc_trans_array_cobounds): New prototype.
	* trans-decl.c (gfc_get_symbol_decl, gfc_trans_deferred_vars):
	Handle static coarrays with nonconstant cobounds.

2011-05-30  Tobias Burnus  <burnus@net-b.de>

	PR fortran/18918
	* gfortran.dg/coarray/save_1.f90: New.
	* gfortran.dg/coarray_4.f90: Update dg-error.

diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c
index 4b18529..6ca98f2 100644
--- a/gcc/fortran/resolve.c
+++ b/gcc/fortran/resolve.c
@@ -10118,7 +10118,14 @@ resolve_fl_variable (gfc_symbol *sym, int mp_flag)
 
       /* Also, they must not have the SAVE attribute.
 	 SAVE_IMPLICIT is checked below.  */
-      if (sym->attr.save == SAVE_EXPLICIT)
+      if (sym->as && sym->attr.codimension)
+	{
+	  int corank = sym->as->corank;
+	  sym->as->corank = 0;
+	  no_init_flag = automatic_flag = is_non_constant_shape_array (sym);
+	  sym->as->corank = corank;
+	}
+      if (automatic_flag && sym->attr.save == SAVE_EXPLICIT)
 	{
 	  gfc_error (auto_save_msg, sym->name, &sym->declared_at);
 	  return FAILURE;
@@ -12337,6 +12344,7 @@ resolve_symbol (gfc_symbol *sym)
   if (((sym->ts.type == BT_DERIVED && sym->ts.u.derived->attr.coarray_comp)
        || sym->attr.codimension)
       && !(sym->attr.allocatable || sym->attr.dummy || sym->attr.save
+	   || sym->ns->save_all
 	   || sym->ns->proc_name->attr.flavor == FL_MODULE
 	   || sym->ns->proc_name->attr.is_main_program
 	   || sym->attr.function || sym->attr.result || sym->attr.use_assoc))
diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c
index d83a7a9..0c6c638 100644
--- a/gcc/fortran/trans-array.c
+++ b/gcc/fortran/trans-array.c
@@ -4648,6 +4648,43 @@ gfc_conv_array_initializer (tree type, gfc_expr * expr)
 }
 
 
+/* Generate code to evaluate non-constant coarray cobounds.  */
+
+void
+gfc_trans_array_cobounds (tree type, stmtblock_t * pblock,
+			  const gfc_symbol *sym)
+{
+  int dim;
+  tree ubound;
+  tree lbound;
+  gfc_se se;
+  gfc_array_spec *as;
+
+  as = sym->as;
+
+  for (dim = as->rank; dim < as->rank + as->corank; dim++)
+    {
+      /* Evaluate non-constant array bound expressions.  */
+      lbound = GFC_TYPE_ARRAY_LBOUND (type, dim);
+      if (as->lower[dim] && !INTEGER_CST_P (lbound))
+        {
+          gfc_init_se (&se, NULL);
+          gfc_conv_expr_type (&se, as->lower[dim], gfc_array_index_type);
+          gfc_add_block_to_block (pblock, &se.pre);
+          gfc_add_modify (pblock, lbound, se.expr);
+        }
+      ubound = GFC_TYPE_ARRAY_UBOUND (type, dim);
+      if (as->upper[dim] && !INTEGER_CST_P (ubound))
+        {
+          gfc_init_se (&se, NULL);
+          gfc_conv_expr_type (&se, as->upper[dim], gfc_array_index_type);
+          gfc_add_block_to_block (pblock, &se.pre);
+          gfc_add_modify (pblock, ubound, se.expr);
+        }
+    }
+}
+
+
 /* Generate code to evaluate non-constant array bounds.  Sets *poffset and
    returns the size (in elements) of the array.  */
 
@@ -4728,26 +4765,8 @@ gfc_trans_array_bounds (tree type, gfc_symbol * sym, tree * poffset,
 
       size = stride;
     }
-  for (dim = as->rank; dim < as->rank + as->corank; dim++)
-    {
-      /* Evaluate non-constant array bound expressions.  */
-      lbound = GFC_TYPE_ARRAY_LBOUND (type, dim);
-      if (as->lower[dim] && !INTEGER_CST_P (lbound))
-        {
-          gfc_init_se (&se, NULL);
-          gfc_conv_expr_type (&se, as->lower[dim], gfc_array_index_type);
-          gfc_add_block_to_block (pblock, &se.pre);
-          gfc_add_modify (pblock, lbound, se.expr);
-        }
-      ubound = GFC_TYPE_ARRAY_UBOUND (type, dim);
-      if (as->upper[dim] && !INTEGER_CST_P (ubound))
-        {
-          gfc_init_se (&se, NULL);
-          gfc_conv_expr_type (&se, as->upper[dim], gfc_array_index_type);
-          gfc_add_block_to_block (pblock, &se.pre);
-          gfc_add_modify (pblock, ubound, se.expr);
-        }
-    }
+
+  gfc_trans_array_cobounds (type, pblock, sym);
   gfc_trans_vla_type_sizes (sym, pblock);
 
   *poffset = offset;
diff --git a/gcc/fortran/trans-array.h b/gcc/fortran/trans-array.h
index fef56ae..f29162e 100644
--- a/gcc/fortran/trans-array.h
+++ b/gcc/fortran/trans-array.h
@@ -132,6 +132,9 @@ tree gfc_conv_array_stride (tree, int);
 tree gfc_conv_array_lbound (tree, int);
 tree gfc_conv_array_ubound (tree, int);
 
+/* Set cobounds of an array.  */
+void gfc_trans_array_cobounds (tree, stmtblock_t *, const gfc_symbol *);
+
 /* Build expressions for accessing components of an array descriptor.  */
 tree gfc_conv_descriptor_data_get (tree);
 tree gfc_conv_descriptor_data_addr (tree);
diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c
index 299f224..27eca79 100644
--- a/gcc/fortran/trans-decl.c
+++ b/gcc/fortran/trans-decl.c
@@ -1349,7 +1349,7 @@ gfc_get_symbol_decl (gfc_symbol * sym)
     }
 
   /* Remember this variable for allocation/cleanup.  */
-  if (sym->attr.dimension || sym->attr.allocatable
+  if (sym->attr.dimension || sym->attr.allocatable || sym->attr.codimension
       || (sym->ts.type == BT_CLASS &&
 	  (CLASS_DATA (sym)->attr.dimension
 	   || CLASS_DATA (sym)->attr.allocatable))
@@ -3485,6 +3485,15 @@ gfc_trans_deferred_vars (gfc_symbol * proc_sym, gfc_wrapped_block * block)
 		      gfc_trans_deferred_array (sym, block);
 		    }
 		}
+	      else if (sym->attr.codimension && TREE_STATIC (sym->backend_decl))
+		{
+		  gfc_init_block (&tmpblock);
+		  gfc_trans_array_cobounds (TREE_TYPE (sym->backend_decl),
+					    &tmpblock, sym);
+		  gfc_add_init_cleanup (block, gfc_finish_block (&tmpblock),
+					NULL_TREE);
+		  continue;
+		}
 	      else if (gfc_option.coarray != GFC_FCOARRAY_LIB)
 		{
 		  gfc_save_backend_locus (&loc);
diff --git a/gcc/testsuite/gfortran.dg/coarray_4.f90 b/gcc/testsuite/gfortran.dg/coarray_4.f90
index 5607ec9..be2bc4e 100644
--- a/gcc/testsuite/gfortran.dg/coarray_4.f90
+++ b/gcc/testsuite/gfortran.dg/coarray_4.f90
@@ -18,7 +18,8 @@ subroutine valid(n, c, f)
   save :: k
   integer :: ii = 7
   block
-    integer, save :: kk[ii, *] ! { dg-error "cannot have the SAVE attribute" }
+    integer :: j = 5
+    integer, save :: kk[j, *] ! { dg-error "Variable .j. cannot appear in the expression" }
   end block
 end subroutine valid
 
@@ -43,10 +44,10 @@ subroutine invalid(n)
   complex, save :: hh(n)[*] ! { dg-error "cannot have the SAVE attribute" }
   integer :: j = 6
 
-  integer, save :: hf1[j,*] ! { dg-error "cannot appear in the expression|cannot have the SAVE attribute" }
-  integer, save :: hf2[n,*] ! { dg-error "cannot have the SAVE attribute" }
+  integer, save :: hf1[j,*] ! { dg-error "cannot appear in the expression" }
+  integer, save :: hf2[n,*] ! OK
   integer, save :: hf3(4)[j,*] ! { dg-error "cannot appear in the expression|cannot have the SAVE attribute" }
-  integer, save :: hf4(5)[n,*] ! { dg-error "cannot have the SAVE attribute" }
+  integer, save :: hf4(5)[n,*] ! OK
 
   integer, allocatable :: a2[*] ! { dg-error "must have deferred shape" }
   integer, allocatable :: a3(:)[*] ! { dg-error "must have deferred shape" }

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