std::vector<qualifier<Allocator>, Allocator> M_qualifier_starts;
session<Allocator>& M_demangler;
+ void decode_KVrA(string_type& prefix, string_type& postfix, int cvq,
+ typename std::vector<qualifier<Allocator>, Allocator>::
+ const_reverse_iterator const& iter_array) const;
+
public:
qualifier_list(session<Allocator>& demangler_obj)
: M_printing_suppressed(false), M_demangler(demangler_obj)
static int
decode_encoding(string_type& output, char const* input, int len);
- bool
- decode_type_with_postfix(string_type& prefix,
- string_type& postfix,
- qualifier_list<Allocator>* qualifiers = NULL);
-
bool
decode_type(string_type& output,
qualifier_list<Allocator>* qualifiers = NULL)
substitution_nt sub_type,
int number_of_prefixes);
+ bool decode_type_with_postfix(string_type& prefix,
+ string_type& postfix, qualifier_list<Allocator>* qualifiers = NULL);
bool decode_bare_function_type(string_type& output);
bool decode_builtin_type(string_type& output);
bool decode_call_offset(string_type& output);
// <Q>M<C> ==> C::*Q "M<C>..." (<C> recurs.)
// A<I> ==> [I] "A<I>..." (<I> recurs.)
// <Q>A<I> ==> (Q) [I] "A<I>..." (<I> recurs.)
- // Note that when <Q> ends on an A<I2> then the brackets are omitted:
- // A<I2>A<I> ==> [I2][I]
+ // Note that when <Q> ends on an A<I2> then the brackets are omitted
+ // and no space is written between the two:
+ // A<I2>A<I> ==> [I2][I]
+ // If <Q> ends on [KVr]+, which can happen in combination with
+ // substitutions only, then special handling is required, see below.
//
// A <substitution> is handled with an input position switch during which
// new substitutions are turned off. Because recursive handling of types
// For some weird reason, g++ (3.2.1) does not add substitutions for
// qualified member function pointers. I think that is another bug.
//
+
+ // In the case of
+ // <Q>A<I>
+ // where <Q> ends on [K|V|r]+ then that part should be processed as
+ // if it was behind the A<I> instead of in front of it. This is
+ // because a constant array of ints is normally always mangled as
+ // an array of constant ints. KVr qualifiers can end up in front
+ // of an array when the array is part of a substitution or template
+ // parameter, but the demangling should still result in the same
+ // syntax; thus KA2_i (const array of ints) must result in the same
+ // demangling as A2_Ki (array of const ints). As a result we must
+ // demangle ...[...[[KVr]+A<I0>][KVr]+A<I1>]...[KVr]+A<In>[KVr]+
+ // as A<I0>A<I1>...A<In>[KVr]+ where each K, V and r in the series
+ // collapses to a single character at the right of the string.
+ // For example:
+ // VA9_KrA6_KVi --> A9_A6_KVri --> int volatile const restrict [9][6]
+ // Note that substitutions are still added as usual (the translation
+ // to A9_A6_KVri does not really happen).
+ //
+ // This decoding is achieved by delaying the decoding of any sequence
+ // of [KVrA]'s and processing them together in the order: first the
+ // short-circuited KVr part and then the arrays.
+ static int const cvq_K = 1; // Saw at least one K
+ static int const cvq_V = 2; // Saw at least one V
+ static int const cvq_r = 4; // Saw at least one r
+ static int const cvq_A = 8; // Saw at least one A
+ static int const cvq_last = 16; // No remaining qualifiers.
+ static int const cvq_A_cnt = 32; // Bit 5 and higher represent the
+ // number of A's in the series.
+ // In the function below, iter_array points to the first (right most)
+ // A in the series, if any.
+ template<typename Allocator>
+ void
+ qualifier_list<Allocator>::decode_KVrA(
+ string_type& prefix, string_type& postfix, int cvq,
+ typename std::vector<qualifier<Allocator>, Allocator>::
+ const_reverse_iterator const& iter_array) const
+ {
+ _GLIBCXX_DEMANGLER_DOUT_ENTERING3("decode_KVrA");
+ if ((cvq & cvq_K))
+ prefix += " const";
+ if ((cvq & cvq_V))
+ prefix += " volatile";
+ if ((cvq & cvq_r))
+ prefix += " restrict";
+ if ((cvq & cvq_A))
+ {
+ int n = cvq >> 5;
+ for (typename std::vector<qualifier<Allocator>, Allocator>::
+ const_reverse_iterator iter = iter_array;
+ iter != M_qualifier_starts.rend(); ++iter)
+ {
+ switch((*iter).first_qualifier())
+ {
+ case 'K':
+ case 'V':
+ case 'r':
+ break;
+ case 'A':
+ {
+ 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 Allocator>
void
qualifier_list<Allocator>::decode_qualifiers(
bool member_function_pointer_qualifiers = false) const
{
_GLIBCXX_DEMANGLER_DOUT_ENTERING3("decode_qualifiers");
+ int cvq = 0;
+ typename std::vector<qualifier<Allocator>, Allocator>::
+ const_reverse_iterator iter_array;
for(typename std::vector<qualifier<Allocator>, Allocator>::
const_reverse_iterator iter = M_qualifier_starts.rbegin();
- iter != M_qualifier_starts.rend();)
+ iter != M_qualifier_starts.rend(); ++iter)
{
if (!member_function_pointer_qualifiers
&& !(*iter).part_of_substitution())
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':
- prefix += " const";
+ cvq |= cvq_K;
continue;
case 'V':
- prefix += " volatile";
+ cvq |= cvq_V;
continue;
case 'r':
- prefix += " restrict";
+ cvq |= cvq_r;
continue;
case 'A':
- {
- string_type index = (*iter).get_optional_type();
- if (++iter == M_qualifier_starts.rend())
- postfix = " [" + index + "]" + postfix;
- else if ((*iter).first_qualifier() == 'A')
- postfix = "[" + index + "]" + postfix;
- else
+ if (!(cvq & cvq_A))
{
- prefix += " (";
- postfix = ") [" + index + "]" + postfix;
+ 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;
}
break;
}
- if (qualifier_char != 'A')
- ++iter;
}
+ if (cvq)
+ decode_KVrA(prefix, postfix, cvq|cvq_last, iter_array);
M_printing_suppressed = false;
_GLIBCXX_DEMANGLER_RETURN3;
}