public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [committed] Allow _Atomic with -fopenmp (PR c/65467)
@ 2016-09-02 18:46 Jakub Jelinek
  2016-09-03  9:37 ` [committed] Fix up gomp/_Atomic-4.c " Jakub Jelinek
  0 siblings, 1 reply; 2+ messages in thread
From: Jakub Jelinek @ 2016-09-02 18:46 UTC (permalink / raw)
  To: Joseph S. Myers, Marek Polacek; +Cc: gcc-patches

Hi!

While even OpenMP 4.5 for C only supports C90 and C99, not C11, the current
state where we sorry when parsing _Atomic keyword in C11 mode with -fopenmp
is really bad, it affects even code that uses the C11 atomics in code which
is not using any OpenMP features.

I've committed following changes, which handle _Atomic qualified vars and
expressions in clauses where it is easy and non-controversial and rejects it
on other explicit or implicit clauses.

In particular, for clauses that take (usually integral) expression it forces
them to rvalue and thus __atomic_load* if it is _Atomic var, for shared
clause does the obvious thing - passes around the address, i.e. shares by
reference, never by in/out, private clause is also the obvious one, just
create a private _Atomic var, and firstprivate (except for target construct)
is __atomic_load* into a temporary followed by __atomic_store* to the
private copy.  Similarly various other clauses like copyin, copyprivate,
lastprivate.

In the PR I've listed in detail what is currently rejected and why, and the
testcases should cover that.

Bootstrapped/regtested on x86_64-linux and i686-linux, committed to trunk.

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.
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.

--- gcc/gimplify.c.jj	2016-08-31 20:40:26.000000000 +0200
+++ gcc/gimplify.c	2016-09-02 12:56:43.814116536 +0200
@@ -7910,7 +7910,15 @@ gimplify_adjust_omp_clauses_1 (splay_tre
   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))
@@ -7934,7 +7942,17 @@ gimplify_adjust_omp_clauses_1 (splay_tre
   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)
@@ -8089,9 +8107,21 @@ gimplify_adjust_omp_clauses (gimple_seq
 
       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);
--- gcc/omp-low.c.jj	2016-09-01 11:43:47.391233439 +0200
+++ gcc/omp-low.c	2016-09-01 12:44:17.062130554 +0200
@@ -1120,7 +1120,8 @@ maybe_lookup_field (tree var, omp_contex
 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
--- gcc/omp-simd-clone.c.jj	2016-09-01 11:43:47.635230415 +0200
+++ gcc/omp-simd-clone.c	2016-09-01 12:44:17.063130541 +0200
@@ -126,13 +126,11 @@ simd_clone_clauses_extract (struct cgrap
   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 cgrap
 	  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;
 }
--- gcc/c/c-parser.c.jj	2016-09-01 11:43:48.258222695 +0200
+++ gcc/c/c-parser.c	2016-09-01 12:44:17.127129749 +0200
@@ -2600,10 +2600,6 @@ c_parser_declspecs (c_parser *parser, st
 	     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 *pa
 		  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 *pa
 			}
 		      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
   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_parse
   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
   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
   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 *
   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 *pars
   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_parse
   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 *pa
 	    }
 
 	  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 *par
       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 *par
 	      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 *
       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_par
   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
   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_pars
   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 *p
   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 *pa
   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 *p
   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 *p
   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 *pa
   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_par
     {
       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
 		   || 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%>");
--- gcc/c/c-objc-common.h.jj	2016-09-01 11:43:47.389233464 +0200
+++ gcc/c/c-objc-common.h	2016-09-01 12:44:17.082130306 +0200
@@ -100,6 +100,12 @@ along with GCC; see the file COPYING3.
 #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 */
--- gcc/c/c-tree.h.jj	2016-09-01 11:43:47.388233476 +0200
+++ gcc/c/c-tree.h	2016-09-01 12:44:17.088130232 +0200
@@ -682,6 +682,7 @@ extern tree c_finish_transaction (locati
 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.  */
--- gcc/c/c-typeck.c.jj	2016-09-01 11:43:47.388233476 +0200
+++ gcc/c/c-typeck.c	2016-09-02 17:24:00.263348127 +0200
@@ -12072,6 +12072,13 @@ handle_omp_array_sections_1 (tree c, tre
       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, tre
 	  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
 	  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
 	      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
 		  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
 			"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
 				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
 			    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
 			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
   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
--- gcc/c-family/c-omp.c.jj	2016-09-01 11:43:47.386233501 +0200
+++ gcc/c-family/c-omp.c	2016-09-01 13:21:18.233749314 +0200
@@ -199,6 +199,11 @@ c_finish_omp_atomic (location_t loc, enu
       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
 	  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.  */
--- gcc/testsuite/gcc.dg/gomp/_Atomic-1.c.jj	2016-09-01 12:44:17.062130554 +0200
+++ gcc/testsuite/gcc.dg/gomp/_Atomic-1.c	2016-09-01 17:16:26.000000000 +0200
@@ -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; }
+}
--- gcc/testsuite/gcc.dg/gomp/_Atomic-2.c.jj	2016-09-01 15:25:45.600447786 +0200
+++ gcc/testsuite/gcc.dg/gomp/_Atomic-2.c	2016-09-01 14:55:28.000000000 +0200
@@ -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++;
+}
--- gcc/testsuite/gcc.dg/gomp/_Atomic-3.c.jj	2016-09-01 15:54:17.245884526 +0200
+++ gcc/testsuite/gcc.dg/gomp/_Atomic-3.c	2016-09-01 16:43:44.887509121 +0200
@@ -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;
+}
--- gcc/testsuite/gcc.dg/gomp/_Atomic-4.c.jj	2016-09-01 16:44:58.596581054 +0200
+++ gcc/testsuite/gcc.dg/gomp/_Atomic-4.c	2016-09-01 16:44:53.000000000 +0200
@@ -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;
+}
--- gcc/testsuite/gcc.dg/gomp/_Atomic-5.c.jj	2016-09-02 11:28:09.016506745 +0200
+++ gcc/testsuite/gcc.dg/gomp/_Atomic-5.c	2016-09-02 12:58:52.000000000 +0200
@@ -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]++;
+}

	Jakub

^ permalink raw reply	[flat|nested] 2+ messages in thread

* [committed] Fix up gomp/_Atomic-4.c (PR c/65467)
  2016-09-02 18:46 [committed] Allow _Atomic with -fopenmp (PR c/65467) Jakub Jelinek
@ 2016-09-03  9:37 ` Jakub Jelinek
  0 siblings, 0 replies; 2+ messages in thread
From: Jakub Jelinek @ 2016-09-03  9:37 UTC (permalink / raw)
  To: gcc-patches

Hi!

On Fri, Sep 02, 2016 at 08:46:21PM +0200, Jakub Jelinek wrote:
> 	* gcc.dg/gomp/_Atomic-4.c: New test.

Andreas noted in the PR the test fails on targets other than x86_64/i686.
That is because no other target yet provides the compute_vecsize_and_simdlen
target hook (basically, backend maintainers should agree on some ABI for
simd clones and implement those in the target hook).

So, I've committed following patch as obvious:

2016-09-03  Jakub Jelinek  <jakub@redhat.com>

	PR c/65467
	* gcc.dg/gomp/_Atomic-4.c: Require vect_simd_clones effective target.

--- gcc/testsuite/gcc.dg/gomp/_Atomic-4.c.jj	2016-09-02 20:36:22.000000000 +0200
+++ gcc/testsuite/gcc.dg/gomp/_Atomic-4.c	2016-09-03 10:30:29.708581112 +0200
@@ -1,6 +1,7 @@
 /* PR c/65467 */
 /* { dg-do compile } */
 /* { dg-additional-options "-std=c11" } */
+/* { dg-require-effective-target vect_simd_clones } */
 
 #pragma omp declare simd
 int


	Jakub

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2016-09-03  9:22 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-09-02 18:46 [committed] Allow _Atomic with -fopenmp (PR c/65467) Jakub Jelinek
2016-09-03  9:37 ` [committed] Fix up gomp/_Atomic-4.c " Jakub Jelinek

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).