mirror of
https://gcc.gnu.org/git/gcc.git
synced 2024-11-23 10:54:07 +08:00
OpenMP: lvalue parsing for map/to/from clauses (C)
This patch adds support for parsing general lvalues ("locator list item types") for OpenMP "map", "to" and "from" clauses to the C front-end, similar to the previously-posted patch for C++. Such syntax is permitted for OpenMP 5.0 and above. It was previously posted for mainline here: https://gcc.gnu.org/pipermail/gcc-patches/2022-December/609038.html and for the og13 branch here: https://gcc.gnu.org/pipermail/gcc-patches/2023-June/623355.html 2024-01-11 Julian Brown <julian@codesourcery.com> gcc/c-family/ * c-pretty-print.cc (c_pretty_printer::postfix_expression, c_pretty_printer::expression): Add OMP_ARRAY_SECTION support. gcc/c/ * c-parser.cc (c_parser_braced_init, c_parser_conditional_expression): Don't allow OpenMP array section. (c_parser_postfix_expression): Don't allow array section in statement expression. (c_parser_postfix_expression_after_primary): Add support for OpenMP array section parsing. (c_parser_expr_list): Don't allow OpenMP array section here. (c_parser_omp_variable_list): Change ALLOW_DEREF parameter to MAP_LVALUE. Support parsing of general lvalues in "map", "to" and "from" clauses. (c_parser_omp_var_list_parens): Change ALLOW_DEREF parameter to MAP_LVALUE. Update call to c_parser_omp_variable_list. (c_parser_oacc_data_clause): Update calls to c_parser_omp_var_list_parens. (c_parser_omp_clause_reduction): Use OMP_ARRAY_SECTION tree node instead of TREE_LIST for array sections. (c_parser_omp_target): Allow GOMP_MAP_ATTACH. * c-tree.h (c_omp_array_section_p): Add extern declaration. (build_omp_array_section): Add prototype. * c-typeck.cc (c_omp_array_section_p): Add flag. (mark_exp_read): Support OMP_ARRAY_SECTION. (build_omp_array_section): Add function. (build_external_ref): Tweak error path for OpenMP array sections. (handle_omp_array_sections_1): Use OMP_ARRAY_SECTION tree code instead of TREE_LIST. Handle more kinds of expressions. (c_oacc_check_attachments): Use OMP_ARRAY_SECTION instead of TREE_LIST for array sections. (c_finish_omp_clauses): Use OMP_ARRAY_SECTION instead of TREE_LIST. Check for supported expression types. gcc/testsuite/ * gcc.dg/gomp/bad-array-section-c-1.c: New test. * gcc.dg/gomp/bad-array-section-c-2.c: New test. * gcc.dg/gomp/bad-array-section-c-3.c: New test. * gcc.dg/gomp/bad-array-section-c-4.c: New test. * gcc.dg/gomp/bad-array-section-c-5.c: New test. * gcc.dg/gomp/bad-array-section-c-6.c: New test. * gcc.dg/gomp/bad-array-section-c-7.c: New test. * gcc.dg/gomp/bad-array-section-c-8.c: New test. libgomp/ * libgomp.texi: C/C++ lvalues are supported now for map/to/from. * testsuite/libgomp.c-c++-common/ind-base-4.c: New test. * testsuite/libgomp.c-c++-common/unary-ptr-1.c: New test.
This commit is contained in:
parent
61b493f17e
commit
b5476e4c88
@ -1650,6 +1650,17 @@ c_pretty_printer::postfix_expression (tree e)
|
||||
pp_c_right_bracket (this);
|
||||
break;
|
||||
|
||||
case OMP_ARRAY_SECTION:
|
||||
postfix_expression (TREE_OPERAND (e, 0));
|
||||
pp_c_left_bracket (this);
|
||||
if (TREE_OPERAND (e, 1))
|
||||
expression (TREE_OPERAND (e, 1));
|
||||
pp_colon (this);
|
||||
if (TREE_OPERAND (e, 2))
|
||||
expression (TREE_OPERAND (e, 2));
|
||||
pp_c_right_bracket (this);
|
||||
break;
|
||||
|
||||
case CALL_EXPR:
|
||||
{
|
||||
call_expr_arg_iterator iter;
|
||||
@ -2699,6 +2710,7 @@ c_pretty_printer::expression (tree e)
|
||||
case POSTINCREMENT_EXPR:
|
||||
case POSTDECREMENT_EXPR:
|
||||
case ARRAY_REF:
|
||||
case OMP_ARRAY_SECTION:
|
||||
case CALL_EXPR:
|
||||
case COMPONENT_REF:
|
||||
case BIT_FIELD_REF:
|
||||
|
@ -6146,6 +6146,8 @@ c_parser_braced_init (c_parser *parser, tree type, bool nested_p,
|
||||
location_t brace_loc = c_parser_peek_token (parser)->location;
|
||||
gcc_obstack_init (&braced_init_obstack);
|
||||
gcc_assert (c_parser_next_token_is (parser, CPP_OPEN_BRACE));
|
||||
bool save_c_omp_array_section_p = c_omp_array_section_p;
|
||||
c_omp_array_section_p = false;
|
||||
matching_braces braces;
|
||||
braces.consume_open (parser);
|
||||
if (nested_p)
|
||||
@ -6184,6 +6186,7 @@ c_parser_braced_init (c_parser *parser, tree type, bool nested_p,
|
||||
break;
|
||||
}
|
||||
}
|
||||
c_omp_array_section_p = save_c_omp_array_section_p;
|
||||
c_token *next_tok = c_parser_peek_token (parser);
|
||||
if (next_tok->type != CPP_CLOSE_BRACE)
|
||||
{
|
||||
@ -9149,6 +9152,7 @@ c_parser_conditional_expression (c_parser *parser, struct c_expr *after,
|
||||
{
|
||||
struct c_expr cond, exp1, exp2, ret;
|
||||
location_t start, cond_loc, colon_loc;
|
||||
bool save_c_omp_array_section_p = c_omp_array_section_p;
|
||||
|
||||
gcc_assert (!after || c_dialect_objc ());
|
||||
|
||||
@ -9156,6 +9160,7 @@ c_parser_conditional_expression (c_parser *parser, struct c_expr *after,
|
||||
|
||||
if (c_parser_next_token_is_not (parser, CPP_QUERY))
|
||||
return cond;
|
||||
c_omp_array_section_p = false;
|
||||
if (cond.value != error_mark_node)
|
||||
start = cond.get_start ();
|
||||
else
|
||||
@ -9208,6 +9213,7 @@ c_parser_conditional_expression (c_parser *parser, struct c_expr *after,
|
||||
ret.set_error ();
|
||||
ret.original_code = ERROR_MARK;
|
||||
ret.original_type = NULL;
|
||||
c_omp_array_section_p = save_c_omp_array_section_p;
|
||||
return ret;
|
||||
}
|
||||
{
|
||||
@ -9254,6 +9260,7 @@ c_parser_conditional_expression (c_parser *parser, struct c_expr *after,
|
||||
}
|
||||
set_c_expr_source_range (&ret, start, exp2.get_finish ());
|
||||
ret.m_decimal = 0;
|
||||
c_omp_array_section_p = save_c_omp_array_section_p;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -10705,6 +10712,7 @@ c_parser_postfix_expression (c_parser *parser)
|
||||
/* A statement expression. */
|
||||
tree stmt;
|
||||
location_t brace_loc;
|
||||
bool save_c_omp_array_section_p = c_omp_array_section_p;
|
||||
c_parser_consume_token (parser);
|
||||
brace_loc = c_parser_peek_token (parser)->location;
|
||||
c_parser_consume_token (parser);
|
||||
@ -10721,6 +10729,7 @@ c_parser_postfix_expression (c_parser *parser)
|
||||
expr.set_error ();
|
||||
break;
|
||||
}
|
||||
c_omp_array_section_p = false;
|
||||
stmt = c_begin_stmt_expr ();
|
||||
c_parser_compound_statement_nostart (parser);
|
||||
location_t close_loc = c_parser_peek_token (parser)->location;
|
||||
@ -10731,6 +10740,7 @@ c_parser_postfix_expression (c_parser *parser)
|
||||
expr.value = c_finish_stmt_expr (brace_loc, stmt);
|
||||
set_c_expr_source_range (&expr, loc, close_loc);
|
||||
mark_exp_read (expr.value);
|
||||
c_omp_array_section_p = save_c_omp_array_section_p;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -12480,7 +12490,7 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
|
||||
struct c_expr expr)
|
||||
{
|
||||
struct c_expr orig_expr;
|
||||
tree ident, idx;
|
||||
tree ident, idx, len;
|
||||
location_t sizeof_arg_loc[6], comp_loc;
|
||||
tree sizeof_arg[6];
|
||||
unsigned int literal_zero_mask;
|
||||
@ -12499,12 +12509,29 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
|
||||
case CPP_OPEN_SQUARE:
|
||||
/* Array reference. */
|
||||
c_parser_consume_token (parser);
|
||||
idx = c_parser_expression (parser).value;
|
||||
idx = len = NULL_TREE;
|
||||
if (!c_omp_array_section_p
|
||||
|| c_parser_next_token_is_not (parser, CPP_COLON))
|
||||
idx = c_parser_expression (parser).value;
|
||||
|
||||
if (c_omp_array_section_p
|
||||
&& c_parser_next_token_is (parser, CPP_COLON))
|
||||
{
|
||||
c_parser_consume_token (parser);
|
||||
if (c_parser_next_token_is_not (parser, CPP_CLOSE_SQUARE))
|
||||
len = c_parser_expression (parser).value;
|
||||
|
||||
expr.value = build_omp_array_section (op_loc, expr.value, idx,
|
||||
len);
|
||||
}
|
||||
else
|
||||
expr.value = build_array_ref (op_loc, expr.value, idx);
|
||||
|
||||
c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
|
||||
"expected %<]%>");
|
||||
|
||||
start = expr.get_start ();
|
||||
finish = parser->tokens_buf[0].location;
|
||||
expr.value = build_array_ref (op_loc, expr.value, idx);
|
||||
set_c_expr_source_range (&expr, start, finish);
|
||||
expr.original_code = ERROR_MARK;
|
||||
expr.original_type = NULL;
|
||||
@ -12829,6 +12856,8 @@ c_parser_expr_list (c_parser *parser, bool convert_p, bool fold_p,
|
||||
vec<tree, va_gc> *orig_types;
|
||||
struct c_expr expr;
|
||||
unsigned int idx = 0;
|
||||
bool save_c_omp_array_section_p = c_omp_array_section_p;
|
||||
c_omp_array_section_p = false;
|
||||
|
||||
ret = make_tree_vector ();
|
||||
if (p_orig_types == NULL)
|
||||
@ -12882,6 +12911,7 @@ c_parser_expr_list (c_parser *parser, bool convert_p, bool fold_p,
|
||||
}
|
||||
if (orig_types)
|
||||
*p_orig_types = orig_types;
|
||||
c_omp_array_section_p = save_c_omp_array_section_p;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -15126,7 +15156,7 @@ static tree
|
||||
c_parser_omp_variable_list (c_parser *parser,
|
||||
location_t clause_loc,
|
||||
enum omp_clause_code kind, tree list,
|
||||
bool allow_deref = false)
|
||||
bool map_lvalue = false)
|
||||
{
|
||||
auto_vec<omp_dim> dims;
|
||||
bool array_section_p;
|
||||
@ -15137,6 +15167,8 @@ c_parser_omp_variable_list (c_parser *parser,
|
||||
|
||||
while (1)
|
||||
{
|
||||
tree t = NULL_TREE;
|
||||
|
||||
if (kind == OMP_CLAUSE_DEPEND || kind == OMP_CLAUSE_AFFINITY)
|
||||
{
|
||||
if (c_parser_next_token_is_not (parser, CPP_NAME)
|
||||
@ -15217,8 +15249,96 @@ c_parser_omp_variable_list (c_parser *parser,
|
||||
parser->tokens = tokens.address ();
|
||||
parser->tokens_avail = tokens.length ();
|
||||
}
|
||||
else if (map_lvalue
|
||||
&& (kind == OMP_CLAUSE_MAP
|
||||
|| kind == OMP_CLAUSE_TO
|
||||
|| kind == OMP_CLAUSE_FROM))
|
||||
{
|
||||
location_t loc = c_parser_peek_token (parser)->location;
|
||||
bool save_c_omp_array_section_p = c_omp_array_section_p;
|
||||
c_omp_array_section_p = true;
|
||||
c_expr expr = c_parser_expr_no_commas (parser, NULL);
|
||||
if (expr.value != error_mark_node)
|
||||
mark_exp_read (expr.value);
|
||||
c_omp_array_section_p = save_c_omp_array_section_p;
|
||||
tree decl = expr.value;
|
||||
|
||||
tree t = NULL_TREE;
|
||||
/* This code rewrites a parsed expression containing various tree
|
||||
codes used to represent array accesses into a more uniform nest of
|
||||
OMP_ARRAY_SECTION nodes before it is processed by
|
||||
c-typeck.cc:handle_omp_array_sections_1. It might be more
|
||||
efficient to move this logic to that function instead, analysing
|
||||
the parsed expression directly rather than this preprocessed
|
||||
form. (See also equivalent code in cp/parser.cc,
|
||||
cp/semantics.cc). */
|
||||
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 (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);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = dims.length () - 1; i >= 0; i--)
|
||||
decl = build_omp_array_section (loc, decl, dims[i].low_bound,
|
||||
dims[i].length);
|
||||
}
|
||||
else if (TREE_CODE (decl) == INDIRECT_REF)
|
||||
{
|
||||
/* Turn indirection of a pointer "*foo" into "foo[0:1]". */
|
||||
decl = TREE_OPERAND (decl, 0);
|
||||
STRIP_NOPS (decl);
|
||||
|
||||
decl = build_omp_array_section (loc, decl, integer_zero_node,
|
||||
integer_one_node);
|
||||
}
|
||||
else if (TREE_CODE (decl) == ARRAY_REF)
|
||||
{
|
||||
tree idx = TREE_OPERAND (decl, 1);
|
||||
|
||||
decl = TREE_OPERAND (decl, 0);
|
||||
STRIP_NOPS (decl);
|
||||
|
||||
decl = build_omp_array_section (loc, decl, idx, integer_one_node);
|
||||
}
|
||||
else if (TREE_CODE (decl) == NON_LVALUE_EXPR
|
||||
|| CONVERT_EXPR_P (decl))
|
||||
decl = TREE_OPERAND (decl, 0);
|
||||
|
||||
tree u = build_omp_clause (clause_loc, kind);
|
||||
OMP_CLAUSE_DECL (u) = decl;
|
||||
OMP_CLAUSE_CHAIN (u) = list;
|
||||
list = u;
|
||||
|
||||
goto next_item;
|
||||
}
|
||||
|
||||
if (c_parser_next_token_is (parser, CPP_NAME)
|
||||
&& c_parser_peek_token (parser)->id_kind == C_ID_ID)
|
||||
@ -15269,8 +15389,7 @@ c_parser_omp_variable_list (c_parser *parser,
|
||||
case OMP_CLAUSE_TO:
|
||||
start_component_ref:
|
||||
while (c_parser_next_token_is (parser, CPP_DOT)
|
||||
|| (allow_deref
|
||||
&& c_parser_next_token_is (parser, CPP_DEREF)))
|
||||
|| c_parser_next_token_is (parser, CPP_DEREF))
|
||||
{
|
||||
location_t op_loc = c_parser_peek_token (parser)->location;
|
||||
location_t arrow_loc = UNKNOWN_LOCATION;
|
||||
@ -15371,9 +15490,7 @@ c_parser_omp_variable_list (c_parser *parser,
|
||||
|| kind == OMP_CLAUSE_TO)
|
||||
&& !array_section_p
|
||||
&& (c_parser_next_token_is (parser, CPP_DOT)
|
||||
|| (allow_deref
|
||||
&& c_parser_next_token_is (parser,
|
||||
CPP_DEREF))))
|
||||
|| c_parser_next_token_is (parser, CPP_DEREF)))
|
||||
{
|
||||
for (unsigned i = 0; i < dims.length (); i++)
|
||||
{
|
||||
@ -15385,7 +15502,9 @@ c_parser_omp_variable_list (c_parser *parser,
|
||||
}
|
||||
else
|
||||
for (unsigned i = 0; i < dims.length (); i++)
|
||||
t = tree_cons (dims[i].low_bound, dims[i].length, t);
|
||||
t = build_omp_array_section (clause_loc, t,
|
||||
dims[i].low_bound,
|
||||
dims[i].length);
|
||||
}
|
||||
|
||||
if ((kind == OMP_CLAUSE_DEPEND || kind == OMP_CLAUSE_AFFINITY)
|
||||
@ -15433,6 +15552,8 @@ c_parser_omp_variable_list (c_parser *parser,
|
||||
parser->tokens = saved_tokens;
|
||||
parser->tokens_avail = tokens_avail;
|
||||
}
|
||||
|
||||
next_item:
|
||||
if (c_parser_next_token_is_not (parser, CPP_COMMA))
|
||||
break;
|
||||
|
||||
@ -15449,7 +15570,7 @@ c_parser_omp_variable_list (c_parser *parser,
|
||||
|
||||
static tree
|
||||
c_parser_omp_var_list_parens (c_parser *parser, enum omp_clause_code kind,
|
||||
tree list, bool allow_deref = false)
|
||||
tree list, bool map_lvalue = false)
|
||||
{
|
||||
/* The clauses location. */
|
||||
location_t loc = c_parser_peek_token (parser)->location;
|
||||
@ -15470,7 +15591,7 @@ c_parser_omp_var_list_parens (c_parser *parser, enum omp_clause_code kind,
|
||||
matching_parens parens;
|
||||
if (parens.require_open (parser))
|
||||
{
|
||||
list = c_parser_omp_variable_list (parser, loc, kind, list, allow_deref);
|
||||
list = c_parser_omp_variable_list (parser, loc, kind, list, map_lvalue);
|
||||
parens.skip_until_found_close (parser);
|
||||
}
|
||||
return list;
|
||||
@ -15541,7 +15662,7 @@ c_parser_oacc_data_clause (c_parser *parser, pragma_omp_clause c_kind,
|
||||
gcc_unreachable ();
|
||||
}
|
||||
tree nl, c;
|
||||
nl = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_MAP, list, true);
|
||||
nl = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_MAP, list, false);
|
||||
|
||||
for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
|
||||
OMP_CLAUSE_SET_MAP_KIND (c, kind);
|
||||
@ -17221,13 +17342,15 @@ c_parser_omp_clause_reduction (c_parser *parser, enum omp_clause_code kind,
|
||||
for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
|
||||
{
|
||||
tree d = OMP_CLAUSE_DECL (c), type;
|
||||
if (TREE_CODE (d) != TREE_LIST)
|
||||
if (TREE_CODE (d) != OMP_ARRAY_SECTION)
|
||||
type = TREE_TYPE (d);
|
||||
else
|
||||
{
|
||||
int cnt = 0;
|
||||
tree t;
|
||||
for (t = d; TREE_CODE (t) == TREE_LIST; t = TREE_CHAIN (t))
|
||||
for (t = d;
|
||||
TREE_CODE (t) == OMP_ARRAY_SECTION;
|
||||
t = TREE_OPERAND (t, 0))
|
||||
cnt++;
|
||||
type = TREE_TYPE (t);
|
||||
while (cnt > 0)
|
||||
|
@ -737,6 +737,7 @@ extern int in_alignof;
|
||||
extern int in_sizeof;
|
||||
extern int in_typeof;
|
||||
extern bool c_in_omp_for;
|
||||
extern bool c_omp_array_section_p;
|
||||
|
||||
extern tree c_last_sizeof_arg;
|
||||
extern location_t c_last_sizeof_loc;
|
||||
@ -777,6 +778,7 @@ extern tree composite_type (tree, tree);
|
||||
extern tree build_component_ref (location_t, tree, tree, location_t,
|
||||
location_t);
|
||||
extern tree build_array_ref (location_t, tree, tree);
|
||||
extern tree build_omp_array_section (location_t, tree, tree, tree);
|
||||
extern tree build_external_ref (location_t, tree, bool, tree *);
|
||||
extern void pop_maybe_used (bool);
|
||||
extern struct c_expr c_expr_sizeof_expr (location_t, struct c_expr);
|
||||
|
@ -76,6 +76,9 @@ int in_typeof;
|
||||
/* True when parsing OpenMP loop expressions. */
|
||||
bool c_in_omp_for;
|
||||
|
||||
/* True when parsing OpenMP map clause. */
|
||||
bool c_omp_array_section_p;
|
||||
|
||||
/* The argument of last parsed sizeof expression, only to be tested
|
||||
if expr.original_code == SIZEOF_EXPR. */
|
||||
tree c_last_sizeof_arg;
|
||||
@ -1987,6 +1990,13 @@ mark_exp_read (tree exp)
|
||||
case C_MAYBE_CONST_EXPR:
|
||||
mark_exp_read (TREE_OPERAND (exp, 1));
|
||||
break;
|
||||
case OMP_ARRAY_SECTION:
|
||||
mark_exp_read (TREE_OPERAND (exp, 0));
|
||||
if (TREE_OPERAND (exp, 1))
|
||||
mark_exp_read (TREE_OPERAND (exp, 1));
|
||||
if (TREE_OPERAND (exp, 2))
|
||||
mark_exp_read (TREE_OPERAND (exp, 2));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -2899,6 +2909,53 @@ build_array_ref (location_t loc, tree array, tree index)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* Build an OpenMP array section reference, creating an exact type for the
|
||||
resulting expression based on the element type and bounds if possible. If
|
||||
we have variable bounds, create an incomplete array type for the result
|
||||
instead. */
|
||||
|
||||
tree
|
||||
build_omp_array_section (location_t loc, tree array, tree index, tree length)
|
||||
{
|
||||
tree type = TREE_TYPE (array);
|
||||
gcc_assert (type);
|
||||
|
||||
tree sectype, eltype = TREE_TYPE (type);
|
||||
|
||||
/* It's not an array or pointer type. Just reuse the type of the original
|
||||
expression as the type of the array section (an error will be raised
|
||||
anyway, later). */
|
||||
if (eltype == NULL_TREE || error_operand_p (eltype))
|
||||
sectype = TREE_TYPE (array);
|
||||
else
|
||||
{
|
||||
tree idxtype = NULL_TREE;
|
||||
|
||||
if (index != NULL_TREE
|
||||
&& length != NULL_TREE
|
||||
&& INTEGRAL_TYPE_P (TREE_TYPE (index))
|
||||
&& INTEGRAL_TYPE_P (TREE_TYPE (length)))
|
||||
{
|
||||
tree low = fold_convert (sizetype, index);
|
||||
tree high = fold_convert (sizetype, length);
|
||||
high = size_binop (PLUS_EXPR, low, high);
|
||||
high = size_binop (MINUS_EXPR, high, size_one_node);
|
||||
idxtype = build_range_type (sizetype, low, high);
|
||||
}
|
||||
else if ((index == NULL_TREE || integer_zerop (index))
|
||||
&& length != NULL_TREE
|
||||
&& INTEGRAL_TYPE_P (TREE_TYPE (length)))
|
||||
idxtype = build_index_type (length);
|
||||
|
||||
gcc_assert (!error_operand_p (idxtype));
|
||||
|
||||
sectype = build_array_type (eltype, idxtype);
|
||||
}
|
||||
|
||||
return build3_loc (loc, OMP_ARRAY_SECTION, sectype, array, index, length);
|
||||
}
|
||||
|
||||
|
||||
/* Build an external reference to identifier ID. FUN indicates
|
||||
whether this will be used for a function call. LOC is the source
|
||||
@ -2938,7 +2995,11 @@ build_external_ref (location_t loc, tree id, bool fun, tree *type)
|
||||
return error_mark_node;
|
||||
}
|
||||
|
||||
if (TREE_TYPE (ref) == error_mark_node)
|
||||
/* For an OpenMP map clause, we can get better diagnostics for decls with
|
||||
unmappable types if we return the decl with an error_mark_node type,
|
||||
rather than returning error_mark_node for the decl itself. */
|
||||
if (TREE_TYPE (ref) == error_mark_node
|
||||
&& !c_omp_array_section_p)
|
||||
return error_mark_node;
|
||||
|
||||
if (TREE_UNAVAILABLE (ref))
|
||||
@ -13762,7 +13823,7 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
|
||||
{
|
||||
tree ret, low_bound, length, type;
|
||||
bool openacc = (ort & C_ORT_ACC) != 0;
|
||||
if (TREE_CODE (t) != TREE_LIST)
|
||||
if (TREE_CODE (t) != OMP_ARRAY_SECTION)
|
||||
{
|
||||
if (error_operand_p (t))
|
||||
return error_mark_node;
|
||||
@ -13787,7 +13848,9 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
|
||||
t = ai.unconverted_ref_origin ();
|
||||
if (t == error_mark_node)
|
||||
return error_mark_node;
|
||||
if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL)
|
||||
if (!VAR_P (t)
|
||||
&& (ort == C_ORT_ACC || !EXPR_P (t))
|
||||
&& TREE_CODE (t) != PARM_DECL)
|
||||
{
|
||||
if (DECL_P (t))
|
||||
error_at (OMP_CLAUSE_LOCATION (c),
|
||||
@ -13835,14 +13898,14 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = handle_omp_array_sections_1 (c, TREE_CHAIN (t), types,
|
||||
ret = handle_omp_array_sections_1 (c, TREE_OPERAND (t, 0), types,
|
||||
maybe_zero_len, first_non_one, ort);
|
||||
if (ret == error_mark_node || ret == NULL_TREE)
|
||||
return ret;
|
||||
|
||||
type = TREE_TYPE (ret);
|
||||
low_bound = TREE_PURPOSE (t);
|
||||
length = TREE_VALUE (t);
|
||||
low_bound = TREE_OPERAND (t, 1);
|
||||
length = TREE_OPERAND (t, 2);
|
||||
|
||||
if (low_bound == error_mark_node || length == error_mark_node)
|
||||
return error_mark_node;
|
||||
@ -14035,7 +14098,7 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
|
||||
tree lb = save_expr (low_bound);
|
||||
if (lb != low_bound)
|
||||
{
|
||||
TREE_PURPOSE (t) = lb;
|
||||
TREE_OPERAND (t, 1) = lb;
|
||||
low_bound = lb;
|
||||
}
|
||||
}
|
||||
@ -14066,14 +14129,15 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
|
||||
array-section-subscript, the array section could be non-contiguous. */
|
||||
if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
|
||||
&& OMP_CLAUSE_CODE (c) != OMP_CLAUSE_AFFINITY
|
||||
&& TREE_CODE (TREE_CHAIN (t)) == TREE_LIST)
|
||||
&& TREE_CODE (TREE_OPERAND (t, 0)) == OMP_ARRAY_SECTION)
|
||||
{
|
||||
/* If any prior dimension has a non-one length, then deem this
|
||||
array section as non-contiguous. */
|
||||
for (tree d = TREE_CHAIN (t); TREE_CODE (d) == TREE_LIST;
|
||||
d = TREE_CHAIN (d))
|
||||
for (tree d = TREE_OPERAND (t, 0);
|
||||
TREE_CODE (d) == OMP_ARRAY_SECTION;
|
||||
d = TREE_OPERAND (d, 0))
|
||||
{
|
||||
tree d_length = TREE_VALUE (d);
|
||||
tree d_length = TREE_OPERAND (d, 2);
|
||||
if (d_length == NULL_TREE || !integer_onep (d_length))
|
||||
{
|
||||
error_at (OMP_CLAUSE_LOCATION (c),
|
||||
@ -14096,7 +14160,7 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
|
||||
tree lb = save_expr (low_bound);
|
||||
if (lb != low_bound)
|
||||
{
|
||||
TREE_PURPOSE (t) = lb;
|
||||
TREE_OPERAND (t, 1) = lb;
|
||||
low_bound = lb;
|
||||
}
|
||||
ret = build_array_ref (OMP_CLAUSE_LOCATION (c), ret, low_bound);
|
||||
@ -14159,10 +14223,10 @@ handle_omp_array_sections (tree &c, enum c_omp_region_type ort)
|
||||
maybe_zero_len = true;
|
||||
|
||||
for (i = num, t = OMP_CLAUSE_DECL (c); i > 0;
|
||||
t = TREE_CHAIN (t))
|
||||
t = TREE_OPERAND (t, 0))
|
||||
{
|
||||
tree low_bound = TREE_PURPOSE (t);
|
||||
tree length = TREE_VALUE (t);
|
||||
tree low_bound = TREE_OPERAND (t, 1);
|
||||
tree length = TREE_OPERAND (t, 2);
|
||||
|
||||
i--;
|
||||
if (low_bound
|
||||
@ -14587,8 +14651,8 @@ c_oacc_check_attachments (tree c)
|
||||
{
|
||||
tree t = OMP_CLAUSE_DECL (c);
|
||||
|
||||
while (TREE_CODE (t) == TREE_LIST)
|
||||
t = TREE_CHAIN (t);
|
||||
while (TREE_CODE (t) == OMP_ARRAY_SECTION)
|
||||
t = TREE_OPERAND (t, 0);
|
||||
|
||||
if (TREE_CODE (TREE_TYPE (t)) != POINTER_TYPE)
|
||||
{
|
||||
@ -14696,7 +14760,7 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
|
||||
case OMP_CLAUSE_TASK_REDUCTION:
|
||||
need_implicitly_determined = true;
|
||||
t = OMP_CLAUSE_DECL (c);
|
||||
if (TREE_CODE (t) == TREE_LIST)
|
||||
if (TREE_CODE (t) == OMP_ARRAY_SECTION)
|
||||
{
|
||||
if (handle_omp_array_sections (c, ort))
|
||||
{
|
||||
@ -15317,7 +15381,7 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
|
||||
}
|
||||
else
|
||||
last_iterators = NULL_TREE;
|
||||
if (TREE_CODE (t) == TREE_LIST)
|
||||
if (TREE_CODE (t) == OMP_ARRAY_SECTION)
|
||||
{
|
||||
if (handle_omp_array_sections (c, ort))
|
||||
remove = true;
|
||||
@ -15427,7 +15491,7 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
|
||||
auto_vec<omp_addr_token *, 10> addr_tokens;
|
||||
|
||||
t = OMP_CLAUSE_DECL (c);
|
||||
if (TREE_CODE (t) == TREE_LIST)
|
||||
if (TREE_CODE (t) == OMP_ARRAY_SECTION)
|
||||
{
|
||||
grp_start_p = pc;
|
||||
grp_sentinel = OMP_CLAUSE_CHAIN (c);
|
||||
@ -15597,6 +15661,9 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
|
||||
|
||||
if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL)
|
||||
{
|
||||
if (ort != C_ORT_ACC && EXPR_P (t))
|
||||
break;
|
||||
|
||||
error_at (OMP_CLAUSE_LOCATION (c),
|
||||
"%qE is not a variable in %qs clause", t,
|
||||
omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
|
||||
@ -15827,7 +15894,7 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
|
||||
|
||||
case OMP_CLAUSE_HAS_DEVICE_ADDR:
|
||||
t = OMP_CLAUSE_DECL (c);
|
||||
if (TREE_CODE (t) == TREE_LIST)
|
||||
if (TREE_CODE (t) == OMP_ARRAY_SECTION)
|
||||
{
|
||||
if (handle_omp_array_sections (c, ort))
|
||||
remove = true;
|
||||
|
16
gcc/testsuite/gcc.dg/gomp/bad-array-section-c-1.c
Normal file
16
gcc/testsuite/gcc.dg/gomp/bad-array-section-c-1.c
Normal file
@ -0,0 +1,16 @@
|
||||
/* { dg-do compile } */
|
||||
|
||||
int foo (int *ptr);
|
||||
|
||||
int main()
|
||||
{
|
||||
int arr[20];
|
||||
/* Reject array section as function argument. */
|
||||
#pragma omp target map(foo(arr[3:5]))
|
||||
/* { dg-error {expected '\]' before ':' token} "" { target *-*-* } .-1 } */
|
||||
/* { dg-error {passing argument 1 of 'foo' makes pointer from integer without a cast} "" { target *-*-* } .-2 } */
|
||||
/* { dg-message {sorry, unimplemented: unsupported map expression} "" { target *-*-* } .-3 } */
|
||||
{ }
|
||||
|
||||
return 0;
|
||||
}
|
13
gcc/testsuite/gcc.dg/gomp/bad-array-section-c-2.c
Normal file
13
gcc/testsuite/gcc.dg/gomp/bad-array-section-c-2.c
Normal file
@ -0,0 +1,13 @@
|
||||
/* { dg-do compile } */
|
||||
|
||||
int main()
|
||||
{
|
||||
int arr[20];
|
||||
/* Reject array section in statement expression. */
|
||||
#pragma omp target map( ({ int x = 5; arr[0:x]; }) )
|
||||
/* { dg-error {expected '\]' before ':' token} "" { target *-*-* } .-1 } */
|
||||
/* { dg-message {sorry, unimplemented: unsupported map expression} "" { target *-*-* } .-2 } */
|
||||
{ }
|
||||
|
||||
return 0;
|
||||
}
|
24
gcc/testsuite/gcc.dg/gomp/bad-array-section-c-3.c
Normal file
24
gcc/testsuite/gcc.dg/gomp/bad-array-section-c-3.c
Normal file
@ -0,0 +1,24 @@
|
||||
/* { dg-do compile } */
|
||||
|
||||
struct S {
|
||||
int *ptr;
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
int arr[20];
|
||||
|
||||
/* Reject array section in compound initialiser. */
|
||||
#pragma omp target map( (struct S) { .ptr = (int *) arr[5:5] } )
|
||||
/* { dg-error {expected '\]' before ':' token} "" { target *-*-* } .-1 } */
|
||||
/* { dg-warning {cast to pointer from integer of different size} "" { target *-*-* } .-2 } */
|
||||
/* { dg-message {sorry, unimplemented: unsupported map expression} "" { target *-*-* } .-3 } */
|
||||
{ }
|
||||
|
||||
/* ...and this is unsupported too (probably not useful anyway). */
|
||||
#pragma omp target map( (struct S) { .ptr = &arr[5] } )
|
||||
/* { dg-message {sorry, unimplemented: unsupported map expression} "" { target *-*-* } .-1 } */
|
||||
{ }
|
||||
|
||||
return 0;
|
||||
}
|
26
gcc/testsuite/gcc.dg/gomp/bad-array-section-c-4.c
Normal file
26
gcc/testsuite/gcc.dg/gomp/bad-array-section-c-4.c
Normal file
@ -0,0 +1,26 @@
|
||||
/* { dg-do compile } */
|
||||
|
||||
int x;
|
||||
|
||||
int main()
|
||||
{
|
||||
int arr[20];
|
||||
int *ptr;
|
||||
/* "arr[1:10]" looks like it might be an expression of array type, hence
|
||||
able to be indexed (again). This isn't allowed, though. */
|
||||
#pragma omp target map(arr[1:10][2])
|
||||
/* { dg-error {'arr\[1\]' does not have pointer or array type} "" { target *-*-* } .-1 } */
|
||||
{ }
|
||||
#pragma omp target map(arr[1:x][2])
|
||||
/* { dg-error {'arr\[1\]' does not have pointer or array type} "" { target *-*-* } .-1 } */
|
||||
{ }
|
||||
/* ...and nor is this. */
|
||||
#pragma omp target map(ptr[1:10][2])
|
||||
/* { dg-error {'\*\(ptr \+ [0-9]+\)' does not have pointer or array type} "" { target *-*-* } .-1 } */
|
||||
{ }
|
||||
#pragma omp target map(ptr[1:x][2])
|
||||
/* { dg-error {'\*\(ptr \+ [0-9]+\)' does not have pointer or array type} "" { target *-*-* } .-1 } */
|
||||
{ }
|
||||
|
||||
return 0;
|
||||
}
|
15
gcc/testsuite/gcc.dg/gomp/bad-array-section-c-5.c
Normal file
15
gcc/testsuite/gcc.dg/gomp/bad-array-section-c-5.c
Normal file
@ -0,0 +1,15 @@
|
||||
/* { dg-do compile } */
|
||||
|
||||
int partly = 0;
|
||||
|
||||
int main()
|
||||
{
|
||||
int arr[20];
|
||||
#pragma omp target map(partly ? arr[5:5] : arr)
|
||||
/* { dg-error {expected '\]' before ':' token} "" { target *-*-* } .-1 } */
|
||||
/* { dg-error {pointer/integer type mismatch in conditional expression} "" { target *-*-* } .-2 } */
|
||||
/* { dg-message {sorry, unimplemented: unsupported map expression} "" { target *-*-* } .-3 } */
|
||||
{ }
|
||||
|
||||
return 0;
|
||||
}
|
16
gcc/testsuite/gcc.dg/gomp/bad-array-section-c-6.c
Normal file
16
gcc/testsuite/gcc.dg/gomp/bad-array-section-c-6.c
Normal file
@ -0,0 +1,16 @@
|
||||
/* { dg-do compile } */
|
||||
|
||||
int x;
|
||||
|
||||
int main()
|
||||
{
|
||||
int arr[20];
|
||||
#pragma omp target map(arr[5:5] * 2)
|
||||
/* { dg-error {invalid operands to binary \*} "" { target *-*-* } .-1 } */
|
||||
{ }
|
||||
#pragma omp target map(arr[x:5] * 2)
|
||||
/* { dg-error {invalid operands to binary \*} "" { target *-*-* } .-1 } */
|
||||
{ }
|
||||
|
||||
return 0;
|
||||
}
|
26
gcc/testsuite/gcc.dg/gomp/bad-array-section-c-7.c
Normal file
26
gcc/testsuite/gcc.dg/gomp/bad-array-section-c-7.c
Normal file
@ -0,0 +1,26 @@
|
||||
/* { dg-do compile } */
|
||||
|
||||
int x;
|
||||
|
||||
struct T {
|
||||
int arr[20];
|
||||
};
|
||||
|
||||
struct S {
|
||||
struct T *tvec;
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
struct S *s;
|
||||
/* You can't use an array section like this. Make sure sensible errors are
|
||||
reported. */
|
||||
#pragma omp target map(s->tvec[3:5].arr[0:20])
|
||||
/* { dg-error {'\(struct T \*\)&s->tvec\[3:5\]' is a pointer; did you mean to use '->'\?} "" { target *-*-* } .-1 } */
|
||||
{ }
|
||||
#pragma omp target map(s->tvec[5:x].arr[0:20])
|
||||
/* { dg-error {'\(struct T \*\)&s->tvec\[5:x\]' is a pointer; did you mean to use '->'\?} "" { target *-*-* } .-1 } */
|
||||
{ }
|
||||
|
||||
return 0;
|
||||
}
|
21
gcc/testsuite/gcc.dg/gomp/bad-array-section-c-8.c
Normal file
21
gcc/testsuite/gcc.dg/gomp/bad-array-section-c-8.c
Normal file
@ -0,0 +1,21 @@
|
||||
/* { dg-do compile } */
|
||||
|
||||
int x;
|
||||
|
||||
int main()
|
||||
{
|
||||
int arr1[40];
|
||||
int arr2[40];
|
||||
#pragma omp target map(arr1[arr2[4:5]:arr2[6:7]])
|
||||
/* { dg-error {low bound 'arr2\[4:5\]' of array section does not have integral type} "" { target *-*-* } .-1 } */
|
||||
{ }
|
||||
#pragma omp target map(arr1[arr2[:1]:arr2[6:1]])
|
||||
/* { dg-error {low bound 'arr2\[:1\]' of array section does not have integral type} "" { target *-*-* } .-1 } */
|
||||
{ }
|
||||
#pragma omp target map(arr1[x:arr2[6:1]])
|
||||
/* { dg-error {length 'arr2\[6:1\]' of array section does not have integral type} "" { target *-*-* } .-1 } */
|
||||
{ }
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -242,7 +242,7 @@ The OpenMP 4.5 specification is fully supported.
|
||||
@item Discontiguous array section with @code{target update} construct
|
||||
@tab N @tab
|
||||
@item C/C++'s lvalue expressions in @code{to}, @code{from}
|
||||
and @code{map} clauses @tab N @tab
|
||||
and @code{map} clauses @tab Y @tab
|
||||
@item C/C++'s lvalue expressions in @code{depend} clauses @tab Y @tab
|
||||
@item Nested @code{declare target} directive @tab Y @tab
|
||||
@item Combined @code{master} constructs @tab Y @tab
|
||||
|
50
libgomp/testsuite/libgomp.c-c++-common/ind-base-4.c
Normal file
50
libgomp/testsuite/libgomp.c-c++-common/ind-base-4.c
Normal file
@ -0,0 +1,50 @@
|
||||
// { dg-do run }
|
||||
// { dg-options "-fopenmp" }
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int x[10];
|
||||
} S;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
S ***s;
|
||||
} T;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
T **t;
|
||||
} U;
|
||||
|
||||
void
|
||||
foo (void)
|
||||
{
|
||||
U *u = (U *) malloc (sizeof (U));
|
||||
T *real_t = (T *) malloc (sizeof (T));
|
||||
S *real_s = (S *) malloc (sizeof (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);
|
||||
free (real_s);
|
||||
free (real_t);
|
||||
free (u);
|
||||
}
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
foo ();
|
||||
return 0;
|
||||
}
|
16
libgomp/testsuite/libgomp.c-c++-common/unary-ptr-1.c
Normal file
16
libgomp/testsuite/libgomp.c-c++-common/unary-ptr-1.c
Normal file
@ -0,0 +1,16 @@
|
||||
#include <assert.h>
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
int y = 0;
|
||||
int *x = &y;
|
||||
|
||||
#pragma omp target map(*x)
|
||||
{
|
||||
(*x)++;
|
||||
}
|
||||
|
||||
assert (y == 1);
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user