https://gcc.gnu.org/g:7044071f07d763444247e32f9db25d7a658b7f9e
commit r16-6273-g7044071f07d763444247e32f9db25d7a658b7f9e Author: Tobias Burnus <[email protected]> Date: Fri Dec 19 12:07:58 2025 +0100 OpenMP: uses_allocators with ';'-separated list OpenMP 6.0 has the following wording for the uses_allocators clause: "More than one clause-argument-specification may be specified"; this permits ';' lists. While that's pointless for predefined allocators, for user-defined allocators it saves redundant ') uses_allocators(' by permitting: uses_allocators( traits(t1): alloc1 ; traits(t2): alloc2 ) Additionally, the order in the tree dump has been changed to place the modifiers before the allocator variable, matching the input syntax. gcc/c/ChangeLog: * c-parser.cc (c_parser_omp_clause_uses_allocators): Accept multiple clause-argument-specifications separated by ';'. gcc/cp/ChangeLog: * parser.cc (cp_parser_omp_clause_uses_allocators): Accept multiple clause-argument-specifications separated by ';'. gcc/fortran/ChangeLog: * openmp.cc (gfc_match_omp_clause_uses_allocators): Accept multiple clause-argument-specifications separated by ';'. gcc/ChangeLog: * tree-pretty-print.cc (dump_omp_clause): For uses_allocators, print modifier before allocator variable. libgomp/ChangeLog: * testsuite/libgomp.fortran/uses_allocators-7.f90: Add ';' test. gcc/testsuite/ChangeLog: * c-c++-common/gomp/uses_allocators-8.c: New test. Diff: --- gcc/c/c-parser.cc | 13 +++++ gcc/cp/parser.cc | 14 +++++ gcc/fortran/openmp.cc | 24 +++++++-- .../c-c++-common/gomp/uses_allocators-8.c | 59 ++++++++++++++++++++++ gcc/tree-pretty-print.cc | 9 ++-- .../libgomp.fortran/uses_allocators-7.f90 | 20 ++++++-- 6 files changed, 125 insertions(+), 14 deletions(-) diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc index e39429afbb5c..8065d3000e61 100644 --- a/gcc/c/c-parser.cc +++ b/gcc/c/c-parser.cc @@ -19577,11 +19577,16 @@ c_parser_omp_clause_allocate (c_parser *parser, tree list) allocator ( traits-array ) allocator ( traits-array ) , allocator-list + Deprecated in 5.2, removed in 6.0: 'allocator(trait-array)' syntax. + OpenMP 5.2: uses_allocators ( modifier : allocator-list ) uses_allocators ( modifier , modifier : allocator-list ) + OpenMP 6.0: + uses_allocators ( [modifier-list :] allocator-list [; ...] ) + modifier: traits ( traits-array ) memspace ( mem-space-handle ) */ @@ -19595,6 +19600,8 @@ c_parser_omp_clause_uses_allocators (c_parser *parser, tree list) if (!parens.require_open (parser)) return list; +parse_next: + bool has_modifiers = false; bool seen_allocators = false; tree memspace_expr = NULL_TREE; @@ -19790,6 +19797,12 @@ c_parser_omp_clause_uses_allocators (c_parser *parser, tree list) break; } + if (c_parser_next_token_is (parser, CPP_SEMICOLON)) + { + c_parser_consume_token (parser); + goto parse_next; + } + end: parens.skip_until_found_close (parser); return nl; diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index e106583c4b8b..4685a9ab80fa 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -42815,11 +42815,16 @@ cp_parser_omp_clause_allocate (cp_parser *parser, tree list) allocator ( traits-array ) allocator ( traits-array ) , allocator-list + Deprecated in 5.2, removed in 6.0: 'allocator(trait-array)' syntax. + OpenMP 5.2: uses_allocators ( modifier : allocator-list ) uses_allocators ( modifier , modifier : allocator-list ) + OpenMP 6.0: + uses_allocators ( [modifier-list :] allocator-list [; ...] ) + modifier: traits ( traits-array ) memspace ( mem-space-handle ) */ @@ -42834,6 +42839,8 @@ cp_parser_omp_clause_uses_allocators (cp_parser *parser, tree list) if (!parens.require_open (parser)) return list; +parse_next: + bool has_modifiers = false; bool seen_allocators = false; tree memspace_expr = NULL_TREE; @@ -42988,9 +42995,16 @@ cp_parser_omp_clause_uses_allocators (cp_parser *parser, tree list) break; } + if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON)) + { + cp_lexer_consume_token (parser->lexer); + goto parse_next; + } + if (!parens.require_close (parser)) goto end; return nl; + end: cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, diff --git a/gcc/fortran/openmp.cc b/gcc/fortran/openmp.cc index a7a76694c2c7..76c601952a70 100644 --- a/gcc/fortran/openmp.cc +++ b/gcc/fortran/openmp.cc @@ -1795,9 +1795,14 @@ omp_verify_merge_absent_contains (gfc_statement st, gfc_omp_assumptions *check, predefined-allocator variable ( traits-array ) + OpenMP 5.2 deprecated, 6.0 deleted: 'variable ( traits-array )' + OpenMP 5.2: uses_allocators ( [modifier-list :] allocator-list ) + OpenMP 6.0: + uses_allocators ( [modifier-list :] allocator-list [; ...]) + allocator: variable or predefined-allocator modifier: @@ -1807,6 +1812,7 @@ omp_verify_merge_absent_contains (gfc_statement st, gfc_omp_assumptions *check, static match gfc_match_omp_clause_uses_allocators (gfc_omp_clauses *c) { +parse_next: gfc_symbol *memspace_sym = NULL; gfc_symbol *traits_sym = NULL; gfc_omp_namelist *head = NULL; @@ -1878,11 +1884,17 @@ gfc_match_omp_clause_uses_allocators (gfc_omp_clauses *c) p->u.memspace_sym = memspace_sym; p->u2.traits_sym = traits_sym; } - if (gfc_match (", ") == MATCH_YES) - continue; - if (gfc_match (") ") == MATCH_YES) + gfc_gobble_whitespace (); + const char c = gfc_peek_ascii_char (); + if (c == ';' || c == ')') break; - goto error; + if (c != ',') + { + gfc_error ("Expected %<,%>, %<)%> or %<;%> at %C"); + goto error; + } + gfc_match_char (','); + gfc_gobble_whitespace (); } while (true); list = &c->lists[OMP_LIST_USES_ALLOCATORS]; @@ -1890,6 +1902,10 @@ gfc_match_omp_clause_uses_allocators (gfc_omp_clauses *c) list = &(*list)->next; *list = head; + if (gfc_match_char (';') == MATCH_YES) + goto parse_next; + + gfc_match_char (')'); return MATCH_YES; error: diff --git a/gcc/testsuite/c-c++-common/gomp/uses_allocators-8.c b/gcc/testsuite/c-c++-common/gomp/uses_allocators-8.c new file mode 100644 index 000000000000..642b6b9caeb0 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/uses_allocators-8.c @@ -0,0 +1,59 @@ +// { dg-do compile } + +//#include <omp.h> + +typedef __UINTPTR_TYPE__ omp_uintptr_t; + +#if __cplusplus >= 201103L +# define __GOMP_UINTPTR_T_ENUM : omp_uintptr_t +#else +# define __GOMP_UINTPTR_T_ENUM +#endif + +typedef enum omp_memspace_handle_t __GOMP_UINTPTR_T_ENUM +{ + omp_default_mem_space = 0, + omp_large_cap_mem_space = 1, + omp_const_mem_space = 2, + omp_high_bw_mem_space = 3, + omp_low_lat_mem_space = 4, + ompx_gnu_managed_mem_space = 200, + __omp_memspace_handle_t_max__ = __UINTPTR_MAX__ +} omp_memspace_handle_t; + +typedef enum omp_allocator_handle_t __GOMP_UINTPTR_T_ENUM +{ + omp_null_allocator = 0, + omp_default_mem_alloc = 1, + omp_large_cap_mem_alloc = 2, + omp_const_mem_alloc = 3, + omp_high_bw_mem_alloc = 4, + omp_low_lat_mem_alloc = 5, + omp_cgroup_mem_alloc = 6, + omp_pteam_mem_alloc = 7, + omp_thread_mem_alloc = 8, + ompx_gnu_pinned_mem_alloc = 200, + ompx_gnu_managed_mem_alloc = 201, + __omp_allocator_handle_t_max__ = __UINTPTR_MAX__ +} omp_allocator_handle_t; + +typedef struct omp_alloctrait_t +{ +// omp_alloctrait_key_t key; +// omp_uintptr_t value; +} omp_alloctrait_t; + + +void f() +{ + omp_allocator_handle_t my, my2, my3, my4; +const omp_alloctrait_t t[] = {}; +const omp_alloctrait_t t2[] = {}; + #pragma omp target uses_allocators(traits(t), memspace(omp_high_bw_mem_space) : my; omp_default_mem_alloc, omp_null_allocator; my2; traits(t2) : my3; memspace(omp_large_cap_mem_space) : my4) + ; +} + +// { dg-final { scan-tree-dump "#pragma omp target uses_allocators\\(memspace\\(1\\), traits\\(\\) : my4\\) uses_allocators\\(memspace\\(\\), traits\\(t2\\) : my3\\) uses_allocators\\(memspace\\(\\), traits\\(\\) : my2\\) uses_allocators\\(memspace\\(3\\), traits\\(t\\) : my\\)" "original" } } + + +// { dg-message "sorry, unimplemented: 'uses_allocators' clause" "" { target *-*-* } 52 } diff --git a/gcc/tree-pretty-print.cc b/gcc/tree-pretty-print.cc index 15e7ead32e1b..54bf79800925 100644 --- a/gcc/tree-pretty-print.cc +++ b/gcc/tree-pretty-print.cc @@ -908,16 +908,15 @@ dump_omp_clause (pretty_printer *pp, tree clause, int spc, dump_flags_t flags) break; case OMP_CLAUSE_USES_ALLOCATORS: - pp_string (pp, "uses_allocators("); - dump_generic_node (pp, OMP_CLAUSE_USES_ALLOCATORS_ALLOCATOR (clause), - spc, flags, false); - pp_string (pp, ": memspace("); + pp_string (pp, "uses_allocators(memspace("); dump_generic_node (pp, OMP_CLAUSE_USES_ALLOCATORS_MEMSPACE (clause), spc, flags, false); pp_string (pp, "), traits("); dump_generic_node (pp, OMP_CLAUSE_USES_ALLOCATORS_TRAITS (clause), spc, flags, false); - pp_right_paren (pp); + pp_string (pp, ") : "); + dump_generic_node (pp, OMP_CLAUSE_USES_ALLOCATORS_ALLOCATOR (clause), + spc, flags, false); pp_right_paren (pp); break; diff --git a/libgomp/testsuite/libgomp.fortran/uses_allocators-7.f90 b/libgomp/testsuite/libgomp.fortran/uses_allocators-7.f90 index e5376e466666..32a901a8e02f 100644 --- a/libgomp/testsuite/libgomp.fortran/uses_allocators-7.f90 +++ b/libgomp/testsuite/libgomp.fortran/uses_allocators-7.f90 @@ -6,8 +6,15 @@ program main implicit none (type, external) integer :: x, xbuf(10) integer(c_intptr_t) :: iptr - integer(omp_allocator_handle_kind) :: my_alloc + integer(omp_allocator_handle_kind) :: my_alloc, my, my2, my3, my4 type(omp_alloctrait), parameter :: trait(*) = [omp_alloctrait(omp_atk_alignment, 128)] + type(omp_alloctrait), parameter :: t(*) = [omp_alloctrait:: ] + type(omp_alloctrait), parameter :: t2(*) = [omp_alloctrait:: ] + + ! FIXME - improve check that that ';' is handled + !$omp target uses_allocators(traits(t), memspace(omp_high_bw_mem_space) : my; omp_default_mem_alloc, omp_null_allocator; my2; traits(t2) : my3; memspace(omp_large_cap_mem_space) : my4) + block + end block !$omp target uses_allocators(omp_low_lat_mem_alloc) map(tofrom: x, xbuf) defaultmap(none) !$omp parallel allocate(allocator(omp_low_lat_mem_alloc), align(128): x, xbuf) if(.false.) firstprivate(x, xbuf) @@ -50,9 +57,12 @@ end ! FIXME ENABLE: 'dg FIXME final' -> 'dg-final' ! { dg FIXME final { scan-tree-dump-times "#pragma omp target .*private\\(my_alloc\\).*uses_allocators\\(my_alloc: memspace\\(\\), traits\\(trait\\)\\)" 1 "gimple" } } ! { dg FIXME final { scan-tree-dump-times "#pragma omp target .*private\\(my_alloc\\).*uses_allocators\\(my_alloc: memspace\\(\\), traits\\(\\)\\)" 1 "gimple" } } +! { dg FIXME final { scan-tree-dump "#pragma omp target uses_allocators\\(memspace\\(1\\), traits\\(\\) : my4\\) uses_allocators\\(memspace\\(\\), traits\\(t2\\) : my3\\) uses_allocators\\(memspace\\(\\), traits\\(\\) : my2\\) uses_allocators\\(memspace\\(3\\), traits\\(t\\) : my\\)" 1 "original" } } + ! FIXME ENABLE code above for "gimple" once it has been implemented: -! { dg-message "sorry, unimplemented: 'uses_allocators' clause with traits and memory spaces" "" { target *-*-* } 23 } -! { dg-message "sorry, unimplemented: 'uses_allocators' clause with traits and memory spaces" "" { target *-*-* } 36 } -! { dg-bogus "'my_alloc' not specified in enclosing 'target'" "bogus issue because clause is ignored" { xfail *-*-* } 24 } -! { dg-bogus "'my_alloc' not specified in enclosing 'target'" "bogus issue because clause is ignored" { xfail *-*-* } 37 } +! { dg-message "sorry, unimplemented: 'uses_allocators' clause with traits and memory spaces" "" { target *-*-* } 15 } +! { dg-message "sorry, unimplemented: 'uses_allocators' clause with traits and memory spaces" "" { target *-*-* } 30 } +! { dg-message "sorry, unimplemented: 'uses_allocators' clause with traits and memory spaces" "" { target *-*-* } 43 } +! { dg-bogus "'my_alloc' not specified in enclosing 'target'" "bogus issue because clause is ignored" { xfail *-*-* } 31 } +! { dg-bogus "'my_alloc' not specified in enclosing 'target'" "bogus issue because clause is ignored" { xfail *-*-* } 44 }
