gcc/libstdc++-v3/testsuite/29_atomics/atomic/nonmembers.cc

231 lines
9.8 KiB
C++
Raw Normal View History

// Copyright (C) 2018-2020 Free Software Foundation, Inc.
Implement P0558R2 changes to std::atomic The restrictions forbidding arithmetic on atomic pointer types are only enabled for C++17 and later, retaining the GNU extension for older standards. The new nested typedefs and changes to prevent scalar parameters participating in template argument deduction are enabled unconditionally. PR libstdc++/69769 PR libstdc++/85886 * include/bits/atomic_base.h (__atomic_base::value_type) (__atomic_base::difference_type): Add new typedefs. * include/std/atomic (atomic<bool>::value_type, atomic<T>::value_type) (atomic<T*>::value_type, atomic<T*>::difference_type): Likewise. (atomic<T*>::operator++, atomic<T*>::operator--) (atomic<T*>::operator+=, atomic<T*>::operator-=) (atomic<T*>::fetch_add, atomic<T*>::fetch_sub): Add static assertion to enforce C++17 requirement on pointer arithmetic. (__atomic_val_t, __atomic_diff_t): New alias templates. (atomic_init, atomic_store_explicit, atomic_exchange_explicit) (atomic_compare_exchange_weak_explicit) (atomic_compare_exchange_strong_explicit, atomic_store) (atomic_exchange, atomic_compare_exchange_weak) (atomic_compare_exchange_strong): Use __atomic_val_t to make scalar parameters be non-deduced contexts. (atomic_fetch_add_explicit, atomic_fetch_sub_explicit) (atomic_fetch_add, atomic_fetch_sub): Change first parameter to be atomic instead of __atomic_base, and use __atomic_diff_t for scalar parameters. (atomic_fetch_and_explicit, atomic_fetch_or_explicit) (atomic_fetch_xor_explicit, atomic_fetch_and, atomic_fetch_or) (atomic_fetch_xor): Use __atomic_val_t for scalar parameters. (atomic_fetch_add_explicit, atomic_fetch_sub_explicit) (atomic_fetch_add, atomic_fetch_sub): Remove overloads for atomic address types. * testsuite/29_atomics/atomic/60695.cc: Adjust dg-error lineno. * testsuite/29_atomics/atomic/69769.cc: New test. * testsuite/29_atomics/atomic/nonmembers.cc: New test. * testsuite/29_atomics/atomic/operators/pointer_partial_void.cc: Disable test for C++17 and later. * testsuite/29_atomics/atomic/requirements/typedefs.cc: New test. * testsuite/29_atomics/atomic_integral/nonmembers.cc: New test. * testsuite/29_atomics/atomic_integral/requirements/typedefs.cc: New test. From-SVN: r260676
2018-05-24 17:28:26 +02:00
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
// { dg-do compile { target c++11 } }
// { dg-require-atomic-builtins "" }
#include <atomic>
void
test01()
{
struct X { };
struct Y { };
// Primary template
volatile std::atomic<X> v;
std::atomic<Y> a;
const std::memory_order mo = std::memory_order_seq_cst;
X x;
Y y;
auto r1 = atomic_is_lock_free(&v);
static_assert( std::is_same<decltype(r1), bool>::value, "" );
auto r2 = atomic_is_lock_free(&a);
static_assert( std::is_same<decltype(r2), bool>::value, "" );
atomic_init(&v, x);
atomic_init(&a, y);
atomic_store(&v, x);
atomic_store(&a, y);
atomic_store_explicit(&v, x, mo);
atomic_store_explicit(&a, y, mo);
auto r3 = atomic_load(&v);
static_assert( std::is_same<decltype(r3), X>::value, "" );
auto r4 = atomic_load(&a);
static_assert( std::is_same<decltype(r4), Y>::value, "" );
auto r5 = atomic_load_explicit(&v, mo);
static_assert( std::is_same<decltype(r5), X>::value, "" );
auto r6 = atomic_load_explicit(&a, mo);
static_assert( std::is_same<decltype(r6), Y>::value, "" );
auto r7 = atomic_exchange(&v, x);
static_assert( std::is_same<decltype(r7), X>::value, "" );
auto r8 = atomic_exchange(&a, y);
static_assert( std::is_same<decltype(r8), Y>::value, "" );
auto r9 = atomic_exchange_explicit(&v, x, mo);
static_assert( std::is_same<decltype(r9), X>::value, "" );
auto r10 = atomic_exchange_explicit(&a, y, mo);
static_assert( std::is_same<decltype(r10), Y>::value, "" );
auto r11 = atomic_compare_exchange_weak(&v, &x, x);
static_assert( std::is_same<decltype(r11), bool>::value, "" );
auto r12 = atomic_compare_exchange_weak(&a, &y, y);
static_assert( std::is_same<decltype(r12), bool>::value, "" );
auto r13 = atomic_compare_exchange_strong(&v, &x, x);
static_assert( std::is_same<decltype(r13), bool>::value, "" );
auto r14 = atomic_compare_exchange_strong(&a, &y, y);
static_assert( std::is_same<decltype(r14), bool>::value, "" );
auto r15 = atomic_compare_exchange_weak_explicit(&v, &x, x, mo, mo);
static_assert( std::is_same<decltype(r15), bool>::value, "" );
auto r16 = atomic_compare_exchange_weak_explicit(&a, &y, y, mo, mo);
static_assert( std::is_same<decltype(r16), bool>::value, "" );
auto r17 = atomic_compare_exchange_strong_explicit(&v, &x, x, mo, mo);
static_assert( std::is_same<decltype(r17), bool>::value, "" );
auto r18 = atomic_compare_exchange_strong_explicit(&a, &y, y, mo, mo);
static_assert( std::is_same<decltype(r18), bool>::value, "" );
}
void
test02()
{
// Specialization for bool
volatile std::atomic<bool> v;
std::atomic<bool> a;
const std::memory_order mo = std::memory_order_seq_cst;
bool b = false;
auto r1 = atomic_is_lock_free(&v);
static_assert( std::is_same<decltype(r1), bool>::value, "" );
auto r2 = atomic_is_lock_free(&a);
static_assert( std::is_same<decltype(r2), bool>::value, "" );
atomic_init(&v, b);
atomic_init(&a, b);
atomic_store(&v, b);
atomic_store(&a, b);
atomic_store_explicit(&v, b, mo);
atomic_store_explicit(&a, b, mo);
auto r3 = atomic_load(&v);
static_assert( std::is_same<decltype(r3), bool>::value, "" );
auto r4 = atomic_load(&a);
static_assert( std::is_same<decltype(r4), bool>::value, "" );
auto r5 = atomic_load_explicit(&v, mo);
static_assert( std::is_same<decltype(r5), bool>::value, "" );
auto r6 = atomic_load_explicit(&a, mo);
static_assert( std::is_same<decltype(r6), bool>::value, "" );
auto r7 = atomic_exchange(&v, b);
static_assert( std::is_same<decltype(r7), bool>::value, "" );
auto r8 = atomic_exchange(&a, b);
static_assert( std::is_same<decltype(r8), bool>::value, "" );
auto r9 = atomic_exchange_explicit(&v, b, mo);
static_assert( std::is_same<decltype(r9), bool>::value, "" );
auto r10 = atomic_exchange_explicit(&a, b, mo);
static_assert( std::is_same<decltype(r10), bool>::value, "" );
auto r11 = atomic_compare_exchange_weak(&v, &b, b);
static_assert( std::is_same<decltype(r11), bool>::value, "" );
auto r12 = atomic_compare_exchange_weak(&a, &b, b);
static_assert( std::is_same<decltype(r12), bool>::value, "" );
auto r13 = atomic_compare_exchange_strong(&v, &b, b);
static_assert( std::is_same<decltype(r13), bool>::value, "" );
auto r14 = atomic_compare_exchange_strong(&a, &b, b);
static_assert( std::is_same<decltype(r14), bool>::value, "" );
auto r15 = atomic_compare_exchange_weak_explicit(&v, &b, b, mo, mo);
static_assert( std::is_same<decltype(r15), bool>::value, "" );
auto r16 = atomic_compare_exchange_weak_explicit(&a, &b, b, mo, mo);
static_assert( std::is_same<decltype(r16), bool>::value, "" );
auto r17 = atomic_compare_exchange_strong_explicit(&v, &b, b, mo, mo);
static_assert( std::is_same<decltype(r17), bool>::value, "" );
auto r18 = atomic_compare_exchange_strong_explicit(&a, &b, b, mo, mo);
static_assert( std::is_same<decltype(r18), bool>::value, "" );
}
void
test03()
{
// Partial specialization for pointers
volatile std::atomic<int*> v;
std::atomic<long*> a;
const std::memory_order mo = std::memory_order_seq_cst;
int* i = nullptr;
long* l = nullptr;
auto r1 = atomic_is_lock_free(&v);
static_assert( std::is_same<decltype(r1), bool>::value, "" );
auto r2 = atomic_is_lock_free(&a);
static_assert( std::is_same<decltype(r2), bool>::value, "" );
atomic_init(&v, i);
atomic_init(&a, l);
atomic_store(&v, i);
atomic_store(&a, l);
atomic_store_explicit(&v, i, mo);
atomic_store_explicit(&a, l, mo);
auto r3 = atomic_load(&v);
static_assert( std::is_same<decltype(r3), int*>::value, "" );
auto r4 = atomic_load(&a);
static_assert( std::is_same<decltype(r4), long*>::value, "" );
auto r5 = atomic_load_explicit(&v, mo);
static_assert( std::is_same<decltype(r5), int*>::value, "" );
auto r6 = atomic_load_explicit(&a, mo);
static_assert( std::is_same<decltype(r6), long*>::value, "" );
auto r7 = atomic_exchange(&v, i);
static_assert( std::is_same<decltype(r7), int*>::value, "" );
auto r8 = atomic_exchange(&a, l);
static_assert( std::is_same<decltype(r8), long*>::value, "" );
auto r9 = atomic_exchange_explicit(&v, i, mo);
static_assert( std::is_same<decltype(r9), int*>::value, "" );
auto r10 = atomic_exchange_explicit(&a, l, mo);
static_assert( std::is_same<decltype(r10), long*>::value, "" );
auto r11 = atomic_compare_exchange_weak(&v, &i, i);
static_assert( std::is_same<decltype(r11), bool>::value, "" );
auto r12 = atomic_compare_exchange_weak(&a, &l, l);
static_assert( std::is_same<decltype(r12), bool>::value, "" );
auto r13 = atomic_compare_exchange_strong(&v, &i, i);
static_assert( std::is_same<decltype(r13), bool>::value, "" );
auto r14 = atomic_compare_exchange_strong(&a, &l, l);
static_assert( std::is_same<decltype(r14), bool>::value, "" );
auto r15 = atomic_compare_exchange_weak_explicit(&v, &i, i, mo, mo);
static_assert( std::is_same<decltype(r15), bool>::value, "" );
auto r16 = atomic_compare_exchange_weak_explicit(&a, &l, l, mo, mo);
static_assert( std::is_same<decltype(r16), bool>::value, "" );
auto r17 = atomic_compare_exchange_strong_explicit(&v, &i, i, mo, mo);
static_assert( std::is_same<decltype(r17), bool>::value, "" );
auto r18 = atomic_compare_exchange_strong_explicit(&a, &l, l, mo, mo);
static_assert( std::is_same<decltype(r18), bool>::value, "" );
auto r19 = atomic_fetch_add(&v, 1);
static_assert( std::is_same<decltype(r19), int*>::value, "" );
auto r20 = atomic_fetch_add(&a, 1);
static_assert( std::is_same<decltype(r20), long*>::value, "" );
auto r21 = atomic_fetch_add_explicit(&v, 1, mo);
static_assert( std::is_same<decltype(r21), int*>::value, "" );
auto r22 = atomic_fetch_add_explicit(&a, 1, mo);
static_assert( std::is_same<decltype(r22), long*>::value, "" );
auto r23 = atomic_fetch_sub(&v, 1);
static_assert( std::is_same<decltype(r23), int*>::value, "" );
auto r24 = atomic_fetch_sub(&a, 1);
static_assert( std::is_same<decltype(r24), long*>::value, "" );
auto r25 = atomic_fetch_sub_explicit(&v, 1, mo);
static_assert( std::is_same<decltype(r25), int*>::value, "" );
auto r26 = atomic_fetch_sub_explicit(&a, 1, mo);
static_assert( std::is_same<decltype(r26), long*>::value, "" );
}
void
test04()
{
struct base { };
struct derived : base { };
// Partial specialization for pointers
volatile std::atomic<base*> v;
std::atomic<base*> a;
const std::memory_order mo = std::memory_order_seq_cst;
// Repeat tests with arguments of type different to value_type.
derived* const p = nullptr;
base* b = nullptr;
atomic_init(&v, p);
atomic_init(&a, p);
atomic_store(&v, p);
atomic_store(&a, p);
atomic_store_explicit(&v, p, mo);
atomic_store_explicit(&a, p, mo);
atomic_exchange(&v, p);
atomic_exchange(&a, p);
atomic_exchange_explicit(&v, p, mo);
atomic_exchange_explicit(&a, p, mo);
atomic_compare_exchange_weak(&v, &b, p);
atomic_compare_exchange_weak(&a, &b, p);
atomic_compare_exchange_strong(&v, &b, p);
atomic_compare_exchange_strong(&a, &b, p);
atomic_compare_exchange_weak_explicit(&v, &b, p, mo, mo);
atomic_compare_exchange_weak_explicit(&a, &b, p, mo, mo);
atomic_compare_exchange_strong_explicit(&v, &b, p, mo, mo);
atomic_compare_exchange_strong_explicit(&a, &b, p, mo, mo);
}