aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/c-family/c-omp.c2
-rw-r--r--gcc/c/c-parser.c161
-rw-r--r--gcc/cp/parser.c71
-rw-r--r--gcc/cp/pt.c10
-rw-r--r--gcc/cp/semantics.c40
-rw-r--r--gcc/omp-low.c40
-rw-r--r--gcc/testsuite/c-c++-common/gomp/allocate-6.c84
-rw-r--r--gcc/testsuite/c-c++-common/gomp/allocate-7.c41
-rw-r--r--gcc/testsuite/g++.dg/gomp/allocate-4.C108
-rw-r--r--gcc/tree-pretty-print.c15
-rw-r--r--gcc/tree.c2
-rw-r--r--gcc/tree.h3
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/allocate-2.c37
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/allocate-3.c405
14 files changed, 986 insertions, 33 deletions
diff --git a/gcc/c-family/c-omp.c b/gcc/c-family/c-omp.c
index b606cf4..1f07a0a 100644
--- a/gcc/c-family/c-omp.c
+++ b/gcc/c-family/c-omp.c
@@ -2511,6 +2511,8 @@ c_omp_split_clauses (location_t loc, enum tree_code code,
= OMP_CLAUSE_DECL (clauses);
OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)
= OMP_CLAUSE_ALLOCATE_ALLOCATOR (clauses);
+ OMP_CLAUSE_ALLOCATE_ALIGN (c)
+ = OMP_CLAUSE_ALLOCATE_ALIGN (clauses);
OMP_CLAUSE_CHAIN (c) = cclauses[s];
cclauses[s] = c;
has_dup_allocate = true;
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index fb1399e..fa29d2c 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -15305,7 +15305,15 @@ c_parser_omp_clause_aligned (c_parser *parser, tree list)
/* OpenMP 5.0:
allocate ( variable-list )
- allocate ( expression : variable-list ) */
+ allocate ( expression : variable-list )
+
+ OpenMP 5.1:
+ allocate ( allocator-modifier : variable-list )
+ allocate ( allocator-modifier , allocator-modifier : variable-list )
+
+ allocator-modifier:
+ allocator ( expression )
+ align ( expression ) */
static tree
c_parser_omp_clause_allocate (c_parser *parser, tree list)
@@ -15313,6 +15321,7 @@ c_parser_omp_clause_allocate (c_parser *parser, tree list)
location_t clause_loc = c_parser_peek_token (parser)->location;
tree nl, c;
tree allocator = NULL_TREE;
+ tree align = NULL_TREE;
matching_parens parens;
if (!parens.require_open (parser))
@@ -15323,17 +15332,128 @@ c_parser_omp_clause_allocate (c_parser *parser, tree list)
|| (c_parser_peek_2nd_token (parser)->type != CPP_COMMA
&& c_parser_peek_2nd_token (parser)->type != CPP_CLOSE_PAREN))
{
- location_t expr_loc = c_parser_peek_token (parser)->location;
- c_expr expr = c_parser_expr_no_commas (parser, NULL);
- expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
- allocator = expr.value;
- allocator = c_fully_fold (allocator, false, NULL);
- tree orig_type
- = expr.original_type ? expr.original_type : TREE_TYPE (allocator);
- orig_type = TYPE_MAIN_VARIANT (orig_type);
- if (!INTEGRAL_TYPE_P (TREE_TYPE (allocator))
- || TREE_CODE (orig_type) != ENUMERAL_TYPE
- || TYPE_NAME (orig_type) != get_identifier ("omp_allocator_handle_t"))
+ bool has_modifiers = false;
+ tree orig_type = NULL_TREE;
+ if (c_parser_next_token_is (parser, CPP_NAME)
+ && c_parser_peek_2nd_token (parser)->type == CPP_OPEN_PAREN)
+ {
+ unsigned int n = 3;
+ const char *p
+ = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+ if ((strcmp (p, "allocator") == 0 || strcmp (p, "align") == 0)
+ && c_parser_check_balanced_raw_token_sequence (parser, &n)
+ && (c_parser_peek_nth_token_raw (parser, n)->type
+ == CPP_CLOSE_PAREN))
+ {
+ if (c_parser_peek_nth_token_raw (parser, n + 1)->type
+ == CPP_COLON)
+ has_modifiers = true;
+ else if (c_parser_peek_nth_token_raw (parser, n + 1)->type
+ == CPP_COMMA
+ && (c_parser_peek_nth_token_raw (parser, n + 2)->type
+ == CPP_NAME)
+ && (c_parser_peek_nth_token_raw (parser, n + 3)->type
+ == CPP_OPEN_PAREN))
+ {
+ c_token *tok = c_parser_peek_nth_token_raw (parser, n + 2);
+ const char *q = IDENTIFIER_POINTER (tok->value);
+ n += 4;
+ if ((strcmp (q, "allocator") == 0
+ || strcmp (q, "align") == 0)
+ && c_parser_check_balanced_raw_token_sequence (parser,
+ &n)
+ && (c_parser_peek_nth_token_raw (parser, n)->type
+ == CPP_CLOSE_PAREN)
+ && (c_parser_peek_nth_token_raw (parser, n + 1)->type
+ == CPP_COLON))
+ has_modifiers = true;
+ }
+ }
+ if (has_modifiers)
+ {
+ c_parser_consume_token (parser);
+ matching_parens parens2;;
+ parens2.require_open (parser);
+ location_t expr_loc = c_parser_peek_token (parser)->location;
+ c_expr expr = c_parser_expr_no_commas (parser, NULL);
+ expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
+ if (strcmp (p, "allocator") == 0)
+ {
+ allocator = expr.value;
+ allocator = c_fully_fold (allocator, false, NULL);
+ orig_type = expr.original_type
+ ? expr.original_type : TREE_TYPE (allocator);
+ orig_type = TYPE_MAIN_VARIANT (orig_type);
+ }
+ else
+ {
+ align = expr.value;
+ align = c_fully_fold (align, false, NULL);
+ }
+ parens2.skip_until_found_close (parser);
+ if (c_parser_next_token_is (parser, CPP_COMMA))
+ {
+ c_parser_consume_token (parser);
+ c_token *tok = c_parser_peek_token (parser);
+ const char *q = "";
+ if (c_parser_next_token_is (parser, CPP_NAME))
+ q = IDENTIFIER_POINTER (tok->value);
+ if (strcmp (q, "allocator") != 0 && strcmp (q, "align") != 0)
+ {
+ c_parser_error (parser, "expected %<allocator%> or "
+ "%<align%>");
+ parens.skip_until_found_close (parser);
+ return list;
+ }
+ else if (strcmp (p, q) == 0)
+ {
+ error_at (tok->location, "duplicate %qs modifier", p);
+ parens.skip_until_found_close (parser);
+ return list;
+ }
+ c_parser_consume_token (parser);
+ if (!parens2.require_open (parser))
+ {
+ parens.skip_until_found_close (parser);
+ return list;
+ }
+ expr_loc = c_parser_peek_token (parser)->location;
+ expr = c_parser_expr_no_commas (parser, NULL);
+ expr = convert_lvalue_to_rvalue (expr_loc, expr, false,
+ true);
+ if (strcmp (q, "allocator") == 0)
+ {
+ allocator = expr.value;
+ allocator = c_fully_fold (allocator, false, NULL);
+ orig_type = expr.original_type
+ ? expr.original_type : TREE_TYPE (allocator);
+ orig_type = TYPE_MAIN_VARIANT (orig_type);
+ }
+ else
+ {
+ align = expr.value;
+ align = c_fully_fold (align, false, NULL);
+ }
+ parens2.skip_until_found_close (parser);
+ }
+ }
+ }
+ if (!has_modifiers)
+ {
+ location_t expr_loc = c_parser_peek_token (parser)->location;
+ c_expr expr = c_parser_expr_no_commas (parser, NULL);
+ expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
+ allocator = expr.value;
+ allocator = c_fully_fold (allocator, false, NULL);
+ orig_type = expr.original_type
+ ? expr.original_type : TREE_TYPE (allocator);
+ orig_type = TYPE_MAIN_VARIANT (orig_type);
+ }
+ if (allocator
+ && (!INTEGRAL_TYPE_P (TREE_TYPE (allocator))
+ || TREE_CODE (orig_type) != ENUMERAL_TYPE
+ || (TYPE_NAME (orig_type)
+ != get_identifier ("omp_allocator_handle_t"))))
{
error_at (clause_loc, "%<allocate%> clause allocator expression "
"has type %qT rather than "
@@ -15341,6 +15461,16 @@ c_parser_omp_clause_allocate (c_parser *parser, tree list)
TREE_TYPE (allocator));
allocator = NULL_TREE;
}
+ if (align
+ && (!INTEGRAL_TYPE_P (TREE_TYPE (align))
+ || !tree_fits_uhwi_p (align)
+ || !integer_pow2p (align)))
+ {
+ error_at (clause_loc, "%<allocate%> clause %<align%> modifier "
+ "argument needs to be positive constant "
+ "power of two integer expression");
+ align = NULL_TREE;
+ }
if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
{
parens.skip_until_found_close (parser);
@@ -15351,9 +15481,12 @@ c_parser_omp_clause_allocate (c_parser *parser, tree list)
nl = c_parser_omp_variable_list (parser, clause_loc,
OMP_CLAUSE_ALLOCATE, list);
- if (allocator)
+ if (allocator || align)
for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
- OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) = allocator;
+ {
+ OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) = allocator;
+ OMP_CLAUSE_ALLOCATE_ALIGN (c) = align;
+ }
parens.skip_until_found_close (parser);
return nl;
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 62908da..26d925c 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -38337,13 +38337,21 @@ cp_parser_omp_clause_aligned (cp_parser *parser, tree list)
/* OpenMP 5.0:
allocate ( variable-list )
- allocate ( expression : variable-list ) */
+ allocate ( expression : variable-list )
+
+ OpenMP 5.1:
+ allocate ( allocator-modifier : variable-list )
+ allocate ( allocator-modifier , allocator-modifier : variable-list )
+
+ allocator-modifier:
+ allocator ( expression )
+ align ( expression ) */
static tree
cp_parser_omp_clause_allocate (cp_parser *parser, tree list)
{
- tree nlist, c, allocator = NULL_TREE;
- bool colon;
+ tree nlist, c, allocator = NULL_TREE, align = NULL_TREE;
+ bool colon, has_modifiers = false;
matching_parens parens;
if (!parens.require_open (parser))
@@ -38352,7 +38360,51 @@ cp_parser_omp_clause_allocate (cp_parser *parser, tree list)
cp_parser_parse_tentatively (parser);
bool saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p;
parser->colon_corrects_to_scope_p = false;
- allocator = cp_parser_assignment_expression (parser);
+ for (int mod = 0; mod < 2; mod++)
+ if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)
+ && cp_lexer_nth_token_is (parser->lexer, 2, CPP_OPEN_PAREN))
+ {
+ tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+ const char *p = IDENTIFIER_POINTER (id);
+ if (strcmp (p, "allocator") != 0 && strcmp (p, "align") != 0)
+ break;
+ cp_lexer_consume_token (parser->lexer);
+ matching_parens parens2;
+ if (!parens2.require_open (parser))
+ break;
+ if (strcmp (p, "allocator") == 0)
+ {
+ if (allocator != NULL_TREE)
+ break;
+ allocator = cp_parser_assignment_expression (parser);
+ }
+ else
+ {
+ if (align != NULL_TREE)
+ break;
+ align = cp_parser_assignment_expression (parser);
+ }
+ if (!parens2.require_close (parser))
+ break;
+ if (cp_lexer_next_token_is (parser->lexer, CPP_COLON))
+ {
+ has_modifiers = true;
+ break;
+ }
+ if (mod != 0 || cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA))
+ break;
+ cp_lexer_consume_token (parser->lexer);
+ }
+ else
+ break;
+ if (!has_modifiers)
+ {
+ cp_parser_abort_tentative_parse (parser);
+ align = NULL_TREE;
+ allocator = NULL_TREE;
+ cp_parser_parse_tentatively (parser);
+ allocator = cp_parser_assignment_expression (parser);
+ }
parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p;
if (cp_lexer_next_token_is (parser->lexer, CPP_COLON))
{
@@ -38360,18 +38412,25 @@ cp_parser_omp_clause_allocate (cp_parser *parser, tree list)
cp_lexer_consume_token (parser->lexer);
if (allocator == error_mark_node)
allocator = NULL_TREE;
+ if (align == error_mark_node)
+ align = NULL_TREE;
}
else
{
cp_parser_abort_tentative_parse (parser);
allocator = NULL_TREE;
+ align = NULL_TREE;
}
nlist = cp_parser_omp_var_list_no_open (parser, OMP_CLAUSE_ALLOCATE, list,
&colon);
- for (c = nlist; c != list; c = OMP_CLAUSE_CHAIN (c))
- OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) = allocator;
+ if (allocator || align)
+ for (c = nlist; c != list; c = OMP_CLAUSE_CHAIN (c))
+ {
+ OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) = allocator;
+ OMP_CLAUSE_ALLOCATE_ALIGN (c) = align;
+ }
return nlist;
}
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 048bbc4..28ba32f4 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -17489,6 +17489,13 @@ tsubst_omp_clauses (tree clauses, enum c_omp_region_type ort,
break;
case OMP_CLAUSE_GANG:
case OMP_CLAUSE_ALIGNED:
+ OMP_CLAUSE_DECL (nc)
+ = tsubst_omp_clause_decl (OMP_CLAUSE_DECL (oc), args, complain,
+ in_decl, NULL);
+ OMP_CLAUSE_OPERAND (nc, 1)
+ = tsubst_expr (OMP_CLAUSE_OPERAND (oc, 1), args, complain,
+ in_decl, /*integral_constant_expression_p=*/false);
+ break;
case OMP_CLAUSE_ALLOCATE:
OMP_CLAUSE_DECL (nc)
= tsubst_omp_clause_decl (OMP_CLAUSE_DECL (oc), args, complain,
@@ -17496,6 +17503,9 @@ tsubst_omp_clauses (tree clauses, enum c_omp_region_type ort,
OMP_CLAUSE_OPERAND (nc, 1)
= tsubst_expr (OMP_CLAUSE_OPERAND (oc, 1), args, complain,
in_decl, /*integral_constant_expression_p=*/false);
+ OMP_CLAUSE_OPERAND (nc, 2)
+ = tsubst_expr (OMP_CLAUSE_OPERAND (oc, 2), args, complain,
+ in_decl, /*integral_constant_expression_p=*/false);
break;
case OMP_CLAUSE_LINEAR:
OMP_CLAUSE_DECL (nc)
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 35a7b9f..0d8e5fd 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -7527,7 +7527,44 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
bitmap_set_bit (&aligned_head, DECL_UID (t));
allocate_seen = true;
}
- tree allocator;
+ tree allocator, align;
+ align = OMP_CLAUSE_ALLOCATE_ALIGN (c);
+ if (error_operand_p (align))
+ {
+ remove = true;
+ break;
+ }
+ if (align)
+ {
+ if (!type_dependent_expression_p (align)
+ && !INTEGRAL_TYPE_P (TREE_TYPE (align)))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<allocate%> clause %<align%> modifier "
+ "argument needs to be positive constant "
+ "power of two integer expression");
+ remove = true;
+ }
+ else
+ {
+ align = mark_rvalue_use (align);
+ if (!processing_template_decl)
+ {
+ align = maybe_constant_value (align);
+ if (TREE_CODE (align) != INTEGER_CST
+ || !tree_fits_uhwi_p (align)
+ || !integer_pow2p (align))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<allocate%> clause %<align%> modifier "
+ "argument needs to be positive constant "
+ "power of two integer expression");
+ remove = true;
+ }
+ }
+ }
+ OMP_CLAUSE_ALLOCATE_ALIGN (c) = align;
+ }
allocator = OMP_CLAUSE_ALLOCATE_ALLOCATOR (c);
if (error_operand_p (allocator))
{
@@ -7552,6 +7589,7 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
"type %qT rather than %<omp_allocator_handle_t%>",
TREE_TYPE (allocator));
remove = true;
+ break;
}
else
{
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index 27a513e..26c5c02 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -1161,14 +1161,17 @@ scan_sharing_clauses (tree clauses, omp_context *ctx)
if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_ALLOCATE
&& (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) == NULL_TREE
/* omp_default_mem_alloc is 1 */
- || !integer_onep (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c))))
+ || !integer_onep (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c))
+ || OMP_CLAUSE_ALLOCATE_ALIGN (c) != NULL_TREE))
{
if (ctx->allocate_map == NULL)
ctx->allocate_map = new hash_map<tree, tree>;
- ctx->allocate_map->put (OMP_CLAUSE_DECL (c),
- OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)
- ? OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)
- : integer_zero_node);
+ tree val = integer_zero_node;
+ if (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c))
+ val = OMP_CLAUSE_ALLOCATE_ALLOCATOR (c);
+ if (OMP_CLAUSE_ALLOCATE_ALIGN (c))
+ val = build_tree_list (val, OMP_CLAUSE_ALLOCATE_ALIGN (c));
+ ctx->allocate_map->put (OMP_CLAUSE_DECL (c), val);
}
for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
@@ -4725,6 +4728,12 @@ lower_private_allocate (tree var, tree new_var, tree &allocator,
return false;
}
+ unsigned HOST_WIDE_INT ialign = 0;
+ if (TREE_CODE (allocator) == TREE_LIST)
+ {
+ ialign = tree_to_uhwi (TREE_VALUE (allocator));
+ allocator = TREE_PURPOSE (allocator);
+ }
if (TREE_CODE (allocator) != INTEGER_CST)
allocator = build_outer_var_ref (allocator, ctx);
allocator = fold_convert (pointer_sized_int_node, allocator);
@@ -4739,21 +4748,21 @@ lower_private_allocate (tree var, tree new_var, tree &allocator,
if (TYPE_P (new_var))
{
ptr_type = build_pointer_type (new_var);
- align = build_int_cst (size_type_node, TYPE_ALIGN_UNIT (new_var));
+ ialign = MAX (ialign, TYPE_ALIGN_UNIT (new_var));
}
else if (is_ref)
{
ptr_type = build_pointer_type (TREE_TYPE (TREE_TYPE (new_var)));
- align = build_int_cst (size_type_node,
- TYPE_ALIGN_UNIT (TREE_TYPE (ptr_type)));
+ ialign = MAX (ialign, TYPE_ALIGN_UNIT (TREE_TYPE (ptr_type)));
}
else
{
ptr_type = build_pointer_type (TREE_TYPE (new_var));
- align = build_int_cst (size_type_node, DECL_ALIGN_UNIT (new_var));
+ ialign = MAX (ialign, DECL_ALIGN_UNIT (new_var));
if (sz == NULL_TREE)
sz = fold_convert (size_type_node, DECL_SIZE_UNIT (new_var));
}
+ align = build_int_cst (size_type_node, ialign);
if (TREE_CODE (sz) != INTEGER_CST)
{
tree szvar = create_tmp_var (size_type_node);
@@ -5707,6 +5716,8 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
if (tree *allocatep = ctx->allocate_map->get (var))
{
allocator = *allocatep;
+ if (TREE_CODE (allocator) == TREE_LIST)
+ allocator = TREE_PURPOSE (allocator);
if (TREE_CODE (allocator) != INTEGER_CST)
allocator = build_outer_var_ref (allocator, ctx);
allocator = fold_convert (pointer_sized_int_node,
@@ -6025,6 +6036,8 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
if (tree *allocatep = ctx->allocate_map->get (var))
{
allocator = *allocatep;
+ if (TREE_CODE (allocator) == TREE_LIST)
+ allocator = TREE_PURPOSE (allocator);
if (TREE_CODE (allocator) != INTEGER_CST)
allocator = build_outer_var_ref (allocator, ctx);
allocator = fold_convert (pointer_sized_int_node,
@@ -12070,6 +12083,12 @@ create_task_copyfn (gomp_task *task_stmt, omp_context *ctx)
if (tree *allocatorp = ctx->allocate_map->get (decl))
{
tree allocator = *allocatorp;
+ HOST_WIDE_INT ialign = 0;
+ if (TREE_CODE (allocator) == TREE_LIST)
+ {
+ ialign = tree_to_uhwi (TREE_VALUE (allocator));
+ allocator = TREE_PURPOSE (allocator);
+ }
if (TREE_CODE (allocator) != INTEGER_CST)
{
n = splay_tree_lookup (ctx->sfield_map,
@@ -12083,7 +12102,8 @@ create_task_copyfn (gomp_task *task_stmt, omp_context *ctx)
allocator = fold_convert (pointer_sized_int_node, allocator);
tree a = builtin_decl_explicit (BUILT_IN_GOMP_ALLOC);
tree align = build_int_cst (size_type_node,
- DECL_ALIGN_UNIT (decl));
+ MAX (ialign,
+ DECL_ALIGN_UNIT (decl)));
tree sz = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (dst)));
tree ptr = build_call_expr_loc (loc, a, 3, align, sz,
allocator);
diff --git a/gcc/testsuite/c-c++-common/gomp/allocate-6.c b/gcc/testsuite/c-c++-common/gomp/allocate-6.c
new file mode 100644
index 0000000..059fd72
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/allocate-6.c
@@ -0,0 +1,84 @@
+typedef enum omp_allocator_handle_t
+#if __cplusplus >= 201103L
+: __UINTPTR_TYPE__
+#endif
+{
+ 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,
+ __omp_allocator_handle_t_max__ = __UINTPTR_MAX__
+} omp_allocator_handle_t;
+
+int bar (int, int *, int);
+omp_allocator_handle_t baz (void);
+
+void
+foo (int x, int z)
+{
+ int y[16] = { 0 }, r = 0, i;
+ omp_allocator_handle_t h = baz ();
+ #pragma omp parallel allocate (align (sizeof (int)) : x) allocate (allocator (omp_default_mem_alloc) : y) \
+ allocate (align (8), allocator ((omp_allocator_handle_t) omp_default_mem_alloc):z) firstprivate (x, y, z)
+ bar (x, y, z);
+ #pragma omp task private (x) firstprivate (z) allocate (allocator (omp_low_lat_mem_alloc) :x,z)
+ bar (0, &x, z);
+ #pragma omp taskwait
+ #pragma omp target teams distribute parallel for private (x) firstprivate (y) \
+ allocate (allocator ((omp_allocator_handle_t)(omp_default_mem_alloc + 0)), align (16) : z) \
+ allocate (allocator (omp_default_mem_alloc) : x, y) allocate (align (32), allocator (omp_low_lat_mem_alloc): r) \
+ lastprivate (z) reduction(+:r)
+ for (i = 0; i < 64; i++)
+ {
+ z = bar (0, &x, 0);
+ r += bar (1, y, 0);
+ }
+ #pragma omp single private (x) allocate (allocator (h):x)
+ ;
+ #pragma omp single allocate (align (2 * sizeof (int)), allocator (*&h) : x) private (x)
+ ;
+ #pragma omp parallel shared (r, x, z)
+ #pragma omp single firstprivate (r) allocate (align (4) : x, r, z) private (x, z)
+ ;
+ #pragma omp for allocate (align (2 * 2 * 2) : x) private (x)
+ for (i = 0; i < 64; i++)
+ x = 1;
+ #pragma omp sections private (x) allocate (allocator (omp_low_lat_mem_alloc), align (8): x)
+ {
+ x = 1;
+ #pragma omp section
+ x = 2;
+ #pragma omp section
+ x = 3;
+ }
+ #pragma omp taskgroup task_reduction(+:r) allocate (allocator (omp_default_mem_alloc), align (__alignof (r)) : r)
+ #pragma omp task in_reduction(+:r) allocate (align (2 * sizeof (r)), allocator (omp_default_mem_alloc) : r)
+ r += bar (r, &r, 0);
+ #pragma omp teams private (x) firstprivate (y) allocate (allocator (h), align (8) : x, y)
+ bar (x, y, 0);
+ #pragma omp taskloop lastprivate (x) reduction (+:r) allocate (align (16), allocator (h) : x, r)
+ for (i = 0; i < 16; i++)
+ {
+ r += bar (0, &r, 0);
+ x = i;
+ }
+ #pragma omp taskgroup task_reduction(+:r) allocate (allocator (omp_default_mem_alloc), align (64) : r)
+ #pragma omp taskloop firstprivate (x) in_reduction (+:r) \
+ allocate (allocator (omp_default_mem_alloc), align (128) : x, r)
+ for (i = 0; i < 16; i++)
+ r += bar (x, &r, 0);
+ #pragma omp taskwait
+}
+
+void
+qux (const omp_allocator_handle_t h)
+{
+ int x = 0;
+ #pragma omp parallel firstprivate (x) allocate (align (16), allocator (h): x)
+ x = 1;
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/allocate-7.c b/gcc/testsuite/c-c++-common/gomp/allocate-7.c
new file mode 100644
index 0000000..d125d92
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/allocate-7.c
@@ -0,0 +1,41 @@
+typedef enum omp_allocator_handle_t
+#if __cplusplus >= 201103L
+: __UINTPTR_TYPE__
+#endif
+{
+ 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,
+ __omp_allocator_handle_t_max__ = __UINTPTR_MAX__
+} omp_allocator_handle_t;
+
+int bar (int *);
+omp_allocator_handle_t baz (void);
+
+void
+foo (int x, int z)
+{
+ int i;
+ #pragma omp parallel private (x) allocate (allocator (0.0) : x) /* { dg-error "'allocate' clause allocator expression has type 'double' rather than 'omp_allocator_handle_t'" } */
+ bar (&x);
+ #pragma omp parallel private (x) allocate (allocator (0) : x) /* { dg-error "'allocate' clause allocator expression has type 'int' rather than 'omp_allocator_handle_t'" } */
+ bar (&x);
+ #pragma omp parallel private (x) allocate (align (z) : x) /* { dg-error "'allocate' clause 'align' modifier argument needs to be positive constant power of two integer expression" } */
+ bar (&x);
+ #pragma omp parallel private (x) allocate (align (16.0) : x) /* { dg-error "'allocate' clause 'align' modifier argument needs to be positive constant power of two integer expression" } */
+ bar (&x);
+ #pragma omp parallel private (x) allocate (align (14) : x) /* { dg-error "'allocate' clause 'align' modifier argument needs to be positive constant power of two integer expression" } */
+ bar (&x);
+ #pragma omp parallel private (x) allocate (align (0) : x) /* { dg-error "'allocate' clause 'align' modifier argument needs to be positive constant power of two integer expression" } */
+ bar (&x);
+ #pragma omp parallel private (x) allocate (align (16), align (16) : x) /* { dg-error "expected|duplicate|declared|specified" } */
+ bar (&x); /* { dg-warning "more than once" "" { target c++ } .-1 } */
+ #pragma omp parallel private (x) allocate (allocator (omp_default_mem_alloc), allocator (omp_default_mem_alloc) : x) /* { dg-error "expected|duplicate|declared|specified" } */
+ bar (&x); /* { dg-warning "more than once" "" { target c++ } .-1 } */
+}
diff --git a/gcc/testsuite/g++.dg/gomp/allocate-4.C b/gcc/testsuite/g++.dg/gomp/allocate-4.C
new file mode 100644
index 0000000..dd5e5f0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/allocate-4.C
@@ -0,0 +1,108 @@
+// { dg-do compile }
+// { dg-additional-options "-std=c++11" }
+
+typedef enum omp_allocator_handle_t
+#if __cplusplus >= 201103L
+: __UINTPTR_TYPE__
+#endif
+{
+ 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,
+ __omp_allocator_handle_t_max__ = __UINTPTR_MAX__
+} omp_allocator_handle_t;
+
+namespace N1
+{
+ using ::omp_allocator_handle_t;
+ void
+ foo (const omp_allocator_handle_t h)
+ {
+ int x = 0;
+ #pragma omp parallel allocate (allocator (h): x) private (x)
+ x = 1;
+ }
+}
+
+namespace N2
+{
+ typedef enum omp_allocator_handle_t { my = 0 } omp_allocator_handle_t;
+ void
+ foo (omp_allocator_handle_t h)
+ {
+ int x = 0;
+ #pragma omp parallel allocate (allocator (h): x) private (x) // { dg-error "'allocate' clause allocator expression has type 'N2::omp_allocator_handle_t' rather than 'omp_allocator_handle_t'" }
+ x = 1;
+ }
+}
+
+struct S
+{
+ void foo ()
+ {
+ #pragma omp parallel allocate (allocator(omp_default_mem_alloc):s) firstprivate (s)
+ s++;
+ }
+ int s;
+};
+
+template <typename T>
+struct U
+{
+ int foo ()
+ {
+ #pragma omp parallel allocate (allocator(omp_default_mem_alloc):s) firstprivate (s)
+ s++;
+ return 1;
+ }
+ T s;
+};
+
+template <typename T, int N>
+int foo (T t)
+{
+ int x = 0;
+ #pragma omp parallel firstprivate (x) allocate (allocator(t), align (N): x)
+ x = 1;
+ return 0;
+}
+
+template <typename T>
+int bar (T t)
+{
+ int x = 0;
+ #pragma omp parallel firstprivate (x) allocate (allocator(t): x) // { dg-error "'allocate' clause allocator expression has type 'int' rather than 'omp_allocator_handle_t'" }
+ x = 1;
+ return 0;
+}
+
+template <typename T, int N>
+int baz (T t)
+{
+ int x = 0;
+ #pragma omp parallel firstprivate (x) allocate (allocator(t), align (N): x) // { dg-error "'allocate' clause 'align' modifier argument needs to be positive constant power of two integer expression" }
+ x = 1;
+ return 0;
+}
+
+template <typename T>
+int qux ()
+{
+ int x = 0;
+ #pragma omp parallel firstprivate (x) allocate (align ((T) 16): x) // { dg-error "'allocate' clause 'align' modifier argument needs to be positive constant power of two integer expression" }
+ x = 1;
+ return 0;
+}
+
+omp_allocator_handle_t h;
+int a = foo<omp_allocator_handle_t, 16> (h);
+int b = bar (0);
+int c = U<int> ().foo ();
+int d = baz<omp_allocator_handle_t, 13> (h);
+int e = qux<long double> ();
diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c
index 7de12f3..35e567c 100644
--- a/gcc/tree-pretty-print.c
+++ b/gcc/tree-pretty-print.c
@@ -735,10 +735,23 @@ dump_omp_clause (pretty_printer *pp, tree clause, int spc, dump_flags_t flags)
pp_string (pp, "allocate(");
if (OMP_CLAUSE_ALLOCATE_ALLOCATOR (clause))
{
+ pp_string (pp, "allocator(");
dump_generic_node (pp, OMP_CLAUSE_ALLOCATE_ALLOCATOR (clause),
spc, flags, false);
- pp_colon (pp);
+ pp_right_paren (pp);
+ }
+ if (OMP_CLAUSE_ALLOCATE_ALIGN (clause))
+ {
+ if (OMP_CLAUSE_ALLOCATE_ALLOCATOR (clause))
+ pp_comma (pp);
+ pp_string (pp, "align(");
+ dump_generic_node (pp, OMP_CLAUSE_ALLOCATE_ALIGN (clause),
+ spc, flags, false);
+ pp_right_paren (pp);
}
+ if (OMP_CLAUSE_ALLOCATE_ALLOCATOR (clause)
+ || OMP_CLAUSE_ALLOCATE_ALIGN (clause))
+ pp_colon (pp);
dump_generic_node (pp, OMP_CLAUSE_DECL (clause),
spc, flags, false);
pp_right_paren (pp);
diff --git a/gcc/tree.c b/gcc/tree.c
index 994775d..561b9cd5 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -291,7 +291,7 @@ unsigned const char omp_clause_num_ops[] =
3, /* OMP_CLAUSE_LINEAR */
1, /* OMP_CLAUSE_AFFINITY */
2, /* OMP_CLAUSE_ALIGNED */
- 2, /* OMP_CLAUSE_ALLOCATE */
+ 3, /* OMP_CLAUSE_ALLOCATE */
1, /* OMP_CLAUSE_DEPEND */
1, /* OMP_CLAUSE_NONTEMPORAL */
1, /* OMP_CLAUSE_UNIFORM */
diff --git a/gcc/tree.h b/gcc/tree.h
index 091ad3d..7d1257b 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -1790,6 +1790,9 @@ class auto_suppress_location_wrappers
#define OMP_CLAUSE_ALLOCATE_ALLOCATOR(NODE) \
OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_ALLOCATE), 1)
+#define OMP_CLAUSE_ALLOCATE_ALIGN(NODE) \
+ OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_ALLOCATE), 2)
+
/* True if an ALLOCATE clause was present on a combined or composite
construct and the code for splitting the clauses has already performed
checking if the listed variable has explicit privatization on the
diff --git a/libgomp/testsuite/libgomp.c-c++-common/allocate-2.c b/libgomp/testsuite/libgomp.c-c++-common/allocate-2.c
new file mode 100644
index 0000000..e4cd09a
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/allocate-2.c
@@ -0,0 +1,37 @@
+#include <omp.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+int zero;
+
+omp_allocator_handle_t
+allocator (omp_allocator_handle_t h)
+{
+ if (zero)
+ return h;
+ else
+ abort ();
+}
+
+omp_allocator_handle_t
+align (int a)
+{
+ if (zero)
+ return omp_default_mem_alloc;
+ else
+ abort ();
+}
+
+int
+main ()
+{
+ int x = 1, y = 2;
+ #pragma omp parallel num_threads(2) firstprivate (x, y) allocate (allocator (omp_default_mem_alloc) : x) allocate (align (16) : y)
+ {
+ if (x != 1 || y != 2)
+ abort ();
+ if ((((uintptr_t) &y) & 15) != 0)
+ abort ();
+ }
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/allocate-3.c b/libgomp/testsuite/libgomp.c-c++-common/allocate-3.c
new file mode 100644
index 0000000..ce1a045
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/allocate-3.c
@@ -0,0 +1,405 @@
+#include <omp.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+struct S { int a, b; };
+
+void
+foo (int x, int *p, int *q, int px, omp_allocator_handle_t h, int fl)
+{
+ int y = 0, r = 0, i, i1, l, l2[4], l3, n = 8;
+ int i2, j2, n2 = 9, l4;
+ int i3, j3, n3 = 10, l5;
+ int i4, j4, n4 = 11, l6;
+ int i5;
+ int v[x], w[x];
+ int r2[4] = { 0, 0, 0, 0 };
+ int xo = x;
+ struct S s = { 27, 29 };
+ for (i = 0; i < 4; i++)
+ p[i] = 0;
+ for (i = 0; i < 3; i++)
+ q[i] = 0;
+ for (i = 0; i < x; i++)
+ w[i] = i;
+ #pragma omp parallel private (y, v) firstprivate (x) allocate (align (32) : x) allocate (align (128) : y) allocate (v)
+ {
+ int *volatile p1 = &x;
+ int *volatile p2 = &y;
+ if (x != 42)
+ abort ();
+ #pragma omp barrier
+ *p2 = 1;
+ p1[0]++;
+ v[0] = 7;
+ v[41] = 8;
+ #pragma omp barrier
+ if (x != 43 || y != 1)
+ abort ();
+ if (v[0] != 7 || v[41] != 8)
+ abort ();
+ if ((fl & 2) && (((uintptr_t) p1 | (uintptr_t) p2
+ | (uintptr_t) &v[0]) & 63) != 0)
+ abort ();
+ if ((((uintptr_t) p1) & 31) != 0)
+ abort ();
+ if ((((uintptr_t) p2) & 127) != 0)
+ abort ();
+ }
+ x = xo;
+ #pragma omp teams
+ #pragma omp parallel private (y) firstprivate (x, w) allocate (allocator (h), align (32) : x) allocate (align (128), allocator (h):y) allocate(allocator(h):w)
+ {
+ int *volatile p1 = &x;
+ int *volatile p2 = &y;
+ if (x != 42 || w[17] != 17 || w[41] != 41)
+ abort ();
+ #pragma omp barrier
+ *p2 = 1;
+ p1[0]++;
+ w[19]++;
+ #pragma omp barrier
+ if (x != 43 || y != 1 || w[19] != 20)
+ abort ();
+ if ((fl & 1) && (((uintptr_t) p1 | (uintptr_t) p2
+ | (uintptr_t) &w[0]) & 63) != 0)
+ abort ();
+ if ((((uintptr_t) p1) & 31) != 0)
+ abort ();
+ if ((((uintptr_t) p2) & 127) != 0)
+ abort ();
+ }
+ x = xo;
+ #pragma omp parallel for private (y) firstprivate (x) allocate (allocator (h), align (32) : x, y, r) allocate (align (128), allocator (h) : l, n) reduction(+: r) lastprivate (l) linear (n: 16)
+ for (i = 0; i < 64; i++)
+ {
+ if (x != 42)
+ abort ();
+ y = 1;
+ l = i;
+ n += y + 15;
+ r += i;
+ if ((fl & 1) && (((uintptr_t) &x | (uintptr_t) &y | (uintptr_t) &r
+ | (uintptr_t) &l | (uintptr_t) &n) & 63) != 0)
+ abort ();
+ if ((((uintptr_t) &x | (uintptr_t) &y | (uintptr_t) &r) & 31) != 0)
+ abort ();
+ if ((((uintptr_t) &l | (uintptr_t) &n) & 127) != 0)
+ abort ();
+ }
+ x = xo;
+ #pragma omp parallel
+ {
+ #pragma omp for lastprivate (l2) private (i1) allocate (allocator (h): l2, l3) allocate (allocator (h),align(16): i1) lastprivate (conditional: l3)
+ for (i1 = 0; i1 < 64; i1++)
+ {
+ l2[0] = i1;
+ l2[1] = i1 + 1;
+ l2[2] = i1 + 2;
+ l2[3] = i1 + 3;
+ if (i1 < 37)
+ l3 = i1;
+ if ((fl & 1) && (((uintptr_t) &l2[0] | (uintptr_t) &l3 | (uintptr_t) &i1) & 63) != 0)
+ abort ();
+ if ((((uintptr_t) &i1) & 15) != 0)
+ abort ();
+ }
+ #pragma omp for collapse(2) lastprivate(l4, i2, j2) linear (n2:17) allocate (allocator (h), align (8): n2, l4, i2, j2)
+ for (i2 = 3; i2 < 5; i2++)
+ for (j2 = 17; j2 < 22; j2 += 2)
+ {
+ n2 += 17;
+ l4 = i2 * 31 + j2;
+ if ((fl & 1) && (((uintptr_t) &l4 | (uintptr_t) &n2
+ | (uintptr_t) &i2 | (uintptr_t) &j2) & 63) != 0)
+ abort ();
+ if ((((uintptr_t) &l4 | (uintptr_t) &n2 | (uintptr_t) &i2 | (uintptr_t) &j2) & 7) != 0)
+ abort ();
+ }
+ #pragma omp for collapse(2) lastprivate(l5, i3, j3) linear (n3:17) schedule (static, 3) allocate (align (16): n3, l5, i3, j3)
+ for (i3 = 3; i3 < 5; i3++)
+ for (j3 = 17; j3 < 23; j3 += 2)
+ {
+ n3 += 17;
+ l5 = i3 * 31 + j3;
+ if ((fl & 2) && (((uintptr_t) &l5 | (uintptr_t) &n3
+ | (uintptr_t) &i3 | (uintptr_t) &j3) & 63) != 0)
+ abort ();
+ if ((((uintptr_t) &l5 | (uintptr_t) &n3 | (uintptr_t) &i3 | (uintptr_t) &j3) & 15) != 0)
+ abort ();
+ }
+ #pragma omp for collapse(2) lastprivate(l6, i4, j4) linear (n4:17) schedule (dynamic) allocate (align (16), allocator (h): n4, l6, i4, j4)
+ for (i4 = 3; i4 < 5; i4++)
+ for (j4 = 17; j4 < 22; j4 += 2)
+ {
+ n4 += 17;
+ l6 = i4 * 31 + j4;
+ if ((fl & 1) && (((uintptr_t) &l6 | (uintptr_t) &n4
+ | (uintptr_t) &i4 | (uintptr_t) &j4) & 63) != 0)
+ abort ();
+ if ((((uintptr_t) &l6 | (uintptr_t) &n4 | (uintptr_t) &i4 | (uintptr_t) &j4) & 15) != 0)
+ abort ();
+ }
+ #pragma omp for lastprivate (i5) allocate (align (32): i5)
+ for (i5 = 1; i5 < 17; i5 += 3)
+ {
+ if ((fl & 2) && (((uintptr_t) &i5) & 63) != 0)
+ abort ();
+ if ((((uintptr_t) &i5) & 31) != 0)
+ abort ();
+ }
+ #pragma omp for reduction(+:p[2:px], q[:3], r2) allocate(align (16), allocator (h): p, q, r2)
+ for (i = 0; i < 32; i++)
+ {
+ p[2] += i;
+ p[3] += 2 * i;
+ q[0] += 3 * i;
+ q[2] += 4 * i;
+ r2[0] += 5 * i;
+ r2[3] += 6 * i;
+ /* Can't really rely on alignment of &p[0], the implementation could
+ allocate the whole array or do what GCC does and allocate only part
+ of it. */
+ if ((fl & 1) && (((uintptr_t) &q[0] | (uintptr_t) &r2[0]) & 63) != 0)
+ abort ();
+ if ((((uintptr_t) &q[0] | (uintptr_t) &r2[0]) & 15) != 0)
+ abort ();
+ }
+ #pragma omp task private(y) firstprivate(x) allocate(align (8) : x, y)
+ {
+ int *volatile p1 = &x;
+ int *volatile p2 = &y;
+ if (x != 42)
+ abort ();
+ p1[0]++;
+ p2[0] = 21;
+ if (x != 43 || y != 21)
+ abort ();
+ if ((fl & 2) && (((uintptr_t) p1 | (uintptr_t) p2) & 63) != 0)
+ abort ();
+ if ((((uintptr_t) p1 | (uintptr_t) p2) & 7) != 0)
+ abort ();
+ }
+ #pragma omp task private(y) firstprivate(x) allocate(allocator (h),align(32): x, y)
+ {
+ int *volatile p1 = &x;
+ int *volatile p2 = &y;
+ if (x != 42)
+ abort ();
+ p1[0]++;
+ p2[0] = 21;
+ if (x != 43 || y != 21)
+ abort ();
+ if ((fl & 1) && (((uintptr_t) p1 | (uintptr_t) p2) & 63) != 0)
+ abort ();
+ if ((((uintptr_t) p1 | (uintptr_t) p2) & 31) != 0)
+ abort ();
+ }
+ #pragma omp task private(y) firstprivate(s) allocate(align(16): s, y)
+ {
+ int *volatile p1 = &s.a;
+ int *volatile p2 = &s.b;
+ int *volatile p3 = &y;
+ if (s.a != 27 || s.b != 29)
+ abort ();
+ p1[0]++;
+ p2[0]++;
+ p3[0] = 21;
+ if (s.a != 28 || s.b != 30 || y != 21)
+ abort ();
+ if ((fl & 2) && (((uintptr_t) p1 | (uintptr_t) p3) & 63) != 0)
+ abort ();
+ if ((((uintptr_t) p1 | (uintptr_t) p3) & 15) != 0)
+ abort ();
+ }
+ #pragma omp task private(y) firstprivate(s) allocate(allocator (h): s, y)
+ {
+ int *volatile p1 = &s.a;
+ int *volatile p2 = &s.b;
+ int *volatile p3 = &y;
+ if (s.a != 27 || s.b != 29)
+ abort ();
+ p1[0]++;
+ p2[0]++;
+ p3[0] = 21;
+ if (s.a != 28 || s.b != 30 || y != 21)
+ abort ();
+ if ((fl & 1) && (((uintptr_t) p1 | (uintptr_t) p3) & 63) != 0)
+ abort ();
+ }
+ }
+ if (r != 64 * 63 / 2 || l != 63 || n != 8 + 16 * 64)
+ abort ();
+ if (l2[0] != 63 || l2[1] != 63 + 1 || l2[2] != 63 + 2 || l2[3] != 63 + 3 || l3 != 36)
+ abort ();
+ if (i2 != 5 || j2 != 23 || n2 != 9 + 6 * 17 || l4 != 4 * 31 + 21)
+ abort ();
+ if (i3 != 5 || j3 != 23 || n3 != 10 + 6 * 17 || l5 != 4 * 31 + 21)
+ abort ();
+ if (i4 != 5 || j4 != 23 || n4 != 11 + 6 * 17 || l6 != 4 * 31 + 21)
+ abort ();
+ if (i5 != 19)
+ abort ();
+ if (p[2] != (32 * 31) / 2 || p[3] != 2 * (32 * 31) / 2
+ || q[0] != 3 * (32 * 31) / 2 || q[2] != 4 * (32 * 31) / 2
+ || r2[0] != 5 * (32 * 31) / 2 || r2[3] != 6 * (32 * 31) / 2)
+ abort ();
+}
+
+void
+bar (int x, omp_allocator_handle_t h)
+{
+ int y = 0, r = 0, i, i1, l, l2[4], l3, n = 8;
+ int i2, j2, n2 = 9, l4;
+ int i3, j3, n3 = 10, l5;
+ int i4, j4, n4 = 11, l6;
+ int i5;
+ struct S s = { 27, 29 };
+ int xo = x;
+ #pragma omp parallel private (y) firstprivate (x) allocate (x, y)
+ {
+ if (x != 42)
+ abort ();
+ #pragma omp barrier
+ y = 1;
+ x++;
+ #pragma omp barrier
+ if (x != 43 || y != 1)
+ abort ();
+ }
+ x = xo;
+ #pragma omp teams
+ #pragma omp parallel private (y) firstprivate (x) allocate (allocator (h): x, y)
+ {
+ if (x != 42)
+ abort ();
+ #pragma omp barrier
+ y = 1;
+ x++;
+ #pragma omp barrier
+ if (x != 43 || y != 1)
+ abort ();
+ }
+ x = xo;
+ #pragma omp parallel for private (y) firstprivate (x) allocate (allocator (h): x, y, r, l, n) reduction(+: r) lastprivate (l) linear (n: 16)
+ for (i = 0; i < 64; i++)
+ {
+ if (x != 42)
+ abort ();
+ y = 1;
+ l = i;
+ n += y + 15;
+ r += i;
+ }
+ x = xo;
+ #pragma omp parallel
+ {
+ #pragma omp for lastprivate (l2) private (i1) allocate (allocator (h): l2, l3, i1) lastprivate (conditional: l3)
+ for (i1 = 0; i1 < 64; i1++)
+ {
+ l2[0] = i1;
+ l2[1] = i1 + 1;
+ l2[2] = i1 + 2;
+ l2[3] = i1 + 3;
+ if (i1 < 37)
+ l3 = i1;
+ }
+ #pragma omp for collapse(2) lastprivate(l4, i2, j2) linear (n2:17) allocate (allocator (h): n2, l4, i2, j2)
+ for (i2 = 3; i2 < 5; i2++)
+ for (j2 = 17; j2 < 22; j2 += 2)
+ {
+ n2 += 17;
+ l4 = i2 * 31 + j2;
+ }
+ #pragma omp for collapse(2) lastprivate(l5, i3, j3) linear (n3:17) schedule (static, 3) allocate (n3, l5, i3, j3)
+ for (i3 = 3; i3 < 5; i3++)
+ for (j3 = 17; j3 < 23; j3 += 2)
+ {
+ n3 += 17;
+ l5 = i3 * 31 + j3;
+ }
+ #pragma omp for collapse(2) lastprivate(l6, i4, j4) linear (n4:17) schedule (dynamic) allocate (allocator (h): n4, l6, i4, j4)
+ for (i4 = 3; i4 < 5; i4++)
+ for (j4 = 17; j4 < 22; j4 += 2)
+ {
+ n4 += 17;
+ l6 = i4 * 31 + j4;
+ }
+ #pragma omp for lastprivate (i5) allocate (i5)
+ for (i5 = 1; i5 < 17; i5 += 3)
+ ;
+ #pragma omp task private(y) firstprivate(x) allocate(x, y)
+ {
+ if (x != 42)
+ abort ();
+ x++;
+ y = 21;
+ if (x != 43 || y != 21)
+ abort ();
+ }
+ #pragma omp task private(y) firstprivate(x) allocate(allocator (h): x, y)
+ {
+ if (x != 42)
+ abort ();
+ x++;
+ y = 21;
+ if (x != 43 || y != 21)
+ abort ();
+ }
+ #pragma omp task private(y) firstprivate(s) allocate(s, y)
+ {
+ if (s.a != 27 || s.b != 29)
+ abort ();
+ s.a++;
+ s.b++;
+ y = 21;
+ if (s.a != 28 || s.b != 30 || y != 21)
+ abort ();
+ }
+ #pragma omp task private(y) firstprivate(s) allocate(allocator (h), align (16): s, y)
+ {
+ if (s.a != 27 || s.b != 29)
+ abort ();
+ s.a++;
+ s.b++;
+ y = 21;
+ if (s.a != 28 || s.b != 30 || y != 21)
+ abort ();
+ }
+ }
+ if (r != 64 * 63 / 2 || l != 63 || n != 8 + 16 * 64)
+ abort ();
+ if (l2[0] != 63 || l2[1] != 63 + 1 || l2[2] != 63 + 2 || l2[3] != 63 + 3 || l3 != 36)
+ abort ();
+ if (i2 != 5 || j2 != 23 || n2 != 9 + 6 * 17 || l4 != 4 * 31 + 21)
+ abort ();
+ if (i3 != 5 || j3 != 23 || n3 != 10 + 6 * 17 || l5 != 4 * 31 + 21)
+ abort ();
+ if (i4 != 5 || j4 != 23 || n4 != 11 + 6 * 17 || l6 != 4 * 31 + 21)
+ abort ();
+ if (i5 != 19)
+ abort ();
+}
+
+int
+main ()
+{
+ omp_alloctrait_t traits[3]
+ = { { omp_atk_alignment, 64 },
+ { omp_atk_fallback, omp_atv_null_fb } };
+ omp_allocator_handle_t a
+ = omp_init_allocator (omp_default_mem_space, 2, traits);
+ int p[4], q[3];
+ if (a == omp_null_allocator)
+ abort ();
+ omp_set_default_allocator (omp_default_mem_alloc);
+ foo (42, p, q, 2, omp_null_allocator, 0);
+ foo (42, p, q, 2, omp_default_mem_alloc, 0);
+ foo (42, p, q, 2, a, 1);
+ omp_set_default_allocator (a);
+ foo (42, p, q, 2, omp_null_allocator, 3);
+ foo (42, p, q, 2, omp_default_mem_alloc, 2);
+ bar (42, a);
+ omp_destroy_allocator (a);
+ return 0;
+}