diff --git a/CMakeLists.txt b/CMakeLists.txt index 888283fb..42542d55 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,7 +20,6 @@ target_link_libraries(boost_dll Boost::filesystem Boost::predef Boost::smart_ptr - Boost::spirit Boost::system Boost::throw_exception Boost::type_index diff --git a/build.jam b/build.jam index 19c19dd2..f5d93e2b 100644 --- a/build.jam +++ b/build.jam @@ -12,7 +12,6 @@ constant boost_dependencies : /boost/filesystem//boost_filesystem /boost/predef//boost_predef /boost/smart_ptr//boost_smart_ptr - /boost/spirit//boost_spirit /boost/system//boost_system /boost/throw_exception//boost_throw_exception /boost/type_index//boost_type_index diff --git a/include/boost/dll/alias.hpp b/include/boost/dll/alias.hpp index a30fbb5b..711fbe17 100644 --- a/include/boost/dll/alias.hpp +++ b/include/boost/dll/alias.hpp @@ -44,7 +44,7 @@ namespace boost { namespace dll { #define BOOST_DLL_SELECTANY __declspec(selectany) #define BOOST_DLL_SECTION(SectionName, Permissions) \ - static_assert( \ + static_assert( \ sizeof(#SectionName) < 10, \ "Some platforms require section names to be at most 8 bytes" \ ); \ @@ -83,7 +83,7 @@ namespace boost { namespace dll { * \param Permissions Can be "read" or "write" (without quotes!). */ #define BOOST_DLL_SECTION(SectionName, Permissions) \ - static_assert( \ + static_assert( \ sizeof(#SectionName) < 10, \ "Some platforms require section names to be at most 8 bytes" \ ); \ @@ -92,7 +92,7 @@ namespace boost { namespace dll { #else // #if !BOOST_OS_MACOS && !BOOST_OS_IOS #define BOOST_DLL_SECTION(SectionName, Permissions) \ - static_assert( \ + static_assert( \ sizeof(#SectionName) < 10, \ "Some platforms require section names to be at most 8 bytes" \ ); \ diff --git a/include/boost/dll/detail/demangling/msvc.hpp b/include/boost/dll/detail/demangling/msvc.hpp index 927428d4..e5b5aa04 100644 --- a/include/boost/dll/detail/demangling/msvc.hpp +++ b/include/boost/dll/detail/demangling/msvc.hpp @@ -8,12 +8,13 @@ #define BOOST_DLL_DETAIL_DEMANGLING_MSVC_HPP_ #include + +#include + #include #include #include -#include - namespace boost { namespace dll { namespace detail { class mangled_storage_impl : public mangled_storage_base @@ -21,11 +22,6 @@ class mangled_storage_impl : public mangled_storage_base template struct dummy {}; - template - std::vector get_func_params(dummy) const - { - return {get_name()...}; - } template std::string get_return_type(dummy) const { @@ -88,131 +84,247 @@ void mangled_storage_impl::trim_typename(std::string & val) } } +namespace parser { -namespace parser -{ - namespace x3 = spirit::x3; + inline bool try_consume_prefix(boost::core::string_view& s, boost::core::string_view prefix) { + const bool result = s.starts_with(prefix); + if (result) { + s.remove_prefix(prefix.size()); + } + return result; + } - inline auto ptr_rule_impl(std::integral_constant) - { - return -((-x3::space) >> "__ptr32"); + inline bool ignore_prefix(boost::core::string_view& s, boost::core::string_view prefix) { + parser::try_consume_prefix(s, prefix); + return true; } - inline auto ptr_rule_impl(std::integral_constant) - { - return -((-x3::space) >> "__ptr64"); + + inline void consume_ptrs(boost::core::string_view& s) { + do { + while (parser::try_consume_prefix(s, " ")) {} + } while (parser::try_consume_prefix(s, "__ptr32") || parser::try_consume_prefix(s, "__ptr64")); } - inline auto ptr_rule() { - return ptr_rule_impl(std::integral_constant()); + inline bool ignore_ptrs(boost::core::string_view& s) { + parser::consume_ptrs(s); + return true; } - auto const visibility = ("public:" | x3::lit("protected:") | "private:"); - auto const virtual_ = x3::space >> "virtual"; - auto const static_ = x3::space >> x3::lit("static") ; - - inline auto const_rule_impl(std::true_type ) {return x3::space >> "const";}; - inline auto const_rule_impl(std::false_type) {return x3::eps;}; - template - auto const_rule() {using t = std::is_const::type>; return const_rule_impl(t());} - - inline auto volatile_rule_impl(std::true_type ) {return x3::space >> "volatile";}; - inline auto volatile_rule_impl(std::false_type) {return x3::eps;}; - template - auto volatile_rule() {using t = std::is_volatile::type>; return volatile_rule_impl(t());} - - - inline auto inv_const_rule_impl(std::true_type ) {return "const" >> x3::space ;}; - inline auto inv_const_rule_impl(std::false_type) {return x3::eps;}; - template - auto inv_const_rule() {using t = std::is_const::type>; return inv_const_rule_impl(t());} + inline bool try_consume_visibility(boost::core::string_view& s) { + return parser::try_consume_prefix(s, "public:") + || parser::try_consume_prefix(s, "protected:") + || parser::try_consume_prefix(s, "private:"); + } - inline auto inv_volatile_rule_impl(std::true_type ) {return "volatile" >> x3::space;}; - inline auto inv_volatile_rule_impl(std::false_type) {return x3::eps;}; template - auto inv_volatile_rule() {using t = std::is_volatile::type>; return inv_volatile_rule_impl(t());} + bool try_consume_type(boost::core::string_view& s, const mangled_storage_impl& ms) { + if (std::is_void::value) { + return parser::try_consume_prefix(s, "void"); + } + parser::ignore_prefix(s, "class "); + parser::ignore_prefix(s, "struct "); - inline auto reference_rule_impl(std::false_type, std::false_type) {return x3::eps;} - inline auto reference_rule_impl(std::true_type, std::false_type) {return x3::space >>"&" ;} - inline auto reference_rule_impl(std::false_type, std::true_type ) {return x3::space >>"&&" ;} + const auto& mangled_name = ms.get_name(); + if (!parser::try_consume_prefix(s, mangled_name)) { + return false; + } + if (std::is_const::type>::value) { + if (!parser::try_consume_prefix(s, " const")) { + return false; + } + } - template - auto reference_rule() {using t_l = std::is_lvalue_reference; using t_r = std::is_rvalue_reference; return reference_rule_impl(t_l(), t_r());} + if (std::is_volatile::type>::value) { + if (!parser::try_consume_prefix(s, " volatile")) { + return false; + } + } - auto const class_ = ("class" | x3::lit("struct")); + if (std::is_rvalue_reference::value) { + if (!parser::try_consume_prefix(s, " &&")) { + return false; + } + } - //it takes a string, because it may be overloaded. - template - auto type_rule(const std::string & type_name) - { - using namespace std; + if (std::is_lvalue_reference::value) { + if (!parser::try_consume_prefix(s, " &")) { + return false; + } + } - return -(class_ >> x3::space)>> x3::string(type_name) >> - const_rule() >> - volatile_rule() >> - reference_rule() >> - ptr_rule(); + return parser::ignore_ptrs(s); } - template<> - inline auto type_rule(const std::string &) { return x3::string("void"); }; - auto const cdecl_ = "__cdecl" >> x3::space; - auto const stdcall = "__stdcall" >> x3::space; -#if defined(_WIN64)//seems to be necessary by msvc 14-x64 - auto const thiscall = "__cdecl" >> x3::space; -#else - auto const thiscall = "__thiscall" >> x3::space; -#endif + inline bool try_consume_thiscall(boost::core::string_view& s) { + parser::try_consume_prefix(s, " "); + return parser::try_consume_prefix(s, "__cdecl ") // Win 64bit + || parser::try_consume_prefix(s, "__thiscall "); // Win 32bit + } template - auto arg_list(const mangled_storage_impl & ms, Return (*)(Arg)) - { - return type_rule(ms.get_name()); + bool try_consume_arg_list(boost::core::string_view& s, const mangled_storage_impl& ms, Return (*)(Arg)) { + return parser::try_consume_type(s, ms); } template - auto arg_list(const mangled_storage_impl & ms, Return (*)(First, Second, Args...)) - { + bool try_consume_arg_list(boost::core::string_view& s, const mangled_storage_impl& ms, Return (*)(First, Second, Args...)) { using next_type = Return (*)(Second, Args...); - return type_rule(ms.get_name()) >> x3::char_(',') >> arg_list(ms, next_type()); + return parser::try_consume_type(s, ms) + && parser::try_consume_prefix(s, ",") + && parser::try_consume_arg_list(s, ms, next_type()); } template - auto arg_list(const mangled_storage_impl& /*ms*/, Return (*)()) - { - return x3::string("void"); + bool try_consume_arg_list(boost::core::string_view& s, const mangled_storage_impl& ms, Return (*)()) { + return parser::try_consume_type(s, ms); } -} + class is_destructor_with_name { + const std::string& dtor_name_; -template std::string mangled_storage_impl::get_variable(const std::string &name) const -{ - using namespace std; - using namespace boost; + public: + explicit is_destructor_with_name(const std::string& dtor_name) + : dtor_name_(dtor_name) {} - namespace x3 = spirit::x3; - using namespace parser; + inline bool operator()(boost::core::string_view s) const { + return parser::try_consume_visibility(s) + && parser::ignore_prefix(s, " virtual") + && parser::try_consume_thiscall(s) + && parser::try_consume_prefix(s, dtor_name_) + && parser::ignore_ptrs(s) + && s.empty(); + } - auto type_name = get_name(); + inline bool operator()(const mangled_storage_base::entry& e) const { + return (*this)(boost::core::string_view(e.demangled.data(), e.demangled.size())); + } + }; - auto matcher = - -(visibility >> static_ >> x3::space) >> //it may be a static class-member - parser::type_rule(type_name) >> x3::space >> - name; + template + class is_variable_with_name { + const std::string& variable_name_; + const mangled_storage_impl& ms_; + + public: + is_variable_with_name(const std::string& variable_name, const mangled_storage_impl& ms) + : variable_name_(variable_name), ms_(ms) {} + + inline bool operator()(boost::core::string_view s) const { + if (parser::try_consume_visibility(s) && !parser::try_consume_prefix(s, " static ")) { + return false; + } + + return parser::try_consume_type(s, ms_) + && parser::try_consume_prefix(s, variable_name_) + && s.empty(); + } - auto predicate = [&](const mangled_storage_base::entry & e) - { - if (e.demangled == name)//maybe not mangled, - return true; + inline bool operator()(const mangled_storage_base::entry& e) const { + return (*this)(boost::core::string_view(e.demangled.data(), e.demangled.size())); + } + }; + + template + class is_constructor_with_name { + const std::string& ctor_name_; + const mangled_storage_impl& ms_; + + public: + is_constructor_with_name(const std::string& ctor_name, const mangled_storage_impl& ms) + : ctor_name_(ctor_name), ms_(ms) {} + + inline bool operator()(boost::core::string_view s) const { + return parser::try_consume_visibility(s) + && parser::try_consume_thiscall(s) + && parser::try_consume_prefix(s, ctor_name_) + && parser::try_consume_prefix(s, "(") + && parser::try_consume_arg_list(s, ms_, Signature()) + && parser::try_consume_prefix(s, ")") + && parser::ignore_ptrs(s) + && s.empty(); + } - auto itr = e.demangled.begin(); - auto end = e.demangled.end(); - auto res = x3::parse(itr, end, matcher); - return res && (itr == end); - }; + inline bool operator()(const mangled_storage_base::entry& e) const { + return (*this)(boost::core::string_view(e.demangled.data(), e.demangled.size())); + } + }; + + template + class is_function_with_name; + + template + class is_function_with_name { + const std::string& function_name_; + const mangled_storage_impl& ms_; + + public: + is_function_with_name(const std::string& function_name, const mangled_storage_impl& ms) + : function_name_(function_name), ms_(ms) {} + + inline bool operator()(boost::core::string_view s) const { + if (parser::try_consume_visibility(s) && !parser::try_consume_prefix(s, " static ")) { + return false; + } + + using Signature = Result(*)(Args...); + return parser::try_consume_type(s, ms_) + && parser::ignore_prefix(s, " ") + && parser::try_consume_prefix(s, "__cdecl ") + && parser::try_consume_prefix(s, function_name_) + && parser::try_consume_prefix(s, "(") + && parser::try_consume_arg_list(s, ms_, Signature()) + && parser::try_consume_prefix(s, ")") + && parser::ignore_ptrs(s) + && s.empty(); + } - auto found = std::find_if(storage_.begin(), storage_.end(), predicate); + inline bool operator()(const mangled_storage_base::entry& e) const { + return (*this)(boost::core::string_view(e.demangled.data(), e.demangled.size())); + } + }; + + template + class is_mem_fn_with_name; + + template + class is_mem_fn_with_name { + const std::string& function_name_; + const mangled_storage_impl& ms_; + + public: + is_mem_fn_with_name(const std::string& function_name, const mangled_storage_impl& ms) + : function_name_(function_name), ms_(ms) {} + + inline bool operator()(boost::core::string_view s) const { + using Signature = Result(*)(Args...); + return parser::try_consume_visibility(s) + && parser::ignore_prefix(s, " virtual") + && parser::try_consume_prefix(s, " ") + && parser::try_consume_type(s, ms_) + && parser::try_consume_thiscall(s) + && parser::try_consume_type::type>(s, ms_) + && parser::try_consume_prefix(s, "::") + && parser::try_consume_prefix(s, function_name_) + && parser::try_consume_prefix(s, "(") + && parser::try_consume_arg_list(s, ms_, Signature()) + && parser::try_consume_prefix(s, ")") + && (!std::is_const::value || parser::try_consume_prefix(s, "const ")) + && (!std::is_volatile::value || parser::try_consume_prefix(s, "volatile ")) + && parser::ignore_ptrs(s) + && s.empty(); + } + + inline bool operator()(const mangled_storage_base::entry& e) const { + return (*this)(boost::core::string_view(e.demangled.data(), e.demangled.size())); + } + }; +} // namespace parser + +template +std::string mangled_storage_impl::get_variable(const std::string &name) const { + const auto found = std::find_if(storage_.begin(), storage_.end(), parser::is_variable_with_name(name, *this)); if (found != storage_.end()) return found->mangled; @@ -220,73 +332,19 @@ template std::string mangled_storage_impl::get_variable(const std::s return ""; } -template std::string mangled_storage_impl::get_function(const std::string &name) const -{ - namespace x3 = spirit::x3; - using namespace parser; - using func_type = Func*; - using return_type = typename function_traits::result_type; - std::string return_type_name = get_name(); - - - auto matcher = - -(visibility >> static_ >> x3::space) >> //it may be a static class-member, which does however not have the static attribute. - parser::type_rule(return_type_name) >> x3::space >> - cdecl_ >> //cdecl declaration for methods. stdcall cannot be - name >> x3::lit('(') >> parser::arg_list(*this, func_type()) >> x3::lit(')') >> parser::ptr_rule(); - - - auto predicate = [&](const mangled_storage_base::entry & e) - { - if (e.demangled == name)//maybe not mangled, - return true; - - auto itr = e.demangled.begin(); - auto end = e.demangled.end(); - auto res = x3::parse(itr, end, matcher); - - return res && (itr == end); - }; - - auto found = std::find_if(storage_.begin(), storage_.end(), predicate); +template +std::string mangled_storage_impl::get_function(const std::string &name) const { + const auto found = std::find_if(storage_.begin(), storage_.end(), parser::is_function_with_name(name, *this)); if (found != storage_.end()) return found->mangled; else return ""; - } template -std::string mangled_storage_impl::get_mem_fn(const std::string &name) const -{ - namespace x3 = spirit::x3; - using namespace parser; - using func_type = Func*; - using return_type = typename function_traits::result_type; - auto return_type_name = get_name(); - - - auto cname = get_name(); - - auto matcher = - visibility >> -virtual_ >> x3::space >> - parser::type_rule(return_type_name) >> x3::space >> - thiscall >> //cdecl declaration for methods. stdcall cannot be - cname >> "::" >> name >> - x3::lit('(') >> parser::arg_list(*this, func_type()) >> x3::lit(')') >> - inv_const_rule() >> inv_volatile_rule() >> parser::ptr_rule(); - - auto predicate = [&](const mangled_storage_base::entry & e) - { - auto itr = e.demangled.begin(); - auto end = e.demangled.end(); - auto res = x3::parse(itr, end, matcher); - - return res && (itr == end); - }; - - auto found = std::find_if(storage_.begin(), storage_.end(), predicate); +std::string mangled_storage_impl::get_mem_fn(const std::string &name) const { + const auto found = std::find_if(storage_.begin(), storage_.end(), parser::is_mem_fn_with_name(name, *this)); if (found != storage_.end()) return found->mangled; @@ -296,14 +354,7 @@ std::string mangled_storage_impl::get_mem_fn(const std::string &name) const template -auto mangled_storage_impl::get_constructor() const -> ctor_sym -{ - namespace x3 = spirit::x3; - using namespace parser; - - using func_type = Signature*; - - +auto mangled_storage_impl::get_constructor() const -> ctor_sym { std::string ctor_name; // = class_name + "::" + name; std::string unscoped_cname; //the unscoped class-name { @@ -321,23 +372,7 @@ auto mangled_storage_impl::get_constructor() const -> ctor_sym } } - auto matcher = - visibility >> x3::space >> - thiscall >> //cdecl declaration for methods. stdcall cannot be - ctor_name >> - x3::lit('(') >> parser::arg_list(*this, func_type()) >> x3::lit(')') >> parser::ptr_rule(); - - - auto predicate = [&](const mangled_storage_base::entry & e) - { - auto itr = e.demangled.begin(); - auto end = e.demangled.end(); - auto res = x3::parse(itr, end, matcher); - - return res && (itr == end); - }; - - auto f = std::find_if(storage_.begin(), storage_.end(), predicate); + const auto f = std::find_if(storage_.begin(), storage_.end(), parser::is_constructor_with_name(ctor_name, *this)); if (f != storage_.end()) return f->mangled; @@ -346,10 +381,7 @@ auto mangled_storage_impl::get_constructor() const -> ctor_sym } template -auto mangled_storage_impl::get_destructor() const -> dtor_sym -{ - namespace x3 = spirit::x3; - using namespace parser; +auto mangled_storage_impl::get_destructor() const -> dtor_sym { std::string dtor_name; // = class_name + "::" + name; std::string unscoped_cname; //the unscoped class-name { @@ -367,23 +399,7 @@ auto mangled_storage_impl::get_destructor() const -> dtor_sym } } - auto matcher = - visibility >> -virtual_ >> x3::space >> - thiscall >> //cdecl declaration for methods. stdcall cannot be - dtor_name >> parser::ptr_rule(); - - - auto predicate = [&](const mangled_storage_base::entry & e) - { - auto itr = e.demangled.begin(); - auto end = e.demangled.end(); - auto res = x3::parse(itr, end, matcher); - - return res && (itr == end); - }; - - auto found = std::find_if(storage_.begin(), storage_.end(), predicate); - + const auto found = std::find_if(storage_.begin(), storage_.end(), parser::is_destructor_with_name(dtor_name)); if (found != storage_.end()) return found->mangled; @@ -392,8 +408,7 @@ auto mangled_storage_impl::get_destructor() const -> dtor_sym } template -std::string mangled_storage_impl::get_vtable() const -{ +std::string mangled_storage_impl::get_vtable() const { std::string id = "const " + get_name() + "::`vftable'"; auto predicate = [&](const mangled_storage_base::entry & e) @@ -411,8 +426,7 @@ std::string mangled_storage_impl::get_vtable() const } template -std::vector mangled_storage_impl::get_related() const -{ +std::vector mangled_storage_impl::get_related() const { std::vector ret; auto name = get_name(); @@ -425,9 +439,6 @@ std::vector mangled_storage_impl::get_related() const return ret; } - }}} - - #endif /* BOOST_DLL_DETAIL_DEMANGLING_MSVC_HPP_ */ diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 692422e4..5779e7bf 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -99,6 +99,7 @@ project [ compile-fail section_name_too_big.cpp ] [ run shared_library_concurrent_load_test.cpp /boost/thread//boost_thread : : library1 library2 my_plugin_aggregator refcounting_plugin : shared ] [ run cpp_mangle_test.cpp : : cpp_plugin ] + [ run cpp_mangling.cpp ] [ run cpp_load_test.cpp : : cpp_plugin ] [ run cpp_import_test.cpp : : cpp_plugin ] [ run template_method_linux_test.cpp : : cpp_plugin ] diff --git a/test/cpp_mangling.cpp b/test/cpp_mangling.cpp new file mode 100644 index 00000000..34ba9901 --- /dev/null +++ b/test/cpp_mangling.cpp @@ -0,0 +1,159 @@ +// Copyright 2024 Antony Polukhin +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +// For more information, see http://www.boost.org + +#include + +#if (__cplusplus > 201402L) || (defined(_MSVC_LANG) && _MSVC_LANG > 201402L) +#include + +int main(int argc, char* argv[]) +{ + namespace parser = boost::dll::detail::parser; + + BOOST_TEST(parser::is_destructor_with_name("foo::~foo(void)")("public: __cdecl foo::~foo(void)")); + BOOST_TEST(parser::is_destructor_with_name("foo::~foo(void)")("private: __cdecl foo::~foo(void)")); + BOOST_TEST(parser::is_destructor_with_name("foo::~foo(void)")("protected: __cdecl foo::~foo(void)")); + + BOOST_TEST(parser::is_destructor_with_name("foo::~foo(void)")("public: virtual __cdecl foo::~foo(void)")); + BOOST_TEST(parser::is_destructor_with_name("foo::~foo(void)")("private: virtual __cdecl foo::~foo(void)")); + BOOST_TEST(parser::is_destructor_with_name("foo::~foo(void)")("protected: virtual __cdecl foo::~foo(void)")); + + BOOST_TEST(parser::is_destructor_with_name("foo::~foo(void)")("public: __cdecl foo::~foo(void) __ptr64")); + BOOST_TEST(parser::is_destructor_with_name("foo::~foo(void)")("private: __cdecl foo::~foo(void) __ptr64")); + BOOST_TEST(parser::is_destructor_with_name("foo::~foo(void)")("protected: __cdecl foo::~foo(void) __ptr64")); + + BOOST_TEST(parser::is_destructor_with_name("some_space::some_father::~some_father(void)")("public: __cdecl some_space::some_father::~some_father(void) __ptr64")); + + BOOST_TEST(parser::is_destructor_with_name("foo::~foo(void)")("public: __thiscall foo::~foo(void)")); + BOOST_TEST(parser::is_destructor_with_name("foo::~foo(void)")("private: __thiscall foo::~foo(void)")); + BOOST_TEST(parser::is_destructor_with_name("foo::~foo(void)")("protected: __thiscall foo::~foo(void)")); + + BOOST_TEST(parser::is_destructor_with_name("foo::~foo(void)")("public: virtual __thiscall foo::~foo(void)")); + BOOST_TEST(parser::is_destructor_with_name("foo::~foo(void)")("private: virtual __thiscall foo::~foo(void)")); + BOOST_TEST(parser::is_destructor_with_name("foo::~foo(void)")("protected: virtual __thiscall foo::~foo(void)")); + + BOOST_TEST(parser::is_destructor_with_name("foo::~foo(void)")("public: __thiscall foo::~foo(void) __ptr32")); + BOOST_TEST(parser::is_destructor_with_name("foo::~foo(void)")("private: __thiscall foo::~foo(void) __ptr32")); + BOOST_TEST(parser::is_destructor_with_name("foo::~foo(void)")("protected: __thiscall foo::~foo(void) __ptr32")); + + BOOST_TEST(parser::is_destructor_with_name("some_space::some_father::~some_father(void)")("public: __thiscall some_space::some_father::~some_father(void) __ptr64")); + + + boost::dll::detail::mangled_storage_impl ms; + { + void(*ptr0)(int) = nullptr; + boost::core::string_view s = "integer"; + BOOST_TEST(parser::try_consume_arg_list(s, ms, ptr0)); + BOOST_TEST_EQ(s, "eger"); + } + { + void(*ptr1)(int) = nullptr; + boost::core::string_view s = "int"; + BOOST_TEST(parser::try_consume_arg_list(s, ms, ptr1)); + BOOST_TEST(s.empty()); + } + { + void(*ptr2)() = nullptr; + boost::core::string_view s = "void"; + BOOST_TEST(parser::try_consume_arg_list(s, ms, ptr2)); + BOOST_TEST(s.empty()); + } + { + void(*ptr3)(int,int) = nullptr; + boost::core::string_view s = "int,int"; + BOOST_TEST(parser::try_consume_arg_list(s, ms, ptr3)); + BOOST_TEST(s.empty()); + } + { + void(*ptr4)(int,int,int) = nullptr; + boost::core::string_view s = "int,int,int"; + BOOST_TEST(parser::try_consume_arg_list(s, ms, ptr4)); + BOOST_TEST(s.empty()); + } + + + BOOST_TEST(( + parser::is_constructor_with_name("some_space::some_class::some_class", ms) + ("public: __cdecl some_space::some_class::some_class(void) __ptr64") + )); + BOOST_TEST(( + parser::is_constructor_with_name("some_space::some_class::some_class", ms) + ("private: __cdecl some_space::some_class::some_class(int)") + )); + BOOST_TEST(( + parser::is_constructor_with_name("some_space::some_class::some_class", ms) + ("private: __cdecl some_space::some_class::some_class(int,int)") + )); + + + BOOST_TEST(( + parser::is_variable_with_name("some_space::some_class::value", ms) + ("public: static int some_space::some_class::value") + )); + + BOOST_TEST(( + parser::is_variable_with_name("some_space::some_class::value", ms) + ("int some_space::some_class::value") + )); + + BOOST_TEST(( + parser::is_variable_with_name("some_space::variable", ms) + ("public: static double some_space::variable") + )); + + BOOST_TEST(( + !parser::is_variable_with_name("some_space::variable", ms) + ("public: static int some_space::variable_that_is_not_exist") + )); + + BOOST_TEST(( + parser::is_variable_with_name("unscoped_c_var", ms) + ("double const unscoped_c_var") + )); + + + BOOST_TEST(( + parser::is_function_with_name("overloaded", ms) + ("void __cdecl overloaded(int)") + )); + + BOOST_TEST(( + parser::is_function_with_name("overloaded", ms) + ("void __cdecl overloaded(double)") + )); + + BOOST_TEST(( + parser::is_function_with_name("some_space::scoped_fun", ms) + ("int const & __ptr64 __cdecl some_space::scoped_fun(void)") + )); + + + BOOST_TEST(( + parser::is_mem_fn_with_name("func", ms) + ("public: int __thiscall int::func(int,int)volatile ") + )); + BOOST_TEST(( + parser::is_mem_fn_with_name("func", ms) + ("private: double __thiscall int::func(double)const volatile ") + )); + + BOOST_TEST(( + parser::is_mem_fn_with_name("func", ms) + ("public: int __cdecl int::func(int,int)volatile __ptr64") + )); + + BOOST_TEST(( + parser::is_mem_fn_with_name("func", ms) + ("public: virtual int __cdecl int::func(int,int)volatile __ptr64") + )); + + return boost::report_errors(); +} +#else +int main() {return 0;} +#endif diff --git a/test/shared_library_errors.cpp b/test/shared_library_errors.cpp index b5f532cf..5fce7f43 100644 --- a/test/shared_library_errors.cpp +++ b/test/shared_library_errors.cpp @@ -12,7 +12,6 @@ #include #include #include -#include // Unit Tests