re PR libstdc++/12736 (Demangler bug)

PR libstdc++/12736
* bits/demangle.h (qualifier_list<Allocator>::decode_KVrA): Added.
(qualifier_list<Allocator>::decode_qualifiers): Collect concatenated
K, V, r and A qualifiers before processing them as a group.
* testsuite/demangle/abi_text/01.cc: Reordered CV-qualifiers.
* testsuite/demangle/regression/cw-16.cc: New.

From-SVN: r73339
This commit is contained in:
Carlo Wood 2003-11-07 17:55:27 +00:00 committed by Carlo Wood
parent bcc8cc820a
commit 2d369f351f
4 changed files with 168 additions and 24 deletions

View File

@ -1,3 +1,12 @@
2003-11-07 Carlo Wood <carlo@alinoe.com>
PR libstdc++/12736
* bits/demangle.h (qualifier_list<Allocator>::decode_KVrA): Added.
(qualifier_list<Allocator>::decode_qualifiers): Collect concatenated
K, V, r and A qualifiers before processing them as a group.
* testsuite/demangle/abi_text/01.cc: Reordered CV-qualifiers.
* testsuite/demangle/regression/cw-16.cc: New.
2003-11-07 Robert Millan <robertmh@gnu.org>
* configure.host: Add kfreebsd*-gnu and knetbsd*-gnu.

View File

@ -227,6 +227,10 @@ namespace __gnu_cxx
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)
@ -339,11 +343,6 @@ namespace __gnu_cxx
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)
@ -384,6 +383,8 @@ namespace __gnu_cxx
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);
@ -1382,8 +1383,11 @@ namespace __gnu_cxx
// <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
@ -1411,6 +1415,86 @@ namespace __gnu_cxx
// 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(
@ -1419,9 +1503,12 @@ namespace __gnu_cxx
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())
@ -1437,40 +1524,54 @@ namespace __gnu_cxx
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;
@ -1479,9 +1580,9 @@ namespace __gnu_cxx
}
break;
}
if (qualifier_char != 'A')
++iter;
}
if (cvq)
decode_KVrA(prefix, postfix, cvq|cvq_last, iter_array);
M_printing_suppressed = false;
_GLIBCXX_DEMANGLER_RETURN3;
}

View File

@ -36,7 +36,7 @@ int main()
// standard text
// verify_demangle("U4_farrVKPi", "int* volatile const restrict _far");
// new __cxa_demangle
verify_demangle("U4_farrVKPi", "int* restrict volatile const _far");
verify_demangle("U4_farrVKPi", "int* const volatile restrict _far");
return 0;
}

View File

@ -0,0 +1,34 @@
// 2003-10-14 Carlo Wood <carlo@alinoe.com>
// Copyright (C) 2003 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 2, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING. If not, write to the Free
// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
// USA.
// IA 64 C++ ABI - 5.1 External Names (a.k.a. Mangling)
#include <testsuite_hooks.h>
// libcwd tests
int main()
{
using namespace __gnu_test;
verify_demangle("_Z3fooIA6_KiEvA9_KT_rVPrS4_",
"void foo<int const [6]>(int const [9][6], int const restrict (* volatile restrict) [9][6])");
return 0;
}