]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/dll/detail/demangling/msvc.hpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / boost / dll / detail / demangling / msvc.hpp
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
7 #ifndef BOOST_DLL_DETAIL_DEMANGLING_MSVC_HPP_
8 #define BOOST_DLL_DETAIL_DEMANGLING_MSVC_HPP_
9
10 #include <boost/dll/detail/demangling/mangled_storage_base.hpp>
11 #include <iterator>
12 #include <algorithm>
13 #include <boost/type_traits/is_const.hpp>
14 #include <boost/type_traits/is_volatile.hpp>
15 #include <boost/type_traits/is_lvalue_reference.hpp>
16 #include <boost/type_traits/is_rvalue_reference.hpp>
17 #include <boost/type_traits/function_traits.hpp>
18 #include <boost/type_traits/remove_reference.hpp>
19
20 #include <boost/spirit/home/x3.hpp>
21
22 namespace boost { namespace dll { namespace detail {
23
24 class mangled_storage_impl : public mangled_storage_base
25 {
26 template<typename T>
27 struct dummy {};
28
29 template<typename Return, typename ...Args>
30 std::vector<std::string> get_func_params(dummy<Return(Args...)>) const
31 {
32 return {get_name<Args>()...};
33 }
34 template<typename Return, typename ...Args>
35 std::string get_return_type(dummy<Return(Args...)>) const
36 {
37 return get_name<Return>();
38 }
39 //function to remove preceding 'class ' or 'struct ' if the are given in this format.
40
41 inline static void trim_typename(std::string & val);
42 public:
43 using ctor_sym = std::string;
44 using dtor_sym = std::string;
45
46 using mangled_storage_base::mangled_storage_base;
47
48 template<typename T>
49 std::string get_variable(const std::string &name) const;
50
51 template<typename Func>
52 std::string get_function(const std::string &name) const;
53
54 template<typename Class, typename Func>
55 std::string get_mem_fn(const std::string &name) const;
56
57 template<typename Signature>
58 ctor_sym get_constructor() const;
59
60 template<typename Class>
61 dtor_sym get_destructor() const;
62
63 template<typename T> //overload, does not need to virtual.
64 std::string get_name() const
65 {
66 auto nm = mangled_storage_base::get_name<T>();
67 trim_typename(nm);
68 return nm;
69 }
70
71 template<typename T>
72 std::string get_vtable() const;
73
74 template<typename T>
75 std::vector<std::string> get_related() const;
76
77 };
78
79 void mangled_storage_impl::trim_typename(std::string & val)
80 {
81 //remove preceding class or struct, because you might want to use a struct as class, et vice versa
82 if (val.size() >= 6)
83 {
84 using namespace std;
85 static constexpr char class_ [7] = "class ";
86 static constexpr char struct_[8] = "struct ";
87
88 if (equal(begin(class_), end(class_)-1, val.begin())) //aklright, starts with 'class '
89 val.erase(0, 6);
90 else if (val.size() >= 7)
91 if (equal(begin(struct_), end(struct_)-1, val.begin()))
92 val.erase(0, 7);
93 }
94 }
95
96
97 namespace parser
98 {
99 namespace x3 = spirit::x3;
100
101 inline auto ptr_rule_impl(std::integral_constant<std::size_t, 32>)
102 {
103 return -((-x3::space) >> "__ptr32");
104 }
105 inline auto ptr_rule_impl(std::integral_constant<std::size_t, 64>)
106 {
107 return -((-x3::space) >> "__ptr64");
108 }
109
110 inline auto ptr_rule() {
111 return ptr_rule_impl(std::integral_constant<std::size_t, sizeof(std::size_t)*8>());
112 }
113
114 auto const visibility = ("public:" | x3::lit("protected:") | "private:");
115 auto const virtual_ = x3::space >> "virtual";
116 auto const static_ = x3::space >> x3::lit("static") ;
117
118 inline auto const_rule_impl(true_type ) {return x3::space >> "const";};
119 inline auto const_rule_impl(false_type) {return x3::eps;};
120 template<typename T>
121 auto const_rule() {using t = is_const<typename remove_reference<T>::type>; return const_rule_impl(t());}
122
123 inline auto volatile_rule_impl(true_type ) {return x3::space >> "volatile";};
124 inline auto volatile_rule_impl(false_type) {return x3::eps;};
125 template<typename T>
126 auto volatile_rule() {using t = is_volatile<typename remove_reference<T>::type>; return volatile_rule_impl(t());}
127
128
129 inline auto inv_const_rule_impl(true_type ) {return "const" >> x3::space ;};
130 inline auto inv_const_rule_impl(false_type) {return x3::eps;};
131 template<typename T>
132 auto inv_const_rule() {using t = is_const<typename remove_reference<T>::type>; return inv_const_rule_impl(t());}
133
134 inline auto inv_volatile_rule_impl(true_type ) {return "volatile" >> x3::space;};
135 inline auto inv_volatile_rule_impl(false_type) {return x3::eps;};
136 template<typename T>
137 auto inv_volatile_rule() {using t = is_volatile<typename remove_reference<T>::type>; return inv_volatile_rule_impl(t());}
138
139
140 inline auto reference_rule_impl(false_type, false_type) {return x3::eps;}
141 inline auto reference_rule_impl(true_type, false_type) {return x3::space >>"&" ;}
142 inline auto reference_rule_impl(false_type, true_type ) {return x3::space >>"&&" ;}
143
144
145 template<typename T>
146 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());}
147
148 auto const class_ = ("class" | x3::lit("struct"));
149
150 //it takes a string, because it may be overloaded.
151 template<typename T>
152 auto type_rule(const std::string & type_name)
153 {
154 using namespace std;
155
156 return -(class_ >> x3::space)>> x3::string(type_name) >>
157 const_rule<T>() >>
158 volatile_rule<T>() >>
159 reference_rule<T>() >>
160 ptr_rule();
161 }
162 template<>
163 inline auto type_rule<void>(const std::string &) { return x3::string("void"); };
164
165 auto const cdecl_ = "__cdecl" >> x3::space;
166 auto const stdcall = "__stdcall" >> x3::space;
167 #if defined(_WIN64)//seems to be necessary by msvc 14-x64
168 auto const thiscall = "__cdecl" >> x3::space;
169 #else
170 auto const thiscall = "__thiscall" >> x3::space;
171 #endif
172
173 template<typename Return, typename Arg>
174 auto arg_list(const mangled_storage_impl & ms, Return (*)(Arg))
175 {
176 using namespace std;
177
178 return type_rule<Arg>(ms.get_name<Arg>());
179 }
180
181 template<typename Return, typename First, typename Second, typename ...Args>
182 auto arg_list(const mangled_storage_impl & ms, Return (*)(First, Second, Args...))
183 {
184
185 using next_type = Return (*)(Second, Args...);
186 return type_rule<First>(ms.get_name<First>()) >> x3::char_(',') >> arg_list(ms, next_type());
187 }
188
189 template<typename Return>
190 auto arg_list(const mangled_storage_impl& /*ms*/, Return (*)())
191 {
192 return x3::string("void");
193 }
194 }
195
196
197 template<typename T> std::string mangled_storage_impl::get_variable(const std::string &name) const
198 {
199 using namespace std;
200 using namespace boost;
201
202 namespace x3 = spirit::x3;
203 using namespace parser;
204
205 auto type_name = get_name<T>();
206
207 auto matcher =
208 -(visibility >> static_ >> x3::space) >> //it may be a static class-member
209 parser::type_rule<T>(type_name) >> x3::space >>
210 name;
211
212 auto predicate = [&](const mangled_storage_base::entry & e)
213 {
214 if (e.demangled == name)//maybe not mangled,
215 return true;
216
217 auto itr = e.demangled.begin();
218 auto end = e.demangled.end();
219 auto res = x3::parse(itr, end, matcher);
220 return res && (itr == end);
221 };
222
223 auto found = std::find_if(storage_.begin(), storage_.end(), predicate);
224
225 if (found != storage_.end())
226 return found->mangled;
227 else
228 return "";
229 }
230
231 template<typename Func> std::string mangled_storage_impl::get_function(const std::string &name) const
232 {
233 namespace x3 = spirit::x3;
234 using namespace parser;
235 using func_type = Func*;
236 using return_type = typename function_traits<Func>::result_type;
237 std::string return_type_name = get_name<return_type>();
238
239
240 auto matcher =
241 -(visibility >> static_ >> x3::space) >> //it may be a static class-member, which does however not have the static attribute.
242 parser::type_rule<return_type>(return_type_name) >> x3::space >>
243 cdecl_ >> //cdecl declaration for methods. stdcall cannot be
244 name >> x3::lit('(') >> parser::arg_list(*this, func_type()) >> x3::lit(')') >> parser::ptr_rule();
245
246
247 auto predicate = [&](const mangled_storage_base::entry & e)
248 {
249 if (e.demangled == name)//maybe not mangled,
250 return true;
251
252 auto itr = e.demangled.begin();
253 auto end = e.demangled.end();
254 auto res = x3::parse(itr, end, matcher);
255
256 return res && (itr == end);
257 };
258
259 auto found = std::find_if(storage_.begin(), storage_.end(), predicate);
260
261 if (found != storage_.end())
262 return found->mangled;
263 else
264 return "";
265
266 }
267
268 template<typename Class, typename Func>
269 std::string mangled_storage_impl::get_mem_fn(const std::string &name) const
270 {
271 namespace x3 = spirit::x3;
272 using namespace parser;
273 using func_type = Func*;
274 using return_type = typename function_traits<Func>::result_type;
275 auto return_type_name = get_name<return_type>();
276
277
278 auto cname = get_name<Class>();
279
280 auto matcher =
281 visibility >> -virtual_ >> x3::space >>
282 parser::type_rule<return_type>(return_type_name) >> x3::space >>
283 thiscall >> //cdecl declaration for methods. stdcall cannot be
284 cname >> "::" >> name >>
285 x3::lit('(') >> parser::arg_list(*this, func_type()) >> x3::lit(')') >>
286 inv_const_rule<Class>() >> inv_volatile_rule<Class>() >> parser::ptr_rule();
287
288 auto predicate = [&](const mangled_storage_base::entry & e)
289 {
290 auto itr = e.demangled.begin();
291 auto end = e.demangled.end();
292 auto res = x3::parse(itr, end, matcher);
293
294 return res && (itr == end);
295 };
296
297 auto found = std::find_if(storage_.begin(), storage_.end(), predicate);
298
299 if (found != storage_.end())
300 return found->mangled;
301 else
302 return "";
303 }
304
305
306 template<typename Signature>
307 auto mangled_storage_impl::get_constructor() const -> ctor_sym
308 {
309 namespace x3 = spirit::x3;
310 using namespace parser;
311
312 using func_type = Signature*;
313
314
315 std::string ctor_name; // = class_name + "::" + name;
316 std::string unscoped_cname; //the unscoped class-name
317 {
318 auto class_name = get_return_type(dummy<Signature>());
319 auto pos = class_name.rfind("::");
320 if (pos == std::string::npos)
321 {
322 ctor_name = class_name+ "::" + class_name ;
323 unscoped_cname = class_name;
324 }
325 else
326 {
327 unscoped_cname = class_name.substr(pos+2) ;
328 ctor_name = class_name+ "::" + unscoped_cname;
329 }
330 }
331
332 auto matcher =
333 visibility >> x3::space >>
334 thiscall >> //cdecl declaration for methods. stdcall cannot be
335 ctor_name >>
336 x3::lit('(') >> parser::arg_list(*this, func_type()) >> x3::lit(')') >> parser::ptr_rule();
337
338
339 auto predicate = [&](const mangled_storage_base::entry & e)
340 {
341 auto itr = e.demangled.begin();
342 auto end = e.demangled.end();
343 auto res = x3::parse(itr, end, matcher);
344
345 return res && (itr == end);
346 };
347
348 auto f = std::find_if(storage_.begin(), storage_.end(), predicate);
349
350 if (f != storage_.end())
351 return f->mangled;
352 else
353 return "";
354 }
355
356 template<typename Class>
357 auto mangled_storage_impl::get_destructor() const -> dtor_sym
358 {
359 namespace x3 = spirit::x3;
360 using namespace parser;
361 std::string dtor_name; // = class_name + "::" + name;
362 std::string unscoped_cname; //the unscoped class-name
363 {
364 auto class_name = get_name<Class>();
365 auto pos = class_name.rfind("::");
366 if (pos == std::string::npos)
367 {
368 dtor_name = class_name+ "::~" + class_name + "(void)";
369 unscoped_cname = class_name;
370 }
371 else
372 {
373 unscoped_cname = class_name.substr(pos+2) ;
374 dtor_name = class_name+ "::~" + unscoped_cname + "(void)";
375 }
376 }
377
378 auto matcher =
379 visibility >> -virtual_ >> x3::space >>
380 thiscall >> //cdecl declaration for methods. stdcall cannot be
381 dtor_name >> parser::ptr_rule();
382
383
384 auto predicate = [&](const mangled_storage_base::entry & e)
385 {
386 auto itr = e.demangled.begin();
387 auto end = e.demangled.end();
388 auto res = x3::parse(itr, end, matcher);
389
390 return res && (itr == end);
391 };
392
393 auto found = std::find_if(storage_.begin(), storage_.end(), predicate);
394
395
396 if (found != storage_.end())
397 return found->mangled;
398 else
399 return "";
400 }
401
402 template<typename T>
403 std::string mangled_storage_impl::get_vtable() const
404 {
405 std::string id = "const " + get_name<T>() + "::`vftable'";
406
407 auto predicate = [&](const mangled_storage_base::entry & e)
408 {
409 return e.demangled == id;
410 };
411
412 auto found = std::find_if(storage_.begin(), storage_.end(), predicate);
413
414
415 if (found != storage_.end())
416 return found->mangled;
417 else
418 return "";
419 }
420
421 template<typename T>
422 std::vector<std::string> mangled_storage_impl::get_related() const
423 {
424 std::vector<std::string> ret;
425 auto name = get_name<T>();
426
427 for (auto & c : storage_)
428 {
429 if (c.demangled.find(name) != std::string::npos)
430 ret.push_back(c.demangled);
431 }
432
433 return ret;
434 }
435
436
437 }}}
438
439
440
441 #endif /* BOOST_DLL_DETAIL_DEMANGLING_MSVC_HPP_ */