@@ -3265,12 +3265,18 @@ c_omp_decompose_attachable_address (tree t, tree *virtbase)
{
*virtbase = t;
- /* It's already a pointer. Just use that. */
- if (POINTER_TYPE_P (TREE_TYPE (t)))
+ /* It's already a non-offset pointer. Just use that. */
+ if (POINTER_TYPE_P (TREE_TYPE (t))
+ && (DECL_P (t)
+ || TREE_CODE (t) == COMPONENT_REF
+ || TREE_CODE (t) == ARRAY_REF))
return NULL_TREE;
/* Otherwise, look for a base pointer deeper within the expression. */
+ while (TREE_CODE (t) == COMPOUND_EXPR)
+ t = TREE_OPERAND (t, 1);
+
while (TREE_CODE (t) == COMPONENT_REF
&& (TREE_CODE (TREE_OPERAND (t, 0)) == COMPONENT_REF
|| TREE_CODE (TREE_OPERAND (t, 0)) == ARRAY_REF))
@@ -3280,9 +3286,24 @@ c_omp_decompose_attachable_address (tree t, tree *virtbase)
t = TREE_OPERAND (t, 0);
}
+ if (TREE_CODE (t) == POINTER_PLUS_EXPR)
+ {
+ t = TREE_OPERAND (t, 0);
+ if (TREE_CODE (t) == SAVE_EXPR)
+ t = TREE_OPERAND (t, 0);
+ }
+
+ if (TREE_CODE (t) == INDIRECT_REF
+ && TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == REFERENCE_TYPE)
+ t = TREE_OPERAND (t, 0);
*virtbase = t;
+ /* If we have a pointer now (e.g. after we've stripped POINTER_PLUS_EXPR),
+ we have an offset pointer. That's the attachment point. */
+ if (POINTER_TYPE_P (TREE_TYPE (t)))
+ return t;
+
if (TREE_CODE (t) != COMPONENT_REF)
return NULL_TREE;
@@ -2415,6 +2415,15 @@ dump_expr (cxx_pretty_printer *pp, tree t, int flags)
pp_cxx_right_bracket (pp);
break;
+ case OMP_ARRAY_SECTION:
+ dump_expr (pp, TREE_OPERAND (t, 0), flags);
+ pp_cxx_left_bracket (pp);
+ dump_expr (pp, TREE_OPERAND (t, 1), flags);
+ pp_colon (pp);
+ dump_expr (pp, TREE_OPERAND (t, 2), flags);
+ pp_cxx_right_bracket (pp);
+ break;
+
case UNARY_PLUS_EXPR:
dump_unary_op (pp, "+", t, flags);
break;
@@ -4241,6 +4241,9 @@ cp_parser_new (cp_lexer *lexer)
parser->omp_declare_simd = NULL;
parser->oacc_routine = NULL;
+ /* Allow array slice in expression. */
+ parser->omp_array_section_p = false;
+
/* Not declaring an implicit function template. */
parser->auto_is_implicit_function_template_parm_p = false;
parser->fully_implicit_function_template_p = false;
@@ -7901,6 +7904,7 @@ cp_parser_postfix_open_square_expression (cp_parser *parser,
tree index = NULL_TREE;
location_t loc = cp_lexer_peek_token (parser->lexer)->location;
bool saved_greater_than_is_operator_p;
+ bool saved_colon_corrects_to_scope_p;
/* Consume the `[' token. */
cp_lexer_consume_token (parser->lexer);
@@ -7908,6 +7912,9 @@ cp_parser_postfix_open_square_expression (cp_parser *parser,
saved_greater_than_is_operator_p = parser->greater_than_is_operator_p;
parser->greater_than_is_operator_p = true;
+ saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p;
+ parser->colon_corrects_to_scope_p = false;
+
/* Parse the index expression. */
/* ??? For offsetof, there is a question of what to allow here. If
offsetof is not being used in an integral constant expression context,
@@ -7918,7 +7925,8 @@ cp_parser_postfix_open_square_expression (cp_parser *parser,
constant expressions here. */
if (for_offsetof)
index = cp_parser_constant_expression (parser);
- else
+ else if (!parser->omp_array_section_p
+ || cp_lexer_next_token_is_not (parser->lexer, CPP_COLON))
{
if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
{
@@ -7935,6 +7943,32 @@ cp_parser_postfix_open_square_expression (cp_parser *parser,
parser->greater_than_is_operator_p = saved_greater_than_is_operator_p;
+ if (parser->omp_array_section_p
+ && cp_lexer_next_token_is (parser->lexer, CPP_COLON))
+ {
+ cp_lexer_consume_token (parser->lexer);
+ tree length = NULL_TREE;
+ if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_SQUARE))
+ length = cp_parser_expression (parser);
+
+ parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p;
+
+ if ((index && error_operand_p (index))
+ || (length && error_operand_p (length)))
+ return error_mark_node;
+
+ cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE);
+
+ /* NOTE: We are reusing using the type of the whole array as the type of
+ the array section here, which isn't necessarily entirely correct.
+ Might need revisiting. */
+ return build3_loc (input_location, OMP_ARRAY_SECTION,
+ TREE_TYPE (postfix_expression),
+ postfix_expression, index, length);
+ }
+
+ parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p;
+
/* Look for the closing `]'. */
cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE);
@@ -36335,7 +36369,7 @@ struct omp_dim
static tree
cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
tree list, bool *colon,
- bool allow_deref = false)
+ bool map_lvalue = false)
{
auto_vec<omp_dim> dims;
bool array_section_p;
@@ -36346,12 +36380,95 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
parser->colon_corrects_to_scope_p = false;
*colon = false;
}
+ begin_scope (sk_omp, NULL);
while (1)
{
tree name, decl;
if (kind == OMP_CLAUSE_DEPEND || kind == OMP_CLAUSE_AFFINITY)
cp_parser_parse_tentatively (parser);
+ else if (map_lvalue && kind == OMP_CLAUSE_MAP)
+ {
+ auto s = make_temp_override (parser->omp_array_section_p, true);
+ token = cp_lexer_peek_token (parser->lexer);
+ location_t loc = token->location;
+ decl = cp_parser_assignment_expression (parser);
+
+ dims.truncate (0);
+ if (TREE_CODE (decl) == OMP_ARRAY_SECTION)
+ {
+ while (TREE_CODE (decl) == OMP_ARRAY_SECTION)
+ {
+ tree low_bound = TREE_OPERAND (decl, 1);
+ tree length = TREE_OPERAND (decl, 2);
+ dims.safe_push (omp_dim (low_bound, length, loc, false));
+ decl = TREE_OPERAND (decl, 0);
+ }
+
+ while (TREE_CODE (decl) == ARRAY_REF
+ || TREE_CODE (decl) == INDIRECT_REF
+ || TREE_CODE (decl) == COMPOUND_EXPR)
+ {
+ if (REFERENCE_REF_P (decl))
+ break;
+
+ if (TREE_CODE (decl) == COMPOUND_EXPR)
+ {
+ decl = TREE_OPERAND (decl, 1);
+ STRIP_NOPS (decl);
+ }
+ else if (TREE_CODE (decl) == INDIRECT_REF)
+ {
+ dims.safe_push (omp_dim (integer_zero_node,
+ integer_one_node, loc, true));
+ decl = TREE_OPERAND (decl, 0);
+ }
+ else /* ARRAY_REF. */
+ {
+ tree index = TREE_OPERAND (decl, 1);
+ dims.safe_push (omp_dim (index, integer_one_node, loc,
+ true));
+ decl = TREE_OPERAND (decl, 0);
+ }
+ }
+
+ /* Bare references have their own special handling, so remove
+ the explicit dereference added by convert_from_reference. */
+ if (REFERENCE_REF_P (decl))
+ decl = TREE_OPERAND (decl, 0);
+
+ for (int i = dims.length () - 1; i >= 0; i--)
+ decl = tree_cons (dims[i].low_bound, dims[i].length, decl);
+ }
+ else if (TREE_CODE (decl) == INDIRECT_REF)
+ {
+ bool ref_p = REFERENCE_REF_P (decl);
+
+ /* Turn *foo into the representation previously used for
+ foo[0]. */
+ decl = TREE_OPERAND (decl, 0);
+ STRIP_NOPS (decl);
+
+ /* ...but don't add the [0:1] representation for references
+ (because they have special handling elsewhere). */
+ if (!ref_p)
+ decl = tree_cons (integer_zero_node, integer_one_node, decl);
+ }
+ else if (TREE_CODE (decl) == ARRAY_REF)
+ {
+ tree idx = TREE_OPERAND (decl, 1);
+
+ decl = TREE_OPERAND (decl, 0);
+ STRIP_NOPS (decl);
+
+ decl = tree_cons (idx, integer_one_node, decl);
+ }
+ else if (TREE_CODE (decl) == NON_LVALUE_EXPR
+ || CONVERT_EXPR_P (decl))
+ decl = TREE_OPERAND (decl, 0);
+
+ goto build_clause;
+ }
token = cp_lexer_peek_token (parser->lexer);
if (kind != 0
&& cp_parser_is_keyword (token, RID_THIS))
@@ -36421,8 +36538,7 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
case OMP_CLAUSE_TO:
start_component_ref:
while (cp_lexer_next_token_is (parser->lexer, CPP_DOT)
- || (allow_deref
- && cp_lexer_next_token_is (parser->lexer, CPP_DEREF)))
+ || cp_lexer_next_token_is (parser->lexer, CPP_DEREF))
{
cpp_ttype ttype
= cp_lexer_next_token_is (parser->lexer, CPP_DOT)
@@ -36508,9 +36624,7 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
|| kind == OMP_CLAUSE_TO)
&& !array_section_p
&& (cp_lexer_next_token_is (parser->lexer, CPP_DOT)
- || (allow_deref
- && cp_lexer_next_token_is (parser->lexer,
- CPP_DEREF))))
+ || cp_lexer_next_token_is (parser->lexer, CPP_DEREF)))
{
for (unsigned i = 0; i < dims.length (); i++)
{
@@ -36546,6 +36660,7 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
cp_parser_parse_definitely (parser);
}
+ build_clause:
tree u = build_omp_clause (token->location, kind);
OMP_CLAUSE_DECL (u) = decl;
OMP_CLAUSE_CHAIN (u) = list;
@@ -36567,6 +36682,7 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
{
*colon = true;
cp_parser_require (parser, CPP_COLON, RT_COLON);
+ finish_scope ();
return list;
}
@@ -36587,6 +36703,7 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
goto get_comma;
}
+ finish_scope ();
return list;
}
@@ -36595,11 +36712,11 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
static tree
cp_parser_omp_var_list (cp_parser *parser, enum omp_clause_code kind, tree list,
- bool allow_deref = false)
+ bool map_lvalue = false)
{
if (cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
return cp_parser_omp_var_list_no_open (parser, kind, list, NULL,
- allow_deref);
+ map_lvalue);
return list;
}
@@ -36666,7 +36783,7 @@ cp_parser_oacc_data_clause (cp_parser *parser, pragma_omp_clause c_kind,
gcc_unreachable ();
}
tree nl, c;
- nl = cp_parser_omp_var_list (parser, OMP_CLAUSE_MAP, list, true);
+ nl = cp_parser_omp_var_list (parser, OMP_CLAUSE_MAP, list, false);
for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
OMP_CLAUSE_SET_MAP_KIND (c, kind);
@@ -40028,12 +40145,12 @@ cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask,
clauses);
else
clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_TO, clauses,
- true);
+ false);
c_name = "to";
break;
case PRAGMA_OMP_CLAUSE_FROM:
clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_FROM, clauses,
- true);
+ false);
c_name = "from";
break;
case PRAGMA_OMP_CLAUSE_UNIFORM:
@@ -404,6 +404,9 @@ struct GTY(()) cp_parser {
/* TRUE if omp::directive or omp::sequence attributes may not appear. */
bool omp_attrs_forbidden_p;
+ /* TRUE if an OpenMP array section is allowed. */
+ bool omp_array_section_p;
+
/* Tracks the function's template parameter list when declaring a function
using generic type parameters. This is either a new chain in the case of a
fully implicit function template or an extension of the function's existing
@@ -5073,7 +5073,9 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
ret = t_insp.get_deref_toplevel ();
if (TREE_CODE (t) == FIELD_DECL)
ret = finish_non_static_data_member (t, NULL_TREE, NULL_TREE);
- else if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL)
+ else if (!VAR_P (t)
+ && (ort == C_ORT_ACC || !EXPR_P (t))
+ && TREE_CODE (t) != PARM_DECL)
{
if (processing_template_decl && TREE_CODE (t) != OVERLOAD)
return NULL_TREE;
@@ -5647,7 +5649,9 @@ handle_omp_array_sections (tree c, enum c_omp_region_type ort)
bool reference_always_pointer = true;
tree c2 = build_omp_clause (OMP_CLAUSE_LOCATION (c),
OMP_CLAUSE_MAP);
- if (TREE_CODE (t) == COMPONENT_REF)
+ if (TREE_CODE (t) == COMPONENT_REF
+ || (TREE_CODE (t) == POINTER_PLUS_EXPR
+ && TREE_CODE (TREE_OPERAND (t, 0)) == COMPONENT_REF))
{
OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
@@ -5677,6 +5681,13 @@ handle_omp_array_sections (tree c, enum c_omp_region_type ort)
}
OMP_CLAUSE_SET_MAP_KIND (c2, k);
}
+ else if (ort != C_ORT_ACC && attach_pt && !DECL_P (attach_pt))
+ {
+ if (TREE_CODE (TREE_TYPE (t)) != POINTER_TYPE)
+ return false;
+
+ OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
+ }
else
OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_FIRSTPRIVATE_POINTER);
OMP_CLAUSE_MAP_IMPLICIT (c2) = OMP_CLAUSE_MAP_IMPLICIT (c);
@@ -7909,6 +7920,15 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
{
t = t_insp.analyze_components (false);
+ if (!t_insp.map_supported_p ())
+ {
+ sorry_at (OMP_CLAUSE_LOCATION (c),
+ "unsupported map expression %qE",
+ OMP_CLAUSE_DECL (c));
+ remove = true;
+ break;
+ }
+
if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
&& OMP_CLAUSE_MAP_IMPLICIT (c)
&& (bitmap_bit_p (&map_head, DECL_UID (t))
@@ -7990,6 +8010,14 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
OMP_CLAUSE_DECL (c) = t_insp.get_deref_toplevel ();
if (type_dependent_expression_p (t_insp.get_deref_toplevel ()))
break;
+ if (!t_insp.map_supported_p ())
+ {
+ sorry_at (OMP_CLAUSE_LOCATION (c),
+ "unsupported map expression %qE",
+ OMP_CLAUSE_DECL (c));
+ remove = true;
+ break;
+ }
if (t == error_mark_node)
{
remove = true;
@@ -8019,7 +8047,8 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
&& (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
|| OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_POINTER
- || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH_DETACH))
+ || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH_DETACH
+ || (ort != C_ORT_ACC && EXPR_P (t))))
break;
if (DECL_P (t))
error_at (OMP_CLAUSE_LOCATION (c),
@@ -9812,6 +9812,7 @@ build_struct_group (enum omp_region_type region_type, enum tree_code code,
{
tree l = build_omp_clause (OMP_CLAUSE_LOCATION (grp_end), OMP_CLAUSE_MAP);
gomp_map_kind k = attach ? GOMP_MAP_FORCE_PRESENT : GOMP_MAP_STRUCT;
+ tree *tail_chain;
OMP_CLAUSE_SET_MAP_KIND (l, k);
@@ -9840,9 +9841,13 @@ build_struct_group (enum omp_region_type region_type, enum tree_code code,
{
OMP_CLAUSE_CHAIN (extra_node) = *insert_node_pos;
OMP_CLAUSE_CHAIN (alloc_node) = extra_node;
+ tail_chain = &OMP_CLAUSE_CHAIN (extra_node);
}
else
- OMP_CLAUSE_CHAIN (alloc_node) = *insert_node_pos;
+ {
+ OMP_CLAUSE_CHAIN (alloc_node) = *insert_node_pos;
+ tail_chain = &OMP_CLAUSE_CHAIN (alloc_node);
+ }
*insert_node_pos = l;
}
@@ -9850,6 +9855,7 @@ build_struct_group (enum omp_region_type region_type, enum tree_code code,
{
gcc_assert (*grp_start_p == grp_end);
grp_start_p = insert_node_after (l, grp_start_p);
+ tail_chain = &OMP_CLAUSE_CHAIN (*grp_start_p);
}
tree noind = strip_indirections (base);
@@ -9914,8 +9920,7 @@ build_struct_group (enum omp_region_type region_type, enum tree_code code,
|| TREE_CODE (sdecl) == POINTER_PLUS_EXPR)
sdecl = TREE_OPERAND (sdecl, 0);
- if (DECL_P (sdecl)
- && POINTER_TYPE_P (TREE_TYPE (sdecl))
+ if (POINTER_TYPE_P (TREE_TYPE (sdecl))
&& (region_type & ORT_TARGET))
{
tree c2 = build_omp_clause (OMP_CLAUSE_LOCATION (grp_end),
@@ -9929,8 +9934,12 @@ build_struct_group (enum omp_region_type region_type, enum tree_code code,
&& (TREE_CODE (TREE_TYPE (TREE_OPERAND
(TREE_OPERAND (base, 0), 0)))
== REFERENCE_TYPE))));
- enum gomp_map_kind mkind = base_ref ? GOMP_MAP_FIRSTPRIVATE_REFERENCE
- : GOMP_MAP_FIRSTPRIVATE_POINTER;
+ enum gomp_map_kind mkind;
+ if (DECL_P (sdecl))
+ mkind = base_ref ? GOMP_MAP_FIRSTPRIVATE_REFERENCE
+ : GOMP_MAP_FIRSTPRIVATE_POINTER;
+ else
+ mkind = GOMP_MAP_ATTACH;
OMP_CLAUSE_SET_MAP_KIND (c2, mkind);
OMP_CLAUSE_DECL (c2) = sdecl;
tree baddr = build_fold_addr_expr (base);
@@ -9946,9 +9955,21 @@ build_struct_group (enum omp_region_type region_type, enum tree_code code,
OMP_CLAUSE_SIZE (c2)
= fold_build2_loc (OMP_CLAUSE_LOCATION (grp_end), MINUS_EXPR,
ptrdiff_type_node, baddr, decladdr);
- /* Insert after struct node. */
- OMP_CLAUSE_CHAIN (c2) = OMP_CLAUSE_CHAIN (l);
- OMP_CLAUSE_CHAIN (l) = c2;
+ if (mkind == GOMP_MAP_FIRSTPRIVATE_POINTER
+ || mkind == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
+ {
+ /* Insert after struct node. */
+ OMP_CLAUSE_CHAIN (c2) = OMP_CLAUSE_CHAIN (l);
+ OMP_CLAUSE_CHAIN (l) = c2;
+ }
+ else /* GOMP_MAP_ATTACH. */
+ {
+ /* Insert after struct group. */
+ OMP_CLAUSE_CHAIN (c2) = *tail_chain;
+ *tail_chain = c2;
+ if (*grp_start_p == grp_end)
+ return &OMP_CLAUSE_CHAIN (*tail_chain);
+ }
}
return NULL;
@@ -20,12 +20,12 @@ foo (void)
;
#pragma omp target map (close a) /* { dg-error "'close' undeclared" "" { target c } } */
- /* { dg-error "'close' has not been declared" "" { target c++ } .-1 } */
+ /* { dg-error "'close' was not declared in this scope" "" { target c++ } .-1 } */
/* { dg-error "expected '\\)' before 'a'" "" { target *-*-* } .-2 } */
;
#pragma omp target map (always a) /* { dg-error "'always' undeclared" "" { target c } } */
- /* { dg-error "'always' has not been declared" "" { target c++ } .-1 } */
+ /* { dg-error "'always' was not declared in this scope" "" { target c++ } .-1 } */
/* { dg-error "expected '\\)' before 'a'" "" { target *-*-* } .-2 } */
;
new file mode 100644
@@ -0,0 +1,38 @@
+#include <cassert>
+
+struct S {
+ int x[10];
+};
+
+S *
+choose (S *a, S *b, int c)
+{
+ if (c < 5)
+ return a;
+ else
+ return b;
+}
+
+int main (int argc, char *argv[])
+{
+ S a, b;
+
+ for (int i = 0; i < 10; i++)
+ a.x[i] = b.x[i] = 0;
+
+ for (int i = 0; i < 10; i++)
+ {
+#pragma omp target map(choose(&a, &b, i)->x[:10])
+/* { dg-message {sorry, unimplemented: unsupported map expression 'choose\(\(& a\), \(& b\), i\)->S::x\[0\]'} "" { target *-*-* } .-1 } */
+/* { dg-message {sorry, unimplemented: unsupported map expression 'choose\(\(& a\), \(& b\), i\)'} "" { target *-*-* } .-2 } */
+ for (int j = 0; j < 10; j++)
+ choose (&a, &b, i)->x[j]++;
+ }
+
+ for (int i = 0; i < 10; i++)
+ assert (a.x[i] == 5 && b.x[i] == 5);
+
+ return 0;
+}
+
+
new file mode 100644
@@ -0,0 +1,12 @@
+#include <cassert>
+
+int main (int argc, char *argv[])
+{
+ int a = 5, b = 2;
+#pragma omp target map(a += b)
+ /* { dg-message {sorry, unimplemented: unsupported map expression '\(a = \(a \+ b\)\)'} "" { target *-*-* } .-1 } */
+ {
+ a++;
+ }
+ return 0;
+}
new file mode 100644
@@ -0,0 +1,10 @@
+int main (int argc, char *argv[])
+{
+ int a = 5;
+#pragma omp target map(++a)
+ /* { dg-message {sorry, unimplemented: unsupported map expression '\+\+ a'} "" { target *-*-* } .-1 } */
+ {
+ a++;
+ }
+ return 0;
+}
new file mode 100644
@@ -0,0 +1,19 @@
+#include <cassert>
+
+int glob = 10;
+
+int& foo ()
+{
+ return glob;
+}
+
+int main (int argc, char *argv[])
+{
+#pragma omp target map(foo())
+ /* { dg-message {sorry, unimplemented: unsupported map expression 'foo\(\)'} "" { target *-*-* } .-1 } */
+ {
+ foo()++;
+ }
+ assert (glob == 11);
+ return 0;
+}
new file mode 100644
@@ -0,0 +1,36 @@
+#include <cassert>
+
+struct S {
+ int x;
+ int *ptr;
+};
+
+int
+main (int argc, char *argv[])
+{
+ S s;
+ int S::* xp = &S::x;
+ int* S::* ptrp = &S::ptr;
+
+ s.ptr = new int[64];
+
+ s.*xp = 6;
+ for (int i = 0; i < 64; i++)
+ (s.*ptrp)[i] = i;
+
+#pragma omp target map(s.*xp, s.*ptrp, (s.*ptrp)[:64])
+ /* { dg-message {sorry, unimplemented: unsupported map expression '\(int\*\*\)\(& s\)'} "" { target *-*-* } .-1 } */
+ /* { dg-message {sorry, unimplemented: unsupported map expression '\(int\*\)\(& s\)'} "" { target *-*-* } .-2 } */
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 64; i++)
+ {
+ (s.*xp)++;
+ (s.*ptrp)[i]++;
+ }
+
+ assert (s.*xp == 70);
+ for (int i = 0; i < 64; i++)
+ assert ((s.*ptrp)[i] == i + 1);
+
+ return 0;
+}
new file mode 100644
@@ -0,0 +1,39 @@
+#include <cassert>
+
+struct S {
+ int x;
+ int *ptr;
+};
+
+int
+main (int argc, char *argv[])
+{
+ S *s = new S;
+ int S::* xp = &S::x;
+ int* S::* ptrp = &S::ptr;
+
+ s->ptr = new int[64];
+
+ s->*xp = 4;
+ for (int i = 0; i < 64; i++)
+ (s->*ptrp)[i] = i;
+
+#pragma omp target map(s->*xp, s->*ptrp, (s->*ptrp)[:64])
+ /* { dg-message {sorry, unimplemented: unsupported map expression '\(int\*\*\)s'} "" { target *-*-* } .-1 } */
+ /* { dg-message {sorry, unimplemented: unsupported map expression '\(int\*\)s'} "" { target *-*-* } .-2 } */
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 64; i++)
+ {
+ (s->*xp)++;
+ (s->*ptrp)[i]++;
+ }
+
+ assert (s->*xp == 68);
+ for (int i = 0; i < 64; i++)
+ assert ((s->*ptrp)[i] == i + 1);
+
+ delete s->ptr;
+ delete s;
+
+ return 0;
+}
new file mode 100644
@@ -0,0 +1,17 @@
+#include <cassert>
+
+int foo (int x)
+{
+#pragma omp target map(static_cast<int&>(x))
+ /* { dg-message {sorry, unimplemented: unsupported map expression '& x'} "" { target *-*-* } .-1 } */
+ {
+ x += 3;
+ }
+ return x;
+}
+
+int main (int argc, char *argv[])
+{
+ assert (foo (5) == 8);
+ return 0;
+}
new file mode 100644
@@ -0,0 +1,20 @@
+#include <cassert>
+
+int foo (bool yesno)
+{
+ int x = 5, y = 7;
+#pragma omp target map(yesno ? x : y)
+ /* { dg-message {sorry, unimplemented: unsupported map expression '\(yesno \? x : y\)'} "" { target *-*-* } .-1 } */
+ {
+ x += 3;
+ y += 5;
+ }
+ return yesno ? x : y;
+}
+
+int main (int argc, char *argv[])
+{
+ assert (foo (true) == 8);
+ assert (foo (false) == 12);
+ return 0;
+}
new file mode 100644
@@ -0,0 +1,86 @@
+#include <cassert>
+
+typedef int intarr100[100];
+
+class C {
+ int arr[100];
+ int *ptr;
+
+public:
+ C();
+ ~C();
+ void zero ();
+ void do_operation ();
+ void check (int, int);
+ intarr100 &get_arr () { return arr; }
+ int *get_ptr() { return ptr; }
+};
+
+C::C()
+{
+ ptr = new int[100];
+ for (int i = 0; i < 100; i++)
+ arr[i] = 0;
+}
+
+C::~C()
+{
+ delete ptr;
+}
+
+void
+C::zero ()
+{
+ for (int i = 0; i < 100; i++)
+ arr[i] = ptr[i] = 0;
+}
+
+void
+C::do_operation ()
+{
+#pragma omp target map(arr, ptr, ptr[:100])
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 100; i++)
+ {
+ arr[i] = arr[i] + 3;
+ ptr[i] = ptr[i] + 5;
+ }
+}
+
+void
+C::check (int arrval, int ptrval)
+{
+ for (int i = 0; i < 100; i++)
+ {
+ assert (arr[i] == arrval);
+ assert (ptr[i] == ptrval);
+ }
+}
+
+int
+main (int argc, char *argv[])
+{
+ C c;
+
+ c.zero ();
+ c.do_operation ();
+ c.check (3, 5);
+
+ #pragma omp target map(c.get_arr()[:100])
+ #pragma omp teams distribute parallel for
+ for (int i = 0; i < 100; i++)
+ c.get_arr()[i] += 2;
+
+ c.check (5, 5);
+
+ #pragma omp target map(c.get_ptr(), c.get_ptr()[:100])
+ /* { dg-message {sorry, unimplemented: unsupported map expression 'c\.C::get_ptr\(\)'} "" { target *-*-* } .-1 } */
+ #pragma omp teams distribute parallel for
+ for (int i = 0; i < 100; i++)
+ c.get_ptr()[i] += 3;
+
+ c.check (5, 8);
+
+ return 0;
+}
+
@@ -12,7 +12,7 @@ foo (void)
for (int i = 0; i < 16; i++)
;
- #pragma omp target map (S[0:10]) // { dg-error "is not a variable in" }
+ #pragma omp target map (S[0:10]) // { dg-error "expected primary-expression before '\\\[' token" }
;
#pragma omp task depend (inout: S[0:10]) // { dg-error "is not a variable in" }
@@ -2516,6 +2516,20 @@ dump_generic_node (pretty_printer *pp, tree node, int spc, dump_flags_t flags,
}
break;
+ case OMP_ARRAY_SECTION:
+ op0 = TREE_OPERAND (node, 0);
+ if (op_prio (op0) < op_prio (node))
+ pp_left_paren (pp);
+ dump_generic_node (pp, op0, spc, flags, false);
+ if (op_prio (op0) < op_prio (node))
+ pp_right_paren (pp);
+ pp_left_bracket (pp);
+ dump_generic_node (pp, TREE_OPERAND (node, 1), spc, flags, false);
+ pp_colon (pp);
+ dump_generic_node (pp, TREE_OPERAND (node, 2), spc, flags, false);
+ pp_right_bracket (pp);
+ break;
+
case CONSTRUCTOR:
{
unsigned HOST_WIDE_INT ix;
@@ -1304,6 +1304,9 @@ DEFTREECODE (OMP_ATOMIC_CAPTURE_NEW, "omp_atomic_capture_new", tcc_statement, 2)
/* OpenMP clauses. */
DEFTREECODE (OMP_CLAUSE, "omp_clause", tcc_exceptional, 0)
+/* An OpenMP array section. */
+DEFTREECODE (OMP_ARRAY_SECTION, "omp_array_section", tcc_expression, 3)
+
/* TRANSACTION_EXPR tree code.
Operand 0: BODY: contains body of the transaction. */
DEFTREECODE (TRANSACTION_EXPR, "transaction_expr", tcc_expression, 1)
new file mode 100644
@@ -0,0 +1,162 @@
+// { dg-do run }
+// { dg-options "-fopenmp" }
+
+#include <cassert>
+
+struct S
+{
+ int x[10];
+};
+
+struct T
+{
+ struct S *s;
+};
+
+struct U
+{
+ struct T *t;
+};
+
+void
+foo_siblist (void)
+{
+ U *u = new U;
+ u->t = new T;
+ u->t->s = new S;
+ for (int i = 0; i < 10; i++)
+ u->t->s->x[i] = 0;
+#pragma omp target map(u->t, *(u->t), u->t->s, *u->t->s)
+ for (int i = 0; i < 10; i++)
+ u->t->s->x[i] = i * 3;
+ for (int i = 0; i < 10; i++)
+ assert (u->t->s->x[i] == i * 3);
+ delete u->t->s;
+ delete u->t;
+ delete u;
+}
+
+void
+foo (void)
+{
+ U *u = new U;
+ u->t = new T;
+ u->t->s = new S;
+ for (int i = 0; i < 10; i++)
+ u->t->s->x[i] = 0;
+#pragma omp target map(*u, u->t, *(u->t), u->t->s, *u->t->s)
+ for (int i = 0; i < 10; i++)
+ u->t->s->x[i] = i * 3;
+ for (int i = 0; i < 10; i++)
+ assert (u->t->s->x[i] == i * 3);
+ delete u->t->s;
+ delete u->t;
+ delete u;
+}
+
+void
+foo_tofrom (void)
+{
+ U *u = new U;
+ u->t = new T;
+ u->t->s = new S;
+ for (int i = 0; i < 10; i++)
+ u->t->s->x[i] = 0;
+#pragma omp target map(u, *u, u->t, *(u->t), u->t->s, *u->t->s)
+ for (int i = 0; i < 10; i++)
+ u->t->s->x[i] = i * 3;
+ for (int i = 0; i < 10; i++)
+ assert (u->t->s->x[i] == i * 3);
+ delete u->t->s;
+ delete u->t;
+ delete u;
+}
+
+void
+bar (void)
+{
+ U *u = new U;
+ U **up = &u;
+ u->t = new T;
+ u->t->s = new S;
+ for (int i = 0; i < 10; i++)
+ (*up)->t->s->x[i] = 0;
+#pragma omp target map(*up, (*up)->t, *(*up)->t, (*up)->t->s, *(*up)->t->s)
+ for (int i = 0; i < 10; i++)
+ (*up)->t->s->x[i] = i * 3;
+ for (int i = 0; i < 10; i++)
+ assert ((*up)->t->s->x[i] == i * 3);
+ delete u->t->s;
+ delete u->t;
+ delete u;
+}
+
+void
+bar_pp (void)
+{
+ U *u = new U;
+ U **up = &u;
+ u->t = new T;
+ u->t->s = new S;
+ for (int i = 0; i < 10; i++)
+ (*up)->t->s->x[i] = 0;
+#pragma omp target map(*up, **up, (*up)->t, *(*up)->t, (*up)->t->s, *(*up)->t->s)
+ for (int i = 0; i < 10; i++)
+ (*up)->t->s->x[i] = i * 3;
+ for (int i = 0; i < 10; i++)
+ assert ((*up)->t->s->x[i] == i * 3);
+ delete u->t->s;
+ delete u->t;
+ delete u;
+}
+
+void
+bar_tofrom (void)
+{
+ U *u = new U;
+ U **up = &u;
+ u->t = new T;
+ u->t->s = new S;
+ for (int i = 0; i < 10; i++)
+ (*up)->t->s->x[i] = 0;
+#pragma omp target map(*up, up, (*up)->t, *(*up)->t, (*up)->t->s, *(*up)->t->s)
+ for (int i = 0; i < 10; i++)
+ (*up)->t->s->x[i] = i * 3;
+ for (int i = 0; i < 10; i++)
+ assert ((*up)->t->s->x[i] == i * 3);
+ delete u->t->s;
+ delete u->t;
+ delete u;
+}
+
+void
+bar_tofrom_pp (void)
+{
+ U *u = new U;
+ U **up = &u;
+ u->t = new T;
+ u->t->s = new S;
+ for (int i = 0; i < 10; i++)
+ (*up)->t->s->x[i] = 0;
+#pragma omp target map(**up, *up, up, (*up)->t, *(*up)->t, (*up)->t->s, \
+ *(*up)->t->s)
+ for (int i = 0; i < 10; i++)
+ (*up)->t->s->x[i] = i * 3;
+ for (int i = 0; i < 10; i++)
+ assert ((*up)->t->s->x[i] == i * 3);
+ delete u->t->s;
+ delete u->t;
+ delete u;
+}
+
+int main (int argc, char *argv[])
+{
+ foo_siblist ();
+ foo ();
+ foo_tofrom ();
+ bar ();
+ bar_pp ();
+ bar_tofrom ();
+ bar_tofrom_pp ();
+ return 0;
+}
new file mode 100644
@@ -0,0 +1,49 @@
+// { dg-do run }
+// { dg-options "-fopenmp" }
+
+#include <cassert>
+
+struct S
+{
+ int x[10];
+};
+
+struct T
+{
+ struct S ***s;
+};
+
+struct U
+{
+ struct T **t;
+};
+
+void
+foo (void)
+{
+ U *u = new U;
+ T *real_t = new T;
+ S *real_s = new S;
+ T **t_pp = &real_t;
+ S **s_pp = &real_s;
+ S ***s_ppp = &s_pp;
+ u->t = t_pp;
+ (*u->t)->s = s_ppp;
+ for (int i = 0; i < 10; i++)
+ (**((*u->t)->s))->x[i] = 0;
+#pragma omp target map(u->t, *u->t, (*u->t)->s, *(*u->t)->s, **(*u->t)->s, \
+ (**(*u->t)->s)->x[0:10])
+ for (int i = 0; i < 10; i++)
+ (**((*u->t)->s))->x[i] = i * 3;
+ for (int i = 0; i < 10; i++)
+ assert ((**((*u->t)->s))->x[i] == i * 3);
+ delete real_s;
+ delete real_t;
+ delete u;
+}
+
+int main (int argc, char *argv[])
+{
+ foo ();
+ return 0;
+}
new file mode 100644
@@ -0,0 +1,15 @@
+/* { dg-do run } */
+
+#include <cassert>
+
+int main (int argc, char *argv[])
+{
+ int a = 5, b = 7;
+#pragma omp target map((a, b))
+ {
+ a++;
+ b++;
+ }
+ assert (a == 5 && b == 8);
+ return 0;
+}
new file mode 100644
@@ -0,0 +1,22 @@
+/* { dg-do run } */
+
+#include <cassert>
+
+int foo (int &&x)
+{
+ int y;
+#pragma omp target map(x, y)
+ {
+ x++;
+ y = x;
+ }
+ return y;
+}
+
+int main (int argc, char *argv[])
+{
+ int y = 5;
+ y = foo (y + 3);
+ assert (y == 9);
+ return 0;
+}
new file mode 100644
@@ -0,0 +1,89 @@
+/* { dg-do run } */
+
+#include <cassert>
+
+typedef int intarr100[100];
+
+class C {
+ int arr[100];
+ int *ptr;
+
+public:
+ C();
+ ~C();
+ void zero ();
+ void do_operation ();
+ void check (int, int);
+ intarr100 &get_arr () { return arr; }
+ int *get_ptr() { return ptr; }
+};
+
+C::C()
+{
+ ptr = new int[100];
+ for (int i = 0; i < 100; i++)
+ arr[i] = 0;
+}
+
+C::~C()
+{
+ delete ptr;
+}
+
+void
+C::zero ()
+{
+ for (int i = 0; i < 100; i++)
+ arr[i] = ptr[i] = 0;
+}
+
+void
+C::do_operation ()
+{
+#pragma omp target map(arr, ptr, ptr[:100])
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 100; i++)
+ {
+ arr[i] = arr[i] + 3;
+ ptr[i] = ptr[i] + 5;
+ }
+}
+
+void
+C::check (int arrval, int ptrval)
+{
+ for (int i = 0; i < 100; i++)
+ {
+ assert (arr[i] == arrval);
+ assert (ptr[i] == ptrval);
+ }
+}
+
+int
+main (int argc, char *argv[])
+{
+ C c;
+
+ c.zero ();
+ c.do_operation ();
+ c.check (3, 5);
+
+ #pragma omp target map(c.get_arr()[:100])
+ #pragma omp teams distribute parallel for
+ for (int i = 0; i < 100; i++)
+ c.get_arr()[i] += 2;
+
+ c.check (5, 5);
+
+ /* This is currently not supported. See also:
+ gcc/testsuite/g++.dg/gomp/member-array-2.C. */
+ //#pragma omp target map(c.get_ptr(), c.get_ptr()[:100])
+ //#pragma omp teams distribute parallel for
+ for (int i = 0; i < 100; i++)
+ c.get_ptr()[i] += 3;
+
+ c.check (5, 8);
+
+ return 0;
+}
+
new file mode 100644
@@ -0,0 +1,97 @@
+// { dg-do run }
+// { dg-options "-fopenmp" }
+
+#include <cassert>
+
+struct S
+{
+ int x[10];
+};
+
+void
+foo (S *s, int x)
+{
+ S *&r = s;
+ for (int i = 0; i < x; i++)
+ s[0].x[i] = s[1].x[i] = 0;
+ #pragma omp target map (s, x)
+ ;
+ #pragma omp target map (s[0], x)
+ for (int i = 0; i < x; i++)
+ s[0].x[i] = i;
+ #pragma omp target map (s[1], x)
+ for (int i = 0; i < x; i++)
+ s[1].x[i] = i * 2;
+ for (int i = 0; i < x; i++)
+ {
+ assert (s[0].x[i] == i);
+ assert (s[1].x[i] == i * 2);
+ s[0].x[i] = 0;
+ s[1].x[i] = 0;
+ }
+ #pragma omp target map (r, x)
+ ;
+ #pragma omp target map (r[0], x)
+ for (int i = 0; i < x; i++)
+ r[0].x[i] = i;
+ #pragma omp target map (r[1], x)
+ for (int i = 0; i < x; i++)
+ r[1].x[i] = i * 2;
+ for (int i = 0; i < x; i++)
+ {
+ assert (r[0].x[i] == i);
+ assert (r[1].x[i] == i * 2);
+ }
+}
+
+template <int N>
+struct T
+{
+ int x[N];
+};
+
+template <int N>
+void
+bar (T<N> *t, int x)
+{
+ T<N> *&r = t;
+ for (int i = 0; i < x; i++)
+ t[0].x[i] = t[1].x[i] = 0;
+ #pragma omp target map (t, x)
+ ;
+ #pragma omp target map (t[0], x)
+ for (int i = 0; i < x; i++)
+ t[0].x[i] = i;
+ #pragma omp target map (t[1], x)
+ for (int i = 0; i < x; i++)
+ t[1].x[i] = i * 2;
+ for (int i = 0; i < x; i++)
+ {
+ assert (t[0].x[i] == i);
+ assert (t[1].x[i] == i * 2);
+ t[0].x[i] = 0;
+ t[1].x[i] = 0;
+ }
+ #pragma omp target map (r, x)
+ ;
+ #pragma omp target map (r[0], x)
+ for (int i = 0; i < x; i++)
+ r[0].x[i] = i;
+ #pragma omp target map (r[1], x)
+ for (int i = 0; i < x; i++)
+ r[1].x[i] = i * 2;
+ for (int i = 0; i < x; i++)
+ {
+ assert (r[0].x[i] == i);
+ assert (r[1].x[i] == i * 2);
+ }
+}
+
+int main (int argc, char *argv[])
+{
+ S s[2];
+ foo (s, 10);
+ T<10> t[2];
+ bar (t, 10);
+ return 0;
+}