msvc.hpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441
  1. // Copyright 2016 Klemens Morgenstern
  2. //
  3. // Distributed under the Boost Software License, Version 1.0.
  4. // (See accompanying file LICENSE_1_0.txt
  5. // or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. #ifndef BOOST_DLL_DETAIL_DEMANGLING_MSVC_HPP_
  7. #define BOOST_DLL_DETAIL_DEMANGLING_MSVC_HPP_
  8. #include <boost/dll/detail/demangling/mangled_storage_base.hpp>
  9. #include <iterator>
  10. #include <algorithm>
  11. #include <boost/type_traits/is_const.hpp>
  12. #include <boost/type_traits/is_volatile.hpp>
  13. #include <boost/type_traits/is_lvalue_reference.hpp>
  14. #include <boost/type_traits/is_rvalue_reference.hpp>
  15. #include <boost/type_traits/function_traits.hpp>
  16. #include <boost/type_traits/remove_reference.hpp>
  17. #include <boost/spirit/home/x3.hpp>
  18. namespace boost { namespace dll { namespace detail {
  19. class mangled_storage_impl : public mangled_storage_base
  20. {
  21. template<typename T>
  22. struct dummy {};
  23. template<typename Return, typename ...Args>
  24. std::vector<std::string> get_func_params(dummy<Return(Args...)>) const
  25. {
  26. return {get_name<Args>()...};
  27. }
  28. template<typename Return, typename ...Args>
  29. std::string get_return_type(dummy<Return(Args...)>) const
  30. {
  31. return get_name<Return>();
  32. }
  33. //function to remove preceding 'class ' or 'struct ' if the are given in this format.
  34. inline static void trim_typename(std::string & val);
  35. public:
  36. using ctor_sym = std::string;
  37. using dtor_sym = std::string;
  38. using mangled_storage_base::mangled_storage_base;
  39. template<typename T>
  40. std::string get_variable(const std::string &name) const;
  41. template<typename Func>
  42. std::string get_function(const std::string &name) const;
  43. template<typename Class, typename Func>
  44. std::string get_mem_fn(const std::string &name) const;
  45. template<typename Signature>
  46. ctor_sym get_constructor() const;
  47. template<typename Class>
  48. dtor_sym get_destructor() const;
  49. template<typename T> //overload, does not need to virtual.
  50. std::string get_name() const
  51. {
  52. auto nm = mangled_storage_base::get_name<T>();
  53. trim_typename(nm);
  54. return nm;
  55. }
  56. template<typename T>
  57. std::string get_vtable() const;
  58. template<typename T>
  59. std::vector<std::string> get_related() const;
  60. };
  61. void mangled_storage_impl::trim_typename(std::string & val)
  62. {
  63. //remove preceding class or struct, because you might want to use a struct as class, et vice versa
  64. if (val.size() >= 6)
  65. {
  66. using namespace std;
  67. static constexpr char class_ [7] = "class ";
  68. static constexpr char struct_[8] = "struct ";
  69. if (equal(begin(class_), end(class_)-1, val.begin())) //aklright, starts with 'class '
  70. val.erase(0, 6);
  71. else if (val.size() >= 7)
  72. if (equal(begin(struct_), end(struct_)-1, val.begin()))
  73. val.erase(0, 7);
  74. }
  75. }
  76. namespace parser
  77. {
  78. namespace x3 = spirit::x3;
  79. inline auto ptr_rule_impl(std::integral_constant<std::size_t, 32>)
  80. {
  81. return -((-x3::space) >> "__ptr32");
  82. }
  83. inline auto ptr_rule_impl(std::integral_constant<std::size_t, 64>)
  84. {
  85. return -((-x3::space) >> "__ptr64");
  86. }
  87. inline auto ptr_rule() {
  88. return ptr_rule_impl(std::integral_constant<std::size_t, sizeof(std::size_t)*8>());
  89. }
  90. auto const visibility = ("public:" | x3::lit("protected:") | "private:");
  91. auto const virtual_ = x3::space >> "virtual";
  92. auto const static_ = x3::space >> x3::lit("static") ;
  93. inline auto const_rule_impl(true_type ) {return x3::space >> "const";};
  94. inline auto const_rule_impl(false_type) {return x3::eps;};
  95. template<typename T>
  96. auto const_rule() {using t = is_const<typename remove_reference<T>::type>; return const_rule_impl(t());}
  97. inline auto volatile_rule_impl(true_type ) {return x3::space >> "volatile";};
  98. inline auto volatile_rule_impl(false_type) {return x3::eps;};
  99. template<typename T>
  100. auto volatile_rule() {using t = is_volatile<typename remove_reference<T>::type>; return volatile_rule_impl(t());}
  101. inline auto inv_const_rule_impl(true_type ) {return "const" >> x3::space ;};
  102. inline auto inv_const_rule_impl(false_type) {return x3::eps;};
  103. template<typename T>
  104. auto inv_const_rule() {using t = is_const<typename remove_reference<T>::type>; return inv_const_rule_impl(t());}
  105. inline auto inv_volatile_rule_impl(true_type ) {return "volatile" >> x3::space;};
  106. inline auto inv_volatile_rule_impl(false_type) {return x3::eps;};
  107. template<typename T>
  108. auto inv_volatile_rule() {using t = is_volatile<typename remove_reference<T>::type>; return inv_volatile_rule_impl(t());}
  109. inline auto reference_rule_impl(false_type, false_type) {return x3::eps;}
  110. inline auto reference_rule_impl(true_type, false_type) {return x3::space >>"&" ;}
  111. inline auto reference_rule_impl(false_type, true_type ) {return x3::space >>"&&" ;}
  112. template<typename T>
  113. auto reference_rule() {using t_l = is_lvalue_reference<T>; using t_r = is_rvalue_reference<T>; return reference_rule_impl(t_l(), t_r());}
  114. auto const class_ = ("class" | x3::lit("struct"));
  115. //it takes a string, because it may be overloaded.
  116. template<typename T>
  117. auto type_rule(const std::string & type_name)
  118. {
  119. using namespace std;
  120. return -(class_ >> x3::space)>> x3::string(type_name) >>
  121. const_rule<T>() >>
  122. volatile_rule<T>() >>
  123. reference_rule<T>() >>
  124. ptr_rule();
  125. }
  126. template<>
  127. inline auto type_rule<void>(const std::string &) { return x3::string("void"); };
  128. auto const cdecl_ = "__cdecl" >> x3::space;
  129. auto const stdcall = "__stdcall" >> x3::space;
  130. #if defined(_WIN64)//seems to be necessary by msvc 14-x64
  131. auto const thiscall = "__cdecl" >> x3::space;
  132. #else
  133. auto const thiscall = "__thiscall" >> x3::space;
  134. #endif
  135. template<typename Return, typename Arg>
  136. auto arg_list(const mangled_storage_impl & ms, Return (*)(Arg))
  137. {
  138. using namespace std;
  139. return type_rule<Arg>(ms.get_name<Arg>());
  140. }
  141. template<typename Return, typename First, typename Second, typename ...Args>
  142. auto arg_list(const mangled_storage_impl & ms, Return (*)(First, Second, Args...))
  143. {
  144. using next_type = Return (*)(Second, Args...);
  145. return type_rule<First>(ms.get_name<First>()) >> x3::char_(',') >> arg_list(ms, next_type());
  146. }
  147. template<typename Return>
  148. auto arg_list(const mangled_storage_impl& /*ms*/, Return (*)())
  149. {
  150. return x3::string("void");
  151. }
  152. }
  153. template<typename T> std::string mangled_storage_impl::get_variable(const std::string &name) const
  154. {
  155. using namespace std;
  156. using namespace boost;
  157. namespace x3 = spirit::x3;
  158. using namespace parser;
  159. auto type_name = get_name<T>();
  160. auto matcher =
  161. -(visibility >> static_ >> x3::space) >> //it may be a static class-member
  162. parser::type_rule<T>(type_name) >> x3::space >>
  163. name;
  164. auto predicate = [&](const mangled_storage_base::entry & e)
  165. {
  166. if (e.demangled == name)//maybe not mangled,
  167. return true;
  168. auto itr = e.demangled.begin();
  169. auto end = e.demangled.end();
  170. auto res = x3::parse(itr, end, matcher);
  171. return res && (itr == end);
  172. };
  173. auto found = std::find_if(storage_.begin(), storage_.end(), predicate);
  174. if (found != storage_.end())
  175. return found->mangled;
  176. else
  177. return "";
  178. }
  179. template<typename Func> std::string mangled_storage_impl::get_function(const std::string &name) const
  180. {
  181. namespace x3 = spirit::x3;
  182. using namespace parser;
  183. using func_type = Func*;
  184. using return_type = typename function_traits<Func>::result_type;
  185. std::string return_type_name = get_name<return_type>();
  186. auto matcher =
  187. -(visibility >> static_ >> x3::space) >> //it may be a static class-member, which does however not have the static attribute.
  188. parser::type_rule<return_type>(return_type_name) >> x3::space >>
  189. cdecl_ >> //cdecl declaration for methods. stdcall cannot be
  190. name >> x3::lit('(') >> parser::arg_list(*this, func_type()) >> x3::lit(')') >> parser::ptr_rule();
  191. auto predicate = [&](const mangled_storage_base::entry & e)
  192. {
  193. if (e.demangled == name)//maybe not mangled,
  194. return true;
  195. auto itr = e.demangled.begin();
  196. auto end = e.demangled.end();
  197. auto res = x3::parse(itr, end, matcher);
  198. return res && (itr == end);
  199. };
  200. auto found = std::find_if(storage_.begin(), storage_.end(), predicate);
  201. if (found != storage_.end())
  202. return found->mangled;
  203. else
  204. return "";
  205. }
  206. template<typename Class, typename Func>
  207. std::string mangled_storage_impl::get_mem_fn(const std::string &name) const
  208. {
  209. namespace x3 = spirit::x3;
  210. using namespace parser;
  211. using func_type = Func*;
  212. using return_type = typename function_traits<Func>::result_type;
  213. auto return_type_name = get_name<return_type>();
  214. auto cname = get_name<Class>();
  215. auto matcher =
  216. visibility >> -virtual_ >> x3::space >>
  217. parser::type_rule<return_type>(return_type_name) >> x3::space >>
  218. thiscall >> //cdecl declaration for methods. stdcall cannot be
  219. cname >> "::" >> name >>
  220. x3::lit('(') >> parser::arg_list(*this, func_type()) >> x3::lit(')') >>
  221. inv_const_rule<Class>() >> inv_volatile_rule<Class>() >> parser::ptr_rule();
  222. auto predicate = [&](const mangled_storage_base::entry & e)
  223. {
  224. auto itr = e.demangled.begin();
  225. auto end = e.demangled.end();
  226. auto res = x3::parse(itr, end, matcher);
  227. return res && (itr == end);
  228. };
  229. auto found = std::find_if(storage_.begin(), storage_.end(), predicate);
  230. if (found != storage_.end())
  231. return found->mangled;
  232. else
  233. return "";
  234. }
  235. template<typename Signature>
  236. auto mangled_storage_impl::get_constructor() const -> ctor_sym
  237. {
  238. namespace x3 = spirit::x3;
  239. using namespace parser;
  240. using func_type = Signature*;
  241. std::string ctor_name; // = class_name + "::" + name;
  242. std::string unscoped_cname; //the unscoped class-name
  243. {
  244. auto class_name = get_return_type(dummy<Signature>());
  245. auto pos = class_name.rfind("::");
  246. if (pos == std::string::npos)
  247. {
  248. ctor_name = class_name+ "::" + class_name ;
  249. unscoped_cname = class_name;
  250. }
  251. else
  252. {
  253. unscoped_cname = class_name.substr(pos+2) ;
  254. ctor_name = class_name+ "::" + unscoped_cname;
  255. }
  256. }
  257. auto matcher =
  258. visibility >> x3::space >>
  259. thiscall >> //cdecl declaration for methods. stdcall cannot be
  260. ctor_name >>
  261. x3::lit('(') >> parser::arg_list(*this, func_type()) >> x3::lit(')') >> parser::ptr_rule();
  262. auto predicate = [&](const mangled_storage_base::entry & e)
  263. {
  264. auto itr = e.demangled.begin();
  265. auto end = e.demangled.end();
  266. auto res = x3::parse(itr, end, matcher);
  267. return res && (itr == end);
  268. };
  269. auto f = std::find_if(storage_.begin(), storage_.end(), predicate);
  270. if (f != storage_.end())
  271. return f->mangled;
  272. else
  273. return "";
  274. }
  275. template<typename Class>
  276. auto mangled_storage_impl::get_destructor() const -> dtor_sym
  277. {
  278. namespace x3 = spirit::x3;
  279. using namespace parser;
  280. std::string dtor_name; // = class_name + "::" + name;
  281. std::string unscoped_cname; //the unscoped class-name
  282. {
  283. auto class_name = get_name<Class>();
  284. auto pos = class_name.rfind("::");
  285. if (pos == std::string::npos)
  286. {
  287. dtor_name = class_name+ "::~" + class_name + "(void)";
  288. unscoped_cname = class_name;
  289. }
  290. else
  291. {
  292. unscoped_cname = class_name.substr(pos+2) ;
  293. dtor_name = class_name+ "::~" + unscoped_cname + "(void)";
  294. }
  295. }
  296. auto matcher =
  297. visibility >> -virtual_ >> x3::space >>
  298. thiscall >> //cdecl declaration for methods. stdcall cannot be
  299. dtor_name >> parser::ptr_rule();
  300. auto predicate = [&](const mangled_storage_base::entry & e)
  301. {
  302. auto itr = e.demangled.begin();
  303. auto end = e.demangled.end();
  304. auto res = x3::parse(itr, end, matcher);
  305. return res && (itr == end);
  306. };
  307. auto found = std::find_if(storage_.begin(), storage_.end(), predicate);
  308. if (found != storage_.end())
  309. return found->mangled;
  310. else
  311. return "";
  312. }
  313. template<typename T>
  314. std::string mangled_storage_impl::get_vtable() const
  315. {
  316. std::string id = "const " + get_name<T>() + "::`vftable'";
  317. auto predicate = [&](const mangled_storage_base::entry & e)
  318. {
  319. return e.demangled == id;
  320. };
  321. auto found = std::find_if(storage_.begin(), storage_.end(), predicate);
  322. if (found != storage_.end())
  323. return found->mangled;
  324. else
  325. return "";
  326. }
  327. template<typename T>
  328. std::vector<std::string> mangled_storage_impl::get_related() const
  329. {
  330. std::vector<std::string> ret;
  331. auto name = get_name<T>();
  332. for (auto & c : storage_)
  333. {
  334. if (c.demangled.find(name) != std::string::npos)
  335. ret.push_back(c.demangled);
  336. }
  337. return ret;
  338. }
  339. }}}
  340. #endif /* BOOST_DLL_DETAIL_DEMANGLING_MSVC_HPP_ */