📄 demangle.h
字号:
{ string_type index = (*iter).get_optional_type(); if (--n == 0 && (cvq & cvq_last)) postfix = " [" + index + "]" + postfix; else if (n > 0) postfix = "[" + index + "]" + postfix; else { prefix += " ("; postfix = ") [" + index + "]" + postfix; } break; } default: _GLIBCXX_DEMANGLER_RETURN3; } } } _GLIBCXX_DEMANGLER_RETURN3; } template<typename Tp, typename Allocator> void qualifier_list<Tp, Allocator>::decode_qualifiers( string_type& prefix, string_type& postfix, bool member_function_pointer_qualifiers = false) const { _GLIBCXX_DEMANGLER_DOUT_ENTERING3("decode_qualifiers"); int cvq = 0; typename qual_vector::const_reverse_iterator iter_array; for(typename qual_vector:: const_reverse_iterator iter = M_qualifier_starts.rbegin(); iter != M_qualifier_starts.rend(); ++iter) { if (!member_function_pointer_qualifiers && !(*iter).part_of_substitution()) { int saved_inside_substitution = M_demangler.M_inside_substitution; M_demangler.M_inside_substitution = 0; M_demangler.add_substitution((*iter).get_start_pos(), type); M_demangler.M_inside_substitution = saved_inside_substitution; } char qualifier_char = (*iter).first_qualifier(); for(; qualifier_char; qualifier_char = (*iter).next_qualifier()) { switch(qualifier_char) { case 'P': if (cvq) { decode_KVrA(prefix, postfix, cvq, iter_array); cvq = 0; } prefix += "*"; break; case 'R': if (cvq) { decode_KVrA(prefix, postfix, cvq, iter_array); cvq = 0; } prefix += "&"; break; case 'K': cvq |= cvq_K; continue; case 'V': cvq |= cvq_V; continue; case 'r': cvq |= cvq_r; continue; case 'A': if (!(cvq & cvq_A)) { cvq |= cvq_A; iter_array = iter; } cvq += cvq_A_cnt; break; case 'M': if (cvq) { decode_KVrA(prefix, postfix, cvq, iter_array); cvq = 0; } prefix += " "; prefix += (*iter).get_optional_type(); prefix += "::*"; break; case 'U': if (cvq) { decode_KVrA(prefix, postfix, cvq, iter_array); cvq = 0; } prefix += " "; prefix += (*iter).get_optional_type(); break; case 'G': // Only here so we added a substitution. break; } break; } } if (cvq) decode_KVrA(prefix, postfix, cvq|cvq_last, iter_array); M_printing_suppressed = false; _GLIBCXX_DEMANGLER_RETURN3; } // template<typename Tp, typename Allocator> bool session<Tp, Allocator>::decode_type_with_postfix( string_type& prefix, string_type& postfix, qualifier_list<Tp, Allocator>* qualifiers) { _GLIBCXX_DEMANGLER_DOUT_ENTERING2("decode_type"); ++M_inside_type; bool recursive_template_param_or_substitution_call; if (!(recursive_template_param_or_substitution_call = qualifiers)) { qualifier_list<Allocator>* raw_qualifiers = M_qualifier_list_alloc.allocate(1); qualifiers = new (raw_qualifiers) qualifier_list<Allocator>(*this); } // First eat all qualifiers. bool failure = false; for(;;) // So we can use 'continue' to eat the next qualifier. { int start_pos = M_pos; switch(current()) { case 'P': qualifiers->add_qualifier_start(pointer, start_pos, M_inside_substitution); eat_current(); continue; case 'R': qualifiers->add_qualifier_start(reference, start_pos, M_inside_substitution); eat_current(); continue; case 'K': case 'V': case 'r': { char c; int count = 0; do { ++count; c = next(); } while(c == 'K' || c == 'V' || c == 'r'); qualifiers->add_qualifier_start(cv_qualifier, start_pos, count, M_inside_substitution); continue; } case 'U': { eat_current(); string_type source_name; if (!decode_source_name(source_name)) { failure = true; break; } qualifiers->add_qualifier_start(vendor_extension, start_pos, source_name, M_inside_substitution); continue; } case 'A': { // <array-type> ::= A <positive dimension number> _ <element type> // ::= A [<dimension expression>] _ <element type> // string_type index; int saved_pos; store(saved_pos); if (next() == 'n' || !decode_number(index)) { restore(saved_pos); if (next() != '_' && !decode_expression(index)) { failure = true; break; } } if (eat_current() != '_') { failure = true; break; } qualifiers->add_qualifier_start(array, start_pos, index, M_inside_substitution); continue; } case 'M': { // <pointer-to-member-type> ::= M <class type> <member type> // <Q>M<C> or <Q>M<C><Q2>F<R><B>E eat_current(); string_type class_type; if (!decode_type(class_type)) // Substitution: "<C>". { failure = true; break; } char c = current(); if (c == 'F' || c == 'K' || c == 'V' || c == 'r') // Must be CV-qualifiers and a member function pointer. { // <Q>M<C><Q2>F<R><B>E ==> R (C::*Q)B Q2 // substitutions: "<C>", "F<R><B>E" (<R> and <B> // recursive), "M<C><Q2>F<R><B>E". int count = 0; int Q2_start_pos = M_pos; while(c == 'K' || c == 'V' || c == 'r') // Decode <Q2>. { ++count; c = next(); } qualifier_list<Tp, Allocator> class_type_qualifiers(*this); if (count) class_type_qualifiers. add_qualifier_start(cv_qualifier, Q2_start_pos, count, M_inside_substitution); string_type member_function_qualifiers; // It is unclear why g++ doesn't add a substitution for // "<Q2>F<R><B>E" as it should I think. string_type member_function_qualifiers_postfix; class_type_qualifiers. decode_qualifiers(member_function_qualifiers, member_function_qualifiers_postfix, true); member_function_qualifiers += member_function_qualifiers_postfix; // I don't think this substitution is actually ever used. int function_pos = M_pos; if (eat_current() != 'F') { failure = true; break; } // Return type. // Constructors, destructors and conversion operators don't // have a return type, but seem to never get here. string_type return_type_postfix; if (!decode_type_with_postfix(prefix, return_type_postfix)) // substitution: <R> recursive { failure = true; break; } prefix += " ("; prefix += class_type; prefix += "::*"; string_type bare_function_type; if (!decode_bare_function_type(bare_function_type) || eat_current() != 'E') // Substitution: <B> recursive. { failure = true; break; } // substitution: "F<R><B>E". add_substitution(function_pos, type); // substitution: "M<C><Q2>F<R><B>E". add_substitution(start_pos, type); // substitution: all qualified types if any. qualifiers->decode_qualifiers(prefix, postfix); postfix += ")"; postfix += bare_function_type; postfix += member_function_qualifiers; postfix += return_type_postfix; goto decode_type_exit; } qualifiers->add_qualifier_start(pointer_to_member, start_pos, class_type, M_inside_substitution); continue; } default: break; } break; } if (!failure) { // <Q>G<T> ==> imaginary T Q // substitutions: "<T>", "G<T>" (<T> recursive). // <Q>C<T> ==> complex T Q // substitutions: "<T>", "C<T>" (<T> recursive). if (current() == 'C' || current() == 'G') { prefix += current() == 'C' ? "complex " : "imaginary "; qualifiers->add_qualifier_start(complex_or_imaginary, M_pos, M_inside_substitution); eat_current(); } int start_pos = M_pos; switch(current()) { case 'F': { // <function-type> ::= F [Y] <bare-function-type> E // // Note that g++ never generates the 'Y', but we try to // demangle it anyway. bool extern_C = (next() == 'Y'); if (extern_C) eat_current(); // <Q>F<R><B>E ==> R (Q)B // substitution: "<R>", "<B>" (<B> recursive) and "F<R><B>E". // Return type. string_type return_type_postfix; if (!decode_type_with_postfix(prefix, return_type_postfix)) // Substitution: "<R>". { failure = true; break; } // Only array and function (pointer) types have a postfix. // In that case we don't want the space but expect something // like prefix is "int (*" and postfix is ") [1]". // We do want the space if this pointer is qualified. if (return_type_postfix.size() == 0 || (prefix.size() > 0 && *prefix.rbegin() != '*')) prefix += ' '; prefix += '('; string_type bare_function_type; if (!decode_bare_function_type(bare_function_type) // substitution: "<B>" (<B> recursive). || eat_current() != 'E') { failure = true; break; } add_substitution(start_pos, type); // Substitution: "F<R><B>E". qualifiers->decode_qualifiers(prefix, postfix); // substitution: all qualified types, if any. postfix += ")"; if (extern_C) postfix += " [extern \"C\"] "; postfix += bare_function_type; postfix += return_type_postfix; break; } case 'T': if (!decode_template_param(prefix, qualifiers)) { failure = true; break; } if (current() == 'I') { add_substitution(start_pos, template_template_param); // substitution: "<template-template-param>". if (!decode_template_args(prefix)) { failure = true; break; } } if (!recursive_template_param_or_substitution_call && qualifiers->suppressed()) { add_substitution(start_pos, type); // substitution: "<template-param>" or // "<template-template-param> <template-args>". qualifiers->decode_qualifiers(prefix, postfix); // substitution: all qualified types, if any. } break; case 'S': if (M_pos >= M_maxpos) { failure = true; break; } if (M_str[M_pos + 1] != 't') { if (!decode_substitution(prefix, qualifiers)) { failure = true; break; } if (current() == 'I') { if (!decode_template_args(prefix)) { failure = true; break; } if (!recursive_template_param_or_substitution_call && qualifiers->suppressed()) add_substitution(start_pos, type); // Substitution: // "<template-template-param> <template-args>". } if (!recursive_template_param_or_substitution_call && qualifiers->suppressed()) qualifiers->decode_qualifiers(prefix, postfix); // Substitution: all qualified types, if any. break; } /* Fall-through for St */ case 'N': case 'Z': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': // <Q><T> ==> T Q // substitutions: "<T>" (<T> recursive). if (!decode_class_enum_type(prefix)) { failure = true; break; } if (!recursive_template_param_or_substitution_call) { add_substitution(start_pos, type); // substitution: "<class-enum-type>". qualifiers->decode_q
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -