r218957 - Add an implementation of C11's stdatomic.h

Hal Finkel hfinkel at anl.gov
Thu Oct 2 21:29:40 PDT 2014


Author: hfinkel
Date: Thu Oct  2 23:29:40 2014
New Revision: 218957

URL: http://llvm.org/viewvc/llvm-project?rev=218957&view=rev
Log:
Add an implementation of C11's stdatomic.h

Adds a Clang-specific implementation of C11's stdatomic.h header. On systems,
such as FreeBSD, where a stdatomic.h header is already provided, we defer to
that header instead (using our __has_include_next technology). Otherwise, we
provide an implementation in terms of our __c11_atomic_* intrinsics (that were
created for this purpose).

C11 7.1.4p1 requires function declarations for atomic_thread_fence,
atomic_signal_fence, atomic_flag_test_and_set,
atomic_flag_test_and_set_explicit, and atomic_flag_clear, and requires that
they have external linkage. Accordingly, we provide these declarations, but if
a user elides the shadowing macros and uses them, then they must have a libc
(or similar) that actually provides definitions.

atomic_flag is implemented using _Bool as the underlying type. This is
consistent with the implementation provided by FreeBSD and also GCC 4.9 (at
least when __GCC_ATOMIC_TEST_AND_SET_TRUEVAL == 1).

Patch by Richard Smith (rebased and slightly edited by me -- Richard said I
should drive at this point).

Added:
    cfe/trunk/lib/Headers/stdatomic.h
Modified:
    cfe/trunk/docs/LanguageExtensions.rst
    cfe/trunk/lib/Headers/CMakeLists.txt
    cfe/trunk/test/CodeGen/atomic-ops.c
    cfe/trunk/test/Sema/atomic-ops.c

Modified: cfe/trunk/docs/LanguageExtensions.rst
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/LanguageExtensions.rst?rev=218957&r1=218956&r2=218957&view=diff
==============================================================================
--- cfe/trunk/docs/LanguageExtensions.rst (original)
+++ cfe/trunk/docs/LanguageExtensions.rst Thu Oct  2 23:29:40 2014
@@ -819,7 +819,16 @@ C11 atomic operations
 Use ``__has_feature(c_atomic)`` or ``__has_extension(c_atomic)`` to determine
 if support for atomic types using ``_Atomic`` is enabled.  Clang also provides
 :ref:`a set of builtins <langext-__c11_atomic>` which can be used to implement
-the ``<stdatomic.h>`` operations on ``_Atomic`` types.
+the ``<stdatomic.h>`` operations on ``_Atomic`` types. Use
+``__has_include(<stdatomic.h>)`` to determine if C11's ``<stdatomic.h>`` header
+is available.
+
+Clang will use the system's ``<stdatomic.h>`` header when one is available, and
+will otherwise use its own. When using its own, implementations of the atomic
+operations are provided as macros. In the cases where C11 also requires a real
+function, this header provides only the declaration of that function (along
+with a shadowing macro implementation), and you must link to a library which
+provides a definition of the function if you use it instead of the macro.
 
 C11 generic selections
 ^^^^^^^^^^^^^^^^^^^^^^
@@ -1597,12 +1606,14 @@ __c11_atomic builtins
 Clang provides a set of builtins which are intended to be used to implement
 C11's ``<stdatomic.h>`` header.  These builtins provide the semantics of the
 ``_explicit`` form of the corresponding C11 operation, and are named with a
-``__c11_`` prefix.  The supported operations are:
+``__c11_`` prefix.  The supported operations, and the differences from
+the corresponding C11 operations, are:
 
 * ``__c11_atomic_init``
 * ``__c11_atomic_thread_fence``
 * ``__c11_atomic_signal_fence``
-* ``__c11_atomic_is_lock_free``
+* ``__c11_atomic_is_lock_free`` (The argument is the size of the
+  ``_Atomic(...)'' object, instead of its address)
 * ``__c11_atomic_store``
 * ``__c11_atomic_load``
 * ``__c11_atomic_exchange``
@@ -1614,6 +1625,11 @@ C11's ``<stdatomic.h>`` header.  These b
 * ``__c11_atomic_fetch_or``
 * ``__c11_atomic_fetch_xor``
 
+The macros ``__ATOMIC_RELAXED``, ``__ATOMIC_CONSUME``, ``__ATOMIC_ACQUIRE``,
+``__ATOMIC_RELEASE``, ``__ATOMIC_ACQ_REL``, and ``_ATOMIC_SEQ_CST`` are
+provided, with values corresponding to the enumerators of C11's
+``memory_order`` enumeration.
+
 Low-level ARM exclusive memory builtins
 ---------------------------------------
 

Modified: cfe/trunk/lib/Headers/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Headers/CMakeLists.txt?rev=218957&r1=218956&r2=218957&view=diff
==============================================================================
--- cfe/trunk/lib/Headers/CMakeLists.txt (original)
+++ cfe/trunk/lib/Headers/CMakeLists.txt Thu Oct  2 23:29:40 2014
@@ -33,6 +33,7 @@ set(files
   smmintrin.h
   stdalign.h
   stdarg.h
+  stdatomic.h
   stdbool.h
   stddef.h
   __stddef_max_align_t.h

Added: cfe/trunk/lib/Headers/stdatomic.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Headers/stdatomic.h?rev=218957&view=auto
==============================================================================
--- cfe/trunk/lib/Headers/stdatomic.h (added)
+++ cfe/trunk/lib/Headers/stdatomic.h Thu Oct  2 23:29:40 2014
@@ -0,0 +1,190 @@
+/*===---- stdatomic.h - Standard header for atomic types and operations -----===
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *===-----------------------------------------------------------------------===
+ */
+
+#ifndef __CLANG_STDATOMIC_H
+#define __CLANG_STDATOMIC_H
+
+/* If we're hosted, fall back to the system's stdatomic.h. FreeBSD, for
+ * example, already has a Clang-compatible stdatomic.h header.
+ */
+#if __STDC_HOSTED__ && __has_include_next(<stdatomic.h>)
+# include_next <stdatomic.h>
+#else
+
+#include <stddef.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* 7.17.1 Introduction */
+
+#define ATOMIC_BOOL_LOCK_FREE       __GCC_ATOMIC_BOOL_LOCK_FREE
+#define ATOMIC_CHAR_LOCK_FREE       __GCC_ATOMIC_CHAR_LOCK_FREE
+#define ATOMIC_CHAR16_T_LOCK_FREE   __GCC_ATOMIC_CHAR16_T_LOCK_FREE
+#define ATOMIC_CHAR32_T_LOCK_FREE   __GCC_ATOMIC_CHAR32_T_LOCK_FREE
+#define ATOMIC_WCHAR_T_LOCK_FREE    __GCC_ATOMIC_WCHAR_T_LOCK_FREE
+#define ATOMIC_SHORT_T_LOCK_FREE    __GCC_ATOMIC_SHORT_T_LOCK_FREE
+#define ATOMIC_INT_T_LOCK_FREE      __GCC_ATOMIC_INT_T_LOCK_FREE
+#define ATOMIC_LONG_T_LOCK_FREE     __GCC_ATOMIC_LONG_T_LOCK_FREE
+#define ATOMIC_LLONG_T_LOCK_FREE    __GCC_ATOMIC_LLONG_T_LOCK_FREE
+#define ATOMIC_POINTER_T_LOCK_FREE  __GCC_ATOMIC_POINTER_T_LOCK_FREE
+
+/* 7.17.2 Initialization */
+
+#define ATOMIC_VAR_INIT(value) (value)
+#define atomic_init __c11_atomic_init
+
+/* 7.17.3 Order and consistency */
+
+typedef enum memory_order {
+  memory_order_relaxed = __ATOMIC_RELAXED,
+  memory_order_consume = __ATOMIC_CONSUME,
+  memory_order_acquire = __ATOMIC_ACQUIRE,
+  memory_order_release = __ATOMIC_RELEASE,
+  memory_order_acq_rel = __ATOMIC_ACQ_REL,
+  memory_order_seq_cst = __ATOMIC_SEQ_CST
+} memory_order;
+
+#define kill_dependency(y) (y)
+
+/* 7.17.4 Fences */
+
+// These should be provided by the libc implementation.
+void atomic_thread_fence(memory_order);
+void atomic_signal_fence(memory_order);
+
+#define atomic_thread_fence(order) __c11_atomic_thread_fence(order)
+#define atomic_signal_fence(order) __c11_atomic_signal_fence(order)
+
+/* 7.17.5 Lock-free property */
+
+#define atomic_is_lock_free(obj) __c11_atomic_is_lock_free(sizeof(*(obj)))
+
+/* 7.17.6 Atomic integer types */
+
+#ifdef __cplusplus
+typedef _Atomic(bool)               atomic_bool;
+#else
+typedef _Atomic(_Bool)              atomic_bool;
+#endif
+typedef _Atomic(char)               atomic_char;
+typedef _Atomic(signed char)        atomic_schar;
+typedef _Atomic(unsigned char)      atomic_uchar;
+typedef _Atomic(short)              atomic_short;
+typedef _Atomic(unsigned short)     atomic_ushort;
+typedef _Atomic(int)                atomic_int;
+typedef _Atomic(unsigned int)       atomic_uint;
+typedef _Atomic(long)               atomic_long;
+typedef _Atomic(unsigned long)      atomic_ulong;
+typedef _Atomic(long long)          atomic_llong;
+typedef _Atomic(unsigned long long) atomic_ullong;
+typedef _Atomic(uint_least16_t)     atomic_char16_t;
+typedef _Atomic(uint_least32_t)     atomic_char32_t;
+typedef _Atomic(wchar_t)            atomic_wchar_t;
+typedef _Atomic(int_least8_t)       atomic_int_least8_t;
+typedef _Atomic(uint_least8_t)      atomic_uint_least8_t;
+typedef _Atomic(int_least16_t)      atomic_int_least16_t;
+typedef _Atomic(uint_least16_t)     atomic_uint_least16_t;
+typedef _Atomic(int_least32_t)      atomic_int_least32_t;
+typedef _Atomic(uint_least32_t)     atomic_uint_least32_t;
+typedef _Atomic(int_least64_t)      atomic_int_least64_t;
+typedef _Atomic(uint_least64_t)     atomic_uint_least64_t;
+typedef _Atomic(int_fast8_t)        atomic_int_fast8_t;
+typedef _Atomic(uint_fast8_t)       atomic_uint_fast8_t;
+typedef _Atomic(int_fast16_t)       atomic_int_fast16_t;
+typedef _Atomic(uint_fast16_t)      atomic_uint_fast16_t;
+typedef _Atomic(int_fast32_t)       atomic_int_fast32_t;
+typedef _Atomic(uint_fast32_t)      atomic_uint_fast32_t;
+typedef _Atomic(int_fast64_t)       atomic_int_fast64_t;
+typedef _Atomic(uint_fast64_t)      atomic_uint_fast64_t;
+typedef _Atomic(intptr_t)           atomic_intptr_t;
+typedef _Atomic(uintptr_t)          atomic_uintptr_t;
+typedef _Atomic(size_t)             atomic_size_t;
+typedef _Atomic(ptrdiff_t)          atomic_ptrdiff_t;
+typedef _Atomic(intmax_t)           atomic_intmax_t;
+typedef _Atomic(uintmax_t)          atomic_uintmax_t;
+
+/* 7.17.7 Operations on atomic types */
+
+#define atomic_store(object, desired) __c11_atomic_store(object, desired, __ATOMIC_SEQ_CST)
+#define atomic_store_explicit __c11_atomic_store
+
+#define atomic_load(object) __c11_atomic_load(object, __ATOMIC_SEQ_CST)
+#define atomic_load_explicit __c11_atomic_load
+
+#define atomic_exchange(object, desired) __c11_atomic_exchange(object, desired, __ATOMIC_SEQ_CST)
+#define atomic_exchange_explicit __c11_atomic_exchange
+
+#define atomic_compare_exchange_strong(object, expected, desired) __c11_atomic_compare_exchange_strong(object, expected, desired, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)
+#define atomic_compare_exchange_strong_explicit __c11_atomic_compare_exchange_strong
+
+#define atomic_compare_exchange_weak(object, expected, desired) __c11_atomic_compare_exchange_weak(object, expected, desired, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)
+#define atomic_compare_exchange_weak_explicit __c11_atomic_compare_exchange_weak
+
+#define atomic_fetch_add(object, operand) __c11_atomic_fetch_add(object, operand, __ATOMIC_SEQ_CST)
+#define atomic_fetch_add_explicit __c11_atomic_fetch_add
+
+#define atomic_fetch_sub(object, operand) __c11_atomic_fetch_sub(object, operand, __ATOMIC_SEQ_CST)
+#define atomic_fetch_sub_explicit __c11_atomic_fetch_sub
+
+#define atomic_fetch_or(object, operand) __c11_atomic_fetch_or(object, operand, __ATOMIC_SEQ_CST)
+#define atomic_fetch_or_explicit __c11_atomic_fetch_or
+
+#define atomic_fetch_xor(object, operand) __c11_atomic_fetch_xor(object, operand, __ATOMIC_SEQ_CST)
+#define atomic_fetch_xor_explicit __c11_atomic_fetch_xor
+
+#define atomic_fetch_and(object, operand) __c11_atomic_fetch_and(object, operand, __ATOMIC_SEQ_CST)
+#define atomic_fetch_and_explicit __c11_atomic_fetch_and
+
+/* 7.17.8 Atomic flag type and operations */
+
+typedef struct atomic_flag { atomic_bool _Value; } atomic_flag;
+
+#define ATOMIC_FLAG_INIT { 0 }
+
+// These should be provided by the libc implementation.
+#ifdef __cplusplus
+bool atomic_flag_test_and_set(volatile atomic_flag *);
+bool atomic_flag_test_and_set_explicit(volatile atomic_flag *, memory_order);
+#else
+_Bool atomic_flag_test_and_set(volatile atomic_flag *);
+_Bool atomic_flag_test_and_set_explicit(volatile atomic_flag *, memory_order);
+#endif
+void atomic_flag_clear(volatile atomic_flag *);
+void atomic_flag_clear_explicit(volatile atomic_flag *, memory_order);
+
+#define atomic_flag_test_and_set(object) __c11_atomic_exchange(&(object)->_Value, 1, __ATOMIC_SEQ_CST)
+#define atomic_flag_test_and_set_explicit(object, order) __c11_atomic_exchange(&(object)->_Value, 1, order)
+
+#define atomic_flag_clear(object) __c11_atomic_store(&(object)->_Value, 0, __ATOMIC_SEQ_CST)
+#define atomic_flag_clear_explicit(object, order) __c11_atomic_store(&(object)->_Value, 0, order)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __STDC_HOSTED__ */
+#endif /* __CLANG_STDATOMIC_H */
+

Modified: cfe/trunk/test/CodeGen/atomic-ops.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/atomic-ops.c?rev=218957&r1=218956&r2=218957&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/atomic-ops.c (original)
+++ cfe/trunk/test/CodeGen/atomic-ops.c Thu Oct  2 23:29:40 2014
@@ -7,12 +7,9 @@
 #ifndef ALREADY_INCLUDED
 #define ALREADY_INCLUDED
 
-// Basic IRGen tests for __c11_atomic_* and GNU __atomic_*
+#include <stdatomic.h>
 
-typedef enum memory_order {
-  memory_order_relaxed, memory_order_consume, memory_order_acquire,
-  memory_order_release, memory_order_acq_rel, memory_order_seq_cst
-} memory_order;
+// Basic IRGen tests for __c11_atomic_* and GNU __atomic_*
 
 int fi1(_Atomic(int) *i) {
   // CHECK-LABEL: @fi1
@@ -34,6 +31,12 @@ int fi1b(int *i) {
   return __atomic_load_n(i, memory_order_seq_cst);
 }
 
+int fi1c(atomic_int *i) {
+  // CHECK-LABEL: @fi1c
+  // CHECK: load atomic i32* {{.*}} seq_cst
+  return atomic_load(i);
+}
+
 void fi2(_Atomic(int) *i) {
   // CHECK-LABEL: @fi2
   // CHECK: store atomic i32 {{.*}} seq_cst
@@ -53,6 +56,12 @@ void fi2b(int *i) {
   __atomic_store_n(i, 1, memory_order_seq_cst);
 }
 
+void fi2c(atomic_int *i) {
+  // CHECK-LABEL: @fi2c
+  // CHECK: store atomic i32 {{.*}} seq_cst
+  atomic_store(i, 1);
+}
+
 int fi3(_Atomic(int) *i) {
   // CHECK-LABEL: @fi3
   // CHECK: atomicrmw and
@@ -89,8 +98,15 @@ int fi3d(int *i) {
   return __atomic_nand_fetch(i, 1, memory_order_seq_cst);
 }
 
+int fi3e(atomic_int *i) {
+  // CHECK-LABEL: @fi3e
+  // CHECK: atomicrmw or
+  // CHECK-NOT: {{ or }}
+  return atomic_fetch_or(i, 1);
+}
+
 _Bool fi4(_Atomic(int) *i) {
-  // CHECK-LABEL: @fi4
+  // CHECK-LABEL: @fi4(
   // CHECK: [[PAIR:%[.0-9A-Z_a-z]+]] = cmpxchg i32* [[PTR:%[.0-9A-Z_a-z]+]], i32 [[EXPECTED:%[.0-9A-Z_a-z]+]], i32 [[DESIRED:%[.0-9A-Z_a-z]+]]
   // CHECK: [[OLD:%[.0-9A-Z_a-z]+]] = extractvalue { i32, i1 } [[PAIR]], 0
   // CHECK: [[CMP:%[.0-9A-Z_a-z]+]] = extractvalue { i32, i1 } [[PAIR]], 1
@@ -101,7 +117,7 @@ _Bool fi4(_Atomic(int) *i) {
 }
 
 _Bool fi4a(int *i) {
-  // CHECK-LABEL: @fi4
+  // CHECK-LABEL: @fi4a
   // CHECK: [[PAIR:%[.0-9A-Z_a-z]+]] = cmpxchg i32* [[PTR:%[.0-9A-Z_a-z]+]], i32 [[EXPECTED:%[.0-9A-Z_a-z]+]], i32 [[DESIRED:%[.0-9A-Z_a-z]+]]
   // CHECK: [[OLD:%[.0-9A-Z_a-z]+]] = extractvalue { i32, i1 } [[PAIR]], 0
   // CHECK: [[CMP:%[.0-9A-Z_a-z]+]] = extractvalue { i32, i1 } [[PAIR]], 1
@@ -113,7 +129,7 @@ _Bool fi4a(int *i) {
 }
 
 _Bool fi4b(int *i) {
-  // CHECK-LABEL: @fi4
+  // CHECK-LABEL: @fi4b(
   // CHECK: [[PAIR:%[.0-9A-Z_a-z]+]] = cmpxchg weak i32* [[PTR:%[.0-9A-Z_a-z]+]], i32 [[EXPECTED:%[.0-9A-Z_a-z]+]], i32 [[DESIRED:%[.0-9A-Z_a-z]+]]
   // CHECK: [[OLD:%[.0-9A-Z_a-z]+]] = extractvalue { i32, i1 } [[PAIR]], 0
   // CHECK: [[CMP:%[.0-9A-Z_a-z]+]] = extractvalue { i32, i1 } [[PAIR]], 1
@@ -123,6 +139,13 @@ _Bool fi4b(int *i) {
   return __atomic_compare_exchange_n(i, &cmp, 1, 1, memory_order_acquire, memory_order_acquire);
 }
 
+_Bool fi4c(atomic_int *i) {
+  // CHECK-LABEL: @fi4c
+  // CHECK: cmpxchg i32*
+  int cmp = 0;
+  return atomic_compare_exchange_strong(i, &cmp, 1);
+}
+
 float ff1(_Atomic(float) *d) {
   // CHECK-LABEL: @ff1
   // CHECK: load atomic i32* {{.*}} monotonic

Modified: cfe/trunk/test/Sema/atomic-ops.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/atomic-ops.c?rev=218957&r1=218956&r2=218957&view=diff
==============================================================================
--- cfe/trunk/test/Sema/atomic-ops.c (original)
+++ cfe/trunk/test/Sema/atomic-ops.c Thu Oct  2 23:29:40 2014
@@ -2,10 +2,7 @@
 
 // Basic parsing/Sema tests for __c11_atomic_*
 
-typedef enum memory_order {
-  memory_order_relaxed, memory_order_consume, memory_order_acquire,
-  memory_order_release, memory_order_acq_rel, memory_order_seq_cst
-} memory_order;
+#include <stdatomic.h>
 
 struct S { char c[3]; };
 
@@ -40,6 +37,14 @@ _Static_assert(__atomic_is_lock_free(8,
 _Static_assert(__atomic_is_lock_free(16, 0), ""); // expected-error {{not an integral constant expression}}
 _Static_assert(__atomic_is_lock_free(17, 0), ""); // expected-error {{not an integral constant expression}}
 
+_Static_assert(atomic_is_lock_free((atomic_char*)0), "");
+_Static_assert(atomic_is_lock_free((atomic_short*)0), "");
+_Static_assert(atomic_is_lock_free((atomic_int*)0), "");
+_Static_assert(atomic_is_lock_free((atomic_long*)0), "");
+// expected-error at +1 {{__int128 is not supported on this target}}
+_Static_assert(atomic_is_lock_free((_Atomic(__int128)*)0), ""); // expected-error {{not an integral constant expression}}
+_Static_assert(atomic_is_lock_free(0 + (atomic_char*)0), "");
+
 char i8;
 short i16;
 int i32;
@@ -171,6 +176,62 @@ void f(_Atomic(int) *i, _Atomic(int*) *p
   __c11_atomic_init(&const_atomic, 0); // expected-error {{address argument to atomic operation must be a pointer to non-const _Atomic type ('const _Atomic(int) *' invalid)}}
   __c11_atomic_store(&const_atomic, 0, memory_order_release); // expected-error {{address argument to atomic operation must be a pointer to non-const _Atomic type ('const _Atomic(int) *' invalid)}}
   __c11_atomic_load(&const_atomic, memory_order_acquire); // expected-error {{address argument to atomic operation must be a pointer to non-const _Atomic type ('const _Atomic(int) *' invalid)}}
+
+  // Ensure the <stdatomic.h> macros behave appropriately.
+  atomic_int n = ATOMIC_VAR_INIT(123);
+  atomic_init(&n, 456);
+  atomic_init(&n, (void*)0); // expected-warning {{passing 'void *' to parameter of type 'int'}}
+
+  const atomic_wchar_t cawt;
+  atomic_init(&cawt, L'x'); // expected-error {{non-const}}
+  atomic_wchar_t awt;
+  atomic_init(&awt, L'x');
+
+  int x = kill_dependency(12);
+
+  atomic_thread_fence(); // expected-error {{too few arguments to function call}}
+  atomic_thread_fence(memory_order_seq_cst);
+  atomic_signal_fence(memory_order_seq_cst);
+  void (*pfn)(memory_order) = &atomic_thread_fence;
+  pfn = &atomic_signal_fence;
+
+  int k = atomic_load_explicit(&n, memory_order_relaxed);
+  atomic_store_explicit(&n, k, memory_order_relaxed);
+  atomic_store(&n, atomic_load(&n));
+
+  k = atomic_exchange(&n, 72);
+  k = atomic_exchange_explicit(&n, k, memory_order_release);
+
+  atomic_compare_exchange_strong(&n, k, k); // expected-warning {{take the address with &}}
+  atomic_compare_exchange_weak(&n, &k, k);
+  atomic_compare_exchange_strong_explicit(&n, &k, k, memory_order_seq_cst); // expected-error {{too few arguments}}
+  atomic_compare_exchange_weak_explicit(&n, &k, k, memory_order_seq_cst, memory_order_acquire);
+
+  atomic_fetch_add(&k, n); // expected-error {{must be a pointer to _Atomic}}
+  k = atomic_fetch_add(&n, k);
+  k = atomic_fetch_sub(&n, k);
+  k = atomic_fetch_and(&n, k);
+  k = atomic_fetch_or(&n, k);
+  k = atomic_fetch_xor(&n, k);
+  k = atomic_fetch_add_explicit(&n, k, memory_order_acquire);
+  k = atomic_fetch_sub_explicit(&n, k, memory_order_release);
+  k = atomic_fetch_and_explicit(&n, k, memory_order_acq_rel);
+  k = atomic_fetch_or_explicit(&n, k, memory_order_consume);
+  k = atomic_fetch_xor_explicit(&n, k, memory_order_relaxed);
+
+  // C11 7.17.1/4: atomic_flag is a structure type.
+  struct atomic_flag must_be_struct = ATOMIC_FLAG_INIT;
+  // C11 7.17.8/5 implies that it is also a typedef type.
+  atomic_flag guard = ATOMIC_FLAG_INIT;
+  _Bool old_val = atomic_flag_test_and_set(&guard);
+  if (old_val) atomic_flag_clear(&guard);
+
+  old_val = (atomic_flag_test_and_set)(&guard);
+  if (old_val) (atomic_flag_clear)(&guard);
+
+  const atomic_flag const_guard;
+  atomic_flag_test_and_set(&const_guard); // expected-error {{address argument to atomic operation must be a pointer to non-const _Atomic type ('const atomic_bool *' (aka 'const _Atomic(_Bool) *') invalid)}}
+  atomic_flag_clear(&const_guard); // expected-error {{address argument to atomic operation must be a pointer to non-const _Atomic type ('const atomic_bool *' (aka 'const _Atomic(_Bool) *') invalid)}}
 }
 
 _Atomic(int*) PR12527_a;
@@ -403,3 +464,5 @@ void memory_checks(_Atomic(int) *Ap, int
   (void)__atomic_compare_exchange_n(p, p, val, 0, memory_order_acq_rel, memory_order_relaxed);
   (void)__atomic_compare_exchange_n(p, p, val, 0, memory_order_seq_cst, memory_order_relaxed);
 }
+
+





More information about the cfe-commits mailing list