summaryrefslogtreecommitdiffstats
path: root/contrib/libc++/src
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/libc++/src')
-rw-r--r--contrib/libc++/src/algorithm.cpp2
-rw-r--r--contrib/libc++/src/any.cpp9
-rw-r--r--contrib/libc++/src/chrono.cpp120
-rw-r--r--contrib/libc++/src/condition_variable.cpp6
-rw-r--r--contrib/libc++/src/debug.cpp100
-rw-r--r--contrib/libc++/src/exception.cpp42
-rw-r--r--contrib/libc++/src/experimental/filesystem/directory_iterator.cpp4
-rw-r--r--contrib/libc++/src/experimental/filesystem/operations.cpp184
-rw-r--r--contrib/libc++/src/experimental/filesystem/path.cpp550
-rw-r--r--contrib/libc++/src/experimental/memory_resource.cpp25
-rw-r--r--contrib/libc++/src/include/atomic_support.h2
-rw-r--r--contrib/libc++/src/include/config_elast.h10
-rw-r--r--contrib/libc++/src/ios.cpp18
-rw-r--r--contrib/libc++/src/iostream.cpp52
-rw-r--r--contrib/libc++/src/locale.cpp330
-rw-r--r--contrib/libc++/src/memory.cpp51
-rw-r--r--contrib/libc++/src/mutex.cpp17
-rw-r--r--contrib/libc++/src/new.cpp184
-rw-r--r--contrib/libc++/src/optional.cpp16
-rw-r--r--contrib/libc++/src/random.cpp2
-rw-r--r--contrib/libc++/src/stdexcept.cpp6
-rw-r--r--contrib/libc++/src/string.cpp8
-rw-r--r--contrib/libc++/src/strstream.cpp3
-rw-r--r--contrib/libc++/src/system_error.cpp17
-rw-r--r--contrib/libc++/src/thread.cpp28
-rw-r--r--contrib/libc++/src/typeinfo.cpp16
-rw-r--r--contrib/libc++/src/variant.cpp18
27 files changed, 1236 insertions, 584 deletions
diff --git a/contrib/libc++/src/algorithm.cpp b/contrib/libc++/src/algorithm.cpp
index e9752b0..f036eb7 100644
--- a/contrib/libc++/src/algorithm.cpp
+++ b/contrib/libc++/src/algorithm.cpp
@@ -48,7 +48,7 @@ template bool __insertion_sort_incomplete<__less<long double>&, long double*>(lo
template unsigned __sort5<__less<long double>&, long double*>(long double*, long double*, long double*, long double*, long double*, __less<long double>&);
#ifndef _LIBCPP_HAS_NO_THREADS
-static __libcpp_mutex_t __rs_mut = _LIBCPP_MUTEX_INITIALIZER;
+_LIBCPP_SAFE_STATIC static __libcpp_mutex_t __rs_mut = _LIBCPP_MUTEX_INITIALIZER;
#endif
unsigned __rs_default::__c_ = 0;
diff --git a/contrib/libc++/src/any.cpp b/contrib/libc++/src/any.cpp
index f776845..45b2337 100644
--- a/contrib/libc++/src/any.cpp
+++ b/contrib/libc++/src/any.cpp
@@ -7,12 +7,17 @@
//
//===----------------------------------------------------------------------===//
+#include "any"
#include "experimental/any"
-_LIBCPP_BEGIN_NAMESPACE_LFTS
-
+namespace std {
const char* bad_any_cast::what() const _NOEXCEPT {
return "bad any cast";
}
+}
+_LIBCPP_BEGIN_NAMESPACE_LFTS
+const char* bad_any_cast::what() const _NOEXCEPT {
+ return "bad any cast";
+}
_LIBCPP_END_NAMESPACE_LFTS
diff --git a/contrib/libc++/src/chrono.cpp b/contrib/libc++/src/chrono.cpp
index 62149fb..9b277a6 100644
--- a/contrib/libc++/src/chrono.cpp
+++ b/contrib/libc++/src/chrono.cpp
@@ -12,14 +12,45 @@
#include "system_error" // __throw_system_error
#include <time.h> // clock_gettime, CLOCK_MONOTONIC and CLOCK_REALTIME
-#if !defined(CLOCK_REALTIME)
-#include <sys/time.h> // for gettimeofday and timeval
+#if (__APPLE__)
+#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__)
+#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 101200
+#define _LIBCXX_USE_CLOCK_GETTIME
+#endif
+#elif defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__)
+#if __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 100000
+#define _LIBCXX_USE_CLOCK_GETTIME
+#endif
+#elif defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__)
+#if __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ >= 100000
+#define _LIBCXX_USE_CLOCK_GETTIME
+#endif
+#elif defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__)
+#if __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ >= 30000
+#define _LIBCXX_USE_CLOCK_GETTIME
+#endif
+#endif // __ENVIRONMENT_.*_VERSION_MIN_REQUIRED__
+#else
+#define _LIBCXX_USE_CLOCK_GETTIME
+#endif // __APPLE__
+
+#if defined(_LIBCPP_WIN32API)
+#define WIN32_LEAN_AND_MEAN
+#define VC_EXTRA_LEAN
+#include <Windows.h>
+#if _WIN32_WINNT >= _WIN32_WINNT_WIN8
+#include <winapifamily.h>
#endif
+#else
+#if !defined(CLOCK_REALTIME) || !defined(_LIBCXX_USE_CLOCK_GETTIME)
+#include <sys/time.h> // for gettimeofday and timeval
+#endif // !defined(CLOCK_REALTIME)
+#endif // defined(_LIBCPP_WIN32API)
-#if !defined(_LIBCPP_HAS_NO_MONOTONIC_CLOCK) && !defined(CLOCK_MONOTONIC)
+#if !defined(_LIBCPP_HAS_NO_MONOTONIC_CLOCK)
#if __APPLE__
#include <mach/mach_time.h> // mach_absolute_time, mach_timebase_info_data_t
-#else
+#elif !defined(_LIBCPP_WIN32API) && !defined(CLOCK_MONOTONIC)
#error "Monotonic clock not implemented"
#endif
#endif
@@ -36,16 +67,42 @@ const bool system_clock::is_steady;
system_clock::time_point
system_clock::now() _NOEXCEPT
{
-#ifdef CLOCK_REALTIME
+#if defined(_LIBCPP_WIN32API)
+ // FILETIME is in 100ns units
+ using filetime_duration =
+ _VSTD::chrono::duration<__int64,
+ _VSTD::ratio_multiply<_VSTD::ratio<100, 1>,
+ nanoseconds::period>>;
+
+ // The Windows epoch is Jan 1 1601, the Unix epoch Jan 1 1970.
+ static _LIBCPP_CONSTEXPR const seconds nt_to_unix_epoch{11644473600};
+
+ FILETIME ft;
+#if _WIN32_WINNT >= _WIN32_WINNT_WIN8
+#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
+ GetSystemTimePreciseAsFileTime(&ft);
+#else
+ GetSystemTimeAsFileTime(&ft);
+#endif
+#else
+ GetSystemTimeAsFileTime(&ft);
+#endif
+
+ filetime_duration d{(static_cast<__int64>(ft.dwHighDateTime) << 32) |
+ static_cast<__int64>(ft.dwLowDateTime)};
+ return time_point(duration_cast<duration>(d - nt_to_unix_epoch));
+#else
+#if defined(_LIBCXX_USE_CLOCK_GETTIME) && defined(CLOCK_REALTIME)
struct timespec tp;
if (0 != clock_gettime(CLOCK_REALTIME, &tp))
__throw_system_error(errno, "clock_gettime(CLOCK_REALTIME) failed");
return time_point(seconds(tp.tv_sec) + microseconds(tp.tv_nsec / 1000));
-#else // !CLOCK_REALTIME
+#else
timeval tv;
gettimeofday(&tv, 0);
return time_point(seconds(tv.tv_sec) + microseconds(tv.tv_usec));
-#endif // CLOCK_REALTIME
+#endif // _LIBCXX_USE_CLOCK_GETTIME && CLOCK_REALTIME
+#endif
}
time_t
@@ -69,19 +126,20 @@ system_clock::from_time_t(time_t t) _NOEXCEPT
const bool steady_clock::is_steady;
-#ifdef CLOCK_MONOTONIC
+#if defined(__APPLE__)
+// Darwin libc versions >= 1133 provide ns precision via CLOCK_UPTIME_RAW
+#if defined(_LIBCXX_USE_CLOCK_GETTIME) && defined(CLOCK_UPTIME_RAW)
steady_clock::time_point
steady_clock::now() _NOEXCEPT
{
struct timespec tp;
- if (0 != clock_gettime(CLOCK_MONOTONIC, &tp))
- __throw_system_error(errno, "clock_gettime(CLOCK_MONOTONIC) failed");
+ if (0 != clock_gettime(CLOCK_UPTIME_RAW, &tp))
+ __throw_system_error(errno, "clock_gettime(CLOCK_UPTIME_RAW) failed");
return time_point(seconds(tp.tv_sec) + nanoseconds(tp.tv_nsec));
}
-#elif defined(__APPLE__)
-
+#else
// mach_absolute_time() * MachInfo.numer / MachInfo.denom is the number of
// nanoseconds since the computer booted up. MachInfo.numer and MachInfo.denom
// are run time constants supplied by the OS. This clock has no relationship
@@ -90,8 +148,6 @@ steady_clock::now() _NOEXCEPT
// MachInfo.numer / MachInfo.denom is often 1 on the latest equipment. Specialize
// for that case as an optimization.
-#pragma GCC visibility push(hidden)
-
static
steady_clock::rep
steady_simplified()
@@ -129,14 +185,46 @@ init_steady_clock()
return &steady_full;
}
-#pragma GCC visibility pop
-
steady_clock::time_point
steady_clock::now() _NOEXCEPT
{
static FP fp = init_steady_clock();
return time_point(duration(fp()));
}
+#endif // defined(_LIBCXX_USE_CLOCK_GETTIME) && defined(CLOCK_UPTIME_RAW)
+
+#elif defined(_LIBCPP_WIN32API)
+
+steady_clock::time_point
+steady_clock::now() _NOEXCEPT
+{
+ static LARGE_INTEGER freq;
+ static BOOL initialized = FALSE;
+ if (!initialized)
+ initialized = QueryPerformanceFrequency(&freq); // always succceeds
+
+ LARGE_INTEGER counter;
+ QueryPerformanceCounter(&counter);
+ return time_point(duration(counter.QuadPart * nano::den / freq.QuadPart));
+}
+
+#elif defined(CLOCK_MONOTONIC)
+
+// On Apple platforms only CLOCK_UPTIME_RAW or mach_absolute_time are able to
+// time functions in the nanosecond range. Thus, they are the only acceptable
+// implementations of steady_clock.
+#ifdef __APPLE__
+#error "Never use CLOCK_MONOTONIC for steady_clock::now on Apple platforms"
+#endif
+
+steady_clock::time_point
+steady_clock::now() _NOEXCEPT
+{
+ struct timespec tp;
+ if (0 != clock_gettime(CLOCK_MONOTONIC, &tp))
+ __throw_system_error(errno, "clock_gettime(CLOCK_MONOTONIC) failed");
+ return time_point(seconds(tp.tv_sec) + nanoseconds(tp.tv_nsec));
+}
#else
#error "Monotonic clock not implemented"
diff --git a/contrib/libc++/src/condition_variable.cpp b/contrib/libc++/src/condition_variable.cpp
index bfb4bf3..25e6603 100644
--- a/contrib/libc++/src/condition_variable.cpp
+++ b/contrib/libc++/src/condition_variable.cpp
@@ -79,6 +79,12 @@ condition_variable::__do_timed_wait(unique_lock<mutex>& lk,
void
notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk)
{
+ auto& tl_ptr = __thread_local_data();
+ // If this thread was not created using std::thread then it will not have
+ // previously allocated.
+ if (tl_ptr.get() == nullptr) {
+ tl_ptr.set_pointer(new __thread_struct);
+ }
__thread_local_data()->notify_all_at_thread_exit(&cond, lk.release());
}
diff --git a/contrib/libc++/src/debug.cpp b/contrib/libc++/src/debug.cpp
index b1a16e6..f2fc1ce 100644
--- a/contrib/libc++/src/debug.cpp
+++ b/contrib/libc++/src/debug.cpp
@@ -7,16 +7,79 @@
//
//===----------------------------------------------------------------------===//
-#define _LIBCPP_DEBUG 1
#include "__config"
#include "__debug"
#include "functional"
#include "algorithm"
+#include "string"
+#include "cstdio"
#include "__hash_table"
#include "mutex"
_LIBCPP_BEGIN_NAMESPACE_STD
+static std::string make_what_str(__libcpp_debug_info const& info) {
+ string msg = info.__file_;
+ msg += ":" + to_string(info.__line_) + ": _LIBCPP_ASSERT '";
+ msg += info.__pred_;
+ msg += "' failed. ";
+ msg += info.__msg_;
+ return msg;
+}
+
+_LIBCPP_SAFE_STATIC __libcpp_debug_function_type
+ __libcpp_debug_function = __libcpp_abort_debug_function;
+
+bool __libcpp_set_debug_function(__libcpp_debug_function_type __func) {
+ __libcpp_debug_function = __func;
+ return true;
+}
+
+_LIBCPP_NORETURN void __libcpp_abort_debug_function(__libcpp_debug_info const& info) {
+ std::fprintf(stderr, "%s\n", make_what_str(info).c_str());
+ std::abort();
+}
+
+_LIBCPP_NORETURN void __libcpp_throw_debug_function(__libcpp_debug_info const& info) {
+#ifndef _LIBCPP_NO_EXCEPTIONS
+ throw __libcpp_debug_exception(info);
+#else
+ __libcpp_abort_debug_function(info);
+#endif
+}
+
+struct __libcpp_debug_exception::__libcpp_debug_exception_imp {
+ __libcpp_debug_info __info_;
+ std::string __what_str_;
+};
+
+__libcpp_debug_exception::__libcpp_debug_exception() _NOEXCEPT
+ : __imp_(nullptr) {
+}
+
+__libcpp_debug_exception::__libcpp_debug_exception(
+ __libcpp_debug_info const& info) : __imp_(new __libcpp_debug_exception_imp)
+{
+ __imp_->__info_ = info;
+ __imp_->__what_str_ = make_what_str(info);
+}
+__libcpp_debug_exception::__libcpp_debug_exception(
+ __libcpp_debug_exception const& other) : __imp_(nullptr) {
+ if (other.__imp_)
+ __imp_ = new __libcpp_debug_exception_imp(*other.__imp_);
+}
+
+__libcpp_debug_exception::~__libcpp_debug_exception() _NOEXCEPT {
+ if (__imp_)
+ delete __imp_;
+}
+
+const char* __libcpp_debug_exception::what() const _NOEXCEPT {
+ if (__imp_)
+ return __imp_->__what_str_.c_str();
+ return "__libcpp_debug_exception";
+}
+
_LIBCPP_FUNC_VIS
__libcpp_db*
__get_db()
@@ -152,11 +215,8 @@ __libcpp_db::__insert_c(void* __c)
size_t nc = __next_prime(2*static_cast<size_t>(__cend_ - __cbeg_) + 1);
__c_node** cbeg = static_cast<__c_node**>(calloc(nc, sizeof(void*)));
if (cbeg == nullptr)
-#ifndef _LIBCPP_NO_EXCEPTIONS
- throw bad_alloc();
-#else
- abort();
-#endif
+ __throw_bad_alloc();
+
for (__c_node** p = __cbeg_; p != __cend_; ++p)
{
__c_node* q = *p;
@@ -178,11 +238,8 @@ __libcpp_db::__insert_c(void* __c)
__c_node* r = __cbeg_[hc] =
static_cast<__c_node*>(malloc(sizeof(__c_node)));
if (__cbeg_[hc] == nullptr)
-#ifndef _LIBCPP_NO_EXCEPTIONS
- throw bad_alloc();
-#else
- abort();
-#endif
+ __throw_bad_alloc();
+
r->__c_ = __c;
r->__next_ = p;
++__csz_;
@@ -475,11 +532,8 @@ __c_node::__add(__i_node* i)
__i_node** beg =
static_cast<__i_node**>(malloc(nc * sizeof(__i_node*)));
if (beg == nullptr)
-#ifndef _LIBCPP_NO_EXCEPTIONS
- throw bad_alloc();
-#else
- abort();
-#endif
+ __throw_bad_alloc();
+
if (nc > 1)
memcpy(beg, beg_, nc/2*sizeof(__i_node*));
free(beg_);
@@ -501,11 +555,8 @@ __libcpp_db::__insert_iterator(void* __i)
size_t nc = __next_prime(2*static_cast<size_t>(__iend_ - __ibeg_) + 1);
__i_node** ibeg = static_cast<__i_node**>(calloc(nc, sizeof(void*)));
if (ibeg == nullptr)
-#ifndef _LIBCPP_NO_EXCEPTIONS
- throw bad_alloc();
-#else
- abort();
-#endif
+ __throw_bad_alloc();
+
for (__i_node** p = __ibeg_; p != __iend_; ++p)
{
__i_node* q = *p;
@@ -527,11 +578,8 @@ __libcpp_db::__insert_iterator(void* __i)
__i_node* r = __ibeg_[hi] =
static_cast<__i_node*>(malloc(sizeof(__i_node)));
if (r == nullptr)
-#ifndef _LIBCPP_NO_EXCEPTIONS
- throw bad_alloc();
-#else
- abort();
-#endif
+ __throw_bad_alloc();
+
::new(r) __i_node(__i, p, nullptr);
++__isz_;
return r;
diff --git a/contrib/libc++/src/exception.cpp b/contrib/libc++/src/exception.cpp
index e172f64..f25041d 100644
--- a/contrib/libc++/src/exception.cpp
+++ b/contrib/libc++/src/exception.cpp
@@ -12,7 +12,11 @@
#include "exception"
#include "new"
-#if defined(__APPLE__) && !defined(LIBCXXRT)
+#if defined(_LIBCPP_ABI_MICROSOFT)
+#include <eh.h>
+#include <corecrt_terminate.h>
+#elif defined(__APPLE__) && !defined(LIBCXXRT) && \
+ !defined(_LIBCPP_BUILDING_HAS_NO_ABI_LIBRARY)
#include <cxxabi.h>
using namespace __cxxabiv1;
@@ -32,8 +36,8 @@
#define HAVE_DEPENDENT_EH_ABI 1
#endif
#elif !defined(__GLIBCXX__) // defined(LIBCXX_BUILDING_LIBCXXABI)
- static std::terminate_handler __terminate_handler;
- static std::unexpected_handler __unexpected_handler;
+ _LIBCPP_SAFE_STATIC static std::terminate_handler __terminate_handler;
+ _LIBCPP_SAFE_STATIC static std::unexpected_handler __unexpected_handler;
#endif // defined(LIBCXX_BUILDING_LIBCXXABI)
namespace std
@@ -45,13 +49,21 @@ namespace std
unexpected_handler
set_unexpected(unexpected_handler func) _NOEXCEPT
{
- return __sync_lock_test_and_set(&__unexpected_handler, func);
+#if defined(_LIBCPP_ABI_MICROSOFT)
+ return ::set_unexpected(func);
+#else
+ return __sync_lock_test_and_set(&__unexpected_handler, func);
+#endif
}
unexpected_handler
get_unexpected() _NOEXCEPT
{
- return __sync_fetch_and_add(&__unexpected_handler, (unexpected_handler)0);
+#if defined(_LIBCPP_ABI_MICROSOFT)
+ return ::_get_unexpected();
+#else
+ return __sync_fetch_and_add(&__unexpected_handler, (unexpected_handler)0);
+#endif
}
_LIBCPP_NORETURN
@@ -66,13 +78,21 @@ unexpected()
terminate_handler
set_terminate(terminate_handler func) _NOEXCEPT
{
- return __sync_lock_test_and_set(&__terminate_handler, func);
+#if defined(_LIBCPP_ABI_MICROSOFT)
+ return ::set_terminate(func);
+#else
+ return __sync_lock_test_and_set(&__terminate_handler, func);
+#endif
}
terminate_handler
get_terminate() _NOEXCEPT
{
- return __sync_fetch_and_add(&__terminate_handler, (terminate_handler)0);
+#if defined(_LIBCPP_ABI_MICROSOFT)
+ return ::_get_terminate();
+#else
+ return __sync_fetch_and_add(&__terminate_handler, (terminate_handler)0);
+#endif
}
#ifndef __EMSCRIPTEN__ // We provide this in JS
@@ -102,18 +122,22 @@ terminate() _NOEXCEPT
#endif // !defined(LIBCXXRT) && !defined(_LIBCPPABI_VERSION)
#if !defined(LIBCXXRT) && !defined(__GLIBCXX__) && !defined(__EMSCRIPTEN__)
+
bool uncaught_exception() _NOEXCEPT { return uncaught_exceptions() > 0; }
int uncaught_exceptions() _NOEXCEPT
{
-#if defined(__APPLE__) || defined(_LIBCPPABI_VERSION)
+#if !defined(_LIBCPP_BUILDING_HAS_NO_ABI_LIBRARY) && \
+ (defined(__APPLE__) || defined(_LIBCPPABI_VERSION))
// on Darwin, there is a helper function so __cxa_get_globals is private
# if _LIBCPPABI_VERSION > 1101
return __cxa_uncaught_exceptions();
# else
return __cxa_uncaught_exception() ? 1 : 0;
# endif
-#else // __APPLE__
+#elif defined(_LIBCPP_ABI_MICROSOFT)
+ return __uncaught_exceptions();
+#else
# if defined(_MSC_VER) && ! defined(__clang__)
_LIBCPP_WARNING("uncaught_exceptions not yet implemented")
# else
diff --git a/contrib/libc++/src/experimental/filesystem/directory_iterator.cpp b/contrib/libc++/src/experimental/filesystem/directory_iterator.cpp
index fa217ba..a888dcf 100644
--- a/contrib/libc++/src/experimental/filesystem/directory_iterator.cpp
+++ b/contrib/libc++/src/experimental/filesystem/directory_iterator.cpp
@@ -20,7 +20,7 @@ inline bool capture_error_or_throw(std::error_code* user_ec,
*user_ec = my_ec;
return true;
}
- __libcpp_throw(filesystem_error(msg, std::forward<Args>(args)..., my_ec));
+ __throw_filesystem_error(msg, std::forward<Args>(args)..., my_ec);
return false;
}
@@ -33,7 +33,7 @@ inline bool set_or_throw(std::error_code& my_ec,
*user_ec = my_ec;
return true;
}
- __libcpp_throw(filesystem_error(msg, std::forward<Args>(args)..., my_ec));
+ __throw_filesystem_error(msg, std::forward<Args>(args)..., my_ec);
return false;
}
diff --git a/contrib/libc++/src/experimental/filesystem/operations.cpp b/contrib/libc++/src/experimental/filesystem/operations.cpp
index 369996f..6c7e4cf 100644
--- a/contrib/libc++/src/experimental/filesystem/operations.cpp
+++ b/contrib/libc++/src/experimental/filesystem/operations.cpp
@@ -51,7 +51,7 @@ void set_or_throw(std::error_code const& m_ec, std::error_code* ec,
} else {
string msg_s("std::experimental::filesystem::");
msg_s += msg;
- __libcpp_throw(filesystem_error(msg_s, p, p2, m_ec));
+ __throw_filesystem_error(msg_s, p, p2, m_ec);
}
}
@@ -236,12 +236,11 @@ void __copy(const path& from, const path& to, copy_options options,
}
return;
}
- else if (is_directory(f)) {
- if (not bool(copy_options::recursive & options) &&
- bool(copy_options::__in_recursive_copy & options))
- {
- return;
- }
+ else if (is_directory(f) && bool(copy_options::create_symlinks & options)) {
+ return set_or_throw(make_error_code(errc::is_a_directory), ec, "copy");
+ }
+ else if (is_directory(f) && (bool(copy_options::recursive & options) ||
+ copy_options::none == options)) {
if (!exists(t)) {
// create directory to with attributes from 'from'.
@@ -283,6 +282,10 @@ bool __copy_file(const path& from, const path& to, copy_options options,
}
const bool to_exists = exists(to_st);
+ if (to_exists && !is_regular_file(to_st)) {
+ set_or_throw(make_error_code(errc::not_supported), ec, "copy_file", from, to);
+ return false;
+ }
if (to_exists && bool(copy_options::skip_existing & options)) {
return false;
}
@@ -303,6 +306,8 @@ bool __copy_file(const path& from, const path& to, copy_options options,
set_or_throw(make_error_code(errc::file_exists), ec, "copy", from, to);
return false;
}
+
+ _LIBCPP_UNREACHABLE();
}
void __copy_symlink(const path& existing_symlink, const path& new_symlink,
@@ -476,18 +481,32 @@ bool __fs_is_empty(const path& p, std::error_code *ec)
std::error_code m_ec;
struct ::stat pst;
auto st = detail::posix_stat(p, pst, &m_ec);
- if (is_directory(st))
- return directory_iterator(p) == directory_iterator{};
+ if (m_ec) {
+ set_or_throw(m_ec, ec, "is_empty", p);
+ return false;
+ }
+ else if (!is_directory(st) && !is_regular_file(st)) {
+ m_ec = make_error_code(errc::not_supported);
+ set_or_throw(m_ec, ec, "is_empty");
+ return false;
+ }
+ else if (is_directory(st)) {
+ auto it = ec ? directory_iterator(p, *ec) : directory_iterator(p);
+ if (ec && *ec)
+ return false;
+ return it == directory_iterator{};
+ }
else if (is_regular_file(st))
return static_cast<std::uintmax_t>(pst.st_size) == 0;
- // else
- set_or_throw(m_ec, ec, "is_empty", p);
- return false;
+
+ _LIBCPP_UNREACHABLE();
}
namespace detail { namespace {
+using namespace std::chrono;
+
template <class CType, class ChronoType>
bool checked_set(CType* out, ChronoType time) {
using Lim = numeric_limits<CType>;
@@ -497,8 +516,127 @@ bool checked_set(CType* out, ChronoType time) {
return true;
}
-constexpr long long min_seconds = file_time_type::duration::min().count()
- / file_time_type::period::den;
+using TimeSpec = struct ::timespec;
+using StatT = struct ::stat;
+
+#if defined(__APPLE__)
+TimeSpec extract_mtime(StatT const& st) { return st.st_mtimespec; }
+TimeSpec extract_atime(StatT const& st) { return st.st_atimespec; }
+#else
+TimeSpec extract_mtime(StatT const& st) { return st.st_mtim; }
+__attribute__((unused)) // Suppress warning
+TimeSpec extract_atime(StatT const& st) { return st.st_atim; }
+#endif
+
+constexpr auto max_seconds = duration_cast<seconds>(
+ file_time_type::duration::max()).count();
+
+constexpr auto max_nsec = duration_cast<nanoseconds>(
+ file_time_type::duration::max() - seconds(max_seconds)).count();
+
+constexpr auto min_seconds = duration_cast<seconds>(
+ file_time_type::duration::min()).count();
+
+constexpr auto min_nsec_timespec = duration_cast<nanoseconds>(
+ (file_time_type::duration::min() - seconds(min_seconds)) + seconds(1)).count();
+
+// Static assert that these values properly round trip.
+static_assert((seconds(min_seconds) + duration_cast<microseconds>(nanoseconds(min_nsec_timespec)))
+ - duration_cast<microseconds>(seconds(1))
+ == file_time_type::duration::min(), "");
+
+constexpr auto max_time_t = numeric_limits<time_t>::max();
+constexpr auto min_time_t = numeric_limits<time_t>::min();
+
+#if !defined(__LP64__) && defined(__clang__)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wtautological-constant-out-of-range-compare"
+#endif
+
+_LIBCPP_CONSTEXPR_AFTER_CXX11
+bool is_representable(TimeSpec const& tm) {
+ if (tm.tv_sec >= 0) {
+ return (tm.tv_sec < max_seconds) ||
+ (tm.tv_sec == max_seconds && tm.tv_nsec <= max_nsec);
+ } else if (tm.tv_sec == (min_seconds - 1)) {
+ return tm.tv_nsec >= min_nsec_timespec;
+ } else {
+ return (tm.tv_sec >= min_seconds);
+ }
+}
+#ifndef _LIBCPP_HAS_NO_CXX14_CONSTEXPR
+#if defined(__LP64__)
+static_assert(is_representable({max_seconds, max_nsec}), "");
+static_assert(!is_representable({max_seconds + 1, 0}), "");
+static_assert(!is_representable({max_seconds, max_nsec + 1}), "");
+static_assert(!is_representable({max_time_t, 0}), "");
+static_assert(is_representable({min_seconds, 0}), "");
+static_assert(is_representable({min_seconds - 1, min_nsec_timespec}), "");
+static_assert(is_representable({min_seconds - 1, min_nsec_timespec + 1}), "");
+static_assert(!is_representable({min_seconds - 1, min_nsec_timespec - 1}), "");
+static_assert(!is_representable({min_time_t, 999999999}), "");
+#else
+static_assert(is_representable({max_time_t, 999999999}), "");
+static_assert(is_representable({max_time_t, 1000000000}), "");
+static_assert(is_representable({min_time_t, 0}), "");
+#endif
+#endif
+
+_LIBCPP_CONSTEXPR_AFTER_CXX11
+bool is_representable(file_time_type const& tm) {
+ auto secs = duration_cast<seconds>(tm.time_since_epoch());
+ auto nsecs = duration_cast<nanoseconds>(tm.time_since_epoch() - secs);
+ if (nsecs.count() < 0) {
+ secs = secs + seconds(1);
+ nsecs = nsecs + seconds(1);
+ }
+ using TLim = numeric_limits<time_t>;
+ if (secs.count() >= 0)
+ return secs.count() <= TLim::max();
+ return secs.count() >= TLim::min();
+}
+#ifndef _LIBCPP_HAS_NO_CXX14_CONSTEXPR
+#if defined(__LP64__)
+static_assert(is_representable(file_time_type::max()), "");
+static_assert(is_representable(file_time_type::min()), "");
+#else
+static_assert(!is_representable(file_time_type::max()), "");
+static_assert(!is_representable(file_time_type::min()), "");
+static_assert(is_representable(file_time_type(seconds(max_time_t))), "");
+static_assert(is_representable(file_time_type(seconds(min_time_t))), "");
+#endif
+#endif
+
+_LIBCPP_CONSTEXPR_AFTER_CXX11
+file_time_type convert_timespec(TimeSpec const& tm) {
+ auto adj_msec = duration_cast<microseconds>(nanoseconds(tm.tv_nsec));
+ if (tm.tv_sec >= 0) {
+ auto Dur = seconds(tm.tv_sec) + microseconds(adj_msec);
+ return file_time_type(Dur);
+ } else if (duration_cast<microseconds>(nanoseconds(tm.tv_nsec)).count() == 0) {
+ return file_time_type(seconds(tm.tv_sec));
+ } else { // tm.tv_sec < 0
+ auto adj_subsec = duration_cast<microseconds>(seconds(1) - nanoseconds(tm.tv_nsec));
+ auto Dur = seconds(tm.tv_sec + 1) - adj_subsec;
+ return file_time_type(Dur);
+ }
+}
+#ifndef _LIBCPP_HAS_NO_CXX14_CONSTEXPR
+#if defined(__LP64__)
+static_assert(convert_timespec({max_seconds, max_nsec}) == file_time_type::max(), "");
+static_assert(convert_timespec({max_seconds, max_nsec - 1}) < file_time_type::max(), "");
+static_assert(convert_timespec({max_seconds - 1, 999999999}) < file_time_type::max(), "");
+static_assert(convert_timespec({min_seconds - 1, min_nsec_timespec}) == file_time_type::min(), "");
+static_assert(convert_timespec({min_seconds - 1, min_nsec_timespec + 1}) > file_time_type::min(), "");
+static_assert(convert_timespec({min_seconds , 0}) > file_time_type::min(), "");
+#else
+// FIXME add tests for 32 bit builds
+#endif
+#endif
+
+#if !defined(__LP64__) && defined(__clang__)
+#pragma clang diagnostic pop
+#endif
template <class SubSecDurT, class SubSecT>
bool set_times_checked(time_t* sec_out, SubSecT* subsec_out, file_time_type tp) {
@@ -509,7 +647,6 @@ bool set_times_checked(time_t* sec_out, SubSecT* subsec_out, file_time_type tp)
// The tv_nsec and tv_usec fields must not be negative so adjust accordingly
if (subsec_dur.count() < 0) {
if (sec_dur.count() > min_seconds) {
-
sec_dur -= seconds(1);
subsec_dur += seconds(1);
} else {
@@ -522,9 +659,9 @@ bool set_times_checked(time_t* sec_out, SubSecT* subsec_out, file_time_type tp)
}} // end namespace detail
-
file_time_type __last_write_time(const path& p, std::error_code *ec)
{
+ using namespace ::std::chrono;
std::error_code m_ec;
struct ::stat st;
detail::posix_stat(p, st, &m_ec);
@@ -533,7 +670,13 @@ file_time_type __last_write_time(const path& p, std::error_code *ec)
return file_time_type::min();
}
if (ec) ec->clear();
- return file_time_type::clock::from_time_t(st.st_mtime);
+ auto ts = detail::extract_mtime(st);
+ if (!detail::is_representable(ts)) {
+ set_or_throw(error_code(EOVERFLOW, generic_category()), ec,
+ "last_write_time", p);
+ return file_time_type::min();
+ }
+ return detail::convert_timespec(ts);
}
void __last_write_time(const path& p, file_time_type new_time,
@@ -554,9 +697,10 @@ void __last_write_time(const path& p, file_time_type new_time,
set_or_throw(m_ec, ec, "last_write_time", p);
return;
}
+ auto atime = detail::extract_atime(st);
struct ::timeval tbuf[2];
- tbuf[0].tv_sec = st.st_atime;
- tbuf[0].tv_usec = 0;
+ tbuf[0].tv_sec = atime.tv_sec;
+ tbuf[0].tv_usec = duration_cast<microseconds>(nanoseconds(atime.tv_nsec)).count();
const bool overflowed = !detail::set_times_checked<microseconds>(
&tbuf[1].tv_sec, &tbuf[1].tv_usec, new_time);
@@ -720,7 +864,7 @@ space_info __space(const path& p, std::error_code *ec) {
// Multiply with overflow checking.
auto do_mult = [&](std::uintmax_t& out, std::uintmax_t other) {
out = other * m_svfs.f_frsize;
- if (out / other != m_svfs.f_frsize || other == 0)
+ if (other == 0 || out / other != m_svfs.f_frsize)
out = static_cast<std::uintmax_t>(-1);
};
do_mult(si.capacity, m_svfs.f_blocks);
diff --git a/contrib/libc++/src/experimental/filesystem/path.cpp b/contrib/libc++/src/experimental/filesystem/path.cpp
index 38c4498..96b81f7 100644
--- a/contrib/libc++/src/experimental/filesystem/path.cpp
+++ b/contrib/libc++/src/experimental/filesystem/path.cpp
@@ -6,242 +6,279 @@
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
+#undef NDEBUG
#include "experimental/filesystem"
-#include "experimental/string_view"
+#include "string_view"
#include "utility"
-
-_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_FILESYSTEM
-
-_LIBCPP_CONSTEXPR path::value_type path::preferred_separator;
+#include "cassert"
namespace { namespace parser
{
+using namespace std;
+using namespace std::experimental::filesystem;
+
+using string_view_t = path::__string_view;
+using string_view_pair = pair<string_view_t, string_view_t>;
+using PosPtr = path::value_type const*;
+
+struct PathParser {
+ enum ParserState : unsigned char {
+ // Zero is a special sentinel value used by default constructed iterators.
+ PS_BeforeBegin = 1,
+ PS_InRootName,
+ PS_InRootDir,
+ PS_InFilenames,
+ PS_InTrailingSep,
+ PS_AtEnd
+ };
-using string_type = string_view;
-using value_type = path::value_type;
-
-using string_view_pair = pair<string_view, string_view>;
-
-// status reporting
-constexpr size_t npos = static_cast<size_t>(-1);
-
-inline bool good(size_t pos) { return pos != npos; }
-
-// lexical elements
-constexpr value_type preferred_separator = path::preferred_separator;
-constexpr value_type const * preferred_separator_str = "/";
-constexpr value_type const * dot = ".";
-
-// forward //
-bool is_separator(string_type const &, size_t);
-bool is_root_name(const string_type&, size_t);
-bool is_root_directory(string_type const &, size_t);
-bool is_trailing_separator(string_type const &, size_t);
-
-size_t start_of(string_type const &, size_t);
-size_t end_of(string_type const &, size_t);
-
-size_t root_name_start(const string_type& s);
-size_t root_name_end(const string_type&);
-
-size_t root_directory_start(string_type const &);
-size_t root_directory_end(string_type const &);
+ const string_view_t Path;
+ string_view_t RawEntry;
+ ParserState State;
-string_view_pair separate_filename(string_type const &);
-string_view extract_raw(string_type const &, size_t);
-string_view extract_preferred(string_type const &, size_t);
+private:
+ PathParser(string_view_t P, ParserState State) noexcept
+ : Path(P), State(State) {}
-inline bool is_separator(const string_type& s, size_t pos) {
- return (pos < s.size() && s[pos] == preferred_separator);
-}
+public:
+ PathParser(string_view_t P, string_view_t E, unsigned char S)
+ : Path(P), RawEntry(E), State(static_cast<ParserState>(S)) {
+ // S cannot be '0' or PS_BeforeBegin.
+ }
-inline bool is_root_name(const string_type& s, size_t pos) {
- return good(pos) && pos == 0 ? root_name_start(s) == pos : false;
-}
+ static PathParser CreateBegin(string_view_t P) noexcept {
+ PathParser PP(P, PS_BeforeBegin);
+ PP.increment();
+ return PP;
+ }
-inline bool is_root_directory(const string_type& s, size_t pos) {
- return good(pos) ? root_directory_start(s) == pos : false;
-}
+ static PathParser CreateEnd(string_view_t P) noexcept {
+ PathParser PP(P, PS_AtEnd);
+ return PP;
+ }
-inline bool is_trailing_separator(const string_type& s, size_t pos) {
- return (pos < s.size() && is_separator(s, pos) &&
- end_of(s, pos) == s.size()-1 &&
- !is_root_directory(s, pos) && !is_root_name(s, pos));
-}
+ PosPtr peek() const noexcept {
+ auto End = &Path.back() + 1;
+ auto TkEnd = getNextTokenStartPos();
+ return TkEnd == End ? nullptr : TkEnd;
+ }
-size_t start_of(const string_type& s, size_t pos) {
- if (pos >= s.size()) return npos;
- bool in_sep = (s[pos] == preferred_separator);
- while (pos - 1 < s.size() &&
- (s[pos-1] == preferred_separator) == in_sep)
- { --pos; }
- if (pos == 2 && !in_sep && s[0] == preferred_separator &&
- s[1] == preferred_separator)
- { return 0; }
- return pos;
-}
+ void increment() noexcept {
+ const PosPtr End = &Path.back() + 1;
+ const PosPtr Start = getNextTokenStartPos();
+ if (Start == End)
+ return makeState(PS_AtEnd);
+
+ switch (State) {
+ case PS_BeforeBegin: {
+ PosPtr TkEnd = consumeSeparator(Start, End);
+ // If we consumed exactly two separators we have a root name.
+ if (TkEnd && TkEnd == Start + 2) {
+ // FIXME Do we need to consume a name or is '//' a root name on its own?
+ // what about '//.', '//..', '//...'?
+ auto NameEnd = consumeName(TkEnd, End);
+ if (NameEnd)
+ TkEnd = NameEnd;
+ return makeState(PS_InRootName, Start, TkEnd);
+ }
+ else if (TkEnd)
+ return makeState(PS_InRootDir, Start, TkEnd);
+ else
+ return makeState(PS_InFilenames, Start, consumeName(Start, End));
+ }
-size_t end_of(const string_type& s, size_t pos) {
- if (pos >= s.size()) return npos;
- // special case for root name
- if (pos == 0 && is_root_name(s, pos)) return root_name_end(s);
- bool in_sep = (s[pos] == preferred_separator);
- while (pos + 1 < s.size() && (s[pos+1] == preferred_separator) == in_sep)
- { ++pos; }
- return pos;
-}
+ case PS_InRootName:
+ return makeState(PS_InRootDir, Start, consumeSeparator(Start, End));
+ case PS_InRootDir:
+ return makeState(PS_InFilenames, Start, consumeName(Start, End));
+
+ case PS_InFilenames: {
+ PosPtr SepEnd = consumeSeparator(Start, End);
+ if (SepEnd != End) {
+ PosPtr TkEnd = consumeName(SepEnd, End);
+ if (TkEnd)
+ return makeState(PS_InFilenames, SepEnd, TkEnd);
+ }
+ return makeState(PS_InTrailingSep, Start, SepEnd);
+ }
-inline size_t root_name_start(const string_type& s) {
- return good(root_name_end(s)) ? 0 : npos;
-}
+ case PS_InTrailingSep:
+ return makeState(PS_AtEnd);
-size_t root_name_end(const string_type& s) {
- if (s.size() < 2 || s[0] != preferred_separator
- || s[1] != preferred_separator) {
- return npos;
+ case PS_AtEnd:
+ _LIBCPP_UNREACHABLE();
}
- if (s.size() == 2) {
- return 1;
+ }
+
+ void decrement() noexcept {
+ const PosPtr REnd = &Path.front() - 1;
+ const PosPtr RStart = getCurrentTokenStartPos() - 1;
+ assert(RStart != REnd);
+
+ switch (State) {
+ case PS_AtEnd: {
+ // Try to consume a trailing separator or root directory first.
+ if (PosPtr SepEnd = consumeSeparator(RStart, REnd)) {
+ if (SepEnd == REnd)
+ return makeState((RStart == REnd + 2) ? PS_InRootName : PS_InRootDir,
+ Path.data(), RStart + 1);
+ // Check if we're seeing the root directory separator
+ auto PP = CreateBegin(Path);
+ bool InRootDir = PP.State == PS_InRootName &&
+ &PP.RawEntry.back() == SepEnd;
+ return makeState(InRootDir ? PS_InRootDir : PS_InTrailingSep,
+ SepEnd + 1, RStart + 1);
+ } else {
+ PosPtr TkStart = consumeName(RStart, REnd);
+ if (TkStart == REnd + 2 && consumeSeparator(TkStart, REnd) == REnd)
+ return makeState(PS_InRootName, Path.data(), RStart + 1);
+ else
+ return makeState(PS_InFilenames, TkStart + 1, RStart + 1);
+ }
}
- size_t index = 2; // current position
- if (s[index] == preferred_separator) {
- return npos;
+ case PS_InTrailingSep:
+ return makeState(PS_InFilenames, consumeName(RStart, REnd) + 1, RStart + 1);
+ case PS_InFilenames: {
+ PosPtr SepEnd = consumeSeparator(RStart, REnd);
+ if (SepEnd == REnd)
+ return makeState((RStart == REnd + 2) ? PS_InRootName : PS_InRootDir,
+ Path.data(), RStart + 1);
+ PosPtr TkEnd = consumeName(SepEnd, REnd);
+ if (TkEnd == REnd + 2 && consumeSeparator(TkEnd, REnd) == REnd)
+ return makeState(PS_InRootDir, SepEnd + 1, RStart + 1);
+ return makeState(PS_InFilenames, TkEnd + 1, SepEnd + 1);
}
- while (index + 1 < s.size() && s[index+1] != preferred_separator) {
- ++index;
+ case PS_InRootDir:
+ return makeState(PS_InRootName, Path.data(), RStart + 1);
+ case PS_InRootName:
+ case PS_BeforeBegin:
+ _LIBCPP_UNREACHABLE();
}
- return index;
-}
-
-size_t root_directory_start(const string_type& s) {
- size_t e = root_name_end(s);
- if (!good(e))
- return is_separator(s, 0) ? 0 : npos;
- return is_separator(s, e + 1) ? e + 1 : npos;
-}
-
-size_t root_directory_end(const string_type& s) {
- size_t st = root_directory_start(s);
- if (!good(st)) return npos;
- size_t index = st;
- while (index + 1 < s.size() && s[index + 1] == preferred_separator)
- { ++index; }
- return index;
-}
-
-string_view_pair separate_filename(string_type const & s) {
- if (s == "." || s == ".." || s.empty()) return string_view_pair{s, ""};
- auto pos = s.find_last_of('.');
- if (pos == string_type::npos) return string_view_pair{s, string_view{}};
- return string_view_pair{s.substr(0, pos), s.substr(pos)};
-}
-
-inline string_view extract_raw(const string_type& s, size_t pos) {
- size_t end_i = end_of(s, pos);
- if (!good(end_i)) return string_view{};
- return string_view(s).substr(pos, end_i - pos + 1);
-}
-
-string_view extract_preferred(const string_type& s, size_t pos) {
- string_view raw = extract_raw(s, pos);
- if (raw.empty())
- return raw;
- if (is_trailing_separator(s, pos))
- return string_view{dot};
- if (is_separator(s, pos) && !is_root_name(s, pos))
- return string_view(preferred_separator_str);
- return raw;
-}
-
-}} // namespace parser
-
-
-////////////////////////////////////////////////////////////////////////////////
-// path_view_iterator
-////////////////////////////////////////////////////////////////////////////////
-namespace {
-
-struct path_view_iterator {
- const string_view __s_;
- size_t __pos_;
+ }
- explicit path_view_iterator(string_view const& __s) : __s_(__s), __pos_(__s_.empty() ? parser::npos : 0) {}
- explicit path_view_iterator(string_view const& __s, size_t __p) : __s_(__s), __pos_(__p) {}
+ /// \brief Return a view with the "preferred representation" of the current
+ /// element. For example trailing separators are represented as a '.'
+ string_view_t operator*() const noexcept {
+ switch (State) {
+ case PS_BeforeBegin:
+ case PS_AtEnd:
+ return "";
+ case PS_InRootDir:
+ return "/";
+ case PS_InTrailingSep:
+ return ".";
+ case PS_InRootName:
+ case PS_InFilenames:
+ return RawEntry;
+ }
+ _LIBCPP_UNREACHABLE();
+ }
- string_view operator*() const {
- return parser::extract_preferred(__s_, __pos_);
+ explicit operator bool() const noexcept {
+ return State != PS_BeforeBegin && State != PS_AtEnd;
}
- path_view_iterator& operator++() {
+ PathParser& operator++() noexcept {
increment();
return *this;
}
- path_view_iterator& operator--() {
+ PathParser& operator--() noexcept {
decrement();
return *this;
}
- void increment() {
- if (__pos_ == parser::npos) return;
- while (! set_position(parser::end_of(__s_, __pos_)+1))
- ;
- return;
+private:
+ void makeState(ParserState NewState, PosPtr Start, PosPtr End) noexcept {
+ State = NewState;
+ RawEntry = string_view_t(Start, End - Start);
+ }
+ void makeState(ParserState NewState) noexcept {
+ State = NewState;
+ RawEntry = {};
}
- void decrement() {
- if (__pos_ == 0) {
- set_position(0);
- }
- else if (__pos_ == parser::npos) {
- auto const str_size = __s_.size();
- set_position(parser::start_of(
- __s_, str_size != 0 ? str_size - 1 : str_size));
- } else {
- while (!set_position(parser::start_of(__s_, __pos_-1)))
- ;
+ /// \brief Return a pointer to the first character after the currently
+ /// lexed element.
+ PosPtr getNextTokenStartPos() const noexcept {
+ switch (State) {
+ case PS_BeforeBegin:
+ return &Path.front();
+ case PS_InRootName:
+ case PS_InRootDir:
+ case PS_InFilenames:
+ return &RawEntry.back() + 1;
+ case PS_InTrailingSep:
+ case PS_AtEnd:
+ return &Path.back() + 1;
}
+ _LIBCPP_UNREACHABLE();
}
- bool set_position(size_t pos) {
- if (pos >= __s_.size()) {
- __pos_ = parser::npos;
- } else {
- __pos_ = pos;
+ /// \brief Return a pointer to the first character in the currently lexed
+ /// element.
+ PosPtr getCurrentTokenStartPos() const noexcept {
+ switch (State) {
+ case PS_BeforeBegin:
+ case PS_InRootName:
+ return &Path.front();
+ case PS_InRootDir:
+ case PS_InFilenames:
+ case PS_InTrailingSep:
+ return &RawEntry.front();
+ case PS_AtEnd:
+ return &Path.back() + 1;
}
- return valid_iterator_position();
+ _LIBCPP_UNREACHABLE();
}
- bool valid_iterator_position() const {
- if (__pos_ == parser::npos) return true; // end position is valid
- return (!parser::is_separator (__s_, __pos_) ||
- parser::is_root_directory (__s_, __pos_) ||
- parser::is_trailing_separator(__s_, __pos_) ||
- parser::is_root_name (__s_, __pos_));
+ PosPtr consumeSeparator(PosPtr P, PosPtr End) const noexcept {
+ if (P == End || *P != '/')
+ return nullptr;
+ const int Inc = P < End ? 1 : -1;
+ P += Inc;
+ while (P != End && *P == '/')
+ P += Inc;
+ return P;
}
- bool is_end() const { return __pos_ == parser::npos; }
-
- inline bool operator==(path_view_iterator const& __p) {
- return __pos_ == __p.__pos_;
+ PosPtr consumeName(PosPtr P, PosPtr End) const noexcept {
+ if (P == End || *P == '/')
+ return nullptr;
+ const int Inc = P < End ? 1 : -1;
+ P += Inc;
+ while (P != End && *P != '/')
+ P += Inc;
+ return P;
}
};
-path_view_iterator pbegin(path const& p) {
- return path_view_iterator(p.native());
+string_view_pair separate_filename(string_view_t const & s) {
+ if (s == "." || s == ".." || s.empty()) return string_view_pair{s, ""};
+ auto pos = s.find_last_of('.');
+ if (pos == string_view_t::npos) return string_view_pair{s, string_view{}};
+ return string_view_pair{s.substr(0, pos), s.substr(pos)};
}
-path_view_iterator pend(path const& p) {
- path_view_iterator __p(p.native());
- __p.__pos_ = parser::npos;
- return __p;
+string_view_t createView(PosPtr S, PosPtr E) noexcept {
+ return {S, static_cast<size_t>(E - S) + 1};
}
-} // end namespace
+}} // namespace parser
+
+_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_FILESYSTEM
+
+using parser::string_view_t;
+using parser::string_view_pair;
+using parser::PathParser;
+using parser::createView;
+
///////////////////////////////////////////////////////////////////////////////
// path definitions
///////////////////////////////////////////////////////////////////////////////
+constexpr path::value_type path::preferred_separator;
+
path & path::replace_extension(path const & replacement)
{
path p = extension();
@@ -260,131 +297,146 @@ path & path::replace_extension(path const & replacement)
///////////////////////////////////////////////////////////////////////////////
// path.decompose
-string_view path::__root_name() const
+string_view_t path::__root_name() const
{
- return parser::is_root_name(__pn_, 0)
- ? parser::extract_preferred(__pn_, 0)
- : string_view{};
+ auto PP = PathParser::CreateBegin(__pn_);
+ if (PP.State == PathParser::PS_InRootName)
+ return *PP;
+ return {};
}
-string_view path::__root_directory() const
+string_view_t path::__root_directory() const
{
- auto start_i = parser::root_directory_start(__pn_);
- if(!parser::good(start_i)) {
- return {};
- }
- return parser::extract_preferred(__pn_, start_i);
+ auto PP = PathParser::CreateBegin(__pn_);
+ if (PP.State == PathParser::PS_InRootName)
+ ++PP;
+ if (PP.State == PathParser::PS_InRootDir)
+ return *PP;
+ return {};
}
-string_view path::__relative_path() const
+string_view_t path::__root_path_raw() const
{
- if (empty()) {
- return {__pn_};
- }
- auto end_i = parser::root_directory_end(__pn_);
- if (not parser::good(end_i)) {
- end_i = parser::root_name_end(__pn_);
+ auto PP = PathParser::CreateBegin(__pn_);
+ if (PP.State == PathParser::PS_InRootName) {
+ auto NextCh = PP.peek();
+ if (NextCh && *NextCh == '/') {
+ ++PP;
+ assert(PP.State == PathParser::PS_InRootDir);
+ return createView(__pn_.data(), &PP.RawEntry.back());
+ }
+ return PP.RawEntry;
}
- if (not parser::good(end_i)) {
- return {__pn_};
- }
- return string_view(__pn_).substr(end_i+1);
+ if (PP.State == PathParser::PS_InRootDir)
+ return *PP;
+ return {};
}
-string_view path::__parent_path() const
+string_view_t path::__relative_path() const
{
- if (empty() || pbegin(*this) == --pend(*this)) {
- return {};
- }
- auto end_it = --(--pend(*this));
- auto end_i = parser::end_of(__pn_, end_it.__pos_);
- return string_view(__pn_).substr(0, end_i+1);
+ auto PP = PathParser::CreateBegin(__pn_);
+ while (PP.State <= PathParser::PS_InRootDir)
+ ++PP;
+ if (PP.State == PathParser::PS_AtEnd)
+ return {};
+ return createView(PP.RawEntry.data(), &__pn_.back());
}
-string_view path::__filename() const
+string_view_t path::__parent_path() const
{
- return empty() ? string_view{} : *--pend(*this);
+ if (empty())
+ return {};
+ auto PP = PathParser::CreateEnd(__pn_);
+ --PP;
+ if (PP.RawEntry.data() == __pn_.data())
+ return {};
+ --PP;
+ return createView(__pn_.data(), &PP.RawEntry.back());
}
-string_view path::__stem() const
+string_view_t path::__filename() const
+{
+ if (empty()) return {};
+ return *(--PathParser::CreateEnd(__pn_));
+}
+
+string_view_t path::__stem() const
{
return parser::separate_filename(__filename()).first;
}
-string_view path::__extension() const
+string_view_t path::__extension() const
{
return parser::separate_filename(__filename()).second;
}
////////////////////////////////////////////////////////////////////////////
// path.comparisons
-int path::__compare(const value_type* __s) const {
- path_view_iterator thisIter(this->native());
- path_view_iterator sIter(__s);
- while (!thisIter.is_end() && !sIter.is_end()) {
- int res = (*thisIter).compare(*sIter);
+int path::__compare(string_view_t __s) const {
+ auto PP = PathParser::CreateBegin(__pn_);
+ auto PP2 = PathParser::CreateBegin(__s);
+ while (PP && PP2) {
+ int res = (*PP).compare(*PP2);
if (res != 0) return res;
- ++thisIter; ++sIter;
+ ++PP; ++PP2;
}
- if (thisIter.is_end() && sIter.is_end())
+ if (PP.State == PP2.State && PP.State == PathParser::PS_AtEnd)
return 0;
- if (thisIter.is_end())
+ if (PP.State == PathParser::PS_AtEnd)
return -1;
return 1;
}
////////////////////////////////////////////////////////////////////////////
// path.nonmembers
-size_t hash_value(const path& __p) _NOEXCEPT {
- path_view_iterator thisIter(__p.native());
- struct HashPairT {
- size_t first;
- size_t second;
- };
- HashPairT hp = {0, 0};
+size_t hash_value(const path& __p) noexcept {
+ auto PP = PathParser::CreateBegin(__p.native());
+ size_t hash_value = 0;
std::hash<string_view> hasher;
- std::__scalar_hash<decltype(hp)> pair_hasher;
- while (!thisIter.is_end()) {
- hp.second = hasher(*thisIter);
- hp.first = pair_hasher(hp);
- ++thisIter;
+ while (PP) {
+ hash_value = __hash_combine(hash_value, hasher(*PP));
+ ++PP;
}
- return hp.first;
+ return hash_value;
}
////////////////////////////////////////////////////////////////////////////
// path.itr
path::iterator path::begin() const
{
- path_view_iterator pit = pbegin(*this);
+ auto PP = PathParser::CreateBegin(__pn_);
iterator it;
it.__path_ptr_ = this;
- it.__pos_ = pit.__pos_;
- it.__elem_.__assign_view(*pit);
+ it.__state_ = PP.State;
+ it.__entry_ = PP.RawEntry;
+ it.__stashed_elem_.__assign_view(*PP);
return it;
}
path::iterator path::end() const
{
iterator it{};
+ it.__state_ = PathParser::PS_AtEnd;
it.__path_ptr_ = this;
- it.__pos_ = parser::npos;
return it;
}
path::iterator& path::iterator::__increment() {
- path_view_iterator it(__path_ptr_->native(), __pos_);
- it.increment();
- __pos_ = it.__pos_;
- __elem_.__assign_view(*it);
+ static_assert(__at_end == PathParser::PS_AtEnd, "");
+ PathParser PP(__path_ptr_->native(), __entry_, __state_);
+ ++PP;
+ __state_ = PP.State;
+ __entry_ = PP.RawEntry;
+ __stashed_elem_.__assign_view(*PP);
return *this;
}
path::iterator& path::iterator::__decrement() {
- path_view_iterator it(__path_ptr_->native(), __pos_);
- it.decrement();
- __pos_ = it.__pos_;
- __elem_.__assign_view(*it);
+ PathParser PP(__path_ptr_->native(), __entry_, __state_);
+ --PP;
+ __state_ = PP.State;
+ __entry_ = PP.RawEntry;
+ __stashed_elem_.__assign_view(*PP);
return *this;
}
diff --git a/contrib/libc++/src/experimental/memory_resource.cpp b/contrib/libc++/src/experimental/memory_resource.cpp
index c01eb08..c4dc1ca 100644
--- a/contrib/libc++/src/experimental/memory_resource.cpp
+++ b/contrib/libc++/src/experimental/memory_resource.cpp
@@ -23,7 +23,7 @@ _LIBCPP_BEGIN_NAMESPACE_LFTS_PMR
// new_delete_resource()
-class _LIBCPP_TYPE_VIS_ONLY __new_delete_memory_resource_imp
+class _LIBCPP_TYPE_VIS __new_delete_memory_resource_imp
: public memory_resource
{
public:
@@ -34,7 +34,7 @@ protected:
{ return __allocate(__size); }
virtual void do_deallocate(void * __p, size_t, size_t)
- { __deallocate(__p); }
+ { _VSTD::__libcpp_deallocate(__p); }
virtual bool do_is_equal(memory_resource const & __other) const _NOEXCEPT
{ return &__other == this; }
@@ -42,7 +42,7 @@ protected:
// null_memory_resource()
-class _LIBCPP_TYPE_VIS_ONLY __null_memory_resource_imp
+class _LIBCPP_TYPE_VIS __null_memory_resource_imp
: public memory_resource
{
public:
@@ -50,11 +50,7 @@ public:
protected:
virtual void* do_allocate(size_t, size_t) {
-#ifndef _LIBCPP_NO_EXCEPTIONS
- throw std::bad_alloc();
-#else
- abort();
-#endif
+ __throw_bad_alloc();
}
virtual void do_deallocate(void *, size_t, size_t) {}
virtual bool do_is_equal(memory_resource const & __other) const _NOEXCEPT
@@ -74,7 +70,10 @@ union ResourceInitHelper {
};
// When compiled in C++14 this initialization should be a constant expression.
// Only in C++11 is "init_priority" needed to ensure initialization order.
-ResourceInitHelper res_init __attribute__((init_priority (101)));
+#if _LIBCPP_STD_VER > 11
+_LIBCPP_SAFE_STATIC
+#endif
+ResourceInitHelper res_init __attribute__((init_priority (101)));
} // end namespace
@@ -93,7 +92,7 @@ static memory_resource *
__default_memory_resource(bool set = false, memory_resource * new_res = nullptr) _NOEXCEPT
{
#ifndef _LIBCPP_HAS_NO_ATOMIC_HEADER
- static atomic<memory_resource*> __res =
+ _LIBCPP_SAFE_STATIC static atomic<memory_resource*> __res =
ATOMIC_VAR_INIT(&res_init.resources.new_delete_res);
if (set) {
new_res = new_res ? new_res : new_delete_resource();
@@ -106,7 +105,7 @@ __default_memory_resource(bool set = false, memory_resource * new_res = nullptr)
&__res, memory_order::memory_order_acquire);
}
#elif !defined(_LIBCPP_HAS_NO_THREADS)
- static memory_resource * res = &res_init.resources.new_delete_res;
+ _LIBCPP_SAFE_STATIC static memory_resource * res = &res_init.resources.new_delete_res;
static mutex res_lock;
if (set) {
new_res = new_res ? new_res : new_delete_resource();
@@ -119,7 +118,7 @@ __default_memory_resource(bool set = false, memory_resource * new_res = nullptr)
return res;
}
#else
- static memory_resource* res = &res_init.resources.new_delete_res;
+ _LIBCPP_SAFE_STATIC static memory_resource* res = &res_init.resources.new_delete_res;
if (set) {
new_res = new_res ? new_res : new_delete_resource();
memory_resource * old_res = res;
@@ -141,4 +140,4 @@ memory_resource * set_default_resource(memory_resource * __new_res) _NOEXCEPT
return __default_memory_resource(true, __new_res);
}
-_LIBCPP_END_NAMESPACE_LFTS_PMR \ No newline at end of file
+_LIBCPP_END_NAMESPACE_LFTS_PMR
diff --git a/contrib/libc++/src/include/atomic_support.h b/contrib/libc++/src/include/atomic_support.h
index 8b719c5..af0f5f5 100644
--- a/contrib/libc++/src/include/atomic_support.h
+++ b/contrib/libc++/src/include/atomic_support.h
@@ -45,7 +45,7 @@ namespace {
enum __libcpp_atomic_order {
_AO_Relaxed = __ATOMIC_RELAXED,
_AO_Consume = __ATOMIC_CONSUME,
- _AO_Aquire = __ATOMIC_ACQUIRE,
+ _AO_Acquire = __ATOMIC_ACQUIRE,
_AO_Release = __ATOMIC_RELEASE,
_AO_Acq_Rel = __ATOMIC_ACQ_REL,
_AO_Seq = __ATOMIC_SEQ_CST
diff --git a/contrib/libc++/src/include/config_elast.h b/contrib/libc++/src/include/config_elast.h
index 9d6a76b..8328978 100644
--- a/contrib/libc++/src/include/config_elast.h
+++ b/contrib/libc++/src/include/config_elast.h
@@ -10,7 +10,9 @@
#ifndef _LIBCPP_CONFIG_ELAST
#define _LIBCPP_CONFIG_ELAST
-#if defined(_WIN32)
+#include <__config>
+
+#if defined(_LIBCPP_MSVCRT)
#include <stdlib.h>
#else
#include <errno.h>
@@ -20,14 +22,16 @@
#define _LIBCPP_ELAST ELAST
#elif defined(_NEWLIB_VERSION)
#define _LIBCPP_ELAST __ELASTERROR
+#elif defined(__Fuchsia__)
+// No _LIBCPP_ELAST needed on Fuchsia
#elif defined(__linux__)
#define _LIBCPP_ELAST 4095
#elif defined(__APPLE__)
// No _LIBCPP_ELAST needed on Apple
#elif defined(__sun__)
#define _LIBCPP_ELAST ESTALE
-#elif defined(_WIN32)
-#define _LIBCPP_ELAST _sys_nerr
+#elif defined(_LIBCPP_MSVCRT)
+#define _LIBCPP_ELAST (_sys_nerr - 1)
#else
// Warn here so that the person doing the libcxx port has an easier time:
#warning ELAST for this platform not yet implemented
diff --git a/contrib/libc++/src/ios.cpp b/contrib/libc++/src/ios.cpp
index 23e3ee0..7c76ca2 100644
--- a/contrib/libc++/src/ios.cpp
+++ b/contrib/libc++/src/ios.cpp
@@ -25,19 +25,19 @@
_LIBCPP_BEGIN_NAMESPACE_STD
-template class basic_ios<char>;
-template class basic_ios<wchar_t>;
+template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_ios<char>;
+template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_ios<wchar_t>;
-template class basic_streambuf<char>;
-template class basic_streambuf<wchar_t>;
+template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_streambuf<char>;
+template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_streambuf<wchar_t>;
-template class basic_istream<char>;
-template class basic_istream<wchar_t>;
+template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_istream<char>;
+template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_istream<wchar_t>;
-template class basic_ostream<char>;
-template class basic_ostream<wchar_t>;
+template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_ostream<char>;
+template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_ostream<wchar_t>;
-template class basic_iostream<char>;
+template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_iostream<char>;
class _LIBCPP_HIDDEN __iostream_category
: public __do_message
diff --git a/contrib/libc++/src/iostream.cpp b/contrib/libc++/src/iostream.cpp
index e073aec..a972be9 100644
--- a/contrib/libc++/src/iostream.cpp
+++ b/contrib/libc++/src/iostream.cpp
@@ -14,32 +14,64 @@
_LIBCPP_BEGIN_NAMESPACE_STD
#ifndef _LIBCPP_HAS_NO_STDIN
-_ALIGNAS_TYPE (istream) _LIBCPP_FUNC_VIS char cin [sizeof(istream)];
-_ALIGNAS_TYPE (__stdinbuf<char> ) static char __cin [sizeof(__stdinbuf <char>)];
+_ALIGNAS_TYPE (istream) _LIBCPP_FUNC_VIS char cin[sizeof(istream)]
+#if defined(_MSC_VER) && defined(__clang__)
+__asm__("?cin@__1@std@@3V?$basic_istream@DU?$char_traits@D@__1@std@@@12@A")
+#endif
+;
+_ALIGNAS_TYPE (__stdinbuf<char> ) static char __cin[sizeof(__stdinbuf <char>)];
static mbstate_t mb_cin;
-_ALIGNAS_TYPE (wistream) _LIBCPP_FUNC_VIS char wcin [sizeof(wistream)];
-_ALIGNAS_TYPE (__stdinbuf<wchar_t> ) static char __wcin [sizeof(__stdinbuf <wchar_t>)];
+_ALIGNAS_TYPE (wistream) _LIBCPP_FUNC_VIS char wcin[sizeof(wistream)]
+#if defined(_MSC_VER) && defined(__clang__)
+__asm__("?wcin@__1@std@@3V?$basic_istream@_WU?$char_traits@_W@__1@std@@@12@A")
+#endif
+;
+_ALIGNAS_TYPE (__stdinbuf<wchar_t> ) static char __wcin[sizeof(__stdinbuf <wchar_t>)];
static mbstate_t mb_wcin;
#endif
#ifndef _LIBCPP_HAS_NO_STDOUT
-_ALIGNAS_TYPE (ostream) _LIBCPP_FUNC_VIS char cout[sizeof(ostream)];
+_ALIGNAS_TYPE (ostream) _LIBCPP_FUNC_VIS char cout[sizeof(ostream)]
+#if defined(_MSC_VER) && defined(__clang__)
+__asm__("?cout@__1@std@@3V?$basic_ostream@DU?$char_traits@D@__1@std@@@12@A")
+#endif
+;
_ALIGNAS_TYPE (__stdoutbuf<char>) static char __cout[sizeof(__stdoutbuf<char>)];
static mbstate_t mb_cout;
-_ALIGNAS_TYPE (wostream) _LIBCPP_FUNC_VIS char wcout[sizeof(wostream)];
+_ALIGNAS_TYPE (wostream) _LIBCPP_FUNC_VIS char wcout[sizeof(wostream)]
+#if defined(_MSC_VER) && defined(__clang__)
+__asm__("?wcout@__1@std@@3V?$basic_ostream@_WU?$char_traits@_W@__1@std@@@12@A")
+#endif
+;
_ALIGNAS_TYPE (__stdoutbuf<wchar_t>) static char __wcout[sizeof(__stdoutbuf<wchar_t>)];
static mbstate_t mb_wcout;
#endif
-_ALIGNAS_TYPE (ostream) _LIBCPP_FUNC_VIS char cerr[sizeof(ostream)];
+_ALIGNAS_TYPE (ostream) _LIBCPP_FUNC_VIS char cerr[sizeof(ostream)]
+#if defined(_MSC_VER) && defined(__clang__)
+__asm__("?cerr@__1@std@@3V?$basic_ostream@DU?$char_traits@D@__1@std@@@12@A")
+#endif
+;
_ALIGNAS_TYPE (__stdoutbuf<char>) static char __cerr[sizeof(__stdoutbuf<char>)];
static mbstate_t mb_cerr;
-_ALIGNAS_TYPE (wostream) _LIBCPP_FUNC_VIS char wcerr[sizeof(wostream)];
+_ALIGNAS_TYPE (wostream) _LIBCPP_FUNC_VIS char wcerr[sizeof(wostream)]
+#if defined(_MSC_VER) && defined(__clang__)
+__asm__("?wcerr@__1@std@@3V?$basic_ostream@_WU?$char_traits@_W@__1@std@@@12@A")
+#endif
+;
_ALIGNAS_TYPE (__stdoutbuf<wchar_t>) static char __wcerr[sizeof(__stdoutbuf<wchar_t>)];
static mbstate_t mb_wcerr;
-_ALIGNAS_TYPE (ostream) _LIBCPP_FUNC_VIS char clog[sizeof(ostream)];
-_ALIGNAS_TYPE (wostream) _LIBCPP_FUNC_VIS char wclog[sizeof(wostream)];
+_ALIGNAS_TYPE (ostream) _LIBCPP_FUNC_VIS char clog[sizeof(ostream)]
+#if defined(_MSC_VER) && defined(__clang__)
+__asm__("?clog@__1@std@@3V?$basic_ostream@DU?$char_traits@D@__1@std@@@12@A")
+#endif
+;
+_ALIGNAS_TYPE (wostream) _LIBCPP_FUNC_VIS char wclog[sizeof(wostream)]
+#if defined(_MSC_VER) && defined(__clang__)
+__asm__("?wclog@__1@std@@3V?$basic_ostream@_WU?$char_traits@_W@__1@std@@@12@A")
+#endif
+;
ios_base::Init __start_std_streams;
diff --git a/contrib/libc++/src/locale.cpp b/contrib/libc++/src/locale.cpp
index da2fd11..338ffde 100644
--- a/contrib/libc++/src/locale.cpp
+++ b/contrib/libc++/src/locale.cpp
@@ -24,11 +24,14 @@
#endif
#include "clocale"
#include "cstring"
+#if defined(_LIBCPP_MSVCRT)
+#define _CTYPE_DISABLE_MACROS
+#endif
#include "cwctype"
#include "__sso_allocator"
#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
#include "support/win32/locale_win32.h"
-#elif !defined(__ANDROID__)
+#elif !defined(__BIONIC__)
#include <langinfo.h>
#endif
#include <stdlib.h>
@@ -107,6 +110,16 @@ countof(const T * const begin, const T * const end)
return static_cast<size_t>(end - begin);
}
+_LIBCPP_NORETURN static void __throw_runtime_error(const string &msg)
+{
+#ifndef _LIBCPP_NO_EXCEPTIONS
+ throw runtime_error(msg);
+#else
+ (void)msg;
+ _VSTD::abort();
+#endif
+}
+
}
#if defined(_AIX)
@@ -127,7 +140,7 @@ class _LIBCPP_HIDDEN locale::__imp
: public facet
{
enum {N = 28};
-#if defined(_LIBCPP_MSVC)
+#if defined(_LIBCPP_COMPILER_MSVC)
// FIXME: MSVC doesn't support aligned parameters by value.
// I can't get the __sso_allocator to work here
// for MSVC I think for this reason.
@@ -646,22 +659,18 @@ collate_byname<char>::collate_byname(const char* n, size_t refs)
: collate<char>(refs),
__l(newlocale(LC_ALL_MASK, n, 0))
{
-#ifndef _LIBCPP_NO_EXCEPTIONS
if (__l == 0)
- throw runtime_error("collate_byname<char>::collate_byname"
+ __throw_runtime_error("collate_byname<char>::collate_byname"
" failed to construct for " + string(n));
-#endif // _LIBCPP_NO_EXCEPTIONS
}
collate_byname<char>::collate_byname(const string& name, size_t refs)
: collate<char>(refs),
__l(newlocale(LC_ALL_MASK, name.c_str(), 0))
{
-#ifndef _LIBCPP_NO_EXCEPTIONS
if (__l == 0)
- throw runtime_error("collate_byname<char>::collate_byname"
+ __throw_runtime_error("collate_byname<char>::collate_byname"
" failed to construct for " + name);
-#endif // _LIBCPP_NO_EXCEPTIONS
}
collate_byname<char>::~collate_byname()
@@ -698,22 +707,18 @@ collate_byname<wchar_t>::collate_byname(const char* n, size_t refs)
: collate<wchar_t>(refs),
__l(newlocale(LC_ALL_MASK, n, 0))
{
-#ifndef _LIBCPP_NO_EXCEPTIONS
if (__l == 0)
- throw runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
+ __throw_runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
" failed to construct for " + string(n));
-#endif // _LIBCPP_NO_EXCEPTIONS
}
collate_byname<wchar_t>::collate_byname(const string& name, size_t refs)
: collate<wchar_t>(refs),
__l(newlocale(LC_ALL_MASK, name.c_str(), 0))
{
-#ifndef _LIBCPP_NO_EXCEPTIONS
if (__l == 0)
- throw runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
+ __throw_runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
" failed to construct for " + name);
-#endif // _LIBCPP_NO_EXCEPTIONS
}
collate_byname<wchar_t>::~collate_byname()
@@ -1106,9 +1111,13 @@ ctype<char>::classic_table() _NOEXCEPT
#elif __sun__
return __ctype_mask;
#elif defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
+#if _VC_CRT_MAJOR_VERSION < 14
+ // This is assumed to be safe, which is a nonsense assumption because we're
+ // going to end up dereferencing it later...
return _ctype+1; // internal ctype mask table defined in msvcrt.dll
-// This is assumed to be safe, which is a nonsense assumption because we're
-// going to end up dereferencing it later...
+#else
+ return __pctype_func();
+#endif
#elif defined(__EMSCRIPTEN__)
return *__ctype_b_loc();
#elif defined(_NEWLIB_VERSION)
@@ -1172,22 +1181,18 @@ ctype_byname<char>::ctype_byname(const char* name, size_t refs)
: ctype<char>(0, false, refs),
__l(newlocale(LC_ALL_MASK, name, 0))
{
-#ifndef _LIBCPP_NO_EXCEPTIONS
if (__l == 0)
- throw runtime_error("ctype_byname<char>::ctype_byname"
+ __throw_runtime_error("ctype_byname<char>::ctype_byname"
" failed to construct for " + string(name));
-#endif // _LIBCPP_NO_EXCEPTIONS
}
ctype_byname<char>::ctype_byname(const string& name, size_t refs)
: ctype<char>(0, false, refs),
__l(newlocale(LC_ALL_MASK, name.c_str(), 0))
{
-#ifndef _LIBCPP_NO_EXCEPTIONS
if (__l == 0)
- throw runtime_error("ctype_byname<char>::ctype_byname"
+ __throw_runtime_error("ctype_byname<char>::ctype_byname"
" failed to construct for " + name);
-#endif // _LIBCPP_NO_EXCEPTIONS
}
ctype_byname<char>::~ctype_byname()
@@ -1229,22 +1234,18 @@ ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs)
: ctype<wchar_t>(refs),
__l(newlocale(LC_ALL_MASK, name, 0))
{
-#ifndef _LIBCPP_NO_EXCEPTIONS
if (__l == 0)
- throw runtime_error("ctype_byname<wchar_t>::ctype_byname"
+ __throw_runtime_error("ctype_byname<wchar_t>::ctype_byname"
" failed to construct for " + string(name));
-#endif // _LIBCPP_NO_EXCEPTIONS
}
ctype_byname<wchar_t>::ctype_byname(const string& name, size_t refs)
: ctype<wchar_t>(refs),
__l(newlocale(LC_ALL_MASK, name.c_str(), 0))
{
-#ifndef _LIBCPP_NO_EXCEPTIONS
if (__l == 0)
- throw runtime_error("ctype_byname<wchar_t>::ctype_byname"
+ __throw_runtime_error("ctype_byname<wchar_t>::ctype_byname"
" failed to construct for " + name);
-#endif // _LIBCPP_NO_EXCEPTIONS
}
ctype_byname<wchar_t>::~ctype_byname()
@@ -1504,11 +1505,9 @@ codecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs)
: locale::facet(refs),
__l(newlocale(LC_ALL_MASK, nm, 0))
{
-#ifndef _LIBCPP_NO_EXCEPTIONS
if (__l == 0)
- throw runtime_error("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname"
+ __throw_runtime_error("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname"
" failed to construct for " + string(nm));
-#endif // _LIBCPP_NO_EXCEPTIONS
}
codecvt<wchar_t, char, mbstate_t>::~codecvt()
@@ -3255,7 +3254,7 @@ __codecvt_utf8<wchar_t>::do_out(state_type&,
const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
{
-#if _WIN32
+#if defined(_LIBCPP_SHORT_WCHAR)
const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
const uint16_t* _frm_nxt = _frm;
@@ -3267,7 +3266,7 @@ __codecvt_utf8<wchar_t>::do_out(state_type&,
uint8_t* _to = reinterpret_cast<uint8_t*>(to);
uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
uint8_t* _to_nxt = _to;
-#if _WIN32
+#if defined(_LIBCPP_SHORT_WCHAR)
result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
_Maxcode_, _Mode_);
#else
@@ -3287,7 +3286,7 @@ __codecvt_utf8<wchar_t>::do_in(state_type&,
const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
const uint8_t* _frm_nxt = _frm;
-#if _WIN32
+#if defined(_LIBCPP_SHORT_WCHAR)
uint16_t* _to = reinterpret_cast<uint16_t*>(to);
uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
uint16_t* _to_nxt = _to;
@@ -4191,6 +4190,54 @@ __widen_from_utf8<32>::~__widen_from_utf8()
{
}
+
+static bool checked_string_to_wchar_convert(wchar_t& dest,
+ const char* ptr,
+ __locale_struct* loc) {
+ if (*ptr == '\0')
+ return false;
+ mbstate_t mb = {};
+ wchar_t out;
+ size_t ret = __libcpp_mbrtowc_l(&out, ptr, strlen(ptr), &mb, loc);
+ if (ret == static_cast<size_t>(-1) || ret == static_cast<size_t>(-2)) {
+ return false;
+ }
+ dest = out;
+ return true;
+}
+
+static bool checked_string_to_char_convert(char& dest,
+ const char* ptr,
+ __locale_struct* __loc) {
+ if (*ptr == '\0')
+ return false;
+ if (!ptr[1]) {
+ dest = *ptr;
+ return true;
+ }
+ // First convert the MBS into a wide char then attempt to narrow it using
+ // wctob_l.
+ wchar_t wout;
+ if (!checked_string_to_wchar_convert(wout, ptr, __loc))
+ return false;
+ int res;
+ if ((res = __libcpp_wctob_l(wout, __loc)) != char_traits<char>::eof()) {
+ dest = res;
+ return true;
+ }
+ // FIXME: Work around specific multibyte sequences that we can reasonable
+ // translate into a different single byte.
+ switch (wout) {
+ case L'\u00A0': // non-breaking space
+ dest = ' ';
+ return true;
+ default:
+ return false;
+ }
+ _LIBCPP_UNREACHABLE();
+}
+
+
// numpunct<char> && numpunct<wchar_t>
locale::id numpunct< char >::id;
@@ -4257,16 +4304,15 @@ numpunct_byname<char>::__init(const char* nm)
if (strcmp(nm, "C") != 0)
{
__locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
-#ifndef _LIBCPP_NO_EXCEPTIONS
if (loc == nullptr)
- throw runtime_error("numpunct_byname<char>::numpunct_byname"
+ __throw_runtime_error("numpunct_byname<char>::numpunct_byname"
" failed to construct for " + string(nm));
-#endif // _LIBCPP_NO_EXCEPTIONS
+
lconv* lc = __libcpp_localeconv_l(loc.get());
- if (*lc->decimal_point)
- __decimal_point_ = *lc->decimal_point;
- if (*lc->thousands_sep)
- __thousands_sep_ = *lc->thousands_sep;
+ checked_string_to_char_convert(__decimal_point_, lc->decimal_point,
+ loc.get());
+ checked_string_to_char_convert(__thousands_sep_, lc->thousands_sep,
+ loc.get());
__grouping_ = lc->grouping;
// localization for truename and falsename is not available
}
@@ -4296,18 +4342,17 @@ numpunct_byname<wchar_t>::__init(const char* nm)
if (strcmp(nm, "C") != 0)
{
__locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
-#ifndef _LIBCPP_NO_EXCEPTIONS
if (loc == nullptr)
- throw runtime_error("numpunct_byname<char>::numpunct_byname"
+ __throw_runtime_error("numpunct_byname<wchar_t>::numpunct_byname"
" failed to construct for " + string(nm));
-#endif // _LIBCPP_NO_EXCEPTIONS
+
lconv* lc = __libcpp_localeconv_l(loc.get());
- if (*lc->decimal_point)
- __decimal_point_ = *lc->decimal_point;
- if (*lc->thousands_sep)
- __thousands_sep_ = *lc->thousands_sep;
+ checked_string_to_wchar_convert(__decimal_point_, lc->decimal_point,
+ loc.get());
+ checked_string_to_wchar_convert(__thousands_sep_, lc->thousands_sep,
+ loc.get());
__grouping_ = lc->grouping;
- // locallization for truename and falsename is not available
+ // localization for truename and falsename is not available
}
}
@@ -4703,21 +4748,17 @@ __time_get_c_storage<wchar_t>::__r() const
__time_get::__time_get(const char* nm)
: __loc_(newlocale(LC_ALL_MASK, nm, 0))
{
-#ifndef _LIBCPP_NO_EXCEPTIONS
if (__loc_ == 0)
- throw runtime_error("time_get_byname"
+ __throw_runtime_error("time_get_byname"
" failed to construct for " + string(nm));
-#endif // _LIBCPP_NO_EXCEPTIONS
}
__time_get::__time_get(const string& nm)
: __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
{
-#ifndef _LIBCPP_NO_EXCEPTIONS
if (__loc_ == 0)
- throw runtime_error("time_get_byname"
+ __throw_runtime_error("time_get_byname"
" failed to construct for " + nm);
-#endif // _LIBCPP_NO_EXCEPTIONS
}
__time_get::~__time_get()
@@ -5363,21 +5404,17 @@ __time_get_storage<wchar_t>::__do_date_order() const
__time_put::__time_put(const char* nm)
: __loc_(newlocale(LC_ALL_MASK, nm, 0))
{
-#ifndef _LIBCPP_NO_EXCEPTIONS
if (__loc_ == 0)
- throw runtime_error("time_put_byname"
+ __throw_runtime_error("time_put_byname"
" failed to construct for " + string(nm));
-#endif // _LIBCPP_NO_EXCEPTIONS
}
__time_put::__time_put(const string& nm)
: __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
{
-#ifndef _LIBCPP_NO_EXCEPTIONS
if (__loc_ == 0)
- throw runtime_error("time_put_byname"
+ __throw_runtime_error("time_put_byname"
" failed to construct for " + nm);
-#endif // _LIBCPP_NO_EXCEPTIONS
}
__time_put::~__time_put()
@@ -5792,20 +5829,20 @@ moneypunct_byname<char, false>::init(const char* nm)
{
typedef moneypunct<char, false> base;
__locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
-#ifndef _LIBCPP_NO_EXCEPTIONS
if (loc == nullptr)
- throw runtime_error("moneypunct_byname"
+ __throw_runtime_error("moneypunct_byname"
" failed to construct for " + string(nm));
-#endif // _LIBCPP_NO_EXCEPTIONS
+
lconv* lc = __libcpp_localeconv_l(loc.get());
- if (*lc->mon_decimal_point)
- __decimal_point_ = *lc->mon_decimal_point;
- else
- __decimal_point_ = base::do_decimal_point();
- if (*lc->mon_thousands_sep)
- __thousands_sep_ = *lc->mon_thousands_sep;
- else
- __thousands_sep_ = base::do_thousands_sep();
+ if (!checked_string_to_char_convert(__decimal_point_,
+ lc->mon_decimal_point,
+ loc.get()))
+ __decimal_point_ = base::do_decimal_point();
+ if (!checked_string_to_char_convert(__thousands_sep_,
+ lc->mon_thousands_sep,
+ loc.get()))
+ __thousands_sep_ = base::do_thousands_sep();
+
__grouping_ = lc->mon_grouping;
__curr_symbol_ = lc->currency_symbol;
if (lc->frac_digits != CHAR_MAX)
@@ -5836,20 +5873,19 @@ moneypunct_byname<char, true>::init(const char* nm)
{
typedef moneypunct<char, true> base;
__locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
-#ifndef _LIBCPP_NO_EXCEPTIONS
if (loc == nullptr)
- throw runtime_error("moneypunct_byname"
+ __throw_runtime_error("moneypunct_byname"
" failed to construct for " + string(nm));
-#endif // _LIBCPP_NO_EXCEPTIONS
+
lconv* lc = __libcpp_localeconv_l(loc.get());
- if (*lc->mon_decimal_point)
- __decimal_point_ = *lc->mon_decimal_point;
- else
- __decimal_point_ = base::do_decimal_point();
- if (*lc->mon_thousands_sep)
- __thousands_sep_ = *lc->mon_thousands_sep;
- else
- __thousands_sep_ = base::do_thousands_sep();
+ if (!checked_string_to_char_convert(__decimal_point_,
+ lc->mon_decimal_point,
+ loc.get()))
+ __decimal_point_ = base::do_decimal_point();
+ if (!checked_string_to_char_convert(__thousands_sep_,
+ lc->mon_thousands_sep,
+ loc.get()))
+ __thousands_sep_ = base::do_thousands_sep();
__grouping_ = lc->mon_grouping;
__curr_symbol_ = lc->int_curr_symbol;
if (lc->int_frac_digits != CHAR_MAX)
@@ -5897,20 +5933,18 @@ moneypunct_byname<wchar_t, false>::init(const char* nm)
{
typedef moneypunct<wchar_t, false> base;
__locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
-#ifndef _LIBCPP_NO_EXCEPTIONS
if (loc == nullptr)
- throw runtime_error("moneypunct_byname"
+ __throw_runtime_error("moneypunct_byname"
" failed to construct for " + string(nm));
-#endif // _LIBCPP_NO_EXCEPTIONS
lconv* lc = __libcpp_localeconv_l(loc.get());
- if (*lc->mon_decimal_point)
- __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
- else
- __decimal_point_ = base::do_decimal_point();
- if (*lc->mon_thousands_sep)
- __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
- else
- __thousands_sep_ = base::do_thousands_sep();
+ if (!checked_string_to_wchar_convert(__decimal_point_,
+ lc->mon_decimal_point,
+ loc.get()))
+ __decimal_point_ = base::do_decimal_point();
+ if (!checked_string_to_wchar_convert(__thousands_sep_,
+ lc->mon_thousands_sep,
+ loc.get()))
+ __thousands_sep_ = base::do_thousands_sep();
__grouping_ = lc->mon_grouping;
wchar_t wbuf[100];
mbstate_t mb = {0};
@@ -5964,20 +5998,19 @@ moneypunct_byname<wchar_t, true>::init(const char* nm)
{
typedef moneypunct<wchar_t, true> base;
__locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
-#ifndef _LIBCPP_NO_EXCEPTIONS
if (loc == nullptr)
- throw runtime_error("moneypunct_byname"
+ __throw_runtime_error("moneypunct_byname"
" failed to construct for " + string(nm));
-#endif // _LIBCPP_NO_EXCEPTIONS
+
lconv* lc = __libcpp_localeconv_l(loc.get());
- if (*lc->mon_decimal_point)
- __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
- else
- __decimal_point_ = base::do_decimal_point();
- if (*lc->mon_thousands_sep)
- __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
- else
- __thousands_sep_ = base::do_thousands_sep();
+ if (!checked_string_to_wchar_convert(__decimal_point_,
+ lc->mon_decimal_point,
+ loc.get()))
+ __decimal_point_ = base::do_decimal_point();
+ if (!checked_string_to_wchar_convert(__thousands_sep_,
+ lc->mon_thousands_sep,
+ loc.get()))
+ __thousands_sep_ = base::do_thousands_sep();
__grouping_ = lc->mon_grouping;
wchar_t wbuf[100];
mbstate_t mb = {0};
@@ -6050,69 +6083,70 @@ void __throw_runtime_error(const char* msg)
throw runtime_error(msg);
#else
(void)msg;
+ _VSTD::abort();
#endif
}
-template class collate<char>;
-template class collate<wchar_t>;
+template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate<char>;
+template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate<wchar_t>;
-template class num_get<char>;
-template class num_get<wchar_t>;
+template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_get<char>;
+template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_get<wchar_t>;
-template struct __num_get<char>;
-template struct __num_get<wchar_t>;
+template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_get<char>;
+template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_get<wchar_t>;
-template class num_put<char>;
-template class num_put<wchar_t>;
+template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_put<char>;
+template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_put<wchar_t>;
-template struct __num_put<char>;
-template struct __num_put<wchar_t>;
+template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_put<char>;
+template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_put<wchar_t>;
-template class time_get<char>;
-template class time_get<wchar_t>;
+template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get<char>;
+template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get<wchar_t>;
-template class time_get_byname<char>;
-template class time_get_byname<wchar_t>;
+template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get_byname<char>;
+template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get_byname<wchar_t>;
-template class time_put<char>;
-template class time_put<wchar_t>;
+template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put<char>;
+template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put<wchar_t>;
-template class time_put_byname<char>;
-template class time_put_byname<wchar_t>;
+template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put_byname<char>;
+template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put_byname<wchar_t>;
-template class moneypunct<char, false>;
-template class moneypunct<char, true>;
-template class moneypunct<wchar_t, false>;
-template class moneypunct<wchar_t, true>;
+template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<char, false>;
+template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<char, true>;
+template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<wchar_t, false>;
+template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<wchar_t, true>;
-template class moneypunct_byname<char, false>;
-template class moneypunct_byname<char, true>;
-template class moneypunct_byname<wchar_t, false>;
-template class moneypunct_byname<wchar_t, true>;
+template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<char, false>;
+template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<char, true>;
+template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<wchar_t, false>;
+template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<wchar_t, true>;
-template class money_get<char>;
-template class money_get<wchar_t>;
+template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_get<char>;
+template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_get<wchar_t>;
-template class __money_get<char>;
-template class __money_get<wchar_t>;
+template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_get<char>;
+template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_get<wchar_t>;
-template class money_put<char>;
-template class money_put<wchar_t>;
+template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_put<char>;
+template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_put<wchar_t>;
-template class __money_put<char>;
-template class __money_put<wchar_t>;
+template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_put<char>;
+template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_put<wchar_t>;
-template class messages<char>;
-template class messages<wchar_t>;
+template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages<char>;
+template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages<wchar_t>;
-template class messages_byname<char>;
-template class messages_byname<wchar_t>;
+template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages_byname<char>;
+template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages_byname<wchar_t>;
-template class codecvt_byname<char, char, mbstate_t>;
-template class codecvt_byname<wchar_t, char, mbstate_t>;
-template class codecvt_byname<char16_t, char, mbstate_t>;
-template class codecvt_byname<char32_t, char, mbstate_t>;
+template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char, char, mbstate_t>;
+template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<wchar_t, char, mbstate_t>;
+template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char16_t, char, mbstate_t>;
+template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char32_t, char, mbstate_t>;
-template class __vector_base_common<true>;
+template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __vector_base_common<true>;
_LIBCPP_END_NAMESPACE_STD
diff --git a/contrib/libc++/src/memory.cpp b/contrib/libc++/src/memory.cpp
index 15e947f..8569faf 100644
--- a/contrib/libc++/src/memory.cpp
+++ b/contrib/libc++/src/memory.cpp
@@ -96,7 +96,35 @@ __shared_weak_count::__release_shared() _NOEXCEPT
void
__shared_weak_count::__release_weak() _NOEXCEPT
{
- if (decrement(__shared_weak_owners_) == -1)
+ // NOTE: The acquire load here is an optimization of the very
+ // common case where a shared pointer is being destructed while
+ // having no other contended references.
+ //
+ // BENEFIT: We avoid expensive atomic stores like XADD and STREX
+ // in a common case. Those instructions are slow and do nasty
+ // things to caches.
+ //
+ // IS THIS SAFE? Yes. During weak destruction, if we see that we
+ // are the last reference, we know that no-one else is accessing
+ // us. If someone were accessing us, then they would be doing so
+ // while the last shared / weak_ptr was being destructed, and
+ // that's undefined anyway.
+ //
+ // If we see anything other than a 0, then we have possible
+ // contention, and need to use an atomicrmw primitive.
+ // The same arguments don't apply for increment, where it is legal
+ // (though inadvisable) to share shared_ptr references between
+ // threads, and have them all get copied at once. The argument
+ // also doesn't apply for __release_shared, because an outstanding
+ // weak_ptr::lock() could read / modify the shared count.
+ if (__libcpp_atomic_load(&__shared_weak_owners_, _AO_Acquire) == 0)
+ {
+ // no need to do this store, because we are about
+ // to destroy everything.
+ //__libcpp_atomic_store(&__shared_weak_owners_, -1, _AO_Release);
+ __on_zero_shared_weak();
+ }
+ else if (decrement(__shared_weak_owners_) == -1)
__on_zero_shared_weak();
}
@@ -126,8 +154,8 @@ __shared_weak_count::__get_deleter(const type_info&) const _NOEXCEPT
#if !defined(_LIBCPP_HAS_NO_ATOMIC_HEADER)
-static const std::size_t __sp_mut_count = 16;
-static __libcpp_mutex_t mut_back_imp[__sp_mut_count] =
+_LIBCPP_SAFE_STATIC static const std::size_t __sp_mut_count = 16;
+_LIBCPP_SAFE_STATIC static __libcpp_mutex_t mut_back[__sp_mut_count] =
{
_LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER,
_LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER,
@@ -135,8 +163,6 @@ static __libcpp_mutex_t mut_back_imp[__sp_mut_count] =
_LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER
};
-static mutex* mut_back = reinterpret_cast<std::mutex*>(mut_back_imp);
-
_LIBCPP_CONSTEXPR __sp_mut::__sp_mut(void* p) _NOEXCEPT
: __lx(p)
{
@@ -145,13 +171,13 @@ _LIBCPP_CONSTEXPR __sp_mut::__sp_mut(void* p) _NOEXCEPT
void
__sp_mut::lock() _NOEXCEPT
{
- mutex& m = *static_cast<mutex*>(__lx);
+ auto m = static_cast<__libcpp_mutex_t*>(__lx);
unsigned count = 0;
- while (!m.try_lock())
+ while (__libcpp_mutex_trylock(m) != 0)
{
if (++count > 16)
{
- m.lock();
+ __libcpp_mutex_lock(m);
break;
}
this_thread::yield();
@@ -161,13 +187,13 @@ __sp_mut::lock() _NOEXCEPT
void
__sp_mut::unlock() _NOEXCEPT
{
- static_cast<mutex*>(__lx)->unlock();
+ __libcpp_mutex_unlock(static_cast<__libcpp_mutex_t*>(__lx));
}
__sp_mut&
__get_sp_mut(const void* p)
{
- static __sp_mut muts[__sp_mut_count]
+ static __sp_mut muts[__sp_mut_count]
{
&mut_back[ 0], &mut_back[ 1], &mut_back[ 2], &mut_back[ 3],
&mut_back[ 4], &mut_back[ 5], &mut_back[ 6], &mut_back[ 7],
@@ -194,11 +220,12 @@ undeclare_no_pointers(char*, size_t)
{
}
-pointer_safety
-get_pointer_safety() _NOEXCEPT
+#if !defined(_LIBCPP_ABI_POINTER_SAFETY_ENUM_TYPE)
+pointer_safety get_pointer_safety() _NOEXCEPT
{
return pointer_safety::relaxed;
}
+#endif
void*
__undeclare_reachable(void* p)
diff --git a/contrib/libc++/src/mutex.cpp b/contrib/libc++/src/mutex.cpp
index 9f808ca..9397ae7 100644
--- a/contrib/libc++/src/mutex.cpp
+++ b/contrib/libc++/src/mutex.cpp
@@ -59,7 +59,7 @@ recursive_mutex::recursive_mutex()
recursive_mutex::~recursive_mutex()
{
- int e = __libcpp_mutex_destroy(&__m_);
+ int e = __libcpp_recursive_mutex_destroy(&__m_);
(void)e;
assert(e == 0);
}
@@ -67,7 +67,7 @@ recursive_mutex::~recursive_mutex()
void
recursive_mutex::lock()
{
- int ec = __libcpp_mutex_lock(&__m_);
+ int ec = __libcpp_recursive_mutex_lock(&__m_);
if (ec)
__throw_system_error(ec, "recursive_mutex lock failed");
}
@@ -75,7 +75,7 @@ recursive_mutex::lock()
void
recursive_mutex::unlock() _NOEXCEPT
{
- int e = __libcpp_mutex_unlock(&__m_);
+ int e = __libcpp_recursive_mutex_unlock(&__m_);
(void)e;
assert(e == 0);
}
@@ -83,7 +83,7 @@ recursive_mutex::unlock() _NOEXCEPT
bool
recursive_mutex::try_lock() _NOEXCEPT
{
- return __libcpp_mutex_trylock(&__m_) == 0;
+ return __libcpp_recursive_mutex_trylock(&__m_) == 0;
}
// timed_mutex
@@ -195,13 +195,10 @@ recursive_timed_mutex::unlock() _NOEXCEPT
// keep in sync with: 7741191.
#ifndef _LIBCPP_HAS_NO_THREADS
-static __libcpp_mutex_t mut = _LIBCPP_MUTEX_INITIALIZER;
-static __libcpp_condvar_t cv = _LIBCPP_CONDVAR_INITIALIZER;
+_LIBCPP_SAFE_STATIC static __libcpp_mutex_t mut = _LIBCPP_MUTEX_INITIALIZER;
+_LIBCPP_SAFE_STATIC static __libcpp_condvar_t cv = _LIBCPP_CONDVAR_INITIALIZER;
#endif
-/// NOTE: Changes to flag are done via relaxed atomic stores
-/// even though the accesses are protected by a mutex because threads
-/// just entering 'call_once` concurrently read from flag.
void
__call_once(volatile unsigned long& flag, void* arg, void(*func)(void*))
{
@@ -238,7 +235,7 @@ __call_once(volatile unsigned long& flag, void* arg, void(*func)(void*))
__libcpp_mutex_unlock(&mut);
func(arg);
__libcpp_mutex_lock(&mut);
- __libcpp_relaxed_store(&flag, ~0ul);
+ __libcpp_atomic_store(&flag, ~0ul, _AO_Release);
__libcpp_mutex_unlock(&mut);
__libcpp_condvar_broadcast(&cv);
#ifndef _LIBCPP_NO_EXCEPTIONS
diff --git a/contrib/libc++/src/new.cpp b/contrib/libc++/src/new.cpp
index f4f73d8..b1e8ee3 100644
--- a/contrib/libc++/src/new.cpp
+++ b/contrib/libc++/src/new.cpp
@@ -13,7 +13,8 @@
#include "new"
-#if defined(__APPLE__) && !defined(LIBCXXRT)
+#if defined(__APPLE__) && !defined(LIBCXXRT) && \
+ !defined(_LIBCPP_BUILDING_HAS_NO_ABI_LIBRARY)
#include <cxxabi.h>
#ifndef _LIBCPPABI_VERSION
@@ -26,7 +27,8 @@
#if defined(LIBCXXRT) || defined(LIBCXX_BUILDING_LIBCXXABI)
#include <cxxabi.h>
#endif // defined(LIBCXX_BUILDING_LIBCXXABI)
- #if !defined(_LIBCPPABI_VERSION) && !defined(__GLIBCXX__)
+ #if defined(_LIBCPP_BUILDING_HAS_NO_ABI_LIBRARY) || \
+ (!defined(_LIBCPPABI_VERSION) && !defined(__GLIBCXX__))
static std::new_handler __new_handler;
#endif // _LIBCPPABI_VERSION
#endif
@@ -37,12 +39,9 @@
// in this shared library, so that they can be overridden by programs
// that define non-weak copies of the functions.
-_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
+_LIBCPP_WEAK
void *
-operator new(std::size_t size)
-#if !__has_feature(cxx_noexcept)
- throw(std::bad_alloc)
-#endif
+operator new(std::size_t size) _THROW_BAD_ALLOC
{
if (size == 0)
size = 1;
@@ -64,7 +63,7 @@ operator new(std::size_t size)
return p;
}
-_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
+_LIBCPP_WEAK
void*
operator new(size_t size, const std::nothrow_t&) _NOEXCEPT
{
@@ -83,17 +82,14 @@ operator new(size_t size, const std::nothrow_t&) _NOEXCEPT
return p;
}
-_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
+_LIBCPP_WEAK
void*
-operator new[](size_t size)
-#if !__has_feature(cxx_noexcept)
- throw(std::bad_alloc)
-#endif
+operator new[](size_t size) _THROW_BAD_ALLOC
{
return ::operator new(size);
}
-_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
+_LIBCPP_WEAK
void*
operator new[](size_t size, const std::nothrow_t&) _NOEXCEPT
{
@@ -112,7 +108,7 @@ operator new[](size_t size, const std::nothrow_t&) _NOEXCEPT
return p;
}
-_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
+_LIBCPP_WEAK
void
operator delete(void* ptr) _NOEXCEPT
{
@@ -120,41 +116,169 @@ operator delete(void* ptr) _NOEXCEPT
::free(ptr);
}
-_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
+_LIBCPP_WEAK
void
operator delete(void* ptr, const std::nothrow_t&) _NOEXCEPT
{
::operator delete(ptr);
}
-_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
+_LIBCPP_WEAK
void
operator delete(void* ptr, size_t) _NOEXCEPT
{
::operator delete(ptr);
}
-_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
+_LIBCPP_WEAK
void
operator delete[] (void* ptr) _NOEXCEPT
{
::operator delete(ptr);
}
-_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
+_LIBCPP_WEAK
void
operator delete[] (void* ptr, const std::nothrow_t&) _NOEXCEPT
{
::operator delete[](ptr);
}
-_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
+_LIBCPP_WEAK
void
operator delete[] (void* ptr, size_t) _NOEXCEPT
{
::operator delete[](ptr);
}
+#if !defined(_LIBCPP_HAS_NO_ALIGNED_ALLOCATION)
+
+_LIBCPP_WEAK
+void *
+operator new(std::size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC
+{
+ if (size == 0)
+ size = 1;
+ if (static_cast<size_t>(alignment) < sizeof(void*))
+ alignment = std::align_val_t(sizeof(void*));
+ void* p;
+#if defined(_LIBCPP_MSVCRT)
+ while ((p = _aligned_malloc(size, static_cast<size_t>(alignment))) == nullptr)
+#else
+ while (::posix_memalign(&p, static_cast<size_t>(alignment), size) != 0)
+#endif
+ {
+ // If posix_memalign fails and there is a new_handler,
+ // call it to try free up memory.
+ std::new_handler nh = std::get_new_handler();
+ if (nh)
+ nh();
+ else {
+#ifndef _LIBCPP_NO_EXCEPTIONS
+ throw std::bad_alloc();
+#else
+ p = nullptr; // posix_memalign doesn't initialize 'p' on failure
+ break;
+#endif
+ }
+ }
+ return p;
+}
+
+_LIBCPP_WEAK
+void*
+operator new(size_t size, std::align_val_t alignment, const std::nothrow_t&) _NOEXCEPT
+{
+ void* p = 0;
+#ifndef _LIBCPP_NO_EXCEPTIONS
+ try
+ {
+#endif // _LIBCPP_NO_EXCEPTIONS
+ p = ::operator new(size, alignment);
+#ifndef _LIBCPP_NO_EXCEPTIONS
+ }
+ catch (...)
+ {
+ }
+#endif // _LIBCPP_NO_EXCEPTIONS
+ return p;
+}
+
+_LIBCPP_WEAK
+void*
+operator new[](size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC
+{
+ return ::operator new(size, alignment);
+}
+
+_LIBCPP_WEAK
+void*
+operator new[](size_t size, std::align_val_t alignment, const std::nothrow_t&) _NOEXCEPT
+{
+ void* p = 0;
+#ifndef _LIBCPP_NO_EXCEPTIONS
+ try
+ {
+#endif // _LIBCPP_NO_EXCEPTIONS
+ p = ::operator new[](size, alignment);
+#ifndef _LIBCPP_NO_EXCEPTIONS
+ }
+ catch (...)
+ {
+ }
+#endif // _LIBCPP_NO_EXCEPTIONS
+ return p;
+}
+
+_LIBCPP_WEAK
+void
+operator delete(void* ptr, std::align_val_t) _NOEXCEPT
+{
+ if (ptr)
+#if defined(_LIBCPP_MSVCRT)
+ ::_aligned_free(ptr);
+#else
+ ::free(ptr);
+#endif
+}
+
+_LIBCPP_WEAK
+void
+operator delete(void* ptr, std::align_val_t alignment, const std::nothrow_t&) _NOEXCEPT
+{
+ ::operator delete(ptr, alignment);
+}
+
+_LIBCPP_WEAK
+void
+operator delete(void* ptr, size_t, std::align_val_t alignment) _NOEXCEPT
+{
+ ::operator delete(ptr, alignment);
+}
+
+_LIBCPP_WEAK
+void
+operator delete[] (void* ptr, std::align_val_t alignment) _NOEXCEPT
+{
+ ::operator delete(ptr, alignment);
+}
+
+_LIBCPP_WEAK
+void
+operator delete[] (void* ptr, std::align_val_t alignment, const std::nothrow_t&) _NOEXCEPT
+{
+ ::operator delete[](ptr, alignment);
+}
+
+_LIBCPP_WEAK
+void
+operator delete[] (void* ptr, size_t, std::align_val_t alignment) _NOEXCEPT
+{
+ ::operator delete[](ptr, alignment);
+}
+
+#endif // !defined(_LIBCPP_HAS_NO_ALIGNED_ALLOCATION)
+
#endif // !__GLIBCXX__
namespace std
@@ -206,6 +330,8 @@ bad_array_new_length::bad_array_new_length() _NOEXCEPT
{
}
+#ifndef __GLIBCXX__
+
bad_array_new_length::~bad_array_new_length() _NOEXCEPT
{
}
@@ -216,22 +342,28 @@ bad_array_new_length::what() const _NOEXCEPT
return "bad_array_new_length";
}
+#endif // !__GLIBCXX__
+
#endif //LIBCXXRT
-const char*
-bad_array_length::what() const _NOEXCEPT
+bad_array_length::bad_array_length() _NOEXCEPT
{
- return "bad_array_length";
}
-bad_array_length::bad_array_length() _NOEXCEPT
+#ifndef __GLIBCXX__
+
+bad_array_length::~bad_array_length() _NOEXCEPT
{
}
-bad_array_length::~bad_array_length() _NOEXCEPT
+const char*
+bad_array_length::what() const _NOEXCEPT
{
+ return "bad_array_length";
}
+#endif // !__GLIBCXX__
+
#endif // _LIBCPPABI_VERSION
#ifndef LIBSTDCXX
@@ -241,6 +373,8 @@ __throw_bad_alloc()
{
#ifndef _LIBCPP_NO_EXCEPTIONS
throw bad_alloc();
+#else
+ _VSTD::abort();
#endif
}
diff --git a/contrib/libc++/src/optional.cpp b/contrib/libc++/src/optional.cpp
index 8c5dd76..2877d17 100644
--- a/contrib/libc++/src/optional.cpp
+++ b/contrib/libc++/src/optional.cpp
@@ -7,18 +7,22 @@
//
//===----------------------------------------------------------------------===//
+#include "optional"
#include "experimental/optional"
-_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL
+namespace std
+{
-#ifdef _LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS
+bad_optional_access::~bad_optional_access() _NOEXCEPT = default;
-bad_optional_access::~bad_optional_access() _NOEXCEPT {}
+const char* bad_optional_access::what() const _NOEXCEPT {
+ return "bad_optional_access";
+ }
-#else
+} // std
-bad_optional_access::~bad_optional_access() _NOEXCEPT = default;
+_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL
-#endif
+bad_optional_access::~bad_optional_access() _NOEXCEPT = default;
_LIBCPP_END_NAMESPACE_EXPERIMENTAL
diff --git a/contrib/libc++/src/random.cpp b/contrib/libc++/src/random.cpp
index 4ab424e..eb2510a 100644
--- a/contrib/libc++/src/random.cpp
+++ b/contrib/libc++/src/random.cpp
@@ -7,6 +7,8 @@
//
//===----------------------------------------------------------------------===//
+#include <__config>
+
#if defined(_LIBCPP_USING_WIN32_RANDOM)
// Must be defined before including stdlib.h to enable rand_s().
#define _CRT_RAND_S
diff --git a/contrib/libc++/src/stdexcept.cpp b/contrib/libc++/src/stdexcept.cpp
index 0a08bfe..3f33330 100644
--- a/contrib/libc++/src/stdexcept.cpp
+++ b/contrib/libc++/src/stdexcept.cpp
@@ -7,19 +7,21 @@
//
//===----------------------------------------------------------------------===//
-#include "__refstring"
#include "stdexcept"
#include "new"
#include "string"
#include "system_error"
+#include "__refstring"
/* For _LIBCPPABI_VERSION */
-#if defined(LIBCXX_BUILDING_LIBCXXABI) || defined(__APPLE__) || defined(LIBCXXRT)
+#if !defined(_LIBCPP_BUILDING_HAS_NO_ABI_LIBRARY) && \
+ (defined(LIBCXX_BUILDING_LIBCXXABI) || defined(__APPLE__) || defined(LIBCXXRT))
#include <cxxabi.h>
#endif
static_assert(sizeof(std::__libcpp_refstring) == sizeof(const char *), "");
+
namespace std // purposefully not using versioning namespace
{
diff --git a/contrib/libc++/src/string.cpp b/contrib/libc++/src/string.cpp
index d3f29df..cd64433 100644
--- a/contrib/libc++/src/string.cpp
+++ b/contrib/libc++/src/string.cpp
@@ -20,10 +20,10 @@
_LIBCPP_BEGIN_NAMESPACE_STD
-template class __basic_string_common<true>;
+template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __basic_string_common<true>;
-template class basic_string<char>;
-template class basic_string<wchar_t>;
+template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_string<char>;
+template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_string<wchar_t>;
template
string
@@ -40,7 +40,7 @@ void throw_helper( const string& msg )
throw T( msg );
#else
fprintf(stderr, "%s\n", msg.c_str());
- abort();
+ _VSTD::abort();
#endif
}
diff --git a/contrib/libc++/src/strstream.cpp b/contrib/libc++/src/strstream.cpp
index 0e2d7ff..be94f9c 100644
--- a/contrib/libc++/src/strstream.cpp
+++ b/contrib/libc++/src/strstream.cpp
@@ -11,6 +11,7 @@
#include "algorithm"
#include "climits"
#include "cstring"
+#include "cstdlib"
#include "__debug"
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -266,6 +267,8 @@ strstreambuf::seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmod
case ios::end:
newoff = seekhigh - eback();
break;
+ default:
+ _LIBCPP_UNREACHABLE();
}
newoff += __off;
if (0 <= newoff && newoff <= seekhigh - eback())
diff --git a/contrib/libc++/src/system_error.cpp b/contrib/libc++/src/system_error.cpp
index 87f35ae..c547124 100644
--- a/contrib/libc++/src/system_error.cpp
+++ b/contrib/libc++/src/system_error.cpp
@@ -29,9 +29,11 @@ _LIBCPP_BEGIN_NAMESPACE_STD
// class error_category
+#if defined(_LIBCPP_DEPRECATED_ABI_EXTERNAL_ERROR_CATEGORY_CONSTRUCTOR)
error_category::error_category() _NOEXCEPT
{
}
+#endif
error_category::~error_category() _NOEXCEPT
{
@@ -55,6 +57,7 @@ error_category::equivalent(const error_code& code, int condition) const _NOEXCEP
return *this == code.category() && code.value() == condition;
}
+#if !defined(_LIBCPP_HAS_NO_THREADS)
namespace {
// GLIBC also uses 1024 as the maximum buffer size internally.
@@ -62,8 +65,16 @@ constexpr size_t strerror_buff_size = 1024;
string do_strerror_r(int ev);
-#if defined(__linux__) && !defined(_LIBCPP_HAS_MUSL_LIBC) \
- && (!defined(__ANDROID__) || __ANDROID_API__ >= 23)
+#if defined(_LIBCPP_MSVCRT)
+string do_strerror_r(int ev) {
+ char buffer[strerror_buff_size];
+ if (::strerror_s(buffer, strerror_buff_size, ev) == 0)
+ return string(buffer);
+ std::snprintf(buffer, strerror_buff_size, "unknown error %d", ev);
+ return string(buffer);
+}
+#elif defined(__linux__) && !defined(_LIBCPP_HAS_MUSL_LIBC) && \
+ (!defined(__ANDROID__) || __ANDROID_API__ >= 23)
// GNU Extended version
string do_strerror_r(int ev) {
char buffer[strerror_buff_size];
@@ -96,6 +107,7 @@ string do_strerror_r(int ev) {
#endif
} // end namespace
+#endif
string
__do_message::message(int ev) const
@@ -258,6 +270,7 @@ __throw_system_error(int ev, const char* what_arg)
#else
(void)ev;
(void)what_arg;
+ _VSTD::abort();
#endif
}
diff --git a/contrib/libc++/src/thread.cpp b/contrib/libc++/src/thread.cpp
index 467402b..5ccf829 100644
--- a/contrib/libc++/src/thread.cpp
+++ b/contrib/libc++/src/thread.cpp
@@ -24,16 +24,17 @@
# endif // defined(BSD)
#endif // defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
-#if !defined(_WIN32)
+#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
# include <unistd.h>
-#endif // !_WIN32
+#endif // defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
#if defined(__NetBSD__)
#pragma weak pthread_create // Do not create libpthread dependency
#endif
-#if defined(_WIN32)
+
+#if defined(_LIBCPP_WIN32API)
#include <windows.h>
-#endif
+#endif // defined(_LIBCPP_WIN32API)
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -53,10 +54,9 @@ thread::join()
if (ec == 0)
__t_ = 0;
}
-#ifndef _LIBCPP_NO_EXCEPTIONS
+
if (ec)
- throw system_error(error_code(ec, system_category()), "thread::join failed");
-#endif // _LIBCPP_NO_EXCEPTIONS
+ __throw_system_error(ec, "thread::join failed");
}
void
@@ -69,10 +69,9 @@ thread::detach()
if (ec == 0)
__t_ = 0;
}
-#ifndef _LIBCPP_NO_EXCEPTIONS
+
if (ec)
- throw system_error(error_code(ec, system_category()), "thread::detach failed");
-#endif // _LIBCPP_NO_EXCEPTIONS
+ __throw_system_error(ec, "thread::detach failed");
}
unsigned
@@ -93,7 +92,7 @@ thread::hardware_concurrency() _NOEXCEPT
if (result < 0)
return 0;
return static_cast<unsigned>(result);
-#elif defined(_WIN32)
+#elif defined(_LIBCPP_WIN32API)
SYSTEM_INFO info;
GetSystemInfo(&info);
return info.dwNumberOfProcessors;
@@ -118,6 +117,12 @@ sleep_for(const chrono::nanoseconds& ns)
using namespace chrono;
if (ns > nanoseconds::zero())
{
+#if defined(_LIBCPP_WIN32API)
+ milliseconds ms = duration_cast<milliseconds>(ns);
+ if (ms.count() == 0 || ns > duration_cast<nanoseconds>(ms))
+ ++ms;
+ Sleep(ms.count());
+#else
seconds s = duration_cast<seconds>(ns);
timespec ts;
typedef decltype(ts.tv_sec) ts_sec;
@@ -135,6 +140,7 @@ sleep_for(const chrono::nanoseconds& ns)
while (nanosleep(&ts, &ts) == -1 && errno == EINTR)
;
+#endif
}
}
diff --git a/contrib/libc++/src/typeinfo.cpp b/contrib/libc++/src/typeinfo.cpp
index 5c0a609..d0a7dae 100644
--- a/contrib/libc++/src/typeinfo.cpp
+++ b/contrib/libc++/src/typeinfo.cpp
@@ -8,13 +8,19 @@
//===----------------------------------------------------------------------===//
#include <stdlib.h>
-#if defined(__APPLE__) || defined(LIBCXXRT) || \
- defined(LIBCXX_BUILDING_LIBCXXABI)
+#if !defined(_LIBCPP_BUILDING_HAS_NO_ABI_LIBRARY) && \
+ (defined(__APPLE__) || defined(LIBCXXRT) || defined(LIBCXX_BUILDING_LIBCXXABI))
#include <cxxabi.h>
#endif
#include "typeinfo"
+#if defined(_LIBCPP_BUILDING_HAS_NO_ABI_LIBRARY)
+std::type_info::~type_info()
+{
+}
+#endif
+
#if !defined(LIBCXXRT) && !defined(_LIBCPPABI_VERSION)
std::bad_cast::bad_cast() _NOEXCEPT
@@ -47,19 +53,23 @@ std::bad_typeid::what() const _NOEXCEPT
return "std::bad_typeid";
}
-#ifdef __APPLE__
+#if defined(__APPLE__) && !defined(_LIBCPP_BUILDING_HAS_NO_ABI_LIBRARY)
// On Darwin, the cxa_bad_* functions cannot be in the lower level library
// because bad_cast and bad_typeid are defined in his higher level library
void __cxxabiv1::__cxa_bad_typeid()
{
#ifndef _LIBCPP_NO_EXCEPTIONS
throw std::bad_typeid();
+#else
+ _VSTD::abort();
#endif
}
void __cxxabiv1::__cxa_bad_cast()
{
#ifndef _LIBCPP_NO_EXCEPTIONS
throw std::bad_cast();
+#else
+ _VSTD::abort();
#endif
}
#endif
diff --git a/contrib/libc++/src/variant.cpp b/contrib/libc++/src/variant.cpp
new file mode 100644
index 0000000..5bb508c
--- /dev/null
+++ b/contrib/libc++/src/variant.cpp
@@ -0,0 +1,18 @@
+//===------------------------ variant.cpp ---------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "variant"
+
+namespace std {
+
+const char* bad_variant_access::what() const noexcept {
+ return "bad_variant_access";
+}
+
+} // namespace std
OpenPOWER on IntegriCloud