check.c (gfc_check_event_query): New function.
authorTobias Burnus <burnus@net-b.de>
Wed, 2 Dec 2015 21:59:05 +0000 (22:59 +0100)
committerSteven G. Kargl <kargl@gcc.gnu.org>
Wed, 2 Dec 2015 21:59:05 +0000 (21:59 +0000)
2015-12-02  Tobias Burnus  <burnus@net-b.de>
    Alessandro Fanfarillo <fanfarillo.gcc@gmail.com>

* check.c (gfc_check_event_query): New function.
* dump-parse-tree.c (show_code_node): Handle EXEC_EVENT_POST,
EXEC_EVENT_WAIT.
* expr.c (gfc_check_vardef_context): New check for event variables
definition.
* gfortran.h (gfc_statement): Add ST_EVENT_POST, ST_EVENT_WAIT.
(gfc_isym_id): GFC_ISYM_EVENT_QUERY.
(struct symbol_attribute): New field.
(gfc_exec_op): Add EXEC_EVENT_POST and EXEC_EVENT_WAIT.
* gfortran.texi: Document about new events functions and minor
changes.
* interface.c (compare_parameter): New check.
(gfc_procedure_use): New check for explicit procedure interface.
(add_subroutines): Add event_query.
* intrinsic.h (gfc_check_event_query,gfc_resolve_event_query):
New prototypes.
* iresolve.c (gfc_resolve_event_query): New function.
* iso-fortran-env.def (event_type): New type.
* match.c (event_statement,gfc_match_event_post,gfc_match_event_wait):
New functions.
(gfc_match_name): New event post and event wait.
* match.h (gfc_match_event_post,gfc_match_event_wait):
New prototypes.
* module.c (ab_attribute): Add AB_EVENT_COMP.
(attr_bits): Likewise.
(mio_symbol_attribute): Handle event_comp attribute.
* parse.c (decode_statement): Add ST_EVENT_POST, ST_EVENT_WAIT.
(next_statement): Add ST_EVENT_POST, ST_EVENT_WAIT.
(gfc_ascii_statement): Add ST_EVENT_POST, ST_EVENT_WAIT.
(parse_derived): Check for event_type components.
* resolve.c (resolve_allocate_expr): Check for event variable def.
(resolve_lock_unlock): Renamed to resolve_lock_unlock_event. It
includes logic for locks and events.
(gfc_resolve_code): Call it.
(gfc_resolve_symbol): New check for event variable to be a corray.
* st.c (gfc_free_statement): Handle new EXEC_EVENT_POST and
EXEC_EVENT_WAIT.
* trans-decl.c (gfor_fndecl_caf_event_post,gfor_fndecl_caf_event_wait,
gfor_fndecl_caf_event_query): New global variables.
(generate_coarray_sym_init): Checking for event_type.
(gfc_conv_procedure_call): Check for C bind attribute.
* trans-intrinsic.c (conv_intrinsic_event_query): New function.
(conv_intrinsic_move_alloc): Call it.
* trans-stmt.c (gfc_trans_lock_unlock): Passing address
of actual argument.
(gfc_trans_sync): Likewise.
(gfc_trans_event_post_wait): New function.
* trans-stmt.h (gfc_trans_event_post_wait): New prototype.
* trans-types.c (gfc_get_derived_type): Integer_kind as event_type.
* trans.c (gfc_allocate_using_lib): New argument and logic for events.
(gfc_allocate_allocatable): Passing new argument.
(trans_code): Handle EXEC_EVENT_POST, EXEC_EVENT_WAIT.
* trans.h (gfc_coarray_type): New elements.
(gfor_fndecl_caf_event_post,gfor_fndecl_caf_event_wait,
gfor_fndecl_caf_event_query): Declare them.

2015-12-02  Tobias Burnus  <burnus@net-b.de>
    Alessandro Fanfarillo <fanfarillo.gcc@gmail.com>

* gfortran.dg/coarray/event_1.f90: New.
* gfortran.dg/coarray/event_2.f90: New.

Co-Authored-By: Alessandro Fanfarillo <fanfarillo.gcc@gmail.com>
From-SVN: r231208

31 files changed:
gcc/fortran/ChangeLog
gcc/fortran/check.c
gcc/fortran/dump-parse-tree.c
gcc/fortran/expr.c
gcc/fortran/gfortran.h
gcc/fortran/gfortran.texi
gcc/fortran/interface.c
gcc/fortran/intrinsic.c
gcc/fortran/intrinsic.h
gcc/fortran/iresolve.c
gcc/fortran/iso-fortran-env.def
gcc/fortran/match.c
gcc/fortran/match.h
gcc/fortran/module.c
gcc/fortran/parse.c
gcc/fortran/resolve.c
gcc/fortran/st.c
gcc/fortran/trans-decl.c
gcc/fortran/trans-expr.c
gcc/fortran/trans-intrinsic.c
gcc/fortran/trans-stmt.c
gcc/fortran/trans-stmt.h
gcc/fortran/trans-types.c
gcc/fortran/trans.c
gcc/fortran/trans.h
gcc/testsuite/ChangeLog
gcc/testsuite/gfortran.dg/coarray/event_1.f90 [new file with mode: 0644]
gcc/testsuite/gfortran.dg/coarray/event_2.f90 [new file with mode: 0644]
libgfortran/ChangeLog
libgfortran/caf/libcaf.h
libgfortran/caf/single.c

index 40c8de6bad0128d47e7221b82082ec4794250866..7617a1adf7cb471de0fcff0b82324c2bcbcada49 100644 (file)
@@ -1,3 +1,62 @@
+2015-12-02  Tobias Burnus  <burnus@net-b.de>
+           Alessandro Fanfarillo <fanfarillo.gcc@gmail.com>
+
+       * check.c (gfc_check_event_query): New function.
+       * dump-parse-tree.c (show_code_node): Handle EXEC_EVENT_POST,
+       EXEC_EVENT_WAIT.
+       * expr.c (gfc_check_vardef_context): New check for event variables
+       definition.
+       * gfortran.h (gfc_statement): Add ST_EVENT_POST, ST_EVENT_WAIT.
+       (gfc_isym_id): GFC_ISYM_EVENT_QUERY.
+       (struct symbol_attribute): New field.
+       (gfc_exec_op): Add EXEC_EVENT_POST and EXEC_EVENT_WAIT.
+       * gfortran.texi: Document about new events functions and minor
+       changes.
+       * interface.c (compare_parameter): New check.
+       (gfc_procedure_use): New check for explicit procedure interface.
+       (add_subroutines): Add event_query.
+       * intrinsic.h (gfc_check_event_query,gfc_resolve_event_query):
+       New prototypes.
+       * iresolve.c (gfc_resolve_event_query): New function.
+       * iso-fortran-env.def (event_type): New type.
+       * match.c (event_statement,gfc_match_event_post,gfc_match_event_wait):
+       New functions.
+       (gfc_match_name): New event post and event wait.
+       * match.h (gfc_match_event_post,gfc_match_event_wait):
+       New prototypes.
+       * module.c (ab_attribute): Add AB_EVENT_COMP.
+       (attr_bits): Likewise.
+       (mio_symbol_attribute): Handle event_comp attribute.
+       * parse.c (decode_statement): Add ST_EVENT_POST, ST_EVENT_WAIT.
+       (next_statement): Add ST_EVENT_POST, ST_EVENT_WAIT.
+       (gfc_ascii_statement): Add ST_EVENT_POST, ST_EVENT_WAIT.
+       (parse_derived): Check for event_type components.
+       * resolve.c (resolve_allocate_expr): Check for event variable def.
+       (resolve_lock_unlock): Renamed to resolve_lock_unlock_event. It
+       includes logic for locks and events.
+       (gfc_resolve_code): Call it.
+       (gfc_resolve_symbol): New check for event variable to be a corray.
+       * st.c (gfc_free_statement): Handle new EXEC_EVENT_POST and
+       EXEC_EVENT_WAIT.
+       * trans-decl.c (gfor_fndecl_caf_event_post,gfor_fndecl_caf_event_wait,
+       gfor_fndecl_caf_event_query): New global variables.
+       (generate_coarray_sym_init): Checking for event_type.
+       (gfc_conv_procedure_call): Check for C bind attribute.
+       * trans-intrinsic.c (conv_intrinsic_event_query): New function.
+       (conv_intrinsic_move_alloc): Call it.
+       * trans-stmt.c (gfc_trans_lock_unlock): Passing address
+       of actual argument.
+       (gfc_trans_sync): Likewise.
+       (gfc_trans_event_post_wait): New function.
+       * trans-stmt.h (gfc_trans_event_post_wait): New prototype.
+       * trans-types.c (gfc_get_derived_type): Integer_kind as event_type.
+       * trans.c (gfc_allocate_using_lib): New argument and logic for events.
+       (gfc_allocate_allocatable): Passing new argument.
+       (trans_code): Handle EXEC_EVENT_POST, EXEC_EVENT_WAIT.
+       * trans.h (gfc_coarray_type): New elements.
+       (gfor_fndecl_caf_event_post,gfor_fndecl_caf_event_wait,
+       gfor_fndecl_caf_event_query): Declare them.
+
 2015-12-02  Cesar Philippidis  <cesar@codesourcery.com>
 
        PR fortran/63861
index 038ee218d9450207301ace67386bec1d785eae9f..6dc7f3e264b86bb1eeebea25332e6b38b5916c42 100644 (file)
@@ -1157,6 +1157,59 @@ gfc_check_atomic_cas (gfc_expr *atom, gfc_expr *old, gfc_expr *compare,
   return true;
 }
 
+bool
+gfc_check_event_query (gfc_expr *event, gfc_expr *count, gfc_expr *stat)
+{
+  if (event->ts.type != BT_DERIVED
+      || event->ts.u.derived->from_intmod != INTMOD_ISO_FORTRAN_ENV
+      || event->ts.u.derived->intmod_sym_id != ISOFORTRAN_EVENT_TYPE)
+    {
+      gfc_error ("EVENT argument at %L to the intrinsic EVENT_QUERY "
+                "shall be of type EVENT_TYPE", &event->where);
+      return false;
+    }
+
+  if (!scalar_check (event, 0))
+    return false;
+
+  if (!gfc_check_vardef_context (count, false, false, false, NULL))
+    {
+      gfc_error ("COUNT argument of the EVENT_QUERY intrinsic function at %L "
+                "shall be definable", &count->where);
+      return false;
+    }
+
+  if (!type_check (count, 1, BT_INTEGER))
+    return false;
+
+  int i = gfc_validate_kind (BT_INTEGER, count->ts.kind, false);
+  int j = gfc_validate_kind (BT_INTEGER, gfc_default_integer_kind, false);
+
+  if (gfc_integer_kinds[i].range < gfc_integer_kinds[j].range)
+    {
+      gfc_error ("COUNT argument of the EVENT_QUERY intrinsic function at %L "
+                "shall have at least the range of the default integer",
+                &count->where);
+      return false;
+    }
+
+  if (stat != NULL)
+    {
+      if (!type_check (stat, 2, BT_INTEGER))
+       return false;
+      if (!scalar_check (stat, 2))
+       return false;
+      if (!variable_check (stat, 2, false))
+       return false;
+
+      if (!gfc_notify_std (GFC_STD_F2008_TS, "STAT= argument to %s at %L",
+                          gfc_current_intrinsic, &stat->where))
+       return false;
+    }
+
+  return true;
+}
+
 
 bool
 gfc_check_atomic_fetch_op (gfc_expr *atom, gfc_expr *value, gfc_expr *old,
index f9abf406fea3f31052a8089fabc12903b711dcbb..dad5c18439af79807d7e8e42b2aa8cd6deee8a12 100644 (file)
@@ -1673,6 +1673,33 @@ show_code_node (int level, gfc_code *c)
        }
       break;
 
+    case EXEC_EVENT_POST:
+    case EXEC_EVENT_WAIT:
+      if (c->op == EXEC_EVENT_POST)
+       fputs ("EVENT POST ", dumpfile);
+      else
+       fputs ("EVENT WAIT ", dumpfile);
+
+      fputs ("event-variable=", dumpfile);
+      if (c->expr1 != NULL)
+       show_expr (c->expr1);
+      if (c->expr4 != NULL)
+       {
+         fputs (" until_count=", dumpfile);
+         show_expr (c->expr4);
+       }
+      if (c->expr2 != NULL)
+       {
+         fputs (" stat=", dumpfile);
+         show_expr (c->expr2);
+       }
+      if (c->expr3 != NULL)
+       {
+         fputs (" errmsg=", dumpfile);
+         show_expr (c->expr3);
+       }
+      break;
+
     case EXEC_LOCK:
     case EXEC_UNLOCK:
       if (c->op == EXEC_LOCK)
index 7aaf0e252a0224da874214a1b03ddc39b4e27e9f..2aeb0b5f94604111817e9016b42d0d6b071c2696 100644 (file)
@@ -4860,6 +4860,19 @@ gfc_check_vardef_context (gfc_expr* e, bool pointer, bool alloc_obj,
       return false;
     }
 
+  /* TS18508, C702/C203.  */
+  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_EVENT_TYPE)))
+    {
+      if (context)
+       gfc_error ("LOCK_EVENT in variable definition context (%s) at %L",
+                  context, &e->where);
+      return false;
+    }
+
   /* INTENT(IN) dummy argument.  Check this, unless the object itself is the
      component of sub-component of a pointer; we need to distinguish
      assignment to a pointer component from pointer-assignment to a pointer
index 92bf633f29c85f9e1d1496a0848b21762ac9db86..9f61e4522c4d3c53187595ffa24f548ed060f109 100644 (file)
@@ -241,7 +241,8 @@ enum gfc_statement
   ST_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD,
   ST_OMP_END_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD,
   ST_PROCEDURE, ST_GENERIC, ST_CRITICAL, ST_END_CRITICAL,
-  ST_GET_FCN_CHARACTERISTICS, ST_LOCK, ST_UNLOCK, ST_NONE
+  ST_GET_FCN_CHARACTERISTICS, ST_LOCK, ST_UNLOCK, ST_EVENT_POST,
+  ST_EVENT_WAIT,ST_NONE
 };
 
 /* Types of interfaces that we can have.  Assignment interfaces are
@@ -393,6 +394,7 @@ enum gfc_isym_id
   GFC_ISYM_ERFC,
   GFC_ISYM_ERFC_SCALED,
   GFC_ISYM_ETIME,
+  GFC_ISYM_EVENT_QUERY,
   GFC_ISYM_EXECUTE_COMMAND_LINE,
   GFC_ISYM_EXIT,
   GFC_ISYM_EXP,
@@ -828,7 +830,7 @@ typedef struct
      entities.  */
   unsigned alloc_comp:1, pointer_comp:1, proc_pointer_comp:1,
           private_comp:1, zero_comp:1, coarray_comp:1, lock_comp:1,
-          defined_assign_comp:1, unlimited_polymorphic:1;
+          event_comp:1, defined_assign_comp:1, unlimited_polymorphic:1;
 
   /* This is a temporary selector for SELECT TYPE or an associate
      variable for SELECT_TYPE or ASSOCIATE.  */
@@ -2366,7 +2368,7 @@ enum gfc_exec_op
   EXEC_OPEN, EXEC_CLOSE, EXEC_WAIT,
   EXEC_READ, EXEC_WRITE, EXEC_IOLENGTH, EXEC_TRANSFER, EXEC_DT_END,
   EXEC_BACKSPACE, EXEC_ENDFILE, EXEC_INQUIRE, EXEC_REWIND, EXEC_FLUSH,
-  EXEC_LOCK, EXEC_UNLOCK,
+  EXEC_LOCK, EXEC_UNLOCK, EXEC_EVENT_POST, EXEC_EVENT_WAIT,
   EXEC_OACC_KERNELS_LOOP, EXEC_OACC_PARALLEL_LOOP, EXEC_OACC_ROUTINE,
   EXEC_OACC_PARALLEL, EXEC_OACC_KERNELS, EXEC_OACC_DATA, EXEC_OACC_HOST_DATA,
   EXEC_OACC_LOOP, EXEC_OACC_UPDATE, EXEC_OACC_WAIT, EXEC_OACC_CACHE,
index 876f22663d5717b14df912a5a9f4276d4c40466e..d82ded61dcf5bbfad42f3ee5bc614f7e529af97d 100644 (file)
@@ -3342,7 +3342,9 @@ typedef enum caf_register_t {
   CAF_REGTYPE_COARRAY_ALLOC,
   CAF_REGTYPE_LOCK_STATIC,
   CAF_REGTYPE_LOCK_ALLOC,
-  CAF_REGTYPE_CRITICAL
+  CAF_REGTYPE_CRITICAL,
+  CAF_REGTYPE_EVENT_STATIC,
+  CAF_REGTYPE_EVENT_ALLOC
 }
 caf_register_t;
 @end verbatim
@@ -3363,6 +3365,9 @@ caf_register_t;
 * _gfortran_caf_sendget:: Sending data between remote images
 * _gfortran_caf_lock:: Locking a lock variable
 * _gfortran_caf_unlock:: Unlocking a lock variable
+* _gfortran_caf_event_post:: Post an event
+* _gfortran_caf_event_wait:: Wait that an event occurred
+* _gfortran_caf_event_query:: Query event count
 * _gfortran_caf_sync_all:: All-image barrier
 * _gfortran_caf_sync_images:: Barrier for selected images
 * _gfortran_caf_sync_memory:: Wait for completion of segment-memory operations
@@ -3516,7 +3521,7 @@ int *stat, char *errmsg, int errmsg_len)}
 @item @emph{Arguments}:
 @multitable @columnfractions .15 .70
 @item @var{size} @tab For normal coarrays, the byte size of the coarray to be
-allocated; for lock types, the number of elements.
+allocated; for lock types and event types, the number of elements.
 @item @var{type} @tab one of the caf_register_t types.
 @item @var{token} @tab intent(out) An opaque pointer identifying the coarray.
 @item @var{stat} @tab intent(out) For allocatable coarrays, stores the STAT=;
@@ -3541,7 +3546,10 @@ image. For lock types, the value shall only used for checking the allocation
 status. Note that for critical blocks, the locking is only required on one
 image; in the locking statement, the processor shall always pass always an
 image index of one for critical-block lock variables
-(@code{CAF_REGTYPE_CRITICAL}).
+(@code{CAF_REGTYPE_CRITICAL}). For lock types and critical-block variables,
+the initial value shall be unlocked (or, respecitively, not in critical
+section) such as the value false; for event types, the initial state should
+be no event, e.g. zero.
 @end table
 
 
@@ -3561,8 +3569,7 @@ int errmsg_len)}
 
 @item @emph{Arguments}:
 @multitable @columnfractions .15 .70
-@item @var{stat} @tab intent(out) For allocatable coarrays, stores the STAT=;
-may be NULL
+@item @var{stat} @tab intent(out) Stores the STAT=; may be NULL
 @item @var{errmsg} @tab intent(out) When an error occurs, this will be set
 to an error message; may be NULL
 @item @var{errmsg_len} @tab the buffer size of errmsg.
@@ -3769,8 +3776,7 @@ always 0.
 number.
 @item @var{aquired_lock} @tab intent(out) If not NULL, it returns whether lock
 could be obtained
-@item @var{stat} @tab intent(out) For allocatable coarrays, stores the STAT=;
-may be NULL
+@item @var{stat} @tab intent(out) Stores the STAT=; may be NULL
 @item @var{errmsg} @tab intent(out) When an error occurs, this will be set to
 an error message; may be NULL
 @item @var{errmsg_len} @tab the buffer size of errmsg.
@@ -3782,7 +3788,6 @@ is always zero and the image index is one.  Libraries are permitted to use other
 images for critical-block locking variables.
 @end table
 
-
 @node _gfortran_caf_unlock
 @subsection @code{_gfortran_caf_lock} --- Unlocking a lock variable
 @cindex Coarray, _gfortran_caf_unlock
@@ -3817,6 +3822,115 @@ is always zero and the image index is one.  Libraries are permitted to use other
 images for critical-block locking variables.
 @end table
 
+@node _gfortran_caf_event_post
+@subsection @code{_gfortran_caf_event_post} --- Post an event
+@cindex Coarray, _gfortran_caf_event_post
+
+@table @asis
+@item @emph{Description}:
+Increment the event count of the specified event variable.
+
+@item @emph{Syntax}:
+@code{void _gfortran_caf_event_post (caf_token_t token, size_t index,
+int image_index, int *stat, char *errmsg, int errmsg_len)}
+
+@item @emph{Arguments}:
+@multitable @columnfractions .15 .70
+@item @var{token} @tab intent(in) An opaque pointer identifying the coarray.
+@item @var{index} @tab Array index; first array index is 0. For scalars, it is
+always 0.
+@item @var{image_index} @tab The ID of the remote image; must be a positive
+number; zero indicates the current image when accessed noncoindexed.
+@item @var{stat} @tab intent(out) Stores the STAT=; may be NULL
+@item @var{errmsg} @tab intent(out) When an error occurs, this will be set to
+an error message; may be NULL
+@item @var{errmsg_len} @tab the buffer size of errmsg.
+@end multitable
+
+@item @emph{NOTES}
+This acts like an atomic add of one to the remote image's event variable.
+The statement is an image-control statement but does not imply sync memory.
+Still, all preceeding push communications of this image to the specified
+remote image has to be completed before @code{event_wait} on the remote
+image returns.
+@end table
+
+
+
+@node _gfortran_caf_event_wait
+@subsection @code{_gfortran_caf_event_wait} --- Wait that an event occurred
+@cindex Coarray, _gfortran_caf_event_wait
+
+@table @asis
+@item @emph{Description}:
+Wait until the event count has reached at least the specified
+@var{until_count}; if so, atomically decrement the event variable by this
+amount and return.
+
+@item @emph{Syntax}:
+@code{void _gfortran_caf_event_wait (caf_token_t token, size_t index,
+int until_count, int *stat, char *errmsg, int errmsg_len)}
+
+@item @emph{Arguments}:
+@multitable @columnfractions .15 .70
+@item @var{token} @tab intent(in) An opaque pointer identifying the coarray.
+@item @var{index} @tab Array index; first array index is 0. For scalars, it is
+always 0.
+@item @var{until_count} @tab The number of events which have to be available
+before the function returns.
+@item @var{stat} @tab intent(out) Stores the STAT=; may be NULL
+@item @var{errmsg} @tab intent(out) When an error occurs, this will be set to
+an error message; may be NULL
+@item @var{errmsg_len} @tab the buffer size of errmsg.
+@end multitable
+
+@item @emph{NOTES}
+This function only operates on a local coarray. It acts like a loop checking
+atomically the value of the event variable, breaking if the value is greater
+or equal the requested number of counts. Before the function returns, the
+event variable has to be decremented by the requested @var{until_count} value.
+A possible implementation would be a busy loop for a certain number of spins
+(possibly depending on the number of threads relative to the number of available
+cores) followed by other waiting strategy such as a sleeping wait (possibly with
+an increasing number of sleep time) or, if possible, a futex wait.
+
+The statement is an image-control statement but does not imply sync memory.
+Still, all preceeding push communications to this image of images having
+issued a @code{event_push} have to be completed before this function returns.
+@end table
+
+
+
+@node _gfortran_caf_event_query
+@subsection @code{_gfortran_caf_event_query} --- Query event count
+@cindex Coarray, _gfortran_caf_event_query
+
+@table @asis
+@item @emph{Description}:
+Return the event count of the specified event count.
+
+@item @emph{Syntax}:
+@code{void _gfortran_caf_event_query (caf_token_t token, size_t index,
+int image_index, int *count, int *stat)}
+
+@item @emph{Arguments}:
+@multitable @columnfractions .15 .70
+@item @var{token} @tab intent(in) An opaque pointer identifying the coarray.
+@item @var{index} @tab Array index; first array index is 0. For scalars, it is
+always 0.
+@item @var{image_index} @tab The ID of the remote image; must be a positive
+number; zero indicates the current image when accessed noncoindexed.
+@item @var{count} @tab intent(out) The number of events currently posted to
+the event variable
+@item @var{stat} @tab intent(out) Stores the STAT=; may be NULL
+@end multitable
+
+@item @emph{NOTES}
+The typical use is to check the local even variable to only call
+@code{event_wait} when the data is available. However, a coindexed variable
+is permitted; there is no ordering or synchronization implied.  It acts like
+an atomic fetch of the value of the event variable.
+@end table
 
 @node _gfortran_caf_sync_all
 @subsection @code{_gfortran_caf_sync_all} --- All-image barrier
@@ -3962,7 +4076,7 @@ int image_index, void *value, int *stat, int type, int kind)}
 @item @var{offset} @tab By which amount of bytes the actual data is shifted
 compared to the base address of the coarray.
 @item @var{image_index} @tab The ID of the remote image; must be a positive
-number.
+number; zero indicates the current image when used noncoindexed.
 @item @var{value} @tab intent(in) the value to be assigned, passed by reference.
 @item @var{stat} @tab intent(out) Stores the status STAT= and may be NULL.
 @item @var{type} @tab the data type, i.e. @code{BT_INTEGER} (1) or
@@ -3992,7 +4106,7 @@ int image_index, void *value, int *stat, int type, int kind)}
 @item @var{offset} @tab By which amount of bytes the actual data is shifted
 compared to the base address of the coarray.
 @item @var{image_index} @tab The ID of the remote image; must be a positive
-number.
+number; zero indicates the current image when used noncoindexed.
 @item @var{value} @tab intent(out) The variable assigned the atomically
 referenced variable.
 @item @var{stat} @tab intent(out) Stores the status STAT= and may be NULL.
@@ -4025,7 +4139,7 @@ int type, int kind)}
 @item @var{offset} @tab By which amount of bytes the actual data is shifted
 compared to the base address of the coarray.
 @item @var{image_index} @tab The ID of the remote image; must be a positive
-number.
+number; zero indicates the current image when used noncoindexed.
 @item @var{old} @tab intent(out) the value which the atomic variable had
 just before the cas operation.
 @item @var{compare} @tab intent(in) The value used for comparision.
@@ -4067,7 +4181,7 @@ int image_index, void *value, void *old, int *stat, int type, int kind)}
 @item @var{offset} @tab By which amount of bytes the actual data is shifted
 compared to the base address of the coarray.
 @item @var{image_index} @tab The ID of the remote image; must be a positive
-number.
+number; zero indicates the current image when used noncoindexed.
 @item @var{old} @tab intent(out) the value which the atomic variable had
 just before the atomic operation.
 @item @var{val} @tab intent(in) The new value for the atomic variable,
index dcf3eae81e7b42ddc2c43ba7549563ee3ea6eb38..f74239d48449c71fed5264e6489ebb56832331cd 100644 (file)
@@ -2157,6 +2157,21 @@ compare_parameter (gfc_symbol *formal, gfc_expr *actual,
                       formal->name, &actual->where);
          return 0;
        }
+
+      /* TS18508, C702/C703.  */
+      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_EVENT_TYPE)
+             || formal->attr.event_comp))
+
+       {
+         if (where)
+           gfc_error ("Actual argument to non-INTENT(INOUT) dummy %qs at %L, "
+                      "which is EVENT_TYPE or has a EVENT_TYPE component",
+                      formal->name, &actual->where);
+         return 0;
+       }
     }
 
   /* F2008, C1239/C1240.  */
@@ -3385,6 +3400,19 @@ gfc_procedure_use (gfc_symbol *sym, gfc_actual_arglist **ap, locus *where)
              break;
            }
 
+         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_EVENT_TYPE)
+                 || gfc_expr_attr (a->expr).event_comp))
+           {
+             gfc_error ("Actual argument of EVENT_TYPE or with EVENT_TYPE "
+                        "component at %L requires an explicit interface for "
+                        "procedure %qs", &a->expr->where, sym->name);
+             break;
+           }
+
          if (a->expr && a->expr->expr_type == EXPR_NULL
              && a->expr->ts.type == BT_UNKNOWN)
            {
index 4e6a0d0e34ae4e2ca2413b7d3d51cf652c9f7108..170006adc3322d8f9daa5534ba187a34c25b2a22 100644 (file)
@@ -3164,6 +3164,13 @@ add_subroutines (void)
              GFC_STD_F95, gfc_check_cpu_time, NULL, gfc_resolve_cpu_time,
              tm, BT_REAL, dr, REQUIRED, INTENT_OUT);
 
+  add_sym_3s ("event_query", GFC_ISYM_EVENT_QUERY, CLASS_ATOMIC,
+             BT_UNKNOWN, 0, GFC_STD_F2008_TS,
+             gfc_check_event_query, NULL, gfc_resolve_event_query,
+             "event", BT_INTEGER, di, REQUIRED, INTENT_IN,
+             c, BT_INTEGER, di, OPTIONAL, INTENT_IN,
+             stat, BT_INTEGER, di, OPTIONAL, INTENT_OUT);
+
   /* More G77 compatibility garbage.  */
   add_sym_2s ("ctime", GFC_ISYM_CTIME, CLASS_IMPURE, BT_UNKNOWN, 0, GFC_STD_GNU,
              gfc_check_ctime_sub, NULL, gfc_resolve_ctime_sub,
index ca2ad306e0d4bc79225a50e4e1779bf854c8ec91..9b76542c526399114661e70b17bf5131ebc1bf8c 100644 (file)
@@ -70,6 +70,7 @@ bool gfc_check_dprod (gfc_expr *, gfc_expr *);
 bool gfc_check_dshift (gfc_expr *, gfc_expr *, gfc_expr *);
 bool gfc_check_eoshift (gfc_expr *, gfc_expr *, gfc_expr *, gfc_expr *);
 bool gfc_check_dtime_etime (gfc_expr *);
+bool gfc_check_event_query (gfc_expr *, gfc_expr *, gfc_expr *);
 bool gfc_check_fgetputc (gfc_expr *, gfc_expr *);
 bool gfc_check_fgetput (gfc_expr *);
 bool gfc_check_float (gfc_expr *);
@@ -462,6 +463,7 @@ void gfc_resolve_dtime_sub (gfc_code *);
 void gfc_resolve_eoshift (gfc_expr *, gfc_expr *, gfc_expr *, gfc_expr *,
                          gfc_expr *);
 void gfc_resolve_etime_sub (gfc_code *);
+void gfc_resolve_event_query (gfc_code *);
 void gfc_resolve_exp (gfc_expr *, gfc_expr *);
 void gfc_resolve_exponent (gfc_expr *, gfc_expr *);
 void gfc_resolve_extends_type_of (gfc_expr *, gfc_expr *, gfc_expr *);
index 80b429fbb36dd641afd1aca852bac651831a509d..8aa3a16af2ee4d068309d7d4e6233313b0c934b2 100644 (file)
@@ -2945,6 +2945,12 @@ gfc_resolve_atomic_ref (gfc_code *c)
   c->resolved_sym = gfc_get_intrinsic_sub_symbol (name);
 }
 
+void
+gfc_resolve_event_query (gfc_code *c)
+{
+  const char *name = "event_query";
+  c->resolved_sym = gfc_get_intrinsic_sub_symbol (name);
+}
 
 void
 gfc_resolve_mvbits (gfc_code *c)
index eba0b4c9e2f8ed4a77311648a66e223dcc56f320..c5fb3ff21f081f4594388b0197b36c1ac8b7dac3 100644 (file)
@@ -123,6 +123,11 @@ NAMED_FUNCTION (ISOFORTRAN_COMPILER_VERSION, "compiler_version", \
 NAMED_DERIVED_TYPE (ISOFORTRAN_LOCK_TYPE, "lock_type", \
               get_int_kind_from_node (ptr_type_node), GFC_STD_F2008)
 
+NAMED_DERIVED_TYPE (ISOFORTRAN_EVENT_TYPE, "event_type", \
+                   flag_coarray == GFC_FCOARRAY_LIB
+                   ?  get_int_kind_from_node (ptr_type_node)
+                   : gfc_default_integer_kind, GFC_STD_F2008_TS)
+
 #undef NAMED_INTCST
 #undef NAMED_KINDARRAY
 #undef NAMED_FUNCTION
index 22b0d7d42f725463a27ff74b560b8426458c3e29..b55346497e9d881780cc17dbbd34ae428f940814 100644 (file)
@@ -1463,6 +1463,8 @@ gfc_match_if (gfc_statement *if_type)
   match ("deallocate", gfc_match_deallocate, ST_DEALLOCATE)
   match ("end file", gfc_match_endfile, ST_END_FILE)
   match ("error stop", gfc_match_error_stop, ST_ERROR_STOP)
+  match ("event post", gfc_match_event_post, ST_EVENT_POST)
+  match ("event wait", gfc_match_event_wait, ST_EVENT_WAIT)
   match ("exit", gfc_match_exit, ST_EXIT)
   match ("flush", gfc_match_flush, ST_FLUSH)
   match ("forall", match_simple_forall, ST_FORALL)
@@ -2747,6 +2749,202 @@ gfc_match_error_stop (void)
   return gfc_match_stopcode (ST_ERROR_STOP);
 }
 
+/* Match EVENT POST/WAIT statement. Syntax:
+     EVENT POST ( event-variable [, sync-stat-list] )
+     EVENT WAIT ( event-variable [, wait-spec-list] )
+   with
+      wait-spec-list  is  sync-stat-list  or until-spec
+      until-spec  is  UNTIL_COUNT = scalar-int-expr
+      sync-stat  is  STAT= or ERRMSG=.  */
+
+static match
+event_statement (gfc_statement st)
+{
+  match m;
+  gfc_expr *tmp, *eventvar, *until_count, *stat, *errmsg;
+  bool saw_until_count, saw_stat, saw_errmsg;
+
+  tmp = eventvar = until_count = stat = errmsg = NULL;
+  saw_until_count = saw_stat = saw_errmsg = false;
+
+  if (gfc_pure (NULL))
+    {
+      gfc_error ("Image control statement EVENT %s at %C in PURE procedure",
+                st == ST_EVENT_POST ? "POST" : "WAIT");
+      return MATCH_ERROR;
+    }
+
+  gfc_unset_implicit_pure (NULL);
+
+  if (flag_coarray == GFC_FCOARRAY_NONE)
+    {
+       gfc_fatal_error ("Coarrays disabled at %C, use %<-fcoarray=%> to enable");
+       return MATCH_ERROR;
+    }
+
+  if (gfc_find_state (COMP_CRITICAL))
+    {
+      gfc_error ("Image control statement EVENT %s at %C in CRITICAL block",
+                st == ST_EVENT_POST ? "POST" : "WAIT");
+      return MATCH_ERROR;
+    }
+
+  if (gfc_find_state (COMP_DO_CONCURRENT))
+    {
+      gfc_error ("Image control statement EVENT %s at %C in DO CONCURRENT "
+                "block", st == ST_EVENT_POST ? "POST" : "WAIT");
+      return MATCH_ERROR;
+    }
+
+  if (gfc_match_char ('(') != MATCH_YES)
+    goto syntax;
+
+  if (gfc_match ("%e", &eventvar) != MATCH_YES)
+    goto syntax;
+  m = gfc_match_char (',');
+  if (m == MATCH_ERROR)
+    goto syntax;
+  if (m == MATCH_NO)
+    {
+      m = gfc_match_char (')');
+      if (m == MATCH_YES)
+       goto done;
+      goto syntax;
+    }
+
+  for (;;)
+    {
+      m = gfc_match (" stat = %v", &tmp);
+      if (m == MATCH_ERROR)
+       goto syntax;
+      if (m == MATCH_YES)
+       {
+         if (saw_stat)
+           {
+             gfc_error ("Redundant STAT tag found at %L ", &tmp->where);
+             goto cleanup;
+           }
+         stat = tmp;
+         saw_stat = true;
+
+         m = gfc_match_char (',');
+         if (m == MATCH_YES)
+           continue;
+
+         tmp = NULL;
+         break;
+       }
+
+      m = gfc_match (" errmsg = %v", &tmp);
+      if (m == MATCH_ERROR)
+       goto syntax;
+      if (m == MATCH_YES)
+       {
+         if (saw_errmsg)
+           {
+             gfc_error ("Redundant ERRMSG tag found at %L ", &tmp->where);
+             goto cleanup;
+           }
+         errmsg = tmp;
+         saw_errmsg = true;
+
+         m = gfc_match_char (',');
+         if (m == MATCH_YES)
+           continue;
+
+         tmp = NULL;
+         break;
+       }
+
+      m = gfc_match (" until_count = %e", &tmp);
+      if (m == MATCH_ERROR || st == ST_EVENT_POST)
+       goto syntax;
+      if (m == MATCH_YES)
+       {
+         if (saw_until_count)
+           {
+             gfc_error ("Redundant UNTIL_COUNT tag found at %L ",
+                        &tmp->where);
+             goto cleanup;
+           }
+         until_count = tmp;
+         saw_until_count = true;
+
+         m = gfc_match_char (',');
+         if (m == MATCH_YES)
+           continue;
+
+         tmp = NULL;
+         break;
+       }
+
+      break;
+    }
+
+  if (m == MATCH_ERROR)
+    goto syntax;
+
+  if (gfc_match (" )%t") != MATCH_YES)
+    goto syntax;
+
+done:
+  switch (st)
+    {
+    case ST_EVENT_POST:
+      new_st.op = EXEC_EVENT_POST;
+      break;
+    case ST_EVENT_WAIT:
+      new_st.op = EXEC_EVENT_WAIT;
+      break;
+    default:
+      gcc_unreachable ();
+    }
+
+  new_st.expr1 = eventvar;
+  new_st.expr2 = stat;
+  new_st.expr3 = errmsg;
+  new_st.expr4 = until_count;
+
+  return MATCH_YES;
+
+syntax:
+  gfc_syntax_error (st);
+
+cleanup:
+  if (until_count != tmp)
+    gfc_free_expr (until_count);
+  if (errmsg != tmp)
+    gfc_free_expr (errmsg);
+  if (stat != tmp)
+    gfc_free_expr (stat);
+
+  gfc_free_expr (tmp);
+  gfc_free_expr (eventvar);
+
+  return MATCH_ERROR;
+
+}
+
+
+match
+gfc_match_event_post (void)
+{
+  if (!gfc_notify_std (GFC_STD_F2008_TS, "EVENT POST statement at %C"))
+    return MATCH_ERROR;
+
+  return event_statement (ST_EVENT_POST);
+}
+
+
+match
+gfc_match_event_wait (void)
+{
+  if (!gfc_notify_std (GFC_STD_F2008_TS, "EVENT WAIT statement at %C"))
+    return MATCH_ERROR;
+
+  return event_statement (ST_EVENT_WAIT);
+}
+
 
 /* Match LOCK/UNLOCK statement. Syntax:
      LOCK ( lock-variable [ , lock-stat-list ] )
index a52c189c1cf5f2d111b670f693030c394ccd0417..7d383ed7357b9b8c0700a534d1eb65cdc33c282e 100644 (file)
@@ -69,6 +69,8 @@ match gfc_match_assignment (void);
 match gfc_match_if (gfc_statement *);
 match gfc_match_else (void);
 match gfc_match_elseif (void);
+match gfc_match_event_post (void);
+match gfc_match_event_wait (void);
 match gfc_match_critical (void);
 match gfc_match_block (void);
 match gfc_match_associate (void);
index 6b544ee7596fdfe898ff12817a8268d5504a9469..704ff1523ef5ba0dc5191e3d68b87ae8aa29c9d4 100644 (file)
@@ -1981,7 +1981,7 @@ enum ab_attribute
   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_LOCK_COMP,
+  AB_VALUE, AB_VOLATILE, AB_PROTECTED, AB_LOCK_COMP, AB_EVENT_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,
@@ -2028,6 +2028,7 @@ static const mstring attr_bits[] =
     minit ("ALLOC_COMP", AB_ALLOC_COMP),
     minit ("COARRAY_COMP", AB_COARRAY_COMP),
     minit ("LOCK_COMP", AB_LOCK_COMP),
+    minit ("EVENT_COMP", AB_EVENT_COMP),
     minit ("POINTER_COMP", AB_POINTER_COMP),
     minit ("PROC_POINTER_COMP", AB_PROC_POINTER_COMP),
     minit ("PRIVATE_COMP", AB_PRIVATE_COMP),
@@ -2216,6 +2217,8 @@ mio_symbol_attribute (symbol_attribute *attr)
        MIO_NAME (ab_attribute) (AB_COARRAY_COMP, attr_bits);
       if (attr->lock_comp)
        MIO_NAME (ab_attribute) (AB_LOCK_COMP, attr_bits);
+      if (attr->event_comp)
+       MIO_NAME (ab_attribute) (AB_EVENT_COMP, attr_bits);
       if (attr->zero_comp)
        MIO_NAME (ab_attribute) (AB_ZERO_COMP, attr_bits);
       if (attr->is_class)
@@ -2383,6 +2386,9 @@ mio_symbol_attribute (symbol_attribute *attr)
            case AB_LOCK_COMP:
              attr->lock_comp = 1;
              break;
+           case AB_EVENT_COMP:
+             attr->event_comp = 1;
+             break;
            case AB_POINTER_COMP:
              attr->pointer_comp = 1;
              break;
index b2d15a89aeb18d4d9be820b8cb893c555059e3f7..157dea874ad2fefbf85f6d476a705c29037cf63c 100644 (file)
@@ -477,6 +477,8 @@ decode_statement (void)
       match ("entry% ", gfc_match_entry, ST_ENTRY);
       match ("equivalence", gfc_match_equivalence, ST_EQUIVALENCE);
       match ("external", gfc_match_external, ST_ATTR_DECL);
+      match ("event post", gfc_match_event_post, ST_EVENT_POST);
+      match ("event wait", gfc_match_event_wait, ST_EVENT_WAIT);
       break;
 
     case 'f':
@@ -1348,6 +1350,7 @@ next_statement (void)
   case ST_OMP_CANCEL: case ST_OMP_CANCELLATION_POINT: \
   case ST_OMP_TARGET_UPDATE: case ST_ERROR_STOP: case ST_SYNC_ALL: \
   case ST_SYNC_IMAGES: case ST_SYNC_MEMORY: case ST_LOCK: case ST_UNLOCK: \
+  case ST_EVENT_POST: case ST_EVENT_WAIT: \
   case ST_OACC_UPDATE: case ST_OACC_WAIT: case ST_OACC_CACHE: \
   case ST_OACC_ENTER_DATA: case ST_OACC_EXIT_DATA
 
@@ -1654,6 +1657,12 @@ gfc_ascii_statement (gfc_statement st)
     case ST_ELSEWHERE:
       p = "ELSEWHERE";
       break;
+    case ST_EVENT_POST:
+      p = "EVENT POST";
+      break;
+    case ST_EVENT_WAIT:
+      p = "EVENT WAIT";
+      break;
     case ST_END_ASSOCIATE:
       p = "END ASSOCIATE";
       break;
@@ -2646,7 +2655,7 @@ parse_derived (void)
   gfc_statement st;
   gfc_state_data s;
   gfc_symbol *sym;
-  gfc_component *c, *lock_comp = NULL;
+  gfc_component *c, *lock_comp = NULL, *event_comp = NULL;
 
   accept_statement (ST_DERIVED_DECL);
   push_state (&s, COMP_DERIVED, gfc_new_block);
@@ -2754,8 +2763,8 @@ endType:
   sym = gfc_current_block ();
   for (c = sym->components; c; c = c->next)
     {
-      bool coarray, lock_type, allocatable, pointer;
-      coarray = lock_type = allocatable = pointer = false;
+      bool coarray, lock_type, event_type, allocatable, pointer;
+      coarray = lock_type = event_type = allocatable = pointer = false;
 
       /* Look for allocatable components.  */
       if (c->attr.allocatable
@@ -2817,6 +2826,23 @@ endType:
          sym->attr.lock_comp = 1;
        }
 
+      /* Looking for event_type components.  */
+      if ((c->ts.type == BT_DERIVED
+             && c->ts.u.derived->from_intmod == INTMOD_ISO_FORTRAN_ENV
+             && c->ts.u.derived->intmod_sym_id == ISOFORTRAN_EVENT_TYPE)
+         || (c->ts.type == BT_CLASS && c->attr.class_ok
+             && CLASS_DATA (c)->ts.u.derived->from_intmod
+                == INTMOD_ISO_FORTRAN_ENV
+             && CLASS_DATA (c)->ts.u.derived->intmod_sym_id
+                == ISOFORTRAN_EVENT_TYPE)
+         || (c->ts.type == BT_DERIVED && c->ts.u.derived->attr.event_comp
+             && !allocatable && !pointer))
+       {
+         event_type = 1;
+         event_comp = c;
+         sym->attr.event_comp = 1;
+       }
+
       /* Check for F2008, C1302 - and recall that pointers may not be coarrays
         (5.3.14) and that subobjects of coarray are coarray themselves (2.4.7),
         unless there are nondirect [allocatable or pointer] components
@@ -2857,6 +2883,43 @@ endType:
                   "coarray subcomponent)", lock_comp->name, &lock_comp->loc,
                   sym->name, c->name, &c->loc);
 
+      /* Similarly for EVENT TYPE.  */
+
+      if (pointer && !coarray && event_type)
+       gfc_error ("Component %s at %L of type EVENT_TYPE must have a "
+                  "codimension or be a subcomponent of a coarray, "
+                  "which is not possible as the component has the "
+                  "pointer attribute", c->name, &c->loc);
+      else if (pointer && !coarray && c->ts.type == BT_DERIVED
+              && c->ts.u.derived->attr.event_comp)
+       gfc_error ("Pointer component %s at %L has a noncoarray subcomponent "
+                  "of type EVENT_TYPE, which must have a codimension or be a "
+                  "subcomponent of a coarray", c->name, &c->loc);
+
+      if (event_type && allocatable && !coarray)
+       gfc_error ("Allocatable component %s at %L of type EVENT_TYPE must have "
+                  "a codimension", c->name, &c->loc);
+      else if (event_type && allocatable && c->ts.type == BT_DERIVED
+              && c->ts.u.derived->attr.event_comp)
+       gfc_error ("Allocatable component %s at %L must have a codimension as "
+                  "it has a noncoarray subcomponent of type EVENT_TYPE",
+                  c->name, &c->loc);
+
+      if (sym->attr.coarray_comp && !coarray && event_type)
+       gfc_error ("Noncoarray component %s at %L of type EVENT_TYPE or with "
+                  "subcomponent of type EVENT_TYPE must have a codimension or "
+                  "be a subcomponent of a coarray. (Variables of type %s may "
+                  "not have a codimension as already a coarray "
+                  "subcomponent exists)", c->name, &c->loc, sym->name);
+
+      if (sym->attr.event_comp && coarray && !event_type)
+       gfc_error ("Noncoarray component %s at %L of type EVENT_TYPE or with "
+                  "subcomponent of type EVENT_TYPE must have a codimension or "
+                  "be a subcomponent of a coarray. (Variables of type %s may "
+                  "not have a codimension as %s at %L has a codimension or a "
+                  "coarray subcomponent)", event_comp->name, &event_comp->loc,
+                  sym->name, c->name, &c->loc);
+
       /* Look for private components.  */
       if (sym->component_access == ACCESS_PRIVATE
          || c->attr.access == ACCESS_PRIVATE
index febf0fa28d62c8a0aee9da77889d1598a2bdc9c6..6598855f81a503af11f119e26e71ea75101fd538 100644 (file)
@@ -7055,6 +7055,21 @@ resolve_allocate_expr (gfc_expr *e, gfc_code *code, bool *array_alloc_wo_spec)
                      &code->expr3->where, &e->where);
          goto failure;
        }
+
+      /* Check TS18508, C702/C703.  */
+      if (code->expr3->ts.type == BT_DERIVED
+         && ((codimension && gfc_expr_attr (code->expr3).event_comp)
+             || (code->expr3->ts.u.derived->from_intmod
+                    == INTMOD_ISO_FORTRAN_ENV
+                 && code->expr3->ts.u.derived->intmod_sym_id
+                    == ISOFORTRAN_EVENT_TYPE)))
+       {
+         gfc_error ("The source-expr at %L shall neither be of type "
+                    "EVENT_TYPE nor have a EVENT_TYPE component if "
+                     "allocate-object at %L is a coarray",
+                     &code->expr3->where, &e->where);
+         goto failure;
+       }
     }
 
   /* Check F08:C629.  */
@@ -7106,6 +7121,13 @@ resolve_allocate_expr (gfc_expr *e, gfc_code *code, bool *array_alloc_wo_spec)
         no SOURCE exists by setting expr3.  */
       code->expr3 = gfc_default_initializer (&code->ext.alloc.ts);
     }
+  else if (flag_coarray != GFC_FCOARRAY_LIB && e->ts.type == BT_DERIVED
+          && e->ts.u.derived->from_intmod == INTMOD_ISO_FORTRAN_ENV
+          && e->ts.u.derived->intmod_sym_id == ISOFORTRAN_EVENT_TYPE)
+    {
+      /* We have to zero initialize the integer variable.  */
+      code->expr3 = gfc_get_int_expr (gfc_default_integer_kind, &e->where, 0);
+    }
   else if (!code->expr3)
     {
       /* Set up default initializer if needed.  */
@@ -8706,21 +8728,40 @@ find_reachable_labels (gfc_code *block)
 
 
 static void
-resolve_lock_unlock (gfc_code *code)
+resolve_lock_unlock_event (gfc_code *code)
 {
   if (code->expr1->expr_type == EXPR_FUNCTION
       && code->expr1->value.function.isym
       && code->expr1->value.function.isym->id == GFC_ISYM_CAF_GET)
     remove_caf_get_intrinsic (code->expr1);
 
-  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_is_coarray (code->expr1) && !gfc_is_coindexed (code->expr1)))
+  if ((code->op == EXEC_LOCK || code->op == EXEC_UNLOCK)
+      && (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_is_coarray (code->expr1) &&
+             !gfc_is_coindexed (code->expr1))))
     gfc_error ("Lock variable at %L must be a scalar of type LOCK_TYPE",
               &code->expr1->where);
+  else if ((code->op == EXEC_EVENT_POST && code->op == EXEC_EVENT_WAIT)
+          && (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_EVENT_TYPE
+              || code->expr1->rank != 0))
+    gfc_error ("Event variable at %L must be a scalar of type EVENT_TYPE",
+              &code->expr1->where);
+  else if (code->op == EXEC_EVENT_POST && !gfc_is_coarray (code->expr1)
+          && !gfc_is_coindexed (code->expr1))
+    gfc_error ("Event variable argument at %L must be a coarray or coindexed",
+              &code->expr1->where);
+  else if (code->op == EXEC_EVENT_WAIT && !gfc_is_coarray (code->expr1))
+    gfc_error ("Event variable argument at %L must be a coarray but not "
+              "coindexed", &code->expr1->where);
 
   /* Check STAT.  */
   if (code->expr2
@@ -8746,17 +8787,23 @@ resolve_lock_unlock (gfc_code *code)
                                    _("ERRMSG variable")))
     return;
 
-  /* Check ACQUIRED_LOCK.  */
-  if (code->expr4
+  /* Check for LOCK the ACQUIRED_LOCK.  */
+  if (code->op != EXEC_EVENT_WAIT && 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
+  if (code->op != EXEC_EVENT_WAIT && code->expr4
       && !gfc_check_vardef_context (code->expr4, false, false, false,
                                    _("ACQUIRED_LOCK variable")))
     return;
+
+  /* Check for EVENT WAIT the UNTIL_COUNT.  */
+  if (code->op == EXEC_EVENT_WAIT && code->expr4
+      && (code->expr4->ts.type != BT_INTEGER || code->expr4->rank != 0))
+    gfc_error ("UNTIL_COUNT= argument at %L must be a scalar INTEGER "
+              "expression", &code->expr4->where);
 }
 
 
@@ -10403,7 +10450,9 @@ start:
 
        case EXEC_LOCK:
        case EXEC_UNLOCK:
-         resolve_lock_unlock (code);
+       case EXEC_EVENT_POST:
+       case EXEC_EVENT_WAIT:
+         resolve_lock_unlock_event (code);
          break;
 
        case EXEC_ENTRY:
@@ -14001,6 +14050,19 @@ resolve_symbol (gfc_symbol *sym)
       return;
     }
 
+  /* TS18508, C702/C703.  */
+  if (sym->ts.type == BT_DERIVED
+      && ((sym->ts.u.derived->from_intmod == INTMOD_ISO_FORTRAN_ENV
+          && sym->ts.u.derived->intmod_sym_id == ISOFORTRAN_EVENT_TYPE)
+         || sym->ts.u.derived->attr.event_comp)
+      && !sym->attr.codimension && !sym->ts.u.derived->attr.coarray_comp)
+    {
+      gfc_error ("Variable %s at %L of type EVENT_TYPE or with subcomponent 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
@@ -14030,6 +14092,15 @@ resolve_symbol (gfc_symbol *sym)
       return;
     }
 
+  /* TS18508.  */
+  if (sym->ts.type == BT_DERIVED && sym->attr.dummy
+      && sym->attr.intent == INTENT_OUT && sym->attr.event_comp)
+    {
+      gfc_error ("Dummy argument %qs at %L of EVENT_TYPE shall not be "
+                "INTENT(OUT)", sym->name, &sym->declared_at);
+      return;
+    }
+
   /* F2008, C525.  */
   if ((((sym->ts.type == BT_DERIVED && sym->ts.u.derived->attr.coarray_comp)
         || (sym->ts.type == BT_CLASS && sym->attr.class_ok
index 566150b1cc2ffe03711b7967dd7d962a5c51aa87..573385f52388e7d539e58fb616230652ad21fd45 100644 (file)
@@ -118,6 +118,8 @@ gfc_free_statement (gfc_code *p)
     case EXEC_SYNC_MEMORY:
     case EXEC_LOCK:
     case EXEC_UNLOCK:
+    case EXEC_EVENT_POST:
+    case EXEC_EVENT_WAIT:
       break;
 
     case EXEC_BLOCK:
index 331b43da4133e8c369e1ee4fc43eab26d21b232a..8c4fa03629b4a4d55d174e042e067d0545eb16b0 100644 (file)
@@ -145,6 +145,9 @@ tree gfor_fndecl_caf_atomic_cas;
 tree gfor_fndecl_caf_atomic_op;
 tree gfor_fndecl_caf_lock;
 tree gfor_fndecl_caf_unlock;
+tree gfor_fndecl_caf_event_post;
+tree gfor_fndecl_caf_event_wait;
+tree gfor_fndecl_caf_event_query;
 tree gfor_fndecl_co_broadcast;
 tree gfor_fndecl_co_max;
 tree gfor_fndecl_co_min;
@@ -3559,6 +3562,21 @@ gfc_build_builtin_function_decls (void)
        void_type_node, 6, pvoid_type_node, size_type_node, integer_type_node,
        pint_type, pchar_type_node, integer_type_node);
 
+      gfor_fndecl_caf_event_post = gfc_build_library_function_decl_with_spec (
+       get_identifier (PREFIX("caf_event_post")), "R..WW",
+       void_type_node, 6, pvoid_type_node, size_type_node, integer_type_node,
+       pint_type, pchar_type_node, integer_type_node);
+
+      gfor_fndecl_caf_event_wait = gfc_build_library_function_decl_with_spec (
+       get_identifier (PREFIX("caf_event_wait")), "R..WW",
+       void_type_node, 6, pvoid_type_node, size_type_node, integer_type_node,
+       pint_type, pchar_type_node, integer_type_node);
+
+      gfor_fndecl_caf_event_query = gfc_build_library_function_decl_with_spec (
+       get_identifier (PREFIX("caf_event_query")), "R..WW",
+       void_type_node, 5, pvoid_type_node, size_type_node, integer_type_node,
+       pint_type, pint_type);
+
       gfor_fndecl_co_broadcast = gfc_build_library_function_decl_with_spec (
        get_identifier (PREFIX("caf_co_broadcast")), "W.WW",
        void_type_node, 5, pvoid_type_node, integer_type_node,
@@ -4854,7 +4872,7 @@ static void
 generate_coarray_sym_init (gfc_symbol *sym)
 {
   tree tmp, size, decl, token;
-  bool is_lock_type;
+  bool is_lock_type, is_event_type;
   int reg_type;
 
   if (sym->attr.dummy || sym->attr.allocatable || !sym->attr.codimension
@@ -4870,13 +4888,17 @@ generate_coarray_sym_init (gfc_symbol *sym)
                 && sym->ts.u.derived->from_intmod == INTMOD_ISO_FORTRAN_ENV
                 && sym->ts.u.derived->intmod_sym_id == ISOFORTRAN_LOCK_TYPE;
 
+  is_event_type = sym->ts.type == BT_DERIVED
+                 && sym->ts.u.derived->from_intmod == INTMOD_ISO_FORTRAN_ENV
+                 && sym->ts.u.derived->intmod_sym_id == ISOFORTRAN_EVENT_TYPE;
+
   /* FIXME: Workaround for PR middle-end/49106, cf. also PR middle-end/49108
      to make sure the variable is not optimized away.  */
   DECL_PRESERVE_P (DECL_CONTEXT (decl)) = 1;
 
   /* For lock types, we pass the array size as only the library knows the
      size of the variable.  */
-  if (is_lock_type)
+  if (is_lock_type || is_event_type)
     size = gfc_index_one_node;
   else
     size = TYPE_SIZE_UNIT (gfc_get_element_type (TREE_TYPE (decl)));
@@ -4898,6 +4920,8 @@ generate_coarray_sym_init (gfc_symbol *sym)
                               GFC_TYPE_ARRAY_CAF_TOKEN (TREE_TYPE(decl)));
   if (is_lock_type)
     reg_type = sym->attr.artificial ? GFC_CAF_CRITICAL : GFC_CAF_LOCK_STATIC;
+  else if (is_event_type)
+    reg_type = GFC_CAF_EVENT_STATIC;
   else
     reg_type = GFC_CAF_COARRAY_STATIC;
   tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_register, 6, size,
index 6647a4ec40463644be608aeb63b7e3fc56e35634..22195e09887172117fabf5b2ead7a437ae2fb19b 100644 (file)
@@ -5784,8 +5784,9 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
       len = cl.backend_decl;
     }
 
-  byref = (comp && (comp->attr.dimension || comp->ts.type == BT_CHARACTER))
-         || (!comp && gfc_return_by_reference (sym));
+  byref = (comp && (comp->attr.dimension
+          || (comp->ts.type == BT_CHARACTER && !sym->attr.is_bind_c)))
+          || (!comp && gfc_return_by_reference (sym));
   if (byref)
     {
       if (se->direct_byref)
@@ -6611,6 +6612,11 @@ gfc_conv_initializer (gfc_expr * expr, gfc_typespec * ts, tree type,
 {
   gfc_se se;
 
+  if (flag_coarray != GFC_FCOARRAY_LIB && ts->type == BT_DERIVED
+      && ts->u.derived->from_intmod == INTMOD_ISO_FORTRAN_ENV
+      && ts->u.derived->intmod_sym_id == ISOFORTRAN_EVENT_TYPE)
+    return build_constructor (type, NULL);
+
   if (!(expr || pointer || procptr))
     return NULL_TREE;
 
index 1dabc26b01093e4e016909e82025134c0aaa5a14..21efe4412bdcb02535c0cb7398507b40787e7cf1 100644 (file)
@@ -9291,6 +9291,154 @@ conv_intrinsic_atomic_cas (gfc_code *code)
   return gfc_finish_block (&block);
 }
 
+static tree
+conv_intrinsic_event_query (gfc_code *code)
+{
+  gfc_se se, argse;
+  tree stat = NULL_TREE, stat2 = NULL_TREE;
+  tree count = NULL_TREE, count2 = NULL_TREE;
+
+  gfc_expr *event_expr = code->ext.actual->expr;
+
+  if (code->ext.actual->next->next->expr)
+    {
+      gcc_assert (code->ext.actual->next->next->expr->expr_type
+                 == EXPR_VARIABLE);
+      gfc_init_se (&argse, NULL);
+      gfc_conv_expr_val (&argse, code->ext.actual->next->next->expr);
+      stat = argse.expr;
+    }
+  else if (flag_coarray == GFC_FCOARRAY_LIB)
+    stat = null_pointer_node;
+
+  if (code->ext.actual->next->expr)
+    {
+      gcc_assert (code->ext.actual->next->expr->expr_type == EXPR_VARIABLE);
+      gfc_init_se (&argse, NULL);
+      gfc_conv_expr_val (&argse, code->ext.actual->next->expr);
+      count = argse.expr;
+    }
+
+  gfc_start_block (&se.pre);
+  if (flag_coarray == GFC_FCOARRAY_LIB)
+    {
+      tree tmp, token, image_index;
+      tree index = size_zero_node;
+
+      if (event_expr->expr_type == EXPR_FUNCTION
+         && event_expr->value.function.isym
+         && event_expr->value.function.isym->id == GFC_ISYM_CAF_GET)
+       event_expr = event_expr->value.function.actual->expr;
+
+      tree caf_decl = gfc_get_tree_for_caf_expr (event_expr);
+
+      if (event_expr->symtree->n.sym->ts.type != BT_DERIVED
+         || event_expr->symtree->n.sym->ts.u.derived->from_intmod
+            != INTMOD_ISO_FORTRAN_ENV
+         || event_expr->symtree->n.sym->ts.u.derived->intmod_sym_id
+            != ISOFORTRAN_EVENT_TYPE)
+       {
+         gfc_error ("Sorry, the event component of derived type at %L is not "
+                    "yet supported", &event_expr->where);
+         return NULL_TREE;
+       }
+
+      if (gfc_is_coindexed (event_expr))
+       {
+         gfc_error ("The event variable at %L shall not be coindexed ",
+                    &event_expr->where);
+          return NULL_TREE;
+       }
+
+      image_index = integer_zero_node;
+
+      gfc_get_caf_token_offset (&token, NULL, caf_decl, NULL_TREE, event_expr);
+
+      /* For arrays, obtain the array index.  */
+      if (gfc_expr_attr (event_expr).dimension)
+       {
+         tree desc, tmp, extent, lbound, ubound;
+          gfc_array_ref *ar, ar2;
+          int i;
+
+         /* TODO: Extend this, once DT components are supported.  */
+         ar = &event_expr->ref->u.ar;
+         ar2 = *ar;
+         memset (ar, '\0', sizeof (*ar));
+         ar->as = ar2.as;
+         ar->type = AR_FULL;
+
+         gfc_init_se (&argse, NULL);
+         argse.descriptor_only = 1;
+         gfc_conv_expr_descriptor (&argse, event_expr);
+         gfc_add_block_to_block (&se.pre, &argse.pre);
+         desc = argse.expr;
+         *ar = ar2;
+
+         extent = integer_one_node;
+         for (i = 0; i < ar->dimen; i++)
+           {
+             gfc_init_se (&argse, NULL);
+             gfc_conv_expr_type (&argse, ar->start[i], integer_type_node);
+             gfc_add_block_to_block (&argse.pre, &argse.pre);
+             lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[i]);
+             tmp = fold_build2_loc (input_location, MINUS_EXPR,
+                                    integer_type_node, argse.expr,
+                                    fold_convert(integer_type_node, lbound));
+             tmp = fold_build2_loc (input_location, MULT_EXPR,
+                                    integer_type_node, extent, tmp);
+             index = fold_build2_loc (input_location, PLUS_EXPR,
+                                      integer_type_node, index, tmp);
+             if (i < ar->dimen - 1)
+               {
+                 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[i]);
+                 tmp = gfc_conv_array_extent_dim (lbound, ubound, NULL);
+                 tmp = fold_convert (integer_type_node, tmp);
+                 extent = fold_build2_loc (input_location, MULT_EXPR,
+                                           integer_type_node, extent, tmp);
+               }
+           }
+       }
+
+      if (count != null_pointer_node && TREE_TYPE (count) != integer_type_node)
+       {
+         count2 = count;
+         count = gfc_create_var (integer_type_node, "count");
+       }
+
+      if (stat != null_pointer_node && TREE_TYPE (stat) != integer_type_node)
+       {
+         stat2 = stat;
+         stat = gfc_create_var (integer_type_node, "stat");
+       }
+
+      tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_event_query, 5,
+                                   token, index, image_index, count
+                                  ? gfc_build_addr_expr (NULL, count) : count,
+                                  stat != null_pointer_node
+                                  ? gfc_build_addr_expr (NULL, stat) : stat);
+      gfc_add_expr_to_block (&se.pre, tmp);
+
+      if (count2 != NULL_TREE)
+       gfc_add_modify (&se.pre, count2,
+                       fold_convert (TREE_TYPE (count2), count));
+
+      if (stat2 != NULL_TREE)
+       gfc_add_modify (&se.pre, stat2,
+                       fold_convert (TREE_TYPE (stat2), stat));
+
+      return gfc_finish_block (&se.pre);
+    }
+
+  gfc_init_se (&argse, NULL);
+  gfc_conv_expr_val (&argse, code->ext.actual->expr);
+  gfc_add_modify (&se.pre, count, fold_convert (TREE_TYPE (count), argse.expr));
+
+  if (stat != NULL_TREE)
+    gfc_add_modify (&se.pre, stat, build_int_cst (TREE_TYPE (stat), 0));
+
+  return gfc_finish_block (&se.pre);
+}
 
 static tree
 conv_intrinsic_move_alloc (gfc_code *code)
@@ -9587,6 +9735,10 @@ gfc_conv_intrinsic_subroutine (gfc_code *code)
       res = conv_intrinsic_atomic_ref (code);
       break;
 
+    case GFC_ISYM_EVENT_QUERY:
+      res = conv_intrinsic_event_query (code);
+      break;
+
     case GFC_ISYM_C_F_POINTER:
     case GFC_ISYM_C_F_PROCPOINTER:
       res = conv_isocbinding_subroutine (code);
index 47ffd78eee600b28f686cd1865adc086c3197170..3df483a29180ae350819dfdf23079c5c717992ab 100644 (file)
@@ -776,6 +776,7 @@ gfc_trans_lock_unlock (gfc_code *code, gfc_exec_op op)
       if (code->expr3)
        {
          gfc_init_se (&argse, NULL);
+         argse.want_pointer = 1;
          gfc_conv_expr (&argse, code->expr3);
          gfc_add_block_to_block (&se.pre, &argse.pre);
          errmsg = argse.expr;
@@ -840,6 +841,165 @@ gfc_trans_lock_unlock (gfc_code *code, gfc_exec_op op)
   return gfc_finish_block (&se.pre);
 }
 
+tree
+gfc_trans_event_post_wait (gfc_code *code, gfc_exec_op op)
+{
+  gfc_se se, argse;
+  tree stat = NULL_TREE, stat2 = NULL_TREE;
+  tree until_count = NULL_TREE;
+
+  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;
+    }
+  else if (flag_coarray == GFC_FCOARRAY_LIB)
+    stat = null_pointer_node;
+
+  if (code->expr4)
+    {
+      gfc_init_se (&argse, NULL);
+      gfc_conv_expr_val (&argse, code->expr4);
+      until_count = fold_convert (integer_type_node, argse.expr);
+    }
+  else
+    until_count = integer_one_node;
+
+  if (flag_coarray != GFC_FCOARRAY_LIB)
+    {
+      gfc_start_block (&se.pre);
+      gfc_init_se (&argse, NULL);
+      gfc_conv_expr_val (&argse, code->expr1);
+
+      if (op == EXEC_EVENT_POST)
+       gfc_add_modify (&se.pre, argse.expr,
+                       fold_build2_loc (input_location, PLUS_EXPR,
+                               TREE_TYPE (argse.expr), argse.expr,
+                               build_int_cst (TREE_TYPE (argse.expr), 1)));
+      else
+       gfc_add_modify (&se.pre, argse.expr,
+                       fold_build2_loc (input_location, MINUS_EXPR,
+                               TREE_TYPE (argse.expr), argse.expr,
+                               fold_convert (TREE_TYPE (argse.expr),
+                                             until_count)));
+      if (stat != NULL_TREE)
+       gfc_add_modify (&se.pre, stat, build_int_cst (TREE_TYPE (stat), 0));
+
+      return gfc_finish_block (&se.pre);
+    }
+
+  gfc_start_block (&se.pre);
+  tree tmp, token, image_index, errmsg, errmsg_len;
+  tree index = size_zero_node;
+  tree caf_decl = gfc_get_tree_for_caf_expr (code->expr1);
+
+  if (code->expr1->symtree->n.sym->ts.type != BT_DERIVED
+      || code->expr1->symtree->n.sym->ts.u.derived->from_intmod
+        != INTMOD_ISO_FORTRAN_ENV
+      || code->expr1->symtree->n.sym->ts.u.derived->intmod_sym_id
+        != ISOFORTRAN_EVENT_TYPE)
+    {
+      gfc_error ("Sorry, the event component of derived type at %L is not "
+                "yet supported", &code->expr1->where);
+      return NULL_TREE;
+    }
+
+  gfc_get_caf_token_offset (&token, NULL, caf_decl, NULL_TREE, code->expr1);
+
+  if (gfc_is_coindexed (code->expr1))
+    image_index = gfc_caf_get_image_index (&se.pre, code->expr1, caf_decl);
+  else
+    image_index = integer_zero_node;
+
+  /* For arrays, obtain the array index.  */
+  if (gfc_expr_attr (code->expr1).dimension)
+    {
+      tree desc, tmp, extent, lbound, ubound;
+      gfc_array_ref *ar, ar2;
+      int i;
+
+      /* TODO: Extend this, once DT components are supported.  */
+      ar = &code->expr1->ref->u.ar;
+      ar2 = *ar;
+      memset (ar, '\0', sizeof (*ar));
+      ar->as = ar2.as;
+      ar->type = AR_FULL;
+
+      gfc_init_se (&argse, NULL);
+      argse.descriptor_only = 1;
+      gfc_conv_expr_descriptor (&argse, code->expr1);
+      gfc_add_block_to_block (&se.pre, &argse.pre);
+      desc = argse.expr;
+      *ar = ar2;
+
+      extent = integer_one_node;
+      for (i = 0; i < ar->dimen; i++)
+       {
+         gfc_init_se (&argse, NULL);
+         gfc_conv_expr_type (&argse, ar->start[i], integer_type_node);
+         gfc_add_block_to_block (&argse.pre, &argse.pre);
+         lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[i]);
+         tmp = fold_build2_loc (input_location, MINUS_EXPR,
+                                integer_type_node, argse.expr,
+                                fold_convert(integer_type_node, lbound));
+         tmp = fold_build2_loc (input_location, MULT_EXPR,
+                                integer_type_node, extent, tmp);
+         index = fold_build2_loc (input_location, PLUS_EXPR,
+                                  integer_type_node, index, tmp);
+         if (i < ar->dimen - 1)
+           {
+             ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[i]);
+             tmp = gfc_conv_array_extent_dim (lbound, ubound, NULL);
+             tmp = fold_convert (integer_type_node, tmp);
+             extent = fold_build2_loc (input_location, MULT_EXPR,
+                                       integer_type_node, extent, tmp);
+           }
+       }
+    }
+
+  /* errmsg.  */
+  if (code->expr3)
+    {
+      gfc_init_se (&argse, NULL);
+      argse.want_pointer = 1;
+      gfc_conv_expr (&argse, code->expr3);
+      gfc_add_block_to_block (&se.pre, &argse.pre);
+      errmsg = argse.expr;
+      errmsg_len = fold_convert (integer_type_node, argse.string_length);
+    }
+  else
+    {
+      errmsg = null_pointer_node;
+      errmsg_len = integer_zero_node;
+    }
+
+  if (stat != null_pointer_node && TREE_TYPE (stat) != integer_type_node)
+    {
+      stat2 = stat;
+      stat = gfc_create_var (integer_type_node, "stat");
+    }
+
+  if (op == EXEC_EVENT_POST)
+    tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_event_post, 6,
+                              token, index, image_index,
+                              stat != null_pointer_node
+                              ? gfc_build_addr_expr (NULL, stat) : stat,
+                              errmsg, errmsg_len);
+  else
+    tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_event_wait, 6,
+                              token, index, until_count,
+                              stat != null_pointer_node
+                              ? gfc_build_addr_expr (NULL, stat) : stat,
+                              errmsg, errmsg_len);
+  gfc_add_expr_to_block (&se.pre, tmp);
+
+  if (stat2 != NULL_TREE)
+    gfc_add_modify (&se.pre, stat2, fold_convert (TREE_TYPE (stat2), stat));
+
+  return gfc_finish_block (&se.pre);
+}
 
 tree
 gfc_trans_sync (gfc_code *code, gfc_exec_op type)
@@ -879,6 +1039,7 @@ gfc_trans_sync (gfc_code *code, gfc_exec_op type)
     {
       gcc_assert (code->expr3->expr_type == EXPR_VARIABLE);
       gfc_init_se (&argse, NULL);
+      argse.want_pointer = 1;
       gfc_conv_expr (&argse, code->expr3);
       gfc_conv_string_parameter (&argse);
       errmsg = gfc_build_addr_expr (NULL, argse.expr);
index 0ff93c490339ca27b268ea4113ce2f9ad3d33e6d..76f1f28f27cc45e28906fd6c1d26970028ae2512 100644 (file)
@@ -55,6 +55,7 @@ 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_event_post_wait (gfc_code *, gfc_exec_op);
 tree gfc_trans_forall (gfc_code *);
 tree gfc_trans_where (gfc_code *);
 tree gfc_trans_allocate (gfc_code *);
index 6e2b3f1a615c2186be0b65d5966ea741a56ec240..60bd8e1b9820743ea89dcbbc82fdea5a869bb964 100644 (file)
@@ -2371,6 +2371,11 @@ gfc_get_derived_type (gfc_symbol * derived)
          && derived->intmod_sym_id == ISOFORTRAN_LOCK_TYPE))
     return ptr_type_node;
 
+  if (flag_coarray != GFC_FCOARRAY_LIB
+      && derived->from_intmod == INTMOD_ISO_FORTRAN_ENV
+      && derived->intmod_sym_id == ISOFORTRAN_EVENT_TYPE)
+    return gfc_get_int_type (gfc_default_integer_kind);
+
   if (derived && derived->attr.flavor == FL_PROCEDURE
       && derived->attr.generic)
     derived = gfc_find_dt_in_generic (derived);
index 2a91c3521b6f12904d1bf82dc0b155856d3c6854..001db41ca8344cd6c6e26e53feeb7d73714e38b8 100644 (file)
@@ -711,7 +711,7 @@ gfc_allocate_using_malloc (stmtblock_t * block, tree pointer,
 static void
 gfc_allocate_using_lib (stmtblock_t * block, tree pointer, tree size,
                        tree token, tree status, tree errmsg, tree errlen,
-                       bool lock_var)
+                       bool lock_var, bool event_var)
 {
   tree tmp, pstat;
 
@@ -738,7 +738,8 @@ gfc_allocate_using_lib (stmtblock_t * block, tree pointer, tree size,
                              build_int_cst (size_type_node, 1)),
             build_int_cst (integer_type_node,
                            lock_var ? GFC_CAF_LOCK_ALLOC
-                                    : GFC_CAF_COARRAY_ALLOC),
+                            : event_var ? GFC_CAF_EVENT_ALLOC
+                                       : GFC_CAF_COARRAY_ALLOC),
             token, pstat, errmsg, errlen);
 
   tmp = fold_build2_loc (input_location, MODIFY_EXPR,
@@ -798,6 +799,11 @@ gfc_allocate_allocatable (stmtblock_t * block, tree mem, tree size, tree token,
                         == INTMOD_ISO_FORTRAN_ENV
                      && expr->ts.u.derived->intmod_sym_id
                         == ISOFORTRAN_LOCK_TYPE;
+      bool event_var = expr->ts.type == BT_DERIVED
+                      && expr->ts.u.derived->from_intmod
+                        == INTMOD_ISO_FORTRAN_ENV
+                      && expr->ts.u.derived->intmod_sym_id
+                        == ISOFORTRAN_EVENT_TYPE;
       /* In the front end, we represent the lock variable as pointer. However,
         the FE only passes the pointer around and leaves the actual
         representation to the library. Hence, we have to convert back to the
@@ -807,7 +813,7 @@ gfc_allocate_allocatable (stmtblock_t * block, tree mem, tree size, tree token,
                                size, TYPE_SIZE_UNIT (ptr_type_node));
 
       gfc_allocate_using_lib (&alloc_block, mem, size, token, status,
-                             errmsg, errlen, lock_var);
+                             errmsg, errlen, lock_var, event_var);
 
       if (status != NULL_TREE)
        {
@@ -1797,6 +1803,11 @@ trans_code (gfc_code * code, tree cond)
          res = gfc_trans_lock_unlock (code, code->op);
          break;
 
+       case EXEC_EVENT_POST:
+       case EXEC_EVENT_WAIT:
+         res = gfc_trans_event_post_wait (code, code->op);
+         break;
+
        case EXEC_FORALL:
          res = gfc_trans_forall (code);
          break;
index 3a23a3cc259e6c456b98365b22c7fb370eb4cd37..088eca376b5e445c1f790c6969393c12b3f6a151 100644 (file)
@@ -113,7 +113,9 @@ enum gfc_coarray_type
   GFC_CAF_COARRAY_ALLOC,
   GFC_CAF_LOCK_STATIC,
   GFC_CAF_LOCK_ALLOC,
-  GFC_CAF_CRITICAL
+  GFC_CAF_CRITICAL,
+  GFC_CAF_EVENT_STATIC,
+  GFC_CAF_EVENT_ALLOC
 };
 
 
@@ -763,6 +765,9 @@ extern GTY(()) tree gfor_fndecl_caf_atomic_cas;
 extern GTY(()) tree gfor_fndecl_caf_atomic_op;
 extern GTY(()) tree gfor_fndecl_caf_lock;
 extern GTY(()) tree gfor_fndecl_caf_unlock;
+extern GTY(()) tree gfor_fndecl_caf_event_post;
+extern GTY(()) tree gfor_fndecl_caf_event_wait;
+extern GTY(()) tree gfor_fndecl_caf_event_query;
 extern GTY(()) tree gfor_fndecl_co_broadcast;
 extern GTY(()) tree gfor_fndecl_co_max;
 extern GTY(()) tree gfor_fndecl_co_min;
index de67812f26d96afcc0f9a10282a5ad1878accbde..517b23e832fc61d4b4f5d177d22ed117bdbf4ab5 100644 (file)
@@ -1,3 +1,9 @@
+2015-12-02  Tobias Burnus  <burnus@net-b.de>
+           Alessandro Fanfarillo <fanfarillo.gcc@gmail.com>
+
+       * gfortran.dg/coarray/event_1.f90: New.
+       * gfortran.dg/coarray/event_2.f90: New.
+
 2015-12-02  Aditya Kumar  <aditya.k7@samsung.com>
            Sebastian Pop  <s.pop@samsung.com>
 
diff --git a/gcc/testsuite/gfortran.dg/coarray/event_1.f90 b/gcc/testsuite/gfortran.dg/coarray/event_1.f90
new file mode 100644 (file)
index 0000000..b4385f3
--- /dev/null
@@ -0,0 +1,51 @@
+! { dg-do run }
+!
+! Run-time test for EVENT_TYPE
+!
+use iso_fortran_env, only: event_type
+implicit none
+
+type(event_type), save :: var[*]
+integer :: count, stat
+
+count = -42
+call event_query (var, count)
+if (count /= 0) call abort()
+
+stat = 99
+event post (var, stat=stat)
+if (stat /= 0) call abort()
+call event_query(var, count, stat=stat)
+if (count /= 1 .or. stat /= 0) call abort()
+
+stat = 99
+event post (var[this_image()])
+call event_query(var, count)
+if (count /= 2) call abort()
+
+stat = 99
+event wait (var)
+call event_query(var, count)
+if (count /= 1) call abort()
+
+stat = 99
+event post (var)
+call event_query(var, count)
+if (count /= 2) call abort()
+
+stat = 99
+event post (var)
+call event_query(var, count)
+if (count /= 3) call abort()
+
+stat = 99
+event wait (var, until_count=2)
+call event_query(var, count)
+if (count /= 1) call abort()
+
+stat = 99
+event wait (var, stat=stat, until_count=1)
+if (stat /= 0) call abort()
+call event_query(event=var, stat=stat, count=count)
+if (count /= 0 .or. stat /= 0) call abort()
+end
diff --git a/gcc/testsuite/gfortran.dg/coarray/event_2.f90 b/gcc/testsuite/gfortran.dg/coarray/event_2.f90
new file mode 100644 (file)
index 0000000..2d451a5
--- /dev/null
@@ -0,0 +1,89 @@
+! { dg-do run }
+!
+! Run-time test for EVENT_TYPE
+!
+use iso_fortran_env, only: event_type
+implicit none
+
+type(event_type), save, allocatable :: var(:)[:]
+integer :: count, stat
+
+allocate(var(3)[*])
+
+count = -42
+call event_query (var(1), count)
+if (count /= 0) call abort()
+call event_query (var(1), count)
+if (count /= 0) call abort()
+call event_query (var(2), count)
+if (count /= 0) call abort()
+call event_query (var(3), count)
+if (count /= 0) call abort()
+
+stat = 99
+event post (var(2), stat=stat)
+if (stat /= 0) call abort()
+call event_query (var(1), count)
+if (count /= 0) call abort()
+call event_query(var(2), count, stat=stat)
+if (count /= 1 .or. stat /= 0) call abort()
+call event_query (var(3), count)
+if (count /= 0) call abort()
+
+stat = 99
+event post (var(2)[this_image()])
+call event_query(var(1), count)
+if (count /= 0) call abort()
+call event_query(var(2), count)
+if (count /= 2) call abort()
+call event_query(var(2), count)
+if (count /= 2) call abort()
+call event_query(var(3), count)
+if (count /= 0) call abort()
+
+stat = 99
+event wait (var(2))
+call event_query(var(1), count)
+if (count /= 0) call abort()
+call event_query(var(2), count)
+if (count /= 1) call abort()
+call event_query(var(3), count)
+if (count /= 0) call abort()
+
+stat = 99
+event post (var(2))
+call event_query(var(1), count)
+if (count /= 0) call abort()
+call event_query(var(2), count)
+if (count /= 2) call abort()
+call event_query(var(3), count)
+if (count /= 0) call abort()
+
+stat = 99
+event post (var(2))
+call event_query(var(1), count)
+if (count /= 0) call abort()
+call event_query(var(2), count)
+if (count /= 3) call abort()
+call event_query(var(3), count)
+if (count /= 0) call abort()
+
+stat = 99
+event wait (var(2), until_count=2)
+call event_query(var(1), count)
+if (count /= 0) call abort()
+call event_query(var(2), count)
+if (count /= 1) call abort()
+call event_query(var(3), count)
+if (count /= 0) call abort()
+
+stat = 99
+event wait (var(2), stat=stat, until_count=1)
+if (stat /= 0) call abort()
+call event_query(event=var(1), stat=stat, count=count)
+if (count /= 0 .or. stat /= 0) call abort()
+call event_query(event=var(2), stat=stat, count=count)
+if (count /= 0 .or. stat /= 0) call abort()
+call event_query(event=var(3), stat=stat, count=count)
+if (count /= 0 .or. stat /= 0) call abort()
+end
index 48db71b8df7d010687d040486c05fc039c16f0de..4843fd5046422a189b21af71e2bbed8964ce44b8 100644 (file)
@@ -1,3 +1,11 @@
+2015-11-26  Tobias Burnus  <burnus@net-b.de>
+           Alessandro Fanfarillo  <fanfarillo.gcc@gmail.com>
+
+        * caf/libcaf.h (_gfortran_caf_event_post,
+       _gfortran_caf_event_wait,_gfortran_caf_event_query): New prototypes.
+        * caf/single.c (_gfortran_caf_event_post,
+       _gfortran_caf_event_wait,_gfortran_caf_event_query): Implement.
+
 2015-11-22  Jerry DeLisle  <jvdelisle@gcc.gnu.org>
 
        PR libfortran/52251
index 660bd7c094543a0c23174af4648841b3926e81af..ebda579d06cb51a00842b8435f92524ce3a7553b 100644 (file)
@@ -57,7 +57,9 @@ typedef enum caf_register_t {
   CAF_REGTYPE_COARRAY_ALLOC,
   CAF_REGTYPE_LOCK_STATIC,
   CAF_REGTYPE_LOCK_ALLOC,
-  CAF_REGTYPE_CRITICAL
+  CAF_REGTYPE_CRITICAL,
+  CAF_REGTYPE_EVENT_STATIC,
+  CAF_REGTYPE_EVENT_ALLOC
 }
 caf_register_t;
 
@@ -133,5 +135,8 @@ void _gfortran_caf_atomic_op (int, caf_token_t, size_t, int, void *, void *,
 
 void _gfortran_caf_lock (caf_token_t, size_t, int, int *, int *, char *, int);
 void _gfortran_caf_unlock (caf_token_t, size_t, int, int *, char *, int);
+void _gfortran_caf_event_post (caf_token_t, size_t, int, int *, char *, int);
+void _gfortran_caf_event_wait (caf_token_t, size_t, int, int *, char *, int);
+void _gfortran_caf_event_query (caf_token_t, size_t, int, int *, int *);
 
 #endif  /* LIBCAF_H  */
index 6c582860ebfaca5f9120c531ed5fffcc77bdb1a3..9c4b3434f5c242b747d3fc997c63d9fc57ffecb3 100644 (file)
@@ -101,7 +101,8 @@ _gfortran_caf_register (size_t size, caf_register_t type, caf_token_t *token,
   void *local;
 
   if (type == CAF_REGTYPE_LOCK_STATIC || type == CAF_REGTYPE_LOCK_ALLOC
-      || type == CAF_REGTYPE_CRITICAL)
+      || type == CAF_REGTYPE_CRITICAL || type == CAF_REGTYPE_EVENT_STATIC
+      || type == CAF_REGTYPE_EVENT_ALLOC)
     local = calloc (size, sizeof (bool));
   else
     local = malloc (size);
@@ -133,7 +134,8 @@ _gfortran_caf_register (size_t size, caf_register_t type, caf_token_t *token,
     *stat = 0;
 
   if (type == CAF_REGTYPE_COARRAY_STATIC || type == CAF_REGTYPE_LOCK_STATIC
-      || type == CAF_REGTYPE_CRITICAL)
+      || type == CAF_REGTYPE_CRITICAL || type == CAF_REGTYPE_EVENT_STATIC
+      || type == CAF_REGTYPE_EVENT_ALLOC)
     {
       caf_static_t *tmp = malloc (sizeof (caf_static_t));
       tmp->prev  = caf_static_list;
@@ -1071,6 +1073,45 @@ _gfortran_caf_atomic_op (int op, caf_token_t token, size_t offset,
     *stat = 0;
 }
 
+void
+_gfortran_caf_event_post (caf_token_t token, size_t index, 
+                         int image_index __attribute__ ((unused)), 
+                         int *stat, char *errmsg __attribute__ ((unused)), 
+                         int errmsg_len __attribute__ ((unused)))
+{
+  uint32_t value = 1;
+  uint32_t *event = (uint32_t *) ((char *) TOKEN (token) + index*sizeof(uint32_t));
+  __atomic_fetch_add (event, (uint32_t) value, __ATOMIC_RELAXED);
+  
+  if(stat)
+    *stat = 0;
+}
+
+void
+_gfortran_caf_event_wait (caf_token_t token, size_t index, 
+                         int until_count, int *stat,
+                         char *errmsg __attribute__ ((unused)), 
+                         int errmsg_len __attribute__ ((unused)))
+{
+  uint32_t *event = (uint32_t *) ((char *) TOKEN (token) + index*sizeof(uint32_t));
+  uint32_t value = (uint32_t)-until_count;
+   __atomic_fetch_add (event, (uint32_t) value, __ATOMIC_RELAXED);
+  
+   if(stat)
+    *stat = 0;    
+}
+
+void
+_gfortran_caf_event_query (caf_token_t token, size_t index, 
+                          int image_index __attribute__ ((unused)), 
+                          int *count, int *stat)
+{
+  uint32_t *event = (uint32_t *) ((char *) TOKEN (token) + index*sizeof(uint32_t));
+  __atomic_load (event, (uint32_t *) count, __ATOMIC_RELAXED);
+  
+  if(stat)
+    *stat = 0;
+}
 
 void
 _gfortran_caf_lock (caf_token_t token, size_t index,