Fix ATOMIC_FLAG_INIT().
ATOMIC_VAR_INIT() has been removed from C23, but ATOMIC_FLAG_INIT() remains. libc++'s <atomic> marks ATOMIC_VAR_INIT() as deprecated, so we need to stop using that in our <stdatomic.h> ATOMIC_FLAG_INIT().
Add an explicit test for ATOMIC_VAR_INIT() as a reminder that -- even if/when POSIX removes it too -- we should keep it until the last users are long gone (which probably means "we should keep it forever", especially since it's a harmless no-op).
(Note that although I've added the #pragma to silence the deprecation warning, the build won't actually be warning-free until our updated <stdatomic.h> has made it into our prebuilt clang sysroot for the host.)
Also remove unused GCC support from <stdatomic.h> to simplify that header a little.
Change-Id: Iea97aa8d3439992f1abcd375504dbfcd4e372c2f
diff --git a/libc/include/bits/stdatomic.h b/libc/include/bits/stdatomic.h
index ebdc9e5..8717e15 100644
--- a/libc/include/bits/stdatomic.h
+++ b/libc/include/bits/stdatomic.h
@@ -53,36 +53,16 @@
* 7.17.1 Atomic lock-free macros.
*/
-#ifdef __GCC_ATOMIC_BOOL_LOCK_FREE
-#define ATOMIC_BOOL_LOCK_FREE __GCC_ATOMIC_BOOL_LOCK_FREE
-#endif
-#ifdef __GCC_ATOMIC_CHAR_LOCK_FREE
-#define ATOMIC_CHAR_LOCK_FREE __GCC_ATOMIC_CHAR_LOCK_FREE
-#endif
-#ifdef __GCC_ATOMIC_CHAR16_T_LOCK_FREE
-#define ATOMIC_CHAR16_T_LOCK_FREE __GCC_ATOMIC_CHAR16_T_LOCK_FREE
-#endif
-#ifdef __GCC_ATOMIC_CHAR32_T_LOCK_FREE
-#define ATOMIC_CHAR32_T_LOCK_FREE __GCC_ATOMIC_CHAR32_T_LOCK_FREE
-#endif
-#ifdef __GCC_ATOMIC_WCHAR_T_LOCK_FREE
-#define ATOMIC_WCHAR_T_LOCK_FREE __GCC_ATOMIC_WCHAR_T_LOCK_FREE
-#endif
-#ifdef __GCC_ATOMIC_SHORT_LOCK_FREE
-#define ATOMIC_SHORT_LOCK_FREE __GCC_ATOMIC_SHORT_LOCK_FREE
-#endif
-#ifdef __GCC_ATOMIC_INT_LOCK_FREE
-#define ATOMIC_INT_LOCK_FREE __GCC_ATOMIC_INT_LOCK_FREE
-#endif
-#ifdef __GCC_ATOMIC_LONG_LOCK_FREE
-#define ATOMIC_LONG_LOCK_FREE __GCC_ATOMIC_LONG_LOCK_FREE
-#endif
-#ifdef __GCC_ATOMIC_LLONG_LOCK_FREE
-#define ATOMIC_LLONG_LOCK_FREE __GCC_ATOMIC_LLONG_LOCK_FREE
-#endif
-#ifdef __GCC_ATOMIC_POINTER_LOCK_FREE
-#define ATOMIC_POINTER_LOCK_FREE __GCC_ATOMIC_POINTER_LOCK_FREE
-#endif
+#define ATOMIC_BOOL_LOCK_FREE __CLANG_ATOMIC_BOOL_LOCK_FREE
+#define ATOMIC_CHAR_LOCK_FREE __CLANG_ATOMIC_CHAR_LOCK_FREE
+#define ATOMIC_CHAR16_T_LOCK_FREE __CLANG_ATOMIC_CHAR16_T_LOCK_FREE
+#define ATOMIC_CHAR32_T_LOCK_FREE __CLANG_ATOMIC_CHAR32_T_LOCK_FREE
+#define ATOMIC_WCHAR_T_LOCK_FREE __CLANG_ATOMIC_WCHAR_T_LOCK_FREE
+#define ATOMIC_SHORT_LOCK_FREE __CLANG_ATOMIC_SHORT_LOCK_FREE
+#define ATOMIC_INT_LOCK_FREE __CLANG_ATOMIC_INT_LOCK_FREE
+#define ATOMIC_LONG_LOCK_FREE __CLANG_ATOMIC_LONG_LOCK_FREE
+#define ATOMIC_LLONG_LOCK_FREE __CLANG_ATOMIC_LLONG_LOCK_FREE
+#define ATOMIC_POINTER_LOCK_FREE __CLANG_ATOMIC_POINTER_LOCK_FREE
/*
* 7.17.2 Initialization.
@@ -92,31 +72,6 @@
#define atomic_init(obj, value) __c11_atomic_init(obj, value)
/*
- * Clang and recent GCC both provide predefined macros for the memory
- * orderings. If we are using a compiler that doesn't define them, use the
- * clang values - these will be ignored in the fallback path.
- */
-
-#ifndef __ATOMIC_RELAXED
-#define __ATOMIC_RELAXED 0
-#endif
-#ifndef __ATOMIC_CONSUME
-#define __ATOMIC_CONSUME 1
-#endif
-#ifndef __ATOMIC_ACQUIRE
-#define __ATOMIC_ACQUIRE 2
-#endif
-#ifndef __ATOMIC_RELEASE
-#define __ATOMIC_RELEASE 3
-#endif
-#ifndef __ATOMIC_ACQ_REL
-#define __ATOMIC_ACQ_REL 4
-#endif
-#ifndef __ATOMIC_SEQ_CST
-#define __ATOMIC_SEQ_CST 5
-#endif
-
-/*
* 7.17.3 Order and consistency.
*
* The memory_order_* constants that denote the barrier behaviour of the
@@ -269,7 +224,7 @@
atomic_bool __flag;
} atomic_flag;
-#define ATOMIC_FLAG_INIT { ATOMIC_VAR_INIT(false) }
+#define ATOMIC_FLAG_INIT {false}
static __inline bool atomic_flag_test_and_set_explicit(volatile atomic_flag * _Nonnull __object, memory_order __order) {
return (atomic_exchange_explicit(&__object->__flag, 1, __order));
diff --git a/tests/stdatomic_test.cpp b/tests/stdatomic_test.cpp
index 8a54080..23e9b3e 100644
--- a/tests/stdatomic_test.cpp
+++ b/tests/stdatomic_test.cpp
@@ -16,8 +16,13 @@
#include <gtest/gtest.h>
-// The real <stdatomic.h> checks for the availability of C++'s atomics and uses them if present. Since
-// we want to test the libc versions, we instead include <bits/stdatomic.h> where they're actually defined.
+// The real <stdatomic.h> checks for the availability of C++'s <atomic> and
+// uses that instead if present.
+// We want to test the C interfaces, so we instead include
+// <bits/stdatomic.h> directly.
+// This doesn't entirely work because gtest also (transitively) pulls in <atomic>.
+// It's not clear there's a good fix for this,
+// other than switching to a non-C++ unit test framework for bionic.
#include <bits/stdatomic.h>
#include <pthread.h>
@@ -37,8 +42,18 @@
}
TEST(stdatomic, init) {
- atomic_int v = 123;
+ // ATOMIC_VAR_INIT has been removed from C23,
+ // but is still in POSIX 2024.
+ // Even if it is removed from there,
+ // we should probably keep it indefinitely for source compatibility.
+ // libc++'s <atomic> (which we can't entirely avoid: see above)
+ // marks the macro deprecated,
+ // so we need to silence that.
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-pragma"
+ atomic_int v = ATOMIC_VAR_INIT(123);
ASSERT_EQ(123, atomic_load(&v));
+#pragma clang diagnostic pop
atomic_store_explicit(&v, 456, memory_order_relaxed);
ASSERT_EQ(456, atomic_load(&v));