[PATCH] PR libstdc++/13045

Carlo Wood carlo@alinoe.com
Thu Dec 4 18:30:00 GMT 2003


On Wed, Dec 03, 2003 at 11:00:20PM -0600, Benjamin Kosnik wrote:
> 
> >2003-12-03  Carlo Wood  <carlo@alinoe.com>
> >
> >	PR libstdc++/13045
> >	* bits/demangle.h
> >	namespace __gnu_cxx::demangler
> >	(enum substitution_nt): Removed trailing comma.
> >	(session<Allocator>::decode_real): Added.
> >	(session<Allocator>::decode_literal): 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 one
> >	and added three tests.
> 
> This is fine, thanks. 

Err - I changed it a little bit - because the virtual decode_real
could not be overridden by users with the given interface.
Instead, I added a new class called 'demangler::implementation_details'
and did put the virtual decode_real into that class.  Then a reference
to this object is being passed around to the static
session<>::decode_encoding.  This was needed because a new encoding
session starts completely fresh (new instance) but does need to keep
the implementation details.
Now, while I was at it, I removed all the _GLIBCXX_DEMANGLER_STYLE_*
macros too and put an equivalent in the new implementation_details
class; this will allow user applications to have all possible formats
in one application at their disposal without any code duplication/bloat.
Hell, I might even add a foo<T> [with T = bar] style later.

The new ChangeLog is:


2003-12-04  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.
	(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 one
	and added three tests.

Tested to compile and run the demangler testsuite.

The functionality of this patch from the point of view
of the default libstdc++-v3 demangling behaviour, did not change.

Still ok to commit?

[New patch attached in case you want to look at it.]

-- 
Carlo Wood <carlo@alinoe.com>
-------------- next part --------------
Index: libstdc++-v3/include/bits/demangle.h
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/include/bits/demangle.h,v
retrieving revision 1.11
diff -u -d -p -r1.11 demangle.h
--- libstdc++-v3/include/bits/demangle.h	12 Nov 2003 02:18:36 -0000	1.11
+++ libstdc++-v3/include/bits/demangle.h	4 Dec 2003 17:51:45 -0000
@@ -54,32 +54,6 @@
 #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;
 	    }
@@ -1311,26 +1408,23 @@ namespace __gnu_cxx
 		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 (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 +1534,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 +1543,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 +1600,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 +1955,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 +1978,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 +2023,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 +2049,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 +2278,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 +2578,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 +2605,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 +2620,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 +2631,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 +2674,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 +2686,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 +2716,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 +2737,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: libstdc++-v3/src/demangle.cc
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/src/demangle.cc,v
retrieving revision 1.3
diff -u -d -p -r1.3 demangle.cc
--- libstdc++-v3/src/demangle.cc	2 Oct 2003 14:29:26 -0000	1.3
+++ libstdc++-v3/src/demangle.cc	4 Dec 2003 17:51:45 -0000
@@ -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: libstdc++-v3/testsuite/demangle/regression/cw-16.cc
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/testsuite/demangle/regression/cw-16.cc,v
retrieving revision 1.3
diff -u -d -p -r1.3 cw-16.cc
--- libstdc++-v3/testsuite/demangle/regression/cw-16.cc	12 Nov 2003 02:18:37 -0000	1.3
+++ libstdc++-v3/testsuite/demangle/regression/cw-16.cc	4 Dec 2003 17:51:50 -0000
@@ -36,11 +36,18 @@ verify_demangle("_Z1fILi5E1AEvN1CIXqugtT
 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;
 }


More information about the Libstdc++ mailing list