diff options
author | Jakub Jelinek <jakub@gcc.gnu.org> | 2016-09-02 20:38:07 +0200 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2016-09-02 20:38:07 +0200 |
commit | 9dc5773f4b529dd0fefffaf2a2bf9b9ff0195edd (patch) | |
tree | 4e53b18a2fda99a485292dfd9bf30c8fbd9145b7 | |
parent | c65236d682789b6a33510aaebfd7e83fe0f30d1a (diff) | |
download | gcc-9dc5773f4b529dd0fefffaf2a2bf9b9ff0195edd.tar.gz |
re PR c/65467 ([libgomp] sorry, unimplemented: '_Atomic' with OpenMP)
PR c/65467
* gimplify.c (gimplify_adjust_omp_clauses_1): Diagnose implicit
map and firstprivate clauses on target construct for _Atomic
qualified decls.
(gimplify_adjust_omp_clauses): Diagnose explicit firstprivate clauses
on target construct for _Atomic qualified decls.
* omp-low.c (use_pointer_for_field): Return true for _Atomic qualified
decls.
* omp-simd-clone.c (simd_clone_clauses_extract): Warn and give up for
_Atomic qualified arguments not mentioned in uniform clause.
c/
* c-parser.c (c_parser_declspecs): Don't sorry about _Atomic if
flag_openmp.
(c_parser_omp_variable_list): Use convert_lvalue_to_rvalue
instead of mark_exp_read on low_bound/length expression.
(c_parser_omp_clause_num_gangs, c_parser_omp_clause_num_threads,
c_parser_omp_clause_num_tasks, c_parser_omp_clause_grainsize,
c_parser_omp_clause_priority, c_parser_omp_clause_hint,
c_parser_omp_clause_num_workers, c_parser_oacc_shape_clause,
c_parser_oacc_clause_tile, c_parser_omp_clause_schedule,
c_parser_omp_clause_vector_length, c_parser_omp_clause_num_teams,
c_parser_omp_clause_thread_limit, c_parser_omp_clause_aligned,
c_parser_omp_clause_linear, c_parser_omp_clause_safelen,
c_parser_omp_clause_simdlen, c_parser_omp_clause_device,
c_parser_omp_clause_dist_schedule): Use convert_lvalue_to_rvalue
instead of mark_expr_read.
(c_parser_omp_declare_reduction): Reject _Atomic qualified types.
* c-objc-common.h (LANG_HOOKS_OMP_CLAUSE_COPY_CTOR,
LANG_HOOKS_OMP_CLAUSE_ASSIGN_OP): Redefine.
* c-tree.h (c_omp_clause_copy_ctor): New prototype.
* c-typeck.c (handle_omp_array_sections_1): Diagnose _Atomic qualified
array section bases outside of depend clause, for depend clause
use convert_lvalue_to_rvalue on the base.
(c_finish_omp_clauses): Reject _Atomic qualified vars in reduction,
linear, aligned, map, to and from clauses.
(c_omp_clause_copy_ctor): New function.
c-family/
* c-omp.c (c_finish_omp_atomic): Reject _Atomic qualified expressions.
(c_finish_omp_for): Reject _Atomic qualified iterators.
testsuite/
* gcc.dg/gomp/_Atomic-1.c: New test.
* gcc.dg/gomp/_Atomic-2.c: New test.
* gcc.dg/gomp/_Atomic-3.c: New test.
* gcc.dg/gomp/_Atomic-4.c: New test.
* gcc.dg/gomp/_Atomic-5.c: New test.
From-SVN: r239964
-rw-r--r-- | gcc/ChangeLog | 13 | ||||
-rw-r--r-- | gcc/c-family/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/c-family/c-omp.c | 13 | ||||
-rw-r--r-- | gcc/c/ChangeLog | 29 | ||||
-rw-r--r-- | gcc/c/c-objc-common.h | 6 | ||||
-rw-r--r-- | gcc/c/c-parser.c | 125 | ||||
-rw-r--r-- | gcc/c/c-tree.h | 1 | ||||
-rw-r--r-- | gcc/c/c-typeck.c | 121 | ||||
-rw-r--r-- | gcc/gimplify.c | 36 | ||||
-rw-r--r-- | gcc/omp-low.c | 3 | ||||
-rw-r--r-- | gcc/omp-simd-clone.c | 30 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/gomp/_Atomic-1.c | 103 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/gomp/_Atomic-2.c | 76 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/gomp/_Atomic-3.c | 65 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/gomp/_Atomic-4.c | 17 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/gomp/_Atomic-5.c | 74 |
17 files changed, 670 insertions, 59 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 19101c478f3..b4710f9274f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +2016-09-02 Jakub Jelinek <jakub@redhat.com> + + PR c/65467 + * gimplify.c (gimplify_adjust_omp_clauses_1): Diagnose implicit + map and firstprivate clauses on target construct for _Atomic + qualified decls. + (gimplify_adjust_omp_clauses): Diagnose explicit firstprivate clauses + on target construct for _Atomic qualified decls. + * omp-low.c (use_pointer_for_field): Return true for _Atomic qualified + decls. + * omp-simd-clone.c (simd_clone_clauses_extract): Warn and give up for + _Atomic qualified arguments not mentioned in uniform clause. + 2016-09-02 David Malcolm <dmalcolm@redhat.com> * Makefile.in (OBJS-libcommon): Add edit-context.o. diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 622a288daac..9dc1fdb5544 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,4 +1,10 @@ -2016-09-01 Martin Sebor <msebor@redhat.com> +2016-09-02 Jakub Jelinek <jakub@redhat.com> + + PR c/65467 + * c-omp.c (c_finish_omp_atomic): Reject _Atomic qualified expressions. + (c_finish_omp_for): Reject _Atomic qualified iterators. + +2016-09-01 Martin Sebor <msebor@redhat.com> * c-ada-spec.c (dump_ada_function_declaration): Increase buffer size to guarantee it fits the output of the formatted function @@ -290,7 +296,7 @@ PR c++/65970 * c.opt (fconstexpr-loop-limit): New. -2016-07-22 Martin Sebor <msebor@redhat.com> +2016-07-22 Martin Sebor <msebor@redhat.com> PR c++/71675 * c-common.c (resolve_overloaded_builtin): Avoid converting diff --git a/gcc/c-family/c-omp.c b/gcc/c-family/c-omp.c index 1691c40f11a..3b131ed1843 100644 --- a/gcc/c-family/c-omp.c +++ b/gcc/c-family/c-omp.c @@ -199,6 +199,11 @@ c_finish_omp_atomic (location_t loc, enum tree_code code, error_at (loc, "invalid expression type for %<#pragma omp atomic%>"); return error_mark_node; } + if (TYPE_ATOMIC (type)) + { + error_at (loc, "%<_Atomic%> expression in %<#pragma omp atomic%>"); + return error_mark_node; + } if (opcode == RDIV_EXPR) opcode = TRUNC_DIV_EXPR; @@ -480,6 +485,14 @@ c_finish_omp_for (location_t locus, enum tree_code code, tree declv, error_at (elocus, "invalid type for iteration variable %qE", decl); fail = true; } + else if (TYPE_ATOMIC (TREE_TYPE (decl))) + { + error_at (elocus, "%<_Atomic%> iteration variable %qE", decl); + fail = true; + /* _Atomic iterator confuses stuff too much, so we risk ICE + trying to diagnose it further. */ + continue; + } /* In the case of "for (int i = 0...)", init will be a decl. It should have a DECL_INITIAL that we can turn into an assignment. */ diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index 6b00f9a5f1e..d10dd6d0689 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,32 @@ +2016-09-02 Jakub Jelinek <jakub@redhat.com> + + PR c/65467 + * c-parser.c (c_parser_declspecs): Don't sorry about _Atomic if + flag_openmp. + (c_parser_omp_variable_list): Use convert_lvalue_to_rvalue + instead of mark_exp_read on low_bound/length expression. + (c_parser_omp_clause_num_gangs, c_parser_omp_clause_num_threads, + c_parser_omp_clause_num_tasks, c_parser_omp_clause_grainsize, + c_parser_omp_clause_priority, c_parser_omp_clause_hint, + c_parser_omp_clause_num_workers, c_parser_oacc_shape_clause, + c_parser_oacc_clause_tile, c_parser_omp_clause_schedule, + c_parser_omp_clause_vector_length, c_parser_omp_clause_num_teams, + c_parser_omp_clause_thread_limit, c_parser_omp_clause_aligned, + c_parser_omp_clause_linear, c_parser_omp_clause_safelen, + c_parser_omp_clause_simdlen, c_parser_omp_clause_device, + c_parser_omp_clause_dist_schedule): Use convert_lvalue_to_rvalue + instead of mark_expr_read. + (c_parser_omp_declare_reduction): Reject _Atomic qualified types. + * c-objc-common.h (LANG_HOOKS_OMP_CLAUSE_COPY_CTOR, + LANG_HOOKS_OMP_CLAUSE_ASSIGN_OP): Redefine. + * c-tree.h (c_omp_clause_copy_ctor): New prototype. + * c-typeck.c (handle_omp_array_sections_1): Diagnose _Atomic qualified + array section bases outside of depend clause, for depend clause + use convert_lvalue_to_rvalue on the base. + (c_finish_omp_clauses): Reject _Atomic qualified vars in reduction, + linear, aligned, map, to and from clauses. + (c_omp_clause_copy_ctor): New function. + 2016-09-01 Marek Polacek <polacek@redhat.com> PR c/7652 diff --git a/gcc/c/c-objc-common.h b/gcc/c/c-objc-common.h index ccb4903ee42..14554ace114 100644 --- a/gcc/c/c-objc-common.h +++ b/gcc/c/c-objc-common.h @@ -100,6 +100,12 @@ along with GCC; see the file COPYING3. If not see #undef LANG_HOOKS_OMP_PREDETERMINED_SHARING #define LANG_HOOKS_OMP_PREDETERMINED_SHARING c_omp_predetermined_sharing +#undef LANG_HOOKS_OMP_CLAUSE_COPY_CTOR +#define LANG_HOOKS_OMP_CLAUSE_COPY_CTOR c_omp_clause_copy_ctor + +#undef LANG_HOOKS_OMP_CLAUSE_ASSIGN_OP +#define LANG_HOOKS_OMP_CLAUSE_ASSIGN_OP c_omp_clause_copy_ctor + #undef LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P #define LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P c_vla_unspec_p #endif /* GCC_C_OBJC_COMMON */ diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c index 0581899e307..0aba51c9cde 100644 --- a/gcc/c/c-parser.c +++ b/gcc/c/c-parser.c @@ -2600,10 +2600,6 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs, and objc_types_are_equivalent may also need updates. */ if (c_dialect_objc ()) sorry ("%<_Atomic%> in Objective-C"); - /* C parser handling of OpenMP constructs needs checking for - correct lvalue-to-rvalue conversions. */ - if (flag_openmp) - sorry ("%<_Atomic%> with OpenMP"); if (flag_isoc99) pedwarn_c99 (loc, OPT_Wpedantic, "ISO C99 does not support the %<_Atomic%> qualifier"); @@ -10718,8 +10714,12 @@ c_parser_omp_variable_list (c_parser *parser, c_parser_consume_token (parser); if (!c_parser_next_token_is (parser, CPP_COLON)) { - low_bound = c_parser_expression (parser).value; - mark_exp_read (low_bound); + location_t expr_loc + = c_parser_peek_token (parser)->location; + c_expr expr = c_parser_expression (parser); + expr = convert_lvalue_to_rvalue (expr_loc, expr, + false, true); + low_bound = expr.value; } if (c_parser_next_token_is (parser, CPP_CLOSE_SQUARE)) length = integer_one_node; @@ -10734,8 +10734,12 @@ c_parser_omp_variable_list (c_parser *parser, } if (!c_parser_next_token_is (parser, CPP_CLOSE_SQUARE)) { - length = c_parser_expression (parser).value; - mark_exp_read (length); + location_t expr_loc + = c_parser_peek_token (parser)->location; + c_expr expr = c_parser_expression (parser); + expr = convert_lvalue_to_rvalue (expr_loc, expr, + false, true); + length = expr.value; } } /* Look for the closing `]'. */ @@ -11257,8 +11261,9 @@ c_parser_omp_clause_num_gangs (c_parser *parser, tree list) if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) { location_t expr_loc = c_parser_peek_token (parser)->location; - tree c, t = c_parser_expression (parser).value; - mark_exp_read (t); + c_expr expr = c_parser_expression (parser); + expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true); + tree c, t = expr.value; t = c_fully_fold (t, false, NULL); c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); @@ -11301,8 +11306,9 @@ c_parser_omp_clause_num_threads (c_parser *parser, tree list) if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) { location_t expr_loc = c_parser_peek_token (parser)->location; - tree c, t = c_parser_expression (parser).value; - mark_exp_read (t); + c_expr expr = c_parser_expression (parser); + expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true); + tree c, t = expr.value; t = c_fully_fold (t, false, NULL); c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); @@ -11345,8 +11351,9 @@ c_parser_omp_clause_num_tasks (c_parser *parser, tree list) if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) { location_t expr_loc = c_parser_peek_token (parser)->location; - tree c, t = c_parser_expression (parser).value; - mark_exp_read (t); + c_expr expr = c_parser_expression (parser); + expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true); + tree c, t = expr.value; t = c_fully_fold (t, false, NULL); c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); @@ -11389,8 +11396,9 @@ c_parser_omp_clause_grainsize (c_parser *parser, tree list) if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) { location_t expr_loc = c_parser_peek_token (parser)->location; - tree c, t = c_parser_expression (parser).value; - mark_exp_read (t); + c_expr expr = c_parser_expression (parser); + expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true); + tree c, t = expr.value; t = c_fully_fold (t, false, NULL); c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); @@ -11433,8 +11441,9 @@ c_parser_omp_clause_priority (c_parser *parser, tree list) if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) { location_t expr_loc = c_parser_peek_token (parser)->location; - tree c, t = c_parser_expression (parser).value; - mark_exp_read (t); + c_expr expr = c_parser_expression (parser); + expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true); + tree c, t = expr.value; t = c_fully_fold (t, false, NULL); c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); @@ -11477,8 +11486,10 @@ c_parser_omp_clause_hint (c_parser *parser, tree list) location_t hint_loc = c_parser_peek_token (parser)->location; if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) { - tree c, t = c_parser_expression (parser).value; - mark_exp_read (t); + location_t expr_loc = c_parser_peek_token (parser)->location; + c_expr expr = c_parser_expression (parser); + expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true); + tree c, t = expr.value; t = c_fully_fold (t, false, NULL); c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); @@ -11581,8 +11592,9 @@ c_parser_omp_clause_num_workers (c_parser *parser, tree list) if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) { location_t expr_loc = c_parser_peek_token (parser)->location; - tree c, t = c_parser_expression (parser).value; - mark_exp_read (t); + c_expr expr = c_parser_expression (parser); + expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true); + tree c, t = expr.value; t = c_fully_fold (t, false, NULL); c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); @@ -11703,11 +11715,12 @@ c_parser_oacc_shape_clause (c_parser *parser, omp_clause_code kind, } location_t expr_loc = c_parser_peek_token (parser)->location; - tree expr = c_parser_expr_no_commas (parser, NULL).value; + c_expr cexpr = c_parser_expr_no_commas (parser, NULL); + cexpr = convert_lvalue_to_rvalue (expr_loc, cexpr, false, true); + tree expr = cexpr.value; if (expr == error_mark_node) goto cleanup_error; - mark_exp_read (expr); expr = c_fully_fold (expr, false, NULL); /* Attempt to statically determine when the number isn't a @@ -11842,7 +11855,9 @@ c_parser_oacc_clause_tile (c_parser *parser, tree list) else { expr_loc = c_parser_peek_token (parser)->location; - expr = c_parser_expr_no_commas (parser, NULL).value; + c_expr cexpr = c_parser_expr_no_commas (parser, NULL); + cexpr = convert_lvalue_to_rvalue (expr_loc, cexpr, false, true); + expr = cexpr.value; if (expr == error_mark_node) { @@ -11857,7 +11872,6 @@ c_parser_oacc_clause_tile (c_parser *parser, tree list) return list; } - mark_exp_read (expr); expr = c_fully_fold (expr, false, NULL); /* Attempt to statically determine when expr isn't positive. */ @@ -12180,8 +12194,9 @@ c_parser_omp_clause_schedule (c_parser *parser, tree list) c_parser_consume_token (parser); here = c_parser_peek_token (parser)->location; - t = c_parser_expr_no_commas (parser, NULL).value; - mark_exp_read (t); + c_expr expr = c_parser_expr_no_commas (parser, NULL); + expr = convert_lvalue_to_rvalue (here, expr, false, true); + t = expr.value; t = c_fully_fold (t, false, NULL); if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_RUNTIME) @@ -12266,8 +12281,9 @@ c_parser_omp_clause_vector_length (c_parser *parser, tree list) if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) { location_t expr_loc = c_parser_peek_token (parser)->location; - tree c, t = c_parser_expression (parser).value; - mark_exp_read (t); + c_expr expr = c_parser_expression (parser); + expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true); + tree c, t = expr.value; t = c_fully_fold (t, false, NULL); c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); @@ -12369,8 +12385,9 @@ c_parser_omp_clause_num_teams (c_parser *parser, tree list) if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) { location_t expr_loc = c_parser_peek_token (parser)->location; - tree c, t = c_parser_expression (parser).value; - mark_exp_read (t); + c_expr expr = c_parser_expression (parser); + expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true); + tree c, t = expr.value; t = c_fully_fold (t, false, NULL); c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); @@ -12412,8 +12429,9 @@ c_parser_omp_clause_thread_limit (c_parser *parser, tree list) if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) { location_t expr_loc = c_parser_peek_token (parser)->location; - tree c, t = c_parser_expression (parser).value; - mark_exp_read (t); + c_expr expr = c_parser_expression (parser); + expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true); + tree c, t = expr.value; t = c_fully_fold (t, false, NULL); c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); @@ -12465,8 +12483,10 @@ c_parser_omp_clause_aligned (c_parser *parser, tree list) if (c_parser_next_token_is (parser, CPP_COLON)) { c_parser_consume_token (parser); - tree alignment = c_parser_expr_no_commas (parser, NULL).value; - mark_exp_read (alignment); + location_t expr_loc = c_parser_peek_token (parser)->location; + c_expr expr = c_parser_expr_no_commas (parser, NULL); + expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true); + tree alignment = expr.value; alignment = c_fully_fold (alignment, false, NULL); if (TREE_CODE (alignment) != INTEGER_CST || !INTEGRAL_TYPE_P (TREE_TYPE (alignment)) @@ -12528,8 +12548,10 @@ c_parser_omp_clause_linear (c_parser *parser, tree list, bool is_cilk_simd_fn) if (c_parser_next_token_is (parser, CPP_COLON)) { c_parser_consume_token (parser); - step = c_parser_expression (parser).value; - mark_exp_read (step); + location_t expr_loc = c_parser_peek_token (parser)->location; + c_expr expr = c_parser_expression (parser); + expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true); + step = expr.value; step = c_fully_fold (step, false, NULL); if (is_cilk_simd_fn && TREE_CODE (step) == PARM_DECL) { @@ -12569,8 +12591,10 @@ c_parser_omp_clause_safelen (c_parser *parser, tree list) if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) return list; - t = c_parser_expr_no_commas (parser, NULL).value; - mark_exp_read (t); + location_t expr_loc = c_parser_peek_token (parser)->location; + c_expr expr = c_parser_expr_no_commas (parser, NULL); + expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true); + t = expr.value; t = c_fully_fold (t, false, NULL); if (TREE_CODE (t) != INTEGER_CST || !INTEGRAL_TYPE_P (TREE_TYPE (t)) @@ -12605,8 +12629,10 @@ c_parser_omp_clause_simdlen (c_parser *parser, tree list) if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) return list; - t = c_parser_expr_no_commas (parser, NULL).value; - mark_exp_read (t); + location_t expr_loc = c_parser_peek_token (parser)->location; + c_expr expr = c_parser_expr_no_commas (parser, NULL); + expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true); + t = expr.value; t = c_fully_fold (t, false, NULL); if (TREE_CODE (t) != INTEGER_CST || !INTEGRAL_TYPE_P (TREE_TYPE (t)) @@ -12921,8 +12947,10 @@ c_parser_omp_clause_device (c_parser *parser, tree list) location_t clause_loc = c_parser_peek_token (parser)->location; if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) { - tree c, t = c_parser_expr_no_commas (parser, NULL).value; - mark_exp_read (t); + location_t expr_loc = c_parser_peek_token (parser)->location; + c_expr expr = c_parser_expr_no_commas (parser, NULL); + expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true); + tree c, t = expr.value; t = c_fully_fold (t, false, NULL); c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); @@ -12970,8 +12998,10 @@ c_parser_omp_clause_dist_schedule (c_parser *parser, tree list) { c_parser_consume_token (parser); - t = c_parser_expr_no_commas (parser, NULL).value; - mark_exp_read (t); + location_t expr_loc = c_parser_peek_token (parser)->location; + c_expr expr = c_parser_expr_no_commas (parser, NULL); + expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true); + t = expr.value; t = c_fully_fold (t, false, NULL); c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); } @@ -16876,6 +16906,9 @@ c_parser_omp_declare_reduction (c_parser *parser, enum pragma_context context) || TREE_CODE (type) == ARRAY_TYPE) error_at (loc, "function or array type in " "%<#pragma omp declare reduction%>"); + else if (TYPE_ATOMIC (type)) + error_at (loc, "%<_Atomic%> qualified type in " + "%<#pragma omp declare reduction%>"); else if (TYPE_QUALS_NO_ADDR_SPACE (type)) error_at (loc, "const, volatile or restrict qualified type in " "%<#pragma omp declare reduction%>"); diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h index 5a8ab6df483..e8060f8b197 100644 --- a/gcc/c/c-tree.h +++ b/gcc/c/c-tree.h @@ -682,6 +682,7 @@ extern tree c_finish_transaction (location_t, tree, int); extern bool c_tree_equal (tree, tree); extern tree c_build_function_call_vec (location_t, vec<location_t>, tree, vec<tree, va_gc> *, vec<tree, va_gc> *); +extern tree c_omp_clause_copy_ctor (tree, tree, tree); /* Set to 0 at beginning of a function definition, set to 1 if a return statement that specifies a return value is seen. */ diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c index fc7a71ef21a..d56c3d6b264 100644 --- a/gcc/c/c-typeck.c +++ b/gcc/c/c-typeck.c @@ -12072,6 +12072,13 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types, if (error_operand_p (t)) return error_mark_node; ret = t; + if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND + && TYPE_ATOMIC (strip_array_types (TREE_TYPE (t)))) + { + error_at (OMP_CLAUSE_LOCATION (c), "%<_Atomic%> %qE in %qs clause", + t, omp_clause_code_name[OMP_CLAUSE_CODE (c)]); + return error_mark_node; + } if (TREE_CODE (t) == COMPONENT_REF && ort == C_ORT_OMP && (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP @@ -12109,13 +12116,35 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types, return error_mark_node; } else if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND - && VAR_P (t) && DECL_THREAD_LOCAL_P (t)) + && TYPE_ATOMIC (TREE_TYPE (t))) + { + error_at (OMP_CLAUSE_LOCATION (c), "%<_Atomic%> %qD in %qs clause", + t, omp_clause_code_name[OMP_CLAUSE_CODE (c)]); + return error_mark_node; + } + else if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND + && VAR_P (t) + && 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)]); return error_mark_node; } + if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND + && TYPE_ATOMIC (TREE_TYPE (t)) + && POINTER_TYPE_P (TREE_TYPE (t))) + { + /* If the array section is pointer based and the pointer + itself is _Atomic qualified, we need to atomically load + the pointer. */ + c_expr expr; + memset (&expr, 0, sizeof (expr)); + expr.value = ret; + expr = convert_lvalue_to_rvalue (OMP_CLAUSE_LOCATION (c), + expr, false, false); + ret = expr.value; + } return ret; } @@ -12675,7 +12704,7 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort) oacc_async = true; break; } - + for (pc = &clauses, c = clauses; c ; c = *pc) { bool remove = false; @@ -12750,6 +12779,13 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort) t = build2 (MEM_REF, atype, t, build_int_cst (ptype, 0)); OMP_CLAUSE_DECL (c) = t; } + if (TYPE_ATOMIC (type)) + { + error_at (OMP_CLAUSE_LOCATION (c), + "%<_Atomic%> %qE in %<reduction%> clause", t); + remove = true; + break; + } if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) == NULL_TREE && (FLOAT_TYPE_P (type) || TREE_CODE (type) == COMPLEX_TYPE)) @@ -12964,6 +13000,13 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort) remove = true; break; } + if (TYPE_ATOMIC (TREE_TYPE (t))) + { + error_at (OMP_CLAUSE_LOCATION (c), + "%<_Atomic%> %qD in %<linear%> clause", t); + remove = true; + break; + } } if (ort == C_ORT_OMP_DECLARE_SIMD) { @@ -13112,6 +13155,13 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort) "an array", t); remove = true; } + else if (TYPE_ATOMIC (TREE_TYPE (t))) + { + error_at (OMP_CLAUSE_LOCATION (c), + "%<_Atomic%> %qD in %<aligned%> clause", t); + remove = true; + break; + } else if (bitmap_bit_p (&aligned_head, DECL_UID (t))) { error_at (OMP_CLAUSE_LOCATION (c), @@ -13197,6 +13247,13 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort) omp_clause_code_name[OMP_CLAUSE_CODE (c)]); remove = true; } + else if (TYPE_ATOMIC (TREE_TYPE (t))) + { + error_at (OMP_CLAUSE_LOCATION (c), + "%<_Atomic%> %qE in %qs clause", t, + 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 @@ -13251,6 +13308,13 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort) t, omp_clause_code_name[OMP_CLAUSE_CODE (c)]); remove = true; } + else if (TYPE_ATOMIC (TREE_TYPE (t))) + { + error_at (OMP_CLAUSE_LOCATION (c), + "%<_Atomic%> %qE 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))) @@ -13304,6 +13368,15 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort) omp_clause_code_name[OMP_CLAUSE_CODE (c)]); remove = true; } + else if (TREE_TYPE (t) == error_mark_node) + remove = true; + else if (TYPE_ATOMIC (strip_array_types (TREE_TYPE (t)))) + { + error_at (OMP_CLAUSE_LOCATION (c), + "%<_Atomic%> %qE in %qs clause", t, + omp_clause_code_name[OMP_CLAUSE_CODE (c)]); + remove = true; + } else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER) { @@ -13644,6 +13717,50 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort) return clauses; } +/* Return code to initialize DST with a copy constructor from SRC. + C doesn't have copy constructors nor assignment operators, only for + _Atomic vars we need to perform __atomic_load from src into a temporary + followed by __atomic_store of the temporary to dst. */ + +tree +c_omp_clause_copy_ctor (tree clause, tree dst, tree src) +{ + if (!really_atomic_lvalue (dst) && !really_atomic_lvalue (src)) + return build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src); + + location_t loc = OMP_CLAUSE_LOCATION (clause); + tree type = TREE_TYPE (dst); + tree nonatomic_type = build_qualified_type (type, TYPE_UNQUALIFIED); + tree tmp = create_tmp_var (nonatomic_type); + tree tmp_addr = build_fold_addr_expr (tmp); + TREE_ADDRESSABLE (tmp) = 1; + TREE_NO_WARNING (tmp) = 1; + tree src_addr = build_fold_addr_expr (src); + tree dst_addr = build_fold_addr_expr (dst); + tree seq_cst = build_int_cst (integer_type_node, MEMMODEL_SEQ_CST); + vec<tree, va_gc> *params; + /* Expansion of a generic atomic load may require an addition + element, so allocate enough to prevent a resize. */ + vec_alloc (params, 4); + + /* Build __atomic_load (&src, &tmp, SEQ_CST); */ + tree fndecl = builtin_decl_explicit (BUILT_IN_ATOMIC_LOAD); + params->quick_push (src_addr); + params->quick_push (tmp_addr); + params->quick_push (seq_cst); + tree load = c_build_function_call_vec (loc, vNULL, fndecl, params, NULL); + + vec_alloc (params, 4); + + /* Build __atomic_store (&dst, &tmp, SEQ_CST); */ + fndecl = builtin_decl_explicit (BUILT_IN_ATOMIC_STORE); + params->quick_push (dst_addr); + params->quick_push (tmp_addr); + params->quick_push (seq_cst); + tree store = c_build_function_call_vec (loc, vNULL, fndecl, params, NULL); + return build2 (COMPOUND_EXPR, void_type_node, load, store); +} + /* Create a transaction node. */ tree diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 21e1c093385..2f0dd88ebd6 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -7911,7 +7911,15 @@ gimplify_adjust_omp_clauses_1 (splay_tree_node n, void *data) if (private_debug) code = OMP_CLAUSE_PRIVATE; else if (flags & GOVD_MAP) - code = OMP_CLAUSE_MAP; + { + code = OMP_CLAUSE_MAP; + if ((gimplify_omp_ctxp->region_type & ORT_ACC) == 0 + && TYPE_ATOMIC (strip_array_types (TREE_TYPE (decl)))) + { + error ("%<_Atomic%> %qD in implicit %<map%> clause", decl); + return 0; + } + } else if (flags & GOVD_SHARED) { if (is_global_var (decl)) @@ -7935,7 +7943,17 @@ gimplify_adjust_omp_clauses_1 (splay_tree_node n, void *data) else if (flags & GOVD_PRIVATE) code = OMP_CLAUSE_PRIVATE; else if (flags & GOVD_FIRSTPRIVATE) - code = OMP_CLAUSE_FIRSTPRIVATE; + { + code = OMP_CLAUSE_FIRSTPRIVATE; + if ((gimplify_omp_ctxp->region_type & ORT_TARGET) + && (gimplify_omp_ctxp->region_type & ORT_ACC) == 0 + && TYPE_ATOMIC (strip_array_types (TREE_TYPE (decl)))) + { + error ("%<_Atomic%> %qD in implicit %<firstprivate%> clause on " + "%<target%> construct", decl); + return 0; + } + } else if (flags & GOVD_LASTPRIVATE) code = OMP_CLAUSE_LASTPRIVATE; else if (flags & GOVD_ALIGNED) @@ -8090,9 +8108,21 @@ gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p, switch (OMP_CLAUSE_CODE (c)) { + case OMP_CLAUSE_FIRSTPRIVATE: + if ((ctx->region_type & ORT_TARGET) + && (ctx->region_type & ORT_ACC) == 0 + && TYPE_ATOMIC (strip_array_types + (TREE_TYPE (OMP_CLAUSE_DECL (c))))) + { + error_at (OMP_CLAUSE_LOCATION (c), + "%<_Atomic%> %qD in %<firstprivate%> clause on " + "%<target%> construct", OMP_CLAUSE_DECL (c)); + remove = true; + break; + } + /* FALLTHRU */ case OMP_CLAUSE_PRIVATE: case OMP_CLAUSE_SHARED: - case OMP_CLAUSE_FIRSTPRIVATE: case OMP_CLAUSE_LINEAR: decl = OMP_CLAUSE_DECL (c); n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl); diff --git a/gcc/omp-low.c b/gcc/omp-low.c index 3f7debf1fd1..7c11b504351 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -1120,7 +1120,8 @@ maybe_lookup_field (tree var, omp_context *ctx) static bool use_pointer_for_field (tree decl, omp_context *shared_ctx) { - if (AGGREGATE_TYPE_P (TREE_TYPE (decl))) + if (AGGREGATE_TYPE_P (TREE_TYPE (decl)) + || TYPE_ATOMIC (TREE_TYPE (decl))) return true; /* We can only use copy-in/copy-out semantics for shared variables diff --git a/gcc/omp-simd-clone.c b/gcc/omp-simd-clone.c index 467d8725225..c418440c550 100644 --- a/gcc/omp-simd-clone.c +++ b/gcc/omp-simd-clone.c @@ -126,13 +126,11 @@ simd_clone_clauses_extract (struct cgraph_node *node, tree clauses, clone_info->cilk_elemental = cilk_clone; if (!clauses) - { - args.release (); - return clone_info; - } + goto out; + clauses = TREE_VALUE (clauses); if (!clauses || TREE_CODE (clauses) != OMP_CLAUSE) - return clone_info; + goto out; for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t)) { @@ -252,6 +250,28 @@ simd_clone_clauses_extract (struct cgraph_node *node, tree clauses, break; } } + + out: + if (TYPE_ATOMIC (TREE_TYPE (TREE_TYPE (node->decl)))) + { + warning_at (DECL_SOURCE_LOCATION (node->decl), 0, + "ignoring %<#pragma omp declare simd%> on function " + "with %<_Atomic%> qualified return type"); + args.release (); + return NULL; + } + + for (unsigned int argno = 0; argno < clone_info->nargs; argno++) + if (TYPE_ATOMIC (args[argno]) + && clone_info->args[argno].arg_type != SIMD_CLONE_ARG_TYPE_UNIFORM) + { + warning_at (DECL_SOURCE_LOCATION (node->decl), 0, + "ignoring %<#pragma omp declare simd%> on function " + "with %<_Atomic%> qualified non-%<uniform%> argument"); + args.release (); + return NULL; + } + args.release (); return clone_info; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 4e31cbea088..434b3db5ac3 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,12 @@ 2016-09-02 Jakub Jelinek <jakub@redhat.com> + PR c/65467 + * gcc.dg/gomp/_Atomic-1.c: New test. + * gcc.dg/gomp/_Atomic-2.c: New test. + * gcc.dg/gomp/_Atomic-3.c: New test. + * gcc.dg/gomp/_Atomic-4.c: New test. + * gcc.dg/gomp/_Atomic-5.c: New test. + PR sanitizer/77396 * g++.dg/asan/pr77396.C: New test. diff --git a/gcc/testsuite/gcc.dg/gomp/_Atomic-1.c b/gcc/testsuite/gcc.dg/gomp/_Atomic-1.c new file mode 100644 index 00000000000..1f784524f67 --- /dev/null +++ b/gcc/testsuite/gcc.dg/gomp/_Atomic-1.c @@ -0,0 +1,103 @@ +/* PR c/65467 */ +/* { dg-do compile } */ +/* { dg-additional-options "-std=c11" } */ + +_Atomic int t; +#pragma omp threadprivate (t) + +void +foo (void) +{ + _Atomic int a = 4, b = 0, c, d = 3, e; + a++; + #pragma omp parallel sections num_threads (a) shared (b) private (c) firstprivate (d) lastprivate (e) + { + #pragma omp section + { + a++; + b++; + c = 5; + c++; + d++; + e = 9; + e++; + } + #pragma omp section + { + a++; + b++; + c = 5; + c++; + d++; + e = 3; + e++; + } + } + e++; + t++; + #pragma omp parallel copyin (t) private (e) + { + t++; + e = t; + #pragma omp single copyprivate (e) + { + e++; + } + e++; + } +} + +void +bar (void) +{ + int a[4]; + _Atomic int b = 1, c = 2, f = 8, g = 8, h = 0; + _Atomic int d, e[3]; + int *_Atomic p; + _Atomic int *_Atomic q; + int i, j; + p = a; + q = e; + #pragma omp target teams map (tofrom: a[b:c]) num_teams (b) thread_limit (c) + a[1]++; + #pragma omp target device(h) + ; + #pragma omp task depend (inout: a[b:c]) + ; + #pragma omp task depend (out: d, e[b:c]) priority (b) + ; + #pragma omp task depend (out: p[b:c]) + ; + #pragma omp task depend (out: q[b:c]) + ; + #pragma omp taskloop num_tasks (c) + for (i = 0; i < 16; i++) + ; + #pragma omp taskloop grainsize (c) + for (i = 0; i < 16; i++) + ; + #pragma omp parallel for schedule (dynamic, b) + for (i = 0; i < 16; i++) + ; + j = 0; + #pragma omp simd linear(j:b) + for (i = 0; i < 16; i++) + j += b; + j = 4; + #pragma omp atomic read + b = j; + #pragma omp atomic write + j = c; + #pragma omp atomic + j += c; + #pragma omp atomic capture + b = j += c; + #pragma omp atomic capture + b = ++j; + #pragma omp atomic capture + { b = j; j = c; } + #pragma omp atomic capture + { b = j; j++; } + #pragma omp atomic capture + { j *= c; b = j; } +} diff --git a/gcc/testsuite/gcc.dg/gomp/_Atomic-2.c b/gcc/testsuite/gcc.dg/gomp/_Atomic-2.c new file mode 100644 index 00000000000..159a5b3ee7d --- /dev/null +++ b/gcc/testsuite/gcc.dg/gomp/_Atomic-2.c @@ -0,0 +1,76 @@ +/* PR c/65467 */ +/* { dg-do compile } */ +/* { dg-additional-options "-std=c11" } */ + +void +f1 (void) +{ + _Atomic int i; + #pragma omp for /* { dg-error "'_Atomic' iteration variable 'i'" } */ + for (i = 0; i < 64; i++) + ; + #pragma omp parallel for /* { dg-error "'_Atomic' iteration variable 'i'" } */ + for (i = 0; i < 64; i++) + ; + #pragma omp simd /* { dg-error "'_Atomic' iteration variable 'i'" } */ + for (i = 0; i < 64; i++) + ; + #pragma omp parallel for simd /* { dg-error "'_Atomic' iteration variable 'i'" } */ + for (i = 0; i < 64; i++) + ; + #pragma omp for simd /* { dg-error "'_Atomic' iteration variable 'i'" } */ + for (i = 0; i < 64; i++) + ; + #pragma omp for /* { dg-error "'_Atomic' iteration variable 'j'" } */ + for (_Atomic int j = 0; j < 64; j++) + ; + #pragma omp parallel for /* { dg-error "'_Atomic' iteration variable 'j'" } */ + for (_Atomic int j = 0; j < 64; j++) + ; + #pragma omp simd /* { dg-error "'_Atomic' iteration variable 'j'" } */ + for (_Atomic int j = 0; j < 64; j++) + ; + #pragma omp parallel for simd /* { dg-error "'_Atomic' iteration variable 'j'" } */ + for (_Atomic int j = 0; j < 64; j++) + ; + #pragma omp for simd /* { dg-error "'_Atomic' iteration variable 'j'" } */ + for (_Atomic int j = 0; j < 64; j++) + ; +} + +void +f2 (void) +{ + _Atomic int i; + #pragma omp distribute /* { dg-error "'_Atomic' iteration variable 'i'" } */ + for (i = 0; i < 64; i++) + ; + #pragma omp distribute parallel for /* { dg-error "'_Atomic' iteration variable 'i'" } */ + for (i = 0; i < 64; i++) + ; + #pragma omp distribute parallel for simd /* { dg-error "'_Atomic' iteration variable 'i'" } */ + for (i = 0; i < 64; i++) + ; + #pragma omp distribute /* { dg-error "'_Atomic' iteration variable 'j'" } */ + for (_Atomic int j = 0; j < 64; j++) + ; + #pragma omp distribute parallel for /* { dg-error "'_Atomic' iteration variable 'j'" } */ + for (_Atomic int j = 0; j < 64; j++) + ; + #pragma omp distribute parallel for simd /* { dg-error "'_Atomic' iteration variable 'j'" } */ + for (_Atomic int j = 0; j < 64; j++) + ; +} + +void +f3 (void) +{ + int i; + _Atomic int j = 0; + #pragma omp simd linear(j:2) /* { dg-error "'_Atomic' 'j' in 'linear' clause" } */ + for (i = 0; i < 64; i++) + j += 2; + #pragma omp parallel for linear(j:1) /* { dg-error "'_Atomic' 'j' in 'linear' clause" } */ + for (i = 0; i < 64; i++) + j++; +} diff --git a/gcc/testsuite/gcc.dg/gomp/_Atomic-3.c b/gcc/testsuite/gcc.dg/gomp/_Atomic-3.c new file mode 100644 index 00000000000..31dd1cb1122 --- /dev/null +++ b/gcc/testsuite/gcc.dg/gomp/_Atomic-3.c @@ -0,0 +1,65 @@ +/* PR c/65467 */ +/* { dg-do compile } */ +/* { dg-additional-options "-std=c11" } */ + +void +f1 (void) +{ + _Atomic int i = 0, k[4]; + int j = 0; + k[0] = 0; + k[1] = 0; + k[2] = 0; + k[3] = 0; + #pragma omp parallel reduction (+:i) /* { dg-error "'_Atomic' 'i' in 'reduction' clause" } */ + i++; + #pragma omp declare reduction (foo: _Atomic int: omp_out += omp_in) initializer (omp_priv = omp_orig * 0) /* { dg-error "'_Atomic' qualified type in '#pragma omp declare reduction'" } */ + #pragma omp declare reduction (bar: int: omp_out += omp_in) initializer (omp_priv = omp_orig * 0) + #pragma omp parallel reduction (bar:j) + j++; + #pragma omp parallel reduction (bar:i) /* { dg-error "'_Atomic' 'i' in 'reduction' clause" } */ + i++; + #pragma omp parallel reduction (+:k) /* { dg-error "'_Atomic' 'k' in 'reduction' clause" } */ + k[1]++; + #pragma omp parallel reduction (+:k[1:2]) /* { dg-error "'_Atomic' \[^\n\r]* in 'reduction' clause" } */ + k[1]++; +} + +void +f2 (int *_Atomic p) +{ + #pragma omp simd aligned (p : 16) /* { dg-error "'_Atomic' 'p' in 'aligned' clause" } */ + for (int i = 0; i < 16; i++) + p[i]++; +} + +_Atomic int x; + +void +f3 (_Atomic int *p) +{ + int i; + #pragma omp atomic write + x = 6; /* { dg-error "'_Atomic' expression in '#pragma omp atomic'" } */ + #pragma omp atomic read + i = x; /* { dg-error "'_Atomic' expression in '#pragma omp atomic'" } */ + #pragma omp atomic update + x += 6; /* { dg-error "'_Atomic' expression in '#pragma omp atomic'" } */ + #pragma omp atomic capture + i = x *= 2; /* { dg-error "'_Atomic' expression in '#pragma omp atomic'" } */ + #pragma omp atomic write + p[2] = 6; /* { dg-error "'_Atomic' expression in '#pragma omp atomic'" } */ + #pragma omp atomic read + i = p[2]; /* { dg-error "'_Atomic' expression in '#pragma omp atomic'" } */ + #pragma omp atomic update + p[2] += 6; /* { dg-error "'_Atomic' expression in '#pragma omp atomic'" } */ + #pragma omp atomic capture + i = p[2] *= 2; /* { dg-error "'_Atomic' expression in '#pragma omp atomic'" } */ +} + +#pragma omp declare simd linear(x:1) /* { dg-error "'_Atomic' 'x' in 'linear' clause" } */ +int +f4 (_Atomic int x, int y) +{ + return x + y; +} diff --git a/gcc/testsuite/gcc.dg/gomp/_Atomic-4.c b/gcc/testsuite/gcc.dg/gomp/_Atomic-4.c new file mode 100644 index 00000000000..c5be3c3ea9b --- /dev/null +++ b/gcc/testsuite/gcc.dg/gomp/_Atomic-4.c @@ -0,0 +1,17 @@ +/* PR c/65467 */ +/* { dg-do compile } */ +/* { dg-additional-options "-std=c11" } */ + +#pragma omp declare simd +int +f1 (_Atomic int x, int y) /* { dg-warning "ignoring '#pragma omp declare simd' on function with '_Atomic' qualified non-'uniform' argument" } */ +{ + return x + y; +} + +#pragma omp declare simd uniform(x) +int +f2 (_Atomic int x, int y) +{ + return x + y; +} diff --git a/gcc/testsuite/gcc.dg/gomp/_Atomic-5.c b/gcc/testsuite/gcc.dg/gomp/_Atomic-5.c new file mode 100644 index 00000000000..9b7f58f0329 --- /dev/null +++ b/gcc/testsuite/gcc.dg/gomp/_Atomic-5.c @@ -0,0 +1,74 @@ +/* PR c/65467 */ +/* { dg-do compile } */ +/* { dg-additional-options "-std=c11" } */ + +void +f1 (void) +{ + struct S { int a; int b[2]; _Atomic int *c; }; + _Atomic int a = 0, b[2]; + _Atomic int d[3]; + _Atomic struct S c = (struct S) { 3, { 4, 5 }, d }; + int *_Atomic p; + _Atomic int *q; + int e[3] = { 1, 2, 3 }; + b[0] = 1; + b[1] = 2; + d[0] = 6; + d[1] = 7; + d[2] = 8; + p = e; + #pragma omp target map(tofrom: a) /* { dg-error "'_Atomic' 'a' in 'map' clause" } */ + ; + #pragma omp target map(to: b) /* { dg-error "'_Atomic' 'b' in 'map' clause" } */ + ; + #pragma omp target map(from: b[1:1]) /* { dg-error "'_Atomic' 'b' in 'map' clause" } */ + ; + #pragma omp target map(to: c.a) /* { dg-error "'_Atomic' 'c.a' in 'map' clause" } */ + /* { dg-warning "accessing a member 'a' of an atomic structure 'c'" "" { target *-*-* } 27 } */ + ; + #pragma omp target map(to: c.b[1]) /* { dg-error "'_Atomic' 'c.b' in 'map' clause" } */ + /* { dg-warning "accessing a member 'b' of an atomic structure 'c'" "" { target *-*-* } 30 } */ + ; + #pragma omp target data map(c) /* { dg-error "'_Atomic' 'c' in 'map' clause" } */ + /* { dg-error "must contain at least one" "" { target *-*-* } 33 } */ + { + #pragma omp target update to (c.a) /* { dg-error "'_Atomic' 'c.a' in 'to' clause" } */ + /* { dg-error "must contain at least one" "" { target *-*-* } 36 } */ + /* { dg-warning "accessing a member 'a' of an atomic structure 'c'" "" { target *-*-* } 36 } */ + #pragma omp target update from (c.b[1]) /* { dg-error "'_Atomic' 'c.b' in 'from' clause" } */ + /* { dg-error "must contain at least one" "" { target *-*-* } 39 } */ + /* { dg-warning "accessing a member 'b' of an atomic structure 'c'" "" { target *-*-* } 39 } */ + #pragma omp target update to (c) /* { dg-error "'_Atomic' 'c' in 'to' clause" } */ + /* { dg-error "must contain at least one" "" { target *-*-* } 42 } */ + } + #pragma omp target map(to: c.c[0:]) /* { dg-error "'_Atomic' 'c.c' in 'map' clause" } */ + /* { dg-warning "accessing a member 'c' of an atomic structure 'c'" "" { target *-*-* } 45 } */ + ; + #pragma omp target map(to: p[1:2]) /* { dg-error "'_Atomic' 'p' in 'map' clause" } */ + ; + #pragma omp target map(to: q[1:2]) /* { dg-error "'_Atomic' '\[^\n\r]*' in 'map' clause" } */ + ; +} + +void +f2 (void) +{ + _Atomic int a = 0, b[2] = { 1, 2 }; + #pragma omp target defaultmap(tofrom:scalar) /* { dg-error "'_Atomic' 'a' in implicit 'map' clause" } */ + a++; + #pragma omp target /* { dg-error "'_Atomic' 'b' in implicit 'map' clause" } */ + b[0]++; +} + +void +f3 (void) +{ + _Atomic int a = 0, b[2] = { 1, 2 }; + #pragma omp target /* { dg-error "'_Atomic' 'a' in implicit 'firstprivate' clause on 'target' construct" } */ + a++; + #pragma omp target firstprivate (a) /* { dg-error "'_Atomic' 'a' in 'firstprivate' clause on 'target' construct" } */ + a++; + #pragma omp target firstprivate (b) /* { dg-error "'_Atomic' 'b' in 'firstprivate' clause on 'target' construct" } */ + b[0]++; +} |