aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libstdc++-v3/ChangeLog9
-rw-r--r--libstdc++-v3/include/bits/demangle.h147
-rw-r--r--libstdc++-v3/testsuite/demangle/abi_text/01.cc2
-rw-r--r--libstdc++-v3/testsuite/demangle/regression/cw-16.cc34
4 files changed, 168 insertions, 24 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index aeb77f7..d0c46d0 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -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.
diff --git a/libstdc++-v3/include/bits/demangle.h b/libstdc++-v3/include/bits/demangle.h
index 2858166..872948c 100644
--- a/libstdc++-v3/include/bits/demangle.h
+++ b/libstdc++-v3/include/bits/demangle.h
@@ -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)
@@ -340,11 +344,6 @@ namespace __gnu_cxx
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;
}
diff --git a/libstdc++-v3/testsuite/demangle/abi_text/01.cc b/libstdc++-v3/testsuite/demangle/abi_text/01.cc
index 33cfd01..5563d50 100644
--- a/libstdc++-v3/testsuite/demangle/abi_text/01.cc
+++ b/libstdc++-v3/testsuite/demangle/abi_text/01.cc
@@ -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;
}
diff --git a/libstdc++-v3/testsuite/demangle/regression/cw-16.cc b/libstdc++-v3/testsuite/demangle/regression/cw-16.cc
new file mode 100644
index 0000000..866143a
--- /dev/null
+++ b/libstdc++-v3/testsuite/demangle/regression/cw-16.cc
@@ -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;
+}