diff options
Diffstat (limited to 'contrib/libc++/src')
26 files changed, 1106 insertions, 569 deletions
| diff --git a/contrib/libc++/src/algorithm.cpp b/contrib/libc++/src/algorithm.cpp index e9752b0653e0..f036eb7abe1c 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 f77684578905..45b2337eb353 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 62149fbf420c..8c8e6b5d31ad 100644 --- a/contrib/libc++/src/chrono.cpp +++ b/contrib/libc++/src/chrono.cpp @@ -12,14 +12,23 @@  #include "system_error"  // __throw_system_error  #include <time.h>        // clock_gettime, CLOCK_MONOTONIC and CLOCK_REALTIME +#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)  #include <sys/time.h>        // for gettimeofday and timeval -#endif +#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,6 +45,31 @@ const bool system_clock::is_steady;  system_clock::time_point  system_clock::now() _NOEXCEPT  { +#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  #ifdef CLOCK_REALTIME      struct timespec tp;      if (0 != clock_gettime(CLOCK_REALTIME, &tp)) @@ -46,6 +80,7 @@ system_clock::now() _NOEXCEPT      gettimeofday(&tv, 0);      return time_point(seconds(tv.tv_sec) + microseconds(tv.tv_usec));  #endif  // CLOCK_REALTIME +#endif  }  time_t @@ -69,18 +104,7 @@ system_clock::from_time_t(time_t t) _NOEXCEPT  const bool steady_clock::is_steady; -#ifdef CLOCK_MONOTONIC - -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)); -} - -#elif defined(__APPLE__) +#if defined(__APPLE__)  //   mach_absolute_time() * MachInfo.numer / MachInfo.denom is the number of  //   nanoseconds since the computer booted up.  MachInfo.numer and MachInfo.denom @@ -90,8 +114,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,8 +151,6 @@ init_steady_clock()      return &steady_full;  } -#pragma GCC visibility pop -  steady_clock::time_point  steady_clock::now() _NOEXCEPT  { @@ -138,6 +158,32 @@ steady_clock::now() _NOEXCEPT      return time_point(duration(fp()));  } +#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) + +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"  #endif diff --git a/contrib/libc++/src/condition_variable.cpp b/contrib/libc++/src/condition_variable.cpp index bfb4bf3925f7..25e66038eec0 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 b1a16e6e72d4..f2fc1ceb495a 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 e172f642d483..ec8969aaf4c0 100644 --- a/contrib/libc++/src/exception.cpp +++ b/contrib/libc++/src/exception.cpp @@ -12,7 +12,8 @@  #include "exception"  #include "new" -#if defined(__APPLE__) && !defined(LIBCXXRT) +#if defined(__APPLE__) && !defined(LIBCXXRT) && \ +    !defined(_LIBCPP_BUILDING_HAS_NO_ABI_LIBRARY)    #include <cxxabi.h>    using namespace __cxxabiv1; @@ -32,8 +33,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 @@ -106,7 +107,8 @@ 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(); diff --git a/contrib/libc++/src/experimental/filesystem/directory_iterator.cpp b/contrib/libc++/src/experimental/filesystem/directory_iterator.cpp index fa217ba7a12c..a888dcfa1190 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 369996fcbe62..6c7e4cf24888 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 38c449832f6e..96b81f7b0a70 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 c01eb0823bae..cc6aab38e058 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: @@ -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 8b719c5f2214..af0f5f505ea5 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 9d6a76b0c004..97104290d883 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,13 +22,15 @@  #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) +#elif defined(_LIBCPP_MSVCRT)  #define _LIBCPP_ELAST _sys_nerr  #else  // Warn here so that the person doing the libcxx port has an easier time: diff --git a/contrib/libc++/src/ios.cpp b/contrib/libc++/src/ios.cpp index 23e3ee0ca044..7c76ca258b26 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/locale.cpp b/contrib/libc++/src/locale.cpp index da2fd11678d6..4b462664a60c 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) @@ -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 15e947fc0ff8..8569fafb337c 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 9f808ca5076c..9397ae73ca4f 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 f4f73d86803d..782aac90fb7a 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,39 @@ operator new(std::size_t size)      return p;  } -_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS +_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, const std::nothrow_t&) _NOEXCEPT  { @@ -83,17 +114,40 @@ 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, 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) _THROW_BAD_ALLOC  {      return ::operator new(size);  } -_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS +_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, const std::nothrow_t&) _NOEXCEPT  { @@ -112,7 +166,26 @@ 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, 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) _NOEXCEPT  { @@ -120,41 +193,84 @@ operator delete(void* ptr) _NOEXCEPT          ::free(ptr);  } -_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS +_LIBCPP_WEAK +void +operator delete(void* ptr, std::align_val_t) _NOEXCEPT +{ +    if (ptr) +        ::free(ptr); +} + +_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, std::align_val_t alignment, const std::nothrow_t&) _NOEXCEPT +{ +    ::operator delete(ptr, alignment); +} + +_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, size_t, std::align_val_t alignment) _NOEXCEPT +{ +    ::operator delete(ptr, alignment); +} + +_LIBCPP_WEAK  void  operator delete[] (void* ptr) _NOEXCEPT  {      ::operator delete(ptr);  } -_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS +_LIBCPP_WEAK +void +operator delete[] (void* ptr, std::align_val_t alignment) _NOEXCEPT +{ +    ::operator delete(ptr, alignment); +} + +_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, std::align_val_t alignment, const std::nothrow_t&) _NOEXCEPT +{ +    ::operator delete[](ptr, alignment); +} + +_LIBCPP_WEAK  void  operator delete[] (void* ptr, size_t) _NOEXCEPT  {      ::operator delete[](ptr);  } +_LIBCPP_WEAK +void +operator delete[] (void* ptr, size_t, std::align_val_t alignment) _NOEXCEPT +{ +    ::operator delete[](ptr, alignment); +} +  #endif // !__GLIBCXX__  namespace std @@ -206,6 +322,8 @@ bad_array_new_length::bad_array_new_length() _NOEXCEPT  {  } +#ifndef __GLIBCXX__ +  bad_array_new_length::~bad_array_new_length() _NOEXCEPT  {  } @@ -216,22 +334,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 +365,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 8c5dd76d86d6..f2fbfdfec1ce 100644 --- a/contrib/libc++/src/optional.cpp +++ b/contrib/libc++/src/optional.cpp @@ -7,18 +7,18 @@  //  //===----------------------------------------------------------------------===// +#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 {} +} // std -#else +_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL  bad_optional_access::~bad_optional_access() _NOEXCEPT = default; -#endif -  _LIBCPP_END_NAMESPACE_EXPERIMENTAL diff --git a/contrib/libc++/src/random.cpp b/contrib/libc++/src/random.cpp index 4ab424eaa6e5..eb2510a48c85 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 0a08bfec27ec..3f333309dd8f 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 d3f29df639f4..cd644330b3a7 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 0e2d7ff21bb9..be94f9c89e83 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 87f35ae37f39..c54712476828 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 467402b6b423..4fb1dd21fc2c 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; diff --git a/contrib/libc++/src/typeinfo.cpp b/contrib/libc++/src/typeinfo.cpp index 5c0a609b5e5c..d0a7dae38025 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 000000000000..5bb508c3f467 --- /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 | 
