libstdc++: Value-initialize std::atomic for C++20 (P0883R2)
This implements the new requirements for C++20 that std::atomic should initialize the atomic variable in its default constructor. This patch does not add the deprecated attribute to atomic_init, but that should be done at some point as it's deprecated in C++20. The paper also deprecates the ATOMIC_FLAG_INIT macro, although we can't apply the deprecated attribute to a macro. PR libstdc++/58605 * include/bits/atomic_base.h (__cpp_lib_atomic_value_initialization): Define. (__atomic_flag_base, __atomic_base, __atomic_base<_PTp*>) (__atomic_float): Add default member initializer for C++20. * include/std/atomic (atomic): Likewise. (atomic::atomic()): Remove noexcept-specifier on default constructor. * include/std/version (__cpp_lib_atomic_value_initialization): Define. * testsuite/29_atomics/atomic/cons/assign_neg.cc: Adjust dg-error line number. * testsuite/29_atomics/atomic/cons/copy_neg.cc: Likewise. * testsuite/29_atomics/atomic/cons/value_init.cc: New test. * testsuite/29_atomics/atomic_flag/cons/value_init.cc: New test. * testsuite/29_atomics/atomic_flag/requirements/trivial.cc: Adjust expected result for is_trivially_default_constructible. * testsuite/29_atomics/atomic_float/requirements.cc: Likewise. * testsuite/29_atomics/atomic_float/value_init.cc: New test. * testsuite/29_atomics/atomic_integral/cons/assign_neg.cc: Likewise. * testsuite/29_atomics/atomic_integral/cons/copy_neg.cc: Likewise. * testsuite/29_atomics/atomic_integral/cons/value_init.cc * testsuite/29_atomics/atomic_integral/requirements/trivial.cc: Adjust expected results for is_trivially_default_constructible. * testsuite/util/testsuite_common_types.h (has_trivial_dtor): Add new test generator.
This commit is contained in:
parent
aef85e40e0
commit
e4379a931d
@ -1,3 +1,30 @@
|
||||
2020-01-13 Jonathan Wakely <jwakely@redhat.com>
|
||||
|
||||
PR libstdc++/58605
|
||||
* include/bits/atomic_base.h (__cpp_lib_atomic_value_initialization):
|
||||
Define.
|
||||
(__atomic_flag_base, __atomic_base, __atomic_base<_PTp*>)
|
||||
(__atomic_float): Add default member initializer for C++20.
|
||||
* include/std/atomic (atomic): Likewise.
|
||||
(atomic::atomic()): Remove noexcept-specifier on default constructor.
|
||||
* include/std/version (__cpp_lib_atomic_value_initialization): Define.
|
||||
* testsuite/29_atomics/atomic/cons/assign_neg.cc: Adjust dg-error line
|
||||
number.
|
||||
* testsuite/29_atomics/atomic/cons/copy_neg.cc: Likewise.
|
||||
* testsuite/29_atomics/atomic/cons/value_init.cc: New test.
|
||||
* testsuite/29_atomics/atomic_flag/cons/value_init.cc: New test.
|
||||
* testsuite/29_atomics/atomic_flag/requirements/trivial.cc: Adjust
|
||||
expected result for is_trivially_default_constructible.
|
||||
* testsuite/29_atomics/atomic_float/requirements.cc: Likewise.
|
||||
* testsuite/29_atomics/atomic_float/value_init.cc: New test.
|
||||
* testsuite/29_atomics/atomic_integral/cons/assign_neg.cc: Likewise.
|
||||
* testsuite/29_atomics/atomic_integral/cons/copy_neg.cc: Likewise.
|
||||
* testsuite/29_atomics/atomic_integral/cons/value_init.cc
|
||||
* testsuite/29_atomics/atomic_integral/requirements/trivial.cc: Adjust
|
||||
expected results for is_trivially_default_constructible.
|
||||
* testsuite/util/testsuite_common_types.h (has_trivial_dtor): Add
|
||||
new test generator.
|
||||
|
||||
2020-01-10 Jonathan Wakely <jwakely@redhat.com>
|
||||
|
||||
* testsuite/util/testsuite_iterators.h: Improve comment.
|
||||
|
@ -139,6 +139,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
template<typename _IntTp>
|
||||
struct __atomic_base;
|
||||
|
||||
#if __cplusplus <= 201703L
|
||||
# define _GLIBCXX20_INIT(I)
|
||||
#else
|
||||
# define __cpp_lib_atomic_value_initialization 201911L
|
||||
# define _GLIBCXX20_INIT(I) = I
|
||||
#endif
|
||||
|
||||
#define ATOMIC_VAR_INIT(_VI) { _VI }
|
||||
|
||||
@ -169,7 +175,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
struct __atomic_flag_base
|
||||
{
|
||||
__atomic_flag_data_type _M_i;
|
||||
__atomic_flag_data_type _M_i _GLIBCXX20_INIT({});
|
||||
};
|
||||
|
||||
_GLIBCXX_END_EXTERN_C
|
||||
@ -267,7 +273,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
static constexpr int _S_alignment =
|
||||
sizeof(_ITp) > alignof(_ITp) ? sizeof(_ITp) : alignof(_ITp);
|
||||
|
||||
alignas(_S_alignment) __int_type _M_i;
|
||||
alignas(_S_alignment) __int_type _M_i _GLIBCXX20_INIT(0);
|
||||
|
||||
public:
|
||||
__atomic_base() noexcept = default;
|
||||
@ -595,7 +601,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
private:
|
||||
typedef _PTp* __pointer_type;
|
||||
|
||||
__pointer_type _M_p;
|
||||
__pointer_type _M_p _GLIBCXX20_INIT(nullptr);
|
||||
|
||||
// Factored out to facilitate explicit specialization.
|
||||
constexpr ptrdiff_t
|
||||
@ -1175,8 +1181,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
{ return __atomic_impl::__sub_fetch_flt(&_M_fp, __i); }
|
||||
|
||||
private:
|
||||
alignas(_S_alignment) _Fp _M_fp;
|
||||
alignas(_S_alignment) _Fp _M_fp _GLIBCXX20_INIT(0);
|
||||
};
|
||||
#undef _GLIBCXX20_INIT
|
||||
|
||||
template<typename _Tp,
|
||||
bool = is_integral_v<_Tp>, bool = is_floating_point_v<_Tp>>
|
||||
|
@ -165,6 +165,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
{ return _M_base.compare_exchange_strong(__i1, __i2, __m); }
|
||||
};
|
||||
|
||||
#if __cplusplus <= 201703L
|
||||
# define _GLIBCXX20_INIT(I)
|
||||
#else
|
||||
# define _GLIBCXX20_INIT(I) = I
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Generic atomic type, primary class template.
|
||||
@ -185,7 +190,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
static constexpr int _S_alignment
|
||||
= _S_min_alignment > alignof(_Tp) ? _S_min_alignment : alignof(_Tp);
|
||||
|
||||
alignas(_S_alignment) _Tp _M_i;
|
||||
alignas(_S_alignment) _Tp _M_i _GLIBCXX20_INIT(_Tp());
|
||||
|
||||
static_assert(__is_trivially_copyable(_Tp),
|
||||
"std::atomic requires a trivially copyable type");
|
||||
@ -194,7 +199,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
"Incomplete or zero-sized types are not supported");
|
||||
|
||||
public:
|
||||
atomic() noexcept = default;
|
||||
atomic() = default;
|
||||
~atomic() noexcept = default;
|
||||
atomic(const atomic&) = delete;
|
||||
atomic& operator=(const atomic&) = delete;
|
||||
@ -348,7 +353,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
{ return compare_exchange_strong(__e, __i, __m,
|
||||
__cmpexch_failure_order(__m)); }
|
||||
};
|
||||
|
||||
#undef _GLIBCXX20_INIT
|
||||
|
||||
/// Partial specialization for pointer types.
|
||||
template<typename _Tp>
|
||||
|
@ -164,6 +164,7 @@
|
||||
#if __cplusplus > 201703L
|
||||
// c++2a
|
||||
#define __cpp_lib_atomic_ref 201806L
|
||||
#define __cpp_lib_atomic_value_initialization 201911L
|
||||
#define __cpp_lib_bitops 201907L
|
||||
#define __cpp_lib_bounded_array_traits 201902L
|
||||
#if __cpp_concepts
|
||||
|
@ -27,5 +27,5 @@ int main()
|
||||
return 0;
|
||||
}
|
||||
|
||||
// { dg-error "deleted" "" { target *-*-* } 639 }
|
||||
// { dg-error "deleted" "" { target *-*-* } 659 }
|
||||
// { dg-prune-output "include" }
|
||||
|
@ -27,5 +27,5 @@ int main()
|
||||
return 0;
|
||||
}
|
||||
|
||||
// { dg-error "deleted" "" { target *-*-* } 678 }
|
||||
// { dg-error "deleted" "" { target *-*-* } 698 }
|
||||
// { dg-prune-output "include" }
|
||||
|
76
libstdc++-v3/testsuite/29_atomics/atomic/cons/value_init.cc
Normal file
76
libstdc++-v3/testsuite/29_atomics/atomic/cons/value_init.cc
Normal file
@ -0,0 +1,76 @@
|
||||
// Copyright (C) 2020 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++2a" }
|
||||
// { dg-do run { target c++2a } }
|
||||
|
||||
#include <atomic>
|
||||
|
||||
#ifndef __cpp_lib_atomic_value_initialization
|
||||
# error "Feature test macro for atomic value-initialization is missing"
|
||||
#elif __cpp_lib_atomic_value_initialization < 201911L
|
||||
# error "Feature test macro for atomic value-initialization has wrong value"
|
||||
#endif
|
||||
|
||||
#include <testsuite_hooks.h>
|
||||
|
||||
struct A
|
||||
{
|
||||
constexpr A() : val(42) { }
|
||||
int val;
|
||||
};
|
||||
|
||||
constexpr std::atomic<A> a;
|
||||
|
||||
void
|
||||
test01()
|
||||
{
|
||||
VERIFY(a.load().val == 42);
|
||||
static_assert(!std::is_nothrow_default_constructible_v<std::atomic<A>>);
|
||||
}
|
||||
|
||||
struct B
|
||||
{
|
||||
constexpr B() noexcept : val(99) { }
|
||||
int val;
|
||||
};
|
||||
|
||||
constexpr std::atomic<B> b;
|
||||
|
||||
void
|
||||
test02()
|
||||
{
|
||||
VERIFY(b.load().val == 99);
|
||||
static_assert(std::is_nothrow_default_constructible_v<std::atomic<B>>);
|
||||
}
|
||||
|
||||
constexpr std::atomic<int*> c;
|
||||
|
||||
void
|
||||
test03()
|
||||
{
|
||||
VERIFY(c.load() == nullptr);
|
||||
static_assert(std::is_nothrow_default_constructible_v<std::atomic<int*>>);
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
test01();
|
||||
test02();
|
||||
test03();
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
// Copyright (C) 2020 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++2a" }
|
||||
// { dg-do run { target c++2a } }
|
||||
|
||||
#include <atomic>
|
||||
#include <testsuite_hooks.h>
|
||||
|
||||
void
|
||||
test01()
|
||||
{
|
||||
std::atomic_flag f;
|
||||
VERIFY(!f.test_and_set());
|
||||
VERIFY(f.test_and_set());
|
||||
static_assert(std::is_nothrow_default_constructible_v<std::atomic_flag>);
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
test01();
|
||||
}
|
@ -22,6 +22,10 @@
|
||||
|
||||
void test01()
|
||||
{
|
||||
#if __cplusplus <= 201703L
|
||||
__gnu_test::has_trivial_cons_dtor test;
|
||||
#else
|
||||
__gnu_test::has_trivial_dtor test;
|
||||
#endif
|
||||
test.operator()<std::atomic_flag>();
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ test01()
|
||||
{
|
||||
using A = std::atomic<float>;
|
||||
static_assert( std::is_standard_layout_v<A> );
|
||||
static_assert( std::is_trivially_default_constructible_v<A> );
|
||||
static_assert( !std::is_trivially_default_constructible_v<A> );
|
||||
static_assert( std::is_trivially_destructible_v<A> );
|
||||
static_assert( std::is_same_v<A::value_type, float> );
|
||||
static_assert( std::is_same_v<A::difference_type, A::value_type> );
|
||||
@ -41,7 +41,7 @@ test02()
|
||||
{
|
||||
using A = std::atomic<double>;
|
||||
static_assert( std::is_standard_layout_v<A> );
|
||||
static_assert( std::is_trivially_default_constructible_v<A> );
|
||||
static_assert( !std::is_trivially_default_constructible_v<A> );
|
||||
static_assert( std::is_trivially_destructible_v<A> );
|
||||
static_assert( std::is_same_v<A::value_type, double> );
|
||||
static_assert( std::is_same_v<A::difference_type, A::value_type> );
|
||||
@ -57,7 +57,7 @@ test03()
|
||||
{
|
||||
using A = std::atomic<long double>;
|
||||
static_assert( std::is_standard_layout_v<A> );
|
||||
static_assert( std::is_trivially_default_constructible_v<A> );
|
||||
static_assert( !std::is_trivially_default_constructible_v<A> );
|
||||
static_assert( std::is_trivially_destructible_v<A> );
|
||||
static_assert( std::is_same_v<A::value_type, long double> );
|
||||
static_assert( std::is_same_v<A::difference_type, A::value_type> );
|
||||
|
37
libstdc++-v3/testsuite/29_atomics/atomic_float/value_init.cc
Normal file
37
libstdc++-v3/testsuite/29_atomics/atomic_float/value_init.cc
Normal file
@ -0,0 +1,37 @@
|
||||
// Copyright (C) 2020 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++2a" }
|
||||
// { dg-do run { target c++2a } }
|
||||
|
||||
#include <atomic>
|
||||
#include <testsuite_hooks.h>
|
||||
|
||||
constexpr std::atomic<double> a;
|
||||
|
||||
void
|
||||
test01()
|
||||
{
|
||||
VERIFY(a.load() == 0);
|
||||
static_assert(std::is_nothrow_default_constructible_v<std::atomic<double>>);
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
test01();
|
||||
}
|
@ -28,5 +28,5 @@ int main()
|
||||
return 0;
|
||||
}
|
||||
|
||||
// { dg-error "deleted" "" { target *-*-* } 639 }
|
||||
// { dg-error "deleted" "" { target *-*-* } 659 }
|
||||
// { dg-prune-output "include" }
|
||||
|
@ -28,5 +28,5 @@ int main()
|
||||
return 0;
|
||||
}
|
||||
|
||||
// { dg-error "deleted" "" { target *-*-* } 678 }
|
||||
// { dg-error "deleted" "" { target *-*-* } 698 }
|
||||
// { dg-prune-output "include" }
|
||||
|
@ -0,0 +1,37 @@
|
||||
// Copyright (C) 2020 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++2a" }
|
||||
// { dg-do run { target c++2a } }
|
||||
|
||||
#include <atomic>
|
||||
#include <testsuite_hooks.h>
|
||||
|
||||
constexpr std::atomic<int> a;
|
||||
|
||||
void
|
||||
test01()
|
||||
{
|
||||
VERIFY(a.load() == 0);
|
||||
static_assert(std::is_nothrow_default_constructible_v<std::atomic<int>>);
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
test01();
|
||||
}
|
@ -22,7 +22,11 @@
|
||||
|
||||
void test01()
|
||||
{
|
||||
#if __cplusplus <= 201703L
|
||||
__gnu_test::has_trivial_cons_dtor test;
|
||||
#else
|
||||
__gnu_test::has_trivial_dtor test;
|
||||
#endif
|
||||
__gnu_cxx::typelist::apply_generator(test,
|
||||
__gnu_test::atomic_integrals::type());
|
||||
}
|
||||
|
@ -558,7 +558,6 @@ namespace __gnu_test
|
||||
}
|
||||
};
|
||||
|
||||
// Generator to test standard layout
|
||||
struct has_trivial_cons_dtor
|
||||
{
|
||||
template<typename _Tp>
|
||||
@ -582,6 +581,27 @@ namespace __gnu_test
|
||||
}
|
||||
};
|
||||
|
||||
struct has_trivial_dtor
|
||||
{
|
||||
template<typename _Tp>
|
||||
void
|
||||
operator()()
|
||||
{
|
||||
struct _Concept
|
||||
{
|
||||
void __constraint()
|
||||
{
|
||||
typedef std::is_trivially_destructible<_Tp> dtor_p;
|
||||
static_assert(dtor_p::value, "destructor not trivial");
|
||||
}
|
||||
};
|
||||
|
||||
void (_Concept::*__x)() __attribute__((unused))
|
||||
= &_Concept::__constraint;
|
||||
}
|
||||
};
|
||||
|
||||
// Generator to test standard layout
|
||||
struct standard_layout
|
||||
{
|
||||
template<typename _Tp>
|
||||
|
Loading…
Reference in New Issue
Block a user