summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHoward Hinnant <hhinnant@apple.com>2013-05-02 20:18:43 +0000
committerHoward Hinnant <hhinnant@apple.com>2013-05-02 20:18:43 +0000
commit74f4da7219100afcff4baab33d12910d29eb127e (patch)
tree49dd83bd8829a518724301a7756a089e297e6cbd
parente58bc12f2aa9548ec3c5fe657dffa2024b5926c1 (diff)
downloadexternal_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.TXT12
-rw-r--r--include/__config8
-rw-r--r--include/atomic20
-rw-r--r--test/atomics/atomics.flag/default.pass.cpp9
-rw-r--r--test/atomics/atomics.types.generic/address.pass.cpp8
-rw-r--r--test/atomics/atomics.types.generic/bool.pass.cpp8
-rw-r--r--test/atomics/atomics.types.generic/integral.pass.cpp8
-rw-r--r--test/atomics/atomics.types.operations/atomics.types.operations.req/atomic_is_lock_free.pass.cpp8
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