re PR fortran/18918 (Eventually support Fortran 2008's coarrays [co-arrays])
authorTobias Burnus <burnus@net-b.de>
Mon, 20 Jun 2011 21:12:39 +0000 (23:12 +0200)
committerTobias Burnus <burnus@gcc.gnu.org>
Mon, 20 Jun 2011 21:12:39 +0000 (23:12 +0200)
2011-06-20  Tobias Burnus  <burnus@net-b.de>

        PR fortran/18918
        * gfortran.h (gfc_check_vardef_context): Update prototype.
        (iso_fortran_env_symbol): Handle derived types.
        (symbol_attribute): Add lock_comp.
        * expr.c (gfc_check_vardef_context): Add LOCK_TYPE check.
        * interface.c (compare_parameter, gfc_procedure_use): Handle
        LOCK_TYPE.
        (compare_actual_formal): Update
        gfc_check_vardef_context call.
        * check.c (gfc_check_atomic_def, gfc_check_atomic_ref): Ditto.
        * intrinsic.c (check_arglist): Ditto.
        * io.c (resolve_tag, gfc_resolve_dt, gfc_resolve_inquire):
        * Ditto.
        * iso-fortran-env.def (ISOFORTRAN_LOCK_TYPE): Add.
        * intrinsic.texi (ISO_FORTRAN_ENV): Document LOCK_TYPE.
        * module.c (mio_symbol_attribute): Handle lock_comp.
        (create_derived_type): New function.
        (use_iso_fortran_env_module): Call it to handle LOCK_TYPE.
        * parse.c (parse_derived): Add constraint check for LOCK_TYPE.
        * resolve.c (resolve_symbol, resolve_lock_unlock): Add
        * constraint
        checks for LOCK_TYPE.
        (gfc_resolve_iterator, resolve_deallocate_expr,
        resolve_allocate_expr, resolve_code, resolve_transfer): Update
        gfc_check_vardef_context call.
        * trans-stmt.h (gfc_trans_lock_unlock): New prototype.
        * trans-stmt.c (gfc_trans_lock_unlock): New function.
        * trans.c (trans_code): Handle LOCK and UNLOCK.

2011-06-20  Tobias Burnus  <burnus@net-b.de>

        PR fortran/18918
        * gfortran.dg/coarray_lock_1.f90: Update dg-error.
        * gfortran.dg/coarray_lock_3.f90: New.
        * gfortran.dg/coarray/lock_1.f90: New.

From-SVN: r175228

19 files changed:
gcc/fortran/ChangeLog
gcc/fortran/check.c
gcc/fortran/expr.c
gcc/fortran/gfortran.h
gcc/fortran/interface.c
gcc/fortran/intrinsic.c
gcc/fortran/intrinsic.texi
gcc/fortran/io.c
gcc/fortran/iso-fortran-env.def
gcc/fortran/module.c
gcc/fortran/parse.c
gcc/fortran/resolve.c
gcc/fortran/trans-stmt.c
gcc/fortran/trans-stmt.h
gcc/fortran/trans.c
gcc/testsuite/ChangeLog
gcc/testsuite/gfortran.dg/coarray/lock_1.f90 [new file with mode: 0644]
gcc/testsuite/gfortran.dg/coarray_lock_1.f90
gcc/testsuite/gfortran.dg/coarray_lock_3.f90 [new file with mode: 0644]

index 08c666ac4a649aebad23da6d54de54c1b95e7efd..2e73625d927c66835bc1d91b3dae58402e0d63de 100644 (file)
@@ -1,3 +1,32 @@
+2011-06-20  Tobias Burnus  <burnus@net-b.de>
+
+       PR fortran/18918
+       * gfortran.h (gfc_check_vardef_context): Update prototype.
+       (iso_fortran_env_symbol): Handle derived types.
+       (symbol_attribute): Add lock_comp.
+       * expr.c (gfc_check_vardef_context): Add LOCK_TYPE check.
+       * interface.c (compare_parameter, gfc_procedure_use): Handle
+       LOCK_TYPE.
+       (compare_actual_formal): Update
+       gfc_check_vardef_context call.
+       * check.c (gfc_check_atomic_def, gfc_check_atomic_ref): Ditto.
+       * intrinsic.c (check_arglist): Ditto.
+       * io.c (resolve_tag, gfc_resolve_dt, gfc_resolve_inquire): Ditto.
+       * iso-fortran-env.def (ISOFORTRAN_LOCK_TYPE): Add.
+       * intrinsic.texi (ISO_FORTRAN_ENV): Document LOCK_TYPE.
+       * module.c (mio_symbol_attribute): Handle lock_comp.
+       (create_derived_type): New function.
+       (use_iso_fortran_env_module): Call it to handle LOCK_TYPE.
+       * parse.c (parse_derived): Add constraint check for LOCK_TYPE.
+       * resolve.c (resolve_symbol, resolve_lock_unlock): Add constraint
+       checks for LOCK_TYPE.
+       (gfc_resolve_iterator, resolve_deallocate_expr,
+       resolve_allocate_expr, resolve_code, resolve_transfer): Update
+       gfc_check_vardef_context call.
+       * trans-stmt.h (gfc_trans_lock_unlock): New prototype.
+       * trans-stmt.c (gfc_trans_lock_unlock): New function.
+       * trans.c (trans_code): Handle LOCK and UNLOCK.
+
 2011-06-18  Janus Weil  <janus@gcc.gnu.org>
 
        PR fortran/49400
index 972b290c987d84b9bc284c28ad421569da057475..79e1c95b9e16445693a5b71e67a8e848353c38c9 100644 (file)
@@ -1011,7 +1011,7 @@ gfc_check_atomic_def (gfc_expr *atom, gfc_expr *value)
   if (scalar_check (atom, 0) == FAILURE || scalar_check (value, 1) == FAILURE)
     return FAILURE;
 
-  if (gfc_check_vardef_context (atom, false, NULL) == FAILURE)
+  if (gfc_check_vardef_context (atom, false, false, NULL) == FAILURE)
     {
       gfc_error ("ATOM argument of the %s intrinsic function at %L shall be "
                 "definable", gfc_current_intrinsic, &atom->where);
@@ -1028,7 +1028,7 @@ gfc_check_atomic_ref (gfc_expr *value, gfc_expr *atom)
   if (scalar_check (value, 0) == FAILURE || scalar_check (atom, 1) == FAILURE)
     return FAILURE;
 
-  if (gfc_check_vardef_context (value, false, NULL) == FAILURE)
+  if (gfc_check_vardef_context (value, false, false, NULL) == FAILURE)
     {
       gfc_error ("VALUE argument of the %s intrinsic function at %L shall be "
                 "definable", gfc_current_intrinsic, &value->where);
index f881bb1dbff98eb9ca012c1ce27575adc3936af1..4a7a951b6d6f1bb3eecb0cdb01d064c71975c97c 100644 (file)
@@ -4373,7 +4373,8 @@ gfc_build_intrinsic_call (const char* name, locus where, unsigned numarg, ...)
    and just the return status (SUCCESS / FAILURE) be requested.  */
 
 gfc_try
-gfc_check_vardef_context (gfc_expr* e, bool pointer, const char* context)
+gfc_check_vardef_context (gfc_expr* e, bool pointer, bool alloc_obj,
+                         const char* context)
 {
   gfc_symbol* sym = NULL;
   bool is_pointer;
@@ -4441,6 +4442,19 @@ gfc_check_vardef_context (gfc_expr* e, bool pointer, const char* context)
       return FAILURE;
     }
 
+  /* F2008, C1303.  */
+  if (!alloc_obj
+      && (attr.lock_comp
+         || (e->ts.type == BT_DERIVED
+             && e->ts.u.derived->from_intmod == INTMOD_ISO_FORTRAN_ENV
+             && e->ts.u.derived->intmod_sym_id == ISOFORTRAN_LOCK_TYPE)))
+    {
+      if (context)
+       gfc_error ("LOCK_TYPE in variable definition context (%s) at %L",
+                  context, &e->where);
+      return FAILURE;
+    }
+
   /* INTENT(IN) dummy argument.  Check this, unless the object itself is
      the component of sub-component of a pointer.  Obviously,
      procedure pointers are of no interest here.  */
@@ -4555,7 +4569,8 @@ gfc_check_vardef_context (gfc_expr* e, bool pointer, const char* context)
        }
 
       /* Target must be allowed to appear in a variable definition context.  */
-      if (gfc_check_vardef_context (assoc->target, pointer, NULL) == FAILURE)
+      if (gfc_check_vardef_context (assoc->target, pointer, false, NULL)
+         == FAILURE)
        {
          if (context)
            gfc_error ("Associate-name '%s' can not appear in a variable"
index f23fbbd4d1288ad9c275408eabe20a9ec20db427..8b834abe095bdb5b07f402fb0b8d4ba0f6ede4ea 100644 (file)
@@ -596,6 +596,7 @@ gfc_reverse;
 #define NAMED_INTCST(a,b,c,d) a,
 #define NAMED_KINDARRAY(a,b,c,d) a,
 #define NAMED_FUNCTION(a,b,c,d) a,
+#define NAMED_DERIVED_TYPE(a,b,c,d) a,
 typedef enum
 {
   ISOFORTRANENV_INVALID = -1,
@@ -606,6 +607,7 @@ iso_fortran_env_symbol;
 #undef NAMED_INTCST
 #undef NAMED_KINDARRAY
 #undef NAMED_FUNCTION
+#undef NAMED_DERIVED_TYPE
 
 #define NAMED_INTCST(a,b,c,d) a,
 #define NAMED_REALCST(a,b,c) a,
@@ -774,7 +776,7 @@ typedef struct
      possibly nested.  zero_comp is true if the derived type has no
      component at all.  */
   unsigned alloc_comp:1, pointer_comp:1, proc_pointer_comp:1,
-          private_comp:1, zero_comp:1, coarray_comp:1;
+          private_comp:1, zero_comp:1, coarray_comp:1, lock_comp:1;
 
   /* This is a temporary selector for SELECT TYPE.  */
   unsigned select_type_temporary:1;
@@ -2735,7 +2737,7 @@ bool gfc_has_ultimate_allocatable (gfc_expr *);
 bool gfc_has_ultimate_pointer (gfc_expr *);
 
 gfc_expr* gfc_build_intrinsic_call (const char*, locus, unsigned, ...);
-gfc_try gfc_check_vardef_context (gfc_expr*, bool, const char*);
+gfc_try gfc_check_vardef_context (gfc_expr*, bool, bool, const char*);
 
 
 /* st.c */
index e787187ba8075d239c6484120f84b8831c418948..dcf6c4e9bd15f66b77505917554262ecd1a9b596 100644 (file)
@@ -1618,7 +1618,22 @@ compare_parameter (gfc_symbol *formal, gfc_expr *actual,
                       "contiguous", formal->name, &actual->where);
          return 0;
        }
-    }
+
+      /* F2008, C1303 and C1304.  */
+      if (formal->attr.intent != INTENT_INOUT
+         && (((formal->ts.type == BT_DERIVED || formal->ts.type == BT_CLASS)
+              && formal->ts.u.derived->from_intmod == INTMOD_ISO_FORTRAN_ENV
+              && formal->ts.u.derived->intmod_sym_id == ISOFORTRAN_LOCK_TYPE)
+             || formal->attr.lock_comp))
+
+       {
+         if (where)
+           gfc_error ("Actual argument to non-INTENT(INOUT) dummy '%s' at %L, "
+                      "which is LOCK_TYPE or has a LOCK_TYPE component",
+                      formal->name, &actual->where);
+         return 0;
+       }
+      }
 
   /* F2008, C1239/C1240.  */
   if (actual->expr_type == EXPR_VARIABLE
@@ -2294,10 +2309,10 @@ compare_actual_formal (gfc_actual_arglist **ap, gfc_formal_arglist *formal,
                                 : NULL);
 
          if (f->sym->attr.pointer
-             && gfc_check_vardef_context (a->expr, true, context)
+             && gfc_check_vardef_context (a->expr, true, false, context)
                   == FAILURE)
            return 0;
-         if (gfc_check_vardef_context (a->expr, false, context)
+         if (gfc_check_vardef_context (a->expr, false, false, context)
                == FAILURE)
            return 0;
        }
@@ -2749,6 +2764,19 @@ gfc_procedure_use (gfc_symbol *sym, gfc_actual_arglist **ap, locus *where)
                        "for procedure '%s' at %L", sym->name, &a->expr->where);
              break;
            }
+
+         /* F2008, C1303 and C1304.  */
+         if (a->expr
+             && (a->expr->ts.type == BT_DERIVED || a->expr->ts.type == BT_CLASS)
+             && ((a->expr->ts.u.derived->from_intmod == INTMOD_ISO_FORTRAN_ENV
+                  && a->expr->ts.u.derived->intmod_sym_id == ISOFORTRAN_LOCK_TYPE)
+                 || gfc_expr_attr (a->expr).lock_comp))
+           {
+             gfc_error("Actual argument of LOCK_TYPE or with LOCK_TYPE "
+                       "component at %L requires an explicit interface for "
+                       "procedure '%s'", &a->expr->where, sym->name);
+             break;
+           }
        }
 
       return;
index 1cce1447b04b6415f3f516216b3027ae41d8c66d..a72da91defc962a47aa8cd87a021d92b0e90ac07 100644 (file)
@@ -3642,7 +3642,7 @@ check_arglist (gfc_actual_arglist **ap, gfc_intrinsic_sym *sym,
                                 : NULL);
 
          /* No pointer arguments for intrinsics.  */
-         if (gfc_check_vardef_context (actual->expr, false, context)
+         if (gfc_check_vardef_context (actual->expr, false, false, context)
                == FAILURE)
            return FAILURE;
        }
index cb46a77e444d8512086d4018513953f274592def..57338f141007361aeec81730bf6f4b8356c6a327 100644 (file)
@@ -12963,6 +12963,16 @@ Scalar default-integer constant used as STAT= return value by @code{UNLOCK} to
 denote that the lock variable is unlocked. (Fortran 2008 or later.)
 @end table
 
+The module provides the following derived type:
+
+@table @asis
+@item @code{LOCK_TYPE}:
+Derived type with private components to be use with the @code{LOCK} and
+@code{UNLOCK} statement. A variable of its type has to be always declared
+as coarray and may not appear in a variable-definition context.
+(Fortran 2008 or later.)
+@end table
+
 The module also provides the following intrinsic procedures:
 @ref{COMPILER_OPTIONS} and @ref{COMPILER_VERSION}.
 
index c2d46afdd66298b8f05ff805ed9e64da439af8ef..58c942f6d5b2cc9786b688a88c845d4be5d13f2f 100644 (file)
@@ -1531,7 +1531,7 @@ resolve_tag (const io_tag *tag, gfc_expr *e)
       char context[64];
 
       sprintf (context, _("%s tag"), tag->name);
-      if (gfc_check_vardef_context (e, false, context) == FAILURE)
+      if (gfc_check_vardef_context (e, false, false, context) == FAILURE)
        return FAILURE;
     }
   
@@ -2836,8 +2836,8 @@ gfc_resolve_dt (gfc_dt *dt, locus *loc)
       /* If we are writing, make sure the internal unit can be changed.  */
       gcc_assert (k != M_PRINT);
       if (k == M_WRITE
-         && gfc_check_vardef_context (e, false, _("internal unit in WRITE"))
-              == FAILURE)
+         && gfc_check_vardef_context (e, false, false,
+                                      _("internal unit in WRITE")) == FAILURE)
        return FAILURE;
     }
 
@@ -2866,7 +2866,7 @@ gfc_resolve_dt (gfc_dt *dt, locus *loc)
          gfc_try t;
 
          e = gfc_get_variable_expr (gfc_find_sym_in_symtree (n->sym));
-         t = gfc_check_vardef_context (e, false, NULL);
+         t = gfc_check_vardef_context (e, false, false, NULL);
          gfc_free_expr (e);
 
          if (t == FAILURE)
@@ -4032,7 +4032,7 @@ gfc_resolve_inquire (gfc_inquire *inquire)
     { \
       char context[64]; \
       sprintf (context, _("%s tag with INQUIRE"), (tag)->name); \
-      if (gfc_check_vardef_context ((expr), false, context) == FAILURE) \
+      if (gfc_check_vardef_context ((expr), false, false, context) == FAILURE) \
        return FAILURE; \
     }
   INQUIRE_RESOLVE_TAG (&tag_iomsg, inquire->iomsg);
index 8ec70745e58edc726437934745d780c7c8772c51..240a02218ab7c6ed6d8387c5138380783857d28d 100644 (file)
@@ -110,7 +110,14 @@ NAMED_FUNCTION (ISOFORTRAN_COMPILER_OPTIONS, "compiler_options", \
 NAMED_FUNCTION (ISOFORTRAN_COMPILER_VERSION, "compiler_version", \
                 GFC_ISYM_COMPILER_VERSION, GFC_STD_F2008)
 
+#ifndef NAMED_DERIVED_TYPE
+# define NAMED_DERIVED_TYPE(a,b,c,d)
+#endif
+
+NAMED_DERIVED_TYPE (ISOFORTRAN_LOCK_TYPE, "lock_type", \
+              get_int_kind_from_node (ptr_type_node), GFC_STD_F2008)
 
 #undef NAMED_INTCST
 #undef NAMED_KINDARRAY
 #undef NAMED_FUNCTION
+#undef NAMED_DERIVED_TYPE
index 89281a5c17c28131ad771be6bba460ccb22601eb..4afe4672db8a51b846797cfc90957bd2c33ccd4a 100644 (file)
@@ -1673,7 +1673,7 @@ typedef enum
   AB_ELEMENTAL, AB_PURE, AB_RECURSIVE, AB_GENERIC, AB_ALWAYS_EXPLICIT,
   AB_CRAY_POINTER, AB_CRAY_POINTEE, AB_THREADPRIVATE,
   AB_ALLOC_COMP, AB_POINTER_COMP, AB_PROC_POINTER_COMP, AB_PRIVATE_COMP,
-  AB_VALUE, AB_VOLATILE, AB_PROTECTED,
+  AB_VALUE, AB_VOLATILE, AB_PROTECTED, AB_LOCK_COMP,
   AB_IS_BIND_C, AB_IS_C_INTEROP, AB_IS_ISO_C, AB_ABSTRACT, AB_ZERO_COMP,
   AB_IS_CLASS, AB_PROCEDURE, AB_PROC_POINTER, AB_ASYNCHRONOUS, AB_CODIMENSION,
   AB_COARRAY_COMP, AB_VTYPE, AB_VTAB, AB_CONTIGUOUS, AB_CLASS_POINTER,
@@ -1716,6 +1716,7 @@ static const mstring attr_bits[] =
     minit ("VALUE", AB_VALUE),
     minit ("ALLOC_COMP", AB_ALLOC_COMP),
     minit ("COARRAY_COMP", AB_COARRAY_COMP),
+    minit ("LOCK_COMP", AB_LOCK_COMP),
     minit ("POINTER_COMP", AB_POINTER_COMP),
     minit ("PROC_POINTER_COMP", AB_PROC_POINTER_COMP),
     minit ("PRIVATE_COMP", AB_PRIVATE_COMP),
@@ -1889,6 +1890,8 @@ mio_symbol_attribute (symbol_attribute *attr)
        MIO_NAME (ab_attribute) (AB_PRIVATE_COMP, attr_bits);
       if (attr->coarray_comp)
        MIO_NAME (ab_attribute) (AB_COARRAY_COMP, attr_bits);
+      if (attr->lock_comp)
+       MIO_NAME (ab_attribute) (AB_LOCK_COMP, attr_bits);
       if (attr->zero_comp)
        MIO_NAME (ab_attribute) (AB_ZERO_COMP, attr_bits);
       if (attr->is_class)
@@ -2028,6 +2031,9 @@ mio_symbol_attribute (symbol_attribute *attr)
            case AB_COARRAY_COMP:
              attr->coarray_comp = 1;
              break;
+           case AB_LOCK_COMP:
+             attr->lock_comp = 1;
+             break;
            case AB_POINTER_COMP:
              attr->pointer_comp = 1;
              break;
@@ -5469,6 +5475,37 @@ create_int_parameter_array (const char *name, int size, gfc_expr *value,
 }
 
 
+/* Add an derived type for a given module.  */
+
+static void
+create_derived_type (const char *name, const char *modname,
+                     intmod_id module, int id)
+{
+  gfc_symtree *tmp_symtree;
+  gfc_symbol *sym;
+
+  tmp_symtree = gfc_find_symtree (gfc_current_ns->sym_root, name);
+  if (tmp_symtree != NULL)
+    {
+      if (strcmp (modname, tmp_symtree->n.sym->module) == 0)
+       return;
+      else
+       gfc_error ("Symbol '%s' already declared", name);
+    }
+
+  gfc_get_sym_tree (name, gfc_current_ns, &tmp_symtree, false);
+  sym = tmp_symtree->n.sym;
+
+  sym->module = gfc_get_string (modname);
+  sym->from_intmod = module;
+  sym->intmod_sym_id = id;
+  sym->attr.flavor = FL_DERIVED;
+  sym->attr.private_comp = 1;
+  sym->attr.zero_comp = 1;
+  sym->attr.use_assoc = 1;
+}
+
+
 
 /* USE the ISO_FORTRAN_ENV intrinsic module.  */
 
@@ -5489,6 +5526,9 @@ use_iso_fortran_env_module (void)
 #define NAMED_KINDARRAY(a,b,c,d) { a, b, 0, d },
 #include "iso-fortran-env.def"
 #undef NAMED_KINDARRAY
+#define NAMED_DERIVED_TYPE(a,b,c,d) { a, b, 0, d },
+#include "iso-fortran-env.def"
+#undef NAMED_DERIVED_TYPE
 #define NAMED_FUNCTION(a,b,c,d) { a, b, c, d },
 #include "iso-fortran-env.def"
 #undef NAMED_FUNCTION
@@ -5573,6 +5613,16 @@ use_iso_fortran_env_module (void)
 #include "iso-fortran-env.def"
 #undef NAMED_KINDARRAY
 
+#define NAMED_DERIVED_TYPE(a,b,TYPE,STD) \
+               case a:
+#include "iso-fortran-env.def"
+                  create_derived_type (u->local_name[0] ? u->local_name
+                                                       : u->use_name,
+                                      mod, INTMOD_ISO_FORTRAN_ENV,
+                                      symbol[i].id);
+                 break;
+#undef NAMED_DERIVED_TYPE
+
 #define NAMED_FUNCTION(a,b,c,d) \
                case a:
 #include "iso-fortran-env.def"
@@ -5626,6 +5676,14 @@ use_iso_fortran_env_module (void)
 #include "iso-fortran-env.def"
 #undef NAMED_KINDARRAY
 
+#define NAMED_DERIVED_TYPE(a,b,TYPE,STD) \
+         case a:
+#include "iso-fortran-env.def"
+           create_derived_type (symbol[i].name, mod, INTMOD_ISO_FORTRAN_ENV,
+                                symbol[i].id);
+           break;
+#undef NAMED_DERIVED_TYPE
+
 #define NAMED_FUNCTION(a,b,c,d) \
                case a:
 #include "iso-fortran-env.def"
index 5ce5c1e042a393dea6542835aa655135af18fda5..ba28648ec2cdb1693fa852b2ffb6b3c40a9d641d 100644 (file)
@@ -2143,6 +2143,13 @@ endType:
          || (c->attr.coarray_comp && !c->attr.pointer && !c->attr.allocatable))
        sym->attr.coarray_comp = 1;
 
+      /* Looking for lock_type components.  */
+      if (c->attr.lock_comp
+         || (sym->ts.type == BT_DERIVED
+             && c->ts.u.derived->from_intmod == INTMOD_ISO_FORTRAN_ENV
+             && c->ts.u.derived->intmod_sym_id == ISOFORTRAN_LOCK_TYPE))
+       sym->attr.lock_comp = 1;
+
       /* Look for private components.  */
       if (sym->component_access == ACCESS_PRIVATE
          || c->attr.access == ACCESS_PRIVATE
index cec45cab44d661936269528b193cc42a172ca5a8..f484a223f9b1de9c7178db06ba3f05d20f6204df 100644 (file)
@@ -6235,7 +6235,7 @@ gfc_resolve_iterator (gfc_iterator *iter, bool real_ok)
       == FAILURE)
     return FAILURE;
 
-  if (gfc_check_vardef_context (iter->var, false, _("iterator variable"))
+  if (gfc_check_vardef_context (iter->var, false, false, _("iterator variable"))
       == FAILURE)
     return FAILURE;
 
@@ -6502,9 +6502,11 @@ resolve_deallocate_expr (gfc_expr *e)
     }
 
   if (pointer
-      && gfc_check_vardef_context (e, true, _("DEALLOCATE object")) == FAILURE)
+      && gfc_check_vardef_context (e, true, true, _("DEALLOCATE object"))
+        == FAILURE)
     return FAILURE;
-  if (gfc_check_vardef_context (e, false, _("DEALLOCATE object")) == FAILURE)
+  if (gfc_check_vardef_context (e, false, true, _("DEALLOCATE object"))
+      == FAILURE)
     return FAILURE;
 
   return SUCCESS;
@@ -6796,6 +6798,21 @@ resolve_allocate_expr (gfc_expr *e, gfc_code *code)
                      &e->where, &code->expr3->where);
          goto failure;
        }
+
+      /* Check F2008, C642.  */
+      if (code->expr3->ts.type == BT_DERIVED
+         && ((codimension &&  gfc_expr_attr (code->expr3).lock_comp)
+             || (code->expr3->ts.u.derived->from_intmod
+                    == INTMOD_ISO_FORTRAN_ENV
+                 && code->expr3->ts.u.derived->intmod_sym_id
+                    == ISOFORTRAN_LOCK_TYPE)))
+       {
+         gfc_error ("The source-expr at %L shall neither be of type "
+                    "LOCK_TYPE nor have a LOCK_TYPE component if "
+                     "allocate-object at %L is a coarray",
+                     &code->expr3->where, &e->where);
+         goto failure;
+       }
     }
 
   /* Check F08:C629.  */
@@ -6814,9 +6831,9 @@ resolve_allocate_expr (gfc_expr *e, gfc_code *code)
   e2 = remove_last_array_ref (e);
   t = SUCCESS;
   if (t == SUCCESS && pointer)
-    t = gfc_check_vardef_context (e2, true, _("ALLOCATE object"));
+    t = gfc_check_vardef_context (e2, true, true, _("ALLOCATE object"));
   if (t == SUCCESS)
-    t = gfc_check_vardef_context (e2, false, _("ALLOCATE object"));
+    t = gfc_check_vardef_context (e2, false, true, _("ALLOCATE object"));
   gfc_free_expr (e2);
   if (t == FAILURE)
     goto failure;
@@ -6992,7 +7009,7 @@ resolve_allocate_deallocate (gfc_code *code, const char *fcn)
   /* Check the stat variable.  */
   if (stat)
     {
-      gfc_check_vardef_context (stat, false, _("STAT variable"));
+      gfc_check_vardef_context (stat, false, false, _("STAT variable"));
 
       if ((stat->ts.type != BT_INTEGER
           && !(stat->ref && (stat->ref->type == REF_ARRAY
@@ -7035,7 +7052,7 @@ resolve_allocate_deallocate (gfc_code *code, const char *fcn)
        gfc_warning ("ERRMSG at %L is useless without a STAT tag",
                     &errmsg->where);
 
-      gfc_check_vardef_context (errmsg, false, _("ERRMSG variable"));
+      gfc_check_vardef_context (errmsg, false, false, _("ERRMSG variable"));
 
       if ((errmsg->ts.type != BT_CHARACTER
           && !(errmsg->ref
@@ -8100,7 +8117,8 @@ resolve_transfer (gfc_code *code)
      code->ext.dt may be NULL if the TRANSFER is related to
      an INQUIRE statement -- but in this case, we are not reading, either.  */
   if (code->ext.dt && code->ext.dt->dt_io_kind->value.iokind == M_READ
-      && gfc_check_vardef_context (exp, false, _("item in READ")) == FAILURE)
+      && gfc_check_vardef_context (exp, false, false, _("item in READ"))
+        == FAILURE)
     return;
 
   sym = exp->symtree->n.sym;
@@ -8201,13 +8219,15 @@ find_reachable_labels (gfc_code *block)
 static void
 resolve_lock_unlock (gfc_code *code)
 {
-  /* FIXME: Add more lock-variable checks. For now, always reject it.
-     Note that ISO_FORTRAN_ENV's LOCK_TYPE is not yet available.  */
-  /* if (code->expr2->ts.type != BT_DERIVED
-        || code->expr2->rank != 0
-        || code->expr2->expr_type != EXPR_VARIABLE)  */
-  gfc_error ("Lock variable at %L must be a scalar of type LOCK_TYPE",
-            &code->expr1->where);
+  if (code->expr1->ts.type != BT_DERIVED
+      || code->expr1->expr_type != EXPR_VARIABLE
+      || code->expr1->ts.u.derived->from_intmod != INTMOD_ISO_FORTRAN_ENV
+      || code->expr1->ts.u.derived->intmod_sym_id != ISOFORTRAN_LOCK_TYPE
+      || code->expr1->rank != 0
+      || !(gfc_expr_attr (code->expr1).codimension
+          || gfc_is_coindexed (code->expr1)))
+    gfc_error ("Lock variable at %L must be a scalar coarray of type "
+              "LOCK_TYPE", &code->expr1->where);
 
   /* Check STAT.  */
   if (code->expr2
@@ -8216,6 +8236,11 @@ resolve_lock_unlock (gfc_code *code)
     gfc_error ("STAT= argument at %L must be a scalar INTEGER variable",
               &code->expr2->where);
 
+  if (code->expr2
+      && gfc_check_vardef_context (code->expr2, false, false,
+                                  _("STAT variable")) == FAILURE)
+    return;
+
   /* Check ERRMSG.  */
   if (code->expr3
       && (code->expr3->ts.type != BT_CHARACTER || code->expr3->rank != 0
@@ -8223,12 +8248,22 @@ resolve_lock_unlock (gfc_code *code)
     gfc_error ("ERRMSG= argument at %L must be a scalar CHARACTER variable",
               &code->expr3->where);
 
+  if (code->expr3
+      && gfc_check_vardef_context (code->expr3, false, false,
+                                  _("ERRMSG variable")) == FAILURE)
+    return;
+
   /* Check ACQUIRED_LOCK.  */
   if (code->expr4
       && (code->expr4->ts.type != BT_LOGICAL || code->expr4->rank != 0
          || code->expr4->expr_type != EXPR_VARIABLE))
     gfc_error ("ACQUIRED_LOCK= argument at %L must be a scalar LOGICAL "
               "variable", &code->expr4->where);
+
+  if (code->expr4
+      && gfc_check_vardef_context (code->expr4, false, false,
+                                  _("ACQUIRED_LOCK variable")) == FAILURE)
+    return;
 }
 
 
@@ -9143,8 +9178,8 @@ resolve_code (gfc_code *code, gfc_namespace *ns)
          if (t == FAILURE)
            break;
 
-         if (gfc_check_vardef_context (code->expr1, false, _("assignment"))
-               == FAILURE)
+         if (gfc_check_vardef_context (code->expr1, false, false,
+                                       _("assignment")) == FAILURE)
            break;
 
          if (resolve_ordinary_assign (code, ns))
@@ -9182,9 +9217,11 @@ resolve_code (gfc_code *code, gfc_namespace *ns)
               array ref may be present on the LHS and fool gfc_expr_attr
               used in gfc_check_vardef_context.  Remove it.  */
            e = remove_last_array_ref (code->expr1);
-           t = gfc_check_vardef_context (e, true, _("pointer assignment"));
+           t = gfc_check_vardef_context (e, true, false,
+                                         _("pointer assignment"));
            if (t == SUCCESS)
-             t = gfc_check_vardef_context (e, false, _("pointer assignment"));
+             t = gfc_check_vardef_context (e, false, false,
+                                           _("pointer assignment"));
            gfc_free_expr (e);
            if (t == FAILURE)
              break;
@@ -12340,6 +12377,17 @@ resolve_symbol (gfc_symbol *sym)
                         sym->ts.u.derived->name) == FAILURE)
     return;
 
+  /* F2008, C1302.  */
+  if (sym->ts.type == BT_DERIVED
+      && sym->ts.u.derived->from_intmod == INTMOD_ISO_FORTRAN_ENV
+      && sym->ts.u.derived->intmod_sym_id == ISOFORTRAN_LOCK_TYPE
+      && !sym->attr.codimension)
+    {
+      gfc_error ("Variable '%s' at %L of type LOCK_TYPE must be a coarray",
+                sym->name, &sym->declared_at);
+      return;
+    }
+
   /* An assumed-size array with INTENT(OUT) shall not be of a type for which
      default initialization is defined (5.1.2.4.4).  */
   if (sym->ts.type == BT_DERIVED
@@ -12360,6 +12408,12 @@ resolve_symbol (gfc_symbol *sym)
        }
     }
 
+  /* F2008, C542.  */
+  if (sym->ts.type == BT_DERIVED && sym->attr.dummy
+      && sym->attr.intent == INTENT_OUT && sym->attr.lock_comp)
+    gfc_error ("Dummy argument '%s' at %L of LOCK_TYPE shall not be "
+              "INTENT(OUT)", sym->name, &sym->declared_at);
+
   /* F2008, C526.  */
   if (((sym->ts.type == BT_DERIVED && sym->ts.u.derived->attr.coarray_comp)
        || sym->attr.codimension)
index 183778f2d68f870627d79543131f1a0b31320743..a5f2d9efb9a33308dbc7f30d396a8e0cd9ce10c1 100644 (file)
@@ -652,6 +652,48 @@ gfc_trans_stop (gfc_code *code, bool error_stop)
 }
 
 
+tree
+gfc_trans_lock_unlock (gfc_code *code, gfc_exec_op type ATTRIBUTE_UNUSED)
+{
+  gfc_se se, argse;
+  tree stat = NULL_TREE, lock_acquired = NULL_TREE;
+
+  /* Short cut: For single images without STAT= or LOCK_ACQUIRED
+     return early. (ERRMSG= is always untouched for -fcoarray=single.)  */
+  if (!code->expr2 && !code->expr4 && gfc_option.coarray != GFC_FCOARRAY_LIB)
+    return NULL_TREE; 
+
+  gfc_init_se (&se, NULL);
+  gfc_start_block (&se.pre);
+
+  if (code->expr2)
+    {
+      gcc_assert (code->expr2->expr_type == EXPR_VARIABLE);
+      gfc_init_se (&argse, NULL);
+      gfc_conv_expr_val (&argse, code->expr2);
+      stat = argse.expr;
+    }
+
+  if (code->expr4)
+    {
+      gcc_assert (code->expr4->expr_type == EXPR_VARIABLE);
+      gfc_init_se (&argse, NULL);
+      gfc_conv_expr_val (&argse, code->expr4);
+      lock_acquired = argse.expr;
+    }
+
+  if (stat != NULL_TREE)
+    gfc_add_modify (&se.pre, stat, build_int_cst (TREE_TYPE (stat), 0));
+
+  if (lock_acquired != NULL_TREE)
+    gfc_add_modify (&se.pre, lock_acquired,
+                   fold_convert (TREE_TYPE (lock_acquired),
+                                 boolean_true_node));
+
+  return gfc_finish_block (&se.pre);
+}
+
+
 tree
 gfc_trans_sync (gfc_code *code, gfc_exec_op type)
 {
index 8b77750c589ff33ba8e42b92ea5f63adad1fd44d..2d0faf17fb7c49db61dc175d4ebde1df33dbb2ce 100644 (file)
@@ -54,6 +54,7 @@ tree gfc_trans_do (gfc_code *, tree);
 tree gfc_trans_do_while (gfc_code *);
 tree gfc_trans_select (gfc_code *);
 tree gfc_trans_sync (gfc_code *, gfc_exec_op);
+tree gfc_trans_lock_unlock (gfc_code *, gfc_exec_op);
 tree gfc_trans_forall (gfc_code *);
 tree gfc_trans_where (gfc_code *);
 tree gfc_trans_allocate (gfc_code *);
index ee35387a7d9dd62f13d89f27882de31b7c3cdbd5..33593c5626adb85f0fd52e9436d2acc493fa9344 100644 (file)
@@ -1318,6 +1318,11 @@ trans_code (gfc_code * code, tree cond)
          res = gfc_trans_sync (code, code->op);
          break;
 
+       case EXEC_LOCK:
+       case EXEC_UNLOCK:
+         res = gfc_trans_lock_unlock (code, code->op);
+         break;
+
        case EXEC_FORALL:
          res = gfc_trans_forall (code);
          break;
index 7939b52153bc22c81caddb16daee814277e65b36..f18487f74b46d8eac7fd1262ccf8fe18364f64ff 100644 (file)
@@ -1,3 +1,10 @@
+2011-06-20  Tobias Burnus  <burnus@net-b.de>
+
+       PR fortran/18918
+       * gfortran.dg/coarray_lock_1.f90: Update dg-error.
+       * gfortran.dg/coarray_lock_3.f90: New.
+       * gfortran.dg/coarray/lock_1.f90: New.
+
 2011-06-20  Janis Johnson  <janisjo@codesourcery.com>
 
        * lib/scandump.exp (scan-dump, scan-dump-times, scan-dump-not,
diff --git a/gcc/testsuite/gfortran.dg/coarray/lock_1.f90 b/gcc/testsuite/gfortran.dg/coarray/lock_1.f90
new file mode 100644 (file)
index 0000000..db4fbc8
--- /dev/null
@@ -0,0 +1,32 @@
+! { dg-do run }
+!
+! LOCK/UNLOCK check
+!
+! PR fortran/18918
+!
+
+use iso_fortran_env
+implicit none
+
+type(lock_type) :: lock[*]
+integer :: stat
+logical :: acquired
+
+LOCK(lock)
+UNLOCK(lock)
+
+stat = 99
+LOCK(lock, stat=stat)
+if (stat /= 0) call abort()
+stat = 99
+UNLOCK(lock, stat=stat)
+if (stat /= 0) call abort()
+
+if (this_image() == 1) then
+  acquired = .false.
+  LOCK (lock[this_image()], acquired_lock=acquired)
+  if (.not. acquired) call abort()
+  UNLOCK (lock[1])
+end if
+end
+
index 419ba47bab1c156e2e079701d30e7d06357b7059..f9ef581985066ea7e004b127f897675dfec73a59 100644 (file)
@@ -10,6 +10,6 @@ integer :: s
 character(len=3) :: c
 logical :: bool
 
-LOCK (a, stat=s, acquired_lock=bool, errmsg=c) ! { dg-error "must be a scalar of type LOCK_TYPE" }
-UNLOCK (a, stat=s, errmsg=c) ! { dg-error "must be a scalar of type LOCK_TYPE" }
+LOCK (a, stat=s, acquired_lock=bool, errmsg=c) ! { dg-error "must be a scalar coarray of type LOCK_TYPE" }
+UNLOCK (a, stat=s, errmsg=c) ! { dg-error "must be a scalar coarray of type LOCK_TYPE" }
 end
diff --git a/gcc/testsuite/gfortran.dg/coarray_lock_3.f90 b/gcc/testsuite/gfortran.dg/coarray_lock_3.f90
new file mode 100644 (file)
index 0000000..5e4c73f
--- /dev/null
@@ -0,0 +1,107 @@
+! { dg-do compile }
+! { dg-options "-fcoarray=single" }
+!
+!
+! LOCK/LOCK_TYPE checks 
+!
+subroutine extends()
+use iso_fortran_env
+type t
+end type t
+type, extends(t) :: t2 ! { dg-error "coarray component, parent type .t. shall also have one" }
+  type(lock_type), allocatable :: c(:)[:]
+end type t2
+end subroutine extends
+
+module m
+  use iso_fortran_env
+
+  type t
+    type(lock_type), allocatable :: x(:)[:]
+  end type t
+
+  type t2
+    type(lock_type), allocatable :: x
+  end type t2
+end module m
+
+subroutine sub(x)
+  use iso_fortran_env
+  type(lock_type), intent(out) :: x[*] ! OK
+end subroutine sub
+
+subroutine sub1(x) ! { dg-error "is INTENT.OUT. and can thus not be an allocatable coarray or have coarray components" }
+  use iso_fortran_env
+  type(lock_type), allocatable, intent(out) :: x(:)[:]
+end subroutine sub1
+
+subroutine sub2(x) ! { dg-error "is INTENT.OUT. and can thus not be an allocatable coarray or have coarray components" }
+  use m
+  type(t), intent(out) :: x
+end subroutine sub2
+
+subroutine sub3(x) ! { dg-error "with coarray component shall be a nonpointer, nonallocatable scalar" }
+  use m
+  type(t), intent(inout) :: x[*]
+end subroutine sub3
+
+subroutine sub4(x)
+  use m
+  type(t2), intent(inout) :: x[*] ! OK
+end subroutine sub4
+
+subroutine lock_test
+  use iso_fortran_env
+  type t
+  end type t
+  type(lock_type) :: lock ! { dg-error "type LOCK_TYPE must be a coarray" }
+end subroutine lock_test
+
+subroutine lock_test2
+  use iso_fortran_env
+  implicit none
+  type t
+  end type t
+  type(t) :: x
+  type(lock_type), save :: lock[*],lock2(2)[*]
+  lock(t) ! { dg-error "Syntax error in LOCK statement" }
+  lock(x) ! { dg-error "must be a scalar coarray of type LOCK_TYPE" }
+  lock(lock)
+  lock(lock2(1))
+  lock(lock2) ! { dg-error "must be a scalar coarray of type LOCK_TYPE" }
+  lock(lock[1]) ! { dg-error "must be a scalar coarray of type LOCK_TYPE" }
+end subroutine lock_test2
+
+
+subroutine lock_test3
+  use iso_fortran_env
+  type(lock_type), save :: a[*], b[*]
+  a = b ! { dg-error "LOCK_TYPE in variable definition context" }
+  b = lock_type() ! { dg-error "LOCK_TYPE in variable definition context" }
+  print *, a ! { dg-error "cannot have PRIVATE components" }
+end subroutine lock_test3
+
+
+subroutine lock_test4
+  use iso_fortran_env
+  type(lock_type), allocatable :: A(:)[:]
+  logical :: ob
+  allocate(A(1)[*])
+  lock(A(1), acquired_lock=ob)
+  unlock(A(1))
+  deallocate(A)
+end subroutine lock_test4
+
+
+subroutine argument_check()
+  use iso_fortran_env
+  type(lock_type), SAVE :: ll[*]
+  call no_interface(ll) ! { dg-error "Actual argument of LOCK_TYPE or with LOCK_TYPE component at .1. requires an explicit interface" }
+  call test(ll) ! { dg-error "non-INTENT.INOUT. dummy .x. at .1., which is LOCK_TYPE or has a LOCK_TYPE component" }
+contains
+  subroutine test(x)
+    type(lock_type), intent(in) :: x[*]
+  end subroutine test
+end subroutine argument_check
+
+! { dg-final { cleanup-modules "m" } }