values = {
v = 201911;
cxxmin = 20;
+ extra_cond = "__cpp_concepts >= 201907L";
};
};
#undef __glibcxx_want_atomic_ref
#if !defined(__cpp_lib_atomic_value_initialization)
-# if (__cplusplus >= 202002L)
+# if (__cplusplus >= 202002L) && (__cpp_concepts >= 201907L)
# define __glibcxx_atomic_value_initialization 201911L
# if defined(__glibcxx_want_all) || defined(__glibcxx_want_atomic_value_initialization)
# define __cpp_lib_atomic_value_initialization 201911L
#include <bits/atomic_base.h>
#include <cstdint>
+#include <type_traits>
namespace std _GLIBCXX_VISIBILITY(default)
{
#endif // __cpp_lib_atomic_wait
};
-/// @cond undocumented
-#if __cpp_lib_atomic_value_initialization
-# define _GLIBCXX20_INIT(I) = I
-#else
-# define _GLIBCXX20_INIT(I)
-#endif
-/// @endcond
-
/**
* @brief Generic atomic type, primary class template.
*
static constexpr int _S_alignment
= _S_min_alignment > alignof(_Tp) ? _S_min_alignment : alignof(_Tp);
- alignas(_S_alignment) _Tp _M_i _GLIBCXX20_INIT(_Tp());
+ alignas(_S_alignment) _Tp _M_i;
static_assert(__is_trivially_copyable(_Tp),
"std::atomic requires a trivially copyable type");
#endif
public:
+#if __cpp_lib_atomic_value_initialization
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 4169. std::atomic<T>'s default constructor should be constrained
+ constexpr atomic() noexcept(is_nothrow_default_constructible_v<_Tp>)
+ requires is_default_constructible_v<_Tp>
+ : _M_i()
+ {}
+#else
atomic() = default;
+#endif
+
~atomic() noexcept = default;
atomic(const atomic&) = delete;
atomic& operator=(const atomic&) = delete;
#endif // __cpp_lib_atomic_wait
};
-#undef _GLIBCXX20_INIT
/// Partial specialization for pointer types.
template<typename _Tp>
template class std::atomic<NonDefaultConstructible>;
+static_assert(!std::is_default_constructible<std::atomic<NonDefaultConstructible>>::value);
+
void
test01()
{
--- /dev/null
+// { dg-do compile { target c++11 } }
+
+#include <atomic>
+#include <type_traits>
+
+// C++20 / P0883R2 makes std::atomic value-initialize, so it's no
+// longer going to be trivially default constructible; check that it
+// still is in earlier language modes.
+// (We are not applying that paper as a DR.)
+#if __cpp_lib_atomic_value_initialization
+constexpr bool atomic_default_ctor_is_trivial = false;
+#else
+constexpr bool atomic_default_ctor_is_trivial = true;
+#endif
+
+template<typename T>
+using isTDC = std::is_trivially_default_constructible<T>;
+
+static_assert(isTDC<std::atomic<bool>>::value == atomic_default_ctor_is_trivial);
+static_assert(isTDC<std::atomic<char>>::value == atomic_default_ctor_is_trivial);
+static_assert(isTDC<std::atomic<unsigned char>>::value == atomic_default_ctor_is_trivial);
+static_assert(isTDC<std::atomic<int>>::value == atomic_default_ctor_is_trivial);
+static_assert(isTDC<std::atomic<long>>::value == atomic_default_ctor_is_trivial);
+static_assert(isTDC<std::atomic<unsigned long long>>::value == atomic_default_ctor_is_trivial);
+static_assert(isTDC<std::atomic<int*>>::value == atomic_default_ctor_is_trivial);
+
+struct DefaultConstructible
+{
+ int a;
+ long long b;
+ char* p;
+};
+static_assert(isTDC<std::atomic<DefaultConstructible>>::value == atomic_default_ctor_is_trivial);
+
+struct NonDefaultConstructible
+{
+ NonDefaultConstructible(int i) : val(i) { }
+ int val;
+};
+// Not default constructible, therefore not trivially default constructible
+static_assert(isTDC<std::atomic<NonDefaultConstructible>>::value == false);