re PR libstdc++/16848 (code in /ext/demangle.h appears broken)
authorBenjamin Kosnik <bkoz@redhat.com>
Thu, 2 Sep 2004 16:56:29 +0000 (16:56 +0000)
committerBenjamin Kosnik <bkoz@gcc.gnu.org>
Thu, 2 Sep 2004 16:56:29 +0000 (16:56 +0000)
2004-09-02  Benjamin Kosnik  <bkoz@redhat.com>

PR libstdc++/16848
* include/Makefile.am (ext_headers): Remove demangle.h.
* include/Makefile.in: Regenerate.
* include/ext/demangle.h: Remove.

From-SVN: r86968

libstdc++-v3/ChangeLog
libstdc++-v3/include/Makefile.am
libstdc++-v3/include/Makefile.in
libstdc++-v3/include/ext/demangle.h [deleted file]

index a230dc9c3c4ac79f4124c663b2dc3517fd198238..aff78de24366ea676f753d1013562c85b02086c4 100644 (file)
@@ -1,3 +1,10 @@
+2004-09-02  Benjamin Kosnik  <bkoz@redhat.com>
+
+       PR libstdc++/16848
+       * include/Makefile.am (ext_headers): Remove demangle.h.
+       * include/Makefile.in: Regenerate.
+       * include/ext/demangle.h: Remove.
+
 2004-09-01  Benjamin Kosnik  <bkoz@redhat.com>
 
        PR libstdc++/16614
index c502d72527fa144acbfe62b7a97884adc3567c82..3e99d3329f2de082afc0399ecb01d9c274158eb4 100644 (file)
@@ -203,7 +203,6 @@ ext_headers = \
        ${ext_srcdir}/algorithm \
        ${ext_srcdir}/bitmap_allocator.h \
        ${ext_srcdir}/debug_allocator.h \
-       ${ext_srcdir}/demangle.h \
        ${ext_srcdir}/enc_filebuf.h \
        ${ext_srcdir}/stdio_filebuf.h \
        ${ext_srcdir}/stdio_sync_filebuf.h \
index 95893581c5c23051c02fb96fe5d959d965323107..6f78ffac412fccff3d7346a922f68014b68057b1 100644 (file)
@@ -418,7 +418,6 @@ ext_headers = \
        ${ext_srcdir}/algorithm \
        ${ext_srcdir}/bitmap_allocator.h \
        ${ext_srcdir}/debug_allocator.h \
-       ${ext_srcdir}/demangle.h \
        ${ext_srcdir}/enc_filebuf.h \
        ${ext_srcdir}/stdio_filebuf.h \
        ${ext_srcdir}/stdio_sync_filebuf.h \
diff --git a/libstdc++-v3/include/ext/demangle.h b/libstdc++-v3/include/ext/demangle.h
deleted file mode 100644 (file)
index 5de4f04..0000000
+++ /dev/null
@@ -1,2789 +0,0 @@
-// C++ IA64 / g++ v3 demangler  -*- C++ -*-
-
-// Copyright (C) 2003, 2004 Free Software Foundation, Inc.
-// Written by Carlo Wood <carlo@alinoe.com>
-//
-// 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.
-
-// As a special exception, you may use this file as part of a free software
-// library without restriction.  Specifically, if other files instantiate
-// templates or use macros or inline functions from this file, or you compile
-// this file and link it with other files to produce an executable, this
-// file does not by itself cause the resulting executable to be covered by
-// the GNU General Public License.  This exception does not however
-// invalidate any other reasons why the executable file might be covered by
-// the GNU General Public License.
-
-// This file implements demangling of "C++ ABI for Itanium"-mangled symbol
-// and type names as described in Revision 1.73 of the C++ ABI as can be found
-// at http://www.codesourcery.com/cxx-abi/abi.html#mangling
-
-#ifndef _DEMANGLER_H
-#define _DEMANGLER_H 1
-
-#include <vector>
-#include <string>
-#include <ext/new_allocator.h>
-
-#ifndef _GLIBCXX_DEMANGLER_DEBUG
-#define _GLIBCXX_DEMANGLER_CWDEBUG 0
-#define _GLIBCXX_DEMANGLER_DEBUG(x)
-#define _GLIBCXX_DEMANGLER_DOUT(cntrl, data)
-#define _GLIBCXX_DEMANGLER_DOUT_ENTERING(x)
-#define _GLIBCXX_DEMANGLER_DOUT_ENTERING2(x)
-#define _GLIBCXX_DEMANGLER_DOUT_ENTERING3(x)
-#define _GLIBCXX_DEMANGLER_RETURN return M_result
-#define _GLIBCXX_DEMANGLER_RETURN2 return M_result
-#define _GLIBCXX_DEMANGLER_RETURN3
-#define _GLIBCXX_DEMANGLER_FAILURE \
-    do { M_result = false; return false; } while(0)
-#else
-#define _GLIBCXX_DEMANGLER_CWDEBUG 1
-#endif
-
-namespace __gnu_cxx
-{
-  namespace demangler
-  {
-    enum substitution_nt
-    {
-      type,
-      template_template_param,
-      nested_name_prefix,
-      nested_name_template_prefix,
-      unscoped_template_name
-    };
-
-    struct substitution_st
-    {
-      int M_start_pos;
-      substitution_nt M_type;
-      int M_number_of_prefixes;
-
-      substitution_st(int start_pos,
-                     substitution_nt type,
-                     int number_of_prefixes)
-      : M_start_pos(start_pos), M_type(type),
-       M_number_of_prefixes(number_of_prefixes)
-      { }
-    };
-
-    enum simple_qualifier_nt
-    {
-      complex_or_imaginary = 'G',
-      pointer = 'P',
-      reference = 'R'
-    };
-
-    enum cv_qualifier_nt
-    {
-      cv_qualifier = 'K'
-    };
-
-    enum param_qualifier_nt
-    {
-      vendor_extension = 'U',
-      array = 'A',
-      pointer_to_member = 'M'
-    };
-
-    template<typename Tp, typename Allocator = __gnu_cxx::new_allocator<Tp> >
-      class qualifier;
-
-    template<typename Tp, typename Allocator = __gnu_cxx::new_allocator<Tp> >
-      class qualifier_list;
-
-    template<typename Tp, typename Allocator = __gnu_cxx::new_allocator<Tp> >
-      class session;
-
-    template<typename Tp, typename Allocator>
-      class qualifier
-      {
-       typedef typename Allocator::template rebind<char>::other
-               char_Allocator;
-       typedef std::basic_string<char, std::char_traits<char>, char_Allocator>
-           string_type;
-
-      private:
-       char M_qualifier1;
-       char M_qualifier2;
-       char M_qualifier3;
-       mutable unsigned char M_cnt;
-       string_type M_optional_type;
-       int M_start_pos;
-       bool M_part_of_substitution;
-
-      public:
-       qualifier(int start_pos,
-                 simple_qualifier_nt simple_qualifier,
-                 int inside_substitution)
-       : M_qualifier1(simple_qualifier),
-         M_start_pos(start_pos),
-         M_part_of_substitution(inside_substitution)
-       { }
-
-       qualifier(int start_pos,
-                 cv_qualifier_nt,
-                 char const* start,
-                 int count,
-                 int inside_substitution)
-       : M_qualifier1(start[0]),
-         M_qualifier2((count > 1) ? start[1] : '\0'),
-         M_qualifier3((count > 2) ? start[2] : '\0'),
-         M_start_pos(start_pos),
-         M_part_of_substitution(inside_substitution)
-       { }
-
-       qualifier(int start_pos,
-                 param_qualifier_nt param_qualifier,
-                 string_type optional_type,
-                 int inside_substitution)
-       : M_qualifier1(param_qualifier),
-         M_optional_type(optional_type),
-         M_start_pos(start_pos),
-         M_part_of_substitution(inside_substitution)
-       { }
-
-       int
-       get_start_pos(void) const
-       { return M_start_pos; }
-
-       char
-       first_qualifier(void) const
-       { M_cnt = 1; return M_qualifier1; }
-
-       char
-       next_qualifier(void) const
-       {
-         return (++M_cnt == 2) ? M_qualifier2
-                               : ((M_cnt == 3) ? M_qualifier3 : 0);
-       }
-
-       string_type const&
-       get_optional_type(void) const
-       { return M_optional_type; }
-
-       bool
-       part_of_substitution(void) const
-       { return M_part_of_substitution; }
-
-#if _GLIBCXX_DEMANGLER_CWDEBUG
-       friend std::ostream& operator<<(std::ostream& os, qualifier const& qual)
-       {
-         os << (char)qual.M_qualifier1;
-         if (qual.M_qualifier1 == vendor_extension ||
-             qual.M_qualifier1 == array ||
-             qual.M_qualifier1 == pointer_to_member)
-           os << " [" << qual.M_optional_type << ']';
-         else if (qual.M_qualifier1 == 'K' ||
-                  qual.M_qualifier1 == 'V' ||
-                  qual.M_qualifier1 == 'r')
-         {
-           if (qual.M_qualifier2)
-           {
-             os << (char)qual.M_qualifier2;
-             if (qual.M_qualifier3)
-               os << (char)qual.M_qualifier3;
-           }
-         }
-         return os;
-       }
-#endif
-      };
-
-    template<typename Tp, typename Allocator>
-      class qualifier_list
-      {
-       typedef typename Allocator::template rebind<char>::other
-         char_Allocator;
-       typedef std::basic_string<char, std::char_traits<char>, char_Allocator>
-         string_type;
-
-      private:
-       mutable bool M_printing_suppressed;
-       typedef qualifier<Tp, Allocator> qual;
-        typedef typename Allocator::template rebind<qual>::other qual_Allocator;
-       typedef std::vector<qual, qual_Allocator> qual_vector;
-       qual_vector M_qualifier_starts;
-       session<Tp, Allocator>& M_demangler;
-
-       void decode_KVrA(string_type& prefix, string_type& postfix, int cvq,
-                        typename qual_vector::
-                          const_reverse_iterator const& iter_array) const;
-
-      public:
-       qualifier_list(session<Tp, Allocator>& demangler_obj)
-       : M_printing_suppressed(false), M_demangler(demangler_obj)
-       { }
-
-       void
-       add_qualifier_start(simple_qualifier_nt simple_qualifier,
-                           int start_pos,
-                           int inside_substitution)
-       { M_qualifier_starts.
-             push_back(qualifier<Tp, Allocator>(start_pos,
-                 simple_qualifier, inside_substitution)); }
-
-       void
-       add_qualifier_start(cv_qualifier_nt cv_qualifier,
-                           int start_pos,
-                           int count,
-                           int inside_substitution)
-       { M_qualifier_starts.
-             push_back(qualifier<Tp, Allocator>(start_pos,
-                   cv_qualifier, &M_demangler.M_str[start_pos],
-                   count, inside_substitution)); }
-
-       void
-       add_qualifier_start(param_qualifier_nt param_qualifier,
-                           int start_pos,
-                           string_type optional_type,
-                           int inside_substitution)
-       { M_qualifier_starts.
-             push_back(qualifier<Tp, Allocator>(start_pos,
-                   param_qualifier, optional_type, inside_substitution)); }
-
-       void
-       decode_qualifiers(string_type& prefix,
-                         string_type& postfix,
-                         bool member_function_pointer_qualifiers) const;
-
-       bool
-       suppressed(void) const
-       { return M_printing_suppressed; }
-
-       void
-       printing_suppressed(void)
-       { M_printing_suppressed = true; }
-
-       size_t
-       size(void) const
-       { return M_qualifier_starts.size(); }
-
-#if _GLIBCXX_DEMANGLER_CWDEBUG
-       friend std::ostream& operator<<(std::ostream& os, qualifier_list const& list)
-       {
-         typename qual_vector::const_iterator
-             iter = list.M_qualifier_starts.begin();
-         if (iter != list.M_qualifier_starts.end())
-         {
-           os << "{ " << *iter;
-           while (++iter != list.M_qualifier_starts.end())
-             os << ", " << *iter;
-           os << " }";
-         }
-         else
-           os << "{ }";
-         return os;
-       }
-#endif
-      };
-
-    struct implementation_details
-    {
-      private:
-        unsigned int M_style;
-
-      public:
-       // The following flags change the behaviour of the demangler.  The
-       // default behaviour is that none of these flags is set.
-
-        static unsigned int const style_void = 1;
-       // Default behaviour:                           int f()
-       // Use (void) instead of ():                    int f(void)
-
-        static unsigned int const style_literal = 2;
-       // Default behaviour:                           (long)13,
-       //                                              (unsigned long long)19
-       // Use extensions 'u', 'l' and 'll' for integral
-       // literals (as in template arguments):         13l, 19ull
-
-        static unsigned int const style_literal_int = 4;
-       // Default behaviour:                           4
-       // Use also an explicit
-       //   cast for int in literals:                  (int)4
-
-        static unsigned int const style_compact_expr_ops = 8;
-       // Default behaviour:                           (i) < (3), sizeof (int)
-       // Don't output spaces around
-       //   operators in expressions:                  (i)<(3), sizeof(int)
-
-        static unsigned int const style_sizeof_typename = 16;
-       // Default behaviour:                           sizeof (X::t)
-       // Put 'typename' infront of <nested-name>
-       // types inside a 'sizeof':                     sizeof (typename X::t)
-
-      public:
-       implementation_details(unsigned int style_flags = 0) :
-           M_style(style_flags) { }
-       virtual ~implementation_details() { }
-       bool get_style_void(void) const
-           { return (M_style & style_void); }
-       bool get_style_literal(void) const
-           { return (M_style & style_literal); }
-       bool get_style_literal_int(void) const
-           { return (M_style & style_literal_int); }
-       bool get_style_compact_expr_ops(void) const
-           { return (M_style & style_compact_expr_ops); }
-       bool get_style_sizeof_typename(void) const
-           { return (M_style & style_sizeof_typename); }
-        // This can be overridden by user implementations.
-        virtual bool decode_real(char* /* output */, unsigned long* /* input */,
-                                size_t /* size_of_real */) const
-            { return false; }
-    };
-
-    template<typename Tp, typename Allocator>
-      class session
-      {
-      public:
-       friend class qualifier_list<Tp, Allocator>;
-       typedef typename Allocator::template rebind<char>::other
-           char_Allocator;
-       typedef std::basic_string<char, std::char_traits<char>, char_Allocator>
-           string_type;
-
-      private:
-       char const* M_str;
-       int M_pos;
-       int M_maxpos;
-       bool M_result;
-       int M_inside_template_args;
-       int M_inside_type;
-       int M_inside_substitution;
-       bool M_saw_destructor;
-       bool M_name_is_cdtor;
-       bool M_name_is_template;
-       bool M_name_is_conversion_operator;
-       bool M_template_args_need_space;
-       string_type M_function_name;
-        typedef typename Allocator::template rebind<int>::other
-                int_Allocator;
-        typedef typename Allocator::template rebind<substitution_st>::other
-                subst_Allocator;
-       std::vector<int, int_Allocator> M_template_arg_pos;
-       int M_template_arg_pos_offset;
-       std::vector<substitution_st, subst_Allocator> M_substitutions_pos;
-       implementation_details const& M_implementation_details;
-       typedef typename Allocator::template
-           rebind<qualifier_list<Allocator> >::other qualifier_list_Allocator;
-       qualifier_list_Allocator M_qualifier_list_alloc;
-#if _GLIBCXX_DEMANGLER_CWDEBUG
-       bool M_inside_add_substitution;
-#endif
-
-      public:
-       explicit session(char const* in, int len,
-           implementation_details const& id = implementation_details())
-       : M_str(in), M_pos(0), M_maxpos(len - 1), M_result(true),
-         M_inside_template_args(0), M_inside_type(0),
-         M_inside_substitution(0), M_saw_destructor(false),
-         M_name_is_cdtor(false), M_name_is_template(false),
-         M_name_is_conversion_operator(false),
-         M_template_args_need_space(false), M_template_arg_pos_offset(0),
-         M_implementation_details(id)
-#if _GLIBCXX_DEMANGLER_CWDEBUG
-         , M_inside_add_substitution(false)
-#endif
-       { }
-
-       static int
-       decode_encoding(string_type& output, char const* input, int len,
-         implementation_details const& id = implementation_details());
-
-       bool
-       decode_type(string_type& output,
-                   qualifier_list<Tp, Allocator>* qualifiers = NULL)
-       {
-         string_type postfix;
-         bool res = decode_type_with_postfix(output, postfix, qualifiers);
-         output += postfix;
-         return res;
-       }
-
-       bool
-       remaining_input_characters(void) const
-       { return current() != 0; }
-
-      private:
-       char
-       current(void) const
-       { return (M_pos > M_maxpos) ? 0 : M_str[M_pos]; }
-
-       char
-       next_peek(void) const
-       { return (M_pos >= M_maxpos) ? 0 : M_str[M_pos + 1]; }
-
-       char
-       next(void)
-       { return (M_pos >= M_maxpos) ? 0 : M_str[++M_pos]; }
-
-       char
-       eat_current(void)
-       { return (M_pos > M_maxpos) ? 0 : M_str[M_pos++]; }
-
-       void
-       store(int& saved_pos)
-       { saved_pos = M_pos; }
-
-       void
-       restore(int saved_pos)
-       { M_pos = saved_pos; M_result = true; }
-
-       void
-       add_substitution(int start_pos,
-                        substitution_nt sub_type,
-                        int number_of_prefixes);
-
-       bool decode_type_with_postfix(string_type& prefix,
-           string_type& postfix, qualifier_list<Tp, 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);
-       bool decode_class_enum_type(string_type& output);
-       bool decode_expression(string_type& output);
-       bool decode_literal(string_type& output);
-       bool decode_local_name(string_type& output);
-       bool decode_name(string_type& output,
-           string_type& nested_name_qualifiers);
-       bool decode_nested_name(string_type& output,
-           string_type& qualifiers);
-       bool decode_number(string_type& output);
-       bool decode_operator_name(string_type& output);
-       bool decode_source_name(string_type& output);
-       bool decode_substitution(string_type& output,
-           qualifier_list<Tp, Allocator>* qualifiers = NULL);
-       bool decode_template_args(string_type& output);
-       bool decode_template_param(string_type& output,
-           qualifier_list<Tp, Allocator>* qualifiers = NULL);
-       bool decode_unqualified_name(string_type& output);
-       bool decode_unscoped_name(string_type& output);
-       bool decode_non_negative_decimal_integer(string_type& output);
-       bool decode_special_name(string_type& output);
-        bool decode_real(string_type& output, size_t size_of_real);
-      };
-
-    template<typename Tp, typename Allocator>
-#if !_GLIBCXX_DEMANGLER_CWDEBUG
-      inline
-#endif
-      void
-      session<Tp, Allocator>::add_substitution(int start_pos,
-                                          substitution_nt sub_type,
-                                          int number_of_prefixes = 0)
-      {
-       if (!M_inside_substitution)
-       {
-#if _GLIBCXX_DEMANGLER_CWDEBUG
-         if (M_inside_add_substitution)
-           return;
-#endif
-         M_substitutions_pos.
-             push_back(substitution_st(start_pos,
-                 sub_type, number_of_prefixes));
-#if _GLIBCXX_DEMANGLER_CWDEBUG
-         if (!DEBUGCHANNELS::dc::demangler.is_on())
-           return;
-         string_type substitution_name("S");
-         int n = M_substitutions_pos.size() - 1;
-         if (n > 0)
-           substitution_name += (n <= 10) ? (char)(n + '0' - 1)
-                                          : (char)(n + 'A' - 11);
-         substitution_name += '_';
-         string_type subst;
-         int saved_pos = M_pos;
-         M_pos = start_pos;
-         M_inside_add_substitution = true;
-         _GLIBCXX_DEMANGLER_DEBUG( dc::demangler.off() );
-         switch(sub_type)
-         {
-           case type:
-             decode_type(subst);
-             break;
-           case template_template_param:
-             decode_template_param(subst);
-             break;
-           case nested_name_prefix:
-           case nested_name_template_prefix:
-             for (int cnt = number_of_prefixes; cnt > 0; --cnt)
-             {
-               if (current() == 'I')
-               {
-                 subst += ' ';
-                 decode_template_args(subst);
-               }
-               else
-               {
-                 if (cnt < number_of_prefixes)
-                   subst += "::";
-                 if (current() == 'S')
-                   decode_substitution(subst);
-                 else if (current() == 'T')
-                   decode_template_param(subst);
-                 else
-                   decode_unqualified_name(subst);
-               }
-             }
-             break;
-           case unscoped_template_name:
-             decode_unscoped_name(subst);
-             break;
-         }
-         M_pos = saved_pos;
-         _GLIBCXX_DEMANGLER_DEBUG( dc::demangler.on() );
-         _GLIBCXX_DEMANGLER_DOUT(dc::demangler,
-             "Adding substitution " << substitution_name
-             << " : " << subst
-             << " (from " << location_ct((char*)__builtin_return_address(0)
-                                         + builtin_return_address_offset)
-             << " <- " << location_ct((char*)__builtin_return_address(1)
-                                      + builtin_return_address_offset)
-             << " <- " << location_ct((char*)__builtin_return_address(2)
-                                      + builtin_return_address_offset)
-             << ").");
-         M_inside_add_substitution = false;
-#endif
-       }
-      }
-
-    // We don't want to depend on locale (or include <cctype> for that matter).
-    // We also don't want to use "safe-ctype.h" because that headerfile is not
-    // available to the users.
-    inline bool isdigit(char c) { return c >= '0' && c <= '9'; }
-    inline bool islower(char c) { return c >= 'a' && c <= 'z'; }
-    inline bool isupper(char c) { return c >= 'A' && c <= 'Z'; }
-    inline char tolower(char c) { return isupper(c) ? c - 'A' + 'a' : c; }
-
-    //
-    // <non-negative decimal integer> ::= 0
-    //                                ::= 1|2|3|4|5|6|7|8|9 [<digit>+]
-    // <digit>                        ::= 0|1|2|3|4|5|6|7|8|9
-    //
-    template<typename Tp, typename Allocator>
-      bool
-      session<Tp, Allocator>::
-         decode_non_negative_decimal_integer(string_type& output)
-      {
-       char c = current();
-       if (c == '0')
-       {
-         output += '0';
-         eat_current();
-       }
-       else if (!isdigit(c))
-         M_result = false;
-       else
-       {
-         do
-         {
-           output += c;
-         }
-         while (isdigit((c = next())));
-       }
-       return M_result;
-      }
-
-    // <number> ::= [n] <non-negative decimal integer>
-    //
-    template<typename Tp, typename Allocator>
-      bool
-      session<Tp, Allocator>::decode_number(string_type& output)
-      {
-       _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_number");
-       if (current() != 'n')
-         decode_non_negative_decimal_integer(output);
-       else
-       {
-         output += '-';
-         eat_current();
-         decode_non_negative_decimal_integer(output);
-       }
-       _GLIBCXX_DEMANGLER_RETURN;
-      }
-
-    // <builtin-type> ::= v  # void
-    //                ::= w  # wchar_t
-    //                ::= b  # bool
-    //                ::= c  # char
-    //                ::= a  # signed char
-    //                ::= h  # unsigned char
-    //                ::= s  # short
-    //                ::= t  # unsigned short
-    //                ::= i  # int
-    //                ::= j  # unsigned int
-    //                ::= l  # long
-    //                ::= m  # unsigned long
-    //                ::= x  # long long, __int64
-    //                ::= y  # unsigned long long, __int64
-    //                ::= n  # __int128
-    //                ::= o  # unsigned __int128
-    //                ::= f  # float
-    //                ::= d  # double
-    //                ::= e  # long double, __float80
-    //                ::= g  # __float128
-    //                ::= z  # ellipsis
-    //                ::= u <source-name>    # vendor extended type
-    //
-    char const* const builtin_type_c[26] =
-    {
-      "signed char",   // a
-      "bool",          // b
-      "char",          // c
-      "double",                // d
-      "long double",   // e
-      "float",         // f
-      "__float128",            // g
-      "unsigned char", // h
-      "int",           // i
-      "unsigned int",  // j
-      NULL,                    // k
-      "long",          // l
-      "unsigned long", // m
-      "__int128",              // n
-      "unsigned __int128",     // o
-      NULL,                    // p
-      NULL,                    // q
-      NULL,                    // r
-      "short",         // s
-      "unsigned short",        // t
-      NULL,                    // u
-      "void",          // v
-      "wchar_t",               // w
-      "long long",             // x
-      "unsigned long long",    // y
-      "..."                    // z
-    };
-
-    //
-    template<typename Tp, typename Allocator>
-      bool
-      session<Tp, Allocator>::decode_builtin_type(string_type& output)
-      {
-       _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_builtin_type");
-       char const* bt;
-       if (!islower(current()) || !(bt = builtin_type_c[current() - 'a']))
-         _GLIBCXX_DEMANGLER_FAILURE;
-       output += bt;
-       eat_current();
-       _GLIBCXX_DEMANGLER_RETURN;
-      }
-
-    // <class-enum-type> ::= <name>
-    //
-    template<typename Tp, typename Allocator>
-      bool
-      session<Tp, Allocator>::decode_class_enum_type(string_type& output)
-      {
-       _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_class_enum_type");
-       string_type nested_name_qualifiers;
-       if (!decode_name(output, nested_name_qualifiers))
-         _GLIBCXX_DEMANGLER_FAILURE;
-       output += nested_name_qualifiers;
-       _GLIBCXX_DEMANGLER_RETURN;
-      }
-
-    // <substitution> ::=
-    //   S <seq-id> _
-    //   S_
-    //   St # ::std::
-    //   Sa # ::std::allocator
-    //   Sb # ::std::basic_string
-    //   Ss # ::std::basic_string<char, std::char_traits<char>,
-    //                            std::allocator<char> >
-    //   Si # ::std::basic_istream<char,  std::char_traits<char> >
-    //   So # ::std::basic_ostream<char,  std::char_traits<char> >
-    //   Sd # ::std::basic_iostream<char, std::char_traits<char> >
-    //
-    // <seq-id> ::=
-    //   0|1|2|3|4|5|6|7|8|9|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z
-    //       [<seq-id>]        # Base 36 number
-    //
-    template<typename Tp, typename Allocator>
-      bool
-      session<Tp, Allocator>::decode_substitution(string_type& output,
-         qualifier_list<Tp, Allocator>* qualifiers)
-      {
-       _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_substitution");
-       unsigned int value = 0;
-       char c = next();
-       if (c != '_')
-       {
-         switch(c)
-         {
-           case 'a':
-           {
-             output += "std::allocator";
-             if (!M_inside_template_args)
-             {
-               M_function_name = "allocator";
-               M_name_is_template = true;
-               M_name_is_cdtor = false;
-               M_name_is_conversion_operator = false;
-             }
-             eat_current();
-             if (qualifiers)
-               qualifiers->printing_suppressed();
-             _GLIBCXX_DEMANGLER_RETURN;
-           }
-           case 'b':
-           {
-             output += "std::basic_string";
-             if (!M_inside_template_args)
-             {
-               M_function_name = "basic_string";
-               M_name_is_template = true;
-               M_name_is_cdtor = false;
-               M_name_is_conversion_operator = false;
-             }
-             eat_current();
-             if (qualifiers)
-               qualifiers->printing_suppressed();
-             _GLIBCXX_DEMANGLER_RETURN;
-           }
-           case 'd':
-             output += "std::iostream";
-             if (!M_inside_template_args)
-             {
-               M_function_name = "iostream";
-               M_name_is_template = true;
-               M_name_is_cdtor = false;
-               M_name_is_conversion_operator = false;
-             }
-             eat_current();
-             if (qualifiers)
-               qualifiers->printing_suppressed();
-             _GLIBCXX_DEMANGLER_RETURN;
-           case 'i':
-             output += "std::istream";
-             if (!M_inside_template_args)
-             {
-               M_function_name = "istream";
-               M_name_is_template = true;
-               M_name_is_cdtor = false;
-               M_name_is_conversion_operator = false;
-             }
-             eat_current();
-             if (qualifiers)
-               qualifiers->printing_suppressed();
-             _GLIBCXX_DEMANGLER_RETURN;
-           case 'o':
-             output += "std::ostream";
-             if (!M_inside_template_args)
-             {
-               M_function_name = "ostream";
-               M_name_is_template = true;
-               M_name_is_cdtor = false;
-               M_name_is_conversion_operator = false;
-             }
-             eat_current();
-             if (qualifiers)
-               qualifiers->printing_suppressed();
-             _GLIBCXX_DEMANGLER_RETURN;
-           case 's':
-             output += "std::string";
-             if (!M_inside_template_args)
-             {
-               M_function_name = "string";
-               M_name_is_template = true;
-               M_name_is_cdtor = false;
-               M_name_is_conversion_operator = false;
-             }
-             eat_current();
-             if (qualifiers)
-               qualifiers->printing_suppressed();
-             _GLIBCXX_DEMANGLER_RETURN;
-           case 't':
-             output += "std";
-             eat_current();
-             if (qualifiers)
-               qualifiers->printing_suppressed();
-             _GLIBCXX_DEMANGLER_RETURN;
-           default:
-             for(;; c = next())
-             {
-               if (isdigit(c))
-                 value = value * 36 + c - '0';
-               else if (isupper(c))
-                 value = value * 36 + c - 'A' + 10;
-               else if (c == '_')
-                 break;
-               else
-                 _GLIBCXX_DEMANGLER_FAILURE;
-             }
-             ++value;
-             break;
-         }
-       }
-       eat_current();
-       if (value >= M_substitutions_pos.size() ||
-           M_inside_type > 20)                 // Rather than core dump.
-         _GLIBCXX_DEMANGLER_FAILURE;
-       ++M_inside_substitution;
-       int saved_pos = M_pos;
-       substitution_st& substitution(M_substitutions_pos[value]);
-       M_pos = substitution.M_start_pos;
-       switch(substitution.M_type)
-       {
-         case type:
-           decode_type(output, qualifiers);
-           break;
-         case template_template_param:
-           decode_template_param(output, qualifiers);
-           break;
-         case nested_name_prefix:
-         case nested_name_template_prefix:
-           for (int cnt = substitution.M_number_of_prefixes; cnt > 0; --cnt)
-           {
-             if (current() == 'I')
-             {
-               if (M_template_args_need_space)
-                 output += ' ';
-               M_template_args_need_space = false;
-               if (!decode_template_args(output))
-                 _GLIBCXX_DEMANGLER_FAILURE;
-             }
-             else
-             {
-               if (cnt < substitution.M_number_of_prefixes)
-                 output += "::";
-               if (current() == 'S')
-               {
-                 if (!decode_substitution(output))
-                   _GLIBCXX_DEMANGLER_FAILURE;
-               }
-               else if (!decode_unqualified_name(output))
-                 _GLIBCXX_DEMANGLER_FAILURE;
-             }
-           }
-           if (qualifiers)
-             qualifiers->printing_suppressed();
-           break;
-         case unscoped_template_name:
-           decode_unscoped_name(output);
-           if (qualifiers)
-             qualifiers->printing_suppressed();
-           break;
-       }
-       M_pos = saved_pos;
-       --M_inside_substitution;
-       _GLIBCXX_DEMANGLER_RETURN;
-      }
-
-    // <template-param> ::= T_                 # first template parameter
-    //                  ::= T <parameter-2 non-negative number> _
-    //
-    template<typename Tp, typename Allocator>
-      bool
-      session<Tp, Allocator>::decode_template_param(string_type& output,
-         qualifier_list<Tp, Allocator>* qualifiers)
-      {
-       _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_template_parameter");
-       if (current() != 'T')
-         _GLIBCXX_DEMANGLER_FAILURE;
-       unsigned int value = 0;
-       char c;
-       if ((c = next()) != '_')
-       {
-         while(isdigit(c))
-         {
-           value = value * 10 + c - '0';
-           c = next();
-         }
-         ++value;
-       }
-       if (eat_current() != '_')
-         _GLIBCXX_DEMANGLER_FAILURE;
-       value += M_template_arg_pos_offset;
-       if (value >= M_template_arg_pos.size())
-         _GLIBCXX_DEMANGLER_FAILURE;
-       int saved_pos = M_pos;
-       M_pos = M_template_arg_pos[value];
-       if (M_inside_type > 20)         // Rather than core dump.
-         _GLIBCXX_DEMANGLER_FAILURE;
-       ++M_inside_substitution;
-       if (current() == 'X')
-       {
-         eat_current();
-         decode_expression(output);
-       }
-       else if (current() == 'L')
-         decode_literal(output);
-       else
-         decode_type(output, qualifiers);
-       --M_inside_substitution;
-       M_pos = saved_pos;
-       _GLIBCXX_DEMANGLER_RETURN;
-      }
-
-    template<typename Tp, typename Allocator>
-      bool
-      session<Tp, Allocator>::decode_real(string_type& output, size_t size_of_real)
-      {
-       _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_real");
-
-       unsigned long words[4]; // 32 bit per long, maximum of 128 bits.
-       unsigned long* word = &words[0];
-
-       int saved_pos;
-       store(saved_pos);
-
-       // The following assumes that leading zeroes are also included in the
-       // mangled name, I am not sure that is conforming to the C++-ABI, but
-       // it is what g++ does.
-       unsigned char nibble, c = current();
-       for(size_t word_cnt = size_of_real / 4; word_cnt > 0; --word_cnt)
-       {
-         for (int nibble_cnt = 0; nibble_cnt < 8; ++nibble_cnt)
-         {
-           // Translate character into nibble.
-           if (c < '0' || c > 'f')
-             _GLIBCXX_DEMANGLER_FAILURE;
-           if (c <= '9')
-             nibble = c - '0';
-           else if (c >= 'a')
-             nibble = c - 'a' + 10;
-           else
-             _GLIBCXX_DEMANGLER_FAILURE;
-           // Write nibble into word array.
-           if (nibble_cnt == 0)
-             *word = nibble << 28;
-           else
-             *word |= (nibble << (28 - 4 * nibble_cnt));
-           c = next();
-         }
-         ++word;
-       }
-       char buf[24];
-       if (M_implementation_details.decode_real(buf, words, size_of_real))
-       {
-         output += buf;
-         _GLIBCXX_DEMANGLER_RETURN;
-       }
-       restore(saved_pos);
-
-       output += '[';
-       c = current();
-       for(size_t nibble_cnt = 0; nibble_cnt < 2 * size_of_real; ++nibble_cnt)
-       {
-         if (c < '0' || c > 'f' || (c > '9' && c < 'a'))
-           _GLIBCXX_DEMANGLER_FAILURE;
-         output += c;
-         c = next();
-       }
-       output += ']';
-
-       _GLIBCXX_DEMANGLER_RETURN;
-      }
-
-    template<typename Tp, typename Allocator>
-      bool
-      session<Tp, Allocator>::decode_literal(string_type& output)
-      {
-       _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_literal");
-       eat_current();  // Eat the 'L'.
-       if (current() == '_')
-       {
-         if (next() != 'Z')
-           _GLIBCXX_DEMANGLER_FAILURE;
-         eat_current();
-         if ((M_pos += decode_encoding(output, M_str + M_pos,
-                 M_maxpos - M_pos + 1, M_implementation_details)) < 0)
-           _GLIBCXX_DEMANGLER_FAILURE;
-       }
-       else
-       {
-         // Special cases
-         if (current() == 'b')
-         {
-           if (next() == '0')
-             output += "false";
-           else
-             output += "true";
-           eat_current();
-           _GLIBCXX_DEMANGLER_RETURN;
-         }
-         char c = current();
-         if ((c == 'i' || c == 'j' || c == 'l' ||
-              c == 'm' || c == 'x' || c == 'y') &&
-              M_implementation_details.get_style_literal())
-           eat_current();
-         else if (c == 'i' &&
-             !M_implementation_details.get_style_literal_int())
-           eat_current();
-         else
-         {
-           output += '(';
-           if (!decode_type(output))
-             _GLIBCXX_DEMANGLER_FAILURE;
-           output += ')';
-         }
-         if (c >= 'd' && c <= 'g')
-         {
-           size_t size_of_real = (c == 'd') ? sizeof(double) :
-               ((c == 'f') ? sizeof(float) :
-               (c == 'e') ?  sizeof(long double) : 16);
-           if (!decode_real(output, size_of_real))
-               _GLIBCXX_DEMANGLER_FAILURE;
-         }
-         else if (!decode_number(output))
-           _GLIBCXX_DEMANGLER_FAILURE;
-          if (M_implementation_details.get_style_literal())
-         {
-           if (c == 'j' || c == 'm' || c == 'y')
-             output += 'u';
-           if (c == 'l' || c == 'm')
-             output += 'l';
-           if (c == 'x' || c == 'y')
-             output += "ll";
-         }
-       }
-       _GLIBCXX_DEMANGLER_RETURN;
-      }
-
-    // <operator-name> ::=
-    //   nw                            # new
-    //   na                            # new[]
-    //   dl                            # delete
-    //   da                            # delete[]
-    //   ps                            # + (unary)
-    //   ng                            # - (unary)
-    //   ad                            # & (unary)
-    //   de                            # * (unary)
-    //   co                            # ~
-    //   pl                            # +
-    //   mi                            # -
-    //   ml                            # *
-    //   dv                            # /
-    //   rm                            # %
-    //   an                            # &
-    //   or                            # |
-    //   eo                            # ^
-    //   aS                            # =
-    //   pL                            # +=
-    //   mI                            # -=
-    //   mL                            # *=
-    //   dV                            # /=
-    //   rM                            # %=
-    //   aN                            # &=
-    //   oR                            # |=
-    //   eO                            # ^=
-    //   ls                            # <<
-    //   rs                            # >>
-    //   lS                            # <<=
-    //   rS                            # >>=
-    //   eq                            # ==
-    //   ne                            # !=
-    //   lt                            # <
-    //   gt                            # >
-    //   le                            # <=
-    //   ge                            # >=
-    //   nt                            # !
-    //   aa                            # &&
-    //   oo                            # ||
-    //   pp                            # ++
-    //   mm                            # --
-    //   cm                            # ,
-    //   pm                            # ->*
-    //   pt                            # ->
-    //   cl                            # ()
-    //   ix                            # []
-    //   qu                            # ?
-    //   st                            # sizeof (a type)
-    //   sz                            # sizeof (an expression)
-    //   cv <type>                     # (cast)
-    //   v <digit> <source-name>       # vendor extended operator
-    //
-    // Symbol operator codes exist of two characters, we need to find a
-    // quick hash so that their names can be looked up in a table.
-    //
-    // The puzzle :)
-    // Shift the rows so that there is at most one character per column.
-    //
-    // A perfect solution (Oh no, it's THE MATRIX!):
-    //                                              horizontal
-    //    .......................................   offset + 'a'
-    // a, a||d|||||||||n||||s||||||||||||||||||||       0
-    // c,  || |||||||lm o||| ||||||||||||||||||||       0
-    // d,  || a|||e||    l|| ||||||v|||||||||||||       4
-    // e,  ||  ||| ||     || |||o|q |||||||||||||       8
-    // g,  ||  ||| ||     || e|| |  ||||||||t||||      15
-    // i,  ||  ||| ||     ||  || |  |||||||| |||x      15
-    // l,  |e  ||| ||     st  || |  |||||||| |||       -2
-    // m,  |   |i| lm         || |  |||||||| |||       -2
-    // n,  a   e g            t| w  |||||||| |||        1
-    // o,                      |    ||||o||r |||       16
-    // p,                      |    ||lm |p  st|       17
-    // q,                      |    u|   |     |        6
-    // r,                      m     s   |     |        9
-    // s,                                t     z       12
-    //    .......................................
-    // ^            ^__ second character
-    // |___ first character
-    //
-
-    // Putting that solution in tables:
-
-    char const offset_table_c [1 + CHAR_MAX - CHAR_MIN ] =
-    {
-      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-#if (CHAR_MIN < 0)
-      // Add -CHAR_MIN extra zeroes (128):
-      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-      //   a    b    c    d    e    f    g    h    i    j    k
-      0, -97,   0, -97, -93, -89,   0, -82,   0, -82,   0,   0,
-      //   l    m    n    o    p    q    r    s    t    u    v
-        -99, -99, -96, -81, -80, -91, -88, -85,   0,   0,   0,
-#else
-      //   a    b    c    d    e    f    g    h    i    j    k
-      0, 159,   0, 159, 163, 167,   0, 174,   0, 174,   0,   0,
-      //   l    m    n    o    p    q    r    s    t    u    v
-        157, 157, 160, 175, 176, 165, 168, 171,   0,   0,   0,
-#endif
-      // ... more zeros
-    };
-
-    enum xary_nt {
-      unary,
-      binary,
-      trinary
-    };
-
-    struct entry_st
-    {
-      char const* opcode;
-      char const* symbol_name;
-      xary_nt type;
-    };
-
-    entry_st const symbol_name_table_c[39] = {
-      { "aa",  "operator&&", binary },
-      { "na",  "operator new[]", unary },
-      { "le",  "operator<=", binary },
-      { "ad",  "operator&", unary },
-      { "da",  "operator delete[]", unary },
-      { "ne",  "operator!=", binary },
-      { "mi=", "operator-", binary },
-      { "ng",  "operator-", unary },
-      { "de",  "operator*", unary },
-      { "ml=", "operator*", binary },
-      { "mm",  "operator--", unary },
-      { "cl",  "operator()", unary },
-      { "cm",  "operator,", binary },
-      { "an=", "operator&", binary },
-      { "co",  "operator~", binary },
-      { "dl",  "operator delete", unary },
-      { "ls=", "operator<<", binary },
-      { "lt",  "operator<", binary },
-      { "as=", "operator", binary },
-      { "ge",  "operator>=", binary },
-      { "nt",  "operator!", unary },
-      { "rm=", "operator%", binary },
-      { "eo=", "operator^", binary },
-      { "nw",  "operator new", unary },
-      { "eq",  "operator==", binary },
-      { "dv=", "operator/", binary },
-      { "qu",  "operator?", trinary },
-      { "rs=", "operator>>", binary },
-      { "pl=", "operator+", binary },
-      { "pm",  "operator->*", binary },
-      { "oo",  "operator||", binary },
-      { "st",  "sizeof", unary },
-      { "pp",  "operator++", unary },
-      { "or=", "operator|", binary },
-      { "gt",  "operator>", binary },
-      { "ps",  "operator+", unary },
-      { "pt",  "operator->", binary },
-      { "sz",  "sizeof", unary },
-      { "ix",  "operator[]", unary }
-    };
-
-    template<typename Tp, typename Allocator>
-      bool
-      session<Tp, Allocator>::decode_operator_name(string_type& output)
-      {
-       _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_operator_name");
-
-       char opcode0 = current();
-       char opcode1 = tolower(next());
-
-       register char hash;
-       if ((hash = offset_table_c[opcode0 - CHAR_MIN]))
-       {
-         hash += opcode1;
-         if (
-#if (CHAR_MIN < 0)
-             hash >= 0 &&
-#endif
-             hash < 39)
-         {
-           int index = static_cast<int>(static_cast<unsigned char>(hash));
-           entry_st entry = symbol_name_table_c[index];
-           if (entry.opcode[0] == opcode0 && entry.opcode[1] == opcode1
-               && (opcode1 == current() || entry.opcode[2] == '='))
-           {
-             output += entry.symbol_name;
-             if (opcode1 != current())
-               output += '=';
-             eat_current();
-             if (hash == 16 || hash == 17)
-               M_template_args_need_space = true;
-             _GLIBCXX_DEMANGLER_RETURN;
-           }
-           else if (opcode0 == 'c' && opcode1 == 'v')  // casting operator
-           {
-             eat_current();
-             output += "operator ";
-             if (current() == 'T')
-             {
-               // This is a templated cast operator.
-               // It must be of the form "cvT_I...E".
-               // Let M_template_arg_pos already point
-               // to the template argument.
-               M_template_arg_pos_offset = M_template_arg_pos.size();
-               M_template_arg_pos.push_back(M_pos + 3);
-             }
-             if (!decode_type(output))
-               _GLIBCXX_DEMANGLER_FAILURE;
-             if (!M_inside_template_args)
-               M_name_is_conversion_operator = true;
-             _GLIBCXX_DEMANGLER_RETURN;
-           }
-         }
-       }
-       _GLIBCXX_DEMANGLER_FAILURE;
-      }
-
-    //
-    // <expression> ::= <unary operator-name> <expression>
-    //              ::= <binary operator-name> <expression> <expression>
-    //              ::= <trinary operator-name> <expression> <expression> <expression>
-    //              ::= st <type>
-    //              ::= <template-param>
-    //              ::= sr <type> <unqualified-name>                   # dependent name
-    //              ::= sr <type> <unqualified-name> <template-args>   # dependent template-id
-    //              ::= <expr-primary>
-    //
-    // <expr-primary> ::= L <type> <value number> E     # integer literal
-    //                ::= L <type> <value float> E     # floating literal
-    //                ::= L <mangled-name> E           # external name
-    //
-    template<typename Tp, typename Allocator>
-      bool
-      session<Tp, Allocator>::decode_expression(string_type& output)
-      {
-       _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_expression");
-       if (current() == 'T')
-       {
-         if (!decode_template_param(output))
-           _GLIBCXX_DEMANGLER_FAILURE;
-         _GLIBCXX_DEMANGLER_RETURN;
-       }
-       else if (current() == 'L')
-       {
-         if (!decode_literal(output))
-           _GLIBCXX_DEMANGLER_FAILURE;
-         if (current() != 'E')
-           _GLIBCXX_DEMANGLER_FAILURE;
-         eat_current();
-         _GLIBCXX_DEMANGLER_RETURN;
-       }
-       else if (current() == 's')
-       {
-         char opcode1 = next();
-         if (opcode1 == 't' || opcode1 == 'z')
-         {
-           eat_current();
-           if (M_implementation_details.get_style_compact_expr_ops())
-             output += "sizeof(";
-           else
-             output += "sizeof (";
-           if (opcode1 == 't')
-           {
-             // I cannot think of a mangled name that is valid for both cases
-             // when just replacing the 't' by a 'z' or vica versa, which
-             // indicates that there is no ambiguity that dictates the need
-             // for a seperate "st" case, except to be able catch invalid
-             // mangled names.  However there CAN be ambiguity in the demangled
-             // name when there are both a type and a symbol of the same name,
-             // which then leads to different encoding (of course) with
-             // sizeof (type) or sizeof (expression) respectively, but that
-             // ambiguity is not per se related to "sizeof" except that that
-             // is the only place where both a type AND an expression are valid
-             // in as part of a (template function) type.
-             //
-             // Example:
-             //
-             // struct B { typedef int t; };
-             // struct A : public B { static int t[2]; };
-             // template<int i, int j> struct C { typedef int q; };
-             // template<int i, typename T>
-             //   void f(typename C<sizeof (typename T::t),
-             //                     sizeof (T::t)>::q) { }
-             // void instantiate() { f<5, A>(0); }
-             //
-             // Leads to _Z1fILi5E1AEvN1CIXstN1T1tEEXszsrS2_1tEE1qE which
-             // demangles as
-             // void f<5, A>(C<sizeof (T::t), sizeof (T::t)>::q)
-             //
-             // This is ambiguity is very unlikely to happen and it is kind
-             // of fuzzy to detect when adding a 'typename' makes sense.
-             //
-             if (M_implementation_details.get_style_sizeof_typename())
-             {
-               // We can only get here inside a template parameter,
-               // so this is syntactically correct if the given type is
-               // a typedef.  The only disadvantage is that it is inconsistent
-               // with all other places where the 'typename' keyword should be
-               // used and we don't.
-               // With this, the above example will demangle as
-               // void f<5, A>(C<sizeof (typename T::t), sizeof (T::t)>::q)
-               if (current() == 'N' || // <nested-name>
-                                         // This should be a safe bet.
-                   (current() == 'S' &&
-                    next_peek() == 't'))       // std::something, guess that
-                                         // this involves a typedef.
-                 output += "typename ";
-             }
-             if (!decode_type(output))
-               _GLIBCXX_DEMANGLER_FAILURE;
-           }
-           else
-           {
-             if (!decode_expression(output))
-               _GLIBCXX_DEMANGLER_FAILURE;
-           }
-           output += ')';
-           _GLIBCXX_DEMANGLER_RETURN;
-         }
-         else if (current() == 'r')
-         {
-           eat_current();
-           if (!decode_type(output))
-             _GLIBCXX_DEMANGLER_FAILURE;
-           output += "::";
-           if (!decode_unqualified_name(output))
-             _GLIBCXX_DEMANGLER_FAILURE;
-           if (current() != 'I' || decode_template_args(output))
-             _GLIBCXX_DEMANGLER_RETURN;
-         }
-       }
-       else
-       {
-         char opcode0 = current();
-         char opcode1 = tolower(next());
-
-         register char hash;
-         if ((hash = offset_table_c[opcode0 - CHAR_MIN]))
-         {
-           hash += opcode1;
-           if (
-#if (CHAR_MIN < 0)
-               hash >= 0 &&
-#endif
-               hash < 39)
-           {
-             int index = static_cast<int>(static_cast<unsigned char>(hash));
-             entry_st entry = symbol_name_table_c[index];
-             if (entry.opcode[0] == opcode0 && entry.opcode[1] == opcode1
-                 && (opcode1 == current() || entry.opcode[2] == '='))
-             {
-               char const* op = entry.symbol_name + 8; // Skip "operator".
-               if (*op == ' ')                         // operator new and delete.
-                 ++op;
-               if (entry.type == unary)
-                 output += op;
-               bool is_eq = (opcode1 != current());
-               eat_current();
-               if (index == 34 && M_inside_template_args)      // operator>
-                 output += '(';
-               output += '(';
-               if (!decode_expression(output))
-                 _GLIBCXX_DEMANGLER_FAILURE;
-               output += ')';
-               if (entry.type != unary)
-               {
-                 if (!M_implementation_details.get_style_compact_expr_ops())
-                   output += ' ';
-                 output += op;
-                 if (is_eq)
-                   output += '=';
-                 if (!M_implementation_details.get_style_compact_expr_ops())
-                   output += ' ';
-                 output += '(';
-                 if (!decode_expression(output))
-                   _GLIBCXX_DEMANGLER_FAILURE;
-                 output += ')';
-                 if (index == 34 && M_inside_template_args)
-                   output += ')';
-                 if (entry.type == trinary)
-                 {
-                   if (M_implementation_details.get_style_compact_expr_ops())
-                     output += ":(";
-                   else
-                     output += " : (";
-                   if (!decode_expression(output))
-                     _GLIBCXX_DEMANGLER_FAILURE;
-                   output += ')';
-                 }
-               }
-               _GLIBCXX_DEMANGLER_RETURN;
-             }
-             else if (opcode0 == 'c' &&
-                      opcode1 == 'v')          // casting operator.
-             {
-               eat_current();
-               output += '(';
-               if (!decode_type(output))
-                 _GLIBCXX_DEMANGLER_FAILURE;
-               output += ")(";
-               if (!decode_expression(output))
-                 _GLIBCXX_DEMANGLER_FAILURE;
-               output += ')';
-               _GLIBCXX_DEMANGLER_RETURN;
-             }
-           }
-         }
-       }
-       _GLIBCXX_DEMANGLER_FAILURE;
-      }
-
-    //
-    // <template-args> ::= I <template-arg>+ E
-    // <template-arg> ::= <type>                       # type or template
-    //                ::= L <type> <value number> E    # integer literal
-    //                ::= L <type> <value float> E     # floating literal
-    //                ::= L <mangled-name> E           # external name
-    //                ::= X <expression> E             # expression
-    template<typename Tp, typename Allocator>
-      bool
-      session<Tp, Allocator>::decode_template_args(string_type& output)
-      {
-       _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_template_args");
-       if (eat_current() != 'I')
-         _GLIBCXX_DEMANGLER_FAILURE;
-       int prev_size = M_template_arg_pos.size();
-       ++M_inside_template_args;
-       if (M_template_args_need_space)
-       {
-         output += ' ';
-         M_template_args_need_space = false;
-       }
-       output += '<';
-       for(;;)
-       {
-         if (M_inside_template_args == 1 && !M_inside_type)
-           M_template_arg_pos.push_back(M_pos);
-         if (current() == 'X')
-         {
-           eat_current();
-           if (!decode_expression(output))
-             _GLIBCXX_DEMANGLER_FAILURE;
-           if (current() != 'E')
-             _GLIBCXX_DEMANGLER_FAILURE;
-           eat_current();
-         }
-         else if (current() == 'L')
-         {
-           if (!decode_literal(output))
-             _GLIBCXX_DEMANGLER_FAILURE;
-           if (current() != 'E')
-             _GLIBCXX_DEMANGLER_FAILURE;
-           eat_current();
-         }
-         else if (!decode_type(output))
-           _GLIBCXX_DEMANGLER_FAILURE;
-         if (current() == 'E')
-           break;
-         output += ", ";
-       }
-       eat_current();
-       if (*(output.rbegin()) == '>')
-         output += ' ';
-       output += '>';
-       --M_inside_template_args;
-       if (!M_inside_template_args && !M_inside_type)
-       {
-         M_name_is_template = true;
-         M_template_arg_pos_offset = prev_size;
-       }
-       _GLIBCXX_DEMANGLER_RETURN;
-      }
-
-    // <bare-function-type> ::=
-    //   <signature type>+             # Types are parameter types.
-    //
-    // Note that the possible return type of the <bare-function-type>
-    // has already been eaten before we call this function.  This makes
-    // our <bare-function-type> slightly different from the one in
-    // the C++-ABI description.
-    //
-    template<typename Tp, typename Allocator>
-      bool
-      session<Tp, Allocator>::decode_bare_function_type(string_type& output)
-      {
-       _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_bare_function_type");
-       if (M_saw_destructor)
-       {
-         if (eat_current() != 'v' || (current() != 'E' && current() != 0))
-           _GLIBCXX_DEMANGLER_FAILURE;
-         output += "()";
-         M_saw_destructor = false;
-         _GLIBCXX_DEMANGLER_RETURN;
-       }
-       if (current() == 'v' && !M_implementation_details.get_style_void())
-       {
-         eat_current();
-         if (current() != 'E' && current() != 0)
-           _GLIBCXX_DEMANGLER_FAILURE;
-         output += "()";
-         M_saw_destructor = false;
-         _GLIBCXX_DEMANGLER_RETURN;
-       }
-       output += '(';
-       M_template_args_need_space = false;
-       if (!decode_type(output))       // Must have at least one parameter.
-         _GLIBCXX_DEMANGLER_FAILURE;
-       while (current() != 'E' && current() != 0)
-       {
-         output += ", ";
-         if (!decode_type(output))
-           _GLIBCXX_DEMANGLER_FAILURE;
-       }
-       output += ')';
-       _GLIBCXX_DEMANGLER_RETURN;
-      }
-
-    // <type> ::=
-    //   <builtin-type>                # Starts with a lower case character != r.
-    //   <function-type>       # Starts with F
-    //   <class-enum-type>     # Starts with N, S, C, D, Z, a digit or a lower
-    //                         # case character.  Since a lower case character
-    //                         # would be an operator name, that would be an
-    //                         # error.  The S is a substitution or St
-    //                         # (::std::).  A 'C' would be a constructor and
-    //                         # thus also an error.
-    //   <template-param>      # Starts with T
-    //   <substitution>         # Starts with S
-    //   <template-template-param> <template-args>  # Starts with T or S,
-    //                                             # equivalent with the above.
-    //
-    //   <array-type>                  # Starts with A
-    //   <pointer-to-member-type>      # Starts with M
-    //   <CV-qualifiers> <type>                # Starts with r, V or K
-    //   P <type>   # pointer-to       # Starts with P
-    //   R <type>   # reference-to     # Starts with R
-    //   C <type>   # complex (C 2000) # Starts with C
-    //   G <type>   # imaginary (C 2000)# Starts with G
-    //   U <source-name> <type>                # vendor extended type qualifier,
-    //                                 # starts with U
-    //
-    // <template-template-param> ::= <template-param>
-    //                           ::= <substitution>
-
-    // My own analysis of how to decode qualifiers:
-    //
-    // F is a <function-type>, <T> is a <builtin-type>, <class-enum-type>,
-    //   <template-param> or <template-template-param> <template-args>.
-    // <Q> represents a series of qualifiers (not G or C).
-    // <C> is an unqualified type.
-    // <R> is a qualified type.
-    // <B> is the bare-function-type without return type.
-    // <I> is the array index.
-    //                                         Substitutions:
-    // <Q>M<C><Q2>F<R><B>E  ==> R (C::*Q)B Q2  "<C>", "F<R><B>E"
-    //                                             (<R> and <B> recursive),
-    //                                             "M<C><Q2>F<R><B>E".
-    // <Q>F<R><B>E         ==> R (Q)B          "<R>", "<B>" (<B> recursive)
-    //                                              and "F<R><B>E".
-    //
-    // Note that if <R> has postfix qualifiers (an array or function), then
-    // those are added AFTER the (member) function type.  For example:
-    // <Q>FPA<R><B>E ==> R (*(Q)B) [], where the PA added the prefix
-    // "(*" and the postfix ") []".
-    //
-    // <Q>G<T>             ==> imaginary T Q   "<T>", "G<T>" (<T> recursive).
-    // <Q>C<T>             ==> complex T Q     "<T>", "C<T>" (<T> recursive).
-    // <Q><T>              ==> T Q             "<T>" (<T> recursive).
-    //
-    // where <Q> is any of:
-    //
-    // <Q>P            ==> *Q                          "P..."
-    // <Q>R            ==> &Q                          "R..."
-    // <Q>[K|V|r]+     ==> [ const| volatile| restrict]+Q      "KVr..."
-    // <Q>U<S>         ==>  SQ                         "U<S>..."
-    // <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
-    //   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
-    // (and therefore the order in which substitutions must be generated) must
-    // be done left to right, but the generation of Q needs processing right to
-    // left, substitutions per <type> are generated by reading the input left
-    // to right and marking the starts of all substitutions only - implicitly
-    // finishing them at the end of the type.  Then the output and real
-    // substitutions are generated.
-    //
-    // The following comment was for the demangling of g++ version 3.0.x.  The
-    // mangling (and I believe even the ABI description) have been fixed now
-    // (as of g++ version 3.1).
-    //
-    // g++ 3.0.x only:
-    // The ABI specifies for pointer-to-member function types the format
-    // <Q>M<T>F<R><B>E.  In other words, the qualifier <Q2> (see above) is
-    // implicitely contained in <T> instead of explicitly part of the M format.
-    // I am convinced that this is a bug in the ABI.  Unfortunately, this is
-    // how we have to demangle things as it has a direct impact on the order
-    // in which substitutions are stored.  This ill-formed design results in
-    // rather ill-formed demangler code too however :/
-    //
-    // <Q2> is now explicitely part of the M format.
-    // 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 Tp, typename Allocator>
-      void
-      qualifier_list<Tp, Allocator>::decode_KVrA(
-          string_type& prefix, string_type& postfix, int cvq,
-          typename qual_vector::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 qual_vector::
-               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 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_qualifiers(prefix, postfix);
-                   // substitution: all qualified types, if any.
-             }
-             else
-               qualifiers->printing_suppressed();
-             break;
-           default:
-             // <Q><T>                 ==> T Q
-             //     substitutions: "<T>" (<T> recursive).
-             if (!decode_builtin_type(prefix))
-             {
-               failure = true;
-               break;
-             }
-             // If decode_type was called from decode_template_param then we
-             // need to suppress calling qualifiers here in order to get a
-             // substitution added anyway (for the <template-param>).
-             if (!recursive_template_param_or_substitution_call)
-               qualifiers->decode_qualifiers(prefix, postfix);
-             else
-               qualifiers->printing_suppressed();
-             break;
-         }
-       }
-    decode_type_exit:
-       --M_inside_type;
-       if (!recursive_template_param_or_substitution_call)
-       {
-         qualifiers->~qualifier_list<Allocator>();
-         M_qualifier_list_alloc.deallocate(qualifiers, 1);
-       }
-       if (failure)
-         _GLIBCXX_DEMANGLER_FAILURE;
-       _GLIBCXX_DEMANGLER_RETURN2;
-      }
-
-    // <nested-name> ::= N [<CV-qualifiers>] <prefix> <unqualified-name> E
-    //               ::= N [<CV-qualifiers>] <template-prefix> <template-args> E
-    //
-    // <prefix> ::= <prefix> <unqualified-name>
-    //          ::= <template-prefix> <template-args>
-    //          ::= <template-param>
-    //          ::= # empty
-    //          ::= <substitution>
-    //
-    // <template-prefix> ::= <prefix> <template unqualified-name>
-    //                   ::= <template-param>
-    //                   ::= <substitution>
-    //
-    template<typename Tp, typename Allocator>
-      bool
-      session<Tp, Allocator>::decode_nested_name(string_type& output,
-                                            string_type& qualifiers)
-      {
-       _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_nested_name");
-
-       if (current() != 'N' || M_pos >= M_maxpos)
-         _GLIBCXX_DEMANGLER_FAILURE;
-
-       // <CV-qualifiers> ::= [r] [V] [K]  # restrict (C99), volatile, const
-       char const* qualifiers_start = &M_str[M_pos + 1];
-       for (char c = next(); c == 'K' || c == 'V' || c == 'r'; c = next());
-       for (char const* qualifier_ptr = &M_str[M_pos - 1];
-            qualifier_ptr >= qualifiers_start; --qualifier_ptr)
-         switch(*qualifier_ptr)
-         {
-           case 'K':
-             qualifiers += " const";
-             break;
-           case 'V':
-             qualifiers += " volatile";
-             break;
-           case 'r':
-             qualifiers += " restrict";
-             break;
-         }
-
-       int number_of_prefixes = 0;
-       int substitution_start = M_pos;
-       for(;;)
-       {
-         ++number_of_prefixes;
-         if (current() == 'S')
-         {
-           if (!decode_substitution(output))
-             _GLIBCXX_DEMANGLER_FAILURE;
-         }
-         else if (current() == 'I')
-         {
-           if (!decode_template_args(output))
-             _GLIBCXX_DEMANGLER_FAILURE;
-           if (current() != 'E')
-           {
-             // substitution: "<template-prefix> <template-args>".
-             add_substitution(substitution_start, nested_name_prefix,
-                              number_of_prefixes);
-           }
-         }
-         else
-         {
-           if (current() == 'T')
-           {
-             if (!decode_template_param(output))
-               _GLIBCXX_DEMANGLER_FAILURE;
-           }
-           else if (!decode_unqualified_name(output))
-             _GLIBCXX_DEMANGLER_FAILURE;
-           if (current() != 'E')
-           {
-             // substitution: "<prefix> <unqualified-name>" or
-             // "<prefix> <template unqualified-name>".
-             add_substitution(substitution_start,
-                 (current() == 'I') ?  nested_name_template_prefix
-                                    : nested_name_prefix,
-                 number_of_prefixes);
-           }
-         }
-         if (current() == 'E')
-         {
-           eat_current();
-           _GLIBCXX_DEMANGLER_RETURN;
-         }
-         if (current() != 'I')
-           output += "::";
-         else if (M_template_args_need_space)
-           output += ' ';
-         M_template_args_need_space = false;
-       }
-       _GLIBCXX_DEMANGLER_FAILURE;
-      }
-
-    // <local-name> := Z <function encoding> E <entity name> [<discriminator>]
-    //              := Z <function encoding> E s [<discriminator>]
-    // <discriminator> := _ <non-negative number>
-    //
-    template<typename Tp, typename Allocator>
-      bool
-      session<Tp, Allocator>::decode_local_name(string_type& output)
-      {
-       _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_local_name");
-       if (current() != 'Z' || M_pos >= M_maxpos)
-         _GLIBCXX_DEMANGLER_FAILURE;
-       if ((M_pos += decode_encoding(output, M_str + M_pos + 1,
-               M_maxpos - M_pos, M_implementation_details) + 1) < 0 ||
-               eat_current() != 'E')
-         _GLIBCXX_DEMANGLER_FAILURE;
-       output += "::";
-       if (current() == 's')
-       {
-         eat_current();
-         output += "string literal";
-       }
-       else
-       {
-         string_type nested_name_qualifiers;
-         if (!decode_name(output, nested_name_qualifiers))
-           _GLIBCXX_DEMANGLER_FAILURE;
-         output += nested_name_qualifiers;
-       }
-       string_type discriminator;
-       if (current() == '_' && next() != 'n' && !decode_number(discriminator))
-         _GLIBCXX_DEMANGLER_FAILURE;
-       _GLIBCXX_DEMANGLER_RETURN;
-      }
-
-    // <source-name> ::= <positive length number> <identifier>
-    //
-    template<typename Tp, typename Allocator>
-      bool
-      session<Tp, Allocator>::decode_source_name(string_type& output)
-      {
-       _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_source_name");
-       int length = current() - '0';
-       if (length < 1 || length > 9)
-         _GLIBCXX_DEMANGLER_FAILURE;
-       while(isdigit(next()))
-         length = 10 * length + current() - '0';
-       char const* ptr = &M_str[M_pos];
-       if (length > 11 && !strncmp(ptr, "_GLOBAL_", 8) && ptr[9] == 'N'
-           && ptr[8] == ptr[10])
-       {
-         output += "(anonymous namespace)";
-         if ((M_pos += length) > M_maxpos + 1)
-           _GLIBCXX_DEMANGLER_FAILURE;
-       }
-       else
-         while(length--)
-         {
-           if (current() == 0)
-             _GLIBCXX_DEMANGLER_FAILURE;
-           output += eat_current();
-         }
-       _GLIBCXX_DEMANGLER_RETURN;
-      }
-
-    // <unqualified-name> ::= <operator-name>  # Starts with lower case.
-    //                    ::= <ctor-dtor-name>  # Starts with 'C' or 'D'.
-    //                    ::= <source-name>    # Starts with a digit.
-    //
-    template<typename Tp, typename Allocator>
-      bool
-      session<Tp, Allocator>::decode_unqualified_name(string_type& output)
-      {
-       _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_unqualified_name");
-       if (M_inside_template_args)
-       {
-         if (!decode_source_name(output))
-           _GLIBCXX_DEMANGLER_FAILURE;
-       }
-       else if (isdigit(current()))
-       {
-         bool recursive_unqualified_name = (&M_function_name == &output);
-         // This can be a recursive call when we are decoding
-         // an <operator-name> that is a cast operator for a some
-         // <unqualified-name>; for example "operator Foo()".
-         // In that case this is thus not a ctor or dtor and we
-         // are not interested in updating M_function_name.
-         if (!recursive_unqualified_name)
-           M_function_name.clear();
-         M_name_is_template = false;
-         M_name_is_cdtor = false;
-         M_name_is_conversion_operator = false;
-         if (!decode_source_name(M_function_name))
-           _GLIBCXX_DEMANGLER_FAILURE;
-         if (!recursive_unqualified_name)
-           output += M_function_name;
-       }
-       else if (islower(current()))
-       {
-         M_function_name.clear();
-         M_name_is_template = false;
-         M_name_is_cdtor = false;
-         M_name_is_conversion_operator = false;
-         if (!decode_operator_name(M_function_name))
-           _GLIBCXX_DEMANGLER_FAILURE;
-         output += M_function_name;
-       }
-       else if (current() == 'C' || current() == 'D')
-       {
-         // <ctor-dtor-name> ::=
-         //   C1       # complete object (in-charge) constructor
-         //   C2       # base object (not-in-charge) constructor
-         //   C3       # complete object (in-charge) allocating constructor
-         //   D0       # deleting (in-charge) destructor
-         //   D1       # complete object (in-charge) destructor
-         //   D2       # base object (not-in-charge) destructor
-         //
-         if (current() == 'C')
-         {
-           char c = next();
-           if (c < '1' || c > '3')
-             _GLIBCXX_DEMANGLER_FAILURE;
-         }
-         else
-         {
-           char c = next();
-           if (c < '0' || c > '2')
-             _GLIBCXX_DEMANGLER_FAILURE;
-           output += '~';
-           M_saw_destructor = true;
-         }
-         M_name_is_cdtor = true;
-         eat_current();
-         output += M_function_name;
-       }
-       else
-         _GLIBCXX_DEMANGLER_FAILURE;
-       _GLIBCXX_DEMANGLER_RETURN;
-      }
-
-    // <unscoped-name> ::=
-    //   <unqualified-name>            # Starts not with an 'S'
-    //   St <unqualified-name>         # ::std::
-    //
-    template<typename Tp, typename Allocator>
-      bool
-      session<Tp, Allocator>::decode_unscoped_name(string_type& output)
-      {
-       _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_unscoped_name");
-       if (current() == 'S')
-       {
-         if (next() != 't')
-           _GLIBCXX_DEMANGLER_FAILURE;
-         eat_current();
-         output += "std::";
-       }
-       decode_unqualified_name(output);
-       _GLIBCXX_DEMANGLER_RETURN;
-      }
-
-    // <name> ::=
-    //   <nested-name>                         # Starts with 'N'
-    //   <unscoped-template-name> <template-args> # idem
-    //   <local-name>                          # Starts with 'Z'
-    //   <unscoped-name>                       # Starts with 'S', 'C', 'D',
-    //                                         # a digit or a lower case
-    //                                         # character.
-    //
-    // <unscoped-template-name> ::= <unscoped-name>
-    //                          ::= <substitution>
-    template<typename Tp, typename Allocator>
-      bool
-      session<Tp, Allocator>::decode_name(string_type& output,
-                                     string_type& nested_name_qualifiers)
-      {
-       _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_name");
-       int substitution_start = M_pos;
-       if (current() == 'S' && (M_pos >= M_maxpos || M_str[M_pos + 1] != 't'))
-       {
-         if (!decode_substitution(output))
-           _GLIBCXX_DEMANGLER_FAILURE;
-       }
-       else if (current() == 'N')
-       {
-         decode_nested_name(output, nested_name_qualifiers);
-         _GLIBCXX_DEMANGLER_RETURN;
-       }
-       else if (current() == 'Z')
-       {
-         decode_local_name(output);
-         _GLIBCXX_DEMANGLER_RETURN;
-       }
-       else if (!decode_unscoped_name(output))
-         _GLIBCXX_DEMANGLER_FAILURE;
-       if (current() == 'I')
-       {
-         // Must have been an <unscoped-template-name>.
-         add_substitution(substitution_start, unscoped_template_name);
-         if (!decode_template_args(output))
-           _GLIBCXX_DEMANGLER_FAILURE;
-       }
-       M_template_args_need_space = false;
-       _GLIBCXX_DEMANGLER_RETURN;
-      }
-
-    // <call-offset> ::= h <nv-offset> _
-    //               ::= v <v-offset> _
-    // <nv-offset>   ::= <offset number>
-    //     non-virtual base override
-    //
-    // <v-offset>    ::= <offset number> _ <virtual offset number>
-    //     virtual base override, with vcall offset
-    template<typename Tp, typename Allocator>
-      bool
-      session<Tp, Allocator>::decode_call_offset(string_type&
-#if _GLIBCXX_DEMANGLER_CWDEBUG
-         output
-#endif
-         )
-      {
-       _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_call_offset");
-       if (current() == 'h')
-       {
-         string_type dummy;
-         eat_current();
-         if (decode_number(dummy) && current() == '_')
-         {
-           eat_current();
-           _GLIBCXX_DEMANGLER_RETURN;
-         }
-       }
-       else if (current() == 'v')
-       {
-         string_type dummy;
-         eat_current();
-         if (decode_number(dummy) && current() == '_')
-         {
-           eat_current();
-           if (decode_number(dummy) && current() == '_')
-           {
-             eat_current();
-             _GLIBCXX_DEMANGLER_RETURN;
-           }
-         }
-       }
-       _GLIBCXX_DEMANGLER_FAILURE;
-      }
-
-    //
-    // <special-name> ::=
-    //   TV <type>                     # virtual table
-    //   TT <type>                     # VTT structure (construction
-    //                                    vtable index).
-    //   TI <type>                     # typeinfo structure
-    //   TS <type>                     # typeinfo name (null-terminated
-    //                                    byte string).
-    //   GV <object name>              # Guard variable for one-time
-    //                                   initialization of static objects in
-    //                                   a local scope.
-    //   T <call-offset> <base encoding># base is the nominal target function
-    //                                   of thunk.
-    //   Tc <call-offset> <call-offset> <base encoding> # base is the nominal
-    //                                    target function of thunk; first
-    //                                    call-offset is 'this' adjustment;
-    //                                   second call-offset is result
-    //                                   adjustment
-    //
-    template<typename Tp, typename Allocator>
-      bool
-      session<Tp, Allocator>::decode_special_name(string_type& output)
-      {
-       _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_special_name");
-       if (current() == 'G')
-       {
-         if (next() != 'V')
-           _GLIBCXX_DEMANGLER_FAILURE;
-         output += "guard variable for ";
-         string_type nested_name_qualifiers;
-         eat_current();
-         if (!decode_name(output, nested_name_qualifiers))
-           _GLIBCXX_DEMANGLER_FAILURE;
-         output += nested_name_qualifiers;
-         _GLIBCXX_DEMANGLER_RETURN;
-       }
-       else if (current() != 'T')
-         _GLIBCXX_DEMANGLER_FAILURE;
-       switch(next())
-       {
-         case 'V':
-           output += "vtable for ";
-           eat_current();
-           decode_type(output);
-           _GLIBCXX_DEMANGLER_RETURN;
-         case 'T':
-           output += "VTT for ";
-           eat_current();
-           decode_type(output);
-           _GLIBCXX_DEMANGLER_RETURN;
-         case 'I':
-           output += "typeinfo for ";
-           eat_current();
-           decode_type(output);
-           _GLIBCXX_DEMANGLER_RETURN;
-         case 'S':
-           output += "typeinfo name for ";
-           eat_current();
-           decode_type(output);
-           _GLIBCXX_DEMANGLER_RETURN;
-         case 'c':
-           output += "covariant return thunk to ";
-           if (!decode_call_offset(output)
-               || !decode_call_offset(output)
-               || (M_pos += decode_encoding(output, M_str + M_pos,
-                   M_maxpos - M_pos + 1, M_implementation_details)) < 0)
-             _GLIBCXX_DEMANGLER_FAILURE;
-           _GLIBCXX_DEMANGLER_RETURN;
-         case 'C':             // GNU extension?
-         {
-           string_type first;
-           output += "construction vtable for ";
-           eat_current();
-           if (!decode_type(first))
-             _GLIBCXX_DEMANGLER_FAILURE;
-           while(isdigit(current()))
-             eat_current();
-           if (eat_current() != '_')
-             _GLIBCXX_DEMANGLER_FAILURE;
-           if (!decode_type(output))
-             _GLIBCXX_DEMANGLER_FAILURE;
-           output += "-in-";
-           output += first;
-           _GLIBCXX_DEMANGLER_RETURN;
-         }
-         default:
-           if (current() == 'v')
-             output += "virtual thunk to ";
-           else
-             output += "non-virtual thunk to ";
-           if (!decode_call_offset(output)
-               || (M_pos += decode_encoding(output, M_str + M_pos,
-                   M_maxpos - M_pos + 1, M_implementation_details)) < 0)
-             _GLIBCXX_DEMANGLER_FAILURE;
-           _GLIBCXX_DEMANGLER_RETURN;
-       }
-      }
-
-    // <encoding> ::=
-    //   <function name> <bare-function-type>  # Starts with 'C', 'D', 'N',
-    //                                           'S', a digit or a lower case
-    //                                           character.
-    //   <data name>                           # Idem.
-    //   <special-name>                                # Starts with 'T' or 'G'.
-    template<typename Tp, typename Allocator>
-      int
-      session<Tp, Allocator>::decode_encoding(string_type& output,
-          char const* in, int len, implementation_details const& id)
-      {
-#if _GLIBCXX_DEMANGLER_CWDEBUG
-       _GLIBCXX_DEMANGLER_DOUT(dc::demangler,
-           "Output thus far: \"" << output << '"');
-       string_type input(in, len > 0x40000000 ? strlen(in) : len);
-       _GLIBCXX_DEMANGLER_DOUT(
-           dc::demangler, "Entering decode_encoding(\"" << input << "\")");
-#endif
-       if (len <= 0)
-         return INT_MIN;
-       session<Tp, Allocator> demangler_session(in, len, id);
-       string_type nested_name_qualifiers;
-       int saved_pos;
-       demangler_session.store(saved_pos);
-       if (demangler_session.decode_special_name(output))
-         return demangler_session.M_pos;
-       demangler_session.restore(saved_pos);
-       string_type name;
-       if (!demangler_session.decode_name(name, nested_name_qualifiers))
-         return INT_MIN;
-       if (demangler_session.current() == 0
-           || demangler_session.current() == 'E')
-       {
-         output += name;
-         output += nested_name_qualifiers;
-         return demangler_session.M_pos;
-       }
-       // Must have been a <function name>.
-       string_type return_type_postfix;
-       if (demangler_session.M_name_is_template
-           && !(demangler_session.M_name_is_cdtor
-                || demangler_session.M_name_is_conversion_operator))
-       {
-         // Return type of function
-         if (!demangler_session.decode_type_with_postfix(output,
-             return_type_postfix))
-           return INT_MIN;
-         output += ' ';
-       }
-       output += name;
-       if (!demangler_session.decode_bare_function_type(output))
-         return INT_MIN;
-       output += nested_name_qualifiers;
-       output += return_type_postfix;
-       return demangler_session.M_pos;
-      }
-
-    } // namespace demangler
-
-  // Public interface
-  template<typename Tp, typename Allocator>
-    struct demangle
-    {
-      typedef typename Allocator::template rebind<char>::other char_Allocator;
-      typedef std::basic_string<char, std::char_traits<char>, char_Allocator>
-         string_type;
-      static string_type symbol(char const* in,
-                                demangler::implementation_details const& id);
-      static string_type type(char const* in,
-                              demangler::implementation_details const& id);
-    };
-
-  // demangle::symbol()
-  //
-  // Demangle `input' which should be a mangled function name as for
-  // instance returned by nm(1).
-  template<typename Tp, typename Allocator>
-    typename demangle<Tp, Allocator>::string_type
-    demangle<Tp, Allocator>::symbol(char const* input,
-                                demangler::implementation_details const& id)
-    {
-      // <mangled-name> ::= _Z <encoding>
-      // <mangled-name> ::= _GLOBAL_ _<type>_ <disambiguation part>
-      //                    <type> can be I or D (GNU extension)
-      typedef demangler::session<Tp, Allocator> demangler_type;
-      string_type result;
-      bool failure = (input[0] != '_');
-
-      if (!failure)
-      {
-       if (input[1] == 'G')
-       {
-         if (!strncmp(input, "_GLOBAL__", 9)
-             && (input[9] == 'D' || input[9] == 'I')
-             && input[10] == '_')
-         {
-           if (input[9] == 'D')
-             result.assign("global destructors keyed to ", 28);
-           else
-             result.assign("global constructors keyed to ", 29);
-           // Output the disambiguation part as-is.
-           result += input + 11;
-         }
-         else
-           failure = true;
-       }
-       else if (input[1] == 'Z')
-       {
-         int cnt =
-             demangler_type::decode_encoding(result, input + 2, INT_MAX, id);
-         if (cnt < 0 || input[cnt + 2] != 0)
-           failure = true;
-       }
-       else
-         failure = true;
-      }
-
-      // Failure to demangle, return the mangled name.
-      if (failure)
-       result.assign(input, strlen(input));
-
-      return result;
-    }
-
-  // demangle::type()
-  // Demangle `input' which must be a zero terminated mangled type
-  // name as for instance returned by std::type_info::name().
-  template<typename Tp, typename Allocator>
-    typename demangle<Tp, Allocator>::string_type
-    demangle<Tp, Allocator>::type(char const* input,
-                              demangler::implementation_details const& id)
-    {
-      std::basic_string<char, std::char_traits<char>, Allocator> result;
-      if (input == NULL)
-       result = "(null)";
-      else
-      {
-       demangler::session<Tp, Allocator> demangler_session(input, INT_MAX, id);
-       if (!demangler_session.decode_type(result)
-           || demangler_session.remaining_input_characters())
-       {
-         // Failure to demangle, return the mangled name.
-         result = input;
-       }
-      }
-      return result;
-    }
-} // namespace __gnu_cxx
-
-#endif // __DEMANGLE_H