]> gcc.gnu.org Git - gcc.git/blob - libstdc++-v3/libsupc++/demangle.h
[multiple changes]
[gcc.git] / libstdc++-v3 / libsupc++ / demangle.h
1 // C++ IA64 / g++ v3 demangler -*- C++ -*-
2
3 // Copyright (C) 2003 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.
11
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.
16
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.
21
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.
30
31 #ifndef __DEMANGLER_H
32 #define __DEMANGLER_H 1
33
34 #include <limits>
35 #include <vector>
36 #include <string>
37 #include <cctype>
38
39 #ifndef _GLIBCPP_DEMANGLER_DEBUG
40 #define _GLIBCPP_DEMANGLER_CWDEBUG 0
41 #define _GLIBCPP_DEMANGLER_DEBUG(x)
42 #define _GLIBCPP_DEMANGLER_DOUT(cntrl, data)
43 #define _GLIBCPP_DEMANGLER_DOUT_ENTERING(x)
44 #define _GLIBCPP_DEMANGLER_DOUT_ENTERING2(x)
45 #define _GLIBCPP_DEMANGLER_RETURN \
46 return M_result
47 #define _GLIBCPP_DEMANGLER_RETURN2 \
48 return M_result
49 #define _GLIBCPP_DEMANGLER_FAILURE \
50 do { M_result = false; return false; } while(0)
51 #else
52 #define _GLIBCPP_DEMANGLER_CWDEBUG 1
53 #endif
54
55 // The following defines change the behaviour of the demangler. The
56 // default behaviour is that none of these macros is defined.
57
58 // _GLIBCPP_DEMANGLER_STYLE_VOID
59 // Default behaviour: int f()
60 // Uses (void) instead of (): int f(void)
61
62 // _GLIBCPP_DEMANGLER_STYLE_LITERAL
63 // Default behaviour: (long)13,
64 // (unsigned long long)19
65 // Use extensions 'u', 'l' and 'll' for integral
66 // literals (as in template arguments): 13l, 19ull
67
68 // _GLIBCPP_DEMANGLER_STYLE_LITERAL_INT
69 // Default behaviour: 4
70 // Use also an explicit cast for int in literals: (int)4
71
72 namespace __gnu_cxx
73 {
74 namespace demangler
75 {
76
77 enum substitution_nt
78 {
79 type,
80 template_template_param,
81 nested_name_prefix,
82 nested_name_template_prefix,
83 unscoped_template_name,
84 };
85
86 struct substitution_st
87 {
88 int M_start_pos;
89 substitution_nt M_type;
90 int M_number_of_prefixes;
91
92 substitution_st(int start_pos,
93 substitution_nt type,
94 int number_of_prefixes)
95 : M_start_pos(start_pos), M_type(type),
96 M_number_of_prefixes(number_of_prefixes)
97 { }
98 };
99
100 enum simple_qualifier_nt
101 {
102 complex_or_imaginary = 'G',
103 pointer = 'P',
104 reference = 'R'
105 };
106
107 enum cv_qualifier_nt
108 {
109 cv_qualifier = 'K'
110 };
111
112 enum param_qualifier_nt
113 {
114 vendor_extension = 'U',
115 array = 'A',
116 pointer_to_member = 'M'
117 };
118
119 template<typename Allocator>
120 class qualifier;
121
122 template<typename Allocator>
123 class qualifier_list;
124
125 template<typename Allocator>
126 class session;
127
128 template<typename Allocator>
129 class qualifier
130 {
131 typedef std::basic_string<char, std::char_traits<char>, Allocator>
132 string_type;
133
134 private:
135 char M_qualifier1;
136 char M_qualifier2;
137 char M_qualifier3;
138 mutable unsigned char M_cnt;
139 string_type M_optional_type;
140 int M_start_pos;
141 bool M_part_of_substitution;
142
143 public:
144 qualifier(int start_pos,
145 simple_qualifier_nt simple_qualifier,
146 int inside_substitution)
147 : M_qualifier1(simple_qualifier),
148 M_start_pos(start_pos),
149 M_part_of_substitution(inside_substitution)
150 { }
151
152 qualifier(int start_pos,
153 cv_qualifier_nt cv_qualifier,
154 char const* start,
155 int count,
156 int inside_substitution)
157 : M_qualifier1(start[0]),
158 M_qualifier2((count > 1) ? start[1] : '\0'),
159 M_qualifier3((count > 2) ? start[2] : '\0'),
160 M_start_pos(start_pos),
161 M_part_of_substitution(inside_substitution)
162 { }
163
164 qualifier(int start_pos,
165 param_qualifier_nt param_qualifier,
166 string_type optional_type,
167 int inside_substitution)
168 : M_qualifier1(param_qualifier),
169 M_optional_type(optional_type),
170 M_start_pos(start_pos),
171 M_part_of_substitution(inside_substitution)
172 { }
173
174 int
175 start_pos(void) const
176 { return M_start_pos; }
177
178 char
179 first_qualifier(void) const
180 { M_cnt = 1; return M_qualifier1; }
181
182 char
183 next_qualifier(void) const
184 {
185 return (++M_cnt == 2) ? M_qualifier2
186 : ((M_cnt == 3) ? M_qualifier3 : 0);
187 }
188
189 string_type const&
190 optional_type(void) const
191 { return M_optional_type; }
192
193 bool
194 part_of_substitution(void) const
195 { return M_part_of_substitution; }
196
197 };
198
199 template<typename Allocator>
200 class qualifier_list
201 {
202 typedef std::basic_string<char, std::char_traits<char>, Allocator>
203 string_type;
204
205 private:
206 bool M_printing_suppressed;
207 std::vector<qualifier<Allocator>, Allocator> M_qualifier_starts;
208 session<Allocator>& M_demangler;
209
210 public:
211 qualifier_list(session<Allocator>& demangler_obj)
212 : M_printing_suppressed(false), M_demangler(demangler_obj)
213 { }
214
215 void
216 add_qualifier_start(simple_qualifier_nt simple_qualifier,
217 int start_pos,
218 int inside_substitution)
219 { M_qualifier_starts.
220 push_back(qualifier<Allocator>(start_pos,
221 simple_qualifier, inside_substitution)); }
222
223 void
224 add_qualifier_start(cv_qualifier_nt cv_qualifier,
225 int start_pos,
226 int count,
227 int inside_substitution)
228 { M_qualifier_starts.
229 push_back(qualifier<Allocator>(start_pos,
230 cv_qualifier, &M_demangler.M_str[start_pos],
231 count, inside_substitution)); }
232
233 void
234 add_qualifier_start(param_qualifier_nt param_qualifier,
235 int start_pos,
236 string_type optional_type,
237 int inside_substitution)
238 { M_qualifier_starts.
239 push_back(qualifier<Allocator>(start_pos,
240 param_qualifier, optional_type, inside_substitution)); }
241
242 void
243 decode_qualifiers(string_type& prefix,
244 string_type& postfix,
245 bool member_function_pointer_qualifiers);
246
247 bool
248 suppressed(void) const
249 { return M_printing_suppressed; }
250
251 void
252 printing_suppressed(void)
253 { M_printing_suppressed = true; }
254
255 size_t
256 size(void) const
257 { return M_qualifier_starts.size(); }
258
259 };
260
261 template<typename Allocator>
262 class session
263 {
264 friend class qualifier_list<Allocator>;
265 typedef std::basic_string<char, std::char_traits<char>, Allocator>
266 string_type;
267
268 private:
269 char const* M_str;
270 int M_pos;
271 int M_maxpos;
272 bool M_result;
273 int M_inside_template_args;
274 int M_inside_type;
275 int M_inside_substitution;
276 bool M_saw_destructor;
277 bool M_name_is_cdtor;
278 bool M_name_is_template;
279 bool M_name_is_conversion_operator;
280 bool M_template_args_need_space;
281 string_type M_function_name;
282 std::vector<int, Allocator> M_template_arg_pos;
283 int M_template_arg_pos_offset;
284 std::vector<substitution_st, Allocator> M_substitutions_pos;
285 #if _GLIBCPP_DEMANGLER_CWDEBUG
286 bool M_inside_add_substitution;
287 #endif
288
289 public:
290 explicit session(char const* in, int len)
291 : M_str(in), M_pos(0), M_maxpos(len - 1), M_result(true),
292 M_inside_template_args(0), M_inside_type(0),
293 M_inside_substitution(0), M_saw_destructor(false),
294 M_name_is_cdtor(false), M_name_is_template(false),
295 M_name_is_conversion_operator(false),
296 M_template_args_need_space(false), M_template_arg_pos_offset(0)
297 #if _GLIBCPP_DEMANGLER_CWDEBUG
298 , M_inside_add_substitution(false)
299 #endif
300 { }
301
302 static int
303 decode_encoding(string_type& output, char const* input, int len);
304
305 bool
306 decode_type_with_postfix(string_type& prefix,
307 string_type& postfix,
308 qualifier_list<Allocator>* qualifiers = NULL);
309
310 bool
311 decode_type(string_type& output,
312 qualifier_list<Allocator>* qualifiers = NULL)
313 {
314 string_type postfix;
315 bool res = decode_type_with_postfix(output, postfix, qualifiers);
316 output += postfix;
317 return res;
318 }
319
320 bool
321 remaining_input_characters(void) const
322 { return current() != 0; }
323
324 private:
325 char
326 current(void) const
327 { return (M_pos > M_maxpos) ? 0 : M_str[M_pos]; }
328
329 char
330 next(void)
331 { return (M_pos >= M_maxpos) ? 0 : M_str[++M_pos]; }
332
333 char
334 eat_current(void)
335 { return (M_pos > M_maxpos) ? 0 : M_str[M_pos++]; }
336
337 void
338 store(int& saved_pos)
339 { saved_pos = M_pos; }
340
341 void
342 restore(int saved_pos)
343 { M_pos = saved_pos; M_result = true; }
344
345 void
346 add_substitution(int start_pos,
347 substitution_nt sub_type,
348 int number_of_prefixes);
349
350 bool decode_bare_function_type(string_type& output);
351 bool decode_builtin_type(string_type& output);
352 bool decode_call_offset(string_type& output);
353 bool decode_class_enum_type(string_type& output);
354 bool decode_expression(string_type& output);
355 bool decode_literal(string_type& output);
356 bool decode_local_name(string_type& output);
357 bool decode_name(string_type& output,
358 string_type& nested_name_qualifiers);
359 bool decode_nested_name(string_type& output,
360 string_type& qualifiers);
361 bool decode_number(string_type& output);
362 bool decode_operator_name(string_type& output);
363 bool decode_source_name(string_type& output);
364 bool decode_substitution(string_type& output,
365 qualifier_list<Allocator>* qualifiers = NULL);
366 bool decode_template_args(string_type& output);
367 bool decode_template_param(string_type& output,
368 qualifier_list<Allocator>* qualifiers = NULL);
369 bool decode_unqualified_name(string_type& output);
370 bool decode_unscoped_name(string_type& output);
371 bool decode_decimal_integer(string_type& output);
372 bool decode_special_name(string_type& output);
373 };
374
375 template<typename Allocator>
376 #if !_GLIBCPP_DEMANGLER_CWDEBUG
377 inline
378 #endif
379 void
380 session<Allocator>::add_substitution(int start_pos,
381 substitution_nt sub_type,
382 int number_of_prefixes = 0)
383 {
384 if (!M_inside_substitution)
385 {
386 #if _GLIBCPP_DEMANGLER_CWDEBUG
387 if (M_inside_add_substitution)
388 return;
389 #endif
390 M_substitutions_pos.
391 push_back(substitution_st(start_pos,
392 sub_type, number_of_prefixes));
393 #if _GLIBCPP_DEMANGLER_CWDEBUG
394 if (!DEBUGCHANNELS::dc::demangler.is_on())
395 return;
396 string_type substitution_name("S");
397 int n = M_substitutions_pos.size() - 1;
398 if (n > 0)
399 substitution_name += (n <= 10) ? (char)(n + '0' - 1)
400 : (char)(n + 'A' - 11);
401 substitution_name += '_';
402 string_type subst;
403 int saved_pos = M_pos;
404 M_pos = start_pos;
405 M_inside_add_substitution = true;
406 _GLIBCPP_DEMANGLER_DEBUG( dc::demangler.off() );
407 switch(sub_type)
408 {
409 case type:
410 decode_type(subst);
411 break;
412 case template_template_param:
413 decode_template_param(subst);
414 break;
415 case nested_name_prefix:
416 case nested_name_template_prefix:
417 for (int cnt = number_of_prefixes; cnt > 0; --cnt)
418 {
419 if (current() == 'I')
420 {
421 subst += ' ';
422 decode_template_args(subst);
423 }
424 else
425 {
426 if (cnt < number_of_prefixes)
427 subst += "::";
428 if (current() == 'S')
429 decode_substitution(subst);
430 else
431 decode_unqualified_name(subst);
432 }
433 }
434 break;
435 case unscoped_template_name:
436 decode_unscoped_name(subst);
437 break;
438 }
439 M_pos = saved_pos;
440 _GLIBCPP_DEMANGLER_DEBUG( dc::demangler.on() );
441 _GLIBCPP_DEMANGLER_DOUT(dc::demangler,
442 "Adding substitution " << substitution_name
443 << " : " << subst
444 << " (from " << location_ct((char*)__builtin_return_address(0)
445 + builtin_return_address_offset)
446 << " <- " << location_ct((char*)__builtin_return_address(1)
447 + builtin_return_address_offset)
448 << " <- " << location_ct((char*)__builtin_return_address(2)
449 + builtin_return_address_offset)
450 << ").");
451 M_inside_add_substitution = false;
452 #endif
453 }
454 }
455
456 //
457 // <decimal-integer> ::= 0
458 // ::= 1|2|3|4|5|6|7|8|9 [<digit>+]
459 // <digit> ::= 0|1|2|3|4|5|6|7|8|9
460 //
461 template<typename Allocator>
462 bool
463 session<Allocator>::decode_decimal_integer(string_type& output)
464 {
465 char c = current();
466 if (c == '0')
467 {
468 output += '0';
469 eat_current();
470 }
471 else if (!std::isdigit(c))
472 M_result = false;
473 else
474 {
475 do
476 {
477 output += c;
478 }
479 while (std::isdigit((c = next())));
480 }
481 return M_result;
482 }
483
484 // <number> ::= [n] <decimal-integer>
485 //
486 template<typename Allocator>
487 bool
488 session<Allocator>::decode_number(string_type& output)
489 {
490 _GLIBCPP_DEMANGLER_DOUT_ENTERING("decode_number");
491 if (current() != 'n')
492 decode_decimal_integer(output);
493 else
494 {
495 output += '-';
496 eat_current();
497 decode_decimal_integer(output);
498 }
499 _GLIBCPP_DEMANGLER_RETURN;
500 }
501
502 // <builtin-type> ::= v # void
503 // ::= w # wchar_t
504 // ::= b # bool
505 // ::= c # char
506 // ::= a # signed char
507 // ::= h # unsigned char
508 // ::= s # short
509 // ::= t # unsigned short
510 // ::= i # int
511 // ::= j # unsigned int
512 // ::= l # long
513 // ::= m # unsigned long
514 // ::= x # long long, __int64
515 // ::= y # unsigned long long, __int64
516 // ::= n # __int128
517 // ::= o # unsigned __int128
518 // ::= f # float
519 // ::= d # double
520 // ::= e # long double, __float80
521 // ::= g # __float128
522 // ::= z # ellipsis
523 // ::= u <source-name> # vendor extended type
524 //
525 char const* const builtin_type_c[26] =
526 {
527 "signed char", // a
528 "bool", // b
529 "char", // c
530 "double", // d
531 "long double", // e
532 "float", // f
533 "__float128", // g
534 "unsigned char", // h
535 "int", // i
536 "unsigned int", // j
537 NULL, // k
538 "long", // l
539 "unsigned long", // m
540 "__int128", // n
541 "unsigned __int128", // o
542 NULL, // p
543 NULL, // q
544 NULL, // r
545 "short", // s
546 "unsigned short", // t
547 NULL, // u
548 "void", // v
549 "wchar_t", // w
550 "long long", // x
551 "unsigned long long", // y
552 "..." // z
553 };
554
555 //
556 template<typename Allocator>
557 bool
558 session<Allocator>::decode_builtin_type(string_type& output)
559 {
560 _GLIBCPP_DEMANGLER_DOUT_ENTERING("decode_builtin_type");
561 char const* bt;
562 if (!islower(current()) || !(bt = builtin_type_c[current() - 'a']))
563 _GLIBCPP_DEMANGLER_FAILURE;
564 output += bt;
565 eat_current();
566 _GLIBCPP_DEMANGLER_RETURN;
567 }
568
569 // <class-enum-type> ::= <name>
570 //
571 template<typename Allocator>
572 bool
573 session<Allocator>::decode_class_enum_type(string_type& output)
574 {
575 _GLIBCPP_DEMANGLER_DOUT_ENTERING("decode_class_enum_type");
576 string_type nested_name_qualifiers;
577 if (!decode_name(output, nested_name_qualifiers))
578 _GLIBCPP_DEMANGLER_FAILURE;
579 output += nested_name_qualifiers;
580 _GLIBCPP_DEMANGLER_RETURN;
581 }
582
583 // <substitution> ::=
584 // S <seq-id> _
585 // S_
586 // St # ::std::
587 // Sa # ::std::allocator
588 // Sb # ::std::basic_string
589 // Ss # ::std::basic_string<char, std::char_traits<char>,
590 // std::allocator<char> >
591 // Si # ::std::basic_istream<char, std::char_traits<char> >
592 // So # ::std::basic_ostream<char, std::char_traits<char> >
593 // Sd # ::std::basic_iostream<char, std::char_traits<char> >
594 //
595 // <seq-id> ::=
596 // 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
597 // [<seq-id>] # Base 36 number
598 //
599 template<typename Allocator>
600 bool
601 session<Allocator>::decode_substitution(string_type& output,
602 qualifier_list<Allocator>* qualifiers)
603 {
604 _GLIBCPP_DEMANGLER_DOUT_ENTERING("decode_substitution");
605 unsigned int value = 0;
606 char c = next();
607 if (c != '_')
608 {
609 switch(c)
610 {
611 case 'a':
612 {
613 output += "std::allocator";
614 if (!M_inside_template_args)
615 {
616 M_function_name = "allocator";
617 M_name_is_template = true;
618 M_name_is_cdtor = false;
619 M_name_is_conversion_operator = false;
620 }
621 eat_current();
622 if (qualifiers)
623 qualifiers->printing_suppressed();
624 _GLIBCPP_DEMANGLER_RETURN;
625 }
626 case 'b':
627 {
628 output += "std::basic_string";
629 if (!M_inside_template_args)
630 {
631 M_function_name = "basic_string";
632 M_name_is_template = true;
633 M_name_is_cdtor = false;
634 M_name_is_conversion_operator = false;
635 }
636 eat_current();
637 if (qualifiers)
638 qualifiers->printing_suppressed();
639 _GLIBCPP_DEMANGLER_RETURN;
640 }
641 case 'd':
642 output += "std::iostream";
643 if (!M_inside_template_args)
644 {
645 M_function_name = "iostream";
646 M_name_is_template = true;
647 M_name_is_cdtor = false;
648 M_name_is_conversion_operator = false;
649 }
650 eat_current();
651 if (qualifiers)
652 qualifiers->printing_suppressed();
653 _GLIBCPP_DEMANGLER_RETURN;
654 case 'i':
655 output += "std::istream";
656 if (!M_inside_template_args)
657 {
658 M_function_name = "istream";
659 M_name_is_template = true;
660 M_name_is_cdtor = false;
661 M_name_is_conversion_operator = false;
662 }
663 eat_current();
664 if (qualifiers)
665 qualifiers->printing_suppressed();
666 _GLIBCPP_DEMANGLER_RETURN;
667 case 'o':
668 output += "std::ostream";
669 if (!M_inside_template_args)
670 {
671 M_function_name = "ostream";
672 M_name_is_template = true;
673 M_name_is_cdtor = false;
674 M_name_is_conversion_operator = false;
675 }
676 eat_current();
677 if (qualifiers)
678 qualifiers->printing_suppressed();
679 _GLIBCPP_DEMANGLER_RETURN;
680 case 's':
681 output += "std::string";
682 if (!M_inside_template_args)
683 {
684 M_function_name = "string";
685 M_name_is_template = true;
686 M_name_is_cdtor = false;
687 M_name_is_conversion_operator = false;
688 }
689 eat_current();
690 if (qualifiers)
691 qualifiers->printing_suppressed();
692 _GLIBCPP_DEMANGLER_RETURN;
693 case 't':
694 output += "std";
695 eat_current();
696 if (qualifiers)
697 qualifiers->printing_suppressed();
698 _GLIBCPP_DEMANGLER_RETURN;
699 default:
700 for(;; c = next())
701 {
702 if (std::isdigit(c))
703 value = value * 36 + c - '0';
704 else if (isupper(c))
705 value = value * 36 + c - 'A' + 10;
706 else if (c == '_')
707 break;
708 else
709 _GLIBCPP_DEMANGLER_FAILURE;
710 }
711 ++value;
712 break;
713 }
714 }
715 eat_current();
716 if (value >= M_substitutions_pos.size() ||
717 M_inside_type > 20) // Rather than core dump.
718 _GLIBCPP_DEMANGLER_FAILURE;
719 ++M_inside_substitution;
720 int saved_pos = M_pos;
721 substitution_st& substitution(M_substitutions_pos[value]);
722 M_pos = substitution.M_start_pos;
723 switch(substitution.M_type)
724 {
725 case type:
726 decode_type(output, qualifiers);
727 break;
728 case template_template_param:
729 decode_template_param(output, qualifiers);
730 break;
731 case nested_name_prefix:
732 case nested_name_template_prefix:
733 for (int cnt = substitution.M_number_of_prefixes; cnt > 0; --cnt)
734 {
735 if (current() == 'I')
736 {
737 if (M_template_args_need_space)
738 output += ' ';
739 M_template_args_need_space = false;
740 if (!decode_template_args(output))
741 _GLIBCPP_DEMANGLER_FAILURE;
742 }
743 else
744 {
745 if (cnt < substitution.M_number_of_prefixes)
746 output += "::";
747 if (current() == 'S')
748 {
749 if (!decode_substitution(output))
750 _GLIBCPP_DEMANGLER_FAILURE;
751 }
752 else if (!decode_unqualified_name(output))
753 _GLIBCPP_DEMANGLER_FAILURE;
754 }
755 }
756 if (qualifiers)
757 qualifiers->printing_suppressed();
758 break;
759 case unscoped_template_name:
760 decode_unscoped_name(output);
761 if (qualifiers)
762 qualifiers->printing_suppressed();
763 break;
764 }
765 M_pos = saved_pos;
766 --M_inside_substitution;
767 _GLIBCPP_DEMANGLER_RETURN;
768 }
769
770 // <template-param> ::= T_ # first template parameter
771 // ::= T <parameter-2 non-negative number> _
772 //
773 template<typename Allocator>
774 bool
775 session<Allocator>::decode_template_param(string_type& output,
776 qualifier_list<Allocator>* qualifiers)
777 {
778 _GLIBCPP_DEMANGLER_DOUT_ENTERING("decode_template_parameter");
779 if (current() != 'T')
780 _GLIBCPP_DEMANGLER_FAILURE;
781 unsigned int value = 0;
782 char c;
783 if ((c = next()) != '_')
784 {
785 while(std::isdigit(c))
786 {
787 value = value * 10 + c - '0';
788 c = next();
789 }
790 ++value;
791 }
792 if (eat_current() != '_')
793 _GLIBCPP_DEMANGLER_FAILURE;
794 value += M_template_arg_pos_offset;
795 if (value >= M_template_arg_pos.size())
796 _GLIBCPP_DEMANGLER_FAILURE;
797 int saved_pos = M_pos;
798 M_pos = M_template_arg_pos[value];
799 if (M_inside_type > 20) // Rather than core dump.
800 _GLIBCPP_DEMANGLER_FAILURE;
801 ++M_inside_substitution;
802 if (current() == 'X')
803 {
804 eat_current();
805 decode_expression(output);
806 }
807 else if (current() == 'L')
808 decode_literal(output);
809 else
810 decode_type(output, qualifiers);
811 --M_inside_substitution;
812 M_pos = saved_pos;
813 _GLIBCPP_DEMANGLER_RETURN;
814 }
815
816 template<typename Allocator>
817 bool
818 session<Allocator>::decode_literal(string_type& output)
819 {
820 _GLIBCPP_DEMANGLER_DOUT_ENTERING("decode_literal");
821 eat_current(); // Eat the 'L'.
822 if (current() == '_')
823 {
824 if (next() != 'Z')
825 _GLIBCPP_DEMANGLER_FAILURE;
826 eat_current();
827 if ((M_pos += decode_encoding(output, M_str + M_pos,
828 M_maxpos - M_pos + 1)) < 0)
829 _GLIBCPP_DEMANGLER_FAILURE;
830 }
831 else
832 {
833 // Special cases
834 if (current() == 'b')
835 {
836 if (next() == '0')
837 output += "false";
838 else
839 output += "true";
840 eat_current();
841 _GLIBCPP_DEMANGLER_RETURN;
842 }
843 char c = current();
844 #ifdef _GLIBCPP_DEMANGLER_STYLE_LITERAL
845 if (c == 'i' || c == 'j' || c == 'l' ||
846 c == 'm' || c == 'x' || c == 'y')
847 eat_current();
848 else
849 #else
850 #ifndef _GLIBCPP_DEMANGLER_STYLE_LITERAL_INT
851 if (c == 'i')
852 eat_current();
853 else
854 #endif
855 #endif
856 {
857 output += '(';
858 if (!decode_type(output))
859 _GLIBCPP_DEMANGLER_FAILURE;
860 output += ')';
861 }
862 if (!decode_number(output))
863 _GLIBCPP_DEMANGLER_FAILURE;
864 #ifdef _GLIBCPP_DEMANGLER_STYLE_LITERAL
865 if (c == 'j' || c == 'm' || c == 'y')
866 output += 'u';
867 if (c == 'l' || c == 'm')
868 output += 'l';
869 if (c == 'x' || c == 'y')
870 output += "ll";
871 #endif
872 }
873 _GLIBCPP_DEMANGLER_RETURN;
874 }
875
876 // <operator-name> ::=
877 // nw # new
878 // na # new[]
879 // dl # delete
880 // da # delete[]
881 // ng # - (unary)
882 // ad # & (unary)
883 // de # * (unary)
884 // co # ~
885 // pl # +
886 // mi # -
887 // ml # *
888 // dv # /
889 // rm # %
890 // an # &
891 // or # |
892 // eo # ^
893 // aS # =
894 // pL # +=
895 // mI # -=
896 // mL # *=
897 // dV # /=
898 // rM # %=
899 // aN # &=
900 // oR # |=
901 // eO # ^=
902 // ls # <<
903 // rs # >>
904 // lS # <<=
905 // rS # >>=
906 // eq # ==
907 // ne # !=
908 // lt # <
909 // gt # >
910 // le # <=
911 // ge # >=
912 // nt # !
913 // aa # &&
914 // oo # ||
915 // pp # ++
916 // mm # --
917 // cm # ,
918 // pm # ->*
919 // pt # ->
920 // cl # ()
921 // ix # []
922 // qu # ?
923 // sz # sizeof
924 // sr # scope resolution (::), see below
925 // cv <type> # (cast)
926 // v <digit> <source-name> # vendor extended operator
927 //
928 //
929 // Symbol operator codes exist of two characters, we need to find a
930 // quick hash so that their names can be looked up in a table.
931 //
932 // The puzzle :)
933 // Shift the rows so that there is at most one character per column.
934 //
935 // A perfect solution:
936 // horizontal
937 // ..................................... offset + 'a'
938 // a, ||a||d|||||||||n||||s|||||||||||||||||| 2
939 // c, || || ||lm|o||| |||| |||||||||||||||||| -3
940 // d, || a| |e | ||l |||| |||v|||||||||||||| 3
941 // e, || | | o q| |||| ||| |||||||||||||| -4
942 // g, |e | | | t||| ||| |||||||||||||| -3
943 // i, | | | | ||| ||| ||||||||||x||| 12
944 // l, | | | e ||| ||| ||st|||||| ||| 9
945 // m, | | | ||| ||| |i lm|||| ||| 18
946 // n, a e g ||t |w| | |||| ||| 0
947 // o, || | | | ||o| r|| 19
948 // p, lm p | t || | || 6
949 // q, | || u || 14
950 // r, | |m |s 20
951 // s, r z | 6
952 // .....................................
953 // ^ ^__ second character
954 // |___ first character
955 //
956
957 // Putting that solution in tables:
958
959 char const offset_table_c [1 + CHAR_MAX - CHAR_MIN ] =
960 {
961 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
962 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
963 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
964 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
965 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
966 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
967 #if (CHAR_MIN < 0)
968 // Add -CHAR_MIN extra zeroes (128):
969 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
970 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
971 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
972 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
973 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
974 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
975 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
976 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
977 // a b c d e f g h i j k
978 0, -95, 0,-100, -94,-101, 0,-100, 0, -85, 0, 0,
979 // l m n o p q r s t u v
980 -88, -79, -97, -78, -91, -83, -77, -91, 0, 0, 0,
981 #else
982 // a b c d e f g h i j k
983 0, 161, 0, 156, 162, 155, 0, 156, 0, 171, 0, 0,
984 // l m n o p q r s t u v
985 168, 177, 159, 178, 165, 173, 179, 165, 0, 0, 0,
986 #endif
987 // ... more zeros
988 };
989
990 struct entry_st
991 {
992 char const* opcode;
993 char const* symbol_name;
994 bool unary;
995 };
996
997 entry_st const symbol_name_table_c[39] = {
998 { "na", "operator new[]", true },
999 { "ge", "operator>=", false },
1000 { "aa", "operator&&", false },
1001 { "da", "operator delete[]", true },
1002 { "ne", "operator!=", false },
1003 { "ad", "operator&", true }, // unary
1004 { "ng", "operator-", true }, // unary
1005 { "de", "operator*", true }, // unary
1006 { "cl", "operator()", true },
1007 { "cm", "operator,", false },
1008 { "eo=", "operator^", false },
1009 { "co", "operator~", false },
1010 { "eq", "operator==", false },
1011 { "le", "operator<=", false },
1012 { "dl", "operator delete", true },
1013 { "an=", "operator&", false },
1014 { "gt", "operator>", false },
1015 { "pl=", "operator+", false },
1016 { "pm", "operator->*", false },
1017 { "nt", "operator!", true },
1018 { "as=", "operator", false },
1019 { "pp", "operator++", true },
1020 { "nw", "operator new", true },
1021 { "sr", "::", true },
1022 { "dv=", "operator/", false },
1023 { "pt", "operator->", false },
1024 { "mi=", "operator-", false },
1025 { "ls=", "operator<<", false },
1026 { "lt", "operator<", false },
1027 { "ml=", "operator*", false },
1028 { "mm", "operator--", true },
1029 { "sz", "sizeof", true },
1030 { "rm=", "operator%", false },
1031 { "oo", "operator||", false },
1032 { "qu", "operator?", false },
1033 { "ix", "operator[]", true },
1034 { "or=", "operator|", false },
1035 { "", NULL, false },
1036 { "rs=", "operator>>", false }
1037 };
1038
1039 template<typename Allocator>
1040 bool
1041 session<Allocator>::decode_operator_name(string_type& output)
1042 {
1043 _GLIBCPP_DEMANGLER_DOUT_ENTERING("decode_operator_name");
1044
1045 char opcode0 = current();
1046 char opcode1 = tolower(next());
1047
1048 register char hash;
1049 if ((hash = offset_table_c[opcode0 - CHAR_MIN]))
1050 {
1051 hash += opcode1;
1052 if (
1053 #if (CHAR_MIN < 0)
1054 hash >= 0 &&
1055 #endif
1056 hash < 39)
1057 {
1058 int index = static_cast<int>(static_cast<unsigned char>(hash));
1059 entry_st entry = symbol_name_table_c[index];
1060 if (entry.opcode[0] == opcode0 && entry.opcode[1] == opcode1
1061 && (opcode1 == current() || entry.opcode[2] == '='))
1062 {
1063 output += entry.symbol_name;
1064 if (opcode1 != current())
1065 output += '=';
1066 eat_current();
1067 if (hash == 27 || hash == 28)
1068 M_template_args_need_space = true;
1069 _GLIBCPP_DEMANGLER_RETURN;
1070 }
1071 else if (opcode0 == 'c' && opcode1 == 'v')
1072 {
1073 eat_current();
1074 output += "operator ";
1075 if (current() == 'T')
1076 {
1077 // This is a templated cast operator.
1078 // It must be of the form "cvT_I...E".
1079 // Let M_template_arg_pos already point
1080 // to the template argument.
1081 M_template_arg_pos_offset = M_template_arg_pos.size();
1082 M_template_arg_pos.push_back(M_pos + 3);
1083 }
1084 if (!decode_type(output))
1085 _GLIBCPP_DEMANGLER_FAILURE;
1086 if (!M_inside_template_args)
1087 M_name_is_conversion_operator = true;
1088 _GLIBCPP_DEMANGLER_RETURN;
1089 }
1090 }
1091 }
1092 _GLIBCPP_DEMANGLER_FAILURE;
1093 }
1094
1095 //
1096 // <expression> ::= <unary operator-name> <expression>
1097 // ::= <binary operator-name> <expression> <expression>
1098 // ::= <expr-primary>
1099 //
1100 // <expr-primary> ::= <template-param> # Starts with a T
1101 // ::= L <type> <value number> E # literal
1102 // ::= L <mangled-name> E # external name
1103 //
1104 template<typename Allocator>
1105 bool
1106 session<Allocator>::decode_expression(string_type& output)
1107 {
1108 _GLIBCPP_DEMANGLER_DOUT_ENTERING("decode_expression");
1109 if (current() == 'T')
1110 {
1111 if (!decode_template_param(output))
1112 _GLIBCPP_DEMANGLER_FAILURE;
1113 _GLIBCPP_DEMANGLER_RETURN;
1114 }
1115 else if (current() == 'L')
1116 {
1117 if (!decode_literal(output))
1118 _GLIBCPP_DEMANGLER_FAILURE;
1119 if (current() != 'E')
1120 _GLIBCPP_DEMANGLER_FAILURE;
1121 eat_current();
1122 _GLIBCPP_DEMANGLER_RETURN;
1123 }
1124 else
1125 {
1126 char opcode0 = current();
1127 char opcode1 = tolower(next());
1128
1129 register char hash;
1130 if ((hash = offset_table_c[opcode0 - CHAR_MIN]))
1131 {
1132 hash += opcode1;
1133 if (
1134 #if (CHAR_MIN < 0)
1135 hash >= 0 &&
1136 #endif
1137 hash < 39)
1138 {
1139 int index = static_cast<int>(static_cast<unsigned char>(hash));
1140 entry_st entry = symbol_name_table_c[index];
1141 if (entry.opcode[0] == opcode0 && entry.opcode[1] == opcode1
1142 && (opcode1 == current() || entry.opcode[2] == '='))
1143 {
1144 char const* p = entry.symbol_name;
1145 if (!strncmp("operator", p, 8))
1146 p += 8;
1147 if (*p == ' ')
1148 ++p;
1149 if (entry.unary)
1150 output += p;
1151 bool is_eq = (opcode1 != current());
1152 eat_current();
1153 output += '(';
1154 if (!decode_expression(output))
1155 _GLIBCPP_DEMANGLER_FAILURE;
1156 output += ')';
1157 if (!entry.unary)
1158 {
1159 output += ' ';
1160 output += p;
1161 if (is_eq)
1162 output += '=';
1163 output += ' ';
1164 output += '(';
1165 if (!decode_expression(output))
1166 _GLIBCPP_DEMANGLER_FAILURE;
1167 output += ')';
1168 }
1169 _GLIBCPP_DEMANGLER_RETURN;
1170 }
1171 }
1172 }
1173 }
1174 _GLIBCPP_DEMANGLER_FAILURE;
1175 }
1176
1177 //
1178 // <template-args> ::= I <template-arg>+ E
1179 // <template-arg> ::= <type> # type or template
1180 // ::= L <type> <value number> E # literal
1181 // ::= L_Z <encoding> E # external name
1182 // ::= X <expression> E # expression
1183 template<typename Allocator>
1184 bool
1185 session<Allocator>::decode_template_args(string_type& output)
1186 {
1187 _GLIBCPP_DEMANGLER_DOUT_ENTERING("decode_template_args");
1188 if (eat_current() != 'I')
1189 _GLIBCPP_DEMANGLER_FAILURE;
1190 int prev_size = M_template_arg_pos.size();
1191 ++M_inside_template_args;
1192 if (M_template_args_need_space)
1193 {
1194 output += ' ';
1195 M_template_args_need_space = false;
1196 }
1197 output += '<';
1198 for(;;)
1199 {
1200 if (M_inside_template_args == 1 && !M_inside_type)
1201 M_template_arg_pos.push_back(M_pos);
1202 if (current() == 'X')
1203 {
1204 eat_current();
1205 if (!decode_expression(output))
1206 _GLIBCPP_DEMANGLER_FAILURE;
1207 if (current() != 'E')
1208 _GLIBCPP_DEMANGLER_FAILURE;
1209 eat_current();
1210 }
1211 else if (current() == 'L')
1212 {
1213 if (!decode_literal(output))
1214 _GLIBCPP_DEMANGLER_FAILURE;
1215 if (current() != 'E')
1216 _GLIBCPP_DEMANGLER_FAILURE;
1217 eat_current();
1218 }
1219 else if (!decode_type(output))
1220 _GLIBCPP_DEMANGLER_FAILURE;
1221 if (current() == 'E')
1222 break;
1223 output += ", ";
1224 }
1225 eat_current();
1226 if (*(output.rbegin()) == '>')
1227 output += ' ';
1228 output += '>';
1229 --M_inside_template_args;
1230 if (!M_inside_template_args && !M_inside_type)
1231 {
1232 M_name_is_template = true;
1233 M_template_arg_pos_offset = prev_size;
1234 }
1235 _GLIBCPP_DEMANGLER_RETURN;
1236 }
1237
1238 // <bare-function-type> ::=
1239 // <signature type>+ # types are parameter types
1240 //
1241 template<typename Allocator>
1242 bool
1243 session<Allocator>::decode_bare_function_type(string_type& output)
1244 {
1245 _GLIBCPP_DEMANGLER_DOUT_ENTERING("decode_bare_function_type");
1246 if (M_saw_destructor)
1247 {
1248 if (eat_current() != 'v' || (current() != 'E' && current() != 0))
1249 _GLIBCPP_DEMANGLER_FAILURE;
1250 output += "()";
1251 M_saw_destructor = false;
1252 _GLIBCPP_DEMANGLER_RETURN;
1253 }
1254 #ifndef _GLIBCPP_DEMANGLER_STYLE_VOID
1255 if (current() == 'v')
1256 {
1257 eat_current();
1258 if (current() != 'E' && current() != 0)
1259 _GLIBCPP_DEMANGLER_FAILURE;
1260 output += "()";
1261 M_saw_destructor = false;
1262 _GLIBCPP_DEMANGLER_RETURN;
1263 }
1264 #endif
1265 output += '(';
1266 M_template_args_need_space = false;
1267 if (!decode_type(output)) // Must have at least one parameter.
1268 _GLIBCPP_DEMANGLER_FAILURE;
1269 while (current() != 'E' && current() != 0)
1270 {
1271 output += ", ";
1272 if (!decode_type(output))
1273 _GLIBCPP_DEMANGLER_FAILURE;
1274 }
1275 output += ')';
1276 _GLIBCPP_DEMANGLER_RETURN;
1277 }
1278
1279 // <type> ::=
1280 // <builtin-type> # Starts with a lower case character != r.
1281 // <function-type> # Starts with F
1282 // <class-enum-type> # Starts with N, S, C, D, Z, a digit or a lower
1283 // # case character. Since a lower case character
1284 // # would be an operator name, that would be an
1285 // # error. The S is a substitution or St
1286 // # (::std::). A 'C' would be a constructor and
1287 // # thus also an error.
1288 // <template-param> # Starts with T
1289 // <substitution> # Starts with S
1290 // <template-template-param> <template-args> # Starts with T or S,
1291 // # equivalent with the above.
1292 //
1293 // <array-type> # Starts with A
1294 // <pointer-to-member-type> # Starts with M
1295 // <CV-qualifiers> <type> # Starts with r, V or K
1296 // P <type> # pointer-to # Starts with P
1297 // R <type> # reference-to # Starts with R
1298 // C <type> # complex (C 2000) # Starts with C
1299 // G <type> # imaginary (C 2000)# Starts with G
1300 // U <source-name> <type> # vendor extended type qualifier,
1301 // # starts with U
1302 //
1303 // <template-template-param> ::= <template-param>
1304 // ::= <substitution>
1305
1306 // My own analysis of how to decode qualifiers:
1307 //
1308 // F is a <function-type>, <T> is a <builtin-type>, <class-enum-type>,
1309 // <template-param> or <template-template-param> <template-args>.
1310 // <Q> represents a series of qualifiers (not G or C).
1311 // <C> is an unqualified type.
1312 // <R> is a qualified type.
1313 // <B> is the bare-function-type without return type.
1314 // <I> is the array index.
1315 // Substitutions:
1316 // <Q>M<C><Q2>F<R><B>E ==> R (C::*Q)B Q2 "<C>", "F<R><B>E"
1317 // (<R> and <B> recursive),
1318 // "M<C><Q2>F<R><B>E".
1319 // <Q>F<R><B>E ==> R (Q)B "<R>", "<B>" (<B> recursive)
1320 // and "F<R><B>E".
1321 //
1322 // Note that if <R> has postfix qualifiers (an array), then those
1323 // are added AFTER the (member) function type. For example:
1324 // <Q>FPA<R><B>E ==> R (*(Q)B) [], where the PA added the prefix
1325 // "(*" and the postfix ") []".
1326 //
1327 // <Q>G<T> ==> imaginary T Q "<T>", "G<T>" (<T> recursive).
1328 // <Q>C<T> ==> complex T Q "<T>", "C<T>" (<T> recursive).
1329 // <Q><T> ==> T Q "<T>" (<T> recursive).
1330 //
1331 // where <Q> is any of:
1332 //
1333 // <Q>P ==> *Q "P..."
1334 // <Q>R ==> &Q "R..."
1335 // <Q>[K|V|r]+ ==> [ const| volatile| restrict]+Q "KVr..."
1336 // <Q>U<S> ==> SQ "U<S>..."
1337 // <Q>M<C> ==> C::*Q "M<C>..." (<C> recurs.)
1338 // A<I> ==> [I] "A<I>..." (<I> recurs.)
1339 // <Q>A<I> ==> (Q) [I] "A<I>..." (<I> recurs.)
1340 // Note that when <Q> ends on an A<I2> then the brackets are omitted:
1341 // A<I2>A<I> ==> [I2][I]
1342 //
1343 // A <substitution> is handled with an input position switch during which
1344 // new substitutions are turned off. Because recursive handling of types
1345 // (and therefore the order in which substitutions must be generated) must
1346 // be done left to right, but the generation of Q needs processing right to
1347 // left, substitutions per <type> are generated by reading the input left
1348 // to right and marking the starts of all substitutions only - implicitly
1349 // finishing them at the end of the type. Then the output and real
1350 // substitutions are generated.
1351 //
1352 // The following comment was for the demangling of g++ version 3.0.x. The
1353 // mangling (and I believe even the ABI description) have been fixed now
1354 // (as of g++ version 3.1).
1355 //
1356 // g++ 3.0.x only:
1357 // The ABI specifies for pointer-to-member function types the format
1358 // <Q>M<T>F<R><B>E. In other words, the qualifier <Q2> (see above) is
1359 // implicitely contained in <T> instead of explicitly part of the M format.
1360 // I am convinced that this is a bug in the ABI. Unfortunately, this is
1361 // how we have to demangle things as it has a direct impact on the order
1362 // in which substitutions are stored. This ill-formed design results in
1363 // rather ill-formed demangler code too however :/
1364 //
1365 // <Q2> is now explicitely part of the M format.
1366 // For some weird reason, g++ (3.2.1) does not add substitutions for
1367 // qualified member function pointers. I think that is another bug.
1368 //
1369 template<typename Allocator>
1370 void
1371 qualifier_list<Allocator>::decode_qualifiers(
1372 string_type& prefix,
1373 string_type& postfix,
1374 bool member_function_pointer_qualifiers = false)
1375 {
1376 for(typename std::vector<qualifier<Allocator>, Allocator>::
1377 reverse_iterator iter = M_qualifier_starts.rbegin();
1378 iter != M_qualifier_starts.rend();)
1379 {
1380 if (!member_function_pointer_qualifiers
1381 && !(*iter).part_of_substitution())
1382 {
1383 int saved_inside_substitution = M_demangler.M_inside_substitution;
1384 M_demangler.M_inside_substitution = 0;
1385 M_demangler.add_substitution((*iter).start_pos(), type);
1386 M_demangler.M_inside_substitution = saved_inside_substitution;
1387 }
1388 char qualifier_char = (*iter).first_qualifier();
1389 for(; qualifier_char; qualifier_char = (*iter).next_qualifier())
1390 {
1391 switch(qualifier_char)
1392 {
1393 case 'P':
1394 prefix += "*";
1395 break;
1396 case 'R':
1397 prefix += "&";
1398 break;
1399 case 'K':
1400 prefix += " const";
1401 continue;
1402 case 'V':
1403 prefix += " volatile";
1404 continue;
1405 case 'r':
1406 prefix += " restrict";
1407 continue;
1408 case 'A':
1409 {
1410 string_type index = (*iter).optional_type();
1411 if (++iter != M_qualifier_starts.rend()
1412 && (*iter).first_qualifier() != 'A')
1413 {
1414 prefix += " (";
1415 postfix = ") [" + index + "]" + postfix;
1416 }
1417 else
1418 postfix = "[" + index + "]" + postfix;
1419 break;
1420 }
1421 case 'M':
1422 prefix += " ";
1423 prefix += (*iter).optional_type();
1424 prefix += "::*";
1425 break;
1426 case 'U':
1427 prefix += " ";
1428 prefix += (*iter).optional_type();
1429 break;
1430 case 'G': // Only here so we added a substitution.
1431 break;
1432 }
1433 break;
1434 }
1435 if (qualifier_char != 'A')
1436 ++iter;
1437 }
1438 M_printing_suppressed = false;
1439 }
1440
1441 //
1442 template<typename Allocator>
1443 bool
1444 session<Allocator>::decode_type_with_postfix(
1445 string_type& prefix, string_type& postfix,
1446 qualifier_list<Allocator>* qualifiers)
1447 {
1448 _GLIBCPP_DEMANGLER_DOUT_ENTERING2
1449 (qualifiers ? "decode_type" : "decode_type[with qualifiers]");
1450 ++M_inside_type;
1451 bool recursive_template_param_or_substitution_call;
1452 if (!(recursive_template_param_or_substitution_call = qualifiers))
1453 qualifiers = new qualifier_list<Allocator>(*this);
1454 // First eat all qualifiers.
1455 bool failure = false;
1456 for(;;) // So we can use 'continue' to eat the next qualifier.
1457 {
1458 int start_pos = M_pos;
1459 switch(current())
1460 {
1461 case 'P':
1462 qualifiers->add_qualifier_start(pointer, start_pos,
1463 M_inside_substitution);
1464 eat_current();
1465 continue;
1466 case 'R':
1467 qualifiers->add_qualifier_start(reference, start_pos,
1468 M_inside_substitution);
1469 eat_current();
1470 continue;
1471 case 'K':
1472 case 'V':
1473 case 'r':
1474 {
1475 char c;
1476 int count = 0;
1477 do
1478 {
1479 ++count;
1480 c = next();
1481 }
1482 while(c == 'K' || c == 'V' || c == 'r');
1483 qualifiers->add_qualifier_start(cv_qualifier, start_pos, count,
1484 M_inside_substitution);
1485 continue;
1486 }
1487 case 'U':
1488 {
1489 eat_current();
1490 string_type source_name;
1491 if (!decode_source_name(source_name))
1492 {
1493 failure = true;
1494 break;
1495 }
1496 qualifiers->add_qualifier_start(vendor_extension, start_pos,
1497 source_name, M_inside_substitution);
1498 continue;
1499 }
1500 case 'A':
1501 {
1502 // <array-type> ::= A <positive dimension number> _ <element type>
1503 // ::= A [<dimension expression>] _ <element type>
1504 //
1505 string_type index;
1506 int saved_pos;
1507 store(saved_pos);
1508 if (next() == 'n' || !decode_number(index))
1509 {
1510 restore(saved_pos);
1511 if (next() != '_' && !decode_expression(index))
1512 {
1513 failure = true;
1514 break;
1515 }
1516 }
1517 if (eat_current() != '_')
1518 {
1519 failure = true;
1520 break;
1521 }
1522 qualifiers->add_qualifier_start(array, start_pos, index,
1523 M_inside_substitution);
1524 continue;
1525 }
1526 case 'M':
1527 {
1528 // <Q>M<C> or <Q>M<C><Q2>F<R><B>E
1529 eat_current();
1530 string_type class_type;
1531 if (!decode_type(class_type)) // Substitution: "<C>".
1532 {
1533 failure = true;
1534 break;
1535 }
1536 char c = current();
1537 if (c == 'F' || c == 'K' || c == 'V' || c == 'r')
1538 // Must be CV-qualifiers and a member function pointer.
1539 {
1540 // <Q>M<C><Q2>F<R><B>E ==> R (C::*Q)B Q2
1541 // substitutions: "<C>", "F<R><B>E" (<R> and <B>
1542 // recursive), "M<C><Q2>F<R><B>E".
1543 int count = 0;
1544 int Q2_start_pos = M_pos;
1545 while(c == 'K' || c == 'V' || c == 'r') // Decode <Q2>.
1546 {
1547 ++count;
1548 c = next();
1549 }
1550 qualifier_list<Allocator> class_type_qualifiers(*this);
1551 if (count)
1552 class_type_qualifiers.
1553 add_qualifier_start(cv_qualifier, Q2_start_pos,
1554 count, M_inside_substitution);
1555 string_type member_function_qualifiers;
1556 // It is unclear why g++ doesn't add a substitution for
1557 // "<Q2>F<R><B>E" as it should I think.
1558 string_type member_function_qualifiers_postfix;
1559 class_type_qualifiers.
1560 decode_qualifiers(member_function_qualifiers,
1561 member_function_qualifiers_postfix, true);
1562 member_function_qualifiers +=
1563 member_function_qualifiers_postfix;
1564 // I don't think this substitution is actually ever used.
1565 int function_pos = M_pos;
1566 if (eat_current() != 'F')
1567 {
1568 failure = true;
1569 break;
1570 }
1571 // Return type.
1572 // Constructors, destructors and conversion operators don't
1573 // have a return type, but seem to never get here.
1574 if (!decode_type_with_postfix(prefix, postfix))
1575 // substitution: <R> recursive
1576 {
1577 failure = true;
1578 break;
1579 }
1580 prefix += " (";
1581 prefix += class_type;
1582 prefix += "::*";
1583 string_type bare_function_type;
1584 if (!decode_bare_function_type(bare_function_type)
1585 || eat_current() != 'E') // Substitution: <B> recursive.
1586 {
1587 failure = true;
1588 break;
1589 }
1590 // substitution: "F<R><B>E".
1591 add_substitution(function_pos, type);
1592 // substitution: "M<C><Q2>F<R><B>E".
1593 add_substitution(start_pos, type);
1594 // substitution: all qualified types if any.
1595 qualifiers->decode_qualifiers(prefix, postfix);
1596 prefix += ")";
1597 prefix += bare_function_type;
1598 prefix += member_function_qualifiers;
1599 goto decode_type_exit;
1600 }
1601 qualifiers->add_qualifier_start(pointer_to_member, start_pos,
1602 class_type, M_inside_substitution);
1603 continue;
1604 }
1605 default:
1606 break;
1607 }
1608 break;
1609 }
1610 if (!failure)
1611 {
1612 // <Q>G<T> ==> imaginary T Q
1613 // substitutions: "<T>", "G<T>" (<T> recursive).
1614 // <Q>C<T> ==> complex T Q
1615 // substitutions: "<T>", "C<T>" (<T> recursive).
1616 if (current() == 'C' || current() == 'G')
1617 {
1618 prefix += current() == 'C' ? "complex " : "imaginary ";
1619 qualifiers->add_qualifier_start(complex_or_imaginary, M_pos,
1620 M_inside_substitution);
1621 eat_current();
1622 }
1623 int start_pos = M_pos;
1624 switch(current())
1625 {
1626 case 'F':
1627 {
1628 // <Q>F<R><B>E ==> R (Q)B
1629 // substitution: "<R>", "<B>" (<B> recursive) and "F<R><B>E".
1630 eat_current();
1631 // Return type.
1632 if (!decode_type_with_postfix(prefix, postfix))
1633 // Substitution: "<R>".
1634 {
1635 failure = true;
1636 break;
1637 }
1638 // Only array (pointer) types have a postfix.
1639 // In that case we don't want the space but
1640 // expect something like prefix is "int (*"
1641 // and postfix is ") [1]".
1642 if (postfix.size() == 0)
1643 prefix += ' ';
1644 prefix += '(';
1645 string_type bare_function_type;
1646 if (!decode_bare_function_type(bare_function_type)
1647 // substitution: "<B>" (<B> recursive).
1648 || eat_current() != 'E')
1649 {
1650 failure = true;
1651 break;
1652 }
1653 add_substitution(start_pos, type); // Substitution: "F<R><B>E".
1654 qualifiers->decode_qualifiers(prefix, postfix);
1655 // substitution: all qualified types, if any.
1656 prefix += ")";
1657 prefix += bare_function_type;
1658 break;
1659 }
1660 case 'T':
1661 if (!decode_template_param(prefix, qualifiers))
1662 {
1663 failure = true;
1664 break;
1665 }
1666 if (current() == 'I')
1667 {
1668 add_substitution(start_pos, template_template_param);
1669 // substitution: "<template-template-param>".
1670 if (!decode_template_args(prefix))
1671 {
1672 failure = true;
1673 break;
1674 }
1675 }
1676 if (!recursive_template_param_or_substitution_call
1677 && qualifiers->suppressed())
1678 {
1679 add_substitution(start_pos, type);
1680 // substitution: "<template-param>" or
1681 // "<template-template-param> <template-args>".
1682 qualifiers->decode_qualifiers(prefix, postfix);
1683 // substitution: all qualified types, if any.
1684 }
1685 break;
1686 case 'S':
1687 if (M_pos >= M_maxpos)
1688 {
1689 failure = true;
1690 break;
1691 }
1692 if (M_str[M_pos + 1] != 't')
1693 {
1694 if (!decode_substitution(prefix, qualifiers))
1695 {
1696 failure = true;
1697 break;
1698 }
1699 if (current() == 'I')
1700 {
1701 if (!decode_template_args(prefix))
1702 {
1703 failure = true;
1704 break;
1705 }
1706 if (!recursive_template_param_or_substitution_call
1707 && qualifiers->suppressed())
1708 add_substitution(start_pos, type);
1709 // Substitution:
1710 // "<template-template-param> <template-args>".
1711 }
1712 if (!recursive_template_param_or_substitution_call
1713 && qualifiers->suppressed())
1714 qualifiers->decode_qualifiers(prefix, postfix);
1715 // Substitution: all qualified types, if any.
1716 break;
1717 }
1718 /* Fall-through for St */
1719 case 'N':
1720 case 'Z':
1721 case '0':
1722 case '1':
1723 case '2':
1724 case '3':
1725 case '4':
1726 case '5':
1727 case '6':
1728 case '7':
1729 case '8':
1730 case '9':
1731 // <Q><T> ==> T Q
1732 // substitutions: "<T>" (<T> recursive).
1733 if (!decode_class_enum_type(prefix))
1734 {
1735 failure = true;
1736 break;
1737 }
1738 if (!recursive_template_param_or_substitution_call)
1739 {
1740 add_substitution(start_pos, type);
1741 // substitution: "<class-enum-type>".
1742 qualifiers->decode_qualifiers(prefix, postfix);
1743 // substitution: all qualified types, if any.
1744 }
1745 else
1746 qualifiers->printing_suppressed();
1747 break;
1748 default:
1749 // <Q><T> ==> T Q
1750 // substitutions: "<T>" (<T> recursive).
1751 if (!decode_builtin_type(prefix))
1752 {
1753 failure = true;
1754 break;
1755 }
1756 // If decode_type was called from decode_template_param then we
1757 // need to suppress calling qualifiers here in order to get a
1758 // substitution added anyway (for the <template-param>).
1759 if (!recursive_template_param_or_substitution_call)
1760 qualifiers->decode_qualifiers(prefix, postfix);
1761 else
1762 qualifiers->printing_suppressed();
1763 break;
1764 }
1765 }
1766 decode_type_exit:
1767 --M_inside_type;
1768 if (!recursive_template_param_or_substitution_call)
1769 delete qualifiers;
1770 if (failure)
1771 _GLIBCPP_DEMANGLER_FAILURE;
1772 _GLIBCPP_DEMANGLER_RETURN2;
1773 }
1774
1775 // <nested-name> ::= N [<CV-qualifiers>] <prefix> <unqualified-name> E
1776 // ::= N [<CV-qualifiers>] <template-prefix> <template-args> E
1777 //
1778 // <prefix> ::= <prefix> <unqualified-name>
1779 // ::= <template-prefix> <template-args>
1780 // ::= # empty
1781 // ::= <substitution>
1782 //
1783 // <template-prefix> ::= <prefix> <template unqualified-name>
1784 // ::= <substitution>
1785 //
1786 template<typename Allocator>
1787 bool
1788 session<Allocator>::decode_nested_name(string_type& output,
1789 string_type& qualifiers)
1790 {
1791 _GLIBCPP_DEMANGLER_DOUT_ENTERING("decode_nested_name");
1792
1793 if (current() != 'N' || M_pos >= M_maxpos)
1794 _GLIBCPP_DEMANGLER_FAILURE;
1795
1796 // <CV-qualifiers> ::= [r] [V] [K] # restrict (C99), volatile, const
1797 char const* qualifiers_start = &M_str[M_pos + 1];
1798 for (char c = next(); c == 'K' || c == 'V' || c == 'r'; c = next());
1799 for (char const* qualifier_ptr = &M_str[M_pos - 1];
1800 qualifier_ptr >= qualifiers_start; --qualifier_ptr)
1801 switch(*qualifier_ptr)
1802 {
1803 case 'K':
1804 qualifiers += " const";
1805 break;
1806 case 'V':
1807 qualifiers += " volatile";
1808 break;
1809 case 'r':
1810 qualifiers += " restrict";
1811 break;
1812 }
1813
1814 int number_of_prefixes = 0;
1815 int substitution_start = M_pos;
1816 for(;;)
1817 {
1818 ++number_of_prefixes;
1819 if (current() == 'S')
1820 {
1821 if (!decode_substitution(output))
1822 _GLIBCPP_DEMANGLER_FAILURE;
1823 }
1824 else if (current() == 'I')
1825 {
1826 if (!decode_template_args(output))
1827 _GLIBCPP_DEMANGLER_FAILURE;
1828 if (current() != 'E')
1829 {
1830 // substitution: "<template-prefix> <template-args>".
1831 add_substitution(substitution_start, nested_name_prefix,
1832 number_of_prefixes);
1833 }
1834 }
1835 else
1836 {
1837 if (!decode_unqualified_name(output))
1838 _GLIBCPP_DEMANGLER_FAILURE;
1839 if (current() != 'E')
1840 {
1841 // substitution: "<prefix> <unqualified-name>" or
1842 // "<prefix> <template unqualified-name>".
1843 add_substitution(substitution_start,
1844 (current() == 'I') ? nested_name_template_prefix
1845 : nested_name_prefix,
1846 number_of_prefixes);
1847 }
1848 }
1849 if (current() == 'E')
1850 {
1851 eat_current();
1852 _GLIBCPP_DEMANGLER_RETURN;
1853 }
1854 if (current() != 'I')
1855 output += "::";
1856 else if (M_template_args_need_space)
1857 output += ' ';
1858 M_template_args_need_space = false;
1859 }
1860 _GLIBCPP_DEMANGLER_FAILURE;
1861 }
1862
1863 // <local-name> := Z <function encoding> E <entity name> [<discriminator>]
1864 // := Z <function encoding> E s [<discriminator>]
1865 // <discriminator> := _ <non-negative number>
1866 //
1867 template<typename Allocator>
1868 bool
1869 session<Allocator>::decode_local_name(string_type& output)
1870 {
1871 _GLIBCPP_DEMANGLER_DOUT_ENTERING("decode_local_name");
1872 if (current() != 'Z' || M_pos >= M_maxpos)
1873 _GLIBCPP_DEMANGLER_FAILURE;
1874 if ((M_pos += decode_encoding(output, M_str + M_pos + 1,
1875 M_maxpos - M_pos) + 1) < 0 || eat_current() != 'E')
1876 _GLIBCPP_DEMANGLER_FAILURE;
1877 output += "::";
1878 if (current() == 's')
1879 {
1880 eat_current();
1881 output += "string literal";
1882 }
1883 else
1884 {
1885 string_type nested_name_qualifiers;
1886 if (!decode_name(output, nested_name_qualifiers))
1887 _GLIBCPP_DEMANGLER_FAILURE;
1888 output += nested_name_qualifiers;
1889 }
1890 string_type discriminator;
1891 if (current() == '_' && next() != 'n' && !decode_number(discriminator))
1892 _GLIBCPP_DEMANGLER_FAILURE;
1893 _GLIBCPP_DEMANGLER_RETURN;
1894 }
1895
1896 // <source-name> ::= <positive length number> <identifier>
1897 //
1898 template<typename Allocator>
1899 bool
1900 session<Allocator>::decode_source_name(string_type& output)
1901 {
1902 _GLIBCPP_DEMANGLER_DOUT_ENTERING("decode_source_name");
1903 int length = current() - '0';
1904 if (length < 1 || length > 9)
1905 _GLIBCPP_DEMANGLER_FAILURE;
1906 while(std::isdigit(next()))
1907 length = 10 * length + current() - '0';
1908 char const* ptr = &M_str[M_pos];
1909 if (length > 11 && !strncmp(ptr, "_GLOBAL_", 8) && ptr[9] == 'N'
1910 && ptr[8] == ptr[10])
1911 {
1912 output += "(anonymous namespace)";
1913 if ((M_pos += length) > M_maxpos + 1)
1914 _GLIBCPP_DEMANGLER_FAILURE;
1915 }
1916 else
1917 while(length--)
1918 {
1919 if (current() == 0)
1920 _GLIBCPP_DEMANGLER_FAILURE;
1921 output += eat_current();
1922 }
1923 _GLIBCPP_DEMANGLER_RETURN;
1924 }
1925
1926 // <unqualified-name> ::= <operator-name> # Starts with lower case.
1927 // ::= <ctor-dtor-name> # Starts with 'C' or 'D'.
1928 // ::= <source-name> # Starts with a digit.
1929 //
1930 template<typename Allocator>
1931 bool
1932 session<Allocator>::decode_unqualified_name(string_type& output)
1933 {
1934 _GLIBCPP_DEMANGLER_DOUT_ENTERING("decode_unqualified_name");
1935 if (std::isdigit(current()))
1936 {
1937 if (!M_inside_template_args)
1938 {
1939 bool recursive_unqualified_name = (&M_function_name == &output);
1940 // This can be a recursive call when we are decoding
1941 // an <operator-name> that is a cast operator for a some
1942 // <unqualified-name>; for example "operator Foo()".
1943 // In that case this is thus not a ctor or dtor and we
1944 // are not interested in updating M_function_name.
1945 if (!recursive_unqualified_name)
1946 M_function_name.clear();
1947 M_name_is_template = false;
1948 M_name_is_cdtor = false;
1949 M_name_is_conversion_operator = false;
1950 if (!decode_source_name(M_function_name))
1951 _GLIBCPP_DEMANGLER_FAILURE;
1952 if (!recursive_unqualified_name)
1953 output += M_function_name;
1954 }
1955 else if (!decode_source_name(output))
1956 _GLIBCPP_DEMANGLER_FAILURE;
1957 _GLIBCPP_DEMANGLER_RETURN;
1958 }
1959 if (islower(current()))
1960 {
1961 if (!M_inside_template_args)
1962 {
1963 M_function_name.clear();
1964 M_name_is_template = false;
1965 M_name_is_cdtor = false;
1966 M_name_is_conversion_operator = false;
1967 if (!decode_operator_name(M_function_name))
1968 _GLIBCPP_DEMANGLER_FAILURE;
1969 output += M_function_name;
1970 }
1971 _GLIBCPP_DEMANGLER_RETURN;
1972 }
1973 if (current() == 'C' || current() == 'D')
1974 {
1975 if (M_inside_template_args)
1976 _GLIBCPP_DEMANGLER_FAILURE;
1977 // <ctor-dtor-name> ::=
1978 // C1 # complete object (in-charge) constructor
1979 // C2 # base object (not-in-charge) constructor
1980 // C3 # complete object (in-charge) allocating constructor
1981 // D0 # deleting (in-charge) destructor
1982 // D1 # complete object (in-charge) destructor
1983 // D2 # base object (not-in-charge) destructor
1984 //
1985 if (current() == 'C')
1986 {
1987 char c = next();
1988 if (c < '1' || c > '3')
1989 _GLIBCPP_DEMANGLER_FAILURE;
1990 }
1991 else
1992 {
1993 char c = next();
1994 if (c < '0' || c > '2')
1995 _GLIBCPP_DEMANGLER_FAILURE;
1996 output += '~';
1997 M_saw_destructor = true;
1998 }
1999 M_name_is_cdtor = true;
2000 eat_current();
2001 output += M_function_name;
2002 _GLIBCPP_DEMANGLER_RETURN;
2003 }
2004 _GLIBCPP_DEMANGLER_FAILURE;
2005 }
2006
2007 // <unscoped-name> ::=
2008 // <unqualified-name> # Starts not with an 'S'
2009 // St <unqualified-name> # ::std::
2010 //
2011 template<typename Allocator>
2012 bool
2013 session<Allocator>::decode_unscoped_name(string_type& output)
2014 {
2015 _GLIBCPP_DEMANGLER_DOUT_ENTERING("decode_unscoped_name");
2016 if (current() == 'S')
2017 {
2018 if (next() != 't')
2019 _GLIBCPP_DEMANGLER_FAILURE;
2020 eat_current();
2021 output += "std::";
2022 }
2023 decode_unqualified_name(output);
2024 _GLIBCPP_DEMANGLER_RETURN;
2025 }
2026
2027 // <name> ::=
2028 // <nested-name> # Starts with 'N'
2029 // <unscoped-template-name> <template-args> # idem
2030 // <local-name> # Starts with 'Z'
2031 // <unscoped-name> # Starts with 'S', 'C', 'D',
2032 // # a digit or a lower case
2033 // # character.
2034 //
2035 // <unscoped-template-name> ::= <unscoped-name>
2036 // ::= <substitution>
2037 template<typename Allocator>
2038 bool
2039 session<Allocator>::decode_name(string_type& output,
2040 string_type& nested_name_qualifiers)
2041 {
2042 _GLIBCPP_DEMANGLER_DOUT_ENTERING("decode_name");
2043 int substitution_start = M_pos;
2044 if (current() == 'S' && (M_pos >= M_maxpos || M_str[M_pos + 1] != 't'))
2045 {
2046 if (!decode_substitution(output))
2047 _GLIBCPP_DEMANGLER_FAILURE;
2048 }
2049 else if (current() == 'N')
2050 {
2051 decode_nested_name(output, nested_name_qualifiers);
2052 _GLIBCPP_DEMANGLER_RETURN;
2053 }
2054 else if (current() == 'Z')
2055 {
2056 decode_local_name(output);
2057 _GLIBCPP_DEMANGLER_RETURN;
2058 }
2059 else if (!decode_unscoped_name(output))
2060 _GLIBCPP_DEMANGLER_FAILURE;
2061 if (current() == 'I')
2062 {
2063 // Must have been an <unscoped-template-name>.
2064 add_substitution(substitution_start, unscoped_template_name);
2065 if (!decode_template_args(output))
2066 _GLIBCPP_DEMANGLER_FAILURE;
2067 }
2068 M_template_args_need_space = false;
2069 _GLIBCPP_DEMANGLER_RETURN;
2070 }
2071
2072 // <call-offset> ::= h <nv-offset> _
2073 // ::= v <v-offset> _
2074 // <nv-offset> ::= <offset number>
2075 // non-virtual base override
2076 //
2077 // <v-offset> ::= <offset number> _ <virtual offset number>
2078 // virtual base override, with vcall offset
2079 template<typename Allocator>
2080 bool
2081 session<Allocator>::decode_call_offset(string_type&
2082 #if _GLIBCPP_DEMANGLER_CWDEBUG
2083 output
2084 #endif
2085 )
2086 {
2087 _GLIBCPP_DEMANGLER_DOUT_ENTERING("decode_call_offset");
2088 if (current() == 'h')
2089 {
2090 string_type dummy;
2091 eat_current();
2092 if (decode_number(dummy) && current() == '_')
2093 {
2094 eat_current();
2095 _GLIBCPP_DEMANGLER_RETURN;
2096 }
2097 }
2098 else if (current() == 'v')
2099 {
2100 string_type dummy;
2101 eat_current();
2102 if (decode_number(dummy) && current() == '_')
2103 {
2104 eat_current();
2105 if (decode_number(dummy) && current() == '_')
2106 {
2107 eat_current();
2108 _GLIBCPP_DEMANGLER_RETURN;
2109 }
2110 }
2111 }
2112 _GLIBCPP_DEMANGLER_FAILURE;
2113 }
2114
2115 //
2116 // <special-name> ::=
2117 // TV <type> # virtual table
2118 // TT <type> # VTT structure (construction
2119 // vtable index).
2120 // TI <type> # typeinfo structure
2121 // TS <type> # typeinfo name (null-terminated
2122 // byte string).
2123 // GV <object name> # Guard variable for one-time
2124 // initialization of static objects in
2125 // a local scope.
2126 // T <call-offset> <base encoding># base is the nominal target function
2127 // of thunk.
2128 // Tc <call-offset> <call-offset> <base encoding> # base is the nominal
2129 // target function of thunk; first
2130 // call-offset is 'this' adjustment;
2131 // second call-offset is result
2132 // adjustment
2133 //
2134 template<typename Allocator>
2135 bool
2136 session<Allocator>::decode_special_name(string_type& output)
2137 {
2138 _GLIBCPP_DEMANGLER_DOUT_ENTERING("decode_special_name");
2139 if (current() == 'G')
2140 {
2141 if (next() != 'V')
2142 _GLIBCPP_DEMANGLER_FAILURE;
2143 output += "guard variable for ";
2144 string_type nested_name_qualifiers;
2145 eat_current();
2146 if (!decode_name(output, nested_name_qualifiers))
2147 _GLIBCPP_DEMANGLER_FAILURE;
2148 output += nested_name_qualifiers;
2149 _GLIBCPP_DEMANGLER_RETURN;
2150 }
2151 else if (current() != 'T')
2152 _GLIBCPP_DEMANGLER_FAILURE;
2153 switch(next())
2154 {
2155 case 'V':
2156 output += "vtable for ";
2157 eat_current();
2158 decode_type(output);
2159 _GLIBCPP_DEMANGLER_RETURN;
2160 case 'T':
2161 output += "VTT for ";
2162 eat_current();
2163 decode_type(output);
2164 _GLIBCPP_DEMANGLER_RETURN;
2165 case 'I':
2166 output += "typeinfo for ";
2167 eat_current();
2168 decode_type(output);
2169 _GLIBCPP_DEMANGLER_RETURN;
2170 case 'S':
2171 output += "typeinfo name for ";
2172 eat_current();
2173 decode_type(output);
2174 _GLIBCPP_DEMANGLER_RETURN;
2175 case 'c':
2176 output += "covariant return thunk to ";
2177 if (!decode_call_offset(output)
2178 || !decode_call_offset(output)
2179 || (M_pos += decode_encoding(output, M_str + M_pos,
2180 M_maxpos - M_pos + 1)) < 0)
2181 _GLIBCPP_DEMANGLER_FAILURE;
2182 _GLIBCPP_DEMANGLER_RETURN;
2183 case 'C': // GNU extension?
2184 {
2185 string_type first;
2186 output += "construction vtable for ";
2187 eat_current();
2188 if (!decode_type(first))
2189 _GLIBCPP_DEMANGLER_FAILURE;
2190 while(std::isdigit(current()))
2191 eat_current();
2192 if (eat_current() != '_')
2193 _GLIBCPP_DEMANGLER_FAILURE;
2194 if (!decode_type(output))
2195 _GLIBCPP_DEMANGLER_FAILURE;
2196 output += "-in-";
2197 output += first;
2198 _GLIBCPP_DEMANGLER_RETURN;
2199 }
2200 default:
2201 if (current() == 'v')
2202 output += "virtual thunk to ";
2203 else
2204 output += "non-virtual thunk to ";
2205 if (!decode_call_offset(output)
2206 || (M_pos += decode_encoding(output, M_str + M_pos,
2207 M_maxpos - M_pos + 1)) < 0)
2208 _GLIBCPP_DEMANGLER_FAILURE;
2209 _GLIBCPP_DEMANGLER_RETURN;
2210 }
2211 }
2212
2213 // <encoding> ::=
2214 // <function name> <bare-function-type> # Starts with 'C', 'D', 'N',
2215 // 'S', a digit or a lower case
2216 // character.
2217 // <data name> # Idem.
2218 // <special-name> # Starts with 'T' or 'G'.
2219 template<typename Allocator>
2220 int
2221 session<Allocator>::decode_encoding(string_type& output,
2222 char const* in,
2223 int len)
2224 {
2225 #if _GLIBCPP_DEMANGLER_CWDEBUG
2226 _GLIBCPP_DEMANGLER_DOUT(dc::demangler,
2227 "Output thus far: \"" << output << '"');
2228 string_type input(in, len > 0x40000000 ? strlen(in) : len);
2229 _GLIBCPP_DEMANGLER_DOUT(
2230 dc::demangler, "Entering decode_encoding(\"" << input << "\")");
2231 #endif
2232 if (len <= 0)
2233 return INT_MIN;
2234 session<Allocator> demangler_session(in, len);
2235 string_type nested_name_qualifiers;
2236 int saved_pos;
2237 demangler_session.store(saved_pos);
2238 if (demangler_session.decode_special_name(output))
2239 return demangler_session.M_pos;
2240 demangler_session.restore(saved_pos);
2241 string_type name;
2242 if (!demangler_session.decode_name(name, nested_name_qualifiers))
2243 return INT_MIN;
2244 if (demangler_session.current() == 0
2245 || demangler_session.current() == 'E')
2246 {
2247 output += name;
2248 output += nested_name_qualifiers;
2249 return demangler_session.M_pos;
2250 }
2251 // Must have been a <function name>.
2252 if (demangler_session.M_name_is_template
2253 && !(demangler_session.M_name_is_cdtor
2254 || demangler_session.M_name_is_conversion_operator))
2255 {
2256 if (!demangler_session.decode_type(output))
2257 // Return type of function
2258 return INT_MIN;
2259 output += ' ';
2260 }
2261 output += name;
2262 if (!demangler_session.decode_bare_function_type(output))
2263 return INT_MIN;
2264 output += nested_name_qualifiers;
2265 return demangler_session.M_pos;
2266 }
2267
2268 } // namespace demangler
2269
2270 // Public interface
2271 template<typename Allocator>
2272 struct demangle
2273 {
2274 typedef Allocator allocator_type;
2275 typedef std::basic_string<char, std::char_traits<char>, Allocator>
2276 string_type;
2277 static string_type symbol(char const* in);
2278 static string_type type(char const* in);
2279 };
2280
2281 // demangle::symbol()
2282 //
2283 // Demangle `input' which should be a mangled function name as for
2284 // instance returned by nm(1).
2285 template<typename Allocator>
2286 std::basic_string<char, std::char_traits<char>, Allocator>
2287 demangle<Allocator>::symbol(char const* input)
2288 {
2289 // <mangled-name> ::= _Z <encoding>
2290 // <mangled-name> ::= _GLOBAL_ _<type>_ _Z <encoding>
2291 // <type> can be I or D (GNU extension)
2292 typedef demangler::session<Allocator> demangler_type;
2293 string_type result;
2294 bool failure = (input[0] != '_');
2295
2296 if (!failure)
2297 {
2298 if (input[1] == 'G')
2299 {
2300 if (!strncmp(input, "_GLOBAL__", 9)
2301 && (input[9] == 'D' || input[9] == 'I')
2302 && input[10] == '_' && input[11] == '_' && input[12] == 'Z')
2303 {
2304 if (input[9] == 'D')
2305 result.assign("global destructors keyed to ", 28);
2306 else
2307 result.assign("global constructors keyed to ", 29);
2308 int cnt = demangler_type::decode_encoding(result, input + 13,
2309 INT_MAX);
2310 if (cnt < 0 || input[cnt + 13] != 0)
2311 failure = true;
2312 }
2313 else
2314 failure = true;
2315 }
2316 else if (input[1] == 'Z')
2317 {
2318 int cnt = demangler_type::decode_encoding(result, input + 2,
2319 INT_MAX);
2320 if (cnt < 0 || input[cnt + 2] != 0)
2321 failure = true;
2322 }
2323 else
2324 failure = true;
2325 }
2326
2327 // Failure to demangle, return the mangled name.
2328 if (failure)
2329 result.assign(input, strlen(input));
2330
2331 return result;
2332 }
2333
2334 // demangle::type()
2335 // Demangle `input' which must be a zero terminated mangled type
2336 // name as for instance returned by std::type_info::name().
2337 template<typename Allocator>
2338 std::basic_string<char, std::char_traits<char>, Allocator>
2339 demangle<Allocator>::type(char const* input)
2340 {
2341 std::basic_string<char, std::char_traits<char>, Allocator> result;
2342 if (input == NULL)
2343 result = "(null)";
2344 else
2345 {
2346 demangler::session<Allocator> demangler_session(input, INT_MAX);
2347 if (!demangler_session.decode_type(result)
2348 || demangler_session.remaining_input_characters())
2349 {
2350 // Failure to demangle, return the mangled name.
2351 result = input;
2352 }
2353 }
2354 return result;
2355 }
2356
2357 } // namespace __gnu_cxx
2358
2359 #endif // __DEMANGLE_H
This page took 0.212148 seconds and 5 git commands to generate.