Skip to content

Commit 9806cca

Browse files
committed
rework error handling
1 parent 5c1b555 commit 9806cca

File tree

10 files changed

+83
-133
lines changed

10 files changed

+83
-133
lines changed

docs.in/reference/set_error_handler.cpp

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,24 @@
11
#ifdef YOMM2_MD
2-
headers: yorel/yomm2/core.hpp, yorel/yomm2.hpp, yorel/yomm2.hpp
2+
headers : yorel / yomm2 / core.hpp, yorel / yomm2.hpp,
3+
yorel /
4+
yomm2.hpp
35

4-
```c++
5-
error_handler_type set_error_handler(error_handler_type handler);
6+
```c++ error_handler_type set_error_handler(error_handler_type handler);
67
```
78

8-
All errors are reported via an indirect call to a handler, passing it a
9-
`std::variant` that identifies the specific error. The handler can be set to
10-
a user-defined function with `set_error_handler`. The library calls `abort()`
11-
immediately after calling the handler, but the handler can prevent program
12-
termination by throwing an exception. The default handler writes an error
13-
message to `stderr` in debug mode.
9+
All errors are reported via an indirect call to a handler,
10+
passing it a
11+
`std::variant` that identifies the specific error.The
12+
handler can be set to a user -
13+
defined function with `set_error_handler`.The
14+
library calls `abort()` immediately after calling the handler,
15+
but the handler can prevent program termination by throwing an exception
16+
.The default handler writes an error message to `stderr` in debug mode
17+
.
1418

1519
`set_error_handler` returns the previous handler.
1620

17-
## Example
21+
##Example
1822

1923
#endif
2024

@@ -30,7 +34,7 @@ message to `stderr` in debug mode.
3034
#include <yorel/yomm2.hpp>
3135
#include <yorel/yomm2/compiler.hpp>
3236

33-
struct Animal {
37+
struct Animal {
3438
virtual ~Animal() {
3539
}
3640
};
@@ -43,9 +47,9 @@ declare_method(void, kick, (virtual_<Animal&>));
4347

4448
using namespace yorel::yomm2; // for brevity
4549

46-
error_handler_type next_error_handler;
50+
default_policy::error_handler_type next_error_handler;
4751

48-
void no_definition_handler(const error_type& ev) {
52+
void no_definition_handler(const default_policy::error_variant& ev) {
4953
if (auto error = std::get_if<resolution_error>(&ev)) {
5054
if (error->status == resolution_error::no_definition) {
5155
throw std::runtime_error("not defined");
@@ -56,7 +60,8 @@ void no_definition_handler(const error_type& ev) {
5660
}
5761

5862
BOOST_AUTO_TEST_CASE(ref_set_error_handler_example) {
59-
next_error_handler = set_error_handler(no_definition_handler);
63+
next_error_handler =
64+
default_policy::set_error_handler(no_definition_handler);
6065
update();
6166

6267
try {

include/yorel/yomm2/core.hpp

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -892,9 +892,9 @@ method<Name, Return(Parameters...), Options...>::vptr(const ArgType& arg) const
892892
template<
893893
typename Name, typename Return, typename... Parameters, class... Options>
894894
template<class Error>
895-
inline void
895+
inline auto
896896
method<Name, Return(Parameters...), Options...>::check_static_offset(
897-
std::size_t actual, std::size_t expected) const noexcept(NoExcept) {
897+
std::size_t actual, std::size_t expected) const noexcept(NoExcept) -> void {
898898
using namespace detail;
899899

900900
if (actual != expected) {
@@ -903,7 +903,7 @@ method<Name, Return(Parameters...), Options...>::check_static_offset(
903903
error.method = Policy::template static_type<method>();
904904
error.expected = this->slots_strides[0];
905905
error.actual = actual;
906-
Policy::error(error_type(std::move(error)));
906+
Policy::error(error);
907907

908908
abort();
909909
}
@@ -1059,7 +1059,7 @@ method<Name, Return(Parameters...), Options...>::not_implemented_handler(
10591059
std::copy_n(
10601060
types, (std::min)(sizeof...(args), resolution_error::max_types),
10611061
&error.types[0]);
1062-
Policy::error(error_type(std::move(error)));
1062+
Policy::error(error);
10631063
}
10641064

10651065
abort(); // in case user handler "forgets" to abort
@@ -1081,7 +1081,7 @@ method<Name, Return(Parameters...), Options...>::ambiguous_handler(
10811081
std::copy_n(
10821082
types, (std::min)(sizeof...(args), resolution_error::max_types),
10831083
&error.types[0]);
1084-
Policy::error(error_type(std::move(error)));
1084+
Policy::error(error);
10851085
}
10861086

10871087
abort(); // in case user handler "forgets" to abort
@@ -1152,18 +1152,6 @@ struct method_macro_aux<Name, Signature, types<Options...>> {
11521152

11531153
} // namespace detail
11541154

1155-
#ifndef BOOST_NO_RTTI
1156-
1157-
inline auto set_error_handler(error_handler_type handler)
1158-
-> error_handler_type {
1159-
auto p = &default_policy::error;
1160-
auto prev = default_policy::error;
1161-
default_policy::error = handler;
1162-
return prev;
1163-
}
1164-
1165-
#endif
1166-
11671155
} // namespace yomm2
11681156
} // namespace yorel
11691157

include/yorel/yomm2/detail/compiler.hpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,7 @@ void compiler<Policy>::augment_classes() {
413413

414414
if constexpr (Policy::template has_facet<
415415
policies::error_handler>) {
416-
Policy::error(error_type(error));
416+
Policy::error(error);
417417
}
418418

419419
abort();
@@ -554,7 +554,7 @@ void compiler<Policy>::augment_methods() {
554554
error.type = ti;
555555

556556
if constexpr (has_facet<Policy, error_handler>) {
557-
Policy::error(error_type(error));
557+
Policy::error(error);
558558
}
559559

560560
abort();
@@ -599,7 +599,7 @@ void compiler<Policy>::augment_methods() {
599599
error.type = type;
600600

601601
if constexpr (has_facet<Policy, error_handler>) {
602-
Policy::error(error_type(error));
602+
Policy::error(error);
603603
}
604604

605605
abort();

include/yorel/yomm2/policies/core.hpp

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -70,24 +70,6 @@ struct static_offset_error : error {
7070
struct static_slot_error : static_offset_error {};
7171
struct static_stride_error : static_offset_error {};
7272

73-
using error_type = std::variant<
74-
error, resolution_error, unknown_class_error, hash_search_error,
75-
method_table_error, static_slot_error, static_stride_error>;
76-
77-
using error_handler_type = std::function<void(const error_type& error)>;
78-
79-
// deprecated
80-
81-
struct method_call_error {
82-
resolution_error::status_type code;
83-
static constexpr auto not_implemented = resolution_error::no_definition;
84-
static constexpr auto ambiguous = resolution_error::ambiguous;
85-
std::string_view method_name;
86-
};
87-
88-
using method_call_error_handler =
89-
void (*)(const method_call_error& error, std::size_t arity, type_id* types);
90-
9173
namespace policies {
9274

9375
struct abstract_policy {};

include/yorel/yomm2/policies/fast_perfect_hash.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ void fast_perfect_hash<Policy>::hash_initialize(
143143
error.buckets = 1 << M;
144144

145145
if constexpr (has_facet<Policy, error_handler>) {
146-
Policy::error(error_type(error));
146+
Policy::error(error);
147147
}
148148

149149
abort();

include/yorel/yomm2/policies/throw_error.hpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@ namespace yomm2 {
1414
namespace policies {
1515

1616
struct yOMM2_API_gcc throw_error : virtual error_handler {
17-
static void error(const error_type& error_v) {
18-
std::visit([](auto&& arg) { throw arg; }, error_v);
17+
template<class Error>
18+
static auto error(const Error& error) {
19+
throw error;
1920
}
2021
};
2122

include/yorel/yomm2/policies/vectored_error.hpp renamed to include/yorel/yomm2/policies/vectored_error_handler.hpp

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,29 @@ namespace yorel {
1313
namespace yomm2 {
1414
namespace policies {
1515

16-
template<class Policy, typename DefaultHandlerProvider = void>
17-
struct yOMM2_API_gcc vectored_error : virtual error_handler {
18-
static error_handler_type error;
16+
template<class Policy>
17+
struct yOMM2_API_gcc vectored_error_handler : virtual error_handler {
1918

20-
static void default_error_handler(const error_type& error_v) {
19+
using error_variant = std::variant<
20+
error, resolution_error, unknown_class_error, hash_search_error,
21+
method_table_error, static_slot_error, static_stride_error>;
22+
23+
using error_handler_type = std::function<void(const error_variant& error)>;
24+
static error_handler_type error_handler;
25+
26+
template<class Error>
27+
static auto error(const Error& error) {
28+
error_handler(error_variant(error));
29+
}
30+
31+
static auto set_error_handler(error_handler_type handler) {
32+
auto prev = error_handler;
33+
error_handler = handler;
34+
35+
return error_handler;
36+
}
37+
38+
static auto default_error_handler(const error_variant& error_v) {
2139
using namespace detail;
2240
using namespace policies;
2341

@@ -59,11 +77,10 @@ struct yOMM2_API_gcc vectored_error : virtual error_handler {
5977
}
6078
};
6179

62-
template<class Policy, typename DefaultHandlerProvider>
63-
error_handler_type vectored_error<Policy, DefaultHandlerProvider>::error =
64-
std::conditional_t<
65-
std::is_same_v<DefaultHandlerProvider, void>, vectored_error<Policy>,
66-
DefaultHandlerProvider>::default_error_handler;
80+
template<class Policy>
81+
typename vectored_error_handler<Policy>::error_handler_type
82+
vectored_error_handler<Policy>::error_handler =
83+
vectored_error_handler<Policy>::default_error_handler;
6784

6885
} // namespace policies
6986
} // namespace yomm2

include/yorel/yomm2/policy.hpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
#include <yorel/yomm2/policies/basic_error_output.hpp>
2222
#include <yorel/yomm2/policies/basic_trace_output.hpp>
2323
#include <yorel/yomm2/policies/fast_perfect_hash.hpp>
24-
#include <yorel/yomm2/policies/vectored_error.hpp>
24+
#include <yorel/yomm2/policies/vectored_error_handler.hpp>
2525

2626
#ifndef BOOST_NO_EXCEPTIONS
2727
#include <yorel/yomm2/policies/throw_error.hpp>
@@ -34,13 +34,13 @@ namespace policies {
3434
struct yOMM2_API_gcc release
3535
: basic_policy<
3636
release, std_rtti, fast_perfect_hash<release>, vptr_vector<release>,
37-
vectored_error<release>> {};
37+
vectored_error_handler<release>> {};
3838

3939
struct yOMM2_API_gcc debug
4040
: basic_policy<
4141
debug, std_rtti, checked_perfect_hash<debug>, vptr_vector<debug>,
4242
basic_error_output<debug>, basic_trace_output<debug>,
43-
vectored_error<debug>> {};
43+
vectored_error_handler<debug>> {};
4444

4545
} // namespace policies
4646

tests/test_blackbox.cpp

Lines changed: 4 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ YOMM2_DEFINE(void, times, (const diagonal_matrix&, const matrix&)) {
262262
YOMM2_DEFINE(void, times, (const matrix&, const diagonal_matrix&)) {
263263
}
264264

265-
void test_handler(const error_type& error_v) {
265+
void test_handler(const default_policy::error_variant& error_v) {
266266
if (auto error = std::get_if<resolution_error>(&error_v)) {
267267
throw *error;
268268
}
@@ -278,46 +278,6 @@ void test_handler(const error_type& error_v) {
278278
throw int();
279279
}
280280

281-
BOOST_AUTO_TEST_CASE(call_error_handling) {
282-
update();
283-
284-
auto prev_handler = set_error_handler(test_handler);
285-
286-
try {
287-
times(dense_matrix(), dense_matrix());
288-
BOOST_FAIL("did not throw");
289-
} catch (const resolution_error& error) {
290-
BOOST_TEST(error.status == resolution_error::no_definition);
291-
} catch (...) {
292-
BOOST_FAIL("unexpected exception");
293-
}
294-
295-
try {
296-
times(diagonal_matrix(), diagonal_matrix());
297-
BOOST_FAIL("did not throw");
298-
} catch (const resolution_error& error) {
299-
BOOST_TEST(error.status == resolution_error::ambiguous);
300-
} catch (...) {
301-
BOOST_FAIL("unexpected exception");
302-
}
303-
304-
#ifndef NDEBUG
305-
struct identity_matrix : matrix {};
306-
307-
try {
308-
times(diagonal_matrix(), identity_matrix());
309-
BOOST_FAIL("did not throw");
310-
} catch (const unknown_class_error& error) {
311-
BOOST_TEST(
312-
error.type == reinterpret_cast<type_id>(&typeid(identity_matrix)));
313-
} catch (...) {
314-
BOOST_FAIL("unexpected exception");
315-
}
316-
#endif
317-
318-
set_error_handler(prev_handler);
319-
}
320-
321281
} // namespace errors
322282

323283
namespace update_error_handling {
@@ -332,17 +292,16 @@ struct base {
332292
YOMM2_DECLARE(void, foo, (virtual_<base&>), test_policy);
333293

334294
BOOST_AUTO_TEST_CASE(test_update_error_handling) {
335-
auto prev_handler = test_policy::error;
336-
test_policy::error = errors::test_handler;
295+
auto prev_handler = test_policy::set_error_handler(errors::test_handler);
337296

338297
try {
339298
update<test_policy>();
340299
} catch (const unknown_class_error& error) {
341-
test_policy::error = prev_handler;
300+
test_policy::set_error_handler(prev_handler);
342301
BOOST_TEST(error.type == reinterpret_cast<type_id>(&typeid(base)));
343302
return;
344303
} catch (...) {
345-
test_policy::error = prev_handler;
304+
test_policy::set_error_handler(prev_handler);
346305
BOOST_FAIL("unexpected exception");
347306
}
348307
BOOST_FAIL("did not throw");

0 commit comments

Comments
 (0)