summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authormsebor <msebor@138bc75d-0d04-0410-961f-82ee72b054a4>2016-07-22 18:32:08 +0000
committermsebor <msebor@138bc75d-0d04-0410-961f-82ee72b054a4>2016-07-22 18:32:08 +0000
commitefa8e86ecde76775981faba460b8eb0edddf4539 (patch)
treea853bd1f354648d922e4b463a253980804d5fdd2 /gcc
parentbe239ed2ba619747b64629895116f209b58baee8 (diff)
downloadgcc-efa8e86ecde76775981faba460b8eb0edddf4539.tar.gz
PR c++/71675 - __atomic_compare_exchange_n returns wrong type for typed enum
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@238664 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/c-family/ChangeLog7
-rw-r--r--gcc/c-family/c-common.c3
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/g++.dg/ext/atomic-3.C37
-rw-r--r--gcc/testsuite/gcc.dg/atomic/pr71675.c32
5 files changed, 84 insertions, 1 deletions
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index a2184ad6756..5c193051824 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -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
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 1cc61ee7e13..1c5974a8e92 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -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)
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 0a48a17c714..c38c41e492b 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 00000000000..89ca7188aaa
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/atomic-3.C
@@ -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
index 00000000000..4a1675cf2f5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/atomic/pr71675.c
@@ -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);
+}