Add exception wrapping utilities, will help issues like #60
This commit is contained in:
parent
61d536bc02
commit
ab7e71f1b2
@ -244,7 +244,7 @@ namespace cpptrace {
|
||||
protected:
|
||||
explicit exception_with_message(
|
||||
std::string&& message_arg,
|
||||
std::uint32_t skip
|
||||
std::size_t skip
|
||||
) noexcept : exception(skip + 1), message(std::move(message_arg)) {}
|
||||
|
||||
explicit exception_with_message(
|
||||
@ -313,6 +313,21 @@ namespace cpptrace {
|
||||
explicit underflow_error(std::string&& message_arg) noexcept
|
||||
: exception_with_message(std::move(message_arg), 1) {}
|
||||
};
|
||||
|
||||
class CPPTRACE_EXPORT nested_exception : public exception {
|
||||
std::exception_ptr ptr;
|
||||
mutable std::string what_value;
|
||||
public:
|
||||
explicit nested_exception(std::exception_ptr exception_ptr) noexcept
|
||||
: exception(1), ptr(exception_ptr) {}
|
||||
explicit nested_exception(std::exception_ptr exception_ptr, std::size_t skip) noexcept
|
||||
: exception(skip + 1), ptr(exception_ptr) {}
|
||||
|
||||
const char* get_raw_what() const noexcept override;
|
||||
std::exception_ptr nested_ptr() const noexcept;
|
||||
};
|
||||
|
||||
CPPTRACE_EXPORT [[noreturn]] void rethrow_and_wrap_if_needed(std::size_t skip = 0);
|
||||
}
|
||||
|
||||
#if defined(CPPTRACE_STD_FORMAT) && defined(__cpp_lib_format)
|
||||
@ -331,4 +346,21 @@ namespace cpptrace {
|
||||
};
|
||||
#endif
|
||||
|
||||
// Exception wrapper utilities
|
||||
#define CPPTRACE_WRAP_BLOCK(statements) do { \
|
||||
try { \
|
||||
statements \
|
||||
} catch(...) { \
|
||||
::cpptrace::rethrow_and_wrap_if_needed(); \
|
||||
} \
|
||||
} while(0);
|
||||
|
||||
#define CPPTRACE_WRAP(expression) [&] () -> decltype((expression)) { \
|
||||
try { \
|
||||
return expression; \
|
||||
} catch(...) { \
|
||||
::cpptrace::rethrow_and_wrap_if_needed(1); \
|
||||
} \
|
||||
} ()
|
||||
|
||||
#endif
|
||||
|
||||
@ -362,6 +362,7 @@ namespace cpptrace {
|
||||
}
|
||||
|
||||
[[noreturn]] void terminate_handler() {
|
||||
// TODO: Support std::nested_exception?
|
||||
try {
|
||||
auto ptr = std::current_exception();
|
||||
if(ptr == nullptr) {
|
||||
@ -486,4 +487,32 @@ namespace cpptrace {
|
||||
const char* exception_with_message::get_raw_what() const noexcept {
|
||||
return message.c_str();
|
||||
}
|
||||
|
||||
const char* nested_exception::get_raw_what() const noexcept {
|
||||
if(what_value.empty()) {
|
||||
try {
|
||||
std::rethrow_exception(ptr);
|
||||
} catch(std::exception& e) {
|
||||
// what_value = std::string("cpptrace::nested_exception: ") + e.what();
|
||||
what_value = e.what();
|
||||
} catch(...) {
|
||||
what_value = "<cpptrace::nested_exception holding instance of " + detail::exception_type_name() + ">";
|
||||
}
|
||||
}
|
||||
return what_value.c_str();
|
||||
}
|
||||
|
||||
std::exception_ptr nested_exception::nested_ptr() const noexcept {
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void rethrow_and_wrap_if_needed(std::size_t skip) {
|
||||
try {
|
||||
std::rethrow_exception(std::current_exception());
|
||||
} catch(cpptrace::exception&) {
|
||||
throw; // already a cpptrace::exception
|
||||
} catch(...) {
|
||||
throw nested_exception(std::current_exception(), skip + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user