summaryrefslogtreecommitdiffstats
path: root/lib/libcxx/src/system_error.cpp
diff options
context:
space:
mode:
authorrobert <robert@openbsd.org>2018-09-11 18:18:58 +0000
committerrobert <robert@openbsd.org>2018-09-11 18:18:58 +0000
commit820e1f31efc1d6ed04795ba2e79f3044e1907492 (patch)
tree815cebb3734784074b661935c33f00bd5eb4d862 /lib/libcxx/src/system_error.cpp
parentNuke unused LIST() ieee80211com_head. (diff)
downloadwireguard-openbsd-820e1f31efc1d6ed04795ba2e79f3044e1907492.tar.xz
wireguard-openbsd-820e1f31efc1d6ed04795ba2e79f3044e1907492.zip
import of libc++ 6.0.0
Diffstat (limited to 'lib/libcxx/src/system_error.cpp')
-rw-r--r--lib/libcxx/src/system_error.cpp83
1 files changed, 58 insertions, 25 deletions
diff --git a/lib/libcxx/src/system_error.cpp b/lib/libcxx/src/system_error.cpp
index 87f35ae37f3..72623ea6bc8 100644
--- a/lib/libcxx/src/system_error.cpp
+++ b/lib/libcxx/src/system_error.cpp
@@ -17,9 +17,9 @@
#include "cstring"
#include "cstdio"
#include "cstdlib"
-#include "cassert"
#include "string"
#include "string.h"
+#include "__debug"
#if defined(__ANDROID__)
#include <android/api-level.h>
@@ -29,9 +29,11 @@ _LIBCPP_BEGIN_NAMESPACE_STD
// class error_category
+#if defined(_LIBCPP_DEPRECATED_ABI_LEGACY_LIBRARY_DEFINITIONS_FOR_INLINE_FUNCTIONS)
error_category::error_category() _NOEXCEPT
{
}
+#endif
error_category::~error_category() _NOEXCEPT
{
@@ -55,6 +57,7 @@ error_category::equivalent(const error_code& code, int condition) const _NOEXCEP
return *this == code.category() && code.value() == condition;
}
+#if !defined(_LIBCPP_HAS_NO_THREADS)
namespace {
// GLIBC also uses 1024 as the maximum buffer size internally.
@@ -62,40 +65,69 @@ constexpr size_t strerror_buff_size = 1024;
string do_strerror_r(int ev);
-#if defined(__linux__) && !defined(_LIBCPP_HAS_MUSL_LIBC) \
- && (!defined(__ANDROID__) || __ANDROID_API__ >= 23)
-// GNU Extended version
+#if defined(_LIBCPP_MSVCRT_LIKE)
string do_strerror_r(int ev) {
- char buffer[strerror_buff_size];
- char* ret = ::strerror_r(ev, buffer, strerror_buff_size);
- return string(ret);
+ char buffer[strerror_buff_size];
+ if (::strerror_s(buffer, strerror_buff_size, ev) == 0)
+ return string(buffer);
+ std::snprintf(buffer, strerror_buff_size, "unknown error %d", ev);
+ return string(buffer);
}
#else
-// POSIX version
+
+// Only one of the two following functions will be used, depending on
+// the return type of strerror_r:
+
+// For the GNU variant, a char* return value:
+__attribute__((unused)) const char *
+handle_strerror_r_return(char *strerror_return, char *buffer) {
+ // GNU always returns a string pointer in its return value. The
+ // string might point to either the input buffer, or a static
+ // buffer, but we don't care which.
+ return strerror_return;
+}
+
+// For the POSIX variant: an int return value.
+__attribute__((unused)) const char *
+handle_strerror_r_return(int strerror_return, char *buffer) {
+ // The POSIX variant either:
+ // - fills in the provided buffer and returns 0
+ // - returns a positive error value, or
+ // - returns -1 and fills in errno with an error value.
+ if (strerror_return == 0)
+ return buffer;
+
+ // Only handle EINVAL. Other errors abort.
+ int new_errno = strerror_return == -1 ? errno : strerror_return;
+ if (new_errno == EINVAL)
+ return "";
+
+ _LIBCPP_ASSERT(new_errno == ERANGE, "unexpected error from ::strerror_r");
+ // FIXME maybe? 'strerror_buff_size' is likely to exceed the
+ // maximum error size so ERANGE shouldn't be returned.
+ std::abort();
+}
+
+// This function handles both GNU and POSIX variants, dispatching to
+// one of the two above functions.
string do_strerror_r(int ev) {
char buffer[strerror_buff_size];
+ // Preserve errno around the call. (The C++ standard requires that
+ // system_error functions not modify errno).
const int old_errno = errno;
- int ret;
- if ((ret = ::strerror_r(ev, buffer, strerror_buff_size)) != 0) {
- // If `ret == -1` then the error is specified using `errno`, otherwise
- // `ret` represents the error.
- const int new_errno = ret == -1 ? errno : ret;
- errno = old_errno;
- if (new_errno == EINVAL) {
- std::snprintf(buffer, strerror_buff_size, "Unknown error %d", ev);
- return string(buffer);
- } else {
- assert(new_errno == ERANGE);
- // FIXME maybe? 'strerror_buff_size' is likely to exceed the
- // maximum error size so ERANGE shouldn't be returned.
- std::abort();
- }
+ const char *error_message = handle_strerror_r_return(
+ ::strerror_r(ev, buffer, strerror_buff_size), buffer);
+ // If we didn't get any message, print one now.
+ if (!error_message[0]) {
+ std::snprintf(buffer, strerror_buff_size, "Unknown error %d", ev);
+ error_message = buffer;
}
- return string(buffer);
+ errno = old_errno;
+ return string(error_message);
}
#endif
-
} // end namespace
+#endif
string
__do_message::message(int ev) const
@@ -258,6 +290,7 @@ __throw_system_error(int ev, const char* what_arg)
#else
(void)ev;
(void)what_arg;
+ _VSTD::abort();
#endif
}