Hi! This patch parses array sections in map/to/from/depend clauses and provides diagnostics (+ testcases for that) for it. Depend clause right now is just ignored during omp lowering, and for map/to/from clause we would ICE during omp expansion, which isn't done yet, but as the testcases test errorneous code we don't go that far right now and bail out earlier. For depend clause with array sections it just affects what address is kept in the clause afterwards, for map/to/from there is OMP_CLAUSE_SIZE which says how many bytes are to be allocated and sometimes also copied.
Does this look reasonable? 2013-06-03 Jakub Jelinek <ja...@redhat.com> * gimplify.c (gimplify_scan_omp_clauses): Handle array sections on OMP_CLAUSE_{MAP,TO,FROM} clauses, handle OMP_CLAUSE_DEPEND clause. (gimplify_adjust_omp_clauses): Handle array sections on OMP_CLAUSE_MAP, handle OMP_CLAUSE_DEPEND clause. * tree.c (omp_clause_num_ops): OMP_CLAUSE_{MAP,TO,FROM} now have 2 arguments, move OMP_CLAUSE_UNIFORM before these 3. (omp_clause_code_name): Adjust for OMP_CLAUSE_UNIFORM movement. (walk_tree_1): Adjust to handle 2 arguments of OMP_CLAUSE_{MAP,TO,FROM}. * tree-pretty-print.c (dump_omp_clause): For OMP_CLAUSE_{MAP,TO,FROM} print OMP_CLAUSE_SIZE, and for OMP_CLAUSE_MAP handle OMP_CLAUSE_MAP_POINTER. * tree.h (enum omp_clause_code): Move OMP_CLAUSE_UNIFORM before OMP_CLAUSE_{MAP,TO,FROM}. (OMP_CLAUSE_SIZE): Define. (enum omp_clause_map_kind): Add OMP_CLAUSE_MAP_POINTER. * omp-low.c (scan_sharing_clauses): Handle OMP_CLAUSE_DEPEND. cp/ * semantics.c (handle_omp_array_sections_1, handle_omp_array_sections): New functions. (finish_omp_clauses): Handle array sections on OMP_CLAUSE_{MAP,TO,FROM,DEPEND}. If not array sections, mark the decl addressable. * parser.c (cp_parser_omp_var_list_no_open): Parse array sections on OMP_CLAUSE_{MAP,TO,FROM,DEPEND} clauses. testsuite/ * g++.dg/gomp/depend-1.C: New test. * g++.dg/gomp/depend-2.C: New test. * c-c++-common/gomp/depend-1.c: New test. * c-c++-common/gomp/depend-2.c: New test. * c-c++-common/gomp/map-1.c: New test. --- gcc/gimplify.c.jj 2013-05-29 10:05:42.000000000 +0200 +++ gcc/gimplify.c 2013-06-03 15:37:14.653703574 +0200 @@ -6258,19 +6258,78 @@ gimplify_scan_omp_clauses (tree *list_p, } flags = GOVD_LINEAR | GOVD_EXPLICIT; goto do_add; + case OMP_CLAUSE_MAP: + if (OMP_CLAUSE_SIZE (c) + && gimplify_expr (&OMP_CLAUSE_SIZE (c), pre_p, + NULL, is_gimple_val, fb_rvalue) == GS_ERROR) + { + remove = true; + break; + } + decl = OMP_CLAUSE_DECL (c); + if (!DECL_P (decl)) + { + if (gimplify_expr (&OMP_CLAUSE_DECL (c), pre_p, + NULL, is_gimple_lvalue, fb_lvalue) + == GS_ERROR) + { + remove = true; + break; + } + break; + } flags = GOVD_MAP | GOVD_EXPLICIT; notice_outer = false; goto do_add; + case OMP_CLAUSE_DEPEND: + 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))) + { + remove = true; + break; + } + 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) + { + remove = true; + break; + } + break; + case OMP_CLAUSE_TO: case OMP_CLAUSE_FROM: + if (OMP_CLAUSE_SIZE (c) + && gimplify_expr (&OMP_CLAUSE_SIZE (c), pre_p, + NULL, is_gimple_val, fb_rvalue) == GS_ERROR) + { + remove = true; + break; + } decl = OMP_CLAUSE_DECL (c); if (error_operand_p (decl)) { remove = true; break; } + if (!DECL_P (decl)) + { + if (gimplify_expr (&OMP_CLAUSE_DECL (c), pre_p, + NULL, is_gimple_lvalue, fb_lvalue) + == GS_ERROR) + { + remove = true; + break; + } + break; + } goto do_notice; do_add: @@ -6621,8 +6680,9 @@ gimplify_adjust_omp_clauses (tree *list_ case OMP_CLAUSE_MAP: decl = OMP_CLAUSE_DECL (c); + if (!DECL_P (decl)) + break; n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl); - remove = false; if (ctx->region_type == ORT_TARGET && !(n->value & GOVD_SEEN)) remove = true; else @@ -6672,6 +6732,7 @@ gimplify_adjust_omp_clauses (tree *list_ case OMP_CLAUSE_SAFELEN: case OMP_CLAUSE_TO: case OMP_CLAUSE_FROM: + case OMP_CLAUSE_DEPEND: break; default: --- gcc/tree.c.jj 2013-05-29 10:04:14.411807856 +0200 +++ gcc/tree.c 2013-05-29 10:52:43.042408309 +0200 @@ -238,10 +238,10 @@ unsigned const char omp_clause_num_ops[] 2, /* OMP_CLAUSE_LINEAR */ 2, /* OMP_CLAUSE_ALIGNED */ 1, /* OMP_CLAUSE_DEPEND */ - 1, /* OMP_CLAUSE_FROM */ - 1, /* OMP_CLAUSE_TO */ 1, /* OMP_CLAUSE_UNIFORM */ - 1, /* OMP_CLAUSE_MAP */ + 2, /* OMP_CLAUSE_FROM */ + 2, /* OMP_CLAUSE_TO */ + 2, /* OMP_CLAUSE_MAP */ 1, /* OMP_CLAUSE_IF */ 1, /* OMP_CLAUSE_NUM_THREADS */ 1, /* OMP_CLAUSE_SCHEDULE */ @@ -279,9 +279,9 @@ const char * const omp_clause_code_name[ "linear", "aligned", "depend", + "uniform", "from", "to", - "uniform", "map", "if", "num_threads", @@ -11011,11 +11011,8 @@ walk_tree_1 (tree *tp, walk_tree_fn func case OMP_CLAUSE_IF: case OMP_CLAUSE_NUM_THREADS: case OMP_CLAUSE_SCHEDULE: - case OMP_CLAUSE_FROM: - case OMP_CLAUSE_TO: case OMP_CLAUSE_UNIFORM: case OMP_CLAUSE_DEPEND: - case OMP_CLAUSE_MAP: case OMP_CLAUSE_NUM_TEAMS: case OMP_CLAUSE_DEVICE: case OMP_CLAUSE_DIST_SCHEDULE: @@ -11053,6 +11050,9 @@ walk_tree_1 (tree *tp, walk_tree_fn func case OMP_CLAUSE_ALIGNED: case OMP_CLAUSE_LINEAR: + case OMP_CLAUSE_FROM: + case OMP_CLAUSE_TO: + case OMP_CLAUSE_MAP: WALK_SUBTREE (OMP_CLAUSE_DECL (*tp)); WALK_SUBTREE (OMP_CLAUSE_OPERAND (*tp, 1)); WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp)); --- gcc/tree-pretty-print.c.jj 2013-05-29 10:04:14.380808033 +0200 +++ gcc/tree-pretty-print.c 2013-06-03 15:15:44.518894511 +0200 @@ -314,12 +314,6 @@ dump_omp_clause (pretty_printer *buffer, case OMP_CLAUSE_COPYPRIVATE: name = "copyprivate"; goto print_remap; - case OMP_CLAUSE_FROM: - name = "from"; - goto print_remap; - case OMP_CLAUSE_TO: - name = "to"; - goto print_remap; case OMP_CLAUSE_UNIFORM: name = "uniform"; goto print_remap; @@ -488,6 +482,7 @@ dump_omp_clause (pretty_printer *buffer, switch (OMP_CLAUSE_MAP_KIND (clause)) { case OMP_CLAUSE_MAP_ALLOC: + case OMP_CLAUSE_MAP_POINTER: pp_string (buffer, "alloc"); break; case OMP_CLAUSE_MAP_TO: @@ -505,9 +500,32 @@ dump_omp_clause (pretty_printer *buffer, pp_character (buffer, ':'); dump_generic_node (buffer, OMP_CLAUSE_DECL (clause), spc, flags, false); + print_clause_size: + if (OMP_CLAUSE_SIZE (clause)) + { + if (OMP_CLAUSE_MAP_KIND (clause) == OMP_CLAUSE_MAP_POINTER) + pp_string (buffer, " [pointer assign, bias: "); + else + pp_string (buffer, " [len: "); + dump_generic_node (buffer, OMP_CLAUSE_SIZE (clause), + spc, flags, false); + pp_character (buffer, ']'); + } pp_character (buffer, ')'); break; + case OMP_CLAUSE_FROM: + pp_string (buffer, "from("); + dump_generic_node (buffer, OMP_CLAUSE_DECL (clause), + spc, flags, false); + goto print_clause_size; + + case OMP_CLAUSE_TO: + pp_string (buffer, "to("); + dump_generic_node (buffer, OMP_CLAUSE_DECL (clause), + spc, flags, false); + goto print_clause_size; + case OMP_CLAUSE_NUM_TEAMS: pp_string (buffer, "num_teams("); dump_generic_node (buffer, OMP_CLAUSE_NUM_TEAMS_EXPR (clause), --- gcc/tree.h.jj 2013-05-29 10:04:14.443807673 +0200 +++ gcc/tree.h 2013-06-03 13:09:02.081260394 +0200 @@ -374,15 +374,15 @@ enum omp_clause_code /* OpenMP clause: depend ({in,out,inout}:variable-list). */ OMP_CLAUSE_DEPEND, + /* OpenMP clause: uniform (argument-list). */ + OMP_CLAUSE_UNIFORM, + /* OpenMP clause: from (variable-list). */ OMP_CLAUSE_FROM, /* OpenMP clause: to (variable-list). */ OMP_CLAUSE_TO, - /* OpenMP clause: uniform (argument-list). */ - OMP_CLAUSE_UNIFORM, - /* OpenMP clause: map ({alloc:,to:,from:,tofrom:,}variable-list). */ OMP_CLAUSE_MAP, @@ -1877,6 +1877,11 @@ extern void protected_set_expr_location #define OMP_TARGET_UPDATE_CLAUSES(NODE)\ TREE_OPERAND (OMP_TARGET_UPDATE_CHECK (NODE), 0) +#define OMP_CLAUSE_SIZE(NODE) \ + OMP_CLAUSE_OPERAND (OMP_CLAUSE_RANGE_CHECK (OMP_CLAUSE_CHECK (NODE), \ + OMP_CLAUSE_FROM, \ + OMP_CLAUSE_MAP), 1) + #define OMP_CLAUSE_CHAIN(NODE) TREE_CHAIN (OMP_CLAUSE_CHECK (NODE)) #define OMP_CLAUSE_DECL(NODE) \ OMP_CLAUSE_OPERAND (OMP_CLAUSE_RANGE_CHECK (OMP_CLAUSE_CHECK (NODE), \ @@ -2025,7 +2030,11 @@ enum omp_clause_map_kind OMP_CLAUSE_MAP_ALLOC, OMP_CLAUSE_MAP_TO, OMP_CLAUSE_MAP_FROM, - OMP_CLAUSE_MAP_TOFROM + OMP_CLAUSE_MAP_TOFROM, + /* This following is an internal only map kind, used for pointer based array + sections. OMP_CLAUSE_SIZE for these is not the pointer size, which is + implicitly POINTER_SIZE / BITS_PER_UNIT, but the bias. */ + OMP_CLAUSE_MAP_POINTER }; #define OMP_CLAUSE_MAP_KIND(NODE) \ --- gcc/omp-low.c.jj 2013-05-29 10:07:14.000000000 +0200 +++ gcc/omp-low.c 2013-05-31 11:32:28.929543246 +0200 @@ -1492,6 +1492,7 @@ scan_sharing_clauses (tree clauses, omp_ case OMP_CLAUSE_NUM_THREADS: case OMP_CLAUSE_SCHEDULE: case OMP_CLAUSE_DIST_SCHEDULE: + case OMP_CLAUSE_DEPEND: if (ctx->outer) scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer); break; @@ -1567,6 +1568,7 @@ scan_sharing_clauses (tree clauses, omp_ case OMP_CLAUSE_PROC_BIND: case OMP_CLAUSE_SAFELEN: case OMP_CLAUSE_ALIGNED: + case OMP_CLAUSE_DEPEND: break; default: --- gcc/cp/semantics.c.jj 2013-05-20 13:21:26.000000000 +0200 +++ gcc/cp/semantics.c 2013-06-03 14:50:41.253417382 +0200 @@ -4068,6 +4068,458 @@ cxx_omp_create_clause_info (tree c, tree return errorcount != save_errorcount; } +/* Helper function for handle_omp_array_sections. Called recursively + to handle multiple array-section-subscripts. C is the clause, + T current expression (initially OMP_CLAUSE_DECL), which is either + a TREE_LIST for array-section-subscript (TREE_PURPOSE is low-bound + expression if specified, TREE_VALUE length expression if specified, + TREE_CHAIN is what it has been specified after, or some decl. + TYPES vector is populated with array section types, MAYBE_ZERO_LEN + set to true if any of the array-section-subscript could have length + of zero (explicit or implicit), FIRST_NON_ONE is the index of the + first array-section-subscript which is known not to have length + of one. Given say: + map(a[:b][2:1][:c][:2][:d][e:f][2:5]) + FIRST_NON_ONE will be 3, array-section-subscript [:b], [2:1] and [:c] + all are or may have length of 1, array-section-subscript [:2] is the + first one knonwn not to have length 1. For array-section-subscript + <= FIRST_NON_ONE we diagnose non-contiguous arrays if low bound isn't + 0 or length isn't the array domain max + 1, for > FIRST_NON_ONE we + can if MAYBE_ZERO_LEN is false. MAYBE_ZERO_LEN will be true in the above + case though, as some lengths could be zero. */ + +static tree +handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types, + bool &maybe_zero_len, unsigned int &first_non_one, + bool &pointer_based_p) +{ + tree ret, low_bound, length, type; + if (TREE_CODE (t) != TREE_LIST) + { + if (error_operand_p (t)) + return error_mark_node; + if (type_dependent_expression_p (t)) + return NULL_TREE; + if (TREE_CODE (t) != VAR_DECL && TREE_CODE (t) != PARM_DECL) + { + if (processing_template_decl) + return NULL_TREE; + if (DECL_P (t)) + error_at (OMP_CLAUSE_LOCATION (c), + "%qD is not a variable in %qs clause", t, + omp_clause_code_name[OMP_CLAUSE_CODE (c)]); + else + error_at (OMP_CLAUSE_LOCATION (c), + "%qE is not a variable in %qs clause", t, + omp_clause_code_name[OMP_CLAUSE_CODE (c)]); + return error_mark_node; + } + else if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND + && TREE_CODE (t) == VAR_DECL && DECL_THREAD_LOCAL_P (t)) + { + error_at (OMP_CLAUSE_LOCATION (c), + "%qD is threadprivate variable in %qs clause", t, + omp_clause_code_name[OMP_CLAUSE_CODE (c)]); + return error_mark_node; + } + if (!processing_template_decl + && POINTER_TYPE_P (TREE_TYPE (t)) + && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP) + pointer_based_p = true; + t = convert_from_reference (t); + return t; + } + + ret = handle_omp_array_sections_1 (c, TREE_CHAIN (t), types, + maybe_zero_len, first_non_one, + pointer_based_p); + if (ret == error_mark_node || ret == NULL_TREE) + return ret; + + type = TREE_TYPE (ret); + low_bound = TREE_PURPOSE (t); + length = TREE_VALUE (t); + if ((low_bound && type_dependent_expression_p (low_bound)) + || (length && type_dependent_expression_p (length))) + return NULL_TREE; + + if (low_bound == error_mark_node || length == error_mark_node) + return error_mark_node; + + if (low_bound && !INTEGRAL_TYPE_P (TREE_TYPE (low_bound))) + { + error_at (OMP_CLAUSE_LOCATION (c), + "low bound %qE of array section does not have integral type", + low_bound); + return error_mark_node; + } + if (length && !INTEGRAL_TYPE_P (TREE_TYPE (length))) + { + error_at (OMP_CLAUSE_LOCATION (c), + "length %qE of array section does not have integral type", + length); + return error_mark_node; + } + if (low_bound + && TREE_CODE (low_bound) == INTEGER_CST + && TYPE_PRECISION (TREE_TYPE (low_bound)) + > TYPE_PRECISION (sizetype)) + low_bound = fold_convert (sizetype, low_bound); + if (length + && TREE_CODE (length) == INTEGER_CST + && TYPE_PRECISION (TREE_TYPE (length)) + > TYPE_PRECISION (sizetype)) + length = fold_convert (sizetype, length); + if (low_bound == NULL_TREE) + low_bound = integer_zero_node; + + if (length != NULL_TREE) + { + if (!integer_nonzerop (length)) + maybe_zero_len = true; + if (first_non_one == types.length () + && (TREE_CODE (length) != INTEGER_CST || integer_onep (length))) + first_non_one++; + } + if (TREE_CODE (type) == ARRAY_TYPE) + { + if (length == NULL_TREE + && (TYPE_DOMAIN (type) == NULL_TREE + || TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == NULL_TREE)) + { + error_at (OMP_CLAUSE_LOCATION (c), + "for unknown bound array type length expression is " + "not optional"); + return error_mark_node; + } + if (TREE_CODE (low_bound) == INTEGER_CST + && tree_int_cst_sgn (low_bound) == -1) + { + error_at (OMP_CLAUSE_LOCATION (c), + "negative low bound in array section in %qs clause", + omp_clause_code_name[OMP_CLAUSE_CODE (c)]); + return error_mark_node; + } + if (length != NULL_TREE + && TREE_CODE (length) == INTEGER_CST + && tree_int_cst_sgn (length) == -1) + { + error_at (OMP_CLAUSE_LOCATION (c), + "negative length in array section in %qs clause", + omp_clause_code_name[OMP_CLAUSE_CODE (c)]); + return error_mark_node; + } + if (TYPE_DOMAIN (type) + && TYPE_MAX_VALUE (TYPE_DOMAIN (type)) + && TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) + == INTEGER_CST) + { + tree size = size_binop (PLUS_EXPR, + TYPE_MAX_VALUE (TYPE_DOMAIN (type)), + size_one_node); + if (TREE_CODE (low_bound) == INTEGER_CST) + { + if (tree_int_cst_lt (size, low_bound)) + { + error_at (OMP_CLAUSE_LOCATION (c), + "low bound %qE above array section size " + "in %qs clause", low_bound, + omp_clause_code_name[OMP_CLAUSE_CODE (c)]); + return error_mark_node; + } + if (tree_int_cst_equal (size, low_bound)) + maybe_zero_len = true; + else if (length == NULL_TREE + && first_non_one == types.length () + && tree_int_cst_equal + (TYPE_MAX_VALUE (TYPE_DOMAIN (type)), + low_bound)) + first_non_one++; + } + else if (length == NULL_TREE) + { + maybe_zero_len = true; + if (first_non_one == types.length ()) + first_non_one++; + } + if (length && TREE_CODE (length) == INTEGER_CST) + { + if (tree_int_cst_lt (size, length)) + { + error_at (OMP_CLAUSE_LOCATION (c), + "length %qE above array section size " + "in %qs clause", length, + omp_clause_code_name[OMP_CLAUSE_CODE (c)]); + return error_mark_node; + } + if (TREE_CODE (low_bound) == INTEGER_CST) + { + tree lbpluslen + = size_binop (PLUS_EXPR, + fold_convert (sizetype, low_bound), + fold_convert (sizetype, length)); + if (TREE_CODE (lbpluslen) == INTEGER_CST + && tree_int_cst_lt (size, lbpluslen)) + { + error_at (OMP_CLAUSE_LOCATION (c), + "high bound %qE above array section size " + "in %qs clause", lbpluslen, + omp_clause_code_name[OMP_CLAUSE_CODE (c)]); + return error_mark_node; + } + } + } + } + else if (length == NULL_TREE) + { + maybe_zero_len = true; + if (first_non_one == types.length ()) + first_non_one++; + } + + /* For [lb:] we will need to evaluate lb more than once. */ + if (length == NULL_TREE && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND) + { + tree lb = cp_save_expr (low_bound); + if (lb != low_bound) + { + TREE_PURPOSE (t) = lb; + low_bound = lb; + } + } + } + else if (TREE_CODE (type) == POINTER_TYPE) + { + if (length == NULL_TREE) + { + error_at (OMP_CLAUSE_LOCATION (c), + "for pointer type length expression is not optional"); + return error_mark_node; + } + /* If there is a pointer type anywhere but in the very first + array-section-subscript, the array section can't be contiguous. */ + if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND + && TREE_CODE (TREE_CHAIN (t)) == TREE_LIST) + { + error_at (OMP_CLAUSE_LOCATION (c), + "array section is not contiguous in %qs clause", + omp_clause_code_name[OMP_CLAUSE_CODE (c)]); + return error_mark_node; + } + } + else + { + error_at (OMP_CLAUSE_LOCATION (c), + "%qE does not have pointer or array type", ret); + return error_mark_node; + } + if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND) + types.safe_push (TREE_TYPE (ret)); + /* For pointer based array sections we will need to evaluate lb more + than once. */ + if (pointer_based_p) + { + tree lb = cp_save_expr (low_bound); + if (lb != low_bound) + { + TREE_PURPOSE (t) = lb; + low_bound = lb; + } + } + ret = grok_array_decl (OMP_CLAUSE_LOCATION (c), ret, low_bound, false); + return ret; +} + +/* Handle array sections for clause C. */ + +static bool +handle_omp_array_sections (tree c) +{ + bool maybe_zero_len = false; + bool pointer_based_p = false; + unsigned int first_non_one = 0; + vec<tree> types = vNULL; + tree first = handle_omp_array_sections_1 (c, OMP_CLAUSE_DECL (c), types, + maybe_zero_len, first_non_one, + pointer_based_p); + if (first == error_mark_node) + { + types.release (); + return true; + } + if (first == NULL_TREE) + { + types.release (); + return false; + } + if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND) + { + tree t = OMP_CLAUSE_DECL (c); + tree tem = NULL_TREE; + types.release (); + if (processing_template_decl) + return false; + /* Need to evaluate side effects in the length expressions + if any. */ + while (TREE_CODE (t) == TREE_LIST) + { + if (TREE_VALUE (t) && TREE_SIDE_EFFECTS (TREE_VALUE (t))) + { + if (tem == NULL_TREE) + tem = TREE_VALUE (t); + else + tem = build2 (COMPOUND_EXPR, TREE_TYPE (tem), + TREE_VALUE (t), tem); + } + t = TREE_CHAIN (t); + } + if (tem) + first = build2 (COMPOUND_EXPR, TREE_TYPE (first), tem, first); + OMP_CLAUSE_DECL (c) = first; + } + else + { + unsigned int num = types.length (), i; + tree t, side_effects = NULL_TREE, size = NULL_TREE; + tree condition = NULL_TREE; + + if (int_size_in_bytes (TREE_TYPE (first)) <= 0) + maybe_zero_len = true; + if (processing_template_decl && maybe_zero_len) + { + types.release (); + return false; + } + + for (i = num, t = OMP_CLAUSE_DECL (c); i > 0; + t = TREE_CHAIN (t)) + { + tree low_bound = TREE_PURPOSE (t); + tree length = TREE_VALUE (t); + + i--; + if (low_bound + && TREE_CODE (low_bound) == INTEGER_CST + && TYPE_PRECISION (TREE_TYPE (low_bound)) + > TYPE_PRECISION (sizetype)) + low_bound = fold_convert (sizetype, low_bound); + if (length + && TREE_CODE (length) == INTEGER_CST + && TYPE_PRECISION (TREE_TYPE (length)) + > TYPE_PRECISION (sizetype)) + length = fold_convert (sizetype, length); + if (low_bound == NULL_TREE) + low_bound = integer_zero_node; + if (!maybe_zero_len && i > first_non_one) + { + if (integer_nonzerop (low_bound)) + goto do_warn_noncontiguous; + if (length != NULL_TREE + && TREE_CODE (length) == INTEGER_CST + && TYPE_DOMAIN (types[i]) + && TYPE_MAX_VALUE (TYPE_DOMAIN (types[i])) + && TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (types[i]))) + == INTEGER_CST) + { + tree size; + size = size_binop (PLUS_EXPR, + TYPE_MAX_VALUE (TYPE_DOMAIN (types[i])), + size_one_node); + if (!tree_int_cst_equal (length, size)) + { + do_warn_noncontiguous: + error_at (OMP_CLAUSE_LOCATION (c), + "array section is not contiguous in %qs " + "clause", + omp_clause_code_name[OMP_CLAUSE_CODE (c)]); + types.release (); + return true; + } + } + if (!processing_template_decl + && length != NULL_TREE + && TREE_SIDE_EFFECTS (length)) + { + if (side_effects == NULL_TREE) + side_effects = length; + else + side_effects = build2 (COMPOUND_EXPR, + TREE_TYPE (side_effects), + length, side_effects); + } + } + else if (processing_template_decl) + continue; + else + { + tree l; + + if (i > first_non_one && length && integer_nonzerop (length)) + continue; + if (length) + l = fold_convert (sizetype, length); + else + { + l = size_binop (PLUS_EXPR, + TYPE_MAX_VALUE (TYPE_DOMAIN (types[i])), + size_one_node); + l = size_binop (MINUS_EXPR, l, + fold_convert (sizetype, low_bound)); + } + if (i > first_non_one) + { + l = fold_build2 (NE_EXPR, boolean_type_node, l, + size_zero_node); + if (condition == NULL_TREE) + condition = l; + else + condition = fold_build2 (BIT_AND_EXPR, boolean_type_node, + l, condition); + } + else if (size == NULL_TREE) + { + size = size_in_bytes (TREE_TYPE (types[i])); + size = size_binop (MULT_EXPR, size, l); + if (condition) + size = fold_build3 (COND_EXPR, sizetype, condition, + size, size_zero_node); + } + else + size = size_binop (MULT_EXPR, size, l); + } + } + types.release (); + if (!processing_template_decl) + { + if (side_effects) + size = build2 (COMPOUND_EXPR, sizetype, side_effects, size); + OMP_CLAUSE_DECL (c) = first; + OMP_CLAUSE_SIZE (c) = size; + if (pointer_based_p) + { + tree c2 = build_omp_clause (OMP_CLAUSE_LOCATION (c), + OMP_CLAUSE_MAP); + OMP_CLAUSE_MAP_KIND (c2) = OMP_CLAUSE_MAP_POINTER; + if (!cxx_mark_addressable (t)) + return false; + OMP_CLAUSE_DECL (c2) = t; + t = build_fold_addr_expr (first); + t = fold_convert_loc (OMP_CLAUSE_LOCATION (c), + build_pointer_type (char_type_node), t); + t = fold_build2_loc (OMP_CLAUSE_LOCATION (c), MINUS_EXPR, + ptrdiff_type_node, t, + fold_convert_loc (OMP_CLAUSE_LOCATION (c), + TREE_TYPE (t), + OMP_CLAUSE_DECL (c2))); + OMP_CLAUSE_SIZE (c2) = t; + OMP_CLAUSE_CHAIN (c2) = OMP_CLAUSE_CHAIN (c); + OMP_CLAUSE_CHAIN (c) = c2; + } + } + } + return false; +} + /* For all elements of CLAUSES, validate them vs OpenMP constraints. Remove any elements from the list that are invalid. */ @@ -4419,8 +4871,15 @@ finish_omp_clauses (tree clauses) case OMP_CLAUSE_DEPEND: t = OMP_CLAUSE_DECL (c); - /* FIXME: depend clause argument may be also array section. */ - if (TREE_CODE (t) != VAR_DECL && TREE_CODE (t) != PARM_DECL) + if (TREE_CODE (t) == TREE_LIST) + { + if (handle_omp_array_sections (c)) + remove = true; + break; + } + if (t == error_mark_node) + remove = true; + else if (TREE_CODE (t) != VAR_DECL && TREE_CODE (t) != PARM_DECL) { if (processing_template_decl) break; @@ -4430,14 +4889,24 @@ finish_omp_clauses (tree clauses) error ("%qE is not a variable in %<depend%> clause", t); remove = true; } + else if (!processing_template_decl + && !cxx_mark_addressable (t)) + remove = true; break; case OMP_CLAUSE_MAP: case OMP_CLAUSE_TO: case OMP_CLAUSE_FROM: t = OMP_CLAUSE_DECL (c); - /* FIXME: map clause argument may be also array section. */ - if (TREE_CODE (t) != VAR_DECL && TREE_CODE (t) != PARM_DECL) + if (TREE_CODE (t) == TREE_LIST) + { + if (handle_omp_array_sections (c)) + remove = true; + break; + } + if (t == error_mark_node) + remove = true; + else if (TREE_CODE (t) != VAR_DECL && TREE_CODE (t) != PARM_DECL) { if (processing_template_decl) break; @@ -4455,6 +4924,9 @@ finish_omp_clauses (tree clauses) omp_clause_code_name[OMP_CLAUSE_CODE (c)]); remove = true; } + else if (!processing_template_decl + && !cxx_mark_addressable (t)) + remove = true; break; case OMP_CLAUSE_UNIFORM: --- gcc/cp/parser.c.jj 2013-05-29 10:05:42.139306172 +0200 +++ gcc/cp/parser.c 2013-05-29 11:54:41.483392567 +0200 @@ -26303,12 +26303,7 @@ cp_parser_omp_var_list_no_open (cp_parse /*declarator_p=*/false, /*optional_p=*/false); if (name == error_mark_node) - { - if (colon) - parser->colon_corrects_to_scope_p - = saved_colon_corrects_to_scope_p; - goto skip_comma; - } + goto skip_comma; decl = cp_parser_lookup_name_simple (parser, name, token->location); } @@ -26317,6 +26312,42 @@ cp_parser_omp_var_list_no_open (cp_parse token->location); else if (kind != 0) { + switch (kind) + { + case OMP_CLAUSE_MAP: + case OMP_CLAUSE_FROM: + case OMP_CLAUSE_TO: + case OMP_CLAUSE_DEPEND: + while (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_SQUARE)) + { + tree low_bound = NULL_TREE, length = NULL_TREE; + + parser->colon_corrects_to_scope_p = false; + cp_lexer_consume_token (parser->lexer); + if (!cp_lexer_next_token_is (parser->lexer, CPP_COLON)) + low_bound = cp_parser_expression (parser, /*cast_p=*/false, + NULL); + if (!colon) + parser->colon_corrects_to_scope_p + = saved_colon_corrects_to_scope_p; + /* Look for `:'. */ + if (!cp_parser_require (parser, CPP_COLON, RT_COLON)) + goto skip_comma; + if (!cp_lexer_next_token_is (parser->lexer, + CPP_CLOSE_SQUARE)) + length = cp_parser_expression (parser, /*cast_p=*/false, + NULL); + /* Look for the closing `]'. */ + if (!cp_parser_require (parser, CPP_CLOSE_SQUARE, + RT_CLOSE_SQUARE)) + goto skip_comma; + decl = tree_cons (low_bound, length, decl); + } + break; + default: + break; + } + tree u = build_omp_clause (token->location, kind); OMP_CLAUSE_DECL (u) = decl; OMP_CLAUSE_CHAIN (u) = list; @@ -26348,6 +26379,8 @@ cp_parser_omp_var_list_no_open (cp_parse /* Try to resync to an unnested comma. Copied from cp_parser_parenthesized_expression_list. */ skip_comma: + if (colon) + parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p; ending = cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, /*or_comma=*/true, --- gcc/testsuite/g++.dg/gomp/depend-1.C.jj 2013-06-03 13:10:11.279237362 +0200 +++ gcc/testsuite/g++.dg/gomp/depend-1.C 2013-06-03 13:22:06.137994982 +0200 @@ -0,0 +1,70 @@ +// { dg-do compile } +// { dg-options "-fopenmp" } + +extern int a[][10], a2[][10]; +int b[10], c[10][2], d[10], e[10], f[10]; +int b2[10], c2[10][2], d2[10], e2[10], f2[10]; +int k[10], l[10], m[10], n[10], o; +int *p; +void bar (void); +int t[10]; +#pragma omp threadprivate (t) + +template <int N> +void +foo (int g[3][10], int h[4][8], int i[2][10], int j[][9], + int g2[3][10], int h2[4][8], int i2[2][10], int j2[][9]) +{ + #pragma omp task depend(out: t[2:5]) + ; + #pragma omp task depend(inout: k[0.5:]) // { dg-error "low bound \[^\n\r]* of array section does not have integral type" } + ; + #pragma omp task depend(in: l[:7.5f]) // { dg-error "length \[^\n\r]* of array section does not have integral type" } + ; + #pragma omp task depend(out: m[p:]) // { dg-error "low bound \[^\n\r]* of array section does not have integral type" } + ; + #pragma omp task depend(inout: n[:p]) // { dg-error "length \[^\n\r]* of array section does not have integral type" } + ; + #pragma omp task depend(in: o[2:5]) // { dg-error "does not have pointer or array type" } + ; + #pragma omp task depend(out: a[:][2:4]) // { dg-error "array type length expression is not optional" } + ; + #pragma omp task depend(in: d[11:]) // { dg-error "low bound \[^\n\r]* above array section size" } + ; + #pragma omp task depend(out: e[:11]) // { dg-error "length \[^\n\r]* above array section size" } + ; + #pragma omp task depend(out: f[1:10]) // { dg-error "high bound \[^\n\r]* above array section size" } + ; + #pragma omp task depend(in: g[:][2:4]) // { dg-error "for pointer type length expression is not optional" } + ; + #pragma omp task depend(out: i[:1][11:]) // { dg-error "low bound \[^\n\r]* above array section size" } + ; + #pragma omp task depend(in: j[3:4][:10]) // { dg-error "length \[^\n\r]* above array section size" } + ; + #pragma omp task depend(out: j[30:10][5:5]) // { dg-error "high bound \[^\n\r]* above array section size" } + ; + #pragma omp task depend(out: a2[:3][2:4]) + ; + #pragma omp task depend(inout: b2[0:]) + ; + #pragma omp task depend(inout: c2[:3][1:1]) + ; + #pragma omp task depend(in: d2[9:]) + ; + #pragma omp task depend(out: e2[:10]) + ; + #pragma omp task depend(out: f2[1:9]) + ; + #pragma omp task depend(in: g2[:2][2:4]) + ; + #pragma omp task depend(in: h2[2:2][0:]) + ; + #pragma omp task depend(inout: h2[:1][:3]) + ; + #pragma omp task depend(out: i2[:1][9:]) + ; + #pragma omp task depend(in: j2[3:4][:9]) + ; + #pragma omp task depend(out: j2[30:10][5:4]) + ; +} --- gcc/testsuite/g++.dg/gomp/depend-2.C.jj 2013-06-03 13:20:00.776124422 +0200 +++ gcc/testsuite/g++.dg/gomp/depend-2.C 2013-06-03 14:00:58.000000000 +0200 @@ -0,0 +1,87 @@ +// { dg-do compile } +// { dg-options "-fopenmp" } + +extern int a[][10], a2[][10]; +int b[10], c[10][2], d[10], e[10], f[10]; +int b2[10], c2[10][2], d2[10], e2[10], f2[10]; +int k[10], l[10], m[10], n[10], o; +int *p; +void bar (void); +int t[10]; +#pragma omp threadprivate (t) + +template <int N> +void +foo (int g[3][10], int h[4][8], int i[2][10], int j[][9], + int g2[3][10], int h2[4][8], int i2[2][10], int j2[][9]) +{ + #pragma omp task depend(in: bar[2:5]) // { dg-error "is not a variable" } + ; + #pragma omp task depend(out: t[2:5]) + ; + #pragma omp task depend(inout: k[0.5:]) // { dg-error "low bound \[^\n\r]* of array section does not have integral type" } + ; + #pragma omp task depend(in: l[:7.5f]) // { dg-error "length \[^\n\r]* of array section does not have integral type" } + ; + #pragma omp task depend(out: m[p:]) // { dg-error "low bound \[^\n\r]* of array section does not have integral type" } + ; + #pragma omp task depend(inout: n[:p]) // { dg-error "length \[^\n\r]* of array section does not have integral type" } + ; + #pragma omp task depend(in: o[2:5]) // { dg-error "does not have pointer or array type" } + ; + #pragma omp task depend(out: a[:][2:4]) // { dg-error "array type length expression is not optional" } + ; + #pragma omp task depend(inout: b[-1:]) // { dg-error "negative low bound in array section" } + ; + #pragma omp task depend(inout: c[:-3][1:1]) // { dg-error "negative length in array section" } + ; + #pragma omp task depend(in: d[11:]) // { dg-error "low bound \[^\n\r]* above array section size" } + ; + #pragma omp task depend(out: e[:11]) // { dg-error "length \[^\n\r]* above array section size" } + ; + #pragma omp task depend(out: f[1:10]) // { dg-error "high bound \[^\n\r]* above array section size" } + ; + #pragma omp task depend(in: g[:][2:4]) // { dg-error "for pointer type length expression is not optional" } + ; + #pragma omp task depend(in: h[2:2][-1:]) // { dg-error "negative low bound in array section" } + ; + #pragma omp task depend(inout: h[:1][:-3]) // { dg-error "negative length in array section" } + ; + #pragma omp task depend(out: i[:1][11:]) // { dg-error "low bound \[^\n\r]* above array section size" } + ; + #pragma omp task depend(in: j[3:4][:10]) // { dg-error "length \[^\n\r]* above array section size" } + ; + #pragma omp task depend(out: j[30:10][5:5]) // { dg-error "high bound \[^\n\r]* above array section size" } + ; + #pragma omp task depend(out: a2[:3][2:4]) + ; + #pragma omp task depend(inout: b2[0:]) + ; + #pragma omp task depend(inout: c2[:3][1:1]) + ; + #pragma omp task depend(in: d2[9:]) + ; + #pragma omp task depend(out: e2[:10]) + ; + #pragma omp task depend(out: f2[1:9]) + ; + #pragma omp task depend(in: g2[:2][2:4]) + ; + #pragma omp task depend(in: h2[2:2][0:]) + ; + #pragma omp task depend(inout: h2[:1][:3]) + ; + #pragma omp task depend(out: i2[:1][9:]) + ; + #pragma omp task depend(in: j2[3:4][:9]) + ; + #pragma omp task depend(out: j2[30:10][5:4]) + ; +} + +void +baz (int g[3][10], int h[4][8], int i[2][10], int j[][9], + int g2[3][10], int h2[4][8], int i2[2][10], int j2[][9]) +{ + foo<0> (g, h, i, j, g2, h2, i2, j2); +} --- gcc/testsuite/c-c++-common/gomp/depend-1.c.jj 2013-05-31 14:19:26.248970104 +0200 +++ gcc/testsuite/c-c++-common/gomp/depend-1.c 2013-06-03 12:34:55.250492986 +0200 @@ -0,0 +1,79 @@ +/* { dg-do compile { target c++ } } */ +/* { dg-options "-fopenmp" } */ + +extern int a[][10], a2[][10]; +int b[10], c[10][2], d[10], e[10], f[10]; +int b2[10], c2[10][2], d2[10], e2[10], f2[10]; +int k[10], l[10], m[10], n[10], o; +int *p; +void bar (void); +int t[10]; +#pragma omp threadprivate (t) + +void +foo (int g[3][10], int h[4][8], int i[2][10], int j[][9], + int g2[3][10], int h2[4][8], int i2[2][10], int j2[][9]) +{ + #pragma omp task depend(in: bar[2:5]) /* { dg-error "is not a variable" } */ + ; + #pragma omp task depend(out: t[2:5]) + ; + #pragma omp task depend(inout: k[0.5:]) /* { dg-error "low bound \[^\n\r]* of array section does not have integral type" } */ + ; + #pragma omp task depend(in: l[:7.5f]) /* { dg-error "length \[^\n\r]* of array section does not have integral type" } */ + ; + #pragma omp task depend(out: m[p:]) /* { dg-error "low bound \[^\n\r]* of array section does not have integral type" } */ + ; + #pragma omp task depend(inout: n[:p]) /* { dg-error "length \[^\n\r]* of array section does not have integral type" } */ + ; + #pragma omp task depend(in: o[2:5]) /* { dg-error "does not have pointer or array type" } */ + ; + #pragma omp task depend(out: a[:][2:4]) /* { dg-error "array type length expression is not optional" } */ + ; + #pragma omp task depend(inout: b[-1:]) /* { dg-error "negative low bound in array section" } */ + ; + #pragma omp task depend(inout: c[:-3][1:1]) /* { dg-error "negative length in array section" } */ + ; + #pragma omp task depend(in: d[11:]) /* { dg-error "low bound \[^\n\r]* above array section size" } */ + ; + #pragma omp task depend(out: e[:11]) /* { dg-error "length \[^\n\r]* above array section size" } */ + ; + #pragma omp task depend(out: f[1:10]) /* { dg-error "high bound \[^\n\r]* above array section size" } */ + ; + #pragma omp task depend(in: g[:][2:4]) /* { dg-error "for pointer type length expression is not optional" } */ + ; + #pragma omp task depend(in: h[2:2][-1:]) /* { dg-error "negative low bound in array section" } */ + ; + #pragma omp task depend(inout: h[:1][:-3]) /* { dg-error "negative length in array section" } */ + ; + #pragma omp task depend(out: i[:1][11:]) /* { dg-error "low bound \[^\n\r]* above array section size" } */ + ; + #pragma omp task depend(in: j[3:4][:10]) /* { dg-error "length \[^\n\r]* above array section size" } */ + ; + #pragma omp task depend(out: j[30:10][5:5]) /* { dg-error "high bound \[^\n\r]* above array section size" } */ + ; + #pragma omp task depend(out: a2[:3][2:4]) + ; + #pragma omp task depend(inout: b2[0:]) + ; + #pragma omp task depend(inout: c2[:3][1:1]) + ; + #pragma omp task depend(in: d2[9:]) + ; + #pragma omp task depend(out: e2[:10]) + ; + #pragma omp task depend(out: f2[1:9]) + ; + #pragma omp task depend(in: g2[:2][2:4]) + ; + #pragma omp task depend(in: h2[2:2][0:]) + ; + #pragma omp task depend(inout: h2[:1][:3]) + ; + #pragma omp task depend(out: i2[:1][9:]) + ; + #pragma omp task depend(in: j2[3:4][:9]) + ; + #pragma omp task depend(out: j2[30:10][5:4]) + ; +} --- gcc/testsuite/c-c++-common/gomp/depend-2.c.jj 2013-05-31 14:31:35.119793004 +0200 +++ gcc/testsuite/c-c++-common/gomp/depend-2.c 2013-05-31 14:32:43.132666656 +0200 @@ -0,0 +1,19 @@ +/* { dg-do compile { target c++ } } */ +/* { dg-options "-fopenmp" } */ + +void bar (int a[10][10][10]); +void +foo (int a[10][10][10], int **b) +{ + int c[10][10][10]; + #pragma omp task depend(out: a[2:4][3:][:7], b[1:7][2:8]) + bar (a); + int i = 1, j = 3, k = 2, l = 6; + #pragma omp task depend(in: a[++i:++j][++k:][:++l]) + bar (a); + #pragma omp task depend(out: a[7:2][:][:], c[5:2][:][:]) + { + bar (c); + bar (a); + } +} --- gcc/testsuite/c-c++-common/gomp/map-1.c.jj 2013-06-03 15:45:12.168316275 +0200 +++ gcc/testsuite/c-c++-common/gomp/map-1.c 2013-06-03 15:55:27.762552097 +0200 @@ -0,0 +1,103 @@ +/* { dg-do compile { target c++ } } */ +/* { dg-options "-fopenmp" } */ + +extern int a[][10], a2[][10]; +int b[10], c[10][2], d[10], e[10], f[10]; +int b2[10], c2[10][2], d2[10], e2[10], f2[10]; +int k[10], l[10], m[10], n[10], o; +int *p; +int **q; +int r[4][4][4][4][4]; +int t[10]; +#pragma omp threadprivate (t) +#pragma omp declare target +void bar (int *); +#pragma omp end declare target + +void +foo (int g[3][10], int h[4][8], int i[2][10], int j[][9], + int g2[3][10], int h2[4][8], int i2[2][10], int j2[][9]) +{ + #pragma omp target map(to: bar[2:5]) /* { dg-error "is not a variable" } */ + ; + #pragma omp target map(from: t[2:5]) /* { dg-error "is threadprivate variable" } */ + ; + #pragma omp target map(tofrom: k[0.5:]) /* { dg-error "low bound \[^\n\r]* of array section does not have integral type" } */ + ; + #pragma omp target map(from: l[:7.5f]) /* { dg-error "length \[^\n\r]* of array section does not have integral type" } */ + ; + #pragma omp target map(to: m[p:]) /* { dg-error "low bound \[^\n\r]* of array section does not have integral type" } */ + ; + #pragma omp target map(tofrom: n[:p]) /* { dg-error "length \[^\n\r]* of array section does not have integral type" } */ + ; + #pragma omp target map(to: o[2:5]) /* { dg-error "does not have pointer or array type" } */ + ; + #pragma omp target map(to: a[:][:]) /* { dg-error "array type length expression is not optional" } */ + bar (&a[0][0]); + #pragma omp target map(tofrom: b[-1:]) /* { dg-error "negative low bound in array section" } */ + bar (b); + #pragma omp target map(tofrom: c[:-3][:]) /* { dg-error "negative length in array section" } */ + bar (&c[0][0]); + #pragma omp target map(from: d[11:]) /* { dg-error "low bound \[^\n\r]* above array section size" } */ + bar (d); + #pragma omp target map(to: e[:11]) /* { dg-error "length \[^\n\r]* above array section size" } */ + bar (e); + #pragma omp target map(to: f[1:10]) /* { dg-error "high bound \[^\n\r]* above array section size" } */ + bar (f); + #pragma omp target map(from: g[:][0:10]) /* { dg-error "for pointer type length expression is not optional" } */ + bar (&g[0][0]); + #pragma omp target map(from: h[2:1][-1:]) /* { dg-error "negative low bound in array section" } */ + bar (&h[0][0]); + #pragma omp target map(tofrom: h[:1][:-3]) /* { dg-error "negative length in array section" } */ + bar (&h[0][0]); + #pragma omp target map(i[:1][11:]) /* { dg-error "low bound \[^\n\r]* above array section size" } */ + bar (&i[0][0]); + #pragma omp target map(from: j[3:1][:10]) /* { dg-error "length \[^\n\r]* above array section size" } */ + bar (&j[0][0]); + #pragma omp target map(to: j[30:1][5:5]) /* { dg-error "high bound \[^\n\r]* above array section size" } */ + bar (&j[0][0]); + #pragma omp target map(to: a2[:1][2:4]) + bar (&a2[0][0]); + #pragma omp target map(a2[3:5][:]) + bar (&a2[0][0]); + #pragma omp target map(to: a2[3:5][:10]) + bar (&a2[0][0]); + #pragma omp target map(tofrom: b2[0:]) + bar (b2); + #pragma omp target map(tofrom: c2[:3][:]) + bar (&c2[0][0]); + #pragma omp target map(from: d2[9:]) + bar (d2); + #pragma omp target map(to: e2[:10]) + bar (e2); + #pragma omp target map(to: f2[1:9]) + bar (f2); + #pragma omp target map(g2[:1][2:4]) + bar (&g2[0][0]); + #pragma omp target map(from: h2[2:2][0:]) + bar (&h2[0][0]); + #pragma omp target map(tofrom: h2[:1][:3]) + bar (&h2[0][0]); + #pragma omp target map(to: i2[:1][9:]) + bar (&i2[0][0]); + #pragma omp target map(from: j2[3:4][:9]) + bar (&j2[0][0]); + #pragma omp target map(to: j2[30:1][5:4]) + bar (&j2[0][0]); + #pragma omp target map(q[1:2]) + ; + #pragma omp target map(tofrom: q[3:5][:10]) /* { dg-error "array section is not contiguous" } */ + ; + #pragma omp target map(r[3:][2:1][1:2]) + ; + #pragma omp target map(r[3:][2:1][1:2][:][0:4]) + ; + #pragma omp target map(r[3:][2:1][1:2][1:][0:4]) /* { dg-error "array section is not contiguous" } */ + ; + #pragma omp target map(r[3:][2:1][1:2][:3][0:4]) /* { dg-error "array section is not contiguous" } */ + ; + #pragma omp target map(r[3:][2:1][1:2][:][1:]) /* { dg-error "array section is not contiguous" } */ + ; + #pragma omp target map(r[3:][2:1][1:2][:][:3]) /* { dg-error "array section is not contiguous" } */ + ; +} Jakub