Commit 25999a11 by Jonathan Wakely Committed by Jonathan Wakely

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
parent 8d39ea2f
2018-05-24 Jonathan Wakely <jwakely@redhat.com>
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.
2018-05-23 Jonathan Wakely <jwakely@redhat.com>
* include/bits/fs_path.h (path::__is_encoded_char): Change from class
......
......@@ -237,6 +237,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _ITp>
struct __atomic_base
{
using value_type = _ITp;
using difference_type = value_type;
private:
typedef _ITp __int_type;
......
......@@ -27,4 +27,4 @@ struct X {
char stuff[0]; // GNU extension, type has zero size
};
std::atomic<X> a; // { dg-error "not supported" "" { target *-*-* } 190 }
std::atomic<X> a; // { dg-error "not supported" "" { target *-*-* } 194 }
// Copyright (C) 2017 Free Software Foundation, Inc.
//
// 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-options "-std=gnu++17" }
// { dg-do compile { target c++17 } }
// { dg-require-atomic-builtins "" }
#include <atomic>
void
test01()
{
std::atomic<void*> p;
p.fetch_add(1); // { dg-error "from here" }
p.fetch_sub(1); // { dg-error "from here" }
p += 1; // { dg-error "from here" }
p -= 1; // { dg-error "from here" }
++p; // { dg-error "from here" }
p++; // { dg-error "from here" }
--p; // { dg-error "from here" }
p--; // { dg-error "from here" }
}
void
test02()
{
std::atomic<void(*)()> p;
p.fetch_add(1); // { dg-error "from here" }
p.fetch_sub(1); // { dg-error "from here" }
p += 1; // { dg-error "from here" }
p -= 1; // { dg-error "from here" }
++p; // { dg-error "from here" }
p++; // { dg-error "from here" }
--p; // { dg-error "from here" }
p--; // { dg-error "from here" }
}
void
test03()
{
volatile std::atomic<void*> p;
p.fetch_add(1); // { dg-error "from here" }
p.fetch_sub(1); // { dg-error "from here" }
p += 1; // { dg-error "from here" }
p -= 1; // { dg-error "from here" }
++p; // { dg-error "from here" }
p++; // { dg-error "from here" }
--p; // { dg-error "from here" }
p--; // { dg-error "from here" }
}
void
test04()
{
volatile std::atomic<void(*)()> p;
p.fetch_add(1); // { dg-error "from here" }
p.fetch_sub(1); // { dg-error "from here" }
p += 1; // { dg-error "from here" }
p -= 1; // { dg-error "from here" }
++p; // { dg-error "from here" }
p++; // { dg-error "from here" }
--p; // { dg-error "from here" }
p--; // { dg-error "from here" }
}
// { dg-prune-output "static assertion failed" }
// { dg-do run { target c++11 } }
// { dg-do run { target { c++11_only || c++14_only } } }
// { dg-require-atomic-builtins "" }
// Copyright (C) 2012-2018 Free Software Foundation, Inc.
......
// Copyright (C) 2017 Free Software Foundation, Inc.
//
// 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-options "-std=gnu++17" }
// { dg-do compile { target c++17 } }
// { dg-require-atomic-builtins "" }
#include <atomic>
template<typename T>
constexpr bool check()
{
typename std::atomic<T>::value_type* pv = (T*)nullptr;
typename std::atomic<T>::difference_type* pd = (std::ptrdiff_t*)nullptr;
return true;
}
static_assert( check<int*>(), "" );
static_assert( check<void*>(), "" );
static_assert( check<void(*)()>(), "" );
struct X { };
static_assert( check<X*>(), "" );
// Copyright (C) 2018 Free Software Foundation, Inc.
//
// 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()
{
volatile std::atomic<int> v;
std::atomic<long> a;
const std::memory_order mo = std::memory_order_seq_cst;
int i = 0;
long l = 0;
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, i);
static_assert( std::is_same<decltype(r19), int>::value, "" );
auto r20 = atomic_fetch_add(&a, l);
static_assert( std::is_same<decltype(r20), long>::value, "" );
auto r21 = atomic_fetch_add_explicit(&v, i, mo);
static_assert( std::is_same<decltype(r21), int>::value, "" );
auto r22 = atomic_fetch_add_explicit(&a, l, mo);
static_assert( std::is_same<decltype(r22), long>::value, "" );
auto r23 = atomic_fetch_sub(&v, i);
static_assert( std::is_same<decltype(r23), int>::value, "" );
auto r24 = atomic_fetch_sub(&a, l);
static_assert( std::is_same<decltype(r24), long>::value, "" );
auto r25 = atomic_fetch_sub_explicit(&v, i, mo);
static_assert( std::is_same<decltype(r25), int>::value, "" );
auto r26 = atomic_fetch_sub_explicit(&a, l, mo);
static_assert( std::is_same<decltype(r26), long>::value, "" );
auto r27 = atomic_fetch_and(&v, i);
static_assert( std::is_same<decltype(r27), int>::value, "" );
auto r28 = atomic_fetch_and(&a, l);
static_assert( std::is_same<decltype(r28), long>::value, "" );
auto r29 = atomic_fetch_and_explicit(&v, i, mo);
static_assert( std::is_same<decltype(r29), int>::value, "" );
auto r30 = atomic_fetch_and_explicit(&a, l, mo);
static_assert( std::is_same<decltype(r30), long>::value, "" );
auto r31 = atomic_fetch_or(&v, i);
static_assert( std::is_same<decltype(r31), int>::value, "" );
auto r32 = atomic_fetch_or(&a, l);
static_assert( std::is_same<decltype(r32), long>::value, "" );
auto r33 = atomic_fetch_or_explicit(&v, i, mo);
static_assert( std::is_same<decltype(r33), int>::value, "" );
auto r34 = atomic_fetch_or_explicit(&a, l, mo);
static_assert( std::is_same<decltype(r34), long>::value, "" );
auto r35 = atomic_fetch_xor(&v, i);
static_assert( std::is_same<decltype(r35), int>::value, "" );
auto r36 = atomic_fetch_xor(&a, l);
static_assert( std::is_same<decltype(r36), long>::value, "" );
auto r37 = atomic_fetch_xor_explicit(&v, i, mo);
static_assert( std::is_same<decltype(r37), int>::value, "" );
auto r38 = atomic_fetch_xor_explicit(&a, l, mo);
static_assert( std::is_same<decltype(r38), long>::value, "" );
}
void
test02()
{
volatile std::atomic<long> v;
std::atomic<long> a;
std::memory_order mo = std::memory_order_seq_cst;
// Repeat tests with arguments of type different to value_type.
const int i = 0;
long l = 0;
atomic_init(&v, i);
atomic_init(&a, i);
atomic_store(&v, i);
atomic_store(&a, i);
atomic_store_explicit(&v, i, mo);
atomic_store_explicit(&a, i, mo);
atomic_exchange(&v, i);
atomic_exchange(&a, i);
atomic_exchange_explicit(&v, i, mo);
atomic_exchange_explicit(&a, i, mo);
atomic_compare_exchange_weak(&v, &l, i);
atomic_compare_exchange_weak(&a, &l, i);
atomic_compare_exchange_strong(&v, &l, i);
atomic_compare_exchange_strong(&a, &l, i);
atomic_compare_exchange_weak_explicit(&v, &l, i, mo, mo);
atomic_compare_exchange_weak_explicit(&a, &l, i, mo, mo);
atomic_compare_exchange_strong_explicit(&v, &l, i, mo, mo);
atomic_compare_exchange_strong_explicit(&a, &l, i, mo, mo);
atomic_fetch_add(&v, i);
atomic_fetch_add(&a, i);
atomic_fetch_add_explicit(&v, i, mo);
atomic_fetch_add_explicit(&a, i, mo);
atomic_fetch_sub(&v, i);
atomic_fetch_sub(&a, i);
atomic_fetch_sub_explicit(&v, i, mo);
atomic_fetch_sub_explicit(&a, i, mo);
atomic_fetch_and(&v, i);
atomic_fetch_and(&a, i);
atomic_fetch_and_explicit(&v, i, mo);
atomic_fetch_and_explicit(&a, i, mo);
atomic_fetch_or(&v, i);
atomic_fetch_or(&a, i);
atomic_fetch_or_explicit(&v, i, mo);
atomic_fetch_or_explicit(&a, i, mo);
atomic_fetch_xor(&v, i);
atomic_fetch_xor(&a, i);
atomic_fetch_xor_explicit(&v, i, mo);
atomic_fetch_xor_explicit(&a, i, mo);
}
// Copyright (C) 2017 Free Software Foundation, Inc.
//
// 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-options "-std=gnu++17" }
// { dg-do compile { target c++17 } }
// { dg-require-atomic-builtins "" }
#include <atomic>
template<typename T>
constexpr bool check()
{
typename std::atomic<T>::value_type* pv = (T*)nullptr;
typename std::atomic<T>::difference_type* pd = (T*)nullptr;
return true;
}
static_assert( check<signed short>(), "" );
static_assert( check<unsigned short>(), "" );
static_assert( check<signed int>(), "" );
static_assert( check<unsigned int>(), "" );
static_assert( check<signed long>(), "" );
static_assert( check<unsigned long>(), "" );
static_assert( check<signed long long>(), "" );
static_assert( check<unsigned long long>(), "" );
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment