summaryrefslogtreecommitdiffstats
path: root/contrib/libc++/src
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/libc++/src')
-rw-r--r--contrib/libc++/src/algorithm.cpp6
-rw-r--r--contrib/libc++/src/bind.cpp21
-rw-r--r--contrib/libc++/src/condition_variable.cpp10
-rw-r--r--contrib/libc++/src/experimental/filesystem/directory_iterator.cpp256
-rw-r--r--contrib/libc++/src/experimental/filesystem/operations.cpp794
-rw-r--r--contrib/libc++/src/experimental/filesystem/path.cpp391
-rw-r--r--contrib/libc++/src/experimental/memory_resource.cpp144
-rw-r--r--contrib/libc++/src/locale.cpp233
-rw-r--r--contrib/libc++/src/memory.cpp14
-rw-r--r--contrib/libc++/src/mutex.cpp74
-rw-r--r--contrib/libc++/src/regex.cpp18
-rw-r--r--contrib/libc++/src/strstream.cpp9
-rw-r--r--contrib/libc++/src/system_error.cpp57
-rw-r--r--contrib/libc++/src/thread.cpp24
14 files changed, 1756 insertions, 295 deletions
diff --git a/contrib/libc++/src/algorithm.cpp b/contrib/libc++/src/algorithm.cpp
index e548856..e9752b0 100644
--- a/contrib/libc++/src/algorithm.cpp
+++ b/contrib/libc++/src/algorithm.cpp
@@ -48,14 +48,14 @@ 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 pthread_mutex_t __rs_mut = PTHREAD_MUTEX_INITIALIZER;
+static __libcpp_mutex_t __rs_mut = _LIBCPP_MUTEX_INITIALIZER;
#endif
unsigned __rs_default::__c_ = 0;
__rs_default::__rs_default()
{
#ifndef _LIBCPP_HAS_NO_THREADS
- pthread_mutex_lock(&__rs_mut);
+ __libcpp_mutex_lock(&__rs_mut);
#endif
__c_ = 1;
}
@@ -69,7 +69,7 @@ __rs_default::~__rs_default()
{
#ifndef _LIBCPP_HAS_NO_THREADS
if (--__c_ == 0)
- pthread_mutex_unlock(&__rs_mut);
+ __libcpp_mutex_unlock(&__rs_mut);
#else
--__c_;
#endif
diff --git a/contrib/libc++/src/bind.cpp b/contrib/libc++/src/bind.cpp
index cab0b7c..b318fc1 100644
--- a/contrib/libc++/src/bind.cpp
+++ b/contrib/libc++/src/bind.cpp
@@ -7,6 +7,7 @@
//
//===----------------------------------------------------------------------===//
+#define _LIBCPP_BUILDING_BIND
#include "functional"
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -14,16 +15,16 @@ _LIBCPP_BEGIN_NAMESPACE_STD
namespace placeholders
{
-__ph<1> _1;
-__ph<2> _2;
-__ph<3> _3;
-__ph<4> _4;
-__ph<5> _5;
-__ph<6> _6;
-__ph<7> _7;
-__ph<8> _8;
-__ph<9> _9;
-__ph<10> _10;
+const __ph<1> _1{};
+const __ph<2> _2{};
+const __ph<3> _3{};
+const __ph<4> _4{};
+const __ph<5> _5{};
+const __ph<6> _6{};
+const __ph<7> _7{};
+const __ph<8> _8{};
+const __ph<9> _9{};
+const __ph<10> _10{};
} // placeholders
diff --git a/contrib/libc++/src/condition_variable.cpp b/contrib/libc++/src/condition_variable.cpp
index 5fd5fc8..bfb4bf3 100644
--- a/contrib/libc++/src/condition_variable.cpp
+++ b/contrib/libc++/src/condition_variable.cpp
@@ -20,19 +20,19 @@ _LIBCPP_BEGIN_NAMESPACE_STD
condition_variable::~condition_variable()
{
- pthread_cond_destroy(&__cv_);
+ __libcpp_condvar_destroy(&__cv_);
}
void
condition_variable::notify_one() _NOEXCEPT
{
- pthread_cond_signal(&__cv_);
+ __libcpp_condvar_signal(&__cv_);
}
void
condition_variable::notify_all() _NOEXCEPT
{
- pthread_cond_broadcast(&__cv_);
+ __libcpp_condvar_broadcast(&__cv_);
}
void
@@ -41,7 +41,7 @@ condition_variable::wait(unique_lock<mutex>& lk) _NOEXCEPT
if (!lk.owns_lock())
__throw_system_error(EPERM,
"condition_variable::wait: mutex not locked");
- int ec = pthread_cond_wait(&__cv_, lk.mutex()->native_handle());
+ int ec = __libcpp_condvar_wait(&__cv_, lk.mutex()->native_handle());
if (ec)
__throw_system_error(ec, "condition_variable wait failed");
}
@@ -71,7 +71,7 @@ condition_variable::__do_timed_wait(unique_lock<mutex>& lk,
ts.tv_sec = ts_sec_max;
ts.tv_nsec = giga::num - 1;
}
- int ec = pthread_cond_timedwait(&__cv_, lk.mutex()->native_handle(), &ts);
+ int ec = __libcpp_condvar_timedwait(&__cv_, lk.mutex()->native_handle(), &ts);
if (ec != 0 && ec != ETIMEDOUT)
__throw_system_error(ec, "condition_variable timed_wait failed");
}
diff --git a/contrib/libc++/src/experimental/filesystem/directory_iterator.cpp b/contrib/libc++/src/experimental/filesystem/directory_iterator.cpp
new file mode 100644
index 0000000..fa217ba
--- /dev/null
+++ b/contrib/libc++/src/experimental/filesystem/directory_iterator.cpp
@@ -0,0 +1,256 @@
+#include "experimental/filesystem"
+#include <dirent.h>
+#include <errno.h>
+
+_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_FILESYSTEM
+
+namespace { namespace detail {
+
+inline error_code capture_errno() {
+ _LIBCPP_ASSERT(errno, "Expected errno to be non-zero");
+ return error_code{errno, std::generic_category()};
+}
+
+template <class ...Args>
+inline bool capture_error_or_throw(std::error_code* user_ec,
+ const char* msg, Args&&... args)
+{
+ std::error_code my_ec = capture_errno();
+ if (user_ec) {
+ *user_ec = my_ec;
+ return true;
+ }
+ __libcpp_throw(filesystem_error(msg, std::forward<Args>(args)..., my_ec));
+ return false;
+}
+
+template <class ...Args>
+inline bool set_or_throw(std::error_code& my_ec,
+ std::error_code* user_ec,
+ const char* msg, Args&&... args)
+{
+ if (user_ec) {
+ *user_ec = my_ec;
+ return true;
+ }
+ __libcpp_throw(filesystem_error(msg, std::forward<Args>(args)..., my_ec));
+ return false;
+}
+
+typedef path::string_type string_type;
+
+
+inline string_type posix_readdir(DIR *dir_stream, error_code& ec) {
+ struct dirent* dir_entry_ptr = nullptr;
+ errno = 0; // zero errno in order to detect errors
+ if ((dir_entry_ptr = ::readdir(dir_stream)) == nullptr) {
+ ec = capture_errno();
+ return {};
+ } else {
+ ec.clear();
+ return dir_entry_ptr->d_name;
+ }
+}
+
+}} // namespace detail
+
+using detail::set_or_throw;
+
+class __dir_stream {
+public:
+ __dir_stream() = delete;
+ __dir_stream& operator=(const __dir_stream&) = delete;
+
+ __dir_stream(__dir_stream&& other) noexcept
+ : __stream_(other.__stream_), __root_(std::move(other.__root_)),
+ __entry_(std::move(other.__entry_))
+ {
+ other.__stream_ = nullptr;
+ }
+
+
+ __dir_stream(const path& root, directory_options opts, error_code& ec)
+ : __stream_(nullptr),
+ __root_(root)
+ {
+ if ((__stream_ = ::opendir(root.c_str())) == nullptr) {
+ ec = detail::capture_errno();
+ const bool allow_eacess =
+ bool(opts & directory_options::skip_permission_denied);
+ if (allow_eacess && ec.value() == EACCES)
+ ec.clear();
+ return;
+ }
+ advance(ec);
+ }
+
+ ~__dir_stream() noexcept
+ { if (__stream_) close(); }
+
+ bool good() const noexcept { return __stream_ != nullptr; }
+
+ bool advance(error_code &ec) {
+ while (true) {
+ auto str = detail::posix_readdir(__stream_, ec);
+ if (str == "." || str == "..") {
+ continue;
+ } else if (ec || str.empty()) {
+ close();
+ return false;
+ } else {
+ __entry_.assign(__root_ / str);
+ return true;
+ }
+ }
+ }
+private:
+ std::error_code close() noexcept {
+ std::error_code m_ec;
+ if (::closedir(__stream_) == -1)
+ m_ec = detail::capture_errno();
+ __stream_ = nullptr;
+ return m_ec;
+ }
+
+ DIR * __stream_{nullptr};
+public:
+ path __root_;
+ directory_entry __entry_;
+};
+
+// directory_iterator
+
+directory_iterator::directory_iterator(const path& p, error_code *ec,
+ directory_options opts)
+{
+ std::error_code m_ec;
+ __imp_ = make_shared<__dir_stream>(p, opts, m_ec);
+ if (ec) *ec = m_ec;
+ if (!__imp_->good()) {
+ __imp_.reset();
+ if (m_ec)
+ set_or_throw(m_ec, ec,
+ "directory_iterator::directory_iterator(...)", p);
+ }
+}
+
+directory_iterator& directory_iterator::__increment(error_code *ec)
+{
+ _LIBCPP_ASSERT(__imp_, "Attempting to increment an invalid iterator");
+ std::error_code m_ec;
+ if (!__imp_->advance(m_ec)) {
+ __imp_.reset();
+ if (m_ec)
+ set_or_throw(m_ec, ec, "directory_iterator::operator++()");
+ } else {
+ if (ec) ec->clear();
+ }
+ return *this;
+
+}
+
+directory_entry const& directory_iterator::__deref() const {
+ _LIBCPP_ASSERT(__imp_, "Attempting to dereference an invalid iterator");
+ return __imp_->__entry_;
+}
+
+// recursive_directory_iterator
+
+struct recursive_directory_iterator::__shared_imp {
+ stack<__dir_stream> __stack_;
+ directory_options __options_;
+};
+
+recursive_directory_iterator::recursive_directory_iterator(const path& p,
+ directory_options opt, error_code *ec)
+ : __imp_(nullptr), __rec_(true)
+{
+ if (ec) ec->clear();
+ std::error_code m_ec;
+ __dir_stream new_s(p, opt, m_ec);
+ if (m_ec) set_or_throw(m_ec, ec, "recursive_directory_iterator", p);
+ if (m_ec || !new_s.good()) return;
+
+ __imp_ = _VSTD::make_shared<__shared_imp>();
+ __imp_->__options_ = opt;
+ __imp_->__stack_.push(_VSTD::move(new_s));
+}
+
+void recursive_directory_iterator::__pop(error_code* ec)
+{
+ _LIBCPP_ASSERT(__imp_, "Popping the end iterator");
+ if (ec) ec->clear();
+ __imp_->__stack_.pop();
+ if (__imp_->__stack_.size() == 0)
+ __imp_.reset();
+ else
+ __advance(ec);
+}
+
+directory_options recursive_directory_iterator::options() const {
+ return __imp_->__options_;
+}
+
+int recursive_directory_iterator::depth() const {
+ return __imp_->__stack_.size() - 1;
+}
+
+const directory_entry& recursive_directory_iterator::__deref() const {
+ return __imp_->__stack_.top().__entry_;
+}
+
+recursive_directory_iterator&
+recursive_directory_iterator::__increment(error_code *ec)
+{
+ if (ec) ec->clear();
+ if (recursion_pending()) {
+ if (__try_recursion(ec) || (ec && *ec))
+ return *this;
+ }
+ __rec_ = true;
+ __advance(ec);
+ return *this;
+}
+
+void recursive_directory_iterator::__advance(error_code* ec) {
+ // REQUIRES: ec must be cleared before calling this function.
+ const directory_iterator end_it;
+ auto& stack = __imp_->__stack_;
+ std::error_code m_ec;
+ while (stack.size() > 0) {
+ if (stack.top().advance(m_ec))
+ return;
+ if (m_ec) break;
+ stack.pop();
+ }
+ __imp_.reset();
+ if (m_ec)
+ set_or_throw(m_ec, ec, "recursive_directory_iterator::operator++()");
+}
+
+bool recursive_directory_iterator::__try_recursion(error_code *ec) {
+
+ bool rec_sym =
+ bool(options() & directory_options::follow_directory_symlink);
+ auto& curr_it = __imp_->__stack_.top();
+
+ if (is_directory(curr_it.__entry_.status()) &&
+ (!is_symlink(curr_it.__entry_.symlink_status()) || rec_sym))
+ {
+ std::error_code m_ec;
+ __dir_stream new_it(curr_it.__entry_.path(), __imp_->__options_, m_ec);
+ if (new_it.good()) {
+ __imp_->__stack_.push(_VSTD::move(new_it));
+ return true;
+ }
+ if (m_ec) {
+ __imp_.reset();
+ set_or_throw(m_ec, ec,
+ "recursive_directory_iterator::operator++()");
+ }
+ }
+ return false;
+}
+
+
+_LIBCPP_END_NAMESPACE_EXPERIMENTAL_FILESYSTEM
diff --git a/contrib/libc++/src/experimental/filesystem/operations.cpp b/contrib/libc++/src/experimental/filesystem/operations.cpp
new file mode 100644
index 0000000..369996f
--- /dev/null
+++ b/contrib/libc++/src/experimental/filesystem/operations.cpp
@@ -0,0 +1,794 @@
+//===--------------------- filesystem/ops.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 "experimental/filesystem"
+#include "iterator"
+#include "fstream"
+#include "type_traits"
+#include "random" /* for unique_path */
+#include "cstdlib"
+#include "climits"
+
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/statvfs.h>
+#include <fcntl.h> /* values for fchmodat */
+#if !defined(UTIME_OMIT)
+#include <sys/time.h> // for ::utimes as used in __last_write_time
+#endif
+
+_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_FILESYSTEM
+
+filesystem_error::~filesystem_error() {}
+
+
+// POSIX HELPERS
+
+namespace detail { namespace {
+
+using value_type = path::value_type;
+using string_type = path::string_type;
+
+
+
+inline std::error_code capture_errno() {
+ _LIBCPP_ASSERT(errno, "Expected errno to be non-zero");
+ std::error_code m_ec(errno, std::generic_category());
+ return m_ec;
+}
+
+void set_or_throw(std::error_code const& m_ec, std::error_code* ec,
+ const char* msg, path const& p = {}, path const& p2 = {})
+{
+ if (ec) {
+ *ec = m_ec;
+ } else {
+ string msg_s("std::experimental::filesystem::");
+ msg_s += msg;
+ __libcpp_throw(filesystem_error(msg_s, p, p2, m_ec));
+ }
+}
+
+void set_or_throw(std::error_code* ec, const char* msg,
+ path const& p = {}, path const& p2 = {})
+{
+ return set_or_throw(capture_errno(), ec, msg, p, p2);
+}
+
+perms posix_get_perms(const struct ::stat & st) noexcept {
+ return static_cast<perms>(st.st_mode) & perms::mask;
+}
+
+::mode_t posix_convert_perms(perms prms) {
+ return static_cast< ::mode_t>(prms & perms::mask);
+}
+
+file_status create_file_status(std::error_code& m_ec, path const& p,
+ struct ::stat& path_stat,
+ std::error_code* ec)
+{
+ if (ec) *ec = m_ec;
+ if (m_ec && (m_ec.value() == ENOENT || m_ec.value() == ENOTDIR)) {
+ return file_status(file_type::not_found);
+ }
+ else if (m_ec) {
+ set_or_throw(m_ec, ec, "posix_stat", p);
+ return file_status(file_type::none);
+ }
+ // else
+
+ file_status fs_tmp;
+ auto const mode = path_stat.st_mode;
+ if (S_ISLNK(mode)) fs_tmp.type(file_type::symlink);
+ else if (S_ISREG(mode)) fs_tmp.type(file_type::regular);
+ else if (S_ISDIR(mode)) fs_tmp.type(file_type::directory);
+ else if (S_ISBLK(mode)) fs_tmp.type(file_type::block);
+ else if (S_ISCHR(mode)) fs_tmp.type(file_type::character);
+ else if (S_ISFIFO(mode)) fs_tmp.type(file_type::fifo);
+ else if (S_ISSOCK(mode)) fs_tmp.type(file_type::socket);
+ else fs_tmp.type(file_type::unknown);
+
+ fs_tmp.permissions(detail::posix_get_perms(path_stat));
+ return fs_tmp;
+}
+
+file_status posix_stat(path const & p, struct ::stat& path_stat,
+ std::error_code* ec)
+{
+ std::error_code m_ec;
+ if (::stat(p.c_str(), &path_stat) == -1)
+ m_ec = detail::capture_errno();
+ return create_file_status(m_ec, p, path_stat, ec);
+}
+
+file_status posix_stat(path const & p, std::error_code* ec) {
+ struct ::stat path_stat;
+ return posix_stat(p, path_stat, ec);
+}
+
+file_status posix_lstat(path const & p, struct ::stat & path_stat,
+ std::error_code* ec)
+{
+ std::error_code m_ec;
+ if (::lstat(p.c_str(), &path_stat) == -1)
+ m_ec = detail::capture_errno();
+ return create_file_status(m_ec, p, path_stat, ec);
+}
+
+file_status posix_lstat(path const & p, std::error_code* ec) {
+ struct ::stat path_stat;
+ return posix_lstat(p, path_stat, ec);
+}
+
+bool stat_equivalent(struct ::stat& st1, struct ::stat& st2) {
+ return (st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino);
+}
+
+// DETAIL::MISC
+
+
+bool copy_file_impl(const path& from, const path& to, perms from_perms,
+ std::error_code *ec)
+{
+ std::ifstream in(from.c_str(), std::ios::binary);
+ std::ofstream out(to.c_str(), std::ios::binary);
+
+ if (in.good() && out.good()) {
+ using InIt = std::istreambuf_iterator<char>;
+ using OutIt = std::ostreambuf_iterator<char>;
+ InIt bin(in);
+ InIt ein;
+ OutIt bout(out);
+ std::copy(bin, ein, bout);
+ }
+ if (out.fail() || in.fail()) {
+ set_or_throw(make_error_code(errc::operation_not_permitted),
+ ec, "copy_file", from, to);
+ return false;
+ }
+ __permissions(to, from_perms, ec);
+ // TODO what if permissions fails?
+ return true;
+}
+
+}} // end namespace detail
+
+using detail::set_or_throw;
+
+path __canonical(path const & orig_p, const path& base, std::error_code *ec)
+{
+ path p = absolute(orig_p, base);
+ char buff[PATH_MAX + 1];
+ char *ret;
+ if ((ret = ::realpath(p.c_str(), buff)) == nullptr) {
+ set_or_throw(ec, "canonical", orig_p, base);
+ return {};
+ }
+ if (ec) ec->clear();
+ return {ret};
+}
+
+void __copy(const path& from, const path& to, copy_options options,
+ std::error_code *ec)
+{
+ const bool sym_status = bool(options &
+ (copy_options::create_symlinks | copy_options::skip_symlinks));
+
+ const bool sym_status2 = bool(options &
+ copy_options::copy_symlinks);
+
+ std::error_code m_ec;
+ struct ::stat f_st = {};
+ const file_status f = sym_status || sym_status2
+ ? detail::posix_lstat(from, f_st, &m_ec)
+ : detail::posix_stat(from, f_st, &m_ec);
+ if (m_ec)
+ return set_or_throw(m_ec, ec, "copy", from, to);
+
+ struct ::stat t_st = {};
+ const file_status t = sym_status ? detail::posix_lstat(to, t_st, &m_ec)
+ : detail::posix_stat(to, t_st, &m_ec);
+
+ if (not status_known(t))
+ return set_or_throw(m_ec, ec, "copy", from, to);
+
+ if (!exists(f) || is_other(f) || is_other(t)
+ || (is_directory(f) && is_regular_file(t))
+ || detail::stat_equivalent(f_st, t_st))
+ {
+ return set_or_throw(make_error_code(errc::function_not_supported),
+ ec, "copy", from, to);
+ }
+
+ if (ec) ec->clear();
+
+ if (is_symlink(f)) {
+ if (bool(copy_options::skip_symlinks & options)) {
+ // do nothing
+ } else if (not exists(t)) {
+ __copy_symlink(from, to, ec);
+ } else {
+ set_or_throw(make_error_code(errc::file_exists),
+ ec, "copy", from, to);
+ }
+ return;
+ }
+ else if (is_regular_file(f)) {
+ if (bool(copy_options::directories_only & options)) {
+ // do nothing
+ }
+ else if (bool(copy_options::create_symlinks & options)) {
+ __create_symlink(from, to, ec);
+ }
+ else if (bool(copy_options::create_hard_links & options)) {
+ __create_hard_link(from, to, ec);
+ }
+ else if (is_directory(t)) {
+ __copy_file(from, to / from.filename(), options, ec);
+ } else {
+ __copy_file(from, to, options, ec);
+ }
+ return;
+ }
+ else if (is_directory(f)) {
+ if (not bool(copy_options::recursive & options) &&
+ bool(copy_options::__in_recursive_copy & options))
+ {
+ return;
+ }
+
+ if (!exists(t)) {
+ // create directory to with attributes from 'from'.
+ __create_directory(to, from, ec);
+ if (ec && *ec) { return; }
+ }
+ directory_iterator it = ec ? directory_iterator(from, *ec)
+ : directory_iterator(from);
+ if (ec && *ec) { return; }
+ std::error_code m_ec;
+ for (; it != directory_iterator(); it.increment(m_ec)) {
+ if (m_ec) return set_or_throw(m_ec, ec, "copy", from, to);
+ __copy(it->path(), to / it->path().filename(),
+ options | copy_options::__in_recursive_copy, ec);
+ if (ec && *ec) { return; }
+ }
+ }
+}
+
+
+bool __copy_file(const path& from, const path& to, copy_options options,
+ std::error_code *ec)
+{
+ if (ec) ec->clear();
+
+ std::error_code m_ec;
+ auto from_st = detail::posix_stat(from, &m_ec);
+ if (not is_regular_file(from_st)) {
+ if (not m_ec)
+ m_ec = make_error_code(errc::not_supported);
+ set_or_throw(m_ec, ec, "copy_file", from, to);
+ return false;
+ }
+
+ auto to_st = detail::posix_stat(to, &m_ec);
+ if (!status_known(to_st)) {
+ set_or_throw(m_ec, ec, "copy_file", from, to);
+ return false;
+ }
+
+ const bool to_exists = exists(to_st);
+ if (to_exists && bool(copy_options::skip_existing & options)) {
+ return false;
+ }
+ else if (to_exists && bool(copy_options::update_existing & options)) {
+ auto from_time = __last_write_time(from, ec);
+ if (ec && *ec) { return false; }
+ auto to_time = __last_write_time(to, ec);
+ if (ec && *ec) { return false; }
+ if (from_time <= to_time) {
+ return false;
+ }
+ return detail::copy_file_impl(from, to, from_st.permissions(), ec);
+ }
+ else if (!to_exists || bool(copy_options::overwrite_existing & options)) {
+ return detail::copy_file_impl(from, to, from_st.permissions(), ec);
+ }
+ else {
+ set_or_throw(make_error_code(errc::file_exists), ec, "copy", from, to);
+ return false;
+ }
+}
+
+void __copy_symlink(const path& existing_symlink, const path& new_symlink,
+ std::error_code *ec)
+{
+ const path real_path(__read_symlink(existing_symlink, ec));
+ if (ec && *ec) { return; }
+ // NOTE: proposal says you should detect if you should call
+ // create_symlink or create_directory_symlink. I don't think this
+ // is needed with POSIX
+ __create_symlink(real_path, new_symlink, ec);
+}
+
+
+bool __create_directories(const path& p, std::error_code *ec)
+{
+ std::error_code m_ec;
+ auto const st = detail::posix_stat(p, &m_ec);
+ if (!status_known(st)) {
+ set_or_throw(m_ec, ec, "create_directories", p);
+ return false;
+ }
+ else if (is_directory(st)) {
+ if (ec) ec->clear();
+ return false;
+ }
+ else if (exists(st)) {
+ set_or_throw(make_error_code(errc::file_exists),
+ ec, "create_directories", p);
+ return false;
+ }
+
+ const path parent = p.parent_path();
+ if (!parent.empty()) {
+ const file_status parent_st = status(parent, m_ec);
+ if (not status_known(parent_st)) {
+ set_or_throw(m_ec, ec, "create_directories", p);
+ return false;
+ }
+ if (not exists(parent_st)) {
+ __create_directories(parent, ec);
+ if (ec && *ec) { return false; }
+ }
+ }
+ return __create_directory(p, ec);
+}
+
+bool __create_directory(const path& p, std::error_code *ec)
+{
+ if (ec) ec->clear();
+ if (::mkdir(p.c_str(), static_cast<int>(perms::all)) == 0)
+ return true;
+ if (errno != EEXIST || !is_directory(p))
+ set_or_throw(ec, "create_directory", p);
+ return false;
+}
+
+bool __create_directory(path const & p, path const & attributes,
+ std::error_code *ec)
+{
+ struct ::stat attr_stat;
+ std::error_code mec;
+ auto st = detail::posix_stat(attributes, attr_stat, &mec);
+ if (!status_known(st)) {
+ set_or_throw(mec, ec, "create_directory", p, attributes);
+ return false;
+ }
+ if (ec) ec->clear();
+ if (::mkdir(p.c_str(), attr_stat.st_mode) == 0)
+ return true;
+ if (errno != EEXIST || !is_directory(p))
+ set_or_throw(ec, "create_directory", p, attributes);
+ return false;
+}
+
+void __create_directory_symlink(path const & from, path const & to,
+ std::error_code *ec){
+ if (::symlink(from.c_str(), to.c_str()) != 0)
+ set_or_throw(ec, "create_directory_symlink", from, to);
+ else if (ec)
+ ec->clear();
+}
+
+void __create_hard_link(const path& from, const path& to, std::error_code *ec){
+ if (::link(from.c_str(), to.c_str()) == -1)
+ set_or_throw(ec, "create_hard_link", from, to);
+ else if (ec)
+ ec->clear();
+}
+
+void __create_symlink(path const & from, path const & to, std::error_code *ec) {
+
+ if (::symlink(from.c_str(), to.c_str()) == -1)
+ set_or_throw(ec, "create_symlink", from, to);
+ else if (ec)
+ ec->clear();
+}
+
+path __current_path(std::error_code *ec) {
+ auto size = ::pathconf(".", _PC_PATH_MAX);
+ _LIBCPP_ASSERT(size >= 0, "pathconf returned a 0 as max size");
+
+ auto buff = std::unique_ptr<char[]>(new char[size + 1]);
+ char* ret;
+ if ((ret = ::getcwd(buff.get(), static_cast<size_t>(size))) == nullptr) {
+ set_or_throw(ec, "current_path");
+ return {};
+ }
+ if (ec) ec->clear();
+ return {buff.get()};
+}
+
+void __current_path(const path& p, std::error_code *ec) {
+ if (::chdir(p.c_str()) == -1)
+ set_or_throw(ec, "current_path", p);
+ else if (ec)
+ ec->clear();
+}
+
+bool __equivalent(const path& p1, const path& p2, std::error_code *ec)
+{
+ std::error_code ec1, ec2;
+ struct ::stat st1 = {};
+ struct ::stat st2 = {};
+ auto s1 = detail::posix_stat(p1.native(), st1, &ec1);
+ auto s2 = detail::posix_stat(p2.native(), st2, &ec2);
+
+ if ((!exists(s1) && !exists(s2)) || (is_other(s1) && is_other(s2))) {
+ set_or_throw(make_error_code(errc::not_supported), ec,
+ "equivalent", p1, p2);
+ return false;
+ }
+ if (ec) ec->clear();
+ return (st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino);
+}
+
+
+std::uintmax_t __file_size(const path& p, std::error_code *ec)
+{
+ std::error_code m_ec;
+ struct ::stat st;
+ file_status fst = detail::posix_stat(p, st, &m_ec);
+ if (!exists(fst) || !is_regular_file(fst)) {
+ if (!m_ec)
+ m_ec = make_error_code(errc::not_supported);
+ set_or_throw(m_ec, ec, "file_size", p);
+ return static_cast<uintmax_t>(-1);
+ }
+ // is_regular_file(p) == true
+ if (ec) ec->clear();
+ return static_cast<std::uintmax_t>(st.st_size);
+}
+
+std::uintmax_t __hard_link_count(const path& p, std::error_code *ec)
+{
+ std::error_code m_ec;
+ struct ::stat st;
+ detail::posix_stat(p, st, &m_ec);
+ if (m_ec) {
+ set_or_throw(m_ec, ec, "hard_link_count", p);
+ return static_cast<std::uintmax_t>(-1);
+ }
+ if (ec) ec->clear();
+ return static_cast<std::uintmax_t>(st.st_nlink);
+}
+
+
+bool __fs_is_empty(const path& p, std::error_code *ec)
+{
+ if (ec) ec->clear();
+ 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{};
+ 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;
+}
+
+
+namespace detail { namespace {
+
+template <class CType, class ChronoType>
+bool checked_set(CType* out, ChronoType time) {
+ using Lim = numeric_limits<CType>;
+ if (time > Lim::max() || time < Lim::min())
+ return false;
+ *out = static_cast<CType>(time);
+ return true;
+}
+
+constexpr long long min_seconds = file_time_type::duration::min().count()
+ / file_time_type::period::den;
+
+template <class SubSecDurT, class SubSecT>
+bool set_times_checked(time_t* sec_out, SubSecT* subsec_out, file_time_type tp) {
+ using namespace chrono;
+ auto dur = tp.time_since_epoch();
+ auto sec_dur = duration_cast<seconds>(dur);
+ auto subsec_dur = duration_cast<SubSecDurT>(dur - sec_dur);
+ // 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 {
+ subsec_dur = SubSecDurT::zero();
+ }
+ }
+ return checked_set(sec_out, sec_dur.count())
+ && checked_set(subsec_out, subsec_dur.count());
+}
+
+}} // end namespace detail
+
+
+file_time_type __last_write_time(const path& p, std::error_code *ec)
+{
+ std::error_code m_ec;
+ struct ::stat st;
+ detail::posix_stat(p, st, &m_ec);
+ if (m_ec) {
+ set_or_throw(m_ec, ec, "last_write_time", p);
+ return file_time_type::min();
+ }
+ if (ec) ec->clear();
+ return file_time_type::clock::from_time_t(st.st_mtime);
+}
+
+void __last_write_time(const path& p, file_time_type new_time,
+ std::error_code *ec)
+{
+ using namespace std::chrono;
+ std::error_code m_ec;
+
+ // We can use the presence of UTIME_OMIT to detect platforms that do not
+ // provide utimensat.
+#if !defined(UTIME_OMIT)
+ // This implementation has a race condition between determining the
+ // last access time and attempting to set it to the same value using
+ // ::utimes
+ struct ::stat st;
+ file_status fst = detail::posix_stat(p, st, &m_ec);
+ if (m_ec && !status_known(fst)) {
+ set_or_throw(m_ec, ec, "last_write_time", p);
+ return;
+ }
+ struct ::timeval tbuf[2];
+ tbuf[0].tv_sec = st.st_atime;
+ tbuf[0].tv_usec = 0;
+ const bool overflowed = !detail::set_times_checked<microseconds>(
+ &tbuf[1].tv_sec, &tbuf[1].tv_usec, new_time);
+
+ if (overflowed) {
+ set_or_throw(make_error_code(errc::invalid_argument), ec,
+ "last_write_time", p);
+ return;
+ }
+ if (::utimes(p.c_str(), tbuf) == -1) {
+ m_ec = detail::capture_errno();
+ }
+#else
+ struct ::timespec tbuf[2];
+ tbuf[0].tv_sec = 0;
+ tbuf[0].tv_nsec = UTIME_OMIT;
+
+ const bool overflowed = !detail::set_times_checked<nanoseconds>(
+ &tbuf[1].tv_sec, &tbuf[1].tv_nsec, new_time);
+ if (overflowed) {
+ set_or_throw(make_error_code(errc::invalid_argument),
+ ec, "last_write_time", p);
+ return;
+ }
+ if (::utimensat(AT_FDCWD, p.c_str(), tbuf, 0) == -1) {
+ m_ec = detail::capture_errno();
+ }
+#endif
+ if (m_ec)
+ set_or_throw(m_ec, ec, "last_write_time", p);
+ else if (ec)
+ ec->clear();
+}
+
+
+void __permissions(const path& p, perms prms, std::error_code *ec)
+{
+
+ const bool resolve_symlinks = !bool(perms::symlink_nofollow & prms);
+ const bool add_perms = bool(perms::add_perms & prms);
+ const bool remove_perms = bool(perms::remove_perms & prms);
+ _LIBCPP_ASSERT(!(add_perms && remove_perms),
+ "Both add_perms and remove_perms are set");
+
+ bool set_sym_perms = false;
+ prms &= perms::mask;
+ if (!resolve_symlinks || (add_perms || remove_perms)) {
+ std::error_code m_ec;
+ file_status st = resolve_symlinks ? detail::posix_stat(p, &m_ec)
+ : detail::posix_lstat(p, &m_ec);
+ set_sym_perms = is_symlink(st);
+ if (m_ec) return set_or_throw(m_ec, ec, "permissions", p);
+ _LIBCPP_ASSERT(st.permissions() != perms::unknown,
+ "Permissions unexpectedly unknown");
+ if (add_perms)
+ prms |= st.permissions();
+ else if (remove_perms)
+ prms = st.permissions() & ~prms;
+ }
+ const auto real_perms = detail::posix_convert_perms(prms);
+
+# if defined(AT_SYMLINK_NOFOLLOW) && defined(AT_FDCWD)
+ const int flags = set_sym_perms ? AT_SYMLINK_NOFOLLOW : 0;
+ if (::fchmodat(AT_FDCWD, p.c_str(), real_perms, flags) == -1) {
+ return set_or_throw(ec, "permissions", p);
+ }
+# else
+ if (set_sym_perms)
+ return set_or_throw(make_error_code(errc::operation_not_supported),
+ ec, "permissions", p);
+ if (::chmod(p.c_str(), real_perms) == -1) {
+ return set_or_throw(ec, "permissions", p);
+ }
+# endif
+ if (ec) ec->clear();
+}
+
+
+path __read_symlink(const path& p, std::error_code *ec) {
+ char buff[PATH_MAX + 1];
+ std::error_code m_ec;
+ ::ssize_t ret;
+ if ((ret = ::readlink(p.c_str(), buff, PATH_MAX)) == -1) {
+ set_or_throw(ec, "read_symlink", p);
+ return {};
+ }
+ _LIBCPP_ASSERT(ret <= PATH_MAX, "TODO");
+ _LIBCPP_ASSERT(ret > 0, "TODO");
+ if (ec) ec->clear();
+ buff[ret] = 0;
+ return {buff};
+}
+
+
+bool __remove(const path& p, std::error_code *ec) {
+ if (ec) ec->clear();
+ if (::remove(p.c_str()) == -1) {
+ set_or_throw(ec, "remove", p);
+ return false;
+ }
+ return true;
+}
+
+namespace {
+
+std::uintmax_t remove_all_impl(path const & p, std::error_code& ec)
+{
+ const auto npos = static_cast<std::uintmax_t>(-1);
+ const file_status st = __symlink_status(p, &ec);
+ if (ec) return npos;
+ std::uintmax_t count = 1;
+ if (is_directory(st)) {
+ for (directory_iterator it(p, ec); !ec && it != directory_iterator();
+ it.increment(ec)) {
+ auto other_count = remove_all_impl(it->path(), ec);
+ if (ec) return npos;
+ count += other_count;
+ }
+ if (ec) return npos;
+ }
+ if (!__remove(p, &ec)) return npos;
+ return count;
+}
+
+} // end namespace
+
+std::uintmax_t __remove_all(const path& p, std::error_code *ec) {
+ std::error_code mec;
+ auto count = remove_all_impl(p, mec);
+ if (mec) {
+ set_or_throw(mec, ec, "remove_all", p);
+ return static_cast<std::uintmax_t>(-1);
+ }
+ if (ec) ec->clear();
+ return count;
+}
+
+void __rename(const path& from, const path& to, std::error_code *ec) {
+ if (::rename(from.c_str(), to.c_str()) == -1)
+ set_or_throw(ec, "rename", from, to);
+ else if (ec)
+ ec->clear();
+}
+
+void __resize_file(const path& p, std::uintmax_t size, std::error_code *ec) {
+ if (::truncate(p.c_str(), static_cast<long>(size)) == -1)
+ set_or_throw(ec, "resize_file", p);
+ else if (ec)
+ ec->clear();
+}
+
+space_info __space(const path& p, std::error_code *ec) {
+ space_info si;
+ struct statvfs m_svfs = {};
+ if (::statvfs(p.c_str(), &m_svfs) == -1) {
+ set_or_throw(ec, "space", p);
+ si.capacity = si.free = si.available =
+ static_cast<std::uintmax_t>(-1);
+ return si;
+ }
+ if (ec) ec->clear();
+ // 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)
+ out = static_cast<std::uintmax_t>(-1);
+ };
+ do_mult(si.capacity, m_svfs.f_blocks);
+ do_mult(si.free, m_svfs.f_bfree);
+ do_mult(si.available, m_svfs.f_bavail);
+ return si;
+}
+
+file_status __status(const path& p, std::error_code *ec) {
+ return detail::posix_stat(p, ec);
+}
+
+file_status __symlink_status(const path& p, std::error_code *ec) {
+ return detail::posix_lstat(p, ec);
+}
+
+path __system_complete(const path& p, std::error_code *ec) {
+ if (ec) ec->clear();
+ return absolute(p, current_path());
+}
+
+path __temp_directory_path(std::error_code *ec) {
+ const char* env_paths[] = {"TMPDIR", "TMP", "TEMP", "TEMPDIR"};
+ const char* ret = nullptr;
+ for (auto & ep : env_paths) {
+ if ((ret = std::getenv(ep)))
+ break;
+ }
+ path p(ret ? ret : "/tmp");
+ std::error_code m_ec;
+ if (is_directory(p, m_ec)) {
+ if (ec) ec->clear();
+ return p;
+ }
+ if (!m_ec || m_ec == make_error_code(errc::no_such_file_or_directory))
+ m_ec = make_error_code(errc::not_a_directory);
+ set_or_throw(m_ec, ec, "temp_directory_path");
+ return {};
+}
+
+// An absolute path is composed according to the table in [fs.op.absolute].
+path absolute(const path& p, const path& base) {
+ auto root_name = p.root_name();
+ auto root_dir = p.root_directory();
+
+ if (!root_name.empty() && !root_dir.empty())
+ return p;
+
+ auto abs_base = base.is_absolute() ? base : absolute(base);
+
+ /* !has_root_name && !has_root_dir */
+ if (root_name.empty() && root_dir.empty())
+ {
+ return abs_base / p;
+ }
+ else if (!root_name.empty()) /* has_root_name && !has_root_dir */
+ {
+ return root_name / abs_base.root_directory()
+ /
+ abs_base.relative_path() / p.relative_path();
+ }
+ else /* !has_root_name && has_root_dir */
+ {
+ if (abs_base.has_root_name())
+ return abs_base.root_name() / p;
+ // else p is absolute, return outside of block
+ }
+ return p;
+}
+
+_LIBCPP_END_NAMESPACE_EXPERIMENTAL_FILESYSTEM
diff --git a/contrib/libc++/src/experimental/filesystem/path.cpp b/contrib/libc++/src/experimental/filesystem/path.cpp
new file mode 100644
index 0000000..38c4498
--- /dev/null
+++ b/contrib/libc++/src/experimental/filesystem/path.cpp
@@ -0,0 +1,391 @@
+//===--------------------- filesystem/path.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 "experimental/filesystem"
+#include "experimental/string_view"
+#include "utility"
+
+_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_FILESYSTEM
+
+_LIBCPP_CONSTEXPR path::value_type path::preferred_separator;
+
+namespace { namespace parser
+{
+
+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 &);
+
+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);
+
+inline bool is_separator(const string_type& s, size_t pos) {
+ return (pos < s.size() && s[pos] == preferred_separator);
+}
+
+inline bool is_root_name(const string_type& s, size_t pos) {
+ return good(pos) && pos == 0 ? root_name_start(s) == pos : false;
+}
+
+inline bool is_root_directory(const string_type& s, size_t pos) {
+ return good(pos) ? root_directory_start(s) == pos : false;
+}
+
+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));
+}
+
+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;
+}
+
+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;
+}
+
+inline size_t root_name_start(const string_type& s) {
+ return good(root_name_end(s)) ? 0 : npos;
+}
+
+size_t root_name_end(const string_type& s) {
+ if (s.size() < 2 || s[0] != preferred_separator
+ || s[1] != preferred_separator) {
+ return npos;
+ }
+ if (s.size() == 2) {
+ return 1;
+ }
+ size_t index = 2; // current position
+ if (s[index] == preferred_separator) {
+ return npos;
+ }
+ while (index + 1 < s.size() && s[index+1] != preferred_separator) {
+ ++index;
+ }
+ 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) {}
+
+ string_view operator*() const {
+ return parser::extract_preferred(__s_, __pos_);
+ }
+
+ path_view_iterator& operator++() {
+ increment();
+ return *this;
+ }
+
+ path_view_iterator& operator--() {
+ decrement();
+ return *this;
+ }
+
+ void increment() {
+ if (__pos_ == parser::npos) return;
+ while (! set_position(parser::end_of(__s_, __pos_)+1))
+ ;
+ return;
+ }
+
+ 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)))
+ ;
+ }
+ }
+
+ bool set_position(size_t pos) {
+ if (pos >= __s_.size()) {
+ __pos_ = parser::npos;
+ } else {
+ __pos_ = pos;
+ }
+ return valid_iterator_position();
+ }
+
+ 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_));
+ }
+
+ bool is_end() const { return __pos_ == parser::npos; }
+
+ inline bool operator==(path_view_iterator const& __p) {
+ return __pos_ == __p.__pos_;
+ }
+};
+
+path_view_iterator pbegin(path const& p) {
+ return path_view_iterator(p.native());
+}
+
+path_view_iterator pend(path const& p) {
+ path_view_iterator __p(p.native());
+ __p.__pos_ = parser::npos;
+ return __p;
+}
+
+} // end namespace
+///////////////////////////////////////////////////////////////////////////////
+// path definitions
+///////////////////////////////////////////////////////////////////////////////
+
+path & path::replace_extension(path const & replacement)
+{
+ path p = extension();
+ if (not p.empty()) {
+ __pn_.erase(__pn_.size() - p.native().size());
+ }
+ if (!replacement.empty()) {
+ if (replacement.native()[0] != '.') {
+ __pn_ += ".";
+ }
+ __pn_.append(replacement.__pn_);
+ }
+ return *this;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// path.decompose
+
+string_view path::__root_name() const
+{
+ return parser::is_root_name(__pn_, 0)
+ ? parser::extract_preferred(__pn_, 0)
+ : string_view{};
+}
+
+string_view 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);
+}
+
+string_view path::__relative_path() 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_);
+ }
+ if (not parser::good(end_i)) {
+ return {__pn_};
+ }
+ return string_view(__pn_).substr(end_i+1);
+}
+
+string_view path::__parent_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);
+}
+
+string_view path::__filename() const
+{
+ return empty() ? string_view{} : *--pend(*this);
+}
+
+string_view path::__stem() const
+{
+ return parser::separate_filename(__filename()).first;
+}
+
+string_view 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);
+ if (res != 0) return res;
+ ++thisIter; ++sIter;
+ }
+ if (thisIter.is_end() && sIter.is_end())
+ return 0;
+ if (thisIter.is_end())
+ 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};
+ 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;
+ }
+ return hp.first;
+}
+
+////////////////////////////////////////////////////////////////////////////
+// path.itr
+path::iterator path::begin() const
+{
+ path_view_iterator pit = pbegin(*this);
+ iterator it;
+ it.__path_ptr_ = this;
+ it.__pos_ = pit.__pos_;
+ it.__elem_.__assign_view(*pit);
+ return it;
+}
+
+path::iterator path::end() const
+{
+ iterator it{};
+ 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);
+ return *this;
+}
+
+path::iterator& path::iterator::__decrement() {
+ path_view_iterator it(__path_ptr_->native(), __pos_);
+ it.decrement();
+ __pos_ = it.__pos_;
+ __elem_.__assign_view(*it);
+ return *this;
+}
+
+_LIBCPP_END_NAMESPACE_EXPERIMENTAL_FILESYSTEM
diff --git a/contrib/libc++/src/experimental/memory_resource.cpp b/contrib/libc++/src/experimental/memory_resource.cpp
new file mode 100644
index 0000000..c01eb08
--- /dev/null
+++ b/contrib/libc++/src/experimental/memory_resource.cpp
@@ -0,0 +1,144 @@
+//===------------------------ memory_resource.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 "experimental/memory_resource"
+
+#ifndef _LIBCPP_HAS_NO_ATOMIC_HEADER
+#include "atomic"
+#elif !defined(_LIBCPP_HAS_NO_THREADS)
+#include "mutex"
+#endif
+
+_LIBCPP_BEGIN_NAMESPACE_LFTS_PMR
+
+// memory_resource
+
+//memory_resource::~memory_resource() {}
+
+// new_delete_resource()
+
+class _LIBCPP_TYPE_VIS_ONLY __new_delete_memory_resource_imp
+ : public memory_resource
+{
+public:
+ ~__new_delete_memory_resource_imp() = default;
+
+protected:
+ virtual void* do_allocate(size_t __size, size_t __align)
+ { return __allocate(__size); }
+
+ virtual void do_deallocate(void * __p, size_t, size_t)
+ { __deallocate(__p); }
+
+ virtual bool do_is_equal(memory_resource const & __other) const _NOEXCEPT
+ { return &__other == this; }
+};
+
+// null_memory_resource()
+
+class _LIBCPP_TYPE_VIS_ONLY __null_memory_resource_imp
+ : public memory_resource
+{
+public:
+ ~__null_memory_resource_imp() = default;
+
+protected:
+ virtual void* do_allocate(size_t, size_t) {
+#ifndef _LIBCPP_NO_EXCEPTIONS
+ throw std::bad_alloc();
+#else
+ abort();
+#endif
+ }
+ virtual void do_deallocate(void *, size_t, size_t) {}
+ virtual bool do_is_equal(memory_resource const & __other) const _NOEXCEPT
+ { return &__other == this; }
+};
+
+namespace {
+
+union ResourceInitHelper {
+ struct {
+ __new_delete_memory_resource_imp new_delete_res;
+ __null_memory_resource_imp null_res;
+ } resources;
+ char dummy;
+ _LIBCPP_CONSTEXPR_AFTER_CXX11 ResourceInitHelper() : resources() {}
+ ~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)));
+
+} // end namespace
+
+
+memory_resource * new_delete_resource() _NOEXCEPT {
+ return &res_init.resources.new_delete_res;
+}
+
+memory_resource * null_memory_resource() _NOEXCEPT {
+ return &res_init.resources.null_res;
+}
+
+// default_memory_resource()
+
+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 =
+ ATOMIC_VAR_INIT(&res_init.resources.new_delete_res);
+ if (set) {
+ new_res = new_res ? new_res : new_delete_resource();
+ // TODO: Can a weaker ordering be used?
+ return _VSTD::atomic_exchange_explicit(
+ &__res, new_res, memory_order::memory_order_acq_rel);
+ }
+ else {
+ return _VSTD::atomic_load_explicit(
+ &__res, memory_order::memory_order_acquire);
+ }
+#elif !defined(_LIBCPP_HAS_NO_THREADS)
+ 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();
+ lock_guard<mutex> guard(res_lock);
+ memory_resource * old_res = res;
+ res = new_res;
+ return old_res;
+ } else {
+ lock_guard<mutex> guard(res_lock);
+ return res;
+ }
+#else
+ 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;
+ res = new_res;
+ return old_res;
+ } else {
+ return res;
+ }
+#endif
+}
+
+memory_resource * get_default_resource() _NOEXCEPT
+{
+ return __default_memory_resource();
+}
+
+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
diff --git a/contrib/libc++/src/locale.cpp b/contrib/libc++/src/locale.cpp
index 6b04e78..da2fd11 100644
--- a/contrib/libc++/src/locale.cpp
+++ b/contrib/libc++/src/locale.cpp
@@ -123,11 +123,6 @@ const locale::category locale::time;
const locale::category locale::messages;
const locale::category locale::all;
-#if defined(__clang__)
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wpadded"
-#endif
-
class _LIBCPP_HIDDEN locale::__imp
: public facet
{
@@ -163,10 +158,6 @@ private:
template <class F> void install_from(const __imp& other);
};
-#if defined(__clang__)
-#pragma clang diagnostic pop
-#endif
-
locale::__imp::__imp(size_t refs)
: facet(refs),
facets_(N),
@@ -1409,33 +1400,21 @@ ctype_byname<wchar_t>::do_tolower(char_type* low, const char_type* high) const
wchar_t
ctype_byname<wchar_t>::do_widen(char c) const
{
-#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
- return btowc_l(c, __l);
-#else
- return __btowc_l(c, __l);
-#endif
+ return __libcpp_btowc_l(c, __l);
}
const char*
ctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
{
for (; low != high; ++low, ++dest)
-#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
- *dest = btowc_l(*low, __l);
-#else
- *dest = __btowc_l(*low, __l);
-#endif
+ *dest = __libcpp_btowc_l(*low, __l);
return low;
}
char
ctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const
{
-#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
- int r = wctob_l(c, __l);
-#else
- int r = __wctob_l(c, __l);
-#endif
+ int r = __libcpp_wctob_l(c, __l);
return r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
}
@@ -1444,11 +1423,7 @@ ctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, ch
{
for (; low != high; ++low, ++dest)
{
-#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
- int r = wctob_l(*low, __l);
-#else
- int r = __wctob_l(*low, __l);
-#endif
+ int r = __libcpp_wctob_l(*low, __l);
*dest = r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
}
return low;
@@ -1558,22 +1533,14 @@ codecvt<wchar_t, char, mbstate_t>::do_out(state_type& st,
{
// save state in case it is needed to recover to_nxt on error
mbstate_t save_state = st;
-#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
- size_t n = wcsnrtombs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
- static_cast<size_t>(to_end-to), &st, __l);
-#else
- size_t n = __wcsnrtombs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
-#endif
+ size_t n = __libcpp_wcsnrtombs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
+ static_cast<size_t>(to_end-to), &st, __l);
if (n == size_t(-1))
{
// need to recover to_nxt
for (to_nxt = to; frm != frm_nxt; ++frm)
{
-#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
- n = wcrtomb_l(to_nxt, *frm, &save_state, __l);
-#else
- n = __wcrtomb_l(to_nxt, *frm, &save_state, __l);
-#endif
+ n = __libcpp_wcrtomb_l(to_nxt, *frm, &save_state, __l);
if (n == size_t(-1))
break;
to_nxt += n;
@@ -1590,11 +1557,7 @@ codecvt<wchar_t, char, mbstate_t>::do_out(state_type& st,
{
// Try to write the terminating null
extern_type tmp[MB_LEN_MAX];
-#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
- n = wcrtomb_l(tmp, intern_type(), &st, __l);
-#else
- n = __wcrtomb_l(tmp, intern_type(), &st, __l);
-#endif
+ n = __libcpp_wcrtomb_l(tmp, intern_type(), &st, __l);
if (n == size_t(-1)) // on error
return error;
if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
@@ -1627,23 +1590,15 @@ codecvt<wchar_t, char, mbstate_t>::do_in(state_type& st,
{
// save state in case it is needed to recover to_nxt on error
mbstate_t save_state = st;
-#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
- size_t n = mbsnrtowcs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
- static_cast<size_t>(to_end-to), &st, __l);
-#else
- size_t n = __mbsnrtowcs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
-#endif
+ size_t n = __libcpp_mbsnrtowcs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
+ static_cast<size_t>(to_end-to), &st, __l);
if (n == size_t(-1))
{
// need to recover to_nxt
for (to_nxt = to; frm != frm_nxt; ++to_nxt)
{
-#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
- n = mbrtowc_l(to_nxt, frm, static_cast<size_t>(fend-frm),
- &save_state, __l);
-#else
- n = __mbrtowc_l(to_nxt, frm, fend-frm, &save_state, __l);
-#endif
+ n = __libcpp_mbrtowc_l(to_nxt, frm, static_cast<size_t>(fend-frm),
+ &save_state, __l);
switch (n)
{
case 0:
@@ -1671,11 +1626,7 @@ codecvt<wchar_t, char, mbstate_t>::do_in(state_type& st,
if (fend != frm_end) // set up next null terminated sequence
{
// Try to write the terminating null
-#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
- n = mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
-#else
- n = __mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
-#endif
+ n = __libcpp_mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
if (n != 0) // on error
return error;
++to_nxt;
@@ -1695,11 +1646,7 @@ codecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st,
{
to_nxt = to;
extern_type tmp[MB_LEN_MAX];
-#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
- size_t n = wcrtomb_l(tmp, intern_type(), &st, __l);
-#else
- size_t n = __wcrtomb_l(tmp, intern_type(), &st, __l);
-#endif
+ size_t n = __libcpp_wcrtomb_l(tmp, intern_type(), &st, __l);
if (n == size_t(-1) || n == 0) // on error
return error;
--n;
@@ -1713,21 +1660,11 @@ codecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st,
int
codecvt<wchar_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
{
-#ifndef __CloudABI__
-#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
- if (mbtowc_l(nullptr, nullptr, MB_LEN_MAX, __l) != 0)
-#else
- if (__mbtowc_l(nullptr, nullptr, MB_LEN_MAX, __l) != 0)
-#endif
+ if (__libcpp_mbtowc_l(nullptr, nullptr, MB_LEN_MAX, __l) != 0)
return -1;
-#endif
// stateless encoding
-#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
- if (__l == 0 || MB_CUR_MAX_L(__l) == 1) // there are no known constant length encodings
-#else
- if (__l == 0 || __mb_cur_max_l(__l) == 1) // there are no known constant length encodings
-#endif
+ if (__l == 0 || __libcpp_mb_cur_max_l(__l) == 1) // there are no known constant length encodings
return 1; // which take more than 1 char to form a wchar_t
return 0;
}
@@ -1745,11 +1682,7 @@ codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st,
int nbytes = 0;
for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t)
{
-#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
- size_t n = mbrlen_l(frm, static_cast<size_t>(frm_end-frm), &st, __l);
-#else
- size_t n = __mbrlen_l(frm, frm_end-frm, &st, __l);
-#endif
+ size_t n = __libcpp_mbrlen_l(frm, static_cast<size_t>(frm_end-frm), &st, __l);
switch (n)
{
case 0:
@@ -1771,11 +1704,7 @@ codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st,
int
codecvt<wchar_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
{
-#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
- return __l == 0 ? 1 : static_cast<int>( MB_CUR_MAX_L(__l));
-#else
- return __l == 0 ? 1 : static_cast<int>(__mb_cur_max_l(__l));
-#endif
+ return __l == 0 ? 1 : static_cast<int>(__libcpp_mb_cur_max_l(__l));
}
// Valid UTF ranges
@@ -2894,10 +2823,10 @@ ucs4_to_utf16le(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& f
to_nxt = to;
if (mode & generate_header)
{
- if (to_end-to_nxt < 2)
+ if (to_end - to_nxt < 2)
return codecvt_base::partial;
- *to_nxt++ = static_cast<uint8_t>(0xFF);
- *to_nxt++ = static_cast<uint8_t>(0xFE);
+ *to_nxt++ = static_cast<uint8_t>(0xFF);
+ *to_nxt++ = static_cast<uint8_t>(0xFE);
}
for (; frm_nxt < frm_end; ++frm_nxt)
{
@@ -4333,11 +4262,7 @@ numpunct_byname<char>::__init(const char* nm)
throw runtime_error("numpunct_byname<char>::numpunct_byname"
" failed to construct for " + string(nm));
#endif // _LIBCPP_NO_EXCEPTIONS
-#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
- lconv* lc = localeconv_l(loc.get());
-#else
- lconv* lc = __localeconv_l(loc.get());
-#endif
+ lconv* lc = __libcpp_localeconv_l(loc.get());
if (*lc->decimal_point)
__decimal_point_ = *lc->decimal_point;
if (*lc->thousands_sep)
@@ -4376,11 +4301,7 @@ numpunct_byname<wchar_t>::__init(const char* nm)
throw runtime_error("numpunct_byname<char>::numpunct_byname"
" failed to construct for " + string(nm));
#endif // _LIBCPP_NO_EXCEPTIONS
-#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
- lconv* lc = localeconv_l(loc.get());
-#else
- lconv* lc = __localeconv_l(loc.get());
-#endif
+ lconv* lc = __libcpp_localeconv_l(loc.get());
if (*lc->decimal_point)
__decimal_point_ = *lc->decimal_point;
if (*lc->thousands_sep)
@@ -4981,11 +4902,7 @@ __time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct)
wchar_t* wbb = wbuf;
mbstate_t mb = {0};
const char* bb = buf;
-#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
- size_t j = mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
-#else
- size_t j = __mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
-#endif
+ size_t j = __libcpp_mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
if (j == size_t(-1))
__throw_runtime_error("locale not supported");
wchar_t* wbe = wbb + j;
@@ -5165,11 +5082,7 @@ __time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
strftime_l(buf, countof(buf), "%A", &t, __loc_);
mb = mbstate_t();
const char* bb = buf;
-#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
- size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
-#else
- size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
-#endif
+ size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
if (j == size_t(-1))
__throw_runtime_error("locale not supported");
wbe = wbuf + j;
@@ -5177,11 +5090,7 @@ __time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
strftime_l(buf, countof(buf), "%a", &t, __loc_);
mb = mbstate_t();
bb = buf;
-#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
- j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
-#else
- j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
-#endif
+ j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
if (j == size_t(-1))
__throw_runtime_error("locale not supported");
wbe = wbuf + j;
@@ -5194,11 +5103,7 @@ __time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
strftime_l(buf, countof(buf), "%B", &t, __loc_);
mb = mbstate_t();
const char* bb = buf;
-#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
- size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
-#else
- size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
-#endif
+ size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
if (j == size_t(-1))
__throw_runtime_error("locale not supported");
wbe = wbuf + j;
@@ -5206,11 +5111,7 @@ __time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
strftime_l(buf, countof(buf), "%b", &t, __loc_);
mb = mbstate_t();
bb = buf;
-#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
- j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
-#else
- j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
-#endif
+ j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
if (j == size_t(-1))
__throw_runtime_error("locale not supported");
wbe = wbuf + j;
@@ -5221,11 +5122,7 @@ __time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
strftime_l(buf, countof(buf), "%p", &t, __loc_);
mb = mbstate_t();
const char* bb = buf;
-#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
- size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
-#else
- size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
-#endif
+ size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
if (j == size_t(-1))
__throw_runtime_error("locale not supported");
wbe = wbuf + j;
@@ -5234,11 +5131,7 @@ __time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
strftime_l(buf, countof(buf), "%p", &t, __loc_);
mb = mbstate_t();
bb = buf;
-#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
- j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
-#else
- j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
-#endif
+ j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
if (j == size_t(-1))
__throw_runtime_error("locale not supported");
wbe = wbuf + j;
@@ -5513,11 +5406,7 @@ __time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
__do_put(__nar, __ne, __tm, __fmt, __mod);
mbstate_t mb = {0};
const char* __nb = __nar;
-#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
- size_t j = mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
-#else
- size_t j = __mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
-#endif
+ size_t j = __libcpp_mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
if (j == size_t(-1))
__throw_runtime_error("locale not supported");
__we = __wb + j;
@@ -5908,11 +5797,7 @@ moneypunct_byname<char, false>::init(const char* nm)
throw runtime_error("moneypunct_byname"
" failed to construct for " + string(nm));
#endif // _LIBCPP_NO_EXCEPTIONS
-#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
- lconv* lc = localeconv_l(loc.get());
-#else
- lconv* lc = __localeconv_l(loc.get());
-#endif
+ lconv* lc = __libcpp_localeconv_l(loc.get());
if (*lc->mon_decimal_point)
__decimal_point_ = *lc->mon_decimal_point;
else
@@ -5956,11 +5841,7 @@ moneypunct_byname<char, true>::init(const char* nm)
throw runtime_error("moneypunct_byname"
" failed to construct for " + string(nm));
#endif // _LIBCPP_NO_EXCEPTIONS
-#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
- lconv* lc = localeconv_l(loc.get());
-#else
- lconv* lc = __localeconv_l(loc.get());
-#endif
+ lconv* lc = __libcpp_localeconv_l(loc.get());
if (*lc->mon_decimal_point)
__decimal_point_ = *lc->mon_decimal_point;
else
@@ -6021,11 +5902,7 @@ moneypunct_byname<wchar_t, false>::init(const char* nm)
throw runtime_error("moneypunct_byname"
" failed to construct for " + string(nm));
#endif // _LIBCPP_NO_EXCEPTIONS
-#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
- lconv* lc = localeconv_l(loc.get());
-#else
- lconv* lc = __localeconv_l(loc.get());
-#endif
+ lconv* lc = __libcpp_localeconv_l(loc.get());
if (*lc->mon_decimal_point)
__decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
else
@@ -6038,11 +5915,7 @@ moneypunct_byname<wchar_t, false>::init(const char* nm)
wchar_t wbuf[100];
mbstate_t mb = {0};
const char* bb = lc->currency_symbol;
-#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
- size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
-#else
- size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
-#endif
+ size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
if (j == size_t(-1))
__throw_runtime_error("locale not supported");
wchar_t* wbe = wbuf + j;
@@ -6057,11 +5930,7 @@ moneypunct_byname<wchar_t, false>::init(const char* nm)
{
mb = mbstate_t();
bb = lc->positive_sign;
-#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
- j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
-#else
- j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
-#endif
+ j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
if (j == size_t(-1))
__throw_runtime_error("locale not supported");
wbe = wbuf + j;
@@ -6073,11 +5942,7 @@ moneypunct_byname<wchar_t, false>::init(const char* nm)
{
mb = mbstate_t();
bb = lc->negative_sign;
-#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
- j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
-#else
- j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
-#endif
+ j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
if (j == size_t(-1))
__throw_runtime_error("locale not supported");
wbe = wbuf + j;
@@ -6104,11 +5969,7 @@ moneypunct_byname<wchar_t, true>::init(const char* nm)
throw runtime_error("moneypunct_byname"
" failed to construct for " + string(nm));
#endif // _LIBCPP_NO_EXCEPTIONS
-#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
- lconv* lc = localeconv_l(loc.get());
-#else
- lconv* lc = __localeconv_l(loc.get());
-#endif
+ lconv* lc = __libcpp_localeconv_l(loc.get());
if (*lc->mon_decimal_point)
__decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
else
@@ -6121,11 +5982,7 @@ moneypunct_byname<wchar_t, true>::init(const char* nm)
wchar_t wbuf[100];
mbstate_t mb = {0};
const char* bb = lc->int_curr_symbol;
-#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
- size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
-#else
- size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
-#endif
+ size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
if (j == size_t(-1))
__throw_runtime_error("locale not supported");
wchar_t* wbe = wbuf + j;
@@ -6144,11 +6001,7 @@ moneypunct_byname<wchar_t, true>::init(const char* nm)
{
mb = mbstate_t();
bb = lc->positive_sign;
-#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
- j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
-#else
- j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
-#endif
+ j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
if (j == size_t(-1))
__throw_runtime_error("locale not supported");
wbe = wbuf + j;
@@ -6164,11 +6017,7 @@ moneypunct_byname<wchar_t, true>::init(const char* nm)
{
mb = mbstate_t();
bb = lc->negative_sign;
-#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
- j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
-#else
- j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
-#endif
+ j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
if (j == size_t(-1))
__throw_runtime_error("locale not supported");
wbe = wbuf + j;
diff --git a/contrib/libc++/src/memory.cpp b/contrib/libc++/src/memory.cpp
index 5b81f26..15e947f 100644
--- a/contrib/libc++/src/memory.cpp
+++ b/contrib/libc++/src/memory.cpp
@@ -124,15 +124,15 @@ __shared_weak_count::__get_deleter(const type_info&) const _NOEXCEPT
#endif // _LIBCPP_NO_RTTI
-#if defined(_LIBCPP_HAS_C_ATOMIC_IMP) && !defined(_LIBCPP_HAS_NO_THREADS)
+#if !defined(_LIBCPP_HAS_NO_ATOMIC_HEADER)
static const std::size_t __sp_mut_count = 16;
-static pthread_mutex_t mut_back_imp[__sp_mut_count] =
+static __libcpp_mutex_t mut_back_imp[__sp_mut_count] =
{
- PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER,
- PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER,
- PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER,
- PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER
+ _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER,
+ _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER,
+ _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER,
+ _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER
};
static mutex* mut_back = reinterpret_cast<std::mutex*>(mut_back_imp);
@@ -177,7 +177,7 @@ __get_sp_mut(const void* p)
return muts[hash<const void*>()(p) & (__sp_mut_count-1)];
}
-#endif // defined(_LIBCPP_HAS_C_ATOMIC_IMP) && !defined(_LIBCPP_HAS_NO_THREADS)
+#endif // !defined(_LIBCPP_HAS_NO_ATOMIC_HEADER)
void
declare_reachable(void*)
diff --git a/contrib/libc++/src/mutex.cpp b/contrib/libc++/src/mutex.cpp
index 127e67a..9f808ca 100644
--- a/contrib/libc++/src/mutex.cpp
+++ b/contrib/libc++/src/mutex.cpp
@@ -23,13 +23,13 @@ const adopt_lock_t adopt_lock = {};
mutex::~mutex()
{
- pthread_mutex_destroy(&__m_);
+ __libcpp_mutex_destroy(&__m_);
}
void
mutex::lock()
{
- int ec = pthread_mutex_lock(&__m_);
+ int ec = __libcpp_mutex_lock(&__m_);
if (ec)
__throw_system_error(ec, "mutex lock failed");
}
@@ -37,13 +37,13 @@ mutex::lock()
bool
mutex::try_lock() _NOEXCEPT
{
- return pthread_mutex_trylock(&__m_) == 0;
+ return __libcpp_mutex_trylock(&__m_) == 0;
}
void
mutex::unlock() _NOEXCEPT
{
- int ec = pthread_mutex_unlock(&__m_);
+ int ec = __libcpp_mutex_unlock(&__m_);
(void)ec;
assert(ec == 0);
}
@@ -52,36 +52,14 @@ mutex::unlock() _NOEXCEPT
recursive_mutex::recursive_mutex()
{
- pthread_mutexattr_t attr;
- int ec = pthread_mutexattr_init(&attr);
+ int ec = __libcpp_recursive_mutex_init(&__m_);
if (ec)
- goto fail;
- ec = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
- if (ec)
- {
- pthread_mutexattr_destroy(&attr);
- goto fail;
- }
- ec = pthread_mutex_init(&__m_, &attr);
- if (ec)
- {
- pthread_mutexattr_destroy(&attr);
- goto fail;
- }
- ec = pthread_mutexattr_destroy(&attr);
- if (ec)
- {
- pthread_mutex_destroy(&__m_);
- goto fail;
- }
- return;
-fail:
- __throw_system_error(ec, "recursive_mutex constructor failed");
+ __throw_system_error(ec, "recursive_mutex constructor failed");
}
recursive_mutex::~recursive_mutex()
{
- int e = pthread_mutex_destroy(&__m_);
+ int e = __libcpp_mutex_destroy(&__m_);
(void)e;
assert(e == 0);
}
@@ -89,7 +67,7 @@ recursive_mutex::~recursive_mutex()
void
recursive_mutex::lock()
{
- int ec = pthread_mutex_lock(&__m_);
+ int ec = __libcpp_mutex_lock(&__m_);
if (ec)
__throw_system_error(ec, "recursive_mutex lock failed");
}
@@ -97,7 +75,7 @@ recursive_mutex::lock()
void
recursive_mutex::unlock() _NOEXCEPT
{
- int e = pthread_mutex_unlock(&__m_);
+ int e = __libcpp_mutex_unlock(&__m_);
(void)e;
assert(e == 0);
}
@@ -105,7 +83,7 @@ recursive_mutex::unlock() _NOEXCEPT
bool
recursive_mutex::try_lock() _NOEXCEPT
{
- return pthread_mutex_trylock(&__m_) == 0;
+ return __libcpp_mutex_trylock(&__m_) == 0;
}
// timed_mutex
@@ -165,9 +143,9 @@ recursive_timed_mutex::~recursive_timed_mutex()
void
recursive_timed_mutex::lock()
{
- pthread_t id = pthread_self();
+ __libcpp_thread_id id = __libcpp_thread_get_current_id();
unique_lock<mutex> lk(__m_);
- if (pthread_equal(id, __id_))
+ if (__libcpp_thread_id_equal(id, __id_))
{
if (__count_ == numeric_limits<size_t>::max())
__throw_system_error(EAGAIN, "recursive_timed_mutex lock limit reached");
@@ -183,9 +161,9 @@ recursive_timed_mutex::lock()
bool
recursive_timed_mutex::try_lock() _NOEXCEPT
{
- pthread_t id = pthread_self();
+ __libcpp_thread_id id = __libcpp_thread_get_current_id();
unique_lock<mutex> lk(__m_, try_to_lock);
- if (lk.owns_lock() && (__count_ == 0 || pthread_equal(id, __id_)))
+ if (lk.owns_lock() && (__count_ == 0 || __libcpp_thread_id_equal(id, __id_)))
{
if (__count_ == numeric_limits<size_t>::max())
return false;
@@ -217,8 +195,8 @@ recursive_timed_mutex::unlock() _NOEXCEPT
// keep in sync with: 7741191.
#ifndef _LIBCPP_HAS_NO_THREADS
-static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
-static pthread_cond_t cv = PTHREAD_COND_INITIALIZER;
+static __libcpp_mutex_t mut = _LIBCPP_MUTEX_INITIALIZER;
+static __libcpp_condvar_t cv = _LIBCPP_CONDVAR_INITIALIZER;
#endif
/// NOTE: Changes to flag are done via relaxed atomic stores
@@ -247,9 +225,9 @@ __call_once(volatile unsigned long& flag, void* arg, void(*func)(void*))
#endif // _LIBCPP_NO_EXCEPTIONS
}
#else // !_LIBCPP_HAS_NO_THREADS
- pthread_mutex_lock(&mut);
+ __libcpp_mutex_lock(&mut);
while (flag == 1)
- pthread_cond_wait(&cv, &mut);
+ __libcpp_condvar_wait(&cv, &mut);
if (flag == 0)
{
#ifndef _LIBCPP_NO_EXCEPTIONS
@@ -257,26 +235,26 @@ __call_once(volatile unsigned long& flag, void* arg, void(*func)(void*))
{
#endif // _LIBCPP_NO_EXCEPTIONS
__libcpp_relaxed_store(&flag, 1ul);
- pthread_mutex_unlock(&mut);
+ __libcpp_mutex_unlock(&mut);
func(arg);
- pthread_mutex_lock(&mut);
+ __libcpp_mutex_lock(&mut);
__libcpp_relaxed_store(&flag, ~0ul);
- pthread_mutex_unlock(&mut);
- pthread_cond_broadcast(&cv);
+ __libcpp_mutex_unlock(&mut);
+ __libcpp_condvar_broadcast(&cv);
#ifndef _LIBCPP_NO_EXCEPTIONS
}
catch (...)
{
- pthread_mutex_lock(&mut);
+ __libcpp_mutex_lock(&mut);
__libcpp_relaxed_store(&flag, 0ul);
- pthread_mutex_unlock(&mut);
- pthread_cond_broadcast(&cv);
+ __libcpp_mutex_unlock(&mut);
+ __libcpp_condvar_broadcast(&cv);
throw;
}
#endif // _LIBCPP_NO_EXCEPTIONS
}
else
- pthread_mutex_unlock(&mut);
+ __libcpp_mutex_unlock(&mut);
#endif // !_LIBCPP_HAS_NO_THREADS
}
diff --git a/contrib/libc++/src/regex.cpp b/contrib/libc++/src/regex.cpp
index 17dd6ea..a736359 100644
--- a/contrib/libc++/src/regex.cpp
+++ b/contrib/libc++/src/regex.cpp
@@ -69,21 +69,12 @@ regex_error::~regex_error() throw() {}
namespace {
-#if defined(__clang__)
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wpadded"
-#endif
-
struct collationnames
{
const char* elem_;
char char_;
};
-#if defined(__clang__)
-#pragma clang diagnostic pop
-#endif
-
const collationnames collatenames[] =
{
{"A", 0x41},
@@ -199,21 +190,12 @@ const collationnames collatenames[] =
{"zero", 0x30}
};
-#if defined(__clang__)
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wpadded"
-#endif
-
struct classnames
{
const char* elem_;
regex_traits<char>::char_class_type mask_;
};
-#if defined(__clang__)
-#pragma clang diagnostic pop
-#endif
-
const classnames ClassNames[] =
{
{"alnum", ctype_base::alnum},
diff --git a/contrib/libc++/src/strstream.cpp b/contrib/libc++/src/strstream.cpp
index ea72813..0e2d7ff 100644
--- a/contrib/libc++/src/strstream.cpp
+++ b/contrib/libc++/src/strstream.cpp
@@ -11,6 +11,7 @@
#include "algorithm"
#include "climits"
#include "cstring"
+#include "__debug"
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -167,11 +168,13 @@ strstreambuf::overflow(int_type __c)
buf = new char[new_size];
if (buf == nullptr)
return int_type(EOF);
- memcpy(buf, eback(), static_cast<size_t>(old_size));
+ if (old_size != 0) {
+ _LIBCPP_ASSERT(eback(), "overflow copying from NULL");
+ memcpy(buf, eback(), static_cast<size_t>(old_size));
+ }
ptrdiff_t ninp = gptr() - eback();
ptrdiff_t einp = egptr() - eback();
ptrdiff_t nout = pptr() - pbase();
- ptrdiff_t eout = epptr() - pbase();
if (__strmode_ & __allocated)
{
if (__pfree_)
@@ -180,7 +183,7 @@ strstreambuf::overflow(int_type __c)
delete [] eback();
}
setg(buf, buf + ninp, buf + einp);
- setp(buf + einp, buf + einp + eout);
+ setp(buf + einp, buf + new_size);
pbump(static_cast<int>(nout));
__strmode_ |= __allocated;
}
diff --git a/contrib/libc++/src/system_error.cpp b/contrib/libc++/src/system_error.cpp
index 3023e20..87f35ae 100644
--- a/contrib/libc++/src/system_error.cpp
+++ b/contrib/libc++/src/system_error.cpp
@@ -13,8 +13,17 @@
#include "system_error"
#include "include/config_elast.h"
+#include "cerrno"
#include "cstring"
+#include "cstdio"
+#include "cstdlib"
+#include "cassert"
#include "string"
+#include "string.h"
+
+#if defined(__ANDROID__)
+#include <android/api-level.h>
+#endif
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -46,10 +55,56 @@ error_category::equivalent(const error_code& code, int condition) const _NOEXCEP
return *this == code.category() && code.value() == condition;
}
+namespace {
+
+// GLIBC also uses 1024 as the maximum buffer size internally.
+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)
+// GNU Extended version
+string do_strerror_r(int ev) {
+ char buffer[strerror_buff_size];
+ char* ret = ::strerror_r(ev, buffer, strerror_buff_size);
+ return string(ret);
+}
+#else
+// POSIX version
+string do_strerror_r(int ev) {
+ char buffer[strerror_buff_size];
+ const int old_errno = errno;
+ int ret;
+ if ((ret = ::strerror_r(ev, buffer, strerror_buff_size)) != 0) {
+ // If `ret == -1` then the error is specified using `errno`, otherwise
+ // `ret` represents the error.
+ const int new_errno = ret == -1 ? errno : ret;
+ errno = old_errno;
+ if (new_errno == EINVAL) {
+ std::snprintf(buffer, strerror_buff_size, "Unknown error %d", ev);
+ return string(buffer);
+ } else {
+ assert(new_errno == ERANGE);
+ // FIXME maybe? 'strerror_buff_size' is likely to exceed the
+ // maximum error size so ERANGE shouldn't be returned.
+ std::abort();
+ }
+ }
+ return string(buffer);
+}
+#endif
+
+} // end namespace
+
string
__do_message::message(int ev) const
{
- return string(strerror(ev));
+#if defined(_LIBCPP_HAS_NO_THREADS)
+ return string(::strerror(ev));
+#else
+ return do_strerror_r(ev);
+#endif
}
class _LIBCPP_HIDDEN __generic_error_category
diff --git a/contrib/libc++/src/thread.cpp b/contrib/libc++/src/thread.cpp
index bd27f28..467402b 100644
--- a/contrib/libc++/src/thread.cpp
+++ b/contrib/libc++/src/thread.cpp
@@ -16,10 +16,15 @@
#include "future"
#include "limits"
#include <sys/types.h>
-#if !defined(_WIN32)
-# if !defined(__sun__) && !defined(__linux__) && !defined(_AIX) && !defined(__native_client__) && !defined(__CloudABI__)
+
+#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
+# include <sys/param.h>
+# if defined(BSD)
# include <sys/sysctl.h>
-# endif // !defined(__sun__) && !defined(__linux__) && !defined(_AIX) && !defined(__native_client__) && !defined(__CloudABI__)
+# endif // defined(BSD)
+#endif // defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
+
+#if !defined(_WIN32)
# include <unistd.h>
#endif // !_WIN32
@@ -41,14 +46,17 @@ thread::~thread()
void
thread::join()
{
- int ec = pthread_join(__t_, 0);
+ int ec = EINVAL;
+ if (__t_ != 0)
+ {
+ ec = __libcpp_thread_join(&__t_);
+ if (ec == 0)
+ __t_ = 0;
+ }
#ifndef _LIBCPP_NO_EXCEPTIONS
if (ec)
throw system_error(error_code(ec, system_category()), "thread::join failed");
-#else
- (void)ec;
#endif // _LIBCPP_NO_EXCEPTIONS
- __t_ = 0;
}
void
@@ -57,7 +65,7 @@ thread::detach()
int ec = EINVAL;
if (__t_ != 0)
{
- ec = pthread_detach(__t_);
+ ec = __libcpp_thread_detach(&__t_);
if (ec == 0)
__t_ = 0;
}
OpenPOWER on IntegriCloud