This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[gomp5] Support OpenMP 5.0 iterators in depend clauses
- From: Jakub Jelinek <jakub at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Wed, 13 Jun 2018 20:41:09 +0200
- Subject: [gomp5] Support OpenMP 5.0 iterators in depend clauses
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
Hi!
The following patch adds support for depend clause iterators.
Tested on x86_64-linux, committed to gomp-5_0-branch.
2018-06-13 Jakub Jelinek <jakub@redhat.com>
* gimplify.c (gimplify_omp_depend): New function.
(gimplify_scan_omp_clauses): Gimplify depend clauses with iterators.
* omp-low.c (lower_depend_clauses): If OMP_CLAUSE_DEPEND_LAST is seen,
assume lowering is done already and return early. Set kind
on artificial depend clause to OMP_CLAUSE_DEPEND_LAST.
* tree-pretty-print.c (dump_omp_iterators): New function.
(dump_omp_clause): Print iterators in depend clauses. Print
__internal__ for OMP_CLAUSE_DEPEND_LAST.
gcc/c/
* c-parser.c (c_parser_omp_iterators): New function.
(c_parser_omp_clause_depend): Parse iterator modifier and handle
iterators.
* c-typeck.c (handle_omp_array_sections): Handle depend clauses
with iterators.
(struct c_find_omp_var_s): New type.
(c_find_omp_var_r): New function.
(c_omp_finish_iterators): New function.
(c_finish_omp_clauses): Handle depend clauses with iterators.
gcc/cp/
* parser.c (cp_parser_omp_iterators): New function.
(cp_parser_omp_clause_depend): Parse iterator modifier and handle
iterators.
* semantics.c (handle_omp_array_sections): Handle depend clauses
with iterators.
(cp_omp_finish_iterators): New function.
(finish_omp_clauses): Handle depend clauses with iterators.
* pt.c (tsubst_omp_clause_decl): Add iterators_cache argument.
Adjust recursive calls. Handle iterators.
(tsubst_omp_clauses): Adjust tsubst_omp_clause_decl callers.
gcc/testsuite/
* c-c++-common/gomp/depend-iterator-1.c: New test.
* c-c++-common/gomp/depend-iterator-2.c: New test.
* g++.dg/gomp/depend-iterator-1.C: New test.
* g++.dg/gomp/depend-iterator-2.C: New test.
libgomp/
* testsuite/libgomp.c-c++-common/depend-iterator-1.c: New test.
* testsuite/libgomp.c++/depend-iterator-1.C: New test.
--- gcc/gimplify.c.jj 2018-06-05 15:00:56.217957674 +0200
+++ gcc/gimplify.c 2018-06-12 11:45:41.817981609 +0200
@@ -7556,6 +7556,368 @@ find_decl_expr (tree *tp, int *walk_subt
return NULL_TREE;
}
+/* If *LIST_P contains any OpenMP depend clauses with iterators,
+ lower all the depend clauses by populating corresponding depend
+ array. Returns 0 if there are no such depend clauses, or
+ 2 if all depend clauses should be removed, 1 otherwise. */
+
+static int
+gimplify_omp_depend (tree *list_p, gimple_seq *pre_p)
+{
+ tree c;
+ gimple *g;
+ size_t n[2] = { 0, 0 };
+ tree counts[2] = { NULL_TREE, NULL_TREE };
+ tree last_iter = NULL_TREE, last_count = NULL_TREE;
+ size_t i;
+ location_t first_loc = UNKNOWN_LOCATION;
+
+ for (c = *list_p; c; c = OMP_CLAUSE_CHAIN (c))
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
+ {
+ switch (OMP_CLAUSE_DEPEND_KIND (c))
+ {
+ case OMP_CLAUSE_DEPEND_IN:
+ i = 0;
+ break;
+ case OMP_CLAUSE_DEPEND_OUT:
+ case OMP_CLAUSE_DEPEND_INOUT:
+ case OMP_CLAUSE_DEPEND_MUTEXINOUTSET:
+ i = 1;
+ break;
+ case OMP_CLAUSE_DEPEND_SOURCE:
+ case OMP_CLAUSE_DEPEND_SINK:
+ continue;
+ default:
+ gcc_unreachable ();
+ }
+ tree t = OMP_CLAUSE_DECL (c);
+ if (first_loc == UNKNOWN_LOCATION)
+ first_loc = OMP_CLAUSE_LOCATION (c);
+ if (TREE_CODE (t) == TREE_LIST
+ && TREE_PURPOSE (t)
+ && TREE_CODE (TREE_PURPOSE (t)) == TREE_VEC)
+ {
+ if (TREE_PURPOSE (t) != last_iter)
+ {
+ tree tcnt = size_one_node;
+ for (tree it = TREE_PURPOSE (t); it; it = TREE_CHAIN (it))
+ {
+ if (gimplify_expr (&TREE_VEC_ELT (it, 1), pre_p, NULL,
+ is_gimple_val, fb_rvalue) == GS_ERROR
+ || gimplify_expr (&TREE_VEC_ELT (it, 2), pre_p, NULL,
+ is_gimple_val, fb_rvalue) == GS_ERROR
+ || (gimplify_expr (&TREE_VEC_ELT (it, 3), pre_p, NULL,
+ is_gimple_val, fb_rvalue)
+ == GS_ERROR))
+ return 2;
+ tree var = TREE_VEC_ELT (it, 0);
+ tree begin = TREE_VEC_ELT (it, 1);
+ tree end = TREE_VEC_ELT (it, 2);
+ tree step = TREE_VEC_ELT (it, 3);
+ tree type = TREE_TYPE (var);
+ tree stype = TREE_TYPE (step);
+ location_t loc = DECL_SOURCE_LOCATION (var);
+ tree endmbegin;
+ /* Compute count for this iterator as
+ step > 0
+ ? (begin < end ? (end - begin + (step - 1)) / step : 0)
+ : (begin > end ? (end - begin + (step + 1)) / step : 0)
+ and compute product of those for the entire depend
+ clause. */
+ if (POINTER_TYPE_P (type))
+ endmbegin = fold_build2_loc (loc, POINTER_DIFF_EXPR,
+ stype, end, begin);
+ else
+ endmbegin = fold_build2_loc (loc, MINUS_EXPR, type,
+ end, begin);
+ tree stepm1 = fold_build2_loc (loc, MINUS_EXPR, stype,
+ step,
+ build_int_cst (stype, 1));
+ tree stepp1 = fold_build2_loc (loc, PLUS_EXPR, stype, step,
+ build_int_cst (stype, 1));
+ tree pos = fold_build2_loc (loc, PLUS_EXPR, stype,
+ unshare_expr (endmbegin),
+ stepm1);
+ pos = fold_build2_loc (loc, TRUNC_DIV_EXPR, stype,
+ pos, step);
+ tree neg = fold_build2_loc (loc, PLUS_EXPR, stype,
+ endmbegin, stepp1);
+ neg = fold_build2_loc (loc, TRUNC_DIV_EXPR, stype,
+ neg, step);
+ tree cond = fold_build2_loc (loc, LT_EXPR,
+ boolean_type_node,
+ begin, end);
+ pos = fold_build3_loc (loc, COND_EXPR, stype, cond, pos,
+ build_int_cst (stype, 0));
+ cond = fold_build2_loc (loc, LT_EXPR, boolean_type_node,
+ end, begin);
+ neg = fold_build3_loc (loc, COND_EXPR, stype, cond, neg,
+ build_int_cst (stype, 0));
+ cond = fold_build2_loc (loc, GT_EXPR, boolean_type_node,
+ step, build_int_cst (stype, 0));
+ tree cnt = fold_build3_loc (loc, COND_EXPR, stype,
+ cond, pos, neg);
+ cnt = fold_convert_loc (loc, sizetype, cnt);
+ if (gimplify_expr (&cnt, pre_p, NULL, is_gimple_val,
+ fb_rvalue) == GS_ERROR)
+ return 2;
+ tcnt = size_binop_loc (loc, MULT_EXPR, tcnt, cnt);
+ }
+ if (gimplify_expr (&tcnt, pre_p, NULL, is_gimple_val,
+ fb_rvalue) == GS_ERROR)
+ return 2;
+ last_iter = TREE_PURPOSE (t);
+ last_count = tcnt;
+ }
+ if (counts[i] == NULL_TREE)
+ counts[i] = last_count;
+ else
+ counts[i] = size_binop_loc (OMP_CLAUSE_LOCATION (c),
+ PLUS_EXPR, counts[i], last_count);
+ }
+ else
+ n[i]++;
+ }
+ if (counts[0] == NULL_TREE && counts[1] == NULL_TREE)
+ return 0;
+ for (i = 0; i < 2; i++)
+ {
+ if (counts[i] == NULL_TREE)
+ counts[i] = size_zero_node;
+ if (n[i])
+ counts[i] = size_binop (PLUS_EXPR, counts[i], size_int (n[i]));
+ if (gimplify_expr (&counts[i], pre_p, NULL, is_gimple_val,
+ fb_rvalue) == GS_ERROR)
+ return 2;
+ }
+
+ tree total = size_binop (PLUS_EXPR, counts[0], counts[1]);
+ if (gimplify_expr (&total, pre_p, NULL, is_gimple_val, fb_rvalue)
+ == GS_ERROR)
+ return 2;
+ tree totalp1 = size_binop (PLUS_EXPR, unshare_expr (total), size_int (1));
+ tree type = build_array_type (ptr_type_node, build_index_type (totalp1));
+ tree array = create_tmp_var_raw (type);
+ TREE_ADDRESSABLE (array) = 1;
+ if (TREE_CODE (totalp1) != INTEGER_CST)
+ {
+ if (!TYPE_SIZES_GIMPLIFIED (TREE_TYPE (array)))
+ gimplify_type_sizes (TREE_TYPE (array), pre_p);
+ if (gimplify_omp_ctxp)
+ {
+ struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
+ while (ctx
+ && (ctx->region_type == ORT_WORKSHARE
+ || ctx->region_type == ORT_SIMD
+ || ctx->region_type == ORT_ACC))
+ ctx = ctx->outer_context;
+ if (ctx)
+ omp_add_variable (ctx, array, GOVD_LOCAL | GOVD_SEEN);
+ }
+ gimplify_vla_decl (array, pre_p);
+ }
+ else
+ gimple_add_tmp_var (array);
+ tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
+ NULL_TREE);
+ tree tem = build2 (MODIFY_EXPR, void_type_node, r,
+ fold_convert (ptr_type_node, total));
+ gimplify_and_add (tem, pre_p);
+ r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
+ NULL_TREE);
+ tem = build2 (MODIFY_EXPR, void_type_node, r, counts[1]);
+ gimplify_and_add (tem, pre_p);
+
+ tree cnts[2];
+ for (i = 0; i < 2; i++)
+ {
+ cnts[i] = create_tmp_var (sizetype, NULL);
+ g = gimple_build_assign (cnts[i], i == 0 ? size_int (2)
+ : size_binop (PLUS_EXPR, counts[0],
+ size_int (2)));
+ gimple_seq_add_stmt (pre_p, g);
+ }
+
+ last_iter = NULL_TREE;
+ tree last_bind = NULL_TREE;
+ tree *last_body = NULL;
+ for (c = *list_p; c; c = OMP_CLAUSE_CHAIN (c))
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
+ {
+ switch (OMP_CLAUSE_DEPEND_KIND (c))
+ {
+ case OMP_CLAUSE_DEPEND_IN:
+ i = 0;
+ break;
+ case OMP_CLAUSE_DEPEND_OUT:
+ case OMP_CLAUSE_DEPEND_INOUT:
+ case OMP_CLAUSE_DEPEND_MUTEXINOUTSET:
+ i = 1;
+ break;
+ case OMP_CLAUSE_DEPEND_SOURCE:
+ case OMP_CLAUSE_DEPEND_SINK:
+ continue;
+ default:
+ gcc_unreachable ();
+ }
+ tree t = OMP_CLAUSE_DECL (c);
+ if (TREE_CODE (t) == TREE_LIST
+ && TREE_PURPOSE (t)
+ && TREE_CODE (TREE_PURPOSE (t)) == TREE_VEC)
+ {
+ if (TREE_PURPOSE (t) != last_iter)
+ {
+ if (last_bind)
+ gimplify_and_add (last_bind, pre_p);
+ tree block = TREE_VEC_ELT (TREE_PURPOSE (t), 4);
+ last_bind = build3 (BIND_EXPR, void_type_node,
+ BLOCK_VARS (block), NULL, block);
+ TREE_SIDE_EFFECTS (last_bind) = 1;
+ SET_EXPR_LOCATION (last_bind, OMP_CLAUSE_LOCATION (c));
+ tree *p = &BIND_EXPR_BODY (last_bind);
+ for (tree it = TREE_PURPOSE (t); it; it = TREE_CHAIN (it))
+ {
+ tree var = TREE_VEC_ELT (it, 0);
+ tree begin = TREE_VEC_ELT (it, 1);
+ tree end = TREE_VEC_ELT (it, 2);
+ tree step = TREE_VEC_ELT (it, 3);
+ tree type = TREE_TYPE (var);
+ tree stype = TREE_TYPE (step);
+ location_t loc = DECL_SOURCE_LOCATION (var);
+ /* Emit:
+ var = begin;
+ goto cond_label;
+ beg_label:
+ ...
+ var = var + step;
+ cond_label:
+ if (step > 0) {
+ if (var < end) goto beg_label;
+ } else {
+ if (var > end) goto beg_label;
+ }
+ for each iterator, with inner iterators added to
+ the ... above. */
+ tree beg_label = create_artificial_label (loc);
+ tree cond_label = NULL_TREE;
+ tem = build2_loc (loc, MODIFY_EXPR, void_type_node,
+ var, begin);
+ append_to_statement_list_force (tem, p);
+ tem = build_and_jump (&cond_label);
+ append_to_statement_list_force (tem, p);
+ tem = build1 (LABEL_EXPR, void_type_node, beg_label);
+ append_to_statement_list (tem, p);
+ tree bind = build3 (BIND_EXPR, void_type_node, NULL_TREE,
+ NULL_TREE, NULL_TREE);
+ TREE_SIDE_EFFECTS (bind) = 1;
+ SET_EXPR_LOCATION (bind, loc);
+ append_to_statement_list_force (bind, p);
+ if (POINTER_TYPE_P (type))
+ tem = build2_loc (loc, POINTER_PLUS_EXPR, type,
+ var, fold_convert_loc (loc, sizetype,
+ step));
+ else
+ tem = build2_loc (loc, PLUS_EXPR, type, var, step);
+ tem = build2_loc (loc, MODIFY_EXPR, void_type_node,
+ var, tem);
+ append_to_statement_list_force (tem, p);
+ tem = build1 (LABEL_EXPR, void_type_node, cond_label);
+ append_to_statement_list (tem, p);
+ tree cond = fold_build2_loc (loc, LT_EXPR,
+ boolean_type_node,
+ var, end);
+ tree pos
+ = fold_build3_loc (loc, COND_EXPR, void_type_node,
+ cond, build_and_jump (&beg_label),
+ void_node);
+ cond = fold_build2_loc (loc, GT_EXPR, boolean_type_node,
+ var, end);
+ tree neg
+ = fold_build3_loc (loc, COND_EXPR, void_type_node,
+ cond, build_and_jump (&beg_label),
+ void_node);
+ cond = fold_build2_loc (loc, GT_EXPR, boolean_type_node,
+ step, build_int_cst (stype, 0));
+ tem = fold_build3_loc (loc, COND_EXPR, void_type_node,
+ cond, pos, neg);
+ append_to_statement_list_force (tem, p);
+ p = &BIND_EXPR_BODY (bind);
+ }
+ last_body = p;
+ }
+ last_iter = TREE_PURPOSE (t);
+ if (TREE_CODE (TREE_VALUE (t)) == COMPOUND_EXPR)
+ {
+ append_to_statement_list (TREE_OPERAND (TREE_VALUE (t),
+ 0), last_body);
+ TREE_VALUE (t) = TREE_OPERAND (TREE_VALUE (t), 1);
+ }
+ if (error_operand_p (TREE_VALUE (t)))
+ return 2;
+ TREE_VALUE (t) = build_fold_addr_expr (TREE_VALUE (t));
+ r = build4 (ARRAY_REF, ptr_type_node, array, cnts[i],
+ NULL_TREE, NULL_TREE);
+ tem = build2_loc (OMP_CLAUSE_LOCATION (c), MODIFY_EXPR,
+ void_type_node, r, TREE_VALUE (t));
+ append_to_statement_list_force (tem, last_body);
+ tem = build2_loc (OMP_CLAUSE_LOCATION (c), MODIFY_EXPR,
+ void_type_node, cnts[i],
+ size_binop (PLUS_EXPR, cnts[i], size_int (1)));
+ append_to_statement_list_force (tem, last_body);
+ TREE_VALUE (t) = null_pointer_node;
+ }
+ else
+ {
+ if (last_bind)
+ {
+ gimplify_and_add (last_bind, pre_p);
+ last_bind = NULL_TREE;
+ }
+ if (TREE_CODE (OMP_CLAUSE_DECL (c)) == COMPOUND_EXPR)
+ {
+ gimplify_expr (&TREE_OPERAND (OMP_CLAUSE_DECL (c), 0), pre_p,
+ NULL, is_gimple_val, fb_rvalue);
+ OMP_CLAUSE_DECL (c) = TREE_OPERAND (OMP_CLAUSE_DECL (c), 1);
+ }
+ if (error_operand_p (OMP_CLAUSE_DECL (c)))
+ return 2;
+ OMP_CLAUSE_DECL (c) = build_fold_addr_expr (OMP_CLAUSE_DECL (c));
+ if (gimplify_expr (&OMP_CLAUSE_DECL (c), pre_p, NULL,
+ is_gimple_val, fb_rvalue) == GS_ERROR)
+ return 2;
+ r = build4 (ARRAY_REF, ptr_type_node, array, cnts[i],
+ NULL_TREE, NULL_TREE);
+ tem = build2 (MODIFY_EXPR, void_type_node, r, OMP_CLAUSE_DECL (c));
+ gimplify_and_add (tem, pre_p);
+ g = gimple_build_assign (cnts[i], size_binop (PLUS_EXPR, cnts[i],
+ size_int (1)));
+ gimple_seq_add_stmt (pre_p, g);
+ }
+ }
+ if (last_bind)
+ gimplify_and_add (last_bind, pre_p);
+ tree cond = build2_loc (first_loc, NE_EXPR, boolean_type_node, cnts[0],
+ size_binop_loc (first_loc, PLUS_EXPR, counts[0],
+ size_int (2)));
+ cond = build2_loc (first_loc, TRUTH_OR_EXPR, boolean_type_node, cond,
+ build2_loc (first_loc, NE_EXPR, boolean_type_node,
+ cnts[1],
+ size_binop_loc (first_loc, PLUS_EXPR,
+ totalp1, size_int (1))));
+ tem = build3_loc (first_loc, COND_EXPR, void_type_node, cond,
+ build_call_expr_loc (first_loc,
+ builtin_decl_explicit (BUILT_IN_TRAP),
+ 0), void_node);
+ gimplify_and_add (tem, pre_p);
+ c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
+ OMP_CLAUSE_DEPEND_KIND (c) = OMP_CLAUSE_DEPEND_LAST;
+ OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
+ OMP_CLAUSE_CHAIN (c) = *list_p;
+ *list_p = c;
+ return 1;
+}
+
/* Scan the OMP clauses in *LIST_P, installing mappings into a new
and previous omp contexts. */
@@ -7568,6 +7930,7 @@ gimplify_scan_omp_clauses (tree *list_p,
tree c;
hash_map<tree, tree> *struct_map_to_clause = NULL;
tree *prev_list_p = NULL;
+ int handled_depend_iterators = -1;
ctx = new_omp_context (region_type);
outer_ctx = ctx->outer_context;
@@ -8330,6 +8693,14 @@ gimplify_scan_omp_clauses (tree *list_p,
}
else if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE)
break;
+ if (handled_depend_iterators == -1)
+ handled_depend_iterators = gimplify_omp_depend (list_p, pre_p);
+ if (handled_depend_iterators)
+ {
+ if (handled_depend_iterators == 2)
+ remove = true;
+ break;
+ }
if (TREE_CODE (OMP_CLAUSE_DECL (c)) == COMPOUND_EXPR)
{
gimplify_expr (&TREE_OPERAND (OMP_CLAUSE_DECL (c), 0), pre_p,
--- gcc/omp-low.c.jj 2018-06-05 15:00:56.232957694 +0200
+++ gcc/omp-low.c 2018-06-08 12:12:34.377111135 +0200
@@ -7347,6 +7347,9 @@ lower_depend_clauses (tree *pclauses, gi
if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
switch (OMP_CLAUSE_DEPEND_KIND (c))
{
+ case OMP_CLAUSE_DEPEND_LAST:
+ /* Lowering already done at gimplification. */
+ return;
case OMP_CLAUSE_DEPEND_IN:
n_in++;
break;
@@ -7390,6 +7393,7 @@ lower_depend_clauses (tree *pclauses, gi
}
}
c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
+ OMP_CLAUSE_DEPEND_KIND (c) = OMP_CLAUSE_DEPEND_LAST;
OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
OMP_CLAUSE_CHAIN (c) = *pclauses;
*pclauses = c;
--- gcc/tree-pretty-print.c.jj 2018-06-05 15:00:56.232957694 +0200
+++ gcc/tree-pretty-print.c 2018-06-08 10:57:43.223983430 +0200
@@ -382,6 +382,31 @@ dump_array_domain (pretty_printer *pp, t
}
+/* Dump OpenMP iterators ITER. */
+
+static void
+dump_omp_iterators (pretty_printer *pp, tree iter, int spc, dump_flags_t flags)
+{
+ pp_string (pp, "iterator(");
+ for (tree it = iter; it; it = TREE_CHAIN (it))
+ {
+ if (it != iter)
+ pp_string (pp, ", ");
+ dump_generic_node (pp, TREE_TYPE (TREE_VEC_ELT (it, 0)), spc, flags,
+ false);
+ pp_space (pp);
+ dump_generic_node (pp, TREE_VEC_ELT (it, 0), spc, flags, false);
+ pp_equal (pp);
+ dump_generic_node (pp, TREE_VEC_ELT (it, 1), spc, flags, false);
+ pp_colon (pp);
+ dump_generic_node (pp, TREE_VEC_ELT (it, 2), spc, flags, false);
+ pp_colon (pp);
+ dump_generic_node (pp, TREE_VEC_ELT (it, 3), spc, flags, false);
+ }
+ pp_right_paren (pp);
+}
+
+
/* Dump OpenMP clause CLAUSE. PP, CLAUSE, SPC and FLAGS are as in
dump_generic_node. */
@@ -650,20 +675,23 @@ dump_omp_clause (pretty_printer *pp, tre
switch (OMP_CLAUSE_DEPEND_KIND (clause))
{
case OMP_CLAUSE_DEPEND_IN:
- pp_string (pp, "in");
+ name = "in";
break;
case OMP_CLAUSE_DEPEND_OUT:
- pp_string (pp, "out");
+ name = "out";
break;
case OMP_CLAUSE_DEPEND_INOUT:
- pp_string (pp, "inout");
+ name = "inout";
break;
case OMP_CLAUSE_DEPEND_MUTEXINOUTSET:
- pp_string (pp, "mutexinoutset");
+ name = "mutexinoutset";
break;
case OMP_CLAUSE_DEPEND_SOURCE:
pp_string (pp, "source)");
return;
+ case OMP_CLAUSE_DEPEND_LAST:
+ name = "__internal__";
+ break;
case OMP_CLAUSE_DEPEND_SINK:
pp_string (pp, "sink:");
for (tree t = OMP_CLAUSE_DECL (clause); t; t = TREE_CHAIN (t))
@@ -689,10 +717,21 @@ dump_omp_clause (pretty_printer *pp, tre
default:
gcc_unreachable ();
}
- pp_colon (pp);
- dump_generic_node (pp, OMP_CLAUSE_DECL (clause),
- spc, flags, false);
- pp_right_paren (pp);
+ {
+ tree t = OMP_CLAUSE_DECL (clause);
+ if (TREE_CODE (t) == TREE_LIST
+ && TREE_PURPOSE (t)
+ && TREE_CODE (TREE_PURPOSE (t)) == TREE_VEC)
+ {
+ dump_omp_iterators (pp, TREE_PURPOSE (t), spc, flags);
+ pp_colon (pp);
+ t = TREE_VALUE (t);
+ }
+ pp_string (pp, name);
+ pp_colon (pp);
+ dump_generic_node (pp, t, spc, flags, false);
+ pp_right_paren (pp);
+ }
break;
case OMP_CLAUSE_MAP:
--- gcc/c/c-parser.c.jj 2018-06-05 15:00:56.357957856 +0200
+++ gcc/c/c-parser.c 2018-06-13 13:07:02.194649345 +0200
@@ -13802,6 +13802,106 @@ c_parser_omp_clause_depend_sink (c_parse
return u;
}
+/* OpenMP 5.0:
+ iterators ( iterators-definition )
+
+ iterators-definition:
+ iterator-specifier
+ iterator-specifier , iterators-definition
+
+ iterator-specifier:
+ identifier = range-specification
+ iterator-type identifier = range-specification
+
+ range-specification:
+ begin : end
+ begin : end : step */
+
+static tree
+c_parser_omp_iterators (c_parser *parser)
+{
+ tree ret = NULL_TREE, *last = &ret;
+ c_parser_consume_token (parser);
+
+ push_scope ();
+
+ matching_parens parens;
+ if (!parens.require_open (parser))
+ return error_mark_node;
+
+ do
+ {
+ tree iter_type = NULL_TREE, type_expr = NULL_TREE;
+ if (c_parser_next_tokens_start_typename (parser, cla_prefer_id))
+ {
+ struct c_type_name *type = c_parser_type_name (parser);
+ if (type != NULL)
+ iter_type = groktypename (type, &type_expr, NULL);
+ }
+ if (iter_type == NULL_TREE)
+ iter_type = integer_type_node;
+
+ location_t loc = c_parser_peek_token (parser)->location;
+ if (!c_parser_next_token_is (parser, CPP_NAME))
+ {
+ c_parser_error (parser, "expected identifier");
+ break;
+ }
+
+ tree id = c_parser_peek_token (parser)->value;
+ c_parser_consume_token (parser);
+
+ if (!c_parser_require (parser, CPP_EQ, "expected %<=%>"))
+ break;
+
+ location_t eloc = c_parser_peek_token (parser)->location;
+ c_expr expr = c_parser_expr_no_commas (parser, NULL);
+ expr = convert_lvalue_to_rvalue (eloc, expr, true, false);
+ tree begin = expr.value;
+
+ if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
+ break;
+
+ eloc = c_parser_peek_token (parser)->location;
+ expr = c_parser_expr_no_commas (parser, NULL);
+ expr = convert_lvalue_to_rvalue (eloc, expr, true, false);
+ tree end = expr.value;
+
+ tree step = integer_one_node;
+ if (c_parser_next_token_is (parser, CPP_COLON))
+ {
+ c_parser_consume_token (parser);
+ eloc = c_parser_peek_token (parser)->location;
+ expr = c_parser_expr_no_commas (parser, NULL);
+ expr = convert_lvalue_to_rvalue (eloc, expr, true, false);
+ step = expr.value;
+ }
+
+ tree iter_var = build_decl (loc, VAR_DECL, id, iter_type);
+ DECL_ARTIFICIAL (iter_var) = 1;
+ DECL_CONTEXT (iter_var) = current_function_decl;
+ pushdecl (iter_var);
+
+ *last = make_tree_vec (5);
+ TREE_VEC_ELT (*last, 0) = iter_var;
+ TREE_VEC_ELT (*last, 1) = begin;
+ TREE_VEC_ELT (*last, 2) = end;
+ TREE_VEC_ELT (*last, 3) = step;
+ last = &TREE_CHAIN (*last);
+
+ if (c_parser_next_token_is (parser, CPP_COMMA))
+ {
+ c_parser_consume_token (parser);
+ continue;
+ }
+ break;
+ }
+ while (1);
+
+ parens.skip_until_found_close (parser);
+ return ret;
+}
+
/* OpenMP 4.0:
depend ( depend-kind: variable-list )
@@ -13818,14 +13918,17 @@ c_parser_omp_clause_depend (c_parser *pa
{
location_t clause_loc = c_parser_peek_token (parser)->location;
enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_INOUT;
- tree nl, c;
+ tree nl, c, iterators = NULL_TREE;
matching_parens parens;
if (!parens.require_open (parser))
return list;
- if (c_parser_next_token_is (parser, CPP_NAME))
+ do
{
+ if (c_parser_next_token_is_not (parser, CPP_NAME))
+ goto invalid_kind;
+
const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
if (strcmp ("in", p) == 0)
kind = OMP_CLAUSE_DEPEND_IN;
@@ -13839,14 +13942,29 @@ c_parser_omp_clause_depend (c_parser *pa
kind = OMP_CLAUSE_DEPEND_SOURCE;
else if (strcmp ("sink", p) == 0)
kind = OMP_CLAUSE_DEPEND_SINK;
+ else if (strcmp ("iterator", p) == 0 && iterators == NULL_TREE)
+ {
+ iterators = c_parser_omp_iterators (parser);
+ c_parser_require (parser, CPP_COLON, "expected %<:%>");
+ continue;
+ }
else
goto invalid_kind;
+ break;
}
- else
- goto invalid_kind;
+ while (1);
c_parser_consume_token (parser);
+ if (iterators
+ && (kind == OMP_CLAUSE_DEPEND_SOURCE || kind == OMP_CLAUSE_DEPEND_SINK))
+ {
+ pop_scope ();
+ error_at (clause_loc, "%<iterator%> modifier incompatible with %qs",
+ kind == OMP_CLAUSE_DEPEND_SOURCE ? "source" : "sink");
+ iterators = NULL_TREE;
+ }
+
if (kind == OMP_CLAUSE_DEPEND_SOURCE)
{
c = build_omp_clause (clause_loc, OMP_CLAUSE_DEPEND);
@@ -13867,8 +13985,22 @@ c_parser_omp_clause_depend (c_parser *pa
nl = c_parser_omp_variable_list (parser, clause_loc,
OMP_CLAUSE_DEPEND, list);
+ if (iterators)
+ {
+ tree block = pop_scope ();
+ if (iterators == error_mark_node)
+ iterators = NULL_TREE;
+ else
+ TREE_VEC_ELT (iterators, 4) = block;
+ }
+
for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
- OMP_CLAUSE_DEPEND_KIND (c) = kind;
+ {
+ OMP_CLAUSE_DEPEND_KIND (c) = kind;
+ if (iterators)
+ OMP_CLAUSE_DECL (c)
+ = build_tree_list (iterators, OMP_CLAUSE_DECL (c));
+ }
}
parens.skip_until_found_close (parser);
@@ -13878,6 +14010,8 @@ c_parser_omp_clause_depend (c_parser *pa
c_parser_error (parser, "invalid depend kind");
resync_fail:
parens.skip_until_found_close (parser);
+ if (iterators)
+ pop_scope ();
return list;
}
--- gcc/c/c-typeck.c.jj 2018-06-05 10:59:17.886728884 +0200
+++ gcc/c/c-typeck.c 2018-06-13 18:21:54.220430042 +0200
@@ -12747,7 +12747,13 @@ handle_omp_array_sections (tree c, enum
bool maybe_zero_len = false;
unsigned int first_non_one = 0;
auto_vec<tree, 10> types;
- tree first = handle_omp_array_sections_1 (c, OMP_CLAUSE_DECL (c), types,
+ tree *tp = &OMP_CLAUSE_DECL (c);
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
+ && TREE_CODE (*tp) == TREE_LIST
+ && TREE_PURPOSE (*tp)
+ && TREE_CODE (TREE_PURPOSE (*tp)) == TREE_VEC)
+ tp = &TREE_VALUE (*tp);
+ tree first = handle_omp_array_sections_1 (c, *tp, types,
maybe_zero_len, first_non_one,
ort);
if (first == error_mark_node)
@@ -12756,7 +12762,7 @@ handle_omp_array_sections (tree c, enum
return false;
if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
{
- tree t = OMP_CLAUSE_DECL (c);
+ tree t = *tp;
tree tem = NULL_TREE;
/* Need to evaluate side effects in the length expressions
if any. */
@@ -12775,7 +12781,7 @@ handle_omp_array_sections (tree c, enum
if (tem)
first = build2 (COMPOUND_EXPR, TREE_TYPE (first), tem, first);
first = c_fully_fold (first, false, NULL, true);
- OMP_CLAUSE_DECL (c) = first;
+ *tp = first;
}
else
{
@@ -13038,6 +13044,162 @@ c_find_omp_placeholder_r (tree *tp, int
return NULL_TREE;
}
+/* Similarly, but also walk aggregate fields. */
+
+struct c_find_omp_var_s { tree var; hash_set<tree> *pset; };
+
+static tree
+c_find_omp_var_r (tree *tp, int *, void *data)
+{
+ if (*tp == ((struct c_find_omp_var_s *) data)->var)
+ return *tp;
+ if (RECORD_OR_UNION_TYPE_P (*tp))
+ {
+ tree field;
+ hash_set<tree> *pset = ((struct c_find_omp_var_s *) data)->pset;
+
+ for (field = TYPE_FIELDS (*tp); field;
+ field = DECL_CHAIN (field))
+ if (TREE_CODE (field) == FIELD_DECL)
+ {
+ tree ret = walk_tree (&DECL_FIELD_OFFSET (field),
+ c_find_omp_var_r, data, pset);
+ if (ret)
+ return ret;
+ ret = walk_tree (&DECL_SIZE (field), c_find_omp_var_r, data, pset);
+ if (ret)
+ return ret;
+ ret = walk_tree (&DECL_SIZE_UNIT (field), c_find_omp_var_r, data,
+ pset);
+ if (ret)
+ return ret;
+ ret = walk_tree (&TREE_TYPE (field), c_find_omp_var_r, data, pset);
+ if (ret)
+ return ret;
+ }
+ }
+ else if (INTEGRAL_TYPE_P (*tp))
+ return walk_tree (&TYPE_MAX_VALUE (*tp), c_find_omp_var_r, data,
+ ((struct c_find_omp_var_s *) data)->pset);
+ return NULL_TREE;
+}
+
+/* Finish OpenMP iterators ITER. Return true if they are errorneous
+ and clauses containing them should be removed. */
+
+static bool
+c_omp_finish_iterators (tree iter)
+{
+ bool ret = false;
+ for (tree it = iter; it; it = TREE_CHAIN (it))
+ {
+ tree var = TREE_VEC_ELT (it, 0);
+ tree begin = TREE_VEC_ELT (it, 1);
+ tree end = TREE_VEC_ELT (it, 2);
+ tree step = TREE_VEC_ELT (it, 3);
+ tree type = TREE_TYPE (var);
+ location_t loc = DECL_SOURCE_LOCATION (var);
+ if (type == error_mark_node)
+ {
+ ret = true;
+ continue;
+ }
+ if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
+ {
+ error_at (loc, "iterator %qD has neither integral nor pointer type",
+ var);
+ ret = true;
+ continue;
+ }
+ else if (TYPE_ATOMIC (type))
+ {
+ error_at (loc, "iterator %qD has %<_Atomic%> qualified type", var);
+ ret = true;
+ continue;
+ }
+ else if (TYPE_READONLY (type))
+ {
+ error_at (loc, "iterator %qD has const qualified type", var);
+ ret = true;
+ continue;
+ }
+
+ begin = c_fully_fold (build_c_cast (loc, type, begin), false, NULL);
+ end = c_fully_fold (build_c_cast (loc, type, end), false, NULL);
+ tree stype = POINTER_TYPE_P (type) ? sizetype : type;
+ step = c_fully_fold (build_c_cast (loc, stype, step), false, NULL);
+ if (POINTER_TYPE_P (type))
+ {
+ begin = save_expr (begin);
+ step = pointer_int_sum (loc, PLUS_EXPR, begin, step);
+ step = fold_build2_loc (loc, MINUS_EXPR, sizetype,
+ fold_convert (sizetype, step),
+ fold_convert (sizetype, begin));
+ step = fold_convert (ssizetype, step);
+ }
+ if (integer_zerop (step))
+ {
+ error_at (loc, "iterator %qD has zero step", var);
+ ret = true;
+ continue;
+ }
+
+ if (begin == error_mark_node
+ || end == error_mark_node
+ || step == error_mark_node)
+ {
+ ret = true;
+ continue;
+ }
+ hash_set<tree> pset;
+ tree it2;
+ for (it2 = TREE_CHAIN (it); it2; it2 = TREE_CHAIN (it2))
+ {
+ tree var2 = TREE_VEC_ELT (it2, 0);
+ tree begin2 = TREE_VEC_ELT (it2, 1);
+ tree end2 = TREE_VEC_ELT (it2, 2);
+ tree step2 = TREE_VEC_ELT (it2, 3);
+ tree type2 = TREE_TYPE (var2);
+ location_t loc2 = DECL_SOURCE_LOCATION (var2);
+ struct c_find_omp_var_s data = { var, &pset };
+ if (walk_tree (&type2, c_find_omp_var_r, &data, &pset))
+ {
+ error_at (loc2,
+ "type of iterator %qD refers to outer iterator %qD",
+ var2, var);
+ break;
+ }
+ else if (walk_tree (&begin2, c_find_omp_var_r, &data, &pset))
+ {
+ error_at (EXPR_LOC_OR_LOC (begin2, loc2),
+ "begin expression refers to outer iterator %qD", var);
+ break;
+ }
+ else if (walk_tree (&end2, c_find_omp_var_r, &data, &pset))
+ {
+ error_at (EXPR_LOC_OR_LOC (end2, loc2),
+ "end expression refers to outer iterator %qD", var);
+ break;
+ }
+ else if (walk_tree (&step2, c_find_omp_var_r, &data, &pset))
+ {
+ error_at (EXPR_LOC_OR_LOC (step2, loc2),
+ "step expression refers to outer iterator %qD", var);
+ break;
+ }
+ }
+ if (it2)
+ {
+ ret = true;
+ continue;
+ }
+ TREE_VEC_ELT (it, 1) = begin;
+ TREE_VEC_ELT (it, 2) = end;
+ TREE_VEC_ELT (it, 3) = step;
+ }
+ return ret;
+}
+
/* For all elements of CLAUSES, validate them against their constraints.
Remove any elements from the list that are invalid. */
@@ -13055,6 +13217,8 @@ c_finish_omp_clauses (tree clauses, enum
bool ordered_seen = false;
tree schedule_clause = NULL_TREE;
bool oacc_async = false;
+ tree last_iterators = NULL_TREE;
+ bool last_iterators_remove = false;
bitmap_obstack_initialize (NULL);
bitmap_initialize (&generic_head, &bitmap_default_obstack);
@@ -13589,6 +13753,20 @@ c_finish_omp_clauses (tree clauses, enum
}
break;
}
+ if (TREE_CODE (t) == TREE_LIST
+ && TREE_PURPOSE (t)
+ && TREE_CODE (TREE_PURPOSE (t)) == TREE_VEC)
+ {
+ if (TREE_PURPOSE (t) != last_iterators)
+ last_iterators_remove
+ = c_omp_finish_iterators (TREE_PURPOSE (t));
+ last_iterators = TREE_PURPOSE (t);
+ t = TREE_VALUE (t);
+ if (last_iterators_remove)
+ t = error_mark_node;
+ }
+ else
+ last_iterators = NULL_TREE;
if (TREE_CODE (t) == TREE_LIST)
{
if (handle_omp_array_sections (c, ort))
--- gcc/cp/parser.c.jj 2018-06-04 18:17:54.995533519 +0200
+++ gcc/cp/parser.c 2018-06-13 16:26:27.294958834 +0200
@@ -33598,6 +33598,118 @@ cp_parser_omp_clause_depend_sink (cp_par
return list;
}
+/* OpenMP 5.0:
+ iterators ( iterators-definition )
+
+ iterators-definition:
+ iterator-specifier
+ iterator-specifier , iterators-definition
+
+ iterator-specifier:
+ identifier = range-specification
+ iterator-type identifier = range-specification
+
+ range-specification:
+ begin : end
+ begin : end : step */
+
+static tree
+cp_parser_omp_iterators (cp_parser *parser)
+{
+ tree ret = NULL_TREE, *last = &ret;
+ cp_lexer_consume_token (parser->lexer);
+
+ matching_parens parens;
+ if (!parens.require_open (parser))
+ return error_mark_node;
+
+ bool saved_colon_corrects_to_scope_p
+ = parser->colon_corrects_to_scope_p;
+ bool saved_colon_doesnt_start_class_def_p
+ = parser->colon_doesnt_start_class_def_p;
+
+ do
+ {
+ tree iter_type;
+ if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)
+ && cp_lexer_nth_token_is (parser->lexer, 2, CPP_EQ))
+ iter_type = integer_type_node;
+ else
+ {
+ const char *saved_message
+ = parser->type_definition_forbidden_message;
+ parser->type_definition_forbidden_message
+ = G_("types may not be defined in iterator type");
+
+ iter_type = cp_parser_type_id (parser);
+
+ parser->type_definition_forbidden_message = saved_message;
+ }
+
+ location_t loc = cp_lexer_peek_token (parser->lexer)->location;
+ if (cp_lexer_next_token_is_not (parser->lexer, CPP_NAME))
+ {
+ cp_parser_error (parser, "expected identifier");
+ break;
+ }
+
+ tree id = cp_parser_identifier (parser);
+ if (id == error_mark_node)
+ break;
+
+ if (!cp_parser_require (parser, CPP_EQ, RT_EQ))
+ break;
+
+ parser->colon_corrects_to_scope_p = false;
+ parser->colon_doesnt_start_class_def_p = true;
+ tree begin = cp_parser_assignment_expression (parser);
+
+ if (!cp_parser_require (parser, CPP_COLON, RT_COLON))
+ break;
+
+ tree end = cp_parser_assignment_expression (parser);
+
+ tree step = integer_one_node;
+ if (cp_lexer_next_token_is (parser->lexer, CPP_COLON))
+ {
+ cp_lexer_consume_token (parser->lexer);
+ step = cp_parser_assignment_expression (parser);
+ }
+
+ tree iter_var = build_decl (loc, VAR_DECL, id, iter_type);
+ DECL_ARTIFICIAL (iter_var) = 1;
+ DECL_CONTEXT (iter_var) = current_function_decl;
+ pushdecl (iter_var);
+
+ *last = make_tree_vec (5);
+ TREE_VEC_ELT (*last, 0) = iter_var;
+ TREE_VEC_ELT (*last, 1) = begin;
+ TREE_VEC_ELT (*last, 2) = end;
+ TREE_VEC_ELT (*last, 3) = step;
+ last = &TREE_CHAIN (*last);
+
+ if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
+ {
+ cp_lexer_consume_token (parser->lexer);
+ continue;
+ }
+ break;
+ }
+ while (1);
+
+ parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p;
+ parser->colon_doesnt_start_class_def_p
+ = saved_colon_doesnt_start_class_def_p;
+
+ if (!parens.require_close (parser))
+ cp_parser_skip_to_closing_parenthesis (parser,
+ /*recovering=*/true,
+ /*or_comma=*/false,
+ /*consume_paren=*/true);
+
+ return ret;
+}
+
/* OpenMP 4.0:
depend ( depend-kind : variable-list )
@@ -33612,15 +33724,18 @@ cp_parser_omp_clause_depend_sink (cp_par
static tree
cp_parser_omp_clause_depend (cp_parser *parser, tree list, location_t loc)
{
- tree nlist, c;
+ tree nlist, c, iterators = NULL_TREE;
enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_INOUT;
matching_parens parens;
if (!parens.require_open (parser))
return list;
- if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+ do
{
+ if (cp_lexer_next_token_is_not (parser->lexer, CPP_NAME))
+ goto invalid_kind;
+
tree id = cp_lexer_peek_token (parser->lexer)->u.value;
const char *p = IDENTIFIER_POINTER (id);
@@ -33636,14 +33751,30 @@ cp_parser_omp_clause_depend (cp_parser *
kind = OMP_CLAUSE_DEPEND_SOURCE;
else if (strcmp ("sink", p) == 0)
kind = OMP_CLAUSE_DEPEND_SINK;
+ else if (strcmp ("iterator", p) == 0 && iterators == NULL_TREE)
+ {
+ begin_scope (sk_omp, NULL);
+ iterators = cp_parser_omp_iterators (parser);
+ cp_parser_require (parser, CPP_COLON, RT_COLON);
+ continue;
+ }
else
goto invalid_kind;
+ break;
}
- else
- goto invalid_kind;
+ while (1);
cp_lexer_consume_token (parser->lexer);
+ if (iterators
+ && (kind == OMP_CLAUSE_DEPEND_SOURCE || kind == OMP_CLAUSE_DEPEND_SINK))
+ {
+ poplevel (0, 1, 0);
+ error_at (loc, "%<iterator%> modifier incompatible with %qs",
+ kind == OMP_CLAUSE_DEPEND_SOURCE ? "source" : "sink");
+ iterators = NULL_TREE;
+ }
+
if (kind == OMP_CLAUSE_DEPEND_SOURCE)
{
c = build_omp_clause (loc, OMP_CLAUSE_DEPEND);
@@ -33667,14 +33798,30 @@ cp_parser_omp_clause_depend (cp_parser *
nlist = cp_parser_omp_var_list_no_open (parser, OMP_CLAUSE_DEPEND,
list, NULL);
+ if (iterators)
+ {
+ tree block = poplevel (1, 1, 0);
+ if (iterators == error_mark_node)
+ iterators = NULL_TREE;
+ else
+ TREE_VEC_ELT (iterators, 4) = block;
+ }
+
for (c = nlist; c != list; c = OMP_CLAUSE_CHAIN (c))
- OMP_CLAUSE_DEPEND_KIND (c) = kind;
+ {
+ OMP_CLAUSE_DEPEND_KIND (c) = kind;
+ if (iterators)
+ OMP_CLAUSE_DECL (c)
+ = build_tree_list (iterators, OMP_CLAUSE_DECL (c));
+ }
}
return nlist;
invalid_kind:
cp_parser_error (parser, "invalid depend kind");
resync_fail:
+ if (iterators)
+ poplevel (0, 1, 0);
cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
/*or_comma=*/false,
/*consume_paren=*/true);
--- gcc/cp/semantics.c.jj 2018-06-05 13:55:00.982594192 +0200
+++ gcc/cp/semantics.c 2018-06-13 19:25:03.003926735 +0200
@@ -4851,7 +4851,13 @@ handle_omp_array_sections (tree c, enum
bool maybe_zero_len = false;
unsigned int first_non_one = 0;
auto_vec<tree, 10> types;
- tree first = handle_omp_array_sections_1 (c, OMP_CLAUSE_DECL (c), types,
+ tree *tp = &OMP_CLAUSE_DECL (c);
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
+ && TREE_CODE (*tp) == TREE_LIST
+ && TREE_PURPOSE (*tp)
+ && TREE_CODE (TREE_PURPOSE (*tp)) == TREE_VEC)
+ tp = &TREE_VALUE (*tp);
+ tree first = handle_omp_array_sections_1 (c, *tp, types,
maybe_zero_len, first_non_one,
ort);
if (first == error_mark_node)
@@ -4860,7 +4866,7 @@ handle_omp_array_sections (tree c, enum
return false;
if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
{
- tree t = OMP_CLAUSE_DECL (c);
+ tree t = *tp;
tree tem = NULL_TREE;
if (processing_template_decl)
return false;
@@ -4880,7 +4886,7 @@ handle_omp_array_sections (tree c, enum
}
if (tem)
first = build2 (COMPOUND_EXPR, TREE_TYPE (first), tem, first);
- OMP_CLAUSE_DECL (c) = first;
+ *tp = first;
}
else
{
@@ -5842,6 +5848,125 @@ cp_finish_omp_clause_depend_sink (tree s
return false;
}
+/* Finish OpenMP iterators ITER. Return true if they are errorneous
+ and clauses containing them should be removed. */
+
+static bool
+cp_omp_finish_iterators (tree iter)
+{
+ bool ret = false;
+ for (tree it = iter; it; it = TREE_CHAIN (it))
+ {
+ tree var = TREE_VEC_ELT (it, 0);
+ tree begin = TREE_VEC_ELT (it, 1);
+ tree end = TREE_VEC_ELT (it, 2);
+ tree step = TREE_VEC_ELT (it, 3);
+ tree type = TREE_TYPE (var);
+ location_t loc = DECL_SOURCE_LOCATION (var);
+ if (type == error_mark_node)
+ {
+ ret = true;
+ continue;
+ }
+ if (type_dependent_expression_p (var))
+ continue;
+ if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
+ {
+ error_at (loc, "iterator %qD has neither integral nor pointer type",
+ var);
+ ret = true;
+ continue;
+ }
+ else if (TYPE_READONLY (type))
+ {
+ error_at (loc, "iterator %qD has const qualified type", var);
+ ret = true;
+ continue;
+ }
+
+ begin = mark_rvalue_use (begin);
+ end = mark_rvalue_use (end);
+ step = mark_rvalue_use (step);
+ begin = cp_build_c_cast (type, begin, tf_warning_or_error);
+ end = cp_build_c_cast (type, end, tf_warning_or_error);
+ tree stype = POINTER_TYPE_P (type) ? sizetype : type;
+ step = cp_build_c_cast (stype, step, tf_warning_or_error);
+ if (POINTER_TYPE_P (type) && !processing_template_decl)
+ {
+ begin = save_expr (begin);
+ step = pointer_int_sum (loc, PLUS_EXPR, begin, step);
+ step = fold_build2_loc (loc, MINUS_EXPR, sizetype,
+ fold_convert (sizetype, step),
+ fold_convert (sizetype, begin));
+ step = fold_convert (ssizetype, step);
+ }
+ if (!processing_template_decl)
+ {
+ begin = maybe_constant_value (begin);
+ end = maybe_constant_value (end);
+ step = maybe_constant_value (step);
+ }
+ if (integer_zerop (step))
+ {
+ error_at (loc, "iterator %qD has zero step", var);
+ ret = true;
+ continue;
+ }
+
+ if (begin == error_mark_node
+ || end == error_mark_node
+ || step == error_mark_node)
+ {
+ ret = true;
+ continue;
+ }
+
+ if (!processing_template_decl)
+ {
+ begin = fold_build_cleanup_point_expr (TREE_TYPE (begin), begin);
+ end = fold_build_cleanup_point_expr (TREE_TYPE (end), end);
+ step = fold_build_cleanup_point_expr (TREE_TYPE (step), step);
+ }
+ hash_set<tree> pset;
+ tree it2;
+ for (it2 = TREE_CHAIN (it); it2; it2 = TREE_CHAIN (it2))
+ {
+ tree var2 = TREE_VEC_ELT (it2, 0);
+ tree begin2 = TREE_VEC_ELT (it2, 1);
+ tree end2 = TREE_VEC_ELT (it2, 2);
+ tree step2 = TREE_VEC_ELT (it2, 3);
+ location_t loc2 = DECL_SOURCE_LOCATION (var2);
+ if (cp_walk_tree (&begin2, find_omp_placeholder_r, var, &pset))
+ {
+ error_at (EXPR_LOC_OR_LOC (begin2, loc2),
+ "begin expression refers to outer iterator %qD", var);
+ break;
+ }
+ else if (cp_walk_tree (&end2, find_omp_placeholder_r, var, &pset))
+ {
+ error_at (EXPR_LOC_OR_LOC (end2, loc2),
+ "end expression refers to outer iterator %qD", var);
+ break;
+ }
+ else if (cp_walk_tree (&step2, find_omp_placeholder_r, var, &pset))
+ {
+ error_at (EXPR_LOC_OR_LOC (step2, loc2),
+ "step expression refers to outer iterator %qD", var);
+ break;
+ }
+ }
+ if (it2)
+ {
+ ret = true;
+ continue;
+ }
+ TREE_VEC_ELT (it, 1) = begin;
+ TREE_VEC_ELT (it, 2) = end;
+ TREE_VEC_ELT (it, 3) = step;
+ }
+ return ret;
+}
+
/* For all elements of CLAUSES, validate them vs OpenMP constraints.
Remove any elements from the list that are invalid. */
@@ -5856,6 +5981,8 @@ finish_omp_clauses (tree clauses, enum c
bool copyprivate_seen = false;
bool ordered_seen = false;
bool oacc_async = false;
+ tree last_iterators = NULL_TREE;
+ bool last_iterators_remove = false;
bitmap_obstack_initialize (NULL);
bitmap_initialize (&generic_head, &bitmap_default_obstack);
@@ -6565,7 +6692,7 @@ finish_omp_clauses (tree clauses, enum c
else
{
t = mark_rvalue_use (t);
- if (!processing_template_decl)
+ if (!processing_template_decl)
t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (c) = t;
}
@@ -6642,6 +6769,8 @@ finish_omp_clauses (tree clauses, enum c
"be positive constant integer expression");
remove = true;
}
+ else
+ t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
}
OMP_CLAUSE_ALIGNED_ALIGNMENT (c) = t;
}
@@ -6688,6 +6817,21 @@ finish_omp_clauses (tree clauses, enum c
remove = true;
break;
}
+ if (TREE_CODE (t) == TREE_LIST
+ && TREE_PURPOSE (t)
+ && TREE_CODE (TREE_PURPOSE (t)) == TREE_VEC)
+ {
+ if (TREE_PURPOSE (t) != last_iterators)
+ last_iterators_remove
+ = cp_omp_finish_iterators (TREE_PURPOSE (t));
+ last_iterators = TREE_PURPOSE (t);
+ t = TREE_VALUE (t);
+ if (last_iterators_remove)
+ t = error_mark_node;
+ }
+ else
+ last_iterators = NULL_TREE;
+
if (TREE_CODE (t) == TREE_LIST)
{
if (handle_omp_array_sections (c, ort))
@@ -6703,7 +6847,7 @@ finish_omp_clauses (tree clauses, enum c
" clauses");
remove = true;
}
- else if (processing_template_decl && TREE_CODE (t) != OVERLOAD)
+ else if (processing_template_decl && TREE_CODE (t) != OVERLOAD)
break;
else if (!lvalue_p (t))
{
--- gcc/cp/pt.c.jj 2018-06-04 18:17:53.478531126 +0200
+++ gcc/cp/pt.c 2018-06-13 17:33:22.060761294 +0200
@@ -15941,11 +15941,49 @@ tsubst_copy (tree t, tree args, tsubst_f
static tree
tsubst_omp_clause_decl (tree decl, tree args, tsubst_flags_t complain,
- tree in_decl)
+ tree in_decl, tree *iterator_cache)
{
if (decl == NULL_TREE)
return NULL_TREE;
+ /* Handle OpenMP iterators. */
+ if (TREE_CODE (decl) == TREE_LIST
+ && TREE_PURPOSE (decl)
+ && TREE_CODE (TREE_PURPOSE (decl)) == TREE_VEC)
+ {
+ tree ret;
+ if (iterator_cache[0] == TREE_PURPOSE (decl))
+ ret = iterator_cache[1];
+ else
+ {
+ tree *tp = &ret;
+ begin_scope (sk_omp, NULL);
+ for (tree it = TREE_PURPOSE (decl); it; it = TREE_CHAIN (it))
+ {
+ *tp = copy_node (it);
+ TREE_VEC_ELT (*tp, 0)
+ = tsubst_decl (TREE_VEC_ELT (it, 0), args, complain);
+ TREE_VEC_ELT (*tp, 1)
+ = tsubst_expr (TREE_VEC_ELT (it, 1), args, complain, in_decl,
+ /*integral_constant_expression_p=*/false);
+ TREE_VEC_ELT (*tp, 2)
+ = tsubst_expr (TREE_VEC_ELT (it, 2), args, complain, in_decl,
+ /*integral_constant_expression_p=*/false);
+ TREE_VEC_ELT (*tp, 3)
+ = tsubst_expr (TREE_VEC_ELT (it, 3), args, complain, in_decl,
+ /*integral_constant_expression_p=*/false);
+ TREE_CHAIN (*tp) = NULL_TREE;
+ tp = &TREE_CHAIN (*tp);
+ }
+ TREE_VEC_ELT (ret, 4) = poplevel (1, 1, 0);
+ iterator_cache[0] = TREE_PURPOSE (decl);
+ iterator_cache[1] = ret;
+ }
+ return build_tree_list (ret, tsubst_omp_clause_decl (TREE_VALUE (decl),
+ args, complain,
+ in_decl, NULL));
+ }
+
/* Handle an OpenMP array section represented as a TREE_LIST (or
OMP_CLAUSE_DEPEND_KIND). An OMP_CLAUSE_DEPEND (with a depend
kind of OMP_CLAUSE_DEPEND_SINK) can also be represented as a
@@ -15960,7 +15998,7 @@ tsubst_omp_clause_decl (tree decl, tree
tree length = tsubst_expr (TREE_VALUE (decl), args, complain, in_decl,
/*integral_constant_expression_p=*/false);
tree chain = tsubst_omp_clause_decl (TREE_CHAIN (decl), args, complain,
- in_decl);
+ in_decl, NULL);
if (TREE_PURPOSE (decl) == low_bound
&& TREE_VALUE (decl) == length
&& TREE_CHAIN (decl) == chain)
@@ -15988,6 +16026,7 @@ tsubst_omp_clauses (tree clauses, enum c
{
tree new_clauses = NULL_TREE, nc, oc;
tree linear_no_step = NULL_TREE;
+ tree iterator_cache[2] = { NULL_TREE, NULL_TREE };
for (oc = clauses; oc ; oc = OMP_CLAUSE_CHAIN (oc))
{
@@ -16022,7 +16061,7 @@ tsubst_omp_clauses (tree clauses, enum c
case OMP_CLAUSE_IS_DEVICE_PTR:
OMP_CLAUSE_DECL (nc)
= tsubst_omp_clause_decl (OMP_CLAUSE_DECL (oc), args, complain,
- in_decl);
+ in_decl, iterator_cache);
break;
case OMP_CLAUSE_TILE:
case OMP_CLAUSE_IF:
@@ -16070,13 +16109,13 @@ tsubst_omp_clauses (tree clauses, enum c
}
OMP_CLAUSE_DECL (nc)
= tsubst_omp_clause_decl (OMP_CLAUSE_DECL (oc), args, complain,
- in_decl);
+ in_decl, NULL);
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);
+ in_decl, NULL);
OMP_CLAUSE_OPERAND (nc, 1)
= tsubst_expr (OMP_CLAUSE_OPERAND (oc, 1), args, complain,
in_decl, /*integral_constant_expression_p=*/false);
@@ -16084,7 +16123,7 @@ tsubst_omp_clauses (tree clauses, enum c
case OMP_CLAUSE_LINEAR:
OMP_CLAUSE_DECL (nc)
= tsubst_omp_clause_decl (OMP_CLAUSE_DECL (oc), args, complain,
- in_decl);
+ in_decl, NULL);
if (OMP_CLAUSE_LINEAR_STEP (oc) == NULL_TREE)
{
gcc_assert (!linear_no_step);
@@ -16093,7 +16132,7 @@ tsubst_omp_clauses (tree clauses, enum c
else if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (oc))
OMP_CLAUSE_LINEAR_STEP (nc)
= tsubst_omp_clause_decl (OMP_CLAUSE_LINEAR_STEP (oc), args,
- complain, in_decl);
+ complain, in_decl, NULL);
else
OMP_CLAUSE_LINEAR_STEP (nc)
= tsubst_expr (OMP_CLAUSE_LINEAR_STEP (oc), args, complain,
--- gcc/testsuite/c-c++-common/gomp/depend-iterator-1.c.jj 2018-06-12 13:02:05.236081056 +0200
+++ gcc/testsuite/c-c++-common/gomp/depend-iterator-1.c 2018-06-12 13:35:30.116318942 +0200
@@ -0,0 +1,75 @@
+int arr[64], arr2[64];
+struct S { int a[4]; } k;
+short arr4[4];
+volatile int v;
+#define TEST_EQ(x,y) ({ int o[x == y ? 1 : -1]; 0; })
+
+void
+foo (unsigned char i, signed char j)
+{
+ #pragma omp task depend (iterator (j=6:2:-2) : out : \
+ arr[TEST_EQ (sizeof (j), sizeof (int)), \
+ TEST_EQ (sizeof (i), sizeof (unsigned char)), \
+ TEST_EQ (sizeof (k), sizeof (struct S)), j], \
+ arr2[TEST_EQ (((__typeof (j)) -1) < 0, 1), \
+ TEST_EQ (((__typeof (i)) -1) < 0, 0), \
+ TEST_EQ (((__typeof (k.a[0])) -1) < 0, 1), j]) \
+ depend(out: arr[0]) \
+ depend (iterator (long long i=__LONG_LONG_MAX__ - 4:__LONG_LONG_MAX__ - 2:2, \
+ unsigned short j=~0U-16:~0U-8:3, \
+ short *k=&arr4[1]:&arr4[2]:1) : in : \
+ arr[TEST_EQ (sizeof (i), sizeof (long long)), \
+ TEST_EQ (sizeof (j), sizeof (unsigned short)), \
+ TEST_EQ (sizeof (k), sizeof (short *)), \
+ TEST_EQ (sizeof (*k), sizeof (short)), i - __LONG_LONG_MAX__ + 4], \
+ arr2[TEST_EQ (((__typeof (i)) -1) < 0, 1), \
+ TEST_EQ (((__typeof (j)) -1) < 0, 0), \
+ TEST_EQ (((__typeof (*k)) -1) < 0, 1), j - (~0U-16)], \
+ arr2[k - &arr4[0]]) \
+ depend(in : k)
+ v++;
+}
+
+void
+bar (unsigned char i, signed char j)
+{
+ int m = j;
+ int n = j + 2;
+ #pragma omp task depend (iterator (j=6:2:m) : out : \
+ arr[TEST_EQ (sizeof (j), sizeof (int)), \
+ TEST_EQ (sizeof (i), sizeof (unsigned char)), \
+ TEST_EQ (sizeof (k), sizeof (struct S)), j], \
+ arr2[TEST_EQ (((__typeof (j)) -1) < 0, 1), \
+ TEST_EQ (((__typeof (i)) -1) < 0, 0), \
+ TEST_EQ (((__typeof (k.a[0])) -1) < 0, 1), j]) \
+ depend(out: arr[0]) \
+ depend (iterator (long long i=__LONG_LONG_MAX__ - 4 - n:__LONG_LONG_MAX__ - 2:2, \
+ unsigned short j=~0U-16:~0U-8-n:3, \
+ short *k=&arr4[1]:&arr4[n + 2]:1) : in : \
+ arr[TEST_EQ (sizeof (i), sizeof (long long)), \
+ TEST_EQ (sizeof (j), sizeof (unsigned short)), \
+ TEST_EQ (sizeof (k), sizeof (short *)), \
+ TEST_EQ (sizeof (*k), sizeof (short)), i - __LONG_LONG_MAX__ + 4], \
+ arr2[TEST_EQ (((__typeof (i)) -1) < 0, 1), \
+ TEST_EQ (((__typeof (j)) -1) < 0, 0), \
+ TEST_EQ (((__typeof (*k)) -1) < 0, 1), j - (~0U-16)], \
+ arr2[k - &arr4[0]:10]) \
+ depend(in : k)
+ v++;
+}
+
+void
+baz (void)
+{
+ #pragma omp parallel
+ #pragma omp master
+ {
+ #pragma omp task depend(iterator(unsigned long int k = 0 : 2) : inout : \
+ arr[TEST_EQ (sizeof (k), sizeof (unsigned long)), \
+ TEST_EQ (((__typeof (k)) -1) < 0, 0), k]) \
+ depend(iterator(signed char s = -3 : -12 : -1) : out : \
+ arr[TEST_EQ (sizeof (s), sizeof (signed char)), \
+ TEST_EQ (((__typeof (s)) -1) < 0, 1), s + 12])
+ v++;
+ }
+}
--- gcc/testsuite/c-c++-common/gomp/depend-iterator-2.c.jj 2018-06-12 14:29:21.653895079 +0200
+++ gcc/testsuite/c-c++-common/gomp/depend-iterator-2.c 2018-06-13 18:27:33.876741370 +0200
@@ -0,0 +1,91 @@
+int a, b[64];
+struct S { int c; } *d, *e;
+struct T;
+struct T *f, *g;
+int *h;
+
+void
+f1 (void)
+{
+ #pragma omp task depend (iterator : in : a) /* { dg-error "expected" } */
+ ;
+ #pragma omp task depend (iterator (for = 0 : 2) : in : a) /* { dg-error "expected" } */
+ ;
+ #pragma omp task depend (iterator (5 = 0 : 2) : in : a) /* { dg-error "expected" } */
+ ;
+ #pragma omp task depend (iterator (i : 0 : 2) : in : a) /* { dg-error "expected '='|name a type|expected" } */
+ ;
+ #pragma omp task depend (iterator (i = 0, 1 : 2) : in : a) /* { dg-error "expected" } */
+ ;
+ #pragma omp task depend (iterator (i = (0, 1) : 2) : in : a)
+ ;
+ #pragma omp task depend (iterator (i = 0 : 1 : 2 : 3) : in : a) /* { dg-error "expected '.'" } */
+ ;
+ #pragma omp task depend (iterator (i = 0 : 2, 3) : in : a) /* { dg-error "expected" } */
+ ;
+ #pragma omp task depend (iterator (i = 0 : 10 : 2, 3) : in : a) /* { dg-error "expected" } */
+ ;
+ #pragma omp task depend (iterator (i = 0:1), iterator (j = 0:1) : in : a) /* { dg-error "expected ':'|invalid depend kind" } */
+ ;
+ #pragma omp task depend (iterator (i = 0:1): iterator (j = 0:1) : in : a) /* { dg-error "invalid depend kind" } */
+ ;
+ #pragma omp task depend (iterator (i = 0:32) : in : b[i*2:2])
+ ;
+ #pragma omp task depend (iterator (struct S i = 0:1): in : a) /* { dg-error "iterator 'i' has neither integral nor pointer type" } */
+ ;
+ #pragma omp task depend (iterator (void i = 0:1) : in : a) /* { dg-error "iterator 'i' has neither integral nor pointer type" } */
+ ;
+ #pragma omp task depend (iterator (float f = 0.2:0.4) : in : a) /* { dg-error "iterator 'f' has neither integral nor pointer type" } */
+ ;
+ #pragma omp task depend (iterator (struct S *p = d:e:2) : in : a)
+ ;
+ #pragma omp task depend (iterator (struct T *p = f:g) : in : a) /* { dg-error "invalid use of" } */
+ ;
+ #pragma omp task depend (iterator (int i = 0:4, \
+ struct U { int (*p)[i + 2]; } *p = 0:2) : in : a) /* { dg-error "type of iterator 'p' refers to outer iterator 'i'" "" { target c } } */
+ ; /* { dg-error "types may not be defined in iterator type|not an integer constant" "" { target c++ } .-1 } */
+ #pragma omp task depend (iterator (i = 0:4, j = i:16) : in : a) /* { dg-error "begin expression refers to outer iterator 'i'" } */
+ ;
+ #pragma omp task depend (iterator (i = 0:4, j = 2:i:1) : in : a) /* { dg-error "end expression refers to outer iterator 'i'" } */
+ ;
+ #pragma omp task depend (iterator (i = 0:4, j = 2:8:i) : in : a) /* { dg-error "step expression refers to outer iterator 'i'" } */
+ ;
+ #pragma omp task depend (iterator (i = *d:2) : in : a) /* { dg-error "aggregate value used where an integer was expected" "" { target c } } */
+ ; /* { dg-error "invalid cast from type 'S' to type 'int'" "" { target c++ } .-1 } */
+ #pragma omp task depend (iterator (i = 2:*d:2) : in : a) /* { dg-error "aggregate value used where an integer was expected" "" { target c } } */
+ ; /* { dg-error "invalid cast from type 'S' to type 'int'" "" { target c++ } .-1 } */
+ #pragma omp task depend (iterator (i = 2:4:*d) : in : a) /* { dg-error "aggregate value used where an integer was expected" "" { target c } } */
+ ; /* { dg-error "invalid cast from type 'S' to type 'int'" "" { target c++ } .-1 } */
+ /* { dg-error "iterator 'i' has zero step" "" { target c } .-2 } */
+ #pragma omp task depend (iterator (i = 1.25:2.5:3.5) : in : a)
+ ;
+ #pragma omp task depend (iterator (int *p = 23 : h) : in : a)
+ ;
+ #pragma omp task depend (iterator (short i=1:3:0) : in : a) /* { dg-error "iterator 'i' has zero step" } */
+ ;
+ #pragma omp task depend (iterator (i = 1 : 3 : 3 - 3) : in : a) /* { dg-error "iterator 'i' has zero step" } */
+ ;
+ #pragma omp task depend (iterator (int *p = &b[6]:&b[9]:4 - 4) : in : a) /* { dg-error "iterator 'p' has zero step" } */
+ ;
+ #pragma omp task depend (iterator (const int i = 0 : 2) : in : a) /* { dg-error "const qualified" } */
+ ;
+ #pragma omp task depend (iterator (const long long unsigned i = 0 : 2) : in : a) /* { dg-error "const qualified" } */
+ ;
+#if !defined (__cplusplus) && __STDC_VERSION__ >= 201112L
+ #pragma omp task depend (iterator (_Atomic unsigned i = 0 : 2) : in : a) /* { dg-error "_Atomic" "" { target c } } */
+ ;
+#endif
+}
+
+void
+f2 (void)
+{
+ int i, j;
+ #pragma omp for ordered(2)
+ for (i = 0; i < 64; i++)
+ for (j = 0; j < 64; j++)
+ {
+ #pragma omp ordered depend (iterator (k=0:1) : sink: i - 1, j - 1) /* { dg-error "'iterator' modifier incompatible with 'sink'" } */
+ #pragma omp ordered depend (iterator (int l = 0:2:3) : source) /* { dg-error "'iterator' modifier incompatible with 'source'" } */
+ }
+}
--- gcc/testsuite/g++.dg/gomp/depend-iterator-1.C.jj 2018-06-13 18:29:02.828823024 +0200
+++ gcc/testsuite/g++.dg/gomp/depend-iterator-1.C 2018-06-13 18:36:35.959238977 +0200
@@ -0,0 +1,86 @@
+int arr[64], arr2[64];
+struct S { int a[4]; } k;
+short arr4[4];
+volatile int v;
+#define TEST_EQ(x,y) ({ int o[x == y ? 1 : -1]; 0; })
+
+template <typename T, typename U, typename V, typename W, int N>
+void
+foo (unsigned char i, signed char j)
+{
+ #pragma omp task depend (iterator (T j=6:N:-2) : out : \
+ arr[TEST_EQ (sizeof (j), sizeof (int)), \
+ TEST_EQ (sizeof (i), sizeof (unsigned char)), \
+ TEST_EQ (sizeof (k), sizeof (struct S)), j], \
+ arr2[TEST_EQ (((__typeof (j)) -1) < 0, 1), \
+ TEST_EQ (((__typeof (i)) -1) < 0, 0), \
+ TEST_EQ (((__typeof (k.a[0])) -1) < 0, 1), j]) \
+ depend(out: arr[0]) \
+ depend (iterator (U i=__LONG_LONG_MAX__ - 4:__LONG_LONG_MAX__ - N:N, \
+ V j=~0U-16:~0U-8:3, \
+ W *k=&arr4[1]:&arr4[2]:1) : in : \
+ arr[TEST_EQ (sizeof (i), sizeof (long long)), \
+ TEST_EQ (sizeof (j), sizeof (unsigned short)), \
+ TEST_EQ (sizeof (k), sizeof (short *)), \
+ TEST_EQ (sizeof (*k), sizeof (short)), i - __LONG_LONG_MAX__ + 4], \
+ arr2[TEST_EQ (((__typeof (i)) -1) < 0, 1), \
+ TEST_EQ (((__typeof (j)) -1) < 0, 0), \
+ TEST_EQ (((__typeof (*k)) -1) < 0, 1), j - (~0U-16)], \
+ arr2[k - &arr4[0]]) \
+ depend(in : k)
+ v++;
+}
+
+template <typename U, typename W, int N>
+void
+bar (unsigned char i, signed char j)
+{
+ int m = j;
+ int n = j + 2;
+ #pragma omp task depend (iterator (j=N:2:m) : out : \
+ arr[TEST_EQ (sizeof (j), sizeof (int)), \
+ TEST_EQ (sizeof (i), sizeof (unsigned char)), \
+ TEST_EQ (sizeof (k), sizeof (struct S)), j], \
+ arr2[TEST_EQ (((__typeof (j)) -1) < 0, 1), \
+ TEST_EQ (((__typeof (i)) -1) < 0, 0), \
+ TEST_EQ (((__typeof (k.a[0])) -1) < 0, 1), j]) \
+ depend(out: arr[0]) \
+ depend (iterator (U i=__LONG_LONG_MAX__ - 4 - n:__LONG_LONG_MAX__ - 2:2, \
+ unsigned short j=~0U-16:~0U-8-n:3, \
+ W k=&arr4[N-5]:&arr4[n + 2]:1) : in : \
+ arr[TEST_EQ (sizeof (i), sizeof (long long)), \
+ TEST_EQ (sizeof (j), sizeof (unsigned short)), \
+ TEST_EQ (sizeof (k), sizeof (short *)), \
+ TEST_EQ (sizeof (*k), sizeof (short)), i - __LONG_LONG_MAX__ + 4], \
+ arr2[TEST_EQ (((__typeof (i)) -1) < 0, 1), \
+ TEST_EQ (((__typeof (j)) -1) < 0, 0), \
+ TEST_EQ (((__typeof (*k)) -1) < 0, 1), j - (~0U-16)], \
+ arr2[k - &arr4[0]:10]) \
+ depend(in : k)
+ v++;
+}
+
+template <typename T, typename U, int N>
+void
+baz (void)
+{
+ #pragma omp parallel
+ #pragma omp master
+ {
+ #pragma omp task depend(iterator(T k = N : 2) : inout : \
+ arr[TEST_EQ (sizeof (k), sizeof (unsigned long)), \
+ TEST_EQ (((__typeof (k)) -1) < N, 0), k]) \
+ depend(iterator(U s = -3 : -12 : -1 + N) : out : \
+ arr[TEST_EQ (sizeof (s), sizeof (signed char)), \
+ TEST_EQ (((__typeof (s)) -1) < 0, 1), s + 12])
+ v++;
+ }
+}
+
+void
+test (void)
+{
+ foo <int, long long, unsigned short, short, 2> (0, 0);
+ bar <long long, short *, 6> (0, -2);
+ baz <unsigned long int, signed char, 0> ();
+}
--- gcc/testsuite/g++.dg/gomp/depend-iterator-2.C.jj 2018-06-13 18:59:57.212537261 +0200
+++ gcc/testsuite/g++.dg/gomp/depend-iterator-2.C 2018-06-13 19:15:06.993378812 +0200
@@ -0,0 +1,110 @@
+int a, b[64];
+struct S { int c; } *d, *e;
+struct T;
+struct T *f, *g;
+int *h;
+
+template <typename U, typename V, typename W, W N>
+void
+f1 ()
+{
+ #pragma omp task depend (iterator : in : a) // { dg-error "expected" }
+ ;
+ #pragma omp task depend (iterator (for = 0 : 2) : in : a) // { dg-error "expected" }
+ ;
+ #pragma omp task depend (iterator (5 = 0 : 2) : in : a) // { dg-error "expected" }
+ ;
+ #pragma omp task depend (iterator (i : N : 2) : in : a) // { dg-error "expected '='|name a type|expected" }
+ ;
+ #pragma omp task depend (iterator (i = 0, 1 : 2) : in : a) // { dg-error "expected" }
+ ;
+ #pragma omp task depend (iterator (i = (0, 1) : 2) : in : a)
+ ;
+ #pragma omp task depend (iterator (i = 0 : 1 : 2 : 3) : in : a) // { dg-error "expected '.'" }
+ ;
+ #pragma omp task depend (iterator (i = 0 : 2, 3) : in : a) // { dg-error "expected" }
+ ;
+ #pragma omp task depend (iterator (i = N : 10 : 2, 3) : in : a) // { dg-error "expected" }
+ ;
+ #pragma omp task depend (iterator (i = 0:1), iterator (j = 0:1) : in : a) // { dg-error "expected ':'|invalid depend kind" }
+ ;
+ #pragma omp task depend (iterator (i = 0:1): iterator (j = 0:1) : in : a) // { dg-error "invalid depend kind" }
+ ;
+ #pragma omp task depend (iterator (i = N:32) : in : b[i*2:2])
+ ;
+ #pragma omp task depend (iterator (void i = 0:1) : in : a) // { dg-error "iterator 'i' has neither integral nor pointer type" }
+ ;
+ #pragma omp task depend (iterator (U *p = d:e:2) : in : a)
+ ;
+ #pragma omp task depend (iterator (W i = N:4, \
+ struct U2 { W *p; } *p = 0:2) : in : a) // { dg-error "types may not be defined in iterator type" }
+ ;
+ #pragma omp task depend (iterator (i = 0:4, j = i:16) : in : a) // { dg-error "begin expression refers to outer iterator 'i'" }
+ ;
+ #pragma omp task depend (iterator (i = N:4, j = 2:i:1) : in : a) // { dg-error "end expression refers to outer iterator 'i'" }
+ ;
+ #pragma omp task depend (iterator (i = 0:4, j = 2:8:i) : in : a) // { dg-error "step expression refers to outer iterator 'i'" }
+ ;
+ #pragma omp task depend (iterator (i = 1.25:2.5:3.5) : in : a)
+ ;
+ #pragma omp task depend (iterator (W *p = 23 : h) : in : a)
+ ;
+ #pragma omp task depend (iterator (const int i = N : 2) : in : a) // { dg-error "const qualified" }
+ ;
+ #pragma omp task depend (iterator (const long long unsigned i = 0 : 2) : in : a) // { dg-error "const qualified" }
+ ;
+}
+
+template <typename W, int N>
+void
+f2 ()
+{
+ int i, j;
+ #pragma omp for ordered(2)
+ for (i = 0; i < 64; i++)
+ for (j = 0; j < 64; j++)
+ {
+ #pragma omp ordered depend (iterator (k=0:N) : sink: i - 1, j - 1) // { dg-error "'iterator' modifier incompatible with 'sink'" }
+ #pragma omp ordered depend (iterator (W l = 0:2:3) : source) // { dg-error "'iterator' modifier incompatible with 'source'" }
+ }
+}
+
+template <typename U, typename V, typename W, W N, typename X, typename Y>
+void
+f3 ()
+{
+ #pragma omp task depend (iterator (U i = 0:1): in : a) // { dg-error "iterator 'i' has neither integral nor pointer type" }
+ ;
+ #pragma omp task depend (iterator (V f = 0.2:0.4) : in : a) // { dg-error "iterator 'f' has neither integral nor pointer type" }
+ ;
+ #pragma omp task depend (iterator (struct T *p = f:g) : in : a) // { dg-error "invalid use of" }
+ ;
+ #pragma omp task depend (iterator (i = *d:2) : in : a) // { dg-error "invalid cast from type 'S' to type 'int'" }
+ ;
+ #pragma omp task depend (iterator (i = 2:*d:2) : in : a) // { dg-error "invalid cast from type 'S' to type 'int'" }
+ ;
+ #pragma omp task depend (iterator (i = 2:4:*d) : in : a) // { dg-error "invalid cast from type 'S' to type 'int'" }
+ ;
+ #pragma omp task depend (iterator (i = 1.25:2.5:3.5) : in : a)
+ ;
+ #pragma omp task depend (iterator (W *p = 23 : h) : in : a)
+ ;
+ #pragma omp task depend (iterator (short i=1:3:N) : in : a) // { dg-error "iterator 'i' has zero step" }
+ ;
+ #pragma omp task depend (iterator (i = 1 : 3 : N + 3 - 3) : in : a) // { dg-error "iterator 'i' has zero step" }
+ ;
+ #pragma omp task depend (iterator (int *p = &b[6]:&b[9]:4 - 4) : in : a) // { dg-error "iterator 'p' has zero step" }
+ ;
+ #pragma omp task depend (iterator (X i = N : 2) : in : a) // { dg-error "const qualified" }
+ ;
+ #pragma omp task depend (iterator (Y i = 0 : 2) : in : a) // { dg-error "const qualified" }
+ ;
+}
+
+void
+f4 ()
+{
+ f1 <struct S, float, int, 0> ();
+ f2 <int, 1> ();
+ f3 <struct S, float, int, 0, const int, const long long unsigned> ();
+}
--- libgomp/testsuite/libgomp.c-c++-common/depend-iterator-1.c.jj 2018-06-12 11:41:35.817715556 +0200
+++ libgomp/testsuite/libgomp.c-c++-common/depend-iterator-1.c 2018-06-12 14:39:09.759522148 +0200
@@ -0,0 +1,81 @@
+#ifdef __cplusplus
+extern "C"
+#endif
+void abort (void);
+int arr[64], arr2[64], arr3[64];
+
+int *
+foo (int x, int y, long z)
+{
+ int v;
+ switch (x)
+ {
+ case 1:
+ if (z != 0 || y < 0 || y >= 64)
+ abort ();
+ #pragma omp atomic capture
+ {
+ v = arr2[y];
+ arr2[y]++;
+ }
+ if (v != 0) abort ();
+ return &arr[y];
+ case 2:
+ if (y < 0 || y > 60 || (y & 3) || z < 0 || z >= 4)
+ abort ();
+ #pragma omp atomic
+ arr2[y + z] = arr2[y + z] + 2;
+ return &arr[y + z];
+ case 3:
+ if (z < 0 || z > 60 || (z & 3) || y < 0 || y >= 4)
+ abort ();
+ #pragma omp atomic
+ arr2[y + z] = arr2[y + z] + 4;
+ return &arr[y + z];
+ case 4:
+ if (y != 0 || z > 64 || z <= 0)
+ abort ();
+ #pragma omp atomic
+ arr2[z - 1] = arr2[z - 1] + 8;
+ return &arr[z - 1];
+ default:
+ abort ();
+ }
+}
+
+volatile int beg, end, step;
+
+int
+main ()
+{
+ int m;
+ beg = 60;
+ end = -4;
+ step = -4;
+ #pragma omp parallel
+ #pragma omp master
+ {
+ int i;
+ for (i = 0; i < 64; i++)
+ #pragma omp task depend (iterator (j=i:i+1) : out : foo (1, j, 0)[0])
+ arr[i] = i;
+ #pragma omp task depend (iterator (int k=beg:end:step,long int l=0:4:1) : inout : \
+ foo (2, k, l)[0], foo (3, l, k)[0]) private (i)
+ for (i = 0; i < 64; i++)
+ if (arr[i] != i)
+ abort ();
+ else
+ arr[i] = arr[i] + 1;
+ #pragma omp task depend (iterator (int *p=&arr3[64]:&arr3[0]:-1) : in : \
+ foo (4, 0, p - &arr3[0])[0]) depend (in : beg)
+ for (i = 0; i < 64; i++)
+ if (arr[i] != i + 1)
+ abort ();
+ else
+ arr[i] = arr[i] + 2;
+ }
+ for (m = 0; m < 64; m++)
+ if (arr[m] != m + 3 || arr2[m] != 15)
+ abort ();
+ return 0;
+}
--- libgomp/testsuite/libgomp.c++/depend-iterator-1.C.jj 2018-06-13 17:56:36.206038796 +0200
+++ libgomp/testsuite/libgomp.c++/depend-iterator-1.C 2018-06-13 18:07:09.183618914 +0200
@@ -0,0 +1,119 @@
+extern "C" void abort ();
+int arr[64], arr2[64], arr3[64];
+
+int *
+foo (int x, int y, long z)
+{
+ int v;
+ switch (x)
+ {
+ case 1:
+ if (z != 0 || y < 0 || y >= 64)
+ abort ();
+ #pragma omp atomic capture
+ {
+ v = arr2[y];
+ arr2[y]++;
+ }
+ if (v != 0) abort ();
+ return &arr[y];
+ case 2:
+ if (y < 0 || y > 60 || (y & 3) || z < 0 || z >= 4)
+ abort ();
+ #pragma omp atomic
+ arr2[y + z] = arr2[y + z] + 2;
+ return &arr[y + z];
+ case 3:
+ if (z < 0 || z > 60 || (z & 3) || y < 0 || y >= 4)
+ abort ();
+ #pragma omp atomic
+ arr2[y + z] = arr2[y + z] + 4;
+ return &arr[y + z];
+ case 4:
+ if (y != 0 || z > 64 || z <= 0)
+ abort ();
+ #pragma omp atomic
+ arr2[z - 1] = arr2[z - 1] + 8;
+ return &arr[z - 1];
+ default:
+ abort ();
+ }
+}
+
+volatile int beg, end, step;
+
+template <int N>
+void
+bar ()
+{
+ #pragma omp parallel
+ #pragma omp master
+ {
+ int i;
+ for (i = 0; i < 64; i++)
+ #pragma omp task depend (iterator (j=i:i+1) : out : foo (1, j, 0)[0])
+ arr[i] = i;
+ #pragma omp task depend (iterator (int k=beg:end:step,long int l=0:4:1) : inout : \
+ foo (2, k, l)[0], foo (3, l, k)[0]) private (i)
+ for (i = 0; i < 64; i++)
+ if (arr[i] != i)
+ abort ();
+ else
+ arr[i] = arr[i] + 1;
+ #pragma omp task depend (iterator (int *p=&arr3[64]:&arr3[0]:-1) : in : \
+ foo (4, 0, p - &arr3[0])[0]) depend (in : beg)
+ for (i = 0; i < 64; i++)
+ if (arr[i] != i + 1)
+ abort ();
+ else
+ arr[i] = arr[i] + 2;
+ }
+}
+
+template <typename A, typename B, typename C>
+void
+baz (A beg, A end, A step)
+{
+ #pragma omp parallel
+ #pragma omp master
+ {
+ int i;
+ for (i = 0; i < 64; i++)
+ #pragma omp task depend (iterator (A j=i:i+1) : out : foo (1, j, 0)[0])
+ arr[i] = i;
+ #pragma omp task depend (iterator (A k=beg:end:step,B l=0:4:1) : inout : \
+ foo (2, k, l)[0], foo (3, l, k)[0]) private (i)
+ for (i = 0; i < 64; i++)
+ if (arr[i] != i)
+ abort ();
+ else
+ arr[i] = arr[i] + 1;
+ #pragma omp task depend (iterator (C p=&arr3[64]:&arr3[0]:-1) : in : \
+ foo (4, 0, p - &arr3[0])[0]) depend (in : beg)
+ for (i = 0; i < 64; i++)
+ if (arr[i] != i + 1)
+ abort ();
+ else
+ arr[i] = arr[i] + 2;
+ }
+}
+
+int
+main ()
+{
+ int m;
+ beg = 60;
+ end = -4;
+ step = -4;
+ bar<0> ();
+ for (m = 0; m < 64; m++)
+ if (arr[m] != m + 3 || arr2[m] != 15)
+ abort ();
+ else
+ arr[m] = arr2[m] = 0;
+ baz<int, long int, int *> (beg, end, step);
+ for (m = 0; m < 64; m++)
+ if (arr[m] != m + 3 || arr2[m] != 15)
+ abort ();
+ return 0;
+}
Jakub