fix #670
This commit is contained in:
ThePhD 2018-06-27 07:14:02 -04:00
parent 301547f260
commit 3935dc497c
7 changed files with 116 additions and 44 deletions

View File

@ -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 2018-06-16 11:58:58.595822 UTC
// This header was generated with sol v2.20.3 (revision 968989b)
// Generated 2018-06-27 11:13:10.992580 UTC
// This header was generated with sol v2.20.3 (revision 301547f)
// https://github.com/ThePhD/sol2
#ifndef SOL_SINGLE_INCLUDE_HPP
@ -5760,7 +5760,7 @@ namespace sol {
struct is_environment : std::integral_constant<bool, is_userdata<T>::value || is_table<T>::value> {};
template <typename T>
struct is_automagical : std::true_type {};
struct is_automagical : meta::neg<std::is_array<meta::unqualified_t<T>>> {};
template <typename T>
inline type type_of() {
@ -7854,7 +7854,8 @@ namespace sol {
template <typename T, typename Handler>
inline decltype(auto) unqualified_check_get(lua_State* L, int index, Handler&& handler, record& tracking) {
check_getter<T> cg{};
typedef meta::unqualified_t<T> Tu;
check_getter<Tu> cg{};
(void)cg;
return cg.get(L, index, std::forward<Handler>(handler), tracking);
}
@ -7895,6 +7896,9 @@ namespace sol {
#if defined(SOL_SAFE_GETTER) && SOL_SAFE_GETTER
template <typename T>
inline auto tagged_unqualified_get(types<T>, lua_State* L, int index, record& tracking) -> decltype(stack_detail::unchecked_unqualified_get<T>(L, index, tracking)) {
if (is_lua_reference<T>::value) {
return stack_detail::unchecked_unqualified_get<T>(L, index, tracking);
}
auto op = unqualified_check_get<T>(L, index, type_panic_c_str, tracking);
return *std::move(op);
}
@ -7906,6 +7910,9 @@ namespace sol {
template <typename T>
inline auto tagged_get(types<T>, lua_State* L, int index, record& tracking) -> decltype(stack_detail::unchecked_get<T>(L, index, tracking)) {
if (is_lua_reference<T>::value) {
return stack_detail::unchecked_get<T>(L, index, tracking);
}
auto op = check_get<T>(L, index, type_panic_c_str, tracking);
return *std::move(op);
}
@ -10087,7 +10094,7 @@ namespace stack {
static optional<T> get(lua_State* L, int index, Handler&& handler, record& tracking) {
// actually check if it's none here, otherwise
// we'll have a none object inside an optional!
bool success = stack::check<T>(L, index, no_panic);
bool success = lua_isnoneornil(L, index) == 0 && stack::check<T>(L, index, no_panic);
if (!success) {
// expected type, actual type
tracking.use(static_cast<int>(success));
@ -10098,14 +10105,6 @@ namespace stack {
}
};
template <typename T>
struct check_getter<optional<T>> {
template <typename Handler>
static decltype(auto) get(lua_State* L, int index, Handler&&, record& tracking) {
return check_get<T>(L, index, no_panic, tracking);
}
};
template <typename T>
struct check_getter<T, std::enable_if_t<std::is_integral<T>::value && lua_type_of<T>::value == type::number>> {
template <typename Handler>
@ -10231,18 +10230,7 @@ namespace stack {
namespace sol {
namespace stack {
template <typename T, typename C>
struct qualified_check_getter {
typedef decltype(stack_detail::unchecked_get<T>(nullptr, 0, std::declval<record&>())) R;
template <typename Handler>
static optional<R> get(lua_State* L, int index, Handler&& handler, record& tracking) {
if (!check<T>(L, index, std::forward<Handler>(handler))) {
tracking.use(static_cast<int>(!lua_isnone(L, index)));
return nullopt;
}
return stack_detail::unchecked_get<T>(L, index, tracking);
}
};
struct qualified_check_getter : check_getter<meta::unqualified_t<T>, C> {};
}
} // namespace sol::stack
@ -18038,7 +18026,7 @@ namespace sol {
template <typename T, typename Op>
int comparsion_operator_wrap(lua_State* L) {
auto maybel = stack::unqualified_check_get<T>(L, 1);
auto maybel = stack::unqualified_check_get<T&>(L, 1);
if (maybel) {
auto mayber = stack::unqualified_check_get<T&>(L, 2);
if (mayber) {
@ -18434,7 +18422,7 @@ namespace sol {
int runtime_new_index(lua_State* L, void*, int runtimetarget);
template <typename T, bool is_simple>
inline int metatable_newindex(lua_State* L) {
inline int metatable_new_index(lua_State* L) {
if (is_toplevel(L)) {
auto non_indexable = [&L]() {
if (is_simple) {
@ -18718,7 +18706,7 @@ namespace sol {
template <typename... Args, typename = std::enable_if_t<sizeof...(Args) == sizeof...(Tn)>>
usertype_metatable(Args&&... args)
: usertype_metatable_core(&usertype_detail::indexing_fail<T, true>, &usertype_detail::metatable_newindex<T, false>), usertype_detail::registrar(), functions(std::forward<Args>(args)...), destructfunc(nullptr), callconstructfunc(nullptr), indexbase(&core_indexing_call<true>), newindexbase(&core_indexing_call<false>), indexbaseclasspropogation(usertype_detail::walk_all_bases<true>), newindexbaseclasspropogation(usertype_detail::walk_all_bases<false>), baseclasscheck(nullptr), baseclasscast(nullptr), secondarymeta(contains_variable()), properties() {
: usertype_metatable_core(&usertype_detail::indexing_fail<T, true>, &usertype_detail::metatable_new_index<T, false>), usertype_detail::registrar(), functions(std::forward<Args>(args)...), destructfunc(nullptr), callconstructfunc(nullptr), indexbase(&core_indexing_call<true>), newindexbase(&core_indexing_call<false>), indexbaseclasspropogation(usertype_detail::walk_all_bases<true>), newindexbaseclasspropogation(usertype_detail::walk_all_bases<false>), baseclasscheck(nullptr), baseclasscast(nullptr), secondarymeta(contains_variable()), properties() {
properties.reset();
std::initializer_list<typename usertype_detail::mapping_t::value_type> ilist{{std::pair<std::string, usertype_detail::call_information>(usertype_detail::make_string(std::get<I * 2>(functions)),
usertype_detail::call_information(&usertype_metatable::real_find_call<I * 2, I * 2 + 1, true>,
@ -18756,7 +18744,7 @@ namespace sol {
return is_index ? f.indexfunc(L) : f.newindexfunc(L);
}
template <bool is_index, bool toplevel = false>
template <bool is_index, bool toplevel = false, bool is_meta_bound = false>
static int core_indexing_call(lua_State* L) {
usertype_metatable& f = toplevel
? static_cast<usertype_metatable&>(stack::get<light<usertype_metatable>>(L, upvalue_index(usertype_detail::metatable_index)))
@ -18795,6 +18783,9 @@ namespace sol {
if (found) {
return ret;
}
if (is_meta_bound) {
return is_index ? usertype_detail::indexing_fail<T, is_index>(L) : usertype_detail::metatable_new_index<T, false>(L);
}
return toplevel ? (is_index ? f.indexfunc(L) : f.newindexfunc(L)) : -1;
}
@ -18806,6 +18797,14 @@ namespace sol {
return core_indexing_call<false, true>(L);
}
static int real_meta_index_call(lua_State* L) {
return core_indexing_call<true, true, true>(L);
}
static int real_meta_new_index_call(lua_State* L) {
return core_indexing_call<false, true, true>(L);
}
template <std::size_t Idx, bool is_index = true, bool is_variable = false>
static int real_call(lua_State* L) {
usertype_metatable& f = stack::get<light<usertype_metatable>>(L, upvalue_index(usertype_detail::metatable_index));
@ -18842,6 +18841,14 @@ namespace sol {
return detail::typed_static_trampoline<decltype(&real_new_index_call), (&real_new_index_call)>(L);
}
static int meta_index_call(lua_State* L) {
return detail::typed_static_trampoline<decltype(&real_meta_index_call), (&real_meta_index_call)>(L);
}
static int meta_new_index_call(lua_State* L) {
return detail::typed_static_trampoline<decltype(&real_meta_new_index_call), (&real_meta_new_index_call)>(L);
}
virtual int push_um(lua_State* L) override {
return stack::push(L, std::move(*this));
}
@ -18995,8 +19002,8 @@ namespace sol {
stack::set_field(L, meta_function::call_function, make_closure(um.callconstructfunc, nullptr, make_light(um), make_light(umc)), metabehind.stack_index());
}
stack::set_field(L, meta_function::index, make_closure(umt_t::index_call, nullptr, make_light(um), make_light(umc), nullptr, usertype_detail::toplevel_magic), metabehind.stack_index());
stack::set_field(L, meta_function::new_index, make_closure(umt_t::new_index_call, nullptr, make_light(um), make_light(umc), nullptr, usertype_detail::toplevel_magic), metabehind.stack_index());
stack::set_field(L, meta_function::index, make_closure(umt_t::meta_index_call, nullptr, make_light(um), make_light(umc), nullptr, usertype_detail::toplevel_magic), metabehind.stack_index());
stack::set_field(L, meta_function::new_index, make_closure(umt_t::meta_new_index_call, nullptr, make_light(um), make_light(umc), nullptr, usertype_detail::toplevel_magic), metabehind.stack_index());
stack::set_field(L, metatable_key, metabehind, t.stack_index());
metabehind.pop();
}
@ -19048,7 +19055,7 @@ namespace sol {
else {
return is_index
? indexing_fail<T, is_index>(L)
: metatable_newindex<T, true>(L);
: metatable_new_index<T, true>(L);
}
}
}
@ -19098,7 +19105,7 @@ namespace sol {
else {
return is_index
? indexing_fail<T, is_index>(L)
: metatable_newindex<T, true>(L);
: metatable_new_index<T, true>(L);
}
}
/* Check table storage first for a method that works
@ -19137,7 +19144,7 @@ namespace sol {
else {
return is_index
? indexing_fail<T, is_index>(L)
: metatable_newindex<T, true>(L);
: metatable_new_index<T, true>(L);
}
}
return -1;

View File

@ -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 2018-06-16 11:58:58.882218 UTC
// This header was generated with sol v2.20.3 (revision 968989b)
// Generated 2018-06-27 11:13:11.257646 UTC
// This header was generated with sol v2.20.3 (revision 301547f)
// https://github.com/ThePhD/sol2
#ifndef SOL_SINGLE_INCLUDE_FORWARD_HPP

View File

@ -63,7 +63,7 @@ namespace sol {
else {
return is_index
? indexing_fail<T, is_index>(L)
: metatable_newindex<T, true>(L);
: metatable_new_index<T, true>(L);
}
}
}
@ -113,7 +113,7 @@ namespace sol {
else {
return is_index
? indexing_fail<T, is_index>(L)
: metatable_newindex<T, true>(L);
: metatable_new_index<T, true>(L);
}
}
/* Check table storage first for a method that works
@ -152,7 +152,7 @@ namespace sol {
else {
return is_index
? indexing_fail<T, is_index>(L)
: metatable_newindex<T, true>(L);
: metatable_new_index<T, true>(L);
}
}
return -1;

View File

@ -809,6 +809,9 @@ namespace sol {
#if defined(SOL_SAFE_GETTER) && SOL_SAFE_GETTER
template <typename T>
inline auto tagged_unqualified_get(types<T>, lua_State* L, int index, record& tracking) -> decltype(stack_detail::unchecked_unqualified_get<T>(L, index, tracking)) {
if (is_lua_reference<T>::value) {
return stack_detail::unchecked_unqualified_get<T>(L, index, tracking);
}
auto op = unqualified_check_get<T>(L, index, type_panic_c_str, tracking);
return *std::move(op);
}
@ -820,6 +823,9 @@ namespace sol {
template <typename T>
inline auto tagged_get(types<T>, lua_State* L, int index, record& tracking) -> decltype(stack_detail::unchecked_get<T>(L, index, tracking)) {
if (is_lua_reference<T>::value) {
return stack_detail::unchecked_get<T>(L, index, tracking);
}
auto op = check_get<T>(L, index, type_panic_c_str, tracking);
return *std::move(op);
}

View File

@ -242,7 +242,7 @@ namespace sol {
int runtime_new_index(lua_State* L, void*, int runtimetarget);
template <typename T, bool is_simple>
inline int metatable_newindex(lua_State* L) {
inline int metatable_new_index(lua_State* L) {
if (is_toplevel(L)) {
auto non_indexable = [&L]() {
if (is_simple) {
@ -526,7 +526,7 @@ namespace sol {
template <typename... Args, typename = std::enable_if_t<sizeof...(Args) == sizeof...(Tn)>>
usertype_metatable(Args&&... args)
: usertype_metatable_core(&usertype_detail::indexing_fail<T, true>, &usertype_detail::metatable_newindex<T, false>), usertype_detail::registrar(), functions(std::forward<Args>(args)...), destructfunc(nullptr), callconstructfunc(nullptr), indexbase(&core_indexing_call<true>), newindexbase(&core_indexing_call<false>), indexbaseclasspropogation(usertype_detail::walk_all_bases<true>), newindexbaseclasspropogation(usertype_detail::walk_all_bases<false>), baseclasscheck(nullptr), baseclasscast(nullptr), secondarymeta(contains_variable()), properties() {
: usertype_metatable_core(&usertype_detail::indexing_fail<T, true>, &usertype_detail::metatable_new_index<T, false>), usertype_detail::registrar(), functions(std::forward<Args>(args)...), destructfunc(nullptr), callconstructfunc(nullptr), indexbase(&core_indexing_call<true>), newindexbase(&core_indexing_call<false>), indexbaseclasspropogation(usertype_detail::walk_all_bases<true>), newindexbaseclasspropogation(usertype_detail::walk_all_bases<false>), baseclasscheck(nullptr), baseclasscast(nullptr), secondarymeta(contains_variable()), properties() {
properties.reset();
std::initializer_list<typename usertype_detail::mapping_t::value_type> ilist{{std::pair<std::string, usertype_detail::call_information>(usertype_detail::make_string(std::get<I * 2>(functions)),
usertype_detail::call_information(&usertype_metatable::real_find_call<I * 2, I * 2 + 1, true>,
@ -564,7 +564,7 @@ namespace sol {
return is_index ? f.indexfunc(L) : f.newindexfunc(L);
}
template <bool is_index, bool toplevel = false>
template <bool is_index, bool toplevel = false, bool is_meta_bound = false>
static int core_indexing_call(lua_State* L) {
usertype_metatable& f = toplevel
? static_cast<usertype_metatable&>(stack::get<light<usertype_metatable>>(L, upvalue_index(usertype_detail::metatable_index)))
@ -603,6 +603,9 @@ namespace sol {
if (found) {
return ret;
}
if (is_meta_bound) {
return is_index ? usertype_detail::indexing_fail<T, is_index>(L) : usertype_detail::metatable_new_index<T, false>(L);
}
return toplevel ? (is_index ? f.indexfunc(L) : f.newindexfunc(L)) : -1;
}
@ -614,6 +617,14 @@ namespace sol {
return core_indexing_call<false, true>(L);
}
static int real_meta_index_call(lua_State* L) {
return core_indexing_call<true, true, true>(L);
}
static int real_meta_new_index_call(lua_State* L) {
return core_indexing_call<false, true, true>(L);
}
template <std::size_t Idx, bool is_index = true, bool is_variable = false>
static int real_call(lua_State* L) {
usertype_metatable& f = stack::get<light<usertype_metatable>>(L, upvalue_index(usertype_detail::metatable_index));
@ -650,6 +661,14 @@ namespace sol {
return detail::typed_static_trampoline<decltype(&real_new_index_call), (&real_new_index_call)>(L);
}
static int meta_index_call(lua_State* L) {
return detail::typed_static_trampoline<decltype(&real_meta_index_call), (&real_meta_index_call)>(L);
}
static int meta_new_index_call(lua_State* L) {
return detail::typed_static_trampoline<decltype(&real_meta_new_index_call), (&real_meta_new_index_call)>(L);
}
virtual int push_um(lua_State* L) override {
return stack::push(L, std::move(*this));
}
@ -803,8 +822,8 @@ namespace sol {
stack::set_field(L, meta_function::call_function, make_closure(um.callconstructfunc, nullptr, make_light(um), make_light(umc)), metabehind.stack_index());
}
stack::set_field(L, meta_function::index, make_closure(umt_t::index_call, nullptr, make_light(um), make_light(umc), nullptr, usertype_detail::toplevel_magic), metabehind.stack_index());
stack::set_field(L, meta_function::new_index, make_closure(umt_t::new_index_call, nullptr, make_light(um), make_light(umc), nullptr, usertype_detail::toplevel_magic), metabehind.stack_index());
stack::set_field(L, meta_function::index, make_closure(umt_t::meta_index_call, nullptr, make_light(um), make_light(umc), nullptr, usertype_detail::toplevel_magic), metabehind.stack_index());
stack::set_field(L, meta_function::new_index, make_closure(umt_t::meta_new_index_call, nullptr, make_light(um), make_light(umc), nullptr, usertype_detail::toplevel_magic), metabehind.stack_index());
stack::set_field(L, metatable_key, metabehind, t.stack_index());
metabehind.pop();
}

View File

@ -759,6 +759,26 @@ TEST_CASE("simple_usertype/runtime replacement", "ensure that functions can be p
}
}
TEST_CASE("simple_usertype/runtime additions with newindex", "ensure that additions when new_index is overriden don't hit the specified new_index function") {
class newindex_object {};
sol::state lua;
lua.open_libraries(sol::lib::base);
lua.new_simple_usertype<newindex_object>("object",
sol::meta_function::new_index, [](newindex_object& o, sol::object key, sol::object value) {
return;
});
lua["object"]["test"] = [](newindex_object& o) {
std::cout << "test" << std::endl;
return 446;
};
auto result1 = lua.safe_script("o = object.new()", sol::script_pass_on_error);
REQUIRE(result1.valid());
auto result2 = lua.safe_script("assert(o:test() == 446)", sol::script_pass_on_error);
REQUIRE(result2.valid());
}
TEST_CASE("simple_usertype/meta key retrievals", "allow for special meta keys (__index, __newindex) to trigger methods even if overwritten directly") {
SECTION("dynamically") {
static int writes = 0;

View File

@ -1801,6 +1801,26 @@ TEST_CASE("usertype/runtime-replacement", "ensure that functions can be properly
}
}
TEST_CASE("usertype/runtime additions with newindex", "ensure that additions when new_index is overriden don't hit the specified new_index function") {
class newindex_object {};
sol::state lua;
lua.open_libraries(sol::lib::base);
lua.new_usertype<newindex_object>("object",
sol::meta_function::new_index, [](newindex_object& o, sol::object key, sol::object value) {
return;
});
lua["object"]["test"] = [](newindex_object& o) {
std::cout << "test" << std::endl;
return 446;
};
auto result1 = lua.safe_script("o = object.new()", sol::script_pass_on_error);
REQUIRE(result1.valid());
auto result2 = lua.safe_script("assert(o:test() == 446)", sol::script_pass_on_error);
REQUIRE(result2.valid());
}
TEST_CASE("usertype/alignment", "ensure that alignment does not trigger weird aliasing issues") {
struct aligned_base {};
struct aligned_derived : aligned_base {};