From 11916a7c72dbfd569df800899e9fb8333827a17c Mon Sep 17 00:00:00 2001 From: ThePhD Date: Fri, 16 Jun 2017 18:43:40 -0400 Subject: [PATCH] add noexcept function type barriers and guards noexcept-proof function call trampolines add noexcept tests to ensure its being checked TODO: check g++ 7.1 builds when using -std=c++17 ... --- single/sol/sol.hpp | 287 +++++++++++++++++++++++++++---- sol/bind_traits.hpp | 120 ++++++------- sol/compatibility/version.hpp | 6 + sol/function_types.hpp | 18 +- sol/function_types_stateful.hpp | 6 +- sol/function_types_templated.hpp | 35 +++- sol/stack_push.hpp | 17 ++ sol/types.hpp | 30 +++- sol/wrapper.hpp | 4 +- test_functions.cpp | 57 +++++- test_usertypes.cpp | 26 ++- 11 files changed, 485 insertions(+), 121 deletions(-) diff --git a/single/sol/sol.hpp b/single/sol/sol.hpp index 775e7bc7..2f2121f8 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-15 05:24:30.745677 UTC -// This header was generated with sol v2.17.5 (revision 0fb5333) +// Generated 2017-06-16 19:36:12.857631 UTC +// This header was generated with sol v2.17.5 (revision 39fdb5e) // https://github.com/ThePhD/sol2 #ifndef SOL_SINGLE_INCLUDE_HPP @@ -47,9 +47,6 @@ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wshadow" #pragma GCC diagnostic ignored "-Wconversion" -#if __GNUC__ > 6 -#pragma GCC diagnostic ignored "-Wnoexcept-type" -#endif #elif defined _MSC_VER #pragma warning( push ) #pragma warning( disable : 4324 ) // structure was padded due to alignment specifier @@ -193,12 +190,13 @@ namespace sol { template using void_tuple_element_t = typename void_tuple_element::type; - template + template struct basic_traits { private: typedef std::conditional_t::value, int, T>& first_type; public: + static const bool is_noexcept = it_is_noexcept; static const bool is_member_function = std::is_void::value; static const bool has_c_var_arg = has_c_variadic; static const std::size_t arity = sizeof...(Args); @@ -218,123 +216,238 @@ namespace sol { }; template::value> - struct fx_traits : basic_traits {}; + struct fx_traits : basic_traits {}; // Free Functions template - struct fx_traits : basic_traits { + struct fx_traits : basic_traits { typedef R(*function_pointer_type)(Args...); }; template - struct fx_traits : basic_traits { + struct fx_traits : basic_traits { typedef R(*function_pointer_type)(Args...); }; template - struct fx_traits : basic_traits { + struct fx_traits : basic_traits { typedef R(*function_pointer_type)(Args..., ...); }; template - struct fx_traits : basic_traits { + struct fx_traits : basic_traits { typedef R(*function_pointer_type)(Args..., ...); }; // Member Functions /* C-Style Variadics */ template - struct fx_traits : basic_traits { + struct fx_traits : basic_traits { typedef R(T::* function_pointer_type)(Args...); }; template - struct fx_traits : basic_traits { + struct fx_traits : basic_traits { typedef R(T::* function_pointer_type)(Args..., ...); }; /* Const Volatile */ template - struct fx_traits : basic_traits { + struct fx_traits : basic_traits { typedef R(T::* function_pointer_type)(Args...) const; }; template - struct fx_traits : basic_traits { + struct fx_traits : basic_traits { typedef R(T::* function_pointer_type)(Args..., ...) const; }; template - struct fx_traits : basic_traits { + struct fx_traits : basic_traits { typedef R(T::* function_pointer_type)(Args...) const volatile; }; template - struct fx_traits : basic_traits { + struct fx_traits : basic_traits { typedef R(T::* function_pointer_type)(Args..., ...) const volatile; }; /* Member Function Qualifiers */ template - struct fx_traits : basic_traits { + struct fx_traits : basic_traits { typedef R(T::* function_pointer_type)(Args...) &; }; template - struct fx_traits : basic_traits { + struct fx_traits : basic_traits { typedef R(T::* function_pointer_type)(Args..., ...) &; }; template - struct fx_traits : basic_traits { + struct fx_traits : basic_traits { typedef R(T::* function_pointer_type)(Args...) const &; }; template - struct fx_traits : basic_traits { + struct fx_traits : basic_traits { typedef R(T::* function_pointer_type)(Args..., ...) const &; }; template - struct fx_traits : basic_traits { + struct fx_traits : basic_traits { typedef R(T::* function_pointer_type)(Args...) const volatile &; }; template - struct fx_traits : basic_traits { + struct fx_traits : basic_traits { typedef R(T::* function_pointer_type)(Args..., ...) const volatile &; }; template - struct fx_traits : basic_traits { + struct fx_traits : basic_traits { typedef R(T::* function_pointer_type)(Args...) && ; }; template - struct fx_traits : basic_traits { + struct fx_traits : basic_traits { typedef R(T::* function_pointer_type)(Args..., ...) && ; }; template - struct fx_traits : basic_traits { + struct fx_traits : basic_traits { typedef R(T::* function_pointer_type)(Args...) const &&; }; template - struct fx_traits : basic_traits { + struct fx_traits : basic_traits { typedef R(T::* function_pointer_type)(Args..., ...) const &&; }; template - struct fx_traits : basic_traits { + struct fx_traits : basic_traits { typedef R(T::* function_pointer_type)(Args...) const volatile &&; }; template - struct fx_traits : basic_traits { + struct fx_traits : basic_traits { typedef R(T::* function_pointer_type)(Args..., ...) const volatile &&; }; +#ifdef SOL_NOEXCEPT_FUNCTION_TYPE + + template + struct fx_traits : basic_traits { + typedef R(*function_pointer_type)(Args...); + }; + + template + struct fx_traits : basic_traits { + typedef R(*function_pointer_type)(Args...); + }; + + template + struct fx_traits : basic_traits { + typedef R(*function_pointer_type)(Args..., ...); + }; + + template + struct fx_traits : basic_traits { + typedef R(*function_pointer_type)(Args..., ...); + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args...); + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args..., ...); + }; + + /* Const Volatile */ + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args...) const; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args..., ...) const; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args...) const volatile; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args..., ...) const volatile; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args...) &; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args..., ...) &; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args...) const &; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args..., ...) const &; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args...) const volatile &; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args..., ...) const volatile &; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args...) && ; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args..., ...) && ; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args...) const &&; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args..., ...) const &&; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args...) const volatile &&; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args..., ...) const volatile &&; + }; + +#endif // noexcept is part of a function's type + template struct fx_traits : fx_traits::function_type, false> {}; @@ -348,6 +461,7 @@ namespace sol { typedef R Arg; typedef T object_type; using signature_type = R(T::*); + static const bool is_noexcept = false; static const bool is_member_function = false; static const std::size_t arity = 1; static const std::size_t free_arity = 2; @@ -362,6 +476,7 @@ namespace sol { template using arg_at = void_tuple_element_t; }; + } // meta_detail template @@ -823,6 +938,12 @@ namespace sol { #include #endif // C++ Mangling for Lua +#if defined(__cpp_noexcept_function_type) && (__cpp_noexcept_function_type >= 201510L) +#ifndef SOL_NOEXCEPT_FUNCTION_TYPE +#define SOL_NOEXCEPT_FUNCTION_TYPE 1 +#endif // noexcept is part of a function's type +#endif + #if defined(_WIN32) || defined(_MSC_VER) #ifndef SOL_CODECVT_SUPPORT #define SOL_CODECVT_SUPPORT 1 @@ -3045,6 +3166,10 @@ namespace sol { namespace sol { namespace detail { +#ifdef SOL_NOEXCEPT_FUNCTION_TYPE + typedef int(*lua_CFunction_noexcept) (lua_State *L) noexcept; +#endif // noexcept function type for lua_CFunction + #ifdef SOL_NO_EXCEPTIONS template int static_trampoline(lua_State* L) { @@ -3080,8 +3205,33 @@ namespace sol { return lua_error(L); } +#ifdef SOL_NOEXCEPT_FUNCTION_TYPE + template + int static_trampoline(lua_State* L) { + try { + return f(L); + } + catch (const char *s) { + lua_pushstring(L, s); + } + catch (const std::exception& e) { + lua_pushstring(L, e.what()); + } +#if !defined(SOL_EXCEPTIONS_SAFE_PROPAGATION) + catch (...) { + std::exception_ptr eptr = std::current_exception(); + lua_pushstring(L, "caught (...) exception"); + } +#endif + return lua_error(L); + } +#endif // noexcept lua_CFunction type + template int trampoline(lua_State* L, Fx&& f, Args&&... args) { + if (meta::bind_traits>::is_noexcept) { + return f(L, std::forward(args)...); + } try { return f(L, std::forward(args)...); } @@ -8032,6 +8182,85 @@ namespace sol { }; +#ifdef SOL_NOEXCEPT_FUNCTION_TYPE //noexcept has become a part of a function's type + + template + struct wrapper : public member_function_wrapper { + + }; + + template + struct wrapper : public member_function_wrapper { + + }; + + template + struct wrapper : public member_function_wrapper { + + }; + + template + struct wrapper : public member_function_wrapper { + + }; + + template + struct wrapper : public member_function_wrapper { + + }; + + template + struct wrapper : public member_function_wrapper { + + }; + + template + struct wrapper : public member_function_wrapper { + + }; + + template + struct wrapper : public member_function_wrapper { + + }; + + template + struct wrapper : public member_function_wrapper { + + }; + + template + struct wrapper : public member_function_wrapper { + + }; + + template + struct wrapper : public member_function_wrapper { + + }; + + template + struct wrapper : public member_function_wrapper { + + }; + + template + struct wrapper : public member_function_wrapper { + + }; + + template + struct wrapper : public member_function_wrapper { + + }; + + template + struct wrapper : public member_function_wrapper { + + }; + +#endif // noexcept is part of a function's type + } // sol // end of sol/wrapper.hpp diff --git a/sol/bind_traits.hpp b/sol/bind_traits.hpp index b2d2d7c9..5cfb83ca 100644 --- a/sol/bind_traits.hpp +++ b/sol/bind_traits.hpp @@ -103,30 +103,6 @@ namespace sol { typedef R(*function_pointer_type)(Args..., ...); }; -#if __cpp_noexcept_function_type >= 201510L //noexcept has become a part of a function's type - - template - struct fx_traits : basic_traits { - typedef R(*function_pointer_type)(Args...); - }; - - template - struct fx_traits : basic_traits { - typedef R(*function_pointer_type)(Args...); - }; - - template - struct fx_traits : basic_traits { - typedef R(*function_pointer_type)(Args..., ...); - }; - - template - struct fx_traits : basic_traits { - typedef R(*function_pointer_type)(Args..., ...); - }; - -#endif//#if __cpp_noexcept_function_type >= 201510L //noexcept has become a part of a function's type - // Member Functions /* C-Style Variadics */ template @@ -139,20 +115,6 @@ namespace sol { typedef R(T::* function_pointer_type)(Args..., ...); }; -#if __cpp_noexcept_function_type >= 201510L //noexcept has become a part of a function's type - - template - struct fx_traits : basic_traits { - typedef R(T::* function_pointer_type)(Args...); - }; - - template - struct fx_traits : basic_traits { - typedef R(T::* function_pointer_type)(Args..., ...); - }; - -#endif//#if __cpp_noexcept_function_type >= 201510L //noexcept has become a part of a function's type - /* Const Volatile */ template struct fx_traits : basic_traits { @@ -174,31 +136,6 @@ namespace sol { typedef R(T::* function_pointer_type)(Args..., ...) const volatile; }; -#if __cpp_noexcept_function_type >= 201510L //noexcept has become a part of a function's type - - /* Const Volatile */ - template - struct fx_traits : basic_traits { - typedef R(T::* function_pointer_type)(Args...) const; - }; - - template - struct fx_traits : basic_traits { - typedef R(T::* function_pointer_type)(Args..., ...) const; - }; - - template - struct fx_traits : basic_traits { - typedef R(T::* function_pointer_type)(Args...) const volatile; - }; - - template - struct fx_traits : basic_traits { - typedef R(T::* function_pointer_type)(Args..., ...) const volatile; - }; - -#endif//#if __cpp_noexcept_function_type >= 201510L //noexcept has become a part of a function's type - /* Member Function Qualifiers */ template struct fx_traits : basic_traits { @@ -260,7 +197,58 @@ namespace sol { typedef R(T::* function_pointer_type)(Args..., ...) const volatile &&; }; -#if __cpp_noexcept_function_type >= 201510L //noexcept has become a part of a function's type +#ifdef SOL_NOEXCEPT_FUNCTION_TYPE + + template + struct fx_traits : basic_traits { + typedef R(*function_pointer_type)(Args...); + }; + + template + struct fx_traits : basic_traits { + typedef R(*function_pointer_type)(Args...); + }; + + template + struct fx_traits : basic_traits { + typedef R(*function_pointer_type)(Args..., ...); + }; + + template + struct fx_traits : basic_traits { + typedef R(*function_pointer_type)(Args..., ...); + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args...); + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args..., ...); + }; + + /* Const Volatile */ + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args...) const; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args..., ...) const; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args...) const volatile; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args..., ...) const volatile; + }; template struct fx_traits : basic_traits { @@ -322,7 +310,7 @@ namespace sol { typedef R(T::* function_pointer_type)(Args..., ...) const volatile &&; }; -#endif//#if __cpp_noexcept_function_type >= 201510L //noexcept has become a part of a function's type +#endif // noexcept is part of a function's type template struct fx_traits : fx_traits::function_type, false> {}; @@ -337,6 +325,7 @@ namespace sol { typedef R Arg; typedef T object_type; using signature_type = R(T::*); + static const bool is_noexcept = false; static const bool is_member_function = false; static const std::size_t arity = 1; static const std::size_t free_arity = 2; @@ -351,6 +340,7 @@ namespace sol { template using arg_at = void_tuple_element_t; }; + } // meta_detail template diff --git a/sol/compatibility/version.hpp b/sol/compatibility/version.hpp index 2153488d..cb25ae1d 100644 --- a/sol/compatibility/version.hpp +++ b/sol/compatibility/version.hpp @@ -30,6 +30,12 @@ #include #endif // C++ Mangling for Lua +#if defined(__cpp_noexcept_function_type) && (__cpp_noexcept_function_type >= 201510L) +#ifndef SOL_NOEXCEPT_FUNCTION_TYPE +#define SOL_NOEXCEPT_FUNCTION_TYPE 1 +#endif // noexcept is part of a function's type +#endif + #if defined(_WIN32) || defined(_MSC_VER) #ifndef SOL_CODECVT_SUPPORT #define SOL_CODECVT_SUPPORT 1 diff --git a/sol/function_types.hpp b/sol/function_types.hpp index 8a6c76d0..9a3c368d 100644 --- a/sol/function_types.hpp +++ b/sol/function_types.hpp @@ -190,9 +190,15 @@ namespace sol { stack::push(L, f); } +#ifdef SOL_NOEXCEPT_FUNCTION_TYPE + static void select_function(std::true_type, lua_State* L, detail::lua_CFunction_noexcept f) { + stack::push(L, f); + } +#endif // noexcept function type + template >, std::is_base_of>>> = meta::enabler> static void select(lua_State* L, Fx&& fx, Args&&... args) { - select_function(std::is_function>(), L, std::forward(fx), std::forward(args)...); + select_function(std::is_function>>(), L, std::forward(fx), std::forward(args)...); } template >, std::is_base_of>>> = meta::enabler> @@ -254,7 +260,15 @@ namespace sol { }; template - struct pusher, meta::neg>, meta::neg>>>::value>> { + struct pusher, + meta::neg>, + meta::neg>> +#ifdef SOL_NOEXCEPT_FUNCTION_TYPE + , meta::neg>, + meta::neg>> +#endif // noexcept function types + >::value>> { template static int push(lua_State* L, F&& f) { return pusher>{}.push(L, std::forward(f)); diff --git a/sol/function_types_stateful.hpp b/sol/function_types_stateful.hpp index ab5c7f10..f5fc5dbc 100644 --- a/sol/function_types_stateful.hpp +++ b/sol/function_types_stateful.hpp @@ -28,11 +28,11 @@ namespace sol { namespace function_detail { template struct functor_function { - typedef meta::unwrapped_t> Function; - Function fx; + typedef std::decay_t> function_type; + function_type fx; template - functor_function(Function f, Args&&... args) : fx(std::move(f), std::forward(args)...) {} + functor_function(function_type f, Args&&... args) : fx(std::move(f), std::forward(args)...) {} int call(lua_State* L) { return call_detail::call_wrapped(L, fx); diff --git a/sol/function_types_templated.hpp b/sol/function_types_templated.hpp index b065c505..533ea359 100644 --- a/sol/function_types_templated.hpp +++ b/sol/function_types_templated.hpp @@ -84,7 +84,7 @@ namespace sol { } template - int call_wrapper_entry(lua_State* L) { + int call_wrapper_entry(lua_State* L) noexcept(meta::bind_traits::is_noexcept) { return call_wrapper_function(std::is_member_function_pointer>(), L); } @@ -97,15 +97,38 @@ namespace sol { } }; + template + inline int c_call_raw(std::true_type, lua_State* L) { +#ifdef __clang__ + return detail::trampoline(L, fx); +#else +#ifdef SOL_NOEXCEPT_FUNCTION_TYPE + return meta::bind_traits::is_noexcept ? detail::static_trampoline_noexcept(L) : detail::static_trampoline(L); +#else + return detail::static_trampoline(L); +#endif +#endif // fuck you clang :c + } + + template + inline int c_call_raw(std::false_type, lua_State* L) { +#ifdef __clang__ + return detail::trampoline(L, function_detail::call_wrapper_entry); +#else + return detail::static_trampoline<(&function_detail::call_wrapper_entry)>(L); +#endif // fuck you clang :c + } + } // function_detail template inline int c_call(lua_State* L) { -#ifdef __clang__ - return detail::trampoline(L, function_detail::call_wrapper_entry); -#else - return detail::static_trampoline<(&function_detail::call_wrapper_entry)>(L); -#endif // fuck you clang :c + typedef meta::unqualified_t Fu; + return function_detail::c_call_raw(std::integral_constant::value +#ifdef SOL_NOEXCEPT_FUNCTION_TYPE + || std::is_same::value +#endif + >(), L); } template diff --git a/sol/stack_push.hpp b/sol/stack_push.hpp index caafceda..ff65749b 100644 --- a/sol/stack_push.hpp +++ b/sol/stack_push.hpp @@ -310,6 +310,23 @@ namespace sol { return 1; } }; +#ifdef SOL_NOEXCEPT_FUNCTION_TYPE + template<> + struct pusher> { + static int push(lua_State* L, detail::lua_CFunction_noexcept func, int n = 0) { + lua_pushcclosure(L, func, n); + return 1; + } + }; + + template<> + struct pusher { + static int push(lua_State* L, detail::lua_CFunction_noexcept func, int n = 0) { + lua_pushcclosure(L, func, n); + return 1; + } + }; +#endif // noexcept function type template<> struct pusher { diff --git a/sol/types.hpp b/sol/types.hpp index 6427a39c..896da0aa 100644 --- a/sol/types.hpp +++ b/sol/types.hpp @@ -31,18 +31,22 @@ namespace sol { namespace detail { +#ifdef SOL_NOEXCEPT_FUNCTION_TYPE + typedef int(*lua_CFunction_noexcept) (lua_State *L) noexcept; +#endif // noexcept function type for lua_CFunction + #ifdef SOL_NO_EXCEPTIONS template - int static_trampoline(lua_State* L) { + int static_trampoline(lua_State* L) noexcept { return f(L); } template - int trampoline(lua_State* L, Fx&& f, Args&&... args) { + int trampoline(lua_State* L, Fx&& f, Args&&... args) noexcept { return f(L, std::forward(args)...); } - inline int c_trampoline(lua_State* L, lua_CFunction f) { + inline int c_trampoline(lua_State* L, lua_CFunction f) noexcept { return trampoline(L, f); } #else @@ -59,15 +63,33 @@ namespace sol { } #if !defined(SOL_EXCEPTIONS_SAFE_PROPAGATION) catch (...) { - std::exception_ptr eptr = std::current_exception(); lua_pushstring(L, "caught (...) exception"); } #endif return lua_error(L); } +#ifdef SOL_NOEXCEPT_FUNCTION_TYPE +#if 0 +// impossible: g++/clang++ choke as they think this function is ambiguous: +// to fix, wait for template and then switch on no-exceptness of the function + template + int static_trampoline(lua_State* L) noexcept { +#else + template + int static_trampoline_noexcept(lua_State* L) noexcept { +#endif // impossible + std::cout << "[STATIC_TRAMPOLINE] HEY A NOEXCEPTION FUNCTION IS GONNA BE CALLED" << std::endl; + return f(L); + } +#endif // noexcept lua_CFunction type + template int trampoline(lua_State* L, Fx&& f, Args&&... args) { + if (meta::bind_traits>::is_noexcept) { + std::cout << "[TRAMPOLINE] HEY A NOEXCEPTION FUNCTION IS GONNA BE CALLED" << std::endl; + return f(L, std::forward(args)...); + } try { return f(L, std::forward(args)...); } diff --git a/sol/wrapper.hpp b/sol/wrapper.hpp index a41ad028..712c0f36 100644 --- a/sol/wrapper.hpp +++ b/sol/wrapper.hpp @@ -233,7 +233,7 @@ namespace sol { }; -#if __cpp_noexcept_function_type >= 201510L //noexcept has become a part of a function's type +#ifdef SOL_NOEXCEPT_FUNCTION_TYPE //noexcept has become a part of a function's type template struct wrapper : public member_function_wrapper { @@ -310,7 +310,7 @@ namespace sol { }; -#endif//#if __cpp_noexcept_function_type >= 201510L //noexcept has become a part of a function's type +#endif // noexcept is part of a function's type } // sol diff --git a/test_functions.cpp b/test_functions.cpp index d1c85bfd..63acbbbc 100644 --- a/test_functions.cpp +++ b/test_functions.cpp @@ -99,8 +99,9 @@ struct fer { } }; -inline void noexcept_function() noexcept {} -struct type_with_noexcept_method{ void noexcept_method() noexcept {} }; +static int raw_noexcept_function(lua_State* L) noexcept { + return sol::stack::push(L, 0x63); +} TEST_CASE("functions/tuple-returns", "Make sure tuple returns are ordered properly") { sol::state lua; @@ -1226,9 +1227,53 @@ TEST_CASE("functions/unique-overloading", "make sure overloading can work with p }; } -TEST_CASE("functions/noexcept", "allow noexcept free - and member functions in Lua") { - sol::state lua; +TEST_CASE("functions/noexcept", "allow noexcept functions to be serialized properly into Lua using sol2") { + struct T { + static int noexcept_function() noexcept { + return 0x61; + } - lua.set_function("noexcept_function", &noexcept_function); - lua.set_function("noexcept_member_function", &type_with_noexcept_method::noexcept_method); + int noexcept_method() noexcept { + return 0x62; + } + } t; + + lua_CFunction ccall = sol::c_call; + + sol::state lua; + + lua.set_function("f", &T::noexcept_function); + lua.set_function("g", &T::noexcept_method); + lua.set_function("h", &T::noexcept_method, T()); + lua.set_function("i", &T::noexcept_method, std::ref(t)); + lua.set_function("j", &T::noexcept_method, &t); + lua.set_function("k", &T::noexcept_method, t); + lua.set_function("l", &raw_noexcept_function); + lua.set_function("m", ccall); + + lua["t"] = T(); + lua.script("v1 = f()"); + lua.script("v2 = g(t)"); + lua.script("v3 = h()"); + lua.script("v4 = i()"); + lua.script("v5 = j()"); + lua.script("v6 = k()"); + lua.script("v7 = l()"); + lua.script("v8 = m()"); + int v1 = lua["v1"]; + int v2 = lua["v2"]; + int v3 = lua["v3"]; + int v4 = lua["v4"]; + int v5 = lua["v5"]; + int v6 = lua["v6"]; + int v7 = lua["v7"]; + int v8 = lua["v8"]; + REQUIRE(v1 == 0x61); + REQUIRE(v2 == 0x62); + REQUIRE(v3 == 0x62); + REQUIRE(v4 == 0x62); + REQUIRE(v5 == 0x62); + REQUIRE(v6 == 0x62); + REQUIRE(v7 == 0x63); + REQUIRE(v8 == 0x63); } diff --git a/test_usertypes.cpp b/test_usertypes.cpp index 6bab97a2..3092b613 100644 --- a/test_usertypes.cpp +++ b/test_usertypes.cpp @@ -265,9 +265,6 @@ struct matrix_xi { } }; -inline void noexcept_function() noexcept {} -struct type_with_noexcept_method{ void noexcept_method() noexcept {} }; - TEST_CASE("usertype/usertype", "Show that we can create classes from usertype and use them") { sol::state lua; @@ -1814,6 +1811,27 @@ TEST_CASE("usertype/meta-key-retrievals", "allow for special meta keys (__index, } TEST_CASE("usertype/noexcept-methods", "make sure noexcept functinos and methods can be bound to usertypes without issues") { + struct T { + static int noexcept_function() noexcept { + return 0x61; + } + + int noexcept_method() noexcept { + return 0x62; + } + }; + sol::state lua; - lua.new_usertype("tmp", "nf", &noexcept_function, "nm", &type_with_noexcept_method::noexcept_method); + lua.new_usertype("T", + "nf", &T::noexcept_function, + "nm", &T::noexcept_method + ); + + lua.script("t = T.new()"); + lua.script("v1 = t.nf()"); + lua.script("v2 = t:nm()"); + int v1 = lua["v1"]; + int v2 = lua["v2"]; + REQUIRE(v1 == 0x61); + REQUIRE(v2 == 0x62); }