PR c++/71675 - __atomic_compare_exchange_n returns wrong type for typed enum
authorMartin Sebor <msebor@redhat.com>
Fri, 22 Jul 2016 18:32:08 +0000 (18:32 +0000)
committerMartin Sebor <msebor@gcc.gnu.org>
Fri, 22 Jul 2016 18:32:08 +0000 (12:32 -0600)
gcc/c-family/ChangeLog:

PR c++/71675
* c-common.c (resolve_overloaded_builtin): Avoid converting
__atomic_compare_exchange_n return type to that of what its
first argument points to.

gcc/testsuite/ChangeLog:

PR c++/71675
* g++.dg/ext/atomic-3.C: New test.
* gcc.dg/atomic/pr71675.c: New test.

From-SVN: r238664

gcc/c-family/ChangeLog
gcc/c-family/c-common.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/ext/atomic-3.C [new file with mode: 0644]
gcc/testsuite/gcc.dg/atomic/pr71675.c [new file with mode: 0644]

index a2184ad6756a81d1f0b3432add1478054255d403..5c1930518247d61e40485289e0160700f0d7e38d 100644 (file)
@@ -1,3 +1,10 @@
+2016-07-22 Martin Sebor  <msebor@redhat.com>
+
+       PR c++/71675
+       * c-common.c (resolve_overloaded_builtin): Avoid converting
+       __atomic_compare_exchange_n return type to that of what its
+       first argument points to.
+
 2016-07-22  Uros Bizjak  <ubizjak@gmail.com>
 
        * c-common.c: Use HOST_WIDE_INT_M1U instead of
index 1cc61ee7e13b608b2509665fa001fa060ad04278..1c5974a8e9289c2d7c7736c0a7efdbbde82530f0 100644 (file)
@@ -11514,7 +11514,8 @@ resolve_overloaded_builtin (location_t loc, tree function,
          return result;
        if (orig_code != BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_N
            && orig_code != BUILT_IN_SYNC_LOCK_RELEASE_N
-           && orig_code != BUILT_IN_ATOMIC_STORE_N)
+           && orig_code != BUILT_IN_ATOMIC_STORE_N
+           && orig_code != BUILT_IN_ATOMIC_COMPARE_EXCHANGE_N)
          result = sync_resolve_return (first_param, result, orig_format);
 
        if (fetch_op)
index 0a48a17c71461d7b9326d517f2e65334c4ab4a64..c38c41e492b7d2afe33b550935755823ff53fd3d 100644 (file)
@@ -1,3 +1,9 @@
+2016-07-22 Martin Sebor  <msebor@redhat.com>
+
+       PR c++/71675
+       * g++.dg/ext/atomic-3.C: New test.
+       * gcc.dg/atomic/pr71675.c: New test.
+
 2016-07-22  Evgeny Stupachenko  <evstupac@gmail.com>
 
        * gcc.target/i386/mvc8.c: New test.
diff --git a/gcc/testsuite/g++.dg/ext/atomic-3.C b/gcc/testsuite/g++.dg/ext/atomic-3.C
new file mode 100644 (file)
index 0000000..89ca718
--- /dev/null
@@ -0,0 +1,37 @@
+// PR c++/71675 - __atomic_compare_exchange_n returns wrong type for typed enum
+// { dg-do compile { target c++11 } }
+
+template <class T>
+void sink (T);
+
+bool sink (bool);
+
+template <class T>
+bool test ()
+{
+  enum class E: T { };
+  static E e;
+
+  return sink (__atomic_compare_exchange_n (&e, &e, e, false, 0, 0));
+}
+
+void tests ()
+{
+  // __atomic_compare_exchange_n would fail to return bool when
+  //   its arguments were one of the three character types.
+  test<char>();
+  test<signed char>();
+  test<unsigned char>();
+
+  test<short>();
+  test<unsigned short>();
+
+  test<int>();
+  test<unsigned int>();
+
+  test<long>();
+  test<unsigned long>();
+
+  test<long long>();
+  test<unsigned long long>();
+}
diff --git a/gcc/testsuite/gcc.dg/atomic/pr71675.c b/gcc/testsuite/gcc.dg/atomic/pr71675.c
new file mode 100644 (file)
index 0000000..4a1675c
--- /dev/null
@@ -0,0 +1,32 @@
+/* PR c++/71675 - __atomic_compare_exchange_n returns wrong type for typed enum
+ */
+/* { dg-do compile { target c11 } } */
+
+#define Test(T)                                                                \
+  do {                                                                 \
+    static T x;                                                                \
+    int r [_Generic (__atomic_compare_exchange_n (&x, &x, x, 0, 0, 0), \
+                    _Bool: 1, default: -1)];                           \
+    (void)&r;                                                          \
+  } while (0)
+
+void f (void)
+{
+  /* __atomic_compare_exchange_n would fail to return _Bool when
+     its arguments were one of the three character types.  */
+  Test (char);
+  Test (signed char);
+  Test (unsigned char);
+
+  Test (int);
+  Test (unsigned int);
+
+  Test (long);
+  Test (unsigned long);
+
+  Test (long long);
+  Test (unsigned long long);
+
+  typedef enum E { e } E;
+  Test (E);
+}