OSDN Git Service

PR libstdc++/13045
authorcarlo <carlo@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 5 Dec 2003 02:40:53 +0000 (02:40 +0000)
committercarlo <carlo@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 5 Dec 2003 02:40:53 +0000 (02:40 +0000)
* bits/demangle.h
namespace __gnu_cxx::demangler
(enum substitution_nt): Removed trailing comma.
(implementation_details): Added.
(session<Allocator>::M_implementation_details): Added.
(session<Allocator>::session): Pass implementation_details.
(session<Allocator>::decode_encoding): Same.
(session<Allocator>::decode_real): Added.
(_GLIBCXX_DEMANGLER_STYLE_VOID _GLIBCXX_DEMANGLER_STYLE_LITERAL
_GLIBCXX_DEMANGLER_STYLE_LITERAL_INT
_GLIBCXX_DEMANGLER_STYLE_COMPACT_EXPR_OPS
_GLIBCXX_DEMANGLER_STYLE_SIZEOF_TYPENAME): Replaced with
implementation_details equivalent.
(session<Allocator>::decode_expression):
Use M_implementation_details instead of macros. Add extra parentheses
around 'larger than' operator in expressions in template arguments.
(session<Allocator>::decode_bare_function_type): Idem.
(session<Allocator>::decode_literal):
Idem, and call decode_real for floating literals.
(session<Allocator>::decode_type_with_postfix): Put the postfix
of the return type of (member) functions after the function
instead of after the return type.  Also, put a space after the
prefix of qualified function pointers: "int (* const<space>".
* src/demangle.cc: include most dependent header file first.
* testsuite/demangle/regression/cw-16.cc: Updated two
and added three tests.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@74304 138bc75d-0d04-0410-961f-82ee72b054a4

libstdc++-v3/ChangeLog
libstdc++-v3/include/bits/demangle.h
libstdc++-v3/src/demangle.cc
libstdc++-v3/testsuite/demangle/regression/cw-16.cc

index 3b7d183..f2936ed 100644 (file)
@@ -1,3 +1,33 @@
+2003-12-05  Carlo Wood  <carlo@alinoe.com>
+
+       PR libstdc++/13045
+       * bits/demangle.h
+       namespace __gnu_cxx::demangler
+       (enum substitution_nt): Removed trailing comma.
+       (implementation_details): Added.
+       (session<Allocator>::M_implementation_details): Added.
+       (session<Allocator>::session): Pass implementation_details.
+       (session<Allocator>::decode_encoding): Same.
+       (session<Allocator>::decode_real): Added.
+       (_GLIBCXX_DEMANGLER_STYLE_VOID _GLIBCXX_DEMANGLER_STYLE_LITERAL
+       _GLIBCXX_DEMANGLER_STYLE_LITERAL_INT
+       _GLIBCXX_DEMANGLER_STYLE_COMPACT_EXPR_OPS
+       _GLIBCXX_DEMANGLER_STYLE_SIZEOF_TYPENAME): Replaced with
+       implementation_details equivalent.
+       (session<Allocator>::decode_expression):
+       Use M_implementation_details instead of macros. Add extra parentheses
+       around 'larger than' operator in expressions in template arguments.
+       (session<Allocator>::decode_bare_function_type): Idem.
+       (session<Allocator>::decode_literal):
+       Idem, and call decode_real for floating literals.
+       (session<Allocator>::decode_type_with_postfix): Put the postfix
+       of the return type of (member) functions after the function
+       instead of after the return type.  Also, put a space after the
+       prefix of qualified function pointers: "int (* const<space>".
+       * src/demangle.cc: include most dependent header file first.
+       * testsuite/demangle/regression/cw-16.cc: Updated two
+       and added three tests.
+
 2003-12-04  Benjamin Kosnik  <bkoz@redhat.com>
 
        PR libstdc++/13284
index af8cff9..cb90acc 100644 (file)
 #define _GLIBCXX_DEMANGLER_CWDEBUG 1
 #endif
 
-// The following defines change the behaviour of the demangler.  The
-// default behaviour is that none of these macros is defined.
-
-// _GLIBCXX_DEMANGLER_STYLE_VOID
-// Default behaviour:                                  int f()
-// Uses (void) instead of ():                          int f(void)
-
-// _GLIBCXX_DEMANGLER_STYLE_LITERAL
-// Default behaviour:                                  (long)13, 
-//                                                     (unsigned long long)19
-// Use extensions 'u', 'l' and 'll' for integral
-// literals (as in template arguments):                        13l, 19ull
-
-// _GLIBCXX_DEMANGLER_STYLE_LITERAL_INT
-// Default behaviour:                                  4
-// Use also an explicit cast for int in literals:      (int)4
-
-// _GLIBCXX_DEMANGLER_STYLE_COMPACT_EXPR_OPS
-// Default behaviour:                                  (i) < (3), sizeof (int)
-// Don't output spaces around operators in expressions:        (i)<(3), sizeof(int)
-
-// _GLIBCXX_DEMANGLER_STYLE_SIZEOF_TYPENAME
-// Default behaviour:                                  sizeof (X::t)
-// Put 'typename' infront of <nested-name> types
-// inside a 'sizeof':                                  sizeof (typename X::t)
-
 namespace __gnu_cxx
 {
   namespace demangler
@@ -91,7 +65,7 @@ namespace __gnu_cxx
       template_template_param,
       nested_name_prefix,
       nested_name_template_prefix,
-      unscoped_template_name,
+      unscoped_template_name
     };
 
     struct substitution_st
@@ -312,6 +286,59 @@ namespace __gnu_cxx
 #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 Allocator>
       class session
       {
@@ -336,25 +363,29 @@ namespace __gnu_cxx
        std::vector<int, Allocator> M_template_arg_pos;
        int M_template_arg_pos_offset;
        std::vector<substitution_st, Allocator> M_substitutions_pos;
+       implementation_details const& M_implementation_details;
 #if _GLIBCXX_DEMANGLER_CWDEBUG
        bool M_inside_add_substitution;
 #endif
 
       public:
-       explicit session(char const* in, int len)
+       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_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);
+       decode_encoding(string_type& output, char const* input, int len,
+         implementation_details const& id = implementation_details());
 
        bool
        decode_type(string_type& output,
@@ -425,6 +456,7 @@ namespace __gnu_cxx
        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 Allocator>
@@ -881,6 +913,66 @@ namespace __gnu_cxx
 
     template<typename Allocator>
       bool
+      session<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 Allocator>
+      bool
       session<Allocator>::decode_literal(string_type& output)
       {
        _GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_literal");
@@ -891,7 +983,7 @@ namespace __gnu_cxx
            _GLIBCXX_DEMANGLER_FAILURE;
          eat_current();
          if ((M_pos += decode_encoding(output, M_str + M_pos,
-                 M_maxpos - M_pos + 1)) < 0)
+                 M_maxpos - M_pos + 1, M_implementation_details)) < 0)
            _GLIBCXX_DEMANGLER_FAILURE;
        }
        else
@@ -907,34 +999,39 @@ namespace __gnu_cxx
            _GLIBCXX_DEMANGLER_RETURN;
          }
          char c = current();
-#ifdef _GLIBCXX_DEMANGLER_STYLE_LITERAL
-         if (c == 'i' || c == 'j' || c == 'l' ||
-             c == 'm' || c == 'x' || c == 'y')
+         if ((c == 'i' || c == 'j' || c == 'l' ||
+              c == 'm' || c == 'x' || c == 'y') &&
+              M_implementation_details.get_style_literal())
            eat_current();
-         else
-#else
-#ifndef _GLIBCXX_DEMANGLER_STYLE_LITERAL_INT
-         if (c == 'i')
+         else if (c == 'i' &&
+             !M_implementation_details.get_style_literal_int())
            eat_current();
          else
-#endif
-#endif
          {
            output += '(';
            if (!decode_type(output))
              _GLIBCXX_DEMANGLER_FAILURE;
            output += ')';
          }
-         if (!decode_number(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;
-#ifdef _GLIBCXX_DEMANGLER_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";
-#endif
+          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;
       }
@@ -1204,11 +1301,10 @@ namespace __gnu_cxx
          if (opcode1 == 't' || opcode1 == 'z')
          {
            eat_current();
-#ifdef _GLIBCXX_DEMANGLER_STYLE_COMPACT_EXPR_OPS
-           output += "sizeof(";
-#else
-           output += "sizeof (";
-#endif
+           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
@@ -1240,21 +1336,22 @@ namespace __gnu_cxx
              // This is ambiguity is very unlikely to happen and it is kind
              // of fuzzy to detect when adding a 'typename' makes sense.
              //
-#ifdef _GLIBCXX_DEMANGLER_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 ";
-#endif
+             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;
            }
@@ -1305,32 +1402,33 @@ namespace __gnu_cxx
                  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)
                {
-#ifndef _GLIBCXX_DEMANGLER_STYLE_COMPACT_EXPR_OPS
-                 output += ' ';
-#endif
+                 if (!M_implementation_details.get_style_compact_expr_ops())
+                   output += ' ';
                  output += op;
                  if (is_eq)
                    output += '=';
-#ifndef _GLIBCXX_DEMANGLER_STYLE_COMPACT_EXPR_OPS
-                 output += ' ';
-#endif
+                 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)
                  {
-#ifdef _GLIBCXX_DEMANGLER_STYLE_COMPACT_EXPR_OPS
-                   output += ":(";
-#else
-                   output += " : (";
-#endif
+                   if (M_implementation_details.get_style_compact_expr_ops())
+                     output += ":(";
+                   else
+                     output += " : (";
                    if (!decode_expression(output))
                      _GLIBCXX_DEMANGLER_FAILURE;
                    output += ')';
@@ -1440,8 +1538,7 @@ namespace __gnu_cxx
          M_saw_destructor = false;
          _GLIBCXX_DEMANGLER_RETURN;
        }
-#ifndef _GLIBCXX_DEMANGLER_STYLE_VOID
-       if (current() == 'v')
+       if (current() == 'v' && !M_implementation_details.get_style_void())
        {
          eat_current();
          if (current() != 'E' && current() != 0)
@@ -1450,7 +1547,6 @@ namespace __gnu_cxx
          M_saw_destructor = false;
          _GLIBCXX_DEMANGLER_RETURN;
        }
-#endif
        output += '(';
        M_template_args_need_space = false;
        if (!decode_type(output))       // Must have at least one parameter.
@@ -1508,8 +1604,8 @@ namespace __gnu_cxx
     // <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), then those
-    // are added AFTER the (member) function type.  For example:
+    // 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 ") []".
     //
@@ -1863,7 +1959,8 @@ namespace __gnu_cxx
                // Return type.
                // Constructors, destructors and conversion operators don't
                // have a return type, but seem to never get here.
-               if (!decode_type_with_postfix(prefix, postfix))
+               string_type return_type_postfix;
+               if (!decode_type_with_postfix(prefix, return_type_postfix))
                    // substitution: <R> recursive
                {
                  failure = true;
@@ -1885,9 +1982,10 @@ namespace __gnu_cxx
                add_substitution(start_pos, type);
                // substitution: all qualified types if any.
                qualifiers->decode_qualifiers(prefix, postfix);
-               prefix += ")";
-               prefix += bare_function_type;
-               prefix += member_function_qualifiers;
+               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,
@@ -1929,17 +2027,19 @@ namespace __gnu_cxx
              //     substitution: "<R>", "<B>" (<B> recursive) and "F<R><B>E".
 
              // Return type.
-             if (!decode_type_with_postfix(prefix, postfix))
+             string_type return_type_postfix;
+             if (!decode_type_with_postfix(prefix, return_type_postfix))
                  // Substitution: "<R>".
              {
                failure = true;
                break;
              }
-             // Only array (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]".
-             if (postfix.size() == 0)
+             // 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;
@@ -1953,10 +2053,11 @@ namespace __gnu_cxx
              add_substitution(start_pos, type);  // Substitution: "F<R><B>E".
              qualifiers->decode_qualifiers(prefix, postfix);
                  // substitution: all qualified types, if any.
-             prefix += ")";
+             postfix += ")";
              if (extern_C)
-               prefix += " [extern \"C\"] ";
-             prefix += bare_function_type;
+               postfix += " [extern \"C\"] ";
+             postfix += bare_function_type;
+             postfix += return_type_postfix;
              break;
            }
            case 'T':
@@ -2181,7 +2282,8 @@ namespace __gnu_cxx
        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) + 1) < 0 || eat_current() != 'E')
+               M_maxpos - M_pos, M_implementation_details) + 1) < 0 ||
+               eat_current() != 'E')
          _GLIBCXX_DEMANGLER_FAILURE;
        output += "::";
        if (current() == 's')
@@ -2480,7 +2582,7 @@ namespace __gnu_cxx
            if (!decode_call_offset(output)
                || !decode_call_offset(output)
                || (M_pos += decode_encoding(output, M_str + M_pos,
-                   M_maxpos - M_pos + 1)) < 0)
+                   M_maxpos - M_pos + 1, M_implementation_details)) < 0)
              _GLIBCXX_DEMANGLER_FAILURE;
            _GLIBCXX_DEMANGLER_RETURN;
          case 'C':             // GNU extension?
@@ -2507,7 +2609,7 @@ namespace __gnu_cxx
              output += "non-virtual thunk to ";
            if (!decode_call_offset(output)
                || (M_pos += decode_encoding(output, M_str + M_pos,
-                   M_maxpos - M_pos + 1)) < 0)
+                   M_maxpos - M_pos + 1, M_implementation_details)) < 0)
              _GLIBCXX_DEMANGLER_FAILURE;
            _GLIBCXX_DEMANGLER_RETURN;
        }
@@ -2522,8 +2624,7 @@ namespace __gnu_cxx
     template<typename Allocator>
       int
       session<Allocator>::decode_encoding(string_type& output,
-                                         char const* in,
-                                         int len)
+          char const* in, int len, implementation_details const& id)
       {
 #if _GLIBCXX_DEMANGLER_CWDEBUG
        _GLIBCXX_DEMANGLER_DOUT(dc::demangler,
@@ -2534,7 +2635,7 @@ namespace __gnu_cxx
 #endif
        if (len <= 0)
          return INT_MIN;
-       session<Allocator> demangler_session(in, len);
+       session<Allocator> demangler_session(in, len, id);
        string_type nested_name_qualifiers;
        int saved_pos;
        demangler_session.store(saved_pos);
@@ -2577,8 +2678,10 @@ namespace __gnu_cxx
       typedef Allocator allocator_type;
       typedef std::basic_string<char, std::char_traits<char>, Allocator> 
          string_type;
-      static string_type symbol(char const* in);
-      static string_type type(char const* in);
+      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()
@@ -2587,7 +2690,8 @@ namespace __gnu_cxx
   // instance returned by nm(1).
   template<typename Allocator>
     std::basic_string<char, std::char_traits<char>, Allocator>
-    demangle<Allocator>::symbol(char const* input)
+    demangle<Allocator>::symbol(char const* input,
+                                demangler::implementation_details const& id)
     {
       // <mangled-name> ::= _Z <encoding>
       // <mangled-name> ::= _GLOBAL_ _<type>_ <disambiguation part>
@@ -2616,8 +2720,8 @@ namespace __gnu_cxx
        }
        else if (input[1] == 'Z')
        {
-         int cnt = demangler_type::decode_encoding(result, input + 2,
-                                                   INT_MAX);
+         int cnt =
+             demangler_type::decode_encoding(result, input + 2, INT_MAX, id);
          if (cnt < 0 || input[cnt + 2] != 0)
            failure = true;
        }
@@ -2637,14 +2741,15 @@ namespace __gnu_cxx
   // name as for instance returned by std::type_info::name().
   template<typename Allocator>
     std::basic_string<char, std::char_traits<char>, Allocator> 
-    demangle<Allocator>::type(char const* input)
+    demangle<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<Allocator> demangler_session(input, INT_MAX);
+       demangler::session<Allocator> demangler_session(input, INT_MAX, id);
        if (!demangler_session.decode_type(result)
            || demangler_session.remaining_input_characters())
        {
index fc5672b..58c0767 100644 (file)
@@ -28,8 +28,8 @@
 // invalidate any other reasons why the executable file might be covered by
 // the GNU General Public License.
 
-#include <cxxabi.h>
 #include <bits/demangle.h>
+#include <cxxabi.h>
 
 // __cxa_demangle
 //
index 6ca0cd7..8dbfcb1 100644 (file)
@@ -32,15 +32,22 @@ verify_demangle("_Z3fooIA6_KiEvA9_KT_rVPrS4_",
                "void foo<int const [6]>(int const [9][6], int const restrict (* volatile restrict) [9][6])");
 // 2003/11/12, libstdc++/12947
 verify_demangle("_Z1fILi5E1AEvN1CIXqugtT_Li0ELi1ELi2EEE1qE",
-                "void f<5, A>(C<((5) > (0)) ? (1) : (2)>::q)");
+                "void f<5, A>(C<(((5) > (0))) ? (1) : (2)>::q)");
 verify_demangle("_Z1fILi5EEvN1AIXcvimlT_Li22EEE1qE",
                 "void f<5>(A<(int)((5) * (22))>::q)");
 verify_demangle("_Z1fPFYPFiiEiE",
-                "f(int (*)(int) (*) [extern \"C\"] (int))");
+                "f(int (*(*) [extern \"C\"] (int))(int))");
 verify_demangle("_Z1fI1XENT_1tES2_",
                 "X::t f<X>(X::t)");
 verify_demangle("_Z1fILi5E1AEvN1CIXstN1T1tEEXszsrS2_1tEE1qE",
                 "void f<5, A>(C<sizeof (T::t), sizeof (T::t)>::q)");
+// 2003/12/03, libstdc++/13045
+verify_demangle("_Z1fILi1ELc120EEv1AIXplT_cviLd4028ae147ae147aeEEE",
+                "void f<1, (char)120>(A<(1) + ((int)((double)[4028ae147ae147ae]))>)");
+verify_demangle("_Z1fILi1ELc120EEv1AIXplT_cviLf3f800000EEE",
+                "void f<1, (char)120>(A<(1) + ((int)((float)[3f800000]))>)");
+verify_demangle("_Z9hairyfuncM1YKFPVPFrPA2_PM1XKFKPA3_ilEPcEiE",
+                "hairyfunc(int (* const (X::** (* restrict (* volatile* (Y::*)(int) const)(char*)) [2])(long) const) [3])");
 
   return 0;
 }