]> git.ipfire.org Git - thirdparty/gcc.git/blame - libstdc++-v3/include/bits/demangle.h
Move from CPP to CXX.
[thirdparty/gcc.git] / libstdc++-v3 / include / bits / demangle.h
CommitLineData
4ffbd077
BK
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
3d7c150e
BK
31#ifndef _DEMANGLER_H
32#define _DEMANGLER_H 1
4ffbd077
BK
33
34#include <limits>
35#include <vector>
36#include <string>
37#include <cctype>
38
3d7c150e
BK
39#ifndef _GLIBCXX_DEMANGLER_DEBUG
40#define _GLIBCXX_DEMANGLER_CWDEBUG 0
41#define _GLIBCXX_DEMANGLER_DEBUG(x)
42#define _GLIBCXX_DEMANGLER_DOUT(cntrl, data)
43#define _GLIBCXX_DEMANGLER_DOUT_ENTERING(x)
44#define _GLIBCXX_DEMANGLER_DOUT_ENTERING2(x)
45#define _GLIBCXX_DEMANGLER_RETURN \
4ffbd077 46 return M_result
3d7c150e 47#define _GLIBCXX_DEMANGLER_RETURN2 \
4ffbd077 48 return M_result
3d7c150e 49#define _GLIBCXX_DEMANGLER_FAILURE \
4ffbd077
BK
50 do { M_result = false; return false; } while(0)
51#else
3d7c150e 52#define _GLIBCXX_DEMANGLER_CWDEBUG 1
4ffbd077
BK
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
3d7c150e 58// _GLIBCXX_DEMANGLER_STYLE_VOID
4ffbd077
BK
59// Default behaviour: int f()
60// Uses (void) instead of (): int f(void)
61
3d7c150e 62// _GLIBCXX_DEMANGLER_STYLE_LITERAL
4ffbd077
BK
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
3d7c150e 68// _GLIBCXX_DEMANGLER_STYLE_LITERAL_INT
4ffbd077
BK
69// Default behaviour: 4
70// Use also an explicit cast for int in literals: (int)4
71
72namespace __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
1be4def3 175 get_start_pos(void) const
4ffbd077
BK
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&
1be4def3 190 get_optional_type(void) const
4ffbd077
BK
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;
3d7c150e 285#if _GLIBCXX_DEMANGLER_CWDEBUG
4ffbd077
BK
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)
3d7c150e 297#if _GLIBCXX_DEMANGLER_CWDEBUG
4ffbd077
BK
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>
3d7c150e 376#if !_GLIBCXX_DEMANGLER_CWDEBUG
4ffbd077
BK
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 {
3d7c150e 386#if _GLIBCXX_DEMANGLER_CWDEBUG
4ffbd077
BK
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));
3d7c150e 393#if _GLIBCXX_DEMANGLER_CWDEBUG
4ffbd077
BK
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;
3d7c150e 406 _GLIBCXX_DEMANGLER_DEBUG( dc::demangler.off() );
4ffbd077
BK
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;
3d7c150e
BK
440 _GLIBCXX_DEMANGLER_DEBUG( dc::demangler.on() );
441 _GLIBCXX_DEMANGLER_DOUT(dc::demangler,
4ffbd077
BK
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 {
3d7c150e 490 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_number");
4ffbd077
BK
491 if (current() != 'n')
492 decode_decimal_integer(output);
493 else
494 {
495 output += '-';
496 eat_current();
497 decode_decimal_integer(output);
498 }
3d7c150e 499 _GLIBCXX_DEMANGLER_RETURN;
4ffbd077
BK
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 {
3d7c150e 560 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_builtin_type");
4ffbd077
BK
561 char const* bt;
562 if (!islower(current()) || !(bt = builtin_type_c[current() - 'a']))
3d7c150e 563 _GLIBCXX_DEMANGLER_FAILURE;
4ffbd077
BK
564 output += bt;
565 eat_current();
3d7c150e 566 _GLIBCXX_DEMANGLER_RETURN;
4ffbd077
BK
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 {
3d7c150e 575 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_class_enum_type");
4ffbd077
BK
576 string_type nested_name_qualifiers;
577 if (!decode_name(output, nested_name_qualifiers))
3d7c150e 578 _GLIBCXX_DEMANGLER_FAILURE;
4ffbd077 579 output += nested_name_qualifiers;
3d7c150e 580 _GLIBCXX_DEMANGLER_RETURN;
4ffbd077
BK
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 {
3d7c150e 604 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_substitution");
4ffbd077
BK
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();
3d7c150e 624 _GLIBCXX_DEMANGLER_RETURN;
4ffbd077
BK
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();
3d7c150e 639 _GLIBCXX_DEMANGLER_RETURN;
4ffbd077
BK
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();
3d7c150e 653 _GLIBCXX_DEMANGLER_RETURN;
4ffbd077
BK
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();
3d7c150e 666 _GLIBCXX_DEMANGLER_RETURN;
4ffbd077
BK
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();
3d7c150e 679 _GLIBCXX_DEMANGLER_RETURN;
4ffbd077
BK
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();
3d7c150e 692 _GLIBCXX_DEMANGLER_RETURN;
4ffbd077
BK
693 case 't':
694 output += "std";
695 eat_current();
696 if (qualifiers)
697 qualifiers->printing_suppressed();
3d7c150e 698 _GLIBCXX_DEMANGLER_RETURN;
4ffbd077
BK
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
3d7c150e 709 _GLIBCXX_DEMANGLER_FAILURE;
4ffbd077
BK
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.
3d7c150e 718 _GLIBCXX_DEMANGLER_FAILURE;
4ffbd077
BK
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))
3d7c150e 741 _GLIBCXX_DEMANGLER_FAILURE;
4ffbd077
BK
742 }
743 else
744 {
745 if (cnt < substitution.M_number_of_prefixes)
746 output += "::";
747 if (current() == 'S')
748 {
749 if (!decode_substitution(output))
3d7c150e 750 _GLIBCXX_DEMANGLER_FAILURE;
4ffbd077
BK
751 }
752 else if (!decode_unqualified_name(output))
3d7c150e 753 _GLIBCXX_DEMANGLER_FAILURE;
4ffbd077
BK
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;
3d7c150e 767 _GLIBCXX_DEMANGLER_RETURN;
4ffbd077
BK
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 {
3d7c150e 778 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_template_parameter");
4ffbd077 779 if (current() != 'T')
3d7c150e 780 _GLIBCXX_DEMANGLER_FAILURE;
4ffbd077
BK
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() != '_')
3d7c150e 793 _GLIBCXX_DEMANGLER_FAILURE;
4ffbd077
BK
794 value += M_template_arg_pos_offset;
795 if (value >= M_template_arg_pos.size())
3d7c150e 796 _GLIBCXX_DEMANGLER_FAILURE;
4ffbd077
BK
797 int saved_pos = M_pos;
798 M_pos = M_template_arg_pos[value];
799 if (M_inside_type > 20) // Rather than core dump.
3d7c150e 800 _GLIBCXX_DEMANGLER_FAILURE;
4ffbd077
BK
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;
3d7c150e 813 _GLIBCXX_DEMANGLER_RETURN;
4ffbd077
BK
814 }
815
816 template<typename Allocator>
817 bool
818 session<Allocator>::decode_literal(string_type& output)
819 {
3d7c150e 820 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_literal");
4ffbd077
BK
821 eat_current(); // Eat the 'L'.
822 if (current() == '_')
823 {
824 if (next() != 'Z')
3d7c150e 825 _GLIBCXX_DEMANGLER_FAILURE;
4ffbd077
BK
826 eat_current();
827 if ((M_pos += decode_encoding(output, M_str + M_pos,
828 M_maxpos - M_pos + 1)) < 0)
3d7c150e 829 _GLIBCXX_DEMANGLER_FAILURE;
4ffbd077
BK
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();
3d7c150e 841 _GLIBCXX_DEMANGLER_RETURN;
4ffbd077
BK
842 }
843 char c = current();
3d7c150e 844#ifdef _GLIBCXX_DEMANGLER_STYLE_LITERAL
4ffbd077
BK
845 if (c == 'i' || c == 'j' || c == 'l' ||
846 c == 'm' || c == 'x' || c == 'y')
847 eat_current();
848 else
849#else
3d7c150e 850#ifndef _GLIBCXX_DEMANGLER_STYLE_LITERAL_INT
4ffbd077
BK
851 if (c == 'i')
852 eat_current();
853 else
854#endif
855#endif
856 {
857 output += '(';
858 if (!decode_type(output))
3d7c150e 859 _GLIBCXX_DEMANGLER_FAILURE;
4ffbd077
BK
860 output += ')';
861 }
862 if (!decode_number(output))
3d7c150e
BK
863 _GLIBCXX_DEMANGLER_FAILURE;
864#ifdef _GLIBCXX_DEMANGLER_STYLE_LITERAL
4ffbd077
BK
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 }
3d7c150e 873 _GLIBCXX_DEMANGLER_RETURN;
4ffbd077
BK
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 {
3d7c150e 1043 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_operator_name");
4ffbd077
BK
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;
3d7c150e 1069 _GLIBCXX_DEMANGLER_RETURN;
4ffbd077
BK
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))
3d7c150e 1085 _GLIBCXX_DEMANGLER_FAILURE;
4ffbd077
BK
1086 if (!M_inside_template_args)
1087 M_name_is_conversion_operator = true;
3d7c150e 1088 _GLIBCXX_DEMANGLER_RETURN;
4ffbd077
BK
1089 }
1090 }
1091 }
3d7c150e 1092 _GLIBCXX_DEMANGLER_FAILURE;
4ffbd077
BK
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 {
3d7c150e 1108 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_expression");
4ffbd077
BK
1109 if (current() == 'T')
1110 {
1111 if (!decode_template_param(output))
3d7c150e
BK
1112 _GLIBCXX_DEMANGLER_FAILURE;
1113 _GLIBCXX_DEMANGLER_RETURN;
4ffbd077
BK
1114 }
1115 else if (current() == 'L')
1116 {
1117 if (!decode_literal(output))
3d7c150e 1118 _GLIBCXX_DEMANGLER_FAILURE;
4ffbd077 1119 if (current() != 'E')
3d7c150e 1120 _GLIBCXX_DEMANGLER_FAILURE;
4ffbd077 1121 eat_current();
3d7c150e 1122 _GLIBCXX_DEMANGLER_RETURN;
4ffbd077
BK
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))
3d7c150e 1155 _GLIBCXX_DEMANGLER_FAILURE;
4ffbd077
BK
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))
3d7c150e 1166 _GLIBCXX_DEMANGLER_FAILURE;
4ffbd077
BK
1167 output += ')';
1168 }
3d7c150e 1169 _GLIBCXX_DEMANGLER_RETURN;
4ffbd077
BK
1170 }
1171 }
1172 }
1173 }
3d7c150e 1174 _GLIBCXX_DEMANGLER_FAILURE;
4ffbd077
BK
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 {
3d7c150e 1187 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_template_args");
4ffbd077 1188 if (eat_current() != 'I')
3d7c150e 1189 _GLIBCXX_DEMANGLER_FAILURE;
4ffbd077
BK
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))
3d7c150e 1206 _GLIBCXX_DEMANGLER_FAILURE;
4ffbd077 1207 if (current() != 'E')
3d7c150e 1208 _GLIBCXX_DEMANGLER_FAILURE;
4ffbd077
BK
1209 eat_current();
1210 }
1211 else if (current() == 'L')
1212 {
1213 if (!decode_literal(output))
3d7c150e 1214 _GLIBCXX_DEMANGLER_FAILURE;
4ffbd077 1215 if (current() != 'E')
3d7c150e 1216 _GLIBCXX_DEMANGLER_FAILURE;
4ffbd077
BK
1217 eat_current();
1218 }
1219 else if (!decode_type(output))
3d7c150e 1220 _GLIBCXX_DEMANGLER_FAILURE;
4ffbd077
BK
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 }
3d7c150e 1235 _GLIBCXX_DEMANGLER_RETURN;
4ffbd077
BK
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 {
3d7c150e 1245 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_bare_function_type");
4ffbd077
BK
1246 if (M_saw_destructor)
1247 {
1248 if (eat_current() != 'v' || (current() != 'E' && current() != 0))
3d7c150e 1249 _GLIBCXX_DEMANGLER_FAILURE;
4ffbd077
BK
1250 output += "()";
1251 M_saw_destructor = false;
3d7c150e 1252 _GLIBCXX_DEMANGLER_RETURN;
4ffbd077 1253 }
3d7c150e 1254#ifndef _GLIBCXX_DEMANGLER_STYLE_VOID
4ffbd077
BK
1255 if (current() == 'v')
1256 {
1257 eat_current();
1258 if (current() != 'E' && current() != 0)
3d7c150e 1259 _GLIBCXX_DEMANGLER_FAILURE;
4ffbd077
BK
1260 output += "()";
1261 M_saw_destructor = false;
3d7c150e 1262 _GLIBCXX_DEMANGLER_RETURN;
4ffbd077
BK
1263 }
1264#endif
1265 output += '(';
1266 M_template_args_need_space = false;
1267 if (!decode_type(output)) // Must have at least one parameter.
3d7c150e 1268 _GLIBCXX_DEMANGLER_FAILURE;
4ffbd077
BK
1269 while (current() != 'E' && current() != 0)
1270 {
1271 output += ", ";
1272 if (!decode_type(output))
3d7c150e 1273 _GLIBCXX_DEMANGLER_FAILURE;
4ffbd077
BK
1274 }
1275 output += ')';
3d7c150e 1276 _GLIBCXX_DEMANGLER_RETURN;
4ffbd077
BK
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;
1be4def3 1385 M_demangler.add_substitution((*iter).get_start_pos(), type);
4ffbd077
BK
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 {
1be4def3 1410 string_type index = (*iter).get_optional_type();
4ffbd077
BK
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 += " ";
1be4def3 1423 prefix += (*iter).get_optional_type();
4ffbd077
BK
1424 prefix += "::*";
1425 break;
1426 case 'U':
1427 prefix += " ";
1be4def3 1428 prefix += (*iter).get_optional_type();
4ffbd077
BK
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 {
3d7c150e 1448 _GLIBCXX_DEMANGLER_DOUT_ENTERING2
4ffbd077
BK
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)
3d7c150e
BK
1771 _GLIBCXX_DEMANGLER_FAILURE;
1772 _GLIBCXX_DEMANGLER_RETURN2;
4ffbd077
BK
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 {
3d7c150e 1791 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_nested_name");
4ffbd077
BK
1792
1793 if (current() != 'N' || M_pos >= M_maxpos)
3d7c150e 1794 _GLIBCXX_DEMANGLER_FAILURE;
4ffbd077
BK
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))
3d7c150e 1822 _GLIBCXX_DEMANGLER_FAILURE;
4ffbd077
BK
1823 }
1824 else if (current() == 'I')
1825 {
1826 if (!decode_template_args(output))
3d7c150e 1827 _GLIBCXX_DEMANGLER_FAILURE;
4ffbd077
BK
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))
3d7c150e 1838 _GLIBCXX_DEMANGLER_FAILURE;
4ffbd077
BK
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();
3d7c150e 1852 _GLIBCXX_DEMANGLER_RETURN;
4ffbd077
BK
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 }
3d7c150e 1860 _GLIBCXX_DEMANGLER_FAILURE;
4ffbd077
BK
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 {
3d7c150e 1871 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_local_name");
4ffbd077 1872 if (current() != 'Z' || M_pos >= M_maxpos)
3d7c150e 1873 _GLIBCXX_DEMANGLER_FAILURE;
4ffbd077
BK
1874 if ((M_pos += decode_encoding(output, M_str + M_pos + 1,
1875 M_maxpos - M_pos) + 1) < 0 || eat_current() != 'E')
3d7c150e 1876 _GLIBCXX_DEMANGLER_FAILURE;
4ffbd077
BK
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))
3d7c150e 1887 _GLIBCXX_DEMANGLER_FAILURE;
4ffbd077
BK
1888 output += nested_name_qualifiers;
1889 }
1890 string_type discriminator;
1891 if (current() == '_' && next() != 'n' && !decode_number(discriminator))
3d7c150e
BK
1892 _GLIBCXX_DEMANGLER_FAILURE;
1893 _GLIBCXX_DEMANGLER_RETURN;
4ffbd077
BK
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 {
3d7c150e 1902 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_source_name");
4ffbd077
BK
1903 int length = current() - '0';
1904 if (length < 1 || length > 9)
3d7c150e 1905 _GLIBCXX_DEMANGLER_FAILURE;
4ffbd077
BK
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)
3d7c150e 1914 _GLIBCXX_DEMANGLER_FAILURE;
4ffbd077
BK
1915 }
1916 else
1917 while(length--)
1918 {
1919 if (current() == 0)
3d7c150e 1920 _GLIBCXX_DEMANGLER_FAILURE;
4ffbd077
BK
1921 output += eat_current();
1922 }
3d7c150e 1923 _GLIBCXX_DEMANGLER_RETURN;
4ffbd077
BK
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 {
3d7c150e 1934 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_unqualified_name");
4ffbd077
BK
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))
3d7c150e 1951 _GLIBCXX_DEMANGLER_FAILURE;
4ffbd077
BK
1952 if (!recursive_unqualified_name)
1953 output += M_function_name;
1954 }
1955 else if (!decode_source_name(output))
3d7c150e
BK
1956 _GLIBCXX_DEMANGLER_FAILURE;
1957 _GLIBCXX_DEMANGLER_RETURN;
4ffbd077
BK
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))
3d7c150e 1968 _GLIBCXX_DEMANGLER_FAILURE;
4ffbd077
BK
1969 output += M_function_name;
1970 }
3d7c150e 1971 _GLIBCXX_DEMANGLER_RETURN;
4ffbd077
BK
1972 }
1973 if (current() == 'C' || current() == 'D')
1974 {
1975 if (M_inside_template_args)
3d7c150e 1976 _GLIBCXX_DEMANGLER_FAILURE;
4ffbd077
BK
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')
3d7c150e 1989 _GLIBCXX_DEMANGLER_FAILURE;
4ffbd077
BK
1990 }
1991 else
1992 {
1993 char c = next();
1994 if (c < '0' || c > '2')
3d7c150e 1995 _GLIBCXX_DEMANGLER_FAILURE;
4ffbd077
BK
1996 output += '~';
1997 M_saw_destructor = true;
1998 }
1999 M_name_is_cdtor = true;
2000 eat_current();
2001 output += M_function_name;
3d7c150e 2002 _GLIBCXX_DEMANGLER_RETURN;
4ffbd077 2003 }
3d7c150e 2004 _GLIBCXX_DEMANGLER_FAILURE;
4ffbd077
BK
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 {
3d7c150e 2015 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_unscoped_name");
4ffbd077
BK
2016 if (current() == 'S')
2017 {
2018 if (next() != 't')
3d7c150e 2019 _GLIBCXX_DEMANGLER_FAILURE;
4ffbd077
BK
2020 eat_current();
2021 output += "std::";
2022 }
2023 decode_unqualified_name(output);
3d7c150e 2024 _GLIBCXX_DEMANGLER_RETURN;
4ffbd077
BK
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 {
3d7c150e 2042 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_name");
4ffbd077
BK
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))
3d7c150e 2047 _GLIBCXX_DEMANGLER_FAILURE;
4ffbd077
BK
2048 }
2049 else if (current() == 'N')
2050 {
2051 decode_nested_name(output, nested_name_qualifiers);
3d7c150e 2052 _GLIBCXX_DEMANGLER_RETURN;
4ffbd077
BK
2053 }
2054 else if (current() == 'Z')
2055 {
2056 decode_local_name(output);
3d7c150e 2057 _GLIBCXX_DEMANGLER_RETURN;
4ffbd077
BK
2058 }
2059 else if (!decode_unscoped_name(output))
3d7c150e 2060 _GLIBCXX_DEMANGLER_FAILURE;
4ffbd077
BK
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))
3d7c150e 2066 _GLIBCXX_DEMANGLER_FAILURE;
4ffbd077
BK
2067 }
2068 M_template_args_need_space = false;
3d7c150e 2069 _GLIBCXX_DEMANGLER_RETURN;
4ffbd077
BK
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&
3d7c150e 2082#if _GLIBCXX_DEMANGLER_CWDEBUG
4ffbd077
BK
2083 output
2084#endif
2085 )
2086 {
3d7c150e 2087 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_call_offset");
4ffbd077
BK
2088 if (current() == 'h')
2089 {
2090 string_type dummy;
2091 eat_current();
2092 if (decode_number(dummy) && current() == '_')
2093 {
2094 eat_current();
3d7c150e 2095 _GLIBCXX_DEMANGLER_RETURN;
4ffbd077
BK
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();
3d7c150e 2108 _GLIBCXX_DEMANGLER_RETURN;
4ffbd077
BK
2109 }
2110 }
2111 }
3d7c150e 2112 _GLIBCXX_DEMANGLER_FAILURE;
4ffbd077
BK
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 {
3d7c150e 2138 _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_special_name");
4ffbd077
BK
2139 if (current() == 'G')
2140 {
2141 if (next() != 'V')
3d7c150e 2142 _GLIBCXX_DEMANGLER_FAILURE;
4ffbd077
BK
2143 output += "guard variable for ";
2144 string_type nested_name_qualifiers;
2145 eat_current();
2146 if (!decode_name(output, nested_name_qualifiers))
3d7c150e 2147 _GLIBCXX_DEMANGLER_FAILURE;
4ffbd077 2148 output += nested_name_qualifiers;
3d7c150e 2149 _GLIBCXX_DEMANGLER_RETURN;
4ffbd077
BK
2150 }
2151 else if (current() != 'T')
3d7c150e 2152 _GLIBCXX_DEMANGLER_FAILURE;
4ffbd077
BK
2153 switch(next())
2154 {
2155 case 'V':
2156 output += "vtable for ";
2157 eat_current();
2158 decode_type(output);
3d7c150e 2159 _GLIBCXX_DEMANGLER_RETURN;
4ffbd077
BK
2160 case 'T':
2161 output += "VTT for ";
2162 eat_current();
2163 decode_type(output);
3d7c150e 2164 _GLIBCXX_DEMANGLER_RETURN;
4ffbd077
BK
2165 case 'I':
2166 output += "typeinfo for ";
2167 eat_current();
2168 decode_type(output);
3d7c150e 2169 _GLIBCXX_DEMANGLER_RETURN;
4ffbd077
BK
2170 case 'S':
2171 output += "typeinfo name for ";
2172 eat_current();
2173 decode_type(output);
3d7c150e 2174 _GLIBCXX_DEMANGLER_RETURN;
4ffbd077
BK
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)
3d7c150e
BK
2181 _GLIBCXX_DEMANGLER_FAILURE;
2182 _GLIBCXX_DEMANGLER_RETURN;
4ffbd077
BK
2183 case 'C': // GNU extension?
2184 {
2185 string_type first;
2186 output += "construction vtable for ";
2187 eat_current();
2188 if (!decode_type(first))
3d7c150e 2189 _GLIBCXX_DEMANGLER_FAILURE;
4ffbd077
BK
2190 while(std::isdigit(current()))
2191 eat_current();
2192 if (eat_current() != '_')
3d7c150e 2193 _GLIBCXX_DEMANGLER_FAILURE;
4ffbd077 2194 if (!decode_type(output))
3d7c150e 2195 _GLIBCXX_DEMANGLER_FAILURE;
4ffbd077
BK
2196 output += "-in-";
2197 output += first;
3d7c150e 2198 _GLIBCXX_DEMANGLER_RETURN;
4ffbd077
BK
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)
3d7c150e
BK
2208 _GLIBCXX_DEMANGLER_FAILURE;
2209 _GLIBCXX_DEMANGLER_RETURN;
4ffbd077
BK
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 {
3d7c150e
BK
2225#if _GLIBCXX_DEMANGLER_CWDEBUG
2226 _GLIBCXX_DEMANGLER_DOUT(dc::demangler,
4ffbd077
BK
2227 "Output thus far: \"" << output << '"');
2228 string_type input(in, len > 0x40000000 ? strlen(in) : len);
3d7c150e 2229 _GLIBCXX_DEMANGLER_DOUT(
4ffbd077
BK
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