diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2021-10-02 10:45:56 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2021-10-02 10:45:56 -0700 |
| commit | dde0adcb363f3a3f306c0fc9eaec511cc3b74965 (patch) | |
| tree | 9388d039a0b77211936c7264f5a3179f63ad51e6 /lib/libcxx/src | |
| parent | c4cd592f0e1eeff5a4056796610d97010ae4e38c (diff) | |
| parent | 7a2624c3e40e2386a4a8a775b839e1d67608ec42 (diff) | |
| download | zig-dde0adcb363f3a3f306c0fc9eaec511cc3b74965.tar.gz zig-dde0adcb363f3a3f306c0fc9eaec511cc3b74965.zip | |
Merge branch 'llvm13'
Diffstat (limited to 'lib/libcxx/src')
42 files changed, 1504 insertions, 547 deletions
diff --git a/lib/libcxx/src/any.cpp b/lib/libcxx/src/any.cpp index 0cf0906883..415d23b0c9 100644 --- a/lib/libcxx/src/any.cpp +++ b/lib/libcxx/src/any.cpp @@ -9,7 +9,7 @@ #include "any" namespace std { -const char* bad_any_cast::what() const _NOEXCEPT { +const char* bad_any_cast::what() const noexcept { return "bad any cast"; } } @@ -24,10 +24,10 @@ _LIBCPP_BEGIN_NAMESPACE_LFTS class _LIBCPP_EXCEPTION_ABI _LIBCPP_AVAILABILITY_BAD_ANY_CAST bad_any_cast : public bad_cast { public: - virtual const char* what() const _NOEXCEPT; + virtual const char* what() const noexcept; }; -const char* bad_any_cast::what() const _NOEXCEPT { +const char* bad_any_cast::what() const noexcept { return "bad any cast"; } diff --git a/lib/libcxx/src/charconv.cpp b/lib/libcxx/src/charconv.cpp index 8cfe40d156..78439f9683 100644 --- a/lib/libcxx/src/charconv.cpp +++ b/lib/libcxx/src/charconv.cpp @@ -99,7 +99,7 @@ append8_no_zeros(char* buffer, T v) noexcept } char* -__u32toa(uint32_t value, char* buffer) _NOEXCEPT +__u32toa(uint32_t value, char* buffer) noexcept { if (value < 100000000) { @@ -120,7 +120,7 @@ __u32toa(uint32_t value, char* buffer) _NOEXCEPT } char* -__u64toa(uint64_t value, char* buffer) _NOEXCEPT +__u64toa(uint64_t value, char* buffer) noexcept { if (value < 100000000) { diff --git a/lib/libcxx/src/chrono.cpp b/lib/libcxx/src/chrono.cpp index 085fbfde26..13b375947b 100644 --- a/lib/libcxx/src/chrono.cpp +++ b/lib/libcxx/src/chrono.cpp @@ -6,9 +6,20 @@ // //===----------------------------------------------------------------------===// +#if defined(__MVS__) +// As part of monotonic clock support on z/OS we need macro _LARGE_TIME_API +// to be defined before any system header to include definition of struct timespec64. +#define _LARGE_TIME_API +#endif + #include "chrono" #include "cerrno" // errno #include "system_error" // __throw_system_error + +#if defined(__MVS__) +#include <__support/ibm/gettod_zos.h> // gettimeofdayMonotonic +#endif + #include <time.h> // clock_gettime and CLOCK_{MONOTONIC,REALTIME,MONOTONIC_RAW} #include "include/apple_availability.h" @@ -20,7 +31,7 @@ # include <sys/time.h> // for gettimeofday and timeval #endif -#if !defined(__APPLE__) && _POSIX_TIMERS > 0 +#if !defined(__APPLE__) && defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0 # define _LIBCPP_USE_CLOCK_GETTIME #endif @@ -96,19 +107,19 @@ static system_clock::time_point __libcpp_system_clock_now() { const bool system_clock::is_steady; system_clock::time_point -system_clock::now() _NOEXCEPT +system_clock::now() noexcept { return __libcpp_system_clock_now(); } time_t -system_clock::to_time_t(const time_point& t) _NOEXCEPT +system_clock::to_time_t(const time_point& t) noexcept { return time_t(duration_cast<seconds>(t.time_since_epoch()).count()); } system_clock::time_point -system_clock::from_time_t(time_t t) _NOEXCEPT +system_clock::from_time_t(time_t t) noexcept { return system_clock::time_point(seconds(t)); } @@ -218,6 +229,16 @@ static steady_clock::time_point __libcpp_steady_clock_now() { return steady_clock::time_point(steady_clock::duration(dur)); } +#elif defined(__MVS__) + +static steady_clock::time_point __libcpp_steady_clock_now() { + struct timespec64 ts; + if (0 != gettimeofdayMonotonic(&ts)) + __throw_system_error(errno, "failed to obtain time of day"); + + return steady_clock::time_point(seconds(ts.tv_sec) + nanoseconds(ts.tv_nsec)); +} + #elif defined(CLOCK_MONOTONIC) static steady_clock::time_point __libcpp_steady_clock_now() { @@ -234,7 +255,7 @@ static steady_clock::time_point __libcpp_steady_clock_now() { const bool steady_clock::is_steady; steady_clock::time_point -steady_clock::now() _NOEXCEPT +steady_clock::now() noexcept { return __libcpp_steady_clock_now(); } diff --git a/lib/libcxx/src/condition_variable.cpp b/lib/libcxx/src/condition_variable.cpp index d133b010d7..1e29083e6e 100644 --- a/lib/libcxx/src/condition_variable.cpp +++ b/lib/libcxx/src/condition_variable.cpp @@ -24,19 +24,19 @@ _LIBCPP_BEGIN_NAMESPACE_STD // ~condition_variable is defined elsewhere. void -condition_variable::notify_one() _NOEXCEPT +condition_variable::notify_one() noexcept { __libcpp_condvar_signal(&__cv_); } void -condition_variable::notify_all() _NOEXCEPT +condition_variable::notify_all() noexcept { __libcpp_condvar_broadcast(&__cv_); } void -condition_variable::wait(unique_lock<mutex>& lk) _NOEXCEPT +condition_variable::wait(unique_lock<mutex>& lk) noexcept { if (!lk.owns_lock()) __throw_system_error(EPERM, @@ -48,7 +48,7 @@ condition_variable::wait(unique_lock<mutex>& lk) _NOEXCEPT void condition_variable::__do_timed_wait(unique_lock<mutex>& lk, - chrono::time_point<chrono::system_clock, chrono::nanoseconds> tp) _NOEXCEPT + chrono::time_point<chrono::system_clock, chrono::nanoseconds> tp) noexcept { using namespace chrono; if (!lk.owns_lock()) diff --git a/lib/libcxx/src/debug.cpp b/lib/libcxx/src/debug.cpp index 20055fcf75..dd5963fcce 100644 --- a/lib/libcxx/src/debug.cpp +++ b/lib/libcxx/src/debug.cpp @@ -438,7 +438,7 @@ __libcpp_db::__less_than_comparable(const void* __i, const void* __j) const __i_node* j = __find_iterator(__j); __c_node* ci = i != nullptr ? i->__c_ : nullptr; __c_node* cj = j != nullptr ? j->__c_ : nullptr; - return ci != nullptr && ci == cj; + return ci == cj; } void diff --git a/lib/libcxx/src/experimental/memory_resource.cpp b/lib/libcxx/src/experimental/memory_resource.cpp index 1304ef3df7..ffe8021514 100644 --- a/lib/libcxx/src/experimental/memory_resource.cpp +++ b/lib/libcxx/src/experimental/memory_resource.cpp @@ -40,7 +40,7 @@ class _LIBCPP_TYPE_VIS __new_delete_memory_resource_imp _VSTD::__libcpp_deallocate(p, n, align); } - bool do_is_equal(memory_resource const & other) const _NOEXCEPT override + bool do_is_equal(memory_resource const & other) const noexcept override { return &other == this; } public: @@ -60,7 +60,7 @@ protected: __throw_bad_alloc(); } virtual void do_deallocate(void *, size_t, size_t) {} - virtual bool do_is_equal(memory_resource const & __other) const _NOEXCEPT + virtual bool do_is_equal(memory_resource const & __other) const noexcept { return &__other == this; } }; @@ -76,28 +76,23 @@ union ResourceInitHelper { ~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. -#if _LIBCPP_STD_VER > 11 -_LIBCPP_SAFE_STATIC -#endif -ResourceInitHelper res_init _LIBCPP_INIT_PRIORITY_MAX; +_LIBCPP_SAFE_STATIC ResourceInitHelper res_init _LIBCPP_INIT_PRIORITY_MAX; } // end namespace -memory_resource * new_delete_resource() _NOEXCEPT { +memory_resource * new_delete_resource() noexcept { return &res_init.resources.new_delete_res; } -memory_resource * null_memory_resource() _NOEXCEPT { +memory_resource * null_memory_resource() noexcept { return &res_init.resources.null_res; } // default_memory_resource() static memory_resource * -__default_memory_resource(bool set = false, memory_resource * new_res = nullptr) _NOEXCEPT +__default_memory_resource(bool set = false, memory_resource * new_res = nullptr) noexcept { #ifndef _LIBCPP_HAS_NO_ATOMIC_HEADER _LIBCPP_SAFE_STATIC static atomic<memory_resource*> __res = @@ -138,12 +133,12 @@ __default_memory_resource(bool set = false, memory_resource * new_res = nullptr) #endif } -memory_resource * get_default_resource() _NOEXCEPT +memory_resource * get_default_resource() noexcept { return __default_memory_resource(); } -memory_resource * set_default_resource(memory_resource * __new_res) _NOEXCEPT +memory_resource * set_default_resource(memory_resource * __new_res) noexcept { return __default_memory_resource(true, __new_res); } diff --git a/lib/libcxx/src/filesystem/directory_iterator.cpp b/lib/libcxx/src/filesystem/directory_iterator.cpp index 2721dea5c9..7b83ba9ff1 100644 --- a/lib/libcxx/src/filesystem/directory_iterator.cpp +++ b/lib/libcxx/src/filesystem/directory_iterator.cpp @@ -124,7 +124,8 @@ public: ec = detail::make_windows_error(GetLastError()); const bool ignore_permission_denied = bool(opts & directory_options::skip_permission_denied); - if (ignore_permission_denied && ec.value() == ERROR_ACCESS_DENIED) + if (ignore_permission_denied && + ec.value() == static_cast<int>(errc::permission_denied)) ec.clear(); return; } @@ -272,7 +273,7 @@ directory_iterator& directory_iterator::__increment(error_code* ec) { path root = move(__imp_->__root_); __imp_.reset(); if (m_ec) - err.report(m_ec, "at root \"%s\"", root); + err.report(m_ec, "at root " PATH_CSTR_FMT, root.c_str()); } return *this; } @@ -359,7 +360,7 @@ void recursive_directory_iterator::__advance(error_code* ec) { if (m_ec) { path root = move(stack.top().__root_); __imp_.reset(); - err.report(m_ec, "at root \"%s\"", root); + err.report(m_ec, "at root " PATH_CSTR_FMT, root.c_str()); } else { __imp_.reset(); } @@ -404,7 +405,8 @@ bool recursive_directory_iterator::__try_recursion(error_code* ec) { } else { path at_ent = move(curr_it.__entry_.__p_); __imp_.reset(); - err.report(m_ec, "attempting recursion into \"%s\"", at_ent); + err.report(m_ec, "attempting recursion into " PATH_CSTR_FMT, + at_ent.c_str()); } } return false; diff --git a/lib/libcxx/src/filesystem/filesystem_common.h b/lib/libcxx/src/filesystem/filesystem_common.h index e0fdbccf96..60d07059e3 100644 --- a/lib/libcxx/src/filesystem/filesystem_common.h +++ b/lib/libcxx/src/filesystem/filesystem_common.h @@ -35,15 +35,17 @@ #endif #endif -#if defined(__GNUC__) +#if defined(__GNUC__) || defined(__clang__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-function" #endif #if defined(_LIBCPP_WIN32API) #define PS(x) (L##x) +#define PATH_CSTR_FMT "\"%ls\"" #else #define PS(x) (x) +#define PATH_CSTR_FMT "\"%s\"" #endif _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM @@ -57,68 +59,47 @@ errc __win_err_to_errc(int err); namespace { -static string format_string_imp(const char* msg, ...) { - // we might need a second shot at this, so pre-emptivly make a copy - struct GuardVAList { - va_list& target; - bool active = true; - GuardVAList(va_list& tgt) : target(tgt), active(true) {} - void clear() { - if (active) - va_end(target); - active = false; - } - ~GuardVAList() { - if (active) - va_end(target); - } - }; - va_list args; - va_start(args, msg); - GuardVAList args_guard(args); - - va_list args_cp; - va_copy(args_cp, args); - GuardVAList args_copy_guard(args_cp); - - std::string result; - - array<char, 256> local_buff; - size_t size_with_null = local_buff.size(); - auto ret = ::vsnprintf(local_buff.data(), size_with_null, msg, args_cp); - - args_copy_guard.clear(); - - // handle empty expansion - if (ret == 0) - return result; - if (static_cast<size_t>(ret) < size_with_null) { - result.assign(local_buff.data(), static_cast<size_t>(ret)); - return result; +static _LIBCPP_FORMAT_PRINTF(1, 0) string +format_string_impl(const char* msg, va_list ap) { + array<char, 256> buf; + + va_list apcopy; + va_copy(apcopy, ap); + int ret = ::vsnprintf(buf.data(), buf.size(), msg, apcopy); + va_end(apcopy); + + string result; + if (static_cast<size_t>(ret) < buf.size()) { + result.assign(buf.data(), static_cast<size_t>(ret)); + } else { + // we did not provide a long enough buffer on our first attempt. The + // return value is the number of bytes (excluding the null byte) that are + // needed for formatting. + size_t size_with_null = static_cast<size_t>(ret) + 1; + result.__resize_default_init(size_with_null - 1); + ret = ::vsnprintf(&result[0], size_with_null, msg, ap); + _LIBCPP_ASSERT(static_cast<size_t>(ret) == (size_with_null - 1), "TODO"); } - - // we did not provide a long enough buffer on our first attempt. The - // return value is the number of bytes (excluding the null byte) that are - // needed for formatting. - size_with_null = static_cast<size_t>(ret) + 1; - result.__resize_default_init(size_with_null - 1); - ret = ::vsnprintf(&result[0], size_with_null, msg, args); - _LIBCPP_ASSERT(static_cast<size_t>(ret) == (size_with_null - 1), "TODO"); - return result; } -const path::value_type* unwrap(path::string_type const& s) { return s.c_str(); } -const path::value_type* unwrap(path const& p) { return p.native().c_str(); } -template <class Arg> -Arg const& unwrap(Arg const& a) { - static_assert(!is_class<Arg>::value, "cannot pass class here"); - return a; -} - -template <class... Args> -string format_string(const char* fmt, Args const&... args) { - return format_string_imp(fmt, unwrap(args)...); +static _LIBCPP_FORMAT_PRINTF(1, 2) string +format_string(const char* msg, ...) { + string ret; + va_list ap; + va_start(ap, msg); +#ifndef _LIBCPP_NO_EXCEPTIONS + try { +#endif // _LIBCPP_NO_EXCEPTIONS + ret = format_string_impl(msg, ap); +#ifndef _LIBCPP_NO_EXCEPTIONS + } catch (...) { + va_end(ap); + throw; + } +#endif // _LIBCPP_NO_EXCEPTIONS + va_end(ap); + return ret; } error_code capture_errno() { @@ -190,14 +171,14 @@ struct ErrorHandler { _LIBCPP_UNREACHABLE(); } - template <class... Args> - T report(const error_code& ec, const char* msg, Args const&... args) const { + _LIBCPP_FORMAT_PRINTF(3, 0) + void report_impl(const error_code& ec, const char* msg, va_list ap) const { if (ec_) { *ec_ = ec; - return error_value<T>(); + return; } string what = - string("in ") + func_name_ + ": " + format_string(msg, args...); + string("in ") + func_name_ + ": " + format_string_impl(msg, ap); switch (bool(p1_) + bool(p2_)) { case 0: __throw_filesystem_error(what, ec); @@ -209,11 +190,44 @@ struct ErrorHandler { _LIBCPP_UNREACHABLE(); } - T report(errc const& err) const { return report(make_error_code(err)); } + _LIBCPP_FORMAT_PRINTF(3, 4) + T report(const error_code& ec, const char* msg, ...) const { + va_list ap; + va_start(ap, msg); +#ifndef _LIBCPP_NO_EXCEPTIONS + try { +#endif // _LIBCPP_NO_EXCEPTIONS + report_impl(ec, msg, ap); +#ifndef _LIBCPP_NO_EXCEPTIONS + } catch (...) { + va_end(ap); + throw; + } +#endif // _LIBCPP_NO_EXCEPTIONS + va_end(ap); + return error_value<T>(); + } + + T report(errc const& err) const { + return report(make_error_code(err)); + } - template <class... Args> - T report(errc const& err, const char* msg, Args const&... args) const { - return report(make_error_code(err), msg, args...); + _LIBCPP_FORMAT_PRINTF(3, 4) + T report(errc const& err, const char* msg, ...) const { + va_list ap; + va_start(ap, msg); +#ifndef _LIBCPP_NO_EXCEPTIONS + try { +#endif // _LIBCPP_NO_EXCEPTIONS + report_impl(make_error_code(err), msg, ap); +#ifndef _LIBCPP_NO_EXCEPTIONS + } catch (...) { + va_end(ap); + throw; + } +#endif // _LIBCPP_NO_EXCEPTIONS + va_end(ap); + return error_value<T>(); } private: @@ -224,9 +238,41 @@ private: using chrono::duration; using chrono::duration_cast; +#if defined(_LIBCPP_WIN32API) +// Various C runtime versions (UCRT, or the legacy msvcrt.dll used by +// some mingw toolchains) provide different stat function implementations, +// with a number of limitations with respect to what we want from the +// stat function. Instead provide our own (in the anonymous detail namespace +// in posix_compat.h) which does exactly what we want, along with our own +// stat structure and flag macros. + +struct TimeSpec { + int64_t tv_sec; + int64_t tv_nsec; +}; +struct StatT { + unsigned st_mode; + TimeSpec st_atim; + TimeSpec st_mtim; + uint64_t st_dev; // FILE_ID_INFO::VolumeSerialNumber + struct FileIdStruct { + unsigned char id[16]; // FILE_ID_INFO::FileId + bool operator==(const FileIdStruct &other) const { + for (int i = 0; i < 16; i++) + if (id[i] != other.id[i]) + return false; + return true; + } + } st_ino; + uint32_t st_nlink; + uintmax_t st_size; +}; + +#else using TimeSpec = struct timespec; using TimeVal = struct timeval; using StatT = struct stat; +#endif template <class FileTimeT, class TimeT, bool IsFloat = is_floating_point<typename FileTimeT::rep>::value> @@ -255,8 +301,7 @@ struct time_util_base { .count(); private: -#if _LIBCPP_STD_VER > 11 && !defined(_LIBCPP_HAS_NO_CXX14_CONSTEXPR) - static constexpr fs_duration get_min_nsecs() { + static _LIBCPP_CONSTEXPR_AFTER_CXX11 fs_duration get_min_nsecs() { return duration_cast<fs_duration>( fs_nanoseconds(min_nsec_timespec) - duration_cast<fs_nanoseconds>(fs_seconds(1))); @@ -266,7 +311,7 @@ private: FileTimeT::duration::min(), "value doesn't roundtrip"); - static constexpr bool check_range() { + static _LIBCPP_CONSTEXPR_AFTER_CXX11 bool check_range() { // This kinda sucks, but it's what happens when we don't have __int128_t. if (sizeof(TimeT) == sizeof(rep)) { typedef duration<long long, ratio<3600 * 24 * 365> > Years; @@ -277,7 +322,6 @@ private: min_seconds <= numeric_limits<TimeT>::min(); } static_assert(check_range(), "the representable range is unacceptable small"); -#endif }; template <class FileTimeT, class TimeT> @@ -405,7 +449,11 @@ public: } }; +#if defined(_LIBCPP_WIN32API) +using fs_time = time_util<file_time_type, int64_t, TimeSpec>; +#else using fs_time = time_util<file_time_type, time_t, TimeSpec>; +#endif #if defined(__APPLE__) inline TimeSpec extract_mtime(StatT const& st) { return st.st_mtimespec; } @@ -419,11 +467,21 @@ inline TimeSpec extract_atime(StatT const& st) { TimeSpec TS = {st.st_atime, 0}; return TS; } +#elif defined(_AIX) +inline TimeSpec extract_mtime(StatT const& st) { + TimeSpec TS = {st.st_mtime, st.st_mtime_n}; + return TS; +} +inline TimeSpec extract_atime(StatT const& st) { + TimeSpec TS = {st.st_atime, st.st_atime_n}; + return TS; +} #else inline TimeSpec extract_mtime(StatT const& st) { return st.st_mtim; } inline TimeSpec extract_atime(StatT const& st) { return st.st_atim; } #endif +#if !defined(_LIBCPP_WIN32API) inline TimeVal make_timeval(TimeSpec const& ts) { using namespace chrono; auto Convert = [](long nsec) { @@ -466,6 +524,7 @@ bool set_file_times(const path& p, std::array<TimeSpec, 2> const& TS, return posix_utimensat(p, TS, ec); #endif } +#endif /* !_LIBCPP_WIN32API */ } // namespace } // end namespace detail diff --git a/lib/libcxx/src/filesystem/operations.cpp b/lib/libcxx/src/filesystem/operations.cpp index 50a895dc2f..5179eeae42 100644 --- a/lib/libcxx/src/filesystem/operations.cpp +++ b/lib/libcxx/src/filesystem/operations.cpp @@ -17,6 +17,8 @@ #include "filesystem_common.h" +#include "posix_compat.h" + #if defined(_LIBCPP_WIN32API) # define WIN32_LEAN_AND_MEAN # define NOMINMAX @@ -40,7 +42,7 @@ # define _LIBCPP_FILESYSTEM_USE_FSTREAM #endif -#if !defined(CLOCK_REALTIME) +#if !defined(CLOCK_REALTIME) && !defined(_LIBCPP_WIN32API) # include <sys/time.h> // for gettimeofday and timeval #endif @@ -62,6 +64,10 @@ bool isSeparator(path::value_type C) { return false; } +bool isDriveLetter(path::value_type C) { + return (C >= 'a' && C <= 'z') || (C >= 'A' && C <= 'Z'); +} + namespace parser { using string_view_t = path::__string_view; @@ -118,7 +124,13 @@ public: switch (State) { case PS_BeforeBegin: { - PosPtr TkEnd = consumeSeparator(Start, End); + PosPtr TkEnd = consumeRootName(Start, End); + if (TkEnd) + return makeState(PS_InRootName, Start, TkEnd); + } + _LIBCPP_FALLTHROUGH(); + case PS_InRootName: { + PosPtr TkEnd = consumeAllSeparators(Start, End); if (TkEnd) return makeState(PS_InRootDir, Start, TkEnd); else @@ -128,7 +140,7 @@ public: return makeState(PS_InFilenames, Start, consumeName(Start, End)); case PS_InFilenames: { - PosPtr SepEnd = consumeSeparator(Start, End); + PosPtr SepEnd = consumeAllSeparators(Start, End); if (SepEnd != End) { PosPtr TkEnd = consumeName(SepEnd, End); if (TkEnd) @@ -140,7 +152,6 @@ public: case PS_InTrailingSep: return makeState(PS_AtEnd); - case PS_InRootName: case PS_AtEnd: _LIBCPP_UNREACHABLE(); } @@ -155,12 +166,18 @@ public: switch (State) { case PS_AtEnd: { // Try to consume a trailing separator or root directory first. - if (PosPtr SepEnd = consumeSeparator(RStart, REnd)) { + if (PosPtr SepEnd = consumeAllSeparators(RStart, REnd)) { if (SepEnd == REnd) return makeState(PS_InRootDir, Path.data(), RStart + 1); + PosPtr TkStart = consumeRootName(SepEnd, REnd); + if (TkStart == REnd) + return makeState(PS_InRootDir, RStart, RStart + 1); return makeState(PS_InTrailingSep, SepEnd + 1, RStart + 1); } else { - PosPtr TkStart = consumeName(RStart, REnd); + PosPtr TkStart = consumeRootName(RStart, REnd); + if (TkStart == REnd) + return makeState(PS_InRootName, TkStart + 1, RStart + 1); + TkStart = consumeName(RStart, REnd); return makeState(PS_InFilenames, TkStart + 1, RStart + 1); } } @@ -168,14 +185,20 @@ public: return makeState(PS_InFilenames, consumeName(RStart, REnd) + 1, RStart + 1); case PS_InFilenames: { - PosPtr SepEnd = consumeSeparator(RStart, REnd); + PosPtr SepEnd = consumeAllSeparators(RStart, REnd); if (SepEnd == REnd) return makeState(PS_InRootDir, Path.data(), RStart + 1); - PosPtr TkEnd = consumeName(SepEnd, REnd); - return makeState(PS_InFilenames, TkEnd + 1, SepEnd + 1); + PosPtr TkStart = consumeRootName(SepEnd ? SepEnd : RStart, REnd); + if (TkStart == REnd) { + if (SepEnd) + return makeState(PS_InRootDir, SepEnd + 1, RStart + 1); + return makeState(PS_InRootName, TkStart + 1, RStart + 1); + } + TkStart = consumeName(SepEnd, REnd); + return makeState(PS_InFilenames, TkStart + 1, SepEnd + 1); } case PS_InRootDir: - // return makeState(PS_InRootName, Path.data(), RStart + 1); + return makeState(PS_InRootName, Path.data(), RStart + 1); case PS_InRootName: case PS_BeforeBegin: _LIBCPP_UNREACHABLE(); @@ -281,8 +304,9 @@ private: _LIBCPP_UNREACHABLE(); } - PosPtr consumeSeparator(PosPtr P, PosPtr End) const noexcept { - if (P == End || !isSeparator(*P)) + // Consume all consecutive separators. + PosPtr consumeAllSeparators(PosPtr P, PosPtr End) const noexcept { + if (P == nullptr || P == End || !isSeparator(*P)) return nullptr; const int Inc = P < End ? 1 : -1; P += Inc; @@ -291,15 +315,72 @@ private: return P; } + // Consume exactly N separators, or return nullptr. + PosPtr consumeNSeparators(PosPtr P, PosPtr End, int N) const noexcept { + PosPtr Ret = consumeAllSeparators(P, End); + if (Ret == nullptr) + return nullptr; + if (P < End) { + if (Ret == P + N) + return Ret; + } else { + if (Ret == P - N) + return Ret; + } + return nullptr; + } + PosPtr consumeName(PosPtr P, PosPtr End) const noexcept { - if (P == End || isSeparator(*P)) + PosPtr Start = P; + if (P == nullptr || P == End || isSeparator(*P)) return nullptr; const int Inc = P < End ? 1 : -1; P += Inc; while (P != End && !isSeparator(*P)) P += Inc; + if (P == End && Inc < 0) { + // Iterating backwards and consumed all the rest of the input. + // Check if the start of the string would have been considered + // a root name. + PosPtr RootEnd = consumeRootName(End + 1, Start); + if (RootEnd) + return RootEnd - 1; + } return P; } + + PosPtr consumeDriveLetter(PosPtr P, PosPtr End) const noexcept { + if (P == End) + return nullptr; + if (P < End) { + if (P + 1 == End || !isDriveLetter(P[0]) || P[1] != ':') + return nullptr; + return P + 2; + } else { + if (P - 1 == End || !isDriveLetter(P[-1]) || P[0] != ':') + return nullptr; + return P - 2; + } + } + + PosPtr consumeNetworkRoot(PosPtr P, PosPtr End) const noexcept { + if (P == End) + return nullptr; + if (P < End) + return consumeName(consumeNSeparators(P, End, 2), End); + else + return consumeNSeparators(consumeName(P, End), End, 2); + } + + PosPtr consumeRootName(PosPtr P, PosPtr End) const noexcept { +#if defined(_LIBCPP_WIN32API) + if (PosPtr Ret = consumeDriveLetter(P, End)) + return Ret; + if (PosPtr Ret = consumeNetworkRoot(P, End)) + return Ret; +#endif + return nullptr; + } }; string_view_pair separate_filename(string_view_t const& s) { @@ -331,6 +412,7 @@ errc __win_err_to_errc(int err) { {ERROR_ACCESS_DENIED, errc::permission_denied}, {ERROR_ALREADY_EXISTS, errc::file_exists}, {ERROR_BAD_NETPATH, errc::no_such_file_or_directory}, + {ERROR_BAD_PATHNAME, errc::no_such_file_or_directory}, {ERROR_BAD_UNIT, errc::no_such_device}, {ERROR_BROKEN_PIPE, errc::broken_pipe}, {ERROR_BUFFER_OVERFLOW, errc::filename_too_long}, @@ -403,7 +485,7 @@ struct FileDescriptor { static FileDescriptor create(const path* p, error_code& ec, Args... args) { ec.clear(); int fd; - if ((fd = ::open(p->c_str(), args...)) == -1) { + if ((fd = detail::open(p->c_str(), args...)) == -1) { ec = capture_errno(); return FileDescriptor{p}; } @@ -429,7 +511,7 @@ struct FileDescriptor { void close() noexcept { if (fd != -1) - ::close(fd); + detail::close(fd); fd = -1; } @@ -453,10 +535,6 @@ perms posix_get_perms(const StatT& st) noexcept { return static_cast<perms>(st.st_mode) & perms::mask; } -::mode_t posix_convert_perms(perms prms) { - return static_cast< ::mode_t>(prms & perms::mask); -} - file_status create_file_status(error_code& m_ec, path const& p, const StatT& path_stat, error_code* ec) { if (ec) @@ -495,7 +573,7 @@ file_status create_file_status(error_code& m_ec, path const& p, file_status posix_stat(path const& p, StatT& path_stat, error_code* ec) { error_code m_ec; - if (::stat(p.c_str(), &path_stat) == -1) + if (detail::stat(p.c_str(), &path_stat) == -1) m_ec = detail::capture_errno(); return create_file_status(m_ec, p, path_stat, ec); } @@ -507,7 +585,7 @@ file_status posix_stat(path const& p, error_code* ec) { file_status posix_lstat(path const& p, StatT& path_stat, error_code* ec) { error_code m_ec; - if (::lstat(p.c_str(), &path_stat) == -1) + if (detail::lstat(p.c_str(), &path_stat) == -1) m_ec = detail::capture_errno(); return create_file_status(m_ec, p, path_stat, ec); } @@ -519,7 +597,7 @@ file_status posix_lstat(path const& p, error_code* ec) { // http://pubs.opengroup.org/onlinepubs/9699919799/functions/ftruncate.html bool posix_ftruncate(const FileDescriptor& fd, off_t to_size, error_code& ec) { - if (::ftruncate(fd.fd, to_size) == -1) { + if (detail::ftruncate(fd.fd, to_size) == -1) { ec = capture_errno(); return true; } @@ -528,7 +606,7 @@ bool posix_ftruncate(const FileDescriptor& fd, off_t to_size, error_code& ec) { } bool posix_fchmod(const FileDescriptor& fd, const StatT& st, error_code& ec) { - if (::fchmod(fd.fd, st.st_mode) == -1) { + if (detail::fchmod(fd.fd, st.st_mode) == -1) { ec = capture_errno(); return true; } @@ -545,7 +623,7 @@ file_status FileDescriptor::refresh_status(error_code& ec) { m_status = file_status{}; m_stat = {}; error_code m_ec; - if (::fstat(fd, &m_stat) == -1) + if (detail::fstat(fd, &m_stat) == -1) m_ec = capture_errno(); m_status = create_file_status(m_ec, name, m_stat, &ec); return m_status; @@ -565,7 +643,14 @@ const bool _FilesystemClock::is_steady; _FilesystemClock::time_point _FilesystemClock::now() noexcept { typedef chrono::duration<rep> __secs; -#if defined(CLOCK_REALTIME) +#if defined(_LIBCPP_WIN32API) + typedef chrono::duration<rep, nano> __nsecs; + FILETIME time; + GetSystemTimeAsFileTime(&time); + TimeSpec tp = detail::filetime_to_timespec(time); + return time_point(__secs(tp.tv_sec) + + chrono::duration_cast<duration>(__nsecs(tp.tv_nsec))); +#elif defined(CLOCK_REALTIME) typedef chrono::duration<rep, nano> __nsecs; struct timespec tp; if (0 != clock_gettime(CLOCK_REALTIME, &tp)) @@ -582,27 +667,20 @@ _FilesystemClock::time_point _FilesystemClock::now() noexcept { filesystem_error::~filesystem_error() {} -#if defined(_LIBCPP_WIN32API) -#define PS_FMT "%ls" -#else -#define PS_FMT "%s" -#endif - void filesystem_error::__create_what(int __num_paths) { const char* derived_what = system_error::what(); __storage_->__what_ = [&]() -> string { - const path::value_type* p1 = path1().native().empty() ? PS("\"\"") : path1().c_str(); - const path::value_type* p2 = path2().native().empty() ? PS("\"\"") : path2().c_str(); switch (__num_paths) { - default: + case 0: return detail::format_string("filesystem error: %s", derived_what); case 1: - return detail::format_string("filesystem error: %s [" PS_FMT "]", derived_what, - p1); + return detail::format_string("filesystem error: %s [" PATH_CSTR_FMT "]", + derived_what, path1().c_str()); case 2: - return detail::format_string("filesystem error: %s [" PS_FMT "] [" PS_FMT "]", - derived_what, p1, p2); + return detail::format_string("filesystem error: %s [" PATH_CSTR_FMT "] [" PATH_CSTR_FMT "]", + derived_what, path1().c_str(), path2().c_str()); } + _LIBCPP_UNREACHABLE(); }(); } @@ -627,20 +705,20 @@ path __canonical(path const& orig_p, error_code* ec) { ErrorHandler<path> err("canonical", ec, &orig_p, &cwd); path p = __do_absolute(orig_p, &cwd, ec); -#if defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112 - std::unique_ptr<char, decltype(&::free)> - hold(::realpath(p.c_str(), nullptr), &::free); +#if (defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112) || defined(_LIBCPP_WIN32API) + std::unique_ptr<path::value_type, decltype(&::free)> + hold(detail::realpath(p.c_str(), nullptr), &::free); if (hold.get() == nullptr) return err.report(capture_errno()); return {hold.get()}; #else #if defined(__MVS__) && !defined(PATH_MAX) - char buff[ _XOPEN_PATH_MAX + 1 ]; + path::value_type buff[ _XOPEN_PATH_MAX + 1 ]; #else - char buff[PATH_MAX + 1]; + path::value_type buff[PATH_MAX + 1]; #endif - char* ret; - if ((ret = ::realpath(p.c_str(), buff)) == nullptr) + path::value_type* ret; + if ((ret = detail::realpath(p.c_str(), buff)) == nullptr) return err.report(capture_errno()); return {ret}; #endif @@ -819,8 +897,8 @@ bool __copy_file(const path& from, const path& to, copy_options options, ErrorHandler<bool> err("copy_file", ec, &to, &from); error_code m_ec; - FileDescriptor from_fd = - FileDescriptor::create_with_status(&from, m_ec, O_RDONLY | O_NONBLOCK); + FileDescriptor from_fd = FileDescriptor::create_with_status( + &from, m_ec, O_RDONLY | O_NONBLOCK | O_BINARY); if (m_ec) return err.report(m_ec); @@ -872,7 +950,7 @@ bool __copy_file(const path& from, const path& to, copy_options options, // Don't truncate right away. We may not be opening the file we originally // looked at; we'll check this later. - int to_open_flags = O_WRONLY; + int to_open_flags = O_WRONLY | O_BINARY; if (!to_exists) to_open_flags |= O_CREAT; FileDescriptor to_fd = FileDescriptor::create_with_status( @@ -908,10 +986,13 @@ void __copy_symlink(const path& existing_symlink, const path& new_symlink, if (ec && *ec) { return; } - // NOTE: proposal says you should detect if you should call - // create_symlink or create_directory_symlink. I don't think this - // is needed with POSIX - __create_symlink(real_path, new_symlink, ec); +#if defined(_LIBCPP_WIN32API) + error_code local_ec; + if (is_directory(real_path, local_ec)) + __create_directory_symlink(real_path, new_symlink, ec); + else +#endif + __create_symlink(real_path, new_symlink, ec); } bool __create_directories(const path& p, error_code* ec) { @@ -932,31 +1013,34 @@ bool __create_directories(const path& p, error_code* ec) { if (not status_known(parent_st)) return err.report(m_ec); if (not exists(parent_st)) { + if (parent == p) + return err.report(errc::invalid_argument); __create_directories(parent, ec); if (ec && *ec) { return false; } - } + } else if (not is_directory(parent_st)) + return err.report(errc::not_a_directory); } - return __create_directory(p, ec); + bool ret = __create_directory(p, &m_ec); + if (m_ec) + return err.report(m_ec); + return ret; } bool __create_directory(const path& p, error_code* ec) { ErrorHandler<bool> err("create_directory", ec, &p); - if (::mkdir(p.c_str(), static_cast<int>(perms::all)) == 0) + if (detail::mkdir(p.c_str(), static_cast<int>(perms::all)) == 0) return true; - if (errno == EEXIST) { - error_code mec = capture_errno(); - error_code ignored_ec; - const file_status st = status(p, ignored_ec); - if (!is_directory(st)) { - err.report(mec); - } - } else { - err.report(capture_errno()); - } + if (errno != EEXIST) + return err.report(capture_errno()); + error_code mec = capture_errno(); + error_code ignored_ec; + const file_status st = status(p, ignored_ec); + if (!is_directory(st)) + return err.report(mec); return false; } @@ -965,65 +1049,80 @@ bool __create_directory(path const& p, path const& attributes, error_code* ec) { StatT attr_stat; error_code mec; - auto st = detail::posix_stat(attributes, attr_stat, &mec); + file_status st = detail::posix_stat(attributes, attr_stat, &mec); if (!status_known(st)) return err.report(mec); if (!is_directory(st)) return err.report(errc::not_a_directory, "the specified attribute path is invalid"); - if (::mkdir(p.c_str(), attr_stat.st_mode) == 0) + if (detail::mkdir(p.c_str(), attr_stat.st_mode) == 0) return true; - if (errno == EEXIST) { - error_code mec = capture_errno(); - error_code ignored_ec; - const file_status st = status(p, ignored_ec); - if (!is_directory(st)) { - err.report(mec); - } - } else { - err.report(capture_errno()); - } + if (errno != EEXIST) + return err.report(capture_errno()); + + mec = capture_errno(); + error_code ignored_ec; + st = status(p, ignored_ec); + if (!is_directory(st)) + return err.report(mec); return false; } void __create_directory_symlink(path const& from, path const& to, error_code* ec) { ErrorHandler<void> err("create_directory_symlink", ec, &from, &to); - if (::symlink(from.c_str(), to.c_str()) != 0) + if (detail::symlink_dir(from.c_str(), to.c_str()) == -1) return err.report(capture_errno()); } void __create_hard_link(const path& from, const path& to, error_code* ec) { ErrorHandler<void> err("create_hard_link", ec, &from, &to); - if (::link(from.c_str(), to.c_str()) == -1) + if (detail::link(from.c_str(), to.c_str()) == -1) return err.report(capture_errno()); } void __create_symlink(path const& from, path const& to, error_code* ec) { ErrorHandler<void> err("create_symlink", ec, &from, &to); - if (::symlink(from.c_str(), to.c_str()) == -1) + if (detail::symlink_file(from.c_str(), to.c_str()) == -1) return err.report(capture_errno()); } path __current_path(error_code* ec) { ErrorHandler<path> err("current_path", ec); +#if defined(_LIBCPP_WIN32API) || defined(__GLIBC__) || defined(__APPLE__) + // Common extension outside of POSIX getcwd() spec, without needing to + // preallocate a buffer. Also supported by a number of other POSIX libcs. + int size = 0; + path::value_type* ptr = nullptr; + typedef decltype(&::free) Deleter; + Deleter deleter = &::free; +#else auto size = ::pathconf(".", _PC_PATH_MAX); _LIBCPP_ASSERT(size >= 0, "pathconf returned a 0 as max size"); - auto buff = unique_ptr<char[]>(new char[size + 1]); - char* ret; - if ((ret = ::getcwd(buff.get(), static_cast<size_t>(size))) == nullptr) + auto buff = unique_ptr<path::value_type[]>(new path::value_type[size + 1]); + path::value_type* ptr = buff.get(); + + // Preallocated buffer, don't free the buffer in the second unique_ptr + // below. + struct Deleter { void operator()(void*) const {} }; + Deleter deleter; +#endif + + unique_ptr<path::value_type, Deleter> hold(detail::getcwd(ptr, size), + deleter); + if (hold.get() == nullptr) return err.report(capture_errno(), "call to getcwd failed"); - return {buff.get()}; + return {hold.get()}; } void __current_path(const path& p, error_code* ec) { ErrorHandler<void> err("current_path", ec, &p); - if (::chdir(p.c_str()) == -1) + if (detail::chdir(p.c_str()) == -1) err.report(capture_errno()); } @@ -1119,6 +1218,17 @@ void __last_write_time(const path& p, file_time_type new_time, error_code* ec) { using detail::fs_time; ErrorHandler<void> err("last_write_time", ec, &p); +#if defined(_LIBCPP_WIN32API) + TimeSpec ts; + if (!fs_time::convert_to_timespec(ts, new_time)) + return err.report(errc::value_too_large); + detail::WinHandle h(p.c_str(), FILE_WRITE_ATTRIBUTES, 0); + if (!h) + return err.report(detail::make_windows_error(GetLastError())); + FILETIME last_write = timespec_to_filetime(ts); + if (!SetFileTime(h, nullptr, nullptr, &last_write)) + return err.report(detail::make_windows_error(GetLastError())); +#else error_code m_ec; array<TimeSpec, 2> tbuf; #if !defined(_LIBCPP_USE_UTIMENSAT) @@ -1140,6 +1250,7 @@ void __last_write_time(const path& p, file_time_type new_time, error_code* ec) { detail::set_file_times(p, tbuf, m_ec); if (m_ec) return err.report(m_ec); +#endif } void __permissions(const path& p, perms prms, perm_options opts, @@ -1171,11 +1282,11 @@ void __permissions(const path& p, perms prms, perm_options opts, else if (remove_perms) prms = st.permissions() & ~prms; } - const auto real_perms = detail::posix_convert_perms(prms); + const auto real_perms = static_cast<detail::ModeT>(prms & perms::mask); #if defined(AT_SYMLINK_NOFOLLOW) && defined(AT_FDCWD) const int flags = set_sym_perms ? AT_SYMLINK_NOFOLLOW : 0; - if (::fchmodat(AT_FDCWD, p.c_str(), real_perms, flags) == -1) { + if (detail::fchmodat(AT_FDCWD, p.c_str(), real_perms, flags) == -1) { return err.report(capture_errno()); } #else @@ -1190,21 +1301,25 @@ void __permissions(const path& p, perms prms, perm_options opts, path __read_symlink(const path& p, error_code* ec) { ErrorHandler<path> err("read_symlink", ec, &p); -#ifdef PATH_MAX +#if defined(PATH_MAX) || defined(MAX_SYMLINK_SIZE) struct NullDeleter { void operator()(void*) const {} }; +#ifdef MAX_SYMLINK_SIZE + const size_t size = MAX_SYMLINK_SIZE + 1; +#else const size_t size = PATH_MAX + 1; - char stack_buff[size]; - auto buff = std::unique_ptr<char[], NullDeleter>(stack_buff); +#endif + path::value_type stack_buff[size]; + auto buff = std::unique_ptr<path::value_type[], NullDeleter>(stack_buff); #else StatT sb; - if (::lstat(p.c_str(), &sb) == -1) { + if (detail::lstat(p.c_str(), &sb) == -1) { return err.report(capture_errno()); } const size_t size = sb.st_size + 1; - auto buff = unique_ptr<char[]>(new char[size]); + auto buff = unique_ptr<path::value_type[]>(new path::value_type[size]); #endif - ::ssize_t ret; - if ((ret = ::readlink(p.c_str(), buff.get(), size)) == -1) + detail::SSizeT ret; + if ((ret = detail::readlink(p.c_str(), buff.get(), size)) == -1) return err.report(capture_errno()); _LIBCPP_ASSERT(ret > 0, "TODO"); if (static_cast<size_t>(ret) >= size) @@ -1215,7 +1330,7 @@ path __read_symlink(const path& p, error_code* ec) { bool __remove(const path& p, error_code* ec) { ErrorHandler<bool> err("remove", ec, &p); - if (::remove(p.c_str()) == -1) { + if (detail::remove(p.c_str()) == -1) { if (errno != ENOENT) err.report(capture_errno()); return false; @@ -1264,21 +1379,21 @@ uintmax_t __remove_all(const path& p, error_code* ec) { void __rename(const path& from, const path& to, error_code* ec) { ErrorHandler<void> err("rename", ec, &from, &to); - if (::rename(from.c_str(), to.c_str()) == -1) + if (detail::rename(from.c_str(), to.c_str()) == -1) err.report(capture_errno()); } void __resize_file(const path& p, uintmax_t size, error_code* ec) { ErrorHandler<void> err("resize_file", ec, &p); - if (::truncate(p.c_str(), static_cast< ::off_t>(size)) == -1) + if (detail::truncate(p.c_str(), static_cast< ::off_t>(size)) == -1) return err.report(capture_errno()); } space_info __space(const path& p, error_code* ec) { ErrorHandler<void> err("space", ec, &p); space_info si; - struct statvfs m_svfs = {}; - if (::statvfs(p.c_str(), &m_svfs) == -1) { + detail::StatVFS m_svfs = {}; + if (detail::statvfs(p.c_str(), &m_svfs) == -1) { err.report(capture_errno()); si.capacity = si.free = si.available = static_cast<uintmax_t>(-1); return si; @@ -1306,6 +1421,19 @@ file_status __symlink_status(const path& p, error_code* ec) { path __temp_directory_path(error_code* ec) { ErrorHandler<path> err("temp_directory_path", ec); +#if defined(_LIBCPP_WIN32API) + wchar_t buf[MAX_PATH]; + DWORD retval = GetTempPathW(MAX_PATH, buf); + if (!retval) + return err.report(detail::make_windows_error(GetLastError())); + if (retval > MAX_PATH) + return err.report(errc::filename_too_long); + // GetTempPathW returns a path with a trailing slash, which we + // shouldn't include for consistency. + if (buf[retval-1] == L'\\') + buf[retval-1] = L'\0'; + path p(buf); +#else const char* env_paths[] = {"TMPDIR", "TMP", "TEMP", "TEMPDIR"}; const char* ret = nullptr; @@ -1316,14 +1444,15 @@ path __temp_directory_path(error_code* ec) { ret = "/tmp"; path p(ret); +#endif error_code m_ec; file_status st = detail::posix_stat(p, &m_ec); if (!status_known(st)) - return err.report(m_ec, "cannot access path \"" PS_FMT "\"", p); + return err.report(m_ec, "cannot access path " PATH_CSTR_FMT, p.c_str()); if (!exists(st) || !is_directory(st)) - return err.report(errc::not_a_directory, "path \"" PS_FMT "\" is not a directory", - p); + return err.report(errc::not_a_directory, + "path " PATH_CSTR_FMT " is not a directory", p.c_str()); return p; } @@ -1586,6 +1715,7 @@ path path::lexically_normal() const { if (NeedTrailingSep) Result /= PS(""); + Result.make_preferred(); return Result; } @@ -1806,7 +1936,6 @@ size_t __char_to_wide(const string &str, wchar_t *out, size_t outlen) { // directory entry definitions /////////////////////////////////////////////////////////////////////////////// -#ifndef _LIBCPP_WIN32API error_code directory_entry::__do_refresh() noexcept { __data_.__reset(); error_code failure_ec; @@ -1860,47 +1989,5 @@ error_code directory_entry::__do_refresh() noexcept { return failure_ec; } -#else -error_code directory_entry::__do_refresh() noexcept { - __data_.__reset(); - error_code failure_ec; - - file_status st = _VSTD_FS::symlink_status(__p_, failure_ec); - if (!status_known(st)) { - __data_.__reset(); - return failure_ec; - } - - if (!_VSTD_FS::exists(st) || !_VSTD_FS::is_symlink(st)) { - __data_.__cache_type_ = directory_entry::_RefreshNonSymlink; - __data_.__type_ = st.type(); - __data_.__non_sym_perms_ = st.permissions(); - } else { // we have a symlink - __data_.__sym_perms_ = st.permissions(); - // Get the information about the linked entity. - // Ignore errors from stat, since we don't want errors regarding symlink - // resolution to be reported to the user. - error_code ignored_ec; - st = _VSTD_FS::status(__p_, ignored_ec); - - __data_.__type_ = st.type(); - __data_.__non_sym_perms_ = st.permissions(); - - // If we failed to resolve the link, then only partially populate the - // cache. - if (!status_known(st)) { - __data_.__cache_type_ = directory_entry::_RefreshSymlinkUnresolved; - return error_code{}; - } - __data_.__cache_type_ = directory_entry::_RefreshSymlink; - } - - // FIXME: This is currently broken, and the implementation only a placeholder. - // We need to cache last_write_time, file_size, and hard_link_count here before - // the implementation actually works. - - return failure_ec; -} -#endif _LIBCPP_END_NAMESPACE_FILESYSTEM diff --git a/lib/libcxx/src/filesystem/posix_compat.h b/lib/libcxx/src/filesystem/posix_compat.h new file mode 100644 index 0000000000..f5c8ec39df --- /dev/null +++ b/lib/libcxx/src/filesystem/posix_compat.h @@ -0,0 +1,521 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// +// POSIX-like portability helper functions. +// +// These generally behave like the proper posix functions, with these +// exceptions: +// On Windows, they take paths in wchar_t* form, instead of char* form. +// The symlink() function is split into two frontends, symlink_file() +// and symlink_dir(). +// +// These are provided within an anonymous namespace within the detail +// namespace - callers need to include this header and call them as +// detail::function(), regardless of platform. +// + +#ifndef POSIX_COMPAT_H +#define POSIX_COMPAT_H + +#include "filesystem" + +#include "filesystem_common.h" + +#if defined(_LIBCPP_WIN32API) +# define WIN32_LEAN_AND_MEAN +# define NOMINMAX +# include <windows.h> +# include <io.h> +# include <winioctl.h> +#else +# include <unistd.h> +# include <sys/stat.h> +# include <sys/statvfs.h> +#endif +#include <time.h> + +#if defined(_LIBCPP_WIN32API) +// This struct isn't defined in the normal Windows SDK, but only in the +// Windows Driver Kit. +struct LIBCPP_REPARSE_DATA_BUFFER { + unsigned long ReparseTag; + unsigned short ReparseDataLength; + unsigned short Reserved; + union { + struct { + unsigned short SubstituteNameOffset; + unsigned short SubstituteNameLength; + unsigned short PrintNameOffset; + unsigned short PrintNameLength; + unsigned long Flags; + wchar_t PathBuffer[1]; + } SymbolicLinkReparseBuffer; + struct { + unsigned short SubstituteNameOffset; + unsigned short SubstituteNameLength; + unsigned short PrintNameOffset; + unsigned short PrintNameLength; + wchar_t PathBuffer[1]; + } MountPointReparseBuffer; + struct { + unsigned char DataBuffer[1]; + } GenericReparseBuffer; + }; +}; +#endif + +_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM + +namespace detail { +namespace { + +#if defined(_LIBCPP_WIN32API) + +// Various C runtime header sets provide more or less of these. As we +// provide our own implementation, undef all potential defines from the +// C runtime headers and provide a complete set of macros of our own. + +#undef _S_IFMT +#undef _S_IFDIR +#undef _S_IFCHR +#undef _S_IFIFO +#undef _S_IFREG +#undef _S_IFBLK +#undef _S_IFLNK +#undef _S_IFSOCK + +#define _S_IFMT 0xF000 +#define _S_IFDIR 0x4000 +#define _S_IFCHR 0x2000 +#define _S_IFIFO 0x1000 +#define _S_IFREG 0x8000 +#define _S_IFBLK 0x6000 +#define _S_IFLNK 0xA000 +#define _S_IFSOCK 0xC000 + +#undef S_ISDIR +#undef S_ISFIFO +#undef S_ISCHR +#undef S_ISREG +#undef S_ISLNK +#undef S_ISBLK +#undef S_ISSOCK + +#define S_ISDIR(m) (((m) & _S_IFMT) == _S_IFDIR) +#define S_ISCHR(m) (((m) & _S_IFMT) == _S_IFCHR) +#define S_ISFIFO(m) (((m) & _S_IFMT) == _S_IFIFO) +#define S_ISREG(m) (((m) & _S_IFMT) == _S_IFREG) +#define S_ISBLK(m) (((m) & _S_IFMT) == _S_IFBLK) +#define S_ISLNK(m) (((m) & _S_IFMT) == _S_IFLNK) +#define S_ISSOCK(m) (((m) & _S_IFMT) == _S_IFSOCK) + +#define O_NONBLOCK 0 + + +// There were 369 years and 89 leap days from the Windows epoch +// (1601) to the Unix epoch (1970). +#define FILE_TIME_OFFSET_SECS (uint64_t(369 * 365 + 89) * (24 * 60 * 60)) + +TimeSpec filetime_to_timespec(LARGE_INTEGER li) { + TimeSpec ret; + ret.tv_sec = li.QuadPart / 10000000 - FILE_TIME_OFFSET_SECS; + ret.tv_nsec = (li.QuadPart % 10000000) * 100; + return ret; +} + +TimeSpec filetime_to_timespec(FILETIME ft) { + LARGE_INTEGER li; + li.LowPart = ft.dwLowDateTime; + li.HighPart = ft.dwHighDateTime; + return filetime_to_timespec(li); +} + +FILETIME timespec_to_filetime(TimeSpec ts) { + LARGE_INTEGER li; + li.QuadPart = + ts.tv_nsec / 100 + (ts.tv_sec + FILE_TIME_OFFSET_SECS) * 10000000; + FILETIME ft; + ft.dwLowDateTime = li.LowPart; + ft.dwHighDateTime = li.HighPart; + return ft; +} + +int set_errno(int e = GetLastError()) { + errno = static_cast<int>(__win_err_to_errc(e)); + return -1; +} + +class WinHandle { +public: + WinHandle(const wchar_t *p, DWORD access, DWORD flags) { + h = CreateFileW( + p, access, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | flags, nullptr); + } + ~WinHandle() { + if (h != INVALID_HANDLE_VALUE) + CloseHandle(h); + } + operator HANDLE() const { return h; } + operator bool() const { return h != INVALID_HANDLE_VALUE; } + +private: + HANDLE h; +}; + +int stat_handle(HANDLE h, StatT *buf) { + FILE_BASIC_INFO basic; + if (!GetFileInformationByHandleEx(h, FileBasicInfo, &basic, sizeof(basic))) + return set_errno(); + memset(buf, 0, sizeof(*buf)); + buf->st_mtim = filetime_to_timespec(basic.LastWriteTime); + buf->st_atim = filetime_to_timespec(basic.LastAccessTime); + buf->st_mode = 0555; // Read-only + if (!(basic.FileAttributes & FILE_ATTRIBUTE_READONLY)) + buf->st_mode |= 0222; // Write + if (basic.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + buf->st_mode |= _S_IFDIR; + } else { + buf->st_mode |= _S_IFREG; + } + if (basic.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { + FILE_ATTRIBUTE_TAG_INFO tag; + if (!GetFileInformationByHandleEx(h, FileAttributeTagInfo, &tag, + sizeof(tag))) + return set_errno(); + if (tag.ReparseTag == IO_REPARSE_TAG_SYMLINK) + buf->st_mode = (buf->st_mode & ~_S_IFMT) | _S_IFLNK; + } + FILE_STANDARD_INFO standard; + if (!GetFileInformationByHandleEx(h, FileStandardInfo, &standard, + sizeof(standard))) + return set_errno(); + buf->st_nlink = standard.NumberOfLinks; + buf->st_size = standard.EndOfFile.QuadPart; + BY_HANDLE_FILE_INFORMATION info; + if (!GetFileInformationByHandle(h, &info)) + return set_errno(); + buf->st_dev = info.dwVolumeSerialNumber; + memcpy(&buf->st_ino.id[0], &info.nFileIndexHigh, 4); + memcpy(&buf->st_ino.id[4], &info.nFileIndexLow, 4); + return 0; +} + +int stat_file(const wchar_t *path, StatT *buf, DWORD flags) { + WinHandle h(path, FILE_READ_ATTRIBUTES, flags); + if (!h) + return set_errno(); + int ret = stat_handle(h, buf); + return ret; +} + +int stat(const wchar_t *path, StatT *buf) { return stat_file(path, buf, 0); } + +int lstat(const wchar_t *path, StatT *buf) { + return stat_file(path, buf, FILE_FLAG_OPEN_REPARSE_POINT); +} + +int fstat(int fd, StatT *buf) { + HANDLE h = reinterpret_cast<HANDLE>(_get_osfhandle(fd)); + return stat_handle(h, buf); +} + +int mkdir(const wchar_t *path, int permissions) { + (void)permissions; + return _wmkdir(path); +} + +int symlink_file_dir(const wchar_t *oldname, const wchar_t *newname, + bool is_dir) { + path dest(oldname); + dest.make_preferred(); + oldname = dest.c_str(); + DWORD flags = is_dir ? SYMBOLIC_LINK_FLAG_DIRECTORY : 0; + if (CreateSymbolicLinkW(newname, oldname, + flags | SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE)) + return 0; + int e = GetLastError(); + if (e != ERROR_INVALID_PARAMETER) + return set_errno(e); + if (CreateSymbolicLinkW(newname, oldname, flags)) + return 0; + return set_errno(); +} + +int symlink_file(const wchar_t *oldname, const wchar_t *newname) { + return symlink_file_dir(oldname, newname, false); +} + +int symlink_dir(const wchar_t *oldname, const wchar_t *newname) { + return symlink_file_dir(oldname, newname, true); +} + +int link(const wchar_t *oldname, const wchar_t *newname) { + if (CreateHardLinkW(newname, oldname, nullptr)) + return 0; + return set_errno(); +} + +int remove(const wchar_t *path) { + detail::WinHandle h(path, DELETE, FILE_FLAG_OPEN_REPARSE_POINT); + if (!h) + return set_errno(); + FILE_DISPOSITION_INFO info; + info.DeleteFile = TRUE; + if (!SetFileInformationByHandle(h, FileDispositionInfo, &info, sizeof(info))) + return set_errno(); + return 0; +} + +int truncate_handle(HANDLE h, off_t length) { + LARGE_INTEGER size_param; + size_param.QuadPart = length; + if (!SetFilePointerEx(h, size_param, 0, FILE_BEGIN)) + return set_errno(); + if (!SetEndOfFile(h)) + return set_errno(); + return 0; +} + +int ftruncate(int fd, off_t length) { + HANDLE h = reinterpret_cast<HANDLE>(_get_osfhandle(fd)); + return truncate_handle(h, length); +} + +int truncate(const wchar_t *path, off_t length) { + detail::WinHandle h(path, GENERIC_WRITE, 0); + if (!h) + return set_errno(); + return truncate_handle(h, length); +} + +int rename(const wchar_t *from, const wchar_t *to) { + if (!(MoveFileExW(from, to, + MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING | + MOVEFILE_WRITE_THROUGH))) + return set_errno(); + return 0; +} + +template <class... Args> int open(const wchar_t *filename, Args... args) { + return _wopen(filename, args...); +} +int close(int fd) { return _close(fd); } +int chdir(const wchar_t *path) { return _wchdir(path); } + +struct StatVFS { + uint64_t f_frsize; + uint64_t f_blocks; + uint64_t f_bfree; + uint64_t f_bavail; +}; + +int statvfs(const wchar_t *p, StatVFS *buf) { + path dir = p; + while (true) { + error_code local_ec; + const file_status st = status(dir, local_ec); + if (!exists(st) || is_directory(st)) + break; + path parent = dir.parent_path(); + if (parent == dir) { + errno = ENOENT; + return -1; + } + dir = parent; + } + ULARGE_INTEGER free_bytes_available_to_caller, total_number_of_bytes, + total_number_of_free_bytes; + if (!GetDiskFreeSpaceExW(dir.c_str(), &free_bytes_available_to_caller, + &total_number_of_bytes, &total_number_of_free_bytes)) + return set_errno(); + buf->f_frsize = 1; + buf->f_blocks = total_number_of_bytes.QuadPart; + buf->f_bfree = total_number_of_free_bytes.QuadPart; + buf->f_bavail = free_bytes_available_to_caller.QuadPart; + return 0; +} + +wchar_t *getcwd(wchar_t *buff, size_t size) { return _wgetcwd(buff, size); } + +wchar_t *realpath(const wchar_t *path, wchar_t *resolved_name) { + // Only expected to be used with us allocating the buffer. + _LIBCPP_ASSERT(resolved_name == nullptr, + "Windows realpath() assumes a null resolved_name"); + + WinHandle h(path, FILE_READ_ATTRIBUTES, 0); + if (!h) { + set_errno(); + return nullptr; + } + size_t buff_size = MAX_PATH + 10; + std::unique_ptr<wchar_t, decltype(&::free)> buff( + static_cast<wchar_t *>(malloc(buff_size * sizeof(wchar_t))), &::free); + DWORD retval = GetFinalPathNameByHandleW( + h, buff.get(), buff_size, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS); + if (retval > buff_size) { + buff_size = retval; + buff.reset(static_cast<wchar_t *>(malloc(buff_size * sizeof(wchar_t)))); + retval = GetFinalPathNameByHandleW(h, buff.get(), buff_size, + FILE_NAME_NORMALIZED | VOLUME_NAME_DOS); + } + if (!retval) { + set_errno(); + return nullptr; + } + wchar_t *ptr = buff.get(); + if (!wcsncmp(ptr, L"\\\\?\\", 4)) { + if (ptr[5] == ':') { // \\?\X: -> X: + memmove(&ptr[0], &ptr[4], (wcslen(&ptr[4]) + 1) * sizeof(wchar_t)); + } else if (!wcsncmp(&ptr[4], L"UNC\\", 4)) { // \\?\UNC\server -> \\server + wcscpy(&ptr[0], L"\\\\"); + memmove(&ptr[2], &ptr[8], (wcslen(&ptr[8]) + 1) * sizeof(wchar_t)); + } + } + return buff.release(); +} + +#define AT_FDCWD -1 +#define AT_SYMLINK_NOFOLLOW 1 +using ModeT = int; + +int fchmod_handle(HANDLE h, int perms) { + FILE_BASIC_INFO basic; + if (!GetFileInformationByHandleEx(h, FileBasicInfo, &basic, sizeof(basic))) + return set_errno(); + DWORD orig_attributes = basic.FileAttributes; + basic.FileAttributes &= ~FILE_ATTRIBUTE_READONLY; + if ((perms & 0222) == 0) + basic.FileAttributes |= FILE_ATTRIBUTE_READONLY; + if (basic.FileAttributes != orig_attributes && + !SetFileInformationByHandle(h, FileBasicInfo, &basic, sizeof(basic))) + return set_errno(); + return 0; +} + +int fchmodat(int fd, const wchar_t *path, int perms, int flag) { + DWORD attributes = GetFileAttributesW(path); + if (attributes == INVALID_FILE_ATTRIBUTES) + return set_errno(); + if (attributes & FILE_ATTRIBUTE_REPARSE_POINT && + !(flag & AT_SYMLINK_NOFOLLOW)) { + // If the file is a symlink, and we are supposed to operate on the target + // of the symlink, we need to open a handle to it, without the + // FILE_FLAG_OPEN_REPARSE_POINT flag, to open the destination of the + // symlink, and operate on it via the handle. + detail::WinHandle h(path, FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES, 0); + if (!h) + return set_errno(); + return fchmod_handle(h, perms); + } else { + // For a non-symlink, or if operating on the symlink itself instead of + // its target, we can use SetFileAttributesW, saving a few calls. + DWORD orig_attributes = attributes; + attributes &= ~FILE_ATTRIBUTE_READONLY; + if ((perms & 0222) == 0) + attributes |= FILE_ATTRIBUTE_READONLY; + if (attributes != orig_attributes && !SetFileAttributesW(path, attributes)) + return set_errno(); + } + return 0; +} + +int fchmod(int fd, int perms) { + HANDLE h = reinterpret_cast<HANDLE>(_get_osfhandle(fd)); + return fchmod_handle(h, perms); +} + +#define MAX_SYMLINK_SIZE MAXIMUM_REPARSE_DATA_BUFFER_SIZE +using SSizeT = ::int64_t; + +SSizeT readlink(const wchar_t *path, wchar_t *ret_buf, size_t bufsize) { + uint8_t buf[MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; + detail::WinHandle h(path, FILE_READ_ATTRIBUTES, FILE_FLAG_OPEN_REPARSE_POINT); + if (!h) + return set_errno(); + DWORD out; + if (!DeviceIoControl(h, FSCTL_GET_REPARSE_POINT, nullptr, 0, buf, sizeof(buf), + &out, 0)) + return set_errno(); + const auto *reparse = reinterpret_cast<LIBCPP_REPARSE_DATA_BUFFER *>(buf); + size_t path_buf_offset = offsetof(LIBCPP_REPARSE_DATA_BUFFER, + SymbolicLinkReparseBuffer.PathBuffer[0]); + if (out < path_buf_offset) { + errno = EINVAL; + return -1; + } + if (reparse->ReparseTag != IO_REPARSE_TAG_SYMLINK) { + errno = EINVAL; + return -1; + } + const auto &symlink = reparse->SymbolicLinkReparseBuffer; + unsigned short name_offset, name_length; + if (symlink.PrintNameLength == 0) { + name_offset = symlink.SubstituteNameOffset; + name_length = symlink.SubstituteNameLength; + } else { + name_offset = symlink.PrintNameOffset; + name_length = symlink.PrintNameLength; + } + // name_offset/length are expressed in bytes, not in wchar_t + if (path_buf_offset + name_offset + name_length > out) { + errno = EINVAL; + return -1; + } + if (name_length / sizeof(wchar_t) > bufsize) { + errno = ENOMEM; + return -1; + } + memcpy(ret_buf, &symlink.PathBuffer[name_offset / sizeof(wchar_t)], + name_length); + return name_length / sizeof(wchar_t); +} + +#else +int symlink_file(const char *oldname, const char *newname) { + return ::symlink(oldname, newname); +} +int symlink_dir(const char *oldname, const char *newname) { + return ::symlink(oldname, newname); +} +using ::chdir; +using ::close; +using ::fchmod; +#if defined(AT_SYMLINK_NOFOLLOW) && defined(AT_FDCWD) +using ::fchmodat; +#endif +using ::fstat; +using ::ftruncate; +using ::getcwd; +using ::link; +using ::lstat; +using ::mkdir; +using ::open; +using ::readlink; +using ::realpath; +using ::remove; +using ::rename; +using ::stat; +using ::statvfs; +using ::truncate; + +#define O_BINARY 0 + +using StatVFS = struct statvfs; +using ModeT = ::mode_t; +using SSizeT = ::ssize_t; + +#endif + +} // namespace +} // end namespace detail + +_LIBCPP_END_NAMESPACE_FILESYSTEM + +#endif // POSIX_COMPAT_H diff --git a/lib/libcxx/src/format.cpp b/lib/libcxx/src/format.cpp new file mode 100644 index 0000000000..c36c20e60a --- /dev/null +++ b/lib/libcxx/src/format.cpp @@ -0,0 +1,19 @@ +//===------------------------- format.cpp ---------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "format" + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +format_error::~format_error() noexcept = default; + +#endif //_LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/src/functional.cpp b/lib/libcxx/src/functional.cpp index 555d2c53f2..cc5f43a9f2 100644 --- a/lib/libcxx/src/functional.cpp +++ b/lib/libcxx/src/functional.cpp @@ -11,12 +11,12 @@ _LIBCPP_BEGIN_NAMESPACE_STD #ifdef _LIBCPP_ABI_BAD_FUNCTION_CALL_KEY_FUNCTION -bad_function_call::~bad_function_call() _NOEXCEPT +bad_function_call::~bad_function_call() noexcept { } const char* -bad_function_call::what() const _NOEXCEPT +bad_function_call::what() const noexcept { return "std::bad_function_call"; } diff --git a/lib/libcxx/src/future.cpp b/lib/libcxx/src/future.cpp index 58d0b4c247..4c59f89e56 100644 --- a/lib/libcxx/src/future.cpp +++ b/lib/libcxx/src/future.cpp @@ -19,12 +19,12 @@ class _LIBCPP_HIDDEN __future_error_category : public __do_message { public: - virtual const char* name() const _NOEXCEPT; + virtual const char* name() const noexcept; virtual string message(int ev) const; }; const char* -__future_error_category::name() const _NOEXCEPT +__future_error_category::name() const noexcept { return "future"; } @@ -65,7 +65,7 @@ __future_error_category::message(int ev) const #endif const error_category& -future_category() _NOEXCEPT +future_category() noexcept { static __future_error_category __f; return __f; @@ -77,12 +77,12 @@ future_error::future_error(error_code __ec) { } -future_error::~future_error() _NOEXCEPT +future_error::~future_error() noexcept { } void -__assoc_sub_state::__on_zero_shared() _NOEXCEPT +__assoc_sub_state::__on_zero_shared() noexcept { delete this; } diff --git a/lib/libcxx/src/include/config_elast.h b/lib/libcxx/src/include/config_elast.h index 3113f9fb5c..7880c733fb 100644 --- a/lib/libcxx/src/include/config_elast.h +++ b/lib/libcxx/src/include/config_elast.h @@ -35,8 +35,12 @@ // No _LIBCPP_ELAST needed on Apple #elif defined(__sun__) #define _LIBCPP_ELAST ESTALE +#elif defined(__MVS__) +#define _LIBCPP_ELAST 1160 #elif defined(_LIBCPP_MSVCRT_LIKE) #define _LIBCPP_ELAST (_sys_nerr - 1) +#elif defined(_AIX) +#define _LIBCPP_ELAST 127 #else // Warn here so that the person doing the libcxx port has an easier time: #warning ELAST for this platform not yet implemented diff --git a/lib/libcxx/src/include/refstring.h b/lib/libcxx/src/include/refstring.h index cefd7caf0f..ad6cd162fb 100644 --- a/lib/libcxx/src/include/refstring.h +++ b/lib/libcxx/src/include/refstring.h @@ -55,7 +55,7 @@ inline char * data_from_rep(_Rep_base *rep) noexcept { #if defined(_LIBCPP_CHECK_FOR_GCC_EMPTY_STRING_STORAGE) inline -const char* compute_gcc_empty_string_storage() _NOEXCEPT +const char* compute_gcc_empty_string_storage() noexcept { void* handle = dlopen("/usr/lib/libstdc++.6.dylib", RTLD_NOLOAD); if (handle == nullptr) @@ -68,7 +68,7 @@ const char* compute_gcc_empty_string_storage() _NOEXCEPT inline const char* -get_gcc_empty_string_storage() _NOEXCEPT +get_gcc_empty_string_storage() noexcept { static const char* p = compute_gcc_empty_string_storage(); return p; @@ -92,7 +92,7 @@ __libcpp_refstring::__libcpp_refstring(const char* msg) { } inline -__libcpp_refstring::__libcpp_refstring(const __libcpp_refstring &s) _NOEXCEPT +__libcpp_refstring::__libcpp_refstring(const __libcpp_refstring &s) noexcept : __imp_(s.__imp_) { if (__uses_refcount()) @@ -100,7 +100,7 @@ __libcpp_refstring::__libcpp_refstring(const __libcpp_refstring &s) _NOEXCEPT } inline -__libcpp_refstring& __libcpp_refstring::operator=(__libcpp_refstring const& s) _NOEXCEPT { +__libcpp_refstring& __libcpp_refstring::operator=(__libcpp_refstring const& s) noexcept { bool adjust_old_count = __uses_refcount(); struct _Rep_base *old_rep = rep_from_data(__imp_); __imp_ = s.__imp_; diff --git a/lib/libcxx/src/include/sso_allocator.h b/lib/libcxx/src/include/sso_allocator.h new file mode 100644 index 0000000000..2baf599c5c --- /dev/null +++ b/lib/libcxx/src/include/sso_allocator.h @@ -0,0 +1,77 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP_SSO_ALLOCATOR_H +#define _LIBCPP_SSO_ALLOCATOR_H + +#include <__config> +#include <memory> +#include <new> +#include <type_traits> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template <class _Tp, size_t _Np> class _LIBCPP_HIDDEN __sso_allocator; + +template <size_t _Np> +class _LIBCPP_HIDDEN __sso_allocator<void, _Np> +{ +public: + typedef const void* const_pointer; + typedef void value_type; +}; + +template <class _Tp, size_t _Np> +class _LIBCPP_HIDDEN __sso_allocator +{ + typename aligned_storage<sizeof(_Tp) * _Np>::type buf_; + bool __allocated_; +public: + typedef size_t size_type; + typedef _Tp* pointer; + typedef _Tp value_type; + + _LIBCPP_INLINE_VISIBILITY __sso_allocator() throw() : __allocated_(false) {} + _LIBCPP_INLINE_VISIBILITY __sso_allocator(const __sso_allocator&) throw() : __allocated_(false) {} + template <class _Up> _LIBCPP_INLINE_VISIBILITY __sso_allocator(const __sso_allocator<_Up, _Np>&) throw() + : __allocated_(false) {} +private: + __sso_allocator& operator=(const __sso_allocator&); +public: + _LIBCPP_INLINE_VISIBILITY pointer allocate(size_type __n, typename __sso_allocator<void, _Np>::const_pointer = nullptr) + { + if (!__allocated_ && __n <= _Np) + { + __allocated_ = true; + return (pointer)&buf_; + } + return allocator<_Tp>().allocate(__n); + } + _LIBCPP_INLINE_VISIBILITY void deallocate(pointer __p, size_type __n) + { + if (__p == (pointer)&buf_) + __allocated_ = false; + else + allocator<_Tp>().deallocate(__p, __n); + } + _LIBCPP_INLINE_VISIBILITY size_type max_size() const throw() {return size_type(~0) / sizeof(_Tp);} + + _LIBCPP_INLINE_VISIBILITY + bool operator==(const __sso_allocator& __a) const {return &buf_ == &__a.buf_;} + _LIBCPP_INLINE_VISIBILITY + bool operator!=(const __sso_allocator& __a) const {return &buf_ != &__a.buf_;} +}; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_SSO_ALLOCATOR_H diff --git a/lib/libcxx/src/ios.cpp b/lib/libcxx/src/ios.cpp index 3a92964657..a8a99015a9 100644 --- a/lib/libcxx/src/ios.cpp +++ b/lib/libcxx/src/ios.cpp @@ -27,12 +27,12 @@ class _LIBCPP_HIDDEN __iostream_category : public __do_message { public: - virtual const char* name() const _NOEXCEPT; + virtual const char* name() const noexcept; virtual string message(int ev) const; }; const char* -__iostream_category::name() const _NOEXCEPT +__iostream_category::name() const noexcept { return "iostream"; } @@ -43,14 +43,14 @@ __iostream_category::message(int ev) const if (ev != static_cast<int>(io_errc::stream) #ifdef _LIBCPP_ELAST && ev <= _LIBCPP_ELAST -#endif // _LIBCPP_ELAST +#endif // _LIBCPP_ELAST ) return __do_message::message(ev); return string("unspecified iostream_category error"); } const error_category& -iostream_category() _NOEXCEPT +iostream_category() noexcept { static __iostream_category s; return s; @@ -387,7 +387,7 @@ ios_base::move(ios_base& rhs) } void -ios_base::swap(ios_base& rhs) _NOEXCEPT +ios_base::swap(ios_base& rhs) noexcept { _VSTD::swap(__fmtflags_, rhs.__fmtflags_); _VSTD::swap(__precision_, rhs.__precision_); @@ -416,7 +416,7 @@ ios_base::__set_badbit_and_consider_rethrow() #ifndef _LIBCPP_NO_EXCEPTIONS if (__exceptions_ & badbit) throw; -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_NO_EXCEPTIONS } void @@ -426,7 +426,7 @@ ios_base::__set_failbit_and_consider_rethrow() #ifndef _LIBCPP_NO_EXCEPTIONS if (__exceptions_ & failbit) throw; -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_NO_EXCEPTIONS } bool diff --git a/lib/libcxx/src/locale.cpp b/lib/libcxx/src/locale.cpp index 989e522980..72982aa7d7 100644 --- a/lib/libcxx/src/locale.cpp +++ b/lib/libcxx/src/locale.cpp @@ -27,7 +27,6 @@ #define _CTYPE_DISABLE_MACROS #endif #include "cwctype" -#include "__sso_allocator" #if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__) #include "__support/win32/locale_win32.h" #elif !defined(__BIONIC__) && !defined(__NuttX__) @@ -36,6 +35,7 @@ #include <stdlib.h> #include <stdio.h> #include "include/atomic_support.h" +#include "include/sso_allocator.h" #include "__undef_macros" // On Linux, wint_t and wchar_t have different signed-ness, and this causes @@ -206,7 +206,7 @@ _LIBCPP_SUPPRESS_DEPRECATED_PUSH install(&make<codecvt<char16_t, char, mbstate_t> >(1u)); install(&make<codecvt<char32_t, char, mbstate_t> >(1u)); _LIBCPP_SUPPRESS_DEPRECATED_POP -#ifndef _LIBCPP_NO_HAS_CHAR8_T +#ifndef _LIBCPP_HAS_NO_CHAR8_T install(&make<codecvt<char16_t, char8_t, mbstate_t> >(1u)); install(&make<codecvt<char32_t, char8_t, mbstate_t> >(1u)); #endif @@ -240,7 +240,7 @@ locale::__imp::__imp(const string& name, size_t refs) #ifndef _LIBCPP_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_NO_EXCEPTIONS facets_ = locale::classic().__locale_->facets_; for (unsigned i = 0; i < facets_.size(); ++i) if (facets_[i]) @@ -255,7 +255,7 @@ _LIBCPP_SUPPRESS_DEPRECATED_PUSH install(new codecvt_byname<char16_t, char, mbstate_t>(name_)); install(new codecvt_byname<char32_t, char, mbstate_t>(name_)); _LIBCPP_SUPPRESS_DEPRECATED_POP -#ifndef _LIBCPP_NO_HAS_CHAR8_T +#ifndef _LIBCPP_HAS_NO_CHAR8_T install(new codecvt_byname<char16_t, char8_t, mbstate_t>(name_)); install(new codecvt_byname<char32_t, char8_t, mbstate_t>(name_)); #endif @@ -280,7 +280,7 @@ _LIBCPP_SUPPRESS_DEPRECATED_POP facets_[i]->__release_shared(); throw; } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_NO_EXCEPTIONS } // NOTE avoid the `base class should be explicitly initialized in the @@ -315,7 +315,7 @@ locale::__imp::__imp(const __imp& other, const string& name, locale::category c) #ifndef _LIBCPP_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_NO_EXCEPTIONS if (c & locale::collate) { install(new collate_byname<char>(name)); @@ -331,7 +331,7 @@ _LIBCPP_SUPPRESS_DEPRECATED_PUSH install(new codecvt_byname<char16_t, char, mbstate_t>(name)); install(new codecvt_byname<char32_t, char, mbstate_t>(name)); _LIBCPP_SUPPRESS_DEPRECATED_POP -#ifndef _LIBCPP_NO_HAS_CHAR8_T +#ifndef _LIBCPP_HAS_NO_CHAR8_T install(new codecvt_byname<char16_t, char8_t, mbstate_t>(name)); install(new codecvt_byname<char32_t, char8_t, mbstate_t>(name)); #endif @@ -369,7 +369,7 @@ _LIBCPP_SUPPRESS_DEPRECATED_POP facets_[i]->__release_shared(); throw; } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_NO_EXCEPTIONS } template<class F> @@ -392,7 +392,7 @@ locale::__imp::__imp(const __imp& other, const __imp& one, locale::category c) #ifndef _LIBCPP_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_NO_EXCEPTIONS if (c & locale::collate) { install_from<_VSTD::collate<char> >(one); @@ -407,7 +407,7 @@ _LIBCPP_SUPPRESS_DEPRECATED_PUSH install_from<_VSTD::codecvt<char16_t, char, mbstate_t> >(one); install_from<_VSTD::codecvt<char32_t, char, mbstate_t> >(one); _LIBCPP_SUPPRESS_DEPRECATED_POP -#ifndef _LIBCPP_NO_HAS_CHAR8_T +#ifndef _LIBCPP_HAS_NO_CHAR8_T install_from<_VSTD::codecvt<char16_t, char8_t, mbstate_t> >(one); install_from<_VSTD::codecvt<char32_t, char8_t, mbstate_t> >(one); #endif @@ -454,7 +454,7 @@ _LIBCPP_SUPPRESS_DEPRECATED_POP facets_[i]->__release_shared(); throw; } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_NO_EXCEPTIONS } locale::__imp::__imp(const __imp& other, facet* f, long id) @@ -532,13 +532,13 @@ locale::__global() return g; } -locale::locale() _NOEXCEPT +locale::locale() noexcept : __locale_(__global().__locale_) { __locale_->__add_shared(); } -locale::locale(const locale& l) _NOEXCEPT +locale::locale(const locale& l) noexcept : __locale_(l.__locale_) { __locale_->__add_shared(); @@ -550,7 +550,7 @@ locale::~locale() } const locale& -locale::operator=(const locale& other) _NOEXCEPT +locale::operator=(const locale& other) noexcept { other.__locale_->__add_shared(); __locale_->__release_shared(); @@ -643,7 +643,7 @@ locale::facet::~facet() } void -locale::facet::__on_zero_shared() _NOEXCEPT +locale::facet::__on_zero_shared() noexcept { delete this; } @@ -1051,7 +1051,7 @@ extern "C" const int ** __ctype_toupper_loc(); #ifdef _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE const ctype<char>::mask* -ctype<char>::classic_table() _NOEXCEPT +ctype<char>::classic_table() noexcept { static _LIBCPP_CONSTEXPR const ctype<char>::mask builtin_table[table_size] = { cntrl, cntrl, @@ -1131,7 +1131,7 @@ ctype<char>::classic_table() _NOEXCEPT } #else const ctype<char>::mask* -ctype<char>::classic_table() _NOEXCEPT +ctype<char>::classic_table() noexcept { #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__DragonFly__) return _DefaultRuneLocale.__runetype; @@ -1139,7 +1139,7 @@ ctype<char>::classic_table() _NOEXCEPT return _C_ctype_tab_ + 1; #elif defined(__GLIBC__) return _LIBCPP_GET_C_LOCALE->__ctype_b; -#elif __sun__ +#elif defined(__sun__) return __ctype_mask; #elif defined(_LIBCPP_MSVCRT) || defined(__MINGW32__) return __pctype_func(); @@ -1163,38 +1163,38 @@ ctype<char>::classic_table() _NOEXCEPT #if defined(__GLIBC__) const int* -ctype<char>::__classic_lower_table() _NOEXCEPT +ctype<char>::__classic_lower_table() noexcept { return _LIBCPP_GET_C_LOCALE->__ctype_tolower; } const int* -ctype<char>::__classic_upper_table() _NOEXCEPT +ctype<char>::__classic_upper_table() noexcept { return _LIBCPP_GET_C_LOCALE->__ctype_toupper; } #elif defined(__NetBSD__) const short* -ctype<char>::__classic_lower_table() _NOEXCEPT +ctype<char>::__classic_lower_table() noexcept { return _C_tolower_tab_ + 1; } const short* -ctype<char>::__classic_upper_table() _NOEXCEPT +ctype<char>::__classic_upper_table() noexcept { return _C_toupper_tab_ + 1; } #elif defined(__EMSCRIPTEN__) const int* -ctype<char>::__classic_lower_table() _NOEXCEPT +ctype<char>::__classic_lower_table() noexcept { return *__ctype_tolower_loc(); } const int* -ctype<char>::__classic_upper_table() _NOEXCEPT +ctype<char>::__classic_upper_table() noexcept { return *__ctype_toupper_loc(); } @@ -1492,13 +1492,13 @@ codecvt<char, char, mbstate_t>::do_unshift(state_type&, } int -codecvt<char, char, mbstate_t>::do_encoding() const _NOEXCEPT +codecvt<char, char, mbstate_t>::do_encoding() const noexcept { return 1; } bool -codecvt<char, char, mbstate_t>::do_always_noconv() const _NOEXCEPT +codecvt<char, char, mbstate_t>::do_always_noconv() const noexcept { return true; } @@ -1511,7 +1511,7 @@ codecvt<char, char, mbstate_t>::do_length(state_type&, } int -codecvt<char, char, mbstate_t>::do_max_length() const _NOEXCEPT +codecvt<char, char, mbstate_t>::do_max_length() const noexcept { return 1; } @@ -1682,7 +1682,7 @@ codecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st, } int -codecvt<wchar_t, char, mbstate_t>::do_encoding() const _NOEXCEPT +codecvt<wchar_t, char, mbstate_t>::do_encoding() const noexcept { if (__libcpp_mbtowc_l(nullptr, nullptr, MB_LEN_MAX, __l) != 0) return -1; @@ -1694,7 +1694,7 @@ codecvt<wchar_t, char, mbstate_t>::do_encoding() const _NOEXCEPT } bool -codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT +codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const noexcept { return false; } @@ -1726,7 +1726,7 @@ codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st, } int -codecvt<wchar_t, char, mbstate_t>::do_max_length() const _NOEXCEPT +codecvt<wchar_t, char, mbstate_t>::do_max_length() const noexcept { return __l == 0 ? 1 : static_cast<int>(__libcpp_mb_cur_max_l(__l)); } @@ -3169,13 +3169,13 @@ codecvt<char16_t, char, mbstate_t>::do_unshift(state_type&, } int -codecvt<char16_t, char, mbstate_t>::do_encoding() const _NOEXCEPT +codecvt<char16_t, char, mbstate_t>::do_encoding() const noexcept { return 0; } bool -codecvt<char16_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT +codecvt<char16_t, char, mbstate_t>::do_always_noconv() const noexcept { return false; } @@ -3190,12 +3190,12 @@ codecvt<char16_t, char, mbstate_t>::do_length(state_type&, } int -codecvt<char16_t, char, mbstate_t>::do_max_length() const _NOEXCEPT +codecvt<char16_t, char, mbstate_t>::do_max_length() const noexcept { return 4; } -#ifndef _LIBCPP_NO_HAS_CHAR8_T +#ifndef _LIBCPP_HAS_NO_CHAR8_T // template <> class codecvt<char16_t, char8_t, mbstate_t> @@ -3248,13 +3248,13 @@ codecvt<char16_t, char8_t, mbstate_t>::do_unshift(state_type&, } int -codecvt<char16_t, char8_t, mbstate_t>::do_encoding() const _NOEXCEPT +codecvt<char16_t, char8_t, mbstate_t>::do_encoding() const noexcept { return 0; } bool -codecvt<char16_t, char8_t, mbstate_t>::do_always_noconv() const _NOEXCEPT +codecvt<char16_t, char8_t, mbstate_t>::do_always_noconv() const noexcept { return false; } @@ -3269,7 +3269,7 @@ codecvt<char16_t, char8_t, mbstate_t>::do_length(state_type&, } int -codecvt<char16_t, char8_t, mbstate_t>::do_max_length() const _NOEXCEPT +codecvt<char16_t, char8_t, mbstate_t>::do_max_length() const noexcept { return 4; } @@ -3327,13 +3327,13 @@ codecvt<char32_t, char, mbstate_t>::do_unshift(state_type&, } int -codecvt<char32_t, char, mbstate_t>::do_encoding() const _NOEXCEPT +codecvt<char32_t, char, mbstate_t>::do_encoding() const noexcept { return 0; } bool -codecvt<char32_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT +codecvt<char32_t, char, mbstate_t>::do_always_noconv() const noexcept { return false; } @@ -3348,12 +3348,12 @@ codecvt<char32_t, char, mbstate_t>::do_length(state_type&, } int -codecvt<char32_t, char, mbstate_t>::do_max_length() const _NOEXCEPT +codecvt<char32_t, char, mbstate_t>::do_max_length() const noexcept { return 4; } -#ifndef _LIBCPP_NO_HAS_CHAR8_T +#ifndef _LIBCPP_HAS_NO_CHAR8_T // template <> class codecvt<char32_t, char8_t, mbstate_t> @@ -3406,13 +3406,13 @@ codecvt<char32_t, char8_t, mbstate_t>::do_unshift(state_type&, } int -codecvt<char32_t, char8_t, mbstate_t>::do_encoding() const _NOEXCEPT +codecvt<char32_t, char8_t, mbstate_t>::do_encoding() const noexcept { return 0; } bool -codecvt<char32_t, char8_t, mbstate_t>::do_always_noconv() const _NOEXCEPT +codecvt<char32_t, char8_t, mbstate_t>::do_always_noconv() const noexcept { return false; } @@ -3427,7 +3427,7 @@ codecvt<char32_t, char8_t, mbstate_t>::do_length(state_type&, } int -codecvt<char32_t, char8_t, mbstate_t>::do_max_length() const _NOEXCEPT +codecvt<char32_t, char8_t, mbstate_t>::do_max_length() const noexcept { return 4; } @@ -3500,13 +3500,13 @@ __codecvt_utf8<wchar_t>::do_unshift(state_type&, } int -__codecvt_utf8<wchar_t>::do_encoding() const _NOEXCEPT +__codecvt_utf8<wchar_t>::do_encoding() const noexcept { return 0; } bool -__codecvt_utf8<wchar_t>::do_always_noconv() const _NOEXCEPT +__codecvt_utf8<wchar_t>::do_always_noconv() const noexcept { return false; } @@ -3521,7 +3521,7 @@ __codecvt_utf8<wchar_t>::do_length(state_type&, } int -__codecvt_utf8<wchar_t>::do_max_length() const _NOEXCEPT +__codecvt_utf8<wchar_t>::do_max_length() const noexcept { if (_Mode_ & consume_header) return 7; @@ -3575,13 +3575,13 @@ __codecvt_utf8<char16_t>::do_unshift(state_type&, } int -__codecvt_utf8<char16_t>::do_encoding() const _NOEXCEPT +__codecvt_utf8<char16_t>::do_encoding() const noexcept { return 0; } bool -__codecvt_utf8<char16_t>::do_always_noconv() const _NOEXCEPT +__codecvt_utf8<char16_t>::do_always_noconv() const noexcept { return false; } @@ -3596,7 +3596,7 @@ __codecvt_utf8<char16_t>::do_length(state_type&, } int -__codecvt_utf8<char16_t>::do_max_length() const _NOEXCEPT +__codecvt_utf8<char16_t>::do_max_length() const noexcept { if (_Mode_ & consume_header) return 6; @@ -3650,13 +3650,13 @@ __codecvt_utf8<char32_t>::do_unshift(state_type&, } int -__codecvt_utf8<char32_t>::do_encoding() const _NOEXCEPT +__codecvt_utf8<char32_t>::do_encoding() const noexcept { return 0; } bool -__codecvt_utf8<char32_t>::do_always_noconv() const _NOEXCEPT +__codecvt_utf8<char32_t>::do_always_noconv() const noexcept { return false; } @@ -3671,7 +3671,7 @@ __codecvt_utf8<char32_t>::do_length(state_type&, } int -__codecvt_utf8<char32_t>::do_max_length() const _NOEXCEPT +__codecvt_utf8<char32_t>::do_max_length() const noexcept { if (_Mode_ & consume_header) return 7; @@ -3725,13 +3725,13 @@ __codecvt_utf16<wchar_t, false>::do_unshift(state_type&, } int -__codecvt_utf16<wchar_t, false>::do_encoding() const _NOEXCEPT +__codecvt_utf16<wchar_t, false>::do_encoding() const noexcept { return 0; } bool -__codecvt_utf16<wchar_t, false>::do_always_noconv() const _NOEXCEPT +__codecvt_utf16<wchar_t, false>::do_always_noconv() const noexcept { return false; } @@ -3746,7 +3746,7 @@ __codecvt_utf16<wchar_t, false>::do_length(state_type&, } int -__codecvt_utf16<wchar_t, false>::do_max_length() const _NOEXCEPT +__codecvt_utf16<wchar_t, false>::do_max_length() const noexcept { if (_Mode_ & consume_header) return 6; @@ -3800,13 +3800,13 @@ __codecvt_utf16<wchar_t, true>::do_unshift(state_type&, } int -__codecvt_utf16<wchar_t, true>::do_encoding() const _NOEXCEPT +__codecvt_utf16<wchar_t, true>::do_encoding() const noexcept { return 0; } bool -__codecvt_utf16<wchar_t, true>::do_always_noconv() const _NOEXCEPT +__codecvt_utf16<wchar_t, true>::do_always_noconv() const noexcept { return false; } @@ -3821,7 +3821,7 @@ __codecvt_utf16<wchar_t, true>::do_length(state_type&, } int -__codecvt_utf16<wchar_t, true>::do_max_length() const _NOEXCEPT +__codecvt_utf16<wchar_t, true>::do_max_length() const noexcept { if (_Mode_ & consume_header) return 6; @@ -3875,13 +3875,13 @@ __codecvt_utf16<char16_t, false>::do_unshift(state_type&, } int -__codecvt_utf16<char16_t, false>::do_encoding() const _NOEXCEPT +__codecvt_utf16<char16_t, false>::do_encoding() const noexcept { return 0; } bool -__codecvt_utf16<char16_t, false>::do_always_noconv() const _NOEXCEPT +__codecvt_utf16<char16_t, false>::do_always_noconv() const noexcept { return false; } @@ -3896,7 +3896,7 @@ __codecvt_utf16<char16_t, false>::do_length(state_type&, } int -__codecvt_utf16<char16_t, false>::do_max_length() const _NOEXCEPT +__codecvt_utf16<char16_t, false>::do_max_length() const noexcept { if (_Mode_ & consume_header) return 4; @@ -3950,13 +3950,13 @@ __codecvt_utf16<char16_t, true>::do_unshift(state_type&, } int -__codecvt_utf16<char16_t, true>::do_encoding() const _NOEXCEPT +__codecvt_utf16<char16_t, true>::do_encoding() const noexcept { return 0; } bool -__codecvt_utf16<char16_t, true>::do_always_noconv() const _NOEXCEPT +__codecvt_utf16<char16_t, true>::do_always_noconv() const noexcept { return false; } @@ -3971,7 +3971,7 @@ __codecvt_utf16<char16_t, true>::do_length(state_type&, } int -__codecvt_utf16<char16_t, true>::do_max_length() const _NOEXCEPT +__codecvt_utf16<char16_t, true>::do_max_length() const noexcept { if (_Mode_ & consume_header) return 4; @@ -4025,13 +4025,13 @@ __codecvt_utf16<char32_t, false>::do_unshift(state_type&, } int -__codecvt_utf16<char32_t, false>::do_encoding() const _NOEXCEPT +__codecvt_utf16<char32_t, false>::do_encoding() const noexcept { return 0; } bool -__codecvt_utf16<char32_t, false>::do_always_noconv() const _NOEXCEPT +__codecvt_utf16<char32_t, false>::do_always_noconv() const noexcept { return false; } @@ -4046,7 +4046,7 @@ __codecvt_utf16<char32_t, false>::do_length(state_type&, } int -__codecvt_utf16<char32_t, false>::do_max_length() const _NOEXCEPT +__codecvt_utf16<char32_t, false>::do_max_length() const noexcept { if (_Mode_ & consume_header) return 6; @@ -4100,13 +4100,13 @@ __codecvt_utf16<char32_t, true>::do_unshift(state_type&, } int -__codecvt_utf16<char32_t, true>::do_encoding() const _NOEXCEPT +__codecvt_utf16<char32_t, true>::do_encoding() const noexcept { return 0; } bool -__codecvt_utf16<char32_t, true>::do_always_noconv() const _NOEXCEPT +__codecvt_utf16<char32_t, true>::do_always_noconv() const noexcept { return false; } @@ -4121,7 +4121,7 @@ __codecvt_utf16<char32_t, true>::do_length(state_type&, } int -__codecvt_utf16<char32_t, true>::do_max_length() const _NOEXCEPT +__codecvt_utf16<char32_t, true>::do_max_length() const noexcept { if (_Mode_ & consume_header) return 6; @@ -4175,13 +4175,13 @@ __codecvt_utf8_utf16<wchar_t>::do_unshift(state_type&, } int -__codecvt_utf8_utf16<wchar_t>::do_encoding() const _NOEXCEPT +__codecvt_utf8_utf16<wchar_t>::do_encoding() const noexcept { return 0; } bool -__codecvt_utf8_utf16<wchar_t>::do_always_noconv() const _NOEXCEPT +__codecvt_utf8_utf16<wchar_t>::do_always_noconv() const noexcept { return false; } @@ -4196,7 +4196,7 @@ __codecvt_utf8_utf16<wchar_t>::do_length(state_type&, } int -__codecvt_utf8_utf16<wchar_t>::do_max_length() const _NOEXCEPT +__codecvt_utf8_utf16<wchar_t>::do_max_length() const noexcept { if (_Mode_ & consume_header) return 7; @@ -4250,13 +4250,13 @@ __codecvt_utf8_utf16<char16_t>::do_unshift(state_type&, } int -__codecvt_utf8_utf16<char16_t>::do_encoding() const _NOEXCEPT +__codecvt_utf8_utf16<char16_t>::do_encoding() const noexcept { return 0; } bool -__codecvt_utf8_utf16<char16_t>::do_always_noconv() const _NOEXCEPT +__codecvt_utf8_utf16<char16_t>::do_always_noconv() const noexcept { return false; } @@ -4271,7 +4271,7 @@ __codecvt_utf8_utf16<char16_t>::do_length(state_type&, } int -__codecvt_utf8_utf16<char16_t>::do_max_length() const _NOEXCEPT +__codecvt_utf8_utf16<char16_t>::do_max_length() const noexcept { if (_Mode_ & consume_header) return 7; @@ -4325,13 +4325,13 @@ __codecvt_utf8_utf16<char32_t>::do_unshift(state_type&, } int -__codecvt_utf8_utf16<char32_t>::do_encoding() const _NOEXCEPT +__codecvt_utf8_utf16<char32_t>::do_encoding() const noexcept { return 0; } bool -__codecvt_utf8_utf16<char32_t>::do_always_noconv() const _NOEXCEPT +__codecvt_utf8_utf16<char32_t>::do_always_noconv() const noexcept { return false; } @@ -4346,7 +4346,7 @@ __codecvt_utf8_utf16<char32_t>::do_length(state_type&, } int -__codecvt_utf8_utf16<char32_t>::do_max_length() const _NOEXCEPT +__codecvt_utf8_utf16<char32_t>::do_max_length() const noexcept { if (_Mode_ & consume_header) return 7; @@ -4597,7 +4597,10 @@ void __num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd, ios_base::fmtflags __flags) { - if (__flags & ios_base::showpos) + if ((__flags & ios_base::showpos) && + (__flags & ios_base::basefield) != ios_base::oct && + (__flags & ios_base::basefield) != ios_base::hex && + __signd) *__fmtp++ = '+'; if (__flags & ios_base::showbase) *__fmtp++ = '#'; @@ -6336,7 +6339,7 @@ template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char, cha template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<wchar_t, char, mbstate_t>; template class _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char16_t, char, mbstate_t>; template class _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char32_t, char, mbstate_t>; -#ifndef _LIBCPP_NO_HAS_CHAR8_T +#ifndef _LIBCPP_HAS_NO_CHAR8_T template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char16_t, char8_t, mbstate_t>; template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char32_t, char8_t, mbstate_t>; #endif diff --git a/lib/libcxx/src/memory.cpp b/lib/libcxx/src/memory.cpp index 5a5894fd94..9bd27df268 100644 --- a/lib/libcxx/src/memory.cpp +++ b/lib/libcxx/src/memory.cpp @@ -20,10 +20,10 @@ _LIBCPP_BEGIN_NAMESPACE_STD const allocator_arg_t allocator_arg = allocator_arg_t(); -bad_weak_ptr::~bad_weak_ptr() _NOEXCEPT {} +bad_weak_ptr::~bad_weak_ptr() noexcept {} const char* -bad_weak_ptr::what() const _NOEXCEPT +bad_weak_ptr::what() const noexcept { return "bad_weak_ptr"; } @@ -38,13 +38,13 @@ __shared_weak_count::~__shared_weak_count() #if defined(_LIBCPP_DEPRECATED_ABI_LEGACY_LIBRARY_DEFINITIONS_FOR_INLINE_FUNCTIONS) void -__shared_count::__add_shared() _NOEXCEPT +__shared_count::__add_shared() noexcept { __libcpp_atomic_refcount_increment(__shared_owners_); } bool -__shared_count::__release_shared() _NOEXCEPT +__shared_count::__release_shared() noexcept { if (__libcpp_atomic_refcount_decrement(__shared_owners_) == -1) { @@ -55,19 +55,19 @@ __shared_count::__release_shared() _NOEXCEPT } void -__shared_weak_count::__add_shared() _NOEXCEPT +__shared_weak_count::__add_shared() noexcept { __shared_count::__add_shared(); } void -__shared_weak_count::__add_weak() _NOEXCEPT +__shared_weak_count::__add_weak() noexcept { __libcpp_atomic_refcount_increment(__shared_weak_owners_); } void -__shared_weak_count::__release_shared() _NOEXCEPT +__shared_weak_count::__release_shared() noexcept { if (__shared_count::__release_shared()) __release_weak(); @@ -76,7 +76,7 @@ __shared_weak_count::__release_shared() _NOEXCEPT #endif // _LIBCPP_DEPRECATED_ABI_LEGACY_LIBRARY_DEFINITIONS_FOR_INLINE_FUNCTIONS void -__shared_weak_count::__release_weak() _NOEXCEPT +__shared_weak_count::__release_weak() noexcept { // NOTE: The acquire load here is an optimization of the very // common case where a shared pointer is being destructed while @@ -111,7 +111,7 @@ __shared_weak_count::__release_weak() _NOEXCEPT } __shared_weak_count* -__shared_weak_count::lock() _NOEXCEPT +__shared_weak_count::lock() noexcept { long object_owners = __libcpp_atomic_load(&__shared_owners_); while (object_owners != -1) @@ -125,7 +125,7 @@ __shared_weak_count::lock() _NOEXCEPT } const void* -__shared_weak_count::__get_deleter(const type_info&) const _NOEXCEPT +__shared_weak_count::__get_deleter(const type_info&) const noexcept { return nullptr; } @@ -141,13 +141,13 @@ _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_CONSTEXPR __sp_mut::__sp_mut(void* p) _NOEXCEPT +_LIBCPP_CONSTEXPR __sp_mut::__sp_mut(void* p) noexcept : __lx(p) { } void -__sp_mut::lock() _NOEXCEPT +__sp_mut::lock() noexcept { auto m = static_cast<__libcpp_mutex_t*>(__lx); unsigned count = 0; @@ -163,7 +163,7 @@ __sp_mut::lock() _NOEXCEPT } void -__sp_mut::unlock() _NOEXCEPT +__sp_mut::unlock() noexcept { __libcpp_mutex_unlock(static_cast<__libcpp_mutex_t*>(__lx)); } @@ -198,13 +198,6 @@ undeclare_no_pointers(char*, size_t) { } -#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/lib/libcxx/src/mutex.cpp b/lib/libcxx/src/mutex.cpp index 27a4fd8927..36362e34f3 100644 --- a/lib/libcxx/src/mutex.cpp +++ b/lib/libcxx/src/mutex.cpp @@ -36,13 +36,13 @@ mutex::lock() } bool -mutex::try_lock() _NOEXCEPT +mutex::try_lock() noexcept { return __libcpp_mutex_trylock(&__m_); } void -mutex::unlock() _NOEXCEPT +mutex::unlock() noexcept { int ec = __libcpp_mutex_unlock(&__m_); (void)ec; @@ -74,7 +74,7 @@ recursive_mutex::lock() } void -recursive_mutex::unlock() _NOEXCEPT +recursive_mutex::unlock() noexcept { int e = __libcpp_recursive_mutex_unlock(&__m_); (void)e; @@ -82,7 +82,7 @@ recursive_mutex::unlock() _NOEXCEPT } bool -recursive_mutex::try_lock() _NOEXCEPT +recursive_mutex::try_lock() noexcept { return __libcpp_recursive_mutex_trylock(&__m_); } @@ -109,7 +109,7 @@ timed_mutex::lock() } bool -timed_mutex::try_lock() _NOEXCEPT +timed_mutex::try_lock() noexcept { unique_lock<mutex> lk(__m_, try_to_lock); if (lk.owns_lock() && !__locked_) @@ -121,7 +121,7 @@ timed_mutex::try_lock() _NOEXCEPT } void -timed_mutex::unlock() _NOEXCEPT +timed_mutex::unlock() noexcept { lock_guard<mutex> _(__m_); __locked_ = false; @@ -160,7 +160,7 @@ recursive_timed_mutex::lock() } bool -recursive_timed_mutex::try_lock() _NOEXCEPT +recursive_timed_mutex::try_lock() noexcept { __thread_id id = this_thread::get_id(); unique_lock<mutex> lk(__m_, try_to_lock); @@ -176,7 +176,7 @@ recursive_timed_mutex::try_lock() _NOEXCEPT } void -recursive_timed_mutex::unlock() _NOEXCEPT +recursive_timed_mutex::unlock() noexcept { unique_lock<mutex> lk(__m_); if (--__count_ == 0) @@ -209,7 +209,7 @@ void __call_once(volatile once_flag::_State_type& flag, void* arg, #ifndef _LIBCPP_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_NO_EXCEPTIONS flag = 1; func(arg); flag = ~once_flag::_State_type(0); @@ -220,7 +220,7 @@ void __call_once(volatile once_flag::_State_type& flag, void* arg, flag = 0; throw; } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_NO_EXCEPTIONS } #else // !_LIBCPP_HAS_NO_THREADS __libcpp_mutex_lock(&mut); @@ -231,7 +231,7 @@ void __call_once(volatile once_flag::_State_type& flag, void* arg, #ifndef _LIBCPP_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_NO_EXCEPTIONS __libcpp_relaxed_store(&flag, once_flag::_State_type(1)); __libcpp_mutex_unlock(&mut); func(arg); @@ -250,7 +250,7 @@ void __call_once(volatile once_flag::_State_type& flag, void* arg, __libcpp_condvar_broadcast(&cv); throw; } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_NO_EXCEPTIONS } else __libcpp_mutex_unlock(&mut); diff --git a/lib/libcxx/src/mutex_destructor.cpp b/lib/libcxx/src/mutex_destructor.cpp index 2038d2bbe2..07197c3fb4 100644 --- a/lib/libcxx/src/mutex_destructor.cpp +++ b/lib/libcxx/src/mutex_destructor.cpp @@ -41,7 +41,7 @@ public: }; -mutex::~mutex() _NOEXCEPT +mutex::~mutex() noexcept { __libcpp_mutex_destroy(&__m_); } diff --git a/lib/libcxx/src/new.cpp b/lib/libcxx/src/new.cpp index 9d01330ba7..5486815abb 100644 --- a/lib/libcxx/src/new.cpp +++ b/lib/libcxx/src/new.cpp @@ -83,20 +83,20 @@ operator new(std::size_t size) _THROW_BAD_ALLOC _LIBCPP_WEAK void* -operator new(size_t size, const std::nothrow_t&) _NOEXCEPT +operator new(size_t size, const std::nothrow_t&) noexcept { void* p = nullptr; #ifndef _LIBCPP_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_NO_EXCEPTIONS p = ::operator new(size); #ifndef _LIBCPP_NO_EXCEPTIONS } catch (...) { } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_NO_EXCEPTIONS return p; } @@ -109,61 +109,61 @@ operator new[](size_t size) _THROW_BAD_ALLOC _LIBCPP_WEAK void* -operator new[](size_t size, const std::nothrow_t&) _NOEXCEPT +operator new[](size_t size, const std::nothrow_t&) noexcept { void* p = nullptr; #ifndef _LIBCPP_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_NO_EXCEPTIONS p = ::operator new[](size); #ifndef _LIBCPP_NO_EXCEPTIONS } catch (...) { } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_NO_EXCEPTIONS return p; } _LIBCPP_WEAK void -operator delete(void* ptr) _NOEXCEPT +operator delete(void* ptr) noexcept { ::free(ptr); } _LIBCPP_WEAK void -operator delete(void* ptr, const std::nothrow_t&) _NOEXCEPT +operator delete(void* ptr, const std::nothrow_t&) noexcept { ::operator delete(ptr); } _LIBCPP_WEAK void -operator delete(void* ptr, size_t) _NOEXCEPT +operator delete(void* ptr, size_t) noexcept { ::operator delete(ptr); } _LIBCPP_WEAK void -operator delete[] (void* ptr) _NOEXCEPT +operator delete[] (void* ptr) noexcept { ::operator delete(ptr); } _LIBCPP_WEAK void -operator delete[] (void* ptr, const std::nothrow_t&) _NOEXCEPT +operator delete[] (void* ptr, const std::nothrow_t&) noexcept { ::operator delete[](ptr); } _LIBCPP_WEAK void -operator delete[] (void* ptr, size_t) _NOEXCEPT +operator delete[] (void* ptr, size_t) noexcept { ::operator delete[](ptr); } @@ -204,20 +204,20 @@ operator new(std::size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC _LIBCPP_WEAK void* -operator new(size_t size, std::align_val_t alignment, const std::nothrow_t&) _NOEXCEPT +operator new(size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept { void* p = nullptr; #ifndef _LIBCPP_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_NO_EXCEPTIONS p = ::operator new(size, alignment); #ifndef _LIBCPP_NO_EXCEPTIONS } catch (...) { } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_NO_EXCEPTIONS return p; } @@ -230,61 +230,61 @@ operator new[](size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC _LIBCPP_WEAK void* -operator new[](size_t size, std::align_val_t alignment, const std::nothrow_t&) _NOEXCEPT +operator new[](size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept { void* p = nullptr; #ifndef _LIBCPP_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_NO_EXCEPTIONS p = ::operator new[](size, alignment); #ifndef _LIBCPP_NO_EXCEPTIONS } catch (...) { } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_NO_EXCEPTIONS return p; } _LIBCPP_WEAK void -operator delete(void* ptr, std::align_val_t) _NOEXCEPT +operator delete(void* ptr, std::align_val_t) noexcept { std::__libcpp_aligned_free(ptr); } _LIBCPP_WEAK void -operator delete(void* ptr, std::align_val_t alignment, const std::nothrow_t&) _NOEXCEPT +operator delete(void* ptr, std::align_val_t alignment, const std::nothrow_t&) noexcept { ::operator delete(ptr, alignment); } _LIBCPP_WEAK void -operator delete(void* ptr, size_t, std::align_val_t alignment) _NOEXCEPT +operator delete(void* ptr, size_t, std::align_val_t alignment) noexcept { ::operator delete(ptr, alignment); } _LIBCPP_WEAK void -operator delete[] (void* ptr, std::align_val_t alignment) _NOEXCEPT +operator delete[] (void* ptr, std::align_val_t alignment) noexcept { ::operator delete(ptr, alignment); } _LIBCPP_WEAK void -operator delete[] (void* ptr, std::align_val_t alignment, const std::nothrow_t&) _NOEXCEPT +operator delete[] (void* ptr, std::align_val_t alignment, const std::nothrow_t&) noexcept { ::operator delete[](ptr, alignment); } _LIBCPP_WEAK void -operator delete[] (void* ptr, size_t, std::align_val_t alignment) _NOEXCEPT +operator delete[] (void* ptr, size_t, std::align_val_t alignment) noexcept { ::operator delete[](ptr, alignment); } diff --git a/lib/libcxx/src/optional.cpp b/lib/libcxx/src/optional.cpp index 86d013b350..39405bec12 100644 --- a/lib/libcxx/src/optional.cpp +++ b/lib/libcxx/src/optional.cpp @@ -12,9 +12,9 @@ namespace std { -bad_optional_access::~bad_optional_access() _NOEXCEPT = default; +bad_optional_access::~bad_optional_access() noexcept = default; -const char* bad_optional_access::what() const _NOEXCEPT { +const char* bad_optional_access::what() const noexcept { return "bad_optional_access"; } @@ -34,9 +34,9 @@ public: bad_optional_access() : std::logic_error("Bad optional Access") {} // Get the key function ~bad_optional_access() into the dylib - virtual ~bad_optional_access() _NOEXCEPT; + virtual ~bad_optional_access() noexcept; }; -bad_optional_access::~bad_optional_access() _NOEXCEPT = default; +bad_optional_access::~bad_optional_access() noexcept = default; _LIBCPP_END_NAMESPACE_EXPERIMENTAL diff --git a/lib/libcxx/src/random.cpp b/lib/libcxx/src/random.cpp index 29aa43b1e1..8ea080842e 100644 --- a/lib/libcxx/src/random.cpp +++ b/lib/libcxx/src/random.cpp @@ -175,7 +175,7 @@ random_device::operator()() #endif double -random_device::entropy() const _NOEXCEPT +random_device::entropy() const noexcept { #if defined(_LIBCPP_USING_DEV_RANDOM) && defined(RNDGETENTCNT) int ent; diff --git a/lib/libcxx/src/string.cpp b/lib/libcxx/src/string.cpp index 5105594cf3..97a773f79a 100644 --- a/lib/libcxx/src/string.cpp +++ b/lib/libcxx/src/string.cpp @@ -20,6 +20,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __basic_string_common<true>; +#define _LIBCPP_EXTERN_TEMPLATE_DEFINE(...) template __VA_ARGS__; #ifdef _LIBCPP_ABI_STRING_OPTIMIZED_EXTERNAL_INSTANTIATION _LIBCPP_STRING_UNSTABLE_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, char) _LIBCPP_STRING_UNSTABLE_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, wchar_t) @@ -27,10 +28,9 @@ _LIBCPP_STRING_UNSTABLE_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, wch _LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, char) _LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, wchar_t) #endif +#undef _LIBCPP_EXTERN_TEMPLATE_DEFINE -template - string - operator+<char, char_traits<char>, allocator<char> >(char const*, string const&); +template string operator+<char, char_traits<char>, allocator<char> >(char const*, string const&); namespace { @@ -423,7 +423,7 @@ get_swprintf() } template <typename S, typename V> -S i_to_string(const V v) +S i_to_string(V v) { // numeric_limits::digits10 returns value less on 1 than desired for unsigned numbers. // For example, for 1-byte unsigned value digits10 is 2 (999 can not be represented), diff --git a/lib/libcxx/src/support/ibm/xlocale_zos.cpp b/lib/libcxx/src/support/ibm/xlocale_zos.cpp new file mode 100644 index 0000000000..cb3a9507eb --- /dev/null +++ b/lib/libcxx/src/support/ibm/xlocale_zos.cpp @@ -0,0 +1,137 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include <__support/ibm/xlocale.h> +#include <sstream> +#include <vector> + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +locale_t newlocale(int category_mask, const char* locale, locale_t base) { + // Maintain current locale name(s) to restore later. + std::string current_loc_name(setlocale(LC_ALL, 0)); + + // Check for errors. + if (category_mask == LC_ALL_MASK && setlocale(LC_ALL, locale) == NULL) { + errno = EINVAL; + return (locale_t)0; + } else { + for (int _Cat = 0; _Cat <= _LC_MAX; ++_Cat) { + if ((_CATMASK(_Cat) & category_mask) != 0 && setlocale(_Cat, locale) == NULL) { + setlocale(LC_ALL, current_loc_name.c_str()); + errno = EINVAL; + return (locale_t)0; + } + } + } + + // Create new locale. + locale_t newloc = new locale_struct(); + + if (base) { + if (category_mask != LC_ALL_MASK) { + // Copy base when it will not be overwritten. + memcpy(newloc, base, sizeof (locale_struct)); + newloc->category_mask = category_mask | base->category_mask; + } + delete base; + } else { + newloc->category_mask = category_mask; + } + + if (category_mask & LC_COLLATE_MASK) + newloc->lc_collate = locale; + if (category_mask & LC_CTYPE_MASK) + newloc->lc_ctype = locale; + if (category_mask & LC_MONETARY_MASK) + newloc->lc_monetary = locale; + if (category_mask & LC_NUMERIC_MASK) + newloc->lc_numeric = locale; + if (category_mask & LC_TIME_MASK) + newloc->lc_time = locale; + if (category_mask & LC_MESSAGES_MASK) + newloc->lc_messages = locale; + + // Restore current locale. + setlocale(LC_ALL, current_loc_name.c_str()); + return (locale_t)newloc; +} + +void freelocale(locale_t locobj) { + delete locobj; +} + +locale_t uselocale(locale_t newloc) { + // Maintain current locale name(s). + std::string current_loc_name(setlocale(LC_ALL, 0)); + + if (newloc) { + // Set locales and check for errors. + bool is_error = + (newloc->category_mask & LC_COLLATE_MASK && + setlocale(LC_COLLATE, newloc->lc_collate.c_str()) == NULL) || + (newloc->category_mask & LC_CTYPE_MASK && + setlocale(LC_CTYPE, newloc->lc_ctype.c_str()) == NULL) || + (newloc->category_mask & LC_MONETARY_MASK && + setlocale(LC_MONETARY, newloc->lc_monetary.c_str()) == NULL) || + (newloc->category_mask & LC_NUMERIC_MASK && + setlocale(LC_NUMERIC, newloc->lc_numeric.c_str()) == NULL) || + (newloc->category_mask & LC_TIME_MASK && + setlocale(LC_TIME, newloc->lc_time.c_str()) == NULL) || + (newloc->category_mask & LC_MESSAGES_MASK && + setlocale(LC_MESSAGES, newloc->lc_messages.c_str()) == NULL); + + if (is_error) { + setlocale(LC_ALL, current_loc_name.c_str()); + errno = EINVAL; + return (locale_t)0; + } + } + + // Construct and return previous locale. + locale_t previous_loc = new locale_struct(); + + // current_loc_name might be a comma-separated locale name list. + if (current_loc_name.find(',') != std::string::npos) { + // Tokenize locale name list. + const char delimiter = ','; + std::vector<std::string> tokenized; + std::stringstream ss(current_loc_name); + std::string s; + + while (std::getline(ss, s, delimiter)) { + tokenized.push_back(s); + } + + _LIBCPP_ASSERT(tokenized.size() >= _NCAT, "locale-name list is too short"); + + previous_loc->lc_collate = tokenized[LC_COLLATE]; + previous_loc->lc_ctype = tokenized[LC_CTYPE]; + previous_loc->lc_monetary = tokenized[LC_MONETARY]; + previous_loc->lc_numeric = tokenized[LC_NUMERIC]; + previous_loc->lc_time = tokenized[LC_TIME]; + // Skip LC_TOD. + previous_loc->lc_messages = tokenized[LC_MESSAGES]; + } else { + previous_loc->lc_collate = current_loc_name; + previous_loc->lc_ctype = current_loc_name; + previous_loc->lc_monetary = current_loc_name; + previous_loc->lc_numeric = current_loc_name; + previous_loc->lc_time = current_loc_name; + previous_loc->lc_messages = current_loc_name; + } + + previous_loc->category_mask = LC_ALL_MASK; + return previous_loc; +} + +#ifdef __cplusplus +} +#endif // __cplusplus diff --git a/lib/libcxx/src/support/runtime/exception_fallback.ipp b/lib/libcxx/src/support/runtime/exception_fallback.ipp index faa112f7f3..67ebde3061 100644 --- a/lib/libcxx/src/support/runtime/exception_fallback.ipp +++ b/lib/libcxx/src/support/runtime/exception_fallback.ipp @@ -17,13 +17,13 @@ _LIBCPP_SAFE_STATIC static std::unexpected_handler __unexpected_handler; // libcxxrt provides implementations of these functions itself. unexpected_handler -set_unexpected(unexpected_handler func) _NOEXCEPT +set_unexpected(unexpected_handler func) noexcept { return __libcpp_atomic_exchange(&__unexpected_handler, func); } unexpected_handler -get_unexpected() _NOEXCEPT +get_unexpected() noexcept { return __libcpp_atomic_load(&__unexpected_handler); @@ -38,25 +38,25 @@ void unexpected() } terminate_handler -set_terminate(terminate_handler func) _NOEXCEPT +set_terminate(terminate_handler func) noexcept { return __libcpp_atomic_exchange(&__terminate_handler, func); } terminate_handler -get_terminate() _NOEXCEPT +get_terminate() noexcept { return __libcpp_atomic_load(&__terminate_handler); } _LIBCPP_NORETURN void -terminate() _NOEXCEPT +terminate() noexcept { #ifndef _LIBCPP_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_NO_EXCEPTIONS (*get_terminate())(); // handler should not return fprintf(stderr, "terminate_handler unexpectedly returned\n"); @@ -69,12 +69,12 @@ terminate() _NOEXCEPT fprintf(stderr, "terminate_handler unexpectedly threw an exception\n"); ::abort(); } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_NO_EXCEPTIONS } -bool uncaught_exception() _NOEXCEPT { return uncaught_exceptions() > 0; } +bool uncaught_exception() noexcept { return uncaught_exceptions() > 0; } -int uncaught_exceptions() _NOEXCEPT +int uncaught_exceptions() noexcept { #warning uncaught_exception not yet implemented fprintf(stderr, "uncaught_exceptions not yet implemented\n"); @@ -82,77 +82,77 @@ int uncaught_exceptions() _NOEXCEPT } -exception::~exception() _NOEXCEPT +exception::~exception() noexcept { } -const char* exception::what() const _NOEXCEPT +const char* exception::what() const noexcept { return "std::exception"; } -bad_exception::~bad_exception() _NOEXCEPT +bad_exception::~bad_exception() noexcept { } -const char* bad_exception::what() const _NOEXCEPT +const char* bad_exception::what() const noexcept { return "std::bad_exception"; } -bad_alloc::bad_alloc() _NOEXCEPT +bad_alloc::bad_alloc() noexcept { } -bad_alloc::~bad_alloc() _NOEXCEPT +bad_alloc::~bad_alloc() noexcept { } const char* -bad_alloc::what() const _NOEXCEPT +bad_alloc::what() const noexcept { return "std::bad_alloc"; } -bad_array_new_length::bad_array_new_length() _NOEXCEPT +bad_array_new_length::bad_array_new_length() noexcept { } -bad_array_new_length::~bad_array_new_length() _NOEXCEPT +bad_array_new_length::~bad_array_new_length() noexcept { } const char* -bad_array_new_length::what() const _NOEXCEPT +bad_array_new_length::what() const noexcept { return "bad_array_new_length"; } -bad_cast::bad_cast() _NOEXCEPT +bad_cast::bad_cast() noexcept { } -bad_typeid::bad_typeid() _NOEXCEPT +bad_typeid::bad_typeid() noexcept { } -bad_cast::~bad_cast() _NOEXCEPT +bad_cast::~bad_cast() noexcept { } const char* -bad_cast::what() const _NOEXCEPT +bad_cast::what() const noexcept { return "std::bad_cast"; } -bad_typeid::~bad_typeid() _NOEXCEPT +bad_typeid::~bad_typeid() noexcept { } const char* -bad_typeid::what() const _NOEXCEPT +bad_typeid::what() const noexcept { return "std::bad_typeid"; } diff --git a/lib/libcxx/src/support/runtime/exception_glibcxx.ipp b/lib/libcxx/src/support/runtime/exception_glibcxx.ipp index 4bf3c4d877..e478ccbb6e 100644 --- a/lib/libcxx/src/support/runtime/exception_glibcxx.ipp +++ b/lib/libcxx/src/support/runtime/exception_glibcxx.ipp @@ -13,19 +13,19 @@ namespace std { -bad_alloc::bad_alloc() _NOEXCEPT +bad_alloc::bad_alloc() noexcept { } -bad_array_new_length::bad_array_new_length() _NOEXCEPT +bad_array_new_length::bad_array_new_length() noexcept { } -bad_cast::bad_cast() _NOEXCEPT +bad_cast::bad_cast() noexcept { } -bad_typeid::bad_typeid() _NOEXCEPT +bad_typeid::bad_typeid() noexcept { } diff --git a/lib/libcxx/src/support/runtime/exception_libcxxabi.ipp b/lib/libcxx/src/support/runtime/exception_libcxxabi.ipp index 6bc049bf38..ee15e437e6 100644 --- a/lib/libcxx/src/support/runtime/exception_libcxxabi.ipp +++ b/lib/libcxx/src/support/runtime/exception_libcxxabi.ipp @@ -13,9 +13,9 @@ namespace std { -bool uncaught_exception() _NOEXCEPT { return uncaught_exceptions() > 0; } +bool uncaught_exception() noexcept { return uncaught_exceptions() > 0; } -int uncaught_exceptions() _NOEXCEPT +int uncaught_exceptions() noexcept { # if _LIBCPPABI_VERSION > 1001 return __cxa_uncaught_exceptions(); diff --git a/lib/libcxx/src/support/runtime/exception_libcxxrt.ipp b/lib/libcxx/src/support/runtime/exception_libcxxrt.ipp index 0ebffdedba..62aa3229ed 100644 --- a/lib/libcxx/src/support/runtime/exception_libcxxrt.ipp +++ b/lib/libcxx/src/support/runtime/exception_libcxxrt.ipp @@ -13,11 +13,11 @@ namespace std { -bad_exception::~bad_exception() _NOEXCEPT +bad_exception::~bad_exception() noexcept { } -const char* bad_exception::what() const _NOEXCEPT +const char* bad_exception::what() const noexcept { return "std::bad_exception"; } diff --git a/lib/libcxx/src/support/runtime/exception_msvc.ipp b/lib/libcxx/src/support/runtime/exception_msvc.ipp index 7315b8261b..7e36c7068a 100644 --- a/lib/libcxx/src/support/runtime/exception_msvc.ipp +++ b/lib/libcxx/src/support/runtime/exception_msvc.ipp @@ -31,11 +31,11 @@ int __cdecl __uncaught_exceptions(); namespace std { unexpected_handler -set_unexpected(unexpected_handler func) _NOEXCEPT { +set_unexpected(unexpected_handler func) noexcept { return ::set_unexpected(func); } -unexpected_handler get_unexpected() _NOEXCEPT { +unexpected_handler get_unexpected() noexcept { return ::_get_unexpected(); } @@ -46,21 +46,21 @@ void unexpected() { terminate(); } -terminate_handler set_terminate(terminate_handler func) _NOEXCEPT { +terminate_handler set_terminate(terminate_handler func) noexcept { return ::set_terminate(func); } -terminate_handler get_terminate() _NOEXCEPT { +terminate_handler get_terminate() noexcept { return ::_get_terminate(); } _LIBCPP_NORETURN -void terminate() _NOEXCEPT +void terminate() noexcept { #ifndef _LIBCPP_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_NO_EXCEPTIONS (*get_terminate())(); // handler should not return fprintf(stderr, "terminate_handler unexpectedly returned\n"); @@ -73,88 +73,88 @@ void terminate() _NOEXCEPT fprintf(stderr, "terminate_handler unexpectedly threw an exception\n"); ::abort(); } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_NO_EXCEPTIONS } -bool uncaught_exception() _NOEXCEPT { return uncaught_exceptions() > 0; } +bool uncaught_exception() noexcept { return uncaught_exceptions() > 0; } -int uncaught_exceptions() _NOEXCEPT { +int uncaught_exceptions() noexcept { return __uncaught_exceptions(); } #if !defined(_LIBCPP_ABI_VCRUNTIME) -bad_cast::bad_cast() _NOEXCEPT +bad_cast::bad_cast() noexcept { } -bad_cast::~bad_cast() _NOEXCEPT +bad_cast::~bad_cast() noexcept { } const char * -bad_cast::what() const _NOEXCEPT +bad_cast::what() const noexcept { return "std::bad_cast"; } -bad_typeid::bad_typeid() _NOEXCEPT +bad_typeid::bad_typeid() noexcept { } -bad_typeid::~bad_typeid() _NOEXCEPT +bad_typeid::~bad_typeid() noexcept { } const char * -bad_typeid::what() const _NOEXCEPT +bad_typeid::what() const noexcept { return "std::bad_typeid"; } -exception::~exception() _NOEXCEPT +exception::~exception() noexcept { } -const char* exception::what() const _NOEXCEPT +const char* exception::what() const noexcept { return "std::exception"; } -bad_exception::~bad_exception() _NOEXCEPT +bad_exception::~bad_exception() noexcept { } -const char* bad_exception::what() const _NOEXCEPT +const char* bad_exception::what() const noexcept { return "std::bad_exception"; } -bad_alloc::bad_alloc() _NOEXCEPT +bad_alloc::bad_alloc() noexcept { } -bad_alloc::~bad_alloc() _NOEXCEPT +bad_alloc::~bad_alloc() noexcept { } const char* -bad_alloc::what() const _NOEXCEPT +bad_alloc::what() const noexcept { return "std::bad_alloc"; } -bad_array_new_length::bad_array_new_length() _NOEXCEPT +bad_array_new_length::bad_array_new_length() noexcept { } -bad_array_new_length::~bad_array_new_length() _NOEXCEPT +bad_array_new_length::~bad_array_new_length() noexcept { } const char* -bad_array_new_length::what() const _NOEXCEPT +bad_array_new_length::what() const noexcept { return "bad_array_new_length"; } diff --git a/lib/libcxx/src/support/runtime/exception_pointer_cxxabi.ipp b/lib/libcxx/src/support/runtime/exception_pointer_cxxabi.ipp index 82a8e6972f..33aa94502b 100644 --- a/lib/libcxx/src/support/runtime/exception_pointer_cxxabi.ipp +++ b/lib/libcxx/src/support/runtime/exception_pointer_cxxabi.ipp @@ -13,17 +13,17 @@ namespace std { -exception_ptr::~exception_ptr() _NOEXCEPT { +exception_ptr::~exception_ptr() noexcept { __cxa_decrement_exception_refcount(__ptr_); } -exception_ptr::exception_ptr(const exception_ptr& other) _NOEXCEPT +exception_ptr::exception_ptr(const exception_ptr& other) noexcept : __ptr_(other.__ptr_) { __cxa_increment_exception_refcount(__ptr_); } -exception_ptr& exception_ptr::operator=(const exception_ptr& other) _NOEXCEPT +exception_ptr& exception_ptr::operator=(const exception_ptr& other) noexcept { if (__ptr_ != other.__ptr_) { @@ -34,12 +34,12 @@ exception_ptr& exception_ptr::operator=(const exception_ptr& other) _NOEXCEPT return *this; } -nested_exception::nested_exception() _NOEXCEPT +nested_exception::nested_exception() noexcept : __ptr_(current_exception()) { } -nested_exception::~nested_exception() _NOEXCEPT +nested_exception::~nested_exception() noexcept { } @@ -52,7 +52,7 @@ nested_exception::rethrow_nested() const rethrow_exception(__ptr_); } -exception_ptr current_exception() _NOEXCEPT +exception_ptr current_exception() noexcept { // be nicer if there was a constructor that took a ptr, then // this whole function would be just: diff --git a/lib/libcxx/src/support/runtime/exception_pointer_glibcxx.ipp b/lib/libcxx/src/support/runtime/exception_pointer_glibcxx.ipp index 3abc137c67..983a08808d 100644 --- a/lib/libcxx/src/support/runtime/exception_pointer_glibcxx.ipp +++ b/lib/libcxx/src/support/runtime/exception_pointer_glibcxx.ipp @@ -25,35 +25,35 @@ struct exception_ptr { void* __ptr_; - exception_ptr(const exception_ptr&) _NOEXCEPT; - exception_ptr& operator=(const exception_ptr&) _NOEXCEPT; - ~exception_ptr() _NOEXCEPT; + exception_ptr(const exception_ptr&) noexcept; + exception_ptr& operator=(const exception_ptr&) noexcept; + ~exception_ptr() noexcept; }; } _LIBCPP_NORETURN void rethrow_exception(__exception_ptr::exception_ptr); -exception_ptr::~exception_ptr() _NOEXCEPT +exception_ptr::~exception_ptr() noexcept { reinterpret_cast<__exception_ptr::exception_ptr*>(this)->~exception_ptr(); } -exception_ptr::exception_ptr(const exception_ptr& other) _NOEXCEPT +exception_ptr::exception_ptr(const exception_ptr& other) noexcept : __ptr_(other.__ptr_) { new (reinterpret_cast<void*>(this)) __exception_ptr::exception_ptr( reinterpret_cast<const __exception_ptr::exception_ptr&>(other)); } -exception_ptr& exception_ptr::operator=(const exception_ptr& other) _NOEXCEPT +exception_ptr& exception_ptr::operator=(const exception_ptr& other) noexcept { *reinterpret_cast<__exception_ptr::exception_ptr*>(this) = reinterpret_cast<const __exception_ptr::exception_ptr&>(other); return *this; } -nested_exception::nested_exception() _NOEXCEPT +nested_exception::nested_exception() noexcept : __ptr_(current_exception()) { } diff --git a/lib/libcxx/src/support/runtime/exception_pointer_msvc.ipp b/lib/libcxx/src/support/runtime/exception_pointer_msvc.ipp index b1a3695223..9e7f392e76 100644 --- a/lib/libcxx/src/support/runtime/exception_pointer_msvc.ipp +++ b/lib/libcxx/src/support/runtime/exception_pointer_msvc.ipp @@ -24,35 +24,35 @@ __ExceptionPtrCopyException(void*, const void*, const void*); namespace std { -exception_ptr::exception_ptr() _NOEXCEPT { __ExceptionPtrCreate(this); } -exception_ptr::exception_ptr(nullptr_t) _NOEXCEPT { __ExceptionPtrCreate(this); } +exception_ptr::exception_ptr() noexcept { __ExceptionPtrCreate(this); } +exception_ptr::exception_ptr(nullptr_t) noexcept { __ExceptionPtrCreate(this); } -exception_ptr::exception_ptr(const exception_ptr& __other) _NOEXCEPT { +exception_ptr::exception_ptr(const exception_ptr& __other) noexcept { __ExceptionPtrCopy(this, &__other); } -exception_ptr& exception_ptr::operator=(const exception_ptr& __other) _NOEXCEPT { +exception_ptr& exception_ptr::operator=(const exception_ptr& __other) noexcept { __ExceptionPtrAssign(this, &__other); return *this; } -exception_ptr& exception_ptr::operator=(nullptr_t) _NOEXCEPT { +exception_ptr& exception_ptr::operator=(nullptr_t) noexcept { exception_ptr dummy; __ExceptionPtrAssign(this, &dummy); return *this; } -exception_ptr::~exception_ptr() _NOEXCEPT { __ExceptionPtrDestroy(this); } +exception_ptr::~exception_ptr() noexcept { __ExceptionPtrDestroy(this); } -exception_ptr::operator bool() const _NOEXCEPT { +exception_ptr::operator bool() const noexcept { return __ExceptionPtrToBool(this); } -bool operator==(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT { +bool operator==(const exception_ptr& __x, const exception_ptr& __y) noexcept { return __ExceptionPtrCompare(&__x, &__y); } -void swap(exception_ptr& lhs, exception_ptr& rhs) _NOEXCEPT { +void swap(exception_ptr& lhs, exception_ptr& rhs) noexcept { __ExceptionPtrSwap(&rhs, &lhs); } @@ -63,7 +63,7 @@ exception_ptr __copy_exception_ptr(void* __except, const void* __ptr) { return __ret; } -exception_ptr current_exception() _NOEXCEPT { +exception_ptr current_exception() noexcept { exception_ptr __ret; __ExceptionPtrCurrentException(&__ret); return __ret; @@ -72,9 +72,9 @@ exception_ptr current_exception() _NOEXCEPT { _LIBCPP_NORETURN void rethrow_exception(exception_ptr p) { __ExceptionPtrRethrow(&p); } -nested_exception::nested_exception() _NOEXCEPT : __ptr_(current_exception()) {} +nested_exception::nested_exception() noexcept : __ptr_(current_exception()) {} -nested_exception::~nested_exception() _NOEXCEPT {} +nested_exception::~nested_exception() noexcept {} _LIBCPP_NORETURN void nested_exception::rethrow_nested() const { diff --git a/lib/libcxx/src/support/runtime/exception_pointer_unimplemented.ipp b/lib/libcxx/src/support/runtime/exception_pointer_unimplemented.ipp index 991bca9ecf..9e8ec04e11 100644 --- a/lib/libcxx/src/support/runtime/exception_pointer_unimplemented.ipp +++ b/lib/libcxx/src/support/runtime/exception_pointer_unimplemented.ipp @@ -12,14 +12,14 @@ namespace std { -exception_ptr::~exception_ptr() _NOEXCEPT +exception_ptr::~exception_ptr() noexcept { # warning exception_ptr not yet implemented fprintf(stderr, "exception_ptr not yet implemented\n"); ::abort(); } -exception_ptr::exception_ptr(const exception_ptr& other) _NOEXCEPT +exception_ptr::exception_ptr(const exception_ptr& other) noexcept : __ptr_(other.__ptr_) { # warning exception_ptr not yet implemented @@ -27,21 +27,21 @@ exception_ptr::exception_ptr(const exception_ptr& other) _NOEXCEPT ::abort(); } -exception_ptr& exception_ptr::operator=(const exception_ptr& other) _NOEXCEPT +exception_ptr& exception_ptr::operator=(const exception_ptr& other) noexcept { # warning exception_ptr not yet implemented fprintf(stderr, "exception_ptr not yet implemented\n"); ::abort(); } -nested_exception::nested_exception() _NOEXCEPT +nested_exception::nested_exception() noexcept : __ptr_(current_exception()) { } #if !defined(__GLIBCXX__) -nested_exception::~nested_exception() _NOEXCEPT +nested_exception::~nested_exception() noexcept { } @@ -61,7 +61,7 @@ nested_exception::rethrow_nested() const #endif // FIXME } -exception_ptr current_exception() _NOEXCEPT +exception_ptr current_exception() noexcept { # warning exception_ptr not yet implemented fprintf(stderr, "exception_ptr not yet implemented\n"); diff --git a/lib/libcxx/src/support/runtime/new_handler_fallback.ipp b/lib/libcxx/src/support/runtime/new_handler_fallback.ipp index 7205093942..a969b2a45d 100644 --- a/lib/libcxx/src/support/runtime/new_handler_fallback.ipp +++ b/lib/libcxx/src/support/runtime/new_handler_fallback.ipp @@ -12,13 +12,13 @@ namespace std { _LIBCPP_SAFE_STATIC static std::new_handler __new_handler; new_handler -set_new_handler(new_handler handler) _NOEXCEPT +set_new_handler(new_handler handler) noexcept { return __libcpp_atomic_exchange(&__new_handler, handler); } new_handler -get_new_handler() _NOEXCEPT +get_new_handler() noexcept { return __libcpp_atomic_load(&__new_handler); } diff --git a/lib/libcxx/src/support/runtime/stdexcept_default.ipp b/lib/libcxx/src/support/runtime/stdexcept_default.ipp index c827ca4c51..ad7bd40b61 100644 --- a/lib/libcxx/src/support/runtime/stdexcept_default.ipp +++ b/lib/libcxx/src/support/runtime/stdexcept_default.ipp @@ -23,9 +23,9 @@ logic_error::logic_error(const string& msg) : __imp_(msg.c_str()) {} logic_error::logic_error(const char* msg) : __imp_(msg) {} -logic_error::logic_error(const logic_error& le) _NOEXCEPT : __imp_(le.__imp_) {} +logic_error::logic_error(const logic_error& le) noexcept : __imp_(le.__imp_) {} -logic_error& logic_error::operator=(const logic_error& le) _NOEXCEPT { +logic_error& logic_error::operator=(const logic_error& le) noexcept { __imp_ = le.__imp_; return *this; } @@ -34,30 +34,30 @@ runtime_error::runtime_error(const string& msg) : __imp_(msg.c_str()) {} runtime_error::runtime_error(const char* msg) : __imp_(msg) {} -runtime_error::runtime_error(const runtime_error& re) _NOEXCEPT +runtime_error::runtime_error(const runtime_error& re) noexcept : __imp_(re.__imp_) {} -runtime_error& runtime_error::operator=(const runtime_error& re) _NOEXCEPT { +runtime_error& runtime_error::operator=(const runtime_error& re) noexcept { __imp_ = re.__imp_; return *this; } #if !defined(_LIBCPPABI_VERSION) && !defined(LIBSTDCXX) -const char* logic_error::what() const _NOEXCEPT { return __imp_.c_str(); } +const char* logic_error::what() const noexcept { return __imp_.c_str(); } -const char* runtime_error::what() const _NOEXCEPT { return __imp_.c_str(); } +const char* runtime_error::what() const noexcept { return __imp_.c_str(); } -logic_error::~logic_error() _NOEXCEPT {} -domain_error::~domain_error() _NOEXCEPT {} -invalid_argument::~invalid_argument() _NOEXCEPT {} -length_error::~length_error() _NOEXCEPT {} -out_of_range::~out_of_range() _NOEXCEPT {} +logic_error::~logic_error() noexcept {} +domain_error::~domain_error() noexcept {} +invalid_argument::~invalid_argument() noexcept {} +length_error::~length_error() noexcept {} +out_of_range::~out_of_range() noexcept {} -runtime_error::~runtime_error() _NOEXCEPT {} -range_error::~range_error() _NOEXCEPT {} -overflow_error::~overflow_error() _NOEXCEPT {} -underflow_error::~underflow_error() _NOEXCEPT {} +runtime_error::~runtime_error() noexcept {} +range_error::~range_error() noexcept {} +overflow_error::~overflow_error() noexcept {} +underflow_error::~underflow_error() noexcept {} #endif diff --git a/lib/libcxx/src/support/win32/support.cpp b/lib/libcxx/src/support/win32/support.cpp index 52453f5479..5890e669a3 100644 --- a/lib/libcxx/src/support/win32/support.cpp +++ b/lib/libcxx/src/support/win32/support.cpp @@ -22,7 +22,10 @@ int __libcpp_vasprintf( char **sptr, const char *__restrict format, va_list ap ) { *sptr = NULL; // Query the count required. - int count = _vsnprintf( NULL, 0, format, ap ); + va_list ap_copy; + va_copy(ap_copy, ap); + int count = _vsnprintf( NULL, 0, format, ap_copy ); + va_end(ap_copy); if (count < 0) return count; size_t buffer_size = static_cast<size_t>(count) + 1; diff --git a/lib/libcxx/src/support/win32/thread_win32.cpp b/lib/libcxx/src/support/win32/thread_win32.cpp index 35c4c87145..63c5aa6537 100644 --- a/lib/libcxx/src/support/win32/thread_win32.cpp +++ b/lib/libcxx/src/support/win32/thread_win32.cpp @@ -8,6 +8,8 @@ //===----------------------------------------------------------------------===// #include <__threading_support> +#define NOMINMAX +#define WIN32_LEAN_AND_MEAN #include <windows.h> #include <process.h> #include <fibersapi.h> @@ -37,6 +39,9 @@ static_assert(alignof(__libcpp_thread_t) == alignof(HANDLE), ""); static_assert(sizeof(__libcpp_tls_key) == sizeof(DWORD), ""); static_assert(alignof(__libcpp_tls_key) == alignof(DWORD), ""); +static_assert(sizeof(__libcpp_semaphore_t) == sizeof(HANDLE), ""); +static_assert(alignof(__libcpp_semaphore_t) == alignof(HANDLE), ""); + // Mutex int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m) { @@ -241,10 +246,8 @@ void __libcpp_thread_yield() void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns) { - using namespace chrono; - // round-up to the nearest milisecond - milliseconds __ms = - duration_cast<milliseconds>(__ns + chrono::nanoseconds(999999)); + // round-up to the nearest millisecond + chrono::milliseconds __ms = chrono::ceil<chrono::milliseconds>(__ns); // FIXME(compnerd) this should be an alertable sleep (WFSO or SleepEx) Sleep(__ms.count()); } @@ -272,4 +275,37 @@ int __libcpp_tls_set(__libcpp_tls_key __key, void *__p) return 0; } +// Semaphores +bool __libcpp_semaphore_init(__libcpp_semaphore_t* __sem, int __init) +{ + *(PHANDLE)__sem = CreateSemaphoreEx(nullptr, __init, _LIBCPP_SEMAPHORE_MAX, + nullptr, 0, SEMAPHORE_ALL_ACCESS); + return *__sem != nullptr; +} + +bool __libcpp_semaphore_destroy(__libcpp_semaphore_t* __sem) +{ + CloseHandle(*(PHANDLE)__sem); + return true; +} + +bool __libcpp_semaphore_post(__libcpp_semaphore_t* __sem) +{ + return ReleaseSemaphore(*(PHANDLE)__sem, 1, nullptr); +} + +bool __libcpp_semaphore_wait(__libcpp_semaphore_t* __sem) +{ + return WaitForSingleObjectEx(*(PHANDLE)__sem, INFINITE, false) == + WAIT_OBJECT_0; +} + +bool __libcpp_semaphore_wait_timed(__libcpp_semaphore_t* __sem, + chrono::nanoseconds const& __ns) +{ + chrono::milliseconds __ms = chrono::ceil<chrono::milliseconds>(__ns); + return WaitForSingleObjectEx(*(PHANDLE)__sem, __ms.count(), false) == + WAIT_OBJECT_0; +} + _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/src/system_error.cpp b/lib/libcxx/src/system_error.cpp index 9ddf7bcbe0..a1ea6c4754 100644 --- a/lib/libcxx/src/system_error.cpp +++ b/lib/libcxx/src/system_error.cpp @@ -28,29 +28,29 @@ _LIBCPP_BEGIN_NAMESPACE_STD // class error_category #if defined(_LIBCPP_DEPRECATED_ABI_LEGACY_LIBRARY_DEFINITIONS_FOR_INLINE_FUNCTIONS) -error_category::error_category() _NOEXCEPT +error_category::error_category() noexcept { } #endif -error_category::~error_category() _NOEXCEPT +error_category::~error_category() noexcept { } error_condition -error_category::default_error_condition(int ev) const _NOEXCEPT +error_category::default_error_condition(int ev) const noexcept { return error_condition(ev, *this); } bool -error_category::equivalent(int code, const error_condition& condition) const _NOEXCEPT +error_category::equivalent(int code, const error_condition& condition) const noexcept { return default_error_condition(code) == condition; } bool -error_category::equivalent(const error_code& code, int condition) const _NOEXCEPT +error_category::equivalent(const error_code& code, int condition) const noexcept { return *this == code.category() && code.value() == condition; } @@ -141,12 +141,12 @@ class _LIBCPP_HIDDEN __generic_error_category : public __do_message { public: - virtual const char* name() const _NOEXCEPT; + virtual const char* name() const noexcept; virtual string message(int ev) const; }; const char* -__generic_error_category::name() const _NOEXCEPT +__generic_error_category::name() const noexcept { return "generic"; } @@ -157,12 +157,12 @@ __generic_error_category::message(int ev) const #ifdef _LIBCPP_ELAST if (ev > _LIBCPP_ELAST) return string("unspecified generic_category error"); -#endif // _LIBCPP_ELAST +#endif // _LIBCPP_ELAST return __do_message::message(ev); } const error_category& -generic_category() _NOEXCEPT +generic_category() noexcept { static __generic_error_category s; return s; @@ -172,13 +172,13 @@ class _LIBCPP_HIDDEN __system_error_category : public __do_message { public: - virtual const char* name() const _NOEXCEPT; + virtual const char* name() const noexcept; virtual string message(int ev) const; - virtual error_condition default_error_condition(int ev) const _NOEXCEPT; + virtual error_condition default_error_condition(int ev) const noexcept; }; const char* -__system_error_category::name() const _NOEXCEPT +__system_error_category::name() const noexcept { return "system"; } @@ -189,22 +189,22 @@ __system_error_category::message(int ev) const #ifdef _LIBCPP_ELAST if (ev > _LIBCPP_ELAST) return string("unspecified system_category error"); -#endif // _LIBCPP_ELAST +#endif // _LIBCPP_ELAST return __do_message::message(ev); } error_condition -__system_error_category::default_error_condition(int ev) const _NOEXCEPT +__system_error_category::default_error_condition(int ev) const noexcept { #ifdef _LIBCPP_ELAST if (ev > _LIBCPP_ELAST) return error_condition(ev, system_category()); -#endif // _LIBCPP_ELAST +#endif // _LIBCPP_ELAST return error_condition(ev, generic_category()); } const error_category& -system_category() _NOEXCEPT +system_category() noexcept { static __system_error_category s; return s; @@ -276,7 +276,7 @@ system_error::system_error(int ev, const error_category& ecat) { } -system_error::~system_error() _NOEXCEPT +system_error::~system_error() noexcept { } diff --git a/lib/libcxx/src/thread.cpp b/lib/libcxx/src/thread.cpp index 5959d8b711..8dddb240b5 100644 --- a/lib/libcxx/src/thread.cpp +++ b/lib/libcxx/src/thread.cpp @@ -70,7 +70,7 @@ thread::detach() } unsigned -thread::hardware_concurrency() _NOEXCEPT +thread::hardware_concurrency() noexcept { #if defined(_SC_NPROCESSORS_ONLN) long result = sysconf(_SC_NPROCESSORS_ONLN); @@ -94,7 +94,7 @@ thread::hardware_concurrency() _NOEXCEPT # warning hardware_concurrency not yet implemented # endif return 0; // Means not computable [thread.thread.static] -#endif // defined(CTL_HW) && defined(HW_NCPU) +#endif // defined(CTL_HW) && defined(HW_NCPU) } namespace this_thread diff --git a/lib/libcxx/src/typeinfo.cpp b/lib/libcxx/src/typeinfo.cpp index 49a07ef7da..ce3867ea93 100644 --- a/lib/libcxx/src/typeinfo.cpp +++ b/lib/libcxx/src/typeinfo.cpp @@ -11,18 +11,18 @@ #if defined(_LIBCPP_ABI_MICROSOFT) && !defined(_LIBCPP_ABI_VCRUNTIME) #include <string.h> -int std::type_info::__compare(const type_info &__rhs) const _NOEXCEPT { +int std::type_info::__compare(const type_info &__rhs) const noexcept { if (&__data == &__rhs.__data) return 0; return strcmp(&__data.__decorated_name[1], &__rhs.__data.__decorated_name[1]); } -const char *std::type_info::name() const _NOEXCEPT { +const char *std::type_info::name() const noexcept { // TODO(compnerd) cache demangled &__data.__decorated_name[1] return &__data.__decorated_name[1]; } -size_t std::type_info::hash_code() const _NOEXCEPT { +size_t std::type_info::hash_code() const noexcept { #if defined(_WIN64) constexpr size_t fnv_offset_basis = 14695981039346656037ull; constexpr size_t fnv_prime = 10995116282110ull; |
