aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/semantics.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/semantics.c')
-rw-r--r--gcc/cp/semantics.c1330
1 files changed, 1223 insertions, 107 deletions
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index c1f4330..8796b17 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -63,6 +63,12 @@ static tree maybe_convert_cond (tree);
static tree finalize_nrv_r (tree *, int *, void *);
static tree capture_decltype (tree);
+/* Used for OpenMP non-static data member privatization. */
+
+static hash_map<tree, tree> *omp_private_member_map;
+static vec<tree> omp_private_member_vec;
+static bool omp_private_member_ignore_next;
+
/* Deferred Access Checking Overview
---------------------------------
@@ -1704,6 +1710,8 @@ tree
finish_non_static_data_member (tree decl, tree object, tree qualifying_scope)
{
gcc_assert (TREE_CODE (decl) == FIELD_DECL);
+ bool try_omp_private = !object && omp_private_member_map;
+ tree ret;
if (!object)
{
@@ -1755,17 +1763,17 @@ finish_non_static_data_member (tree decl, tree object, tree qualifying_scope)
type = cp_build_qualified_type (type, quals);
}
- return (convert_from_reference
+ ret = (convert_from_reference
(build_min (COMPONENT_REF, type, object, decl, NULL_TREE)));
}
/* If PROCESSING_TEMPLATE_DECL is nonzero here, then
QUALIFYING_SCOPE is also non-null. Wrap this in a SCOPE_REF
for now. */
else if (processing_template_decl)
- return build_qualified_name (TREE_TYPE (decl),
- qualifying_scope,
- decl,
- /*template_p=*/false);
+ ret = build_qualified_name (TREE_TYPE (decl),
+ qualifying_scope,
+ decl,
+ /*template_p=*/false);
else
{
tree access_type = TREE_TYPE (object);
@@ -1782,11 +1790,18 @@ finish_non_static_data_member (tree decl, tree object, tree qualifying_scope)
&binfo);
}
- return build_class_member_access_expr (object, decl,
- /*access_path=*/NULL_TREE,
- /*preserve_reference=*/false,
- tf_warning_or_error);
+ ret = build_class_member_access_expr (object, decl,
+ /*access_path=*/NULL_TREE,
+ /*preserve_reference=*/false,
+ tf_warning_or_error);
}
+ if (try_omp_private)
+ {
+ tree *v = omp_private_member_map->get (decl);
+ if (v)
+ ret = convert_from_reference (*v);
+ }
+ return ret;
}
/* If we are currently parsing a template and we encountered a typedef
@@ -4252,6 +4267,91 @@ cxx_omp_create_clause_info (tree c, tree type, bool need_default_ctor,
return errorcount != save_errorcount;
}
+/* If DECL is DECL_OMP_PRIVATIZED_MEMBER, return corresponding
+ FIELD_DECL, otherwise return DECL itself. */
+
+static tree
+omp_clause_decl_field (tree decl)
+{
+ if (VAR_P (decl)
+ && DECL_HAS_VALUE_EXPR_P (decl)
+ && DECL_ARTIFICIAL (decl)
+ && DECL_LANG_SPECIFIC (decl)
+ && DECL_OMP_PRIVATIZED_MEMBER (decl))
+ {
+ tree f = DECL_VALUE_EXPR (decl);
+ if (TREE_CODE (f) == INDIRECT_REF)
+ f = TREE_OPERAND (f, 0);
+ if (TREE_CODE (f) == COMPONENT_REF)
+ {
+ f = TREE_OPERAND (f, 1);
+ gcc_assert (TREE_CODE (f) == FIELD_DECL);
+ return f;
+ }
+ }
+ return NULL_TREE;
+}
+
+/* Adjust DECL if needed for printing using %qE. */
+
+static tree
+omp_clause_printable_decl (tree decl)
+{
+ tree t = omp_clause_decl_field (decl);
+ if (t)
+ return t;
+ return decl;
+}
+
+/* For a FIELD_DECL F and corresponding DECL_OMP_PRIVATIZED_MEMBER
+ VAR_DECL T that doesn't need a DECL_EXPR added, record it for
+ privatization. */
+
+static void
+omp_note_field_privatization (tree f, tree t)
+{
+ if (!omp_private_member_map)
+ omp_private_member_map = new hash_map<tree, tree>;
+ tree &v = omp_private_member_map->get_or_insert (f);
+ if (v == NULL_TREE)
+ {
+ v = t;
+ omp_private_member_vec.safe_push (f);
+ /* Signal that we don't want to create DECL_EXPR for this dummy var. */
+ omp_private_member_vec.safe_push (integer_zero_node);
+ }
+}
+
+/* Privatize FIELD_DECL T, return corresponding DECL_OMP_PRIVATIZED_MEMBER
+ dummy VAR_DECL. */
+
+tree
+omp_privatize_field (tree t)
+{
+ tree m = finish_non_static_data_member (t, NULL_TREE, NULL_TREE);
+ if (m == error_mark_node)
+ return error_mark_node;
+ if (!omp_private_member_map)
+ omp_private_member_map = new hash_map<tree, tree>;
+ if (TREE_CODE (TREE_TYPE (t)) == REFERENCE_TYPE)
+ {
+ gcc_assert (TREE_CODE (m) == INDIRECT_REF);
+ m = TREE_OPERAND (m, 0);
+ }
+ tree &v = omp_private_member_map->get_or_insert (t);
+ if (v == NULL_TREE)
+ {
+ v = create_temporary_var (TREE_TYPE (m));
+ if (!DECL_LANG_SPECIFIC (v))
+ retrofit_lang_decl (v);
+ DECL_OMP_PRIVATIZED_MEMBER (v) = 1;
+ SET_DECL_VALUE_EXPR (v, m);
+ DECL_HAS_VALUE_EXPR_P (v) = 1;
+ omp_private_member_vec.safe_push (t);
+ }
+ return v;
+}
+
/* Helper function for handle_omp_array_sections. Called recursively
to handle multiple array-section-subscripts. C is the clause,
T current expression (initially OMP_CLAUSE_DECL), which is either
@@ -4266,7 +4366,7 @@ cxx_omp_create_clause_info (tree c, tree type, bool need_default_ctor,
map(a[:b][2:1][:c][:2][:d][e:f][2:5])
FIRST_NON_ONE will be 3, array-section-subscript [:b], [2:1] and [:c]
all are or may have length of 1, array-section-subscript [:2] is the
- first one knonwn not to have length 1. For array-section-subscript
+ first one known not to have length 1. For array-section-subscript
<= FIRST_NON_ONE we diagnose non-contiguous arrays if low bound isn't
0 or length isn't the array domain max + 1, for > FIRST_NON_ONE we
can if MAYBE_ZERO_LEN is false. MAYBE_ZERO_LEN will be true in the above
@@ -4274,13 +4374,43 @@ cxx_omp_create_clause_info (tree c, tree type, bool need_default_ctor,
static tree
handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
- bool &maybe_zero_len, unsigned int &first_non_one)
+ bool &maybe_zero_len, unsigned int &first_non_one,
+ bool is_omp)
{
tree ret, low_bound, length, type;
if (TREE_CODE (t) != TREE_LIST)
{
if (error_operand_p (t))
return error_mark_node;
+ if (REFERENCE_REF_P (t)
+ && TREE_CODE (TREE_OPERAND (t, 0)) == COMPONENT_REF)
+ t = TREE_OPERAND (t, 0);
+ ret = t;
+ if (TREE_CODE (t) == COMPONENT_REF
+ && is_omp
+ && (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
+ || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TO
+ || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FROM)
+ && !type_dependent_expression_p (t))
+ {
+ if (DECL_BIT_FIELD (TREE_OPERAND (t, 1)))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "bit-field %qE in %qs clause",
+ t, omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ return error_mark_node;
+ }
+ while (TREE_CODE (t) == COMPONENT_REF)
+ {
+ if (TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == UNION_TYPE)
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qE is a member of a union", t);
+ return error_mark_node;
+ }
+ t = TREE_OPERAND (t, 0);
+ }
+ }
if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL)
{
if (processing_template_decl)
@@ -4295,6 +4425,15 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
return error_mark_node;
}
+ else if (TREE_CODE (t) == PARM_DECL
+ && DECL_ARTIFICIAL (t)
+ && DECL_NAME (t) == this_identifier)
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<this%> allowed in OpenMP only in %<declare simd%>"
+ " clauses");
+ return error_mark_node;
+ }
else if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
&& VAR_P (t) && CP_DECL_THREAD_LOCAL_P (t))
{
@@ -4303,14 +4442,17 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
return error_mark_node;
}
- if (type_dependent_expression_p (t))
+ if (type_dependent_expression_p (ret))
return NULL_TREE;
- t = convert_from_reference (t);
- return t;
+ ret = convert_from_reference (ret);
+ return ret;
}
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+ && TREE_CODE (TREE_CHAIN (t)) == FIELD_DECL)
+ TREE_CHAIN (t) = omp_privatize_field (TREE_CHAIN (t));
ret = handle_omp_array_sections_1 (c, TREE_CHAIN (t), types,
- maybe_zero_len, first_non_one);
+ maybe_zero_len, first_non_one, is_omp);
if (ret == error_mark_node || ret == NULL_TREE)
return ret;
@@ -4358,11 +4500,32 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
if (length != NULL_TREE)
{
if (!integer_nonzerop (length))
- maybe_zero_len = true;
+ {
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
+ || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
+ {
+ if (integer_zerop (length))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "zero length array section in %qs clause",
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ return error_mark_node;
+ }
+ }
+ else
+ maybe_zero_len = true;
+ }
if (first_non_one == types.length ()
&& (TREE_CODE (length) != INTEGER_CST || integer_onep (length)))
first_non_one++;
}
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+ && !integer_zerop (low_bound))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<reduction%> array section has to be zero-based");
+ return error_mark_node;
+ }
if (TREE_CODE (type) == ARRAY_TYPE)
{
if (length == NULL_TREE
@@ -4410,7 +4573,17 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
return error_mark_node;
}
if (tree_int_cst_equal (size, low_bound))
- maybe_zero_len = true;
+ {
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
+ || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "zero length array section in %qs clause",
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ return error_mark_node;
+ }
+ maybe_zero_len = true;
+ }
else if (length == NULL_TREE
&& first_non_one == types.length ()
&& tree_int_cst_equal
@@ -4420,7 +4593,9 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
}
else if (length == NULL_TREE)
{
- maybe_zero_len = true;
+ if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
+ && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
+ maybe_zero_len = true;
if (first_non_one == types.length ())
first_non_one++;
}
@@ -4454,7 +4629,9 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
}
else if (length == NULL_TREE)
{
- maybe_zero_len = true;
+ if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
+ && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
+ maybe_zero_len = true;
if (first_non_one == types.length ())
first_non_one++;
}
@@ -4478,6 +4655,15 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
"for pointer type length expression must be specified");
return error_mark_node;
}
+ if (length != NULL_TREE
+ && TREE_CODE (length) == INTEGER_CST
+ && tree_int_cst_sgn (length) == -1)
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "negative length in array section in %qs clause",
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ return error_mark_node;
+ }
/* If there is a pointer type anywhere but in the very first
array-section-subscript, the array section can't be contiguous. */
if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
@@ -4511,13 +4697,14 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
/* Handle array sections for clause C. */
static bool
-handle_omp_array_sections (tree c)
+handle_omp_array_sections (tree c, bool is_omp)
{
bool maybe_zero_len = false;
unsigned int first_non_one = 0;
- auto_vec<tree> types;
+ auto_vec<tree, 10> types;
tree first = handle_omp_array_sections_1 (c, OMP_CLAUSE_DECL (c), types,
- maybe_zero_len, first_non_one);
+ maybe_zero_len, first_non_one,
+ is_omp);
if (first == error_mark_node)
return true;
if (first == NULL_TREE)
@@ -4619,7 +4806,9 @@ handle_omp_array_sections (tree c)
{
tree l;
- if (i > first_non_one && length && integer_nonzerop (length))
+ if (i > first_non_one
+ && ((length && integer_nonzerop (length))
+ || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION))
continue;
if (length)
l = fold_convert (sizetype, length);
@@ -4644,6 +4833,12 @@ handle_omp_array_sections (tree c)
else if (size == NULL_TREE)
{
size = size_in_bytes (TREE_TYPE (types[i]));
+ tree eltype = TREE_TYPE (types[num - 1]);
+ while (TREE_CODE (eltype) == ARRAY_TYPE)
+ eltype = TREE_TYPE (eltype);
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
+ size = size_binop (EXACT_DIV_EXPR, size,
+ size_in_bytes (eltype));
size = size_binop (MULT_EXPR, size, l);
if (condition)
size = fold_build3 (COND_EXPR, sizetype, condition,
@@ -4657,14 +4852,52 @@ handle_omp_array_sections (tree c)
{
if (side_effects)
size = build2 (COMPOUND_EXPR, sizetype, side_effects, size);
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
+ {
+ size = size_binop (MINUS_EXPR, size, size_one_node);
+ tree index_type = build_index_type (size);
+ tree eltype = TREE_TYPE (first);
+ while (TREE_CODE (eltype) == ARRAY_TYPE)
+ eltype = TREE_TYPE (eltype);
+ tree type = build_array_type (eltype, index_type);
+ tree ptype = build_pointer_type (eltype);
+ if (TREE_CODE (TREE_TYPE (t)) == REFERENCE_TYPE
+ && POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (t))))
+ t = convert_from_reference (t);
+ else if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE)
+ t = build_fold_addr_expr (t);
+ t = build2 (MEM_REF, type, t, build_int_cst (ptype, 0));
+ OMP_CLAUSE_DECL (c) = t;
+ return false;
+ }
OMP_CLAUSE_DECL (c) = first;
OMP_CLAUSE_SIZE (c) = size;
- if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP)
+ if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
+ || (TREE_CODE (t) == COMPONENT_REF
+ && TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE))
return false;
+ if (is_omp)
+ switch (OMP_CLAUSE_MAP_KIND (c))
+ {
+ case GOMP_MAP_ALLOC:
+ case GOMP_MAP_TO:
+ case GOMP_MAP_FROM:
+ case GOMP_MAP_TOFROM:
+ case GOMP_MAP_ALWAYS_TO:
+ case GOMP_MAP_ALWAYS_FROM:
+ case GOMP_MAP_ALWAYS_TOFROM:
+ case GOMP_MAP_RELEASE:
+ case GOMP_MAP_DELETE:
+ OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (c) = 1;
+ break;
+ default:
+ break;
+ }
tree c2 = build_omp_clause (OMP_CLAUSE_LOCATION (c),
OMP_CLAUSE_MAP);
- OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_POINTER);
- if (!cxx_mark_addressable (t))
+ OMP_CLAUSE_SET_MAP_KIND (c2, is_omp ? GOMP_MAP_FIRSTPRIVATE_POINTER
+ : GOMP_MAP_POINTER);
+ if (!is_omp && !cxx_mark_addressable (t))
return false;
OMP_CLAUSE_DECL (c2) = t;
t = build_fold_addr_expr (first);
@@ -4682,7 +4915,8 @@ handle_omp_array_sections (tree c)
OMP_CLAUSE_CHAIN (c2) = OMP_CLAUSE_CHAIN (c);
OMP_CLAUSE_CHAIN (c) = c2;
ptr = OMP_CLAUSE_DECL (c2);
- if (TREE_CODE (TREE_TYPE (ptr)) == REFERENCE_TYPE
+ if (!is_omp
+ && TREE_CODE (TREE_TYPE (ptr)) == REFERENCE_TYPE
&& POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (ptr))))
{
tree c3 = build_omp_clause (OMP_CLAUSE_LOCATION (c),
@@ -5091,9 +5325,45 @@ finish_omp_reduction_clause (tree c, bool *need_default_ctor, bool *need_dtor)
{
tree t = OMP_CLAUSE_DECL (c);
bool predefined = false;
+ if (TREE_CODE (t) == TREE_LIST)
+ {
+ gcc_assert (processing_template_decl);
+ return false;
+ }
tree type = TREE_TYPE (t);
+ if (TREE_CODE (t) == MEM_REF)
+ type = TREE_TYPE (type);
if (TREE_CODE (type) == REFERENCE_TYPE)
type = TREE_TYPE (type);
+ if (TREE_CODE (type) == ARRAY_TYPE)
+ {
+ tree oatype = type;
+ gcc_assert (TREE_CODE (t) != MEM_REF);
+ while (TREE_CODE (type) == ARRAY_TYPE)
+ type = TREE_TYPE (type);
+ if (!processing_template_decl)
+ {
+ t = require_complete_type (t);
+ if (t == error_mark_node)
+ return true;
+ tree size = size_binop (EXACT_DIV_EXPR, TYPE_SIZE_UNIT (oatype),
+ TYPE_SIZE_UNIT (type));
+ if (integer_zerop (size))
+ {
+ error ("%qE in %<reduction%> clause is a zero size array",
+ omp_clause_printable_decl (t));
+ return true;
+ }
+ size = size_binop (MINUS_EXPR, size, size_one_node);
+ tree index_type = build_index_type (size);
+ tree atype = build_array_type (type, index_type);
+ tree ptype = build_pointer_type (type);
+ if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE)
+ t = build_fold_addr_expr (t);
+ t = build2 (MEM_REF, atype, t, build_int_cst (ptype, 0));
+ OMP_CLAUSE_DECL (c) = t;
+ }
+ }
if (type == error_mark_node)
return true;
else if (ARITHMETIC_TYPE_P (type))
@@ -5126,9 +5396,10 @@ finish_omp_reduction_clause (tree c, bool *need_default_ctor, bool *need_dtor)
default:
break;
}
- else if (TREE_CODE (type) == ARRAY_TYPE || TYPE_READONLY (type))
+ else if (TYPE_READONLY (type))
{
- error ("%qE has invalid type for %<reduction%>", t);
+ error ("%qE has const type for %<reduction%>",
+ omp_clause_printable_decl (t));
return true;
}
else if (!processing_template_decl)
@@ -5149,9 +5420,7 @@ finish_omp_reduction_clause (tree c, bool *need_default_ctor, bool *need_dtor)
tree id = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
- type = TYPE_MAIN_VARIANT (TREE_TYPE (t));
- if (TREE_CODE (type) == REFERENCE_TYPE)
- type = TREE_TYPE (type);
+ type = TYPE_MAIN_VARIANT (type);
OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL_TREE;
if (id == NULL_TREE)
id = omp_reduction_id (OMP_CLAUSE_REDUCTION_CODE (c),
@@ -5169,7 +5438,7 @@ finish_omp_reduction_clause (tree c, bool *need_default_ctor, bool *need_dtor)
if (TREE_CODE (body) == STATEMENT_LIST)
{
tree_stmt_iterator tsi;
- tree placeholder = NULL_TREE;
+ tree placeholder = NULL_TREE, decl_placeholder = NULL_TREE;
int i;
tree stmts[7];
tree atype = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (id)));
@@ -5190,14 +5459,24 @@ finish_omp_reduction_clause (tree c, bool *need_default_ctor, bool *need_dtor)
DECL_ARTIFICIAL (placeholder) = 1;
DECL_IGNORED_P (placeholder) = 1;
OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = placeholder;
+ if (TREE_CODE (t) == MEM_REF)
+ {
+ decl_placeholder = build_lang_decl (VAR_DECL, NULL_TREE,
+ type);
+ DECL_ARTIFICIAL (decl_placeholder) = 1;
+ DECL_IGNORED_P (decl_placeholder) = 1;
+ OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c) = decl_placeholder;
+ }
if (TREE_ADDRESSABLE (DECL_EXPR_DECL (stmts[0])))
cxx_mark_addressable (placeholder);
if (TREE_ADDRESSABLE (DECL_EXPR_DECL (stmts[1]))
&& TREE_CODE (TREE_TYPE (OMP_CLAUSE_DECL (c)))
!= REFERENCE_TYPE)
- cxx_mark_addressable (OMP_CLAUSE_DECL (c));
+ cxx_mark_addressable (decl_placeholder ? decl_placeholder
+ : OMP_CLAUSE_DECL (c));
tree omp_out = placeholder;
- tree omp_in = convert_from_reference (OMP_CLAUSE_DECL (c));
+ tree omp_in = decl_placeholder ? decl_placeholder
+ : convert_from_reference (OMP_CLAUSE_DECL (c));
if (need_static_cast)
{
tree rtype = build_reference_type (atype);
@@ -5219,10 +5498,12 @@ finish_omp_reduction_clause (tree c, bool *need_default_ctor, bool *need_dtor)
gcc_assert (TREE_CODE (stmts[3]) == DECL_EXPR
&& TREE_CODE (stmts[4]) == DECL_EXPR);
if (TREE_ADDRESSABLE (DECL_EXPR_DECL (stmts[3])))
- cxx_mark_addressable (OMP_CLAUSE_DECL (c));
+ cxx_mark_addressable (decl_placeholder ? decl_placeholder
+ : OMP_CLAUSE_DECL (c));
if (TREE_ADDRESSABLE (DECL_EXPR_DECL (stmts[4])))
cxx_mark_addressable (placeholder);
- tree omp_priv = convert_from_reference (OMP_CLAUSE_DECL (c));
+ tree omp_priv = decl_placeholder ? decl_placeholder
+ : convert_from_reference (OMP_CLAUSE_DECL (c));
tree omp_orig = placeholder;
if (need_static_cast)
{
@@ -5261,7 +5542,8 @@ finish_omp_reduction_clause (tree c, bool *need_default_ctor, bool *need_dtor)
else
{
tree init;
- tree v = convert_from_reference (t);
+ tree v = decl_placeholder ? decl_placeholder
+ : convert_from_reference (t);
if (AGGREGATE_TYPE_P (TREE_TYPE (v)))
init = build_constructor (TREE_TYPE (v), NULL);
else
@@ -5276,9 +5558,85 @@ finish_omp_reduction_clause (tree c, bool *need_default_ctor, bool *need_dtor)
*need_dtor = true;
else
{
- error ("user defined reduction not found for %qD", t);
+ error ("user defined reduction not found for %qE",
+ omp_clause_printable_decl (t));
return true;
}
+ if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF)
+ gcc_assert (TYPE_SIZE_UNIT (type)
+ && TREE_CODE (TYPE_SIZE_UNIT (type)) == INTEGER_CST);
+ return false;
+}
+
+/* Called from finish_struct_1. linear(this) or linear(this:step)
+ clauses might not be finalized yet because the class has been incomplete
+ when parsing #pragma omp declare simd methods. Fix those up now. */
+
+void
+finish_omp_declare_simd_methods (tree t)
+{
+ if (processing_template_decl)
+ return;
+
+ for (tree x = TYPE_METHODS (t); x; x = DECL_CHAIN (x))
+ {
+ if (TREE_CODE (TREE_TYPE (x)) != METHOD_TYPE)
+ continue;
+ tree ods = lookup_attribute ("omp declare simd", DECL_ATTRIBUTES (x));
+ if (!ods || !TREE_VALUE (ods))
+ continue;
+ for (tree c = TREE_VALUE (TREE_VALUE (ods)); c; c = OMP_CLAUSE_CHAIN (c))
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
+ && integer_zerop (OMP_CLAUSE_DECL (c))
+ && OMP_CLAUSE_LINEAR_STEP (c)
+ && TREE_CODE (TREE_TYPE (OMP_CLAUSE_LINEAR_STEP (c)))
+ == POINTER_TYPE)
+ {
+ tree s = OMP_CLAUSE_LINEAR_STEP (c);
+ s = fold_convert_loc (OMP_CLAUSE_LOCATION (c), sizetype, s);
+ s = fold_build2_loc (OMP_CLAUSE_LOCATION (c), MULT_EXPR,
+ sizetype, s, TYPE_SIZE_UNIT (t));
+ OMP_CLAUSE_LINEAR_STEP (c) = s;
+ }
+ }
+}
+
+/* Adjust sink depend clause to take into account pointer offsets.
+
+ Return TRUE if there was a problem processing the offset, and the
+ whole clause should be removed. */
+
+static bool
+cp_finish_omp_clause_depend_sink (tree sink_clause)
+{
+ tree t = OMP_CLAUSE_DECL (sink_clause);
+ gcc_assert (TREE_CODE (t) == TREE_LIST);
+
+ /* Make sure we don't adjust things twice for templates. */
+ if (processing_template_decl)
+ return false;
+
+ for (; t; t = TREE_CHAIN (t))
+ {
+ tree decl = TREE_VALUE (t);
+ if (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE)
+ {
+ tree offset = TREE_PURPOSE (t);
+ bool neg = wi::neg_p ((wide_int) offset);
+ offset = fold_unary (ABS_EXPR, TREE_TYPE (offset), offset);
+ decl = mark_rvalue_use (decl);
+ decl = convert_from_reference (decl);
+ tree t2 = pointer_int_sum (OMP_CLAUSE_LOCATION (sink_clause),
+ neg ? MINUS_EXPR : PLUS_EXPR,
+ decl, offset);
+ t2 = fold_build2_loc (OMP_CLAUSE_LOCATION (sink_clause),
+ MINUS_EXPR, sizetype, t2,
+ decl);
+ if (t2 == error_mark_node)
+ return true;
+ TREE_PURPOSE (t) = t2;
+ }
+ }
return false;
}
@@ -5286,11 +5644,12 @@ finish_omp_reduction_clause (tree c, bool *need_default_ctor, bool *need_dtor)
Remove any elements from the list that are invalid. */
tree
-finish_omp_clauses (tree clauses)
+finish_omp_clauses (tree clauses, bool allow_fields, bool declare_simd)
{
bitmap_head generic_head, firstprivate_head, lastprivate_head;
- bitmap_head aligned_head;
+ bitmap_head aligned_head, map_head, map_field_head, generic_field_head;
tree c, t, *pc;
+ tree safelen = NULL_TREE;
bool branch_seen = false;
bool copyprivate_seen = false;
@@ -5299,35 +5658,93 @@ finish_omp_clauses (tree clauses)
bitmap_initialize (&firstprivate_head, &bitmap_default_obstack);
bitmap_initialize (&lastprivate_head, &bitmap_default_obstack);
bitmap_initialize (&aligned_head, &bitmap_default_obstack);
+ bitmap_initialize (&map_head, &bitmap_default_obstack);
+ bitmap_initialize (&map_field_head, &bitmap_default_obstack);
+ bitmap_initialize (&generic_field_head, &bitmap_default_obstack);
for (pc = &clauses, c = clauses; c ; c = *pc)
{
bool remove = false;
+ bool field_ok = false;
switch (OMP_CLAUSE_CODE (c))
{
case OMP_CLAUSE_SHARED:
goto check_dup_generic;
case OMP_CLAUSE_PRIVATE:
+ field_ok = allow_fields;
goto check_dup_generic;
case OMP_CLAUSE_REDUCTION:
+ field_ok = allow_fields;
+ t = OMP_CLAUSE_DECL (c);
+ if (TREE_CODE (t) == TREE_LIST)
+ {
+ if (handle_omp_array_sections (c, allow_fields))
+ {
+ remove = true;
+ break;
+ }
+ if (TREE_CODE (t) == TREE_LIST)
+ {
+ while (TREE_CODE (t) == TREE_LIST)
+ t = TREE_CHAIN (t);
+ }
+ else
+ {
+ gcc_assert (TREE_CODE (t) == MEM_REF);
+ t = TREE_OPERAND (t, 0);
+ if (TREE_CODE (t) == ADDR_EXPR
+ || TREE_CODE (t) == INDIRECT_REF)
+ t = TREE_OPERAND (t, 0);
+ }
+ tree n = omp_clause_decl_field (t);
+ if (n)
+ t = n;
+ goto check_dup_generic_t;
+ }
goto check_dup_generic;
case OMP_CLAUSE_COPYPRIVATE:
copyprivate_seen = true;
+ field_ok = allow_fields;
goto check_dup_generic;
case OMP_CLAUSE_COPYIN:
goto check_dup_generic;
case OMP_CLAUSE_LINEAR:
+ field_ok = allow_fields;
t = OMP_CLAUSE_DECL (c);
+ if (!declare_simd
+ && OMP_CLAUSE_LINEAR_KIND (c) != OMP_CLAUSE_LINEAR_DEFAULT)
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "modifier should not be specified in %<linear%> "
+ "clause on %<simd%> or %<for%> constructs");
+ OMP_CLAUSE_LINEAR_KIND (c) = OMP_CLAUSE_LINEAR_DEFAULT;
+ }
if ((VAR_P (t) || TREE_CODE (t) == PARM_DECL)
- && !type_dependent_expression_p (t)
- && !INTEGRAL_TYPE_P (TREE_TYPE (t))
- && TREE_CODE (TREE_TYPE (t)) != POINTER_TYPE)
+ && !type_dependent_expression_p (t))
{
- error ("linear clause applied to non-integral non-pointer "
- "variable with %qT type", TREE_TYPE (t));
- remove = true;
- break;
+ tree type = TREE_TYPE (t);
+ if ((OMP_CLAUSE_LINEAR_KIND (c) == OMP_CLAUSE_LINEAR_REF
+ || OMP_CLAUSE_LINEAR_KIND (c) == OMP_CLAUSE_LINEAR_UVAL)
+ && TREE_CODE (type) != REFERENCE_TYPE)
+ {
+ error ("linear clause with %qs modifier applied to "
+ "non-reference variable with %qT type",
+ OMP_CLAUSE_LINEAR_KIND (c) == OMP_CLAUSE_LINEAR_REF
+ ? "ref" : "uval", TREE_TYPE (t));
+ remove = true;
+ break;
+ }
+ if (TREE_CODE (type) == REFERENCE_TYPE)
+ type = TREE_TYPE (type);
+ if (!INTEGRAL_TYPE_P (type)
+ && TREE_CODE (type) != POINTER_TYPE)
+ {
+ error ("linear clause applied to non-integral non-pointer "
+ "variable with %qT type", TREE_TYPE (t));
+ remove = true;
+ break;
+ }
}
t = OMP_CLAUSE_LINEAR_STEP (c);
if (t == NULL_TREE)
@@ -5354,14 +5771,38 @@ finish_omp_clauses (tree clauses)
if (TREE_CODE (OMP_CLAUSE_DECL (c)) == PARM_DECL)
t = maybe_constant_value (t);
t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
- if (TREE_CODE (TREE_TYPE (OMP_CLAUSE_DECL (c)))
- == POINTER_TYPE)
+ tree type = TREE_TYPE (OMP_CLAUSE_DECL (c));
+ if (TREE_CODE (type) == REFERENCE_TYPE)
+ type = TREE_TYPE (type);
+ if (OMP_CLAUSE_LINEAR_KIND (c) == OMP_CLAUSE_LINEAR_REF)
+ {
+ type = build_pointer_type (type);
+ tree d = fold_convert (type, OMP_CLAUSE_DECL (c));
+ t = pointer_int_sum (OMP_CLAUSE_LOCATION (c), PLUS_EXPR,
+ d, t);
+ t = fold_build2_loc (OMP_CLAUSE_LOCATION (c),
+ MINUS_EXPR, sizetype, t, d);
+ if (t == error_mark_node)
+ {
+ remove = true;
+ break;
+ }
+ }
+ else if (TREE_CODE (type) == POINTER_TYPE
+ /* Can't multiply the step yet if *this
+ is still incomplete type. */
+ && (!declare_simd
+ || TREE_CODE (OMP_CLAUSE_DECL (c)) != PARM_DECL
+ || !DECL_ARTIFICIAL (OMP_CLAUSE_DECL (c))
+ || DECL_NAME (OMP_CLAUSE_DECL (c))
+ != this_identifier
+ || !TYPE_BEING_DEFINED (TREE_TYPE (type))))
{
+ tree d = convert_from_reference (OMP_CLAUSE_DECL (c));
t = pointer_int_sum (OMP_CLAUSE_LOCATION (c), PLUS_EXPR,
- OMP_CLAUSE_DECL (c), t);
+ d, t);
t = fold_build2_loc (OMP_CLAUSE_LOCATION (c),
- MINUS_EXPR, sizetype, t,
- OMP_CLAUSE_DECL (c));
+ MINUS_EXPR, sizetype, t, d);
if (t == error_mark_node)
{
remove = true;
@@ -5369,14 +5810,33 @@ finish_omp_clauses (tree clauses)
}
}
else
- t = fold_convert (TREE_TYPE (OMP_CLAUSE_DECL (c)), t);
+ t = fold_convert (type, t);
}
OMP_CLAUSE_LINEAR_STEP (c) = t;
}
goto check_dup_generic;
check_dup_generic:
- t = OMP_CLAUSE_DECL (c);
- if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL)
+ t = omp_clause_decl_field (OMP_CLAUSE_DECL (c));
+ if (t)
+ {
+ if (!remove)
+ omp_note_field_privatization (t, OMP_CLAUSE_DECL (c));
+ }
+ else
+ t = OMP_CLAUSE_DECL (c);
+ check_dup_generic_t:
+ if (t == current_class_ptr
+ && (!declare_simd
+ || (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
+ && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_UNIFORM)))
+ {
+ error ("%<this%> allowed in OpenMP only in %<declare simd%>"
+ " clauses");
+ remove = true;
+ break;
+ }
+ if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL
+ && (!field_ok || TREE_CODE (t) != FIELD_DECL))
{
if (processing_template_decl)
break;
@@ -5397,11 +5857,34 @@ finish_omp_clauses (tree clauses)
}
else
bitmap_set_bit (&generic_head, DECL_UID (t));
+ if (!field_ok)
+ break;
+ handle_field_decl:
+ if (!remove
+ && TREE_CODE (t) == FIELD_DECL
+ && t == OMP_CLAUSE_DECL (c))
+ {
+ OMP_CLAUSE_DECL (c) = omp_privatize_field (t);
+ if (OMP_CLAUSE_DECL (c) == error_mark_node)
+ remove = true;
+ }
break;
case OMP_CLAUSE_FIRSTPRIVATE:
- t = OMP_CLAUSE_DECL (c);
- if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL)
+ t = omp_clause_decl_field (OMP_CLAUSE_DECL (c));
+ if (t)
+ omp_note_field_privatization (t, OMP_CLAUSE_DECL (c));
+ else
+ t = OMP_CLAUSE_DECL (c);
+ if (t == current_class_ptr)
+ {
+ error ("%<this%> allowed in OpenMP only in %<declare simd%>"
+ " clauses");
+ remove = true;
+ break;
+ }
+ if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL
+ && (!allow_fields || TREE_CODE (t) != FIELD_DECL))
{
if (processing_template_decl)
break;
@@ -5419,11 +5902,23 @@ finish_omp_clauses (tree clauses)
}
else
bitmap_set_bit (&firstprivate_head, DECL_UID (t));
- break;
+ goto handle_field_decl;
case OMP_CLAUSE_LASTPRIVATE:
- t = OMP_CLAUSE_DECL (c);
- if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL)
+ t = omp_clause_decl_field (OMP_CLAUSE_DECL (c));
+ if (t)
+ omp_note_field_privatization (t, OMP_CLAUSE_DECL (c));
+ else
+ t = OMP_CLAUSE_DECL (c);
+ if (t == current_class_ptr)
+ {
+ error ("%<this%> allowed in OpenMP only in %<declare simd%>"
+ " clauses");
+ remove = true;
+ break;
+ }
+ if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL
+ && (!allow_fields || TREE_CODE (t) != FIELD_DECL))
{
if (processing_template_decl)
break;
@@ -5441,7 +5936,7 @@ finish_omp_clauses (tree clauses)
}
else
bitmap_set_bit (&lastprivate_head, DECL_UID (t));
- break;
+ goto handle_field_decl;
case OMP_CLAUSE_IF:
t = OMP_CLAUSE_IF_EXPR (c);
@@ -5477,7 +5972,17 @@ finish_omp_clauses (tree clauses)
{
t = mark_rvalue_use (t);
if (!processing_template_decl)
- t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
+ {
+ t = maybe_constant_value (t);
+ if (TREE_CODE (t) == INTEGER_CST
+ && tree_int_cst_sgn (t) != 1)
+ {
+ warning_at (OMP_CLAUSE_LOCATION (c), 0,
+ "%<num_threads%> value must be positive");
+ t = integer_one_node;
+ }
+ t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
+ }
OMP_CLAUSE_NUM_THREADS_EXPR (c) = t;
}
break;
@@ -5545,6 +6050,8 @@ finish_omp_clauses (tree clauses)
}
}
OMP_CLAUSE_OPERAND (c, 0) = t;
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SAFELEN)
+ safelen = c;
}
break;
@@ -5562,7 +6069,17 @@ finish_omp_clauses (tree clauses)
{
t = mark_rvalue_use (t);
if (!processing_template_decl)
- t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
+ {
+ t = maybe_constant_value (t);
+ if (TREE_CODE (t) == INTEGER_CST
+ && tree_int_cst_sgn (t) != 1)
+ {
+ warning_at (OMP_CLAUSE_LOCATION (c), 0,
+ "%<num_teams%> value must be positive");
+ t = integer_one_node;
+ }
+ t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
+ }
OMP_CLAUSE_NUM_TEAMS_EXPR (c) = t;
}
break;
@@ -5619,7 +6136,17 @@ finish_omp_clauses (tree clauses)
{
t = mark_rvalue_use (t);
if (!processing_template_decl)
- t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
+ {
+ t = maybe_constant_value (t);
+ if (TREE_CODE (t) == INTEGER_CST
+ && tree_int_cst_sgn (t) != 1)
+ {
+ warning_at (OMP_CLAUSE_LOCATION (c), 0,
+ "%<thread_limit%> value must be positive");
+ t = integer_one_node;
+ }
+ t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
+ }
OMP_CLAUSE_THREAD_LIMIT_EXPR (c) = t;
}
break;
@@ -5667,6 +6194,13 @@ finish_omp_clauses (tree clauses)
case OMP_CLAUSE_ALIGNED:
t = OMP_CLAUSE_DECL (c);
+ if (t == current_class_ptr && !declare_simd)
+ {
+ error ("%<this%> allowed in OpenMP only in %<declare simd%>"
+ " clauses");
+ remove = true;
+ break;
+ }
if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL)
{
if (processing_template_decl)
@@ -5729,9 +6263,21 @@ finish_omp_clauses (tree clauses)
case OMP_CLAUSE_DEPEND:
t = OMP_CLAUSE_DECL (c);
+ if (t == NULL_TREE)
+ {
+ gcc_assert (OMP_CLAUSE_DEPEND_KIND (c)
+ == OMP_CLAUSE_DEPEND_SOURCE);
+ break;
+ }
+ if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK)
+ {
+ if (cp_finish_omp_clause_depend_sink (c))
+ remove = true;
+ break;
+ }
if (TREE_CODE (t) == TREE_LIST)
{
- if (handle_omp_array_sections (c))
+ if (handle_omp_array_sections (c, allow_fields))
remove = true;
break;
}
@@ -5747,6 +6293,12 @@ finish_omp_clauses (tree clauses)
error ("%qE is not a variable in %<depend%> clause", t);
remove = true;
}
+ else if (t == current_class_ptr)
+ {
+ error ("%<this%> allowed in OpenMP only in %<declare simd%>"
+ " clauses");
+ remove = true;
+ }
else if (!processing_template_decl
&& !cxx_mark_addressable (t))
remove = true;
@@ -5759,7 +6311,7 @@ finish_omp_clauses (tree clauses)
t = OMP_CLAUSE_DECL (c);
if (TREE_CODE (t) == TREE_LIST)
{
- if (handle_omp_array_sections (c))
+ if (handle_omp_array_sections (c, allow_fields))
remove = true;
else
{
@@ -5774,12 +6326,90 @@ finish_omp_clauses (tree clauses)
omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
remove = true;
}
+ while (TREE_CODE (t) == ARRAY_REF)
+ t = TREE_OPERAND (t, 0);
+ if (TREE_CODE (t) == COMPONENT_REF
+ && TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE)
+ {
+ while (TREE_CODE (t) == COMPONENT_REF)
+ t = TREE_OPERAND (t, 0);
+ if (bitmap_bit_p (&map_field_head, DECL_UID (t)))
+ break;
+ if (bitmap_bit_p (&map_head, DECL_UID (t)))
+ {
+ if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP)
+ error ("%qD appears more than once in motion"
+ " clauses", t);
+ else
+ error ("%qD appears more than once in map"
+ " clauses", t);
+ remove = true;
+ }
+ else
+ {
+ bitmap_set_bit (&map_head, DECL_UID (t));
+ bitmap_set_bit (&map_field_head, DECL_UID (t));
+ }
+ }
}
break;
}
if (t == error_mark_node)
- remove = true;
- else if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL)
+ {
+ remove = true;
+ break;
+ }
+ if (REFERENCE_REF_P (t)
+ && TREE_CODE (TREE_OPERAND (t, 0)) == COMPONENT_REF)
+ t = TREE_OPERAND (t, 0);
+ if (TREE_CODE (t) == COMPONENT_REF
+ && allow_fields
+ && OMP_CLAUSE_CODE (c) != OMP_CLAUSE__CACHE_)
+ {
+ if (type_dependent_expression_p (t))
+ break;
+ if (DECL_BIT_FIELD (TREE_OPERAND (t, 1)))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "bit-field %qE in %qs clause",
+ t, omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ remove = true;
+ }
+ else if (!cp_omp_mappable_type (TREE_TYPE (t)))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qE does not have a mappable type in %qs clause",
+ t, omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ remove = true;
+ }
+ while (TREE_CODE (t) == COMPONENT_REF)
+ {
+ if (TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0)))
+ == UNION_TYPE)
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qE is a member of a union", t);
+ remove = true;
+ break;
+ }
+ t = TREE_OPERAND (t, 0);
+ }
+ if (remove)
+ break;
+ if (VAR_P (t) || TREE_CODE (t) == PARM_DECL)
+ {
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
+ && (OMP_CLAUSE_MAP_KIND (c)
+ == GOMP_MAP_FIRSTPRIVATE_POINTER))
+ {
+ if (bitmap_bit_p (&generic_field_head, DECL_UID (t)))
+ break;
+ }
+ else if (bitmap_bit_p (&map_field_head, DECL_UID (t)))
+ break;
+ }
+ }
+ if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL)
{
if (processing_template_decl)
break;
@@ -5800,12 +6430,22 @@ finish_omp_clauses (tree clauses)
omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
remove = true;
}
+ else if (t == current_class_ptr)
+ {
+ error ("%<this%> allowed in OpenMP only in %<declare simd%>"
+ " clauses");
+ remove = true;
+ break;
+ }
else if (!processing_template_decl
&& TREE_CODE (TREE_TYPE (t)) != REFERENCE_TYPE
&& !cxx_mark_addressable (t))
remove = true;
else if (!(OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
- && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER)
+ && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
+ || (OMP_CLAUSE_MAP_KIND (c)
+ == GOMP_MAP_FIRSTPRIVATE_POINTER)))
+ && t == OMP_CLAUSE_DECL (c)
&& !type_dependent_expression_p (t)
&& !cp_omp_mappable_type ((TREE_CODE (TREE_TYPE (t))
== REFERENCE_TYPE)
@@ -5817,7 +6457,28 @@ finish_omp_clauses (tree clauses)
omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
remove = true;
}
- else if (bitmap_bit_p (&generic_head, DECL_UID (t)))
+ else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
+ && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER)
+ {
+ if (bitmap_bit_p (&generic_head, DECL_UID (t))
+ || bitmap_bit_p (&firstprivate_head, DECL_UID (t)))
+ {
+ error ("%qD appears more than once in data clauses", t);
+ remove = true;
+ }
+ else
+ {
+ bitmap_set_bit (&generic_head, DECL_UID (t));
+ if (t != OMP_CLAUSE_DECL (c)
+ && (TREE_CODE (OMP_CLAUSE_DECL (c)) == COMPONENT_REF
+ || (REFERENCE_REF_P (OMP_CLAUSE_DECL (c))
+ && (TREE_CODE (TREE_OPERAND (OMP_CLAUSE_DECL (c),
+ 0))
+ == COMPONENT_REF))))
+ bitmap_set_bit (&generic_field_head, DECL_UID (t));
+ }
+ }
+ else if (bitmap_bit_p (&map_head, DECL_UID (t)))
{
if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP)
error ("%qD appears more than once in motion clauses", t);
@@ -5826,7 +6487,42 @@ finish_omp_clauses (tree clauses)
remove = true;
}
else
- bitmap_set_bit (&generic_head, DECL_UID (t));
+ {
+ bitmap_set_bit (&map_head, DECL_UID (t));
+ if (t != OMP_CLAUSE_DECL (c)
+ && TREE_CODE (OMP_CLAUSE_DECL (c)) == COMPONENT_REF)
+ bitmap_set_bit (&map_field_head, DECL_UID (t));
+ }
+ break;
+
+ case OMP_CLAUSE_TO_DECLARE:
+ t = OMP_CLAUSE_DECL (c);
+ if (TREE_CODE (t) == FUNCTION_DECL)
+ break;
+ /* FALLTHRU */
+ case OMP_CLAUSE_LINK:
+ t = OMP_CLAUSE_DECL (c);
+ if (!VAR_P (t))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qE is not a variable in clause %qs", t,
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ remove = true;
+ }
+ else if (DECL_THREAD_LOCAL_P (t))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qD is threadprivate variable in %qs clause", t,
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ remove = true;
+ }
+ else if (!cp_omp_mappable_type (TREE_TYPE (t)))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qD does not have a mappable type in %qs clause", t,
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ remove = true;
+ }
break;
case OMP_CLAUSE_UNIFORM:
@@ -5844,6 +6540,137 @@ finish_omp_clauses (tree clauses)
}
goto check_dup_generic;
+ case OMP_CLAUSE_NUM_TASKS:
+ t = OMP_CLAUSE_NUM_TASKS_EXPR (c);
+ if (t == error_mark_node)
+ remove = true;
+ else if (!type_dependent_expression_p (t)
+ && !INTEGRAL_TYPE_P (TREE_TYPE (t)))
+ {
+ error ("%<num_tasks%> expression must be integral");
+ remove = true;
+ }
+ else
+ {
+ t = mark_rvalue_use (t);
+ if (!processing_template_decl)
+ {
+ t = maybe_constant_value (t);
+ if (TREE_CODE (t) == INTEGER_CST
+ && tree_int_cst_sgn (t) != 1)
+ {
+ warning_at (OMP_CLAUSE_LOCATION (c), 0,
+ "%<num_tasks%> value must be positive");
+ t = integer_one_node;
+ }
+ t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
+ }
+ OMP_CLAUSE_NUM_TASKS_EXPR (c) = t;
+ }
+ break;
+
+ case OMP_CLAUSE_GRAINSIZE:
+ t = OMP_CLAUSE_GRAINSIZE_EXPR (c);
+ if (t == error_mark_node)
+ remove = true;
+ else if (!type_dependent_expression_p (t)
+ && !INTEGRAL_TYPE_P (TREE_TYPE (t)))
+ {
+ error ("%<grainsize%> expression must be integral");
+ remove = true;
+ }
+ else
+ {
+ t = mark_rvalue_use (t);
+ if (!processing_template_decl)
+ {
+ t = maybe_constant_value (t);
+ if (TREE_CODE (t) == INTEGER_CST
+ && tree_int_cst_sgn (t) != 1)
+ {
+ warning_at (OMP_CLAUSE_LOCATION (c), 0,
+ "%<grainsize%> value must be positive");
+ t = integer_one_node;
+ }
+ t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
+ }
+ OMP_CLAUSE_GRAINSIZE_EXPR (c) = t;
+ }
+ break;
+
+ case OMP_CLAUSE_PRIORITY:
+ t = OMP_CLAUSE_PRIORITY_EXPR (c);
+ if (t == error_mark_node)
+ remove = true;
+ else if (!type_dependent_expression_p (t)
+ && !INTEGRAL_TYPE_P (TREE_TYPE (t)))
+ {
+ error ("%<priority%> expression must be integral");
+ remove = true;
+ }
+ else
+ {
+ t = mark_rvalue_use (t);
+ if (!processing_template_decl)
+ {
+ t = maybe_constant_value (t);
+ if (TREE_CODE (t) == INTEGER_CST
+ && tree_int_cst_sgn (t) == -1)
+ {
+ warning_at (OMP_CLAUSE_LOCATION (c), 0,
+ "%<priority%> value must be non-negative");
+ t = integer_one_node;
+ }
+ t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
+ }
+ OMP_CLAUSE_PRIORITY_EXPR (c) = t;
+ }
+ break;
+
+ case OMP_CLAUSE_HINT:
+ t = OMP_CLAUSE_HINT_EXPR (c);
+ if (t == error_mark_node)
+ remove = true;
+ else if (!type_dependent_expression_p (t)
+ && !INTEGRAL_TYPE_P (TREE_TYPE (t)))
+ {
+ error ("%<num_tasks%> expression must be integral");
+ remove = true;
+ }
+ else
+ {
+ t = mark_rvalue_use (t);
+ if (!processing_template_decl)
+ {
+ t = maybe_constant_value (t);
+ t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
+ }
+ OMP_CLAUSE_HINT_EXPR (c) = t;
+ }
+ break;
+
+ case OMP_CLAUSE_IS_DEVICE_PTR:
+ case OMP_CLAUSE_USE_DEVICE_PTR:
+ field_ok = allow_fields;
+ t = OMP_CLAUSE_DECL (c);
+ if (!type_dependent_expression_p (t))
+ {
+ tree type = TREE_TYPE (t);
+ if (TREE_CODE (type) != POINTER_TYPE
+ && TREE_CODE (type) != ARRAY_TYPE
+ && (TREE_CODE (type) != REFERENCE_TYPE
+ || (TREE_CODE (TREE_TYPE (type)) != POINTER_TYPE
+ && TREE_CODE (TREE_TYPE (type)) != ARRAY_TYPE)))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qs variable is neither a pointer, nor an array"
+ "nor reference to pointer or array",
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ remove = true;
+ }
+ }
+ goto check_dup_generic;
+
case OMP_CLAUSE_NOWAIT:
case OMP_CLAUSE_ORDERED:
case OMP_CLAUSE_DEFAULT:
@@ -5855,6 +6682,10 @@ finish_omp_clauses (tree clauses)
case OMP_CLAUSE_SECTIONS:
case OMP_CLAUSE_TASKGROUP:
case OMP_CLAUSE_PROC_BIND:
+ case OMP_CLAUSE_NOGROUP:
+ case OMP_CLAUSE_THREADS:
+ case OMP_CLAUSE_SIMD:
+ case OMP_CLAUSE_DEFAULTMAP:
case OMP_CLAUSE__CILK_FOR_COUNT_:
break;
@@ -5883,7 +6714,7 @@ finish_omp_clauses (tree clauses)
{
enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
bool remove = false;
- bool need_complete_non_reference = false;
+ bool need_complete_type = false;
bool need_default_ctor = false;
bool need_copy_ctor = false;
bool need_copy_assignment = false;
@@ -5897,31 +6728,49 @@ finish_omp_clauses (tree clauses)
need_implicitly_determined = true;
break;
case OMP_CLAUSE_PRIVATE:
- need_complete_non_reference = true;
+ need_complete_type = true;
need_default_ctor = true;
need_dtor = true;
need_implicitly_determined = true;
break;
case OMP_CLAUSE_FIRSTPRIVATE:
- need_complete_non_reference = true;
+ need_complete_type = true;
need_copy_ctor = true;
need_dtor = true;
need_implicitly_determined = true;
break;
case OMP_CLAUSE_LASTPRIVATE:
- need_complete_non_reference = true;
+ need_complete_type = true;
need_copy_assignment = true;
need_implicitly_determined = true;
break;
case OMP_CLAUSE_REDUCTION:
need_implicitly_determined = true;
break;
+ case OMP_CLAUSE_LINEAR:
+ if (!declare_simd)
+ need_implicitly_determined = true;
+ break;
case OMP_CLAUSE_COPYPRIVATE:
need_copy_assignment = true;
break;
case OMP_CLAUSE_COPYIN:
need_copy_assignment = true;
break;
+ case OMP_CLAUSE_SIMDLEN:
+ if (safelen
+ && !processing_template_decl
+ && tree_int_cst_lt (OMP_CLAUSE_SAFELEN_EXPR (safelen),
+ OMP_CLAUSE_SIMDLEN_EXPR (c)))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<simdlen%> clause value is bigger than "
+ "%<safelen%> clause value");
+ OMP_CLAUSE_SIMDLEN_EXPR (c)
+ = OMP_CLAUSE_SAFELEN_EXPR (safelen);
+ }
+ pc = &OMP_CLAUSE_CHAIN (c);
+ continue;
case OMP_CLAUSE_NOWAIT:
if (copyprivate_seen)
{
@@ -5975,18 +6824,14 @@ finish_omp_clauses (tree clauses)
break;
}
- if (need_complete_non_reference || need_copy_assignment)
+ if (need_complete_type || need_copy_assignment)
{
t = require_complete_type (t);
if (t == error_mark_node)
remove = true;
else if (TREE_CODE (TREE_TYPE (t)) == REFERENCE_TYPE
- && need_complete_non_reference)
- {
- error ("%qE has reference type for %qs", t,
- omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
- remove = true;
- }
+ && !complete_type_or_else (TREE_TYPE (TREE_TYPE (t)), t))
+ remove = true;
}
if (need_implicitly_determined)
{
@@ -6014,19 +6859,21 @@ finish_omp_clauses (tree clauses)
if (share_name)
{
error ("%qE is predetermined %qs for %qs",
- t, share_name, omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ omp_clause_printable_decl (t), share_name,
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
remove = true;
}
}
/* We're interested in the base element, not arrays. */
inner_type = type = TREE_TYPE (t);
- while (TREE_CODE (inner_type) == ARRAY_TYPE)
- inner_type = TREE_TYPE (inner_type);
-
- if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+ if ((need_complete_type
+ || need_copy_assignment
+ || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
&& TREE_CODE (inner_type) == REFERENCE_TYPE)
inner_type = TREE_TYPE (inner_type);
+ while (TREE_CODE (inner_type) == ARRAY_TYPE)
+ inner_type = TREE_TYPE (inner_type);
/* Check for special function availability by building a call to one.
Save the results, because later we won't be in the right context
@@ -6051,6 +6898,134 @@ finish_omp_clauses (tree clauses)
return clauses;
}
+/* Start processing OpenMP clauses that can include any
+ privatization clauses for non-static data members. */
+
+tree
+push_omp_privatization_clauses (bool ignore_next)
+{
+ if (omp_private_member_ignore_next)
+ {
+ omp_private_member_ignore_next = ignore_next;
+ return NULL_TREE;
+ }
+ omp_private_member_ignore_next = ignore_next;
+ if (omp_private_member_map)
+ omp_private_member_vec.safe_push (error_mark_node);
+ return push_stmt_list ();
+}
+
+/* Revert remapping of any non-static data members since
+ the last push_omp_privatization_clauses () call. */
+
+void
+pop_omp_privatization_clauses (tree stmt)
+{
+ if (stmt == NULL_TREE)
+ return;
+ stmt = pop_stmt_list (stmt);
+ if (omp_private_member_map)
+ {
+ while (!omp_private_member_vec.is_empty ())
+ {
+ tree t = omp_private_member_vec.pop ();
+ if (t == error_mark_node)
+ {
+ add_stmt (stmt);
+ return;
+ }
+ bool no_decl_expr = t == integer_zero_node;
+ if (no_decl_expr)
+ t = omp_private_member_vec.pop ();
+ tree *v = omp_private_member_map->get (t);
+ gcc_assert (v);
+ if (!no_decl_expr)
+ add_decl_expr (*v);
+ omp_private_member_map->remove (t);
+ }
+ delete omp_private_member_map;
+ omp_private_member_map = NULL;
+ }
+ add_stmt (stmt);
+}
+
+/* Remember OpenMP privatization clauses mapping and clear it.
+ Used for lambdas. */
+
+void
+save_omp_privatization_clauses (vec<tree> &save)
+{
+ save = vNULL;
+ if (omp_private_member_ignore_next)
+ save.safe_push (integer_one_node);
+ omp_private_member_ignore_next = false;
+ if (!omp_private_member_map)
+ return;
+
+ while (!omp_private_member_vec.is_empty ())
+ {
+ tree t = omp_private_member_vec.pop ();
+ if (t == error_mark_node)
+ {
+ save.safe_push (t);
+ continue;
+ }
+ tree n = t;
+ if (t == integer_zero_node)
+ t = omp_private_member_vec.pop ();
+ tree *v = omp_private_member_map->get (t);
+ gcc_assert (v);
+ save.safe_push (*v);
+ save.safe_push (t);
+ if (n != t)
+ save.safe_push (n);
+ }
+ delete omp_private_member_map;
+ omp_private_member_map = NULL;
+}
+
+/* Restore OpenMP privatization clauses mapping saved by the
+ above function. */
+
+void
+restore_omp_privatization_clauses (vec<tree> &save)
+{
+ gcc_assert (omp_private_member_vec.is_empty ());
+ omp_private_member_ignore_next = false;
+ if (save.is_empty ())
+ return;
+ if (save.length () == 1 && save[0] == integer_one_node)
+ {
+ omp_private_member_ignore_next = true;
+ save.release ();
+ return;
+ }
+
+ omp_private_member_map = new hash_map <tree, tree>;
+ while (!save.is_empty ())
+ {
+ tree t = save.pop ();
+ tree n = t;
+ if (t != error_mark_node)
+ {
+ if (t == integer_one_node)
+ {
+ omp_private_member_ignore_next = true;
+ gcc_assert (save.is_empty ());
+ break;
+ }
+ if (t == integer_zero_node)
+ t = save.pop ();
+ tree &v = omp_private_member_map->get_or_insert (t);
+ v = save.pop ();
+ }
+ omp_private_member_vec.safe_push (t);
+ if (n != t)
+ omp_private_member_vec.safe_push (n);
+ }
+ save.release ();
+}
+
/* For all variables in the tree_list VARS, mark them as thread local. */
void
@@ -6228,9 +7203,10 @@ finish_omp_task (tree clauses, tree body)
into integral iterator. Return FALSE if successful. */
static bool
-handle_omp_for_class_iterator (int i, location_t locus, tree declv, tree initv,
- tree condv, tree incrv, tree *body,
- tree *pre_body, tree clauses, tree *lastp)
+handle_omp_for_class_iterator (int i, location_t locus, enum tree_code code,
+ tree declv, tree initv, tree condv, tree incrv,
+ tree *body, tree *pre_body, tree &clauses,
+ tree *lastp, int collapse, int ordered)
{
tree diff, iter_init, iter_incr = NULL, last;
tree incr_var = NULL, orig_pre_body, orig_body, c;
@@ -6388,10 +7364,25 @@ handle_omp_for_class_iterator (int i, location_t locus, tree declv, tree initv,
}
incr = cp_convert (TREE_TYPE (diff), incr, tf_warning_or_error);
+ bool taskloop_iv_seen = false;
for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
&& OMP_CLAUSE_DECL (c) == iter)
- break;
+ {
+ if (code == OMP_TASKLOOP)
+ {
+ taskloop_iv_seen = true;
+ OMP_CLAUSE_LASTPRIVATE_TASKLOOP_IV (c) = 1;
+ }
+ break;
+ }
+ else if (code == OMP_TASKLOOP
+ && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
+ && OMP_CLAUSE_DECL (c) == iter)
+ {
+ taskloop_iv_seen = true;
+ OMP_CLAUSE_PRIVATE_TASKLOOP_IV (c) = 1;
+ }
decl = create_temporary_var (TREE_TYPE (diff));
pushdecl (decl);
@@ -6399,13 +7390,33 @@ handle_omp_for_class_iterator (int i, location_t locus, tree declv, tree initv,
last = create_temporary_var (TREE_TYPE (diff));
pushdecl (last);
add_decl_expr (last);
- if (c && iter_incr == NULL)
+ if (c && iter_incr == NULL && TREE_CODE (incr) != INTEGER_CST
+ && (!ordered || (i < collapse && collapse > 1)))
{
incr_var = create_temporary_var (TREE_TYPE (diff));
pushdecl (incr_var);
add_decl_expr (incr_var);
}
gcc_assert (stmts_are_full_exprs_p ());
+ tree diffvar = NULL_TREE;
+ if (code == OMP_TASKLOOP)
+ {
+ if (!taskloop_iv_seen)
+ {
+ tree ivc = build_omp_clause (locus, OMP_CLAUSE_FIRSTPRIVATE);
+ OMP_CLAUSE_DECL (ivc) = iter;
+ cxx_omp_finish_clause (ivc, NULL);
+ OMP_CLAUSE_CHAIN (ivc) = clauses;
+ clauses = ivc;
+ }
+ tree lvc = build_omp_clause (locus, OMP_CLAUSE_FIRSTPRIVATE);
+ OMP_CLAUSE_DECL (lvc) = last;
+ OMP_CLAUSE_CHAIN (lvc) = clauses;
+ clauses = lvc;
+ diffvar = create_temporary_var (TREE_TYPE (diff));
+ pushdecl (diffvar);
+ add_decl_expr (diffvar);
+ }
orig_pre_body = *pre_body;
*pre_body = push_stmt_list ();
@@ -6416,19 +7427,32 @@ handle_omp_for_class_iterator (int i, location_t locus, tree declv, tree initv,
iter, NOP_EXPR, init,
tf_warning_or_error));
init = build_int_cst (TREE_TYPE (diff), 0);
- if (c && iter_incr == NULL)
+ if (c && iter_incr == NULL
+ && (!ordered || (i < collapse && collapse > 1)))
{
- finish_expr_stmt (build_x_modify_expr (elocus,
- incr_var, NOP_EXPR,
- incr, tf_warning_or_error));
- incr = incr_var;
+ if (incr_var)
+ {
+ finish_expr_stmt (build_x_modify_expr (elocus,
+ incr_var, NOP_EXPR,
+ incr, tf_warning_or_error));
+ incr = incr_var;
+ }
iter_incr = build_x_modify_expr (elocus,
iter, PLUS_EXPR, incr,
tf_warning_or_error);
}
+ if (c && ordered && i < collapse && collapse > 1)
+ iter_incr = incr;
finish_expr_stmt (build_x_modify_expr (elocus,
last, NOP_EXPR, init,
tf_warning_or_error));
+ if (diffvar)
+ {
+ finish_expr_stmt (build_x_modify_expr (elocus,
+ diffvar, NOP_EXPR,
+ diff, tf_warning_or_error));
+ diff = diffvar;
+ }
*pre_body = pop_stmt_list (*pre_body);
cond = cp_build_binary_op (elocus,
@@ -6455,7 +7479,22 @@ handle_omp_for_class_iterator (int i, location_t locus, tree declv, tree initv,
if (c)
{
OMP_CLAUSE_LASTPRIVATE_STMT (c) = push_stmt_list ();
- finish_expr_stmt (iter_incr);
+ if (!ordered)
+ finish_expr_stmt (iter_incr);
+ else
+ {
+ iter_init = decl;
+ if (i < collapse && collapse > 1 && !error_operand_p (iter_incr))
+ iter_init = build2 (PLUS_EXPR, TREE_TYPE (diff),
+ iter_init, iter_incr);
+ iter_init = build2 (MINUS_EXPR, TREE_TYPE (diff), iter_init, last);
+ iter_init = build_x_modify_expr (elocus,
+ iter, PLUS_EXPR, iter_init,
+ tf_warning_or_error);
+ if (iter_init != error_mark_node)
+ iter_init = build1 (NOP_EXPR, void_type_node, iter_init);
+ finish_expr_stmt (iter_init);
+ }
OMP_CLAUSE_LASTPRIVATE_STMT (c)
= pop_stmt_list (OMP_CLAUSE_LASTPRIVATE_STMT (c));
}
@@ -6477,18 +7516,29 @@ handle_omp_for_class_iterator (int i, location_t locus, tree declv, tree initv,
sk_omp scope. */
tree
-finish_omp_for (location_t locus, enum tree_code code, tree declv, tree initv,
- tree condv, tree incrv, tree body, tree pre_body, tree clauses)
+finish_omp_for (location_t locus, enum tree_code code, tree declv,
+ tree orig_declv, tree initv, tree condv, tree incrv,
+ tree body, tree pre_body, tree clauses)
{
tree omp_for = NULL, orig_incr = NULL;
tree decl = NULL, init, cond, incr, orig_decl = NULL_TREE, block = NULL_TREE;
tree last = NULL_TREE;
location_t elocus;
int i;
+ int collapse = 1;
+ int ordered = 0;
gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (initv));
gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (condv));
gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (incrv));
+ if (TREE_VEC_LENGTH (declv) > 1)
+ {
+ tree c = find_omp_clause (clauses, OMP_CLAUSE_COLLAPSE);
+ if (c)
+ collapse = tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (c));
+ if (collapse != TREE_VEC_LENGTH (declv))
+ ordered = TREE_VEC_LENGTH (declv);
+ }
for (i = 0; i < TREE_VEC_LENGTH (declv); i++)
{
decl = TREE_VEC_ELT (declv, i);
@@ -6572,6 +7622,9 @@ finish_omp_for (location_t locus, enum tree_code code, tree declv, tree initv,
return add_stmt (stmt);
}
+ if (!orig_declv)
+ orig_declv = copy_node (declv);
+
if (processing_template_decl)
orig_incr = make_tree_vec (TREE_VEC_LENGTH (incrv));
@@ -6614,9 +7667,10 @@ finish_omp_for (location_t locus, enum tree_code code, tree declv, tree initv,
}
if (code == CILK_FOR && i == 0)
orig_decl = decl;
- if (handle_omp_for_class_iterator (i, locus, declv, initv, condv,
- incrv, &body, &pre_body,
- clauses, &last))
+ if (handle_omp_for_class_iterator (i, locus, code, declv, initv,
+ condv, incrv, &body, &pre_body,
+ clauses, &last, collapse,
+ ordered))
return NULL;
continue;
}
@@ -6672,8 +7726,8 @@ finish_omp_for (location_t locus, enum tree_code code, tree declv, tree initv,
if (code == CILK_FOR && !processing_template_decl)
block = push_stmt_list ();
- omp_for = c_finish_omp_for (locus, code, declv, initv, condv, incrv,
- body, pre_body);
+ omp_for = c_finish_omp_for (locus, code, declv, orig_declv, initv, condv,
+ incrv, body, pre_body);
if (omp_for == NULL)
{
@@ -6716,6 +7770,68 @@ finish_omp_for (location_t locus, enum tree_code code, tree declv, tree initv,
}
OMP_FOR_CLAUSES (omp_for) = clauses;
+ /* For simd loops with non-static data member iterators, we could have added
+ OMP_CLAUSE_LINEAR clauses without OMP_CLAUSE_LINEAR_STEP. As we know the
+ step at this point, fill it in. */
+ if (code == OMP_SIMD && !processing_template_decl
+ && TREE_VEC_LENGTH (OMP_FOR_INCR (omp_for)) == 1)
+ for (tree c = find_omp_clause (clauses, OMP_CLAUSE_LINEAR); c;
+ c = find_omp_clause (OMP_CLAUSE_CHAIN (c), OMP_CLAUSE_LINEAR))
+ if (OMP_CLAUSE_LINEAR_STEP (c) == NULL_TREE)
+ {
+ decl = TREE_OPERAND (TREE_VEC_ELT (OMP_FOR_INIT (omp_for), 0), 0);
+ gcc_assert (decl == OMP_CLAUSE_DECL (c));
+ incr = TREE_VEC_ELT (OMP_FOR_INCR (omp_for), 0);
+ tree step, stept;
+ switch (TREE_CODE (incr))
+ {
+ case PREINCREMENT_EXPR:
+ case POSTINCREMENT_EXPR:
+ /* c_omp_for_incr_canonicalize_ptr() should have been
+ called to massage things appropriately. */
+ gcc_assert (!POINTER_TYPE_P (TREE_TYPE (decl)));
+ OMP_CLAUSE_LINEAR_STEP (c) = build_int_cst (TREE_TYPE (decl), 1);
+ break;
+ case PREDECREMENT_EXPR:
+ case POSTDECREMENT_EXPR:
+ /* c_omp_for_incr_canonicalize_ptr() should have been
+ called to massage things appropriately. */
+ gcc_assert (!POINTER_TYPE_P (TREE_TYPE (decl)));
+ OMP_CLAUSE_LINEAR_STEP (c)
+ = build_int_cst (TREE_TYPE (decl), -1);
+ break;
+ case MODIFY_EXPR:
+ gcc_assert (TREE_OPERAND (incr, 0) == decl);
+ incr = TREE_OPERAND (incr, 1);
+ switch (TREE_CODE (incr))
+ {
+ case PLUS_EXPR:
+ if (TREE_OPERAND (incr, 1) == decl)
+ step = TREE_OPERAND (incr, 0);
+ else
+ step = TREE_OPERAND (incr, 1);
+ break;
+ case MINUS_EXPR:
+ case POINTER_PLUS_EXPR:
+ gcc_assert (TREE_OPERAND (incr, 0) == decl);
+ step = TREE_OPERAND (incr, 1);
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ stept = TREE_TYPE (decl);
+ if (POINTER_TYPE_P (stept))
+ stept = sizetype;
+ step = fold_convert (stept, step);
+ if (TREE_CODE (incr) == MINUS_EXPR)
+ step = fold_build1 (NEGATE_EXPR, stept, step);
+ OMP_CLAUSE_LINEAR_STEP (c) = step;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ }
+
if (block)
{
tree omp_par = make_node (OMP_PARALLEL);
@@ -6802,7 +7918,7 @@ finish_omp_for (location_t locus, enum tree_code code, tree declv, tree initv,
OMP_CLAUSE_OPERAND (c, 0)
= cilk_for_number_of_iterations (omp_for);
OMP_CLAUSE_CHAIN (c) = clauses;
- OMP_PARALLEL_CLAUSES (omp_par) = finish_omp_clauses (c);
+ OMP_PARALLEL_CLAUSES (omp_par) = finish_omp_clauses (c, false);
add_stmt (omp_par);
return omp_par;
}