aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/constexpr.cc1
-rw-r--r--gcc/cp/cp-tree.h2
-rw-r--r--gcc/cp/decl2.cc37
-rw-r--r--gcc/cp/error.cc9
-rw-r--r--gcc/cp/parser.cc208
-rw-r--r--gcc/cp/parser.h3
-rw-r--r--gcc/cp/pt.cc37
-rw-r--r--gcc/cp/semantics.cc69
-rw-r--r--gcc/cp/typeck.cc50
9 files changed, 372 insertions, 44 deletions
diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index e3f398b..37500b7 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -10105,6 +10105,7 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
case OACC_ENTER_DATA:
case OACC_EXIT_DATA:
case OACC_UPDATE:
+ case OMP_ARRAY_SECTION:
/* GCC internal stuff. */
case VA_ARG_EXPR:
case TRANSACTION_EXPR:
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index e43effa..86084b5 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -7069,6 +7069,7 @@ extern void grokclassfn (tree, tree,
enum overload_flags);
extern tree grok_array_decl (location_t, tree, tree,
vec<tree, va_gc> **, tsubst_flags_t);
+extern tree grok_omp_array_section (location_t, tree, tree, tree);
extern tree delete_sanity (location_t, tree, tree, bool,
int, tsubst_flags_t);
extern tree check_classfn (tree, tree, tree);
@@ -8172,6 +8173,7 @@ inline tree build_x_binary_op (const op_location_t &loc,
}
extern tree build_x_array_ref (location_t, tree, tree,
tsubst_flags_t);
+extern tree build_omp_array_section (location_t, tree, tree, tree);
extern tree build_x_unary_op (location_t,
enum tree_code, cp_expr,
tree, tsubst_flags_t);
diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc
index fb99656..5ceed56 100644
--- a/gcc/cp/decl2.cc
+++ b/gcc/cp/decl2.cc
@@ -617,6 +617,43 @@ grok_array_decl (location_t loc, tree array_expr, tree index_exp,
return expr;
}
+/* Build an OMP_ARRAY_SECTION expression, handling usage in template
+ definitions, etc. */
+
+tree
+grok_omp_array_section (location_t loc, tree array_expr, tree index,
+ tree length)
+{
+ tree orig_array_expr = array_expr;
+ tree orig_index = index;
+ tree orig_length = length;
+
+ if (error_operand_p (array_expr)
+ || error_operand_p (index)
+ || error_operand_p (length))
+ return error_mark_node;
+
+ if (processing_template_decl
+ && (type_dependent_expression_p (array_expr)
+ || type_dependent_expression_p (index)
+ || type_dependent_expression_p (length)))
+ return build_min_nt_loc (loc, OMP_ARRAY_SECTION, array_expr, index, length);
+
+ index = fold_non_dependent_expr (index);
+ length = fold_non_dependent_expr (length);
+
+ /* NOTE: We can pass through invalidly-typed index/length fields
+ here (e.g. if the user tries to use a floating-point index/length).
+ This is diagnosed later in semantics.cc:handle_omp_array_sections_1. */
+
+ tree expr = build_omp_array_section (loc, array_expr, index, length);
+
+ if (processing_template_decl)
+ expr = build_min_non_dep (OMP_ARRAY_SECTION, expr, orig_array_expr,
+ orig_index, orig_length);
+ return expr;
+}
+
/* Given the cast expression EXP, checking out its validity. Either return
an error_mark_node if there was an unavoidable error, return a cast to
void for trying to delete a pointer w/ the value 0, or return the
diff --git a/gcc/cp/error.cc b/gcc/cp/error.cc
index 9100496..a384f62 100644
--- a/gcc/cp/error.cc
+++ b/gcc/cp/error.cc
@@ -2497,6 +2497,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;
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index bc1683b..706ed21 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -4459,6 +4459,9 @@ cp_parser_new (cp_lexer *lexer)
parser->omp_declare_simd = NULL;
parser->oacc_routine = NULL;
+ /* Disallow OpenMP array sections in expressions. */
+ 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;
@@ -5462,6 +5465,7 @@ static cp_expr
cp_parser_statement_expr (cp_parser *parser)
{
cp_token_position start = cp_parser_start_tentative_firewall (parser);
+ auto oas = make_temp_override (parser->omp_array_section_p, false);
/* Consume the '('. */
location_t start_loc = cp_lexer_peek_token (parser->lexer)->location;
@@ -8299,6 +8303,7 @@ cp_parser_postfix_open_square_expression (cp_parser *parser,
releasing_vec expression_list = NULL;
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);
@@ -8306,6 +8311,10 @@ 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;
+ if (parser->omp_array_section_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,
@@ -8316,7 +8325,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 (cxx_dialect >= cxx23
&& cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_SQUARE))
@@ -8372,6 +8382,68 @@ cp_parser_postfix_open_square_expression (cp_parser *parser,
parser->greater_than_is_operator_p = saved_greater_than_is_operator_p;
+ if (cxx_dialect >= cxx23
+ && parser->omp_array_section_p
+ && expression_list.get () != NULL
+ && vec_safe_length (expression_list) > 1)
+ {
+ error_at (loc, "cannot use multidimensional subscript in OpenMP array "
+ "section");
+ index = error_mark_node;
+ }
+ 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))
+ {
+ if (cxx_dialect >= cxx23)
+ {
+ cp_expr expr
+ = cp_parser_parenthesized_expression_list_elt (parser,
+ /*cast_p=*/
+ false,
+ /*allow_exp_p=*/
+ true,
+ /*non_cst_p=*/
+ NULL);
+
+ if (expr == error_mark_node)
+ length = error_mark_node;
+ else
+ length = expr.get_value ();
+
+ if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
+ {
+ error_at (loc, "cannot use multidimensional subscript in "
+ "OpenMP array section");
+ length = error_mark_node;
+ }
+ }
+ else
+ length
+ = cp_parser_expression (parser, NULL, /*cast_p=*/false,
+ /*decltype_p=*/false,
+ /*warn_comma_p=*/warn_comma_subscript);
+ }
+
+ parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p;
+
+ if (index == error_mark_node || length == error_mark_node)
+ {
+ cp_parser_skip_to_closing_square_bracket (parser);
+ return error_mark_node;
+ }
+ else
+ cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE);
+
+ return grok_omp_array_section (input_location, 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);
@@ -8700,6 +8772,7 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
{
vec<tree, va_gc> *expression_list;
bool saved_greater_than_is_operator_p;
+ bool saved_omp_array_section_p;
/* Assume all the expressions will be constant. */
if (non_constant_p)
@@ -8717,6 +8790,9 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
= parser->greater_than_is_operator_p;
parser->greater_than_is_operator_p = true;
+ saved_omp_array_section_p = parser->omp_array_section_p;
+ parser->omp_array_section_p = false;
+
cp_expr expr (NULL_TREE);
/* Consume expressions until there are no more. */
@@ -8783,12 +8859,14 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
{
parser->greater_than_is_operator_p
= saved_greater_than_is_operator_p;
+ parser->omp_array_section_p = saved_omp_array_section_p;
return NULL;
}
}
parser->greater_than_is_operator_p
= saved_greater_than_is_operator_p;
+ parser->omp_array_section_p = saved_omp_array_section_p;
return expression_list;
}
@@ -11299,6 +11377,7 @@ cp_parser_lambda_expression (cp_parser* parser)
cp_binding_level* implicit_template_scope = parser->implicit_template_scope;
bool auto_is_implicit_function_template_parm_p
= parser->auto_is_implicit_function_template_parm_p;
+ bool saved_omp_array_section_p = parser->omp_array_section_p;
parser->num_template_parameter_lists = 0;
parser->in_statement = 0;
@@ -11307,6 +11386,7 @@ cp_parser_lambda_expression (cp_parser* parser)
parser->implicit_template_parms = 0;
parser->implicit_template_scope = 0;
parser->auto_is_implicit_function_template_parm_p = false;
+ parser->omp_array_section_p = false;
/* The body of a lambda in a discarded statement is not discarded. */
bool discarded = in_discarded_stmt;
@@ -11357,6 +11437,7 @@ cp_parser_lambda_expression (cp_parser* parser)
parser->implicit_template_scope = implicit_template_scope;
parser->auto_is_implicit_function_template_parm_p
= auto_is_implicit_function_template_parm_p;
+ parser->omp_array_section_p = saved_omp_array_section_p;
}
/* This field is only used during parsing of the lambda. */
@@ -25917,6 +25998,7 @@ cp_parser_braced_list (cp_parser *parser, bool *non_constant_p /*=nullptr*/)
{
tree initializer;
location_t start_loc = cp_lexer_peek_token (parser->lexer)->location;
+ auto oas = make_temp_override (parser->omp_array_section_p, false);
/* Consume the `{' token. */
matching_braces braces;
@@ -37862,7 +37944,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;
@@ -37879,6 +37961,104 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
if (kind == OMP_CLAUSE_DEPEND || kind == OMP_CLAUSE_AFFINITY)
cp_parser_parse_tentatively (parser);
+ /* This condition doesn't include OMP_CLAUSE_DEPEND or
+ OMP_CLAUSE_AFFINITY since lvalue ("locator list") parsing for those is
+ handled further down the function. */
+ else if (map_lvalue
+ && (kind == OMP_CLAUSE_MAP
+ || kind == OMP_CLAUSE_TO
+ || kind == OMP_CLAUSE_FROM))
+ {
+ 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);
+
+ /* 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
+ semantics.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. */
+ 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 = grok_omp_array_section (loc, decl, dims[i].low_bound,
+ dims[i].length);
+ }
+ else if (TREE_CODE (decl) == INDIRECT_REF)
+ {
+ bool ref_p = REFERENCE_REF_P (decl);
+
+ /* If we have "*foo" and
+ - it's an indirection of a reference, "unconvert" it, i.e.
+ strip the indirection (to just "foo").
+ - it's an indirection of a pointer, turn it into
+ "foo[0:1]". */
+ decl = TREE_OPERAND (decl, 0);
+ STRIP_NOPS (decl);
+
+ if (!ref_p)
+ decl = grok_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 = grok_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);
+
+ goto build_clause;
+ }
token = cp_lexer_peek_token (parser->lexer);
if (kind != 0
&& cp_parser_is_keyword (token, RID_THIS))
@@ -37957,8 +38137,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)
@@ -38044,9 +38223,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++)
{
@@ -38058,8 +38235,9 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
}
else
for (unsigned i = 0; i < dims.length (); i++)
- decl = tree_cons (dims[i].low_bound, dims[i].length, decl);
-
+ decl = build_omp_array_section (input_location, decl,
+ dims[i].low_bound,
+ dims[i].length);
break;
default:
break;
@@ -38080,6 +38258,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;
@@ -38129,7 +38308,7 @@ 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 (parser->lexer->in_omp_decl_attribute)
{
@@ -38148,7 +38327,7 @@ cp_parser_omp_var_list (cp_parser *parser, enum omp_clause_code kind, tree list,
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;
}
@@ -38217,7 +38396,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);
@@ -41157,8 +41336,13 @@ cp_parser_omp_clause_map (cp_parser *parser, tree list)
cp_lexer_consume_token (parser->lexer);
}
+ /* We introduce a scope here so that errors parsing e.g. "always", "close"
+ tokens do not propagate to later directives that might use them
+ legally. */
+ begin_scope (sk_omp, NULL);
nlist = cp_parser_omp_var_list_no_open (parser, OMP_CLAUSE_MAP, list,
NULL, true);
+ finish_scope ();
for (c = nlist; c != list; c = OMP_CLAUSE_CHAIN (c))
OMP_CLAUSE_SET_MAP_KIND (c, kind);
diff --git a/gcc/cp/parser.h b/gcc/cp/parser.h
index 8a40d38..373e78f 100644
--- a/gcc/cp/parser.h
+++ b/gcc/cp/parser.h
@@ -412,6 +412,9 @@ struct GTY(()) cp_parser {
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
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index e38e7a7..7237bd3 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -16838,6 +16838,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
case CALL_EXPR:
case ARRAY_REF:
case SCOPE_REF:
+ case OMP_ARRAY_SECTION:
/* We should use one of the expression tsubsts for these codes. */
gcc_unreachable ();
@@ -17432,6 +17433,21 @@ tsubst_omp_clause_decl (tree decl, tree args, tsubst_flags_t complain,
= OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (decl);
return ret;
}
+ else if (TREE_CODE (decl) == OMP_ARRAY_SECTION)
+ {
+ tree low_bound
+ = tsubst_stmt (TREE_OPERAND (decl, 1), args, complain, in_decl);
+ tree length = tsubst_stmt (TREE_OPERAND (decl, 2), args, complain,
+ in_decl);
+ tree base = tsubst_omp_clause_decl (TREE_OPERAND (decl, 0), args,
+ complain, in_decl, NULL);
+ if (TREE_OPERAND (decl, 0) == base
+ && TREE_OPERAND (decl, 1) == low_bound
+ && TREE_OPERAND (decl, 2) == length)
+ return decl;
+ return build3 (OMP_ARRAY_SECTION, TREE_TYPE (base), base, low_bound,
+ length);
+ }
tree ret = tsubst_stmt (decl, args, complain, in_decl);
/* Undo convert_from_reference tsubst_expr could have called. */
if (decl
@@ -20230,6 +20246,27 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
RECUR (TREE_OPERAND (t, 1)),
complain|decltype_flag));
+ case OMP_ARRAY_SECTION:
+ {
+ tree op0 = RECUR (TREE_OPERAND (t, 0));
+ tree op1 = NULL_TREE, op2 = NULL_TREE;
+ if (op0 == error_mark_node)
+ RETURN (error_mark_node);
+ if (TREE_OPERAND (t, 1))
+ {
+ op1 = RECUR (TREE_OPERAND (t, 1));
+ if (op1 == error_mark_node)
+ RETURN (error_mark_node);
+ }
+ if (TREE_OPERAND (t, 2))
+ {
+ op2 = RECUR (TREE_OPERAND (t, 2));
+ if (op2 == error_mark_node)
+ RETURN (error_mark_node);
+ }
+ RETURN (build_omp_array_section (EXPR_LOCATION (t), op0, op1, op2));
+ }
+
case SIZEOF_EXPR:
if (PACK_EXPANSION_P (TREE_OPERAND (t, 0))
|| ARGUMENT_PACK_P (TREE_OPERAND (t, 0)))
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 082fe2d..2162c57 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -5426,7 +5426,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;
@@ -5448,7 +5448,9 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
ret = t_refto;
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)
+ && (openacc || !EXPR_P (t))
+ && TREE_CODE (t) != PARM_DECL)
{
if (processing_template_decl && TREE_CODE (t) != OVERLOAD)
return NULL_TREE;
@@ -5481,16 +5483,16 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
&& (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
|| OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION
|| OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION)
- && TREE_CODE (TREE_CHAIN (t)) == FIELD_DECL)
- TREE_CHAIN (t) = omp_privatize_field (TREE_CHAIN (t), false);
- ret = handle_omp_array_sections_1 (c, TREE_CHAIN (t), types,
+ && TREE_CODE (TREE_OPERAND (t, 0)) == FIELD_DECL)
+ TREE_OPERAND (t, 0) = omp_privatize_field (TREE_OPERAND (t, 0), false);
+ 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 && type_dependent_expression_p (low_bound))
|| (length && type_dependent_expression_p (length)))
return NULL_TREE;
@@ -5696,7 +5698,7 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
tree lb = cp_save_expr (low_bound);
if (lb != low_bound)
{
- TREE_PURPOSE (t) = lb;
+ TREE_OPERAND (t, 1) = lb;
low_bound = lb;
}
}
@@ -5727,14 +5729,14 @@ 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_AFFINITY
&& OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
- && 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),
@@ -5757,7 +5759,7 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
tree lb = cp_save_expr (low_bound);
if (lb != low_bound)
{
- TREE_PURPOSE (t) = lb;
+ TREE_OPERAND (t, 1) = lb;
low_bound = lb;
}
/* Temporarily disable -fstrong-eval-order for array reductions.
@@ -5835,10 +5837,12 @@ handle_omp_array_sections (tree &c, enum c_omp_region_type ort)
return false;
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);
+ gcc_assert (TREE_CODE (t) == OMP_ARRAY_SECTION);
+
+ tree low_bound = TREE_OPERAND (t, 1);
+ tree length = TREE_OPERAND (t, 2);
i--;
if (low_bound
@@ -6951,8 +6955,8 @@ cp_oacc_check_attachments (tree c)
tree t = OMP_CLAUSE_DECL (c);
tree type;
- while (TREE_CODE (t) == TREE_LIST)
- t = TREE_CHAIN (t);
+ while (TREE_CODE (t) == OMP_ARRAY_SECTION)
+ t = TREE_OPERAND (t, 0);
type = TREE_TYPE (t);
@@ -7059,7 +7063,7 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
case OMP_CLAUSE_TASK_REDUCTION:
field_ok = ((ort & C_ORT_OMP_DECLARE_SIMD) == C_ORT_OMP);
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))
{
@@ -7075,10 +7079,10 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
remove = true;
break;
}
- if (TREE_CODE (t) == TREE_LIST)
+ if (TREE_CODE (t) == OMP_ARRAY_SECTION)
{
- while (TREE_CODE (t) == TREE_LIST)
- t = TREE_CHAIN (t);
+ while (TREE_CODE (t) == OMP_ARRAY_SECTION)
+ t = TREE_OPERAND (t, 0);
}
else
{
@@ -8102,7 +8106,7 @@ 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;
@@ -8262,7 +8266,7 @@ 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);
@@ -8272,7 +8276,7 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
else
{
t = OMP_CLAUSE_DECL (c);
- if (TREE_CODE (t) != TREE_LIST
+ if (TREE_CODE (t) != OMP_ARRAY_SECTION
&& !type_dependent_expression_p (t)
&& !omp_mappable_type (TREE_TYPE (t)))
{
@@ -8455,7 +8459,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
+ || (!openacc && EXPR_P (t))))
break;
if (DECL_P (t))
error_at (OMP_CLAUSE_LOCATION (c),
@@ -8854,15 +8859,15 @@ 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;
else
{
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);
while (INDIRECT_REF_P (t)
|| TREE_CODE (t) == ARRAY_REF)
t = TREE_OPERAND (t, 0);
@@ -9234,10 +9239,10 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
if (DECL_P (t))
bitmap_clear_bit (&aligned_head, DECL_UID (t));
}
- else if (TREE_CODE (t) == TREE_LIST)
+ else if (TREE_CODE (t) == OMP_ARRAY_SECTION)
{
- while (TREE_CODE (t) == TREE_LIST)
- t = TREE_CHAIN (t);
+ while (TREE_CODE (t) == OMP_ARRAY_SECTION)
+ t = TREE_OPERAND (t, 0);
if (DECL_P (t))
bitmap_clear_bit (&aligned_head, DECL_UID (t));
t = OMP_CLAUSE_DECL (c);
diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
index 49e9674..cfcaf12 100644
--- a/gcc/cp/typeck.cc
+++ b/gcc/cp/typeck.cc
@@ -4796,6 +4796,56 @@ build_x_array_ref (location_t loc, tree arg1, tree arg2,
return expr;
}
+/* 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_expr, tree index,
+ tree length)
+{
+ tree type = TREE_TYPE (array_expr);
+ gcc_assert (type);
+ type = non_reference (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)
+ sectype = TREE_TYPE (array_expr);
+ else
+ {
+ tree idxtype = NULL_TREE;
+
+ /* If we know the integer bounds, create an index type with exact
+ low/high (or zero/length) bounds. Otherwise, create an incomplete
+ array type. (This mostly only affects diagnostics.) */
+ if (index != NULL_TREE
+ && length != NULL_TREE
+ && TREE_CODE (index) == INTEGER_CST
+ && TREE_CODE (length) == INTEGER_CST)
+ {
+ 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
+ && TREE_CODE (length) == INTEGER_CST)
+ idxtype = build_index_type (length);
+
+ sectype = build_array_type (eltype, idxtype);
+ }
+
+ return build3_loc (loc, OMP_ARRAY_SECTION, sectype, array_expr, index,
+ length);
+}
+
/* Return whether OP is an expression of enum type cast to integer
type. In C++ even unsigned enum types are cast to signed integer
types. We do not want to issue warnings about comparisons between