diff mbox

[C11-atomic] Miscellaneous fixes 4/n

Message ID Pine.LNX.4.64.1310260037590.21421@digraph.polyomino.org.uk
State New
Headers show

Commit Message

Joseph Myers Oct. 26, 2013, 12:39 a.m. UTC
I've committed this patch to C11-atomic branch with more miscellaneous
fixes.  The compiler changes and additions to c11-atomic-3.c are based
on reviewing existing C/ObjC front-end code for constructs likely to
need updating to handle atomics.  In addition, execution test coverage
is added for language handling of atomics (meaning loads and stores,
compound assignment, increment and decrement - other things need
<stdatomic.h>).

I'm using a new testsuite directory gcc.dg/atomic/ for the tests that
need (or may need, depending on the target) to link against libatomic.
I expect many of the existing atomic-* tests will get variants that
use <stdatomic.h> copied there, once I get onto <stdatomic.h> testing.
Tests in this directory should not have special dg-options lines for
hardware atomics support, or be restricted to targets with particular
atomics support (they *are* restricted to targets with libatomic
available, and tests for floating-point cases working correctly will
also be restricted to targets with pthreads and the <fenv.h> features
required for the testcases to test exceptions).  It seems pretty
dubious to me that the tests in the libatomic testsuite have such
dg-require-effective-target and dg-options lines; as library tests,
they should work regardless of what the compiler can inline, and
anyway they get built with -fno-inline-atomics.

With this patch, I consider the code and testsuite feature-complete
regarding the language support, except only for the special handling
of floating-point compound assignment, increment and decrement, which
needs both compiler implementation (probably including libatomic
functions) and testcases - so I'll work on that next.

c-family:
2013-10-26  Joseph Myers  <joseph@codesourcery.com>

	* c-pretty-print.c (pp_c_type_qualifier_list): Mention _Atomic in
	comment.

c:
2013-10-26  Joseph Myers  <joseph@codesourcery.com>

	* c-decl.c (get_parm_info): Diagnose any qualifier on "void" as
	only parameter.
	* c-parser.c (c_parser_declspecs): Expand list of ObjC cases
	needing updating for atomics.
	(c_parser_objc_selector): Handle _Atomic.
	* c-typeck.c (digest_init): Do not accept initialization of arrays
	of atomic elements by string constants.

testsuite:
2013-10-26  Joseph Myers  <joseph@codesourcery.com>

	* gcc.dg/c11-atomic-3.c: Add more tests.
	* lib/atomic-dg.exp, gcc.dg/atomic/atomic.exp: New files.
	* gcc.dg/atomic/c11-atomic-exec-1.c,
	gcc.dg/atomic/c11-atomic-exec-2.c,
	gcc.dg/atomic/c11-atomic-exec-3.c: New tests.
diff mbox

Patch

Index: gcc/c/c-parser.c
===================================================================
--- gcc/c/c-parser.c	(revision 204001)
+++ gcc/c/c-parser.c	(working copy)
@@ -2187,7 +2187,8 @@  c_parser_declspecs (c_parser *parser, struct c_dec
 	     the code in build_modify_expr handling various
 	     Objective-C cases, and that in build_unary_op handling
 	     Objective-C cases for increment / decrement, also needs
-	     updating.  */
+	     updating; uses of TYPE_MAIN_VARIANT in objc_compare_types
+	     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
@@ -8478,6 +8479,7 @@  c_parser_objc_synchronized_statement (c_parser *pa
        break continue return goto asm sizeof typeof __alignof
        unsigned long const short volatile signed restrict _Complex
        in out inout bycopy byref oneway int char float double void _Bool
+       _Atomic
 
    ??? Why this selection of keywords but not, for example, storage
    class specifiers?  */
@@ -8536,6 +8538,7 @@  c_parser_objc_selector (c_parser *parser)
     case RID_DOUBLE:
     case RID_VOID:
     case RID_BOOL:
+    case RID_ATOMIC:
       c_parser_consume_token (parser);
       return value;
     default:
Index: gcc/c/c-typeck.c
===================================================================
--- gcc/c/c-typeck.c	(revision 204001)
+++ gcc/c/c-typeck.c	(working copy)
@@ -6242,7 +6242,11 @@  digest_init (location_t init_loc, tree type, tree
   if (code == ARRAY_TYPE && inside_init
       && TREE_CODE (inside_init) == STRING_CST)
     {
-      tree typ1 = TYPE_MAIN_VARIANT (TREE_TYPE (type));
+      tree typ1
+	= (TYPE_ATOMIC (TREE_TYPE (type))
+	   ? c_build_qualified_type (TYPE_MAIN_VARIANT (TREE_TYPE (type)),
+				     TYPE_QUAL_ATOMIC)
+	   : TYPE_MAIN_VARIANT (TREE_TYPE (type)));
       /* Note that an array could be both an array of character type
 	 and an array of wchar_t if wchar_t is signed char or unsigned
 	 char.  */
Index: gcc/c/c-decl.c
===================================================================
--- gcc/c/c-decl.c	(revision 204001)
+++ gcc/c/c-decl.c	(working copy)
@@ -6481,8 +6481,7 @@  get_parm_info (bool ellipsis, tree expr)
       && !DECL_NAME (b->decl)               /* anonymous */
       && VOID_TYPE_P (TREE_TYPE (b->decl))) /* of void type */
     {
-      if (TREE_THIS_VOLATILE (b->decl)
-	  || TREE_READONLY (b->decl)
+      if (TYPE_QUALS (TREE_TYPE (b->decl)) != TYPE_UNQUALIFIED
 	  || C_DECL_REGISTER (b->decl))
 	error ("%<void%> as only parameter may not be qualified");
 
Index: gcc/c-family/c-pretty-print.c
===================================================================
--- gcc/c-family/c-pretty-print.c	(revision 204001)
+++ gcc/c-family/c-pretty-print.c	(working copy)
@@ -252,6 +252,7 @@  pp_c_space_for_pointer_operator (c_pretty_printer
        __restrict__                          -- GNU C
        address-space-qualifier		     -- GNU C
        volatile
+       _Atomic                               -- C11
 
    address-space-qualifier:
        identifier			     -- GNU C  */
Index: gcc/testsuite/lib/atomic-dg.exp
===================================================================
--- gcc/testsuite/lib/atomic-dg.exp	(revision 0)
+++ gcc/testsuite/lib/atomic-dg.exp	(revision 0)
@@ -0,0 +1,104 @@ 
+# Copyright (C) 2013 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3.  If not see
+# <http://www.gnu.org/licenses/>.
+
+#
+# atomic_link_flags -- compute library path and flags to find libatomic.
+# (originally from g++.exp)
+#
+
+proc atomic_link_flags { paths } {
+    global srcdir
+    global ld_library_path
+    global shlib_ext
+
+    set gccpath ${paths}
+    set flags ""
+
+    set shlib_ext [get_shlib_extension]
+
+    if { $gccpath != "" } {
+      if { [file exists "${gccpath}/libatomic/.libs/libatomic.a"]
+	   || [file exists "${gccpath}/libatomic/.libs/libatomic.${shlib_ext}"] } {
+	  append flags " -B${gccpath}/libatomic/ "
+	  append flags " -L${gccpath}/libatomic/.libs"
+	  append ld_library_path ":${gccpath}/libatomic/.libs"
+      }
+    } else {
+      global tool_root_dir
+
+      set libatomic [lookfor_file ${tool_root_dir} libatomic]
+      if { $libatomic != "" } {
+	  append flags "-L${libatomic} "
+	  append ld_library_path ":${libatomic}"
+      }
+    }
+
+    set_ld_library_path_env_vars
+
+    append flags " -latomic "
+    return "$flags"
+}
+
+#
+# atomic_init -- called at the start of each subdir of tests
+#
+
+proc atomic_init { args } {
+    global TEST_ALWAYS_FLAGS
+    global ALWAYS_CXXFLAGS
+    global TOOL_OPTIONS
+    global atomic_saved_TEST_ALWAYS_FLAGS
+
+    set link_flags ""
+    if ![is_remote host] {
+	if [info exists TOOL_OPTIONS] {
+	    set link_flags "[atomic_link_flags [get_multilibs ${TOOL_OPTIONS}]]"
+	} else {
+	    set link_flags "[atomic_link_flags [get_multilibs]]"
+	}
+    }
+
+    if [info exists TEST_ALWAYS_FLAGS] {
+	set atomic_saved_TEST_ALWAYS_FLAGS $TEST_ALWAYS_FLAGS
+    }
+    if [info exists ALWAYS_CXXFLAGS] {
+	set ALWAYS_CXXFLAGS [concat "{ldflags=$link_flags}" $ALWAYS_CXXFLAGS]
+    } else {
+	if [info exists TEST_ALWAYS_FLAGS] {
+	    set TEST_ALWAYS_FLAGS "$link_flags $TEST_ALWAYS_FLAGS"
+	} else {
+	    set TEST_ALWAYS_FLAGS "$link_flags"
+	}
+    }
+    return [check_no_compiler_messages_nocache libatomic_available executable {
+	int main (void) { return 0; }
+    }]
+}
+
+#
+# atomic_finish -- called at the end of each subdir of tests
+#
+
+proc atomic_finish { args } {
+    global TEST_ALWAYS_FLAGS
+    global atomic_saved_TEST_ALWAYS_FLAGS
+
+    if [info exists atomic_saved_TEST_ALWAYS_FLAGS] {
+	set TEST_ALWAYS_FLAGS $atomic_saved_TEST_ALWAYS_FLAGS
+    } else {
+	unset TEST_ALWAYS_FLAGS
+    }
+}
Index: gcc/testsuite/gcc.dg/c11-atomic-3.c
===================================================================
--- gcc/testsuite/gcc.dg/c11-atomic-3.c	(revision 204001)
+++ gcc/testsuite/gcc.dg/c11-atomic-3.c	(working copy)
@@ -155,3 +155,20 @@  fc4 (x) /* { dg-message "previous definition" } */
 {
 }
 void fc4 (int); /* { dg-error "incompatible type" } */
+
+/* Arrays of atomic elements cannot be initialized with string
+   literals.  */
+_Atomic char si0[] = ""; /* { dg-error "inappropriate type" } */
+_Atomic char si1[] = u8""; /* { dg-error "inappropriate type" } */
+_Atomic signed char si2[] = ""; /* { dg-error "inappropriate type" } */
+_Atomic signed char si3[] = u8""; /* { dg-error "inappropriate type" } */
+_Atomic unsigned char si4[] = ""; /* { dg-error "inappropriate type" } */
+_Atomic unsigned char si5[] = u8""; /* { dg-error "inappropriate type" } */
+_Atomic __WCHAR_TYPE__ si6[] = L""; /* { dg-error "inappropriate type" } */
+_Atomic __CHAR16_TYPE__ si7[] = u""; /* { dg-error "inappropriate type" } */
+_Atomic __CHAR32_TYPE__ si8[] = U""; /* { dg-error "inappropriate type" } */
+
+/* Anything that is syntactically a qualifier applied to the (void)
+   parameter list results in undefined behavior, which we
+   diagnose.  */
+void fv (_Atomic void); /* { dg-error "may not be qualified" } */
Index: gcc/testsuite/gcc.dg/atomic/atomic.exp
===================================================================
--- gcc/testsuite/gcc.dg/atomic/atomic.exp	(revision 0)
+++ gcc/testsuite/gcc.dg/atomic/atomic.exp	(revision 0)
@@ -0,0 +1,34 @@ 
+# Copyright (C) 2012-2013 Free Software Foundation, Inc.
+#
+# This file is part of GCC.
+#
+# GCC is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GCC is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3.  If not see
+# <http://www.gnu.org/licenses/>.
+
+# GCC testsuite that uses the `dg.exp' driver.
+
+# Load support procs.
+load_lib gcc-dg.exp
+load_lib atomic-dg.exp
+
+# Initialize `dg'.
+dg-init
+if [atomic_init] {
+    # Main loop.
+    gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] ""
+}
+
+# All done.
+atomic_finish
+dg-finish
Index: gcc/testsuite/gcc.dg/atomic/c11-atomic-exec-1.c
===================================================================
--- gcc/testsuite/gcc.dg/atomic/c11-atomic-exec-1.c	(revision 0)
+++ gcc/testsuite/gcc.dg/atomic/c11-atomic-exec-1.c	(revision 0)
@@ -0,0 +1,88 @@ 
+/* Test for _Atomic in C11.  Basic execution tests for atomic loads
+   and stores.  */
+/* { dg-do run } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+extern void abort (void);
+extern void exit (int);
+extern int memcmp (const void *, const void *, __SIZE_TYPE__);
+
+#define CMPLX(X, Y) __builtin_complex ((X), (Y))
+
+#define TEST_SIMPLE_ASSIGN(TYPE, VALUE)				\
+  do								\
+    {								\
+      static volatile _Atomic (TYPE) a, b = (TYPE) (VALUE);	\
+      if (a != 0)						\
+	abort ();						\
+      if (b != ((TYPE) (VALUE)))				\
+	abort ();						\
+      if ((a = b) != ((TYPE) (VALUE)))				\
+	abort ();						\
+      if (a != ((TYPE) (VALUE)))				\
+	abort ();						\
+    }								\
+  while (0)
+
+#define TEST_SIMPLE_ASSIGN_ARITH(VALUE)				\
+  do								\
+    {								\
+      TEST_SIMPLE_ASSIGN (_Bool, (VALUE));			\
+      TEST_SIMPLE_ASSIGN (char, (VALUE));			\
+      TEST_SIMPLE_ASSIGN (signed char, (VALUE));		\
+      TEST_SIMPLE_ASSIGN (unsigned char, (VALUE));		\
+      TEST_SIMPLE_ASSIGN (signed short, (VALUE));		\
+      TEST_SIMPLE_ASSIGN (unsigned short, (VALUE));		\
+      TEST_SIMPLE_ASSIGN (signed int, (VALUE));			\
+      TEST_SIMPLE_ASSIGN (unsigned int, (VALUE));		\
+      TEST_SIMPLE_ASSIGN (signed long, (VALUE));		\
+      TEST_SIMPLE_ASSIGN (unsigned long, (VALUE));		\
+      TEST_SIMPLE_ASSIGN (signed long long, (VALUE));		\
+      TEST_SIMPLE_ASSIGN (unsigned long long, (VALUE));		\
+      TEST_SIMPLE_ASSIGN (float, (VALUE));			\
+      TEST_SIMPLE_ASSIGN (double, (VALUE));			\
+      TEST_SIMPLE_ASSIGN (long double, (VALUE));		\
+      TEST_SIMPLE_ASSIGN (_Complex float, (VALUE));		\
+      TEST_SIMPLE_ASSIGN (_Complex double, (VALUE));		\
+      TEST_SIMPLE_ASSIGN (_Complex long double, (VALUE));	\
+    }								\
+  while (0)
+
+static void
+test_simple_assign (void)
+{
+  TEST_SIMPLE_ASSIGN_ARITH (0);
+  TEST_SIMPLE_ASSIGN_ARITH (1);
+  TEST_SIMPLE_ASSIGN_ARITH (2);
+  TEST_SIMPLE_ASSIGN_ARITH (-1);
+  TEST_SIMPLE_ASSIGN_ARITH (1ULL << 63);
+  TEST_SIMPLE_ASSIGN_ARITH (1.5);
+  TEST_SIMPLE_ASSIGN_ARITH (CMPLX (2.5, 3.5));
+  static int i;
+  TEST_SIMPLE_ASSIGN (int *, 0);
+  TEST_SIMPLE_ASSIGN (int *, &i);
+  struct s { short a[1024]; };
+  struct s init, copy;
+  _Atomic struct s s1, s2;
+  for (int j = 0; j < 1024; j++)
+    init.a[j] = j;
+  copy = (s1 = init);
+  if (memcmp (&init, &copy, sizeof init) != 0)
+    abort ();
+  copy = (s2 = s1);
+  if (memcmp (&init, &copy, sizeof init) != 0)
+    abort ();
+  copy = s1;
+  if (memcmp (&init, &copy, sizeof init) != 0)
+    abort ();
+  copy = s2;
+  if (memcmp (&init, &copy, sizeof init) != 0)
+    abort ();
+}
+
+int
+main (void)
+{
+  test_simple_assign ();
+  exit (0);
+}
Index: gcc/testsuite/gcc.dg/atomic/c11-atomic-exec-2.c
===================================================================
--- gcc/testsuite/gcc.dg/atomic/c11-atomic-exec-2.c	(revision 0)
+++ gcc/testsuite/gcc.dg/atomic/c11-atomic-exec-2.c	(revision 0)
@@ -0,0 +1,171 @@ 
+/* Test for _Atomic in C11.  Basic execution tests for atomic compound
+   assignment.  */
+/* { dg-do run } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+extern void abort (void);
+extern void exit (int);
+
+#define CMPLX(X, Y) __builtin_complex ((X), (Y))
+
+#define TEST_COMPOUND(TYPE, LHSVAL, RHSVAL, OP)				\
+  do									\
+    {									\
+      static volatile _Atomic (TYPE) a = (TYPE) (LHSVAL);		\
+      if ((a OP##= (RHSVAL)) != (TYPE) ((TYPE) (LHSVAL) OP (RHSVAL)))	\
+	abort ();							\
+      if (a != (TYPE) ((TYPE) (LHSVAL) OP (RHSVAL)))			\
+	abort ();							\
+    }									\
+  while (0)
+
+#define TEST_COMPOUND_ARITH(LHSVAL, RHSVAL, OP)				\
+  do									\
+    {									\
+      TEST_COMPOUND (_Bool, (LHSVAL), (RHSVAL), OP);			\
+      TEST_COMPOUND (char, (LHSVAL), (RHSVAL), OP);			\
+      TEST_COMPOUND (signed char, (LHSVAL), (RHSVAL), OP);		\
+      TEST_COMPOUND (unsigned char, (LHSVAL), (RHSVAL), OP);		\
+      TEST_COMPOUND (signed short, (LHSVAL), (RHSVAL), OP);		\
+      TEST_COMPOUND (unsigned short, (LHSVAL), (RHSVAL), OP);		\
+      TEST_COMPOUND (signed int, (LHSVAL), (RHSVAL), OP);		\
+      TEST_COMPOUND (unsigned int, (LHSVAL), (RHSVAL), OP);		\
+      TEST_COMPOUND (signed long, (LHSVAL), (RHSVAL), OP);		\
+      TEST_COMPOUND (unsigned long, (LHSVAL), (RHSVAL), OP);		\
+      TEST_COMPOUND (signed long long, (LHSVAL), (RHSVAL), OP);		\
+      TEST_COMPOUND (unsigned long long, (LHSVAL), (RHSVAL), OP);	\
+      TEST_COMPOUND (float, (LHSVAL), (RHSVAL), OP);			\
+      TEST_COMPOUND (double, (LHSVAL), (RHSVAL), OP);			\
+      TEST_COMPOUND (long double, (LHSVAL), (RHSVAL), OP);		\
+      TEST_COMPOUND (_Complex float, (LHSVAL), (RHSVAL), OP);		\
+      TEST_COMPOUND (_Complex double, (LHSVAL), (RHSVAL), OP);		\
+      TEST_COMPOUND (_Complex long double, (LHSVAL), (RHSVAL), OP);	\
+    }									\
+  while (0)
+
+#define TEST_COMPOUND_INT(LHSVAL, RHSVAL, OP)				\
+  do									\
+    {									\
+      TEST_COMPOUND (_Bool, (LHSVAL), (RHSVAL), OP);			\
+      TEST_COMPOUND (char, (LHSVAL), (RHSVAL), OP);			\
+      TEST_COMPOUND (signed char, (LHSVAL), (RHSVAL), OP);		\
+      TEST_COMPOUND (unsigned char, (LHSVAL), (RHSVAL), OP);		\
+      TEST_COMPOUND (signed short, (LHSVAL), (RHSVAL), OP);		\
+      TEST_COMPOUND (unsigned short, (LHSVAL), (RHSVAL), OP);		\
+      TEST_COMPOUND (signed int, (LHSVAL), (RHSVAL), OP);		\
+      TEST_COMPOUND (unsigned int, (LHSVAL), (RHSVAL), OP);		\
+      TEST_COMPOUND (signed long, (LHSVAL), (RHSVAL), OP);		\
+      TEST_COMPOUND (unsigned long, (LHSVAL), (RHSVAL), OP);		\
+      TEST_COMPOUND (signed long long, (LHSVAL), (RHSVAL), OP);		\
+      TEST_COMPOUND (unsigned long long, (LHSVAL), (RHSVAL), OP);	\
+    }									\
+  while (0)
+
+static void
+test_mult (void)
+{
+  TEST_COMPOUND_ARITH (1, 2, *);
+  TEST_COMPOUND_ARITH (-3, 5, *);
+  TEST_COMPOUND_ARITH (-7, -20, *);
+  TEST_COMPOUND_ARITH (1.25, 3.5, *);
+  TEST_COMPOUND_ARITH (CMPLX (1.5, 2.5), CMPLX (3.5, 4.5), *);
+  TEST_COMPOUND_ARITH (CMPLX (1.5, 2.5), 2, *);
+}
+
+static void
+test_div (void)
+{
+  TEST_COMPOUND_ARITH (1, 2, /);
+  TEST_COMPOUND_ARITH (-6, 3, /);
+  TEST_COMPOUND_ARITH (-70, -10, /);
+  TEST_COMPOUND_ARITH (1.25, 2.5, /);
+  TEST_COMPOUND_ARITH (CMPLX (1.0, 1.0), CMPLX (0.5, 0.5), /);
+  TEST_COMPOUND_ARITH (CMPLX (1.5, 2.5), 2, /);
+}
+
+static void
+test_mod (void)
+{
+  TEST_COMPOUND_INT (1, 2, %);
+  TEST_COMPOUND_INT (-3, 5, %);
+  TEST_COMPOUND_INT (-7, -2, %);
+}
+
+static void
+test_plus (void)
+{
+  TEST_COMPOUND_ARITH (1, 2, +);
+  TEST_COMPOUND_ARITH (-3, 5, +);
+  TEST_COMPOUND_ARITH (-7, -20, +);
+  TEST_COMPOUND_ARITH (1.25, 3.5, +);
+  TEST_COMPOUND_ARITH (CMPLX (1.5, 2.5), CMPLX (3.5, 4.5), +);
+  TEST_COMPOUND_ARITH (CMPLX (1.5, 2.5), 2, +);
+  static int ia[2];
+  TEST_COMPOUND (int *, &ia[1], 1, +);
+  TEST_COMPOUND (int *, &ia[1], -1, +);
+}
+
+static void
+test_minus (void)
+{
+  TEST_COMPOUND_ARITH (1, 2, -);
+  TEST_COMPOUND_ARITH (-3, 5, -);
+  TEST_COMPOUND_ARITH (-7, -20, -);
+  TEST_COMPOUND_ARITH (3.5, 1.25, -);
+  TEST_COMPOUND_ARITH (CMPLX (3.5, 4.5), CMPLX (1.5, 2.5), -);
+  TEST_COMPOUND_ARITH (CMPLX (3.5, 2.5), 2, -);
+  static int ia[2];
+  TEST_COMPOUND (int *, &ia[1], 1, -);
+  TEST_COMPOUND (int *, &ia[1], -1, -);
+}
+
+static void
+test_lshift (void)
+{
+  TEST_COMPOUND_INT (1, 7, <<);
+  TEST_COMPOUND_INT (15, 3, <<);
+}
+
+static void
+test_rshift (void)
+{
+  TEST_COMPOUND_INT (1, 1, >>);
+  TEST_COMPOUND_INT (127, 4, >>);
+}
+
+static void
+test_and (void)
+{
+  TEST_COMPOUND_INT (0x1234, 0x7856, &);
+  TEST_COMPOUND_INT (-1, 0x12345678, &);
+}
+
+static void
+test_xor (void)
+{
+  TEST_COMPOUND_INT (0x1234, 0x7856, ^);
+  TEST_COMPOUND_INT (-1, 0x12345678, ^);
+}
+
+static void
+test_or (void)
+{
+  TEST_COMPOUND_INT (0x1234, 0x7856, |);
+  TEST_COMPOUND_INT (-12345, 0x12345678, |);
+}
+
+int
+main (void)
+{
+  test_mult ();
+  test_div ();
+  test_mod ();
+  test_plus ();
+  test_minus ();
+  test_lshift ();
+  test_rshift ();
+  test_and ();
+  test_xor ();
+  test_or ();
+  exit (0);
+}
Index: gcc/testsuite/gcc.dg/atomic/c11-atomic-exec-3.c
===================================================================
--- gcc/testsuite/gcc.dg/atomic/c11-atomic-exec-3.c	(revision 0)
+++ gcc/testsuite/gcc.dg/atomic/c11-atomic-exec-3.c	(revision 0)
@@ -0,0 +1,85 @@ 
+/* Test for _Atomic in C11.  Basic execution tests for atomic
+   increment and decrement.  */
+/* { dg-do run } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+extern void abort (void);
+extern void exit (int);
+
+#define TEST_INCDEC(TYPE, VALUE, PREOP, POSTOP, PRE_P, CHANGE)		\
+  do									\
+    {									\
+      static volatile _Atomic (TYPE) a = (TYPE) (VALUE);		\
+      if (PREOP a POSTOP != (PRE_P					\
+			     ? (TYPE) ((TYPE) (VALUE) + (CHANGE))	\
+			     : (TYPE) (VALUE)))				\
+	abort ();							\
+      if (a != (TYPE) ((TYPE) (VALUE) + (CHANGE)))			\
+	abort ();							\
+    }									\
+  while (0)
+
+#define TEST_INCDEC_ARITH(VALUE, PREOP, POSTOP, PRE_P, CHANGE)		\
+  do									\
+    {									\
+      TEST_INCDEC (_Bool, (VALUE), PREOP, POSTOP, (PRE_P), (CHANGE));	\
+      TEST_INCDEC (char, (VALUE), PREOP, POSTOP, (PRE_P), (CHANGE));	\
+      TEST_INCDEC (signed char, (VALUE), PREOP, POSTOP, (PRE_P),	\
+		   (CHANGE));						\
+      TEST_INCDEC (unsigned char, (VALUE), PREOP, POSTOP, (PRE_P),	\
+		   (CHANGE));						\
+      TEST_INCDEC (signed short, (VALUE), PREOP, POSTOP, (PRE_P),	\
+		   (CHANGE));						\
+      TEST_INCDEC (unsigned short, (VALUE), PREOP, POSTOP, (PRE_P),	\
+		   (CHANGE));						\
+      TEST_INCDEC (signed int, (VALUE), PREOP, POSTOP, (PRE_P),		\
+		   (CHANGE));						\
+      TEST_INCDEC (unsigned int, (VALUE), PREOP, POSTOP, (PRE_P),	\
+		   (CHANGE));						\
+      TEST_INCDEC (signed long, (VALUE), PREOP, POSTOP, (PRE_P),	\
+		   (CHANGE));						\
+      TEST_INCDEC (unsigned long, (VALUE), PREOP, POSTOP, (PRE_P),	\
+		   (CHANGE));						\
+      TEST_INCDEC (signed long long, (VALUE), PREOP, POSTOP, (PRE_P),	\
+		   (CHANGE));						\
+      TEST_INCDEC (unsigned long long, (VALUE), PREOP, POSTOP, (PRE_P), \
+		   (CHANGE));						\
+      TEST_INCDEC (float, (VALUE), PREOP, POSTOP, (PRE_P), (CHANGE));	\
+      TEST_INCDEC (double, (VALUE), PREOP, POSTOP, (PRE_P), (CHANGE));	\
+      TEST_INCDEC (long double, (VALUE), PREOP, POSTOP, (PRE_P),	\
+		   (CHANGE));						\
+    }									\
+  while (0)
+
+#define TEST_ALL_INCDEC_ARITH(VALUE)		\
+  do						\
+    {						\
+      TEST_INCDEC_ARITH ((VALUE), ++, , 1, 1);	\
+      TEST_INCDEC_ARITH ((VALUE), --, , 1, -1);	\
+      TEST_INCDEC_ARITH ((VALUE), , ++, 0, 1);	\
+      TEST_INCDEC_ARITH ((VALUE), , --, 0, -1);	\
+    }						\
+  while (0)
+
+static void
+test_incdec (void)
+{
+  TEST_ALL_INCDEC_ARITH (0);
+  TEST_ALL_INCDEC_ARITH (1);
+  TEST_ALL_INCDEC_ARITH (2);
+  TEST_ALL_INCDEC_ARITH (-1);
+  TEST_ALL_INCDEC_ARITH (1ULL << 60);
+  TEST_ALL_INCDEC_ARITH (1.5);
+  static int ia[2];
+  TEST_INCDEC (int *, &ia[1], ++, , 1, 1);
+  TEST_INCDEC (int *, &ia[1], --, , 1, -1);
+  TEST_INCDEC (int *, &ia[1], , ++, 0, 1);
+  TEST_INCDEC (int *, &ia[1], , --, 0, -1);
+}
+
+int
+main (void)
+{
+  test_incdec ();
+  exit (0);
+}