暂无描述

demangle_test.go 17KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. // Copyright 2015 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package demangle
  5. import (
  6. "strconv"
  7. "strings"
  8. "testing"
  9. )
  10. // Check test cases discovered after the code passed the tests in
  11. // demangle-expected (which are tested by TestExpected). Some of this
  12. // are cases where we differ from the standard demangler, some we are
  13. // the same but we weren't initially.
  14. func TestDemangler(t *testing.T) {
  15. var tests = []struct {
  16. input string
  17. want string
  18. wantNoParams string
  19. wantNoTemplateParams string
  20. wantMinimal string
  21. }{
  22. {
  23. "_ZNSaIcEC1ERKS_",
  24. "std::allocator<char>::allocator(std::allocator<char> const&)",
  25. "std::allocator<char>::allocator",
  26. "std::allocator::allocator(std::allocator const&)",
  27. "std::allocator::allocator",
  28. },
  29. {
  30. "_ZN9__gnu_cxx13stdio_filebufIcSt11char_traitsIcEEC1EP8_IO_FILESt13_Ios_Openmodem",
  31. "__gnu_cxx::stdio_filebuf<char, std::char_traits<char> >::stdio_filebuf(_IO_FILE*, std::_Ios_Openmode, unsigned long)",
  32. "__gnu_cxx::stdio_filebuf<char, std::char_traits<char> >::stdio_filebuf",
  33. "__gnu_cxx::stdio_filebuf::stdio_filebuf(_IO_FILE*, std::_Ios_Openmode, unsigned long)",
  34. "__gnu_cxx::stdio_filebuf::stdio_filebuf",
  35. },
  36. {
  37. "_ZN1n1CcvNS_1DIT_EEI1EEEv",
  38. "n::C::operator n::D<E><E>()",
  39. "n::C::operator n::D<E><E>",
  40. "n::C::operator n::D()",
  41. "n::C::operator n::D",
  42. },
  43. {
  44. "_Z1CIvPN1D1E1FIdJEEEdEPN1GILb0ET_T0_T1_E1HEPFS6_S7_S8_EN1H1I1JIS7_E1KENSG_IS8_E1KE",
  45. "G<false, void, D::E::F<double>*, double>::H* C<void, D::E::F<double>*, double>(void (*)(D::E::F<double>*, double), H::I::J<D::E::F<double>*>::K, H::I::J<double>::K)",
  46. "C<void, D::E::F<double>*, double>",
  47. "G::H* C(void (*)(D::E::F*, double), H::I::J::K, H::I::J::K)",
  48. "C",
  49. },
  50. {
  51. "_ZZNK1CI1DIcSt1EIcESaIcEEJEE1FEvE1F",
  52. "C<D<char, std::E<char>, std::allocator<char> > >::F() const::F",
  53. "C<D<char, std::E<char>, std::allocator<char> > >::F() const::F",
  54. "C::F() const::F",
  55. "C::F() const::F",
  56. },
  57. {
  58. "_ZN1CI1DSt1EIK1FN1G1HEEE1I1JIJRKS6_EEEvDpOT_",
  59. "void C<D, std::E<F const, G::H> >::I::J<std::E<F const, G::H> const&>(std::E<F const, G::H> const&)",
  60. "C<D, std::E<F const, G::H> >::I::J<std::E<F const, G::H> const&>",
  61. "void C::I::J(std::E const&)",
  62. "C::I::J",
  63. },
  64. {
  65. "_ZN1C1D1E1FIJEEEvi1GDpT_",
  66. "void C::D::E::F<>(int, G)",
  67. "C::D::E::F<>",
  68. "void C::D::E::F(int, G)",
  69. "C::D::E::F",
  70. },
  71. {
  72. "_ZN1CILj50ELb1EE1DEv",
  73. "C<50u, true>::D()",
  74. "C<50u, true>::D",
  75. "C::D()",
  76. "C::D",
  77. },
  78. {
  79. "_ZN1CUt_C2Ev",
  80. "C::{unnamed type#1}::{unnamed type#1}()",
  81. "C::{unnamed type#1}::{unnamed type#1}",
  82. "C::{unnamed type#1}::{unnamed type#1}()",
  83. "C::{unnamed type#1}::{unnamed type#1}",
  84. },
  85. {
  86. "_ZN1C12_GLOBAL__N_11DINS_1EEEEN1F1GIDTadcldtcvT__E1HEEEERKS5_NS_1I1JE",
  87. "F::G<decltype (&((((C::E)()).H)()))> C::(anonymous namespace)::D<C::E>(C::E const&, C::I::J)",
  88. "C::(anonymous namespace)::D<C::E>",
  89. "F::G C::(anonymous namespace)::D(C::E const&, C::I::J)",
  90. "C::(anonymous namespace)::D",
  91. },
  92. {
  93. "_ZN1CI1DE1EIJiRiRPKcRA1_S4_S8_bS6_S3_RjRPKN1F1GERPKN1H1IEEEEvDpOT_",
  94. "void C<D>::E<int, int&, char const*&, char const (&) [1], char const (&) [1], bool, char const*&, int&, unsigned int&, F::G const*&, H::I const*&>(int&&, int&, char const*&, char const (&) [1], char const (&) [1], bool&&, char const*&, int&, unsigned int&, F::G const*&, H::I const*&)",
  95. "C<D>::E<int, int&, char const*&, char const (&) [1], char const (&) [1], bool, char const*&, int&, unsigned int&, F::G const*&, H::I const*&>",
  96. "void C::E(int&&, int&, char const*&, char const (&) [1], char const (&) [1], bool&&, char const*&, int&, unsigned int&, F::G const*&, H::I const*&)",
  97. "C::E",
  98. },
  99. {
  100. "_ZN1C12_GLOBAL__N_11DIFbPKNS_1EEEEEvPNS_1FERKT_",
  101. "void C::(anonymous namespace)::D<bool (C::E const*)>(C::F*, bool (&)(C::E const*) const)",
  102. "C::(anonymous namespace)::D<bool (C::E const*)>",
  103. "void C::(anonymous namespace)::D(C::F*, bool (&)(C::E const*) const)",
  104. "C::(anonymous namespace)::D",
  105. },
  106. {
  107. "_ZN1C1D1EIJRFviSt1FIFvRKN1G1H1IEEERKSt6vectorINS_1JESaISB_EEERiS9_EvEENS0_1K1LIJDpNSt1MIT_E1NEEEEDpOSM_",
  108. "C::D::K::L<std::M<void (&)(int, std::F<void (G::H::I const&)>, std::vector<C::J, std::allocator<C::J> > const&)>::N, std::M<int&>::N, std::M<std::F<void (G::H::I const&)> >::N> C::D::E<void (&)(int, std::F<void (G::H::I const&)>, std::vector<C::J, std::allocator<C::J> > const&), int&, std::F<void (G::H::I const&)>, void>(void (&)(int, std::F<void (G::H::I const&)>, std::vector<C::J, std::allocator<C::J> > const&), int&, std::F<void (G::H::I const&)>&&)",
  109. "C::D::E<void (&)(int, std::F<void (G::H::I const&)>, std::vector<C::J, std::allocator<C::J> > const&), int&, std::F<void (G::H::I const&)>, void>",
  110. "C::D::K::L C::D::E(void (&)(int, std::F, std::vector const&), int&, std::F&&)",
  111. "C::D::E",
  112. },
  113. {
  114. "_ZN1C1D1E1FcvNS_1GIT_EEI1HEEv",
  115. "C::D::E::F::operator C::G<H><H>()",
  116. "C::D::E::F::operator C::G<H><H>",
  117. "C::D::E::F::operator C::G()",
  118. "C::D::E::F::operator C::G",
  119. },
  120. {
  121. "_ZN9__gnu_cxx17__normal_iteratorIPK1EIN1F1G1HEESt6vectorIS5_SaIS5_EEEC2IPS5_EERKNS0_IT_NS_11__enable_ifIXsr3std10__are_sameISE_SD_EE7__valueESA_E1IEEE",
  122. "__gnu_cxx::__normal_iterator<E<F::G::H> const*, std::vector<E<F::G::H>, std::allocator<E<F::G::H> > > >::__normal_iterator<E<F::G::H>*>(__gnu_cxx::__normal_iterator<E<F::G::H>*, __gnu_cxx::__enable_if<std::__are_same<E<F::G::H>*, E<F::G::H>*>::__value, std::vector<E<F::G::H>, std::allocator<E<F::G::H> > > >::I> const&)",
  123. "__gnu_cxx::__normal_iterator<E<F::G::H> const*, std::vector<E<F::G::H>, std::allocator<E<F::G::H> > > >::__normal_iterator<E<F::G::H>*>",
  124. "__gnu_cxx::__normal_iterator::__normal_iterator(__gnu_cxx::__normal_iterator const&)",
  125. "__gnu_cxx::__normal_iterator::__normal_iterator",
  126. },
  127. {
  128. "_ZNKSt1CIM1DKFjvEEclIJEvEEjPKS0_DpOT_",
  129. "unsigned int std::C<unsigned int (D::*)() const>::operator()<void>(D const*) const",
  130. "std::C<unsigned int (D::*)() const>::operator()<void>",
  131. "unsigned int std::C::operator()(D const*) const",
  132. "std::C::operator()",
  133. },
  134. {
  135. "_ZNSt10_HashtableI12basic_stringIcSt11char_traitsIcESaIcEESt4pairIKS4_N1C1D1EEESaISA_ENSt8__detail10_Select1stESt8equal_toIS4_ESt4hashIS4_ENSC_18_Mod_range_hashingENSC_20_Default_ranged_hashENSC_20_Prime_rehash_policyENSC_17_Hashtable_traitsILb1ELb0ELb1EEEE9_M_assignIZNSN_C1ERKSN_EUlPKNSC_10_Hash_nodeISA_Lb1EEEE_EEvSQ_RKT_",
  136. "void std::_Hashtable<basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<basic_string<char, std::char_traits<char>, std::allocator<char> > const, C::D::E>, std::allocator<std::pair<basic_string<char, std::char_traits<char>, std::allocator<char> > const, C::D::E> >, std::__detail::_Select1st, std::equal_to<basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::hash<basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true> >::_M_assign<std::_Hashtable<basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<basic_string<char, std::char_traits<char>, std::allocator<char> > const, C::D::E>, std::allocator<std::pair<basic_string<char, std::char_traits<char>, std::allocator<char> > const, C::D::E> >, std::__detail::_Select1st, std::equal_to<basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::hash<basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true> >::_Hashtable(std::_Hashtable<basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<basic_string<char, std::char_traits<char>, std::allocator<char> > const, C::D::E>, std::allocator<std::pair<basic_string<char, std::char_traits<char>, std::allocator<char> > const, C::D::E> >, std::__detail::_Select1st, std::equal_to<basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::hash<basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true> > const&)::{lambda(std::__detail::_Hash_node<std::pair<basic_string<char, std::char_traits<char>, std::allocator<char> > const, C::D::E>, true> const*)#1}>(std::_Hashtable<basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<basic_string<char, std::char_traits<char>, std::allocator<char> > const, C::D::E>, std::allocator<std::pair<basic_string<char, std::char_traits<char>, std::allocator<char> > const, C::D::E> >, std::__detail::_Select1st, std::equal_to<basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::hash<basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true> > const&, std::_Hashtable<basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<basic_string<char, std::char_traits<char>, std::allocator<char> > const, C::D::E>, std::allocator<std::pair<basic_string<char, std::char_traits<char>, std::allocator<char> > const, C::D::E> >, std::__detail::_Select1st, std::equal_to<basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::hash<basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true> >::_Hashtable(std::_Hashtable<basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<basic_string<char, std::char_traits<char>, std::allocator<char> > const, C::D::E>, std::allocator<std::pair<basic_string<char, std::char_traits<char>, std::allocator<char> > const, C::D::E> >, std::__detail::_Select1st, std::equal_to<basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::hash<basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true> > const&)::{lambda(std::__detail::_Hash_node<std::pair<basic_string<char, std::char_traits<char>, std::allocator<char> > const, C::D::E>, true> const*)#1} const&)",
  137. "std::_Hashtable<basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<basic_string<char, std::char_traits<char>, std::allocator<char> > const, C::D::E>, std::allocator<std::pair<basic_string<char, std::char_traits<char>, std::allocator<char> > const, C::D::E> >, std::__detail::_Select1st, std::equal_to<basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::hash<basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true> >::_M_assign<std::_Hashtable<basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<basic_string<char, std::char_traits<char>, std::allocator<char> > const, C::D::E>, std::allocator<std::pair<basic_string<char, std::char_traits<char>, std::allocator<char> > const, C::D::E> >, std::__detail::_Select1st, std::equal_to<basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::hash<basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true> >::_Hashtable(std::_Hashtable<basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<basic_string<char, std::char_traits<char>, std::allocator<char> > const, C::D::E>, std::allocator<std::pair<basic_string<char, std::char_traits<char>, std::allocator<char> > const, C::D::E> >, std::__detail::_Select1st, std::equal_to<basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::hash<basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true> > const&)::{lambda(std::__detail::_Hash_node<std::pair<basic_string<char, std::char_traits<char>, std::allocator<char> > const, C::D::E>, true> const*)#1}>",
  138. "void std::_Hashtable::_M_assign(std::_Hashtable const&, std::_Hashtable::_Hashtable(std::_Hashtable const&)::{lambda(std::__detail::_Hash_node const*)#1} const&)",
  139. "std::_Hashtable::_M_assign",
  140. },
  141. {
  142. "_ZSt3maxIVdERKT_S3_S3_",
  143. "double const volatile& std::max<double volatile>(double const volatile&, double const volatile&)",
  144. "std::max<double volatile>",
  145. "double const volatile& std::max(double const volatile&, double const volatile&)",
  146. "std::max",
  147. },
  148. {
  149. "_ZZN1C1D1E1F1G1HEvENUlvE_C2EOS4_",
  150. "C::D::E::F::G::H()::{lambda()#1}::{lambda()#1}({lambda()#1}&&)",
  151. "C::D::E::F::G::H()::{lambda()#1}::{lambda()#1}",
  152. "C::D::E::F::G::H()::{lambda()#1}::{lambda()#1}({lambda()#1}&&)",
  153. "C::D::E::F::G::H()::{lambda()#1}::{lambda()#1}",
  154. },
  155. {
  156. "_ZThn8_NK1C1D1EEv",
  157. "non-virtual thunk to C::D::E() const",
  158. "non-virtual thunk to C::D::E() const",
  159. "non-virtual thunk to C::D::E() const",
  160. "non-virtual thunk to C::D::E() const",
  161. },
  162. {
  163. "_ZTv0_n96_NK1C1D1E1FEv",
  164. "virtual thunk to C::D::E::F() const",
  165. "virtual thunk to C::D::E::F() const",
  166. "virtual thunk to C::D::E::F() const",
  167. "virtual thunk to C::D::E::F() const",
  168. },
  169. {
  170. "_ZTCSt9strstream16_So",
  171. "construction vtable for std::ostream-in-std::strstream",
  172. "construction vtable for std::ostream-in-std::strstream",
  173. "construction vtable for std::ostream-in-std::strstream",
  174. "construction vtable for std::ostream-in-std::strstream",
  175. },
  176. {
  177. "_ZGVZZN1C1D1EEvENK3$_0clEvE1F",
  178. "guard variable for C::D::E()::$_0::operator()() const::F",
  179. "guard variable for C::D::E()::$_0::operator()() const::F",
  180. "guard variable for C::D::E()::$_0::operator()() const::F",
  181. "guard variable for C::D::E()::$_0::operator()() const::F",
  182. },
  183. {
  184. "_Z1fICiEvT_",
  185. "void f<int _Complex>(int _Complex)",
  186. "f<int _Complex>",
  187. "void f(int _Complex)",
  188. "f",
  189. },
  190. {
  191. "_GLOBAL__D__Z2fnv",
  192. "global destructors keyed to fn()",
  193. "global destructors keyed to fn()",
  194. "global destructors keyed to fn()",
  195. "global destructors keyed to fn()",
  196. },
  197. {
  198. "_Z1fIXadL_Z1hvEEEvv",
  199. "void f<&h>()",
  200. "f<&h>",
  201. "void f()",
  202. "f",
  203. },
  204. {
  205. "_Z1CIP1DEiRK1EPT_N1F1GIS5_Xaasr1HIS5_E1IntsrSA_1JEE1KE",
  206. "int C<D*>(E const&, D**, F::G<D*, H<D*>::I&&(!H<D*>::J)>::K)",
  207. "C<D*>",
  208. "int C(E const&, D**, F::G::K)",
  209. "C",
  210. },
  211. }
  212. for _, test := range tests {
  213. if got, err := ToString(test.input); err != nil {
  214. t.Errorf("demangling %s: unexpected error %v", test.input, err)
  215. } else if got != test.want {
  216. t.Errorf("demangling %s: got %s, want %s", test.input, got, test.want)
  217. }
  218. if got, err := ToString(test.input, NoParams); err != nil {
  219. t.Errorf("demangling NoParams %s: unexpected error %v", test.input, err)
  220. } else if got != test.wantNoParams {
  221. t.Errorf("demangling NoParams %s: got %s, want %s", test.input, got, test.wantNoParams)
  222. }
  223. if got, err := ToString(test.input, NoTemplateParams); err != nil {
  224. t.Errorf("demangling NoTemplateParams %s: unexpected error %v", test.input, err)
  225. } else if got != test.wantNoTemplateParams {
  226. t.Errorf("demangling NoTemplateParams %s: got %s, want %s", test.input, got, test.wantNoTemplateParams)
  227. }
  228. if got, err := ToString(test.input, NoParams, NoTemplateParams); err != nil {
  229. t.Errorf("demangling NoTemplateParams %s: unexpected error %v", test.input, err)
  230. } else if got != test.wantMinimal {
  231. t.Errorf("demangling Minimal %s: got %s, want %s", test.input, got, test.wantMinimal)
  232. }
  233. // Test Filter also.
  234. if got := Filter(test.input); got != test.want {
  235. t.Errorf("Filter(%s) == %s, want %s", test.input, got, test.want)
  236. }
  237. }
  238. }
  239. // Test for some failure cases.
  240. func TestFailure(t *testing.T) {
  241. var tests = []struct {
  242. input string
  243. error string
  244. off int
  245. }{
  246. {
  247. "_Z1FE",
  248. "unparsed characters at end of mangled name",
  249. 4,
  250. },
  251. {
  252. "_Z1FQ",
  253. "unrecognized type code",
  254. 4,
  255. },
  256. }
  257. for _, test := range tests {
  258. got, err := ToString(test.input)
  259. if err == nil {
  260. t.Errorf("unexpected success for %s: %s", test.input, got)
  261. } else if !strings.Contains(err.Error(), test.error) {
  262. t.Errorf("unexpected error for %s: %v", test.input, err)
  263. } else {
  264. s := err.Error()
  265. i := strings.LastIndex(s, " at ")
  266. if i < 0 {
  267. t.Errorf("missing offset in error for %s: %v", test.input, err)
  268. } else {
  269. off, oerr := strconv.Atoi(s[i+4:])
  270. if oerr != nil {
  271. t.Errorf("can't parse offset (%s) for %s: %v", s[i+4:], test.input, err)
  272. } else if off != test.off {
  273. t.Errorf("unexpected offset for %s: got %d, want %d", test.input, off, test.off)
  274. }
  275. }
  276. }
  277. if got := Filter(test.input); got != test.input {
  278. t.Errorf("Filter(%s) == %s, want %s", test.input, got, test.input)
  279. }
  280. }
  281. }