new checker for unique_usertype to ensure type safety, when SOL_CHECK_ARGUMENTS or a protected tag is used to protect a function

This commit is contained in:
ThePhD 2017-06-13 16:34:18 -04:00
parent 51a03b2b35
commit 85620df63c
4 changed files with 92 additions and 14 deletions

View File

@ -20,8 +20,8 @@
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// This file was generated with a script. // This file was generated with a script.
// Generated 2017-06-12 14:43:06.223161 UTC // Generated 2017-06-13 20:34:08.313723 UTC
// This header was generated with sol v2.17.5 (revision 50935ae) // This header was generated with sol v2.17.5 (revision 51a03b2)
// https://github.com/ThePhD/sol2 // https://github.com/ThePhD/sol2
#ifndef SOL_SINGLE_INCLUDE_HPP #ifndef SOL_SINGLE_INCLUDE_HPP
@ -5482,11 +5482,26 @@ namespace sol {
} }
}; };
template<typename T> template<typename X>
struct checker<T, type::userdata, std::enable_if_t<is_unique_usertype<T>::value>> { struct checker<X, type::userdata, std::enable_if_t<is_unique_usertype<X>::value>> {
typedef typename unique_usertype_traits<X>::type T;
template <typename Handler> template <typename Handler>
static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
return checker<typename unique_usertype_traits<T>::type, type::userdata>{}.check(L, index, std::forward<Handler>(handler), tracking); const type indextype = type_of(L, index);
tracking.use(1);
if (indextype != type::userdata) {
handler(L, index, type::userdata, indextype);
return false;
}
if (lua_getmetatable(L, index) == 0) {
return true;
}
int metatableindex = lua_gettop(L);
if (stack_detail::check_metatable<detail::unique_usertype<T>>(L, metatableindex))
return true;
lua_pop(L, 1);
handler(L, index, type::userdata, indextype);
return false;
} }
}; };
@ -8213,7 +8228,7 @@ namespace sol {
template <typename Fx, typename... Fxs, std::size_t I, std::size_t... In, std::size_t... M, typename Match, typename... Args> template <typename Fx, typename... Fxs, std::size_t I, std::size_t... In, std::size_t... M, typename Match, typename... Args>
inline int overload_match_arity(types<Fx, Fxs...>, std::index_sequence<I, In...>, std::index_sequence<M...>, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { inline int overload_match_arity(types<Fx, Fxs...>, std::index_sequence<I, In...>, std::index_sequence<M...>, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) {
typedef lua_bind_traits<meta::unqualified_t<Fx>> traits; typedef lua_bind_traits<meta::unwrap_unqualified_t<Fx>> traits;
typedef meta::tuple_types<typename traits::return_type> return_types; typedef meta::tuple_types<typename traits::return_type> return_types;
typedef typename traits::free_args_list args_list; typedef typename traits::free_args_list args_list;
// compile-time eliminate any functions that we know ahead of time are of improper arity // compile-time eliminate any functions that we know ahead of time are of improper arity
@ -8237,7 +8252,7 @@ namespace sol {
template <typename Fx, std::size_t I, std::size_t... M, typename Match, typename... Args> template <typename Fx, std::size_t I, std::size_t... M, typename Match, typename... Args>
inline int overload_match_arity_single(types<Fx>, std::index_sequence<I>, std::index_sequence<M...>, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { inline int overload_match_arity_single(types<Fx>, std::index_sequence<I>, std::index_sequence<M...>, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) {
typedef lua_bind_traits<meta::unqualified_t<Fx>> traits; typedef lua_bind_traits<meta::unwrap_unqualified_t<Fx>> traits;
typedef meta::tuple_types<typename traits::return_type> return_types; typedef meta::tuple_types<typename traits::return_type> return_types;
typedef typename traits::free_args_list args_list; typedef typename traits::free_args_list args_list;
// compile-time eliminate any functions that we know ahead of time are of improper arity // compile-time eliminate any functions that we know ahead of time are of improper arity
@ -8252,7 +8267,7 @@ namespace sol {
template <typename Fx, typename Fx1, typename... Fxs, std::size_t I, std::size_t I1, std::size_t... In, std::size_t... M, typename Match, typename... Args> template <typename Fx, typename Fx1, typename... Fxs, std::size_t I, std::size_t I1, std::size_t... In, std::size_t... M, typename Match, typename... Args>
inline int overload_match_arity_single(types<Fx, Fx1, Fxs...>, std::index_sequence<I, I1, In...>, std::index_sequence<M...>, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { inline int overload_match_arity_single(types<Fx, Fx1, Fxs...>, std::index_sequence<I, I1, In...>, std::index_sequence<M...>, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) {
typedef lua_bind_traits<meta::unqualified_t<Fx>> traits; typedef lua_bind_traits<meta::unwrap_unqualified_t<Fx>> traits;
typedef meta::tuple_types<typename traits::return_type> return_types; typedef meta::tuple_types<typename traits::return_type> return_types;
typedef typename traits::free_args_list args_list; typedef typename traits::free_args_list args_list;
// compile-time eliminate any functions that we know ahead of time are of improper arity // compile-time eliminate any functions that we know ahead of time are of improper arity
@ -8400,6 +8415,13 @@ namespace sol {
} }
}; };
template <typename T, bool is_index, bool is_variable, bool checked, int boost, typename C>
struct agnostic_lua_call_wrapper<std::reference_wrapper<T>, is_index, is_variable, checked, boost, C> {
static int call(lua_State* L, std::reference_wrapper<T> f) {
return agnostic_lua_call_wrapper<T, is_index, is_variable, checked, boost>{}.call(L, f.get());
}
};
template <typename T, typename F, bool is_index, bool is_variable, bool checked = stack::stack_detail::default_check_arguments, int boost = 0, typename = void> template <typename T, typename F, bool is_index, bool is_variable, bool checked = stack::stack_detail::default_check_arguments, int boost = 0, typename = void>
struct lua_call_wrapper : agnostic_lua_call_wrapper<F, is_index, is_variable, checked, boost> {}; struct lua_call_wrapper : agnostic_lua_call_wrapper<F, is_index, is_variable, checked, boost> {};

View File

@ -75,7 +75,7 @@ namespace sol {
template <typename Fx, typename... Fxs, std::size_t I, std::size_t... In, std::size_t... M, typename Match, typename... Args> template <typename Fx, typename... Fxs, std::size_t I, std::size_t... In, std::size_t... M, typename Match, typename... Args>
inline int overload_match_arity(types<Fx, Fxs...>, std::index_sequence<I, In...>, std::index_sequence<M...>, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { inline int overload_match_arity(types<Fx, Fxs...>, std::index_sequence<I, In...>, std::index_sequence<M...>, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) {
typedef lua_bind_traits<meta::unqualified_t<Fx>> traits; typedef lua_bind_traits<meta::unwrap_unqualified_t<Fx>> traits;
typedef meta::tuple_types<typename traits::return_type> return_types; typedef meta::tuple_types<typename traits::return_type> return_types;
typedef typename traits::free_args_list args_list; typedef typename traits::free_args_list args_list;
// compile-time eliminate any functions that we know ahead of time are of improper arity // compile-time eliminate any functions that we know ahead of time are of improper arity
@ -99,7 +99,7 @@ namespace sol {
template <typename Fx, std::size_t I, std::size_t... M, typename Match, typename... Args> template <typename Fx, std::size_t I, std::size_t... M, typename Match, typename... Args>
inline int overload_match_arity_single(types<Fx>, std::index_sequence<I>, std::index_sequence<M...>, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { inline int overload_match_arity_single(types<Fx>, std::index_sequence<I>, std::index_sequence<M...>, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) {
typedef lua_bind_traits<meta::unqualified_t<Fx>> traits; typedef lua_bind_traits<meta::unwrap_unqualified_t<Fx>> traits;
typedef meta::tuple_types<typename traits::return_type> return_types; typedef meta::tuple_types<typename traits::return_type> return_types;
typedef typename traits::free_args_list args_list; typedef typename traits::free_args_list args_list;
// compile-time eliminate any functions that we know ahead of time are of improper arity // compile-time eliminate any functions that we know ahead of time are of improper arity
@ -114,7 +114,7 @@ namespace sol {
template <typename Fx, typename Fx1, typename... Fxs, std::size_t I, std::size_t I1, std::size_t... In, std::size_t... M, typename Match, typename... Args> template <typename Fx, typename Fx1, typename... Fxs, std::size_t I, std::size_t I1, std::size_t... In, std::size_t... M, typename Match, typename... Args>
inline int overload_match_arity_single(types<Fx, Fx1, Fxs...>, std::index_sequence<I, I1, In...>, std::index_sequence<M...>, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { inline int overload_match_arity_single(types<Fx, Fx1, Fxs...>, std::index_sequence<I, I1, In...>, std::index_sequence<M...>, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) {
typedef lua_bind_traits<meta::unqualified_t<Fx>> traits; typedef lua_bind_traits<meta::unwrap_unqualified_t<Fx>> traits;
typedef meta::tuple_types<typename traits::return_type> return_types; typedef meta::tuple_types<typename traits::return_type> return_types;
typedef typename traits::free_args_list args_list; typedef typename traits::free_args_list args_list;
// compile-time eliminate any functions that we know ahead of time are of improper arity // compile-time eliminate any functions that we know ahead of time are of improper arity
@ -262,6 +262,13 @@ namespace sol {
} }
}; };
template <typename T, bool is_index, bool is_variable, bool checked, int boost, typename C>
struct agnostic_lua_call_wrapper<std::reference_wrapper<T>, is_index, is_variable, checked, boost, C> {
static int call(lua_State* L, std::reference_wrapper<T> f) {
return agnostic_lua_call_wrapper<T, is_index, is_variable, checked, boost>{}.call(L, f.get());
}
};
template <typename T, typename F, bool is_index, bool is_variable, bool checked = stack::stack_detail::default_check_arguments, int boost = 0, typename = void> template <typename T, typename F, bool is_index, bool is_variable, bool checked = stack::stack_detail::default_check_arguments, int boost = 0, typename = void>
struct lua_call_wrapper : agnostic_lua_call_wrapper<F, is_index, is_variable, checked, boost> {}; struct lua_call_wrapper : agnostic_lua_call_wrapper<F, is_index, is_variable, checked, boost> {};

View File

@ -414,11 +414,26 @@ namespace sol {
} }
}; };
template<typename T> template<typename X>
struct checker<T, type::userdata, std::enable_if_t<is_unique_usertype<T>::value>> { struct checker<X, type::userdata, std::enable_if_t<is_unique_usertype<X>::value>> {
typedef typename unique_usertype_traits<X>::type T;
template <typename Handler> template <typename Handler>
static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
return checker<typename unique_usertype_traits<T>::type, type::userdata>{}.check(L, index, std::forward<Handler>(handler), tracking); const type indextype = type_of(L, index);
tracking.use(1);
if (indextype != type::userdata) {
handler(L, index, type::userdata, indextype);
return false;
}
if (lua_getmetatable(L, index) == 0) {
return true;
}
int metatableindex = lua_gettop(L);
if (stack_detail::check_metatable<detail::unique_usertype<T>>(L, metatableindex))
return true;
lua_pop(L, 1);
handler(L, index, type::userdata, indextype);
return false;
} }
}; };

View File

@ -1135,3 +1135,37 @@ TEST_CASE("functions/set_function-already-wrapped", "setting a function returned
REQUIRE_NOTHROW(lua.script("assert(test() == 5)")); REQUIRE_NOTHROW(lua.script("assert(test() == 5)"));
} }
} }
TEST_CASE("functions/unique-overloading", "make sure overloading can work with ptr vs. specifically asking for a unique usertype") {
sol::state lua;
struct test { int special_value = 17; };
auto print_up_test = [](std::unique_ptr<test>& x) {
REQUIRE(x->special_value == 17);
};
auto print_ptr_test = [](test* x) {
REQUIRE(x->special_value == 17);
};
lua.set_function("f", print_up_test);
lua.set_function("g", sol::overload(
std::ref(print_up_test),
print_ptr_test
));
lua["v1"] = std::make_unique<test>();
lua["v2"] = test{};
REQUIRE_NOTHROW([&]() {
lua.script("g(v1)");
}());
REQUIRE_NOTHROW([&]() {
lua.script("g(v2)");
}());
REQUIRE_NOTHROW([&]() {
lua.script("f(v1)");
}());
REQUIRE_THROWS([&]() {
lua.script("f(v2)");
}());
}