summaryrefslogtreecommitdiffstats
path: root/gnu/llvm/lldb/source/Utility/Status.cpp
diff options
context:
space:
mode:
authorpatrick <patrick@openbsd.org>2020-08-03 14:33:06 +0000
committerpatrick <patrick@openbsd.org>2020-08-03 14:33:06 +0000
commit061da546b983eb767bad15e67af1174fb0bcf31c (patch)
tree83c78b820819d70aa40c36d90447978b300078c5 /gnu/llvm/lldb/source/Utility/Status.cpp
parentImport LLVM 10.0.0 release including clang, lld and lldb. (diff)
downloadwireguard-openbsd-061da546b983eb767bad15e67af1174fb0bcf31c.tar.xz
wireguard-openbsd-061da546b983eb767bad15e67af1174fb0bcf31c.zip
Import LLVM 10.0.0 release including clang, lld and lldb.
ok hackroom tested by plenty
Diffstat (limited to 'gnu/llvm/lldb/source/Utility/Status.cpp')
-rw-r--r--gnu/llvm/lldb/source/Utility/Status.cpp295
1 files changed, 295 insertions, 0 deletions
diff --git a/gnu/llvm/lldb/source/Utility/Status.cpp b/gnu/llvm/lldb/source/Utility/Status.cpp
new file mode 100644
index 00000000000..b74db72773d
--- /dev/null
+++ b/gnu/llvm/lldb/source/Utility/Status.cpp
@@ -0,0 +1,295 @@
+//===-- Status.cpp -----------------------------------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Utility/Status.h"
+
+#include "lldb/Utility/VASPrintf.h"
+#include "lldb/lldb-defines.h"
+#include "lldb/lldb-enumerations.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Errno.h"
+#include "llvm/Support/FormatProviders.h"
+
+#include <cerrno>
+#include <cstdarg>
+#include <string>
+#include <system_error>
+
+#ifdef __APPLE__
+#include <mach/mach.h>
+#endif
+
+#ifdef _WIN32
+#include <windows.h>
+#endif
+#include <stdint.h>
+
+namespace llvm {
+class raw_ostream;
+}
+
+using namespace lldb;
+using namespace lldb_private;
+
+Status::Status() : m_code(0), m_type(eErrorTypeInvalid), m_string() {}
+
+Status::Status(ValueType err, ErrorType type)
+ : m_code(err), m_type(type), m_string() {}
+
+Status::Status(std::error_code EC)
+ : m_code(EC.value()), m_type(ErrorType::eErrorTypeGeneric),
+ m_string(EC.message()) {}
+
+Status::Status(const char *format, ...)
+ : m_code(0), m_type(eErrorTypeInvalid), m_string() {
+ va_list args;
+ va_start(args, format);
+ SetErrorToGenericError();
+ SetErrorStringWithVarArg(format, args);
+ va_end(args);
+}
+
+const Status &Status::operator=(llvm::Error error) {
+ if (!error) {
+ Clear();
+ return *this;
+ }
+
+ // if the error happens to be a errno error, preserve the error code
+ error = llvm::handleErrors(
+ std::move(error), [&](std::unique_ptr<llvm::ECError> e) -> llvm::Error {
+ std::error_code ec = e->convertToErrorCode();
+ if (ec.category() == std::generic_category()) {
+ m_code = ec.value();
+ m_type = ErrorType::eErrorTypePOSIX;
+ return llvm::Error::success();
+ }
+ return llvm::Error(std::move(e));
+ });
+
+ // Otherwise, just preserve the message
+ if (error) {
+ SetErrorToGenericError();
+ SetErrorString(llvm::toString(std::move(error)));
+ }
+
+ return *this;
+}
+
+llvm::Error Status::ToError() const {
+ if (Success())
+ return llvm::Error::success();
+ if (m_type == ErrorType::eErrorTypePOSIX)
+ return llvm::errorCodeToError(
+ std::error_code(m_code, std::generic_category()));
+ return llvm::make_error<llvm::StringError>(AsCString(),
+ llvm::inconvertibleErrorCode());
+}
+
+Status::~Status() = default;
+
+#ifdef _WIN32
+static std::string RetrieveWin32ErrorString(uint32_t error_code) {
+ char *buffer = nullptr;
+ std::string message;
+ // Retrieve win32 system error.
+ // First, attempt to load a en-US message
+ if (::FormatMessageA(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_MAX_WIDTH_MASK,
+ NULL, error_code, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
+ (LPSTR)&buffer, 0, NULL)) {
+ message.assign(buffer);
+ ::LocalFree(buffer);
+ }
+ // If the previous didn't work, use the default OS language
+ else if (::FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_MAX_WIDTH_MASK,
+ NULL, error_code, 0, (LPSTR)&buffer, 0, NULL)) {
+ message.assign(buffer);
+ ::LocalFree(buffer);
+ }
+ return message;
+}
+#endif
+
+// Get the error value as a NULL C string. The error string will be fetched and
+// cached on demand. The cached error string value will remain until the error
+// value is changed or cleared.
+const char *Status::AsCString(const char *default_error_str) const {
+ if (Success())
+ return nullptr;
+
+ if (m_string.empty()) {
+ switch (m_type) {
+ case eErrorTypeMachKernel:
+#if defined(__APPLE__)
+ if (const char *s = ::mach_error_string(m_code))
+ m_string.assign(s);
+#endif
+ break;
+
+ case eErrorTypePOSIX:
+ m_string = llvm::sys::StrError(m_code);
+ break;
+
+ case eErrorTypeWin32:
+#if defined(_WIN32)
+ m_string = RetrieveWin32ErrorString(m_code);
+#endif
+ break;
+
+ default:
+ break;
+ }
+ }
+ if (m_string.empty()) {
+ if (default_error_str)
+ m_string.assign(default_error_str);
+ else
+ return nullptr; // User wanted a nullptr string back...
+ }
+ return m_string.c_str();
+}
+
+// Clear the error and any cached error string that it might contain.
+void Status::Clear() {
+ m_code = 0;
+ m_type = eErrorTypeInvalid;
+ m_string.clear();
+}
+
+// Access the error value.
+Status::ValueType Status::GetError() const { return m_code; }
+
+// Access the error type.
+ErrorType Status::GetType() const { return m_type; }
+
+// Returns true if this object contains a value that describes an error or
+// otherwise non-success result.
+bool Status::Fail() const { return m_code != 0; }
+
+// Set accessor for the error value to "err" and the type to
+// "eErrorTypeMachKernel"
+void Status::SetMachError(uint32_t err) {
+ m_code = err;
+ m_type = eErrorTypeMachKernel;
+ m_string.clear();
+}
+
+void Status::SetExpressionError(lldb::ExpressionResults result,
+ const char *mssg) {
+ m_code = result;
+ m_type = eErrorTypeExpression;
+ m_string = mssg;
+}
+
+int Status::SetExpressionErrorWithFormat(lldb::ExpressionResults result,
+ const char *format, ...) {
+ int length = 0;
+
+ if (format != nullptr && format[0]) {
+ va_list args;
+ va_start(args, format);
+ length = SetErrorStringWithVarArg(format, args);
+ va_end(args);
+ } else {
+ m_string.clear();
+ }
+ m_code = result;
+ m_type = eErrorTypeExpression;
+ return length;
+}
+
+// Set accessor for the error value and type.
+void Status::SetError(ValueType err, ErrorType type) {
+ m_code = err;
+ m_type = type;
+ m_string.clear();
+}
+
+// Update the error value to be "errno" and update the type to be "POSIX".
+void Status::SetErrorToErrno() {
+ m_code = errno;
+ m_type = eErrorTypePOSIX;
+ m_string.clear();
+}
+
+// Update the error value to be LLDB_GENERIC_ERROR and update the type to be
+// "Generic".
+void Status::SetErrorToGenericError() {
+ m_code = LLDB_GENERIC_ERROR;
+ m_type = eErrorTypeGeneric;
+ m_string.clear();
+}
+
+// Set accessor for the error string value for a specific error. This allows
+// any string to be supplied as an error explanation. The error string value
+// will remain until the error value is cleared or a new error value/type is
+// assigned.
+void Status::SetErrorString(llvm::StringRef err_str) {
+ if (!err_str.empty()) {
+ // If we have an error string, we should always at least have an error set
+ // to a generic value.
+ if (Success())
+ SetErrorToGenericError();
+ }
+ m_string = err_str;
+}
+
+/// Set the current error string to a formatted error string.
+///
+/// \param format
+/// A printf style format string
+int Status::SetErrorStringWithFormat(const char *format, ...) {
+ if (format != nullptr && format[0]) {
+ va_list args;
+ va_start(args, format);
+ int length = SetErrorStringWithVarArg(format, args);
+ va_end(args);
+ return length;
+ } else {
+ m_string.clear();
+ }
+ return 0;
+}
+
+int Status::SetErrorStringWithVarArg(const char *format, va_list args) {
+ if (format != nullptr && format[0]) {
+ // If we have an error string, we should always at least have an error set
+ // to a generic value.
+ if (Success())
+ SetErrorToGenericError();
+
+ llvm::SmallString<1024> buf;
+ VASprintf(buf, format, args);
+ m_string = buf.str();
+ return buf.size();
+ } else {
+ m_string.clear();
+ }
+ return 0;
+}
+
+// Returns true if the error code in this object is considered a successful
+// return value.
+bool Status::Success() const { return m_code == 0; }
+
+bool Status::WasInterrupted() const {
+ return (m_type == eErrorTypePOSIX && m_code == EINTR);
+}
+
+void llvm::format_provider<lldb_private::Status>::format(
+ const lldb_private::Status &error, llvm::raw_ostream &OS,
+ llvm::StringRef Options) {
+ llvm::format_provider<llvm::StringRef>::format(error.AsCString(), OS,
+ Options);
+}