1 //===-- FastDemangle.cpp ----------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
14 //#define DEBUG_FAILURES 1
15 //#define DEBUG_SUBSTITUTIONS 1
16 //#define DEBUG_TEMPLATE_ARGS 1
17 //#define DEBUG_HIGHWATER 1
18 //#define DEBUG_REORDERING 1
22 /// @brief Represents the collection of qualifiers on a type
28 QualifierRestrict = 2,
29 QualifierVolatile = 4,
30 QualifierReference = 8,
31 QualifierRValueReference = 16,
35 /// @brief Categorizes the recognized operators
37 enum class OperatorKind
49 /// @brief Represents one of the recognized two-character operator
50 /// abbreviations used when parsing operators as names and expressions
58 /// @brief Represents a range of characters in the output buffer, typically for
59 /// use with RewriteRange()
67 /// @brief Transient state required while parsing a name
71 bool parse_function_params;
73 bool has_no_return_type;
74 BufferRange last_name_range;
77 /// @brief LLDB's fast C++ demangler
79 /// This is an incomplete implementation designed to speed up the demangling
80 /// process that is often a bottleneck when LLDB stops a process for the first
81 /// time. Where the implementation doesn't know how to demangle a symbol it
82 /// fails gracefully to allow the caller to fall back to the existing demangler.
84 /// Over time the full mangling spec should be supported without compromising
85 /// performance for the most common cases.
91 //----------------------------------------------------
93 //----------------------------------------------------
95 /// @brief Create a SymbolDemangler
97 /// The newly created demangler allocates and owns scratch memory sufficient
98 /// for demangling typical symbols. Additional memory will be allocated if
99 /// needed and managed by the demangler instance.
103 m_buffer = (char *) malloc(8192);
104 m_buffer_end = m_buffer + 8192;
105 m_owns_buffer = true;
107 m_rewrite_ranges = (BufferRange *) malloc(128 * sizeof (BufferRange));
108 m_rewrite_ranges_size = 128;
109 m_owns_m_rewrite_ranges = true;
112 /// @brief Create a SymbolDemangler that uses provided scratch memory
114 /// The provided memory is not owned by the demangler. It will be
115 /// overwritten during calls to GetDemangledCopy() but can be used for
116 /// other purposes between calls. The provided memory will not be freed
117 /// when this instance is destroyed.
119 /// If demangling a symbol requires additional space it will be allocated
120 /// and managed by the demangler instance.
122 /// @param storage_ptr Valid pointer to at least storage_size bytes of
123 /// space that the SymbolDemangler can use during demangling
125 /// @param storage_size Number of bytes of space available scratch memory
126 /// referenced by storage_ptr
128 SymbolDemangler(void *storage_ptr, int storage_size)
130 // Use up to 1/8th of the provided space for rewrite ranges
131 m_rewrite_ranges_size = (storage_size >> 3) / sizeof (BufferRange);
132 m_rewrite_ranges = (BufferRange *) storage_ptr;
133 m_owns_m_rewrite_ranges = false;
135 // Use the rest for the character buffer
136 m_buffer = (char *) storage_ptr + m_rewrite_ranges_size * sizeof (BufferRange);
137 m_buffer_end = (const char *)storage_ptr + storage_size;
138 m_owns_buffer = false;
141 /// @brief Destroys the SymbolDemangler and deallocates any scratch
142 /// memory that it owns
148 if (m_owns_m_rewrite_ranges)
149 free(m_rewrite_ranges);
152 #ifdef DEBUG_HIGHWATER
153 int highwater_store = 0;
154 int highwater_buffer = 0;
157 /// @brief Parses the provided mangled name and returns a newly allocated
160 /// @param mangled_name Valid null-terminated C++ mangled name following
161 /// the Itanium C++ ABI mangling specification as implemented by Clang
163 /// @result Newly allocated null-terminated demangled name when demangling
164 /// is succesful, and nullptr when demangling fails. The caller is
165 /// responsible for freeing the allocated memory.
168 GetDemangledCopy(const char *mangled_name,
169 long mangled_name_length = 0)
171 if (!ParseMangling(mangled_name, mangled_name_length))
174 #ifdef DEBUG_HIGHWATER
175 int rewrite_count = m_next_substitute_index +
176 (m_rewrite_ranges_size - 1 - m_next_template_arg_index);
177 int buffer_size = (int)(m_write_ptr - m_buffer);
178 if (rewrite_count > highwater_store)
179 highwater_store = rewrite_count;
180 if (buffer_size > highwater_buffer)
181 highwater_buffer = buffer_size;
184 int length = (int)(m_write_ptr - m_buffer);
185 char *copy = (char *)malloc(length + 1);
186 memcpy(copy, m_buffer, length);
193 //----------------------------------------------------
196 // Manage the storage used during demangling
197 //----------------------------------------------------
199 void GrowBuffer(long min_growth = 0)
201 // By default, double the size of the buffer
202 long growth = m_buffer_end - m_buffer;
204 // Avoid growing by more than 1MB at a time
205 if (growth > 1 << 20)
208 // ... but never grow by less than requested,
209 // or 1K, whichever is greater
210 if (min_growth < 1024)
212 if (growth < min_growth)
215 // Allocate the new m_buffer and migrate content
216 long new_size = (m_buffer_end - m_buffer) + growth;
217 char *new_buffer = (char *) malloc(new_size);
218 memcpy(new_buffer, m_buffer, m_write_ptr - m_buffer);
221 m_owns_buffer = true;
223 // Update references to the new buffer
224 m_write_ptr = new_buffer + (m_write_ptr - m_buffer);
225 m_buffer = new_buffer;
226 m_buffer_end = m_buffer + new_size;
232 // By default, double the size of the array
233 int growth = m_rewrite_ranges_size;
235 // Apply reasonable minimum and maximum sizes for growth
241 // Allocate the new array and migrate content
242 int bytes = (m_rewrite_ranges_size + growth) * sizeof (BufferRange);
243 BufferRange *new_ranges = (BufferRange *) malloc (bytes);
244 for (int index = 0; index < m_next_substitute_index; index++)
246 new_ranges[index] = m_rewrite_ranges[index];
248 for (int index = m_rewrite_ranges_size - 1;
249 index > m_next_template_arg_index; index--)
251 new_ranges[index + growth] = m_rewrite_ranges[index];
253 if (m_owns_m_rewrite_ranges)
254 free(m_rewrite_ranges);
255 m_owns_m_rewrite_ranges = true;
257 // Update references to the new array
258 m_rewrite_ranges = new_ranges;
259 m_rewrite_ranges_size += growth;
260 m_next_template_arg_index += growth;
263 //----------------------------------------------------
264 // Range and state management
265 //----------------------------------------------------
270 return (int)(m_write_ptr - m_buffer);
274 EndRange(int start_cookie)
276 return { start_cookie, (int)(m_write_ptr - (m_buffer + start_cookie)) };
280 ReorderRange(BufferRange source_range, int insertion_point_cookie)
282 // Ensure there's room the preserve the source range
283 if (m_write_ptr + source_range.length > m_buffer_end)
285 GrowBuffer(m_write_ptr + source_range.length - m_buffer_end);
288 // Reorder the content
289 memcpy(m_write_ptr, m_buffer + source_range.offset, source_range.length);
290 memmove(m_buffer + insertion_point_cookie + source_range.length,
291 m_buffer + insertion_point_cookie,
292 source_range.offset - insertion_point_cookie);
293 memcpy(m_buffer + insertion_point_cookie, m_write_ptr, source_range.length);
295 // Fix up rewritable ranges, covering both substitutions and templates
299 if (index == m_next_substitute_index)
300 index = m_next_template_arg_index + 1;
301 if (index == m_rewrite_ranges_size)
304 // Affected ranges are either shuffled forward when after the
305 // insertion but before the source, or backward when inside the
307 int candidate_offset = m_rewrite_ranges[index].offset;
308 if (candidate_offset >= insertion_point_cookie)
310 if (candidate_offset < source_range.offset)
312 m_rewrite_ranges[index].offset += source_range.length;
314 else if (candidate_offset >= source_range.offset)
316 m_rewrite_ranges[index].offset -= (source_range.offset - insertion_point_cookie);
324 EndSubstitution(int start_cookie)
326 if (m_next_substitute_index == m_next_template_arg_index)
329 int index = m_next_substitute_index++;
330 m_rewrite_ranges[index] = EndRange(start_cookie);
331 #ifdef DEBUG_SUBSTITUTIONS
332 printf("Saved substitution # %d = %.*s\n", index,
333 m_rewrite_ranges[index].length, m_buffer + start_cookie);
338 EndTemplateArg(int start_cookie)
340 if (m_next_substitute_index == m_next_template_arg_index)
343 int index = m_next_template_arg_index--;
344 m_rewrite_ranges[index] = EndRange(start_cookie);
345 #ifdef DEBUG_TEMPLATE_ARGS
346 printf("Saved template arg # %d = %.*s\n",
347 m_rewrite_ranges_size - index - 1,
348 m_rewrite_ranges[index].length, m_buffer + start_cookie);
355 //TODO: this works, but is it the right thing to do?
356 // Should we push/pop somehow at the call sites?
357 m_next_template_arg_index = m_rewrite_ranges_size - 1;
360 //----------------------------------------------------
363 // Appends content to the existing output buffer
364 //----------------------------------------------------
367 Write(char character)
369 if (m_write_ptr == m_buffer_end)
371 *m_write_ptr++ = character;
375 Write(const char *content)
377 Write(content, strlen(content));
381 Write(const char *content, long content_length)
383 char *end_m_write_ptr = m_write_ptr + content_length;
384 if (end_m_write_ptr > m_buffer_end)
386 GrowBuffer(end_m_write_ptr - m_buffer_end);
387 end_m_write_ptr = m_write_ptr + content_length;
389 memcpy(m_write_ptr, content, content_length);
390 m_write_ptr = end_m_write_ptr;
392 #define WRITE(x) Write(x, sizeof (x) - 1)
403 // Put a space between terminal > characters when nesting templates
404 if (m_write_ptr != m_buffer && *(m_write_ptr - 1) == '>')
416 WriteNamespaceSeparator()
428 WriteQualifiers(int qualifiers, bool space_before_reference = true)
430 if (qualifiers & QualifierPointer)
432 if (qualifiers & QualifierConst)
434 if (qualifiers & QualifierVolatile)
436 if (qualifiers & QualifierRestrict)
438 if (qualifiers & QualifierReference)
440 if (space_before_reference)
444 if (qualifiers & QualifierRValueReference)
446 if (space_before_reference)
452 //----------------------------------------------------
455 // Write another copy of content already present
456 // earlier in the output buffer
457 //----------------------------------------------------
460 RewriteRange(BufferRange range)
462 Write(m_buffer + range.offset, range.length);
466 RewriteSubstitution(int index)
468 if (index < 0 || index >= m_next_substitute_index)
470 #ifdef DEBUG_FAILURES
471 printf("*** Invalid substitution #%d\n", index);
475 RewriteRange(m_rewrite_ranges[index]);
480 RewriteTemplateArg(int template_index)
482 int index = m_rewrite_ranges_size - 1 - template_index;
483 if (template_index < 0 || index <= m_next_template_arg_index)
485 #ifdef DEBUG_FAILURES
486 printf("*** Invalid template arg reference #%d\n", template_index);
490 RewriteRange(m_rewrite_ranges[index]);
494 //----------------------------------------------------
497 // Provide information with return values instead of
498 // writing to the output buffer
500 // Values indicating failure guarantee that the pre-
501 // call m_read_ptr is unchanged
502 //----------------------------------------------------
507 unsigned char digit = *m_read_ptr - '0';
514 digit = *++m_read_ptr - '0';
518 count = count * 10 + digit;
524 TryParseBase36Number()
526 char digit = *m_read_ptr;
528 if (digit >= '0' && digit <= '9')
529 count = digit -= '0';
530 else if (digit >= 'A' && digit <= 'Z')
531 count = digit -= ('A' - 10);
536 digit = *++m_read_ptr;
537 if (digit >= '0' && digit <= '9')
539 else if (digit >= 'A' && digit <= 'Z')
543 count = count * 36 + digit;
548 // <builtin-type> ::= v # void
552 // ::= a # signed char
553 // ::= h # unsigned char
555 // ::= t # unsigned short
557 // ::= j # unsigned int
559 // ::= m # unsigned long
560 // ::= x # long long, __int64
561 // ::= y # unsigned long long, __int64
563 // ::= o # unsigned __int128
566 // ::= e # long double, __float80
567 // ::= g # __float128
569 // ::= Dd # IEEE 754r decimal floating point (64 bits)
570 // ::= De # IEEE 754r decimal floating point (128 bits)
571 // ::= Df # IEEE 754r decimal floating point (32 bits)
572 // ::= Dh # IEEE 754r half-precision floating point (16 bits)
575 // ::= Da # auto (in dependent new-expressions)
576 // ::= Dn # std::nullptr_t (i.e., decltype(nullptr))
577 // ::= u <source-name> # vendor extended type
580 TryParseBuiltinType()
582 switch (*m_read_ptr++)
584 case 'v': return "void";
585 case 'w': return "wchar_t";
586 case 'b': return "bool";
587 case 'c': return "char";
588 case 'a': return "signed char";
589 case 'h': return "unsigned char";
590 case 's': return "short";
591 case 't': return "unsigned short";
592 case 'i': return "int";
593 case 'j': return "unsigned int";
594 case 'l': return "long";
595 case 'm': return "unsigned long";
596 case 'x': return "long long";
597 case 'y': return "unsigned long long";
598 case 'n': return "__int128";
599 case 'o': return "unsigned __int128";
600 case 'f': return "float";
601 case 'd': return "double";
602 case 'e': return "long double";
603 case 'g': return "__float128";
604 case 'z': return "...";
607 switch (*m_read_ptr++)
609 case 'd': return "decimal64";
610 case 'e': return "decimal128";
611 case 'f': return "decimal32";
612 case 'h': return "decimal16";
613 case 'i': return "char32_t";
614 case 's': return "char16_t";
615 case 'a': return "auto";
616 case 'c': return "decltype(auto)";
617 case 'n': return "std::nullptr_t";
629 // ::= ad # & (unary)
637 // ::= de # * (unary)
655 // ::= mm # -- (postfix in <expression> context)
658 // ::= ng # - (unary)
667 // ::= pp # ++ (postfix in <expression> context)
668 // ::= ps # + (unary)
675 // ::= cv <type> # (cast)
676 // ::= v <digit> <source-name> # vendor extended operator
681 switch (*m_read_ptr++)
684 switch (*m_read_ptr++)
686 case 'a': return { "&&", OperatorKind::Binary };
687 case 'd': return { "&", OperatorKind::Unary };
688 case 'n': return { "&", OperatorKind::Binary };
689 case 'N': return { "&=", OperatorKind::Binary };
690 case 'S': return { "=", OperatorKind::Binary };
695 switch (*m_read_ptr++)
697 case 'l': return { "()", OperatorKind::Other };
698 case 'm': return { ",", OperatorKind::Other };
699 case 'o': return { "~", OperatorKind::Unary };
700 case 'v': return { nullptr, OperatorKind::ConversionOperator };
705 switch (*m_read_ptr++)
707 case 'a': return { " delete[]", OperatorKind::Other };
708 case 'e': return { "*", OperatorKind::Unary };
709 case 'l': return { " delete", OperatorKind::Other };
710 case 'v': return { "/", OperatorKind::Binary };
711 case 'V': return { "/=", OperatorKind::Binary };
716 switch (*m_read_ptr++)
718 case 'o': return { "^", OperatorKind::Binary };
719 case 'O': return { "^=", OperatorKind::Binary };
720 case 'q': return { "==", OperatorKind::Binary };
725 switch (*m_read_ptr++)
727 case 'e': return { ">=", OperatorKind::Binary };
728 case 't': return { ">", OperatorKind::Binary };
733 switch (*m_read_ptr++)
735 case 'x': return { "[]", OperatorKind::Other };
740 switch (*m_read_ptr++)
742 case 'e': return { "<=", OperatorKind::Binary };
743 case 's': return { "<<", OperatorKind::Binary };
744 case 'S': return { "<<=", OperatorKind::Binary };
745 case 't': return { "<", OperatorKind::Binary };
746 // case 'i': return { "?", OperatorKind::Binary };
751 switch (*m_read_ptr++)
753 case 'i': return { "-", OperatorKind::Binary };
754 case 'I': return { "-=", OperatorKind::Binary };
755 case 'l': return { "*", OperatorKind::Binary };
756 case 'L': return { "*=", OperatorKind::Binary };
757 case 'm': return { "--", OperatorKind::Postfix };
762 switch (*m_read_ptr++)
764 case 'a': return { " new[]", OperatorKind::Other };
765 case 'e': return { "!=", OperatorKind::Binary };
766 case 'g': return { "-", OperatorKind::Unary };
767 case 't': return { "!", OperatorKind::Unary };
768 case 'w': return { " new", OperatorKind::Other };
773 switch (*m_read_ptr++)
775 case 'o': return { "||", OperatorKind::Binary };
776 case 'r': return { "|", OperatorKind::Binary };
777 case 'R': return { "|=", OperatorKind::Binary };
782 switch (*m_read_ptr++)
784 case 'm': return { "->*", OperatorKind::Binary };
785 case 's': return { "+", OperatorKind::Unary };
786 case 'l': return { "+", OperatorKind::Binary };
787 case 'L': return { "+=", OperatorKind::Binary };
788 case 'p': return { "++", OperatorKind::Postfix };
789 case 't': return { "->", OperatorKind::Binary };
794 switch (*m_read_ptr++)
796 case 'u': return { "?", OperatorKind::Ternary };
801 switch (*m_read_ptr++)
803 case 'm': return { "%", OperatorKind::Binary };
804 case 'M': return { "%=", OperatorKind::Binary };
805 case 's': return { ">>", OperatorKind::Binary };
806 case 'S': return { ">=", OperatorKind::Binary };
811 char digit = *m_read_ptr;
812 if (digit >= '0' && digit <= '9')
815 return { nullptr, OperatorKind::Vendor };
821 return { nullptr, OperatorKind::NoMatch };
824 // <CV-qualifiers> ::= [r] [V] [K]
825 // <ref-qualifier> ::= R # & ref-qualifier
826 // <ref-qualifier> ::= O # && ref-qualifier
829 TryParseQualifiers(bool allow_cv, bool allow_ro)
831 int qualifiers = QualifierNone;
832 char next = *m_read_ptr;
835 if (next == 'r') // restrict
837 qualifiers |= QualifierRestrict;
838 next = *++m_read_ptr;
840 if (next == 'V') // volatile
842 qualifiers |= QualifierVolatile;
843 next = *++m_read_ptr;
845 if (next == 'K') // const
847 qualifiers |= QualifierConst;
848 next = *++m_read_ptr;
856 qualifiers |= QualifierReference;
861 qualifiers |= QualifierRValueReference;
867 // <discriminator> := _ <non-negative number> # when number < 10
868 // := __ <non-negative number> _ # when number >= 10
869 // extension := decimal-digit+
872 TryParseDiscriminator()
874 const char *discriminator_start = m_read_ptr;
876 // Test the extension first, since it's what Clang uses
877 int discriminator_value = TryParseNumber();
878 if (discriminator_value != -1)
879 return discriminator_value;
881 char next = *m_read_ptr;
884 next = *++m_read_ptr;
888 discriminator_value = TryParseNumber();
889 if (discriminator_value != -1 && *m_read_ptr++ != '_')
891 return discriminator_value;
894 else if (next >= '0' && next <= '9')
901 // Not a valid discriminator
902 m_read_ptr = discriminator_start;
906 //----------------------------------------------------
909 // Consume input starting from m_read_ptr and produce
910 // buffered output at m_write_ptr
912 // Failures return false and may leave m_read_ptr in an
913 // indeterminate state
914 //----------------------------------------------------
917 Parse(char character)
919 if (*m_read_ptr++ == character)
921 #ifdef DEBUG_FAILURES
922 printf("*** Expected '%c'\n", character);
927 // <number> ::= [n] <non-negative decimal integer>
930 ParseNumber(bool allow_negative = false)
932 if (allow_negative && *m_read_ptr == 'n')
937 const char *before_digits = m_read_ptr;
940 unsigned char digit = *m_read_ptr - '0';
945 if (int digit_count = (int)(m_read_ptr - before_digits))
947 Write(before_digits, digit_count);
950 #ifdef DEBUG_FAILURES
951 printf("*** Expected number\n");
956 // <substitution> ::= S <seq-id> _
958 // <substitution> ::= Sa # ::std::allocator
959 // <substitution> ::= Sb # ::std::basic_string
960 // <substitution> ::= Ss # ::std::basic_string < char,
961 // ::std::char_traits<char>,
962 // ::std::allocator<char> >
963 // <substitution> ::= Si # ::std::basic_istream<char, std::char_traits<char> >
964 // <substitution> ::= So # ::std::basic_ostream<char, std::char_traits<char> >
965 // <substitution> ::= Sd # ::std::basic_iostream<char, std::char_traits<char> >
970 const char *substitution;
973 case 'a': substitution = "std::allocator"; break;
974 case 'b': substitution = "std::basic_string"; break;
975 case 's': substitution = "std::string"; break;
976 case 'i': substitution = "std::istream"; break;
977 case 'o': substitution = "std::ostream"; break;
978 case 'd': substitution = "std::iostream"; break;
980 // A failed attempt to parse a number will return -1 which turns out to be
981 // perfect here as S_ is the first substitution, S0_ the next and so forth
982 int substitution_index = TryParseBase36Number();
983 if (*m_read_ptr++ != '_')
985 #ifdef DEBUG_FAILURES
986 printf("*** Expected terminal _ in substitution\n");
990 return RewriteSubstitution (substitution_index + 1);
997 // <function-type> ::= F [Y] <bare-function-type> [<ref-qualifier>] E
999 // <bare-function-type> ::= <signature type>+ # types are possible return type, then parameter types
1002 ParseFunctionType (int inner_qualifiers = QualifierNone)
1004 #ifdef DEBUG_FAILURES
1005 printf("*** Function types not supported\n");
1007 //TODO: first steps toward an implementation follow, but they're far
1008 // from complete. Function types tend to bracket other types eg:
1009 // int (*)() when used as the type for "name" becomes int (*name)().
1010 // This makes substitution et al ... interesting.
1014 if (*m_read_ptr == 'Y')
1017 int return_type_start_cookie = GetStartCookie();
1022 int insert_cookie = GetStartCookie();
1024 bool first_param = true;
1025 int qualifiers = QualifierNone;
1028 switch (*m_read_ptr)
1039 if (*(m_read_ptr + 1) == 'E')
1041 qualifiers = TryParseQualifiers (false, true);
1049 first_param = false;
1050 else WriteCommaSpace();
1062 WriteQualifiers (qualifiers);
1063 EndSubstitution (return_type_start_cookie);
1066 if (inner_qualifiers)
1068 int qualifier_start_cookie = GetStartCookie();
1070 WriteQualifiers (inner_qualifiers);
1072 ReorderRange (EndRange (qualifier_start_cookie), insert_cookie);
1078 // <array-type> ::= A <positive dimension number> _ <element type>
1079 // ::= A [<dimension expression>] _ <element type>
1082 ParseArrayType(int qualifiers = QualifierNone)
1084 #ifdef DEBUG_FAILURES
1085 printf("*** Array type unsupported\n");
1087 //TODO: We fail horribly when recalling these as substitutions or
1088 // templates and trying to constify them eg:
1089 // _ZN4llvm2cl5applyIA28_cNS0_3optIbLb0ENS0_6parserIbEEEEEEvRKT_PT0_
1091 //TODO: Chances are we don't do any better with references and pointers
1092 // that should be type (&) [] instead of type & []
1097 if (*m_read_ptr == '_')
1103 WriteQualifiers(qualifiers);
1109 const char *before_digits = m_read_ptr;
1110 if (TryParseNumber() != -1)
1112 const char *after_digits = m_read_ptr;
1118 WriteQualifiers(qualifiers);
1121 Write(before_digits, after_digits - before_digits);
1125 int type_insertion_cookie = GetStartCookie();
1126 if (!ParseExpression())
1131 int type_start_cookie = GetStartCookie();
1135 WriteQualifiers(qualifiers);
1138 ReorderRange (EndRange (type_start_cookie), type_insertion_cookie);
1146 // <pointer-to-member-type> ::= M <class type> <member type>
1148 //TODO: Determine how to handle pointers to function members correctly,
1149 // currently not an issue because we don't have function types at all...
1151 ParsePointerToMemberType()
1153 int insertion_cookie = GetStartCookie();
1159 int type_cookie = GetStartCookie();
1162 ReorderRange (EndRange (type_cookie), insertion_cookie);
1166 // <template-param> ::= T_ # first template parameter
1167 // ::= T <parameter-2 non-negative number> _
1170 ParseTemplateParam()
1172 int count = TryParseNumber();
1176 // When no number is present we get -1, which is convenient since
1177 // T_ is the zeroth element T0_ is element 1, and so on
1178 return RewriteTemplateArg (count + 1);
1181 // <type> ::= <builtin-type>
1182 // ::= <function-type>
1183 // ::= <class-enum-type>
1185 // ::= <pointer-to-member-type>
1186 // ::= <template-param>
1187 // ::= <template-template-param> <template-args>
1189 // ::= <substitution>
1190 // ::= <CV-qualifiers> <type>
1191 // ::= P <type> # pointer-to
1192 // ::= R <type> # reference-to
1193 // ::= O <type> # rvalue reference-to (C++0x)
1194 // ::= C <type> # complex pair (C 2000)
1195 // ::= G <type> # imaginary (C 2000)
1196 // ::= Dp <type> # pack expansion (C++0x)
1197 // ::= U <source-name> <type> # vendor extended type qualifier
1198 // extension := U <objc-name> <objc-type> # objc-type<identifier>
1199 // extension := <vector-type> # <vector-type> starts with Dv
1201 // <objc-name> ::= <k0 number> objcproto <k1 number> <identifier> # k0 = 9 + <number of digits in k1> + k1
1202 // <objc-type> := <source-name> # PU<11+>objcproto 11objc_object<source-name> 11objc_object -> id<source-name>
1207 #ifdef DEBUG_FAILURES
1208 const char *failed_type = m_read_ptr;
1210 int type_start_cookie = GetStartCookie();
1211 bool suppress_substitution = false;
1213 int qualifiers = TryParseQualifiers (true, false);
1214 switch (*m_read_ptr)
1218 switch (*m_read_ptr++)
1228 #ifdef DEBUG_FAILURES
1229 printf("*** Unsupported type: %.3s\n", failed_type);
1236 if (!ParseTemplateParam())
1241 if (!ParsePointerToMemberType())
1246 if (!ParseArrayType())
1251 if (!ParseFunctionType())
1255 if (*++m_read_ptr == 't')
1264 suppress_substitution = true;
1265 if (!ParseSubstitution())
1271 switch (*++m_read_ptr)
1275 if (!ParseFunctionType(QualifierPointer))
1306 #ifdef DEBUG_FAILURES
1307 printf("*** Unsupported type: %.3s\n", failed_type);
1310 // Test for common cases to avoid TryParseBuiltinType() overhead
1318 if (const char *builtin = TryParseBuiltinType())
1321 suppress_substitution = true;
1331 // Allow base substitutions to be suppressed, but always record
1332 // substitutions for the qualified variant
1333 if (!suppress_substitution)
1334 EndSubstitution(type_start_cookie);
1337 WriteQualifiers(qualifiers, false);
1338 EndSubstitution(type_start_cookie);
1343 // <unnamed-type-name> ::= Ut [ <nonnegative number> ] _
1344 // ::= <closure-type-name>
1346 // <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _
1348 // <lambda-sig> ::= <parameter type>+ # Parameter types or "v" if the lambda has no parameters
1351 ParseUnnamedTypeName(NameState & name_state)
1353 switch (*m_read_ptr++)
1357 int cookie = GetStartCookie();
1359 const char *before_digits = m_read_ptr;
1360 if (TryParseNumber() != -1) Write (before_digits,
1361 m_read_ptr - before_digits);
1365 name_state.last_name_range = EndRange (cookie);
1370 int cookie = GetStartCookie();
1372 const char *before_digits = m_read_ptr;
1373 if (TryParseNumber() != -1) Write (before_digits,
1374 m_read_ptr - before_digits);
1378 name_state.last_name_range = EndRange (cookie);
1382 #ifdef DEBUG_FAILURES
1383 printf("*** Lambda type names unsupported\n");
1387 #ifdef DEBUG_FAILURES
1388 printf("*** Unknown unnamed type %.3s\n", m_read_ptr - 2);
1393 // <ctor-dtor-name> ::= C1 # complete object constructor
1394 // ::= C2 # base object constructor
1395 // ::= C3 # complete object allocating constructor
1398 ParseCtor(NameState & name_state)
1400 char next = *m_read_ptr;
1401 if (next == '1' || next == '2' || next == '3' || next == '5')
1403 RewriteRange (name_state.last_name_range);
1404 name_state.has_no_return_type = true;
1408 #ifdef DEBUG_FAILURES
1409 printf("*** Broken constructor\n");
1414 // <ctor-dtor-name> ::= D0 # deleting destructor
1415 // ::= D1 # complete object destructor
1416 // ::= D2 # base object destructor
1419 ParseDtor(NameState & name_state)
1421 char next = *m_read_ptr;
1422 if (next == '0' || next == '1' || next == '2' || next == '5')
1425 RewriteRange(name_state.last_name_range);
1426 name_state.has_no_return_type = true;
1430 #ifdef DEBUG_FAILURES
1431 printf("*** Broken destructor\n");
1436 // See TryParseOperator()
1439 ParseOperatorName(NameState & name_state)
1441 #ifdef DEBUG_FAILURES
1442 const char *operator_ptr = m_read_ptr;
1444 Operator parsed_operator = TryParseOperator();
1445 if (parsed_operator.name)
1448 Write(parsed_operator.name);
1452 // Handle special operators
1453 switch (parsed_operator.kind)
1455 case OperatorKind::Vendor:
1457 return ParseSourceName();
1458 case OperatorKind::ConversionOperator:
1459 ResetTemplateArgs();
1460 name_state.has_no_return_type = true;
1464 #ifdef DEBUG_FAILURES
1465 printf("*** Unknown operator: %.2s\n", operator_ptr);
1471 // <source-name> ::= <positive length number> <identifier>
1476 int count = TryParseNumber();
1479 #ifdef DEBUG_FAILURES
1480 printf("*** Malformed source name, missing length count\n");
1485 const char *next_m_read_ptr = m_read_ptr + count;
1486 if (next_m_read_ptr > m_read_end)
1488 #ifdef DEBUG_FAILURES
1489 printf("*** Malformed source name, premature termination\n");
1494 if (count >= 10 && strncmp(m_read_ptr, "_GLOBAL__N", 10) == 0)
1495 WRITE("(anonymous namespace)");
1496 else Write(m_read_ptr, count);
1498 m_read_ptr = next_m_read_ptr;
1502 // <unqualified-name> ::= <operator-name>
1503 // ::= <ctor-dtor-name>
1504 // ::= <source-name>
1505 // ::= <unnamed-type-name>
1508 ParseUnqualifiedName(NameState & name_state)
1510 // Note that these are detected directly in ParseNestedName for
1511 // performance rather than switching on the same options twice
1512 char next = *m_read_ptr;
1517 return ParseCtor(name_state);
1520 return ParseDtor(name_state);
1523 return ParseUnnamedTypeName(name_state);
1535 int name_start_cookie = GetStartCookie();
1536 if (!ParseSourceName())
1538 name_state.last_name_range = EndRange(name_start_cookie);
1542 return ParseOperatorName(name_state);
1546 // <unscoped-name> ::= <unqualified-name>
1547 // ::= St <unqualified-name> # ::std::
1548 // extension ::= StL<unqualified-name>
1551 ParseUnscopedName(NameState & name_state)
1553 if (*m_read_ptr == 'S' && *(m_read_ptr + 1) == 't')
1556 if (*(m_read_ptr += 2) == 'L')
1559 return ParseUnqualifiedName(name_state);
1563 ParseIntegerLiteral(const char *prefix, const char *suffix,
1564 bool allow_negative)
1568 if (!ParseNumber(allow_negative))
1576 ParseBooleanLiteral()
1578 switch (*m_read_ptr++)
1580 case '0': WRITE("false"); break;
1581 case '1': WRITE("true"); break;
1583 #ifdef DEBUG_FAILURES
1584 printf("*** Boolean literal not 0 or 1\n");
1591 // <expr-primary> ::= L <type> <value number> E # integer literal
1592 // ::= L <type> <value float> E # floating literal
1593 // ::= L <string type> E # string literal
1594 // ::= L <nullptr type> E # nullptr literal (i.e., "LDnE")
1595 // ::= L <type> <real-part float> _ <imag-part float> E # complex floating point literal (C 2000)
1596 // ::= L <mangled-name> E # external name
1599 ParseExpressionPrimary()
1601 switch (*m_read_ptr++)
1603 case 'b': return ParseBooleanLiteral();
1604 case 'x': return ParseIntegerLiteral(nullptr, "ll", true);
1605 case 'l': return ParseIntegerLiteral(nullptr, "l", true);
1606 case 'i': return ParseIntegerLiteral(nullptr, nullptr, true);
1607 case 'n': return ParseIntegerLiteral("(__int128)", nullptr, true);
1608 case 'j': return ParseIntegerLiteral(nullptr, "u", false);
1609 case 'm': return ParseIntegerLiteral(nullptr, "ul", false);
1610 case 'y': return ParseIntegerLiteral(nullptr, "ull", false);
1611 case 'o': return ParseIntegerLiteral("(unsigned __int128)",
1614 if (*m_read_ptr++ == 'Z')
1616 if (!ParseEncoding())
1631 #ifdef DEBUG_FAILURES
1632 printf("*** Unsupported primary expression %.5s\n", m_read_ptr - 1);
1636 // Invalid mangled name per
1637 // http://sourcerytools.com/pipermail/cxx-abi-dev/2011-August/002422.html
1638 #ifdef DEBUG_FAILURES
1639 printf("*** Invalid primary expr encoding\n");
1654 // <unresolved-type> ::= <template-param>
1656 // ::= <substitution>
1659 ParseUnresolvedType()
1661 int type_start_cookie = GetStartCookie();
1662 switch (*m_read_ptr++)
1665 if (!ParseTemplateParam())
1667 EndSubstitution(type_start_cookie);
1671 if (*m_read_ptr != 't')
1672 return ParseSubstitution();
1676 NameState type_name = {};
1677 if (!ParseUnqualifiedName(type_name))
1679 EndSubstitution(type_start_cookie);
1685 #ifdef DEBUG_FAILURES
1686 printf("*** Unsupported unqualified type: %3s\n", m_read_ptr - 1);
1692 // <base-unresolved-name> ::= <simple-id> # unresolved name
1693 // extension ::= <operator-name> # unresolved operator-function-id
1694 // extension ::= <operator-name> <template-args> # unresolved operator template-id
1695 // ::= on <operator-name> # unresolved operator-function-id
1696 // ::= on <operator-name> <template-args> # unresolved operator template-id
1697 // ::= dn <destructor-name> # destructor or pseudo-destructor;
1698 // # e.g. ~X or ~X<N-1>
1701 ParseBaseUnresolvedName()
1703 #ifdef DEBUG_FAILURES
1704 printf("*** Base unresolved name unsupported\n");
1709 // <unresolved-name>
1710 // extension ::= srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
1711 // ::= [gs] <base-unresolved-name> # x or (with "gs") ::x
1712 // ::= [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
1713 // # A::x, N::y, A<T>::z; "gs" means leading "::"
1714 // ::= sr <unresolved-type> <base-unresolved-name> # T::x / decltype(p)::x
1715 // extension ::= sr <unresolved-type> <template-args> <base-unresolved-name>
1716 // # T::N::x /decltype(p)::N::x
1717 // (ignored) ::= srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>
1720 ParseUnresolvedName()
1722 #ifdef DEBUG_FAILURES
1723 printf("*** Unresolved names not supported\n");
1725 //TODO: grammar for all of this seems unclear...
1729 if (*m_read_ptr == 'g' && *(m_read_ptr + 1) == 's')
1732 WriteNamespaceSeparator();
1737 // <expression> ::= <unary operator-name> <expression>
1738 // ::= <binary operator-name> <expression> <expression>
1739 // ::= <ternary operator-name> <expression> <expression> <expression>
1740 // ::= cl <expression>+ E # call
1741 // ::= cv <type> <expression> # conversion with one argument
1742 // ::= cv <type> _ <expression>* E # conversion with a different number of arguments
1743 // ::= [gs] nw <expression>* _ <type> E # new (expr-list) type
1744 // ::= [gs] nw <expression>* _ <type> <initializer> # new (expr-list) type (init)
1745 // ::= [gs] na <expression>* _ <type> E # new[] (expr-list) type
1746 // ::= [gs] na <expression>* _ <type> <initializer> # new[] (expr-list) type (init)
1747 // ::= [gs] dl <expression> # delete expression
1748 // ::= [gs] da <expression> # delete[] expression
1749 // ::= pp_ <expression> # prefix ++
1750 // ::= mm_ <expression> # prefix --
1751 // ::= ti <type> # typeid (type)
1752 // ::= te <expression> # typeid (expression)
1753 // ::= dc <type> <expression> # dynamic_cast<type> (expression)
1754 // ::= sc <type> <expression> # static_cast<type> (expression)
1755 // ::= cc <type> <expression> # const_cast<type> (expression)
1756 // ::= rc <type> <expression> # reinterpret_cast<type> (expression)
1757 // ::= st <type> # sizeof (a type)
1758 // ::= sz <expression> # sizeof (an expression)
1759 // ::= at <type> # alignof (a type)
1760 // ::= az <expression> # alignof (an expression)
1761 // ::= nx <expression> # noexcept (expression)
1762 // ::= <template-param>
1763 // ::= <function-param>
1764 // ::= dt <expression> <unresolved-name> # expr.name
1765 // ::= pt <expression> <unresolved-name> # expr->name
1766 // ::= ds <expression> <expression> # expr.*expr
1767 // ::= sZ <template-param> # size of a parameter pack
1768 // ::= sZ <function-param> # size of a function parameter pack
1769 // ::= sp <expression> # pack expansion
1770 // ::= tw <expression> # throw expression
1771 // ::= tr # throw with no operand (rethrow)
1772 // ::= <unresolved-name> # f(p), N::f(p), ::f(p),
1773 // # freestanding dependent name (e.g., T::x),
1774 // # objectless nonstatic member reference
1775 // ::= <expr-primary>
1780 Operator expression_operator = TryParseOperator();
1781 switch (expression_operator.kind)
1783 case OperatorKind::Unary:
1784 Write(expression_operator.name);
1786 if (!ParseExpression())
1790 case OperatorKind::Binary:
1791 if (!ParseExpression())
1793 Write(expression_operator.name);
1794 return ParseExpression();
1795 case OperatorKind::Ternary:
1796 if (!ParseExpression())
1799 if (!ParseExpression())
1802 return ParseExpression();
1803 case OperatorKind::NoMatch:
1805 case OperatorKind::Other:
1807 #ifdef DEBUG_FAILURES
1808 printf("*** Unsupported operator: %s\n", expression_operator.name);
1813 switch (*m_read_ptr++)
1815 case 'T': return ParseTemplateParam();
1816 case 'L': return ParseExpressionPrimary();
1818 if (*m_read_ptr++ == 'r')
1819 return ParseUnresolvedName();
1823 return ParseExpressionPrimary();
1827 // <template-arg> ::= <type> # type or template
1828 // ::= X <expression> E # expression
1829 // ::= <expr-primary> # simple expressions
1830 // ::= J <template-arg>* E # argument pack
1831 // ::= LZ <encoding> E # extension
1836 switch (*m_read_ptr) {
1838 #ifdef DEBUG_FAILURES
1839 printf("*** Template argument packs unsupported\n");
1844 if (!ParseExpression())
1849 return ParseExpressionPrimary();
1855 // <template-args> ::= I <template-arg>* E
1856 // extension, the abi says <template-arg>+
1859 ParseTemplateArgs(bool record_template_args = false)
1861 if (record_template_args)
1862 ResetTemplateArgs();
1864 bool first_arg = true;
1865 while (*m_read_ptr != 'E')
1869 else WriteCommaSpace();
1871 int template_start_cookie = GetStartCookie();
1872 if (!ParseTemplateArg())
1874 if (record_template_args)
1875 EndTemplateArg(template_start_cookie);
1881 // <nested-name> ::= N [<CV-qualifiers>] [<ref-qualifier>] <prefix> <unqualified-name> E
1882 // ::= N [<CV-qualifiers>] [<ref-qualifier>] <template-prefix> <template-args> E
1884 // <prefix> ::= <prefix> <unqualified-name>
1885 // ::= <template-prefix> <template-args>
1886 // ::= <template-param>
1889 // ::= <substitution>
1890 // ::= <prefix> <data-member-prefix>
1893 // <template-prefix> ::= <prefix> <template unqualified-name>
1894 // ::= <template-param>
1895 // ::= <substitution>
1897 // <unqualified-name> ::= <operator-name>
1898 // ::= <ctor-dtor-name>
1899 // ::= <source-name>
1900 // ::= <unnamed-type-name>
1903 ParseNestedName(NameState & name_state, bool parse_discriminator = false)
1905 int qualifiers = TryParseQualifiers(true, true);
1906 bool first_part = true;
1907 bool suppress_substitution = true;
1908 int name_start_cookie = GetStartCookie();
1911 char next = *m_read_ptr;
1918 // Record a substitution candidate for all prefixes, but not the full name
1919 if (suppress_substitution)
1920 suppress_substitution = false;
1921 else EndSubstitution(name_start_cookie);
1926 name_state.is_last_generic = true;
1927 WriteTemplateStart();
1928 if (!ParseTemplateArgs(name_state.parse_function_params))
1936 else WriteNamespaceSeparator();
1938 name_state.is_last_generic = false;
1952 int name_start_cookie = GetStartCookie();
1953 if (!ParseSourceName())
1955 name_state.last_name_range = EndRange(name_start_cookie);
1959 if (*++m_read_ptr == 't')
1963 if (!ParseUnqualifiedName(name_state))
1968 if (!ParseSubstitution())
1970 suppress_substitution = true;
1975 if (!ParseTemplateParam())
1980 if (!ParseCtor(name_state))
1985 switch (*(m_read_ptr + 1))
1989 #ifdef DEBUG_FAILURES
1990 printf("*** Decltype unsupported\n");
1995 if (!ParseDtor(name_state))
2001 if (!ParseUnnamedTypeName(name_state))
2006 if (!ParseUnqualifiedName(name_state))
2010 if (!ParseOperatorName(name_state))
2015 if (parse_discriminator)
2016 TryParseDiscriminator();
2017 if (name_state.parse_function_params
2018 && !ParseFunctionArgs(name_state, name_start_cookie))
2023 WriteQualifiers(qualifiers);
2027 // <local-name> := Z <function encoding> E <entity name> [<discriminator>]
2028 // := Z <function encoding> E s [<discriminator>]
2029 // := Z <function encoding> Ed [ <parameter number> ] _ <entity name>
2032 ParseLocalName(bool parse_function_params)
2034 if (!ParseEncoding())
2039 switch (*m_read_ptr)
2043 TryParseDiscriminator(); // Optional and ignored
2044 WRITE("::string literal");
2048 TryParseNumber(); // Optional and ignored
2051 WriteNamespaceSeparator();
2056 WriteNamespaceSeparator();
2057 if (!ParseName(parse_function_params, true))
2059 TryParseDiscriminator(); // Optional and ignored
2064 // <name> ::= <nested-name>
2066 // ::= <unscoped-template-name> <template-args>
2067 // ::= <unscoped-name>
2069 // <unscoped-template-name> ::= <unscoped-name>
2070 // ::= <substitution>
2073 ParseName(bool parse_function_params = false,
2074 bool parse_discriminator = false)
2076 NameState name_state = { parse_function_params, false, false, {0, 0}};
2077 int name_start_cookie = GetStartCookie();
2079 switch (*m_read_ptr)
2083 return ParseNestedName(name_state, parse_discriminator);
2087 if (!ParseLocalName(parse_function_params))
2096 if (!ParseUnscopedName(name_state))
2099 if (*m_read_ptr == 'I')
2101 EndSubstitution(name_start_cookie);
2104 name_state.is_last_generic = true;
2105 WriteTemplateStart();
2106 if (!ParseTemplateArgs(parse_function_params))
2113 if (parse_discriminator)
2114 TryParseDiscriminator();
2115 if (parse_function_params &&
2116 !ParseFunctionArgs(name_state, name_start_cookie))
2123 // <call-offset> ::= h <nv-offset> _
2124 // ::= v <v-offset> _
2126 // <nv-offset> ::= <offset number>
2127 // # non-virtual base override
2129 // <v-offset> ::= <offset number> _ <virtual offset number>
2130 // # virtual base override, with vcall offset
2135 switch (*m_read_ptr++)
2138 if (*m_read_ptr == 'n')
2140 if (TryParseNumber() == -1 || *m_read_ptr++ != '_')
2144 if (*m_read_ptr == 'n')
2146 if (TryParseNumber() == -1 || *m_read_ptr++ != '_')
2148 if (*m_read_ptr == 'n')
2150 if (TryParseNumber() == -1 || *m_read_ptr++ != '_')
2154 #ifdef DEBUG_FAILURES
2155 printf("*** Malformed call offset\n");
2160 // <special-name> ::= TV <type> # virtual table
2161 // ::= TT <type> # VTT structure (construction vtable index)
2162 // ::= TI <type> # typeinfo structure
2163 // ::= TS <type> # typeinfo name (null-terminated byte string)
2164 // ::= Tc <call-offset> <call-offset> <base encoding>
2165 // # base is the nominal target function of thunk
2166 // # first call-offset is 'this' adjustment
2167 // # second call-offset is result adjustment
2168 // ::= T <call-offset> <base encoding>
2169 // # base is the nominal target function of thunk
2170 // extension ::= TC <first type> <number> _ <second type> # construction vtable for second-in-first
2175 switch (*m_read_ptr++)
2178 WRITE("vtable for ");
2184 WRITE("typeinfo for ");
2187 WRITE("typeinfo name for ");
2191 #ifdef DEBUG_FAILURES
2192 printf("*** Unsupported thunk or construction vtable name: %.3s\n", m_read_ptr - 1);
2196 if (*--m_read_ptr == 'v')
2198 WRITE("virtual thunk to ");
2202 WRITE("non-virtual thunk to ");
2204 if (!ParseCallOffset())
2206 return ParseEncoding();
2210 // <special-name> ::= GV <object name> # Guard variable for one-time initialization
2212 // extension ::= GR <object name> # reference temporary for object
2217 switch (*m_read_ptr++)
2220 WRITE("guard variable for ");
2221 if (!ParseName(true))
2225 WRITE("reference temporary for ");
2226 if (!ParseName(true))
2230 #ifdef DEBUG_FAILURES
2231 printf("*** Unknown G encoding\n");
2238 // <bare-function-type> ::= <signature type>+ # types are possible return type, then parameter types
2241 ParseFunctionArgs(NameState & name_state, int return_insert_cookie)
2243 char next = *m_read_ptr;
2244 if (next == 'E' || next == '\0' || next == '.')
2247 // Clang has a bad habit of making unique manglings by just sticking numbers on the end of a symbol,
2248 // which is ambiguous with malformed source name manglings
2249 const char *before_clang_uniquing_test = m_read_ptr;
2250 if (TryParseNumber())
2252 if (*m_read_ptr == '\0')
2254 m_read_ptr = before_clang_uniquing_test;
2257 if (name_state.is_last_generic && !name_state.has_no_return_type)
2259 int return_type_start_cookie = GetStartCookie();
2263 ReorderRange(EndRange(return_type_start_cookie),
2264 return_insert_cookie);
2268 bool first_param = true;
2271 switch (*m_read_ptr)
2281 // Not a formal part of the mangling specification, but clang emits suffixes starting with _block_invoke
2282 if (strncmp(m_read_ptr, "_block_invoke", 13) == 0)
2284 m_read_ptr += strlen(m_read_ptr);
2290 first_param = false;
2291 else WriteCommaSpace();
2303 // <encoding> ::= <function name> <bare-function-type>
2305 // ::= <special-name>
2310 switch (*m_read_ptr)
2314 if (!ParseSpecialNameT())
2319 if (!ParseSpecialNameG())
2323 if (!ParseName(true))
2331 ParseMangling(const char *mangled_name, long mangled_name_length = 0)
2333 if (!mangled_name_length)
2334 mangled_name_length = strlen(mangled_name);
2335 m_read_end = mangled_name + mangled_name_length;
2336 m_read_ptr = mangled_name;
2337 m_write_ptr = m_buffer;
2338 m_next_substitute_index = 0;
2339 m_next_template_arg_index = m_rewrite_ranges_size - 1;
2341 if (*m_read_ptr++ != '_' || *m_read_ptr++ != 'Z')
2343 #ifdef DEBUG_FAILURES
2344 printf("*** Missing _Z prefix\n");
2348 if (!ParseEncoding())
2350 switch (*m_read_ptr)
2355 Write(m_read_ptr, m_read_end - m_read_ptr);
2360 #ifdef DEBUG_FAILURES
2361 printf("*** Unparsed mangled content\n");
2369 // External scratch storage used during demanglings
2372 const char *m_buffer_end;
2373 BufferRange *m_rewrite_ranges;
2374 int m_rewrite_ranges_size;
2376 bool m_owns_m_rewrite_ranges;
2378 // Internal state used during demangling
2380 const char *m_read_ptr;
2381 const char *m_read_end;
2383 int m_next_template_arg_index;
2384 int m_next_substitute_index;
2387 } // Anonymous namespace
2389 // Public entry points referenced from Mangled.cpp
2390 namespace lldb_private
2393 FastDemangle(const char *mangled_name)
2396 SymbolDemangler demangler(buffer, sizeof (buffer));
2397 return demangler.GetDemangledCopy(mangled_name);
2401 FastDemangle(const char *mangled_name, long mangled_name_length)
2404 SymbolDemangler demangler(buffer, sizeof (buffer));
2405 return demangler.GetDemangledCopy(mangled_name, mangled_name_length);
2407 } // lldb_private namespace