1 // C++ IA64 / g++ v3 demangler -*- C++ -*-
3 // Copyright (C) 2003, 2004 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
40 #include <ext/new_allocator.h>
42 #ifndef _GLIBCXX_DEMANGLER_DEBUG
43 #define _GLIBCXX_DEMANGLER_CWDEBUG 0
44 #define _GLIBCXX_DEMANGLER_DEBUG(x)
45 #define _GLIBCXX_DEMANGLER_DOUT(cntrl, data)
46 #define _GLIBCXX_DEMANGLER_DOUT_ENTERING(x)
47 #define _GLIBCXX_DEMANGLER_DOUT_ENTERING2(x)
48 #define _GLIBCXX_DEMANGLER_DOUT_ENTERING3(x)
49 #define _GLIBCXX_DEMANGLER_RETURN return M_result
50 #define _GLIBCXX_DEMANGLER_RETURN2 return M_result
51 #define _GLIBCXX_DEMANGLER_RETURN3
52 #define _GLIBCXX_DEMANGLER_FAILURE \
53 do { M_result = false; return false; } while(0)
55 #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 Tp
, typename Allocator
= __gnu_cxx::new_allocator
<Tp
> >
107 template<typename Tp
, typename Allocator
= __gnu_cxx::new_allocator
<Tp
> >
108 class qualifier_list
;
110 template<typename Tp
, typename Allocator
= __gnu_cxx::new_allocator
<Tp
> >
113 template<typename Tp
, 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 Tp
, 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
<Tp
, 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
<Tp
, 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
<Tp
, 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
<Tp
, 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
<Tp
, 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
<Tp
, 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 Tp
, typename Allocator
>
354 friend class qualifier_list
<Tp
, Allocator
>;
355 typedef typename
Allocator::template rebind
<char>::other
357 typedef std::basic_string
<char, std::char_traits
<char>, char_Allocator
>
365 int M_inside_template_args
;
367 int M_inside_substitution
;
368 bool M_saw_destructor
;
369 bool M_name_is_cdtor
;
370 bool M_name_is_template
;
371 bool M_name_is_conversion_operator
;
372 bool M_template_args_need_space
;
373 string_type M_function_name
;
374 typedef typename
Allocator::template rebind
<int>::other
376 typedef typename
Allocator::template rebind
<substitution_st
>::other
378 std::vector
<int, int_Allocator
> M_template_arg_pos
;
379 int M_template_arg_pos_offset
;
380 std::vector
<substitution_st
, subst_Allocator
> M_substitutions_pos
;
381 implementation_details
const& M_implementation_details
;
382 typedef typename
Allocator::template
383 rebind
<qualifier_list
<Allocator
> >::other qualifier_list_Allocator
;
384 qualifier_list_Allocator M_qualifier_list_alloc
;
385 #if _GLIBCXX_DEMANGLER_CWDEBUG
386 bool M_inside_add_substitution
;
390 explicit session(char const* in
, int len
,
391 implementation_details
const& id
= implementation_details())
392 : M_str(in
), M_pos(0), M_maxpos(len
- 1), M_result(true),
393 M_inside_template_args(0), M_inside_type(0),
394 M_inside_substitution(0), M_saw_destructor(false),
395 M_name_is_cdtor(false), M_name_is_template(false),
396 M_name_is_conversion_operator(false),
397 M_template_args_need_space(false), M_template_arg_pos_offset(0),
398 M_implementation_details(id
)
399 #if _GLIBCXX_DEMANGLER_CWDEBUG
400 , M_inside_add_substitution(false)
405 decode_encoding(string_type
& output
, char const* input
, int len
,
406 implementation_details
const& id
= implementation_details());
409 decode_type(string_type
& output
,
410 qualifier_list
<Tp
, Allocator
>* qualifiers
= NULL
)
413 bool res
= decode_type_with_postfix(output
, postfix
, qualifiers
);
419 remaining_input_characters(void) const
420 { return current() != 0; }
425 { return (M_pos
> M_maxpos
) ? 0 : M_str
[M_pos
]; }
428 next_peek(void) const
429 { return (M_pos
>= M_maxpos
) ? 0 : M_str
[M_pos
+ 1]; }
433 { return (M_pos
>= M_maxpos
) ? 0 : M_str
[++M_pos
]; }
437 { return (M_pos
> M_maxpos
) ? 0 : M_str
[M_pos
++]; }
440 store(int& saved_pos
)
441 { saved_pos
= M_pos
; }
444 restore(int saved_pos
)
445 { M_pos
= saved_pos
; M_result
= true; }
448 add_substitution(int start_pos
,
449 substitution_nt sub_type
,
450 int number_of_prefixes
);
452 bool decode_type_with_postfix(string_type
& prefix
,
453 string_type
& postfix
, qualifier_list
<Tp
, Allocator
>* qualifiers
= NULL
);
454 bool decode_bare_function_type(string_type
& output
);
455 bool decode_builtin_type(string_type
& output
);
456 bool decode_call_offset(string_type
& output
);
457 bool decode_class_enum_type(string_type
& output
);
458 bool decode_expression(string_type
& output
);
459 bool decode_literal(string_type
& output
);
460 bool decode_local_name(string_type
& output
);
461 bool decode_name(string_type
& output
,
462 string_type
& nested_name_qualifiers
);
463 bool decode_nested_name(string_type
& output
,
464 string_type
& qualifiers
);
465 bool decode_number(string_type
& output
);
466 bool decode_operator_name(string_type
& output
);
467 bool decode_source_name(string_type
& output
);
468 bool decode_substitution(string_type
& output
,
469 qualifier_list
<Tp
, Allocator
>* qualifiers
= NULL
);
470 bool decode_template_args(string_type
& output
);
471 bool decode_template_param(string_type
& output
,
472 qualifier_list
<Tp
, Allocator
>* qualifiers
= NULL
);
473 bool decode_unqualified_name(string_type
& output
);
474 bool decode_unscoped_name(string_type
& output
);
475 bool decode_non_negative_decimal_integer(string_type
& output
);
476 bool decode_special_name(string_type
& output
);
477 bool decode_real(string_type
& output
, size_t size_of_real
);
480 template<typename Tp
, typename Allocator
>
481 #if !_GLIBCXX_DEMANGLER_CWDEBUG
485 session
<Tp
, Allocator
>::add_substitution(int start_pos
,
486 substitution_nt sub_type
,
487 int number_of_prefixes
= 0)
489 if (!M_inside_substitution
)
491 #if _GLIBCXX_DEMANGLER_CWDEBUG
492 if (M_inside_add_substitution
)
496 push_back(substitution_st(start_pos
,
497 sub_type
, number_of_prefixes
));
498 #if _GLIBCXX_DEMANGLER_CWDEBUG
499 if (!DEBUGCHANNELS::dc::demangler
.is_on())
501 string_type
substitution_name("S");
502 int n
= M_substitutions_pos
.size() - 1;
504 substitution_name
+= (n
<= 10) ? (char)(n
+ '0' - 1)
505 : (char)(n
+ 'A' - 11);
506 substitution_name
+= '_';
508 int saved_pos
= M_pos
;
510 M_inside_add_substitution
= true;
511 _GLIBCXX_DEMANGLER_DEBUG( dc::demangler
.off() );
517 case template_template_param
:
518 decode_template_param(subst
);
520 case nested_name_prefix
:
521 case nested_name_template_prefix
:
522 for (int cnt
= number_of_prefixes
; cnt
> 0; --cnt
)
524 if (current() == 'I')
527 decode_template_args(subst
);
531 if (cnt
< number_of_prefixes
)
533 if (current() == 'S')
534 decode_substitution(subst
);
535 else if (current() == 'T')
536 decode_template_param(subst
);
538 decode_unqualified_name(subst
);
542 case unscoped_template_name
:
543 decode_unscoped_name(subst
);
547 _GLIBCXX_DEMANGLER_DEBUG( dc::demangler
.on() );
548 _GLIBCXX_DEMANGLER_DOUT(dc::demangler
,
549 "Adding substitution " << substitution_name
551 << " (from " << location_ct((char*)__builtin_return_address(0)
552 + builtin_return_address_offset
)
553 << " <- " << location_ct((char*)__builtin_return_address(1)
554 + builtin_return_address_offset
)
555 << " <- " << location_ct((char*)__builtin_return_address(2)
556 + builtin_return_address_offset
)
558 M_inside_add_substitution
= false;
563 // We don't want to depend on locale (or include <cctype> for that matter).
564 // We also don't want to use "safe-ctype.h" because that headerfile is not
565 // available to the users.
566 inline bool isdigit(char c
) { return c
>= '0' && c
<= '9'; }
567 inline bool islower(char c
) { return c
>= 'a' && c
<= 'z'; }
568 inline bool isupper(char c
) { return c
>= 'A' && c
<= 'Z'; }
569 inline char tolower(char c
) { return isupper(c
) ? c
- 'A' + 'a' : c
; }
572 // <non-negative decimal integer> ::= 0
573 // ::= 1|2|3|4|5|6|7|8|9 [<digit>+]
574 // <digit> ::= 0|1|2|3|4|5|6|7|8|9
576 template<typename Tp
, typename Allocator
>
578 session
<Tp
, Allocator
>::
579 decode_non_negative_decimal_integer(string_type
& output
)
587 else if (!isdigit(c
))
595 while (isdigit((c
= next())));
600 // <number> ::= [n] <non-negative decimal integer>
602 template<typename Tp
, typename Allocator
>
604 session
<Tp
, Allocator
>::decode_number(string_type
& output
)
606 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_number");
607 if (current() != 'n')
608 decode_non_negative_decimal_integer(output
);
613 decode_non_negative_decimal_integer(output
);
615 _GLIBCXX_DEMANGLER_RETURN
;
618 // <builtin-type> ::= v # void
622 // ::= a # signed char
623 // ::= h # unsigned char
625 // ::= t # unsigned short
627 // ::= j # unsigned int
629 // ::= m # unsigned long
630 // ::= x # long long, __int64
631 // ::= y # unsigned long long, __int64
633 // ::= o # unsigned __int128
636 // ::= e # long double, __float80
637 // ::= g # __float128
639 // ::= u <source-name> # vendor extended type
641 char const* const builtin_type_c
[26] =
650 "unsigned char", // h
655 "unsigned long", // m
657 "unsigned __int128", // o
662 "unsigned short", // t
667 "unsigned long long", // y
672 template<typename Tp
, typename Allocator
>
674 session
<Tp
, Allocator
>::decode_builtin_type(string_type
& output
)
676 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_builtin_type");
678 if (!islower(current()) || !(bt
= builtin_type_c
[current() - 'a']))
679 _GLIBCXX_DEMANGLER_FAILURE
;
682 _GLIBCXX_DEMANGLER_RETURN
;
685 // <class-enum-type> ::= <name>
687 template<typename Tp
, typename Allocator
>
689 session
<Tp
, Allocator
>::decode_class_enum_type(string_type
& output
)
691 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_class_enum_type");
692 string_type nested_name_qualifiers
;
693 if (!decode_name(output
, nested_name_qualifiers
))
694 _GLIBCXX_DEMANGLER_FAILURE
;
695 output
+= nested_name_qualifiers
;
696 _GLIBCXX_DEMANGLER_RETURN
;
699 // <substitution> ::=
703 // Sa # ::std::allocator
704 // Sb # ::std::basic_string
705 // Ss # ::std::basic_string<char, std::char_traits<char>,
706 // std::allocator<char> >
707 // Si # ::std::basic_istream<char, std::char_traits<char> >
708 // So # ::std::basic_ostream<char, std::char_traits<char> >
709 // Sd # ::std::basic_iostream<char, std::char_traits<char> >
712 // 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
713 // [<seq-id>] # Base 36 number
715 template<typename Tp
, typename Allocator
>
717 session
<Tp
, Allocator
>::decode_substitution(string_type
& output
,
718 qualifier_list
<Tp
, Allocator
>* qualifiers
)
720 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_substitution");
721 unsigned int value
= 0;
729 output
+= "std::allocator";
730 if (!M_inside_template_args
)
732 M_function_name
= "allocator";
733 M_name_is_template
= true;
734 M_name_is_cdtor
= false;
735 M_name_is_conversion_operator
= false;
739 qualifiers
->printing_suppressed();
740 _GLIBCXX_DEMANGLER_RETURN
;
744 output
+= "std::basic_string";
745 if (!M_inside_template_args
)
747 M_function_name
= "basic_string";
748 M_name_is_template
= true;
749 M_name_is_cdtor
= false;
750 M_name_is_conversion_operator
= false;
754 qualifiers
->printing_suppressed();
755 _GLIBCXX_DEMANGLER_RETURN
;
758 output
+= "std::iostream";
759 if (!M_inside_template_args
)
761 M_function_name
= "iostream";
762 M_name_is_template
= true;
763 M_name_is_cdtor
= false;
764 M_name_is_conversion_operator
= false;
768 qualifiers
->printing_suppressed();
769 _GLIBCXX_DEMANGLER_RETURN
;
771 output
+= "std::istream";
772 if (!M_inside_template_args
)
774 M_function_name
= "istream";
775 M_name_is_template
= true;
776 M_name_is_cdtor
= false;
777 M_name_is_conversion_operator
= false;
781 qualifiers
->printing_suppressed();
782 _GLIBCXX_DEMANGLER_RETURN
;
784 output
+= "std::ostream";
785 if (!M_inside_template_args
)
787 M_function_name
= "ostream";
788 M_name_is_template
= true;
789 M_name_is_cdtor
= false;
790 M_name_is_conversion_operator
= false;
794 qualifiers
->printing_suppressed();
795 _GLIBCXX_DEMANGLER_RETURN
;
797 output
+= "std::string";
798 if (!M_inside_template_args
)
800 M_function_name
= "string";
801 M_name_is_template
= true;
802 M_name_is_cdtor
= false;
803 M_name_is_conversion_operator
= false;
807 qualifiers
->printing_suppressed();
808 _GLIBCXX_DEMANGLER_RETURN
;
813 qualifiers
->printing_suppressed();
814 _GLIBCXX_DEMANGLER_RETURN
;
819 value
= value
* 36 + c
- '0';
821 value
= value
* 36 + c
- 'A' + 10;
825 _GLIBCXX_DEMANGLER_FAILURE
;
832 if (value
>= M_substitutions_pos
.size() ||
833 M_inside_type
> 20) // Rather than core dump.
834 _GLIBCXX_DEMANGLER_FAILURE
;
835 ++M_inside_substitution
;
836 int saved_pos
= M_pos
;
837 substitution_st
& substitution(M_substitutions_pos
[value
]);
838 M_pos
= substitution
.M_start_pos
;
839 switch(substitution
.M_type
)
842 decode_type(output
, qualifiers
);
844 case template_template_param
:
845 decode_template_param(output
, qualifiers
);
847 case nested_name_prefix
:
848 case nested_name_template_prefix
:
849 for (int cnt
= substitution
.M_number_of_prefixes
; cnt
> 0; --cnt
)
851 if (current() == 'I')
853 if (M_template_args_need_space
)
855 M_template_args_need_space
= false;
856 if (!decode_template_args(output
))
857 _GLIBCXX_DEMANGLER_FAILURE
;
861 if (cnt
< substitution
.M_number_of_prefixes
)
863 if (current() == 'S')
865 if (!decode_substitution(output
))
866 _GLIBCXX_DEMANGLER_FAILURE
;
868 else if (!decode_unqualified_name(output
))
869 _GLIBCXX_DEMANGLER_FAILURE
;
873 qualifiers
->printing_suppressed();
875 case unscoped_template_name
:
876 decode_unscoped_name(output
);
878 qualifiers
->printing_suppressed();
882 --M_inside_substitution
;
883 _GLIBCXX_DEMANGLER_RETURN
;
886 // <template-param> ::= T_ # first template parameter
887 // ::= T <parameter-2 non-negative number> _
889 template<typename Tp
, typename Allocator
>
891 session
<Tp
, Allocator
>::decode_template_param(string_type
& output
,
892 qualifier_list
<Tp
, Allocator
>* qualifiers
)
894 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_template_parameter");
895 if (current() != 'T')
896 _GLIBCXX_DEMANGLER_FAILURE
;
897 unsigned int value
= 0;
899 if ((c
= next()) != '_')
903 value
= value
* 10 + c
- '0';
908 if (eat_current() != '_')
909 _GLIBCXX_DEMANGLER_FAILURE
;
910 value
+= M_template_arg_pos_offset
;
911 if (value
>= M_template_arg_pos
.size())
912 _GLIBCXX_DEMANGLER_FAILURE
;
913 int saved_pos
= M_pos
;
914 M_pos
= M_template_arg_pos
[value
];
915 if (M_inside_type
> 20) // Rather than core dump.
916 _GLIBCXX_DEMANGLER_FAILURE
;
917 ++M_inside_substitution
;
918 if (current() == 'X')
921 decode_expression(output
);
923 else if (current() == 'L')
924 decode_literal(output
);
926 decode_type(output
, qualifiers
);
927 --M_inside_substitution
;
929 _GLIBCXX_DEMANGLER_RETURN
;
932 template<typename Tp
, typename Allocator
>
934 session
<Tp
, Allocator
>::decode_real(string_type
& output
, size_t size_of_real
)
936 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_real");
938 unsigned long words
[4]; // 32 bit per long, maximum of 128 bits.
939 unsigned long* word
= &words
[0];
944 // The following assumes that leading zeroes are also included in the
945 // mangled name, I am not sure that is conforming to the C++-ABI, but
946 // it is what g++ does.
947 unsigned char nibble
, c
= current();
948 for(size_t word_cnt
= size_of_real
/ 4; word_cnt
> 0; --word_cnt
)
950 for (int nibble_cnt
= 0; nibble_cnt
< 8; ++nibble_cnt
)
952 // Translate character into nibble.
953 if (c
< '0' || c
> 'f')
954 _GLIBCXX_DEMANGLER_FAILURE
;
958 nibble
= c
- 'a' + 10;
960 _GLIBCXX_DEMANGLER_FAILURE
;
961 // Write nibble into word array.
963 *word
= nibble
<< 28;
965 *word
|= (nibble
<< (28 - 4 * nibble_cnt
));
971 if (M_implementation_details
.decode_real(buf
, words
, size_of_real
))
974 _GLIBCXX_DEMANGLER_RETURN
;
980 for(size_t nibble_cnt
= 0; nibble_cnt
< 2 * size_of_real
; ++nibble_cnt
)
982 if (c
< '0' || c
> 'f' || (c
> '9' && c
< 'a'))
983 _GLIBCXX_DEMANGLER_FAILURE
;
989 _GLIBCXX_DEMANGLER_RETURN
;
992 template<typename Tp
, typename Allocator
>
994 session
<Tp
, Allocator
>::decode_literal(string_type
& output
)
996 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_literal");
997 eat_current(); // Eat the 'L'.
998 if (current() == '_')
1001 _GLIBCXX_DEMANGLER_FAILURE
;
1003 if ((M_pos
+= decode_encoding(output
, M_str
+ M_pos
,
1004 M_maxpos
- M_pos
+ 1, M_implementation_details
)) < 0)
1005 _GLIBCXX_DEMANGLER_FAILURE
;
1010 if (current() == 'b')
1017 _GLIBCXX_DEMANGLER_RETURN
;
1020 if ((c
== 'i' || c
== 'j' || c
== 'l' ||
1021 c
== 'm' || c
== 'x' || c
== 'y') &&
1022 M_implementation_details
.get_style_literal())
1024 else if (c
== 'i' &&
1025 !M_implementation_details
.get_style_literal_int())
1030 if (!decode_type(output
))
1031 _GLIBCXX_DEMANGLER_FAILURE
;
1034 if (c
>= 'd' && c
<= 'g')
1036 size_t size_of_real
= (c
== 'd') ? sizeof(double) :
1037 ((c
== 'f') ? sizeof(float) :
1038 (c
== 'e') ? sizeof(long double) : 16);
1039 if (!decode_real(output
, size_of_real
))
1040 _GLIBCXX_DEMANGLER_FAILURE
;
1042 else if (!decode_number(output
))
1043 _GLIBCXX_DEMANGLER_FAILURE
;
1044 if (M_implementation_details
.get_style_literal())
1046 if (c
== 'j' || c
== 'm' || c
== 'y')
1048 if (c
== 'l' || c
== 'm')
1050 if (c
== 'x' || c
== 'y')
1054 _GLIBCXX_DEMANGLER_RETURN
;
1057 // <operator-name> ::=
1105 // st # sizeof (a type)
1106 // sz # sizeof (an expression)
1107 // cv <type> # (cast)
1108 // v <digit> <source-name> # vendor extended operator
1110 // Symbol operator codes exist of two characters, we need to find a
1111 // quick hash so that their names can be looked up in a table.
1114 // Shift the rows so that there is at most one character per column.
1116 // A perfect solution (Oh no, it's THE MATRIX!):
1118 // ....................................... offset + 'a'
1119 // a, a||d|||||||||n||||s|||||||||||||||||||| 0
1120 // c, || |||||||lm o||| |||||||||||||||||||| 0
1121 // d, || a|||e|| l|| ||||||v||||||||||||| 4
1122 // e, || ||| || || |||o|q ||||||||||||| 8
1123 // g, || ||| || || e|| | ||||||||t|||| 15
1124 // i, || ||| || || || | |||||||| |||x 15
1125 // l, |e ||| || st || | |||||||| ||| -2
1126 // m, | |i| lm || | |||||||| ||| -2
1127 // n, a e g t| w |||||||| ||| 1
1128 // o, | ||||o||r ||| 16
1129 // p, | ||lm |p st| 17
1133 // .......................................
1134 // ^ ^__ second character
1135 // |___ first character
1138 // Putting that solution in tables:
1140 char const offset_table_c
[1 + CHAR_MAX
- CHAR_MIN
] =
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,
1144 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1145 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
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,
1149 // Add -CHAR_MIN extra zeroes (128):
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 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1155 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1156 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1157 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1158 // a b c d e f g h i j k
1159 0, -97, 0, -97, -93, -89, 0, -82, 0, -82, 0, 0,
1160 // l m n o p q r s t u v
1161 -99, -99, -96, -81, -80, -91, -88, -85, 0, 0, 0,
1163 // a b c d e f g h i j k
1164 0, 159, 0, 159, 163, 167, 0, 174, 0, 174, 0, 0,
1165 // l m n o p q r s t u v
1166 157, 157, 160, 175, 176, 165, 168, 171, 0, 0, 0,
1180 char const* symbol_name
;
1184 entry_st
const symbol_name_table_c
[39] = {
1185 { "aa", "operator&&", binary
},
1186 { "na", "operator new[]", unary
},
1187 { "le", "operator<=", binary
},
1188 { "ad", "operator&", unary
},
1189 { "da", "operator delete[]", unary
},
1190 { "ne", "operator!=", binary
},
1191 { "mi=", "operator-", binary
},
1192 { "ng", "operator-", unary
},
1193 { "de", "operator*", unary
},
1194 { "ml=", "operator*", binary
},
1195 { "mm", "operator--", unary
},
1196 { "cl", "operator()", unary
},
1197 { "cm", "operator,", binary
},
1198 { "an=", "operator&", binary
},
1199 { "co", "operator~", binary
},
1200 { "dl", "operator delete", unary
},
1201 { "ls=", "operator<<", binary
},
1202 { "lt", "operator<", binary
},
1203 { "as=", "operator", binary
},
1204 { "ge", "operator>=", binary
},
1205 { "nt", "operator!", unary
},
1206 { "rm=", "operator%", binary
},
1207 { "eo=", "operator^", binary
},
1208 { "nw", "operator new", unary
},
1209 { "eq", "operator==", binary
},
1210 { "dv=", "operator/", binary
},
1211 { "qu", "operator?", trinary
},
1212 { "rs=", "operator>>", binary
},
1213 { "pl=", "operator+", binary
},
1214 { "pm", "operator->*", binary
},
1215 { "oo", "operator||", binary
},
1216 { "st", "sizeof", unary
},
1217 { "pp", "operator++", unary
},
1218 { "or=", "operator|", binary
},
1219 { "gt", "operator>", binary
},
1220 { "ps", "operator+", unary
},
1221 { "pt", "operator->", binary
},
1222 { "sz", "sizeof", unary
},
1223 { "ix", "operator[]", unary
}
1226 template<typename Tp
, typename Allocator
>
1228 session
<Tp
, Allocator
>::decode_operator_name(string_type
& output
)
1230 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_operator_name");
1232 char opcode0
= current();
1233 char opcode1
= tolower(next());
1236 if ((hash
= offset_table_c
[opcode0
- CHAR_MIN
]))
1245 int index
= static_cast<int>(static_cast<unsigned char>(hash
));
1246 entry_st entry
= symbol_name_table_c
[index
];
1247 if (entry
.opcode
[0] == opcode0
&& entry
.opcode
[1] == opcode1
1248 && (opcode1
== current() || entry
.opcode
[2] == '='))
1250 output
+= entry
.symbol_name
;
1251 if (opcode1
!= current())
1254 if (hash
== 16 || hash
== 17)
1255 M_template_args_need_space
= true;
1256 _GLIBCXX_DEMANGLER_RETURN
;
1258 else if (opcode0
== 'c' && opcode1
== 'v') // casting operator
1261 output
+= "operator ";
1262 if (current() == 'T')
1264 // This is a templated cast operator.
1265 // It must be of the form "cvT_I...E".
1266 // Let M_template_arg_pos already point
1267 // to the template argument.
1268 M_template_arg_pos_offset
= M_template_arg_pos
.size();
1269 M_template_arg_pos
.push_back(M_pos
+ 3);
1271 if (!decode_type(output
))
1272 _GLIBCXX_DEMANGLER_FAILURE
;
1273 if (!M_inside_template_args
)
1274 M_name_is_conversion_operator
= true;
1275 _GLIBCXX_DEMANGLER_RETURN
;
1279 _GLIBCXX_DEMANGLER_FAILURE
;
1283 // <expression> ::= <unary operator-name> <expression>
1284 // ::= <binary operator-name> <expression> <expression>
1285 // ::= <trinary operator-name> <expression> <expression> <expression>
1287 // ::= <template-param>
1288 // ::= sr <type> <unqualified-name> # dependent name
1289 // ::= sr <type> <unqualified-name> <template-args> # dependent template-id
1290 // ::= <expr-primary>
1292 // <expr-primary> ::= L <type> <value number> E # integer literal
1293 // ::= L <type> <value float> E # floating literal
1294 // ::= L <mangled-name> E # external name
1296 template<typename Tp
, typename Allocator
>
1298 session
<Tp
, Allocator
>::decode_expression(string_type
& output
)
1300 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_expression");
1301 if (current() == 'T')
1303 if (!decode_template_param(output
))
1304 _GLIBCXX_DEMANGLER_FAILURE
;
1305 _GLIBCXX_DEMANGLER_RETURN
;
1307 else if (current() == 'L')
1309 if (!decode_literal(output
))
1310 _GLIBCXX_DEMANGLER_FAILURE
;
1311 if (current() != 'E')
1312 _GLIBCXX_DEMANGLER_FAILURE
;
1314 _GLIBCXX_DEMANGLER_RETURN
;
1316 else if (current() == 's')
1318 char opcode1
= next();
1319 if (opcode1
== 't' || opcode1
== 'z')
1322 if (M_implementation_details
.get_style_compact_expr_ops())
1323 output
+= "sizeof(";
1325 output
+= "sizeof (";
1328 // I cannot think of a mangled name that is valid for both cases
1329 // when just replacing the 't' by a 'z' or vica versa, which
1330 // indicates that there is no ambiguity that dictates the need
1331 // for a seperate "st" case, except to be able catch invalid
1332 // mangled names. However there CAN be ambiguity in the demangled
1333 // name when there are both a type and a symbol of the same name,
1334 // which then leads to different encoding (of course) with
1335 // sizeof (type) or sizeof (expression) respectively, but that
1336 // ambiguity is not per se related to "sizeof" except that that
1337 // is the only place where both a type AND an expression are valid
1338 // in as part of a (template function) type.
1342 // struct B { typedef int t; };
1343 // struct A : public B { static int t[2]; };
1344 // template<int i, int j> struct C { typedef int q; };
1345 // template<int i, typename T>
1346 // void f(typename C<sizeof (typename T::t),
1347 // sizeof (T::t)>::q) { }
1348 // void instantiate() { f<5, A>(0); }
1350 // Leads to _Z1fILi5E1AEvN1CIXstN1T1tEEXszsrS2_1tEE1qE which
1352 // void f<5, A>(C<sizeof (T::t), sizeof (T::t)>::q)
1354 // This is ambiguity is very unlikely to happen and it is kind
1355 // of fuzzy to detect when adding a 'typename' makes sense.
1357 if (M_implementation_details
.get_style_sizeof_typename())
1359 // We can only get here inside a template parameter,
1360 // so this is syntactically correct if the given type is
1361 // a typedef. The only disadvantage is that it is inconsistent
1362 // with all other places where the 'typename' keyword should be
1363 // used and we don't.
1364 // With this, the above example will demangle as
1365 // void f<5, A>(C<sizeof (typename T::t), sizeof (T::t)>::q)
1366 if (current() == 'N' || // <nested-name>
1367 // This should be a safe bet.
1368 (current() == 'S' &&
1369 next_peek() == 't')) // std::something, guess that
1370 // this involves a typedef.
1371 output
+= "typename ";
1373 if (!decode_type(output
))
1374 _GLIBCXX_DEMANGLER_FAILURE
;
1378 if (!decode_expression(output
))
1379 _GLIBCXX_DEMANGLER_FAILURE
;
1382 _GLIBCXX_DEMANGLER_RETURN
;
1384 else if (current() == 'r')
1387 if (!decode_type(output
))
1388 _GLIBCXX_DEMANGLER_FAILURE
;
1390 if (!decode_unqualified_name(output
))
1391 _GLIBCXX_DEMANGLER_FAILURE
;
1392 if (current() != 'I' || decode_template_args(output
))
1393 _GLIBCXX_DEMANGLER_RETURN
;
1398 char opcode0
= current();
1399 char opcode1
= tolower(next());
1402 if ((hash
= offset_table_c
[opcode0
- CHAR_MIN
]))
1411 int index
= static_cast<int>(static_cast<unsigned char>(hash
));
1412 entry_st entry
= symbol_name_table_c
[index
];
1413 if (entry
.opcode
[0] == opcode0
&& entry
.opcode
[1] == opcode1
1414 && (opcode1
== current() || entry
.opcode
[2] == '='))
1416 char const* op
= entry
.symbol_name
+ 8; // Skip "operator".
1417 if (*op
== ' ') // operator new and delete.
1419 if (entry
.type
== unary
)
1421 bool is_eq
= (opcode1
!= current());
1423 if (index
== 34 && M_inside_template_args
) // operator>
1426 if (!decode_expression(output
))
1427 _GLIBCXX_DEMANGLER_FAILURE
;
1429 if (entry
.type
!= unary
)
1431 if (!M_implementation_details
.get_style_compact_expr_ops())
1436 if (!M_implementation_details
.get_style_compact_expr_ops())
1439 if (!decode_expression(output
))
1440 _GLIBCXX_DEMANGLER_FAILURE
;
1442 if (index
== 34 && M_inside_template_args
)
1444 if (entry
.type
== trinary
)
1446 if (M_implementation_details
.get_style_compact_expr_ops())
1450 if (!decode_expression(output
))
1451 _GLIBCXX_DEMANGLER_FAILURE
;
1455 _GLIBCXX_DEMANGLER_RETURN
;
1457 else if (opcode0
== 'c' &&
1458 opcode1
== 'v') // casting operator.
1462 if (!decode_type(output
))
1463 _GLIBCXX_DEMANGLER_FAILURE
;
1465 if (!decode_expression(output
))
1466 _GLIBCXX_DEMANGLER_FAILURE
;
1468 _GLIBCXX_DEMANGLER_RETURN
;
1473 _GLIBCXX_DEMANGLER_FAILURE
;
1477 // <template-args> ::= I <template-arg>+ E
1478 // <template-arg> ::= <type> # type or template
1479 // ::= L <type> <value number> E # integer literal
1480 // ::= L <type> <value float> E # floating literal
1481 // ::= L <mangled-name> E # external name
1482 // ::= X <expression> E # expression
1483 template<typename Tp
, typename Allocator
>
1485 session
<Tp
, Allocator
>::decode_template_args(string_type
& output
)
1487 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_template_args");
1488 if (eat_current() != 'I')
1489 _GLIBCXX_DEMANGLER_FAILURE
;
1490 int prev_size
= M_template_arg_pos
.size();
1491 ++M_inside_template_args
;
1492 if (M_template_args_need_space
)
1495 M_template_args_need_space
= false;
1500 if (M_inside_template_args
== 1 && !M_inside_type
)
1501 M_template_arg_pos
.push_back(M_pos
);
1502 if (current() == 'X')
1505 if (!decode_expression(output
))
1506 _GLIBCXX_DEMANGLER_FAILURE
;
1507 if (current() != 'E')
1508 _GLIBCXX_DEMANGLER_FAILURE
;
1511 else if (current() == 'L')
1513 if (!decode_literal(output
))
1514 _GLIBCXX_DEMANGLER_FAILURE
;
1515 if (current() != 'E')
1516 _GLIBCXX_DEMANGLER_FAILURE
;
1519 else if (!decode_type(output
))
1520 _GLIBCXX_DEMANGLER_FAILURE
;
1521 if (current() == 'E')
1526 if (*(output
.rbegin()) == '>')
1529 --M_inside_template_args
;
1530 if (!M_inside_template_args
&& !M_inside_type
)
1532 M_name_is_template
= true;
1533 M_template_arg_pos_offset
= prev_size
;
1535 _GLIBCXX_DEMANGLER_RETURN
;
1538 // <bare-function-type> ::=
1539 // <signature type>+ # Types are parameter types.
1541 // Note that the possible return type of the <bare-function-type>
1542 // has already been eaten before we call this function. This makes
1543 // our <bare-function-type> slightly different from the one in
1544 // the C++-ABI description.
1546 template<typename Tp
, typename Allocator
>
1548 session
<Tp
, Allocator
>::decode_bare_function_type(string_type
& output
)
1550 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_bare_function_type");
1551 if (M_saw_destructor
)
1553 if (eat_current() != 'v' || (current() != 'E' && current() != 0))
1554 _GLIBCXX_DEMANGLER_FAILURE
;
1556 M_saw_destructor
= false;
1557 _GLIBCXX_DEMANGLER_RETURN
;
1559 if (current() == 'v' && !M_implementation_details
.get_style_void())
1562 if (current() != 'E' && current() != 0)
1563 _GLIBCXX_DEMANGLER_FAILURE
;
1565 M_saw_destructor
= false;
1566 _GLIBCXX_DEMANGLER_RETURN
;
1569 M_template_args_need_space
= false;
1570 if (!decode_type(output
)) // Must have at least one parameter.
1571 _GLIBCXX_DEMANGLER_FAILURE
;
1572 while (current() != 'E' && current() != 0)
1575 if (!decode_type(output
))
1576 _GLIBCXX_DEMANGLER_FAILURE
;
1579 _GLIBCXX_DEMANGLER_RETURN
;
1583 // <builtin-type> # Starts with a lower case character != r.
1584 // <function-type> # Starts with F
1585 // <class-enum-type> # Starts with N, S, C, D, Z, a digit or a lower
1586 // # case character. Since a lower case character
1587 // # would be an operator name, that would be an
1588 // # error. The S is a substitution or St
1589 // # (::std::). A 'C' would be a constructor and
1590 // # thus also an error.
1591 // <template-param> # Starts with T
1592 // <substitution> # Starts with S
1593 // <template-template-param> <template-args> # Starts with T or S,
1594 // # equivalent with the above.
1596 // <array-type> # Starts with A
1597 // <pointer-to-member-type> # Starts with M
1598 // <CV-qualifiers> <type> # Starts with r, V or K
1599 // P <type> # pointer-to # Starts with P
1600 // R <type> # reference-to # Starts with R
1601 // C <type> # complex (C 2000) # Starts with C
1602 // G <type> # imaginary (C 2000)# Starts with G
1603 // U <source-name> <type> # vendor extended type qualifier,
1606 // <template-template-param> ::= <template-param>
1607 // ::= <substitution>
1609 // My own analysis of how to decode qualifiers:
1611 // F is a <function-type>, <T> is a <builtin-type>, <class-enum-type>,
1612 // <template-param> or <template-template-param> <template-args>.
1613 // <Q> represents a series of qualifiers (not G or C).
1614 // <C> is an unqualified type.
1615 // <R> is a qualified type.
1616 // <B> is the bare-function-type without return type.
1617 // <I> is the array index.
1619 // <Q>M<C><Q2>F<R><B>E ==> R (C::*Q)B Q2 "<C>", "F<R><B>E"
1620 // (<R> and <B> recursive),
1621 // "M<C><Q2>F<R><B>E".
1622 // <Q>F<R><B>E ==> R (Q)B "<R>", "<B>" (<B> recursive)
1625 // Note that if <R> has postfix qualifiers (an array or function), then
1626 // those are added AFTER the (member) function type. For example:
1627 // <Q>FPA<R><B>E ==> R (*(Q)B) [], where the PA added the prefix
1628 // "(*" and the postfix ") []".
1630 // <Q>G<T> ==> imaginary T Q "<T>", "G<T>" (<T> recursive).
1631 // <Q>C<T> ==> complex T Q "<T>", "C<T>" (<T> recursive).
1632 // <Q><T> ==> T Q "<T>" (<T> recursive).
1634 // where <Q> is any of:
1636 // <Q>P ==> *Q "P..."
1637 // <Q>R ==> &Q "R..."
1638 // <Q>[K|V|r]+ ==> [ const| volatile| restrict]+Q "KVr..."
1639 // <Q>U<S> ==> SQ "U<S>..."
1640 // <Q>M<C> ==> C::*Q "M<C>..." (<C> recurs.)
1641 // A<I> ==> [I] "A<I>..." (<I> recurs.)
1642 // <Q>A<I> ==> (Q) [I] "A<I>..." (<I> recurs.)
1643 // Note that when <Q> ends on an A<I2> then the brackets are omitted
1644 // and no space is written between the two:
1645 // A<I2>A<I> ==> [I2][I]
1646 // If <Q> ends on [KVr]+, which can happen in combination with
1647 // substitutions only, then special handling is required, see below.
1649 // A <substitution> is handled with an input position switch during which
1650 // new substitutions are turned off. Because recursive handling of types
1651 // (and therefore the order in which substitutions must be generated) must
1652 // be done left to right, but the generation of Q needs processing right to
1653 // left, substitutions per <type> are generated by reading the input left
1654 // to right and marking the starts of all substitutions only - implicitly
1655 // finishing them at the end of the type. Then the output and real
1656 // substitutions are generated.
1658 // The following comment was for the demangling of g++ version 3.0.x. The
1659 // mangling (and I believe even the ABI description) have been fixed now
1660 // (as of g++ version 3.1).
1663 // The ABI specifies for pointer-to-member function types the format
1664 // <Q>M<T>F<R><B>E. In other words, the qualifier <Q2> (see above) is
1665 // implicitely contained in <T> instead of explicitly part of the M format.
1666 // I am convinced that this is a bug in the ABI. Unfortunately, this is
1667 // how we have to demangle things as it has a direct impact on the order
1668 // in which substitutions are stored. This ill-formed design results in
1669 // rather ill-formed demangler code too however :/
1671 // <Q2> is now explicitely part of the M format.
1672 // For some weird reason, g++ (3.2.1) does not add substitutions for
1673 // qualified member function pointers. I think that is another bug.
1678 // where <Q> ends on [K|V|r]+ then that part should be processed as
1679 // if it was behind the A<I> instead of in front of it. This is
1680 // because a constant array of ints is normally always mangled as
1681 // an array of constant ints. KVr qualifiers can end up in front
1682 // of an array when the array is part of a substitution or template
1683 // parameter, but the demangling should still result in the same
1684 // syntax; thus KA2_i (const array of ints) must result in the same
1685 // demangling as A2_Ki (array of const ints). As a result we must
1686 // demangle ...[...[[KVr]+A<I0>][KVr]+A<I1>]...[KVr]+A<In>[KVr]+
1687 // as A<I0>A<I1>...A<In>[KVr]+ where each K, V and r in the series
1688 // collapses to a single character at the right of the string.
1690 // VA9_KrA6_KVi --> A9_A6_KVri --> int volatile const restrict [9][6]
1691 // Note that substitutions are still added as usual (the translation
1692 // to A9_A6_KVri does not really happen).
1694 // This decoding is achieved by delaying the decoding of any sequence
1695 // of [KVrA]'s and processing them together in the order: first the
1696 // short-circuited KVr part and then the arrays.
1697 static int const cvq_K
= 1; // Saw at least one K
1698 static int const cvq_V
= 2; // Saw at least one V
1699 static int const cvq_r
= 4; // Saw at least one r
1700 static int const cvq_A
= 8; // Saw at least one A
1701 static int const cvq_last
= 16; // No remaining qualifiers.
1702 static int const cvq_A_cnt
= 32; // Bit 5 and higher represent the
1703 // number of A's in the series.
1704 // In the function below, iter_array points to the first (right most)
1705 // A in the series, if any.
1706 template<typename Tp
, typename Allocator
>
1708 qualifier_list
<Tp
, Allocator
>::decode_KVrA(
1709 string_type
& prefix
, string_type
& postfix
, int cvq
,
1710 typename
qual_vector::const_reverse_iterator
const& iter_array
) const
1712 _GLIBCXX_DEMANGLER_DOUT_ENTERING3("decode_KVrA");
1716 prefix
+= " volatile";
1718 prefix
+= " restrict";
1722 for (typename
qual_vector::
1723 const_reverse_iterator iter
= iter_array
;
1724 iter
!= M_qualifier_starts
.rend(); ++iter
)
1726 switch((*iter
).first_qualifier())
1734 string_type index
= (*iter
).get_optional_type();
1735 if (--n
== 0 && (cvq
& cvq_last
))
1736 postfix
= " [" + index
+ "]" + postfix
;
1738 postfix
= "[" + index
+ "]" + postfix
;
1742 postfix
= ") [" + index
+ "]" + postfix
;
1747 _GLIBCXX_DEMANGLER_RETURN3
;
1751 _GLIBCXX_DEMANGLER_RETURN3
;
1754 template<typename Tp
, typename Allocator
>
1756 qualifier_list
<Tp
, Allocator
>::decode_qualifiers(
1757 string_type
& prefix
,
1758 string_type
& postfix
,
1759 bool member_function_pointer_qualifiers
= false) const
1761 _GLIBCXX_DEMANGLER_DOUT_ENTERING3("decode_qualifiers");
1763 typename
qual_vector::const_reverse_iterator iter_array
;
1764 for(typename
qual_vector::
1765 const_reverse_iterator iter
= M_qualifier_starts
.rbegin();
1766 iter
!= M_qualifier_starts
.rend(); ++iter
)
1768 if (!member_function_pointer_qualifiers
1769 && !(*iter
).part_of_substitution())
1771 int saved_inside_substitution
= M_demangler
.M_inside_substitution
;
1772 M_demangler
.M_inside_substitution
= 0;
1773 M_demangler
.add_substitution((*iter
).get_start_pos(), type
);
1774 M_demangler
.M_inside_substitution
= saved_inside_substitution
;
1776 char qualifier_char
= (*iter
).first_qualifier();
1777 for(; qualifier_char
; qualifier_char
= (*iter
).next_qualifier())
1779 switch(qualifier_char
)
1784 decode_KVrA(prefix
, postfix
, cvq
, iter_array
);
1792 decode_KVrA(prefix
, postfix
, cvq
, iter_array
);
1817 decode_KVrA(prefix
, postfix
, cvq
, iter_array
);
1821 prefix
+= (*iter
).get_optional_type();
1827 decode_KVrA(prefix
, postfix
, cvq
, iter_array
);
1831 prefix
+= (*iter
).get_optional_type();
1833 case 'G': // Only here so we added a substitution.
1840 decode_KVrA(prefix
, postfix
, cvq
|cvq_last
, iter_array
);
1841 M_printing_suppressed
= false;
1842 _GLIBCXX_DEMANGLER_RETURN3
;
1846 template<typename Tp
, typename Allocator
>
1848 session
<Tp
, Allocator
>::decode_type_with_postfix(
1849 string_type
& prefix
, string_type
& postfix
,
1850 qualifier_list
<Tp
, Allocator
>* qualifiers
)
1852 _GLIBCXX_DEMANGLER_DOUT_ENTERING2("decode_type");
1854 bool recursive_template_param_or_substitution_call
;
1855 if (!(recursive_template_param_or_substitution_call
= qualifiers
))
1857 qualifier_list
<Allocator
>* raw_qualifiers
= M_qualifier_list_alloc
.allocate(1);
1858 qualifiers
= new (raw_qualifiers
) qualifier_list
<Allocator
>(*this);
1860 // First eat all qualifiers.
1861 bool failure
= false;
1862 for(;;) // So we can use 'continue' to eat the next qualifier.
1864 int start_pos
= M_pos
;
1868 qualifiers
->add_qualifier_start(pointer
, start_pos
,
1869 M_inside_substitution
);
1873 qualifiers
->add_qualifier_start(reference
, start_pos
,
1874 M_inside_substitution
);
1888 while(c
== 'K' || c
== 'V' || c
== 'r');
1889 qualifiers
->add_qualifier_start(cv_qualifier
, start_pos
, count
,
1890 M_inside_substitution
);
1896 string_type source_name
;
1897 if (!decode_source_name(source_name
))
1902 qualifiers
->add_qualifier_start(vendor_extension
, start_pos
,
1903 source_name
, M_inside_substitution
);
1908 // <array-type> ::= A <positive dimension number> _ <element type>
1909 // ::= A [<dimension expression>] _ <element type>
1914 if (next() == 'n' || !decode_number(index
))
1917 if (next() != '_' && !decode_expression(index
))
1923 if (eat_current() != '_')
1928 qualifiers
->add_qualifier_start(array
, start_pos
, index
,
1929 M_inside_substitution
);
1934 // <pointer-to-member-type> ::= M <class type> <member type>
1935 // <Q>M<C> or <Q>M<C><Q2>F<R><B>E
1937 string_type class_type
;
1938 if (!decode_type(class_type
)) // Substitution: "<C>".
1944 if (c
== 'F' || c
== 'K' || c
== 'V' || c
== 'r')
1945 // Must be CV-qualifiers and a member function pointer.
1947 // <Q>M<C><Q2>F<R><B>E ==> R (C::*Q)B Q2
1948 // substitutions: "<C>", "F<R><B>E" (<R> and <B>
1949 // recursive), "M<C><Q2>F<R><B>E".
1951 int Q2_start_pos
= M_pos
;
1952 while(c
== 'K' || c
== 'V' || c
== 'r') // Decode <Q2>.
1957 qualifier_list
<Tp
, Allocator
> class_type_qualifiers(*this);
1959 class_type_qualifiers
.
1960 add_qualifier_start(cv_qualifier
, Q2_start_pos
,
1961 count
, M_inside_substitution
);
1962 string_type member_function_qualifiers
;
1963 // It is unclear why g++ doesn't add a substitution for
1964 // "<Q2>F<R><B>E" as it should I think.
1965 string_type member_function_qualifiers_postfix
;
1966 class_type_qualifiers
.
1967 decode_qualifiers(member_function_qualifiers
,
1968 member_function_qualifiers_postfix
, true);
1969 member_function_qualifiers
+=
1970 member_function_qualifiers_postfix
;
1971 // I don't think this substitution is actually ever used.
1972 int function_pos
= M_pos
;
1973 if (eat_current() != 'F')
1979 // Constructors, destructors and conversion operators don't
1980 // have a return type, but seem to never get here.
1981 string_type return_type_postfix
;
1982 if (!decode_type_with_postfix(prefix
, return_type_postfix
))
1983 // substitution: <R> recursive
1989 prefix
+= class_type
;
1991 string_type bare_function_type
;
1992 if (!decode_bare_function_type(bare_function_type
)
1993 || eat_current() != 'E') // Substitution: <B> recursive.
1998 // substitution: "F<R><B>E".
1999 add_substitution(function_pos
, type
);
2000 // substitution: "M<C><Q2>F<R><B>E".
2001 add_substitution(start_pos
, type
);
2002 // substitution: all qualified types if any.
2003 qualifiers
->decode_qualifiers(prefix
, postfix
);
2005 postfix
+= bare_function_type
;
2006 postfix
+= member_function_qualifiers
;
2007 postfix
+= return_type_postfix
;
2008 goto decode_type_exit
;
2010 qualifiers
->add_qualifier_start(pointer_to_member
, start_pos
,
2011 class_type
, M_inside_substitution
);
2021 // <Q>G<T> ==> imaginary T Q
2022 // substitutions: "<T>", "G<T>" (<T> recursive).
2023 // <Q>C<T> ==> complex T Q
2024 // substitutions: "<T>", "C<T>" (<T> recursive).
2025 if (current() == 'C' || current() == 'G')
2027 prefix
+= current() == 'C' ? "complex " : "imaginary ";
2028 qualifiers
->add_qualifier_start(complex_or_imaginary
, M_pos
,
2029 M_inside_substitution
);
2032 int start_pos
= M_pos
;
2037 // <function-type> ::= F [Y] <bare-function-type> E
2039 // Note that g++ never generates the 'Y', but we try to
2040 // demangle it anyway.
2041 bool extern_C
= (next() == 'Y');
2045 // <Q>F<R><B>E ==> R (Q)B
2046 // substitution: "<R>", "<B>" (<B> recursive) and "F<R><B>E".
2049 string_type return_type_postfix
;
2050 if (!decode_type_with_postfix(prefix
, return_type_postfix
))
2051 // Substitution: "<R>".
2056 // Only array and function (pointer) types have a postfix.
2057 // In that case we don't want the space but expect something
2058 // like prefix is "int (*" and postfix is ") [1]".
2059 // We do want the space if this pointer is qualified.
2060 if (return_type_postfix
.size() == 0 ||
2061 (prefix
.size() > 0 && *prefix
.rbegin() != '*'))
2064 string_type bare_function_type
;
2065 if (!decode_bare_function_type(bare_function_type
)
2066 // substitution: "<B>" (<B> recursive).
2067 || eat_current() != 'E')
2072 add_substitution(start_pos
, type
); // Substitution: "F<R><B>E".
2073 qualifiers
->decode_qualifiers(prefix
, postfix
);
2074 // substitution: all qualified types, if any.
2077 postfix
+= " [extern \"C\"] ";
2078 postfix
+= bare_function_type
;
2079 postfix
+= return_type_postfix
;
2083 if (!decode_template_param(prefix
, qualifiers
))
2088 if (current() == 'I')
2090 add_substitution(start_pos
, template_template_param
);
2091 // substitution: "<template-template-param>".
2092 if (!decode_template_args(prefix
))
2098 if (!recursive_template_param_or_substitution_call
2099 && qualifiers
->suppressed())
2101 add_substitution(start_pos
, type
);
2102 // substitution: "<template-param>" or
2103 // "<template-template-param> <template-args>".
2104 qualifiers
->decode_qualifiers(prefix
, postfix
);
2105 // substitution: all qualified types, if any.
2109 if (M_pos
>= M_maxpos
)
2114 if (M_str
[M_pos
+ 1] != 't')
2116 if (!decode_substitution(prefix
, qualifiers
))
2121 if (current() == 'I')
2123 if (!decode_template_args(prefix
))
2128 if (!recursive_template_param_or_substitution_call
2129 && qualifiers
->suppressed())
2130 add_substitution(start_pos
, type
);
2132 // "<template-template-param> <template-args>".
2134 if (!recursive_template_param_or_substitution_call
2135 && qualifiers
->suppressed())
2136 qualifiers
->decode_qualifiers(prefix
, postfix
);
2137 // Substitution: all qualified types, if any.
2140 /* Fall-through for St */
2154 // substitutions: "<T>" (<T> recursive).
2155 if (!decode_class_enum_type(prefix
))
2160 if (!recursive_template_param_or_substitution_call
)
2162 add_substitution(start_pos
, type
);
2163 // substitution: "<class-enum-type>".
2164 qualifiers
->decode_qualifiers(prefix
, postfix
);
2165 // substitution: all qualified types, if any.
2168 qualifiers
->printing_suppressed();
2172 // substitutions: "<T>" (<T> recursive).
2173 if (!decode_builtin_type(prefix
))
2178 // If decode_type was called from decode_template_param then we
2179 // need to suppress calling qualifiers here in order to get a
2180 // substitution added anyway (for the <template-param>).
2181 if (!recursive_template_param_or_substitution_call
)
2182 qualifiers
->decode_qualifiers(prefix
, postfix
);
2184 qualifiers
->printing_suppressed();
2190 if (!recursive_template_param_or_substitution_call
)
2192 qualifiers
->~qualifier_list
<Allocator
>();
2193 M_qualifier_list_alloc
.deallocate(qualifiers
, 1);
2196 _GLIBCXX_DEMANGLER_FAILURE
;
2197 _GLIBCXX_DEMANGLER_RETURN2
;
2200 // <nested-name> ::= N [<CV-qualifiers>] <prefix> <unqualified-name> E
2201 // ::= N [<CV-qualifiers>] <template-prefix> <template-args> E
2203 // <prefix> ::= <prefix> <unqualified-name>
2204 // ::= <template-prefix> <template-args>
2205 // ::= <template-param>
2207 // ::= <substitution>
2209 // <template-prefix> ::= <prefix> <template unqualified-name>
2210 // ::= <template-param>
2211 // ::= <substitution>
2213 template<typename Tp
, typename Allocator
>
2215 session
<Tp
, Allocator
>::decode_nested_name(string_type
& output
,
2216 string_type
& qualifiers
)
2218 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_nested_name");
2220 if (current() != 'N' || M_pos
>= M_maxpos
)
2221 _GLIBCXX_DEMANGLER_FAILURE
;
2223 // <CV-qualifiers> ::= [r] [V] [K] # restrict (C99), volatile, const
2224 char const* qualifiers_start
= &M_str
[M_pos
+ 1];
2225 for (char c
= next(); c
== 'K' || c
== 'V' || c
== 'r'; c
= next());
2226 for (char const* qualifier_ptr
= &M_str
[M_pos
- 1];
2227 qualifier_ptr
>= qualifiers_start
; --qualifier_ptr
)
2228 switch(*qualifier_ptr
)
2231 qualifiers
+= " const";
2234 qualifiers
+= " volatile";
2237 qualifiers
+= " restrict";
2241 int number_of_prefixes
= 0;
2242 int substitution_start
= M_pos
;
2245 ++number_of_prefixes
;
2246 if (current() == 'S')
2248 if (!decode_substitution(output
))
2249 _GLIBCXX_DEMANGLER_FAILURE
;
2251 else if (current() == 'I')
2253 if (!decode_template_args(output
))
2254 _GLIBCXX_DEMANGLER_FAILURE
;
2255 if (current() != 'E')
2257 // substitution: "<template-prefix> <template-args>".
2258 add_substitution(substitution_start
, nested_name_prefix
,
2259 number_of_prefixes
);
2264 if (current() == 'T')
2266 if (!decode_template_param(output
))
2267 _GLIBCXX_DEMANGLER_FAILURE
;
2269 else if (!decode_unqualified_name(output
))
2270 _GLIBCXX_DEMANGLER_FAILURE
;
2271 if (current() != 'E')
2273 // substitution: "<prefix> <unqualified-name>" or
2274 // "<prefix> <template unqualified-name>".
2275 add_substitution(substitution_start
,
2276 (current() == 'I') ? nested_name_template_prefix
2277 : nested_name_prefix
,
2278 number_of_prefixes
);
2281 if (current() == 'E')
2284 _GLIBCXX_DEMANGLER_RETURN
;
2286 if (current() != 'I')
2288 else if (M_template_args_need_space
)
2290 M_template_args_need_space
= false;
2292 _GLIBCXX_DEMANGLER_FAILURE
;
2295 // <local-name> := Z <function encoding> E <entity name> [<discriminator>]
2296 // := Z <function encoding> E s [<discriminator>]
2297 // <discriminator> := _ <non-negative number>
2299 template<typename Tp
, typename Allocator
>
2301 session
<Tp
, Allocator
>::decode_local_name(string_type
& output
)
2303 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_local_name");
2304 if (current() != 'Z' || M_pos
>= M_maxpos
)
2305 _GLIBCXX_DEMANGLER_FAILURE
;
2306 if ((M_pos
+= decode_encoding(output
, M_str
+ M_pos
+ 1,
2307 M_maxpos
- M_pos
, M_implementation_details
) + 1) < 0 ||
2308 eat_current() != 'E')
2309 _GLIBCXX_DEMANGLER_FAILURE
;
2311 if (current() == 's')
2314 output
+= "string literal";
2318 string_type nested_name_qualifiers
;
2319 if (!decode_name(output
, nested_name_qualifiers
))
2320 _GLIBCXX_DEMANGLER_FAILURE
;
2321 output
+= nested_name_qualifiers
;
2323 string_type discriminator
;
2324 if (current() == '_' && next() != 'n' && !decode_number(discriminator
))
2325 _GLIBCXX_DEMANGLER_FAILURE
;
2326 _GLIBCXX_DEMANGLER_RETURN
;
2329 // <source-name> ::= <positive length number> <identifier>
2331 template<typename Tp
, typename Allocator
>
2333 session
<Tp
, Allocator
>::decode_source_name(string_type
& output
)
2335 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_source_name");
2336 int length
= current() - '0';
2337 if (length
< 1 || length
> 9)
2338 _GLIBCXX_DEMANGLER_FAILURE
;
2339 while(isdigit(next()))
2340 length
= 10 * length
+ current() - '0';
2341 char const* ptr
= &M_str
[M_pos
];
2342 if (length
> 11 && !strncmp(ptr
, "_GLOBAL_", 8) && ptr
[9] == 'N'
2343 && ptr
[8] == ptr
[10])
2345 output
+= "(anonymous namespace)";
2346 if ((M_pos
+= length
) > M_maxpos
+ 1)
2347 _GLIBCXX_DEMANGLER_FAILURE
;
2353 _GLIBCXX_DEMANGLER_FAILURE
;
2354 output
+= eat_current();
2356 _GLIBCXX_DEMANGLER_RETURN
;
2359 // <unqualified-name> ::= <operator-name> # Starts with lower case.
2360 // ::= <ctor-dtor-name> # Starts with 'C' or 'D'.
2361 // ::= <source-name> # Starts with a digit.
2363 template<typename Tp
, typename Allocator
>
2365 session
<Tp
, Allocator
>::decode_unqualified_name(string_type
& output
)
2367 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_unqualified_name");
2368 if (M_inside_template_args
)
2370 if (!decode_source_name(output
))
2371 _GLIBCXX_DEMANGLER_FAILURE
;
2373 else if (isdigit(current()))
2375 bool recursive_unqualified_name
= (&M_function_name
== &output
);
2376 // This can be a recursive call when we are decoding
2377 // an <operator-name> that is a cast operator for a some
2378 // <unqualified-name>; for example "operator Foo()".
2379 // In that case this is thus not a ctor or dtor and we
2380 // are not interested in updating M_function_name.
2381 if (!recursive_unqualified_name
)
2382 M_function_name
.clear();
2383 M_name_is_template
= false;
2384 M_name_is_cdtor
= false;
2385 M_name_is_conversion_operator
= false;
2386 if (!decode_source_name(M_function_name
))
2387 _GLIBCXX_DEMANGLER_FAILURE
;
2388 if (!recursive_unqualified_name
)
2389 output
+= M_function_name
;
2391 else if (islower(current()))
2393 M_function_name
.clear();
2394 M_name_is_template
= false;
2395 M_name_is_cdtor
= false;
2396 M_name_is_conversion_operator
= false;
2397 if (!decode_operator_name(M_function_name
))
2398 _GLIBCXX_DEMANGLER_FAILURE
;
2399 output
+= M_function_name
;
2401 else if (current() == 'C' || current() == 'D')
2403 // <ctor-dtor-name> ::=
2404 // C1 # complete object (in-charge) constructor
2405 // C2 # base object (not-in-charge) constructor
2406 // C3 # complete object (in-charge) allocating constructor
2407 // D0 # deleting (in-charge) destructor
2408 // D1 # complete object (in-charge) destructor
2409 // D2 # base object (not-in-charge) destructor
2411 if (current() == 'C')
2414 if (c
< '1' || c
> '3')
2415 _GLIBCXX_DEMANGLER_FAILURE
;
2420 if (c
< '0' || c
> '2')
2421 _GLIBCXX_DEMANGLER_FAILURE
;
2423 M_saw_destructor
= true;
2425 M_name_is_cdtor
= true;
2427 output
+= M_function_name
;
2430 _GLIBCXX_DEMANGLER_FAILURE
;
2431 _GLIBCXX_DEMANGLER_RETURN
;
2434 // <unscoped-name> ::=
2435 // <unqualified-name> # Starts not with an 'S'
2436 // St <unqualified-name> # ::std::
2438 template<typename Tp
, typename Allocator
>
2440 session
<Tp
, Allocator
>::decode_unscoped_name(string_type
& output
)
2442 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_unscoped_name");
2443 if (current() == 'S')
2446 _GLIBCXX_DEMANGLER_FAILURE
;
2450 decode_unqualified_name(output
);
2451 _GLIBCXX_DEMANGLER_RETURN
;
2455 // <nested-name> # Starts with 'N'
2456 // <unscoped-template-name> <template-args> # idem
2457 // <local-name> # Starts with 'Z'
2458 // <unscoped-name> # Starts with 'S', 'C', 'D',
2459 // # a digit or a lower case
2462 // <unscoped-template-name> ::= <unscoped-name>
2463 // ::= <substitution>
2464 template<typename Tp
, typename Allocator
>
2466 session
<Tp
, Allocator
>::decode_name(string_type
& output
,
2467 string_type
& nested_name_qualifiers
)
2469 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_name");
2470 int substitution_start
= M_pos
;
2471 if (current() == 'S' && (M_pos
>= M_maxpos
|| M_str
[M_pos
+ 1] != 't'))
2473 if (!decode_substitution(output
))
2474 _GLIBCXX_DEMANGLER_FAILURE
;
2476 else if (current() == 'N')
2478 decode_nested_name(output
, nested_name_qualifiers
);
2479 _GLIBCXX_DEMANGLER_RETURN
;
2481 else if (current() == 'Z')
2483 decode_local_name(output
);
2484 _GLIBCXX_DEMANGLER_RETURN
;
2486 else if (!decode_unscoped_name(output
))
2487 _GLIBCXX_DEMANGLER_FAILURE
;
2488 if (current() == 'I')
2490 // Must have been an <unscoped-template-name>.
2491 add_substitution(substitution_start
, unscoped_template_name
);
2492 if (!decode_template_args(output
))
2493 _GLIBCXX_DEMANGLER_FAILURE
;
2495 M_template_args_need_space
= false;
2496 _GLIBCXX_DEMANGLER_RETURN
;
2499 // <call-offset> ::= h <nv-offset> _
2500 // ::= v <v-offset> _
2501 // <nv-offset> ::= <offset number>
2502 // non-virtual base override
2504 // <v-offset> ::= <offset number> _ <virtual offset number>
2505 // virtual base override, with vcall offset
2506 template<typename Tp
, typename Allocator
>
2508 session
<Tp
, Allocator
>::decode_call_offset(string_type
&
2509 #if _GLIBCXX_DEMANGLER_CWDEBUG
2514 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_call_offset");
2515 if (current() == 'h')
2519 if (decode_number(dummy
) && current() == '_')
2522 _GLIBCXX_DEMANGLER_RETURN
;
2525 else if (current() == 'v')
2529 if (decode_number(dummy
) && current() == '_')
2532 if (decode_number(dummy
) && current() == '_')
2535 _GLIBCXX_DEMANGLER_RETURN
;
2539 _GLIBCXX_DEMANGLER_FAILURE
;
2543 // <special-name> ::=
2544 // TV <type> # virtual table
2545 // TT <type> # VTT structure (construction
2547 // TI <type> # typeinfo structure
2548 // TS <type> # typeinfo name (null-terminated
2550 // GV <object name> # Guard variable for one-time
2551 // initialization of static objects in
2553 // T <call-offset> <base encoding># base is the nominal target function
2555 // Tc <call-offset> <call-offset> <base encoding> # base is the nominal
2556 // target function of thunk; first
2557 // call-offset is 'this' adjustment;
2558 // second call-offset is result
2561 template<typename Tp
, typename Allocator
>
2563 session
<Tp
, Allocator
>::decode_special_name(string_type
& output
)
2565 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_special_name");
2566 if (current() == 'G')
2569 _GLIBCXX_DEMANGLER_FAILURE
;
2570 output
+= "guard variable for ";
2571 string_type nested_name_qualifiers
;
2573 if (!decode_name(output
, nested_name_qualifiers
))
2574 _GLIBCXX_DEMANGLER_FAILURE
;
2575 output
+= nested_name_qualifiers
;
2576 _GLIBCXX_DEMANGLER_RETURN
;
2578 else if (current() != 'T')
2579 _GLIBCXX_DEMANGLER_FAILURE
;
2583 output
+= "vtable for ";
2585 decode_type(output
);
2586 _GLIBCXX_DEMANGLER_RETURN
;
2588 output
+= "VTT for ";
2590 decode_type(output
);
2591 _GLIBCXX_DEMANGLER_RETURN
;
2593 output
+= "typeinfo for ";
2595 decode_type(output
);
2596 _GLIBCXX_DEMANGLER_RETURN
;
2598 output
+= "typeinfo name for ";
2600 decode_type(output
);
2601 _GLIBCXX_DEMANGLER_RETURN
;
2603 output
+= "covariant return thunk to ";
2604 if (!decode_call_offset(output
)
2605 || !decode_call_offset(output
)
2606 || (M_pos
+= decode_encoding(output
, M_str
+ M_pos
,
2607 M_maxpos
- M_pos
+ 1, M_implementation_details
)) < 0)
2608 _GLIBCXX_DEMANGLER_FAILURE
;
2609 _GLIBCXX_DEMANGLER_RETURN
;
2610 case 'C': // GNU extension?
2613 output
+= "construction vtable for ";
2615 if (!decode_type(first
))
2616 _GLIBCXX_DEMANGLER_FAILURE
;
2617 while(isdigit(current()))
2619 if (eat_current() != '_')
2620 _GLIBCXX_DEMANGLER_FAILURE
;
2621 if (!decode_type(output
))
2622 _GLIBCXX_DEMANGLER_FAILURE
;
2625 _GLIBCXX_DEMANGLER_RETURN
;
2628 if (current() == 'v')
2629 output
+= "virtual thunk to ";
2631 output
+= "non-virtual thunk to ";
2632 if (!decode_call_offset(output
)
2633 || (M_pos
+= decode_encoding(output
, M_str
+ M_pos
,
2634 M_maxpos
- M_pos
+ 1, M_implementation_details
)) < 0)
2635 _GLIBCXX_DEMANGLER_FAILURE
;
2636 _GLIBCXX_DEMANGLER_RETURN
;
2641 // <function name> <bare-function-type> # Starts with 'C', 'D', 'N',
2642 // 'S', a digit or a lower case
2644 // <data name> # Idem.
2645 // <special-name> # Starts with 'T' or 'G'.
2646 template<typename Tp
, typename Allocator
>
2648 session
<Tp
, Allocator
>::decode_encoding(string_type
& output
,
2649 char const* in
, int len
, implementation_details
const& id
)
2651 #if _GLIBCXX_DEMANGLER_CWDEBUG
2652 _GLIBCXX_DEMANGLER_DOUT(dc::demangler
,
2653 "Output thus far: \"" << output
<< '"');
2654 string_type
input(in
, len
> 0x40000000 ? strlen(in
) : len
);
2655 _GLIBCXX_DEMANGLER_DOUT(
2656 dc::demangler
, "Entering decode_encoding(\"" << input
<< "\")");
2660 session
<Tp
, Allocator
> demangler_session(in
, len
, id
);
2661 string_type nested_name_qualifiers
;
2663 demangler_session
.store(saved_pos
);
2664 if (demangler_session
.decode_special_name(output
))
2665 return demangler_session
.M_pos
;
2666 demangler_session
.restore(saved_pos
);
2668 if (!demangler_session
.decode_name(name
, nested_name_qualifiers
))
2670 if (demangler_session
.current() == 0
2671 || demangler_session
.current() == 'E')
2674 output
+= nested_name_qualifiers
;
2675 return demangler_session
.M_pos
;
2677 // Must have been a <function name>.
2678 string_type return_type_postfix
;
2679 if (demangler_session
.M_name_is_template
2680 && !(demangler_session
.M_name_is_cdtor
2681 || demangler_session
.M_name_is_conversion_operator
))
2683 // Return type of function
2684 if (!demangler_session
.decode_type_with_postfix(output
,
2685 return_type_postfix
))
2690 if (!demangler_session
.decode_bare_function_type(output
))
2692 output
+= nested_name_qualifiers
;
2693 output
+= return_type_postfix
;
2694 return demangler_session
.M_pos
;
2697 } // namespace demangler
2700 template<typename Tp
, typename Allocator
>
2703 typedef typename
Allocator::template rebind
<char>::other char_Allocator
;
2704 typedef std::basic_string
<char, std::char_traits
<char>, char_Allocator
>
2706 static string_type
symbol(char const* in
,
2707 demangler::implementation_details
const& id
);
2708 static string_type
type(char const* in
,
2709 demangler::implementation_details
const& id
);
2712 // demangle::symbol()
2714 // Demangle `input' which should be a mangled function name as for
2715 // instance returned by nm(1).
2716 template<typename Tp
, typename Allocator
>
2717 typename demangle
<Tp
, Allocator
>::string_type
2718 demangle
<Tp
, Allocator
>::symbol(char const* input
,
2719 demangler::implementation_details
const& id
)
2721 // <mangled-name> ::= _Z <encoding>
2722 // <mangled-name> ::= _GLOBAL_ _<type>_ <disambiguation part>
2723 // <type> can be I or D (GNU extension)
2724 typedef demangler::session
<Tp
, Allocator
> demangler_type
;
2726 bool failure
= (input
[0] != '_');
2730 if (input
[1] == 'G')
2732 if (!strncmp(input
, "_GLOBAL__", 9)
2733 && (input
[9] == 'D' || input
[9] == 'I')
2734 && input
[10] == '_')
2736 if (input
[9] == 'D')
2737 result
.assign("global destructors keyed to ", 28);
2739 result
.assign("global constructors keyed to ", 29);
2740 // Output the disambiguation part as-is.
2741 result
+= input
+ 11;
2746 else if (input
[1] == 'Z')
2749 demangler_type::decode_encoding(result
, input
+ 2, INT_MAX
, id
);
2750 if (cnt
< 0 || input
[cnt
+ 2] != 0)
2757 // Failure to demangle, return the mangled name.
2759 result
.assign(input
, strlen(input
));
2765 // Demangle `input' which must be a zero terminated mangled type
2766 // name as for instance returned by std::type_info::name().
2767 template<typename Tp
, typename Allocator
>
2768 typename demangle
<Tp
, Allocator
>::string_type
2769 demangle
<Tp
, Allocator
>::type(char const* input
,
2770 demangler::implementation_details
const& id
)
2772 std::basic_string
<char, std::char_traits
<char>, Allocator
> result
;
2777 demangler::session
<Tp
, Allocator
> demangler_session(input
, INT_MAX
, id
);
2778 if (!demangler_session
.decode_type(result
)
2779 || demangler_session
.remaining_input_characters())
2781 // Failure to demangle, return the mangled name.
2787 } // namespace __gnu_cxx
2789 #endif // __DEMANGLE_H