From 6546dadbe7001802d9d89bca567face092bf4ba9 Mon Sep 17 00:00:00 2001 From: carlo Date: Fri, 7 Nov 2003 17:55:27 +0000 Subject: [PATCH] PR libstdc++/12736 * bits/demangle.h (qualifier_list::decode_KVrA): Added. (qualifier_list::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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@73339 138bc75d-0d04-0410-961f-82ee72b054a4 --- libstdc++-v3/ChangeLog | 9 ++ libstdc++-v3/include/bits/demangle.h | 147 +++++++++++++++++---- libstdc++-v3/testsuite/demangle/abi_text/01.cc | 2 +- .../testsuite/demangle/regression/cw-16.cc | 34 +++++ 4 files changed, 168 insertions(+), 24 deletions(-) create mode 100644 libstdc++-v3/testsuite/demangle/regression/cw-16.cc 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 + + PR libstdc++/12736 + * bits/demangle.h (qualifier_list::decode_KVrA): Added. + (qualifier_list::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 * 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, Allocator> M_qualifier_starts; session& M_demangler; + void decode_KVrA(string_type& prefix, string_type& postfix, int cvq, + typename std::vector, Allocator>:: + const_reverse_iterator const& iter_array) const; + public: qualifier_list(session& 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* qualifiers = NULL); - - bool decode_type(string_type& output, qualifier_list* 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* 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 // M ==> C::*Q "M..." ( recurs.) // A ==> [I] "A..." ( recurs.) // A ==> (Q) [I] "A..." ( recurs.) - // Note that when ends on an A then the brackets are omitted: - // AA ==> [I2][I] + // Note that when ends on an A then the brackets are omitted + // and no space is written between the two: + // AA ==> [I2][I] + // If ends on [KVr]+, which can happen in combination with + // substitutions only, then special handling is required, see below. // // A 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 + // A + // where ends on [K|V|r]+ then that part should be processed as + // if it was behind the A 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][KVr]+A]...[KVr]+A[KVr]+ + // as AA...A[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 + void + qualifier_list::decode_KVrA( + string_type& prefix, string_type& postfix, int cvq, + typename std::vector, 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, 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 void qualifier_list::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, Allocator>:: + const_reverse_iterator iter_array; for(typename std::vector, 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 + +// 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 + +// libcwd tests +int main() +{ + using namespace __gnu_test; + +verify_demangle("_Z3fooIA6_KiEvA9_KT_rVPrS4_", + "void foo(int const [9][6], int const restrict (* volatile restrict) [9][6])"); + + return 0; +} -- 2.7.4