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 if (content >= m_buffer && content < m_buffer_end)
388 long offset = content - m_buffer;
389 GrowBuffer (end_m_write_ptr - m_buffer_end);
390 content = m_buffer + offset;
394 GrowBuffer (end_m_write_ptr - m_buffer_end);
396 end_m_write_ptr = m_write_ptr + content_length;
398 memcpy (m_write_ptr, content, content_length);
399 m_write_ptr = end_m_write_ptr;
401 #define WRITE(x) Write(x, sizeof (x) - 1)
412 // Put a space between terminal > characters when nesting templates
413 if (m_write_ptr != m_buffer && *(m_write_ptr - 1) == '>')
425 WriteNamespaceSeparator()
437 WriteQualifiers(int qualifiers, bool space_before_reference = true)
439 if (qualifiers & QualifierPointer)
441 if (qualifiers & QualifierConst)
443 if (qualifiers & QualifierVolatile)
445 if (qualifiers & QualifierRestrict)
447 if (qualifiers & QualifierReference)
449 if (space_before_reference)
453 if (qualifiers & QualifierRValueReference)
455 if (space_before_reference)
461 //----------------------------------------------------
464 // Write another copy of content already present
465 // earlier in the output buffer
466 //----------------------------------------------------
469 RewriteRange(BufferRange range)
471 Write(m_buffer + range.offset, range.length);
475 RewriteSubstitution(int index)
477 if (index < 0 || index >= m_next_substitute_index)
479 #ifdef DEBUG_FAILURES
480 printf("*** Invalid substitution #%d\n", index);
484 RewriteRange(m_rewrite_ranges[index]);
489 RewriteTemplateArg(int template_index)
491 int index = m_rewrite_ranges_size - 1 - template_index;
492 if (template_index < 0 || index <= m_next_template_arg_index)
494 #ifdef DEBUG_FAILURES
495 printf("*** Invalid template arg reference #%d\n", template_index);
499 RewriteRange(m_rewrite_ranges[index]);
503 //----------------------------------------------------
506 // Provide information with return values instead of
507 // writing to the output buffer
509 // Values indicating failure guarantee that the pre-
510 // call m_read_ptr is unchanged
511 //----------------------------------------------------
516 unsigned char digit = *m_read_ptr - '0';
523 digit = *++m_read_ptr - '0';
527 count = count * 10 + digit;
533 TryParseBase36Number()
535 char digit = *m_read_ptr;
537 if (digit >= '0' && digit <= '9')
538 count = digit -= '0';
539 else if (digit >= 'A' && digit <= 'Z')
540 count = digit -= ('A' - 10);
545 digit = *++m_read_ptr;
546 if (digit >= '0' && digit <= '9')
548 else if (digit >= 'A' && digit <= 'Z')
552 count = count * 36 + digit;
557 // <builtin-type> ::= v # void
561 // ::= a # signed char
562 // ::= h # unsigned char
564 // ::= t # unsigned short
566 // ::= j # unsigned int
568 // ::= m # unsigned long
569 // ::= x # long long, __int64
570 // ::= y # unsigned long long, __int64
572 // ::= o # unsigned __int128
575 // ::= e # long double, __float80
576 // ::= g # __float128
578 // ::= Dd # IEEE 754r decimal floating point (64 bits)
579 // ::= De # IEEE 754r decimal floating point (128 bits)
580 // ::= Df # IEEE 754r decimal floating point (32 bits)
581 // ::= Dh # IEEE 754r half-precision floating point (16 bits)
584 // ::= Da # auto (in dependent new-expressions)
585 // ::= Dn # std::nullptr_t (i.e., decltype(nullptr))
586 // ::= u <source-name> # vendor extended type
589 TryParseBuiltinType()
591 switch (*m_read_ptr++)
593 case 'v': return "void";
594 case 'w': return "wchar_t";
595 case 'b': return "bool";
596 case 'c': return "char";
597 case 'a': return "signed char";
598 case 'h': return "unsigned char";
599 case 's': return "short";
600 case 't': return "unsigned short";
601 case 'i': return "int";
602 case 'j': return "unsigned int";
603 case 'l': return "long";
604 case 'm': return "unsigned long";
605 case 'x': return "long long";
606 case 'y': return "unsigned long long";
607 case 'n': return "__int128";
608 case 'o': return "unsigned __int128";
609 case 'f': return "float";
610 case 'd': return "double";
611 case 'e': return "long double";
612 case 'g': return "__float128";
613 case 'z': return "...";
616 switch (*m_read_ptr++)
618 case 'd': return "decimal64";
619 case 'e': return "decimal128";
620 case 'f': return "decimal32";
621 case 'h': return "decimal16";
622 case 'i': return "char32_t";
623 case 's': return "char16_t";
624 case 'a': return "auto";
625 case 'c': return "decltype(auto)";
626 case 'n': return "std::nullptr_t";
638 // ::= ad # & (unary)
646 // ::= de # * (unary)
664 // ::= mm # -- (postfix in <expression> context)
667 // ::= ng # - (unary)
676 // ::= pp # ++ (postfix in <expression> context)
677 // ::= ps # + (unary)
684 // ::= cv <type> # (cast)
685 // ::= v <digit> <source-name> # vendor extended operator
690 switch (*m_read_ptr++)
693 switch (*m_read_ptr++)
695 case 'a': return { "&&", OperatorKind::Binary };
696 case 'd': return { "&", OperatorKind::Unary };
697 case 'n': return { "&", OperatorKind::Binary };
698 case 'N': return { "&=", OperatorKind::Binary };
699 case 'S': return { "=", OperatorKind::Binary };
704 switch (*m_read_ptr++)
706 case 'l': return { "()", OperatorKind::Other };
707 case 'm': return { ",", OperatorKind::Other };
708 case 'o': return { "~", OperatorKind::Unary };
709 case 'v': return { nullptr, OperatorKind::ConversionOperator };
714 switch (*m_read_ptr++)
716 case 'a': return { " delete[]", OperatorKind::Other };
717 case 'e': return { "*", OperatorKind::Unary };
718 case 'l': return { " delete", OperatorKind::Other };
719 case 'v': return { "/", OperatorKind::Binary };
720 case 'V': return { "/=", OperatorKind::Binary };
725 switch (*m_read_ptr++)
727 case 'o': return { "^", OperatorKind::Binary };
728 case 'O': return { "^=", OperatorKind::Binary };
729 case 'q': return { "==", OperatorKind::Binary };
734 switch (*m_read_ptr++)
736 case 'e': return { ">=", OperatorKind::Binary };
737 case 't': return { ">", OperatorKind::Binary };
742 switch (*m_read_ptr++)
744 case 'x': return { "[]", OperatorKind::Other };
749 switch (*m_read_ptr++)
751 case 'e': return { "<=", OperatorKind::Binary };
752 case 's': return { "<<", OperatorKind::Binary };
753 case 'S': return { "<<=", OperatorKind::Binary };
754 case 't': return { "<", OperatorKind::Binary };
755 // case 'i': return { "?", OperatorKind::Binary };
760 switch (*m_read_ptr++)
762 case 'i': return { "-", OperatorKind::Binary };
763 case 'I': return { "-=", OperatorKind::Binary };
764 case 'l': return { "*", OperatorKind::Binary };
765 case 'L': return { "*=", OperatorKind::Binary };
766 case 'm': return { "--", OperatorKind::Postfix };
771 switch (*m_read_ptr++)
773 case 'a': return { " new[]", OperatorKind::Other };
774 case 'e': return { "!=", OperatorKind::Binary };
775 case 'g': return { "-", OperatorKind::Unary };
776 case 't': return { "!", OperatorKind::Unary };
777 case 'w': return { " new", OperatorKind::Other };
782 switch (*m_read_ptr++)
784 case 'o': return { "||", OperatorKind::Binary };
785 case 'r': return { "|", OperatorKind::Binary };
786 case 'R': return { "|=", OperatorKind::Binary };
791 switch (*m_read_ptr++)
793 case 'm': return { "->*", OperatorKind::Binary };
794 case 's': return { "+", OperatorKind::Unary };
795 case 'l': return { "+", OperatorKind::Binary };
796 case 'L': return { "+=", OperatorKind::Binary };
797 case 'p': return { "++", OperatorKind::Postfix };
798 case 't': return { "->", OperatorKind::Binary };
803 switch (*m_read_ptr++)
805 case 'u': return { "?", OperatorKind::Ternary };
810 switch (*m_read_ptr++)
812 case 'm': return { "%", OperatorKind::Binary };
813 case 'M': return { "%=", OperatorKind::Binary };
814 case 's': return { ">>", OperatorKind::Binary };
815 case 'S': return { ">=", OperatorKind::Binary };
820 char digit = *m_read_ptr;
821 if (digit >= '0' && digit <= '9')
824 return { nullptr, OperatorKind::Vendor };
830 return { nullptr, OperatorKind::NoMatch };
833 // <CV-qualifiers> ::= [r] [V] [K]
834 // <ref-qualifier> ::= R # & ref-qualifier
835 // <ref-qualifier> ::= O # && ref-qualifier
838 TryParseQualifiers(bool allow_cv, bool allow_ro)
840 int qualifiers = QualifierNone;
841 char next = *m_read_ptr;
844 if (next == 'r') // restrict
846 qualifiers |= QualifierRestrict;
847 next = *++m_read_ptr;
849 if (next == 'V') // volatile
851 qualifiers |= QualifierVolatile;
852 next = *++m_read_ptr;
854 if (next == 'K') // const
856 qualifiers |= QualifierConst;
857 next = *++m_read_ptr;
865 qualifiers |= QualifierReference;
870 qualifiers |= QualifierRValueReference;
876 // <discriminator> := _ <non-negative number> # when number < 10
877 // := __ <non-negative number> _ # when number >= 10
878 // extension := decimal-digit+
881 TryParseDiscriminator()
883 const char *discriminator_start = m_read_ptr;
885 // Test the extension first, since it's what Clang uses
886 int discriminator_value = TryParseNumber();
887 if (discriminator_value != -1)
888 return discriminator_value;
890 char next = *m_read_ptr;
893 next = *++m_read_ptr;
897 discriminator_value = TryParseNumber();
898 if (discriminator_value != -1 && *m_read_ptr++ != '_')
900 return discriminator_value;
903 else if (next >= '0' && next <= '9')
910 // Not a valid discriminator
911 m_read_ptr = discriminator_start;
915 //----------------------------------------------------
918 // Consume input starting from m_read_ptr and produce
919 // buffered output at m_write_ptr
921 // Failures return false and may leave m_read_ptr in an
922 // indeterminate state
923 //----------------------------------------------------
926 Parse(char character)
928 if (*m_read_ptr++ == character)
930 #ifdef DEBUG_FAILURES
931 printf("*** Expected '%c'\n", character);
936 // <number> ::= [n] <non-negative decimal integer>
939 ParseNumber(bool allow_negative = false)
941 if (allow_negative && *m_read_ptr == 'n')
946 const char *before_digits = m_read_ptr;
949 unsigned char digit = *m_read_ptr - '0';
954 if (int digit_count = (int)(m_read_ptr - before_digits))
956 Write(before_digits, digit_count);
959 #ifdef DEBUG_FAILURES
960 printf("*** Expected number\n");
965 // <substitution> ::= S <seq-id> _
967 // <substitution> ::= Sa # ::std::allocator
968 // <substitution> ::= Sb # ::std::basic_string
969 // <substitution> ::= Ss # ::std::basic_string < char,
970 // ::std::char_traits<char>,
971 // ::std::allocator<char> >
972 // <substitution> ::= Si # ::std::basic_istream<char, std::char_traits<char> >
973 // <substitution> ::= So # ::std::basic_ostream<char, std::char_traits<char> >
974 // <substitution> ::= Sd # ::std::basic_iostream<char, std::char_traits<char> >
979 const char *substitution;
982 case 'a': substitution = "std::allocator"; break;
983 case 'b': substitution = "std::basic_string"; break;
984 case 's': substitution = "std::string"; break;
985 case 'i': substitution = "std::istream"; break;
986 case 'o': substitution = "std::ostream"; break;
987 case 'd': substitution = "std::iostream"; break;
989 // A failed attempt to parse a number will return -1 which turns out to be
990 // perfect here as S_ is the first substitution, S0_ the next and so forth
991 int substitution_index = TryParseBase36Number();
992 if (*m_read_ptr++ != '_')
994 #ifdef DEBUG_FAILURES
995 printf("*** Expected terminal _ in substitution\n");
999 return RewriteSubstitution (substitution_index + 1);
1001 Write(substitution);
1006 // <function-type> ::= F [Y] <bare-function-type> [<ref-qualifier>] E
1008 // <bare-function-type> ::= <signature type>+ # types are possible return type, then parameter types
1011 ParseFunctionType (int inner_qualifiers = QualifierNone)
1013 #ifdef DEBUG_FAILURES
1014 printf("*** Function types not supported\n");
1016 //TODO: first steps toward an implementation follow, but they're far
1017 // from complete. Function types tend to bracket other types eg:
1018 // int (*)() when used as the type for "name" becomes int (*name)().
1019 // This makes substitution et al ... interesting.
1023 if (*m_read_ptr == 'Y')
1026 int return_type_start_cookie = GetStartCookie();
1031 int insert_cookie = GetStartCookie();
1033 bool first_param = true;
1034 int qualifiers = QualifierNone;
1037 switch (*m_read_ptr)
1048 if (*(m_read_ptr + 1) == 'E')
1050 qualifiers = TryParseQualifiers (false, true);
1058 first_param = false;
1059 else WriteCommaSpace();
1071 WriteQualifiers (qualifiers);
1072 EndSubstitution (return_type_start_cookie);
1075 if (inner_qualifiers)
1077 int qualifier_start_cookie = GetStartCookie();
1079 WriteQualifiers (inner_qualifiers);
1081 ReorderRange (EndRange (qualifier_start_cookie), insert_cookie);
1087 // <array-type> ::= A <positive dimension number> _ <element type>
1088 // ::= A [<dimension expression>] _ <element type>
1091 ParseArrayType(int qualifiers = QualifierNone)
1093 #ifdef DEBUG_FAILURES
1094 printf("*** Array type unsupported\n");
1096 //TODO: We fail horribly when recalling these as substitutions or
1097 // templates and trying to constify them eg:
1098 // _ZN4llvm2cl5applyIA28_cNS0_3optIbLb0ENS0_6parserIbEEEEEEvRKT_PT0_
1100 //TODO: Chances are we don't do any better with references and pointers
1101 // that should be type (&) [] instead of type & []
1106 if (*m_read_ptr == '_')
1112 WriteQualifiers(qualifiers);
1118 const char *before_digits = m_read_ptr;
1119 if (TryParseNumber() != -1)
1121 const char *after_digits = m_read_ptr;
1127 WriteQualifiers(qualifiers);
1130 Write(before_digits, after_digits - before_digits);
1134 int type_insertion_cookie = GetStartCookie();
1135 if (!ParseExpression())
1140 int type_start_cookie = GetStartCookie();
1144 WriteQualifiers(qualifiers);
1147 ReorderRange (EndRange (type_start_cookie), type_insertion_cookie);
1155 // <pointer-to-member-type> ::= M <class type> <member type>
1157 //TODO: Determine how to handle pointers to function members correctly,
1158 // currently not an issue because we don't have function types at all...
1160 ParsePointerToMemberType()
1162 int insertion_cookie = GetStartCookie();
1168 int type_cookie = GetStartCookie();
1171 ReorderRange (EndRange (type_cookie), insertion_cookie);
1175 // <template-param> ::= T_ # first template parameter
1176 // ::= T <parameter-2 non-negative number> _
1179 ParseTemplateParam()
1181 int count = TryParseNumber();
1185 // When no number is present we get -1, which is convenient since
1186 // T_ is the zeroth element T0_ is element 1, and so on
1187 return RewriteTemplateArg (count + 1);
1190 // <type> ::= <builtin-type>
1191 // ::= <function-type>
1192 // ::= <class-enum-type>
1194 // ::= <pointer-to-member-type>
1195 // ::= <template-param>
1196 // ::= <template-template-param> <template-args>
1198 // ::= <substitution>
1199 // ::= <CV-qualifiers> <type>
1200 // ::= P <type> # pointer-to
1201 // ::= R <type> # reference-to
1202 // ::= O <type> # rvalue reference-to (C++0x)
1203 // ::= C <type> # complex pair (C 2000)
1204 // ::= G <type> # imaginary (C 2000)
1205 // ::= Dp <type> # pack expansion (C++0x)
1206 // ::= U <source-name> <type> # vendor extended type qualifier
1207 // extension := U <objc-name> <objc-type> # objc-type<identifier>
1208 // extension := <vector-type> # <vector-type> starts with Dv
1210 // <objc-name> ::= <k0 number> objcproto <k1 number> <identifier> # k0 = 9 + <number of digits in k1> + k1
1211 // <objc-type> := <source-name> # PU<11+>objcproto 11objc_object<source-name> 11objc_object -> id<source-name>
1216 #ifdef DEBUG_FAILURES
1217 const char *failed_type = m_read_ptr;
1219 int type_start_cookie = GetStartCookie();
1220 bool suppress_substitution = false;
1222 int qualifiers = TryParseQualifiers (true, false);
1223 switch (*m_read_ptr)
1227 switch (*m_read_ptr++)
1237 #ifdef DEBUG_FAILURES
1238 printf("*** Unsupported type: %.3s\n", failed_type);
1245 if (!ParseTemplateParam())
1250 if (!ParsePointerToMemberType())
1255 if (!ParseArrayType())
1260 if (!ParseFunctionType())
1264 if (*++m_read_ptr == 't')
1273 suppress_substitution = true;
1274 if (!ParseSubstitution())
1280 switch (*++m_read_ptr)
1284 if (!ParseFunctionType(QualifierPointer))
1315 #ifdef DEBUG_FAILURES
1316 printf("*** Unsupported type: %.3s\n", failed_type);
1319 // Test for common cases to avoid TryParseBuiltinType() overhead
1327 if (const char *builtin = TryParseBuiltinType())
1330 suppress_substitution = true;
1340 // Allow base substitutions to be suppressed, but always record
1341 // substitutions for the qualified variant
1342 if (!suppress_substitution)
1343 EndSubstitution(type_start_cookie);
1346 WriteQualifiers(qualifiers, false);
1347 EndSubstitution(type_start_cookie);
1352 // <unnamed-type-name> ::= Ut [ <nonnegative number> ] _
1353 // ::= <closure-type-name>
1355 // <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _
1357 // <lambda-sig> ::= <parameter type>+ # Parameter types or "v" if the lambda has no parameters
1360 ParseUnnamedTypeName(NameState & name_state)
1362 switch (*m_read_ptr++)
1366 int cookie = GetStartCookie();
1368 const char *before_digits = m_read_ptr;
1369 if (TryParseNumber() != -1) Write (before_digits,
1370 m_read_ptr - before_digits);
1374 name_state.last_name_range = EndRange (cookie);
1379 int cookie = GetStartCookie();
1381 const char *before_digits = m_read_ptr;
1382 if (TryParseNumber() != -1) Write (before_digits,
1383 m_read_ptr - before_digits);
1387 name_state.last_name_range = EndRange (cookie);
1391 #ifdef DEBUG_FAILURES
1392 printf("*** Lambda type names unsupported\n");
1396 #ifdef DEBUG_FAILURES
1397 printf("*** Unknown unnamed type %.3s\n", m_read_ptr - 2);
1402 // <ctor-dtor-name> ::= C1 # complete object constructor
1403 // ::= C2 # base object constructor
1404 // ::= C3 # complete object allocating constructor
1407 ParseCtor(NameState & name_state)
1409 char next = *m_read_ptr;
1410 if (next == '1' || next == '2' || next == '3' || next == '5')
1412 RewriteRange (name_state.last_name_range);
1413 name_state.has_no_return_type = true;
1417 #ifdef DEBUG_FAILURES
1418 printf("*** Broken constructor\n");
1423 // <ctor-dtor-name> ::= D0 # deleting destructor
1424 // ::= D1 # complete object destructor
1425 // ::= D2 # base object destructor
1428 ParseDtor(NameState & name_state)
1430 char next = *m_read_ptr;
1431 if (next == '0' || next == '1' || next == '2' || next == '5')
1434 RewriteRange(name_state.last_name_range);
1435 name_state.has_no_return_type = true;
1439 #ifdef DEBUG_FAILURES
1440 printf("*** Broken destructor\n");
1445 // See TryParseOperator()
1448 ParseOperatorName(NameState & name_state)
1450 #ifdef DEBUG_FAILURES
1451 const char *operator_ptr = m_read_ptr;
1453 Operator parsed_operator = TryParseOperator();
1454 if (parsed_operator.name)
1457 Write(parsed_operator.name);
1461 // Handle special operators
1462 switch (parsed_operator.kind)
1464 case OperatorKind::Vendor:
1466 return ParseSourceName();
1467 case OperatorKind::ConversionOperator:
1468 ResetTemplateArgs();
1469 name_state.has_no_return_type = true;
1473 #ifdef DEBUG_FAILURES
1474 printf("*** Unknown operator: %.2s\n", operator_ptr);
1480 // <source-name> ::= <positive length number> <identifier>
1485 int count = TryParseNumber();
1488 #ifdef DEBUG_FAILURES
1489 printf("*** Malformed source name, missing length count\n");
1494 const char *next_m_read_ptr = m_read_ptr + count;
1495 if (next_m_read_ptr > m_read_end)
1497 #ifdef DEBUG_FAILURES
1498 printf("*** Malformed source name, premature termination\n");
1503 if (count >= 10 && strncmp(m_read_ptr, "_GLOBAL__N", 10) == 0)
1504 WRITE("(anonymous namespace)");
1505 else Write(m_read_ptr, count);
1507 m_read_ptr = next_m_read_ptr;
1511 // <unqualified-name> ::= <operator-name>
1512 // ::= <ctor-dtor-name>
1513 // ::= <source-name>
1514 // ::= <unnamed-type-name>
1517 ParseUnqualifiedName(NameState & name_state)
1519 // Note that these are detected directly in ParseNestedName for
1520 // performance rather than switching on the same options twice
1521 char next = *m_read_ptr;
1526 return ParseCtor(name_state);
1529 return ParseDtor(name_state);
1532 return ParseUnnamedTypeName(name_state);
1544 int name_start_cookie = GetStartCookie();
1545 if (!ParseSourceName())
1547 name_state.last_name_range = EndRange(name_start_cookie);
1551 return ParseOperatorName(name_state);
1555 // <unscoped-name> ::= <unqualified-name>
1556 // ::= St <unqualified-name> # ::std::
1557 // extension ::= StL<unqualified-name>
1560 ParseUnscopedName(NameState & name_state)
1562 if (*m_read_ptr == 'S' && *(m_read_ptr + 1) == 't')
1565 if (*(m_read_ptr += 2) == 'L')
1568 return ParseUnqualifiedName(name_state);
1572 ParseIntegerLiteral(const char *prefix, const char *suffix,
1573 bool allow_negative)
1577 if (!ParseNumber(allow_negative))
1585 ParseBooleanLiteral()
1587 switch (*m_read_ptr++)
1589 case '0': WRITE("false"); break;
1590 case '1': WRITE("true"); break;
1592 #ifdef DEBUG_FAILURES
1593 printf("*** Boolean literal not 0 or 1\n");
1600 // <expr-primary> ::= L <type> <value number> E # integer literal
1601 // ::= L <type> <value float> E # floating literal
1602 // ::= L <string type> E # string literal
1603 // ::= L <nullptr type> E # nullptr literal (i.e., "LDnE")
1604 // ::= L <type> <real-part float> _ <imag-part float> E # complex floating point literal (C 2000)
1605 // ::= L <mangled-name> E # external name
1608 ParseExpressionPrimary()
1610 switch (*m_read_ptr++)
1612 case 'b': return ParseBooleanLiteral();
1613 case 'x': return ParseIntegerLiteral(nullptr, "ll", true);
1614 case 'l': return ParseIntegerLiteral(nullptr, "l", true);
1615 case 'i': return ParseIntegerLiteral(nullptr, nullptr, true);
1616 case 'n': return ParseIntegerLiteral("(__int128)", nullptr, true);
1617 case 'j': return ParseIntegerLiteral(nullptr, "u", false);
1618 case 'm': return ParseIntegerLiteral(nullptr, "ul", false);
1619 case 'y': return ParseIntegerLiteral(nullptr, "ull", false);
1620 case 'o': return ParseIntegerLiteral("(unsigned __int128)",
1623 if (*m_read_ptr++ == 'Z')
1625 if (!ParseEncoding())
1640 #ifdef DEBUG_FAILURES
1641 printf("*** Unsupported primary expression %.5s\n", m_read_ptr - 1);
1645 // Invalid mangled name per
1646 // http://sourcerytools.com/pipermail/cxx-abi-dev/2011-August/002422.html
1647 #ifdef DEBUG_FAILURES
1648 printf("*** Invalid primary expr encoding\n");
1663 // <unresolved-type> ::= <template-param>
1665 // ::= <substitution>
1668 ParseUnresolvedType()
1670 int type_start_cookie = GetStartCookie();
1671 switch (*m_read_ptr++)
1674 if (!ParseTemplateParam())
1676 EndSubstitution(type_start_cookie);
1680 if (*m_read_ptr != 't')
1681 return ParseSubstitution();
1685 NameState type_name = {};
1686 if (!ParseUnqualifiedName(type_name))
1688 EndSubstitution(type_start_cookie);
1694 #ifdef DEBUG_FAILURES
1695 printf("*** Unsupported unqualified type: %3s\n", m_read_ptr - 1);
1701 // <base-unresolved-name> ::= <simple-id> # unresolved name
1702 // extension ::= <operator-name> # unresolved operator-function-id
1703 // extension ::= <operator-name> <template-args> # unresolved operator template-id
1704 // ::= on <operator-name> # unresolved operator-function-id
1705 // ::= on <operator-name> <template-args> # unresolved operator template-id
1706 // ::= dn <destructor-name> # destructor or pseudo-destructor;
1707 // # e.g. ~X or ~X<N-1>
1710 ParseBaseUnresolvedName()
1712 #ifdef DEBUG_FAILURES
1713 printf("*** Base unresolved name unsupported\n");
1718 // <unresolved-name>
1719 // extension ::= srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
1720 // ::= [gs] <base-unresolved-name> # x or (with "gs") ::x
1721 // ::= [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
1722 // # A::x, N::y, A<T>::z; "gs" means leading "::"
1723 // ::= sr <unresolved-type> <base-unresolved-name> # T::x / decltype(p)::x
1724 // extension ::= sr <unresolved-type> <template-args> <base-unresolved-name>
1725 // # T::N::x /decltype(p)::N::x
1726 // (ignored) ::= srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>
1729 ParseUnresolvedName()
1731 #ifdef DEBUG_FAILURES
1732 printf("*** Unresolved names not supported\n");
1734 //TODO: grammar for all of this seems unclear...
1738 if (*m_read_ptr == 'g' && *(m_read_ptr + 1) == 's')
1741 WriteNamespaceSeparator();
1746 // <expression> ::= <unary operator-name> <expression>
1747 // ::= <binary operator-name> <expression> <expression>
1748 // ::= <ternary operator-name> <expression> <expression> <expression>
1749 // ::= cl <expression>+ E # call
1750 // ::= cv <type> <expression> # conversion with one argument
1751 // ::= cv <type> _ <expression>* E # conversion with a different number of arguments
1752 // ::= [gs] nw <expression>* _ <type> E # new (expr-list) type
1753 // ::= [gs] nw <expression>* _ <type> <initializer> # new (expr-list) type (init)
1754 // ::= [gs] na <expression>* _ <type> E # new[] (expr-list) type
1755 // ::= [gs] na <expression>* _ <type> <initializer> # new[] (expr-list) type (init)
1756 // ::= [gs] dl <expression> # delete expression
1757 // ::= [gs] da <expression> # delete[] expression
1758 // ::= pp_ <expression> # prefix ++
1759 // ::= mm_ <expression> # prefix --
1760 // ::= ti <type> # typeid (type)
1761 // ::= te <expression> # typeid (expression)
1762 // ::= dc <type> <expression> # dynamic_cast<type> (expression)
1763 // ::= sc <type> <expression> # static_cast<type> (expression)
1764 // ::= cc <type> <expression> # const_cast<type> (expression)
1765 // ::= rc <type> <expression> # reinterpret_cast<type> (expression)
1766 // ::= st <type> # sizeof (a type)
1767 // ::= sz <expression> # sizeof (an expression)
1768 // ::= at <type> # alignof (a type)
1769 // ::= az <expression> # alignof (an expression)
1770 // ::= nx <expression> # noexcept (expression)
1771 // ::= <template-param>
1772 // ::= <function-param>
1773 // ::= dt <expression> <unresolved-name> # expr.name
1774 // ::= pt <expression> <unresolved-name> # expr->name
1775 // ::= ds <expression> <expression> # expr.*expr
1776 // ::= sZ <template-param> # size of a parameter pack
1777 // ::= sZ <function-param> # size of a function parameter pack
1778 // ::= sp <expression> # pack expansion
1779 // ::= tw <expression> # throw expression
1780 // ::= tr # throw with no operand (rethrow)
1781 // ::= <unresolved-name> # f(p), N::f(p), ::f(p),
1782 // # freestanding dependent name (e.g., T::x),
1783 // # objectless nonstatic member reference
1784 // ::= <expr-primary>
1789 Operator expression_operator = TryParseOperator();
1790 switch (expression_operator.kind)
1792 case OperatorKind::Unary:
1793 Write(expression_operator.name);
1795 if (!ParseExpression())
1799 case OperatorKind::Binary:
1800 if (!ParseExpression())
1802 Write(expression_operator.name);
1803 return ParseExpression();
1804 case OperatorKind::Ternary:
1805 if (!ParseExpression())
1808 if (!ParseExpression())
1811 return ParseExpression();
1812 case OperatorKind::NoMatch:
1814 case OperatorKind::Other:
1816 #ifdef DEBUG_FAILURES
1817 printf("*** Unsupported operator: %s\n", expression_operator.name);
1822 switch (*m_read_ptr++)
1824 case 'T': return ParseTemplateParam();
1825 case 'L': return ParseExpressionPrimary();
1827 if (*m_read_ptr++ == 'r')
1828 return ParseUnresolvedName();
1832 return ParseExpressionPrimary();
1836 // <template-arg> ::= <type> # type or template
1837 // ::= X <expression> E # expression
1838 // ::= <expr-primary> # simple expressions
1839 // ::= J <template-arg>* E # argument pack
1840 // ::= LZ <encoding> E # extension
1845 switch (*m_read_ptr) {
1847 #ifdef DEBUG_FAILURES
1848 printf("*** Template argument packs unsupported\n");
1853 if (!ParseExpression())
1858 return ParseExpressionPrimary();
1864 // <template-args> ::= I <template-arg>* E
1865 // extension, the abi says <template-arg>+
1868 ParseTemplateArgs(bool record_template_args = false)
1870 if (record_template_args)
1871 ResetTemplateArgs();
1873 bool first_arg = true;
1874 while (*m_read_ptr != 'E')
1878 else WriteCommaSpace();
1880 int template_start_cookie = GetStartCookie();
1881 if (!ParseTemplateArg())
1883 if (record_template_args)
1884 EndTemplateArg(template_start_cookie);
1890 // <nested-name> ::= N [<CV-qualifiers>] [<ref-qualifier>] <prefix> <unqualified-name> E
1891 // ::= N [<CV-qualifiers>] [<ref-qualifier>] <template-prefix> <template-args> E
1893 // <prefix> ::= <prefix> <unqualified-name>
1894 // ::= <template-prefix> <template-args>
1895 // ::= <template-param>
1898 // ::= <substitution>
1899 // ::= <prefix> <data-member-prefix>
1902 // <template-prefix> ::= <prefix> <template unqualified-name>
1903 // ::= <template-param>
1904 // ::= <substitution>
1906 // <unqualified-name> ::= <operator-name>
1907 // ::= <ctor-dtor-name>
1908 // ::= <source-name>
1909 // ::= <unnamed-type-name>
1912 ParseNestedName(NameState & name_state, bool parse_discriminator = false)
1914 int qualifiers = TryParseQualifiers(true, true);
1915 bool first_part = true;
1916 bool suppress_substitution = true;
1917 int name_start_cookie = GetStartCookie();
1920 char next = *m_read_ptr;
1927 // Record a substitution candidate for all prefixes, but not the full name
1928 if (suppress_substitution)
1929 suppress_substitution = false;
1930 else EndSubstitution(name_start_cookie);
1935 name_state.is_last_generic = true;
1936 WriteTemplateStart();
1937 if (!ParseTemplateArgs(name_state.parse_function_params))
1945 else WriteNamespaceSeparator();
1947 name_state.is_last_generic = false;
1961 int name_start_cookie = GetStartCookie();
1962 if (!ParseSourceName())
1964 name_state.last_name_range = EndRange(name_start_cookie);
1968 if (*++m_read_ptr == 't')
1972 if (!ParseUnqualifiedName(name_state))
1977 if (!ParseSubstitution())
1979 suppress_substitution = true;
1984 if (!ParseTemplateParam())
1989 if (!ParseCtor(name_state))
1994 switch (*(m_read_ptr + 1))
1998 #ifdef DEBUG_FAILURES
1999 printf("*** Decltype unsupported\n");
2004 if (!ParseDtor(name_state))
2010 if (!ParseUnnamedTypeName(name_state))
2015 if (!ParseUnqualifiedName(name_state))
2019 if (!ParseOperatorName(name_state))
2024 if (parse_discriminator)
2025 TryParseDiscriminator();
2026 if (name_state.parse_function_params
2027 && !ParseFunctionArgs(name_state, name_start_cookie))
2032 WriteQualifiers(qualifiers);
2036 // <local-name> := Z <function encoding> E <entity name> [<discriminator>]
2037 // := Z <function encoding> E s [<discriminator>]
2038 // := Z <function encoding> Ed [ <parameter number> ] _ <entity name>
2041 ParseLocalName(bool parse_function_params)
2043 if (!ParseEncoding())
2048 switch (*m_read_ptr)
2052 TryParseDiscriminator(); // Optional and ignored
2053 WRITE("::string literal");
2057 TryParseNumber(); // Optional and ignored
2060 WriteNamespaceSeparator();
2065 WriteNamespaceSeparator();
2066 if (!ParseName(parse_function_params, true))
2068 TryParseDiscriminator(); // Optional and ignored
2073 // <name> ::= <nested-name>
2075 // ::= <unscoped-template-name> <template-args>
2076 // ::= <unscoped-name>
2078 // <unscoped-template-name> ::= <unscoped-name>
2079 // ::= <substitution>
2082 ParseName(bool parse_function_params = false,
2083 bool parse_discriminator = false)
2085 NameState name_state = { parse_function_params, false, false, {0, 0}};
2086 int name_start_cookie = GetStartCookie();
2088 switch (*m_read_ptr)
2092 return ParseNestedName(name_state, parse_discriminator);
2096 if (!ParseLocalName(parse_function_params))
2105 if (!ParseUnscopedName(name_state))
2108 if (*m_read_ptr == 'I')
2110 EndSubstitution(name_start_cookie);
2113 name_state.is_last_generic = true;
2114 WriteTemplateStart();
2115 if (!ParseTemplateArgs(parse_function_params))
2122 if (parse_discriminator)
2123 TryParseDiscriminator();
2124 if (parse_function_params &&
2125 !ParseFunctionArgs(name_state, name_start_cookie))
2132 // <call-offset> ::= h <nv-offset> _
2133 // ::= v <v-offset> _
2135 // <nv-offset> ::= <offset number>
2136 // # non-virtual base override
2138 // <v-offset> ::= <offset number> _ <virtual offset number>
2139 // # virtual base override, with vcall offset
2144 switch (*m_read_ptr++)
2147 if (*m_read_ptr == 'n')
2149 if (TryParseNumber() == -1 || *m_read_ptr++ != '_')
2153 if (*m_read_ptr == 'n')
2155 if (TryParseNumber() == -1 || *m_read_ptr++ != '_')
2157 if (*m_read_ptr == 'n')
2159 if (TryParseNumber() == -1 || *m_read_ptr++ != '_')
2163 #ifdef DEBUG_FAILURES
2164 printf("*** Malformed call offset\n");
2169 // <special-name> ::= TV <type> # virtual table
2170 // ::= TT <type> # VTT structure (construction vtable index)
2171 // ::= TI <type> # typeinfo structure
2172 // ::= TS <type> # typeinfo name (null-terminated byte string)
2173 // ::= Tc <call-offset> <call-offset> <base encoding>
2174 // # base is the nominal target function of thunk
2175 // # first call-offset is 'this' adjustment
2176 // # second call-offset is result adjustment
2177 // ::= T <call-offset> <base encoding>
2178 // # base is the nominal target function of thunk
2179 // extension ::= TC <first type> <number> _ <second type> # construction vtable for second-in-first
2184 switch (*m_read_ptr++)
2187 WRITE("vtable for ");
2193 WRITE("typeinfo for ");
2196 WRITE("typeinfo name for ");
2200 #ifdef DEBUG_FAILURES
2201 printf("*** Unsupported thunk or construction vtable name: %.3s\n", m_read_ptr - 1);
2205 if (*--m_read_ptr == 'v')
2207 WRITE("virtual thunk to ");
2211 WRITE("non-virtual thunk to ");
2213 if (!ParseCallOffset())
2215 return ParseEncoding();
2219 // <special-name> ::= GV <object name> # Guard variable for one-time initialization
2221 // extension ::= GR <object name> # reference temporary for object
2226 switch (*m_read_ptr++)
2229 WRITE("guard variable for ");
2230 if (!ParseName(true))
2234 WRITE("reference temporary for ");
2235 if (!ParseName(true))
2239 #ifdef DEBUG_FAILURES
2240 printf("*** Unknown G encoding\n");
2247 // <bare-function-type> ::= <signature type>+ # types are possible return type, then parameter types
2250 ParseFunctionArgs(NameState & name_state, int return_insert_cookie)
2252 char next = *m_read_ptr;
2253 if (next == 'E' || next == '\0' || next == '.')
2256 // Clang has a bad habit of making unique manglings by just sticking numbers on the end of a symbol,
2257 // which is ambiguous with malformed source name manglings
2258 const char *before_clang_uniquing_test = m_read_ptr;
2259 if (TryParseNumber())
2261 if (*m_read_ptr == '\0')
2263 m_read_ptr = before_clang_uniquing_test;
2266 if (name_state.is_last_generic && !name_state.has_no_return_type)
2268 int return_type_start_cookie = GetStartCookie();
2272 ReorderRange(EndRange(return_type_start_cookie),
2273 return_insert_cookie);
2277 bool first_param = true;
2280 switch (*m_read_ptr)
2290 // Not a formal part of the mangling specification, but clang emits suffixes starting with _block_invoke
2291 if (strncmp(m_read_ptr, "_block_invoke", 13) == 0)
2293 m_read_ptr += strlen(m_read_ptr);
2299 first_param = false;
2300 else WriteCommaSpace();
2312 // <encoding> ::= <function name> <bare-function-type>
2314 // ::= <special-name>
2319 switch (*m_read_ptr)
2323 if (!ParseSpecialNameT())
2328 if (!ParseSpecialNameG())
2332 if (!ParseName(true))
2340 ParseMangling(const char *mangled_name, long mangled_name_length = 0)
2342 if (!mangled_name_length)
2343 mangled_name_length = strlen(mangled_name);
2344 m_read_end = mangled_name + mangled_name_length;
2345 m_read_ptr = mangled_name;
2346 m_write_ptr = m_buffer;
2347 m_next_substitute_index = 0;
2348 m_next_template_arg_index = m_rewrite_ranges_size - 1;
2350 if (*m_read_ptr++ != '_' || *m_read_ptr++ != 'Z')
2352 #ifdef DEBUG_FAILURES
2353 printf("*** Missing _Z prefix\n");
2357 if (!ParseEncoding())
2359 switch (*m_read_ptr)
2364 Write(m_read_ptr, m_read_end - m_read_ptr);
2369 #ifdef DEBUG_FAILURES
2370 printf("*** Unparsed mangled content\n");
2378 // External scratch storage used during demanglings
2381 const char *m_buffer_end;
2382 BufferRange *m_rewrite_ranges;
2383 int m_rewrite_ranges_size;
2385 bool m_owns_m_rewrite_ranges;
2387 // Internal state used during demangling
2389 const char *m_read_ptr;
2390 const char *m_read_end;
2392 int m_next_template_arg_index;
2393 int m_next_substitute_index;
2396 } // Anonymous namespace
2398 // Public entry points referenced from Mangled.cpp
2399 namespace lldb_private
2402 FastDemangle(const char *mangled_name)
2405 SymbolDemangler demangler(buffer, sizeof (buffer));
2406 return demangler.GetDemangledCopy(mangled_name);
2410 FastDemangle(const char *mangled_name, long mangled_name_length)
2413 SymbolDemangler demangler(buffer, sizeof (buffer));
2414 return demangler.GetDemangledCopy(mangled_name, mangled_name_length);
2416 } // lldb_private namespace