From 2e6b45afba5f9606e6322e1a2b08b86971f38e92 Mon Sep 17 00:00:00 2001 From: Martin Sebor Date: Fri, 22 Jul 2016 18:32:08 +0000 Subject: [PATCH] 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. From-SVN: r238664 --- gcc/c-family/ChangeLog | 7 +++++ gcc/c-family/c-common.c | 3 ++- gcc/testsuite/ChangeLog | 6 +++++ gcc/testsuite/g++.dg/ext/atomic-3.C | 37 +++++++++++++++++++++++++++ gcc/testsuite/gcc.dg/atomic/pr71675.c | 32 +++++++++++++++++++++++ 5 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/g++.dg/ext/atomic-3.C create mode 100644 gcc/testsuite/gcc.dg/atomic/pr71675.c 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 + + 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 * 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 + + PR c++/71675 + * g++.dg/ext/atomic-3.C: New test. + * gcc.dg/atomic/pr71675.c: New test. + 2016-07-22 Evgeny Stupachenko * 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 +void sink (T); + +bool sink (bool); + +template +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(); + test(); + test(); + + test(); + test(); + + test(); + test(); + + test(); + test(); + + test(); + test(); +} 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); +} -- 2.30.2