re PR c/65467 ([libgomp] sorry, unimplemented: '_Atomic' with OpenMP)
authorJakub Jelinek <jakub@gcc.gnu.org>
Fri, 2 Sep 2016 18:38:07 +0000 (20:38 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Fri, 2 Sep 2016 18:38:07 +0000 (20:38 +0200)
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

17 files changed:
gcc/ChangeLog
gcc/c-family/ChangeLog
gcc/c-family/c-omp.c
gcc/c/ChangeLog
gcc/c/c-objc-common.h
gcc/c/c-parser.c
gcc/c/c-tree.h
gcc/c/c-typeck.c
gcc/gimplify.c
gcc/omp-low.c
gcc/omp-simd-clone.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/gomp/_Atomic-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/gomp/_Atomic-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/gomp/_Atomic-3.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/gomp/_Atomic-4.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/gomp/_Atomic-5.c [new file with mode: 0644]

index 19101c478f39c47aa3f69891d7c1bf59d607f387..b4710f9274f10d2852d93ab06f866be39ddd5cd4 100644 (file)
@@ -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.
index 622a288daac92e8c4a1ac862c3574c84c7e8e8cc..9dc1fdb55440d4cafa9376d3224393d1e358aaac 100644 (file)
@@ -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
        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
index 1691c40f11a661cafb8fbe53a4689be64d13ad60..3b131ed1843109a18d72e58432ae6bfa57df0ae2 100644 (file)
@@ -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.  */
index 6b00f9a5f1e6b9695ac889c731098e493160439a..d10dd6d0689b610d7ee0b36ad91d62472fed2f06 100644 (file)
@@ -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
index ccb4903ee429c700c2673ce7ed757b1217002373..14554ace114a916c66f5fadfd7a04df770d2ad98 100644 (file)
@@ -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 */
index 0581899e307dd782cd1d6c45c0a8a050f9928f4b..0aba51c9cde994d72baa0908b6385476fc4ee07f 100644 (file)
@@ -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%>");
index 5a8ab6df48381d14a8d53f092b8fe657a6aac9de..e8060f8b1977afde270cb90bf829d814af59139a 100644 (file)
@@ -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.  */
index fc7a71ef21ab5270fed470c291a1c06d9d8472ff..d56c3d6b2643f3a2a755210357a2c6ffbeb7c179 100644 (file)
@@ -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
index 21e1c093385c6f1a417ed9c2020752d16a29e529..2f0dd88ebd67848f2859376c3f94707f034a92bc 100644 (file)
@@ -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);
index 3f7debf1fd1e9c5b5d5e9bf32390e4299a7f977a..7c11b5043519b325df7cc3afcf7c2f4cad6f6711 100644 (file)
@@ -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
index 467d8725225750e5bbc1609aa0bcc3b224e8fda8..c418440c55079f1352afbc03cb6a2abe46b3ef7d 100644 (file)
@@ -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;
 }
index 4e31cbea08809f33062223959ff56ea0f7182b68..434b3db5ac33c97696d4f2f485fa76fb50e0e490 100644 (file)
@@ -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 (file)
index 0000000..1f78452
--- /dev/null
@@ -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 (file)
index 0000000..159a5b3
--- /dev/null
@@ -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 (file)
index 0000000..31dd1cb
--- /dev/null
@@ -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 (file)
index 0000000..c5be3c3
--- /dev/null
@@ -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 (file)
index 0000000..9b7f58f
--- /dev/null
@@ -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]++;
+}