1 // C++ IA64 / g++ v3 demangler -*- C++ -*-
3 // Copyright (C) 2003 Free Software Foundation, Inc.
4 // Written by Carlo Wood <carlo@alinoe.com>
6 // This file is part of the GNU ISO C++ Library. This library is free
7 // software; you can redistribute it and/or modify it under the
8 // terms of the GNU General Public License as published by the
9 // Free Software Foundation; either version 2, or (at your option)
12 // This library is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
17 // You should have received a copy of the GNU General Public License along
18 // with this library; see the file COPYING. If not, write to the Free
19 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
22 // As a special exception, you may use this file as part of a free software
23 // library without restriction. Specifically, if other files instantiate
24 // templates or use macros or inline functions from this file, or you compile
25 // this file and link it with other files to produce an executable, this
26 // file does not by itself cause the resulting executable to be covered by
27 // the GNU General Public License. This exception does not however
28 // invalidate any other reasons why the executable file might be covered by
29 // the GNU General Public License.
31 // This file implements demangling of "C++ ABI for Itanium"-mangled symbol
32 // and type names as described in Revision 1.73 of the C++ ABI as can be found
33 // at http://www.codesourcery.com/cxx-abi/abi.html#mangling
36 #define _DEMANGLER_H 1
41 #ifndef _GLIBCXX_DEMANGLER_DEBUG
42 #define _GLIBCXX_DEMANGLER_CWDEBUG 0
43 #define _GLIBCXX_DEMANGLER_DEBUG(x)
44 #define _GLIBCXX_DEMANGLER_DOUT(cntrl, data)
45 #define _GLIBCXX_DEMANGLER_DOUT_ENTERING(x)
46 #define _GLIBCXX_DEMANGLER_DOUT_ENTERING2(x)
47 #define _GLIBCXX_DEMANGLER_DOUT_ENTERING3(x)
48 #define _GLIBCXX_DEMANGLER_RETURN return M_result
49 #define _GLIBCXX_DEMANGLER_RETURN2 return M_result
50 #define _GLIBCXX_DEMANGLER_RETURN3
51 #define _GLIBCXX_DEMANGLER_FAILURE \
52 do { M_result = false; return false; } while(0)
54 #define _GLIBCXX_DEMANGLER_CWDEBUG 1
65 template_template_param
,
67 nested_name_template_prefix
,
68 unscoped_template_name
71 struct substitution_st
74 substitution_nt M_type
;
75 int M_number_of_prefixes
;
77 substitution_st(int start_pos
,
79 int number_of_prefixes
)
80 : M_start_pos(start_pos
), M_type(type
),
81 M_number_of_prefixes(number_of_prefixes
)
85 enum simple_qualifier_nt
87 complex_or_imaginary
= 'G',
97 enum param_qualifier_nt
99 vendor_extension
= 'U',
101 pointer_to_member
= 'M'
104 template<typename Allocator
>
107 template<typename Allocator
>
108 class qualifier_list
;
110 template<typename Allocator
>
113 template<typename Allocator
>
116 typedef typename
Allocator::template rebind
<char>::other
118 typedef std::basic_string
<char, std::char_traits
<char>, char_Allocator
>
125 mutable unsigned char M_cnt
;
126 string_type M_optional_type
;
128 bool M_part_of_substitution
;
131 qualifier(int start_pos
,
132 simple_qualifier_nt simple_qualifier
,
133 int inside_substitution
)
134 : M_qualifier1(simple_qualifier
),
135 M_start_pos(start_pos
),
136 M_part_of_substitution(inside_substitution
)
139 qualifier(int start_pos
,
143 int inside_substitution
)
144 : M_qualifier1(start
[0]),
145 M_qualifier2((count
> 1) ? start
[1] : '\0'),
146 M_qualifier3((count
> 2) ? start
[2] : '\0'),
147 M_start_pos(start_pos
),
148 M_part_of_substitution(inside_substitution
)
151 qualifier(int start_pos
,
152 param_qualifier_nt param_qualifier
,
153 string_type optional_type
,
154 int inside_substitution
)
155 : M_qualifier1(param_qualifier
),
156 M_optional_type(optional_type
),
157 M_start_pos(start_pos
),
158 M_part_of_substitution(inside_substitution
)
162 get_start_pos(void) const
163 { return M_start_pos
; }
166 first_qualifier(void) const
167 { M_cnt
= 1; return M_qualifier1
; }
170 next_qualifier(void) const
172 return (++M_cnt
== 2) ? M_qualifier2
173 : ((M_cnt
== 3) ? M_qualifier3
: 0);
177 get_optional_type(void) const
178 { return M_optional_type
; }
181 part_of_substitution(void) const
182 { return M_part_of_substitution
; }
184 #if _GLIBCXX_DEMANGLER_CWDEBUG
185 friend std::ostream
& operator<<(std::ostream
& os
, qualifier
const& qual
)
187 os
<< (char)qual
.M_qualifier1
;
188 if (qual
.M_qualifier1
== vendor_extension
||
189 qual
.M_qualifier1
== array
||
190 qual
.M_qualifier1
== pointer_to_member
)
191 os
<< " [" << qual
.M_optional_type
<< ']';
192 else if (qual
.M_qualifier1
== 'K' ||
193 qual
.M_qualifier1
== 'V' ||
194 qual
.M_qualifier1
== 'r')
196 if (qual
.M_qualifier2
)
198 os
<< (char)qual
.M_qualifier2
;
199 if (qual
.M_qualifier3
)
200 os
<< (char)qual
.M_qualifier3
;
208 template<typename Allocator
>
211 typedef typename
Allocator::template rebind
<char>::other
213 typedef std::basic_string
<char, std::char_traits
<char>, char_Allocator
>
217 mutable bool M_printing_suppressed
;
218 typedef qualifier
<Allocator
> qual
;
219 typedef typename
Allocator::template rebind
<qual
>::other qual_Allocator
;
220 typedef std::vector
<qual
, qual_Allocator
> qual_vector
;
221 qual_vector M_qualifier_starts
;
222 session
<Allocator
>& M_demangler
;
224 void decode_KVrA(string_type
& prefix
, string_type
& postfix
, int cvq
,
225 typename
qual_vector::
226 const_reverse_iterator
const& iter_array
) const;
229 qualifier_list(session
<Allocator
>& demangler_obj
)
230 : M_printing_suppressed(false), M_demangler(demangler_obj
)
234 add_qualifier_start(simple_qualifier_nt simple_qualifier
,
236 int inside_substitution
)
237 { M_qualifier_starts
.
238 push_back(qualifier
<Allocator
>(start_pos
,
239 simple_qualifier
, inside_substitution
)); }
242 add_qualifier_start(cv_qualifier_nt cv_qualifier
,
245 int inside_substitution
)
246 { M_qualifier_starts
.
247 push_back(qualifier
<Allocator
>(start_pos
,
248 cv_qualifier
, &M_demangler
.M_str
[start_pos
],
249 count
, inside_substitution
)); }
252 add_qualifier_start(param_qualifier_nt param_qualifier
,
254 string_type optional_type
,
255 int inside_substitution
)
256 { M_qualifier_starts
.
257 push_back(qualifier
<Allocator
>(start_pos
,
258 param_qualifier
, optional_type
, inside_substitution
)); }
261 decode_qualifiers(string_type
& prefix
,
262 string_type
& postfix
,
263 bool member_function_pointer_qualifiers
) const;
266 suppressed(void) const
267 { return M_printing_suppressed
; }
270 printing_suppressed(void)
271 { M_printing_suppressed
= true; }
275 { return M_qualifier_starts
.size(); }
277 #if _GLIBCXX_DEMANGLER_CWDEBUG
278 friend std::ostream
& operator<<(std::ostream
& os
, qualifier_list
const& list
)
280 typename
qual_vector::const_iterator
281 iter
= list
.M_qualifier_starts
.begin();
282 if (iter
!= list
.M_qualifier_starts
.end())
285 while (++iter
!= list
.M_qualifier_starts
.end())
296 struct implementation_details
299 unsigned int M_style
;
302 // The following flags change the behaviour of the demangler. The
303 // default behaviour is that none of these flags is set.
305 static unsigned int const style_void
= 1;
306 // Default behaviour: int f()
307 // Use (void) instead of (): int f(void)
309 static unsigned int const style_literal
= 2;
310 // Default behaviour: (long)13,
311 // (unsigned long long)19
312 // Use extensions 'u', 'l' and 'll' for integral
313 // literals (as in template arguments): 13l, 19ull
315 static unsigned int const style_literal_int
= 4;
316 // Default behaviour: 4
317 // Use also an explicit
318 // cast for int in literals: (int)4
320 static unsigned int const style_compact_expr_ops
= 8;
321 // Default behaviour: (i) < (3), sizeof (int)
322 // Don't output spaces around
323 // operators in expressions: (i)<(3), sizeof(int)
325 static unsigned int const style_sizeof_typename
= 16;
326 // Default behaviour: sizeof (X::t)
327 // Put 'typename' infront of <nested-name>
328 // types inside a 'sizeof': sizeof (typename X::t)
331 implementation_details(unsigned int style_flags
= 0) :
332 M_style(style_flags
) { }
333 virtual ~implementation_details() { }
334 bool get_style_void(void) const
335 { return (M_style
& style_void
); }
336 bool get_style_literal(void) const
337 { return (M_style
& style_literal
); }
338 bool get_style_literal_int(void) const
339 { return (M_style
& style_literal_int
); }
340 bool get_style_compact_expr_ops(void) const
341 { return (M_style
& style_compact_expr_ops
); }
342 bool get_style_sizeof_typename(void) const
343 { return (M_style
& style_sizeof_typename
); }
344 // This can be overridden by user implementations.
345 virtual bool decode_real(char* /* output */, unsigned long* /* input */,
346 size_t /* size_of_real */) const
350 template<typename Allocator
>
353 friend class qualifier_list
<Allocator
>;
354 typedef typename
Allocator::template rebind
<char>::other
356 typedef std::basic_string
<char, std::char_traits
<char>, char_Allocator
>
364 int M_inside_template_args
;
366 int M_inside_substitution
;
367 bool M_saw_destructor
;
368 bool M_name_is_cdtor
;
369 bool M_name_is_template
;
370 bool M_name_is_conversion_operator
;
371 bool M_template_args_need_space
;
372 string_type M_function_name
;
373 typedef typename
Allocator::template rebind
<int>::other
375 typedef typename
Allocator::template rebind
<substitution_st
>::other
377 std::vector
<int, int_Allocator
> M_template_arg_pos
;
378 int M_template_arg_pos_offset
;
379 std::vector
<substitution_st
, subst_Allocator
> M_substitutions_pos
;
380 implementation_details
const& M_implementation_details
;
381 #if _GLIBCXX_DEMANGLER_CWDEBUG
382 bool M_inside_add_substitution
;
386 explicit session(char const* in
, int len
,
387 implementation_details
const& id
= implementation_details())
388 : M_str(in
), M_pos(0), M_maxpos(len
- 1), M_result(true),
389 M_inside_template_args(0), M_inside_type(0),
390 M_inside_substitution(0), M_saw_destructor(false),
391 M_name_is_cdtor(false), M_name_is_template(false),
392 M_name_is_conversion_operator(false),
393 M_template_args_need_space(false), M_template_arg_pos_offset(0),
394 M_implementation_details(id
)
395 #if _GLIBCXX_DEMANGLER_CWDEBUG
396 , M_inside_add_substitution(false)
401 decode_encoding(string_type
& output
, char const* input
, int len
,
402 implementation_details
const& id
= implementation_details());
405 decode_type(string_type
& output
,
406 qualifier_list
<Allocator
>* qualifiers
= NULL
)
409 bool res
= decode_type_with_postfix(output
, postfix
, qualifiers
);
415 remaining_input_characters(void) const
416 { return current() != 0; }
421 { return (M_pos
> M_maxpos
) ? 0 : M_str
[M_pos
]; }
424 next_peek(void) const
425 { return (M_pos
>= M_maxpos
) ? 0 : M_str
[M_pos
+ 1]; }
429 { return (M_pos
>= M_maxpos
) ? 0 : M_str
[++M_pos
]; }
433 { return (M_pos
> M_maxpos
) ? 0 : M_str
[M_pos
++]; }
436 store(int& saved_pos
)
437 { saved_pos
= M_pos
; }
440 restore(int saved_pos
)
441 { M_pos
= saved_pos
; M_result
= true; }
444 add_substitution(int start_pos
,
445 substitution_nt sub_type
,
446 int number_of_prefixes
);
448 bool decode_type_with_postfix(string_type
& prefix
,
449 string_type
& postfix
, qualifier_list
<Allocator
>* qualifiers
= NULL
);
450 bool decode_bare_function_type(string_type
& output
);
451 bool decode_builtin_type(string_type
& output
);
452 bool decode_call_offset(string_type
& output
);
453 bool decode_class_enum_type(string_type
& output
);
454 bool decode_expression(string_type
& output
);
455 bool decode_literal(string_type
& output
);
456 bool decode_local_name(string_type
& output
);
457 bool decode_name(string_type
& output
,
458 string_type
& nested_name_qualifiers
);
459 bool decode_nested_name(string_type
& output
,
460 string_type
& qualifiers
);
461 bool decode_number(string_type
& output
);
462 bool decode_operator_name(string_type
& output
);
463 bool decode_source_name(string_type
& output
);
464 bool decode_substitution(string_type
& output
,
465 qualifier_list
<Allocator
>* qualifiers
= NULL
);
466 bool decode_template_args(string_type
& output
);
467 bool decode_template_param(string_type
& output
,
468 qualifier_list
<Allocator
>* qualifiers
= NULL
);
469 bool decode_unqualified_name(string_type
& output
);
470 bool decode_unscoped_name(string_type
& output
);
471 bool decode_non_negative_decimal_integer(string_type
& output
);
472 bool decode_special_name(string_type
& output
);
473 bool decode_real(string_type
& output
, size_t size_of_real
);
476 template<typename Allocator
>
477 #if !_GLIBCXX_DEMANGLER_CWDEBUG
481 session
<Allocator
>::add_substitution(int start_pos
,
482 substitution_nt sub_type
,
483 int number_of_prefixes
= 0)
485 if (!M_inside_substitution
)
487 #if _GLIBCXX_DEMANGLER_CWDEBUG
488 if (M_inside_add_substitution
)
492 push_back(substitution_st(start_pos
,
493 sub_type
, number_of_prefixes
));
494 #if _GLIBCXX_DEMANGLER_CWDEBUG
495 if (!DEBUGCHANNELS::dc::demangler
.is_on())
497 string_type
substitution_name("S");
498 int n
= M_substitutions_pos
.size() - 1;
500 substitution_name
+= (n
<= 10) ? (char)(n
+ '0' - 1)
501 : (char)(n
+ 'A' - 11);
502 substitution_name
+= '_';
504 int saved_pos
= M_pos
;
506 M_inside_add_substitution
= true;
507 _GLIBCXX_DEMANGLER_DEBUG( dc::demangler
.off() );
513 case template_template_param
:
514 decode_template_param(subst
);
516 case nested_name_prefix
:
517 case nested_name_template_prefix
:
518 for (int cnt
= number_of_prefixes
; cnt
> 0; --cnt
)
520 if (current() == 'I')
523 decode_template_args(subst
);
527 if (cnt
< number_of_prefixes
)
529 if (current() == 'S')
530 decode_substitution(subst
);
531 else if (current() == 'T')
532 decode_template_param(subst
);
534 decode_unqualified_name(subst
);
538 case unscoped_template_name
:
539 decode_unscoped_name(subst
);
543 _GLIBCXX_DEMANGLER_DEBUG( dc::demangler
.on() );
544 _GLIBCXX_DEMANGLER_DOUT(dc::demangler
,
545 "Adding substitution " << substitution_name
547 << " (from " << location_ct((char*)__builtin_return_address(0)
548 + builtin_return_address_offset
)
549 << " <- " << location_ct((char*)__builtin_return_address(1)
550 + builtin_return_address_offset
)
551 << " <- " << location_ct((char*)__builtin_return_address(2)
552 + builtin_return_address_offset
)
554 M_inside_add_substitution
= false;
559 // We don't want to depend on locale (or include <cctype> for that matter).
560 // We also don't want to use "safe-ctype.h" because that headerfile is not
561 // available to the users.
562 inline bool isdigit(char c
) { return c
>= '0' && c
<= '9'; }
563 inline bool islower(char c
) { return c
>= 'a' && c
<= 'z'; }
564 inline bool isupper(char c
) { return c
>= 'A' && c
<= 'Z'; }
565 inline char tolower(char c
) { return isupper(c
) ? c
- 'A' + 'a' : c
; }
568 // <non-negative decimal integer> ::= 0
569 // ::= 1|2|3|4|5|6|7|8|9 [<digit>+]
570 // <digit> ::= 0|1|2|3|4|5|6|7|8|9
572 template<typename Allocator
>
575 decode_non_negative_decimal_integer(string_type
& output
)
583 else if (!isdigit(c
))
591 while (isdigit((c
= next())));
596 // <number> ::= [n] <non-negative decimal integer>
598 template<typename Allocator
>
600 session
<Allocator
>::decode_number(string_type
& output
)
602 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_number");
603 if (current() != 'n')
604 decode_non_negative_decimal_integer(output
);
609 decode_non_negative_decimal_integer(output
);
611 _GLIBCXX_DEMANGLER_RETURN
;
614 // <builtin-type> ::= v # void
618 // ::= a # signed char
619 // ::= h # unsigned char
621 // ::= t # unsigned short
623 // ::= j # unsigned int
625 // ::= m # unsigned long
626 // ::= x # long long, __int64
627 // ::= y # unsigned long long, __int64
629 // ::= o # unsigned __int128
632 // ::= e # long double, __float80
633 // ::= g # __float128
635 // ::= u <source-name> # vendor extended type
637 char const* const builtin_type_c
[26] =
646 "unsigned char", // h
651 "unsigned long", // m
653 "unsigned __int128", // o
658 "unsigned short", // t
663 "unsigned long long", // y
668 template<typename Allocator
>
670 session
<Allocator
>::decode_builtin_type(string_type
& output
)
672 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_builtin_type");
674 if (!islower(current()) || !(bt
= builtin_type_c
[current() - 'a']))
675 _GLIBCXX_DEMANGLER_FAILURE
;
678 _GLIBCXX_DEMANGLER_RETURN
;
681 // <class-enum-type> ::= <name>
683 template<typename Allocator
>
685 session
<Allocator
>::decode_class_enum_type(string_type
& output
)
687 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_class_enum_type");
688 string_type nested_name_qualifiers
;
689 if (!decode_name(output
, nested_name_qualifiers
))
690 _GLIBCXX_DEMANGLER_FAILURE
;
691 output
+= nested_name_qualifiers
;
692 _GLIBCXX_DEMANGLER_RETURN
;
695 // <substitution> ::=
699 // Sa # ::std::allocator
700 // Sb # ::std::basic_string
701 // Ss # ::std::basic_string<char, std::char_traits<char>,
702 // std::allocator<char> >
703 // Si # ::std::basic_istream<char, std::char_traits<char> >
704 // So # ::std::basic_ostream<char, std::char_traits<char> >
705 // Sd # ::std::basic_iostream<char, std::char_traits<char> >
708 // 0|1|2|3|4|5|6|7|8|9|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z
709 // [<seq-id>] # Base 36 number
711 template<typename Allocator
>
713 session
<Allocator
>::decode_substitution(string_type
& output
,
714 qualifier_list
<Allocator
>* qualifiers
)
716 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_substitution");
717 unsigned int value
= 0;
725 output
+= "std::allocator";
726 if (!M_inside_template_args
)
728 M_function_name
= "allocator";
729 M_name_is_template
= true;
730 M_name_is_cdtor
= false;
731 M_name_is_conversion_operator
= false;
735 qualifiers
->printing_suppressed();
736 _GLIBCXX_DEMANGLER_RETURN
;
740 output
+= "std::basic_string";
741 if (!M_inside_template_args
)
743 M_function_name
= "basic_string";
744 M_name_is_template
= true;
745 M_name_is_cdtor
= false;
746 M_name_is_conversion_operator
= false;
750 qualifiers
->printing_suppressed();
751 _GLIBCXX_DEMANGLER_RETURN
;
754 output
+= "std::iostream";
755 if (!M_inside_template_args
)
757 M_function_name
= "iostream";
758 M_name_is_template
= true;
759 M_name_is_cdtor
= false;
760 M_name_is_conversion_operator
= false;
764 qualifiers
->printing_suppressed();
765 _GLIBCXX_DEMANGLER_RETURN
;
767 output
+= "std::istream";
768 if (!M_inside_template_args
)
770 M_function_name
= "istream";
771 M_name_is_template
= true;
772 M_name_is_cdtor
= false;
773 M_name_is_conversion_operator
= false;
777 qualifiers
->printing_suppressed();
778 _GLIBCXX_DEMANGLER_RETURN
;
780 output
+= "std::ostream";
781 if (!M_inside_template_args
)
783 M_function_name
= "ostream";
784 M_name_is_template
= true;
785 M_name_is_cdtor
= false;
786 M_name_is_conversion_operator
= false;
790 qualifiers
->printing_suppressed();
791 _GLIBCXX_DEMANGLER_RETURN
;
793 output
+= "std::string";
794 if (!M_inside_template_args
)
796 M_function_name
= "string";
797 M_name_is_template
= true;
798 M_name_is_cdtor
= false;
799 M_name_is_conversion_operator
= false;
803 qualifiers
->printing_suppressed();
804 _GLIBCXX_DEMANGLER_RETURN
;
809 qualifiers
->printing_suppressed();
810 _GLIBCXX_DEMANGLER_RETURN
;
815 value
= value
* 36 + c
- '0';
817 value
= value
* 36 + c
- 'A' + 10;
821 _GLIBCXX_DEMANGLER_FAILURE
;
828 if (value
>= M_substitutions_pos
.size() ||
829 M_inside_type
> 20) // Rather than core dump.
830 _GLIBCXX_DEMANGLER_FAILURE
;
831 ++M_inside_substitution
;
832 int saved_pos
= M_pos
;
833 substitution_st
& substitution(M_substitutions_pos
[value
]);
834 M_pos
= substitution
.M_start_pos
;
835 switch(substitution
.M_type
)
838 decode_type(output
, qualifiers
);
840 case template_template_param
:
841 decode_template_param(output
, qualifiers
);
843 case nested_name_prefix
:
844 case nested_name_template_prefix
:
845 for (int cnt
= substitution
.M_number_of_prefixes
; cnt
> 0; --cnt
)
847 if (current() == 'I')
849 if (M_template_args_need_space
)
851 M_template_args_need_space
= false;
852 if (!decode_template_args(output
))
853 _GLIBCXX_DEMANGLER_FAILURE
;
857 if (cnt
< substitution
.M_number_of_prefixes
)
859 if (current() == 'S')
861 if (!decode_substitution(output
))
862 _GLIBCXX_DEMANGLER_FAILURE
;
864 else if (!decode_unqualified_name(output
))
865 _GLIBCXX_DEMANGLER_FAILURE
;
869 qualifiers
->printing_suppressed();
871 case unscoped_template_name
:
872 decode_unscoped_name(output
);
874 qualifiers
->printing_suppressed();
878 --M_inside_substitution
;
879 _GLIBCXX_DEMANGLER_RETURN
;
882 // <template-param> ::= T_ # first template parameter
883 // ::= T <parameter-2 non-negative number> _
885 template<typename Allocator
>
887 session
<Allocator
>::decode_template_param(string_type
& output
,
888 qualifier_list
<Allocator
>* qualifiers
)
890 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_template_parameter");
891 if (current() != 'T')
892 _GLIBCXX_DEMANGLER_FAILURE
;
893 unsigned int value
= 0;
895 if ((c
= next()) != '_')
899 value
= value
* 10 + c
- '0';
904 if (eat_current() != '_')
905 _GLIBCXX_DEMANGLER_FAILURE
;
906 value
+= M_template_arg_pos_offset
;
907 if (value
>= M_template_arg_pos
.size())
908 _GLIBCXX_DEMANGLER_FAILURE
;
909 int saved_pos
= M_pos
;
910 M_pos
= M_template_arg_pos
[value
];
911 if (M_inside_type
> 20) // Rather than core dump.
912 _GLIBCXX_DEMANGLER_FAILURE
;
913 ++M_inside_substitution
;
914 if (current() == 'X')
917 decode_expression(output
);
919 else if (current() == 'L')
920 decode_literal(output
);
922 decode_type(output
, qualifiers
);
923 --M_inside_substitution
;
925 _GLIBCXX_DEMANGLER_RETURN
;
928 template<typename Allocator
>
930 session
<Allocator
>::decode_real(string_type
& output
, size_t size_of_real
)
932 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_real");
934 unsigned long words
[4]; // 32 bit per long, maximum of 128 bits.
935 unsigned long* word
= &words
[0];
940 // The following assumes that leading zeroes are also included in the
941 // mangled name, I am not sure that is conforming to the C++-ABI, but
942 // it is what g++ does.
943 unsigned char nibble
, c
= current();
944 for(size_t word_cnt
= size_of_real
/ 4; word_cnt
> 0; --word_cnt
)
946 for (int nibble_cnt
= 0; nibble_cnt
< 8; ++nibble_cnt
)
948 // Translate character into nibble.
949 if (c
< '0' || c
> 'f')
950 _GLIBCXX_DEMANGLER_FAILURE
;
954 nibble
= c
- 'a' + 10;
956 _GLIBCXX_DEMANGLER_FAILURE
;
957 // Write nibble into word array.
959 *word
= nibble
<< 28;
961 *word
|= (nibble
<< (28 - 4 * nibble_cnt
));
967 if (M_implementation_details
.decode_real(buf
, words
, size_of_real
))
970 _GLIBCXX_DEMANGLER_RETURN
;
976 for(size_t nibble_cnt
= 0; nibble_cnt
< 2 * size_of_real
; ++nibble_cnt
)
978 if (c
< '0' || c
> 'f' || (c
> '9' && c
< 'a'))
979 _GLIBCXX_DEMANGLER_FAILURE
;
985 _GLIBCXX_DEMANGLER_RETURN
;
988 template<typename Allocator
>
990 session
<Allocator
>::decode_literal(string_type
& output
)
992 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_literal");
993 eat_current(); // Eat the 'L'.
994 if (current() == '_')
997 _GLIBCXX_DEMANGLER_FAILURE
;
999 if ((M_pos
+= decode_encoding(output
, M_str
+ M_pos
,
1000 M_maxpos
- M_pos
+ 1, M_implementation_details
)) < 0)
1001 _GLIBCXX_DEMANGLER_FAILURE
;
1006 if (current() == 'b')
1013 _GLIBCXX_DEMANGLER_RETURN
;
1016 if ((c
== 'i' || c
== 'j' || c
== 'l' ||
1017 c
== 'm' || c
== 'x' || c
== 'y') &&
1018 M_implementation_details
.get_style_literal())
1020 else if (c
== 'i' &&
1021 !M_implementation_details
.get_style_literal_int())
1026 if (!decode_type(output
))
1027 _GLIBCXX_DEMANGLER_FAILURE
;
1030 if (c
>= 'd' && c
<= 'g')
1032 size_t size_of_real
= (c
== 'd') ? sizeof(double) :
1033 ((c
== 'f') ? sizeof(float) :
1034 (c
== 'e') ? sizeof(long double) : 16);
1035 if (!decode_real(output
, size_of_real
))
1036 _GLIBCXX_DEMANGLER_FAILURE
;
1038 else if (!decode_number(output
))
1039 _GLIBCXX_DEMANGLER_FAILURE
;
1040 if (M_implementation_details
.get_style_literal())
1042 if (c
== 'j' || c
== 'm' || c
== 'y')
1044 if (c
== 'l' || c
== 'm')
1046 if (c
== 'x' || c
== 'y')
1050 _GLIBCXX_DEMANGLER_RETURN
;
1053 // <operator-name> ::=
1101 // st # sizeof (a type)
1102 // sz # sizeof (an expression)
1103 // cv <type> # (cast)
1104 // v <digit> <source-name> # vendor extended operator
1106 // Symbol operator codes exist of two characters, we need to find a
1107 // quick hash so that their names can be looked up in a table.
1110 // Shift the rows so that there is at most one character per column.
1112 // A perfect solution (Oh no, it's THE MATRIX!):
1114 // ....................................... offset + 'a'
1115 // a, a||d|||||||||n||||s|||||||||||||||||||| 0
1116 // c, || |||||||lm o||| |||||||||||||||||||| 0
1117 // d, || a|||e|| l|| ||||||v||||||||||||| 4
1118 // e, || ||| || || |||o|q ||||||||||||| 8
1119 // g, || ||| || || e|| | ||||||||t|||| 15
1120 // i, || ||| || || || | |||||||| |||x 15
1121 // l, |e ||| || st || | |||||||| ||| -2
1122 // m, | |i| lm || | |||||||| ||| -2
1123 // n, a e g t| w |||||||| ||| 1
1124 // o, | ||||o||r ||| 16
1125 // p, | ||lm |p st| 17
1129 // .......................................
1130 // ^ ^__ second character
1131 // |___ first character
1134 // Putting that solution in tables:
1136 char const offset_table_c
[1 + CHAR_MAX
- CHAR_MIN
] =
1138 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1139 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1140 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1141 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1142 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1143 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1145 // Add -CHAR_MIN extra zeroes (128):
1146 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1147 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1148 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1149 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1150 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1151 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1152 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1153 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1154 // a b c d e f g h i j k
1155 0, -97, 0, -97, -93, -89, 0, -82, 0, -82, 0, 0,
1156 // l m n o p q r s t u v
1157 -99, -99, -96, -81, -80, -91, -88, -85, 0, 0, 0,
1159 // a b c d e f g h i j k
1160 0, 159, 0, 159, 163, 167, 0, 174, 0, 174, 0, 0,
1161 // l m n o p q r s t u v
1162 157, 157, 160, 175, 176, 165, 168, 171, 0, 0, 0,
1176 char const* symbol_name
;
1180 entry_st
const symbol_name_table_c
[39] = {
1181 { "aa", "operator&&", binary
},
1182 { "na", "operator new[]", unary
},
1183 { "le", "operator<=", binary
},
1184 { "ad", "operator&", unary
},
1185 { "da", "operator delete[]", unary
},
1186 { "ne", "operator!=", binary
},
1187 { "mi=", "operator-", binary
},
1188 { "ng", "operator-", unary
},
1189 { "de", "operator*", unary
},
1190 { "ml=", "operator*", binary
},
1191 { "mm", "operator--", unary
},
1192 { "cl", "operator()", unary
},
1193 { "cm", "operator,", binary
},
1194 { "an=", "operator&", binary
},
1195 { "co", "operator~", binary
},
1196 { "dl", "operator delete", unary
},
1197 { "ls=", "operator<<", binary
},
1198 { "lt", "operator<", binary
},
1199 { "as=", "operator", binary
},
1200 { "ge", "operator>=", binary
},
1201 { "nt", "operator!", unary
},
1202 { "rm=", "operator%", binary
},
1203 { "eo=", "operator^", binary
},
1204 { "nw", "operator new", unary
},
1205 { "eq", "operator==", binary
},
1206 { "dv=", "operator/", binary
},
1207 { "qu", "operator?", trinary
},
1208 { "rs=", "operator>>", binary
},
1209 { "pl=", "operator+", binary
},
1210 { "pm", "operator->*", binary
},
1211 { "oo", "operator||", binary
},
1212 { "st", "sizeof", unary
},
1213 { "pp", "operator++", unary
},
1214 { "or=", "operator|", binary
},
1215 { "gt", "operator>", binary
},
1216 { "ps", "operator+", unary
},
1217 { "pt", "operator->", binary
},
1218 { "sz", "sizeof", unary
},
1219 { "ix", "operator[]", unary
}
1222 template<typename Allocator
>
1224 session
<Allocator
>::decode_operator_name(string_type
& output
)
1226 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_operator_name");
1228 char opcode0
= current();
1229 char opcode1
= tolower(next());
1232 if ((hash
= offset_table_c
[opcode0
- CHAR_MIN
]))
1241 int index
= static_cast<int>(static_cast<unsigned char>(hash
));
1242 entry_st entry
= symbol_name_table_c
[index
];
1243 if (entry
.opcode
[0] == opcode0
&& entry
.opcode
[1] == opcode1
1244 && (opcode1
== current() || entry
.opcode
[2] == '='))
1246 output
+= entry
.symbol_name
;
1247 if (opcode1
!= current())
1250 if (hash
== 16 || hash
== 17)
1251 M_template_args_need_space
= true;
1252 _GLIBCXX_DEMANGLER_RETURN
;
1254 else if (opcode0
== 'c' && opcode1
== 'v') // casting operator
1257 output
+= "operator ";
1258 if (current() == 'T')
1260 // This is a templated cast operator.
1261 // It must be of the form "cvT_I...E".
1262 // Let M_template_arg_pos already point
1263 // to the template argument.
1264 M_template_arg_pos_offset
= M_template_arg_pos
.size();
1265 M_template_arg_pos
.push_back(M_pos
+ 3);
1267 if (!decode_type(output
))
1268 _GLIBCXX_DEMANGLER_FAILURE
;
1269 if (!M_inside_template_args
)
1270 M_name_is_conversion_operator
= true;
1271 _GLIBCXX_DEMANGLER_RETURN
;
1275 _GLIBCXX_DEMANGLER_FAILURE
;
1279 // <expression> ::= <unary operator-name> <expression>
1280 // ::= <binary operator-name> <expression> <expression>
1281 // ::= <trinary operator-name> <expression> <expression> <expression>
1283 // ::= <template-param>
1284 // ::= sr <type> <unqualified-name> # dependent name
1285 // ::= sr <type> <unqualified-name> <template-args> # dependent template-id
1286 // ::= <expr-primary>
1288 // <expr-primary> ::= L <type> <value number> E # integer literal
1289 // ::= L <type> <value float> E # floating literal
1290 // ::= L <mangled-name> E # external name
1292 template<typename Allocator
>
1294 session
<Allocator
>::decode_expression(string_type
& output
)
1296 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_expression");
1297 if (current() == 'T')
1299 if (!decode_template_param(output
))
1300 _GLIBCXX_DEMANGLER_FAILURE
;
1301 _GLIBCXX_DEMANGLER_RETURN
;
1303 else if (current() == 'L')
1305 if (!decode_literal(output
))
1306 _GLIBCXX_DEMANGLER_FAILURE
;
1307 if (current() != 'E')
1308 _GLIBCXX_DEMANGLER_FAILURE
;
1310 _GLIBCXX_DEMANGLER_RETURN
;
1312 else if (current() == 's')
1314 char opcode1
= next();
1315 if (opcode1
== 't' || opcode1
== 'z')
1318 if (M_implementation_details
.get_style_compact_expr_ops())
1319 output
+= "sizeof(";
1321 output
+= "sizeof (";
1324 // I cannot think of a mangled name that is valid for both cases
1325 // when just replacing the 't' by a 'z' or vica versa, which
1326 // indicates that there is no ambiguity that dictates the need
1327 // for a seperate "st" case, except to be able catch invalid
1328 // mangled names. However there CAN be ambiguity in the demangled
1329 // name when there are both a type and a symbol of the same name,
1330 // which then leads to different encoding (of course) with
1331 // sizeof (type) or sizeof (expression) respectively, but that
1332 // ambiguity is not per se related to "sizeof" except that that
1333 // is the only place where both a type AND an expression are valid
1334 // in as part of a (template function) type.
1338 // struct B { typedef int t; };
1339 // struct A : public B { static int t[2]; };
1340 // template<int i, int j> struct C { typedef int q; };
1341 // template<int i, typename T>
1342 // void f(typename C<sizeof (typename T::t),
1343 // sizeof (T::t)>::q) { }
1344 // void instantiate() { f<5, A>(0); }
1346 // Leads to _Z1fILi5E1AEvN1CIXstN1T1tEEXszsrS2_1tEE1qE which
1348 // void f<5, A>(C<sizeof (T::t), sizeof (T::t)>::q)
1350 // This is ambiguity is very unlikely to happen and it is kind
1351 // of fuzzy to detect when adding a 'typename' makes sense.
1353 if (M_implementation_details
.get_style_sizeof_typename())
1355 // We can only get here inside a template parameter,
1356 // so this is syntactically correct if the given type is
1357 // a typedef. The only disadvantage is that it is inconsistent
1358 // with all other places where the 'typename' keyword should be
1359 // used and we don't.
1360 // With this, the above example will demangle as
1361 // void f<5, A>(C<sizeof (typename T::t), sizeof (T::t)>::q)
1362 if (current() == 'N' || // <nested-name>
1363 // This should be a safe bet.
1364 (current() == 'S' &&
1365 next_peek() == 't')) // std::something, guess that
1366 // this involves a typedef.
1367 output
+= "typename ";
1369 if (!decode_type(output
))
1370 _GLIBCXX_DEMANGLER_FAILURE
;
1374 if (!decode_expression(output
))
1375 _GLIBCXX_DEMANGLER_FAILURE
;
1378 _GLIBCXX_DEMANGLER_RETURN
;
1380 else if (current() == 'r')
1383 if (!decode_type(output
))
1384 _GLIBCXX_DEMANGLER_FAILURE
;
1386 if (!decode_unqualified_name(output
))
1387 _GLIBCXX_DEMANGLER_FAILURE
;
1388 if (current() != 'I' || decode_template_args(output
))
1389 _GLIBCXX_DEMANGLER_RETURN
;
1394 char opcode0
= current();
1395 char opcode1
= tolower(next());
1398 if ((hash
= offset_table_c
[opcode0
- CHAR_MIN
]))
1407 int index
= static_cast<int>(static_cast<unsigned char>(hash
));
1408 entry_st entry
= symbol_name_table_c
[index
];
1409 if (entry
.opcode
[0] == opcode0
&& entry
.opcode
[1] == opcode1
1410 && (opcode1
== current() || entry
.opcode
[2] == '='))
1412 char const* op
= entry
.symbol_name
+ 8; // Skip "operator".
1413 if (*op
== ' ') // operator new and delete.
1415 if (entry
.type
== unary
)
1417 bool is_eq
= (opcode1
!= current());
1419 if (index
== 34 && M_inside_template_args
) // operator>
1422 if (!decode_expression(output
))
1423 _GLIBCXX_DEMANGLER_FAILURE
;
1425 if (entry
.type
!= unary
)
1427 if (!M_implementation_details
.get_style_compact_expr_ops())
1432 if (!M_implementation_details
.get_style_compact_expr_ops())
1435 if (!decode_expression(output
))
1436 _GLIBCXX_DEMANGLER_FAILURE
;
1438 if (index
== 34 && M_inside_template_args
)
1440 if (entry
.type
== trinary
)
1442 if (M_implementation_details
.get_style_compact_expr_ops())
1446 if (!decode_expression(output
))
1447 _GLIBCXX_DEMANGLER_FAILURE
;
1451 _GLIBCXX_DEMANGLER_RETURN
;
1453 else if (opcode0
== 'c' &&
1454 opcode1
== 'v') // casting operator.
1458 if (!decode_type(output
))
1459 _GLIBCXX_DEMANGLER_FAILURE
;
1461 if (!decode_expression(output
))
1462 _GLIBCXX_DEMANGLER_FAILURE
;
1464 _GLIBCXX_DEMANGLER_RETURN
;
1469 _GLIBCXX_DEMANGLER_FAILURE
;
1473 // <template-args> ::= I <template-arg>+ E
1474 // <template-arg> ::= <type> # type or template
1475 // ::= L <type> <value number> E # integer literal
1476 // ::= L <type> <value float> E # floating literal
1477 // ::= L <mangled-name> E # external name
1478 // ::= X <expression> E # expression
1479 template<typename Allocator
>
1481 session
<Allocator
>::decode_template_args(string_type
& output
)
1483 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_template_args");
1484 if (eat_current() != 'I')
1485 _GLIBCXX_DEMANGLER_FAILURE
;
1486 int prev_size
= M_template_arg_pos
.size();
1487 ++M_inside_template_args
;
1488 if (M_template_args_need_space
)
1491 M_template_args_need_space
= false;
1496 if (M_inside_template_args
== 1 && !M_inside_type
)
1497 M_template_arg_pos
.push_back(M_pos
);
1498 if (current() == 'X')
1501 if (!decode_expression(output
))
1502 _GLIBCXX_DEMANGLER_FAILURE
;
1503 if (current() != 'E')
1504 _GLIBCXX_DEMANGLER_FAILURE
;
1507 else if (current() == 'L')
1509 if (!decode_literal(output
))
1510 _GLIBCXX_DEMANGLER_FAILURE
;
1511 if (current() != 'E')
1512 _GLIBCXX_DEMANGLER_FAILURE
;
1515 else if (!decode_type(output
))
1516 _GLIBCXX_DEMANGLER_FAILURE
;
1517 if (current() == 'E')
1522 if (*(output
.rbegin()) == '>')
1525 --M_inside_template_args
;
1526 if (!M_inside_template_args
&& !M_inside_type
)
1528 M_name_is_template
= true;
1529 M_template_arg_pos_offset
= prev_size
;
1531 _GLIBCXX_DEMANGLER_RETURN
;
1534 // <bare-function-type> ::=
1535 // <signature type>+ # Types are parameter types.
1537 // Note that the possible return type of the <bare-function-type>
1538 // has already been eaten before we call this function. This makes
1539 // our <bare-function-type> slightly different from the one in
1540 // the C++-ABI description.
1542 template<typename Allocator
>
1544 session
<Allocator
>::decode_bare_function_type(string_type
& output
)
1546 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_bare_function_type");
1547 if (M_saw_destructor
)
1549 if (eat_current() != 'v' || (current() != 'E' && current() != 0))
1550 _GLIBCXX_DEMANGLER_FAILURE
;
1552 M_saw_destructor
= false;
1553 _GLIBCXX_DEMANGLER_RETURN
;
1555 if (current() == 'v' && !M_implementation_details
.get_style_void())
1558 if (current() != 'E' && current() != 0)
1559 _GLIBCXX_DEMANGLER_FAILURE
;
1561 M_saw_destructor
= false;
1562 _GLIBCXX_DEMANGLER_RETURN
;
1565 M_template_args_need_space
= false;
1566 if (!decode_type(output
)) // Must have at least one parameter.
1567 _GLIBCXX_DEMANGLER_FAILURE
;
1568 while (current() != 'E' && current() != 0)
1571 if (!decode_type(output
))
1572 _GLIBCXX_DEMANGLER_FAILURE
;
1575 _GLIBCXX_DEMANGLER_RETURN
;
1579 // <builtin-type> # Starts with a lower case character != r.
1580 // <function-type> # Starts with F
1581 // <class-enum-type> # Starts with N, S, C, D, Z, a digit or a lower
1582 // # case character. Since a lower case character
1583 // # would be an operator name, that would be an
1584 // # error. The S is a substitution or St
1585 // # (::std::). A 'C' would be a constructor and
1586 // # thus also an error.
1587 // <template-param> # Starts with T
1588 // <substitution> # Starts with S
1589 // <template-template-param> <template-args> # Starts with T or S,
1590 // # equivalent with the above.
1592 // <array-type> # Starts with A
1593 // <pointer-to-member-type> # Starts with M
1594 // <CV-qualifiers> <type> # Starts with r, V or K
1595 // P <type> # pointer-to # Starts with P
1596 // R <type> # reference-to # Starts with R
1597 // C <type> # complex (C 2000) # Starts with C
1598 // G <type> # imaginary (C 2000)# Starts with G
1599 // U <source-name> <type> # vendor extended type qualifier,
1602 // <template-template-param> ::= <template-param>
1603 // ::= <substitution>
1605 // My own analysis of how to decode qualifiers:
1607 // F is a <function-type>, <T> is a <builtin-type>, <class-enum-type>,
1608 // <template-param> or <template-template-param> <template-args>.
1609 // <Q> represents a series of qualifiers (not G or C).
1610 // <C> is an unqualified type.
1611 // <R> is a qualified type.
1612 // <B> is the bare-function-type without return type.
1613 // <I> is the array index.
1615 // <Q>M<C><Q2>F<R><B>E ==> R (C::*Q)B Q2 "<C>", "F<R><B>E"
1616 // (<R> and <B> recursive),
1617 // "M<C><Q2>F<R><B>E".
1618 // <Q>F<R><B>E ==> R (Q)B "<R>", "<B>" (<B> recursive)
1621 // Note that if <R> has postfix qualifiers (an array or function), then
1622 // those are added AFTER the (member) function type. For example:
1623 // <Q>FPA<R><B>E ==> R (*(Q)B) [], where the PA added the prefix
1624 // "(*" and the postfix ") []".
1626 // <Q>G<T> ==> imaginary T Q "<T>", "G<T>" (<T> recursive).
1627 // <Q>C<T> ==> complex T Q "<T>", "C<T>" (<T> recursive).
1628 // <Q><T> ==> T Q "<T>" (<T> recursive).
1630 // where <Q> is any of:
1632 // <Q>P ==> *Q "P..."
1633 // <Q>R ==> &Q "R..."
1634 // <Q>[K|V|r]+ ==> [ const| volatile| restrict]+Q "KVr..."
1635 // <Q>U<S> ==> SQ "U<S>..."
1636 // <Q>M<C> ==> C::*Q "M<C>..." (<C> recurs.)
1637 // A<I> ==> [I] "A<I>..." (<I> recurs.)
1638 // <Q>A<I> ==> (Q) [I] "A<I>..." (<I> recurs.)
1639 // Note that when <Q> ends on an A<I2> then the brackets are omitted
1640 // and no space is written between the two:
1641 // A<I2>A<I> ==> [I2][I]
1642 // If <Q> ends on [KVr]+, which can happen in combination with
1643 // substitutions only, then special handling is required, see below.
1645 // A <substitution> is handled with an input position switch during which
1646 // new substitutions are turned off. Because recursive handling of types
1647 // (and therefore the order in which substitutions must be generated) must
1648 // be done left to right, but the generation of Q needs processing right to
1649 // left, substitutions per <type> are generated by reading the input left
1650 // to right and marking the starts of all substitutions only - implicitly
1651 // finishing them at the end of the type. Then the output and real
1652 // substitutions are generated.
1654 // The following comment was for the demangling of g++ version 3.0.x. The
1655 // mangling (and I believe even the ABI description) have been fixed now
1656 // (as of g++ version 3.1).
1659 // The ABI specifies for pointer-to-member function types the format
1660 // <Q>M<T>F<R><B>E. In other words, the qualifier <Q2> (see above) is
1661 // implicitely contained in <T> instead of explicitly part of the M format.
1662 // I am convinced that this is a bug in the ABI. Unfortunately, this is
1663 // how we have to demangle things as it has a direct impact on the order
1664 // in which substitutions are stored. This ill-formed design results in
1665 // rather ill-formed demangler code too however :/
1667 // <Q2> is now explicitely part of the M format.
1668 // For some weird reason, g++ (3.2.1) does not add substitutions for
1669 // qualified member function pointers. I think that is another bug.
1674 // where <Q> ends on [K|V|r]+ then that part should be processed as
1675 // if it was behind the A<I> instead of in front of it. This is
1676 // because a constant array of ints is normally always mangled as
1677 // an array of constant ints. KVr qualifiers can end up in front
1678 // of an array when the array is part of a substitution or template
1679 // parameter, but the demangling should still result in the same
1680 // syntax; thus KA2_i (const array of ints) must result in the same
1681 // demangling as A2_Ki (array of const ints). As a result we must
1682 // demangle ...[...[[KVr]+A<I0>][KVr]+A<I1>]...[KVr]+A<In>[KVr]+
1683 // as A<I0>A<I1>...A<In>[KVr]+ where each K, V and r in the series
1684 // collapses to a single character at the right of the string.
1686 // VA9_KrA6_KVi --> A9_A6_KVri --> int volatile const restrict [9][6]
1687 // Note that substitutions are still added as usual (the translation
1688 // to A9_A6_KVri does not really happen).
1690 // This decoding is achieved by delaying the decoding of any sequence
1691 // of [KVrA]'s and processing them together in the order: first the
1692 // short-circuited KVr part and then the arrays.
1693 static int const cvq_K
= 1; // Saw at least one K
1694 static int const cvq_V
= 2; // Saw at least one V
1695 static int const cvq_r
= 4; // Saw at least one r
1696 static int const cvq_A
= 8; // Saw at least one A
1697 static int const cvq_last
= 16; // No remaining qualifiers.
1698 static int const cvq_A_cnt
= 32; // Bit 5 and higher represent the
1699 // number of A's in the series.
1700 // In the function below, iter_array points to the first (right most)
1701 // A in the series, if any.
1702 template<typename Allocator
>
1704 qualifier_list
<Allocator
>::decode_KVrA(
1705 string_type
& prefix
, string_type
& postfix
, int cvq
,
1706 typename
qual_vector::const_reverse_iterator
const& iter_array
) const
1708 _GLIBCXX_DEMANGLER_DOUT_ENTERING3("decode_KVrA");
1712 prefix
+= " volatile";
1714 prefix
+= " restrict";
1718 for (typename
qual_vector::
1719 const_reverse_iterator iter
= iter_array
;
1720 iter
!= M_qualifier_starts
.rend(); ++iter
)
1722 switch((*iter
).first_qualifier())
1730 string_type index
= (*iter
).get_optional_type();
1731 if (--n
== 0 && (cvq
& cvq_last
))
1732 postfix
= " [" + index
+ "]" + postfix
;
1734 postfix
= "[" + index
+ "]" + postfix
;
1738 postfix
= ") [" + index
+ "]" + postfix
;
1743 _GLIBCXX_DEMANGLER_RETURN3
;
1747 _GLIBCXX_DEMANGLER_RETURN3
;
1750 template<typename Allocator
>
1752 qualifier_list
<Allocator
>::decode_qualifiers(
1753 string_type
& prefix
,
1754 string_type
& postfix
,
1755 bool member_function_pointer_qualifiers
= false) const
1757 _GLIBCXX_DEMANGLER_DOUT_ENTERING3("decode_qualifiers");
1759 typename
qual_vector::const_reverse_iterator iter_array
;
1760 for(typename
qual_vector::
1761 const_reverse_iterator iter
= M_qualifier_starts
.rbegin();
1762 iter
!= M_qualifier_starts
.rend(); ++iter
)
1764 if (!member_function_pointer_qualifiers
1765 && !(*iter
).part_of_substitution())
1767 int saved_inside_substitution
= M_demangler
.M_inside_substitution
;
1768 M_demangler
.M_inside_substitution
= 0;
1769 M_demangler
.add_substitution((*iter
).get_start_pos(), type
);
1770 M_demangler
.M_inside_substitution
= saved_inside_substitution
;
1772 char qualifier_char
= (*iter
).first_qualifier();
1773 for(; qualifier_char
; qualifier_char
= (*iter
).next_qualifier())
1775 switch(qualifier_char
)
1780 decode_KVrA(prefix
, postfix
, cvq
, iter_array
);
1788 decode_KVrA(prefix
, postfix
, cvq
, iter_array
);
1813 decode_KVrA(prefix
, postfix
, cvq
, iter_array
);
1817 prefix
+= (*iter
).get_optional_type();
1823 decode_KVrA(prefix
, postfix
, cvq
, iter_array
);
1827 prefix
+= (*iter
).get_optional_type();
1829 case 'G': // Only here so we added a substitution.
1836 decode_KVrA(prefix
, postfix
, cvq
|cvq_last
, iter_array
);
1837 M_printing_suppressed
= false;
1838 _GLIBCXX_DEMANGLER_RETURN3
;
1842 template<typename Allocator
>
1844 session
<Allocator
>::decode_type_with_postfix(
1845 string_type
& prefix
, string_type
& postfix
,
1846 qualifier_list
<Allocator
>* qualifiers
)
1848 _GLIBCXX_DEMANGLER_DOUT_ENTERING2("decode_type");
1850 bool recursive_template_param_or_substitution_call
;
1851 if (!(recursive_template_param_or_substitution_call
= qualifiers
))
1852 qualifiers
= new qualifier_list
<Allocator
>(*this);
1853 // First eat all qualifiers.
1854 bool failure
= false;
1855 for(;;) // So we can use 'continue' to eat the next qualifier.
1857 int start_pos
= M_pos
;
1861 qualifiers
->add_qualifier_start(pointer
, start_pos
,
1862 M_inside_substitution
);
1866 qualifiers
->add_qualifier_start(reference
, start_pos
,
1867 M_inside_substitution
);
1881 while(c
== 'K' || c
== 'V' || c
== 'r');
1882 qualifiers
->add_qualifier_start(cv_qualifier
, start_pos
, count
,
1883 M_inside_substitution
);
1889 string_type source_name
;
1890 if (!decode_source_name(source_name
))
1895 qualifiers
->add_qualifier_start(vendor_extension
, start_pos
,
1896 source_name
, M_inside_substitution
);
1901 // <array-type> ::= A <positive dimension number> _ <element type>
1902 // ::= A [<dimension expression>] _ <element type>
1907 if (next() == 'n' || !decode_number(index
))
1910 if (next() != '_' && !decode_expression(index
))
1916 if (eat_current() != '_')
1921 qualifiers
->add_qualifier_start(array
, start_pos
, index
,
1922 M_inside_substitution
);
1927 // <pointer-to-member-type> ::= M <class type> <member type>
1928 // <Q>M<C> or <Q>M<C><Q2>F<R><B>E
1930 string_type class_type
;
1931 if (!decode_type(class_type
)) // Substitution: "<C>".
1937 if (c
== 'F' || c
== 'K' || c
== 'V' || c
== 'r')
1938 // Must be CV-qualifiers and a member function pointer.
1940 // <Q>M<C><Q2>F<R><B>E ==> R (C::*Q)B Q2
1941 // substitutions: "<C>", "F<R><B>E" (<R> and <B>
1942 // recursive), "M<C><Q2>F<R><B>E".
1944 int Q2_start_pos
= M_pos
;
1945 while(c
== 'K' || c
== 'V' || c
== 'r') // Decode <Q2>.
1950 qualifier_list
<Allocator
> class_type_qualifiers(*this);
1952 class_type_qualifiers
.
1953 add_qualifier_start(cv_qualifier
, Q2_start_pos
,
1954 count
, M_inside_substitution
);
1955 string_type member_function_qualifiers
;
1956 // It is unclear why g++ doesn't add a substitution for
1957 // "<Q2>F<R><B>E" as it should I think.
1958 string_type member_function_qualifiers_postfix
;
1959 class_type_qualifiers
.
1960 decode_qualifiers(member_function_qualifiers
,
1961 member_function_qualifiers_postfix
, true);
1962 member_function_qualifiers
+=
1963 member_function_qualifiers_postfix
;
1964 // I don't think this substitution is actually ever used.
1965 int function_pos
= M_pos
;
1966 if (eat_current() != 'F')
1972 // Constructors, destructors and conversion operators don't
1973 // have a return type, but seem to never get here.
1974 string_type return_type_postfix
;
1975 if (!decode_type_with_postfix(prefix
, return_type_postfix
))
1976 // substitution: <R> recursive
1982 prefix
+= class_type
;
1984 string_type bare_function_type
;
1985 if (!decode_bare_function_type(bare_function_type
)
1986 || eat_current() != 'E') // Substitution: <B> recursive.
1991 // substitution: "F<R><B>E".
1992 add_substitution(function_pos
, type
);
1993 // substitution: "M<C><Q2>F<R><B>E".
1994 add_substitution(start_pos
, type
);
1995 // substitution: all qualified types if any.
1996 qualifiers
->decode_qualifiers(prefix
, postfix
);
1998 postfix
+= bare_function_type
;
1999 postfix
+= member_function_qualifiers
;
2000 postfix
+= return_type_postfix
;
2001 goto decode_type_exit
;
2003 qualifiers
->add_qualifier_start(pointer_to_member
, start_pos
,
2004 class_type
, M_inside_substitution
);
2014 // <Q>G<T> ==> imaginary T Q
2015 // substitutions: "<T>", "G<T>" (<T> recursive).
2016 // <Q>C<T> ==> complex T Q
2017 // substitutions: "<T>", "C<T>" (<T> recursive).
2018 if (current() == 'C' || current() == 'G')
2020 prefix
+= current() == 'C' ? "complex " : "imaginary ";
2021 qualifiers
->add_qualifier_start(complex_or_imaginary
, M_pos
,
2022 M_inside_substitution
);
2025 int start_pos
= M_pos
;
2030 // <function-type> ::= F [Y] <bare-function-type> E
2032 // Note that g++ never generates the 'Y', but we try to
2033 // demangle it anyway.
2034 bool extern_C
= (next() == 'Y');
2038 // <Q>F<R><B>E ==> R (Q)B
2039 // substitution: "<R>", "<B>" (<B> recursive) and "F<R><B>E".
2042 string_type return_type_postfix
;
2043 if (!decode_type_with_postfix(prefix
, return_type_postfix
))
2044 // Substitution: "<R>".
2049 // Only array and function (pointer) types have a postfix.
2050 // In that case we don't want the space but expect something
2051 // like prefix is "int (*" and postfix is ") [1]".
2052 // We do want the space if this pointer is qualified.
2053 if (return_type_postfix
.size() == 0 ||
2054 (prefix
.size() > 0 && *prefix
.rbegin() != '*'))
2057 string_type bare_function_type
;
2058 if (!decode_bare_function_type(bare_function_type
)
2059 // substitution: "<B>" (<B> recursive).
2060 || eat_current() != 'E')
2065 add_substitution(start_pos
, type
); // Substitution: "F<R><B>E".
2066 qualifiers
->decode_qualifiers(prefix
, postfix
);
2067 // substitution: all qualified types, if any.
2070 postfix
+= " [extern \"C\"] ";
2071 postfix
+= bare_function_type
;
2072 postfix
+= return_type_postfix
;
2076 if (!decode_template_param(prefix
, qualifiers
))
2081 if (current() == 'I')
2083 add_substitution(start_pos
, template_template_param
);
2084 // substitution: "<template-template-param>".
2085 if (!decode_template_args(prefix
))
2091 if (!recursive_template_param_or_substitution_call
2092 && qualifiers
->suppressed())
2094 add_substitution(start_pos
, type
);
2095 // substitution: "<template-param>" or
2096 // "<template-template-param> <template-args>".
2097 qualifiers
->decode_qualifiers(prefix
, postfix
);
2098 // substitution: all qualified types, if any.
2102 if (M_pos
>= M_maxpos
)
2107 if (M_str
[M_pos
+ 1] != 't')
2109 if (!decode_substitution(prefix
, qualifiers
))
2114 if (current() == 'I')
2116 if (!decode_template_args(prefix
))
2121 if (!recursive_template_param_or_substitution_call
2122 && qualifiers
->suppressed())
2123 add_substitution(start_pos
, type
);
2125 // "<template-template-param> <template-args>".
2127 if (!recursive_template_param_or_substitution_call
2128 && qualifiers
->suppressed())
2129 qualifiers
->decode_qualifiers(prefix
, postfix
);
2130 // Substitution: all qualified types, if any.
2133 /* Fall-through for St */
2147 // substitutions: "<T>" (<T> recursive).
2148 if (!decode_class_enum_type(prefix
))
2153 if (!recursive_template_param_or_substitution_call
)
2155 add_substitution(start_pos
, type
);
2156 // substitution: "<class-enum-type>".
2157 qualifiers
->decode_qualifiers(prefix
, postfix
);
2158 // substitution: all qualified types, if any.
2161 qualifiers
->printing_suppressed();
2165 // substitutions: "<T>" (<T> recursive).
2166 if (!decode_builtin_type(prefix
))
2171 // If decode_type was called from decode_template_param then we
2172 // need to suppress calling qualifiers here in order to get a
2173 // substitution added anyway (for the <template-param>).
2174 if (!recursive_template_param_or_substitution_call
)
2175 qualifiers
->decode_qualifiers(prefix
, postfix
);
2177 qualifiers
->printing_suppressed();
2183 if (!recursive_template_param_or_substitution_call
)
2186 _GLIBCXX_DEMANGLER_FAILURE
;
2187 _GLIBCXX_DEMANGLER_RETURN2
;
2190 // <nested-name> ::= N [<CV-qualifiers>] <prefix> <unqualified-name> E
2191 // ::= N [<CV-qualifiers>] <template-prefix> <template-args> E
2193 // <prefix> ::= <prefix> <unqualified-name>
2194 // ::= <template-prefix> <template-args>
2195 // ::= <template-param>
2197 // ::= <substitution>
2199 // <template-prefix> ::= <prefix> <template unqualified-name>
2200 // ::= <template-param>
2201 // ::= <substitution>
2203 template<typename Allocator
>
2205 session
<Allocator
>::decode_nested_name(string_type
& output
,
2206 string_type
& qualifiers
)
2208 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_nested_name");
2210 if (current() != 'N' || M_pos
>= M_maxpos
)
2211 _GLIBCXX_DEMANGLER_FAILURE
;
2213 // <CV-qualifiers> ::= [r] [V] [K] # restrict (C99), volatile, const
2214 char const* qualifiers_start
= &M_str
[M_pos
+ 1];
2215 for (char c
= next(); c
== 'K' || c
== 'V' || c
== 'r'; c
= next());
2216 for (char const* qualifier_ptr
= &M_str
[M_pos
- 1];
2217 qualifier_ptr
>= qualifiers_start
; --qualifier_ptr
)
2218 switch(*qualifier_ptr
)
2221 qualifiers
+= " const";
2224 qualifiers
+= " volatile";
2227 qualifiers
+= " restrict";
2231 int number_of_prefixes
= 0;
2232 int substitution_start
= M_pos
;
2235 ++number_of_prefixes
;
2236 if (current() == 'S')
2238 if (!decode_substitution(output
))
2239 _GLIBCXX_DEMANGLER_FAILURE
;
2241 else if (current() == 'I')
2243 if (!decode_template_args(output
))
2244 _GLIBCXX_DEMANGLER_FAILURE
;
2245 if (current() != 'E')
2247 // substitution: "<template-prefix> <template-args>".
2248 add_substitution(substitution_start
, nested_name_prefix
,
2249 number_of_prefixes
);
2254 if (current() == 'T')
2256 if (!decode_template_param(output
))
2257 _GLIBCXX_DEMANGLER_FAILURE
;
2259 else if (!decode_unqualified_name(output
))
2260 _GLIBCXX_DEMANGLER_FAILURE
;
2261 if (current() != 'E')
2263 // substitution: "<prefix> <unqualified-name>" or
2264 // "<prefix> <template unqualified-name>".
2265 add_substitution(substitution_start
,
2266 (current() == 'I') ? nested_name_template_prefix
2267 : nested_name_prefix
,
2268 number_of_prefixes
);
2271 if (current() == 'E')
2274 _GLIBCXX_DEMANGLER_RETURN
;
2276 if (current() != 'I')
2278 else if (M_template_args_need_space
)
2280 M_template_args_need_space
= false;
2282 _GLIBCXX_DEMANGLER_FAILURE
;
2285 // <local-name> := Z <function encoding> E <entity name> [<discriminator>]
2286 // := Z <function encoding> E s [<discriminator>]
2287 // <discriminator> := _ <non-negative number>
2289 template<typename Allocator
>
2291 session
<Allocator
>::decode_local_name(string_type
& output
)
2293 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_local_name");
2294 if (current() != 'Z' || M_pos
>= M_maxpos
)
2295 _GLIBCXX_DEMANGLER_FAILURE
;
2296 if ((M_pos
+= decode_encoding(output
, M_str
+ M_pos
+ 1,
2297 M_maxpos
- M_pos
, M_implementation_details
) + 1) < 0 ||
2298 eat_current() != 'E')
2299 _GLIBCXX_DEMANGLER_FAILURE
;
2301 if (current() == 's')
2304 output
+= "string literal";
2308 string_type nested_name_qualifiers
;
2309 if (!decode_name(output
, nested_name_qualifiers
))
2310 _GLIBCXX_DEMANGLER_FAILURE
;
2311 output
+= nested_name_qualifiers
;
2313 string_type discriminator
;
2314 if (current() == '_' && next() != 'n' && !decode_number(discriminator
))
2315 _GLIBCXX_DEMANGLER_FAILURE
;
2316 _GLIBCXX_DEMANGLER_RETURN
;
2319 // <source-name> ::= <positive length number> <identifier>
2321 template<typename Allocator
>
2323 session
<Allocator
>::decode_source_name(string_type
& output
)
2325 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_source_name");
2326 int length
= current() - '0';
2327 if (length
< 1 || length
> 9)
2328 _GLIBCXX_DEMANGLER_FAILURE
;
2329 while(isdigit(next()))
2330 length
= 10 * length
+ current() - '0';
2331 char const* ptr
= &M_str
[M_pos
];
2332 if (length
> 11 && !strncmp(ptr
, "_GLOBAL_", 8) && ptr
[9] == 'N'
2333 && ptr
[8] == ptr
[10])
2335 output
+= "(anonymous namespace)";
2336 if ((M_pos
+= length
) > M_maxpos
+ 1)
2337 _GLIBCXX_DEMANGLER_FAILURE
;
2343 _GLIBCXX_DEMANGLER_FAILURE
;
2344 output
+= eat_current();
2346 _GLIBCXX_DEMANGLER_RETURN
;
2349 // <unqualified-name> ::= <operator-name> # Starts with lower case.
2350 // ::= <ctor-dtor-name> # Starts with 'C' or 'D'.
2351 // ::= <source-name> # Starts with a digit.
2353 template<typename Allocator
>
2355 session
<Allocator
>::decode_unqualified_name(string_type
& output
)
2357 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_unqualified_name");
2358 if (M_inside_template_args
)
2360 if (!decode_source_name(output
))
2361 _GLIBCXX_DEMANGLER_FAILURE
;
2363 else if (isdigit(current()))
2365 bool recursive_unqualified_name
= (&M_function_name
== &output
);
2366 // This can be a recursive call when we are decoding
2367 // an <operator-name> that is a cast operator for a some
2368 // <unqualified-name>; for example "operator Foo()".
2369 // In that case this is thus not a ctor or dtor and we
2370 // are not interested in updating M_function_name.
2371 if (!recursive_unqualified_name
)
2372 M_function_name
.clear();
2373 M_name_is_template
= false;
2374 M_name_is_cdtor
= false;
2375 M_name_is_conversion_operator
= false;
2376 if (!decode_source_name(M_function_name
))
2377 _GLIBCXX_DEMANGLER_FAILURE
;
2378 if (!recursive_unqualified_name
)
2379 output
+= M_function_name
;
2381 else if (islower(current()))
2383 M_function_name
.clear();
2384 M_name_is_template
= false;
2385 M_name_is_cdtor
= false;
2386 M_name_is_conversion_operator
= false;
2387 if (!decode_operator_name(M_function_name
))
2388 _GLIBCXX_DEMANGLER_FAILURE
;
2389 output
+= M_function_name
;
2391 else if (current() == 'C' || current() == 'D')
2393 // <ctor-dtor-name> ::=
2394 // C1 # complete object (in-charge) constructor
2395 // C2 # base object (not-in-charge) constructor
2396 // C3 # complete object (in-charge) allocating constructor
2397 // D0 # deleting (in-charge) destructor
2398 // D1 # complete object (in-charge) destructor
2399 // D2 # base object (not-in-charge) destructor
2401 if (current() == 'C')
2404 if (c
< '1' || c
> '3')
2405 _GLIBCXX_DEMANGLER_FAILURE
;
2410 if (c
< '0' || c
> '2')
2411 _GLIBCXX_DEMANGLER_FAILURE
;
2413 M_saw_destructor
= true;
2415 M_name_is_cdtor
= true;
2417 output
+= M_function_name
;
2420 _GLIBCXX_DEMANGLER_FAILURE
;
2421 _GLIBCXX_DEMANGLER_RETURN
;
2424 // <unscoped-name> ::=
2425 // <unqualified-name> # Starts not with an 'S'
2426 // St <unqualified-name> # ::std::
2428 template<typename Allocator
>
2430 session
<Allocator
>::decode_unscoped_name(string_type
& output
)
2432 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_unscoped_name");
2433 if (current() == 'S')
2436 _GLIBCXX_DEMANGLER_FAILURE
;
2440 decode_unqualified_name(output
);
2441 _GLIBCXX_DEMANGLER_RETURN
;
2445 // <nested-name> # Starts with 'N'
2446 // <unscoped-template-name> <template-args> # idem
2447 // <local-name> # Starts with 'Z'
2448 // <unscoped-name> # Starts with 'S', 'C', 'D',
2449 // # a digit or a lower case
2452 // <unscoped-template-name> ::= <unscoped-name>
2453 // ::= <substitution>
2454 template<typename Allocator
>
2456 session
<Allocator
>::decode_name(string_type
& output
,
2457 string_type
& nested_name_qualifiers
)
2459 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_name");
2460 int substitution_start
= M_pos
;
2461 if (current() == 'S' && (M_pos
>= M_maxpos
|| M_str
[M_pos
+ 1] != 't'))
2463 if (!decode_substitution(output
))
2464 _GLIBCXX_DEMANGLER_FAILURE
;
2466 else if (current() == 'N')
2468 decode_nested_name(output
, nested_name_qualifiers
);
2469 _GLIBCXX_DEMANGLER_RETURN
;
2471 else if (current() == 'Z')
2473 decode_local_name(output
);
2474 _GLIBCXX_DEMANGLER_RETURN
;
2476 else if (!decode_unscoped_name(output
))
2477 _GLIBCXX_DEMANGLER_FAILURE
;
2478 if (current() == 'I')
2480 // Must have been an <unscoped-template-name>.
2481 add_substitution(substitution_start
, unscoped_template_name
);
2482 if (!decode_template_args(output
))
2483 _GLIBCXX_DEMANGLER_FAILURE
;
2485 M_template_args_need_space
= false;
2486 _GLIBCXX_DEMANGLER_RETURN
;
2489 // <call-offset> ::= h <nv-offset> _
2490 // ::= v <v-offset> _
2491 // <nv-offset> ::= <offset number>
2492 // non-virtual base override
2494 // <v-offset> ::= <offset number> _ <virtual offset number>
2495 // virtual base override, with vcall offset
2496 template<typename Allocator
>
2498 session
<Allocator
>::decode_call_offset(string_type
&
2499 #if _GLIBCXX_DEMANGLER_CWDEBUG
2504 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_call_offset");
2505 if (current() == 'h')
2509 if (decode_number(dummy
) && current() == '_')
2512 _GLIBCXX_DEMANGLER_RETURN
;
2515 else if (current() == 'v')
2519 if (decode_number(dummy
) && current() == '_')
2522 if (decode_number(dummy
) && current() == '_')
2525 _GLIBCXX_DEMANGLER_RETURN
;
2529 _GLIBCXX_DEMANGLER_FAILURE
;
2533 // <special-name> ::=
2534 // TV <type> # virtual table
2535 // TT <type> # VTT structure (construction
2537 // TI <type> # typeinfo structure
2538 // TS <type> # typeinfo name (null-terminated
2540 // GV <object name> # Guard variable for one-time
2541 // initialization of static objects in
2543 // T <call-offset> <base encoding># base is the nominal target function
2545 // Tc <call-offset> <call-offset> <base encoding> # base is the nominal
2546 // target function of thunk; first
2547 // call-offset is 'this' adjustment;
2548 // second call-offset is result
2551 template<typename Allocator
>
2553 session
<Allocator
>::decode_special_name(string_type
& output
)
2555 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_special_name");
2556 if (current() == 'G')
2559 _GLIBCXX_DEMANGLER_FAILURE
;
2560 output
+= "guard variable for ";
2561 string_type nested_name_qualifiers
;
2563 if (!decode_name(output
, nested_name_qualifiers
))
2564 _GLIBCXX_DEMANGLER_FAILURE
;
2565 output
+= nested_name_qualifiers
;
2566 _GLIBCXX_DEMANGLER_RETURN
;
2568 else if (current() != 'T')
2569 _GLIBCXX_DEMANGLER_FAILURE
;
2573 output
+= "vtable for ";
2575 decode_type(output
);
2576 _GLIBCXX_DEMANGLER_RETURN
;
2578 output
+= "VTT for ";
2580 decode_type(output
);
2581 _GLIBCXX_DEMANGLER_RETURN
;
2583 output
+= "typeinfo for ";
2585 decode_type(output
);
2586 _GLIBCXX_DEMANGLER_RETURN
;
2588 output
+= "typeinfo name for ";
2590 decode_type(output
);
2591 _GLIBCXX_DEMANGLER_RETURN
;
2593 output
+= "covariant return thunk to ";
2594 if (!decode_call_offset(output
)
2595 || !decode_call_offset(output
)
2596 || (M_pos
+= decode_encoding(output
, M_str
+ M_pos
,
2597 M_maxpos
- M_pos
+ 1, M_implementation_details
)) < 0)
2598 _GLIBCXX_DEMANGLER_FAILURE
;
2599 _GLIBCXX_DEMANGLER_RETURN
;
2600 case 'C': // GNU extension?
2603 output
+= "construction vtable for ";
2605 if (!decode_type(first
))
2606 _GLIBCXX_DEMANGLER_FAILURE
;
2607 while(isdigit(current()))
2609 if (eat_current() != '_')
2610 _GLIBCXX_DEMANGLER_FAILURE
;
2611 if (!decode_type(output
))
2612 _GLIBCXX_DEMANGLER_FAILURE
;
2615 _GLIBCXX_DEMANGLER_RETURN
;
2618 if (current() == 'v')
2619 output
+= "virtual thunk to ";
2621 output
+= "non-virtual thunk to ";
2622 if (!decode_call_offset(output
)
2623 || (M_pos
+= decode_encoding(output
, M_str
+ M_pos
,
2624 M_maxpos
- M_pos
+ 1, M_implementation_details
)) < 0)
2625 _GLIBCXX_DEMANGLER_FAILURE
;
2626 _GLIBCXX_DEMANGLER_RETURN
;
2631 // <function name> <bare-function-type> # Starts with 'C', 'D', 'N',
2632 // 'S', a digit or a lower case
2634 // <data name> # Idem.
2635 // <special-name> # Starts with 'T' or 'G'.
2636 template<typename Allocator
>
2638 session
<Allocator
>::decode_encoding(string_type
& output
,
2639 char const* in
, int len
, implementation_details
const& id
)
2641 #if _GLIBCXX_DEMANGLER_CWDEBUG
2642 _GLIBCXX_DEMANGLER_DOUT(dc::demangler
,
2643 "Output thus far: \"" << output
<< '"');
2644 string_type
input(in
, len
> 0x40000000 ? strlen(in
) : len
);
2645 _GLIBCXX_DEMANGLER_DOUT(
2646 dc::demangler
, "Entering decode_encoding(\"" << input
<< "\")");
2650 session
<Allocator
> demangler_session(in
, len
, id
);
2651 string_type nested_name_qualifiers
;
2653 demangler_session
.store(saved_pos
);
2654 if (demangler_session
.decode_special_name(output
))
2655 return demangler_session
.M_pos
;
2656 demangler_session
.restore(saved_pos
);
2658 if (!demangler_session
.decode_name(name
, nested_name_qualifiers
))
2660 if (demangler_session
.current() == 0
2661 || demangler_session
.current() == 'E')
2664 output
+= nested_name_qualifiers
;
2665 return demangler_session
.M_pos
;
2667 // Must have been a <function name>.
2668 string_type return_type_postfix
;
2669 if (demangler_session
.M_name_is_template
2670 && !(demangler_session
.M_name_is_cdtor
2671 || demangler_session
.M_name_is_conversion_operator
))
2673 // Return type of function
2674 if (!demangler_session
.decode_type_with_postfix(output
,
2675 return_type_postfix
))
2680 if (!demangler_session
.decode_bare_function_type(output
))
2682 output
+= nested_name_qualifiers
;
2683 output
+= return_type_postfix
;
2684 return demangler_session
.M_pos
;
2687 } // namespace demangler
2690 template<typename Allocator
>
2693 typedef typename
Allocator::template rebind
<char>::other char_Allocator
;
2694 typedef std::basic_string
<char, std::char_traits
<char>, char_Allocator
>
2696 static string_type
symbol(char const* in
,
2697 demangler::implementation_details
const& id
);
2698 static string_type
type(char const* in
,
2699 demangler::implementation_details
const& id
);
2702 // demangle::symbol()
2704 // Demangle `input' which should be a mangled function name as for
2705 // instance returned by nm(1).
2706 template<typename Allocator
>
2707 typename demangle
<Allocator
>::string_type
2708 demangle
<Allocator
>::symbol(char const* input
,
2709 demangler::implementation_details
const& id
)
2711 // <mangled-name> ::= _Z <encoding>
2712 // <mangled-name> ::= _GLOBAL_ _<type>_ <disambiguation part>
2713 // <type> can be I or D (GNU extension)
2714 typedef demangler::session
<Allocator
> demangler_type
;
2716 bool failure
= (input
[0] != '_');
2720 if (input
[1] == 'G')
2722 if (!strncmp(input
, "_GLOBAL__", 9)
2723 && (input
[9] == 'D' || input
[9] == 'I')
2724 && input
[10] == '_')
2726 if (input
[9] == 'D')
2727 result
.assign("global destructors keyed to ", 28);
2729 result
.assign("global constructors keyed to ", 29);
2730 // Output the disambiguation part as-is.
2731 result
+= input
+ 11;
2736 else if (input
[1] == 'Z')
2739 demangler_type::decode_encoding(result
, input
+ 2, INT_MAX
, id
);
2740 if (cnt
< 0 || input
[cnt
+ 2] != 0)
2747 // Failure to demangle, return the mangled name.
2749 result
.assign(input
, strlen(input
));
2755 // Demangle `input' which must be a zero terminated mangled type
2756 // name as for instance returned by std::type_info::name().
2757 template<typename Allocator
>
2758 typename demangle
<Allocator
>::string_type
2759 demangle
<Allocator
>::type(char const* input
,
2760 demangler::implementation_details
const& id
)
2762 std::basic_string
<char, std::char_traits
<char>, Allocator
> result
;
2767 demangler::session
<Allocator
> demangler_session(input
, INT_MAX
, id
);
2768 if (!demangler_session
.decode_type(result
)
2769 || demangler_session
.remaining_input_characters())
2771 // Failure to demangle, return the mangled name.
2778 } // namespace __gnu_cxx
2780 #endif // __DEMANGLE_H