From 74f4da7219100afcff4baab33d12910d29eb127e Mon Sep 17 00:00:00 2001 From: Howard Hinnant Date: Thu, 2 May 2013 20:18:43 +0000 Subject: [PATCH] Stephan Tolksdorf: fixes the issue in the header and adds corresponding tests. I've used macros to fall back to a user-provided default constructor if _LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS (though I suspect that there won't be many users defining that macro). The tests use placement new to check that atomic values get properly zero-initialized. I had to modify the atomic_is_lock_free test, because default initialization of an object of const type 'const A' (aka 'const atomic') requires a user-provided default constructor. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@180945 91177308-0d34-0410-b5e6-96231b3b80d8 --- CREDITS.TXT | 12 +++++++---- include/__config | 8 ++++++++ include/atomic | 20 ++++++++++++++----- test/atomics/atomics.flag/default.pass.cpp | 9 +++++++++ .../atomics.types.generic/address.pass.cpp | 8 ++++++++ .../atomics.types.generic/bool.pass.cpp | 8 ++++++++ .../atomics.types.generic/integral.pass.cpp | 8 ++++++++ .../atomic_is_lock_free.pass.cpp | 8 ++++---- 8 files changed, 68 insertions(+), 13 deletions(-) diff --git a/CREDITS.TXT b/CREDITS.TXT index 61b3542d..34a901f5 100644 --- a/CREDITS.TXT +++ b/CREDITS.TXT @@ -48,6 +48,10 @@ N: Argyrios Kyrtzidis E: kyrtzidis@apple.com D: Bug fixes. +N: Bruce Mitchener, Jr. +E: bruce.mitchener@gmail.com +D: Emscripten-related changes. + N: Michel Morin E: mimomorin@gmail.com D: Minor patches to is_convertible. @@ -78,6 +82,10 @@ N: Joerg Sonnenberger E: joerg@NetBSD.org D: NetBSD port. +N: Stephan Tolksdorf +E: st@quanttec.com +D: Minor fix + N: Michael van der Westhuizen E: r1mikey at gmail dot com @@ -93,7 +101,3 @@ N: Jeffrey Yasskin E: jyasskin@gmail.com E: jyasskin@google.com D: Linux fixes. - -N: Bruce Mitchener, Jr. -E: bruce.mitchener@gmail.com -D: Emscripten-related changes. diff --git a/include/__config b/include/__config index 389b6c4b..7923f2f4 100644 --- a/include/__config +++ b/include/__config @@ -216,7 +216,9 @@ typedef __char32_t char32_t; # define _LIBCPP_NORETURN __attribute__ ((noreturn)) #endif +#if !(__has_feature(cxx_defaulted_functions)) #define _LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS +#endif // !(__has_feature(cxx_defaulted_functions)) #if !(__has_feature(cxx_deleted_functions)) #define _LIBCPP_HAS_NO_DELETED_FUNCTIONS @@ -422,6 +424,12 @@ template struct __static_assert_check {}; #define _LIBCPP_CONSTEXPR constexpr #endif +#ifdef _LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS +#define _LIBCPP_DEFAULT {} +#else +#define _LIBCPP_DEFAULT = default; +#endif + #ifdef __GNUC__ #define _NOALIAS __attribute__((__malloc__)) #else diff --git a/include/atomic b/include/atomic index db67e762..f6ab1cba 100644 --- a/include/atomic +++ b/include/atomic @@ -622,7 +622,12 @@ struct __atomic_base // false {return __c11_atomic_compare_exchange_strong(&__a_, &__e, __d, __m, __m);} _LIBCPP_INLINE_VISIBILITY - __atomic_base() _NOEXCEPT {} // = default; +#ifndef _LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS + __atomic_base() _NOEXCEPT = default; +#else + __atomic_base() _NOEXCEPT : __a_() {} +#endif // _LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR __atomic_base(_Tp __d) _NOEXCEPT : __a_(__d) {} #ifndef _LIBCPP_HAS_NO_DELETED_FUNCTIONS @@ -645,7 +650,7 @@ struct __atomic_base<_Tp, true> { typedef __atomic_base<_Tp, false> __base; _LIBCPP_INLINE_VISIBILITY - __atomic_base() _NOEXCEPT {} // = default; + __atomic_base() _NOEXCEPT _LIBCPP_DEFAULT _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR __atomic_base(_Tp __d) _NOEXCEPT : __base(__d) {} @@ -726,7 +731,7 @@ struct atomic { typedef __atomic_base<_Tp> __base; _LIBCPP_INLINE_VISIBILITY - atomic() _NOEXCEPT {} // = default; + atomic() _NOEXCEPT _LIBCPP_DEFAULT _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR atomic(_Tp __d) _NOEXCEPT : __base(__d) {} @@ -746,7 +751,7 @@ struct atomic<_Tp*> { typedef __atomic_base<_Tp*> __base; _LIBCPP_INLINE_VISIBILITY - atomic() _NOEXCEPT {} // = default; + atomic() _NOEXCEPT _LIBCPP_DEFAULT _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR atomic(_Tp* __d) _NOEXCEPT : __base(__d) {} @@ -1367,7 +1372,12 @@ typedef struct atomic_flag {__c11_atomic_store(&__a_, false, __m);} _LIBCPP_INLINE_VISIBILITY - atomic_flag() _NOEXCEPT {} // = default; +#ifndef _LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS + atomic_flag() _NOEXCEPT = default; +#else + atomic_flag() _NOEXCEPT : __a_() {} +#endif // _LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS + _LIBCPP_INLINE_VISIBILITY atomic_flag(bool __b) _NOEXCEPT : __a_(__b) {} diff --git a/test/atomics/atomics.flag/default.pass.cpp b/test/atomics/atomics.flag/default.pass.cpp index 489e3d2b..5c077b0a 100644 --- a/test/atomics/atomics.flag/default.pass.cpp +++ b/test/atomics/atomics.flag/default.pass.cpp @@ -14,9 +14,18 @@ // atomic_flag() = default; #include +#include #include int main() { std::atomic_flag f; + + { + typedef std::atomic_flag A; + _ALIGNAS_TYPE(A) char storage[sizeof(A)] = {1}; + A& zero = *new (storage) A(); + assert(!zero.test_and_set()); + zero.~A(); + } } diff --git a/test/atomics/atomics.types.generic/address.pass.cpp b/test/atomics/atomics.types.generic/address.pass.cpp index 1cfdef50..af9826f7 100644 --- a/test/atomics/atomics.types.generic/address.pass.cpp +++ b/test/atomics/atomics.types.generic/address.pass.cpp @@ -66,6 +66,7 @@ // }; #include +#include #include #include @@ -112,6 +113,13 @@ do_test() assert(obj == T(5*sizeof(X))); assert((obj -= std::ptrdiff_t(3)) == T(2*sizeof(X))); assert(obj == T(2*sizeof(X))); + + { + _ALIGNAS_TYPE(A) char storage[sizeof(A)] = {23}; + A& zero = *new (storage) A(); + assert(zero == 0); + zero.~A(); + } } template diff --git a/test/atomics/atomics.types.generic/bool.pass.cpp b/test/atomics/atomics.types.generic/bool.pass.cpp index f6379dc7..80e56656 100644 --- a/test/atomics/atomics.types.generic/bool.pass.cpp +++ b/test/atomics/atomics.types.generic/bool.pass.cpp @@ -50,6 +50,7 @@ // typedef atomic atomic_bool; #include +#include #include int main() @@ -219,4 +220,11 @@ int main() assert((obj = true) == true); assert(obj == true); } + { + typedef std::atomic A; + _ALIGNAS_TYPE(A) char storage[sizeof(A)] = {1}; + A& zero = *new (storage) A(); + assert(zero == false); + zero.~A(); + } } diff --git a/test/atomics/atomics.types.generic/integral.pass.cpp b/test/atomics/atomics.types.generic/integral.pass.cpp index fc678bcf..26caa500 100644 --- a/test/atomics/atomics.types.generic/integral.pass.cpp +++ b/test/atomics/atomics.types.generic/integral.pass.cpp @@ -85,6 +85,7 @@ // }; #include +#include #include template @@ -143,6 +144,13 @@ do_test() assert(obj == T(7)); assert((obj ^= T(0xF)) == T(8)); assert(obj == T(8)); + + { + _ALIGNAS_TYPE(A) char storage[sizeof(A)] = {23}; + A& zero = *new (storage) A(); + assert(zero == 0); + zero.~A(); + } } template diff --git a/test/atomics/atomics.types.operations/atomics.types.operations.req/atomic_is_lock_free.pass.cpp b/test/atomics/atomics.types.operations/atomics.types.operations.req/atomic_is_lock_free.pass.cpp index 4b09c38d..40719892 100644 --- a/test/atomics/atomics.types.operations/atomics.types.operations.req/atomic_is_lock_free.pass.cpp +++ b/test/atomics/atomics.types.operations/atomics.types.operations.req/atomic_is_lock_free.pass.cpp @@ -24,10 +24,10 @@ void test() { typedef std::atomic A; - const A ct; - bool b1 = std::atomic_is_lock_free(&ct); - const volatile A cvt; - bool b2 = std::atomic_is_lock_free(&cvt); + A t; + bool b1 = std::atomic_is_lock_free(static_cast(&t)); + volatile A vt; + bool b2 = std::atomic_is_lock_free(static_cast(&vt)); } struct A