From 8c94cb730b33a6cda3b7d0b13635c161e375b022 Mon Sep 17 00:00:00 2001 From: ThePhD Date: Tue, 4 Apr 2017 16:16:22 -0400 Subject: [PATCH] Fix static initialization order fiasco with meta_function_names --- docs/source/api/usertype.rst | 19 ---- single/sol/sol.hpp | 138 +++++++++++++++--------------- sol/simple_usertype_metatable.hpp | 20 ++--- sol/stack_check.hpp | 2 +- sol/stack_get.hpp | 5 +- sol/stack_push.hpp | 2 +- sol/types.hpp | 75 ++++++++-------- sol/usertype_metatable.hpp | 30 +++---- 8 files changed, 136 insertions(+), 155 deletions(-) diff --git a/docs/source/api/usertype.rst b/docs/source/api/usertype.rst index 048cac52..8960323f 100644 --- a/docs/source/api/usertype.rst +++ b/docs/source/api/usertype.rst @@ -295,25 +295,6 @@ inheritance + overloading While overloading is supported regardless of inheritance caveats or not, the current version of Sol has a first-match, first-call style of overloading when it comes to inheritance. Put the functions with the most derived arguments first to get the kind of matching you expect or cast inside of an intermediary C++ function and call the function you desire. -traits ------- - -.. code-block:: cpp - :caption: usertype_traits - :name: usertype-traits - - template - struct usertype_traits { - static const std::string name; - static const std::string metatable; - static const std::string variable_metatable; - static const std::string gc_table; - }; - - -This trait is used to provide names for the various metatables and global tables used to perform cleanup and lookup. They are automagically generated at runtime. Sol attempts to parse the output of ``__PRETTY_FUCNTION__`` (``g++``/``clang++``) or ``_FUNCDSIG`` (``vc++``) to get the proper type name. If you have a special need you can override the names for your specific type. If you notice a bug in a class name when you don't manually specify it during setting a usertype, feel free to open an issue request or send an e-mail! - - compilation speed ----------------- diff --git a/single/sol/sol.hpp b/single/sol/sol.hpp index 651da2ef..1970e767 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-04-03 02:39:07.019670 UTC -// This header was generated with sol v2.16.0 (revision 185f5ec) +// Generated 2017-04-04 20:15:59.634079 UTC +// This header was generated with sol v2.16.0 (revision 32feb7a) // https://github.com/ThePhD/sol2 #ifndef SOL_SINGLE_INCLUDE_HPP @@ -3044,6 +3044,7 @@ namespace sol { } #if !defined(SOL_EXCEPTIONS_SAFE_PROPAGATION) catch (...) { + std::exception_ptr eptr = std::current_exception(); lua_pushstring(L, "caught (...) exception"); } #endif @@ -3478,47 +3479,45 @@ namespace sol { typedef meta_function meta_method; - const std::array meta_variable_names = { { - "__index", - "__newindex", - } }; + inline const std::array& meta_function_names() { + static const std::array names = { { + "new", + "__index", + "__newindex", + "__mode", + "__call", + "__mt", + "__tostring", + "__len", + "__unm", + "__add", + "__sub", + "__mul", + "__div", + "__mod", + "__pow", + "__concat", + "__eq", + "__lt", + "__le", + "__gc", - const std::array meta_function_names = { { - "new", - "__index", - "__newindex", - "__mode", - "__call", - "__mt", - "__tostring", - "__len", - "__unm", - "__add", - "__sub", - "__mul", - "__div", - "__mod", - "__pow", - "__concat", - "__eq", - "__lt", - "__le", - "__gc", - - "__idiv", - "__shl", - "__shr", - "__bnot", - "__band", - "__bor", - "__bxor", + "__idiv", + "__shl", + "__shr", + "__bnot", + "__band", + "__bor", + "__bxor", - "__pairs", - "__next" - } }; + "__pairs", + "__next" + } }; + return names; + } - inline const std::string& name_of(meta_function mf) { - return meta_function_names[static_cast(mf)]; + inline const std::string& to_string(meta_function mf) { + return meta_function_names()[static_cast(mf)]; } inline type type_of(lua_State* L, int index) { @@ -5178,7 +5177,7 @@ namespace sol { return false; } // Do advanced check for call-style userdata? - static const auto& callkey = name_of(meta_function::call); + static const auto& callkey = to_string(meta_function::call); if (lua_getmetatable(L, index) == 0) { // No metatable, no __call key possible handler(L, index, type::function, t); @@ -5730,8 +5729,9 @@ namespace sol { static meta_function get(lua_State *L, int index, record& tracking) { tracking.use(1); const char* name = getter{}.get(L, index, tracking); - for (std::size_t i = 0; i < meta_function_names.size(); ++i) - if (meta_function_names[i] == name) + const auto& mfnames = meta_function_names(); + for (std::size_t i = 0; i < mfnames.size(); ++i) + if (mfnames[i] == name) return static_cast(i); return meta_function::construct; } @@ -6571,7 +6571,7 @@ namespace sol { template<> struct pusher { static int push(lua_State* L, meta_function m) { - const std::string& str = name_of(m); + const std::string& str = to_string(m); lua_pushlstring(L, str.c_str(), str.size()); return 1; } @@ -10439,7 +10439,7 @@ namespace sol { }; inline bool is_indexer(string_detail::string_shim s) { - return s == name_of(meta_function::index) || s == name_of(meta_function::new_index); + return s == to_string(meta_function::index) || s == to_string(meta_function::new_index); } inline bool is_indexer(meta_function mf) { @@ -10459,11 +10459,11 @@ namespace sol { } inline auto make_shim(call_construction) { - return string_detail::string_shim(name_of(meta_function::call_function)); + return string_detail::string_shim(to_string(meta_function::call_function)); } inline auto make_shim(meta_function mf) { - return string_detail::string_shim(name_of(mf)); + return string_detail::string_shim(to_string(mf)); } inline auto make_shim(base_classes_tag) { @@ -10704,19 +10704,19 @@ namespace sol { int finish_regs(regs_t& l, int& index) { if (!hasless) { - const char* name = name_of(meta_function::less_than).c_str(); + const char* name = to_string(meta_function::less_than).c_str(); usertype_detail::make_reg_op, meta::supports_op_less>(l, index, name); } if (!haslessequals) { - const char* name = name_of(meta_function::less_than_or_equal_to).c_str(); + const char* name = to_string(meta_function::less_than_or_equal_to).c_str(); usertype_detail::make_reg_op, meta::supports_op_less_equal>(l, index, name); } if (!hasequals) { - const char* name = name_of(meta_function::equal_to).c_str(); + const char* name = to_string(meta_function::equal_to).c_str(); usertype_detail::make_reg_op::value, std::equal_to<>, usertype_detail::no_comp>, std::true_type>(l, index, name); } if (destructfunc != nullptr) { - l[index] = { name_of(meta_function::garbage_collect).c_str(), destructfunc }; + l[index] = { to_string(meta_function::garbage_collect).c_str(), destructfunc }; ++index; } return index; @@ -10753,25 +10753,25 @@ namespace sol { // Returnable scope // That would be a neat keyword for C++ // returnable { ... }; - if (reg.name == name_of(meta_function::equal_to)) { + if (reg.name == to_string(meta_function::equal_to)) { hasequals = true; } - if (reg.name == name_of(meta_function::less_than)) { + if (reg.name == to_string(meta_function::less_than)) { hasless = true; } - if (reg.name == name_of(meta_function::less_than_or_equal_to)) { + if (reg.name == to_string(meta_function::less_than_or_equal_to)) { haslessequals = true; } - if (reg.name == name_of(meta_function::garbage_collect)) { + if (reg.name == to_string(meta_function::garbage_collect)) { destructfunc = reg.func; return; } - else if (reg.name == name_of(meta_function::index)) { + else if (reg.name == to_string(meta_function::index)) { indexfunc = reg.func; mustindex = true; return; } - else if (reg.name == name_of(meta_function::new_index)) { + else if (reg.name == to_string(meta_function::new_index)) { newindexfunc = reg.func; mustindex = true; return; @@ -10796,7 +10796,7 @@ namespace sol { ) }... }; this->mapping.insert(ilist); - for (const auto& n : meta_function_names) { + for (const auto& n : meta_function_names()) { this->mapping.erase(n); } this->mustindex = contains_variable() || contains_index(); @@ -10950,7 +10950,7 @@ namespace sol { value_table[lastreg] = { nullptr, nullptr }; regs_t ref_table = value_table; regs_t unique_table = value_table; - bool hasdestructor = !value_table.empty() && name_of(meta_function::garbage_collect) == value_table[lastreg - 1].name; + bool hasdestructor = !value_table.empty() && to_string(meta_function::garbage_collect) == value_table[lastreg - 1].name; if (hasdestructor) { ref_table[lastreg - 1] = { nullptr, nullptr }; unique_table[lastreg - 1] = { value_table[lastreg - 1].name, detail::unique_destruct }; @@ -11399,29 +11399,29 @@ namespace sol { bool hasless = false; bool haslessequals = false; auto register_kvp = [&](std::size_t i, stack_reference& t, const std::string& first, object& second) { - if (first == name_of(meta_function::equal_to)) { + if (first == to_string(meta_function::equal_to)) { hasequals = true; } - else if (first == name_of(meta_function::less_than)) { + else if (first == to_string(meta_function::less_than)) { hasless = true; } - else if (first == name_of(meta_function::less_than_or_equal_to)) { + else if (first == to_string(meta_function::less_than_or_equal_to)) { haslessequals = true; } - else if (first == name_of(meta_function::index)) { + else if (first == to_string(meta_function::index)) { umx.indexfunc = second.template as(); } - else if (first == name_of(meta_function::new_index)) { + else if (first == to_string(meta_function::new_index)) { umx.newindexfunc = second.template as(); } switch (i) { case 0: - if (first == name_of(meta_function::garbage_collect)) { + if (first == to_string(meta_function::garbage_collect)) { return; } break; case 1: - if (first == name_of(meta_function::garbage_collect)) { + if (first == to_string(meta_function::garbage_collect)) { stack::set_field(L, first, detail::unique_destruct, t.stack_index()); return; } @@ -11457,15 +11457,15 @@ namespace sol { luaL_Reg opregs[4]{}; int opregsindex = 0; if (!hasless) { - const char* name = name_of(meta_function::less_than).c_str(); + const char* name = to_string(meta_function::less_than).c_str(); usertype_detail::make_reg_op, meta::supports_op_less>(opregs, opregsindex, name); } if (!haslessequals) { - const char* name = name_of(meta_function::less_than_or_equal_to).c_str(); + const char* name = to_string(meta_function::less_than_or_equal_to).c_str(); usertype_detail::make_reg_op, meta::supports_op_less_equal>(opregs, opregsindex, name); } if (!hasequals) { - const char* name = name_of(meta_function::equal_to).c_str(); + const char* name = to_string(meta_function::equal_to).c_str(); usertype_detail::make_reg_op::value, std::equal_to<>, usertype_detail::no_comp>, std::true_type>(opregs, opregsindex, name); } t.push(); diff --git a/sol/simple_usertype_metatable.hpp b/sol/simple_usertype_metatable.hpp index ffc1815d..15bfdaaa 100644 --- a/sol/simple_usertype_metatable.hpp +++ b/sol/simple_usertype_metatable.hpp @@ -376,29 +376,29 @@ namespace sol { bool hasless = false; bool haslessequals = false; auto register_kvp = [&](std::size_t i, stack_reference& t, const std::string& first, object& second) { - if (first == name_of(meta_function::equal_to)) { + if (first == to_string(meta_function::equal_to)) { hasequals = true; } - else if (first == name_of(meta_function::less_than)) { + else if (first == to_string(meta_function::less_than)) { hasless = true; } - else if (first == name_of(meta_function::less_than_or_equal_to)) { + else if (first == to_string(meta_function::less_than_or_equal_to)) { haslessequals = true; } - else if (first == name_of(meta_function::index)) { + else if (first == to_string(meta_function::index)) { umx.indexfunc = second.template as(); } - else if (first == name_of(meta_function::new_index)) { + else if (first == to_string(meta_function::new_index)) { umx.newindexfunc = second.template as(); } switch (i) { case 0: - if (first == name_of(meta_function::garbage_collect)) { + if (first == to_string(meta_function::garbage_collect)) { return; } break; case 1: - if (first == name_of(meta_function::garbage_collect)) { + if (first == to_string(meta_function::garbage_collect)) { stack::set_field(L, first, detail::unique_destruct, t.stack_index()); return; } @@ -434,15 +434,15 @@ namespace sol { luaL_Reg opregs[4]{}; int opregsindex = 0; if (!hasless) { - const char* name = name_of(meta_function::less_than).c_str(); + const char* name = to_string(meta_function::less_than).c_str(); usertype_detail::make_reg_op, meta::supports_op_less>(opregs, opregsindex, name); } if (!haslessequals) { - const char* name = name_of(meta_function::less_than_or_equal_to).c_str(); + const char* name = to_string(meta_function::less_than_or_equal_to).c_str(); usertype_detail::make_reg_op, meta::supports_op_less_equal>(opregs, opregsindex, name); } if (!hasequals) { - const char* name = name_of(meta_function::equal_to).c_str(); + const char* name = to_string(meta_function::equal_to).c_str(); usertype_detail::make_reg_op::value, std::equal_to<>, usertype_detail::no_comp>, std::true_type>(opregs, opregsindex, name); } t.push(); diff --git a/sol/stack_check.hpp b/sol/stack_check.hpp index 771331b3..7e64ad61 100644 --- a/sol/stack_check.hpp +++ b/sol/stack_check.hpp @@ -226,7 +226,7 @@ namespace sol { return false; } // Do advanced check for call-style userdata? - static const auto& callkey = name_of(meta_function::call); + static const auto& callkey = to_string(meta_function::call); if (lua_getmetatable(L, index) == 0) { // No metatable, no __call key possible handler(L, index, type::function, t); diff --git a/sol/stack_get.hpp b/sol/stack_get.hpp index 2b736ec7..6fd2f28c 100644 --- a/sol/stack_get.hpp +++ b/sol/stack_get.hpp @@ -401,8 +401,9 @@ namespace sol { static meta_function get(lua_State *L, int index, record& tracking) { tracking.use(1); const char* name = getter{}.get(L, index, tracking); - for (std::size_t i = 0; i < meta_function_names.size(); ++i) - if (meta_function_names[i] == name) + const auto& mfnames = meta_function_names(); + for (std::size_t i = 0; i < mfnames.size(); ++i) + if (mfnames[i] == name) return static_cast(i); return meta_function::construct; } diff --git a/sol/stack_push.hpp b/sol/stack_push.hpp index 318a8f59..34717dd3 100644 --- a/sol/stack_push.hpp +++ b/sol/stack_push.hpp @@ -466,7 +466,7 @@ namespace sol { template<> struct pusher { static int push(lua_State* L, meta_function m) { - const std::string& str = name_of(m); + const std::string& str = to_string(m); lua_pushlstring(L, str.c_str(), str.size()); return 1; } diff --git a/sol/types.hpp b/sol/types.hpp index 2e25b3c6..a44751bd 100644 --- a/sol/types.hpp +++ b/sol/types.hpp @@ -59,6 +59,7 @@ namespace sol { } #if !defined(SOL_EXCEPTIONS_SAFE_PROPAGATION) catch (...) { + std::exception_ptr eptr = std::current_exception(); lua_pushstring(L, "caught (...) exception"); } #endif @@ -493,47 +494,45 @@ namespace sol { typedef meta_function meta_method; - const std::array meta_variable_names = { { - "__index", - "__newindex", - } }; + inline const std::array& meta_function_names() { + static const std::array names = { { + "new", + "__index", + "__newindex", + "__mode", + "__call", + "__mt", + "__tostring", + "__len", + "__unm", + "__add", + "__sub", + "__mul", + "__div", + "__mod", + "__pow", + "__concat", + "__eq", + "__lt", + "__le", + "__gc", - const std::array meta_function_names = { { - "new", - "__index", - "__newindex", - "__mode", - "__call", - "__mt", - "__tostring", - "__len", - "__unm", - "__add", - "__sub", - "__mul", - "__div", - "__mod", - "__pow", - "__concat", - "__eq", - "__lt", - "__le", - "__gc", - - "__idiv", - "__shl", - "__shr", - "__bnot", - "__band", - "__bor", - "__bxor", + "__idiv", + "__shl", + "__shr", + "__bnot", + "__band", + "__bor", + "__bxor", - "__pairs", - "__next" - } }; + "__pairs", + "__next" + } }; + return names; + } - inline const std::string& name_of(meta_function mf) { - return meta_function_names[static_cast(mf)]; + inline const std::string& to_string(meta_function mf) { + return meta_function_names()[static_cast(mf)]; } inline type type_of(lua_State* L, int index) { diff --git a/sol/usertype_metatable.hpp b/sol/usertype_metatable.hpp index 1d4c29d2..f164f906 100644 --- a/sol/usertype_metatable.hpp +++ b/sol/usertype_metatable.hpp @@ -117,7 +117,7 @@ namespace sol { }; inline bool is_indexer(string_detail::string_shim s) { - return s == name_of(meta_function::index) || s == name_of(meta_function::new_index); + return s == to_string(meta_function::index) || s == to_string(meta_function::new_index); } inline bool is_indexer(meta_function mf) { @@ -137,11 +137,11 @@ namespace sol { } inline auto make_shim(call_construction) { - return string_detail::string_shim(name_of(meta_function::call_function)); + return string_detail::string_shim(to_string(meta_function::call_function)); } inline auto make_shim(meta_function mf) { - return string_detail::string_shim(name_of(mf)); + return string_detail::string_shim(to_string(mf)); } inline auto make_shim(base_classes_tag) { @@ -382,19 +382,19 @@ namespace sol { int finish_regs(regs_t& l, int& index) { if (!hasless) { - const char* name = name_of(meta_function::less_than).c_str(); + const char* name = to_string(meta_function::less_than).c_str(); usertype_detail::make_reg_op, meta::supports_op_less>(l, index, name); } if (!haslessequals) { - const char* name = name_of(meta_function::less_than_or_equal_to).c_str(); + const char* name = to_string(meta_function::less_than_or_equal_to).c_str(); usertype_detail::make_reg_op, meta::supports_op_less_equal>(l, index, name); } if (!hasequals) { - const char* name = name_of(meta_function::equal_to).c_str(); + const char* name = to_string(meta_function::equal_to).c_str(); usertype_detail::make_reg_op::value, std::equal_to<>, usertype_detail::no_comp>, std::true_type>(l, index, name); } if (destructfunc != nullptr) { - l[index] = { name_of(meta_function::garbage_collect).c_str(), destructfunc }; + l[index] = { to_string(meta_function::garbage_collect).c_str(), destructfunc }; ++index; } return index; @@ -431,25 +431,25 @@ namespace sol { // Returnable scope // That would be a neat keyword for C++ // returnable { ... }; - if (reg.name == name_of(meta_function::equal_to)) { + if (reg.name == to_string(meta_function::equal_to)) { hasequals = true; } - if (reg.name == name_of(meta_function::less_than)) { + if (reg.name == to_string(meta_function::less_than)) { hasless = true; } - if (reg.name == name_of(meta_function::less_than_or_equal_to)) { + if (reg.name == to_string(meta_function::less_than_or_equal_to)) { haslessequals = true; } - if (reg.name == name_of(meta_function::garbage_collect)) { + if (reg.name == to_string(meta_function::garbage_collect)) { destructfunc = reg.func; return; } - else if (reg.name == name_of(meta_function::index)) { + else if (reg.name == to_string(meta_function::index)) { indexfunc = reg.func; mustindex = true; return; } - else if (reg.name == name_of(meta_function::new_index)) { + else if (reg.name == to_string(meta_function::new_index)) { newindexfunc = reg.func; mustindex = true; return; @@ -474,7 +474,7 @@ namespace sol { ) }... }; this->mapping.insert(ilist); - for (const auto& n : meta_function_names) { + for (const auto& n : meta_function_names()) { this->mapping.erase(n); } this->mustindex = contains_variable() || contains_index(); @@ -628,7 +628,7 @@ namespace sol { value_table[lastreg] = { nullptr, nullptr }; regs_t ref_table = value_table; regs_t unique_table = value_table; - bool hasdestructor = !value_table.empty() && name_of(meta_function::garbage_collect) == value_table[lastreg - 1].name; + bool hasdestructor = !value_table.empty() && to_string(meta_function::garbage_collect) == value_table[lastreg - 1].name; if (hasdestructor) { ref_table[lastreg - 1] = { nullptr, nullptr }; unique_table[lastreg - 1] = { value_table[lastreg - 1].name, detail::unique_destruct };