diff options
author | Howard Hinnant <hhinnant@apple.com> | 2013-05-02 20:18:43 +0000 |
---|---|---|
committer | Howard Hinnant <hhinnant@apple.com> | 2013-05-02 20:18:43 +0000 |
commit | 74f4da7219100afcff4baab33d12910d29eb127e (patch) | |
tree | 49dd83bd8829a518724301a7756a089e297e6cbd | |
parent | e58bc12f2aa9548ec3c5fe657dffa2024b5926c1 (diff) | |
download | external_libcxx-74f4da7219100afcff4baab33d12910d29eb127e.tar.gz external_libcxx-74f4da7219100afcff4baab33d12910d29eb127e.tar.bz2 external_libcxx-74f4da7219100afcff4baab33d12910d29eb127e.zip |
Stephan Tolksdorf: fixes the issue in the <atomic> 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<int>') requires a user-provided default constructor.
git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@180945 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | CREDITS.TXT | 12 | ||||
-rw-r--r-- | include/__config | 8 | ||||
-rw-r--r-- | include/atomic | 20 | ||||
-rw-r--r-- | test/atomics/atomics.flag/default.pass.cpp | 9 | ||||
-rw-r--r-- | test/atomics/atomics.types.generic/address.pass.cpp | 8 | ||||
-rw-r--r-- | test/atomics/atomics.types.generic/bool.pass.cpp | 8 | ||||
-rw-r--r-- | test/atomics/atomics.types.generic/integral.pass.cpp | 8 | ||||
-rw-r--r-- | test/atomics/atomics.types.operations/atomics.types.operations.req/atomic_is_lock_free.pass.cpp | 8 |
8 files changed, 68 insertions, 13 deletions
diff --git a/CREDITS.TXT b/CREDITS.TXT index 61b3542db..34a901f58 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 <atomic> 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 389b6c4b9..7923f2f48 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 <unsigned> 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 db67e7625..f6ab1cbaf 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 489e3d2b8..5c077b0a1 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 <atomic> +#include <new> #include <cassert> 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 1cfdef501..af9826f7f 100644 --- a/test/atomics/atomics.types.generic/address.pass.cpp +++ b/test/atomics/atomics.types.generic/address.pass.cpp @@ -66,6 +66,7 @@ // }; #include <atomic> +#include <new> #include <type_traits> #include <cassert> @@ -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 <class A, class T> diff --git a/test/atomics/atomics.types.generic/bool.pass.cpp b/test/atomics/atomics.types.generic/bool.pass.cpp index f6379dc7a..80e566563 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<bool> atomic_bool; #include <atomic> +#include <new> #include <cassert> int main() @@ -219,4 +220,11 @@ int main() assert((obj = true) == true); assert(obj == true); } + { + typedef std::atomic<bool> 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 fc678bcfa..26caa5001 100644 --- a/test/atomics/atomics.types.generic/integral.pass.cpp +++ b/test/atomics/atomics.types.generic/integral.pass.cpp @@ -85,6 +85,7 @@ // }; #include <atomic> +#include <new> #include <cassert> template <class A, class T> @@ -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 <class A, class T> 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 4b09c38db..407198920 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<T> 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<const A*>(&t)); + volatile A vt; + bool b2 = std::atomic_is_lock_free(static_cast<const volatile A*>(&vt)); } struct A |