Commit 7bc60af3 authored by Dominik Charousset's avatar Dominik Charousset

Fix undefined behavior in init_fun_factory

parent 3e3c9479
...@@ -55,13 +55,16 @@ protected: ...@@ -55,13 +55,16 @@ protected:
}; };
/// Wraps a user-defined function and gives it a uniform signature. /// Wraps a user-defined function and gives it a uniform signature.
template <class Base, class F, class ArgsPtr, bool ReturnsBehavior, template <class Base, class F, class Tuple, bool ReturnsBehavior,
bool HasSelfPtr> bool HasSelfPtr>
class init_fun_factory_helper final : public init_fun_factory_helper_base { class init_fun_factory_helper final : public init_fun_factory_helper_base {
public: public:
init_fun_factory_helper(F fun, ArgsPtr args) using args_pointer = std::shared_ptr<Tuple>;
: fun_(std::move(fun)),
args_(std::move(args)) { static constexpr bool args_empty = std::tuple_size<Tuple>::value == 0;
init_fun_factory_helper(F fun, args_pointer args)
: fun_(std::move(fun)), args_(std::move(args)) {
// nop // nop
} }
...@@ -72,41 +75,52 @@ public: ...@@ -72,41 +75,52 @@ public:
behavior operator()(local_actor* self) final { behavior operator()(local_actor* self) final {
if (hook_ != nullptr) if (hook_ != nullptr)
hook_(self); hook_(self);
bool_token<ReturnsBehavior> returns_behavior_token; auto dptr = static_cast<Base*>(self);
bool_token<HasSelfPtr> captures_self_token; if constexpr (ReturnsBehavior) {
return apply(returns_behavior_token, captures_self_token, self); auto unbox = [](auto x) -> behavior { return std::move(x.unbox()); };
} if constexpr (args_empty) {
if constexpr (HasSelfPtr) {
// behavior (pointer)
private: return unbox(fun_(dptr));
// behavior (pointer) } else {
behavior apply(std::true_type, std::true_type, local_actor* ptr) { // behavior ()
auto res = apply_moved_args_prefixed(fun_, get_indices(*args_), *args_, return unbox(fun_());
static_cast<Base*>(ptr)); }
return std::move(res.unbox()); } else {
} if constexpr (HasSelfPtr) {
// behavior (pointer, args...)
// void (pointer) auto res = apply_moved_args_prefixed(fun_, get_indices(*args_),
behavior apply(std::false_type, std::true_type, local_actor* ptr) { *args_, dptr);
apply_moved_args_prefixed(fun_, get_indices(*args_), return unbox(std::move(res));
*args_, static_cast<Base*>(ptr)); } else {
return behavior{}; // behavior (args...)
} return unbox(apply_args(fun_, get_indices(*args_), *args_));
}
// behavior () }
behavior apply(std::true_type, std::false_type, local_actor*) { } else {
auto res = apply_args(fun_, get_indices(*args_), *args_); if constexpr (args_empty) {
return std::move(res.unbox()); if constexpr (HasSelfPtr) {
} // void (pointer)
fun_(dptr);
// void () } else {
behavior apply(std::false_type, std::false_type, local_actor*) { // void ()
apply_args(fun_, get_indices(*args_), *args_); fun_();
return behavior{}; }
} else {
if constexpr (HasSelfPtr) {
// void (pointer, args...)
apply_moved_args_prefixed(fun_, get_indices(*args_), *args_, dptr);
} else {
// void (args...)
apply_args(fun_, get_indices(*args_), *args_);
}
}
return {};
}
} }
F fun_; F fun_;
ArgsPtr args_; args_pointer args_;
}; };
template <class Base, class F> template <class Base, class F>
...@@ -127,8 +141,7 @@ public: ...@@ -127,8 +141,7 @@ public:
constexpr bool selfptr = std::is_pointer<first_arg>::value; constexpr bool selfptr = std::is_pointer<first_arg>::value;
constexpr bool rets = std::is_convertible<res_type, behavior>::value; constexpr bool rets = std::is_convertible<res_type, behavior>::value;
using tuple_type = decltype(std::make_tuple(detail::spawn_fwd<Ts>(xs)...)); using tuple_type = decltype(std::make_tuple(detail::spawn_fwd<Ts>(xs)...));
using tuple_ptr = std::shared_ptr<tuple_type>; using helper = init_fun_factory_helper<Base, F, tuple_type, rets, selfptr>;
using helper = init_fun_factory_helper<Base, F, tuple_ptr, rets, selfptr>;
return ptr_type{new helper{std::move(f), sizeof...(Ts) > 0 return ptr_type{new helper{std::move(f), sizeof...(Ts) > 0
? std::make_shared<tuple_type>( ? std::make_shared<tuple_type>(
detail::spawn_fwd<Ts>(xs)...) detail::spawn_fwd<Ts>(xs)...)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment