This is the first step in adding sane error handling support to LLVMSystem.

The system API's will be shifted over to returning an error_code, and returning
other return values as out parameters to the function.

Code that needs to check error conditions will use the errc enum values which
are the same as the posix_errno defines (EBADF, E2BIG, etc...), and are
compatable with the error codes in WinError.h due to some magic in system_error.

An example would be:

if (error_code ec = KillEvil("Java")) { // error_code can be converted to bool.
  handle_error(ec);
}

llvm-svn: 119360
This commit is contained in:
Michael J. Spencer 2010-11-16 18:31:52 +00:00
parent 20ee5ae871
commit 5ed2428b3c
8 changed files with 359 additions and 368 deletions

View File

@ -7,7 +7,10 @@
//
//===----------------------------------------------------------------------===//
//
// This was lifted from libc++ and modified for C++03.
// This was lifted from libc++ and modified for C++03. This is called
// system_error even though it does not define that class because that's what
// it's called in C++0x. We don't define system_error because it is only used
// for exception handling, which we don't use in LLVM.
//
//===----------------------------------------------------------------------===//
@ -224,6 +227,8 @@ template <> struct hash<std::error_code>;
#include <cerrno>
#include <string>
// This must be here instead of a .inc file because it is used in the definition
// of the enum values below.
#ifdef LLVM_ON_WIN32
// VS 2008 needs this for some of the defines below.
# include <WinSock2.h>
@ -691,7 +696,7 @@ inline error_condition make_error_condition(errc _e) {
inline bool operator<(const error_condition& _x, const error_condition& _y) {
return _x.category() < _y.category()
|| _x.category() == _y.category() && _x.value() < _y.value();
|| (_x.category() == _y.category() && _x.value() < _y.value());
}
// error_code
@ -750,7 +755,7 @@ inline error_code make_error_code(errc _e) {
inline bool operator<(const error_code& _x, const error_code& _y) {
return _x.category() < _y.category()
|| _x.category() == _y.category() && _x.value() < _y.value();
|| (_x.category() == _y.category() && _x.value() < _y.value());
}
inline bool operator==(const error_code& _x, const error_code& _y) {
@ -788,97 +793,73 @@ inline bool operator!=(const error_condition& _x, const error_condition& _y) {
// system_error
class system_error : public std::runtime_error {
error_code _ec_;
public:
system_error(error_code _ec, const std::string& _what_arg);
system_error(error_code _ec, const char* _what_arg);
system_error(error_code _ec);
system_error(int _ev, const error_category& _ecat,
const std::string& _what_arg);
system_error(int _ev, const error_category& _ecat, const char* _what_arg);
system_error(int _ev, const error_category& _ecat);
~system_error() throw();
const error_code& code() const throw() {return _ec_;}
private:
static std::string _init(const error_code&, std::string);
};
void _throw_system_error(int ev, const char* what_arg);
} // end namespace llvm
// This needs to stay here for KillTheDoctor.
#ifdef LLVM_ON_WIN32
#include <Windows.h>
#include <WinError.h>
namespace llvm {
// To construct an error_code after a API error:
// To construct an error_code after an API error:
//
// error_code( ::GetLastError(), system_category() )
struct windows_error {
enum _ {
success = 0,
// These names and values are based on Windows winerror.h
invalid_function = ERROR_INVALID_FUNCTION,
file_not_found = ERROR_FILE_NOT_FOUND,
path_not_found = ERROR_PATH_NOT_FOUND,
too_many_open_files = ERROR_TOO_MANY_OPEN_FILES,
access_denied = ERROR_ACCESS_DENIED,
invalid_handle = ERROR_INVALID_HANDLE,
arena_trashed = ERROR_ARENA_TRASHED,
not_enough_memory = ERROR_NOT_ENOUGH_MEMORY,
invalid_block = ERROR_INVALID_BLOCK,
bad_environment = ERROR_BAD_ENVIRONMENT,
bad_format = ERROR_BAD_FORMAT,
invalid_access = ERROR_INVALID_ACCESS,
outofmemory = ERROR_OUTOFMEMORY,
invalid_drive = ERROR_INVALID_DRIVE,
current_directory = ERROR_CURRENT_DIRECTORY,
not_same_device = ERROR_NOT_SAME_DEVICE,
no_more_files = ERROR_NO_MORE_FILES,
write_protect = ERROR_WRITE_PROTECT,
bad_unit = ERROR_BAD_UNIT,
not_ready = ERROR_NOT_READY,
bad_command = ERROR_BAD_COMMAND,
crc = ERROR_CRC,
bad_length = ERROR_BAD_LENGTH,
seek = ERROR_SEEK,
not_dos_disk = ERROR_NOT_DOS_DISK,
sector_not_found = ERROR_SECTOR_NOT_FOUND,
out_of_paper = ERROR_OUT_OF_PAPER,
write_fault = ERROR_WRITE_FAULT,
read_fault = ERROR_READ_FAULT,
gen_failure = ERROR_GEN_FAILURE,
sharing_violation = ERROR_SHARING_VIOLATION,
lock_violation = ERROR_LOCK_VIOLATION,
wrong_disk = ERROR_WRONG_DISK,
// This is not a complete list.
invalid_function = ERROR_INVALID_FUNCTION,
file_not_found = ERROR_FILE_NOT_FOUND,
path_not_found = ERROR_PATH_NOT_FOUND,
too_many_open_files = ERROR_TOO_MANY_OPEN_FILES,
access_denied = ERROR_ACCESS_DENIED,
invalid_handle = ERROR_INVALID_HANDLE,
arena_trashed = ERROR_ARENA_TRASHED,
not_enough_memory = ERROR_NOT_ENOUGH_MEMORY,
invalid_block = ERROR_INVALID_BLOCK,
bad_environment = ERROR_BAD_ENVIRONMENT,
bad_format = ERROR_BAD_FORMAT,
invalid_access = ERROR_INVALID_ACCESS,
outofmemory = ERROR_OUTOFMEMORY,
invalid_drive = ERROR_INVALID_DRIVE,
current_directory = ERROR_CURRENT_DIRECTORY,
not_same_device = ERROR_NOT_SAME_DEVICE,
no_more_files = ERROR_NO_MORE_FILES,
write_protect = ERROR_WRITE_PROTECT,
bad_unit = ERROR_BAD_UNIT,
not_ready = ERROR_NOT_READY,
bad_command = ERROR_BAD_COMMAND,
crc = ERROR_CRC,
bad_length = ERROR_BAD_LENGTH,
seek = ERROR_SEEK,
not_dos_disk = ERROR_NOT_DOS_DISK,
sector_not_found = ERROR_SECTOR_NOT_FOUND,
out_of_paper = ERROR_OUT_OF_PAPER,
write_fault = ERROR_WRITE_FAULT,
read_fault = ERROR_READ_FAULT,
gen_failure = ERROR_GEN_FAILURE,
sharing_violation = ERROR_SHARING_VIOLATION,
lock_violation = ERROR_LOCK_VIOLATION,
wrong_disk = ERROR_WRONG_DISK,
sharing_buffer_exceeded = ERROR_SHARING_BUFFER_EXCEEDED,
handle_eof = ERROR_HANDLE_EOF,
handle_disk_full= ERROR_HANDLE_DISK_FULL,
rem_not_list = ERROR_REM_NOT_LIST,
dup_name = ERROR_DUP_NAME,
bad_net_path = ERROR_BAD_NETPATH,
network_busy = ERROR_NETWORK_BUSY,
// ...
file_exists = ERROR_FILE_EXISTS,
cannot_make = ERROR_CANNOT_MAKE,
// ...
broken_pipe = ERROR_BROKEN_PIPE,
open_failed = ERROR_OPEN_FAILED,
buffer_overflow = ERROR_BUFFER_OVERFLOW,
disk_full= ERROR_DISK_FULL,
// ...
lock_failed = ERROR_LOCK_FAILED,
busy = ERROR_BUSY,
cancel_violation = ERROR_CANCEL_VIOLATION,
already_exists = ERROR_ALREADY_EXISTS
// ...
// TODO: add more Windows errors
handle_eof = ERROR_HANDLE_EOF,
handle_disk_full = ERROR_HANDLE_DISK_FULL,
rem_not_list = ERROR_REM_NOT_LIST,
dup_name = ERROR_DUP_NAME,
bad_net_path = ERROR_BAD_NETPATH,
network_busy = ERROR_NETWORK_BUSY,
file_exists = ERROR_FILE_EXISTS,
cannot_make = ERROR_CANNOT_MAKE,
broken_pipe = ERROR_BROKEN_PIPE,
open_failed = ERROR_OPEN_FAILED,
buffer_overflow = ERROR_BUFFER_OVERFLOW,
disk_full = ERROR_DISK_FULL,
lock_failed = ERROR_LOCK_FAILED,
busy = ERROR_BUSY,
cancel_violation = ERROR_CANCEL_VIOLATION,
already_exists = ERROR_ALREADY_EXISTS
};
_ v_;

View File

@ -19,6 +19,7 @@ add_llvm_library(LLVMSystem
RWMutex.cpp
SearchForAddressOfSpecialSymbol.cpp
Signals.cpp
system_error.cpp
ThreadLocal.cpp
Threading.cpp
TimeValue.cpp
@ -32,6 +33,7 @@ add_llvm_library(LLVMSystem
Unix/Program.inc
Unix/RWMutex.inc
Unix/Signals.inc
Unix/system_error.inc
Unix/ThreadLocal.inc
Unix/TimeValue.inc
Win32/Alarm.inc
@ -44,6 +46,7 @@ add_llvm_library(LLVMSystem
Win32/Program.inc
Win32/RWMutex.inc
Win32/Signals.inc
Win32/system_error.inc
Win32/ThreadLocal.inc
Win32/TimeValue.inc
)

View File

@ -0,0 +1,34 @@
//===- llvm/System/Unix/system_error.inc - Unix error_code ------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file provides the Unix specific implementation of the error_code
// and error_condition classes.
//
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
//=== WARNING: Implementation here must contain only generic UNIX code that
//=== is guaranteed to work on *all* UNIX variants.
//===----------------------------------------------------------------------===//
using namespace llvm;
std::string
_system_error_category::message(int ev) const {
return _do_message::message(ev);
}
error_condition
_system_error_category::default_error_condition(int ev) const {
#ifdef ELAST
if (ev > ELAST)
return error_condition(ev, system_category());
#endif // ELAST
return error_condition(ev, generic_category());
}

View File

@ -0,0 +1,140 @@
//===- llvm/System/Win32/system_error.inc - Windows error_code --*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file provides the Windows specific implementation of the error_code
// and error_condition classes.
//
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
//=== WARNING: Implementation here must contain only generic Windows code that
//=== is guaranteed to work on *all* Windows variants.
//===----------------------------------------------------------------------===//
#include <Windows.h>
#include <WinError.h>
using namespace llvm;
std::string
_system_error_category::message(int ev) const {
LPVOID lpMsgBuf = 0;
DWORD retval = ::FormatMessageA(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
ev,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPSTR) &lpMsgBuf,
0,
NULL);
if (retval == 0) {
::LocalFree(lpMsgBuf);
return std::string("Unknown error");
}
std::string str( static_cast<LPCSTR>(lpMsgBuf) );
::LocalFree(lpMsgBuf);
while (str.size()
&& (str[str.size()-1] == '\n' || str[str.size()-1] == '\r'))
str.erase( str.size()-1 );
if (str.size() && str[str.size()-1] == '.')
str.erase( str.size()-1 );
return str;
}
// I'd rather not double the line count of the following.
#define MAP_ERR_TO_COND(x, y) case x: return make_error_condition(errc::y)
error_condition
_system_error_category::default_error_condition(int ev) const {
switch (ev) {
MAP_ERR_TO_COND(0, success);
// Windows system -> posix_errno decode table ---------------------------//
// see WinError.h comments for descriptions of errors
MAP_ERR_TO_COND(ERROR_ACCESS_DENIED, permission_denied);
MAP_ERR_TO_COND(ERROR_ALREADY_EXISTS, file_exists);
MAP_ERR_TO_COND(ERROR_BAD_UNIT, no_such_device);
MAP_ERR_TO_COND(ERROR_BUFFER_OVERFLOW, filename_too_long);
MAP_ERR_TO_COND(ERROR_BUSY, device_or_resource_busy);
MAP_ERR_TO_COND(ERROR_BUSY_DRIVE, device_or_resource_busy);
MAP_ERR_TO_COND(ERROR_CANNOT_MAKE, permission_denied);
MAP_ERR_TO_COND(ERROR_CANTOPEN, io_error);
MAP_ERR_TO_COND(ERROR_CANTREAD, io_error);
MAP_ERR_TO_COND(ERROR_CANTWRITE, io_error);
MAP_ERR_TO_COND(ERROR_CURRENT_DIRECTORY, permission_denied);
MAP_ERR_TO_COND(ERROR_DEV_NOT_EXIST, no_such_device);
MAP_ERR_TO_COND(ERROR_DEVICE_IN_USE, device_or_resource_busy);
MAP_ERR_TO_COND(ERROR_DIR_NOT_EMPTY, directory_not_empty);
MAP_ERR_TO_COND(ERROR_DIRECTORY, invalid_argument);
MAP_ERR_TO_COND(ERROR_DISK_FULL, no_space_on_device);
MAP_ERR_TO_COND(ERROR_FILE_EXISTS, file_exists);
MAP_ERR_TO_COND(ERROR_FILE_NOT_FOUND, no_such_file_or_directory);
MAP_ERR_TO_COND(ERROR_HANDLE_DISK_FULL, no_space_on_device);
MAP_ERR_TO_COND(ERROR_INVALID_ACCESS, permission_denied);
MAP_ERR_TO_COND(ERROR_INVALID_DRIVE, no_such_device);
MAP_ERR_TO_COND(ERROR_INVALID_FUNCTION, function_not_supported);
MAP_ERR_TO_COND(ERROR_INVALID_HANDLE, invalid_argument);
MAP_ERR_TO_COND(ERROR_INVALID_NAME, invalid_argument);
MAP_ERR_TO_COND(ERROR_LOCK_VIOLATION, no_lock_available);
MAP_ERR_TO_COND(ERROR_LOCKED, no_lock_available);
MAP_ERR_TO_COND(ERROR_NEGATIVE_SEEK, invalid_argument);
MAP_ERR_TO_COND(ERROR_NOACCESS, permission_denied);
MAP_ERR_TO_COND(ERROR_NOT_ENOUGH_MEMORY, not_enough_memory);
MAP_ERR_TO_COND(ERROR_NOT_READY, resource_unavailable_try_again);
MAP_ERR_TO_COND(ERROR_NOT_SAME_DEVICE, cross_device_link);
MAP_ERR_TO_COND(ERROR_OPEN_FAILED, io_error);
MAP_ERR_TO_COND(ERROR_OPEN_FILES, device_or_resource_busy);
MAP_ERR_TO_COND(ERROR_OPERATION_ABORTED, operation_canceled);
MAP_ERR_TO_COND(ERROR_OUTOFMEMORY, not_enough_memory);
MAP_ERR_TO_COND(ERROR_PATH_NOT_FOUND, no_such_file_or_directory);
MAP_ERR_TO_COND(ERROR_READ_FAULT, io_error);
MAP_ERR_TO_COND(ERROR_RETRY, resource_unavailable_try_again);
MAP_ERR_TO_COND(ERROR_SEEK, io_error);
MAP_ERR_TO_COND(ERROR_SHARING_VIOLATION, permission_denied);
MAP_ERR_TO_COND(ERROR_TOO_MANY_OPEN_FILES, too_many_files_open);
MAP_ERR_TO_COND(ERROR_WRITE_FAULT, io_error);
MAP_ERR_TO_COND(ERROR_WRITE_PROTECT, permission_denied);
MAP_ERR_TO_COND(ERROR_SEM_TIMEOUT, timed_out);
MAP_ERR_TO_COND(WSAEACCES, permission_denied);
MAP_ERR_TO_COND(WSAEADDRINUSE, address_in_use);
MAP_ERR_TO_COND(WSAEADDRNOTAVAIL, address_not_available);
MAP_ERR_TO_COND(WSAEAFNOSUPPORT, address_family_not_supported);
MAP_ERR_TO_COND(WSAEALREADY, connection_already_in_progress);
MAP_ERR_TO_COND(WSAEBADF, bad_file_descriptor);
MAP_ERR_TO_COND(WSAECONNABORTED, connection_aborted);
MAP_ERR_TO_COND(WSAECONNREFUSED, connection_refused);
MAP_ERR_TO_COND(WSAECONNRESET, connection_reset);
MAP_ERR_TO_COND(WSAEDESTADDRREQ, destination_address_required);
MAP_ERR_TO_COND(WSAEFAULT, bad_address);
MAP_ERR_TO_COND(WSAEHOSTUNREACH, host_unreachable);
MAP_ERR_TO_COND(WSAEINPROGRESS, operation_in_progress);
MAP_ERR_TO_COND(WSAEINTR, interrupted);
MAP_ERR_TO_COND(WSAEINVAL, invalid_argument);
MAP_ERR_TO_COND(WSAEISCONN, already_connected);
MAP_ERR_TO_COND(WSAEMFILE, too_many_files_open);
MAP_ERR_TO_COND(WSAEMSGSIZE, message_size);
MAP_ERR_TO_COND(WSAENAMETOOLONG, filename_too_long);
MAP_ERR_TO_COND(WSAENETDOWN, network_down);
MAP_ERR_TO_COND(WSAENETRESET, network_reset);
MAP_ERR_TO_COND(WSAENETUNREACH, network_unreachable);
MAP_ERR_TO_COND(WSAENOBUFS, no_buffer_space);
MAP_ERR_TO_COND(WSAENOPROTOOPT, no_protocol_option);
MAP_ERR_TO_COND(WSAENOTCONN, not_connected);
MAP_ERR_TO_COND(WSAENOTSOCK, not_a_socket);
MAP_ERR_TO_COND(WSAEOPNOTSUPP, operation_not_supported);
MAP_ERR_TO_COND(WSAEPROTONOSUPPORT, protocol_not_supported);
MAP_ERR_TO_COND(WSAEPROTOTYPE, wrong_protocol_type);
MAP_ERR_TO_COND(WSAETIMEDOUT, timed_out);
MAP_ERR_TO_COND(WSAEWOULDBLOCK, operation_would_block);
default: return error_condition(ev, system_category());
}
}

View File

@ -0,0 +1,121 @@
//===---------------------- system_error.cpp ------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This was lifted from libc++ and modified for C++03.
//
//===----------------------------------------------------------------------===//
#include "llvm/System/system_error.h"
#include "llvm/System/Errno.h"
#include <string>
#include <cstring>
namespace llvm {
// class error_category
error_category::error_category() {
}
error_category::~error_category() {
}
error_condition
error_category::default_error_condition(int ev) const {
return error_condition(ev, *this);
}
bool
error_category::equivalent(int code, const error_condition& condition) const {
return default_error_condition(code) == condition;
}
bool
error_category::equivalent(const error_code& code, int condition) const {
return *this == code.category() && code.value() == condition;
}
std::string
_do_message::message(int ev) const {
return std::string(sys::StrError(ev));
}
class _generic_error_category : public _do_message {
public:
virtual const char* name() const;
virtual std::string message(int ev) const;
};
const char*
_generic_error_category::name() const {
return "generic";
}
std::string
_generic_error_category::message(int ev) const {
#ifdef ELAST
if (ev > ELAST)
return std::string("unspecified generic_category error");
#endif // ELAST
return _do_message::message(ev);
}
const error_category&
generic_category() {
static _generic_error_category s;
return s;
}
class _system_error_category : public _do_message {
public:
virtual const char* name() const;
virtual std::string message(int ev) const;
virtual error_condition default_error_condition(int ev) const;
};
const char*
_system_error_category::name() const {
return "system";
}
// std::string _system_error_category::message(int ev) const {
// Is in Platform/system_error.inc
// error_condition _system_error_category::default_error_condition(int ev) const
// Is in Platform/system_error.inc
const error_category&
system_category() {
static _system_error_category s;
return s;
}
// error_condition
std::string
error_condition::message() const {
return _cat_->message(_val_);
}
// error_code
std::string
error_code::message() const {
return _cat_->message(_val_);
}
} // end namespace llvm
// Include the truly platform-specific parts of this class.
#if defined(LLVM_ON_UNIX)
#include "Unix/system_error.inc"
#endif
#if defined(LLVM_ON_WIN32)
#include "Win32/system_error.inc"
#endif

View File

@ -1,6 +1,5 @@
add_executable(KillTheDoctor
KillTheDoctor.cpp
system_error.cpp
)
target_link_libraries(KillTheDoctor LLVMSupport LLVMSystem)

View File

@ -42,7 +42,7 @@
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/type_traits.h"
#include "llvm/System/Signals.h"
#include "system_error.h"
#include "llvm/System/system_error.h"
#include <algorithm>
#include <cerrno>
#include <cstdlib>

View File

@ -1,287 +0,0 @@
//===---------------------- system_error.cpp ------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This was lifted from libc++ and modified for C++03.
//
//===----------------------------------------------------------------------===//
#include "llvm/Config/config.h"
#include "system_error.h"
#include <string>
#include <cstring>
namespace llvm {
// class error_category
error_category::error_category() {
}
error_category::~error_category() {
}
error_condition
error_category::default_error_condition(int ev) const {
return error_condition(ev, *this);
}
bool
error_category::equivalent(int code, const error_condition& condition) const {
return default_error_condition(code) == condition;
}
bool
error_category::equivalent(const error_code& code, int condition) const {
return *this == code.category() && code.value() == condition;
}
std::string
_do_message::message(int ev) const {
return std::string(std::strerror(ev));
}
class _generic_error_category : public _do_message {
public:
virtual const char* name() const;
virtual std::string message(int ev) const;
};
const char*
_generic_error_category::name() const {
return "generic";
}
std::string
_generic_error_category::message(int ev) const {
#ifdef ELAST
if (ev > ELAST)
return std::string("unspecified generic_category error");
#endif // ELAST
return _do_message::message(ev);
}
const error_category&
generic_category() {
static _generic_error_category s;
return s;
}
class _system_error_category : public _do_message {
public:
virtual const char* name() const;
virtual std::string message(int ev) const;
virtual error_condition default_error_condition(int ev) const;
};
const char*
_system_error_category::name() const {
return "system";
}
// std::string _system_error_category::message(int ev) const {
// Is in Platform/system_error.inc
// error_condition _system_error_category::default_error_condition(int ev) const
// Is in Platform/system_error.inc
const error_category&
system_category() {
static _system_error_category s;
return s;
}
// error_condition
std::string
error_condition::message() const {
return _cat_->message(_val_);
}
// error_code
std::string
error_code::message() const {
return _cat_->message(_val_);
}
// system_error
std::string
system_error::_init(const error_code& ec, std::string what_arg) {
if (ec)
{
if (!what_arg.empty())
what_arg += ": ";
what_arg += ec.message();
}
return what_arg;
}
system_error::system_error(error_code ec, const std::string& what_arg)
: runtime_error(_init(ec, what_arg)), _ec_(ec) {
}
system_error::system_error(error_code ec, const char* what_arg)
: runtime_error(_init(ec, what_arg)), _ec_(ec) {
}
system_error::system_error(error_code ec)
: runtime_error(_init(ec, "")), _ec_(ec) {
}
system_error::system_error(int ev, const error_category& ecat,
const std::string& what_arg)
: runtime_error(_init(error_code(ev, ecat), what_arg))
, _ec_(error_code(ev, ecat)) {
}
system_error::system_error(int ev, const error_category& ecat,
const char* what_arg)
: runtime_error(_init(error_code(ev, ecat), what_arg))
, _ec_(error_code(ev, ecat)) {
}
system_error::system_error(int ev, const error_category& ecat)
: runtime_error(_init(error_code(ev, ecat), "")), _ec_(error_code(ev, ecat)) {
}
system_error::~system_error() throw() {
}
void
_throw_system_error(int ev, const char* what_arg) {
throw system_error(error_code(ev, system_category()), what_arg);
}
} // end namespace llvm
#ifdef LLVM_ON_WIN32
#include <Windows.h>
#include <WinError.h>
namespace llvm {
std::string
_system_error_category::message(int ev) const {
LPVOID lpMsgBuf = 0;
DWORD retval = ::FormatMessageA(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
ev,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPSTR) &lpMsgBuf,
0,
NULL);
if (retval == 0) {
::LocalFree(lpMsgBuf);
return std::string("Unknown error");
}
std::string str( static_cast<LPCSTR>(lpMsgBuf) );
::LocalFree(lpMsgBuf);
while (str.size()
&& (str[str.size()-1] == '\n' || str[str.size()-1] == '\r'))
str.erase( str.size()-1 );
if (str.size() && str[str.size()-1] == '.')
str.erase( str.size()-1 );
return str;
}
error_condition
_system_error_category::default_error_condition(int ev) const {
switch (ev)
{
case 0: return make_error_condition(errc::success);
// Windows system -> posix_errno decode table ---------------------------//
// see WinError.h comments for descriptions of errors
case ERROR_ACCESS_DENIED: return make_error_condition(errc::permission_denied);
case ERROR_ALREADY_EXISTS: return make_error_condition(errc::file_exists);
case ERROR_BAD_UNIT: return make_error_condition(errc::no_such_device);
case ERROR_BUFFER_OVERFLOW: return make_error_condition(errc::filename_too_long);
case ERROR_BUSY: return make_error_condition(errc::device_or_resource_busy);
case ERROR_BUSY_DRIVE: return make_error_condition(errc::device_or_resource_busy);
case ERROR_CANNOT_MAKE: return make_error_condition(errc::permission_denied);
case ERROR_CANTOPEN: return make_error_condition(errc::io_error);
case ERROR_CANTREAD: return make_error_condition(errc::io_error);
case ERROR_CANTWRITE: return make_error_condition(errc::io_error);
case ERROR_CURRENT_DIRECTORY: return make_error_condition(errc::permission_denied);
case ERROR_DEV_NOT_EXIST: return make_error_condition(errc::no_such_device);
case ERROR_DEVICE_IN_USE: return make_error_condition(errc::device_or_resource_busy);
case ERROR_DIR_NOT_EMPTY: return make_error_condition(errc::directory_not_empty);
case ERROR_DIRECTORY: return make_error_condition(errc::invalid_argument);
case ERROR_DISK_FULL: return make_error_condition(errc::no_space_on_device);
case ERROR_FILE_EXISTS: return make_error_condition(errc::file_exists);
case ERROR_FILE_NOT_FOUND: return make_error_condition(errc::no_such_file_or_directory);
case ERROR_HANDLE_DISK_FULL: return make_error_condition(errc::no_space_on_device);
case ERROR_INVALID_ACCESS: return make_error_condition(errc::permission_denied);
case ERROR_INVALID_DRIVE: return make_error_condition(errc::no_such_device);
case ERROR_INVALID_FUNCTION: return make_error_condition(errc::function_not_supported);
case ERROR_INVALID_HANDLE: return make_error_condition(errc::invalid_argument);
case ERROR_INVALID_NAME: return make_error_condition(errc::invalid_argument);
case ERROR_LOCK_VIOLATION: return make_error_condition(errc::no_lock_available);
case ERROR_LOCKED: return make_error_condition(errc::no_lock_available);
case ERROR_NEGATIVE_SEEK: return make_error_condition(errc::invalid_argument);
case ERROR_NOACCESS: return make_error_condition(errc::permission_denied);
case ERROR_NOT_ENOUGH_MEMORY: return make_error_condition(errc::not_enough_memory);
case ERROR_NOT_READY: return make_error_condition(errc::resource_unavailable_try_again);
case ERROR_NOT_SAME_DEVICE: return make_error_condition(errc::cross_device_link);
case ERROR_OPEN_FAILED: return make_error_condition(errc::io_error);
case ERROR_OPEN_FILES: return make_error_condition(errc::device_or_resource_busy);
case ERROR_OPERATION_ABORTED: return make_error_condition(errc::operation_canceled);
case ERROR_OUTOFMEMORY: return make_error_condition(errc::not_enough_memory);
case ERROR_PATH_NOT_FOUND: return make_error_condition(errc::no_such_file_or_directory);
case ERROR_READ_FAULT: return make_error_condition(errc::io_error);
case ERROR_RETRY: return make_error_condition(errc::resource_unavailable_try_again);
case ERROR_SEEK: return make_error_condition(errc::io_error);
case ERROR_SHARING_VIOLATION: return make_error_condition(errc::permission_denied);
case ERROR_TOO_MANY_OPEN_FILES: return make_error_condition(errc::too_many_files_open);
case ERROR_WRITE_FAULT: return make_error_condition(errc::io_error);
case ERROR_WRITE_PROTECT: return make_error_condition(errc::permission_denied);
case ERROR_SEM_TIMEOUT: return make_error_condition(errc::timed_out);
case WSAEACCES: return make_error_condition(errc::permission_denied);
case WSAEADDRINUSE: return make_error_condition(errc::address_in_use);
case WSAEADDRNOTAVAIL: return make_error_condition(errc::address_not_available);
case WSAEAFNOSUPPORT: return make_error_condition(errc::address_family_not_supported);
case WSAEALREADY: return make_error_condition(errc::connection_already_in_progress);
case WSAEBADF: return make_error_condition(errc::bad_file_descriptor);
case WSAECONNABORTED: return make_error_condition(errc::connection_aborted);
case WSAECONNREFUSED: return make_error_condition(errc::connection_refused);
case WSAECONNRESET: return make_error_condition(errc::connection_reset);
case WSAEDESTADDRREQ: return make_error_condition(errc::destination_address_required);
case WSAEFAULT: return make_error_condition(errc::bad_address);
case WSAEHOSTUNREACH: return make_error_condition(errc::host_unreachable);
case WSAEINPROGRESS: return make_error_condition(errc::operation_in_progress);
case WSAEINTR: return make_error_condition(errc::interrupted);
case WSAEINVAL: return make_error_condition(errc::invalid_argument);
case WSAEISCONN: return make_error_condition(errc::already_connected);
case WSAEMFILE: return make_error_condition(errc::too_many_files_open);
case WSAEMSGSIZE: return make_error_condition(errc::message_size);
case WSAENAMETOOLONG: return make_error_condition(errc::filename_too_long);
case WSAENETDOWN: return make_error_condition(errc::network_down);
case WSAENETRESET: return make_error_condition(errc::network_reset);
case WSAENETUNREACH: return make_error_condition(errc::network_unreachable);
case WSAENOBUFS: return make_error_condition(errc::no_buffer_space);
case WSAENOPROTOOPT: return make_error_condition(errc::no_protocol_option);
case WSAENOTCONN: return make_error_condition(errc::not_connected);
case WSAENOTSOCK: return make_error_condition(errc::not_a_socket);
case WSAEOPNOTSUPP: return make_error_condition(errc::operation_not_supported);
case WSAEPROTONOSUPPORT: return make_error_condition(errc::protocol_not_supported);
case WSAEPROTOTYPE: return make_error_condition(errc::wrong_protocol_type);
case WSAETIMEDOUT: return make_error_condition(errc::timed_out);
case WSAEWOULDBLOCK: return make_error_condition(errc::operation_would_block);
default: return error_condition(ev, system_category());
}
}
} // end namespace llvm
#endif // LLVM_ON_WIN32