From 1a6937e24e48ebe00d04fda4d81a144861f77378 Mon Sep 17 00:00:00 2001 From: ThePhD Date: Fri, 30 Jun 2017 18:18:25 -0400 Subject: [PATCH] Revert previous change of not pushing `nil` when we encounter a `nullptr` from special usertypes. If people want to check, they'll need to use optional or a raw pointer: messing with the raw usertype can also lead to some surprising problems, so we don't need to specialize for that use case. --- single/sol/sol.hpp | 9 ++- sol/stack_push.hpp | 3 + test_functions.cpp | 166 ++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 174 insertions(+), 4 deletions(-) diff --git a/single/sol/sol.hpp b/single/sol/sol.hpp index ad1296e9..a2295247 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-26 14:10:10.059447 UTC -// This header was generated with sol v2.17.5 (revision 13370e7) +// Generated 2017-06-30 22:15:33.363723 UTC +// This header was generated with sol v2.17.5 (revision 874a14f) // https://github.com/ThePhD/sol2 #ifndef SOL_SINGLE_INCLUDE_HPP @@ -1614,7 +1614,7 @@ inline int luaL_fileresult(lua_State *L, int stat, const char *fname) { } else { char buf[1024]; -#if defined(__GLIBC__) || defined(_POSIX_VERSION) +#if defined(__GLIBC__) || defined(_POSIX_VERSION) || defined(__APPLE__) strerror_r(en, buf, 1024); #else strerror_s(buf, 1024, en); @@ -6679,6 +6679,9 @@ namespace sol { template >> = meta::enabler> static int push(lua_State* L, Arg&& arg) { + if (unique_usertype_traits::is_null(arg)) { + return stack::push(L, lua_nil); + } return push_deep(L, std::forward(arg)); } diff --git a/sol/stack_push.hpp b/sol/stack_push.hpp index ff65749b..a974bc69 100644 --- a/sol/stack_push.hpp +++ b/sol/stack_push.hpp @@ -143,6 +143,9 @@ namespace sol { template >> = meta::enabler> static int push(lua_State* L, Arg&& arg) { + if (unique_usertype_traits::is_null(arg)) { + return stack::push(L, lua_nil); + } return push_deep(L, std::forward(arg)); } diff --git a/test_functions.cpp b/test_functions.cpp index 226af14f..ebffb83b 100644 --- a/test_functions.cpp +++ b/test_functions.cpp @@ -1140,7 +1140,171 @@ TEST_CASE("functions/set_function-already-wrapped", "setting a function returned } } -TEST_CASE("functions/unique-overloading", "make sure overloading can work with ptr vs. specifically asking for a unique usertype") { +TEST_CASE("functions/pointer-nil", "ensure specific semantics for handling pointer-nils passed through sol") { + struct nil_test { + + static void f(nil_test* p) { + REQUIRE(p == nullptr); + } + static void g(std::unique_ptr& p) { + REQUIRE(p == nullptr); + } + static void h(std::shared_ptr& p) { + REQUIRE(p == nullptr); + } + }; + + std::shared_ptr sptr; + std::unique_ptr uptr; + std::unique_ptr ruptr; + nil_test* rptr = ruptr.get(); + nil_test* vptr = nullptr; + + SECTION("ptr") { + sol::state lua; + lua["v1"] = sptr; + lua["v2"] = std::unique_ptr(); + lua["v3"] = rptr; + lua["v4"] = vptr; + + REQUIRE_NOTHROW([&]() { + nil_test* v1 = lua["v1"]; + nil_test* v2 = lua["v2"]; + nil_test* v3 = lua["v3"]; + nil_test* v4 = lua["v4"]; + REQUIRE(v1 == sptr.get()); + REQUIRE(v1 == nullptr); + REQUIRE(v2 == uptr.get()); + REQUIRE(v2 == nullptr); + REQUIRE(v3 == rptr); + REQUIRE(v3 == nullptr); + REQUIRE(v4 == vptr); + REQUIRE(v4 == nullptr); + }()); + } + SECTION("ptr") { + sol::state lua; + lua.open_libraries(); + + lua["v1"] = sptr; + lua["v2"] = std::unique_ptr(); + lua["v3"] = rptr; + lua["v4"] = vptr; + lua["f"] = &nil_test::f; + lua["g"] = &nil_test::g; + lua["h"] = &nil_test::h; + + REQUIRE_NOTHROW([&]() { + lua.script("f(v1)"); + lua.script("f(v2)"); + lua.script("f(v3)"); + lua.script("f(v4)"); + + lua.script("assert(v1 == nil)"); + lua.script("assert(v2 == nil)"); + lua.script("assert(v3 == nil)"); + lua.script("assert(v4 == nil)"); + }()); + } + SECTION("throw unique argument") { + sol::state lua; + lua["v2"] = std::unique_ptr(); + lua["g"] = &nil_test::g; + + REQUIRE_THROWS([&]() { + lua.script("g(v2)"); + }()); + } + SECTION("throw shared argument") { + sol::state lua; + lua["v1"] = sptr; + lua["h"] = &nil_test::h; + + REQUIRE_THROWS([&]() { + lua.script("h(v1)"); + }()); + } + SECTION("throw ref") { + REQUIRE_THROWS([&]() { + sol::state lua; + lua["v1"] = sptr; + nil_test& v1 = lua["v1"]; + (void)(&v1 == sptr.get()); + }()); + REQUIRE_THROWS([&]() { + sol::state lua; + lua["v2"] = std::unique_ptr(); + nil_test& v2 = lua["v2"]; + (void)(&v2 == uptr.get()); + }()); + REQUIRE_THROWS([&]() { + sol::state lua; + lua["v3"] = rptr; + nil_test& v3 = lua["v3"]; + (void)(&v3 == rptr); + }()); + REQUIRE_THROWS([&]() { + sol::state lua; + lua["v4"] = vptr; + nil_test& v4 = lua["v4"]; + (void)(&v4 == vptr); + }()); + } + SECTION("throw unique") { + REQUIRE_THROWS([&]() { + sol::state lua; + lua["v1"] = sptr; + std::unique_ptr& v1 = lua["v1"]; + (void)(v1.get() == sptr.get()); + }()); + REQUIRE_THROWS([&]() { + sol::state lua; + lua["v2"] = std::unique_ptr(); + std::unique_ptr& v2 = lua["v2"]; + (void)(v2.get() == uptr.get()); + }()); + REQUIRE_THROWS([&]() { + sol::state lua; + lua["v3"] = rptr; + std::unique_ptr& v3 = lua["v3"]; + (void)(v3.get() == rptr); + }()); + REQUIRE_THROWS([&]() { + sol::state lua; + lua["v4"] = vptr; + std::unique_ptr& v4 = lua["v4"]; + (void)(v4.get() == vptr); + }()); + } + SECTION("throw shared") { + REQUIRE_THROWS([&]() { + sol::state lua; + lua["v1"] = sptr; + std::shared_ptr& v1 = lua["v1"]; + (void)(v1.get() == sptr.get()); + }()); + REQUIRE_THROWS([&]() { + sol::state lua; + lua["v2"] = std::unique_ptr(); + std::shared_ptr& v2 = lua["v2"]; + (void)(v2.get() == uptr.get()); + }()); + REQUIRE_THROWS([&]() { + sol::state lua; + lua["v3"] = rptr; + std::shared_ptr& v3 = lua["v3"]; + (void)(v3.get() == rptr); + }()); + REQUIRE_THROWS([&]() { + sol::state lua; + lua["v4"] = vptr; + std::shared_ptr& v4 = lua["v4"]; + (void)(v4.get() == vptr); + }()); + } +} + +TEST_CASE("functions/unique_usertype-overloading", "make sure overloading can work with ptr vs. specifically asking for a unique_usertype") { struct test { int special_value = 17; test() : special_value(17) {}