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 ...
This commit is contained in:
ThePhD 2017-06-16 18:43:40 -04:00
parent 39fdb5e041
commit 11916a7c72
11 changed files with 485 additions and 121 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-15 05:24:30.745677 UTC // Generated 2017-06-16 19:36:12.857631 UTC
// This header was generated with sol v2.17.5 (revision 0fb5333) // This header was generated with sol v2.17.5 (revision 39fdb5e)
// https://github.com/ThePhD/sol2 // https://github.com/ThePhD/sol2
#ifndef SOL_SINGLE_INCLUDE_HPP #ifndef SOL_SINGLE_INCLUDE_HPP
@ -47,9 +47,6 @@
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wshadow" #pragma GCC diagnostic ignored "-Wshadow"
#pragma GCC diagnostic ignored "-Wconversion" #pragma GCC diagnostic ignored "-Wconversion"
#if __GNUC__ > 6
#pragma GCC diagnostic ignored "-Wnoexcept-type"
#endif
#elif defined _MSC_VER #elif defined _MSC_VER
#pragma warning( push ) #pragma warning( push )
#pragma warning( disable : 4324 ) // structure was padded due to alignment specifier #pragma warning( disable : 4324 ) // structure was padded due to alignment specifier
@ -193,12 +190,13 @@ namespace sol {
template <std::size_t I, typename T> template <std::size_t I, typename T>
using void_tuple_element_t = typename void_tuple_element<I, T>::type; using void_tuple_element_t = typename void_tuple_element<I, T>::type;
template <bool has_c_variadic, typename T, typename R, typename... Args> template <bool it_is_noexcept, bool has_c_variadic, typename T, typename R, typename... Args>
struct basic_traits { struct basic_traits {
private: private:
typedef std::conditional_t<std::is_void<T>::value, int, T>& first_type; typedef std::conditional_t<std::is_void<T>::value, int, T>& first_type;
public: public:
static const bool is_noexcept = it_is_noexcept;
static const bool is_member_function = std::is_void<T>::value; static const bool is_member_function = std::is_void<T>::value;
static const bool has_c_var_arg = has_c_variadic; static const bool has_c_var_arg = has_c_variadic;
static const std::size_t arity = sizeof...(Args); static const std::size_t arity = sizeof...(Args);
@ -218,123 +216,238 @@ namespace sol {
}; };
template<typename Signature, bool b = has_deducible_signature<Signature>::value> template<typename Signature, bool b = has_deducible_signature<Signature>::value>
struct fx_traits : basic_traits<false, void, void> {}; struct fx_traits : basic_traits<false, false, void, void> {};
// Free Functions // Free Functions
template<typename R, typename... Args> template<typename R, typename... Args>
struct fx_traits<R(Args...), false> : basic_traits<false, void, R, Args...> { struct fx_traits<R(Args...), false> : basic_traits<false, false, void, R, Args...> {
typedef R(*function_pointer_type)(Args...); typedef R(*function_pointer_type)(Args...);
}; };
template<typename R, typename... Args> template<typename R, typename... Args>
struct fx_traits<R(*)(Args...), false> : basic_traits<false, void, R, Args...> { struct fx_traits<R(*)(Args...), false> : basic_traits<false, false, void, R, Args...> {
typedef R(*function_pointer_type)(Args...); typedef R(*function_pointer_type)(Args...);
}; };
template<typename R, typename... Args> template<typename R, typename... Args>
struct fx_traits<R(Args..., ...), false> : basic_traits<true, void, R, Args...> { struct fx_traits<R(Args..., ...), false> : basic_traits<false, true, void, R, Args...> {
typedef R(*function_pointer_type)(Args..., ...); typedef R(*function_pointer_type)(Args..., ...);
}; };
template<typename R, typename... Args> template<typename R, typename... Args>
struct fx_traits<R(*)(Args..., ...), false> : basic_traits<true, void, R, Args...> { struct fx_traits<R(*)(Args..., ...), false> : basic_traits<false, true, void, R, Args...> {
typedef R(*function_pointer_type)(Args..., ...); typedef R(*function_pointer_type)(Args..., ...);
}; };
// Member Functions // Member Functions
/* C-Style Variadics */ /* C-Style Variadics */
template<typename T, typename R, typename... Args> template<typename T, typename R, typename... Args>
struct fx_traits<R(T::*)(Args...), false> : basic_traits<false, T, R, Args...> { struct fx_traits<R(T::*)(Args...), false> : basic_traits<false, false, T, R, Args...> {
typedef R(T::* function_pointer_type)(Args...); typedef R(T::* function_pointer_type)(Args...);
}; };
template<typename T, typename R, typename... Args> template<typename T, typename R, typename... Args>
struct fx_traits<R(T::*)(Args..., ...), false> : basic_traits<true, T, R, Args...> { struct fx_traits<R(T::*)(Args..., ...), false> : basic_traits<false, true, T, R, Args...> {
typedef R(T::* function_pointer_type)(Args..., ...); typedef R(T::* function_pointer_type)(Args..., ...);
}; };
/* Const Volatile */ /* Const Volatile */
template<typename T, typename R, typename... Args> template<typename T, typename R, typename... Args>
struct fx_traits<R(T::*)(Args...) const, false> : basic_traits<false, T, R, Args...> { struct fx_traits<R(T::*)(Args...) const, false> : basic_traits<false, false, T, R, Args...> {
typedef R(T::* function_pointer_type)(Args...) const; typedef R(T::* function_pointer_type)(Args...) const;
}; };
template<typename T, typename R, typename... Args> template<typename T, typename R, typename... Args>
struct fx_traits<R(T::*)(Args..., ...) const, false> : basic_traits<true, T, R, Args...> { struct fx_traits<R(T::*)(Args..., ...) const, false> : basic_traits<false, true, T, R, Args...> {
typedef R(T::* function_pointer_type)(Args..., ...) const; typedef R(T::* function_pointer_type)(Args..., ...) const;
}; };
template<typename T, typename R, typename... Args> template<typename T, typename R, typename... Args>
struct fx_traits<R(T::*)(Args...) const volatile, false> : basic_traits<false, T, R, Args...> { struct fx_traits<R(T::*)(Args...) const volatile, false> : basic_traits<false, false, T, R, Args...> {
typedef R(T::* function_pointer_type)(Args...) const volatile; typedef R(T::* function_pointer_type)(Args...) const volatile;
}; };
template<typename T, typename R, typename... Args> template<typename T, typename R, typename... Args>
struct fx_traits<R(T::*)(Args..., ...) const volatile, false> : basic_traits<true, T, R, Args...> { struct fx_traits<R(T::*)(Args..., ...) const volatile, false> : basic_traits<false, true, T, R, Args...> {
typedef R(T::* function_pointer_type)(Args..., ...) const volatile; typedef R(T::* function_pointer_type)(Args..., ...) const volatile;
}; };
/* Member Function Qualifiers */ /* Member Function Qualifiers */
template<typename T, typename R, typename... Args> template<typename T, typename R, typename... Args>
struct fx_traits<R(T::*)(Args...) &, false> : basic_traits<false, T, R, Args...> { struct fx_traits<R(T::*)(Args...) &, false> : basic_traits<false, false, T, R, Args...> {
typedef R(T::* function_pointer_type)(Args...) &; typedef R(T::* function_pointer_type)(Args...) &;
}; };
template<typename T, typename R, typename... Args> template<typename T, typename R, typename... Args>
struct fx_traits<R(T::*)(Args..., ...) &, false> : basic_traits<true, T, R, Args...> { struct fx_traits<R(T::*)(Args..., ...) &, false> : basic_traits<false, true, T, R, Args...> {
typedef R(T::* function_pointer_type)(Args..., ...) &; typedef R(T::* function_pointer_type)(Args..., ...) &;
}; };
template<typename T, typename R, typename... Args> template<typename T, typename R, typename... Args>
struct fx_traits<R(T::*)(Args...) const &, false> : basic_traits<false, T, R, Args...> { struct fx_traits<R(T::*)(Args...) const &, false> : basic_traits<false, false, T, R, Args...> {
typedef R(T::* function_pointer_type)(Args...) const &; typedef R(T::* function_pointer_type)(Args...) const &;
}; };
template<typename T, typename R, typename... Args> template<typename T, typename R, typename... Args>
struct fx_traits<R(T::*)(Args..., ...) const &, false> : basic_traits<true, T, R, Args...> { struct fx_traits<R(T::*)(Args..., ...) const &, false> : basic_traits<false, true, T, R, Args...> {
typedef R(T::* function_pointer_type)(Args..., ...) const &; typedef R(T::* function_pointer_type)(Args..., ...) const &;
}; };
template<typename T, typename R, typename... Args> template<typename T, typename R, typename... Args>
struct fx_traits<R(T::*)(Args...) const volatile &, false> : basic_traits<false, T, R, Args...> { struct fx_traits<R(T::*)(Args...) const volatile &, false> : basic_traits<false, false, T, R, Args...> {
typedef R(T::* function_pointer_type)(Args...) const volatile &; typedef R(T::* function_pointer_type)(Args...) const volatile &;
}; };
template<typename T, typename R, typename... Args> template<typename T, typename R, typename... Args>
struct fx_traits<R(T::*)(Args..., ...) const volatile &, false> : basic_traits<true, T, R, Args...> { struct fx_traits<R(T::*)(Args..., ...) const volatile &, false> : basic_traits<false, true, T, R, Args...> {
typedef R(T::* function_pointer_type)(Args..., ...) const volatile &; typedef R(T::* function_pointer_type)(Args..., ...) const volatile &;
}; };
template<typename T, typename R, typename... Args> template<typename T, typename R, typename... Args>
struct fx_traits<R(T::*)(Args...) && , false> : basic_traits<false, T, R, Args...> { struct fx_traits<R(T::*)(Args...) && , false> : basic_traits<false, false, T, R, Args...> {
typedef R(T::* function_pointer_type)(Args...) && ; typedef R(T::* function_pointer_type)(Args...) && ;
}; };
template<typename T, typename R, typename... Args> template<typename T, typename R, typename... Args>
struct fx_traits<R(T::*)(Args..., ...) && , false> : basic_traits<true, T, R, Args...> { struct fx_traits<R(T::*)(Args..., ...) && , false> : basic_traits<false, true, T, R, Args...> {
typedef R(T::* function_pointer_type)(Args..., ...) && ; typedef R(T::* function_pointer_type)(Args..., ...) && ;
}; };
template<typename T, typename R, typename... Args> template<typename T, typename R, typename... Args>
struct fx_traits<R(T::*)(Args...) const &&, false> : basic_traits<false, T, R, Args...> { struct fx_traits<R(T::*)(Args...) const &&, false> : basic_traits<false, false, T, R, Args...> {
typedef R(T::* function_pointer_type)(Args...) const &&; typedef R(T::* function_pointer_type)(Args...) const &&;
}; };
template<typename T, typename R, typename... Args> template<typename T, typename R, typename... Args>
struct fx_traits<R(T::*)(Args..., ...) const &&, false> : basic_traits<true, T, R, Args...> { struct fx_traits<R(T::*)(Args..., ...) const &&, false> : basic_traits<false, true, T, R, Args...> {
typedef R(T::* function_pointer_type)(Args..., ...) const &&; typedef R(T::* function_pointer_type)(Args..., ...) const &&;
}; };
template<typename T, typename R, typename... Args> template<typename T, typename R, typename... Args>
struct fx_traits<R(T::*)(Args...) const volatile &&, false> : basic_traits<false, T, R, Args...> { struct fx_traits<R(T::*)(Args...) const volatile &&, false> : basic_traits<false, false, T, R, Args...> {
typedef R(T::* function_pointer_type)(Args...) const volatile &&; typedef R(T::* function_pointer_type)(Args...) const volatile &&;
}; };
template<typename T, typename R, typename... Args> template<typename T, typename R, typename... Args>
struct fx_traits<R(T::*)(Args..., ...) const volatile &&, false> : basic_traits<true, T, R, Args...> { struct fx_traits<R(T::*)(Args..., ...) const volatile &&, false> : basic_traits<false, true, T, R, Args...> {
typedef R(T::* function_pointer_type)(Args..., ...) const volatile &&; typedef R(T::* function_pointer_type)(Args..., ...) const volatile &&;
}; };
#ifdef SOL_NOEXCEPT_FUNCTION_TYPE
template<typename R, typename... Args>
struct fx_traits<R(Args...) noexcept, false> : basic_traits<true, false, void, R, Args...> {
typedef R(*function_pointer_type)(Args...);
};
template<typename R, typename... Args>
struct fx_traits<R(*)(Args...) noexcept, false> : basic_traits<true, false, void, R, Args...> {
typedef R(*function_pointer_type)(Args...);
};
template<typename R, typename... Args>
struct fx_traits<R(Args..., ...) noexcept, false> : basic_traits<true, true, void, R, Args...> {
typedef R(*function_pointer_type)(Args..., ...);
};
template<typename R, typename... Args>
struct fx_traits<R(*)(Args..., ...) noexcept, false> : basic_traits<true, true, void, R, Args...> {
typedef R(*function_pointer_type)(Args..., ...);
};
template<typename T, typename R, typename... Args>
struct fx_traits<R(T::*)(Args...) noexcept, false> : basic_traits<true, false, T, R, Args...> {
typedef R(T::* function_pointer_type)(Args...);
};
template<typename T, typename R, typename... Args>
struct fx_traits<R(T::*)(Args..., ...) noexcept, false> : basic_traits<true, true, T, R, Args...> {
typedef R(T::* function_pointer_type)(Args..., ...);
};
/* Const Volatile */
template<typename T, typename R, typename... Args>
struct fx_traits<R(T::*)(Args...) const noexcept, false> : basic_traits<true, false, T, R, Args...> {
typedef R(T::* function_pointer_type)(Args...) const;
};
template<typename T, typename R, typename... Args>
struct fx_traits<R(T::*)(Args..., ...) const noexcept, false> : basic_traits<true, true, T, R, Args...> {
typedef R(T::* function_pointer_type)(Args..., ...) const;
};
template<typename T, typename R, typename... Args>
struct fx_traits<R(T::*)(Args...) const volatile noexcept, false> : basic_traits<true, false, T, R, Args...> {
typedef R(T::* function_pointer_type)(Args...) const volatile;
};
template<typename T, typename R, typename... Args>
struct fx_traits<R(T::*)(Args..., ...) const volatile noexcept, false> : basic_traits<true, true, T, R, Args...> {
typedef R(T::* function_pointer_type)(Args..., ...) const volatile;
};
template<typename T, typename R, typename... Args>
struct fx_traits<R(T::*)(Args...) & noexcept, false> : basic_traits<true, false, T, R, Args...> {
typedef R(T::* function_pointer_type)(Args...) &;
};
template<typename T, typename R, typename... Args>
struct fx_traits<R(T::*)(Args..., ...) & noexcept, false> : basic_traits<true, true, T, R, Args...> {
typedef R(T::* function_pointer_type)(Args..., ...) &;
};
template<typename T, typename R, typename... Args>
struct fx_traits<R(T::*)(Args...) const & noexcept, false> : basic_traits<true, false, T, R, Args...> {
typedef R(T::* function_pointer_type)(Args...) const &;
};
template<typename T, typename R, typename... Args>
struct fx_traits<R(T::*)(Args..., ...) const & noexcept, false> : basic_traits<true, true, T, R, Args...> {
typedef R(T::* function_pointer_type)(Args..., ...) const &;
};
template<typename T, typename R, typename... Args>
struct fx_traits<R(T::*)(Args...) const volatile & noexcept, false> : basic_traits<true, false, T, R, Args...> {
typedef R(T::* function_pointer_type)(Args...) const volatile &;
};
template<typename T, typename R, typename... Args>
struct fx_traits<R(T::*)(Args..., ...) const volatile & noexcept, false> : basic_traits<true, true, T, R, Args...> {
typedef R(T::* function_pointer_type)(Args..., ...) const volatile &;
};
template<typename T, typename R, typename... Args>
struct fx_traits<R(T::*)(Args...) && noexcept , false> : basic_traits<true, false, T, R, Args...> {
typedef R(T::* function_pointer_type)(Args...) && ;
};
template<typename T, typename R, typename... Args>
struct fx_traits<R(T::*)(Args..., ...) && noexcept , false> : basic_traits<true, true, T, R, Args...> {
typedef R(T::* function_pointer_type)(Args..., ...) && ;
};
template<typename T, typename R, typename... Args>
struct fx_traits<R(T::*)(Args...) const && noexcept, false> : basic_traits<true, false, T, R, Args...> {
typedef R(T::* function_pointer_type)(Args...) const &&;
};
template<typename T, typename R, typename... Args>
struct fx_traits<R(T::*)(Args..., ...) const && noexcept, false> : basic_traits<true, true, T, R, Args...> {
typedef R(T::* function_pointer_type)(Args..., ...) const &&;
};
template<typename T, typename R, typename... Args>
struct fx_traits<R(T::*)(Args...) const volatile && noexcept, false> : basic_traits<true, false, T, R, Args...> {
typedef R(T::* function_pointer_type)(Args...) const volatile &&;
};
template<typename T, typename R, typename... Args>
struct fx_traits<R(T::*)(Args..., ...) const volatile && noexcept, false> : basic_traits<true, true, T, R, Args...> {
typedef R(T::* function_pointer_type)(Args..., ...) const volatile &&;
};
#endif // noexcept is part of a function's type
template<typename Signature> template<typename Signature>
struct fx_traits<Signature, true> : fx_traits<typename fx_traits<decltype(&Signature::operator())>::function_type, false> {}; struct fx_traits<Signature, true> : fx_traits<typename fx_traits<decltype(&Signature::operator())>::function_type, false> {};
@ -348,6 +461,7 @@ namespace sol {
typedef R Arg; typedef R Arg;
typedef T object_type; typedef T object_type;
using signature_type = R(T::*); using signature_type = R(T::*);
static const bool is_noexcept = false;
static const bool is_member_function = false; static const bool is_member_function = false;
static const std::size_t arity = 1; static const std::size_t arity = 1;
static const std::size_t free_arity = 2; static const std::size_t free_arity = 2;
@ -362,6 +476,7 @@ namespace sol {
template<std::size_t i> template<std::size_t i>
using arg_at = void_tuple_element_t<i, args_tuple>; using arg_at = void_tuple_element_t<i, args_tuple>;
}; };
} // meta_detail } // meta_detail
template<typename Signature> template<typename Signature>
@ -823,6 +938,12 @@ namespace sol {
#include <lua.hpp> #include <lua.hpp>
#endif // C++ Mangling for Lua #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) #if defined(_WIN32) || defined(_MSC_VER)
#ifndef SOL_CODECVT_SUPPORT #ifndef SOL_CODECVT_SUPPORT
#define SOL_CODECVT_SUPPORT 1 #define SOL_CODECVT_SUPPORT 1
@ -3045,6 +3166,10 @@ namespace sol {
namespace sol { namespace sol {
namespace detail { 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 #ifdef SOL_NO_EXCEPTIONS
template <lua_CFunction f> template <lua_CFunction f>
int static_trampoline(lua_State* L) { int static_trampoline(lua_State* L) {
@ -3080,8 +3205,33 @@ namespace sol {
return lua_error(L); return lua_error(L);
} }
#ifdef SOL_NOEXCEPT_FUNCTION_TYPE
template <lua_CFunction_noexcept f>
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 <typename Fx, typename... Args> template <typename Fx, typename... Args>
int trampoline(lua_State* L, Fx&& f, Args&&... args) { int trampoline(lua_State* L, Fx&& f, Args&&... args) {
if (meta::bind_traits<meta::unqualified_t<Fx>>::is_noexcept) {
return f(L, std::forward<Args>(args)...);
}
try { try {
return f(L, std::forward<Args>(args)...); return f(L, std::forward<Args>(args)...);
} }
@ -8032,6 +8182,85 @@ namespace sol {
}; };
#ifdef SOL_NOEXCEPT_FUNCTION_TYPE //noexcept has become a part of a function's type
template <typename R, typename O, typename... Args>
struct wrapper<R(O:: *)(Args...) noexcept> : public member_function_wrapper<R(O:: *)(Args...) noexcept, R, O, Args...> {
};
template <typename R, typename O, typename... Args>
struct wrapper<R(O:: *)(Args...) const noexcept> : public member_function_wrapper<R(O:: *)(Args...) const noexcept, R, O, Args...> {
};
template <typename R, typename O, typename... Args>
struct wrapper<R(O:: *)(Args...) const volatile noexcept> : public member_function_wrapper<R(O:: *)(Args...) const volatile noexcept, R, O, Args...> {
};
template <typename R, typename O, typename... Args>
struct wrapper<R(O:: *)(Args...) & noexcept> : public member_function_wrapper<R(O:: *)(Args...) & noexcept, R, O, Args...> {
};
template <typename R, typename O, typename... Args>
struct wrapper<R(O:: *)(Args...) const & noexcept> : public member_function_wrapper<R(O:: *)(Args...) const & noexcept, R, O, Args...> {
};
template <typename R, typename O, typename... Args>
struct wrapper<R(O:: *)(Args...) const volatile & noexcept> : public member_function_wrapper<R(O:: *)(Args...) const volatile & noexcept, R, O, Args...> {
};
template <typename R, typename O, typename... Args>
struct wrapper<R(O:: *)(Args..., ...) & noexcept> : public member_function_wrapper<R(O:: *)(Args..., ...) & noexcept, R, O, Args...> {
};
template <typename R, typename O, typename... Args>
struct wrapper<R(O:: *)(Args..., ...) const & noexcept> : public member_function_wrapper<R(O:: *)(Args..., ...) const & noexcept, R, O, Args...> {
};
template <typename R, typename O, typename... Args>
struct wrapper<R(O:: *)(Args..., ...) const volatile & noexcept> : public member_function_wrapper<R(O:: *)(Args..., ...) const volatile & noexcept, R, O, Args...> {
};
template <typename R, typename O, typename... Args>
struct wrapper<R(O:: *)(Args...) && noexcept> : public member_function_wrapper<R(O:: *)(Args...) & noexcept, R, O, Args...> {
};
template <typename R, typename O, typename... Args>
struct wrapper<R(O:: *)(Args...) const && noexcept> : public member_function_wrapper<R(O:: *)(Args...) const & noexcept, R, O, Args...> {
};
template <typename R, typename O, typename... Args>
struct wrapper<R(O:: *)(Args...) const volatile && noexcept> : public member_function_wrapper<R(O:: *)(Args...) const volatile & noexcept, R, O, Args...> {
};
template <typename R, typename O, typename... Args>
struct wrapper<R(O:: *)(Args..., ...) && noexcept> : public member_function_wrapper<R(O:: *)(Args..., ...) & noexcept, R, O, Args...> {
};
template <typename R, typename O, typename... Args>
struct wrapper<R(O:: *)(Args..., ...) const && noexcept> : public member_function_wrapper<R(O:: *)(Args..., ...) const & noexcept, R, O, Args...> {
};
template <typename R, typename O, typename... Args>
struct wrapper<R(O:: *)(Args..., ...) const volatile && noexcept> : public member_function_wrapper<R(O:: *)(Args..., ...) const volatile & noexcept, R, O, Args...> {
};
#endif // noexcept is part of a function's type
} // sol } // sol
// end of sol/wrapper.hpp // end of sol/wrapper.hpp

View File

@ -103,30 +103,6 @@ namespace sol {
typedef R(*function_pointer_type)(Args..., ...); typedef R(*function_pointer_type)(Args..., ...);
}; };
#if __cpp_noexcept_function_type >= 201510L //noexcept has become a part of a function's type
template<typename R, typename... Args>
struct fx_traits<R(Args...) noexcept, false> : basic_traits<true, false, void, R, Args...> {
typedef R(*function_pointer_type)(Args...);
};
template<typename R, typename... Args>
struct fx_traits<R(*)(Args...) noexcept, false> : basic_traits<true, false, void, R, Args...> {
typedef R(*function_pointer_type)(Args...);
};
template<typename R, typename... Args>
struct fx_traits<R(Args..., ...) noexcept, false> : basic_traits<true, true, void, R, Args...> {
typedef R(*function_pointer_type)(Args..., ...);
};
template<typename R, typename... Args>
struct fx_traits<R(*)(Args..., ...) noexcept, false> : basic_traits<true, true, void, R, Args...> {
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 // Member Functions
/* C-Style Variadics */ /* C-Style Variadics */
template<typename T, typename R, typename... Args> template<typename T, typename R, typename... Args>
@ -139,20 +115,6 @@ namespace sol {
typedef R(T::* function_pointer_type)(Args..., ...); typedef R(T::* function_pointer_type)(Args..., ...);
}; };
#if __cpp_noexcept_function_type >= 201510L //noexcept has become a part of a function's type
template<typename T, typename R, typename... Args>
struct fx_traits<R(T::*)(Args...) noexcept, false> : basic_traits<true, false, T, R, Args...> {
typedef R(T::* function_pointer_type)(Args...);
};
template<typename T, typename R, typename... Args>
struct fx_traits<R(T::*)(Args..., ...) noexcept, false> : basic_traits<true, true, T, R, Args...> {
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 */ /* Const Volatile */
template<typename T, typename R, typename... Args> template<typename T, typename R, typename... Args>
struct fx_traits<R(T::*)(Args...) const, false> : basic_traits<false, false, T, R, Args...> { struct fx_traits<R(T::*)(Args...) const, false> : basic_traits<false, false, T, R, Args...> {
@ -174,31 +136,6 @@ namespace sol {
typedef R(T::* function_pointer_type)(Args..., ...) const volatile; 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<typename T, typename R, typename... Args>
struct fx_traits<R(T::*)(Args...) const noexcept, false> : basic_traits<true, false, T, R, Args...> {
typedef R(T::* function_pointer_type)(Args...) const;
};
template<typename T, typename R, typename... Args>
struct fx_traits<R(T::*)(Args..., ...) const noexcept, false> : basic_traits<true, true, T, R, Args...> {
typedef R(T::* function_pointer_type)(Args..., ...) const;
};
template<typename T, typename R, typename... Args>
struct fx_traits<R(T::*)(Args...) const volatile noexcept, false> : basic_traits<true, false, T, R, Args...> {
typedef R(T::* function_pointer_type)(Args...) const volatile;
};
template<typename T, typename R, typename... Args>
struct fx_traits<R(T::*)(Args..., ...) const volatile noexcept, false> : basic_traits<true, true, T, R, Args...> {
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 */ /* Member Function Qualifiers */
template<typename T, typename R, typename... Args> template<typename T, typename R, typename... Args>
struct fx_traits<R(T::*)(Args...) &, false> : basic_traits<false, false, T, R, Args...> { struct fx_traits<R(T::*)(Args...) &, false> : basic_traits<false, false, T, R, Args...> {
@ -260,7 +197,58 @@ namespace sol {
typedef R(T::* function_pointer_type)(Args..., ...) const volatile &&; 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<typename R, typename... Args>
struct fx_traits<R(Args...) noexcept, false> : basic_traits<true, false, void, R, Args...> {
typedef R(*function_pointer_type)(Args...);
};
template<typename R, typename... Args>
struct fx_traits<R(*)(Args...) noexcept, false> : basic_traits<true, false, void, R, Args...> {
typedef R(*function_pointer_type)(Args...);
};
template<typename R, typename... Args>
struct fx_traits<R(Args..., ...) noexcept, false> : basic_traits<true, true, void, R, Args...> {
typedef R(*function_pointer_type)(Args..., ...);
};
template<typename R, typename... Args>
struct fx_traits<R(*)(Args..., ...) noexcept, false> : basic_traits<true, true, void, R, Args...> {
typedef R(*function_pointer_type)(Args..., ...);
};
template<typename T, typename R, typename... Args>
struct fx_traits<R(T::*)(Args...) noexcept, false> : basic_traits<true, false, T, R, Args...> {
typedef R(T::* function_pointer_type)(Args...);
};
template<typename T, typename R, typename... Args>
struct fx_traits<R(T::*)(Args..., ...) noexcept, false> : basic_traits<true, true, T, R, Args...> {
typedef R(T::* function_pointer_type)(Args..., ...);
};
/* Const Volatile */
template<typename T, typename R, typename... Args>
struct fx_traits<R(T::*)(Args...) const noexcept, false> : basic_traits<true, false, T, R, Args...> {
typedef R(T::* function_pointer_type)(Args...) const;
};
template<typename T, typename R, typename... Args>
struct fx_traits<R(T::*)(Args..., ...) const noexcept, false> : basic_traits<true, true, T, R, Args...> {
typedef R(T::* function_pointer_type)(Args..., ...) const;
};
template<typename T, typename R, typename... Args>
struct fx_traits<R(T::*)(Args...) const volatile noexcept, false> : basic_traits<true, false, T, R, Args...> {
typedef R(T::* function_pointer_type)(Args...) const volatile;
};
template<typename T, typename R, typename... Args>
struct fx_traits<R(T::*)(Args..., ...) const volatile noexcept, false> : basic_traits<true, true, T, R, Args...> {
typedef R(T::* function_pointer_type)(Args..., ...) const volatile;
};
template<typename T, typename R, typename... Args> template<typename T, typename R, typename... Args>
struct fx_traits<R(T::*)(Args...) & noexcept, false> : basic_traits<true, false, T, R, Args...> { struct fx_traits<R(T::*)(Args...) & noexcept, false> : basic_traits<true, false, T, R, Args...> {
@ -322,7 +310,7 @@ namespace sol {
typedef R(T::* function_pointer_type)(Args..., ...) const volatile &&; 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<typename Signature> template<typename Signature>
struct fx_traits<Signature, true> : fx_traits<typename fx_traits<decltype(&Signature::operator())>::function_type, false> {}; struct fx_traits<Signature, true> : fx_traits<typename fx_traits<decltype(&Signature::operator())>::function_type, false> {};
@ -337,6 +325,7 @@ namespace sol {
typedef R Arg; typedef R Arg;
typedef T object_type; typedef T object_type;
using signature_type = R(T::*); using signature_type = R(T::*);
static const bool is_noexcept = false;
static const bool is_member_function = false; static const bool is_member_function = false;
static const std::size_t arity = 1; static const std::size_t arity = 1;
static const std::size_t free_arity = 2; static const std::size_t free_arity = 2;
@ -351,6 +340,7 @@ namespace sol {
template<std::size_t i> template<std::size_t i>
using arg_at = void_tuple_element_t<i, args_tuple>; using arg_at = void_tuple_element_t<i, args_tuple>;
}; };
} // meta_detail } // meta_detail
template<typename Signature> template<typename Signature>

View File

@ -30,6 +30,12 @@
#include <lua.hpp> #include <lua.hpp>
#endif // C++ Mangling for Lua #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) #if defined(_WIN32) || defined(_MSC_VER)
#ifndef SOL_CODECVT_SUPPORT #ifndef SOL_CODECVT_SUPPORT
#define SOL_CODECVT_SUPPORT 1 #define SOL_CODECVT_SUPPORT 1

View File

@ -190,9 +190,15 @@ namespace sol {
stack::push(L, f); 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 <typename Fx, typename... Args, meta::disable<meta::any<std::is_base_of<reference, meta::unqualified_t<Fx>>, std::is_base_of<stack_reference, meta::unqualified_t<Fx>>>> = meta::enabler> template <typename Fx, typename... Args, meta::disable<meta::any<std::is_base_of<reference, meta::unqualified_t<Fx>>, std::is_base_of<stack_reference, meta::unqualified_t<Fx>>>> = meta::enabler>
static void select(lua_State* L, Fx&& fx, Args&&... args) { static void select(lua_State* L, Fx&& fx, Args&&... args) {
select_function(std::is_function<meta::unqualified_t<Fx>>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...); select_function(std::is_function<std::remove_pointer_t<meta::unqualified_t<Fx>>>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...);
} }
template <typename Fx, meta::enable<meta::any<std::is_base_of<reference, meta::unqualified_t<Fx>>, std::is_base_of<stack_reference, meta::unqualified_t<Fx>>>> = meta::enabler> template <typename Fx, meta::enable<meta::any<std::is_base_of<reference, meta::unqualified_t<Fx>>, std::is_base_of<stack_reference, meta::unqualified_t<Fx>>>> = meta::enabler>
@ -254,7 +260,15 @@ namespace sol {
}; };
template<typename Signature> template<typename Signature>
struct pusher<Signature, std::enable_if_t<meta::all<std::is_function<Signature>, meta::neg<std::is_same<Signature, lua_CFunction>>, meta::neg<std::is_same<Signature, std::remove_pointer_t<lua_CFunction>>>>::value>> { struct pusher<Signature, std::enable_if_t<meta::all<
std::is_function<Signature>,
meta::neg<std::is_same<Signature, lua_CFunction>>,
meta::neg<std::is_same<Signature, std::remove_pointer_t<lua_CFunction>>>
#ifdef SOL_NOEXCEPT_FUNCTION_TYPE
, meta::neg<std::is_same<Signature, detail::lua_CFunction_noexcept>>,
meta::neg<std::is_same<Signature, std::remove_pointer_t<detail::lua_CFunction_noexcept>>>
#endif // noexcept function types
>::value>> {
template <typename F> template <typename F>
static int push(lua_State* L, F&& f) { static int push(lua_State* L, F&& f) {
return pusher<function_sig<>>{}.push(L, std::forward<F>(f)); return pusher<function_sig<>>{}.push(L, std::forward<F>(f));

View File

@ -28,11 +28,11 @@ namespace sol {
namespace function_detail { namespace function_detail {
template<typename Func> template<typename Func>
struct functor_function { struct functor_function {
typedef meta::unwrapped_t<meta::unqualified_t<Func>> Function; typedef std::decay_t<meta::unwrap_unqualified_t<Func>> function_type;
Function fx; function_type fx;
template<typename... Args> template<typename... Args>
functor_function(Function f, Args&&... args) : fx(std::move(f), std::forward<Args>(args)...) {} functor_function(function_type f, Args&&... args) : fx(std::move(f), std::forward<Args>(args)...) {}
int call(lua_State* L) { int call(lua_State* L) {
return call_detail::call_wrapped<void, true, false>(L, fx); return call_detail::call_wrapped<void, true, false>(L, fx);

View File

@ -84,7 +84,7 @@ namespace sol {
} }
template <typename F, F fx> template <typename F, F fx>
int call_wrapper_entry(lua_State* L) { int call_wrapper_entry(lua_State* L) noexcept(meta::bind_traits<F>::is_noexcept) {
return call_wrapper_function<F, fx>(std::is_member_function_pointer<meta::unqualified_t<F>>(), L); return call_wrapper_function<F, fx>(std::is_member_function_pointer<meta::unqualified_t<F>>(), L);
} }
@ -97,15 +97,38 @@ namespace sol {
} }
}; };
template <typename F, F fx>
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<F>::is_noexcept ? detail::static_trampoline_noexcept<fx>(L) : detail::static_trampoline<fx>(L);
#else
return detail::static_trampoline<fx>(L);
#endif
#endif // fuck you clang :c
}
template <typename F, F fx>
inline int c_call_raw(std::false_type, lua_State* L) {
#ifdef __clang__
return detail::trampoline(L, function_detail::call_wrapper_entry<F, fx>);
#else
return detail::static_trampoline<(&function_detail::call_wrapper_entry<F, fx>)>(L);
#endif // fuck you clang :c
}
} // function_detail } // function_detail
template <typename F, F fx> template <typename F, F fx>
inline int c_call(lua_State* L) { inline int c_call(lua_State* L) {
#ifdef __clang__ typedef meta::unqualified_t<F> Fu;
return detail::trampoline(L, function_detail::call_wrapper_entry<F, fx>); return function_detail::c_call_raw<F, fx>(std::integral_constant<bool, std::is_same<Fu, lua_CFunction>::value
#else #ifdef SOL_NOEXCEPT_FUNCTION_TYPE
return detail::static_trampoline<(&function_detail::call_wrapper_entry<F, fx>)>(L); || std::is_same<Fu, detail::lua_CFunction_noexcept>::value
#endif // fuck you clang :c #endif
>(), L);
} }
template <typename F, F f> template <typename F, F f>

View File

@ -310,6 +310,23 @@ namespace sol {
return 1; return 1;
} }
}; };
#ifdef SOL_NOEXCEPT_FUNCTION_TYPE
template<>
struct pusher<std::remove_pointer_t<detail::lua_CFunction_noexcept>> {
static int push(lua_State* L, detail::lua_CFunction_noexcept func, int n = 0) {
lua_pushcclosure(L, func, n);
return 1;
}
};
template<>
struct pusher<detail::lua_CFunction_noexcept> {
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<> template<>
struct pusher<c_closure> { struct pusher<c_closure> {

View File

@ -31,18 +31,22 @@
namespace sol { namespace sol {
namespace detail { 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 #ifdef SOL_NO_EXCEPTIONS
template <lua_CFunction f> template <lua_CFunction f>
int static_trampoline(lua_State* L) { int static_trampoline(lua_State* L) noexcept {
return f(L); return f(L);
} }
template <typename Fx, typename... Args> template <typename Fx, typename... Args>
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>(args)...); return f(L, std::forward<Args>(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); return trampoline(L, f);
} }
#else #else
@ -59,15 +63,33 @@ namespace sol {
} }
#if !defined(SOL_EXCEPTIONS_SAFE_PROPAGATION) #if !defined(SOL_EXCEPTIONS_SAFE_PROPAGATION)
catch (...) { catch (...) {
std::exception_ptr eptr = std::current_exception();
lua_pushstring(L, "caught (...) exception"); lua_pushstring(L, "caught (...) exception");
} }
#endif #endif
return lua_error(L); 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 <auto X> and then switch on no-exceptness of the function
template <lua_CFunction_noexcept f>
int static_trampoline(lua_State* L) noexcept {
#else
template <lua_CFunction_noexcept f>
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 <typename Fx, typename... Args> template <typename Fx, typename... Args>
int trampoline(lua_State* L, Fx&& f, Args&&... args) { int trampoline(lua_State* L, Fx&& f, Args&&... args) {
if (meta::bind_traits<meta::unqualified_t<Fx>>::is_noexcept) {
std::cout << "[TRAMPOLINE] HEY A NOEXCEPTION FUNCTION IS GONNA BE CALLED" << std::endl;
return f(L, std::forward<Args>(args)...);
}
try { try {
return f(L, std::forward<Args>(args)...); return f(L, std::forward<Args>(args)...);
} }

View File

@ -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 <typename R, typename O, typename... Args> template <typename R, typename O, typename... Args>
struct wrapper<R(O:: *)(Args...) noexcept> : public member_function_wrapper<R(O:: *)(Args...) noexcept, R, O, Args...> { struct wrapper<R(O:: *)(Args...) noexcept> : public member_function_wrapper<R(O:: *)(Args...) noexcept, R, O, Args...> {
@ -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 } // sol

View File

@ -99,8 +99,9 @@ struct fer {
} }
}; };
inline void noexcept_function() noexcept {} static int raw_noexcept_function(lua_State* L) noexcept {
struct type_with_noexcept_method{ void noexcept_method() noexcept {} }; return sol::stack::push(L, 0x63);
}
TEST_CASE("functions/tuple-returns", "Make sure tuple returns are ordered properly") { TEST_CASE("functions/tuple-returns", "Make sure tuple returns are ordered properly") {
sol::state lua; 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") { TEST_CASE("functions/noexcept", "allow noexcept functions to be serialized properly into Lua using sol2") {
sol::state lua; struct T {
static int noexcept_function() noexcept {
return 0x61;
}
lua.set_function("noexcept_function", &noexcept_function); int noexcept_method() noexcept {
lua.set_function("noexcept_member_function", &type_with_noexcept_method::noexcept_method); return 0x62;
}
} t;
lua_CFunction ccall = sol::c_call<decltype(&raw_noexcept_function), &raw_noexcept_function>;
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);
} }

View File

@ -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") { TEST_CASE("usertype/usertype", "Show that we can create classes from usertype and use them") {
sol::state lua; 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") { 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; sol::state lua;
lua.new_usertype<type_with_noexcept_method>("tmp", "nf", &noexcept_function, "nm", &type_with_noexcept_method::noexcept_method); lua.new_usertype<T>("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);
} }