]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Fortran: Various fixes on F2018 teams.
authorAndre Vehreschild <vehre@gcc.gnu.org>
Tue, 15 Apr 2025 13:21:26 +0000 (15:21 +0200)
committerAndre Vehreschild <vehre@gcc.gnu.org>
Tue, 22 Apr 2025 11:17:51 +0000 (13:17 +0200)
gcc/fortran/ChangeLog:

* match.cc (match_exit_cycle): Allow to exit team block.
(gfc_match_end_team): Create end_team node also without
parameter list.
* trans-intrinsic.cc (conv_stat_and_team): Team and team_number
only need to be a single pointer.
* trans-stmt.cc (trans_associate_var): Create a mapping coarray
token for coarray associations or it is not addressed correctly.
* trans.h (enum gfc_coarray_regtype): Add mapping mode to
coarray register.

libgfortran/ChangeLog:

* caf/libcaf.h: Add mapping mode to coarray's register.
* caf/single.c (_gfortran_caf_register): Create a token sharing
another token's memory.
(check_team): Check team parameters to coindexed expressions are
valid.

gcc/testsuite/ChangeLog:

* gfortran.dg/coarray/coindexed_3.f08: Add minimal test for
get_team().
* gfortran.dg/team_change_2.f90: Add test for change team with
label and exiting out of it.
* gfortran.dg/team_end_2.f90: Check parsing to labeled team
blocks is correct now.
* gfortran.dg/team_end_3.f90: Check that end_team call is
generated for labeled end_teams, too.
* gfortran.dg/coarray/coindexed_5.f90: New test.

gcc/fortran/match.cc
gcc/fortran/trans-intrinsic.cc
gcc/fortran/trans-stmt.cc
gcc/fortran/trans.h
gcc/testsuite/gfortran.dg/coarray/coindexed_3.f08
gcc/testsuite/gfortran.dg/coarray/coindexed_5.f90 [new file with mode: 0644]
gcc/testsuite/gfortran.dg/team_change_2.f90
gcc/testsuite/gfortran.dg/team_end_2.f90
gcc/testsuite/gfortran.dg/team_end_3.f90
libgfortran/caf/libcaf.h
libgfortran/caf/single.c

index 0d81b69025e0b8dbe4795e24deac5ef88f24ac10..474ba81b2aa09f4ff8a2db556d79b9c599d1acf7 100644 (file)
@@ -3325,6 +3325,7 @@ match_exit_cycle (gfc_statement st, gfc_exec_op op)
 
     case COMP_ASSOCIATE:
     case COMP_BLOCK:
+    case COMP_CHANGE_TEAM:
     case COMP_IF:
     case COMP_SELECT:
     case COMP_SELECT_TYPE:
@@ -4162,9 +4163,12 @@ gfc_match_end_team (void)
     goto done;
 
   if (gfc_match_char ('(') != MATCH_YES)
-    /* There could be a team-construct-name following.  Let caller decide
-       about error.  */
-    return MATCH_NO;
+    {
+      /* There could be a team-construct-name following.  Let caller decide
+        about error.  */
+      new_st.op = EXEC_END_TEAM;
+      return MATCH_NO;
+    }
 
   for (;;)
     {
index f388ba5bc81defe55656c3e35678ac111cdcf147..440cbdd19abc5800ed4dac2343fbcd2fcdd3e8c9 100644 (file)
@@ -1183,7 +1183,7 @@ conv_stat_and_team (stmtblock_t *block, gfc_expr *expr, tree *stat, tree *team,
     {
       gfc_se team_se;
       gfc_init_se (&team_se, NULL);
-      gfc_conv_expr_reference (&team_se, team_e);
+      gfc_conv_expr (&team_se, team_e);
       *team
        = gfc_build_addr_expr (NULL_TREE, gfc_trans_force_lval (&team_se.pre,
                                                                team_se.expr));
@@ -1198,7 +1198,7 @@ conv_stat_and_team (stmtblock_t *block, gfc_expr *expr, tree *stat, tree *team,
     {
       gfc_se team_se;
       gfc_init_se (&team_se, NULL);
-      gfc_conv_expr_reference (&team_se, team_e);
+      gfc_conv_expr (&team_se, team_e);
       *team_no = gfc_build_addr_expr (
        NULL_TREE,
        gfc_trans_force_lval (&team_se.pre,
index 11fc1a8ff064ac0ed92f3ca9af9ae3a7cb8b5a5b..487b7687ef1492eca90c03c9db289d4d77f52446 100644 (file)
@@ -2056,6 +2056,30 @@ trans_associate_var (gfc_symbol *sym, gfc_wrapped_block *block)
 
       gfc_conv_expr_descriptor (&se, e);
 
+      if (flag_coarray == GFC_FCOARRAY_LIB && sym->attr.codimension)
+       {
+         tree token = gfc_conv_descriptor_token (se.expr),
+              size
+              = sym->attr.dimension
+                  ? fold_build2 (MULT_EXPR, gfc_array_index_type,
+                                 gfc_conv_descriptor_size (se.expr, e->rank),
+                                 gfc_conv_descriptor_span_get (se.expr))
+                  : gfc_conv_descriptor_span_get (se.expr);
+         /* Create a new token, because in the token the modified descriptor
+            is stored.  The modified descriptor is needed for accesses on the
+            remote image.  In the scalar case, the base address needs to be
+            associated correctly, which also needs a new token.
+            The token is freed automatically be the end team statement.  */
+         gfc_add_expr_to_block (
+           &se.pre,
+           build_call_expr_loc (
+             input_location, gfor_fndecl_caf_register, 7, size,
+             build_int_cst (integer_type_node, GFC_CAF_COARRAY_MAP_EXISTING),
+             gfc_build_addr_expr (pvoid_type_node, token),
+             gfc_build_addr_expr (NULL_TREE, se.expr), null_pointer_node,
+             null_pointer_node, integer_zero_node));
+       }
+
       if (sym->ts.type == BT_CHARACTER
          && !sym->attr.select_type_temporary
          && sym->ts.u.cl->backend_decl
index 13bb04af1d2cf929662bf6449c420dbcdb155b40..461b0cdac71c8dcd209ecec2efa81ad29ce99d7c 100644 (file)
@@ -139,10 +139,10 @@ enum gfc_coarray_regtype
   GFC_CAF_EVENT_STATIC,
   GFC_CAF_EVENT_ALLOC,
   GFC_CAF_COARRAY_ALLOC_REGISTER_ONLY,
-  GFC_CAF_COARRAY_ALLOC_ALLOCATE_ONLY
+  GFC_CAF_COARRAY_ALLOC_ALLOCATE_ONLY,
+  GFC_CAF_COARRAY_MAP_EXISTING
 };
 
-
 /* Describes the action to take on _caf_deregister.  Keep in sync with
    gcc/fortran/trans.h.  The negative values are not valid for the library and
    are used by the drivers for building the correct call.  */
index 29c2b3a8028705af8dedf71b6df5799d55122dc8..7fd20851e0a94e68195a830f5aeda0dc0bf189d4 100644 (file)
@@ -9,6 +9,7 @@ program pr98903
   integer :: a[*]
   type(team_type) :: team
 
+  team = get_team()
   me = this_image()
   n = num_images()
   a = 42
diff --git a/gcc/testsuite/gfortran.dg/coarray/coindexed_5.f90 b/gcc/testsuite/gfortran.dg/coarray/coindexed_5.f90
new file mode 100644 (file)
index 0000000..c35ec10
--- /dev/null
@@ -0,0 +1,80 @@
+!{ dg-do run }
+
+! Check coindexes with team= or team_number= are working.
+
+program coindexed_5
+  use, intrinsic :: iso_fortran_env
+
+  type(team_type) :: parentteam, team, formed_team
+  integer :: t_num= 42, stat = 42, lhs
+  integer(kind=2) :: st_num=42
+  integer :: caf(2)[*]
+
+  parentteam = get_team()
+
+  caf = [23, 32]
+  form team(t_num, team, new_index=1)
+  form team(t_num, formed_team)
+
+  change team(team, cell[*] => caf(2))
+    ! for get_from_remote
+    ! Checking against caf_single is very limitted.
+    if (cell[1, team_number=t_num] /= 32) stop 1
+    if (cell[1, team_number=st_num] /= 32) stop 2
+    if (cell[1, team=parentteam] /= 32) stop 3
+
+    ! Check that team_number is validated
+    lhs = cell[1, team_number=5, stat=stat]
+    if (stat /= 1) stop 4
+
+    ! Check that only access to active teams is valid
+    stat = 42
+    lhs = cell[1, team=formed_team, stat=stat]
+    if (stat /= 1) stop 5
+
+    ! for send_to_remote
+    ! Checking against caf_single is very limitted.
+    cell[1, team_number=t_num] = 45
+    if (cell /= 45) stop 11
+    cell[1, team_number=st_num] = 46
+    if (cell /= 46) stop 12
+    cell[1, team=parentteam] = 47
+    if (cell /= 47) stop 13
+
+    ! Check that team_number is validated
+    stat = -1
+    cell[1, team_number=5, stat=stat] = 0
+    if (stat /= 1) stop 14
+
+    ! Check that only access to active teams is valid
+    stat = 42
+    cell[1, team=formed_team, stat=stat] = -1
+    if (stat /= 1) stop 15
+
+    ! for transfer_between_remotes
+    ! Checking against caf_single is very limitted.
+    cell[1, team_number=t_num] = caf(1)[1, team_number=-1]
+    if (cell /= 23) stop 21
+    cell[1, team_number=st_num] = caf(2)[1, team_number=-1]
+    ! cell is an alias for caf(2) and has been overwritten by caf(1)!
+    if (cell /= 23) stop 22
+    cell[1, team=parentteam] = caf(1)[1, team= team]
+    if (cell /= 23) stop 23
+
+    ! Check that team_number is validated
+    stat = -1
+    cell[1, team_number=5, stat=stat] = caf(1)[1, team_number= -1]
+    if (stat /= 1) stop 24
+    stat = -1
+    cell[1, team_number=t_num] = caf(1)[1, team_number= -2, stat=stat]
+    if (stat /= 1) stop 25
+
+    ! Check that only access to active teams is valid
+    stat = 42
+    cell[1, team=formed_team, stat=stat] = caf(1)[1]
+    if (stat /= 1) stop 26
+    stat = 42
+    cell[1] = caf(1)[1, team=formed_team, stat=stat]
+    if (stat /= 1) stop 27
+  end team
+end program coindexed_5
index 00cc489bf1fd6c04c47ee122d27697bd1c77b08b..66fe63c829b7f16b8740390e2bb2bf3633ccac3b 100644 (file)
     continue
   end team !{ dg-error "Expecting END PROGRAM statement" }
 
+  t: change team(team)
+    exit t
+  end team t
+
+  change team(team)
+    exit t !{ dg-error "EXIT statement at \\(1\\) is not within construct 't'" }
+  end team
 contains
   subroutine foo(team)
     type(team_type) :: team
index 64f072aed3de9fe45dd0bbec6fe027093532f52b..c27b59d17384219260236ab681cb922a9bbfe905 100644 (file)
   change team (team)
     continue
   end team (stat=istat, errmsg=err, errmsg=err) ! { dg-error "Duplicate ERRMSG" }
+
+  t: change team (team)
+    continue
+  end team (stat=istat) t ! ok
+
+  t2: change team (team)
+    continue
+  end team   ! { dg-error "Expected block name of 't2' in END TEAM" }
+  end team t2  ! close the team correctly to catch other errors
 end
 
index 5e004ada64f7fcbfcf7369f2a6dfb519dfddba58..9cd7d4c9d64d58f530bacf4f01602b383bfe4ec9 100644 (file)
   deallocate(sample, stat=istat)
   if (istat == 0) stop 6
 
-  change team (team)
+  istat = 42
+  t: change team (team)
     continue
-  end team (stat=istat, errmsg=err)
-  if (trim(err) /= 'unchanged') stop 7
+  end team (stat=istat, errmsg=err) t
+  if (istat /= 0) stop 7
+  if (trim(err) /= 'unchanged') stop 8
 end
 
 ! { dg-final { scan-tree-dump "_gfortran_caf_end_team \\(&istat, 0B, 0\\)" "original" } }
index 2db8e3903822edd36433cc81ea43daad64f6ff03..7267bc76905e29d7a1b6a638dcf0e326c2bd2ca3 100644 (file)
@@ -55,7 +55,8 @@ typedef enum
 
 /* Describes what type of array we are registerring.  Keep in sync with
    gcc/fortran/trans.h.  */
-typedef enum caf_register_t {
+typedef enum caf_register_t
+{
   CAF_REGTYPE_COARRAY_STATIC,
   CAF_REGTYPE_COARRAY_ALLOC,
   CAF_REGTYPE_LOCK_STATIC,
@@ -64,9 +65,9 @@ typedef enum caf_register_t {
   CAF_REGTYPE_EVENT_STATIC,
   CAF_REGTYPE_EVENT_ALLOC,
   CAF_REGTYPE_COARRAY_ALLOC_REGISTER_ONLY,
-  CAF_REGTYPE_COARRAY_ALLOC_ALLOCATE_ONLY
-}
-caf_register_t;
+  CAF_REGTYPE_COARRAY_ALLOC_ALLOCATE_ONLY,
+  CAF_REGTYPE_COARRAY_MAP_EXISTING,
+caf_register_t;
 
 /* Describes the action to take on _caf_deregister.  Keep in sync with
    gcc/fortran/trans.h.  */
index a80fd966f441a5db9ad154a0eec217d0a5521aee..97876fa9d8c2685e2df67ece22afd8acc83415bc 100644 (file)
@@ -227,6 +227,8 @@ _gfortran_caf_register (size_t size, caf_register_t type, caf_token_t *token,
     local = calloc (size, sizeof (uint32_t));
   else if (type == CAF_REGTYPE_COARRAY_ALLOC_REGISTER_ONLY)
     local = NULL;
+  else if (type == CAF_REGTYPE_COARRAY_MAP_EXISTING)
+    local = GFC_DESCRIPTOR_DATA (data);
   else
     local = malloc (size);
 
@@ -248,7 +250,8 @@ _gfortran_caf_register (size_t size, caf_register_t type, caf_token_t *token,
 
   single_token = TOKEN (*token);
   single_token->memptr = local;
-  single_token->owning_memory = type != CAF_REGTYPE_COARRAY_ALLOC_REGISTER_ONLY;
+  single_token->owning_memory = type != CAF_REGTYPE_COARRAY_ALLOC_REGISTER_ONLY
+                               && type != CAF_REGTYPE_COARRAY_MAP_EXISTING;
   single_token->desc = GFC_DESCRIPTOR_RANK (data) > 0 ? data : NULL;
 
   if (unlikely (!caf_team_stack))
@@ -620,6 +623,37 @@ _gfortran_caf_get_remote_function_index (const int hash)
   return index;
 }
 
+static bool
+check_team (caf_team_t *team, int *team_number, int *stat)
+{
+  if (team || team_number)
+    {
+      caf_single_team_t cur = caf_team_stack;
+
+      if (team)
+       {
+         caf_single_team_t single_team = (caf_single_team_t) (*team);
+         while (cur && cur != single_team)
+           cur = cur->parent;
+       }
+      else
+       while (cur && cur->team_no != *team_number)
+         cur = cur->parent;
+
+      if (!cur)
+       {
+         if (stat)
+           {
+             *stat = 1;
+             return false;
+           }
+         else
+           caf_runtime_error ("requested team not found");
+       }
+    }
+  return true;
+}
+
 void
 _gfortran_caf_get_from_remote (
   caf_token_t token, const gfc_descriptor_t *opt_src_desc,
@@ -628,8 +662,7 @@ _gfortran_caf_get_from_remote (
   size_t *opt_dst_charlen, gfc_descriptor_t *opt_dst_desc,
   const bool may_realloc_dst, const int getter_index, void *add_data,
   const size_t add_data_size __attribute__ ((unused)), int *stat,
-  caf_team_t *team __attribute__ ((unused)),
-  int *team_number __attribute__ ((unused)))
+  caf_team_t *team, int *team_number)
 {
   caf_single_token_t single_token = TOKEN (token);
   void *src_ptr = opt_src_desc ? (void *) opt_src_desc : single_token->memptr;
@@ -644,6 +677,9 @@ _gfortran_caf_get_from_remote (
   if (stat)
     *stat = 0;
 
+  if (!check_team (team, team_number, stat))
+    return;
+
   if (opt_dst_desc && !may_realloc_dst)
     {
       old_dst_data_ptr = opt_dst_desc->base_addr;
@@ -696,8 +732,7 @@ _gfortran_caf_send_to_remote (
   const size_t *opt_src_charlen, const gfc_descriptor_t *opt_src_desc,
   const int accessor_index, void *add_data,
   const size_t add_data_size __attribute__ ((unused)), int *stat,
-  caf_team_t *team __attribute__ ((unused)),
-  int *team_number __attribute__ ((unused)))
+  caf_team_t *team, int *team_number)
 {
   caf_single_token_t single_token = TOKEN (token);
   void *dst_ptr = opt_dst_desc ? (void *) opt_dst_desc : single_token->memptr;
@@ -710,6 +745,9 @@ _gfortran_caf_send_to_remote (
   if (stat)
     *stat = 0;
 
+  if (!check_team (team, team_number, stat))
+    return;
+
   accessor_hash_table[accessor_index].u.receiver (add_data, &image_index,
                                                  dst_ptr, src_ptr, &cb_token,
                                                  0, opt_dst_charlen,
@@ -727,10 +765,8 @@ _gfortran_caf_transfer_between_remotes (
   const int src_access_index, void *src_add_data,
   const size_t src_add_data_size __attribute__ ((unused)),
   const size_t src_size, const bool scalar_transfer, int *dst_stat,
-  int *src_stat, caf_team_t *dst_team __attribute__ ((unused)),
-  int *dst_team_number __attribute__ ((unused)),
-  caf_team_t *src_team __attribute__ ((unused)),
-  int *src_team_number __attribute__ ((unused)))
+  int *src_stat, caf_team_t *dst_team, int *dst_team_number,
+  caf_team_t *src_team, int *src_team_number)
 {
   caf_single_token_t src_single_token = TOKEN (src_token),
                     dst_single_token = TOKEN (dst_token);
@@ -749,6 +785,9 @@ _gfortran_caf_transfer_between_remotes (
   if (src_stat)
     *src_stat = 0;
 
+  if (!check_team (src_team, src_team_number, src_stat))
+    return;
+
   if (!scalar_transfer)
     {
       const size_t desc_size = sizeof (*transfer_desc);
@@ -771,6 +810,9 @@ _gfortran_caf_transfer_between_remotes (
   if (dst_stat)
     *dst_stat = 0;
 
+  if (!check_team (dst_team, dst_team_number, dst_stat))
+    return;
+
   if (scalar_transfer)
     transfer_ptr = *(void **) transfer_ptr;