https://gcc.gnu.org/g:6e3b92848b529b1c4b7fc12fa3fe0f54df16ecec
commit r16-79-g6e3b92848b529b1c4b7fc12fa3fe0f54df16ecec Author: Andre Vehreschild <ve...@gcc.gnu.org> Date: Tue Apr 15 15:21:26 2025 +0200 Fortran: Various fixes on F2018 teams. 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. Diff: --- gcc/fortran/match.cc | 10 ++- gcc/fortran/trans-intrinsic.cc | 4 +- gcc/fortran/trans-stmt.cc | 24 +++++++ gcc/fortran/trans.h | 4 +- gcc/testsuite/gfortran.dg/coarray/coindexed_3.f08 | 1 + gcc/testsuite/gfortran.dg/coarray/coindexed_5.f90 | 80 +++++++++++++++++++++++ gcc/testsuite/gfortran.dg/team_change_2.f90 | 7 ++ gcc/testsuite/gfortran.dg/team_end_2.f90 | 9 +++ gcc/testsuite/gfortran.dg/team_end_3.f90 | 8 ++- libgfortran/caf/libcaf.h | 9 +-- libgfortran/caf/single.c | 60 ++++++++++++++--- 11 files changed, 193 insertions(+), 23 deletions(-) diff --git a/gcc/fortran/match.cc b/gcc/fortran/match.cc index 0d81b69025e0..474ba81b2aa0 100644 --- a/gcc/fortran/match.cc +++ b/gcc/fortran/match.cc @@ -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 (;;) { diff --git a/gcc/fortran/trans-intrinsic.cc b/gcc/fortran/trans-intrinsic.cc index f388ba5bc81d..440cbdd19abc 100644 --- a/gcc/fortran/trans-intrinsic.cc +++ b/gcc/fortran/trans-intrinsic.cc @@ -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, diff --git a/gcc/fortran/trans-stmt.cc b/gcc/fortran/trans-stmt.cc index 11fc1a8ff064..487b7687ef14 100644 --- a/gcc/fortran/trans-stmt.cc +++ b/gcc/fortran/trans-stmt.cc @@ -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 diff --git a/gcc/fortran/trans.h b/gcc/fortran/trans.h index 13bb04af1d2c..461b0cdac71c 100644 --- a/gcc/fortran/trans.h +++ b/gcc/fortran/trans.h @@ -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. */ diff --git a/gcc/testsuite/gfortran.dg/coarray/coindexed_3.f08 b/gcc/testsuite/gfortran.dg/coarray/coindexed_3.f08 index 29c2b3a80287..7fd20851e0a9 100644 --- a/gcc/testsuite/gfortran.dg/coarray/coindexed_3.f08 +++ b/gcc/testsuite/gfortran.dg/coarray/coindexed_3.f08 @@ -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 index 000000000000..c35ec1093c1f --- /dev/null +++ b/gcc/testsuite/gfortran.dg/coarray/coindexed_5.f90 @@ -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 diff --git a/gcc/testsuite/gfortran.dg/team_change_2.f90 b/gcc/testsuite/gfortran.dg/team_change_2.f90 index 00cc489bf1fd..66fe63c829b7 100644 --- a/gcc/testsuite/gfortran.dg/team_change_2.f90 +++ b/gcc/testsuite/gfortran.dg/team_change_2.f90 @@ -74,6 +74,13 @@ 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 diff --git a/gcc/testsuite/gfortran.dg/team_end_2.f90 b/gcc/testsuite/gfortran.dg/team_end_2.f90 index 64f072aed3de..c27b59d17384 100644 --- a/gcc/testsuite/gfortran.dg/team_end_2.f90 +++ b/gcc/testsuite/gfortran.dg/team_end_2.f90 @@ -29,5 +29,14 @@ 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 diff --git a/gcc/testsuite/gfortran.dg/team_end_3.f90 b/gcc/testsuite/gfortran.dg/team_end_3.f90 index 5e004ada64f7..9cd7d4c9d64d 100644 --- a/gcc/testsuite/gfortran.dg/team_end_3.f90 +++ b/gcc/testsuite/gfortran.dg/team_end_3.f90 @@ -29,10 +29,12 @@ 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" } } diff --git a/libgfortran/caf/libcaf.h b/libgfortran/caf/libcaf.h index 2db8e3903822..7267bc76905e 100644 --- a/libgfortran/caf/libcaf.h +++ b/libgfortran/caf/libcaf.h @@ -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. */ diff --git a/libgfortran/caf/single.c b/libgfortran/caf/single.c index a80fd966f441..97876fa9d8c2 100644 --- a/libgfortran/caf/single.c +++ b/libgfortran/caf/single.c @@ -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;