Skip to content
This repository was archived by the owner on Apr 23, 2020. It is now read-only.

Commit 00f4a49

Browse files
committed
[libcxx] Allow use of <atomic> in C++03. Try 3.
Summary: After putting this question up on cfe-dev I have decided that it would be best to allow the use of `<atomic>` in C++03. Although static initialization is a concern the syntax required to get it is C++11 only. Meaning that C++11 constant static initialization cannot silently break in C++03, it will always cause a syntax error. Furthermore `ATOMIC_VAR_INIT` and `ATOMIC_FLAG_INIT` remain defined in C++03 even though they cannot be used because C++03 usages will cause better error messages. The main change in this patch is to replace `__has_feature(cxx_atomic)`, which only returns true when C++ >= 11, to `__has_extension(c_atomic)` which returns true whenever clang supports the required atomic builtins. This patch adds the following macros: * `_LIBCPP_HAS_C_ATOMIC_IMP` - Defined on clang versions which provide the C `_Atomic` keyword. * `_LIBCPP_HAS_GCC_ATOMIC_IMP` - Defined on GCC > 4.7. We must use the fallback atomic implementation. * `_LIBCPP_HAS_NO_ATOMIC_HEADER` - Defined when it is not safe to include `<atomic>`. `_LIBCPP_HAS_C_ATOMIC_IMP` and `_LIBCPP_HAS_GCC_ATOMIC_IMP` are mutually exclusive, only one should be defined. If neither is defined then `<atomic>` is not implemented and including `<atomic>` will issue an error. Reviewers: chandlerc, jroelofs, mclow.lists Subscribers: cfe-commits Differential Revision: http://reviews.llvm.org/D11555 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@245463 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 8966350 commit 00f4a49

37 files changed

+304
-698
lines changed

include/__config

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@
3737
#ifndef __has_builtin
3838
#define __has_builtin(__x) 0
3939
#endif
40+
#ifndef __has_extension
41+
#define __has_extension(__x) 0
42+
#endif
4043
#ifndef __has_feature
4144
#define __has_feature(__x) 0
4245
#endif
@@ -773,4 +776,15 @@ extern "C" void __sanitizer_annotate_contiguous_container(
773776
#define _LIBCPP_HAS_NO_THREAD_UNSAFE_C_FUNCTIONS
774777
#endif
775778

776-
#endif // _LIBCPP_CONFIG
779+
#if __has_extension(c_atomic)
780+
#define _LIBCPP_HAS_C_ATOMIC_IMP
781+
#elif _GNUC_VER > 407
782+
#define _LIBCPP_HAS_GCC_ATOMIC_IMP
783+
#endif
784+
785+
#if (!defined(_LIBCPP_HAS_C_ATOMIC_IMP) && !defined(_LIBCPP_HAS_GCC_ATOMIC_IMP)) \
786+
|| defined(_LIBCPP_HAS_NO_THREADS)
787+
#define _LIBCPP_HAS_NO_ATOMIC_HEADER
788+
#endif
789+
790+
#endif // _LIBCPP_CONFIG

include/atomic

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -535,21 +535,20 @@ void atomic_signal_fence(memory_order m) noexcept;
535535

536536
#ifdef _LIBCPP_HAS_NO_THREADS
537537
#error <atomic> is not supported on this single threaded system
538-
#else // !_LIBCPP_HAS_NO_THREADS
538+
#endif
539+
#if !defined(_LIBCPP_HAS_C_ATOMIC_IMP) && !defined(_LIBCPP_HAS_GCC_ATOMIC_IMP)
540+
#error <atomic> is not implemented
541+
#endif
539542

540543
_LIBCPP_BEGIN_NAMESPACE_STD
541544

542-
#if !__has_feature(cxx_atomic) && _GNUC_VER < 407
543-
#error <atomic> is not implemented
544-
#else
545-
546545
typedef enum memory_order
547546
{
548547
memory_order_relaxed, memory_order_consume, memory_order_acquire,
549548
memory_order_release, memory_order_acq_rel, memory_order_seq_cst
550549
} memory_order;
551550

552-
#if _GNUC_VER >= 407
551+
#if defined(_LIBCPP_HAS_GCC_ATOMIC_IMP)
553552
namespace __gcc_atomic {
554553
template <typename _Tp>
555554
struct __gcc_atomic_t {
@@ -805,7 +804,7 @@ static inline _Tp __c11_atomic_fetch_xor(_Atomic(_Tp)* __a, _Tp __pattern,
805804
return __atomic_fetch_xor(&__a->__a_value, __pattern,
806805
__gcc_atomic::__to_gcc_order(__order));
807806
}
808-
#endif // _GNUC_VER >= 407
807+
#endif // _LIBCPP_HAS_GCC_ATOMIC_IMP
809808

810809
template <class _Tp>
811810
inline _LIBCPP_INLINE_VISIBILITY
@@ -825,7 +824,7 @@ struct __atomic_base // false
825824
_LIBCPP_INLINE_VISIBILITY
826825
bool is_lock_free() const volatile _NOEXCEPT
827826
{
828-
#if __has_feature(cxx_atomic)
827+
#if defined(_LIBCPP_HAS_C_ATOMIC_IMP)
829828
return __c11_atomic_is_lock_free(sizeof(_Tp));
830829
#else
831830
return __atomic_is_lock_free(sizeof(_Tp), 0);
@@ -1779,8 +1778,6 @@ typedef atomic<uintmax_t> atomic_uintmax_t;
17791778
#define ATOMIC_FLAG_INIT {false}
17801779
#define ATOMIC_VAR_INIT(__v) {__v}
17811780

1782-
// lock-free property
1783-
17841781
#define ATOMIC_BOOL_LOCK_FREE __GCC_ATOMIC_BOOL_LOCK_FREE
17851782
#define ATOMIC_CHAR_LOCK_FREE __GCC_ATOMIC_CHAR_LOCK_FREE
17861783
#define ATOMIC_CHAR16_T_LOCK_FREE __GCC_ATOMIC_CHAR16_T_LOCK_FREE
@@ -1792,10 +1789,6 @@ typedef atomic<uintmax_t> atomic_uintmax_t;
17921789
#define ATOMIC_LLONG_LOCK_FREE __GCC_ATOMIC_LLONG_LOCK_FREE
17931790
#define ATOMIC_POINTER_LOCK_FREE __GCC_ATOMIC_POINTER_LOCK_FREE
17941791

1795-
#endif // !__has_feature(cxx_atomic)
1796-
17971792
_LIBCPP_END_NAMESPACE_STD
17981793

1799-
#endif // !_LIBCPP_HAS_NO_THREADS
1800-
18011794
#endif // _LIBCPP_ATOMIC

include/ios

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ storage-class-specifier const error_category& iostream_category() noexcept;
216216
#include <__locale>
217217
#include <system_error>
218218

219-
#if __has_feature(cxx_atomic) && !defined(_LIBCPP_HAS_NO_THREADS)
219+
#if !defined(_LIBCPP_HAS_NO_ATOMIC_HEADER)
220220
#include <atomic> // for __xindex_
221221
#endif
222222

@@ -367,7 +367,9 @@ private:
367367
int* __index_;
368368
size_t __event_size_;
369369
size_t __event_cap_;
370-
#if __has_feature(cxx_atomic) && !defined(_LIBCPP_HAS_NO_THREADS)
370+
// TODO(EricWF): Enable this for both Clang and GCC. Currently it is only
371+
// enabled with clang.
372+
#if defined(_LIBCPP_HAS_C_ATOMIC_IMP) && !defined(_LIBCPP_HAS_NO_THREADS)
371373
static atomic<int> __xindex_;
372374
#else
373375
static int __xindex_;

include/memory

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -612,7 +612,7 @@ void* align(size_t alignment, size_t size, void*& ptr, size_t& space);
612612
#include <cassert>
613613
#endif
614614

615-
#if __has_feature(cxx_atomic) && !defined(_LIBCPP_HAS_NO_THREADS)
615+
#if !defined(_LIBCPP_HAS_NO_ATOMIC_HEADER)
616616
# include <atomic>
617617
#endif
618618

@@ -5381,7 +5381,9 @@ inline _LIBCPP_INLINE_VISIBILITY
53815381
basic_ostream<_CharT, _Traits>&
53825382
operator<<(basic_ostream<_CharT, _Traits>& __os, shared_ptr<_Yp> const& __p);
53835383

5384-
#if __has_feature(cxx_atomic) && !defined(_LIBCPP_HAS_NO_THREADS)
5384+
// TODO(EricWF): Enable this for both Clang and GCC. Currently it is only
5385+
// enabled with clang.
5386+
#if defined(_LIBCPP_HAS_C_ATOMIC_IMP) && !defined(_LIBCPP_HAS_NO_THREADS)
53855387

53865388
class _LIBCPP_TYPE_VIS __sp_mut
53875389
{
@@ -5507,7 +5509,7 @@ atomic_compare_exchange_weak_explicit(shared_ptr<_Tp>* __p, shared_ptr<_Tp>* __v
55075509
return atomic_compare_exchange_weak(__p, __v, __w);
55085510
}
55095511

5510-
#endif // __has_feature(cxx_atomic) && !defined(_LIBCPP_HAS_NO_THREADS)
5512+
#endif // defined(_LIBCPP_HAS_C_ATOMIC_IMP) && !defined(_LIBCPP_HAS_NO_THREADS)
55115513

55125514
//enum class
55135515
struct _LIBCPP_TYPE_VIS pointer_safety

src/ios.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ ios_base::getloc() const
152152
}
153153

154154
// xalloc
155-
#if __has_feature(cxx_atomic) && !defined(_LIBCPP_HAS_NO_THREADS)
155+
#if defined(_LIBCPP_HAS_C_ATOMIC_IMP) && !defined(_LIBCPP_HAS_NO_THREADS)
156156
atomic<int> ios_base::__xindex_ = ATOMIC_VAR_INIT(0);
157157
#else
158158
int ios_base::__xindex_ = 0;

src/memory.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ __shared_weak_count::__get_deleter(const type_info&) const _NOEXCEPT
124124

125125
#endif // _LIBCPP_NO_RTTI
126126

127-
#if __has_feature(cxx_atomic) && !defined(_LIBCPP_HAS_NO_THREADS)
127+
#if defined(_LIBCPP_HAS_C_ATOMIC_IMP) && !defined(_LIBCPP_HAS_NO_THREADS)
128128

129129
static const std::size_t __sp_mut_count = 16;
130130
static pthread_mutex_t mut_back_imp[__sp_mut_count] =
@@ -177,7 +177,7 @@ __get_sp_mut(const void* p)
177177
return muts[hash<const void*>()(p) & (__sp_mut_count-1)];
178178
}
179179

180-
#endif // __has_feature(cxx_atomic) && !_LIBCPP_HAS_NO_THREADS
180+
#endif // defined(_LIBCPP_HAS_C_ATOMIC_IMP) && !defined(_LIBCPP_HAS_NO_THREADS)
181181

182182
void
183183
declare_reachable(void*)

test/std/atomics/atomics.flag/atomic_flag_clear.pass.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,13 @@
2222
int main()
2323
{
2424
{
25-
std::atomic_flag f = ATOMIC_FLAG_INIT;
25+
std::atomic_flag f(false);
2626
f.test_and_set();
2727
atomic_flag_clear(&f);
2828
assert(f.test_and_set() == 0);
2929
}
3030
{
31-
volatile std::atomic_flag f = ATOMIC_FLAG_INIT;
31+
volatile std::atomic_flag f(false);
3232
f.test_and_set();
3333
atomic_flag_clear(&f);
3434
assert(f.test_and_set() == 0);

test/std/atomics/atomics.flag/atomic_flag_clear_explicit.pass.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,37 +22,37 @@
2222
int main()
2323
{
2424
{
25-
std::atomic_flag f = ATOMIC_FLAG_INIT;
25+
std::atomic_flag f(false);
2626
f.test_and_set();
2727
atomic_flag_clear_explicit(&f, std::memory_order_relaxed);
2828
assert(f.test_and_set() == 0);
2929
}
3030
{
31-
std::atomic_flag f = ATOMIC_FLAG_INIT;
31+
std::atomic_flag f(false);
3232
f.test_and_set();
3333
atomic_flag_clear_explicit(&f, std::memory_order_release);
3434
assert(f.test_and_set() == 0);
3535
}
3636
{
37-
std::atomic_flag f = ATOMIC_FLAG_INIT;
37+
std::atomic_flag f(false);
3838
f.test_and_set();
3939
atomic_flag_clear_explicit(&f, std::memory_order_seq_cst);
4040
assert(f.test_and_set() == 0);
4141
}
4242
{
43-
volatile std::atomic_flag f = ATOMIC_FLAG_INIT;
43+
volatile std::atomic_flag f(false);
4444
f.test_and_set();
4545
atomic_flag_clear_explicit(&f, std::memory_order_relaxed);
4646
assert(f.test_and_set() == 0);
4747
}
4848
{
49-
volatile std::atomic_flag f = ATOMIC_FLAG_INIT;
49+
volatile std::atomic_flag f(false);
5050
f.test_and_set();
5151
atomic_flag_clear_explicit(&f, std::memory_order_release);
5252
assert(f.test_and_set() == 0);
5353
}
5454
{
55-
volatile std::atomic_flag f = ATOMIC_FLAG_INIT;
55+
volatile std::atomic_flag f(false);
5656
f.test_and_set();
5757
atomic_flag_clear_explicit(&f, std::memory_order_seq_cst);
5858
assert(f.test_and_set() == 0);

test/std/atomics/atomics.flag/clear.pass.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,49 +22,49 @@
2222
int main()
2323
{
2424
{
25-
std::atomic_flag f = ATOMIC_FLAG_INIT;
25+
std::atomic_flag f(false);
2626
f.test_and_set();
2727
f.clear();
2828
assert(f.test_and_set() == 0);
2929
}
3030
{
31-
std::atomic_flag f = ATOMIC_FLAG_INIT;
31+
std::atomic_flag f(false);
3232
f.test_and_set();
3333
f.clear(std::memory_order_relaxed);
3434
assert(f.test_and_set() == 0);
3535
}
3636
{
37-
std::atomic_flag f = ATOMIC_FLAG_INIT;
37+
std::atomic_flag f(false);
3838
f.test_and_set();
3939
f.clear(std::memory_order_release);
4040
assert(f.test_and_set() == 0);
4141
}
4242
{
43-
std::atomic_flag f = ATOMIC_FLAG_INIT;
43+
std::atomic_flag f(false);
4444
f.test_and_set();
4545
f.clear(std::memory_order_seq_cst);
4646
assert(f.test_and_set() == 0);
4747
}
4848
{
49-
volatile std::atomic_flag f = ATOMIC_FLAG_INIT;
49+
volatile std::atomic_flag f(false);
5050
f.test_and_set();
5151
f.clear();
5252
assert(f.test_and_set() == 0);
5353
}
5454
{
55-
volatile std::atomic_flag f = ATOMIC_FLAG_INIT;
55+
volatile std::atomic_flag f(false);
5656
f.test_and_set();
5757
f.clear(std::memory_order_relaxed);
5858
assert(f.test_and_set() == 0);
5959
}
6060
{
61-
volatile std::atomic_flag f = ATOMIC_FLAG_INIT;
61+
volatile std::atomic_flag f(false);
6262
f.test_and_set();
6363
f.clear(std::memory_order_release);
6464
assert(f.test_and_set() == 0);
6565
}
6666
{
67-
volatile std::atomic_flag f = ATOMIC_FLAG_INIT;
67+
volatile std::atomic_flag f(false);
6868
f.test_and_set();
6969
f.clear(std::memory_order_seq_cst);
7070
assert(f.test_and_set() == 0);

test/std/atomics/atomics.flag/init.pass.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
//===----------------------------------------------------------------------===//
99
//
1010
// UNSUPPORTED: libcpp-has-no-threads
11+
// XFAIL: c++98, c++03
1112

1213
// <atomic>
1314

0 commit comments

Comments
 (0)