From 85620df63c539754b9d0363db7957ece4939ead1 Mon Sep 17 00:00:00 2001 From: ThePhD Date: Tue, 13 Jun 2017 16:34:18 -0400 Subject: [PATCH] new checker for unique_usertype to ensure type safety, when SOL_CHECK_ARGUMENTS or a protected tag is used to protect a function --- single/sol/sol.hpp | 38 ++++++++++++++++++++++++++++++-------- sol/call.hpp | 13 ++++++++++--- sol/stack_check.hpp | 21 ++++++++++++++++++--- test_functions.cpp | 34 ++++++++++++++++++++++++++++++++++ 4 files changed, 92 insertions(+), 14 deletions(-) diff --git a/single/sol/sol.hpp b/single/sol/sol.hpp index 5018e42d..a349ea9d 100644 --- a/single/sol/sol.hpp +++ b/single/sol/sol.hpp @@ -20,8 +20,8 @@ // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // This file was generated with a script. -// Generated 2017-06-12 14:43:06.223161 UTC -// This header was generated with sol v2.17.5 (revision 50935ae) +// Generated 2017-06-13 20:34:08.313723 UTC +// This header was generated with sol v2.17.5 (revision 51a03b2) // https://github.com/ThePhD/sol2 #ifndef SOL_SINGLE_INCLUDE_HPP @@ -5482,11 +5482,26 @@ namespace sol { } }; - template - struct checker::value>> { + template + struct checker::value>> { + typedef typename unique_usertype_traits::type T; template static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { - return checker::type, type::userdata>{}.check(L, index, std::forward(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>(L, metatableindex)) + return true; + lua_pop(L, 1); + handler(L, index, type::userdata, indextype); + return false; } }; @@ -8213,7 +8228,7 @@ namespace sol { template inline int overload_match_arity(types, std::index_sequence, std::index_sequence, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { - typedef lua_bind_traits> traits; + typedef lua_bind_traits> traits; typedef meta::tuple_types return_types; typedef typename traits::free_args_list args_list; // compile-time eliminate any functions that we know ahead of time are of improper arity @@ -8237,7 +8252,7 @@ namespace sol { template inline int overload_match_arity_single(types, std::index_sequence, std::index_sequence, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { - typedef lua_bind_traits> traits; + typedef lua_bind_traits> traits; typedef meta::tuple_types return_types; typedef typename traits::free_args_list args_list; // compile-time eliminate any functions that we know ahead of time are of improper arity @@ -8252,7 +8267,7 @@ namespace sol { template inline int overload_match_arity_single(types, std::index_sequence, std::index_sequence, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { - typedef lua_bind_traits> traits; + typedef lua_bind_traits> traits; typedef meta::tuple_types return_types; typedef typename traits::free_args_list args_list; // compile-time eliminate any functions that we know ahead of time are of improper arity @@ -8400,6 +8415,13 @@ namespace sol { } }; + template + struct agnostic_lua_call_wrapper, is_index, is_variable, checked, boost, C> { + static int call(lua_State* L, std::reference_wrapper f) { + return agnostic_lua_call_wrapper{}.call(L, f.get()); + } + }; + template struct lua_call_wrapper : agnostic_lua_call_wrapper {}; diff --git a/sol/call.hpp b/sol/call.hpp index 2257a6de..d68ee80e 100644 --- a/sol/call.hpp +++ b/sol/call.hpp @@ -75,7 +75,7 @@ namespace sol { template inline int overload_match_arity(types, std::index_sequence, std::index_sequence, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { - typedef lua_bind_traits> traits; + typedef lua_bind_traits> traits; typedef meta::tuple_types return_types; typedef typename traits::free_args_list args_list; // compile-time eliminate any functions that we know ahead of time are of improper arity @@ -99,7 +99,7 @@ namespace sol { template inline int overload_match_arity_single(types, std::index_sequence, std::index_sequence, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { - typedef lua_bind_traits> traits; + typedef lua_bind_traits> traits; typedef meta::tuple_types return_types; typedef typename traits::free_args_list args_list; // compile-time eliminate any functions that we know ahead of time are of improper arity @@ -114,7 +114,7 @@ namespace sol { template inline int overload_match_arity_single(types, std::index_sequence, std::index_sequence, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { - typedef lua_bind_traits> traits; + typedef lua_bind_traits> traits; typedef meta::tuple_types return_types; typedef typename traits::free_args_list args_list; // compile-time eliminate any functions that we know ahead of time are of improper arity @@ -262,6 +262,13 @@ namespace sol { } }; + template + struct agnostic_lua_call_wrapper, is_index, is_variable, checked, boost, C> { + static int call(lua_State* L, std::reference_wrapper f) { + return agnostic_lua_call_wrapper{}.call(L, f.get()); + } + }; + template struct lua_call_wrapper : agnostic_lua_call_wrapper {}; diff --git a/sol/stack_check.hpp b/sol/stack_check.hpp index 4fe575aa..b92bca89 100644 --- a/sol/stack_check.hpp +++ b/sol/stack_check.hpp @@ -414,11 +414,26 @@ namespace sol { } }; - template - struct checker::value>> { + template + struct checker::value>> { + typedef typename unique_usertype_traits::type T; template static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { - return checker::type, type::userdata>{}.check(L, index, std::forward(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>(L, metatableindex)) + return true; + lua_pop(L, 1); + handler(L, index, type::userdata, indextype); + return false; } }; diff --git a/test_functions.cpp b/test_functions.cpp index 18cbcfe7..aa287a97 100644 --- a/test_functions.cpp +++ b/test_functions.cpp @@ -1135,3 +1135,37 @@ TEST_CASE("functions/set_function-already-wrapped", "setting a function returned 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& 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(); + 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)"); + }()); +}