diff options
Diffstat (limited to 'gcc/cp/semantics.c')
-rw-r--r-- | gcc/cp/semantics.c | 813 |
1 files changed, 652 insertions, 161 deletions
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index b54ecb0..182d360 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -44,6 +44,7 @@ along with GCC; see the file COPYING3. If not see #include "attribs.h" #include "gomp-constants.h" #include "predict.h" +#include "memmodel.h" /* There routines provide a modular interface to perform many parsing operations. They may therefore be used during actual parsing, or @@ -4634,7 +4635,9 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types, } if (ort == C_ORT_OMP - && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION + && (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, @@ -4693,7 +4696,9 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types, if (!integer_nonzerop (length)) { if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND - || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION) + || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION + || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION + || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION) { if (integer_zerop (length)) { @@ -4759,7 +4764,9 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types, if (tree_int_cst_equal (size, low_bound)) { if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND - || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION) + || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION + || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION + || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION) { error_at (OMP_CLAUSE_LOCATION (c), "zero length array section in %qs clause", @@ -4778,7 +4785,9 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types, else if (length == NULL_TREE) { if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND - && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION) + && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION + && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_IN_REDUCTION + && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_TASK_REDUCTION) maybe_zero_len = true; if (first_non_one == types.length ()) first_non_one++; @@ -4814,7 +4823,9 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types, else if (length == NULL_TREE) { if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND - && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION) + && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION + && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_IN_REDUCTION + && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_TASK_REDUCTION) maybe_zero_len = true; if (first_non_one == types.length ()) first_non_one++; @@ -4886,7 +4897,13 @@ handle_omp_array_sections (tree c, enum c_omp_region_type ort) bool maybe_zero_len = false; unsigned int first_non_one = 0; auto_vec<tree, 10> types; - tree first = handle_omp_array_sections_1 (c, OMP_CLAUSE_DECL (c), types, + tree *tp = &OMP_CLAUSE_DECL (c); + if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND + && TREE_CODE (*tp) == TREE_LIST + && TREE_PURPOSE (*tp) + && TREE_CODE (TREE_PURPOSE (*tp)) == TREE_VEC) + tp = &TREE_VALUE (*tp); + tree first = handle_omp_array_sections_1 (c, *tp, types, maybe_zero_len, first_non_one, ort); if (first == error_mark_node) @@ -4895,7 +4912,7 @@ handle_omp_array_sections (tree c, enum c_omp_region_type ort) return false; if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND) { - tree t = OMP_CLAUSE_DECL (c); + tree t = *tp; tree tem = NULL_TREE; if (processing_template_decl) return false; @@ -4915,7 +4932,7 @@ handle_omp_array_sections (tree c, enum c_omp_region_type ort) } if (tem) first = build2 (COMPOUND_EXPR, TREE_TYPE (first), tem, first); - OMP_CLAUSE_DECL (c) = first; + *tp = first; } else { @@ -4992,7 +5009,9 @@ handle_omp_array_sections (tree c, enum c_omp_region_type ort) if (i > first_non_one && ((length && integer_nonzerop (length)) - || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)) + || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION + || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION + || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION)) continue; if (length) l = fold_convert (sizetype, length); @@ -5020,7 +5039,9 @@ handle_omp_array_sections (tree c, enum c_omp_region_type ort) 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) + if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION + || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION + || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION) size = size_binop (EXACT_DIV_EXPR, size, size_in_bytes (eltype)); size = size_binop (MULT_EXPR, size, l); @@ -5036,9 +5057,12 @@ handle_omp_array_sections (tree c, enum c_omp_region_type ort) { if (side_effects) size = build2 (COMPOUND_EXPR, sizetype, side_effects, size); - if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION) + if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION + || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION + || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION) { size = size_binop (MINUS_EXPR, size, size_one_node); + size = save_expr (size); tree index_type = build_index_type (size); tree eltype = TREE_TYPE (first); while (TREE_CODE (eltype) == ARRAY_TYPE) @@ -5576,11 +5600,13 @@ finish_omp_reduction_clause (tree c, bool *need_default_ctor, bool *need_dtor) TYPE_SIZE_UNIT (type)); if (integer_zerop (size)) { - error ("%qE in %<reduction%> clause is a zero size array", - omp_clause_printable_decl (t)); + error_at (OMP_CLAUSE_LOCATION (c), + "%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); + size = save_expr (size); tree index_type = build_index_type (size); tree atype = build_array_type (type, index_type); tree ptype = build_pointer_type (type); @@ -5624,8 +5650,9 @@ finish_omp_reduction_clause (tree c, bool *need_default_ctor, bool *need_dtor) } else if (TYPE_READONLY (type)) { - error ("%qE has const type for %<reduction%>", - omp_clause_printable_decl (t)); + error_at (OMP_CLAUSE_LOCATION (c), + "%qE has const type for %<reduction%>", + omp_clause_printable_decl (t)); return true; } else if (!processing_template_decl) @@ -5699,7 +5726,8 @@ finish_omp_reduction_clause (tree c, bool *need_default_ctor, bool *need_dtor) if (TREE_ADDRESSABLE (DECL_EXPR_DECL (stmts[0]))) cxx_mark_addressable (placeholder); if (TREE_ADDRESSABLE (DECL_EXPR_DECL (stmts[1])) - && !TYPE_REF_P (TREE_TYPE (OMP_CLAUSE_DECL (c)))) + && (decl_placeholder + || !TYPE_REF_P (TREE_TYPE (OMP_CLAUSE_DECL (c))))) cxx_mark_addressable (decl_placeholder ? decl_placeholder : OMP_CLAUSE_DECL (c)); tree omp_out = placeholder; @@ -5725,7 +5753,9 @@ 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]))) + if (TREE_ADDRESSABLE (DECL_EXPR_DECL (stmts[3])) + && (decl_placeholder + || !TYPE_REF_P (TREE_TYPE (OMP_CLAUSE_DECL (c))))) cxx_mark_addressable (decl_placeholder ? decl_placeholder : OMP_CLAUSE_DECL (c)); if (TREE_ADDRESSABLE (DECL_EXPR_DECL (stmts[4]))) @@ -5786,8 +5816,9 @@ finish_omp_reduction_clause (tree c, bool *need_default_ctor, bool *need_dtor) *need_dtor = true; else { - error ("user defined reduction not found for %qE", - omp_clause_printable_decl (t)); + error_at (OMP_CLAUSE_LOCATION (c), + "user defined reduction not found for %qE", + omp_clause_printable_decl (t)); return true; } if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF) @@ -5868,6 +5899,155 @@ cp_finish_omp_clause_depend_sink (tree sink_clause) return false; } +/* Finish OpenMP iterators ITER. Return true if they are errorneous + and clauses containing them should be removed. */ + +static bool +cp_omp_finish_iterators (tree iter) +{ + bool ret = false; + for (tree it = iter; it; it = TREE_CHAIN (it)) + { + tree var = TREE_VEC_ELT (it, 0); + tree begin = TREE_VEC_ELT (it, 1); + tree end = TREE_VEC_ELT (it, 2); + tree step = TREE_VEC_ELT (it, 3); + tree orig_step; + tree type = TREE_TYPE (var); + location_t loc = DECL_SOURCE_LOCATION (var); + if (type == error_mark_node) + { + ret = true; + continue; + } + if (type_dependent_expression_p (var)) + continue; + if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type)) + { + error_at (loc, "iterator %qD has neither integral nor pointer type", + var); + ret = true; + continue; + } + else if (TYPE_READONLY (type)) + { + error_at (loc, "iterator %qD has const qualified type", var); + ret = true; + continue; + } + if (type_dependent_expression_p (begin) + || type_dependent_expression_p (end) + || type_dependent_expression_p (step)) + continue; + else if (error_operand_p (step)) + { + ret = true; + continue; + } + else if (!INTEGRAL_TYPE_P (TREE_TYPE (step))) + { + error_at (EXPR_LOC_OR_LOC (step, loc), + "iterator step with non-integral type"); + ret = true; + continue; + } + + begin = mark_rvalue_use (begin); + end = mark_rvalue_use (end); + step = mark_rvalue_use (step); + begin = cp_build_c_cast (type, begin, tf_warning_or_error); + end = cp_build_c_cast (type, end, tf_warning_or_error); + orig_step = step; + if (!processing_template_decl) + step = orig_step = save_expr (step); + tree stype = POINTER_TYPE_P (type) ? sizetype : type; + step = cp_build_c_cast (stype, step, tf_warning_or_error); + if (POINTER_TYPE_P (type) && !processing_template_decl) + { + begin = save_expr (begin); + step = pointer_int_sum (loc, PLUS_EXPR, begin, step); + step = fold_build2_loc (loc, MINUS_EXPR, sizetype, + fold_convert (sizetype, step), + fold_convert (sizetype, begin)); + step = fold_convert (ssizetype, step); + } + if (!processing_template_decl) + { + begin = maybe_constant_value (begin); + end = maybe_constant_value (end); + step = maybe_constant_value (step); + orig_step = maybe_constant_value (orig_step); + } + if (integer_zerop (step)) + { + error_at (loc, "iterator %qD has zero step", var); + ret = true; + continue; + } + + if (begin == error_mark_node + || end == error_mark_node + || step == error_mark_node + || orig_step == error_mark_node) + { + ret = true; + continue; + } + + if (!processing_template_decl) + { + begin = fold_build_cleanup_point_expr (TREE_TYPE (begin), begin); + end = fold_build_cleanup_point_expr (TREE_TYPE (end), end); + step = fold_build_cleanup_point_expr (TREE_TYPE (step), step); + orig_step = fold_build_cleanup_point_expr (TREE_TYPE (orig_step), + orig_step); + } + hash_set<tree> pset; + tree it2; + for (it2 = TREE_CHAIN (it); it2; it2 = TREE_CHAIN (it2)) + { + tree var2 = TREE_VEC_ELT (it2, 0); + tree begin2 = TREE_VEC_ELT (it2, 1); + tree end2 = TREE_VEC_ELT (it2, 2); + tree step2 = TREE_VEC_ELT (it2, 3); + location_t loc2 = DECL_SOURCE_LOCATION (var2); + if (cp_walk_tree (&begin2, find_omp_placeholder_r, var, &pset)) + { + error_at (EXPR_LOC_OR_LOC (begin2, loc2), + "begin expression refers to outer iterator %qD", var); + break; + } + else if (cp_walk_tree (&end2, find_omp_placeholder_r, var, &pset)) + { + error_at (EXPR_LOC_OR_LOC (end2, loc2), + "end expression refers to outer iterator %qD", var); + break; + } + else if (cp_walk_tree (&step2, find_omp_placeholder_r, var, &pset)) + { + error_at (EXPR_LOC_OR_LOC (step2, loc2), + "step expression refers to outer iterator %qD", var); + break; + } + } + if (it2) + { + ret = true; + continue; + } + TREE_VEC_ELT (it, 1) = begin; + TREE_VEC_ELT (it, 2) = end; + if (processing_template_decl) + TREE_VEC_ELT (it, 3) = orig_step; + else + { + TREE_VEC_ELT (it, 3) = step; + TREE_VEC_ELT (it, 4) = orig_step; + } + } + return ret; +} + /* For all elements of CLAUSES, validate them vs OpenMP constraints. Remove any elements from the list that are invalid. */ @@ -5882,14 +6062,19 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) bool copyprivate_seen = false; bool ordered_seen = false; bool oacc_async = false; + tree last_iterators = NULL_TREE; + bool last_iterators_remove = false; + bool reduction_seen = false; bitmap_obstack_initialize (NULL); bitmap_initialize (&generic_head, &bitmap_default_obstack); bitmap_initialize (&firstprivate_head, &bitmap_default_obstack); bitmap_initialize (&lastprivate_head, &bitmap_default_obstack); bitmap_initialize (&aligned_head, &bitmap_default_obstack); + /* If ort == C_ORT_OMP_DECLARE_SIMD used as uniform_head instead. */ bitmap_initialize (&map_head, &bitmap_default_obstack); bitmap_initialize (&map_field_head, &bitmap_default_obstack); + /* If ort == C_ORT_OMP used as nontemporal_head instead. */ bitmap_initialize (&oacc_reduction_head, &bitmap_default_obstack); if (ort & C_ORT_ACC) @@ -5914,6 +6099,10 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) field_ok = ((ort & C_ORT_OMP_DECLARE_SIMD) == C_ORT_OMP); goto check_dup_generic; case OMP_CLAUSE_REDUCTION: + reduction_seen = true; + /* FALLTHRU */ + case OMP_CLAUSE_IN_REDUCTION: + 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) @@ -5971,10 +6160,11 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) || OMP_CLAUSE_LINEAR_KIND (c) == OMP_CLAUSE_LINEAR_UVAL) && !TYPE_REF_P (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)); + error_at (OMP_CLAUSE_LOCATION (c), + "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; } @@ -5985,8 +6175,10 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) if (!INTEGRAL_TYPE_P (type) && !TYPE_PTR_P (type)) { - error ("linear clause applied to non-integral non-pointer" - " variable with %qT type", TREE_TYPE (t)); + error_at (OMP_CLAUSE_LOCATION (c), + "linear clause applied to non-integral " + "non-pointer variable with %qT type", + TREE_TYPE (t)); remove = true; break; } @@ -6007,7 +6199,8 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) || !TYPE_REF_P (TREE_TYPE (t)) || !INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (t))))) { - error ("linear step expression must be integral"); + error_at (OMP_CLAUSE_LOCATION (c), + "linear step expression must be integral"); remove = true; break; } @@ -6099,8 +6292,9 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) || (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_UNIFORM))) { - error ("%<this%> allowed in OpenMP only in %<declare simd%>" - " clauses"); + error_at (OMP_CLAUSE_LOCATION (c), + "%<this%> allowed in OpenMP only in %<declare simd%>" + " clauses"); remove = true; break; } @@ -6110,11 +6304,13 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) if (processing_template_decl && TREE_CODE (t) != OVERLOAD) break; if (DECL_P (t)) - error ("%qD is not a variable in clause %qs", t, - omp_clause_code_name[OMP_CLAUSE_CODE (c)]); + error_at (OMP_CLAUSE_LOCATION (c), + "%qD is not a variable in clause %qs", t, + omp_clause_code_name[OMP_CLAUSE_CODE (c)]); else - error ("%qE is not a variable in clause %qs", t, - omp_clause_code_name[OMP_CLAUSE_CODE (c)]); + 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 (ort == C_ORT_ACC @@ -6122,7 +6318,9 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) { if (bitmap_bit_p (&oacc_reduction_head, DECL_UID (t))) { - error ("%qD appears more than once in reduction clauses", t); + error_at (OMP_CLAUSE_LOCATION (c), + "%qD appears more than once in reduction clauses", + t); remove = true; } else @@ -6132,16 +6330,19 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) || bitmap_bit_p (&firstprivate_head, DECL_UID (t)) || bitmap_bit_p (&lastprivate_head, DECL_UID (t))) { - error ("%qD appears more than once in data clauses", t); + error_at (OMP_CLAUSE_LOCATION (c), + "%qD appears more than once in data clauses", t); remove = true; } else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE && bitmap_bit_p (&map_head, DECL_UID (t))) { if (ort == C_ORT_ACC) - error ("%qD appears more than once in data clauses", t); + error_at (OMP_CLAUSE_LOCATION (c), + "%qD appears more than once in data clauses", t); else - error ("%qD appears both in data and map clauses", t); + error_at (OMP_CLAUSE_LOCATION (c), + "%qD appears both in data and map clauses", t); remove = true; } else @@ -6170,8 +6371,9 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) t = OMP_CLAUSE_DECL (c); if (ort != C_ORT_ACC && t == current_class_ptr) { - error ("%<this%> allowed in OpenMP only in %<declare simd%>" - " clauses"); + error_at (OMP_CLAUSE_LOCATION (c), + "%<this%> allowed in OpenMP only in %<declare simd%>" + " clauses"); remove = true; break; } @@ -6182,23 +6384,30 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) if (processing_template_decl && TREE_CODE (t) != OVERLOAD) break; if (DECL_P (t)) - error ("%qD is not a variable in clause %<firstprivate%>", t); + error_at (OMP_CLAUSE_LOCATION (c), + "%qD is not a variable in clause %<firstprivate%>", + t); else - error ("%qE is not a variable in clause %<firstprivate%>", t); + error_at (OMP_CLAUSE_LOCATION (c), + "%qE is not a variable in clause %<firstprivate%>", + t); remove = true; } else 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); + error_at (OMP_CLAUSE_LOCATION (c), + "%qD appears more than once in data clauses", t); remove = true; } else if (bitmap_bit_p (&map_head, DECL_UID (t))) { if (ort == C_ORT_ACC) - error ("%qD appears more than once in data clauses", t); + error_at (OMP_CLAUSE_LOCATION (c), + "%qD appears more than once in data clauses", t); else - error ("%qD appears both in data and map clauses", t); + error_at (OMP_CLAUSE_LOCATION (c), + "%qD appears both in data and map clauses", t); remove = true; } else @@ -6213,8 +6422,9 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) t = OMP_CLAUSE_DECL (c); if (t == current_class_ptr) { - error ("%<this%> allowed in OpenMP only in %<declare simd%>" - " clauses"); + error_at (OMP_CLAUSE_LOCATION (c), + "%<this%> allowed in OpenMP only in %<declare simd%>" + " clauses"); remove = true; break; } @@ -6225,15 +6435,20 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) if (processing_template_decl && TREE_CODE (t) != OVERLOAD) break; if (DECL_P (t)) - error ("%qD is not a variable in clause %<lastprivate%>", t); + error_at (OMP_CLAUSE_LOCATION (c), + "%qD is not a variable in clause %<lastprivate%>", + t); else - error ("%qE is not a variable in clause %<lastprivate%>", t); + error_at (OMP_CLAUSE_LOCATION (c), + "%qE is not a variable in clause %<lastprivate%>", + t); remove = true; } else if (bitmap_bit_p (&generic_head, DECL_UID (t)) || bitmap_bit_p (&lastprivate_head, DECL_UID (t))) { - error ("%qD appears more than once in data clauses", t); + error_at (OMP_CLAUSE_LOCATION (c), + "%qD appears more than once in data clauses", t); remove = true; } else @@ -6270,7 +6485,8 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) else if (!type_dependent_expression_p (t) && !INTEGRAL_TYPE_P (TREE_TYPE (t))) { - error ("%<gang%> static expression must be integral"); + error_at (OMP_CLAUSE_LOCATION (c), + "%<gang%> static expression must be integral"); remove = true; } else @@ -6374,30 +6590,6 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) break; case OMP_CLAUSE_SCHEDULE: - if (OMP_CLAUSE_SCHEDULE_KIND (c) & OMP_CLAUSE_SCHEDULE_NONMONOTONIC) - { - const char *p = NULL; - switch (OMP_CLAUSE_SCHEDULE_KIND (c) & OMP_CLAUSE_SCHEDULE_MASK) - { - case OMP_CLAUSE_SCHEDULE_STATIC: p = "static"; break; - case OMP_CLAUSE_SCHEDULE_DYNAMIC: break; - case OMP_CLAUSE_SCHEDULE_GUIDED: break; - case OMP_CLAUSE_SCHEDULE_AUTO: p = "auto"; break; - case OMP_CLAUSE_SCHEDULE_RUNTIME: p = "runtime"; break; - default: gcc_unreachable (); - } - if (p) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%<nonmonotonic%> modifier specified for %qs " - "schedule kind", p); - OMP_CLAUSE_SCHEDULE_KIND (c) - = (enum omp_clause_schedule_kind) - (OMP_CLAUSE_SCHEDULE_KIND (c) - & ~OMP_CLAUSE_SCHEDULE_NONMONOTONIC); - } - } - t = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c); if (t == NULL) ; @@ -6406,7 +6598,8 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) else if (!type_dependent_expression_p (t) && !INTEGRAL_TYPE_P (TREE_TYPE (t))) { - error ("schedule chunk size expression must be integral"); + error_at (OMP_CLAUSE_LOCATION (c), + "schedule chunk size expression must be integral"); remove = true; } else @@ -6436,8 +6629,9 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) else if (!type_dependent_expression_p (t) && !INTEGRAL_TYPE_P (TREE_TYPE (t))) { - error ("%qs length expression must be integral", - omp_clause_code_name[OMP_CLAUSE_CODE (c)]); + error_at (OMP_CLAUSE_LOCATION (c), + "%qs length expression must be integral", + omp_clause_code_name[OMP_CLAUSE_CODE (c)]); remove = true; } else @@ -6449,9 +6643,10 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) if (TREE_CODE (t) != INTEGER_CST || tree_int_cst_sgn (t) != 1) { - error ("%qs length expression must be positive constant" - " integer expression", - omp_clause_code_name[OMP_CLAUSE_CODE (c)]); + error_at (OMP_CLAUSE_LOCATION (c), + "%qs length expression must be positive " + "constant integer expression", + omp_clause_code_name[OMP_CLAUSE_CODE (c)]); remove = true; } } @@ -6468,7 +6663,8 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) else if (!type_dependent_expression_p (t) && !INTEGRAL_TYPE_P (TREE_TYPE (t))) { - error ("%<async%> expression must be integral"); + error_at (OMP_CLAUSE_LOCATION (c), + "%<async%> expression must be integral"); remove = true; } else @@ -6496,7 +6692,8 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) else if (!type_dependent_expression_p (t) && !INTEGRAL_TYPE_P (TREE_TYPE (t))) { - error ("%<thread_limit%> expression must be integral"); + error_at (OMP_CLAUSE_LOCATION (c), + "%<thread_limit%> expression must be integral"); remove = true; } else @@ -6525,7 +6722,8 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) else if (!type_dependent_expression_p (t) && !INTEGRAL_TYPE_P (TREE_TYPE (t))) { - error ("%<device%> id must be integral"); + error_at (OMP_CLAUSE_LOCATION (c), + "%<device%> id must be integral"); remove = true; } else @@ -6546,14 +6744,15 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) else if (!type_dependent_expression_p (t) && !INTEGRAL_TYPE_P (TREE_TYPE (t))) { - error ("%<dist_schedule%> chunk size expression must be " - "integral"); + error_at (OMP_CLAUSE_LOCATION (c), + "%<dist_schedule%> chunk size expression must be " + "integral"); remove = true; } else { t = mark_rvalue_use (t); - if (!processing_template_decl) + if (!processing_template_decl) t = fold_build_cleanup_point_expr (TREE_TYPE (t), t); OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (c) = t; } @@ -6563,8 +6762,9 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) t = OMP_CLAUSE_DECL (c); if (t == current_class_ptr && ort != C_ORT_OMP_DECLARE_SIMD) { - error ("%<this%> allowed in OpenMP only in %<declare simd%>" - " clauses"); + error_at (OMP_CLAUSE_LOCATION (c), + "%<this%> allowed in OpenMP only in %<declare simd%>" + " clauses"); remove = true; break; } @@ -6573,9 +6773,11 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) if (processing_template_decl && TREE_CODE (t) != OVERLOAD) break; if (DECL_P (t)) - error ("%qD is not a variable in %<aligned%> clause", t); + error_at (OMP_CLAUSE_LOCATION (c), + "%qD is not a variable in %<aligned%> clause", t); else - error ("%qE is not a variable in %<aligned%> clause", t); + error_at (OMP_CLAUSE_LOCATION (c), + "%qE is not a variable in %<aligned%> clause", t); remove = true; } else if (!type_dependent_expression_p (t) @@ -6593,7 +6795,9 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) } else if (bitmap_bit_p (&aligned_head, DECL_UID (t))) { - error ("%qD appears more than once in %<aligned%> clauses", t); + error_at (OMP_CLAUSE_LOCATION (c), + "%qD appears more than once in %<aligned%> clauses", + t); remove = true; } else @@ -6606,8 +6810,9 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) else if (!type_dependent_expression_p (t) && !INTEGRAL_TYPE_P (TREE_TYPE (t))) { - error ("%<aligned%> clause alignment expression must " - "be integral"); + error_at (OMP_CLAUSE_LOCATION (c), + "%<aligned%> clause alignment expression must " + "be integral"); remove = true; } else @@ -6619,15 +6824,45 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) if (TREE_CODE (t) != INTEGER_CST || tree_int_cst_sgn (t) != 1) { - error ("%<aligned%> clause alignment expression must be " - "positive constant integer expression"); + error_at (OMP_CLAUSE_LOCATION (c), + "%<aligned%> clause alignment expression must " + "be positive constant integer expression"); remove = true; } + else + t = fold_build_cleanup_point_expr (TREE_TYPE (t), t); } OMP_CLAUSE_ALIGNED_ALIGNMENT (c) = t; } break; + case OMP_CLAUSE_NONTEMPORAL: + t = OMP_CLAUSE_DECL (c); + if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL) + { + if (processing_template_decl && TREE_CODE (t) != OVERLOAD) + break; + if (DECL_P (t)) + error_at (OMP_CLAUSE_LOCATION (c), + "%qD is not a variable in %<nontemporal%> clause", + t); + else + error_at (OMP_CLAUSE_LOCATION (c), + "%qE is not a variable in %<nontemporal%> clause", + t); + remove = true; + } + else if (bitmap_bit_p (&oacc_reduction_head, DECL_UID (t))) + { + error_at (OMP_CLAUSE_LOCATION (c), + "%qD appears more than once in %<nontemporal%> " + "clauses", t); + remove = true; + } + else + bitmap_set_bit (&oacc_reduction_head, DECL_UID (t)); + break; + case OMP_CLAUSE_DEPEND: t = OMP_CLAUSE_DECL (c); if (t == NULL_TREE) @@ -6642,33 +6877,108 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) remove = true; break; } + if (TREE_CODE (t) == TREE_LIST + && TREE_PURPOSE (t) + && TREE_CODE (TREE_PURPOSE (t)) == TREE_VEC) + { + if (TREE_PURPOSE (t) != last_iterators) + last_iterators_remove + = cp_omp_finish_iterators (TREE_PURPOSE (t)); + last_iterators = TREE_PURPOSE (t); + t = TREE_VALUE (t); + if (last_iterators_remove) + t = error_mark_node; + } + else + last_iterators = NULL_TREE; + if (TREE_CODE (t) == TREE_LIST) { if (handle_omp_array_sections (c, ort)) remove = true; + else if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_DEPOBJ) + { + error_at (OMP_CLAUSE_LOCATION (c), + "%<depend%> clause with %<depobj%> dependence " + "type on array section"); + remove = true; + } break; } if (t == error_mark_node) remove = true; - else if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL) + else if (t == current_class_ptr) + { + error_at (OMP_CLAUSE_LOCATION (c), + "%<this%> allowed in OpenMP only in %<declare simd%>" + " clauses"); + remove = true; + } + else if (processing_template_decl && TREE_CODE (t) != OVERLOAD) + break; + else if (!lvalue_p (t)) { - if (processing_template_decl && TREE_CODE (t) != OVERLOAD) - break; if (DECL_P (t)) - error ("%qD is not a variable in %<depend%> clause", t); + error_at (OMP_CLAUSE_LOCATION (c), + "%qD is not lvalue expression nor array section " + "in %<depend%> clause", t); else - error ("%qE is not a variable in %<depend%> clause", t); + error_at (OMP_CLAUSE_LOCATION (c), + "%qE is not lvalue expression nor array section " + "in %<depend%> clause", t); remove = true; } - else if (t == current_class_ptr) + else if (TREE_CODE (t) == COMPONENT_REF + && TREE_CODE (TREE_OPERAND (t, 1)) == FIELD_DECL + && DECL_BIT_FIELD (TREE_OPERAND (t, 1))) { - error ("%<this%> allowed in OpenMP only in %<declare simd%>" - " clauses"); + error_at (OMP_CLAUSE_LOCATION (c), + "bit-field %qE in %qs clause", t, "depend"); remove = true; } - else if (!processing_template_decl - && !cxx_mark_addressable (t)) - remove = true; + else if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_DEPOBJ) + { + if (!c_omp_depend_t_p (TYPE_REF_P (TREE_TYPE (t)) + ? TREE_TYPE (TREE_TYPE (t)) + : TREE_TYPE (t))) + { + error_at (OMP_CLAUSE_LOCATION (c), + "%qE does not have %<omp_depend_t%> type in " + "%<depend%> clause with %<depobj%> dependence " + "type", t); + remove = true; + } + } + else if (c_omp_depend_t_p (TYPE_REF_P (TREE_TYPE (t)) + ? TREE_TYPE (TREE_TYPE (t)) + : TREE_TYPE (t))) + { + error_at (OMP_CLAUSE_LOCATION (c), + "%qE should not have %<omp_depend_t%> type in " + "%<depend%> clause with dependence type other than " + "%<depobj%>", t); + remove = true; + } + if (!remove) + { + tree addr = cp_build_addr_expr (t, tf_warning_or_error); + if (addr == error_mark_node) + remove = true; + else + { + t = cp_build_indirect_ref (addr, RO_UNARY_STAR, + tf_warning_or_error); + if (t == error_mark_node) + remove = true; + else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == TREE_LIST + && TREE_PURPOSE (OMP_CLAUSE_DECL (c)) + && (TREE_CODE (TREE_PURPOSE (OMP_CLAUSE_DECL (c))) + == TREE_VEC)) + TREE_VALUE (OMP_CLAUSE_DECL (c)) = t; + else + OMP_CLAUSE_DECL (c) = t; + } + } break; case OMP_CLAUSE_MAP: @@ -6707,14 +7017,17 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) 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); + error_at (OMP_CLAUSE_LOCATION (c), + "%qD appears more than once in motion" + " clauses", t); else if (ort == C_ORT_ACC) - error ("%qD appears more than once in data" - " clauses", t); + error_at (OMP_CLAUSE_LOCATION (c), + "%qD appears more than once in data" + " clauses", t); else - error ("%qD appears more than once in map" - " clauses", t); + error_at (OMP_CLAUSE_LOCATION (c), + "%qD appears more than once in map" + " clauses", t); remove = true; } else @@ -6790,23 +7103,27 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_POINTER)) break; if (DECL_P (t)) - error ("%qD is not a variable in %qs clause", t, - omp_clause_code_name[OMP_CLAUSE_CODE (c)]); + error_at (OMP_CLAUSE_LOCATION (c), + "%qD is not a variable in %qs clause", t, + omp_clause_code_name[OMP_CLAUSE_CODE (c)]); else - error ("%qE is not a variable in %qs clause", t, - omp_clause_code_name[OMP_CLAUSE_CODE (c)]); + error_at (OMP_CLAUSE_LOCATION (c), + "%qE is not a variable in %qs clause", t, + omp_clause_code_name[OMP_CLAUSE_CODE (c)]); remove = true; } else if (VAR_P (t) && CP_DECL_THREAD_LOCAL_P (t)) { - error ("%qD is threadprivate variable in %qs clause", t, - omp_clause_code_name[OMP_CLAUSE_CODE (c)]); + 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 (ort != C_ORT_ACC && t == current_class_ptr) { - error ("%<this%> allowed in OpenMP only in %<declare simd%>" - " clauses"); + error_at (OMP_CLAUSE_LOCATION (c), + "%<this%> allowed in OpenMP only in %<declare simd%>" + " clauses"); remove = true; break; } @@ -6837,7 +7154,8 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) && !type_dependent_expression_p (t) && !INDIRECT_TYPE_P (TREE_TYPE (t))) { - error ("%qD is not a pointer variable", t); + error_at (OMP_CLAUSE_LOCATION (c), + "%qD is not a pointer variable", t); remove = true; } else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP @@ -6846,15 +7164,18 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) 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); + error_at (OMP_CLAUSE_LOCATION (c), + "%qD appears more than once in data clauses", t); remove = true; } else if (bitmap_bit_p (&map_head, DECL_UID (t))) { if (ort == C_ORT_ACC) - error ("%qD appears more than once in data clauses", t); + error_at (OMP_CLAUSE_LOCATION (c), + "%qD appears more than once in data clauses", t); else - error ("%qD appears both in data and map clauses", t); + error_at (OMP_CLAUSE_LOCATION (c), + "%qD appears both in data and map clauses", t); remove = true; } else @@ -6863,20 +7184,25 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) 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); + error_at (OMP_CLAUSE_LOCATION (c), + "%qD appears more than once in motion clauses", t); if (ort == C_ORT_ACC) - error ("%qD appears more than once in data clauses", t); + error_at (OMP_CLAUSE_LOCATION (c), + "%qD appears more than once in data clauses", t); else - error ("%qD appears more than once in map clauses", t); + error_at (OMP_CLAUSE_LOCATION (c), + "%qD appears more than once in map clauses", t); remove = true; } else if (bitmap_bit_p (&generic_head, DECL_UID (t)) || bitmap_bit_p (&firstprivate_head, DECL_UID (t))) { if (ort == C_ORT_ACC) - error ("%qD appears more than once in data clauses", t); + error_at (OMP_CLAUSE_LOCATION (c), + "%qD appears more than once in data clauses", t); else - error ("%qD appears both in data and map clauses", t); + error_at (OMP_CLAUSE_LOCATION (c), + "%qD appears both in data and map clauses", t); remove = true; } else @@ -6991,9 +7317,11 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) if (processing_template_decl) break; if (DECL_P (t)) - error ("%qD is not an argument in %<uniform%> clause", t); + error_at (OMP_CLAUSE_LOCATION (c), + "%qD is not an argument in %<uniform%> clause", t); else - error ("%qE is not an argument in %<uniform%> clause", t); + error_at (OMP_CLAUSE_LOCATION (c), + "%qE is not an argument in %<uniform%> clause", t); remove = true; break; } @@ -7008,7 +7336,8 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) else if (!type_dependent_expression_p (t) && !INTEGRAL_TYPE_P (TREE_TYPE (t))) { - error ("%<grainsize%> expression must be integral"); + error_at (OMP_CLAUSE_LOCATION (c), + "%<grainsize%> expression must be integral"); remove = true; } else @@ -7037,7 +7366,8 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) else if (!type_dependent_expression_p (t) && !INTEGRAL_TYPE_P (TREE_TYPE (t))) { - error ("%<priority%> expression must be integral"); + error_at (OMP_CLAUSE_LOCATION (c), + "%<priority%> expression must be integral"); remove = true; } else @@ -7066,7 +7396,8 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) else if (!type_dependent_expression_p (t) && !INTEGRAL_TYPE_P (TREE_TYPE (t))) { - error ("%<num_tasks%> expression must be integral"); + error_at (OMP_CLAUSE_LOCATION (c), + "%<hint%> expression must be integral"); remove = true; } else @@ -7076,6 +7407,13 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) { t = maybe_constant_value (t); t = fold_build_cleanup_point_expr (TREE_TYPE (t), t); + if (TREE_CODE (t) != INTEGER_CST) + { + error_at (OMP_CLAUSE_LOCATION (c), + "%<hint%> expression must be constant integer " + "expression"); + remove = true; + } } OMP_CLAUSE_HINT_EXPR (c) = t; } @@ -7172,8 +7510,9 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) case OMP_CLAUSE_NOTINBRANCH: if (branch_seen) { - error ("%<inbranch%> clause is incompatible with " - "%<notinbranch%>"); + error_at (OMP_CLAUSE_LOCATION (c), + "%<inbranch%> clause is incompatible with " + "%<notinbranch%>"); remove = true; } branch_seen = true; @@ -7224,6 +7563,8 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) need_implicitly_determined = true; break; case OMP_CLAUSE_REDUCTION: + case OMP_CLAUSE_IN_REDUCTION: + case OMP_CLAUSE_TASK_REDUCTION: need_implicitly_determined = true; break; case OMP_CLAUSE_LINEAR: @@ -7276,6 +7617,17 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) } pc = &OMP_CLAUSE_CHAIN (c); continue; + case OMP_CLAUSE_NOGROUP: + if (reduction_seen) + { + error_at (OMP_CLAUSE_LOCATION (c), + "%<nogroup%> clause must not be used together with " + "%<reduction%> clause"); + *pc = OMP_CLAUSE_CHAIN (c); + continue; + } + pc = &OMP_CLAUSE_CHAIN (c); + continue; case OMP_CLAUSE_NOWAIT: if (copyprivate_seen) { @@ -7310,6 +7662,8 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) break; case OMP_CLAUSE_REDUCTION: + case OMP_CLAUSE_IN_REDUCTION: + case OMP_CLAUSE_TASK_REDUCTION: if (finish_omp_reduction_clause (c, &need_default_ctor, &need_dtor)) remove = true; @@ -7320,7 +7674,8 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) case OMP_CLAUSE_COPYIN: if (!VAR_P (t) || !CP_DECL_THREAD_LOCAL_P (t)) { - error ("%qE must be %<threadprivate%> for %<copyin%>", t); + error_at (OMP_CLAUSE_LOCATION (c), + "%qE must be %<threadprivate%> for %<copyin%>", t); remove = true; } break; @@ -7349,10 +7704,17 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) case OMP_CLAUSE_DEFAULT_UNSPECIFIED: break; case OMP_CLAUSE_DEFAULT_SHARED: - /* const vars may be specified in firstprivate clause. */ - if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE + if (VAR_P (t) + && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE + && TREE_STATIC (t) && cxx_omp_const_qual_no_mutable (t)) - break; + { + tree ctx = CP_DECL_CONTEXT (t); + /* const qualified static data members without mutable + member may be specified in firstprivate clause. */ + if (TYPE_P (ctx) && MAYBE_CLASS_TYPE_P (ctx)) + break; + } share_name = "shared"; break; case OMP_CLAUSE_DEFAULT_PRIVATE: @@ -7363,9 +7725,20 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) } if (share_name) { - error ("%qE is predetermined %qs for %qs", - omp_clause_printable_decl (t), share_name, - omp_clause_code_name[OMP_CLAUSE_CODE (c)]); + error_at (OMP_CLAUSE_LOCATION (c), + "%qE is predetermined %qs for %qs", + omp_clause_printable_decl (t), share_name, + omp_clause_code_name[OMP_CLAUSE_CODE (c)]); + remove = true; + } + else if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_SHARED + && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_FIRSTPRIVATE + && cxx_omp_const_qual_no_mutable (t)) + { + error_at (OMP_CLAUSE_LOCATION (c), + "%<const%> qualified %qE without %<mutable%> member " + "may appear only in %<shared%> or %<firstprivate%> " + "clauses", omp_clause_printable_decl (t)); remove = true; } } @@ -7374,7 +7747,9 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) inner_type = type = TREE_TYPE (t); if ((need_complete_type || need_copy_assignment - || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION) + || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION + || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION + || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION) && TYPE_REF_P (inner_type)) inner_type = TREE_TYPE (inner_type); while (TREE_CODE (inner_type) == ARRAY_TYPE) @@ -7876,6 +8251,7 @@ handle_omp_for_class_iterator (int i, location_t locus, enum tree_code code, } incr = cp_convert (TREE_TYPE (diff), incr, tf_warning_or_error); + incr = cp_fully_fold (incr); bool taskloop_iv_seen = false; for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c)) if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE @@ -8011,12 +8387,22 @@ handle_omp_for_class_iterator (int i, location_t locus, enum tree_code code, = pop_stmt_list (OMP_CLAUSE_LASTPRIVATE_STMT (c)); } + if (TREE_CODE (TREE_VEC_ELT (orig_declv, i)) == TREE_LIST) + { + tree t = TREE_VEC_ELT (orig_declv, i); + gcc_assert (TREE_PURPOSE (t) == NULL_TREE + && TREE_VALUE (t) == NULL_TREE + && TREE_CODE (TREE_CHAIN (t)) == TREE_VEC); + TREE_PURPOSE (t) = TREE_VEC_ELT (declv, i); + TREE_VALUE (t) = last; + } + else + TREE_VEC_ELT (orig_declv, i) + = tree_cons (TREE_VEC_ELT (declv, i), last, NULL_TREE); TREE_VEC_ELT (declv, i) = decl; TREE_VEC_ELT (initv, i) = init; TREE_VEC_ELT (condv, i) = cond; TREE_VEC_ELT (incrv, i) = incr; - TREE_VEC_ELT (orig_declv, i) - = tree_cons (TREE_VEC_ELT (orig_declv, i), last, NULL_TREE); return false; } @@ -8098,6 +8484,9 @@ finish_omp_for (location_t locus, enum tree_code code, tree declv, if (init && EXPR_HAS_LOCATION (init)) elocus = EXPR_LOCATION (init); + if (cond == global_namespace) + continue; + if (cond == NULL) { error_at (elocus, "missing controlling predicate"); @@ -8120,7 +8509,8 @@ finish_omp_for (location_t locus, enum tree_code code, tree declv, tree orig_init; FOR_EACH_VEC_ELT (*orig_inits, i, orig_init) if (orig_init - && !c_omp_check_loop_iv_exprs (locus, declv, + && !c_omp_check_loop_iv_exprs (locus, orig_declv + ? orig_declv : declv, TREE_VEC_ELT (declv, i), orig_init, NULL_TREE, cp_walk_subtrees)) fail = true; @@ -8253,11 +8643,12 @@ finish_omp_for (location_t locus, enum tree_code code, tree declv, i++; } - if (IS_EMPTY_STMT (pre_body)) + if (pre_body && IS_EMPTY_STMT (pre_body)) pre_body = NULL; omp_for = c_finish_omp_for (locus, code, declv, orig_declv, initv, condv, - incrv, body, pre_body); + incrv, body, pre_body, + !processing_template_decl); /* Check for iterators appearing in lb, b or incr expressions. */ if (omp_for && !c_omp_check_loop_iv (omp_for, orig_declv, cp_walk_subtrees)) @@ -8369,9 +8760,55 @@ finish_omp_for (location_t locus, enum tree_code code, tree declv, return omp_for; } +/* Fix up range for decls. Those decls were pushed into BIND's BIND_EXPR_VARS + and need to be moved into the BIND_EXPR inside of the OMP_FOR's body. */ + +tree +finish_omp_for_block (tree bind, tree omp_for) +{ + if (omp_for == NULL_TREE + || !OMP_FOR_ORIG_DECLS (omp_for) + || bind == NULL_TREE + || TREE_CODE (bind) != BIND_EXPR) + return bind; + tree b = NULL_TREE; + for (int i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (omp_for)); i++) + if (TREE_CODE (TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (omp_for), i)) == TREE_LIST + && TREE_CHAIN (TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (omp_for), i))) + { + tree v = TREE_CHAIN (TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (omp_for), i)); + gcc_assert (BIND_EXPR_BLOCK (bind) + && (BIND_EXPR_VARS (bind) + == BLOCK_VARS (BIND_EXPR_BLOCK (bind)))); + for (int j = 2; j < TREE_VEC_LENGTH (v); j++) + for (tree *p = &BIND_EXPR_VARS (bind); *p; p = &DECL_CHAIN (*p)) + { + if (*p == TREE_VEC_ELT (v, j)) + { + tree var = *p; + *p = DECL_CHAIN (*p); + if (b == NULL_TREE) + { + b = make_node (BLOCK); + b = build3 (BIND_EXPR, void_type_node, NULL_TREE, + OMP_FOR_BODY (omp_for), b); + TREE_SIDE_EFFECTS (b) = 1; + OMP_FOR_BODY (omp_for) = b; + } + DECL_CHAIN (var) = BIND_EXPR_VARS (b); + BIND_EXPR_VARS (b) = var; + BLOCK_VARS (BIND_EXPR_BLOCK (b)) = var; + } + } + BLOCK_VARS (BIND_EXPR_BLOCK (bind)) = BIND_EXPR_VARS (bind); + } + return bind; +} + void -finish_omp_atomic (enum tree_code code, enum tree_code opcode, tree lhs, - tree rhs, tree v, tree lhs1, tree rhs1, bool seq_cst) +finish_omp_atomic (location_t loc, enum tree_code code, enum tree_code opcode, + tree lhs, tree rhs, tree v, tree lhs1, tree rhs1, + tree clauses, enum omp_memory_order mo) { tree orig_lhs; tree orig_rhs; @@ -8398,6 +8835,15 @@ finish_omp_atomic (enum tree_code code, enum tree_code opcode, tree lhs, || (v && type_dependent_expression_p (v)) || (lhs1 && type_dependent_expression_p (lhs1)) || (rhs1 && type_dependent_expression_p (rhs1))); + if (clauses) + { + gcc_assert (TREE_CODE (clauses) == OMP_CLAUSE + && OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_HINT + && OMP_CLAUSE_CHAIN (clauses) == NULL_TREE); + if (type_dependent_expression_p (OMP_CLAUSE_HINT_EXPR (clauses)) + || TREE_CODE (OMP_CLAUSE_HINT_EXPR (clauses)) != INTEGER_CST) + dependent_p = true; + } if (!dependent_p) { lhs = build_non_dependent_expr (lhs); @@ -8439,8 +8885,8 @@ finish_omp_atomic (enum tree_code code, enum tree_code opcode, tree lhs, "expressions for memory"); return; } - stmt = c_finish_omp_atomic (input_location, code, opcode, lhs, rhs, - v, lhs1, rhs1, swapped, seq_cst, + stmt = c_finish_omp_atomic (loc, code, opcode, lhs, rhs, + v, lhs1, rhs1, swapped, mo, processing_template_decl != 0); if (stmt == error_mark_node) return; @@ -8449,9 +8895,8 @@ finish_omp_atomic (enum tree_code code, enum tree_code opcode, tree lhs, { if (code == OMP_ATOMIC_READ) { - stmt = build_min_nt_loc (EXPR_LOCATION (orig_lhs), - OMP_ATOMIC_READ, orig_lhs); - OMP_ATOMIC_SEQ_CST (stmt) = seq_cst; + stmt = build_min_nt_loc (loc, OMP_ATOMIC_READ, orig_lhs); + OMP_ATOMIC_MEMORY_ORDER (stmt) = mo; stmt = build2 (MODIFY_EXPR, void_type_node, orig_v, stmt); } else @@ -8465,14 +8910,15 @@ finish_omp_atomic (enum tree_code code, enum tree_code opcode, tree lhs, COMPOUND_EXPR, orig_rhs1, stmt); if (code != OMP_ATOMIC) { - stmt = build_min_nt_loc (EXPR_LOCATION (orig_lhs1), - code, orig_lhs1, stmt); - OMP_ATOMIC_SEQ_CST (stmt) = seq_cst; + stmt = build_min_nt_loc (loc, code, orig_lhs1, stmt); + OMP_ATOMIC_MEMORY_ORDER (stmt) = mo; stmt = build2 (MODIFY_EXPR, void_type_node, orig_v, stmt); } } - stmt = build2 (OMP_ATOMIC, void_type_node, integer_zero_node, stmt); - OMP_ATOMIC_SEQ_CST (stmt) = seq_cst; + stmt = build2 (OMP_ATOMIC, void_type_node, + clauses ? clauses : integer_zero_node, stmt); + OMP_ATOMIC_MEMORY_ORDER (stmt) = mo; + SET_EXPR_LOCATION (stmt, loc); } finish_expr_stmt (stmt); } @@ -8488,10 +8934,50 @@ finish_omp_barrier (void) } void -finish_omp_flush (void) +finish_omp_depobj (location_t loc, tree depobj, + enum omp_clause_depend_kind kind, tree clause) +{ + if (!error_operand_p (depobj) && !type_dependent_expression_p (depobj)) + { + if (!lvalue_p (depobj)) + { + error_at (EXPR_LOC_OR_LOC (depobj, loc), + "%<depobj%> expression is not lvalue expression"); + depobj = error_mark_node; + } + } + + if (processing_template_decl) + { + if (clause == NULL_TREE) + clause = build_int_cst (integer_type_node, kind); + add_stmt (build_min_nt_loc (loc, OMP_DEPOBJ, depobj, clause)); + return; + } + + if (!error_operand_p (depobj)) + { + tree addr = cp_build_addr_expr (depobj, tf_warning_or_error); + if (addr == error_mark_node) + depobj = error_mark_node; + else + depobj = cp_build_indirect_ref (addr, RO_UNARY_STAR, + tf_warning_or_error); + } + + c_finish_omp_depobj (loc, depobj, kind, clause); +} + +void +finish_omp_flush (int mo) { tree fn = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE); vec<tree, va_gc> *vec = make_tree_vector (); + if (mo != MEMMODEL_LAST) + { + fn = builtin_decl_explicit (BUILT_IN_ATOMIC_THREAD_FENCE); + vec->quick_push (build_int_cst (integer_type_node, mo)); + } tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error); release_tree_vector (vec); finish_expr_stmt (stmt); @@ -8540,6 +9026,11 @@ finish_omp_cancel (tree clauses) tree ifc = omp_find_clause (clauses, OMP_CLAUSE_IF); if (ifc != NULL_TREE) { + if (OMP_CLAUSE_IF_MODIFIER (ifc) != ERROR_MARK + && OMP_CLAUSE_IF_MODIFIER (ifc) != VOID_CST) + error_at (OMP_CLAUSE_LOCATION (ifc), + "expected %<cancel%> %<if%> clause modifier"); + tree type = TREE_TYPE (OMP_CLAUSE_IF_EXPR (ifc)); ifc = fold_build2_loc (OMP_CLAUSE_LOCATION (ifc), NE_EXPR, boolean_type_node, OMP_CLAUSE_IF_EXPR (ifc), |