This commit was manufactured by cvs2svn to create branch
[official-gcc.git] / libstdc++-v3 / include / ext / demangle.h
blob5de4f04a22461e88fcaa15f9009f9fa9182b6cc9
1 // C++ IA64 / g++ v3 demangler -*- C++ -*-
3 // Copyright (C) 2003, 2004 Free Software Foundation, Inc.
4 // Written by Carlo Wood <carlo@alinoe.com>
5 //
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)
10 // any later version.
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,
20 // USA.
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
35 #ifndef _DEMANGLER_H
36 #define _DEMANGLER_H 1
38 #include <vector>
39 #include <string>
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)
54 #else
55 #define _GLIBCXX_DEMANGLER_CWDEBUG 1
56 #endif
58 namespace __gnu_cxx
60 namespace demangler
62 enum substitution_nt
64 type,
65 template_template_param,
66 nested_name_prefix,
67 nested_name_template_prefix,
68 unscoped_template_name
71 struct substitution_st
73 int M_start_pos;
74 substitution_nt M_type;
75 int M_number_of_prefixes;
77 substitution_st(int start_pos,
78 substitution_nt type,
79 int number_of_prefixes)
80 : M_start_pos(start_pos), M_type(type),
81 M_number_of_prefixes(number_of_prefixes)
82 { }
85 enum simple_qualifier_nt
87 complex_or_imaginary = 'G',
88 pointer = 'P',
89 reference = 'R'
92 enum cv_qualifier_nt
94 cv_qualifier = 'K'
97 enum param_qualifier_nt
99 vendor_extension = 'U',
100 array = 'A',
101 pointer_to_member = 'M'
104 template<typename Tp, typename Allocator = __gnu_cxx::new_allocator<Tp> >
105 class qualifier;
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> >
111 class session;
113 template<typename Tp, typename Allocator>
114 class qualifier
116 typedef typename Allocator::template rebind<char>::other
117 char_Allocator;
118 typedef std::basic_string<char, std::char_traits<char>, char_Allocator>
119 string_type;
121 private:
122 char M_qualifier1;
123 char M_qualifier2;
124 char M_qualifier3;
125 mutable unsigned char M_cnt;
126 string_type M_optional_type;
127 int M_start_pos;
128 bool M_part_of_substitution;
130 public:
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,
140 cv_qualifier_nt,
141 char const* start,
142 int count,
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; }
165 char
166 first_qualifier(void) const
167 { M_cnt = 1; return M_qualifier1; }
169 char
170 next_qualifier(void) const
172 return (++M_cnt == 2) ? M_qualifier2
173 : ((M_cnt == 3) ? M_qualifier3 : 0);
176 string_type const&
177 get_optional_type(void) const
178 { return M_optional_type; }
180 bool
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;
203 return os;
205 #endif
208 template<typename Tp, typename Allocator>
209 class qualifier_list
211 typedef typename Allocator::template rebind<char>::other
212 char_Allocator;
213 typedef std::basic_string<char, std::char_traits<char>, char_Allocator>
214 string_type;
216 private:
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;
228 public:
229 qualifier_list(session<Tp, Allocator>& demangler_obj)
230 : M_printing_suppressed(false), M_demangler(demangler_obj)
233 void
234 add_qualifier_start(simple_qualifier_nt simple_qualifier,
235 int start_pos,
236 int inside_substitution)
237 { M_qualifier_starts.
238 push_back(qualifier<Tp, Allocator>(start_pos,
239 simple_qualifier, inside_substitution)); }
241 void
242 add_qualifier_start(cv_qualifier_nt cv_qualifier,
243 int start_pos,
244 int count,
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)); }
251 void
252 add_qualifier_start(param_qualifier_nt param_qualifier,
253 int start_pos,
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)); }
260 void
261 decode_qualifiers(string_type& prefix,
262 string_type& postfix,
263 bool member_function_pointer_qualifiers) const;
265 bool
266 suppressed(void) const
267 { return M_printing_suppressed; }
269 void
270 printing_suppressed(void)
271 { M_printing_suppressed = true; }
273 size_t
274 size(void) const
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())
284 os << "{ " << *iter;
285 while (++iter != list.M_qualifier_starts.end())
286 os << ", " << *iter;
287 os << " }";
289 else
290 os << "{ }";
291 return os;
293 #endif
296 struct implementation_details
298 private:
299 unsigned int M_style;
301 public:
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)
330 public:
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
347 { return false; }
350 template<typename Tp, typename Allocator>
351 class session
353 public:
354 friend class qualifier_list<Tp, Allocator>;
355 typedef typename Allocator::template rebind<char>::other
356 char_Allocator;
357 typedef std::basic_string<char, std::char_traits<char>, char_Allocator>
358 string_type;
360 private:
361 char const* M_str;
362 int M_pos;
363 int M_maxpos;
364 bool M_result;
365 int M_inside_template_args;
366 int M_inside_type;
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
375 int_Allocator;
376 typedef typename Allocator::template rebind<substitution_st>::other
377 subst_Allocator;
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;
387 #endif
389 public:
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)
401 #endif
404 static int
405 decode_encoding(string_type& output, char const* input, int len,
406 implementation_details const& id = implementation_details());
408 bool
409 decode_type(string_type& output,
410 qualifier_list<Tp, Allocator>* qualifiers = NULL)
412 string_type postfix;
413 bool res = decode_type_with_postfix(output, postfix, qualifiers);
414 output += postfix;
415 return res;
418 bool
419 remaining_input_characters(void) const
420 { return current() != 0; }
422 private:
423 char
424 current(void) const
425 { return (M_pos > M_maxpos) ? 0 : M_str[M_pos]; }
427 char
428 next_peek(void) const
429 { return (M_pos >= M_maxpos) ? 0 : M_str[M_pos + 1]; }
431 char
432 next(void)
433 { return (M_pos >= M_maxpos) ? 0 : M_str[++M_pos]; }
435 char
436 eat_current(void)
437 { return (M_pos > M_maxpos) ? 0 : M_str[M_pos++]; }
439 void
440 store(int& saved_pos)
441 { saved_pos = M_pos; }
443 void
444 restore(int saved_pos)
445 { M_pos = saved_pos; M_result = true; }
447 void
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
482 inline
483 #endif
484 void
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)
493 return;
494 #endif
495 M_substitutions_pos.
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())
500 return;
501 string_type substitution_name("S");
502 int n = M_substitutions_pos.size() - 1;
503 if (n > 0)
504 substitution_name += (n <= 10) ? (char)(n + '0' - 1)
505 : (char)(n + 'A' - 11);
506 substitution_name += '_';
507 string_type subst;
508 int saved_pos = M_pos;
509 M_pos = start_pos;
510 M_inside_add_substitution = true;
511 _GLIBCXX_DEMANGLER_DEBUG( dc::demangler.off() );
512 switch(sub_type)
514 case type:
515 decode_type(subst);
516 break;
517 case template_template_param:
518 decode_template_param(subst);
519 break;
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')
526 subst += ' ';
527 decode_template_args(subst);
529 else
531 if (cnt < number_of_prefixes)
532 subst += "::";
533 if (current() == 'S')
534 decode_substitution(subst);
535 else if (current() == 'T')
536 decode_template_param(subst);
537 else
538 decode_unqualified_name(subst);
541 break;
542 case unscoped_template_name:
543 decode_unscoped_name(subst);
544 break;
546 M_pos = saved_pos;
547 _GLIBCXX_DEMANGLER_DEBUG( dc::demangler.on() );
548 _GLIBCXX_DEMANGLER_DOUT(dc::demangler,
549 "Adding substitution " << substitution_name
550 << " : " << subst
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)
557 << ").");
558 M_inside_add_substitution = false;
559 #endif
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>
577 bool
578 session<Tp, Allocator>::
579 decode_non_negative_decimal_integer(string_type& output)
581 char c = current();
582 if (c == '0')
584 output += '0';
585 eat_current();
587 else if (!isdigit(c))
588 M_result = false;
589 else
593 output += c;
595 while (isdigit((c = next())));
597 return M_result;
600 // <number> ::= [n] <non-negative decimal integer>
602 template<typename Tp, typename Allocator>
603 bool
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);
609 else
611 output += '-';
612 eat_current();
613 decode_non_negative_decimal_integer(output);
615 _GLIBCXX_DEMANGLER_RETURN;
618 // <builtin-type> ::= v # void
619 // ::= w # wchar_t
620 // ::= b # bool
621 // ::= c # char
622 // ::= a # signed char
623 // ::= h # unsigned char
624 // ::= s # short
625 // ::= t # unsigned short
626 // ::= i # int
627 // ::= j # unsigned int
628 // ::= l # long
629 // ::= m # unsigned long
630 // ::= x # long long, __int64
631 // ::= y # unsigned long long, __int64
632 // ::= n # __int128
633 // ::= o # unsigned __int128
634 // ::= f # float
635 // ::= d # double
636 // ::= e # long double, __float80
637 // ::= g # __float128
638 // ::= z # ellipsis
639 // ::= u <source-name> # vendor extended type
641 char const* const builtin_type_c[26] =
643 "signed char", // a
644 "bool", // b
645 "char", // c
646 "double", // d
647 "long double", // e
648 "float", // f
649 "__float128", // g
650 "unsigned char", // h
651 "int", // i
652 "unsigned int", // j
653 NULL, // k
654 "long", // l
655 "unsigned long", // m
656 "__int128", // n
657 "unsigned __int128", // o
658 NULL, // p
659 NULL, // q
660 NULL, // r
661 "short", // s
662 "unsigned short", // t
663 NULL, // u
664 "void", // v
665 "wchar_t", // w
666 "long long", // x
667 "unsigned long long", // y
668 "..." // z
672 template<typename Tp, typename Allocator>
673 bool
674 session<Tp, Allocator>::decode_builtin_type(string_type& output)
676 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_builtin_type");
677 char const* bt;
678 if (!islower(current()) || !(bt = builtin_type_c[current() - 'a']))
679 _GLIBCXX_DEMANGLER_FAILURE;
680 output += bt;
681 eat_current();
682 _GLIBCXX_DEMANGLER_RETURN;
685 // <class-enum-type> ::= <name>
687 template<typename Tp, typename Allocator>
688 bool
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> ::=
700 // S <seq-id> _
701 // S_
702 // St # ::std::
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> >
711 // <seq-id> ::=
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>
716 bool
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;
722 char c = next();
723 if (c != '_')
725 switch(c)
727 case 'a':
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;
737 eat_current();
738 if (qualifiers)
739 qualifiers->printing_suppressed();
740 _GLIBCXX_DEMANGLER_RETURN;
742 case 'b':
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;
752 eat_current();
753 if (qualifiers)
754 qualifiers->printing_suppressed();
755 _GLIBCXX_DEMANGLER_RETURN;
757 case 'd':
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;
766 eat_current();
767 if (qualifiers)
768 qualifiers->printing_suppressed();
769 _GLIBCXX_DEMANGLER_RETURN;
770 case 'i':
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;
779 eat_current();
780 if (qualifiers)
781 qualifiers->printing_suppressed();
782 _GLIBCXX_DEMANGLER_RETURN;
783 case 'o':
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;
792 eat_current();
793 if (qualifiers)
794 qualifiers->printing_suppressed();
795 _GLIBCXX_DEMANGLER_RETURN;
796 case 's':
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;
805 eat_current();
806 if (qualifiers)
807 qualifiers->printing_suppressed();
808 _GLIBCXX_DEMANGLER_RETURN;
809 case 't':
810 output += "std";
811 eat_current();
812 if (qualifiers)
813 qualifiers->printing_suppressed();
814 _GLIBCXX_DEMANGLER_RETURN;
815 default:
816 for(;; c = next())
818 if (isdigit(c))
819 value = value * 36 + c - '0';
820 else if (isupper(c))
821 value = value * 36 + c - 'A' + 10;
822 else if (c == '_')
823 break;
824 else
825 _GLIBCXX_DEMANGLER_FAILURE;
827 ++value;
828 break;
831 eat_current();
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)
841 case type:
842 decode_type(output, qualifiers);
843 break;
844 case template_template_param:
845 decode_template_param(output, qualifiers);
846 break;
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)
854 output += ' ';
855 M_template_args_need_space = false;
856 if (!decode_template_args(output))
857 _GLIBCXX_DEMANGLER_FAILURE;
859 else
861 if (cnt < substitution.M_number_of_prefixes)
862 output += "::";
863 if (current() == 'S')
865 if (!decode_substitution(output))
866 _GLIBCXX_DEMANGLER_FAILURE;
868 else if (!decode_unqualified_name(output))
869 _GLIBCXX_DEMANGLER_FAILURE;
872 if (qualifiers)
873 qualifiers->printing_suppressed();
874 break;
875 case unscoped_template_name:
876 decode_unscoped_name(output);
877 if (qualifiers)
878 qualifiers->printing_suppressed();
879 break;
881 M_pos = saved_pos;
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>
890 bool
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;
898 char c;
899 if ((c = next()) != '_')
901 while(isdigit(c))
903 value = value * 10 + c - '0';
904 c = next();
906 ++value;
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')
920 eat_current();
921 decode_expression(output);
923 else if (current() == 'L')
924 decode_literal(output);
925 else
926 decode_type(output, qualifiers);
927 --M_inside_substitution;
928 M_pos = saved_pos;
929 _GLIBCXX_DEMANGLER_RETURN;
932 template<typename Tp, typename Allocator>
933 bool
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];
941 int saved_pos;
942 store(saved_pos);
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;
955 if (c <= '9')
956 nibble = c - '0';
957 else if (c >= 'a')
958 nibble = c - 'a' + 10;
959 else
960 _GLIBCXX_DEMANGLER_FAILURE;
961 // Write nibble into word array.
962 if (nibble_cnt == 0)
963 *word = nibble << 28;
964 else
965 *word |= (nibble << (28 - 4 * nibble_cnt));
966 c = next();
968 ++word;
970 char buf[24];
971 if (M_implementation_details.decode_real(buf, words, size_of_real))
973 output += buf;
974 _GLIBCXX_DEMANGLER_RETURN;
976 restore(saved_pos);
978 output += '[';
979 c = current();
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;
984 output += c;
985 c = next();
987 output += ']';
989 _GLIBCXX_DEMANGLER_RETURN;
992 template<typename Tp, typename Allocator>
993 bool
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() == '_')
1000 if (next() != 'Z')
1001 _GLIBCXX_DEMANGLER_FAILURE;
1002 eat_current();
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;
1007 else
1009 // Special cases
1010 if (current() == 'b')
1012 if (next() == '0')
1013 output += "false";
1014 else
1015 output += "true";
1016 eat_current();
1017 _GLIBCXX_DEMANGLER_RETURN;
1019 char c = current();
1020 if ((c == 'i' || c == 'j' || c == 'l' ||
1021 c == 'm' || c == 'x' || c == 'y') &&
1022 M_implementation_details.get_style_literal())
1023 eat_current();
1024 else if (c == 'i' &&
1025 !M_implementation_details.get_style_literal_int())
1026 eat_current();
1027 else
1029 output += '(';
1030 if (!decode_type(output))
1031 _GLIBCXX_DEMANGLER_FAILURE;
1032 output += ')';
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')
1047 output += 'u';
1048 if (c == 'l' || c == 'm')
1049 output += 'l';
1050 if (c == 'x' || c == 'y')
1051 output += "ll";
1054 _GLIBCXX_DEMANGLER_RETURN;
1057 // <operator-name> ::=
1058 // nw # new
1059 // na # new[]
1060 // dl # delete
1061 // da # delete[]
1062 // ps # + (unary)
1063 // ng # - (unary)
1064 // ad # & (unary)
1065 // de # * (unary)
1066 // co # ~
1067 // pl # +
1068 // mi # -
1069 // ml # *
1070 // dv # /
1071 // rm # %
1072 // an # &
1073 // or # |
1074 // eo # ^
1075 // aS # =
1076 // pL # +=
1077 // mI # -=
1078 // mL # *=
1079 // dV # /=
1080 // rM # %=
1081 // aN # &=
1082 // oR # |=
1083 // eO # ^=
1084 // ls # <<
1085 // rs # >>
1086 // lS # <<=
1087 // rS # >>=
1088 // eq # ==
1089 // ne # !=
1090 // lt # <
1091 // gt # >
1092 // le # <=
1093 // ge # >=
1094 // nt # !
1095 // aa # &&
1096 // oo # ||
1097 // pp # ++
1098 // mm # --
1099 // cm # ,
1100 // pm # ->*
1101 // pt # ->
1102 // cl # ()
1103 // ix # []
1104 // qu # ?
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.
1113 // The puzzle :)
1114 // Shift the rows so that there is at most one character per column.
1116 // A perfect solution (Oh no, it's THE MATRIX!):
1117 // horizontal
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
1130 // q, | u| | | 6
1131 // r, m s | | 9
1132 // s, t z 12
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,
1148 #if (CHAR_MIN < 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,
1162 #else
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,
1167 #endif
1168 // ... more zeros
1171 enum xary_nt {
1172 unary,
1173 binary,
1174 trinary
1177 struct entry_st
1179 char const* opcode;
1180 char const* symbol_name;
1181 xary_nt type;
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>
1227 bool
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());
1235 register char hash;
1236 if ((hash = offset_table_c[opcode0 - CHAR_MIN]))
1238 hash += opcode1;
1239 if (
1240 #if (CHAR_MIN < 0)
1241 hash >= 0 &&
1242 #endif
1243 hash < 39)
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())
1252 output += '=';
1253 eat_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
1260 eat_current();
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>
1286 // ::= st <type>
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>
1297 bool
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;
1313 eat_current();
1314 _GLIBCXX_DEMANGLER_RETURN;
1316 else if (current() == 's')
1318 char opcode1 = next();
1319 if (opcode1 == 't' || opcode1 == 'z')
1321 eat_current();
1322 if (M_implementation_details.get_style_compact_expr_ops())
1323 output += "sizeof(";
1324 else
1325 output += "sizeof (";
1326 if (opcode1 == 't')
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.
1340 // Example:
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
1351 // demangles as
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;
1376 else
1378 if (!decode_expression(output))
1379 _GLIBCXX_DEMANGLER_FAILURE;
1381 output += ')';
1382 _GLIBCXX_DEMANGLER_RETURN;
1384 else if (current() == 'r')
1386 eat_current();
1387 if (!decode_type(output))
1388 _GLIBCXX_DEMANGLER_FAILURE;
1389 output += "::";
1390 if (!decode_unqualified_name(output))
1391 _GLIBCXX_DEMANGLER_FAILURE;
1392 if (current() != 'I' || decode_template_args(output))
1393 _GLIBCXX_DEMANGLER_RETURN;
1396 else
1398 char opcode0 = current();
1399 char opcode1 = tolower(next());
1401 register char hash;
1402 if ((hash = offset_table_c[opcode0 - CHAR_MIN]))
1404 hash += opcode1;
1405 if (
1406 #if (CHAR_MIN < 0)
1407 hash >= 0 &&
1408 #endif
1409 hash < 39)
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.
1418 ++op;
1419 if (entry.type == unary)
1420 output += op;
1421 bool is_eq = (opcode1 != current());
1422 eat_current();
1423 if (index == 34 && M_inside_template_args) // operator>
1424 output += '(';
1425 output += '(';
1426 if (!decode_expression(output))
1427 _GLIBCXX_DEMANGLER_FAILURE;
1428 output += ')';
1429 if (entry.type != unary)
1431 if (!M_implementation_details.get_style_compact_expr_ops())
1432 output += ' ';
1433 output += op;
1434 if (is_eq)
1435 output += '=';
1436 if (!M_implementation_details.get_style_compact_expr_ops())
1437 output += ' ';
1438 output += '(';
1439 if (!decode_expression(output))
1440 _GLIBCXX_DEMANGLER_FAILURE;
1441 output += ')';
1442 if (index == 34 && M_inside_template_args)
1443 output += ')';
1444 if (entry.type == trinary)
1446 if (M_implementation_details.get_style_compact_expr_ops())
1447 output += ":(";
1448 else
1449 output += " : (";
1450 if (!decode_expression(output))
1451 _GLIBCXX_DEMANGLER_FAILURE;
1452 output += ')';
1455 _GLIBCXX_DEMANGLER_RETURN;
1457 else if (opcode0 == 'c' &&
1458 opcode1 == 'v') // casting operator.
1460 eat_current();
1461 output += '(';
1462 if (!decode_type(output))
1463 _GLIBCXX_DEMANGLER_FAILURE;
1464 output += ")(";
1465 if (!decode_expression(output))
1466 _GLIBCXX_DEMANGLER_FAILURE;
1467 output += ')';
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>
1484 bool
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)
1494 output += ' ';
1495 M_template_args_need_space = false;
1497 output += '<';
1498 for(;;)
1500 if (M_inside_template_args == 1 && !M_inside_type)
1501 M_template_arg_pos.push_back(M_pos);
1502 if (current() == 'X')
1504 eat_current();
1505 if (!decode_expression(output))
1506 _GLIBCXX_DEMANGLER_FAILURE;
1507 if (current() != 'E')
1508 _GLIBCXX_DEMANGLER_FAILURE;
1509 eat_current();
1511 else if (current() == 'L')
1513 if (!decode_literal(output))
1514 _GLIBCXX_DEMANGLER_FAILURE;
1515 if (current() != 'E')
1516 _GLIBCXX_DEMANGLER_FAILURE;
1517 eat_current();
1519 else if (!decode_type(output))
1520 _GLIBCXX_DEMANGLER_FAILURE;
1521 if (current() == 'E')
1522 break;
1523 output += ", ";
1525 eat_current();
1526 if (*(output.rbegin()) == '>')
1527 output += ' ';
1528 output += '>';
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>
1547 bool
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;
1555 output += "()";
1556 M_saw_destructor = false;
1557 _GLIBCXX_DEMANGLER_RETURN;
1559 if (current() == 'v' && !M_implementation_details.get_style_void())
1561 eat_current();
1562 if (current() != 'E' && current() != 0)
1563 _GLIBCXX_DEMANGLER_FAILURE;
1564 output += "()";
1565 M_saw_destructor = false;
1566 _GLIBCXX_DEMANGLER_RETURN;
1568 output += '(';
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)
1574 output += ", ";
1575 if (!decode_type(output))
1576 _GLIBCXX_DEMANGLER_FAILURE;
1578 output += ')';
1579 _GLIBCXX_DEMANGLER_RETURN;
1582 // <type> ::=
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,
1604 // # starts with U
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.
1618 // Substitutions:
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)
1623 // and "F<R><B>E".
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).
1662 // g++ 3.0.x only:
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.
1676 // In the case of
1677 // <Q>A<I>
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.
1689 // For example:
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>
1707 void
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");
1713 if ((cvq & cvq_K))
1714 prefix += " const";
1715 if ((cvq & cvq_V))
1716 prefix += " volatile";
1717 if ((cvq & cvq_r))
1718 prefix += " restrict";
1719 if ((cvq & cvq_A))
1721 int n = cvq >> 5;
1722 for (typename qual_vector::
1723 const_reverse_iterator iter = iter_array;
1724 iter != M_qualifier_starts.rend(); ++iter)
1726 switch((*iter).first_qualifier())
1728 case 'K':
1729 case 'V':
1730 case 'r':
1731 break;
1732 case 'A':
1734 string_type index = (*iter).get_optional_type();
1735 if (--n == 0 && (cvq & cvq_last))
1736 postfix = " [" + index + "]" + postfix;
1737 else if (n > 0)
1738 postfix = "[" + index + "]" + postfix;
1739 else
1741 prefix += " (";
1742 postfix = ") [" + index + "]" + postfix;
1744 break;
1746 default:
1747 _GLIBCXX_DEMANGLER_RETURN3;
1751 _GLIBCXX_DEMANGLER_RETURN3;
1754 template<typename Tp, typename Allocator>
1755 void
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");
1762 int cvq = 0;
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)
1781 case 'P':
1782 if (cvq)
1784 decode_KVrA(prefix, postfix, cvq, iter_array);
1785 cvq = 0;
1787 prefix += "*";
1788 break;
1789 case 'R':
1790 if (cvq)
1792 decode_KVrA(prefix, postfix, cvq, iter_array);
1793 cvq = 0;
1795 prefix += "&";
1796 break;
1797 case 'K':
1798 cvq |= cvq_K;
1799 continue;
1800 case 'V':
1801 cvq |= cvq_V;
1802 continue;
1803 case 'r':
1804 cvq |= cvq_r;
1805 continue;
1806 case 'A':
1807 if (!(cvq & cvq_A))
1809 cvq |= cvq_A;
1810 iter_array = iter;
1812 cvq += cvq_A_cnt;
1813 break;
1814 case 'M':
1815 if (cvq)
1817 decode_KVrA(prefix, postfix, cvq, iter_array);
1818 cvq = 0;
1820 prefix += " ";
1821 prefix += (*iter).get_optional_type();
1822 prefix += "::*";
1823 break;
1824 case 'U':
1825 if (cvq)
1827 decode_KVrA(prefix, postfix, cvq, iter_array);
1828 cvq = 0;
1830 prefix += " ";
1831 prefix += (*iter).get_optional_type();
1832 break;
1833 case 'G': // Only here so we added a substitution.
1834 break;
1836 break;
1839 if (cvq)
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>
1847 bool
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");
1853 ++M_inside_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;
1865 switch(current())
1867 case 'P':
1868 qualifiers->add_qualifier_start(pointer, start_pos,
1869 M_inside_substitution);
1870 eat_current();
1871 continue;
1872 case 'R':
1873 qualifiers->add_qualifier_start(reference, start_pos,
1874 M_inside_substitution);
1875 eat_current();
1876 continue;
1877 case 'K':
1878 case 'V':
1879 case 'r':
1881 char c;
1882 int count = 0;
1885 ++count;
1886 c = next();
1888 while(c == 'K' || c == 'V' || c == 'r');
1889 qualifiers->add_qualifier_start(cv_qualifier, start_pos, count,
1890 M_inside_substitution);
1891 continue;
1893 case 'U':
1895 eat_current();
1896 string_type source_name;
1897 if (!decode_source_name(source_name))
1899 failure = true;
1900 break;
1902 qualifiers->add_qualifier_start(vendor_extension, start_pos,
1903 source_name, M_inside_substitution);
1904 continue;
1906 case 'A':
1908 // <array-type> ::= A <positive dimension number> _ <element type>
1909 // ::= A [<dimension expression>] _ <element type>
1911 string_type index;
1912 int saved_pos;
1913 store(saved_pos);
1914 if (next() == 'n' || !decode_number(index))
1916 restore(saved_pos);
1917 if (next() != '_' && !decode_expression(index))
1919 failure = true;
1920 break;
1923 if (eat_current() != '_')
1925 failure = true;
1926 break;
1928 qualifiers->add_qualifier_start(array, start_pos, index,
1929 M_inside_substitution);
1930 continue;
1932 case 'M':
1934 // <pointer-to-member-type> ::= M <class type> <member type>
1935 // <Q>M<C> or <Q>M<C><Q2>F<R><B>E
1936 eat_current();
1937 string_type class_type;
1938 if (!decode_type(class_type)) // Substitution: "<C>".
1940 failure = true;
1941 break;
1943 char c = current();
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".
1950 int count = 0;
1951 int Q2_start_pos = M_pos;
1952 while(c == 'K' || c == 'V' || c == 'r') // Decode <Q2>.
1954 ++count;
1955 c = next();
1957 qualifier_list<Tp, Allocator> class_type_qualifiers(*this);
1958 if (count)
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')
1975 failure = true;
1976 break;
1978 // Return type.
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
1985 failure = true;
1986 break;
1988 prefix += " (";
1989 prefix += class_type;
1990 prefix += "::*";
1991 string_type bare_function_type;
1992 if (!decode_bare_function_type(bare_function_type)
1993 || eat_current() != 'E') // Substitution: <B> recursive.
1995 failure = true;
1996 break;
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);
2004 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);
2012 continue;
2014 default:
2015 break;
2017 break;
2019 if (!failure)
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);
2030 eat_current();
2032 int start_pos = M_pos;
2033 switch(current())
2035 case 'F':
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');
2042 if (extern_C)
2043 eat_current();
2045 // <Q>F<R><B>E ==> R (Q)B
2046 // substitution: "<R>", "<B>" (<B> recursive) and "F<R><B>E".
2048 // Return type.
2049 string_type return_type_postfix;
2050 if (!decode_type_with_postfix(prefix, return_type_postfix))
2051 // Substitution: "<R>".
2053 failure = true;
2054 break;
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() != '*'))
2062 prefix += ' ';
2063 prefix += '(';
2064 string_type bare_function_type;
2065 if (!decode_bare_function_type(bare_function_type)
2066 // substitution: "<B>" (<B> recursive).
2067 || eat_current() != 'E')
2069 failure = true;
2070 break;
2072 add_substitution(start_pos, type); // Substitution: "F<R><B>E".
2073 qualifiers->decode_qualifiers(prefix, postfix);
2074 // substitution: all qualified types, if any.
2075 postfix += ")";
2076 if (extern_C)
2077 postfix += " [extern \"C\"] ";
2078 postfix += bare_function_type;
2079 postfix += return_type_postfix;
2080 break;
2082 case 'T':
2083 if (!decode_template_param(prefix, qualifiers))
2085 failure = true;
2086 break;
2088 if (current() == 'I')
2090 add_substitution(start_pos, template_template_param);
2091 // substitution: "<template-template-param>".
2092 if (!decode_template_args(prefix))
2094 failure = true;
2095 break;
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.
2107 break;
2108 case 'S':
2109 if (M_pos >= M_maxpos)
2111 failure = true;
2112 break;
2114 if (M_str[M_pos + 1] != 't')
2116 if (!decode_substitution(prefix, qualifiers))
2118 failure = true;
2119 break;
2121 if (current() == 'I')
2123 if (!decode_template_args(prefix))
2125 failure = true;
2126 break;
2128 if (!recursive_template_param_or_substitution_call
2129 && qualifiers->suppressed())
2130 add_substitution(start_pos, type);
2131 // Substitution:
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.
2138 break;
2140 /* Fall-through for St */
2141 case 'N':
2142 case 'Z':
2143 case '0':
2144 case '1':
2145 case '2':
2146 case '3':
2147 case '4':
2148 case '5':
2149 case '6':
2150 case '7':
2151 case '8':
2152 case '9':
2153 // <Q><T> ==> T Q
2154 // substitutions: "<T>" (<T> recursive).
2155 if (!decode_class_enum_type(prefix))
2157 failure = true;
2158 break;
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.
2167 else
2168 qualifiers->printing_suppressed();
2169 break;
2170 default:
2171 // <Q><T> ==> T Q
2172 // substitutions: "<T>" (<T> recursive).
2173 if (!decode_builtin_type(prefix))
2175 failure = true;
2176 break;
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);
2183 else
2184 qualifiers->printing_suppressed();
2185 break;
2188 decode_type_exit:
2189 --M_inside_type;
2190 if (!recursive_template_param_or_substitution_call)
2192 qualifiers->~qualifier_list<Allocator>();
2193 M_qualifier_list_alloc.deallocate(qualifiers, 1);
2195 if (failure)
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>
2206 // ::= # empty
2207 // ::= <substitution>
2209 // <template-prefix> ::= <prefix> <template unqualified-name>
2210 // ::= <template-param>
2211 // ::= <substitution>
2213 template<typename Tp, typename Allocator>
2214 bool
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)
2230 case 'K':
2231 qualifiers += " const";
2232 break;
2233 case 'V':
2234 qualifiers += " volatile";
2235 break;
2236 case 'r':
2237 qualifiers += " restrict";
2238 break;
2241 int number_of_prefixes = 0;
2242 int substitution_start = M_pos;
2243 for(;;)
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);
2262 else
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')
2283 eat_current();
2284 _GLIBCXX_DEMANGLER_RETURN;
2286 if (current() != 'I')
2287 output += "::";
2288 else if (M_template_args_need_space)
2289 output += ' ';
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>
2300 bool
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;
2310 output += "::";
2311 if (current() == 's')
2313 eat_current();
2314 output += "string literal";
2316 else
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>
2332 bool
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;
2349 else
2350 while(length--)
2352 if (current() == 0)
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>
2364 bool
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')
2413 char c = next();
2414 if (c < '1' || c > '3')
2415 _GLIBCXX_DEMANGLER_FAILURE;
2417 else
2419 char c = next();
2420 if (c < '0' || c > '2')
2421 _GLIBCXX_DEMANGLER_FAILURE;
2422 output += '~';
2423 M_saw_destructor = true;
2425 M_name_is_cdtor = true;
2426 eat_current();
2427 output += M_function_name;
2429 else
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>
2439 bool
2440 session<Tp, Allocator>::decode_unscoped_name(string_type& output)
2442 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_unscoped_name");
2443 if (current() == 'S')
2445 if (next() != 't')
2446 _GLIBCXX_DEMANGLER_FAILURE;
2447 eat_current();
2448 output += "std::";
2450 decode_unqualified_name(output);
2451 _GLIBCXX_DEMANGLER_RETURN;
2454 // <name> ::=
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
2460 // # character.
2462 // <unscoped-template-name> ::= <unscoped-name>
2463 // ::= <substitution>
2464 template<typename Tp, typename Allocator>
2465 bool
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>
2507 bool
2508 session<Tp, Allocator>::decode_call_offset(string_type&
2509 #if _GLIBCXX_DEMANGLER_CWDEBUG
2510 output
2511 #endif
2514 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_call_offset");
2515 if (current() == 'h')
2517 string_type dummy;
2518 eat_current();
2519 if (decode_number(dummy) && current() == '_')
2521 eat_current();
2522 _GLIBCXX_DEMANGLER_RETURN;
2525 else if (current() == 'v')
2527 string_type dummy;
2528 eat_current();
2529 if (decode_number(dummy) && current() == '_')
2531 eat_current();
2532 if (decode_number(dummy) && current() == '_')
2534 eat_current();
2535 _GLIBCXX_DEMANGLER_RETURN;
2539 _GLIBCXX_DEMANGLER_FAILURE;
2543 // <special-name> ::=
2544 // TV <type> # virtual table
2545 // TT <type> # VTT structure (construction
2546 // vtable index).
2547 // TI <type> # typeinfo structure
2548 // TS <type> # typeinfo name (null-terminated
2549 // byte string).
2550 // GV <object name> # Guard variable for one-time
2551 // initialization of static objects in
2552 // a local scope.
2553 // T <call-offset> <base encoding># base is the nominal target function
2554 // of thunk.
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
2559 // adjustment
2561 template<typename Tp, typename Allocator>
2562 bool
2563 session<Tp, Allocator>::decode_special_name(string_type& output)
2565 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_special_name");
2566 if (current() == 'G')
2568 if (next() != 'V')
2569 _GLIBCXX_DEMANGLER_FAILURE;
2570 output += "guard variable for ";
2571 string_type nested_name_qualifiers;
2572 eat_current();
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;
2580 switch(next())
2582 case 'V':
2583 output += "vtable for ";
2584 eat_current();
2585 decode_type(output);
2586 _GLIBCXX_DEMANGLER_RETURN;
2587 case 'T':
2588 output += "VTT for ";
2589 eat_current();
2590 decode_type(output);
2591 _GLIBCXX_DEMANGLER_RETURN;
2592 case 'I':
2593 output += "typeinfo for ";
2594 eat_current();
2595 decode_type(output);
2596 _GLIBCXX_DEMANGLER_RETURN;
2597 case 'S':
2598 output += "typeinfo name for ";
2599 eat_current();
2600 decode_type(output);
2601 _GLIBCXX_DEMANGLER_RETURN;
2602 case 'c':
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?
2612 string_type first;
2613 output += "construction vtable for ";
2614 eat_current();
2615 if (!decode_type(first))
2616 _GLIBCXX_DEMANGLER_FAILURE;
2617 while(isdigit(current()))
2618 eat_current();
2619 if (eat_current() != '_')
2620 _GLIBCXX_DEMANGLER_FAILURE;
2621 if (!decode_type(output))
2622 _GLIBCXX_DEMANGLER_FAILURE;
2623 output += "-in-";
2624 output += first;
2625 _GLIBCXX_DEMANGLER_RETURN;
2627 default:
2628 if (current() == 'v')
2629 output += "virtual thunk to ";
2630 else
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;
2640 // <encoding> ::=
2641 // <function name> <bare-function-type> # Starts with 'C', 'D', 'N',
2642 // 'S', a digit or a lower case
2643 // character.
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 << "\")");
2657 #endif
2658 if (len <= 0)
2659 return INT_MIN;
2660 session<Tp, Allocator> demangler_session(in, len, id);
2661 string_type nested_name_qualifiers;
2662 int saved_pos;
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);
2667 string_type name;
2668 if (!demangler_session.decode_name(name, nested_name_qualifiers))
2669 return INT_MIN;
2670 if (demangler_session.current() == 0
2671 || demangler_session.current() == 'E')
2673 output += name;
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))
2686 return INT_MIN;
2687 output += ' ';
2689 output += name;
2690 if (!demangler_session.decode_bare_function_type(output))
2691 return INT_MIN;
2692 output += nested_name_qualifiers;
2693 output += return_type_postfix;
2694 return demangler_session.M_pos;
2697 } // namespace demangler
2699 // Public interface
2700 template<typename Tp, typename Allocator>
2701 struct demangle
2703 typedef typename Allocator::template rebind<char>::other char_Allocator;
2704 typedef std::basic_string<char, std::char_traits<char>, char_Allocator>
2705 string_type;
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;
2725 string_type result;
2726 bool failure = (input[0] != '_');
2728 if (!failure)
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);
2738 else
2739 result.assign("global constructors keyed to ", 29);
2740 // Output the disambiguation part as-is.
2741 result += input + 11;
2743 else
2744 failure = true;
2746 else if (input[1] == 'Z')
2748 int cnt =
2749 demangler_type::decode_encoding(result, input + 2, INT_MAX, id);
2750 if (cnt < 0 || input[cnt + 2] != 0)
2751 failure = true;
2753 else
2754 failure = true;
2757 // Failure to demangle, return the mangled name.
2758 if (failure)
2759 result.assign(input, strlen(input));
2761 return result;
2764 // demangle::type()
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;
2773 if (input == NULL)
2774 result = "(null)";
2775 else
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.
2782 result = input;
2785 return result;
2787 } // namespace __gnu_cxx
2789 #endif // __DEMANGLE_H