summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@gcc.gnu.org>2016-09-02 20:38:07 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2016-09-02 20:38:07 +0200
commit9dc5773f4b529dd0fefffaf2a2bf9b9ff0195edd (patch)
tree4e53b18a2fda99a485292dfd9bf30c8fbd9145b7
parentc65236d682789b6a33510aaebfd7e83fe0f30d1a (diff)
downloadgcc-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/ChangeLog13
-rw-r--r--gcc/c-family/ChangeLog10
-rw-r--r--gcc/c-family/c-omp.c13
-rw-r--r--gcc/c/ChangeLog29
-rw-r--r--gcc/c/c-objc-common.h6
-rw-r--r--gcc/c/c-parser.c125
-rw-r--r--gcc/c/c-tree.h1
-rw-r--r--gcc/c/c-typeck.c121
-rw-r--r--gcc/gimplify.c36
-rw-r--r--gcc/omp-low.c3
-rw-r--r--gcc/omp-simd-clone.c30
-rw-r--r--gcc/testsuite/ChangeLog7
-rw-r--r--gcc/testsuite/gcc.dg/gomp/_Atomic-1.c103
-rw-r--r--gcc/testsuite/gcc.dg/gomp/_Atomic-2.c76
-rw-r--r--gcc/testsuite/gcc.dg/gomp/_Atomic-3.c65
-rw-r--r--gcc/testsuite/gcc.dg/gomp/_Atomic-4.c17
-rw-r--r--gcc/testsuite/gcc.dg/gomp/_Atomic-5.c74
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]++;
+}