Trivial patch to permit:
uses_allocators( traits(t1): alloc1 ; traits(t2): alloc2 )
using ';' to split the items. (With commas, the modifier applies
to all list items; with semicolons, new modifiers can be specified.)
This syntax saves typing of multiple (here: one) ') uses_allocators('
in addition.
Committed as Rev. r16-6273-g7044071f07d763.
Tobias
commit 7044071f07d763444247e32f9db25d7a658b7f9e
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 --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
index e39429afbb5..8065d3000e6 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 e106583c4b8..4685a9ab80f 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 a7a76694c2c..76c601952a7 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 00000000000..642b6b9caeb
--- /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 15e7ead32e1..54bf7980092 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 e5376e46666..32a901a8e02 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 }