public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* Re: RFA/RFC: Add stack recursion limit to libiberty's demangler
@ 2018-11-30  8:38 Nick Clifton
  2018-11-30  8:42 ` Jakub Jelinek
  0 siblings, 1 reply; 55+ messages in thread
From: Nick Clifton @ 2018-11-30  8:38 UTC (permalink / raw)
  To: ian; +Cc: gcc-patches, binutils, matz, sgayou, jason

[-- Attachment #1: Type: text/plain, Size: 1718 bytes --]

Hi Ian,

  *sigh* it is always the way.  You post a patch and five minutes later
  you find a bug in it.  In this case it turned out that I had forgotten
  that gcc has its own copy of the libiberty sources, so the bootstrap
  test that I had run did not use the patched sources.  Doh.  When I did
  rerun the bootstrap with the patched sources it failed because I had
  forgotten to use the CP_STATIC_IF_GLIBCPP_V3 macro when declaring the
  new cplus_demangle_set_recursion_limit() function.

  I am attaching a revised patch with this bug fixed, and an updated
  changelog entry as I have found a few more CVE PRs that it fixes.

  Also - Tom and Pedro have raised the issue that the patch introduces
  a new static variable to the library that is not thread safe.  I am
  not sure of the best way to address this problem.  Possibly the
  variable could be made thread local ?  Are there any other static
  variables in libiberty that face the same issue ?
  
Cheers
  Nick

libiberty/ChangeLog
2018-11-29  Nick Clifton  <nickc@redhat.com>

	PR 87681
	PR 87675
	PR 87636
	PR 87335
	* cp-demangle.c (demangle_recursion_limit): New static
	variable.
        (d_function_type): Add recursion counter.  If the recursion
        limit is enabled and reached, return with a failure result.
        (d_demangle_callback): If the recursion limit is enabled, check
	for a mangled string that is so long that there is not enough
	stack space for the local arrays.
        (cplus_demangle_set_recursion): New function.  Sets and/or
	returns the current stack recursion limit.
        * cplus-dem.c (demangle_nested_args): Add recursion counter.  If
	the recursion limit is enabled and reached, return with a
	failure result.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: libiberty-demangler-recursion-limit.2.patch --]
[-- Type: text/x-patch, Size: 4725 bytes --]

Index: libiberty/cp-demangle.c
===================================================================
--- libiberty/cp-demangle.c	(revision 266657)
+++ libiberty/cp-demangle.c	(working copy)
@@ -62,6 +62,7 @@
       cplus_demangle_fill_dtor
       cplus_demangle_print
       cplus_demangle_print_callback
+      cplus_demangle_set_recursion_limit
    and other functions defined in the file cp-demint.c.
 
    This file also defines some other functions and variables which are
@@ -181,6 +182,9 @@
 #define cplus_demangle_init_info d_init_info
 static void d_init_info (const char *, int, size_t, struct d_info *);
 
+#define cplus_demangle_set_recursion_limit d_set_recursion_level
+static  unsigned int d_set_recursion_limit (unsigned int);
+
 #else /* ! defined(IN_GLIBCPP_V3) */
 #define CP_STATIC_IF_GLIBCPP_V3
 #endif /* ! defined(IN_GLIBCPP_V3) */
@@ -2852,21 +2856,34 @@
 static struct demangle_component *
 d_function_type (struct d_info *di)
 {
-  struct demangle_component *ret;
+  static unsigned long recursion_level = 0;
+  struct demangle_component *ret = NULL;
 
-  if (! d_check_char (di, 'F'))
-    return NULL;
-  if (d_peek_char (di) == 'Y')
+  if ((di->options & DMGL_RECURSE_LIMIT)
+      && recursion_level > demangle_recursion_limit)
     {
-      /* Function has C linkage.  We don't print this information.
-	 FIXME: We should print it in verbose mode.  */
-      d_advance (di, 1);
+      /* FIXME: There ought to be a way to report that the recursion limit
+	 has been reached.  */
+      return NULL;
     }
-  ret = d_bare_function_type (di, 1);
-  ret = d_ref_qualifier (di, ret);
 
-  if (! d_check_char (di, 'E'))
-    return NULL;
+  recursion_level ++;
+  if (d_check_char (di, 'F'))
+    {
+      if (d_peek_char (di) == 'Y')
+	{
+	  /* Function has C linkage.  We don't print this information.
+	     FIXME: We should print it in verbose mode.  */
+	  d_advance (di, 1);
+	}
+      ret = d_bare_function_type (di, 1);
+      ret = d_ref_qualifier (di, ret);
+      
+      if (! d_check_char (di, 'E'))
+	ret = NULL;
+    }
+
+  recursion_level --;
   return ret;
 }
 
@@ -6242,6 +6259,20 @@
 
   cplus_demangle_init_info (mangled, options, strlen (mangled), &di);
 
+  /* PR 87675 - Check for a mangled string that is so long
+     that we do not have enough stack space to demangle it.  */
+  if ((options & DMGL_RECURSE_LIMIT)
+      /* This check is a bit arbitrary, since what we really want to do is to
+	 compare the sizes of the di.comps and di.subs arrays against the
+	 amount of stack space remaining.  But there is no portable way to do
+	 this, so instead we use the recursion limit as a guide to the maximum
+	 size of the arrays.  */
+      && (unsigned long) di.num_comps > demangle_recursion_limit)
+    {
+      /* FIXME: We need a way to indicate that a stack limit has been reached.  */
+      return 0;
+    }
+
   {
 #ifdef CP_DYNAMIC_ARRAYS
     __extension__ struct demangle_component comps[di.num_comps];
@@ -6324,6 +6355,23 @@
   return dgs.buf;
 }
 
+/* Set a limit on the amount of recursion allowed in mangled strings.
+   Only effective if the DMGL_RECURSE_LIMIT option has been set.
+   Returns the previous value of the recursion limit.
+   Ignores settings a limit of 0 or 1.
+   Note - setting the limit is not a thread-safe operation.  */
+
+CP_STATIC_IF_GLIBCPP_V3
+unsigned long
+cplus_demangle_set_recursion_limit (unsigned long limit)
+{
+  unsigned long result = demangle_recursion_limit;
+
+  if (limit > 1)
+    demangle_recursion_limit = limit;
+  return result;
+}
+
 #if defined(IN_LIBGCC2) || defined(IN_GLIBCPP_V3)
 
 extern char *__cxa_demangle (const char *, char *, size_t *, int *);
Index: libiberty/cplus-dem.c
===================================================================
--- libiberty/cplus-dem.c	(revision 266657)
+++ libiberty/cplus-dem.c	(working copy)
@@ -4693,10 +4693,21 @@
 demangle_nested_args (struct work_stuff *work, const char **mangled,
                       string *declp)
 {
+  static unsigned long recursion_level = 0;
   string* saved_previous_argument;
   int result;
   int saved_nrepeats;
 
+  if ((work->options & DMGL_RECURSE_LIMIT)
+      && recursion_level > cplus_demangle_set_recursion_limit (0))
+    {
+      /* FIXME: There ought to be a way to report that the recursion limit
+	 has been reached.  */
+      return 0;
+    }
+
+  recursion_level ++;
+
   /* The G++ name-mangling algorithm does not remember types on nested
      argument lists, unless -fsquangling is used, and in that case the
      type vector updated by remember_type is not used.  So, we turn
@@ -4723,6 +4734,7 @@
   --work->forgetting_types;
   work->nrepeats = saved_nrepeats;
 
+  --recursion_level;
   return result;
 }
 

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: RFA/RFC: Add stack recursion limit to libiberty's demangler
  2018-11-30  8:38 RFA/RFC: Add stack recursion limit to libiberty's demangler Nick Clifton
@ 2018-11-30  8:42 ` Jakub Jelinek
  2018-11-30 10:27   ` Nick Clifton
  0 siblings, 1 reply; 55+ messages in thread
From: Jakub Jelinek @ 2018-11-30  8:42 UTC (permalink / raw)
  To: Nick Clifton; +Cc: ian, gcc-patches, binutils, matz, sgayou, jason

On Fri, Nov 30, 2018 at 08:38:48AM +0000, Nick Clifton wrote:
>   Also - Tom and Pedro have raised the issue that the patch introduces
>   a new static variable to the library that is not thread safe.  I am
>   not sure of the best way to address this problem.  Possibly the
>   variable could be made thread local ?  Are there any other static

Please don't.  That has a cost for all the programs that link against
libstdc++ or any other library that includes the demangler, even when they
don't use the demangler at all (99.9% of the users).
Most of the demangler functions pass around a pointer to a struct with
context, can't this be added in there?

	Jakub

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: RFA/RFC: Add stack recursion limit to libiberty's demangler
  2018-11-30  8:42 ` Jakub Jelinek
@ 2018-11-30 10:27   ` Nick Clifton
  2018-11-30 13:46     ` Michael Matz
  2018-11-30 13:56     ` Ian Lance Taylor
  0 siblings, 2 replies; 55+ messages in thread
From: Nick Clifton @ 2018-11-30 10:27 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: ian, gcc-patches, binutils, matz, sgayou, jason

Hi Jakub,

>>   Also - Tom and Pedro have raised the issue that the patch introduces
>>   a new static variable to the library that is not thread safe.  I am
>>   not sure of the best way to address this problem.  Possibly the
>>   variable could be made thread local ?  Are there any other static
> 
> Please don't.

OK. :-)

> Most of the demangler functions pass around a pointer to a struct with
> context, can't this be added in there?

Not without modifying the current demangling interface.  The problem is 
that the context structure is created for each invocation of a demangling 
function (from outside the library), and no state is preserved across 
demangling calls.  Thus in order to have a recursion limit which is 
configurable by the caller, you either need to have a global variable or 
else extend the demangling interface to include a recursion limit parameter.

I did consider just having a fixed limit, that the user cannot change, but
I thought that this might be rejected by reviewers.  (On the grounds that
different limits are appropriate to different execution environments).
Note - enabling or disabling the recursion limit is controlled by a separate
feature of the proposed patch, ie the new DMGL_RECURSE_LIMIT flag in the 
options field of the cplus_demangleXXX() functions.  But there is not enough
room in the options field to also include a recursion limit value.

Cheers
  Nick



^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: RFA/RFC: Add stack recursion limit to libiberty's demangler
  2018-11-30 10:27   ` Nick Clifton
@ 2018-11-30 13:46     ` Michael Matz
  2018-11-30 14:57       ` Ian Lance Taylor
  2018-11-30 13:56     ` Ian Lance Taylor
  1 sibling, 1 reply; 55+ messages in thread
From: Michael Matz @ 2018-11-30 13:46 UTC (permalink / raw)
  To: Nick Clifton; +Cc: Jakub Jelinek, ian, gcc-patches, binutils, sgayou, jason

[-- Attachment #1: Type: text/plain, Size: 2384 bytes --]

Hi,

On Fri, 30 Nov 2018, Nick Clifton wrote:

> Not without modifying the current demangling interface.  The problem is 
> that the context structure is created for each invocation of a 
> demangling function (from outside the library), and no state is 
> preserved across demangling calls.  Thus in order to have a recursion 
> limit which is configurable by the caller, you either need to have a 
> global variable or else extend the demangling interface to include a 
> recursion limit parameter.
> 
> I did consider just having a fixed limit, that the user cannot change, 
> but I thought that this might be rejected by reviewers.  (On the grounds 
> that different limits are appropriate to different execution 
> environments). Note - enabling or disabling the recursion limit is 
> controlled by a separate feature of the proposed patch, ie the new 
> DMGL_RECURSE_LIMIT flag in the options field of the cplus_demangleXXX() 
> functions.  But there is not enough room in the options field to also 
> include a recursion limit value.

Or we decide to not ignore this part of the GNU coding standard ...

> 4.2 Writing Robust Programs
>  
> Avoid arbitrary limits on the length or number of any data structure, 
> including file names, lines, files, and symbols, by allocating all data 
> structures dynamically. In most Unix utilities, “long lines are silently 
> truncated”. This is not acceptable in a GNU utility.

... just because script kiddies do mindless fuzzing work.  I realize that 
you didn't implement a fixed limit, but IMHO it's bordering with that.

But re the static variables: you have two, once the recursion depth, and 
once the limit.

The limit can be a static variable just fine, you state, as part of the 
interface that it sets global state, and if that needs to happen from 
multiple threads that the user must synchronize.  This is fine because 
there won't be many calls to constantly change that limit.

The current depth needs to be part of the d_info (resp. workstuff) 
structure, avoiding the thread-unsafety.

Another crazy idea: do encode the limit in the option field.  If you 
declare that the limit is a power of two (which IMHO doesn't 
materially change the usefullness of such limit) then you only need to 
encode the log2 of it, for which 5 bits are plenty enough (you can encode 
limits from 1 to 1<<32 then).


Ciao,
Michael.

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: RFA/RFC: Add stack recursion limit to libiberty's demangler
  2018-11-30 10:27   ` Nick Clifton
  2018-11-30 13:46     ` Michael Matz
@ 2018-11-30 13:56     ` Ian Lance Taylor
  2018-11-30 14:03       ` Jakub Jelinek
  1 sibling, 1 reply; 55+ messages in thread
From: Ian Lance Taylor @ 2018-11-30 13:56 UTC (permalink / raw)
  To: Nick Clifton; +Cc: Jakub Jelinek, gcc-patches, binutils, matz, sgayou, jason

Nick Clifton <nickc@redhat.com> writes:

> I did consider just having a fixed limit, that the user cannot change, but
> I thought that this might be rejected by reviewers.  (On the grounds that
> different limits are appropriate to different execution environments).
> Note - enabling or disabling the recursion limit is controlled by a separate
> feature of the proposed patch, ie the new DMGL_RECURSE_LIMIT flag in the 
> options field of the cplus_demangleXXX() functions.  But there is not enough
> room in the options field to also include a recursion limit value.

I think it would be fine to have a large fixed limit plus a flag to
disable the limit.  I can't think of any reason why a program would want
to change the limit unless it has complete trust in the symbols it is
demangling, and in that case it may as well simply disable the limit.

Ian

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: RFA/RFC: Add stack recursion limit to libiberty's demangler
  2018-11-30 13:56     ` Ian Lance Taylor
@ 2018-11-30 14:03       ` Jakub Jelinek
  2018-11-30 17:41         ` RFA/RFC: Add stack recursion limit to libiberty's demangler [v3] Nick Clifton
  0 siblings, 1 reply; 55+ messages in thread
From: Jakub Jelinek @ 2018-11-30 14:03 UTC (permalink / raw)
  To: gcc-patches, binutils, matz, sgayou, jason, nickc

On Fri, Nov 30, 2018 at 05:55:52AM -0800, Ian Lance Taylor wrote:
> Nick Clifton <nickc@redhat.com> writes:
> 
> > I did consider just having a fixed limit, that the user cannot change, but
> > I thought that this might be rejected by reviewers.  (On the grounds that
> > different limits are appropriate to different execution environments).
> > Note - enabling or disabling the recursion limit is controlled by a separate
> > feature of the proposed patch, ie the new DMGL_RECURSE_LIMIT flag in the 
> > options field of the cplus_demangleXXX() functions.  But there is not enough
> > room in the options field to also include a recursion limit value.
> 
> I think it would be fine to have a large fixed limit plus a flag to
> disable the limit.  I can't think of any reason why a program would want
> to change the limit unless it has complete trust in the symbols it is
> demangling, and in that case it may as well simply disable the limit.

Well, disabling the limit is what the people fuzzing it will use then
and report it still crashes.
We'd need to document that if somebody asks for no limit, then we don't
consider any cases of running as out of stack etc. as bugs, and simply
people shouldn't set that on when running on untrusted symbols.

	Jakub

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: RFA/RFC: Add stack recursion limit to libiberty's demangler
  2018-11-30 13:46     ` Michael Matz
@ 2018-11-30 14:57       ` Ian Lance Taylor
  2018-12-02  0:49         ` Cary Coutant
  0 siblings, 1 reply; 55+ messages in thread
From: Ian Lance Taylor @ 2018-11-30 14:57 UTC (permalink / raw)
  To: Michael Matz
  Cc: Nick Clifton, Jakub Jelinek, gcc-patches, binutils, sgayou, jason

Michael Matz <matz@suse.de> writes:

> On Fri, 30 Nov 2018, Nick Clifton wrote:
>
>> Not without modifying the current demangling interface.  The problem is 
>> that the context structure is created for each invocation of a 
>> demangling function (from outside the library), and no state is 
>> preserved across demangling calls.  Thus in order to have a recursion 
>> limit which is configurable by the caller, you either need to have a 
>> global variable or else extend the demangling interface to include a 
>> recursion limit parameter.
>> 
>> I did consider just having a fixed limit, that the user cannot change, 
>> but I thought that this might be rejected by reviewers.  (On the grounds 
>> that different limits are appropriate to different execution 
>> environments). Note - enabling or disabling the recursion limit is 
>> controlled by a separate feature of the proposed patch, ie the new 
>> DMGL_RECURSE_LIMIT flag in the options field of the cplus_demangleXXX() 
>> functions.  But there is not enough room in the options field to also 
>> include a recursion limit value.
>
> Or we decide to not ignore this part of the GNU coding standard ...
>
>> 4.2 Writing Robust Programs
>>  
>> Avoid arbitrary limits on the length or number of any data structure, 
>> including file names, lines, files, and symbols, by allocating all data 
>> structures dynamically. In most Unix utilities, “long lines are silently 
>> truncated”. This is not acceptable in a GNU utility.
>
> ... just because script kiddies do mindless fuzzing work.  I realize that 
> you didn't implement a fixed limit, but IMHO it's bordering with that.

That section is "Writing Robust Programs."  Robustness guarantees have
to be different for utilities and servers.  A robust server doesn't
crash because of arbitrary user input, but there are servers that
demangle names that are provided by the user.  So we need two modes for
the demangler: one that takes anything and sometimes crashes, for
utilities like c++filt, and one that doesn't crash, for servers.  And it
seems like that is what Nick is suggesting.

Ian

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: RFA/RFC: Add stack recursion limit to libiberty's demangler [v3]
  2018-11-30 14:03       ` Jakub Jelinek
@ 2018-11-30 17:41         ` Nick Clifton
  2018-11-30 17:49           ` Jakub Jelinek
                             ` (2 more replies)
  0 siblings, 3 replies; 55+ messages in thread
From: Nick Clifton @ 2018-11-30 17:41 UTC (permalink / raw)
  To: Jakub Jelinek, matz, sgayou, Ian Lance Taylor, Pedro Alves, Tom Tromey
  Cc: gcc-patches, binutils, jason

[-- Attachment #1: Type: text/plain, Size: 3776 bytes --]

Hi Guys,

>> I think it would be fine to have a large fixed limit plus a flag to
>> disable the limit.

Great - in which case please may I present version 3 of the patch.  In 
this version:

  * The cplus_demangle_set_recursion_limit() function has been removed
    and instead a new constant - DEMANGLE_RECURSION_LIMIT - is defined in
    demangle.h.

  * The recursion counters in cp-demangle.c have been merged into one
    counter, now contained in the d_info structure.

  * In cplus-dem.c the recursion counter has been moved into the work
    structure.

  * The description of the DMGL_RECURSE_LIMIT option in demangle.h has
    been enhanced to add a note that if the option is not used, then
    bug reports about stack overflows in the demangler will be rejected.

  * The binutils patch has been updated to reflect these changes.  The
    addr2line, cxxfilt, nm and objdump programs now have two new options
    --recurse-limit and --no-recurse-limit, with --recurse-limit being
    the default.  The documentation is updated to describe these options
    and to also add a note about bug reports being rejected if 
    --no-recurse-limit is used.

What do you think, is this version acceptable ?

Cheers
  Nick

libiberty/ChangeLog
2018-11-29  Nick Clifton  <nickc@redhat.com>

	PR 87681
	PR 87675
	PR 87636
	PR 87335
	* cp-demangle.h (struct d_info): Add recursion_limit field.
	* cp-demangle.c (d_function_type): If the recursion limit is 
	enabled and reached, return with a failure result.
        (d_demangle_callback): If the recursion limit is enabled, check
	for a mangled string that is so long that there is not enough
	stack space for the local arrays.
        * cplus-dem.c (struct work): Add recursion_level field.
	(demangle_nested_args): If the recursion limit is enabled and 
	reached, return with a failure result.

include/ChangeLog
2018-11-29  Nick Clifton  <nickc@redhat.com>

	* demangle.h (DMGL_RECURSE_LIMIT): Define.
        (DEMANGLE_RECURSION_LIMIT): Prototype.

binutils/ChangeLog
2018-11-29  Nick Clifton  <nickc@redhat.com>

	* addr2line.c (demangle_flags): New static variable.
        (long_options): Add --recurse-limit and --no-recurse-limit.
        (translate_address): Pass demangle_flags to bfd_demangle.
        (main): Handle --recurse-limit and --no-recurse-limit options.
        * cxxfilt.c (flags): Add DMGL_RECURSE_LIMIT.
        (long_options): Add --recurse-limit and --no-recurse-limit.
        (main): Handle new options.
        * dlltool.c (gen_def_file): Include DMGL_RECURSE_LIMIT in flags
        passed to cplus_demangle.
        * nm.c (demangle_flags): New static variable.
        (long_options): Add --recurse-limit and --no-recurse-limit.
        (main): Handle new options.
        * objdump.c (demangle_flags): New static variable.
        (usage): Add --recurse-limit and --no-recurse-limit.
        (long_options): Likewise.
        (objdump_print_symname): Pass demangle_flags to bfd_demangle.
        (disassemble_section): Likewise.
        (dump_dymbols): Likewise.
        (main): Handle new options.
        * prdbg.c (demangle_flags): New static variable.
        (tg_variable): Pass demangle_flags to demangler.
        (tg_start_function): Likewise.
        * stabs.c (demangle_flags): New static variable.
        (stab_demangle_template): Pass demangle_flags to demangler.
        (stab_demangle_v3_argtypes): Likewise.
        (stab_demangle_v3_arg): Likewise.
	* doc/binutuls.texi: Document new command line options.
	* NEWS: Mention the new feature.
        * testsuite/config/default.exp (CXXFILT): Define if not already
        defined.
        (CXXFILTFLAGS): Likewise.
        * testsuite/binutils-all/cxxfilt.exp: New file.  Runs a few
        simple tests of the cxxfilt program.

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: binutils-demangler-recursion-limit.3.patch --]
[-- Type: text/x-patch; name="binutils-demangler-recursion-limit.3.patch", Size: 26090 bytes --]

diff --git a/binutils/NEWS b/binutils/NEWS
index a3ee86ef7f..5ed61c8513 100644
--- a/binutils/NEWS
+++ b/binutils/NEWS
@@ -1,5 +1,16 @@
 -*- text -*-
 
+* The addr2line, c++filt, nm and objdump tools now have a limit on the
+  maximum amount of recursion that is allowed whilst demangling strings.
+  The value for this limit is defined by the DEMANGLE_RECRUSE_LIMIT
+  constant declared in the include/demangle.h header file.  At the time
+  of writing this constant has the value of 1024.
+
+  The --no-recurse-limit option can be used to remove the limit, restoring
+  the behaviour of earlier versions of these tools.  This may be needed in
+  order to dmangle truely complicated names, but it also leaves the tools
+  vulnerable to stack exhaustion from maliciously constructed mangled names.
+
 * Objdump's --disassemble option can now take a parameter, specifying the
   starting symbol for disassembly.  Disassembly will continue from this
   symbol up to the next symbol.
diff --git a/binutils/addr2line.c b/binutils/addr2line.c
index 008e62026e..3085806a4a 100644
--- a/binutils/addr2line.c
+++ b/binutils/addr2line.c
@@ -45,6 +45,9 @@ static bfd_boolean do_demangle;		/* -C, demangle names.  */
 static bfd_boolean pretty_print;	/* -p, print on one line.  */
 static bfd_boolean base_names;		/* -s, strip directory names.  */
 
+/* Flags passed to the name demangler.  */
+static int demangle_flags = DMGL_PARAMS | DMGL_ANSI | DMGL_RECURSE_LIMIT;
+
 static int naddr;		/* Number of addresses to process.  */
 static char **addr;		/* Hex addresses to process.  */
 
@@ -59,6 +62,10 @@ static struct option long_options[] =
   {"functions", no_argument, NULL, 'f'},
   {"inlines", no_argument, NULL, 'i'},
   {"pretty-print", no_argument, NULL, 'p'},
+  {"recurse-limit", no_argument, NULL, 'R'},
+  {"recursion-limit", no_argument, NULL, 'R'},  
+  {"no-recurse-limit", no_argument, NULL, 'r'},
+  {"no-recursion-limit", no_argument, NULL, 'r'},  
   {"section", required_argument, NULL, 'j'},
   {"target", required_argument, NULL, 'b'},
   {"help", no_argument, NULL, 'H'},
@@ -91,6 +98,8 @@ usage (FILE *stream, int status)
   -s --basenames         Strip directory names\n\
   -f --functions         Show function names\n\
   -C --demangle[=style]  Demangle function names\n\
+  -R --recurse-limit     Enable a limit on recursion whilst demangling.  [Default]\n\
+  -r --no-recurse-limit  Disable a limit on recursion whilst demangling\n\
   -h --help              Display this information\n\
   -v --version           Display the program's version\n\
 \n"));
@@ -289,7 +298,7 @@ translate_addresses (bfd *abfd, asection *section)
                     name = "??";
                   else if (do_demangle)
                     {
-                      alloc = bfd_demangle (abfd, name, DMGL_ANSI | DMGL_PARAMS);
+                      alloc = bfd_demangle (abfd, name, demangle_flags);
                       if (alloc != NULL)
                         name = alloc;
                     }
@@ -442,7 +451,7 @@ main (int argc, char **argv)
   file_name = NULL;
   section_name = NULL;
   target = NULL;
-  while ((c = getopt_long (argc, argv, "ab:Ce:sfHhij:pVv", long_options, (int *) 0))
+  while ((c = getopt_long (argc, argv, "ab:Ce:rRsfHhij:pVv", long_options, (int *) 0))
 	 != EOF)
     {
       switch (c)
@@ -469,6 +478,12 @@ main (int argc, char **argv)
 	      cplus_demangle_set_style (style);
 	    }
 	  break;
+	case 'R':
+	  demangle_flags |= DMGL_RECURSE_LIMIT;
+	  break;
+	case 'r':
+	  demangle_flags &= ~ DMGL_RECURSE_LIMIT;
+	  break;
 	case 'e':
 	  file_name = optarg;
 	  break;
diff --git a/binutils/cxxfilt.c b/binutils/cxxfilt.c
index e7272445c9..f1027c020c 100644
--- a/binutils/cxxfilt.c
+++ b/binutils/cxxfilt.c
@@ -29,7 +29,7 @@
 #include "safe-ctype.h"
 #include "bucomm.h"
 
-static int flags = DMGL_PARAMS | DMGL_ANSI | DMGL_VERBOSE;
+static int flags = DMGL_PARAMS | DMGL_ANSI | DMGL_VERBOSE | DMGL_RECURSE_LIMIT;
 static int strip_underscore = TARGET_PREPENDS_UNDERSCORE;
 
 static const struct option long_options[] =
@@ -42,6 +42,10 @@ static const struct option long_options[] =
   {"no-verbose", no_argument, NULL, 'i'},
   {"types", no_argument, NULL, 't'},
   {"version", no_argument, NULL, 'v'},
+  {"recurse-limit", no_argument, NULL, 'R'},
+  {"recursion-limit", no_argument, NULL, 'R'},
+  {"no-recurse-limit", no_argument, NULL, 'r'},
+  {"no-recursion-limit", no_argument, NULL, 'r'},
   {NULL, no_argument, NULL, 0}
 };
 
@@ -102,6 +106,8 @@ Options are:\n\
   fprintf (stream, "\
   [-p|--no-params]            Do not display function arguments\n\
   [-i|--no-verbose]           Do not show implementation details (if any)\n\
+  [-R|--recurse-limit]        Enable a limit on recursion whilst demangling.  [Default]\n\
+  ]-r|--no-recurse-limit]     Disable a limit on recursion whilst demangling\n\
   [-t|--types]                Also attempt to demangle type encodings\n\
   [-s|--format ");
   print_demangler_list (stream);
@@ -180,7 +186,7 @@ main (int argc, char **argv)
 
   expandargv (&argc, &argv);
 
-  while ((c = getopt_long (argc, argv, "_hinps:tv", long_options, (int *) 0)) != EOF)
+  while ((c = getopt_long (argc, argv, "_hinprRs:tv", long_options, (int *) 0)) != EOF)
     {
       switch (c)
 	{
@@ -195,6 +201,12 @@ main (int argc, char **argv)
 	case 'p':
 	  flags &= ~ DMGL_PARAMS;
 	  break;
+	case 'R':
+	  flags |= DMGL_RECURSE_LIMIT;
+	  break;
+	case 'r':
+	  flags &= ~ DMGL_RECURSE_LIMIT;
+	  break;
 	case 't':
 	  flags |= DMGL_TYPES;
 	  break;
diff --git a/binutils/dlltool.c b/binutils/dlltool.c
index 2c751241f1..963d541b8e 100644
--- a/binutils/dlltool.c
+++ b/binutils/dlltool.c
@@ -1802,7 +1802,7 @@ gen_def_file (void)
   for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
     {
       char *quote = strchr (exp->name, '.') ? "\"" : "";
-      char *res = cplus_demangle (exp->internal_name, DMGL_ANSI | DMGL_PARAMS);
+      char *res = cplus_demangle (exp->internal_name, DMGL_ANSI | DMGL_PARAMS | DMGL_RECURSE_LIMIT);
 
       if (res)
 	{
diff --git a/binutils/doc/binutils.texi b/binutils/doc/binutils.texi
index 9954adf484..0f1b493e39 100644
--- a/binutils/doc/binutils.texi
+++ b/binutils/doc/binutils.texi
@@ -769,7 +769,9 @@ nm [@option{-A}|@option{-o}|@option{--print-file-name}] [@option{-a}|@option{--d
    [@option{-s}|@option{--print-armap}] [@option{-t} @var{radix}|@option{--radix=}@var{radix}]
    [@option{-u}|@option{--undefined-only}] [@option{-V}|@option{--version}]
    [@option{-X 32_64}] [@option{--defined-only}] [@option{--no-demangle}]
-   [@option{--plugin} @var{name}] [@option{--size-sort}] [@option{--special-syms}]
+   [@option{--plugin} @var{name}]
+   [@option{--no-recurse-limit}|@option{--recurse-limit}]]
+   [@option{--size-sort}] [@option{--special-syms}]
    [@option{--synthetic}] [@option{--with-symbol-versions}] [@option{--target=}@var{bfdname}]
    [@var{objfile}@dots{}]
 @c man end
@@ -939,6 +941,22 @@ for more information on demangling.
 @item --no-demangle
 Do not demangle low-level symbol names.  This is the default.
 
+@item --recurse-limit
+@itemx --no-recurse-limit
+@itemx --recursion-limit
+@itemx --no-recursion-limit
+Enables or disables a limit on the amount of recursion performed
+whilst demangling strings.  Since the name mangling formats allow for
+an inifinite level of recursion it is possible to create strings whose
+decoding will exhaust the amount of stack space available on the host
+machine, triggering a memory fault.  The limit tries to prevent this
+from happening by restricting recursion to 1024 levels of nesting.
+
+The default is for this limit to be enabled, but disabling it may be
+necessary in order to demangle truely complicated names.  Note however
+that if the recursion limit is disabled then stack exhaustion is
+possible and any bug reports about such an event will be rejected.
+
 @item -D
 @itemx --dynamic
 @cindex dynamic symbols
@@ -2098,6 +2116,7 @@ objdump [@option{-a}|@option{--archive-headers}]
         [@option{--adjust-vma=}@var{offset}]
         [@option{--dwarf-depth=@var{n}}]
         [@option{--dwarf-start=@var{n}}]
+        [@option{--no-recurse-limit}|@option{--recurse-limit}]
         [@option{--special-syms}]
         [@option{--prefix=}@var{prefix}]
         [@option{--prefix-strip=}@var{level}]
@@ -2174,6 +2193,22 @@ mangling styles. The optional demangling style argument can be used to
 choose an appropriate demangling style for your compiler. @xref{c++filt},
 for more information on demangling.
 
+@item --recurse-limit
+@itemx --no-recurse-limit
+@itemx --recursion-limit
+@itemx --no-recursion-limit
+Enables or disables a limit on the amount of recursion performed
+whilst demangling strings.  Since the name mangling formats allow for
+an inifinite level of recursion it is possible to create strings whose
+decoding will exhaust the amount of stack space available on the host
+machine, triggering a memory fault.  The limit tries to prevent this
+from happening by restricting recursion to 1024 levels of nesting.
+
+The default is for this limit to be enabled, but disabling it may be
+necessary in order to demangle truely complicated names.  Note however
+that if the recursion limit is disabled then stack exhaustion is
+possible and any bug reports about such an event will be rejected.
+
 @item -g
 @itemx --debugging
 Display debugging information.  This attempts to parse STABS
@@ -3403,6 +3438,8 @@ c++filt [@option{-_}|@option{--strip-underscore}]
         [@option{-p}|@option{--no-params}]
         [@option{-t}|@option{--types}]
         [@option{-i}|@option{--no-verbose}]
+        [@option{-r}|@option{--no-recurse-limit}]
+        [@option{-R}|@option{--recurse-limit}]
         [@option{-s} @var{format}|@option{--format=}@var{format}]
         [@option{--help}]  [@option{--version}]  [@var{symbol}@dots{}]
 @c man end
@@ -3507,6 +3544,28 @@ demangled to ``signed char''.
 Do not include implementation details (if any) in the demangled
 output.
 
+@item -r
+@itemx -R
+@itemx --recurse-limit
+@itemx --no-recurse-limit
+@itemx --recursion-limit
+@itemx --no-recursion-limit
+Enables or disables a limit on the amount of recursion performed
+whilst demangling strings.  Since the name mangling formats allow for
+an inifinite level of recursion it is possible to create strings whose
+decoding will exhaust the amount of stack space available on the host
+machine, triggering a memory fault.  The limit tries to prevent this
+from happening by restricting recursion to 1024 levels of nesting.
+
+The default is for this limit to be enabled, but disabling it may be
+necessary in order to demangle truely complicated names.  Note however
+that if the recursion limit is disabled then stack exhaustion is
+possible and any bug reports about such an event will be rejected.
+
+The @option{-r} option is a snyonym for the
+@option{--no-recurse-limit} option.  The @option{-R} option is a
+synonym for the @option{--recurse-limit} option.
+
 @item -s @var{format}
 @itemx --format=@var{format}
 @command{c++filt} can decode various methods of mangling, used by
@@ -3580,6 +3639,8 @@ c++filt @var{option} @var{symbol}
 addr2line [@option{-a}|@option{--addresses}]
           [@option{-b} @var{bfdname}|@option{--target=}@var{bfdname}]
           [@option{-C}|@option{--demangle}[=@var{style}]]
+          [@option{-r}|@option{--no-recurse-limit}]
+          [@option{-R}|@option{--recurse-limit}]
           [@option{-e} @var{filename}|@option{--exe=}@var{filename}]
           [@option{-f}|@option{--functions}] [@option{-s}|@option{--basename}]
           [@option{-i}|@option{--inlines}]
@@ -3705,6 +3766,32 @@ Read offsets relative to the specified section instead of absolute addresses.
 Make the output more human friendly: each location are printed on one line.
 If option @option{-i} is specified, lines for all enclosing scopes are
 prefixed with @samp{(inlined by)}.
+
+@item -r
+@itemx -R
+@itemx --recurse-limit
+@itemx --no-recurse-limit
+@itemx --recursion-limit
+@itemx --no-recursion-limit
+Enables or disables a limit on the amount of recursion performed
+whilst demangling strings.  Since the name mangling formats allow for
+an inifinite level of recursion it is possible to create strings whose
+decoding will exhaust the amount of stack space available on the host
+machine, triggering a memory fault.  The limit tries to prevent this
+from happening by restricting recursion to 1024 levels of nesting.
+
+The default is for this limit to be enabled, but disabling it may be
+necessary in order to demangle truely complicated names.  Note however
+that if the recursion limit is disabled then stack exhaustion is
+possible and any bug reports about such an event will be rejected.
+
+The @option{-r} option is a snyonym for the
+@option{--no-recurse-limit} option.  The @option{-R} option is a
+synonym for the @option{--recurse-limit} option.
+
+Note this option is only effective if the @option{-C} or
+@option{--demangle} option has been enabled.
+
 @end table
 
 @c man end
diff --git a/binutils/nm.c b/binutils/nm.c
index bc4fccb5fc..1172d6222c 100644
--- a/binutils/nm.c
+++ b/binutils/nm.c
@@ -162,6 +162,8 @@ static int line_numbers = 0;	/* Print line numbers for symbols.  */
 static int allow_special_symbols = 0;  /* Allow special symbols.  */
 static int with_symbol_versions = 0; /* Include symbol version information in the output.  */
 
+static int demangle_flags = DMGL_ANSI | DMGL_PARAMS | DMGL_RECURSE_LIMIT;
+
 /* When to print the names of files.  Not mutually exclusive in SYSV format.  */
 static int filename_per_file = 0;	/* Once per file, on its own line.  */
 static int filename_per_symbol = 0;	/* Once per symbol, at start of line.  */
@@ -194,9 +196,14 @@ static const char *plugin_target = NULL;
 static bfd *lineno_cache_bfd;
 static bfd *lineno_cache_rel_bfd;
 
-#define OPTION_TARGET 200
-#define OPTION_PLUGIN (OPTION_TARGET + 1)
-#define OPTION_SIZE_SORT (OPTION_PLUGIN + 1)
+enum long_option_values
+{
+  OPTION_TARGET = 200,
+  OPTION_PLUGIN,
+  OPTION_SIZE_SORT,
+  OPTION_RECURSE_LIMIT,
+  OPTION_NO_RECURSE_LIMIT
+};
 
 static struct option long_options[] =
 {
@@ -209,6 +216,8 @@ static struct option long_options[] =
   {"line-numbers", no_argument, 0, 'l'},
   {"no-cplus", no_argument, &do_demangle, 0},  /* Linux compatibility.  */
   {"no-demangle", no_argument, &do_demangle, 0},
+  {"no-recurse-limit", no_argument, NULL, OPTION_NO_RECURSE_LIMIT},
+  {"no-recursion-limit", no_argument, NULL, OPTION_NO_RECURSE_LIMIT},
   {"no-sort", no_argument, 0, 'p'},
   {"numeric-sort", no_argument, 0, 'n'},
   {"plugin", required_argument, 0, OPTION_PLUGIN},
@@ -217,6 +226,8 @@ static struct option long_options[] =
   {"print-file-name", no_argument, 0, 'o'},
   {"print-size", no_argument, 0, 'S'},
   {"radix", required_argument, 0, 't'},
+  {"recurse-limit", no_argument, NULL, OPTION_RECURSE_LIMIT},
+  {"recursion-limit", no_argument, NULL, OPTION_RECURSE_LIMIT},
   {"reverse-sort", no_argument, &reverse_sort, 1},
   {"size-sort", no_argument, 0, OPTION_SIZE_SORT},
   {"special-syms", no_argument, &allow_special_symbols, 1},
@@ -245,6 +256,8 @@ usage (FILE *stream, int status)
                           `gnu', `lucid', `arm', `hp', `edg', `gnu-v3', `java'\n\
                           or `gnat'\n\
       --no-demangle      Do not demangle low-level symbol names\n\
+      --recurse-limit    Enable a demangling recursion limit.  This is the default.\n\
+      --no-recurse-limit Disable a demangling recursion limit.\n\
   -D, --dynamic          Display dynamic symbols instead of normal symbols\n\
       --defined-only     Display only defined symbols\n\
   -e                     (ignored)\n\
@@ -407,7 +420,7 @@ print_symname (const char *form, const char *name, bfd *abfd)
 {
   if (do_demangle && *name)
     {
-      char *res = bfd_demangle (abfd, name, DMGL_ANSI | DMGL_PARAMS);
+      char *res = bfd_demangle (abfd, name, demangle_flags);
 
       if (res != NULL)
 	{
@@ -1687,6 +1700,12 @@ main (int argc, char **argv)
 	      cplus_demangle_set_style (style);
 	    }
 	  break;
+	case OPTION_RECURSE_LIMIT:
+	  demangle_flags |= DMGL_RECURSE_LIMIT;
+	  break;
+	case OPTION_NO_RECURSE_LIMIT:
+	  demangle_flags &= ~ DMGL_RECURSE_LIMIT;
+	  break;
 	case 'D':
 	  dynamic = 1;
 	  break;
diff --git a/binutils/objdump.c b/binutils/objdump.c
index 21f1284319..e0234232a4 100644
--- a/binutils/objdump.c
+++ b/binutils/objdump.c
@@ -120,6 +120,8 @@ static size_t prefix_length;
 static bfd_boolean unwind_inlines;	/* --inlines.  */
 static const char * disasm_sym;		/* Disassembly start symbol.  */
 
+static int demangle_flags = DMGL_ANSI | DMGL_PARAMS | DMGL_RECURSE_LIMIT;
+
 /* A structure to record the sections mentioned in -j switches.  */
 struct only
 {
@@ -252,6 +254,8 @@ usage (FILE *stream, int status)
                                   The STYLE, if specified, can be `auto', `gnu',\n\
                                   `lucid', `arm', `hp', `edg', `gnu-v3', `java'\n\
                                   or `gnat'\n\
+      --recurse-limit            Enable a limit on recursion whilst demangling.  [Default]\n\
+      --no-recurse-limit         Disable a limit on recursion whilst demangling\n\
   -w, --wide                     Format output for more than 80 columns\n\
   -z, --disassemble-zeroes       Do not skip blocks of zeroes when disassembling\n\
       --start-address=ADDR       Only process data whose address is >= ADDR\n\
@@ -302,6 +306,8 @@ enum option_values
     OPTION_DWARF_DEPTH,
     OPTION_DWARF_CHECK,
     OPTION_DWARF_START,
+    OPTION_RECURSE_LIMIT,
+    OPTION_NO_RECURSE_LIMIT,
     OPTION_INLINES
   };
 
@@ -333,6 +339,10 @@ static struct option long_options[]=
   {"line-numbers", no_argument, NULL, 'l'},
   {"no-show-raw-insn", no_argument, &show_raw_insn, -1},
   {"prefix-addresses", no_argument, &prefix_addresses, 1},
+  {"recurse-limit", no_argument, NULL, OPTION_RECURSE_LIMIT},
+  {"recursion-limit", no_argument, NULL, OPTION_RECURSE_LIMIT},
+  {"no-recurse-limit", no_argument, NULL, OPTION_NO_RECURSE_LIMIT},
+  {"no-recursion-limit", no_argument, NULL, OPTION_NO_RECURSE_LIMIT},
   {"reloc", no_argument, NULL, 'r'},
   {"section", required_argument, NULL, 'j'},
   {"section-headers", no_argument, NULL, 'h'},
@@ -884,7 +894,7 @@ objdump_print_symname (bfd *abfd, struct disassemble_info *inf,
   if (do_demangle && name[0] != '\0')
     {
       /* Demangle the name.  */
-      alloc = bfd_demangle (abfd, name, DMGL_ANSI | DMGL_PARAMS);
+      alloc = bfd_demangle (abfd, name, demangle_flags);
       if (alloc != NULL)
 	name = alloc;
     }
@@ -2290,7 +2300,7 @@ disassemble_section (bfd *abfd, asection *section, void *inf)
 	  if (do_demangle && name[0] != '\0')
 	    {
 	      /* Demangle the name.  */
-	      alloc = bfd_demangle (abfd, name, DMGL_ANSI | DMGL_PARAMS);
+	      alloc = bfd_demangle (abfd, name, demangle_flags);
 	      if (alloc != NULL)
 		name = alloc;
 	    }
@@ -3268,7 +3278,7 @@ dump_symbols (bfd *abfd ATTRIBUTE_UNUSED, bfd_boolean dynamic)
 	      /* If we want to demangle the name, we demangle it
 		 here, and temporarily clobber it while calling
 		 bfd_print_symbol.  FIXME: This is a gross hack.  */
-	      alloc = bfd_demangle (cur_bfd, name, DMGL_ANSI | DMGL_PARAMS);
+	      alloc = bfd_demangle (cur_bfd, name, demangle_flags);
 	      if (alloc != NULL)
 		(*current)->name = alloc;
 	      bfd_print_symbol (cur_bfd, stdout, *current,
@@ -3927,6 +3937,12 @@ main (int argc, char **argv)
 	      cplus_demangle_set_style (style);
 	    }
 	  break;
+	case OPTION_RECURSE_LIMIT:
+	  demangle_flags |= DMGL_RECURSE_LIMIT;
+	  break;
+	case OPTION_NO_RECURSE_LIMIT:
+	  demangle_flags &= ~ DMGL_RECURSE_LIMIT;
+	  break;
 	case 'w':
 	  do_wide = wide_output = TRUE;
 	  break;
diff --git a/binutils/prdbg.c b/binutils/prdbg.c
index 4b9fa06c26..c981555521 100644
--- a/binutils/prdbg.c
+++ b/binutils/prdbg.c
@@ -286,6 +286,8 @@ static const struct debug_write_fns tg_fns =
   pr_end_function,		/* Same, does nothing.  */
   tg_lineno
 };
+
+static int demangle_flags = DMGL_ANSI | DMGL_PARAMS | DMGL_RECURSE_LIMIT;
 \f
 /* Print out the generic debugging information recorded in dhandle.  */
 
@@ -2600,7 +2602,7 @@ tg_variable (void *p, const char *name, enum debug_var_kind kind,
 
   dname = NULL;
   if (info->demangler)
-    dname = info->demangler (info->abfd, name, DMGL_ANSI | DMGL_PARAMS);
+    dname = info->demangler (info->abfd, name, demangle_flags);
 
   from_class = NULL;
   if (dname != NULL)
@@ -2661,7 +2663,7 @@ tg_start_function (void *p, const char *name, bfd_boolean global)
 
   dname = NULL;
   if (info->demangler)
-    dname = info->demangler (info->abfd, name, DMGL_ANSI | DMGL_PARAMS);
+    dname = info->demangler (info->abfd, name, demangle_flags);
 
   if (! substitute_type (info, dname ? dname : name))
     return FALSE;
diff --git a/binutils/stabs.c b/binutils/stabs.c
index bf53607560..dcd2aba57f 100644
--- a/binutils/stabs.c
+++ b/binutils/stabs.c
@@ -215,6 +215,8 @@ static debug_type stab_demangle_v3_arg
   (void *, struct stab_handle *, struct demangle_component *, debug_type,
    bfd_boolean *);
 
+static int demangle_flags = DMGL_ANSI | DMGL_RECURSE_LIMIT;
+
 /* Save a string in memory.  */
 
 static char *
@@ -4517,7 +4519,7 @@ stab_demangle_template (struct stab_demangle_info *minfo, const char **pp,
 
       free (s1);
 
-      s3 = cplus_demangle (s2, DMGL_ANSI);
+      s3 = cplus_demangle (s2, demangle_flags);
 
       free (s2);
 
@@ -5243,7 +5245,7 @@ stab_demangle_v3_argtypes (void *dhandle, struct stab_handle *info,
   void *mem;
   debug_type *pargs;
 
-  dc = cplus_demangle_v3_components (physname, DMGL_PARAMS | DMGL_ANSI, &mem);
+  dc = cplus_demangle_v3_components (physname, DMGL_PARAMS | demangle_flags, &mem);
   if (dc == NULL)
     {
       stab_bad_demangle (physname);
@@ -5418,7 +5420,7 @@ stab_demangle_v3_arg (void *dhandle, struct stab_handle *info,
 	/* We print this component to get a class name which we can
 	   use.  FIXME: This probably won't work if the template uses
 	   template parameters which refer to an outer template.  */
-	p = cplus_demangle_print (DMGL_PARAMS | DMGL_ANSI, dc, 20, &alc);
+	p = cplus_demangle_print (DMGL_PARAMS | demangle_flags, dc, 20, &alc);
 	if (p == NULL)
 	  {
 	    fprintf (stderr, _("Failed to print demangled template\n"));
@@ -5498,7 +5500,7 @@ stab_demangle_v3_arg (void *dhandle, struct stab_handle *info,
 	/* We print this component in order to find out the type name.
 	   FIXME: Should we instead expose the
 	   demangle_builtin_type_info structure?  */
-	p = cplus_demangle_print (DMGL_PARAMS | DMGL_ANSI, dc, 20, &alc);
+	p = cplus_demangle_print (DMGL_PARAMS | demangle_flags, dc, 20, &alc);
 	if (p == NULL)
 	  {
 	    fprintf (stderr, _("Couldn't get demangled builtin type\n"));
diff --git a/binutils/testsuite/config/default.exp b/binutils/testsuite/config/default.exp
index b34e45cd20..9ecfcf3e15 100644
--- a/binutils/testsuite/config/default.exp
+++ b/binutils/testsuite/config/default.exp
@@ -93,6 +93,12 @@ if ![info exists WINDRES] then {
 if ![info exists DLLTOOL] then {
     set DLLTOOL [findfile $base_dir/dlltool]
 }
+if ![info exists CXXFILT] then {
+    set CXXFILT [findfile $base_dir/cxxfilt]
+}
+if ![info exists CXXFILTFLAGS] then {
+    set CXXFILTFLAGS ""
+}
 
 if ![file isdirectory tmpdir] {catch "exec mkdir tmpdir" status}
 
--- /dev/null	2018-11-29 08:15:54.667999248 +0000
+++ binutils/testsuite/binutils-all/cxxfilt.exp	2018-11-29 13:09:29.789147447 +0000
@@ -0,0 +1,44 @@
+#   Copyright (C) 2018 Free Software Foundation, Inc.
+
+# This program 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 3 of the License, or
+# (at your option) any later version.
+# 
+# This program 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 program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+
+proc test_cxxfilt {options mangled_string demangled_string} {
+    global CXXFILT
+    global CXXFILTFLAGS
+    
+    set testname "cxxfilt: demangling $mangled_string"
+    set got [binutils_run $CXXFILT "$options $CXXFILTFLAGS $mangled_string"]
+
+    if ![regexp $demangled_string $got] then {
+	fail "$testname"
+	verbose 0 "expected: $demangled_string"
+	return
+    }
+
+    pass $testname
+}
+
+# Mangled and demangled strings stolen from libiberty/testsuite/demangle-expected.
+test_cxxfilt {} \
+    "AddAlignment__9ivTSolverUiP12ivInteractorP7ivTGlue" \
+    "ivTSolver::AddAlignment(unsigned int, ivInteractor ., ivTGlue .)*"
+
+test_cxxfilt {--format=lucid} \
+    "__ct__12strstreambufFPFl_PvPFPv_v" \
+    "strstreambuf..strstreambuf(void .(.)(long), void (.)(void .))*"
+
+test_cxxfilt {--recurse-limit=2} \
+    "Z3fooiPiPS_PS0_PS1_PS2_PS3_PS4_PS5_PS6_PS7_PS8_PS9_PSA_PSB_PSC_" \
+    "foo(int, int., int.., int..., int...., int....., int......, int......., int........, int........., int.........., int..........., int............, int............., int.............., int...............)*"

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: libiberty-demangler-recursion-limit.3.patch --]
[-- Type: text/x-patch; name="libiberty-demangler-recursion-limit.3.patch", Size: 5517 bytes --]

Index: libiberty/cp-demangle.c
===================================================================
--- libiberty/cp-demangle.c	(revision 266657)
+++ libiberty/cp-demangle.c	(working copy)
@@ -2852,21 +2852,35 @@
 static struct demangle_component *
 d_function_type (struct d_info *di)
 {
-  struct demangle_component *ret;
+  struct demangle_component *ret = NULL;
 
-  if (! d_check_char (di, 'F'))
-    return NULL;
-  if (d_peek_char (di) == 'Y')
+  if (di->options & DMGL_RECURSE_LIMIT)
     {
-      /* Function has C linkage.  We don't print this information.
-	 FIXME: We should print it in verbose mode.  */
-      d_advance (di, 1);
+      if (di->recursion_level > DEMANGLE_RECURSION_LIMIT)
+	/* FIXME: There ought to be a way to report
+	   that the recursion limit has been reached.  */
+	return NULL;
+
+      di->recursion_level ++;
     }
-  ret = d_bare_function_type (di, 1);
-  ret = d_ref_qualifier (di, ret);
 
-  if (! d_check_char (di, 'E'))
-    return NULL;
+  if (d_check_char (di, 'F'))
+    {
+      if (d_peek_char (di) == 'Y')
+	{
+	  /* Function has C linkage.  We don't print this information.
+	     FIXME: We should print it in verbose mode.  */
+	  d_advance (di, 1);
+	}
+      ret = d_bare_function_type (di, 1);
+      ret = d_ref_qualifier (di, ret);
+      
+      if (! d_check_char (di, 'E'))
+	ret = NULL;
+    }
+
+  if (di->options & DMGL_RECURSE_LIMIT)
+    di->recursion_level --;
   return ret;
 }
 
@@ -6203,6 +6217,7 @@
   di->expansion = 0;
   di->is_expression = 0;
   di->is_conversion = 0;
+  di->recursion_level = 0;
 }
 
 /* Internal implementation for the demangler.  If MANGLED is a g++ v3 ABI
@@ -6242,6 +6257,20 @@
 
   cplus_demangle_init_info (mangled, options, strlen (mangled), &di);
 
+  /* PR 87675 - Check for a mangled string that is so long
+     that we do not have enough stack space to demangle it.  */
+  if ((options & DMGL_RECURSE_LIMIT)
+      /* This check is a bit arbitrary, since what we really want to do is to
+	 compare the sizes of the di.comps and di.subs arrays against the
+	 amount of stack space remaining.  But there is no portable way to do
+	 this, so instead we use the recursion limit as a guide to the maximum
+	 size of the arrays.  */
+      && (unsigned long) di.num_comps > DEMANGLE_RECURSION_LIMIT)
+    {
+      /* FIXME: We need a way to indicate that a stack limit has been reached.  */
+      return 0;
+    }
+
   {
 #ifdef CP_DYNAMIC_ARRAYS
     __extension__ struct demangle_component comps[di.num_comps];
Index: libiberty/cp-demangle.h
===================================================================
--- libiberty/cp-demangle.h	(revision 266657)
+++ libiberty/cp-demangle.h	(working copy)
@@ -122,6 +122,9 @@
   /* Non-zero if we are parsing the type operand of a conversion
      operator, but not when in an expression.  */
   int is_conversion;
+  /* If DMGL_RECURSE_LIMIT is active then this is set to the
+     current recursion level.  */
+  unsigned int recursion_level;
 };
 
 /* To avoid running past the ending '\0', don't:
Index: libiberty/cplus-dem.c
===================================================================
--- libiberty/cplus-dem.c	(revision 266657)
+++ libiberty/cplus-dem.c	(working copy)
@@ -146,6 +146,7 @@
   int *proctypevec;     /* Indices of currently processed remembered typevecs.  */
   int proctypevec_size;
   int nproctypes;
+  unsigned int recursion_level;
 };
 
 #define PRINT_ANSI_QUALIFIERS (work -> options & DMGL_ANSI)
@@ -4693,10 +4694,21 @@
 demangle_nested_args (struct work_stuff *work, const char **mangled,
                       string *declp)
 {
+  static unsigned long recursion_level = 0;
   string* saved_previous_argument;
   int result;
   int saved_nrepeats;
 
+  if ((work->options & DMGL_RECURSE_LIMIT)
+      && work->recursion_level > DEMANGLE_RECURSION_LIMIT)
+    {
+      /* FIXME: There ought to be a way to report that the recursion limit
+	 has been reached.  */
+      return 0;
+    }
+
+  recursion_level ++;
+
   /* The G++ name-mangling algorithm does not remember types on nested
      argument lists, unless -fsquangling is used, and in that case the
      type vector updated by remember_type is not used.  So, we turn
@@ -4723,6 +4735,7 @@
   --work->forgetting_types;
   work->nrepeats = saved_nrepeats;
 
+  --recursion_level;
   return result;
 }
 
Index: include/demangle.h
===================================================================
--- include/demangle.h	(revision 266657)
+++ include/demangle.h	(working copy)
@@ -68,6 +68,16 @@
 /* If none of these are set, use 'current_demangling_style' as the default. */
 #define DMGL_STYLE_MASK (DMGL_AUTO|DMGL_GNU|DMGL_LUCID|DMGL_ARM|DMGL_HP|DMGL_EDG|DMGL_GNU_V3|DMGL_JAVA|DMGL_GNAT|DMGL_DLANG|DMGL_RUST)
 
+/* Enable a limit on the depth of recursion in mangled strings.
+   Note if this limit is not enabled then stack exhaustion is possible when
+   demangling pathologically complicated strings.  Bug reports about stack
+   exhaustion when the option is not enabled will be rejected.  */  
+#define DMGL_RECURSE_LIMIT (1 << 18)	
+
+/* If DMGL_RECURE_LIMIT is enabled, then this is the value
+   used as the maximum depth of recursion allowed.  */
+#define DEMANGLE_RECURSION_LIMIT 1024
+  
 /* Enumeration of possible demangling styles.
 
    Lucid and ARM styles are still kept logically distinct, even though

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: RFA/RFC: Add stack recursion limit to libiberty's demangler [v3]
  2018-11-30 17:41         ` RFA/RFC: Add stack recursion limit to libiberty's demangler [v3] Nick Clifton
@ 2018-11-30 17:49           ` Jakub Jelinek
  2018-11-30 18:19           ` Pedro Alves
  2018-12-03 10:28           ` Richard Biener
  2 siblings, 0 replies; 55+ messages in thread
From: Jakub Jelinek @ 2018-11-30 17:49 UTC (permalink / raw)
  To: Nick Clifton
  Cc: matz, sgayou, Ian Lance Taylor, Pedro Alves, Tom Tromey,
	gcc-patches, binutils, jason

Hi!

Just spelling nitpicking.

On Fri, Nov 30, 2018 at 05:41:35PM +0000, Nick Clifton wrote:
> +  order to dmangle truely complicated names, but it also leaves the tools

truly? Multiple times.

> +The @option{-r} option is a snyonym for the

synonym? Multiple times.

	Jakub

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: RFA/RFC: Add stack recursion limit to libiberty's demangler [v3]
  2018-11-30 17:41         ` RFA/RFC: Add stack recursion limit to libiberty's demangler [v3] Nick Clifton
  2018-11-30 17:49           ` Jakub Jelinek
@ 2018-11-30 18:19           ` Pedro Alves
  2018-12-03 10:28           ` Richard Biener
  2 siblings, 0 replies; 55+ messages in thread
From: Pedro Alves @ 2018-11-30 18:19 UTC (permalink / raw)
  To: Nick Clifton, Jakub Jelinek, matz, sgayou, Ian Lance Taylor, Tom Tromey
  Cc: gcc-patches, binutils, jason

On 11/30/2018 05:41 PM, Nick Clifton wrote:
> @@ -4693,10 +4694,21 @@
>  demangle_nested_args (struct work_stuff *work, const char **mangled,
>                        string *declp)
>  {
> +  static unsigned long recursion_level = 0;
>    string* saved_previous_argument;
>    int result;
>    int saved_nrepeats;
>  
> +  if ((work->options & DMGL_RECURSE_LIMIT)
> +      && work->recursion_level > DEMANGLE_RECURSION_LIMIT)
> +    {
> +      /* FIXME: There ought to be a way to report that the recursion limit
> +	 has been reached.  */
> +      return 0;
> +    }
> +
> +  recursion_level ++;
> +

There's still a static recursion level counter here?

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: RFA/RFC: Add stack recursion limit to libiberty's demangler
  2018-11-30 14:57       ` Ian Lance Taylor
@ 2018-12-02  0:49         ` Cary Coutant
  2018-12-03 14:53           ` Nick Clifton
  2018-12-03 22:00           ` Joseph Myers
  0 siblings, 2 replies; 55+ messages in thread
From: Cary Coutant @ 2018-12-02  0:49 UTC (permalink / raw)
  To: Nick Clifton, Jakub Jelinek, GCC Patches, Binutils, sgayou,
	Jason Merrill, Michael Matz

> That section is "Writing Robust Programs."  Robustness guarantees have
> to be different for utilities and servers.  A robust server doesn't
> crash because of arbitrary user input, but there are servers that
> demangle names that are provided by the user.  So we need two modes for
> the demangler: one that takes anything and sometimes crashes, for
> utilities like c++filt, and one that doesn't crash, for servers.  And it
> seems like that is what Nick is suggesting.

In order to handle arbitrary user input without crashing, perhaps the
demangler should switch from recursive descent parsing to a state
machine, where exhaustion of resources can be handled gracefully.

-cary

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: RFA/RFC: Add stack recursion limit to libiberty's demangler [v3]
  2018-11-30 17:41         ` RFA/RFC: Add stack recursion limit to libiberty's demangler [v3] Nick Clifton
  2018-11-30 17:49           ` Jakub Jelinek
  2018-11-30 18:19           ` Pedro Alves
@ 2018-12-03 10:28           ` Richard Biener
  2018-12-03 14:45             ` Nick Clifton
  2 siblings, 1 reply; 55+ messages in thread
From: Richard Biener @ 2018-12-03 10:28 UTC (permalink / raw)
  To: Nick Clifton
  Cc: Jakub Jelinek, matz, sgayou, Ian Lance Taylor, Pedro Alves, tom,
	GCC Patches, Binutils, Jason Merrill

On Fri, Nov 30, 2018 at 6:41 PM Nick Clifton <nickc@redhat.com> wrote:
>
> Hi Guys,
>
> >> I think it would be fine to have a large fixed limit plus a flag to
> >> disable the limit.
>
> Great - in which case please may I present version 3 of the patch.  In
> this version:
>
>   * The cplus_demangle_set_recursion_limit() function has been removed
>     and instead a new constant - DEMANGLE_RECURSION_LIMIT - is defined in
>     demangle.h.
>
>   * The recursion counters in cp-demangle.c have been merged into one
>     counter, now contained in the d_info structure.
>
>   * In cplus-dem.c the recursion counter has been moved into the work
>     structure.
>
>   * The description of the DMGL_RECURSE_LIMIT option in demangle.h has
>     been enhanced to add a note that if the option is not used, then
>     bug reports about stack overflows in the demangler will be rejected.

Shouldn't we make it fool-proof by instead introducing a DMGL_NO_RECURSION_LIMIT
flag and when not set default to limiting recursion?

>   * The binutils patch has been updated to reflect these changes.  The
>     addr2line, cxxfilt, nm and objdump programs now have two new options
>     --recurse-limit and --no-recurse-limit, with --recurse-limit being
>     the default.  The documentation is updated to describe these options
>     and to also add a note about bug reports being rejected if
>     --no-recurse-limit is used.
>
> What do you think, is this version acceptable ?
>
> Cheers
>   Nick
>
> libiberty/ChangeLog
> 2018-11-29  Nick Clifton  <nickc@redhat.com>
>
>         PR 87681
>         PR 87675
>         PR 87636
>         PR 87335
>         * cp-demangle.h (struct d_info): Add recursion_limit field.
>         * cp-demangle.c (d_function_type): If the recursion limit is
>         enabled and reached, return with a failure result.
>         (d_demangle_callback): If the recursion limit is enabled, check
>         for a mangled string that is so long that there is not enough
>         stack space for the local arrays.
>         * cplus-dem.c (struct work): Add recursion_level field.
>         (demangle_nested_args): If the recursion limit is enabled and
>         reached, return with a failure result.
>
> include/ChangeLog
> 2018-11-29  Nick Clifton  <nickc@redhat.com>
>
>         * demangle.h (DMGL_RECURSE_LIMIT): Define.
>         (DEMANGLE_RECURSION_LIMIT): Prototype.
>
> binutils/ChangeLog
> 2018-11-29  Nick Clifton  <nickc@redhat.com>
>
>         * addr2line.c (demangle_flags): New static variable.
>         (long_options): Add --recurse-limit and --no-recurse-limit.
>         (translate_address): Pass demangle_flags to bfd_demangle.
>         (main): Handle --recurse-limit and --no-recurse-limit options.
>         * cxxfilt.c (flags): Add DMGL_RECURSE_LIMIT.
>         (long_options): Add --recurse-limit and --no-recurse-limit.
>         (main): Handle new options.
>         * dlltool.c (gen_def_file): Include DMGL_RECURSE_LIMIT in flags
>         passed to cplus_demangle.
>         * nm.c (demangle_flags): New static variable.
>         (long_options): Add --recurse-limit and --no-recurse-limit.
>         (main): Handle new options.
>         * objdump.c (demangle_flags): New static variable.
>         (usage): Add --recurse-limit and --no-recurse-limit.
>         (long_options): Likewise.
>         (objdump_print_symname): Pass demangle_flags to bfd_demangle.
>         (disassemble_section): Likewise.
>         (dump_dymbols): Likewise.
>         (main): Handle new options.
>         * prdbg.c (demangle_flags): New static variable.
>         (tg_variable): Pass demangle_flags to demangler.
>         (tg_start_function): Likewise.
>         * stabs.c (demangle_flags): New static variable.
>         (stab_demangle_template): Pass demangle_flags to demangler.
>         (stab_demangle_v3_argtypes): Likewise.
>         (stab_demangle_v3_arg): Likewise.
>         * doc/binutuls.texi: Document new command line options.
>         * NEWS: Mention the new feature.
>         * testsuite/config/default.exp (CXXFILT): Define if not already
>         defined.
>         (CXXFILTFLAGS): Likewise.
>         * testsuite/binutils-all/cxxfilt.exp: New file.  Runs a few
>         simple tests of the cxxfilt program.

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: RFA/RFC: Add stack recursion limit to libiberty's demangler [v3]
  2018-12-03 10:28           ` Richard Biener
@ 2018-12-03 14:45             ` Nick Clifton
  2018-12-03 18:49               ` Ian Lance Taylor via gcc-patches
  0 siblings, 1 reply; 55+ messages in thread
From: Nick Clifton @ 2018-12-03 14:45 UTC (permalink / raw)
  To: Richard Biener
  Cc: Jakub Jelinek, matz, sgayou, Ian Lance Taylor, Pedro Alves, tom,
	GCC Patches, Binutils, Jason Merrill

Hi Richard,

>>   * The description of the DMGL_RECURSE_LIMIT option in demangle.h has
>>     been enhanced to add a note that if the option is not used, then
>>     bug reports about stack overflows in the demangler will be rejected.
> 
> Shouldn't we make it fool-proof by instead introducing a DMGL_NO_RECURSION_LIMIT
> flag and when not set default to limiting recursion?

Well I wanted the patch to be backwards compatible. Just on the
general principle of not surprising users/programmers by changing 
things without telling them first.

I could change this of course, but I would rather have Ian's blessing
first.

Cheers
  Nick

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: RFA/RFC: Add stack recursion limit to libiberty's demangler
  2018-12-02  0:49         ` Cary Coutant
@ 2018-12-03 14:53           ` Nick Clifton
  2018-12-03 22:00           ` Joseph Myers
  1 sibling, 0 replies; 55+ messages in thread
From: Nick Clifton @ 2018-12-03 14:53 UTC (permalink / raw)
  To: Cary Coutant, Jakub Jelinek, GCC Patches, Binutils, sgayou,
	Jason Merrill, Michael Matz

Hi Cary,

> In order to handle arbitrary user input without crashing, perhaps the
> demangler should switch from recursive descent parsing to a state
> machine, where exhaustion of resources can be handled gracefully.

I think that that would be a better long term fix for the problem,
but it is not one that I have time to work on right now.

My main goal with this patch submission is to stop the flood of PR 
and CVEs about mangled inputs that trigger stack exhaustion.  Being 
able to properly demangle such inputs would be nice, but not something
that I think should be a priority.  I think that in real life no 
program is ever going to generate a mangled name that is sufficiently 
complex to trigger a seg-fault this way, so the only real purpose of
the patch is to resolve these PRs and stop more from being filed.

Cheers
  Nick


^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: RFA/RFC: Add stack recursion limit to libiberty's demangler [v3]
  2018-12-03 14:45             ` Nick Clifton
@ 2018-12-03 18:49               ` Ian Lance Taylor via gcc-patches
  2018-12-04 14:00                 ` RFA/RFC: Add stack recursion limit to libiberty's demangler [v4] Nick Clifton
  0 siblings, 1 reply; 55+ messages in thread
From: Ian Lance Taylor via gcc-patches @ 2018-12-03 18:49 UTC (permalink / raw)
  To: Nick Clifton
  Cc: Richard Biener, Jakub Jelinek, matz, sgayou, Pedro Alves,
	Tom Tromey, GCC Patches, Binutils, Jason Merrill

On Mon, Dec 3, 2018 at 6:45 AM, Nick Clifton <nickc@redhat.com> wrote:
> Hi Richard,
>
>>>   * The description of the DMGL_RECURSE_LIMIT option in demangle.h has
>>>     been enhanced to add a note that if the option is not used, then
>>>     bug reports about stack overflows in the demangler will be rejected.
>>
>> Shouldn't we make it fool-proof by instead introducing a DMGL_NO_RECURSION_LIMIT
>> flag and when not set default to limiting recursion?
>
> Well I wanted the patch to be backwards compatible. Just on the
> general principle of not surprising users/programmers by changing
> things without telling them first.
>
> I could change this of course, but I would rather have Ian's blessing
> first.

You don't need my blessing--I wrote that code ages ago--but I agree
with Richard that in practice it's OK to limit recursion depth by
default.  Real symbols have very limited recursion requirements.

Ian

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: RFA/RFC: Add stack recursion limit to libiberty's demangler
  2018-12-02  0:49         ` Cary Coutant
  2018-12-03 14:53           ` Nick Clifton
@ 2018-12-03 22:00           ` Joseph Myers
  1 sibling, 0 replies; 55+ messages in thread
From: Joseph Myers @ 2018-12-03 22:00 UTC (permalink / raw)
  To: Cary Coutant
  Cc: Nick Clifton, Jakub Jelinek, GCC Patches, Binutils, sgayou,
	Jason Merrill, Michael Matz

On Sat, 1 Dec 2018, Cary Coutant wrote:

> In order to handle arbitrary user input without crashing, perhaps the
> demangler should switch from recursive descent parsing to a state
> machine, where exhaustion of resources can be handled gracefully.

I've wondered if a GCC C/C++ extension could be defined that means 
"convert this set of mutually recursive functions into a single function 
with a state machine that allocates the equivalent of the stack manually".  
But such an extension would certainly be nontrivial to define.  (One use 
for such an extension would be to avoid the GCC bugs that occasionally get 
reported of the form "expressions with a million nested pairs of 
parentheses make the compiler segfault", by using it to avoid recursion in 
the parsers.)

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: RFA/RFC: Add stack recursion limit to libiberty's demangler [v4]
  2018-12-03 18:49               ` Ian Lance Taylor via gcc-patches
@ 2018-12-04 14:00                 ` Nick Clifton
  2018-12-04 15:02                   ` Pedro Alves
  0 siblings, 1 reply; 55+ messages in thread
From: Nick Clifton @ 2018-12-04 14:00 UTC (permalink / raw)
  To: Ian Lance Taylor
  Cc: Richard Biener, Jakub Jelinek, matz, sgayou, Pedro Alves,
	Tom Tromey, GCC Patches, Binutils, Jason Merrill

[-- Attachment #1: Type: text/plain, Size: 1776 bytes --]

Hi Ian,

>>> Shouldn't we make it fool-proof by instead introducing a DMGL_NO_RECURSION_LIMIT

> You don't need my blessing--I wrote that code ages ago--but I agree
> with Richard that in practice it's OK to limit recursion depth by
> default.  Real symbols have very limited recursion requirements.

OK then, here is a fourth revision of the patch.

In this version:

  * The demangler option has been renamed to DMGHL_NO_RECURSE_LIMIT
    and if the option is not present then the limit is enforced.

  * I also found another PR that is fixed by the patch, although I had
    to make sure that the affected code could handle NULL pointers 
    properly afterwards.

  OK to apply ?

Cheers
  Nick


include/ChangeLog
2018-11-29  Nick Clifton  <nickc@redhat.com>

	* demangle.h (DMGL_NO_RECURSE_LIMIT): Define.
        (DEMANGLE_RECURSION_LIMIT): Define

libiberty/ChangeLog
2018-11-29  Nick Clifton  <nickc@redhat.com>

	PR 87681
	PR 87675
	PR 87636
	PR 87350
	PR 87335
	* cp-demangle.h (struct d_info): Add recursion_level field.
	* cp-demangle.c (d_function_type): Add recursion counter.
	If the recursion limit is reached and the check is not disabled,
	then return with a failure result.
	(cplus_demangle_init_info): Initialise the recursion_level field.
        (d_demangle_callback): If the recursion limit is enabled, check
	for a mangled string that is so long that there is not enough
	stack space for the local arrays.
        * cplus-dem.c (struct work): Add recursion_level field.
	(squangle_mop_up): Set the numb and numk fields to zero.
	(work_stuff_copy_to_from): Handle the case where a btypevec or 
	ktypevec field is NULL.
	(demangle_nested_args): Add recursion counter.  If
	the recursion limit is not disabled and reached, return with a
	failure result.

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: libiberty-demangler-recursion-limit.4.patch --]
[-- Type: text/x-patch; name="libiberty-demangler-recursion-limit.4.patch", Size: 7243 bytes --]

Index: include/demangle.h
===================================================================
--- include/demangle.h	(revision 266771)
+++ include/demangle.h	(working copy)
@@ -68,6 +68,17 @@
 /* If none of these are set, use 'current_demangling_style' as the default. */
 #define DMGL_STYLE_MASK (DMGL_AUTO|DMGL_GNU|DMGL_LUCID|DMGL_ARM|DMGL_HP|DMGL_EDG|DMGL_GNU_V3|DMGL_JAVA|DMGL_GNAT|DMGL_DLANG|DMGL_RUST)
 
+/* Disable a limit on the depth of recursion in mangled strings.
+   Note if this limit is disabled then stack exhaustion is possible when
+   demangling pathologically complicated strings.  Bug reports about stack
+   exhaustion when the option is enabled will be rejected.  */  
+#define DMGL_NO_RECURSE_LIMIT (1 << 18)	
+
+/* If DMGL_NO_RECURE_LIMIT is not enabled, then this is the value used as
+   the maximum depth of recursion allowed.  It should be enough for any
+   real-world mangled name.  */
+#define DEMANGLE_RECURSION_LIMIT 1024
+  
 /* Enumeration of possible demangling styles.
 
    Lucid and ARM styles are still kept logically distinct, even though
Index: libiberty/cp-demangle.c
===================================================================
--- libiberty/cp-demangle.c	(revision 266771)
+++ libiberty/cp-demangle.c	(working copy)
@@ -2852,21 +2852,35 @@
 static struct demangle_component *
 d_function_type (struct d_info *di)
 {
-  struct demangle_component *ret;
+  struct demangle_component *ret = NULL;
 
-  if (! d_check_char (di, 'F'))
-    return NULL;
-  if (d_peek_char (di) == 'Y')
+  if ((di->options & DMGL_NO_RECURSE_LIMIT) == 0)
     {
-      /* Function has C linkage.  We don't print this information.
-	 FIXME: We should print it in verbose mode.  */
-      d_advance (di, 1);
+      if (di->recursion_level > DEMANGLE_RECURSION_LIMIT)
+	/* FIXME: There ought to be a way to report
+	   that the recursion limit has been reached.  */
+	return NULL;
+
+      di->recursion_level ++;
     }
-  ret = d_bare_function_type (di, 1);
-  ret = d_ref_qualifier (di, ret);
 
-  if (! d_check_char (di, 'E'))
-    return NULL;
+  if (d_check_char (di, 'F'))
+    {
+      if (d_peek_char (di) == 'Y')
+	{
+	  /* Function has C linkage.  We don't print this information.
+	     FIXME: We should print it in verbose mode.  */
+	  d_advance (di, 1);
+	}
+      ret = d_bare_function_type (di, 1);
+      ret = d_ref_qualifier (di, ret);
+      
+      if (! d_check_char (di, 'E'))
+	ret = NULL;
+    }
+
+  if ((di->options & DMGL_NO_RECURSE_LIMIT) == 0)
+    di->recursion_level --;
   return ret;
 }
 
@@ -6203,6 +6217,7 @@
   di->expansion = 0;
   di->is_expression = 0;
   di->is_conversion = 0;
+  di->recursion_level = 0;
 }
 
 /* Internal implementation for the demangler.  If MANGLED is a g++ v3 ABI
@@ -6242,6 +6257,20 @@
 
   cplus_demangle_init_info (mangled, options, strlen (mangled), &di);
 
+  /* PR 87675 - Check for a mangled string that is so long
+     that we do not have enough stack space to demangle it.  */
+  if (((options & DMGL_NO_RECURSE_LIMIT) == 0)
+      /* This check is a bit arbitrary, since what we really want to do is to
+	 compare the sizes of the di.comps and di.subs arrays against the
+	 amount of stack space remaining.  But there is no portable way to do
+	 this, so instead we use the recursion limit as a guide to the maximum
+	 size of the arrays.  */
+      && (unsigned long) di.num_comps > DEMANGLE_RECURSION_LIMIT)
+    {
+      /* FIXME: We need a way to indicate that a stack limit has been reached.  */
+      return 0;
+    }
+
   {
 #ifdef CP_DYNAMIC_ARRAYS
     __extension__ struct demangle_component comps[di.num_comps];
Index: libiberty/cp-demangle.h
===================================================================
--- libiberty/cp-demangle.h	(revision 266771)
+++ libiberty/cp-demangle.h	(working copy)
@@ -122,6 +122,9 @@
   /* Non-zero if we are parsing the type operand of a conversion
      operator, but not when in an expression.  */
   int is_conversion;
+  /* If DMGL_NO_RECURSE_LIMIT is not active then this is set to
+     the current recursion level.  */
+  unsigned int recursion_level;
 };
 
 /* To avoid running past the ending '\0', don't:
Index: libiberty/cplus-dem.c
===================================================================
--- libiberty/cplus-dem.c	(revision 266771)
+++ libiberty/cplus-dem.c	(working copy)
@@ -146,6 +146,7 @@
   int *proctypevec;     /* Indices of currently processed remembered typevecs.  */
   int proctypevec_size;
   int nproctypes;
+  unsigned int recursion_level;
 };
 
 #define PRINT_ANSI_QUALIFIERS (work -> options & DMGL_ANSI)
@@ -1292,6 +1293,7 @@
       free ((char *) work -> btypevec);
       work->btypevec = NULL;
       work->bsize = 0;
+      work->numb = 0;
     }
   if (work -> ktypevec != NULL)
     {
@@ -1298,6 +1300,7 @@
       free ((char *) work -> ktypevec);
       work->ktypevec = NULL;
       work->ksize = 0;
+      work->numk = 0;
     }
 }
 
@@ -1331,8 +1334,15 @@
 
   for (i = 0; i < from->numk; i++)
     {
-      int len = strlen (from->ktypevec[i]) + 1;
+      int len;
 
+      if (from->ktypevec[i] == NULL)
+	{
+	  to->ktypevec[i] = NULL;
+	  continue;
+	}
+
+      len = strlen (from->ktypevec[i]) + 1;
       to->ktypevec[i] = XNEWVEC (char, len);
       memcpy (to->ktypevec[i], from->ktypevec[i], len);
     }
@@ -1342,8 +1352,15 @@
 
   for (i = 0; i < from->numb; i++)
     {
-      int len = strlen (from->btypevec[i]) + 1;
+      int len;
 
+      if (from->btypevec[i] == NULL)
+	{
+	  to->btypevec[i] = NULL;
+	  continue;
+	}
+
+      len = strlen (from->btypevec[i]) + 1;
       to->btypevec[i] = XNEWVEC (char , len);
       memcpy (to->btypevec[i], from->btypevec[i], len);
     }
@@ -1401,6 +1418,7 @@
 
       free ((char*) work->tmpl_argvec);
       work->tmpl_argvec = NULL;
+      work->ntmpl_args = 0;
     }
   if (work->previous_argument)
     {
@@ -4478,6 +4496,7 @@
 }
 
 /* Lose all the info related to B and K type codes. */
+
 static void
 forget_B_and_K_types (struct work_stuff *work)
 {
@@ -4503,6 +4522,7 @@
 	}
     }
 }
+
 /* Forget the remembered types, but not the type vector itself.  */
 
 static void
@@ -4693,10 +4713,21 @@
 demangle_nested_args (struct work_stuff *work, const char **mangled,
                       string *declp)
 {
+  static unsigned long recursion_level = 0;
   string* saved_previous_argument;
   int result;
   int saved_nrepeats;
 
+  if ((work->options & DMGL_NO_RECURSE_LIMIT) == 0
+      && work->recursion_level > DEMANGLE_RECURSION_LIMIT)
+    {
+      /* FIXME: There ought to be a way to report that the recursion limit
+	 has been reached.  */
+      return 0;
+    }
+
+  recursion_level ++;
+
   /* The G++ name-mangling algorithm does not remember types on nested
      argument lists, unless -fsquangling is used, and in that case the
      type vector updated by remember_type is not used.  So, we turn
@@ -4723,6 +4754,7 @@
   --work->forgetting_types;
   work->nrepeats = saved_nrepeats;
 
+  --recursion_level;
   return result;
 }
 

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: RFA/RFC: Add stack recursion limit to libiberty's demangler [v4]
  2018-12-04 14:00                 ` RFA/RFC: Add stack recursion limit to libiberty's demangler [v4] Nick Clifton
@ 2018-12-04 15:02                   ` Pedro Alves
  2018-12-04 16:57                     ` RFA/RFC: Add stack recursion limit to libiberty's demangler [v5] Nick Clifton
  0 siblings, 1 reply; 55+ messages in thread
From: Pedro Alves @ 2018-12-04 15:02 UTC (permalink / raw)
  To: Nick Clifton, Ian Lance Taylor
  Cc: Richard Biener, Jakub Jelinek, matz, sgayou, Tom Tromey,
	GCC Patches, Binutils, Jason Merrill

On 12/04/2018 01:59 PM, Nick Clifton wrote:

> OK then, here is a fourth revision of the patch.

The issue pointed out by

 https://gcc.gnu.org/ml/gcc-patches/2018-11/msg02592.html

is still present in this version.

Also, noticed a typo here:

> +/* If DMGL_NO_RECURE_LIMIT is not enabled, then this is the value used as

Typo: "RECURE"

> +   the maximum depth of recursion allowed.  It should be enough for any
> +   real-world mangled name.  */
> +#define DEMANGLE_RECURSION_LIMIT 1024
> +  

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: RFA/RFC: Add stack recursion limit to libiberty's demangler [v5]
  2018-12-04 15:02                   ` Pedro Alves
@ 2018-12-04 16:57                     ` Nick Clifton
  2018-12-04 17:08                       ` Pedro Alves
  2018-12-06 16:14                       ` RFA/RFC: Add stack recursion limit to libiberty's demangler [v5] Jason Merrill
  0 siblings, 2 replies; 55+ messages in thread
From: Nick Clifton @ 2018-12-04 16:57 UTC (permalink / raw)
  To: Pedro Alves, Ian Lance Taylor
  Cc: Richard Biener, Jakub Jelinek, matz, sgayou, Tom Tromey,
	GCC Patches, Binutils, Jason Merrill

[-- Attachment #1: Type: text/plain, Size: 426 bytes --]

Hi Pedro,

> The issue pointed out by
> 
>  https://gcc.gnu.org/ml/gcc-patches/2018-11/msg02592.html
> 
> is still present in this version.

Doh!  Yes I meant to fix that one too, but forgot.

> Also, noticed a typo here:
> 
>> +/* If DMGL_NO_RECURE_LIMIT is not enabled, then this is the value used as
> 
> Typo: "RECURE"

Oops - thanks.

OK, revised (v5) patch attached.  Is this version acceptable to all ?

Cheers
  Nick


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: libiberty-demangler-recursion-limit.5.patch --]
[-- Type: text/x-patch; name="libiberty-demangler-recursion-limit.5.patch", Size: 7115 bytes --]

Index: include/demangle.h
===================================================================
--- include/demangle.h	(revision 266771)
+++ include/demangle.h	(working copy)
@@ -68,6 +68,17 @@
 /* If none of these are set, use 'current_demangling_style' as the default. */
 #define DMGL_STYLE_MASK (DMGL_AUTO|DMGL_GNU|DMGL_LUCID|DMGL_ARM|DMGL_HP|DMGL_EDG|DMGL_GNU_V3|DMGL_JAVA|DMGL_GNAT|DMGL_DLANG|DMGL_RUST)
 
+/* Disable a limit on the depth of recursion in mangled strings.
+   Note if this limit is disabled then stack exhaustion is possible when
+   demangling pathologically complicated strings.  Bug reports about stack
+   exhaustion when the option is enabled will be rejected.  */  
+#define DMGL_NO_RECURSE_LIMIT (1 << 18)	
+
+/* If DMGL_NO_RECURSE_LIMIT is not enabled, then this is the value used as
+   the maximum depth of recursion allowed.  It should be enough for any
+   real-world mangled name.  */
+#define DEMANGLE_RECURSION_LIMIT 1024
+  
 /* Enumeration of possible demangling styles.
 
    Lucid and ARM styles are still kept logically distinct, even though
Index: libiberty/cp-demangle.c
===================================================================
--- libiberty/cp-demangle.c	(revision 266771)
+++ libiberty/cp-demangle.c	(working copy)
@@ -2852,21 +2852,35 @@
 static struct demangle_component *
 d_function_type (struct d_info *di)
 {
-  struct demangle_component *ret;
+  struct demangle_component *ret = NULL;
 
-  if (! d_check_char (di, 'F'))
-    return NULL;
-  if (d_peek_char (di) == 'Y')
+  if ((di->options & DMGL_NO_RECURSE_LIMIT) == 0)
     {
-      /* Function has C linkage.  We don't print this information.
-	 FIXME: We should print it in verbose mode.  */
-      d_advance (di, 1);
+      if (di->recursion_level > DEMANGLE_RECURSION_LIMIT)
+	/* FIXME: There ought to be a way to report
+	   that the recursion limit has been reached.  */
+	return NULL;
+
+      di->recursion_level ++;
     }
-  ret = d_bare_function_type (di, 1);
-  ret = d_ref_qualifier (di, ret);
 
-  if (! d_check_char (di, 'E'))
-    return NULL;
+  if (d_check_char (di, 'F'))
+    {
+      if (d_peek_char (di) == 'Y')
+	{
+	  /* Function has C linkage.  We don't print this information.
+	     FIXME: We should print it in verbose mode.  */
+	  d_advance (di, 1);
+	}
+      ret = d_bare_function_type (di, 1);
+      ret = d_ref_qualifier (di, ret);
+      
+      if (! d_check_char (di, 'E'))
+	ret = NULL;
+    }
+
+  if ((di->options & DMGL_NO_RECURSE_LIMIT) == 0)
+    di->recursion_level --;
   return ret;
 }
 
@@ -6203,6 +6217,7 @@
   di->expansion = 0;
   di->is_expression = 0;
   di->is_conversion = 0;
+  di->recursion_level = 0;
 }
 
 /* Internal implementation for the demangler.  If MANGLED is a g++ v3 ABI
@@ -6242,6 +6257,20 @@
 
   cplus_demangle_init_info (mangled, options, strlen (mangled), &di);
 
+  /* PR 87675 - Check for a mangled string that is so long
+     that we do not have enough stack space to demangle it.  */
+  if (((options & DMGL_NO_RECURSE_LIMIT) == 0)
+      /* This check is a bit arbitrary, since what we really want to do is to
+	 compare the sizes of the di.comps and di.subs arrays against the
+	 amount of stack space remaining.  But there is no portable way to do
+	 this, so instead we use the recursion limit as a guide to the maximum
+	 size of the arrays.  */
+      && (unsigned long) di.num_comps > DEMANGLE_RECURSION_LIMIT)
+    {
+      /* FIXME: We need a way to indicate that a stack limit has been reached.  */
+      return 0;
+    }
+
   {
 #ifdef CP_DYNAMIC_ARRAYS
     __extension__ struct demangle_component comps[di.num_comps];
Index: libiberty/cp-demangle.h
===================================================================
--- libiberty/cp-demangle.h	(revision 266771)
+++ libiberty/cp-demangle.h	(working copy)
@@ -122,6 +122,9 @@
   /* Non-zero if we are parsing the type operand of a conversion
      operator, but not when in an expression.  */
   int is_conversion;
+  /* If DMGL_NO_RECURSE_LIMIT is not active then this is set to
+     the current recursion level.  */
+  unsigned int recursion_level;
 };
 
 /* To avoid running past the ending '\0', don't:
Index: libiberty/cplus-dem.c
===================================================================
--- libiberty/cplus-dem.c	(revision 266771)
+++ libiberty/cplus-dem.c	(working copy)
@@ -146,6 +146,7 @@
   int *proctypevec;     /* Indices of currently processed remembered typevecs.  */
   int proctypevec_size;
   int nproctypes;
+  unsigned int recursion_level;
 };
 
 #define PRINT_ANSI_QUALIFIERS (work -> options & DMGL_ANSI)
@@ -1292,6 +1293,7 @@
       free ((char *) work -> btypevec);
       work->btypevec = NULL;
       work->bsize = 0;
+      work->numb = 0;
     }
   if (work -> ktypevec != NULL)
     {
@@ -1298,6 +1300,7 @@
       free ((char *) work -> ktypevec);
       work->ktypevec = NULL;
       work->ksize = 0;
+      work->numk = 0;
     }
 }
 
@@ -1331,8 +1334,15 @@
 
   for (i = 0; i < from->numk; i++)
     {
-      int len = strlen (from->ktypevec[i]) + 1;
+      int len;
 
+      if (from->ktypevec[i] == NULL)
+	{
+	  to->ktypevec[i] = NULL;
+	  continue;
+	}
+
+      len = strlen (from->ktypevec[i]) + 1;
       to->ktypevec[i] = XNEWVEC (char, len);
       memcpy (to->ktypevec[i], from->ktypevec[i], len);
     }
@@ -1342,8 +1352,15 @@
 
   for (i = 0; i < from->numb; i++)
     {
-      int len = strlen (from->btypevec[i]) + 1;
+      int len;
 
+      if (from->btypevec[i] == NULL)
+	{
+	  to->btypevec[i] = NULL;
+	  continue;
+	}
+
+      len = strlen (from->btypevec[i]) + 1;
       to->btypevec[i] = XNEWVEC (char , len);
       memcpy (to->btypevec[i], from->btypevec[i], len);
     }
@@ -1401,6 +1418,7 @@
 
       free ((char*) work->tmpl_argvec);
       work->tmpl_argvec = NULL;
+      work->ntmpl_args = 0;
     }
   if (work->previous_argument)
     {
@@ -4478,6 +4496,7 @@
 }
 
 /* Lose all the info related to B and K type codes. */
+
 static void
 forget_B_and_K_types (struct work_stuff *work)
 {
@@ -4503,6 +4522,7 @@
 	}
     }
 }
+
 /* Forget the remembered types, but not the type vector itself.  */
 
 static void
@@ -4697,6 +4717,16 @@
   int result;
   int saved_nrepeats;
 
+  if ((work->options & DMGL_NO_RECURSE_LIMIT) == 0)
+    {
+      if (work->recursion_level > DEMANGLE_RECURSION_LIMIT)
+	/* FIXME: There ought to be a way to report
+	   that the recursion limit has been reached.  */
+	return 0;
+
+      work->recursion_level ++;
+    }
+
   /* The G++ name-mangling algorithm does not remember types on nested
      argument lists, unless -fsquangling is used, and in that case the
      type vector updated by remember_type is not used.  So, we turn
@@ -4723,6 +4753,9 @@
   --work->forgetting_types;
   work->nrepeats = saved_nrepeats;
 
+  if ((work->options & DMGL_NO_RECURSE_LIMIT) == 0)
+    --work->recursion_level;
+
   return result;
 }
 

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: RFA/RFC: Add stack recursion limit to libiberty's demangler [v5]
  2018-12-04 16:57                     ` RFA/RFC: Add stack recursion limit to libiberty's demangler [v5] Nick Clifton
@ 2018-12-04 17:08                       ` Pedro Alves
  2018-12-06 11:12                         ` Nick Clifton
  2018-12-06 16:14                       ` RFA/RFC: Add stack recursion limit to libiberty's demangler [v5] Jason Merrill
  1 sibling, 1 reply; 55+ messages in thread
From: Pedro Alves @ 2018-12-04 17:08 UTC (permalink / raw)
  To: Nick Clifton, Ian Lance Taylor
  Cc: Richard Biener, Jakub Jelinek, matz, sgayou, Tom Tromey,
	GCC Patches, Binutils, Jason Merrill

On 12/04/2018 04:56 PM, Nick Clifton wrote:
> Hi Pedro,
> 
>> The issue pointed out by
>>
>>  https://gcc.gnu.org/ml/gcc-patches/2018-11/msg02592.html
>>
>> is still present in this version.
> 
> Doh!  Yes I meant to fix that one too, but forgot.
> 
>> Also, noticed a typo here:
>>
>>> +/* If DMGL_NO_RECURE_LIMIT is not enabled, then this is the value used as
>>
>> Typo: "RECURE"
> 
> Oops - thanks.
> 
> OK, revised (v5) patch attached.  Is this version acceptable to all ?
> 
This is fine with me.

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: RFA/RFC: Add stack recursion limit to libiberty's demangler [v5]
  2018-12-04 17:08                       ` Pedro Alves
@ 2018-12-06 11:12                         ` Nick Clifton
  2018-12-06 18:04                           ` Ian Lance Taylor via gcc-patches
  0 siblings, 1 reply; 55+ messages in thread
From: Nick Clifton @ 2018-12-06 11:12 UTC (permalink / raw)
  To: Ian Lance Taylor
  Cc: Pedro Alves, Richard Biener, Jakub Jelinek, matz, sgayou,
	Tom Tromey, GCC Patches, Binutils, Jason Merrill

Hi Ian,

  Is the patch OK with you ?

Cheers
  Nick

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: RFA/RFC: Add stack recursion limit to libiberty's demangler [v5]
  2018-12-04 16:57                     ` RFA/RFC: Add stack recursion limit to libiberty's demangler [v5] Nick Clifton
  2018-12-04 17:08                       ` Pedro Alves
@ 2018-12-06 16:14                       ` Jason Merrill
  2018-12-06 21:22                         ` RFC: libiberty PATCH to disable demangling of ancient mangling schemes Jason Merrill
  1 sibling, 1 reply; 55+ messages in thread
From: Jason Merrill @ 2018-12-06 16:14 UTC (permalink / raw)
  To: Nick Clifton, Pedro Alves, Ian Lance Taylor
  Cc: Richard Biener, Jakub Jelinek, matz, sgayou, Tom Tromey,
	GCC Patches, Binutils

On 12/4/18 11:56 AM, Nick Clifton wrote:
> OK, revised (v5) patch attached.  Is this version acceptable to all ?

Looks good to me.  Independently, do you see a reason not to disable the 
old demangler entirely?

Jason

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: RFA/RFC: Add stack recursion limit to libiberty's demangler [v5]
  2018-12-06 11:12                         ` Nick Clifton
@ 2018-12-06 18:04                           ` Ian Lance Taylor via gcc-patches
  2018-12-07 16:17                             ` H.J. Lu
  0 siblings, 1 reply; 55+ messages in thread
From: Ian Lance Taylor via gcc-patches @ 2018-12-06 18:04 UTC (permalink / raw)
  To: Nick Clifton
  Cc: Pedro Alves, Richard Guenther, Jakub Jelinek, matz, sgayou,
	Tom Tromey, gcc-patches, Binutils, Jason Merrill

On Thu, Dec 6, 2018 at 3:12 AM Nick Clifton <nickc@redhat.com> wrote:
>
>   Is the patch OK with you ?

Yes, thanks.

Ian

^ permalink raw reply	[flat|nested] 55+ messages in thread

* RFC: libiberty PATCH to disable demangling of ancient mangling schemes
  2018-12-06 16:14                       ` RFA/RFC: Add stack recursion limit to libiberty's demangler [v5] Jason Merrill
@ 2018-12-06 21:22                         ` Jason Merrill
  2018-12-07 10:27                           ` Nick Clifton
  2018-12-07 11:37                           ` Richard Biener
  0 siblings, 2 replies; 55+ messages in thread
From: Jason Merrill @ 2018-12-06 21:22 UTC (permalink / raw)
  To: Nick Clifton, Pedro Alves, Ian Lance Taylor
  Cc: Richard Biener, Jakub Jelinek, matz, Scott Gayou, Tom Tromey,
	gcc-patches List, Binutils

[-- Attachment #1: Type: text/plain, Size: 272 bytes --]

On Thu, Dec 6, 2018 at 11:14 AM Jason Merrill <jason@redhat.com> wrote:
>
> Looks good to me.  Independently, do you see a reason not to disable the
> old demangler entirely?

Like so.  Does anyone object to this?  These mangling schemes haven't
been relevant in decades.

[-- Attachment #2: old-dem-off.diff --]
[-- Type: text/x-patch, Size: 1221 bytes --]

commit 175323701ad923aa47f25e1e37fa1f3c487dc5ea
Author: Jason Merrill <jason@redhat.com>
Date:   Tue Nov 20 01:17:48 2018 -0500

            * cplus-dem.c (cplus_demangle): Turn off the old demangler.

diff --git a/libiberty/cplus-dem.c b/libiberty/cplus-dem.c
index 4f29d54d089..8ee23b2fe71 100644
--- a/libiberty/cplus-dem.c
+++ b/libiberty/cplus-dem.c
@@ -267,6 +267,7 @@ const struct demangler_engine libiberty_demanglers[] =
       "Automatic selection based on executable"
   }
   ,
+#ifdef OLD_DEMANGLERS
   {
     GNU_DEMANGLING_STYLE_STRING,
       gnu_demangling,
@@ -297,10 +298,11 @@ const struct demangler_engine libiberty_demanglers[] =
       "EDG style demangling"
   }
   ,
+#endif
   {
     GNU_V3_DEMANGLING_STYLE_STRING,
     gnu_v3_demangling,
-    "GNU (g++) V3 ABI-style demangling"
+    "GNU (g++) V3 (Itanium C++ ABI) style demangling"
   }
   ,
   {
@@ -915,8 +917,12 @@ cplus_demangle (const char *mangled, int options)
 	return ret;
     }
 
+#if OLD_DEMANGLERS
+  /* People have been busily breaking the old demangler with fuzzers
+     (CVE-2018-12641 etc), so let's turn it off.  */
   ret = internal_cplus_demangle (work, mangled);
   squangle_mop_up (work);
+#endif
   return (ret);
 }
 

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: RFC: libiberty PATCH to disable demangling of ancient mangling schemes
  2018-12-06 21:22                         ` RFC: libiberty PATCH to disable demangling of ancient mangling schemes Jason Merrill
@ 2018-12-07 10:27                           ` Nick Clifton
  2018-12-07 10:40                             ` Jakub Jelinek
  2018-12-07 11:37                           ` Richard Biener
  1 sibling, 1 reply; 55+ messages in thread
From: Nick Clifton @ 2018-12-07 10:27 UTC (permalink / raw)
  To: Jason Merrill, Pedro Alves, Ian Lance Taylor
  Cc: Richard Biener, Jakub Jelinek, matz, Scott Gayou, Tom Tromey,
	gcc-patches List, Binutils

Hi Jason,

>> Looks good to me.  Independently, do you see a reason not to disable the
>> old demangler entirely?
> 
> Like so.  Does anyone object to this?  These mangling schemes haven't
> been relevant in decades.

I am not really familiar with this old scheme, so please excuse my ignorance
in asking these questions:

  * How likely is it that there are old toolchain in use out there that still 
    use the v2 mangling ?  Ie I guess that I am asking "which generation(s)
    of gcc used v2 mangling ?"

  * If a user does try to demangle a v2 mangled name, what will happen ?
    Ie I guess I am asking if they will be given a hint that they need to use
    an older toolchain in order to demangle the names.

Cheers
  Nick



^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: RFC: libiberty PATCH to disable demangling of ancient mangling schemes
  2018-12-07 10:27                           ` Nick Clifton
@ 2018-12-07 10:40                             ` Jakub Jelinek
  2018-12-07 16:11                               ` Pedro Alves
  2018-12-07 16:28                               ` Nick Clifton
  0 siblings, 2 replies; 55+ messages in thread
From: Jakub Jelinek @ 2018-12-07 10:40 UTC (permalink / raw)
  To: Nick Clifton
  Cc: Jason Merrill, Pedro Alves, Ian Lance Taylor, Richard Biener,
	matz, Scott Gayou, Tom Tromey, gcc-patches List, Binutils

On Fri, Dec 07, 2018 at 10:27:17AM +0000, Nick Clifton wrote:
> >> Looks good to me.  Independently, do you see a reason not to disable the
> >> old demangler entirely?
> > 
> > Like so.  Does anyone object to this?  These mangling schemes haven't
> > been relevant in decades.
> 
> I am not really familiar with this old scheme, so please excuse my ignorance
> in asking these questions:
> 
>   * How likely is it that there are old toolchain in use out there that still 
>     use the v2 mangling ?  Ie I guess that I am asking "which generation(s)
>     of gcc used v2 mangling ?"

GCC 3.0 and up used the new (Itanium C++ ABI) mangling, 2.95 and older used the old
mangling (2.96-RH used the new mangling I believe).
So you need compiler older than 17.5 years to have the old mangling.
Such a compiler didn't support most of the contemporarily used platforms
though at all (e.g. x86-64, powerpc64le, aarch64, I believe not even
powerpc64-linux).

	Jakub

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: RFC: libiberty PATCH to disable demangling of ancient mangling schemes
  2018-12-06 21:22                         ` RFC: libiberty PATCH to disable demangling of ancient mangling schemes Jason Merrill
  2018-12-07 10:27                           ` Nick Clifton
@ 2018-12-07 11:37                           ` Richard Biener
  2018-12-07 15:49                             ` Jason Merrill
  1 sibling, 1 reply; 55+ messages in thread
From: Richard Biener @ 2018-12-07 11:37 UTC (permalink / raw)
  To: Jason Merrill
  Cc: Nick Clifton, Pedro Alves, Ian Lance Taylor, Jakub Jelinek, matz,
	sgayou, tom, GCC Patches, Binutils

On Thu, Dec 6, 2018 at 10:22 PM Jason Merrill <jason@redhat.com> wrote:
>
> On Thu, Dec 6, 2018 at 11:14 AM Jason Merrill <jason@redhat.com> wrote:
> >
> > Looks good to me.  Independently, do you see a reason not to disable the
> > old demangler entirely?
>
> Like so.  Does anyone object to this?  These mangling schemes haven't
> been relevant in decades.

Why #ifdef the code?  Just rip it out?

Richard.

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: RFC: libiberty PATCH to disable demangling of ancient mangling schemes
  2018-12-07 11:37                           ` Richard Biener
@ 2018-12-07 15:49                             ` Jason Merrill
  2018-12-10  1:04                               ` Eric Gallager
  0 siblings, 1 reply; 55+ messages in thread
From: Jason Merrill @ 2018-12-07 15:49 UTC (permalink / raw)
  To: Richard Biener
  Cc: Nick Clifton, Pedro Alves, Ian Lance Taylor, Jakub Jelinek, matz,
	sgayou, tom, GCC Patches, Binutils

On 12/7/18 6:36 AM, Richard Biener wrote:
> On Thu, Dec 6, 2018 at 10:22 PM Jason Merrill <jason@redhat.com> wrote:
>>
>> On Thu, Dec 6, 2018 at 11:14 AM Jason Merrill <jason@redhat.com> wrote:
>>>
>>> Looks good to me.  Independently, do you see a reason not to disable the
>>> old demangler entirely?
>>
>> Like so.  Does anyone object to this?  These mangling schemes haven't
>> been relevant in decades.
> 
> Why #ifdef the code?  Just rip it out?

I was thinking as an intermediate measure in case some user wanted it 
for some reason, but I'd be fine with that as well.

Jason

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: RFC: libiberty PATCH to disable demangling of ancient mangling schemes
  2018-12-07 10:40                             ` Jakub Jelinek
@ 2018-12-07 16:11                               ` Pedro Alves
  2018-12-07 17:49                                 ` Tom Tromey
  2018-12-07 16:28                               ` Nick Clifton
  1 sibling, 1 reply; 55+ messages in thread
From: Pedro Alves @ 2018-12-07 16:11 UTC (permalink / raw)
  To: Jakub Jelinek, Nick Clifton
  Cc: Jason Merrill, Ian Lance Taylor, Richard Biener, matz,
	Scott Gayou, Tom Tromey, gcc-patches List, Binutils, GDB Patches

Adding gdb-patches, since demangling affects gdb.

Ref: https://gcc.gnu.org/ml/gcc-patches/2018-12/msg00407.html

On 12/07/2018 10:40 AM, Jakub Jelinek wrote:
> On Fri, Dec 07, 2018 at 10:27:17AM +0000, Nick Clifton wrote:
>>>> Looks good to me.  Independently, do you see a reason not to disable the
>>>> old demangler entirely?
>>>
>>> Like so.  Does anyone object to this?  These mangling schemes haven't
>>> been relevant in decades.
>>
>> I am not really familiar with this old scheme, so please excuse my ignorance
>> in asking these questions:
>>
>>   * How likely is it that there are old toolchain in use out there that still 
>>     use the v2 mangling ?  Ie I guess that I am asking "which generation(s)
>>     of gcc used v2 mangling ?"
> 
> GCC 3.0 and up used the new (Itanium C++ ABI) mangling, 2.95 and older used the old
> mangling (2.96-RH used the new mangling I believe).
> So you need compiler older than 17.5 years to have the old mangling.
> Such a compiler didn't support most of the contemporarily used platforms
> though at all (e.g. x86-64, powerpc64le, aarch64, I believe not even
> powerpc64-linux).
> 
Yeah.

I guess the question would be whether it is reasonable to expect
that people will still need to debug&inspect (with gdb, c++filt, etc.)
any such old binary, and that they will need to do it with with modern
tools, as opposed to sticking with older binutils&gdb, and how often
would that be needed.

I would say that it's very, very unlikely, and not worth it of the
maintenance burden.

Last I heard of 2.95-produced binaries I think was for some ancient gcc-2.95-based
cross compiler that was still being minimally maintained, because it was needed
to build&maintain some legacy stuff.  That was maybe over 8 years ago, and
it was off trunk.  It's probably dead by now.  And if isn't dead,
whoever maintains the compiler off trunk certainly can also maintain old-ish
binutils & gdb off trunk.

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: RFA/RFC: Add stack recursion limit to libiberty's demangler [v5]
  2018-12-06 18:04                           ` Ian Lance Taylor via gcc-patches
@ 2018-12-07 16:17                             ` H.J. Lu
  2018-12-07 16:25                               ` [PATCH] Set DEMANGLE_RECURSION_LIMIT to 1536 H.J. Lu
  0 siblings, 1 reply; 55+ messages in thread
From: H.J. Lu @ 2018-12-07 16:17 UTC (permalink / raw)
  To: Ian Lance Taylor
  Cc: Nick Clifton, Pedro Alves, Richard Guenther, Jakub Jelinek, matz,
	sgayou, Tom Tromey, GCC Patches, Binutils, Jason Merrill

On Thu, Dec 6, 2018 at 10:04 AM Ian Lance Taylor via gcc-patches
<gcc-patches@gcc.gnu.org> wrote:
>
> On Thu, Dec 6, 2018 at 3:12 AM Nick Clifton <nickc@redhat.com> wrote:
> >
> >   Is the patch OK with you ?
>

This caused:

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88409


-- 
H.J.

^ permalink raw reply	[flat|nested] 55+ messages in thread

* [PATCH] Set DEMANGLE_RECURSION_LIMIT to 1536
  2018-12-07 16:17                             ` H.J. Lu
@ 2018-12-07 16:25                               ` H.J. Lu
  2018-12-10 14:52                                 ` Michael Matz
  0 siblings, 1 reply; 55+ messages in thread
From: H.J. Lu @ 2018-12-07 16:25 UTC (permalink / raw)
  To: Ian Lance Taylor
  Cc: Nick Clifton, Pedro Alves, Richard Guenther, Jakub Jelinek, matz,
	sgayou, Tom Tromey, GCC Patches, Binutils, Jason Merrill

[-- Attachment #1: Type: text/plain, Size: 422 bytes --]

On Fri, Dec 7, 2018 at 8:17 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> On Thu, Dec 6, 2018 at 10:04 AM Ian Lance Taylor via gcc-patches
> <gcc-patches@gcc.gnu.org> wrote:
> >
> > On Thu, Dec 6, 2018 at 3:12 AM Nick Clifton <nickc@redhat.com> wrote:
> > >
> > >   Is the patch OK with you ?
> >
>
> This caused:
>
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88409
>

Here is the fix.   OK for trunk?

Thanks.

-- 
H.J.

[-- Attachment #2: 0001-Set-DEMANGLE_RECURSION_LIMIT-to-1536.patch --]
[-- Type: application/x-patch, Size: 1583 bytes --]

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: RFC: libiberty PATCH to disable demangling of ancient mangling schemes
  2018-12-07 10:40                             ` Jakub Jelinek
  2018-12-07 16:11                               ` Pedro Alves
@ 2018-12-07 16:28                               ` Nick Clifton
  1 sibling, 0 replies; 55+ messages in thread
From: Nick Clifton @ 2018-12-07 16:28 UTC (permalink / raw)
  To: Jakub Jelinek
  Cc: Jason Merrill, Pedro Alves, Ian Lance Taylor, Richard Biener,
	matz, Scott Gayou, Tom Tromey, gcc-patches List, Binutils

Hi Guys,

>>>> Looks good to me.  Independently, do you see a reason not to disable the
>>>> old demangler entirely?

>>   * How likely is it that there are old toolchain in use out there that still 
>>     use the v2 mangling ?

> GCC 3.0 and up used the new (Itanium C++ ABI) mangling, 2.95 and older used the old
> mangling (2.96-RH used the new mangling I believe).
> So you need compiler older than 17.5 years to have the old mangling.
> Such a compiler didn't support most of the contemporarily used platforms
> though at all (e.g. x86-64, powerpc64le, aarch64, I believe not even
> powerpc64-linux).

Well that is good enough for me. :-)  I do not have the power to approve
the patch, but I would certainly be happy to see it go in.

Cheers
  Nick


^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: RFC: libiberty PATCH to disable demangling of ancient mangling schemes
  2018-12-07 16:11                               ` Pedro Alves
@ 2018-12-07 17:49                                 ` Tom Tromey
  2018-12-07 21:00                                   ` Jason Merrill
  0 siblings, 1 reply; 55+ messages in thread
From: Tom Tromey @ 2018-12-07 17:49 UTC (permalink / raw)
  To: Pedro Alves
  Cc: Jakub Jelinek, Nick Clifton, Jason Merrill, Ian Lance Taylor,
	Richard Biener, matz, Scott Gayou, Tom Tromey, gcc-patches List,
	Binutils, GDB Patches

>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:

Pedro> I would say that it's very, very unlikely, and not worth it of the
Pedro> maintenance burden.

Agreed, and especially true for the more unusual demanglings like Lucid
or EDG.

On the gdb side perhaps we can get rid of "demangle-style" now.  It
probably hasn't worked properly in years, and after this it would be
guaranteed not to.

Tom

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: RFC: libiberty PATCH to disable demangling of ancient mangling schemes
  2018-12-07 17:49                                 ` Tom Tromey
@ 2018-12-07 21:00                                   ` Jason Merrill
  2018-12-14 22:39                                     ` Jason Merrill
  0 siblings, 1 reply; 55+ messages in thread
From: Jason Merrill @ 2018-12-07 21:00 UTC (permalink / raw)
  To: Tom Tromey, Pedro Alves
  Cc: Jakub Jelinek, Nick Clifton, Ian Lance Taylor, Richard Biener,
	matz, Scott Gayou, gcc-patches List, Binutils, GDB Patches

[-- Attachment #1: Type: text/plain, Size: 710 bytes --]

On 12/7/18 12:48 PM, Tom Tromey wrote:
>>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:
> 
> Pedro> I would say that it's very, very unlikely, and not worth it of the
> Pedro> maintenance burden.
> 
> Agreed, and especially true for the more unusual demanglings like Lucid
> or EDG.
> 
> On the gdb side perhaps we can get rid of "demangle-style" now.  It
> probably hasn't worked properly in years, and after this it would be
> guaranteed not to.

So, here's the patch to tear out the old code, which passes the GCC 
regression testsuite.  I also tried building binutils/gdb with it, and 
both will need to remove code that calls cplus_mangle_opname for dealing 
with the old mangling scheme.

Jason

[-- Attachment #2: old-dem-remove.diff --]
[-- Type: text/x-patch, Size: 196381 bytes --]

diff --git a/libiberty/cplus-dem.c b/libiberty/cplus-dem.c
index 48c0cfd848a..676e9d119da 100644
--- a/libiberty/cplus-dem.c
+++ b/libiberty/cplus-dem.c
@@ -29,12 +29,6 @@ License along with libiberty; see the file COPYING.LIB.  If
 not, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 Boston, MA 02110-1301, USA.  */
 
-/* This file exports two functions; cplus_mangle_opname and cplus_demangle.
-
-   This file imports xmalloc and xrealloc, which are like malloc and
-   realloc except that they generate a fatal error if there is no
-   available memory.  */
-
 /* This file lives in both GCC and libiberty.  When making changes, please
    try not to break either.  */
 
@@ -44,9 +38,7 @@ Boston, MA 02110-1301, USA.  */
 
 #include "safe-ctype.h"
 
-#include <sys/types.h>
 #include <string.h>
-#include <stdio.h>
 
 #ifdef HAVE_STDLIB_H
 #include <stdlib.h>
@@ -55,205 +47,12 @@ void * malloc ();
 void * realloc ();
 #endif
 
-#ifdef HAVE_LIMITS_H
-#include <limits.h>
-#endif
-#ifndef INT_MAX
-# define INT_MAX       (int)(((unsigned int) ~0) >> 1)          /* 0x7FFFFFFF */ 
-#endif
-
 #include <demangle.h>
-#undef CURRENT_DEMANGLING_STYLE
-#define CURRENT_DEMANGLING_STYLE work->options
 
 #include "libiberty.h"
 
-#define min(X,Y) (((X) < (Y)) ? (X) : (Y))
-
-/* A value at least one greater than the maximum number of characters
-   that will be output when using the `%d' format with `printf'.  */
-#define INTBUF_SIZE 32
-
-extern void fancy_abort (void) ATTRIBUTE_NORETURN;
-
-/* In order to allow a single demangler executable to demangle strings
-   using various common values of CPLUS_MARKER, as well as any specific
-   one set at compile time, we maintain a string containing all the
-   commonly used ones, and check to see if the marker we are looking for
-   is in that string.  CPLUS_MARKER is usually '$' on systems where the
-   assembler can deal with that.  Where the assembler can't, it's usually
-   '.' (but on many systems '.' is used for other things).  We put the
-   current defined CPLUS_MARKER first (which defaults to '$'), followed
-   by the next most common value, followed by an explicit '$' in case
-   the value of CPLUS_MARKER is not '$'.
-
-   We could avoid this if we could just get g++ to tell us what the actual
-   cplus marker character is as part of the debug information, perhaps by
-   ensuring that it is the character that terminates the gcc<n>_compiled
-   marker symbol (FIXME).  */
-
-#if !defined (CPLUS_MARKER)
-#define CPLUS_MARKER '$'
-#endif
-
 enum demangling_styles current_demangling_style = auto_demangling;
 
-static char cplus_markers[] = { CPLUS_MARKER, '.', '$', '\0' };
-
-static char char_str[2] = { '\000', '\000' };
-
-void
-set_cplus_marker_for_demangling (int ch)
-{
-  cplus_markers[0] = ch;
-}
-
-typedef struct string		/* Beware: these aren't required to be */
-{				/*  '\0' terminated.  */
-  char *b;			/* pointer to start of string */
-  char *p;			/* pointer after last character */
-  char *e;			/* pointer after end of allocated space */
-} string;
-
-/* Stuff that is shared between sub-routines.
-   Using a shared structure allows cplus_demangle to be reentrant.  */
-
-struct work_stuff
-{
-  int options;
-  char **typevec;
-  char **ktypevec;
-  char **btypevec;
-  int numk;
-  int numb;
-  int ksize;
-  int bsize;
-  int ntypes;
-  int typevec_size;
-  int constructor;
-  int destructor;
-  int static_type;	/* A static member function */
-  int temp_start;       /* index in demangled to start of template args */
-  int type_quals;       /* The type qualifiers.  */
-  int dllimported;	/* Symbol imported from a PE DLL */
-  char **tmpl_argvec;   /* Template function arguments. */
-  int ntmpl_args;       /* The number of template function arguments. */
-  int forgetting_types; /* Nonzero if we are not remembering the types
-			   we see.  */
-  string* previous_argument; /* The last function argument demangled.  */
-  int nrepeats;         /* The number of times to repeat the previous
-			   argument.  */
-  int *proctypevec;     /* Indices of currently processed remembered typevecs.  */
-  int proctypevec_size;
-  int nproctypes;
-  unsigned int recursion_level;
-};
-
-#define PRINT_ANSI_QUALIFIERS (work -> options & DMGL_ANSI)
-#define PRINT_ARG_TYPES       (work -> options & DMGL_PARAMS)
-
-static const struct optable
-{
-  const char *const in;
-  const char *const out;
-  const int flags;
-} optable[] = {
-  {"nw",	  " new",	DMGL_ANSI},	/* new (1.92,	 ansi) */
-  {"dl",	  " delete",	DMGL_ANSI},	/* new (1.92,	 ansi) */
-  {"new",	  " new",	0},		/* old (1.91,	 and 1.x) */
-  {"delete",	  " delete",	0},		/* old (1.91,	 and 1.x) */
-  {"vn",	  " new []",	DMGL_ANSI},	/* GNU, pending ansi */
-  {"vd",	  " delete []",	DMGL_ANSI},	/* GNU, pending ansi */
-  {"as",	  "=",		DMGL_ANSI},	/* ansi */
-  {"ne",	  "!=",		DMGL_ANSI},	/* old, ansi */
-  {"eq",	  "==",		DMGL_ANSI},	/* old,	ansi */
-  {"ge",	  ">=",		DMGL_ANSI},	/* old,	ansi */
-  {"gt",	  ">",		DMGL_ANSI},	/* old,	ansi */
-  {"le",	  "<=",		DMGL_ANSI},	/* old,	ansi */
-  {"lt",	  "<",		DMGL_ANSI},	/* old,	ansi */
-  {"plus",	  "+",		0},		/* old */
-  {"pl",	  "+",		DMGL_ANSI},	/* ansi */
-  {"apl",	  "+=",		DMGL_ANSI},	/* ansi */
-  {"minus",	  "-",		0},		/* old */
-  {"mi",	  "-",		DMGL_ANSI},	/* ansi */
-  {"ami",	  "-=",		DMGL_ANSI},	/* ansi */
-  {"mult",	  "*",		0},		/* old */
-  {"ml",	  "*",		DMGL_ANSI},	/* ansi */
-  {"amu",	  "*=",		DMGL_ANSI},	/* ansi (ARM/Lucid) */
-  {"aml",	  "*=",		DMGL_ANSI},	/* ansi (GNU/g++) */
-  {"convert",	  "+",		0},		/* old (unary +) */
-  {"negate",	  "-",		0},		/* old (unary -) */
-  {"trunc_mod",	  "%",		0},		/* old */
-  {"md",	  "%",		DMGL_ANSI},	/* ansi */
-  {"amd",	  "%=",		DMGL_ANSI},	/* ansi */
-  {"trunc_div",	  "/",		0},		/* old */
-  {"dv",	  "/",		DMGL_ANSI},	/* ansi */
-  {"adv",	  "/=",		DMGL_ANSI},	/* ansi */
-  {"truth_andif", "&&",		0},		/* old */
-  {"aa",	  "&&",		DMGL_ANSI},	/* ansi */
-  {"truth_orif",  "||",		0},		/* old */
-  {"oo",	  "||",		DMGL_ANSI},	/* ansi */
-  {"truth_not",	  "!",		0},		/* old */
-  {"nt",	  "!",		DMGL_ANSI},	/* ansi */
-  {"postincrement","++",	0},		/* old */
-  {"pp",	  "++",		DMGL_ANSI},	/* ansi */
-  {"postdecrement","--",	0},		/* old */
-  {"mm",	  "--",		DMGL_ANSI},	/* ansi */
-  {"bit_ior",	  "|",		0},		/* old */
-  {"or",	  "|",		DMGL_ANSI},	/* ansi */
-  {"aor",	  "|=",		DMGL_ANSI},	/* ansi */
-  {"bit_xor",	  "^",		0},		/* old */
-  {"er",	  "^",		DMGL_ANSI},	/* ansi */
-  {"aer",	  "^=",		DMGL_ANSI},	/* ansi */
-  {"bit_and",	  "&",		0},		/* old */
-  {"ad",	  "&",		DMGL_ANSI},	/* ansi */
-  {"aad",	  "&=",		DMGL_ANSI},	/* ansi */
-  {"bit_not",	  "~",		0},		/* old */
-  {"co",	  "~",		DMGL_ANSI},	/* ansi */
-  {"call",	  "()",		0},		/* old */
-  {"cl",	  "()",		DMGL_ANSI},	/* ansi */
-  {"alshift",	  "<<",		0},		/* old */
-  {"ls",	  "<<",		DMGL_ANSI},	/* ansi */
-  {"als",	  "<<=",	DMGL_ANSI},	/* ansi */
-  {"arshift",	  ">>",		0},		/* old */
-  {"rs",	  ">>",		DMGL_ANSI},	/* ansi */
-  {"ars",	  ">>=",	DMGL_ANSI},	/* ansi */
-  {"component",	  "->",		0},		/* old */
-  {"pt",	  "->",		DMGL_ANSI},	/* ansi; Lucid C++ form */
-  {"rf",	  "->",		DMGL_ANSI},	/* ansi; ARM/GNU form */
-  {"indirect",	  "*",		0},		/* old */
-  {"method_call",  "->()",	0},		/* old */
-  {"addr",	  "&",		0},		/* old (unary &) */
-  {"array",	  "[]",		0},		/* old */
-  {"vc",	  "[]",		DMGL_ANSI},	/* ansi */
-  {"compound",	  ", ",		0},		/* old */
-  {"cm",	  ", ",		DMGL_ANSI},	/* ansi */
-  {"cond",	  "?:",		0},		/* old */
-  {"cn",	  "?:",		DMGL_ANSI},	/* pseudo-ansi */
-  {"max",	  ">?",		0},		/* old */
-  {"mx",	  ">?",		DMGL_ANSI},	/* pseudo-ansi */
-  {"min",	  "<?",		0},		/* old */
-  {"mn",	  "<?",		DMGL_ANSI},	/* pseudo-ansi */
-  {"nop",	  "",		0},		/* old (for operator=) */
-  {"rm",	  "->*",	DMGL_ANSI},	/* ansi */
-  {"sz",          "sizeof ",    DMGL_ANSI}      /* pseudo-ansi */
-};
-
-/* These values are used to indicate the various type varieties.
-   They are all non-zero so that they can be used as `success'
-   values.  */
-typedef enum type_kind_t
-{
-  tk_none,
-  tk_pointer,
-  tk_reference,
-  tk_rvalue_reference,
-  tk_integral,
-  tk_bool,
-  tk_char,
-  tk_real
-} type_kind_t;
-
 const struct demangler_engine libiberty_demanglers[] =
 {
   {
@@ -268,40 +67,10 @@ const struct demangler_engine libiberty_demanglers[] =
       "Automatic selection based on executable"
   }
   ,
-  {
-    GNU_DEMANGLING_STYLE_STRING,
-      gnu_demangling,
-      "GNU (g++) style demangling"
-  }
-  ,
-  {
-    LUCID_DEMANGLING_STYLE_STRING,
-      lucid_demangling,
-      "Lucid (lcc) style demangling"
-  }
-  ,
-  {
-    ARM_DEMANGLING_STYLE_STRING,
-      arm_demangling,
-      "ARM style demangling"
-  }
-  ,
-  {
-    HP_DEMANGLING_STYLE_STRING,
-      hp_demangling,
-      "HP (aCC) style demangling"
-  }
-  ,
-  {
-    EDG_DEMANGLING_STYLE_STRING,
-      edg_demangling,
-      "EDG style demangling"
-  }
-  ,
   {
     GNU_V3_DEMANGLING_STYLE_STRING,
     gnu_v3_demangling,
-    "GNU (g++) V3 ABI-style demangling"
+    "GNU (g++) V3 (Itanium C++ ABI) style demangling"
   }
   ,
   {
@@ -333,474 +102,6 @@ const struct demangler_engine libiberty_demanglers[] =
   }
 };
 
-#define STRING_EMPTY(str)	((str) -> b == (str) -> p)
-#define APPEND_BLANK(str)	{if (!STRING_EMPTY(str)) \
-    string_append(str, " ");}
-#define LEN_STRING(str)         ( (STRING_EMPTY(str))?0:((str)->p - (str)->b))
-
-/* The scope separator appropriate for the language being demangled.  */
-
-#define SCOPE_STRING(work) ((work->options & DMGL_JAVA) ? "." : "::")
-
-#define ARM_VTABLE_STRING "__vtbl__"	/* Lucid/ARM virtual table prefix */
-#define ARM_VTABLE_STRLEN 8		/* strlen (ARM_VTABLE_STRING) */
-
-/* Prototypes for local functions */
-
-static void delete_work_stuff (struct work_stuff *);
-
-static void delete_non_B_K_work_stuff (struct work_stuff *);
-
-static char *mop_up (struct work_stuff *, string *, int);
-
-static void squangle_mop_up (struct work_stuff *);
-
-static void work_stuff_copy_to_from (struct work_stuff *, struct work_stuff *);
-
-#if 0
-static int
-demangle_method_args (struct work_stuff *, const char **, string *);
-#endif
-
-static char *
-internal_cplus_demangle (struct work_stuff *, const char *);
-
-static int
-demangle_template_template_parm (struct work_stuff *work,
-                                 const char **, string *);
-
-static int
-demangle_template (struct work_stuff *work, const char **, string *,
-                   string *, int, int);
-
-static int
-arm_pt (struct work_stuff *, const char *, int, const char **,
-        const char **);
-
-static int
-demangle_class_name (struct work_stuff *, const char **, string *);
-
-static int
-demangle_qualified (struct work_stuff *, const char **, string *,
-                    int, int);
-
-static int demangle_class (struct work_stuff *, const char **, string *);
-
-static int demangle_fund_type (struct work_stuff *, const char **, string *);
-
-static int demangle_signature (struct work_stuff *, const char **, string *);
-
-static int demangle_prefix (struct work_stuff *, const char **, string *);
-
-static int gnu_special (struct work_stuff *, const char **, string *);
-
-static int arm_special (const char **, string *);
-
-static void string_need (string *, int);
-
-static void string_delete (string *);
-
-static void
-string_init (string *);
-
-static void string_clear (string *);
-
-#if 0
-static int string_empty (string *);
-#endif
-
-static void string_append (string *, const char *);
-
-static void string_appends (string *, string *);
-
-static void string_appendn (string *, const char *, int);
-
-static void string_prepend (string *, const char *);
-
-static void string_prependn (string *, const char *, int);
-
-static void string_append_template_idx (string *, int);
-
-static int get_count (const char **, int *);
-
-static int consume_count (const char **);
-
-static int consume_count_with_underscores (const char**);
-
-static int demangle_args (struct work_stuff *, const char **, string *);
-
-static int demangle_nested_args (struct work_stuff*, const char**, string*);
-
-static int do_type (struct work_stuff *, const char **, string *);
-
-static int do_arg (struct work_stuff *, const char **, string *);
-
-static int
-demangle_function_name (struct work_stuff *, const char **, string *,
-                        const char *);
-
-static int
-iterate_demangle_function (struct work_stuff *,
-                           const char **, string *, const char *);
-
-static void remember_type (struct work_stuff *, const char *, int);
-
-static void push_processed_type (struct work_stuff *, int);
-
-static void pop_processed_type (struct work_stuff *);
-
-static void remember_Btype (struct work_stuff *, const char *, int, int);
-
-static int register_Btype (struct work_stuff *);
-
-static void remember_Ktype (struct work_stuff *, const char *, int);
-
-static void forget_types (struct work_stuff *);
-
-static void forget_B_and_K_types (struct work_stuff *);
-
-static void string_prepends (string *, string *);
-
-static int
-demangle_template_value_parm (struct work_stuff*, const char**,
-                              string*, type_kind_t);
-
-static int
-do_hpacc_template_const_value (struct work_stuff *, const char **, string *);
-
-static int
-do_hpacc_template_literal (struct work_stuff *, const char **, string *);
-
-static int snarf_numeric_literal (const char **, string *);
-
-/* There is a TYPE_QUAL value for each type qualifier.  They can be
-   combined by bitwise-or to form the complete set of qualifiers for a
-   type.  */
-
-#define TYPE_UNQUALIFIED   0x0
-#define TYPE_QUAL_CONST    0x1
-#define TYPE_QUAL_VOLATILE 0x2
-#define TYPE_QUAL_RESTRICT 0x4
-
-static int code_for_qualifier (int);
-
-static const char* qualifier_string (int);
-
-static const char* demangle_qualifier (int);
-
-static int demangle_expression (struct work_stuff *, const char **, string *, 
-                                type_kind_t);
-
-static int
-demangle_integral_value (struct work_stuff *, const char **, string *);
-
-static int
-demangle_real_value (struct work_stuff *, const char **, string *);
-
-static void
-demangle_arm_hp_template (struct work_stuff *, const char **, int, string *);
-
-static void
-recursively_demangle (struct work_stuff *, const char **, string *, int);
-
-/* Translate count to integer, consuming tokens in the process.
-   Conversion terminates on the first non-digit character.
-
-   Trying to consume something that isn't a count results in no
-   consumption of input and a return of -1.
-
-   Overflow consumes the rest of the digits, and returns -1.  */
-
-static int
-consume_count (const char **type)
-{
-  int count = 0;
-
-  if (! ISDIGIT ((unsigned char)**type))
-    return -1;
-
-  while (ISDIGIT ((unsigned char)**type))
-    {
-      const int digit = **type - '0';
-      /* Check for overflow.  */
-      if (count > ((INT_MAX - digit) / 10))
-	{
-	  while (ISDIGIT ((unsigned char) **type))
-	    (*type)++;
-	  return -1;
-	}
-
-      count *= 10;
-      count += digit;
-      (*type)++;
-    }
-
-  if (count < 0)
-    count = -1;
-
-  return (count);
-}
-
-
-/* Like consume_count, but for counts that are preceded and followed
-   by '_' if they are greater than 10.  Also, -1 is returned for
-   failure, since 0 can be a valid value.  */
-
-static int
-consume_count_with_underscores (const char **mangled)
-{
-  int idx;
-
-  if (**mangled == '_')
-    {
-      (*mangled)++;
-      if (!ISDIGIT ((unsigned char)**mangled))
-	return -1;
-
-      idx = consume_count (mangled);
-      if (**mangled != '_')
-	/* The trailing underscore was missing. */
-	return -1;
-
-      (*mangled)++;
-    }
-  else
-    {
-      if (**mangled < '0' || **mangled > '9')
-	return -1;
-
-      idx = **mangled - '0';
-      (*mangled)++;
-    }
-
-  return idx;
-}
-
-/* C is the code for a type-qualifier.  Return the TYPE_QUAL
-   corresponding to this qualifier.  */
-
-static int
-code_for_qualifier (int c)
-{
-  switch (c)
-    {
-    case 'C':
-      return TYPE_QUAL_CONST;
-
-    case 'V':
-      return TYPE_QUAL_VOLATILE;
-
-    case 'u':
-      return TYPE_QUAL_RESTRICT;
-
-    default:
-      break;
-    }
-
-  /* C was an invalid qualifier.  */
-  abort ();
-}
-
-/* Return the string corresponding to the qualifiers given by
-   TYPE_QUALS.  */
-
-static const char*
-qualifier_string (int type_quals)
-{
-  switch (type_quals)
-    {
-    case TYPE_UNQUALIFIED:
-      return "";
-
-    case TYPE_QUAL_CONST:
-      return "const";
-
-    case TYPE_QUAL_VOLATILE:
-      return "volatile";
-
-    case TYPE_QUAL_RESTRICT:
-      return "__restrict";
-
-    case TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE:
-      return "const volatile";
-
-    case TYPE_QUAL_CONST | TYPE_QUAL_RESTRICT:
-      return "const __restrict";
-
-    case TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT:
-      return "volatile __restrict";
-
-    case TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT:
-      return "const volatile __restrict";
-
-    default:
-      break;
-    }
-
-  /* TYPE_QUALS was an invalid qualifier set.  */
-  abort ();
-}
-
-/* C is the code for a type-qualifier.  Return the string
-   corresponding to this qualifier.  This function should only be
-   called with a valid qualifier code.  */
-
-static const char*
-demangle_qualifier (int c)
-{
-  return qualifier_string (code_for_qualifier (c));
-}
-
-int
-cplus_demangle_opname (const char *opname, char *result, int options)
-{
-  int len, len1, ret;
-  string type;
-  struct work_stuff work[1];
-  const char *tem;
-
-  len = strlen(opname);
-  result[0] = '\0';
-  ret = 0;
-  memset ((char *) work, 0, sizeof (work));
-  work->options = options;
-
-  if (opname[0] == '_' && opname[1] == '_'
-      && opname[2] == 'o' && opname[3] == 'p')
-    {
-      /* ANSI.  */
-      /* type conversion operator.  */
-      tem = opname + 4;
-      if (do_type (work, &tem, &type))
-	{
-	  strcat (result, "operator ");
-	  strncat (result, type.b, type.p - type.b);
-	  string_delete (&type);
-	  ret = 1;
-	}
-    }
-  else if (opname[0] == '_' && opname[1] == '_'
-	   && ISLOWER((unsigned char)opname[2])
-	   && ISLOWER((unsigned char)opname[3]))
-    {
-      if (opname[4] == '\0')
-	{
-	  /* Operator.  */
-	  size_t i;
-	  for (i = 0; i < ARRAY_SIZE (optable); i++)
-	    {
-	      if (strlen (optable[i].in) == 2
-		  && memcmp (optable[i].in, opname + 2, 2) == 0)
-		{
-		  strcat (result, "operator");
-		  strcat (result, optable[i].out);
-		  ret = 1;
-		  break;
-		}
-	    }
-	}
-      else
-	{
-	  if (opname[2] == 'a' && opname[5] == '\0')
-	    {
-	      /* Assignment.  */
-	      size_t i;
-	      for (i = 0; i < ARRAY_SIZE (optable); i++)
-		{
-		  if (strlen (optable[i].in) == 3
-		      && memcmp (optable[i].in, opname + 2, 3) == 0)
-		    {
-		      strcat (result, "operator");
-		      strcat (result, optable[i].out);
-		      ret = 1;
-		      break;
-		    }
-		}
-	    }
-	}
-    }
-  else if (len >= 3
-	   && opname[0] == 'o'
-	   && opname[1] == 'p'
-	   && strchr (cplus_markers, opname[2]) != NULL)
-    {
-      /* see if it's an assignment expression */
-      if (len >= 10 /* op$assign_ */
-	  && memcmp (opname + 3, "assign_", 7) == 0)
-	{
-	  size_t i;
-	  for (i = 0; i < ARRAY_SIZE (optable); i++)
-	    {
-	      len1 = len - 10;
-	      if ((int) strlen (optable[i].in) == len1
-		  && memcmp (optable[i].in, opname + 10, len1) == 0)
-		{
-		  strcat (result, "operator");
-		  strcat (result, optable[i].out);
-		  strcat (result, "=");
-		  ret = 1;
-		  break;
-		}
-	    }
-	}
-      else
-	{
-	  size_t i;
-	  for (i = 0; i < ARRAY_SIZE (optable); i++)
-	    {
-	      len1 = len - 3;
-	      if ((int) strlen (optable[i].in) == len1
-		  && memcmp (optable[i].in, opname + 3, len1) == 0)
-		{
-		  strcat (result, "operator");
-		  strcat (result, optable[i].out);
-		  ret = 1;
-		  break;
-		}
-	    }
-	}
-    }
-  else if (len >= 5 && memcmp (opname, "type", 4) == 0
-	   && strchr (cplus_markers, opname[4]) != NULL)
-    {
-      /* type conversion operator */
-      tem = opname + 5;
-      if (do_type (work, &tem, &type))
-	{
-	  strcat (result, "operator ");
-	  strncat (result, type.b, type.p - type.b);
-	  string_delete (&type);
-	  ret = 1;
-	}
-    }
-  squangle_mop_up (work);
-  return ret;
-
-}
-
-/* Takes operator name as e.g. "++" and returns mangled
-   operator name (e.g. "postincrement_expr"), or NULL if not found.
-
-   If OPTIONS & DMGL_ANSI == 1, return the ANSI name;
-   if OPTIONS & DMGL_ANSI == 0, return the old GNU name.  */
-
-const char *
-cplus_mangle_opname (const char *opname, int options)
-{
-  size_t i;
-  int len;
-
-  len = strlen (opname);
-  for (i = 0; i < ARRAY_SIZE (optable); i++)
-    {
-      if ((int) strlen (optable[i].out) == len
-	  && (options & DMGL_ANSI) == (optable[i].flags & DMGL_ANSI)
-	  && memcmp (optable[i].out, opname, len) == 0)
-	return optable[i].in;
-    }
-  return (0);
-}
-
 /* Add a routine to set the demangling style to be sure it is valid and
    allow for any demangler initialization that maybe necessary. */
 
@@ -841,22 +142,6 @@ cplus_demangle_name_to_style (const char *name)
    It is the caller's responsibility to free the string which
    is returned.
 
-   The OPTIONS arg may contain one or more of the following bits:
-
-   	DMGL_ANSI	ANSI qualifiers such as `const' and `void' are
-			included.
-	DMGL_PARAMS	Function parameters are included.
-
-   For example,
-
-   cplus_demangle ("foo__1Ai", DMGL_PARAMS)		=> "A::foo(int)"
-   cplus_demangle ("foo__1Ai", DMGL_PARAMS | DMGL_ANSI)	=> "A::foo(int)"
-   cplus_demangle ("foo__1Ai", 0)			=> "A::foo"
-
-   cplus_demangle ("foo__1Afe", DMGL_PARAMS)		=> "A::foo(float,...)"
-   cplus_demangle ("foo__1Afe", DMGL_PARAMS | DMGL_ANSI)=> "A::foo(float,...)"
-   cplus_demangle ("foo__1Afe", 0)			=> "A::foo"
-
    Note that any leading underscores, or other such characters prepended by
    the compilation system, are presumed to have already been stripped from
    MANGLED.  */
@@ -865,20 +150,14 @@ char *
 cplus_demangle (const char *mangled, int options)
 {
   char *ret;
-  struct work_stuff work[1];
 
   if (current_demangling_style == no_demangling)
     return xstrdup (mangled);
 
-  memset ((char *) work, 0, sizeof (work));
-  work->options = options;
-  if ((work->options & DMGL_STYLE_MASK) == 0)
-    work->options |= (int) current_demangling_style & DMGL_STYLE_MASK;
-
   /* The V3 ABI demangling is implemented elsewhere.  */
   if (GNU_V3_DEMANGLING || RUST_DEMANGLING || AUTO_DEMANGLING)
     {
-      ret = cplus_demangle_v3 (mangled, work->options);
+      ret = cplus_demangle_v3 (mangled, options);
       if (GNU_V3_DEMANGLING)
 	return ret;
 
@@ -916,8 +195,6 @@ cplus_demangle (const char *mangled, int options)
 	return ret;
     }
 
-  ret = internal_cplus_demangle (work, mangled);
-  squangle_mop_up (work);
   return (ret);
 }
 
@@ -1206,3861 +483,3 @@ ada_demangle (const char *mangled, int option ATTRIBUTE_UNUSED)
 
   return demangled;
 }
-
-/* This function performs most of what cplus_demangle use to do, but
-   to be able to demangle a name with a B, K or n code, we need to
-   have a longer term memory of what types have been seen. The original
-   now initializes and cleans up the squangle code info, while internal
-   calls go directly to this routine to avoid resetting that info. */
-
-static char *
-internal_cplus_demangle (struct work_stuff *work, const char *mangled)
-{
-
-  string decl;
-  int success = 0;
-  char *demangled = NULL;
-  int s1, s2, s3, s4;
-  s1 = work->constructor;
-  s2 = work->destructor;
-  s3 = work->static_type;
-  s4 = work->type_quals;
-  work->constructor = work->destructor = 0;
-  work->type_quals = TYPE_UNQUALIFIED;
-  work->dllimported = 0;
-
-  if ((mangled != NULL) && (*mangled != '\0'))
-    {
-      string_init (&decl);
-
-      /* First check to see if gnu style demangling is active and if the
-	 string to be demangled contains a CPLUS_MARKER.  If so, attempt to
-	 recognize one of the gnu special forms rather than looking for a
-	 standard prefix.  In particular, don't worry about whether there
-	 is a "__" string in the mangled string.  Consider "_$_5__foo" for
-	 example.  */
-
-      if ((AUTO_DEMANGLING || GNU_DEMANGLING))
-	{
-	  success = gnu_special (work, &mangled, &decl);
-	  if (!success)
-	    {
-	      delete_work_stuff (work);
-	      string_delete (&decl);
-	    }
-	}
-      if (!success)
-	{
-	  success = demangle_prefix (work, &mangled, &decl);
-	}
-      if (success && (*mangled != '\0'))
-	{
-	  success = demangle_signature (work, &mangled, &decl);
-	}
-      if (work->constructor == 2)
-        {
-          string_prepend (&decl, "global constructors keyed to ");
-          work->constructor = 0;
-        }
-      else if (work->destructor == 2)
-        {
-          string_prepend (&decl, "global destructors keyed to ");
-          work->destructor = 0;
-        }
-      else if (work->dllimported == 1)
-        {
-          string_prepend (&decl, "import stub for ");
-          work->dllimported = 0;
-        }
-      demangled = mop_up (work, &decl, success);
-    }
-  work->constructor = s1;
-  work->destructor = s2;
-  work->static_type = s3;
-  work->type_quals = s4;
-  return demangled;
-}
-
-
-/* Clear out and squangling related storage */
-static void
-squangle_mop_up (struct work_stuff *work)
-{
-  /* clean up the B and K type mangling types. */
-  forget_B_and_K_types (work);
-  if (work -> btypevec != NULL)
-    {
-      free ((char *) work -> btypevec);
-      work->btypevec = NULL;
-      work->bsize = 0;
-      work->numb = 0;
-    }
-  if (work -> ktypevec != NULL)
-    {
-      free ((char *) work -> ktypevec);
-      work->ktypevec = NULL;
-      work->ksize = 0;
-      work->numk = 0;
-    }
-}
-
-
-/* Copy the work state and storage.  */
-
-static void
-work_stuff_copy_to_from (struct work_stuff *to, struct work_stuff *from)
-{
-  int i;
-
-  delete_work_stuff (to);
-
-  /* Shallow-copy scalars.  */
-  memcpy (to, from, sizeof (*to));
-
-  /* Deep-copy dynamic storage.  */
-  if (from->typevec_size)
-    to->typevec = XNEWVEC (char *, from->typevec_size);
-
-  for (i = 0; i < from->ntypes; i++)
-    {
-      int len = strlen (from->typevec[i]) + 1;
-
-      to->typevec[i] = XNEWVEC (char, len);
-      memcpy (to->typevec[i], from->typevec[i], len);
-    }
-
-  if (from->ksize)
-    to->ktypevec = XNEWVEC (char *, from->ksize);
-
-  for (i = 0; i < from->numk; i++)
-    {
-      int len;
-
-      if (from->ktypevec[i] == NULL)
-	{
-	  to->ktypevec[i] = NULL;
-	  continue;
-	}
-
-      len = strlen (from->ktypevec[i]) + 1;
-      to->ktypevec[i] = XNEWVEC (char, len);
-      memcpy (to->ktypevec[i], from->ktypevec[i], len);
-    }
-
-  if (from->bsize)
-    to->btypevec = XNEWVEC (char *, from->bsize);
-
-  for (i = 0; i < from->numb; i++)
-    {
-      int len;
-
-      if (from->btypevec[i] == NULL)
-	{
-	  to->btypevec[i] = NULL;
-	  continue;
-	}
-
-      len = strlen (from->btypevec[i]) + 1;
-      to->btypevec[i] = XNEWVEC (char , len);
-      memcpy (to->btypevec[i], from->btypevec[i], len);
-    }
-
-  if (from->proctypevec)
-    to->proctypevec =
-      XDUPVEC (int, from->proctypevec, from->proctypevec_size);
-
-  if (from->ntmpl_args)
-    to->tmpl_argvec = XNEWVEC (char *, from->ntmpl_args);
-
-  for (i = 0; i < from->ntmpl_args; i++)
-    {
-      int len = strlen (from->tmpl_argvec[i]) + 1;
-
-      to->tmpl_argvec[i] = XNEWVEC (char, len);
-      memcpy (to->tmpl_argvec[i], from->tmpl_argvec[i], len);
-    }
-
-  if (from->previous_argument)
-    {
-      to->previous_argument = XNEW (string);
-      string_init (to->previous_argument);
-      string_appends (to->previous_argument, from->previous_argument);
-    }
-}
-
-
-/* Delete dynamic stuff in work_stuff that is not to be re-used.  */
-
-static void
-delete_non_B_K_work_stuff (struct work_stuff *work)
-{
-  /* Discard the remembered types, if any.  */
-
-  forget_types (work);
-  if (work->typevec != NULL)
-    {
-      free ((char *) work->typevec);
-      work->typevec = NULL;
-      work->typevec_size = 0;
-    }
-  if (work->proctypevec != NULL)
-    {
-      free (work->proctypevec);
-      work->proctypevec = NULL;
-      work->proctypevec_size = 0;
-    }
-  if (work->tmpl_argvec)
-    {
-      int i;
-
-      for (i = 0; i < work->ntmpl_args; i++)
-	free ((char*) work->tmpl_argvec[i]);
-
-      free ((char*) work->tmpl_argvec);
-      work->tmpl_argvec = NULL;
-      work->ntmpl_args = 0;
-    }
-  if (work->previous_argument)
-    {
-      string_delete (work->previous_argument);
-      free ((char*) work->previous_argument);
-      work->previous_argument = NULL;
-    }
-}
-
-
-/* Delete all dynamic storage in work_stuff.  */
-static void
-delete_work_stuff (struct work_stuff *work)
-{
-  delete_non_B_K_work_stuff (work);
-  squangle_mop_up (work);
-}
-
-
-/* Clear out any mangled storage */
-
-static char *
-mop_up (struct work_stuff *work, string *declp, int success)
-{
-  char *demangled = NULL;
-
-  delete_non_B_K_work_stuff (work);
-
-  /* If demangling was successful, ensure that the demangled string is null
-     terminated and return it.  Otherwise, free the demangling decl.  */
-
-  if (!success)
-    {
-      string_delete (declp);
-    }
-  else
-    {
-      string_appendn (declp, "", 1);
-      demangled = declp->b;
-    }
-  return (demangled);
-}
-
-/*
-
-LOCAL FUNCTION
-
-	demangle_signature -- demangle the signature part of a mangled name
-
-SYNOPSIS
-
-	static int
-	demangle_signature (struct work_stuff *work, const char **mangled,
-			    string *declp);
-
-DESCRIPTION
-
-	Consume and demangle the signature portion of the mangled name.
-
-	DECLP is the string where demangled output is being built.  At
-	entry it contains the demangled root name from the mangled name
-	prefix.  I.E. either a demangled operator name or the root function
-	name.  In some special cases, it may contain nothing.
-
-	*MANGLED points to the current unconsumed location in the mangled
-	name.  As tokens are consumed and demangling is performed, the
-	pointer is updated to continuously point at the next token to
-	be consumed.
-
-	Demangling GNU style mangled names is nasty because there is no
-	explicit token that marks the start of the outermost function
-	argument list.  */
-
-static int
-demangle_signature (struct work_stuff *work,
-                    const char **mangled, string *declp)
-{
-  int success = 1;
-  int func_done = 0;
-  int expect_func = 0;
-  int expect_return_type = 0;
-  const char *oldmangled = NULL;
-  string trawname;
-  string tname;
-
-  while (success && (**mangled != '\0'))
-    {
-      switch (**mangled)
-	{
-	case 'Q':
-	  oldmangled = *mangled;
-	  success = demangle_qualified (work, mangled, declp, 1, 0);
-	  if (success)
-	    remember_type (work, oldmangled, *mangled - oldmangled);
-	  if (AUTO_DEMANGLING || GNU_DEMANGLING)
-	    expect_func = 1;
-	  oldmangled = NULL;
-	  break;
-
-        case 'K':
-	  oldmangled = *mangled;
-	  success = demangle_qualified (work, mangled, declp, 1, 0);
-	  if (AUTO_DEMANGLING || GNU_DEMANGLING)
-	    {
-	      expect_func = 1;
-	    }
-	  oldmangled = NULL;
-	  break;
-
-	case 'S':
-	  /* Static member function */
-	  if (oldmangled == NULL)
-	    {
-	      oldmangled = *mangled;
-	    }
-	  (*mangled)++;
-	  work -> static_type = 1;
-	  break;
-
-	case 'C':
-	case 'V':
-	case 'u':
-	  work->type_quals |= code_for_qualifier (**mangled);
-
-	  /* a qualified member function */
-	  if (oldmangled == NULL)
-	    oldmangled = *mangled;
-	  (*mangled)++;
-	  break;
-
-	case 'L':
-	  /* Local class name follows after "Lnnn_" */
-	  if (HP_DEMANGLING)
-	    {
-	      while (**mangled && (**mangled != '_'))
-		(*mangled)++;
-	      if (!**mangled)
-		success = 0;
-	      else
-		(*mangled)++;
-	    }
-	  else
-	    success = 0;
-	  break;
-
-	case '0': case '1': case '2': case '3': case '4':
-	case '5': case '6': case '7': case '8': case '9':
-	  if (oldmangled == NULL)
-	    {
-	      oldmangled = *mangled;
-	    }
-          work->temp_start = -1; /* uppermost call to demangle_class */
-	  success = demangle_class (work, mangled, declp);
-	  if (success)
-	    {
-	      remember_type (work, oldmangled, *mangled - oldmangled);
-	    }
-	  if (AUTO_DEMANGLING || GNU_DEMANGLING || EDG_DEMANGLING)
-	    {
-              /* EDG and others will have the "F", so we let the loop cycle
-                 if we are looking at one. */
-              if (**mangled != 'F')
-                 expect_func = 1;
-	    }
-	  oldmangled = NULL;
-	  break;
-
-	case 'B':
-	  {
-	    string s;
-	    success = do_type (work, mangled, &s);
-	    if (success)
-	      {
-		string_append (&s, SCOPE_STRING (work));
-		string_prepends (declp, &s);
-		string_delete (&s);
-	      }
-	    oldmangled = NULL;
-	    expect_func = 1;
-	  }
-	  break;
-
-	case 'F':
-	  /* Function */
-	  /* ARM/HP style demangling includes a specific 'F' character after
-	     the class name.  For GNU style, it is just implied.  So we can
-	     safely just consume any 'F' at this point and be compatible
-	     with either style.  */
-
-	  oldmangled = NULL;
-	  func_done = 1;
-	  (*mangled)++;
-
-	  /* For lucid/ARM/HP style we have to forget any types we might
-	     have remembered up to this point, since they were not argument
-	     types.  GNU style considers all types seen as available for
-	     back references.  See comment in demangle_args() */
-
-	  if (LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING)
-	    {
-	      forget_types (work);
-	    }
-	  success = demangle_args (work, mangled, declp);
-	  /* After picking off the function args, we expect to either
-	     find the function return type (preceded by an '_') or the
-	     end of the string. */
-	  if (success && (AUTO_DEMANGLING || EDG_DEMANGLING) && **mangled == '_')
-	    {
-	      ++(*mangled);
-              /* At this level, we do not care about the return type. */
-              success = do_type (work, mangled, &tname);
-              string_delete (&tname);
-            }
-
-	  break;
-
-	case 't':
-	  /* G++ Template */
-	  string_init(&trawname);
-	  string_init(&tname);
-	  if (oldmangled == NULL)
-	    {
-	      oldmangled = *mangled;
-	    }
-	  success = demangle_template (work, mangled, &tname,
-				       &trawname, 1, 1);
-	  if (success)
-	    {
-	      remember_type (work, oldmangled, *mangled - oldmangled);
-	    }
-	  string_append (&tname, SCOPE_STRING (work));
-
-	  string_prepends(declp, &tname);
-	  if (work -> destructor & 1)
-	    {
-	      string_prepend (&trawname, "~");
-	      string_appends (declp, &trawname);
-	      work->destructor -= 1;
-	    }
-	  if ((work->constructor & 1) || (work->destructor & 1))
-	    {
-	      string_appends (declp, &trawname);
-	      work->constructor -= 1;
-	    }
-	  string_delete(&trawname);
-	  string_delete(&tname);
-	  oldmangled = NULL;
-	  expect_func = 1;
-	  break;
-
-	case '_':
-	  if ((AUTO_DEMANGLING || GNU_DEMANGLING) && expect_return_type)
-	    {
-	      /* Read the return type. */
-	      string return_type;
-
-	      (*mangled)++;
-	      success = do_type (work, mangled, &return_type);
-	      APPEND_BLANK (&return_type);
-
-	      string_prepends (declp, &return_type);
-	      string_delete (&return_type);
-	      break;
-	    }
-	  else
-	    /* At the outermost level, we cannot have a return type specified,
-	       so if we run into another '_' at this point we are dealing with
-	       a mangled name that is either bogus, or has been mangled by
-	       some algorithm we don't know how to deal with.  So just
-	       reject the entire demangling.  */
-            /* However, "_nnn" is an expected suffix for alternate entry point
-               numbered nnn for a function, with HP aCC, so skip over that
-               without reporting failure. pai/1997-09-04 */
-            if (HP_DEMANGLING)
-              {
-                (*mangled)++;
-                while (**mangled && ISDIGIT ((unsigned char)**mangled))
-                  (*mangled)++;
-              }
-            else
-	      success = 0;
-	  break;
-
-	case 'H':
-	  if (AUTO_DEMANGLING || GNU_DEMANGLING)
-	    {
-	      /* A G++ template function.  Read the template arguments. */
-	      success = demangle_template (work, mangled, declp, 0, 0,
-					   0);
-	      if (!(work->constructor & 1))
-		expect_return_type = 1;
-	      if (!**mangled)
-		success = 0;
-	      else
-	        (*mangled)++;
-	      break;
-	    }
-	  /* fall through */
-
-	default:
-	  if (AUTO_DEMANGLING || GNU_DEMANGLING)
-	    {
-	      /* Assume we have stumbled onto the first outermost function
-		 argument token, and start processing args.  */
-	      func_done = 1;
-	      success = demangle_args (work, mangled, declp);
-	    }
-	  else
-	    {
-	      /* Non-GNU demanglers use a specific token to mark the start
-		 of the outermost function argument tokens.  Typically 'F',
-		 for ARM/HP-demangling, for example.  So if we find something
-		 we are not prepared for, it must be an error.  */
-	      success = 0;
-	    }
-	  break;
-	}
-      /*
-	if (AUTO_DEMANGLING || GNU_DEMANGLING)
-	*/
-      {
-	if (success && expect_func)
-	  {
-	    func_done = 1;
-              if (LUCID_DEMANGLING || ARM_DEMANGLING || EDG_DEMANGLING)
-                {
-                  forget_types (work);
-                }
-	    success = demangle_args (work, mangled, declp);
-	    /* Since template include the mangling of their return types,
-	       we must set expect_func to 0 so that we don't try do
-	       demangle more arguments the next time we get here.  */
-	    expect_func = 0;
-	  }
-      }
-    }
-  if (success && !func_done)
-    {
-      if (AUTO_DEMANGLING || GNU_DEMANGLING)
-	{
-	  /* With GNU style demangling, bar__3foo is 'foo::bar(void)', and
-	     bar__3fooi is 'foo::bar(int)'.  We get here when we find the
-	     first case, and need to ensure that the '(void)' gets added to
-	     the current declp.  Note that with ARM/HP, the first case
-	     represents the name of a static data member 'foo::bar',
-	     which is in the current declp, so we leave it alone.  */
-	  success = demangle_args (work, mangled, declp);
-	}
-    }
-  if (success && PRINT_ARG_TYPES)
-    {
-      if (work->static_type)
-	string_append (declp, " static");
-      if (work->type_quals != TYPE_UNQUALIFIED)
-	{
-	  APPEND_BLANK (declp);
-	  string_append (declp, qualifier_string (work->type_quals));
-	}
-    }
-
-  return (success);
-}
-
-#if 0
-
-static int
-demangle_method_args (struct work_stuff *work, const char **mangled,
-                      string *declp)
-{
-  int success = 0;
-
-  if (work -> static_type)
-    {
-      string_append (declp, *mangled + 1);
-      *mangled += strlen (*mangled);
-      success = 1;
-    }
-  else
-    {
-      success = demangle_args (work, mangled, declp);
-    }
-  return (success);
-}
-
-#endif
-
-static int
-demangle_template_template_parm (struct work_stuff *work,
-                                 const char **mangled, string *tname)
-{
-  int i;
-  int r;
-  int need_comma = 0;
-  int success = 1;
-  string temp;
-
-  string_append (tname, "template <");
-  /* get size of template parameter list */
-  if (get_count (mangled, &r))
-    {
-      for (i = 0; i < r; i++)
-	{
-	  if (need_comma)
-	    {
-	      string_append (tname, ", ");
-	    }
-
-	    /* Z for type parameters */
-	    if (**mangled == 'Z')
-	      {
-		(*mangled)++;
-		string_append (tname, "class");
-	      }
-	      /* z for template parameters */
-	    else if (**mangled == 'z')
-	      {
-		(*mangled)++;
-		success =
-		  demangle_template_template_parm (work, mangled, tname);
-		if (!success)
-		  {
-		    break;
-		  }
-	      }
-	    else
-	      {
-		/* temp is initialized in do_type */
-		success = do_type (work, mangled, &temp);
-		if (success)
-		  {
-		    string_appends (tname, &temp);
-		  }
-		string_delete(&temp);
-		if (!success)
-		  {
-		    break;
-		  }
-	      }
-	  need_comma = 1;
-	}
-
-    }
-  if (tname->p[-1] == '>')
-    string_append (tname, " ");
-  string_append (tname, "> class");
-  return (success);
-}
-
-static int
-demangle_expression (struct work_stuff *work, const char **mangled,
-                     string *s, type_kind_t tk)
-{
-  int need_operator = 0;
-  int success;
-
-  success = 1;
-  string_appendn (s, "(", 1);
-  (*mangled)++;
-  while (success && **mangled != 'W' && **mangled != '\0')
-    {
-      if (need_operator)
-	{
-	  size_t i;
-	  size_t len;
-
-	  success = 0;
-
-	  len = strlen (*mangled);
-
-	  for (i = 0; i < ARRAY_SIZE (optable); ++i)
-	    {
-	      size_t l = strlen (optable[i].in);
-
-	      if (l <= len
-		  && memcmp (optable[i].in, *mangled, l) == 0)
-		{
-		  string_appendn (s, " ", 1);
-		  string_append (s, optable[i].out);
-		  string_appendn (s, " ", 1);
-		  success = 1;
-		  (*mangled) += l;
-		  break;
-		}
-	    }
-
-	  if (!success)
-	    break;
-	}
-      else
-	need_operator = 1;
-
-      success = demangle_template_value_parm (work, mangled, s, tk);
-    }
-
-  if (**mangled != 'W')
-    success = 0;
-  else
-    {
-      string_appendn (s, ")", 1);
-      (*mangled)++;
-    }
-
-  return success;
-}
-
-static int
-demangle_integral_value (struct work_stuff *work,
-                         const char **mangled, string *s)
-{
-  int success;
-
-  if (**mangled == 'E')
-    success = demangle_expression (work, mangled, s, tk_integral);
-  else if (**mangled == 'Q' || **mangled == 'K')
-    success = demangle_qualified (work, mangled, s, 0, 1);
-  else
-    {
-      int value;
-
-      /* By default, we let the number decide whether we shall consume an
-	 underscore.  */
-      int multidigit_without_leading_underscore = 0;
-      int leave_following_underscore = 0;
-
-      success = 0;
-
-      if (**mangled == '_')
-        {
-	  if (mangled[0][1] == 'm')
-	    {
-	      /* Since consume_count_with_underscores does not handle the
-		 `m'-prefix we must do it here, using consume_count and
-		 adjusting underscores: we have to consume the underscore
-		 matching the prepended one.  */
-	      multidigit_without_leading_underscore = 1;
-	      string_appendn (s, "-", 1);
-	      (*mangled) += 2;
-	    }
-	  else
-	    {
-	      /* Do not consume a following underscore;
-	         consume_count_with_underscores will consume what
-	         should be consumed.  */
-	      leave_following_underscore = 1;
-	    }
-	}
-      else
-	{
-	  /* Negative numbers are indicated with a leading `m'.  */
-	  if (**mangled == 'm')
-	  {
-	    string_appendn (s, "-", 1);
-	    (*mangled)++;
-	  }
-	  /* Since consume_count_with_underscores does not handle
-	     multi-digit numbers that do not start with an underscore,
-	     and this number can be an integer template parameter,
-	     we have to call consume_count. */
-	  multidigit_without_leading_underscore = 1;
-	  /* These multi-digit numbers never end on an underscore,
-	     so if there is one then don't eat it. */
-	  leave_following_underscore = 1;
-	}
-
-      /* We must call consume_count if we expect to remove a trailing
-	 underscore, since consume_count_with_underscores expects
-	 the leading underscore (that we consumed) if it is to handle
-	 multi-digit numbers.  */
-      if (multidigit_without_leading_underscore)
-	value = consume_count (mangled);
-      else
-	value = consume_count_with_underscores (mangled);
-
-      if (value != -1)
-	{
-	  char buf[INTBUF_SIZE];
-	  sprintf (buf, "%d", value);
-	  string_append (s, buf);
-
-	  /* Numbers not otherwise delimited, might have an underscore
-	     appended as a delimeter, which we should skip.
-
-	     ??? This used to always remove a following underscore, which
-	     is wrong.  If other (arbitrary) cases are followed by an
-	     underscore, we need to do something more radical.  */
-
-	  if ((value > 9 || multidigit_without_leading_underscore)
-	      && ! leave_following_underscore
-	      && **mangled == '_')
-	    (*mangled)++;
-
-	  /* All is well.  */
-	  success = 1;
-	}
-      }
-
-  return success;
-}
-
-/* Demangle the real value in MANGLED.  */
-
-static int
-demangle_real_value (struct work_stuff *work,
-                     const char **mangled, string *s)
-{
-  if (**mangled == 'E')
-    return demangle_expression (work, mangled, s, tk_real);
-
-  if (**mangled == 'm')
-    {
-      string_appendn (s, "-", 1);
-      (*mangled)++;
-    }
-  while (ISDIGIT ((unsigned char)**mangled))
-    {
-      string_appendn (s, *mangled, 1);
-      (*mangled)++;
-    }
-  if (**mangled == '.') /* fraction */
-    {
-      string_appendn (s, ".", 1);
-      (*mangled)++;
-      while (ISDIGIT ((unsigned char)**mangled))
-	{
-	  string_appendn (s, *mangled, 1);
-	  (*mangled)++;
-	}
-    }
-  if (**mangled == 'e') /* exponent */
-    {
-      string_appendn (s, "e", 1);
-      (*mangled)++;
-      while (ISDIGIT ((unsigned char)**mangled))
-	{
-	  string_appendn (s, *mangled, 1);
-	  (*mangled)++;
-	}
-    }
-
-  return 1;
-}
-
-static int
-demangle_template_value_parm (struct work_stuff *work, const char **mangled,
-                              string *s, type_kind_t tk)
-{
-  int success = 1;
-
-  if (**mangled == 'Y')
-    {
-      /* The next argument is a template parameter. */
-      int idx;
-
-      (*mangled)++;
-      idx = consume_count_with_underscores (mangled);
-      if (idx == -1
-	  || (work->tmpl_argvec && idx >= work->ntmpl_args)
-	  || consume_count_with_underscores (mangled) == -1)
-	return -1;
-      if (work->tmpl_argvec)
-	string_append (s, work->tmpl_argvec[idx]);
-      else
-	string_append_template_idx (s, idx);
-    }
-  else if (tk == tk_integral)
-    success = demangle_integral_value (work, mangled, s);
-  else if (tk == tk_char)
-    {
-      char tmp[2];
-      int val;
-      if (**mangled == 'm')
-	{
-	  string_appendn (s, "-", 1);
-	  (*mangled)++;
-	}
-      string_appendn (s, "'", 1);
-      val = consume_count(mangled);
-      if (val <= 0)
-	success = 0;
-      else
-	{
-	  tmp[0] = (char)val;
-	  tmp[1] = '\0';
-	  string_appendn (s, &tmp[0], 1);
-	  string_appendn (s, "'", 1);
-	}
-    }
-  else if (tk == tk_bool)
-    {
-      int val = consume_count (mangled);
-      if (val == 0)
-	string_appendn (s, "false", 5);
-      else if (val == 1)
-	string_appendn (s, "true", 4);
-      else
-	success = 0;
-    }
-  else if (tk == tk_real)
-    success = demangle_real_value (work, mangled, s);
-  else if (tk == tk_pointer || tk == tk_reference
-	   || tk == tk_rvalue_reference)
-    {
-      if (**mangled == 'Q')
-	success = demangle_qualified (work, mangled, s,
-				      /*isfuncname=*/0, 
-				      /*append=*/1);
-      else
-	{
-	  int symbol_len  = consume_count (mangled);
-	  if (symbol_len == -1
-	      || symbol_len > (long) strlen (*mangled))
-	    return -1;
-	  if (symbol_len == 0)
-	    string_appendn (s, "0", 1);
-	  else
-	    {
-	      char *p = XNEWVEC (char, symbol_len + 1), *q;
-	      strncpy (p, *mangled, symbol_len);
-	      p [symbol_len] = '\0';
-	      /* We use cplus_demangle here, rather than
-		 internal_cplus_demangle, because the name of the entity
-		 mangled here does not make use of any of the squangling
-		 or type-code information we have built up thus far; it is
-		 mangled independently.  */
-	      q = cplus_demangle (p, work->options);
-	      if (tk == tk_pointer)
-		string_appendn (s, "&", 1);
-	      /* FIXME: Pointer-to-member constants should get a
-		 qualifying class name here.  */
-	      if (q)
-		{
-		  string_append (s, q);
-		  free (q);
-		}
-	      else
-		string_append (s, p);
-	      free (p);
-	    }
-	  *mangled += symbol_len;
-	}
-    }
-
-  return success;
-}
-
-/* Demangle the template name in MANGLED.  The full name of the
-   template (e.g., S<int>) is placed in TNAME.  The name without the
-   template parameters (e.g. S) is placed in TRAWNAME if TRAWNAME is
-   non-NULL.  If IS_TYPE is nonzero, this template is a type template,
-   not a function template.  If both IS_TYPE and REMEMBER are nonzero,
-   the template is remembered in the list of back-referenceable
-   types.  */
-
-static int
-demangle_template (struct work_stuff *work, const char **mangled,
-                   string *tname, string *trawname,
-                   int is_type, int remember)
-{
-  int i;
-  int r;
-  int need_comma = 0;
-  int success = 0;
-  int is_java_array = 0;
-  string temp;
-
-  (*mangled)++;
-  if (is_type)
-    {
-      /* get template name */
-      if (**mangled == 'z')
-	{
-	  int idx;
-	  (*mangled)++;
-	  if (**mangled == '\0')
-	    return (0);
-	  (*mangled)++;
-
-	  idx = consume_count_with_underscores (mangled);
-	  if (idx == -1
-	      || (work->tmpl_argvec && idx >= work->ntmpl_args)
-	      || consume_count_with_underscores (mangled) == -1)
-	    return (0);
-
-	  if (work->tmpl_argvec)
-	    {
-	      string_append (tname, work->tmpl_argvec[idx]);
-	      if (trawname)
-		string_append (trawname, work->tmpl_argvec[idx]);
-	    }
-	  else
-	    {
-	      string_append_template_idx (tname, idx);
-	      if (trawname)
-		string_append_template_idx (trawname, idx);
-	    }
-	}
-      else
-	{
-	  if ((r = consume_count (mangled)) <= 0
-	      || (int) strlen (*mangled) < r)
-	    {
-	      return (0);
-	    }
-	  is_java_array = (work -> options & DMGL_JAVA)
-	    && strncmp (*mangled, "JArray1Z", 8) == 0;
-	  if (! is_java_array)
-	    {
-	      string_appendn (tname, *mangled, r);
-	    }
-	  if (trawname)
-	    string_appendn (trawname, *mangled, r);
-	  *mangled += r;
-	}
-    }
-  if (!is_java_array)
-    string_append (tname, "<");
-  /* get size of template parameter list */
-  if (!get_count (mangled, &r))
-    {
-      return (0);
-    }
-  if (!is_type)
-    {
-      /* Create an array for saving the template argument values. */
-      work->tmpl_argvec = XNEWVEC (char *, r);
-      work->ntmpl_args = r;
-      for (i = 0; i < r; i++)
-	work->tmpl_argvec[i] = 0;
-    }
-  for (i = 0; i < r; i++)
-    {
-      if (need_comma)
-	{
-	  string_append (tname, ", ");
-	}
-      /* Z for type parameters */
-      if (**mangled == 'Z')
-	{
-	  (*mangled)++;
-	  /* temp is initialized in do_type */
-	  success = do_type (work, mangled, &temp);
-	  if (success)
-	    {
-	      string_appends (tname, &temp);
-
-	      if (!is_type)
-		{
-		  /* Save the template argument. */
-		  int len = temp.p - temp.b;
-		  work->tmpl_argvec[i] = XNEWVEC (char, len + 1);
-		  memcpy (work->tmpl_argvec[i], temp.b, len);
-		  work->tmpl_argvec[i][len] = '\0';
-		}
-	    }
-	  string_delete(&temp);
-	  if (!success)
-	    {
-	      break;
-	    }
-	}
-      /* z for template parameters */
-      else if (**mangled == 'z')
-	{
-	  int r2;
-	  (*mangled)++;
-	  success = demangle_template_template_parm (work, mangled, tname);
-
-	  if (success
-	      && (r2 = consume_count (mangled)) > 0
-	      && (int) strlen (*mangled) >= r2)
-	    {
-	      string_append (tname, " ");
-	      string_appendn (tname, *mangled, r2);
-	      if (!is_type)
-		{
-		  /* Save the template argument. */
-		  int len = r2;
-		  work->tmpl_argvec[i] = XNEWVEC (char, len + 1);
-		  memcpy (work->tmpl_argvec[i], *mangled, len);
-		  work->tmpl_argvec[i][len] = '\0';
-		}
-	      *mangled += r2;
-	    }
-	  if (!success)
-	    {
-	      break;
-	    }
-	}
-      else
-	{
-	  string  param;
-	  string* s;
-
-	  /* otherwise, value parameter */
-
-	  /* temp is initialized in do_type */
-	  success = do_type (work, mangled, &temp);
-	  string_delete(&temp);
-	  if (!success)
-	    break;
-
-	  if (!is_type)
-	    {
-	      s = &param;
-	      string_init (s);
-	    }
-	  else
-	    s = tname;
-
-	  success = demangle_template_value_parm (work, mangled, s,
-						  (type_kind_t) success);
-
-	  if (!success)
-	    {
-	      if (!is_type)
-		string_delete (s);
-	      success = 0;
-	      break;
-	    }
-
-	  if (!is_type)
-	    {
-	      int len = s->p - s->b;
-	      work->tmpl_argvec[i] = XNEWVEC (char, len + 1);
-	      memcpy (work->tmpl_argvec[i], s->b, len);
-	      work->tmpl_argvec[i][len] = '\0';
-
-	      string_appends (tname, s);
-	      string_delete (s);
-	    }
-	}
-      need_comma = 1;
-    }
-  if (is_java_array)
-    {
-      string_append (tname, "[]");
-    }
-  else
-    {
-      if (tname->p[-1] == '>')
-	string_append (tname, " ");
-      string_append (tname, ">");
-    }
-
-  if (is_type && remember)
-    {
-      const int bindex = register_Btype (work);
-      remember_Btype (work, tname->b, LEN_STRING (tname), bindex);
-    }
-
-  /*
-    if (work -> static_type)
-    {
-    string_append (declp, *mangled + 1);
-    *mangled += strlen (*mangled);
-    success = 1;
-    }
-    else
-    {
-    success = demangle_args (work, mangled, declp);
-    }
-    }
-    */
-  return (success);
-}
-
-static int
-arm_pt (struct work_stuff *work, const char *mangled,
-        int n, const char **anchor, const char **args)
-{
-  /* Check if ARM template with "__pt__" in it ("parameterized type") */
-  /* Allow HP also here, because HP's cfront compiler follows ARM to some extent */
-  if ((ARM_DEMANGLING || HP_DEMANGLING) && (*anchor = strstr (mangled, "__pt__")))
-    {
-      int len;
-      *args = *anchor + 6;
-      len = consume_count (args);
-      if (len == -1)
-	return 0;
-      if (*args + len == mangled + n && **args == '_')
-	{
-	  ++*args;
-	  return 1;
-	}
-    }
-  if (AUTO_DEMANGLING || EDG_DEMANGLING)
-    {
-      if ((*anchor = strstr (mangled, "__tm__"))
-          || (*anchor = strstr (mangled, "__ps__"))
-          || (*anchor = strstr (mangled, "__pt__")))
-        {
-          int len;
-          *args = *anchor + 6;
-          len = consume_count (args);
-	  if (len == -1)
-	    return 0;
-          if (*args + len == mangled + n && **args == '_')
-            {
-              ++*args;
-              return 1;
-            }
-        }
-      else if ((*anchor = strstr (mangled, "__S")))
-        {
- 	  int len;
- 	  *args = *anchor + 3;
- 	  len = consume_count (args);
-	  if (len == -1)
-	    return 0;
- 	  if (*args + len == mangled + n && **args == '_')
-            {
-              ++*args;
- 	      return 1;
-            }
-        }
-    }
-
-  return 0;
-}
-
-static void
-demangle_arm_hp_template (struct work_stuff *work, const char **mangled,
-                          int n, string *declp)
-{
-  const char *p;
-  const char *args;
-  const char *e = *mangled + n;
-  string arg;
-
-  /* Check for HP aCC template spec: classXt1t2 where t1, t2 are
-     template args */
-  if (HP_DEMANGLING && ((*mangled)[n] == 'X'))
-    {
-      char *start_spec_args = NULL;
-      int hold_options;
-
-      /* First check for and omit template specialization pseudo-arguments,
-         such as in "Spec<#1,#1.*>" */
-      start_spec_args = strchr (*mangled, '<');
-      if (start_spec_args && (start_spec_args - *mangled < n))
-        string_appendn (declp, *mangled, start_spec_args - *mangled);
-      else
-        string_appendn (declp, *mangled, n);
-      (*mangled) += n + 1;
-      string_init (&arg);
-      if (work->temp_start == -1) /* non-recursive call */
-        work->temp_start = declp->p - declp->b;
-
-      /* We want to unconditionally demangle parameter types in
-	 template parameters.  */
-      hold_options = work->options;
-      work->options |= DMGL_PARAMS;
-
-      string_append (declp, "<");
-      while (1)
-        {
-          string_delete (&arg);
-          switch (**mangled)
-            {
-              case 'T':
-                /* 'T' signals a type parameter */
-                (*mangled)++;
-                if (!do_type (work, mangled, &arg))
-                  goto hpacc_template_args_done;
-                break;
-
-              case 'U':
-              case 'S':
-                /* 'U' or 'S' signals an integral value */
-                if (!do_hpacc_template_const_value (work, mangled, &arg))
-                  goto hpacc_template_args_done;
-                break;
-
-              case 'A':
-                /* 'A' signals a named constant expression (literal) */
-                if (!do_hpacc_template_literal (work, mangled, &arg))
-                  goto hpacc_template_args_done;
-                break;
-
-              default:
-                /* Today, 1997-09-03, we have only the above types
-                   of template parameters */
-                /* FIXME: maybe this should fail and return null */
-                goto hpacc_template_args_done;
-            }
-          string_appends (declp, &arg);
-         /* Check if we're at the end of template args.
-             0 if at end of static member of template class,
-             _ if done with template args for a function */
-          if ((**mangled == '\000') || (**mangled == '_'))
-            break;
-          else
-            string_append (declp, ",");
-        }
-    hpacc_template_args_done:
-      string_append (declp, ">");
-      string_delete (&arg);
-      if (**mangled == '_')
-        (*mangled)++;
-      work->options = hold_options;
-      return;
-    }
-  /* ARM template? (Also handles HP cfront extensions) */
-  else if (arm_pt (work, *mangled, n, &p, &args))
-    {
-      int hold_options;
-      string type_str;
-
-      string_init (&arg);
-      string_appendn (declp, *mangled, p - *mangled);
-      if (work->temp_start == -1)  /* non-recursive call */
-	work->temp_start = declp->p - declp->b;
-
-      /* We want to unconditionally demangle parameter types in
-	 template parameters.  */
-      hold_options = work->options;
-      work->options |= DMGL_PARAMS;
-
-      string_append (declp, "<");
-      /* should do error checking here */
-      while (args < e) {
-	string_delete (&arg);
-
-	/* Check for type or literal here */
-	switch (*args)
-	  {
-	    /* HP cfront extensions to ARM for template args */
-	    /* spec: Xt1Lv1 where t1 is a type, v1 is a literal value */
-	    /* FIXME: We handle only numeric literals for HP cfront */
-          case 'X':
-            /* A typed constant value follows */
-            args++;
-            if (!do_type (work, &args, &type_str))
-	      goto cfront_template_args_done;
-            string_append (&arg, "(");
-            string_appends (&arg, &type_str);
-            string_delete (&type_str);
-            string_append (&arg, ")");
-            if (*args != 'L')
-              goto cfront_template_args_done;
-            args++;
-            /* Now snarf a literal value following 'L' */
-            if (!snarf_numeric_literal (&args, &arg))
-	      goto cfront_template_args_done;
-            break;
-
-          case 'L':
-            /* Snarf a literal following 'L' */
-            args++;
-            if (!snarf_numeric_literal (&args, &arg))
-	      goto cfront_template_args_done;
-            break;
-          default:
-            /* Not handling other HP cfront stuff */
-            {
-              const char* old_args = args;
-              if (!do_type (work, &args, &arg))
-                goto cfront_template_args_done;
-
-              /* Fail if we didn't make any progress: prevent infinite loop. */
-              if (args == old_args)
-		{
-		  work->options = hold_options;
-		  return;
-		}
-            }
-	  }
-	string_appends (declp, &arg);
-	string_append (declp, ",");
-      }
-    cfront_template_args_done:
-      string_delete (&arg);
-      if (args >= e)
-	--declp->p; /* remove extra comma */
-      string_append (declp, ">");
-      work->options = hold_options;
-    }
-  else if (n>10 && strncmp (*mangled, "_GLOBAL_", 8) == 0
-	   && (*mangled)[9] == 'N'
-	   && (*mangled)[8] == (*mangled)[10]
-	   && strchr (cplus_markers, (*mangled)[8]))
-    {
-      /* A member of the anonymous namespace.  */
-      string_append (declp, "{anonymous}");
-    }
-  else
-    {
-      if (work->temp_start == -1) /* non-recursive call only */
-	work->temp_start = 0;     /* disable in recursive calls */
-      string_appendn (declp, *mangled, n);
-    }
-  *mangled += n;
-}
-
-/* Extract a class name, possibly a template with arguments, from the
-   mangled string; qualifiers, local class indicators, etc. have
-   already been dealt with */
-
-static int
-demangle_class_name (struct work_stuff *work, const char **mangled,
-                     string *declp)
-{
-  int n;
-  int success = 0;
-
-  n = consume_count (mangled);
-  if (n == -1)
-    return 0;
-  if ((int) strlen (*mangled) >= n)
-    {
-      demangle_arm_hp_template (work, mangled, n, declp);
-      success = 1;
-    }
-
-  return (success);
-}
-
-/*
-
-LOCAL FUNCTION
-
-	demangle_class -- demangle a mangled class sequence
-
-SYNOPSIS
-
-	static int
-	demangle_class (struct work_stuff *work, const char **mangled,
-			strint *declp)
-
-DESCRIPTION
-
-	DECLP points to the buffer into which demangling is being done.
-
-	*MANGLED points to the current token to be demangled.  On input,
-	it points to a mangled class (I.E. "3foo", "13verylongclass", etc.)
-	On exit, it points to the next token after the mangled class on
-	success, or the first unconsumed token on failure.
-
-	If the CONSTRUCTOR or DESTRUCTOR flags are set in WORK, then
-	we are demangling a constructor or destructor.  In this case
-	we prepend "class::class" or "class::~class" to DECLP.
-
-	Otherwise, we prepend "class::" to the current DECLP.
-
-	Reset the constructor/destructor flags once they have been
-	"consumed".  This allows demangle_class to be called later during
-	the same demangling, to do normal class demangling.
-
-	Returns 1 if demangling is successful, 0 otherwise.
-
-*/
-
-static int
-demangle_class (struct work_stuff *work, const char **mangled, string *declp)
-{
-  int success = 0;
-  int btype;
-  string class_name;
-  char *save_class_name_end = 0;
-
-  string_init (&class_name);
-  btype = register_Btype (work);
-  if (demangle_class_name (work, mangled, &class_name))
-    {
-      save_class_name_end = class_name.p;
-      if ((work->constructor & 1) || (work->destructor & 1))
-	{
-          /* adjust so we don't include template args */
-          if (work->temp_start && (work->temp_start != -1))
-            {
-              class_name.p = class_name.b + work->temp_start;
-            }
-	  string_prepends (declp, &class_name);
-	  if (work -> destructor & 1)
-	    {
-	      string_prepend (declp, "~");
-              work -> destructor -= 1;
-	    }
-	  else
-	    {
-	      work -> constructor -= 1;
-	    }
-	}
-      class_name.p = save_class_name_end;
-      remember_Ktype (work, class_name.b, LEN_STRING(&class_name));
-      remember_Btype (work, class_name.b, LEN_STRING(&class_name), btype);
-      string_prepend (declp, SCOPE_STRING (work));
-      string_prepends (declp, &class_name);
-      success = 1;
-    }
-  string_delete (&class_name);
-  return (success);
-}
-
-
-/* Called when there's a "__" in the mangled name, with `scan' pointing to
-   the rightmost guess.
-
-   Find the correct "__"-sequence where the function name ends and the
-   signature starts, which is ambiguous with GNU mangling.
-   Call demangle_signature here, so we can make sure we found the right
-   one; *mangled will be consumed so caller will not make further calls to
-   demangle_signature.  */
-
-static int
-iterate_demangle_function (struct work_stuff *work, const char **mangled,
-                           string *declp, const char *scan)
-{
-  const char *mangle_init = *mangled;
-  int success = 0;
-  string decl_init;
-  struct work_stuff work_init;
-
-  if (*(scan + 2) == '\0')
-    return 0;
-
-  /* Do not iterate for some demangling modes, or if there's only one
-     "__"-sequence.  This is the normal case.  */
-  if (ARM_DEMANGLING || LUCID_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING
-      || strstr (scan + 2, "__") == NULL)
-    return demangle_function_name (work, mangled, declp, scan);
-
-  /* Save state so we can restart if the guess at the correct "__" was
-     wrong.  */
-  string_init (&decl_init);
-  string_appends (&decl_init, declp);
-  memset (&work_init, 0, sizeof work_init);
-  work_stuff_copy_to_from (&work_init, work);
-
-  /* Iterate over occurrences of __, allowing names and types to have a
-     "__" sequence in them.  We must start with the first (not the last)
-     occurrence, since "__" most often occur between independent mangled
-     parts, hence starting at the last occurence inside a signature
-     might get us a "successful" demangling of the signature.  */
-
-  while (scan[2])
-    {
-      if (demangle_function_name (work, mangled, declp, scan))
-	{
-	  success = demangle_signature (work, mangled, declp);
-	  if (success)
-	    break;
-	}
-
-      /* Reset demangle state for the next round.  */
-      *mangled = mangle_init;
-      string_clear (declp);
-      string_appends (declp, &decl_init);
-      work_stuff_copy_to_from (work, &work_init);
-
-      /* Leave this underscore-sequence.  */
-      scan += 2;
-
-      /* Scan for the next "__" sequence.  */
-      while (*scan && (scan[0] != '_' || scan[1] != '_'))
-	scan++;
-
-      /* Move to last "__" in this sequence.  */
-      while (*scan && *scan == '_')
-	scan++;
-      scan -= 2;
-    }
-
-  /* Delete saved state.  */
-  delete_work_stuff (&work_init);
-  string_delete (&decl_init);
-
-  return success;
-}
-
-/*
-
-LOCAL FUNCTION
-
-	demangle_prefix -- consume the mangled name prefix and find signature
-
-SYNOPSIS
-
-	static int
-	demangle_prefix (struct work_stuff *work, const char **mangled,
-			 string *declp);
-
-DESCRIPTION
-
-	Consume and demangle the prefix of the mangled name.
-	While processing the function name root, arrange to call
-	demangle_signature if the root is ambiguous.
-
-	DECLP points to the string buffer into which demangled output is
-	placed.  On entry, the buffer is empty.  On exit it contains
-	the root function name, the demangled operator name, or in some
-	special cases either nothing or the completely demangled result.
-
-	MANGLED points to the current pointer into the mangled name.  As each
-	token of the mangled name is consumed, it is updated.  Upon entry
-	the current mangled name pointer points to the first character of
-	the mangled name.  Upon exit, it should point to the first character
-	of the signature if demangling was successful, or to the first
-	unconsumed character if demangling of the prefix was unsuccessful.
-
-	Returns 1 on success, 0 otherwise.
- */
-
-static int
-demangle_prefix (struct work_stuff *work, const char **mangled,
-                 string *declp)
-{
-  int success = 1;
-  const char *scan;
-  int i;
-
-  if (strlen(*mangled) > 6
-      && (strncmp(*mangled, "_imp__", 6) == 0
-          || strncmp(*mangled, "__imp_", 6) == 0))
-    {
-      /* it's a symbol imported from a PE dynamic library. Check for both
-         new style prefix _imp__ and legacy __imp_ used by older versions
-	 of dlltool. */
-      (*mangled) += 6;
-      work->dllimported = 1;
-    }
-  else if (strlen(*mangled) >= 11 && strncmp(*mangled, "_GLOBAL_", 8) == 0)
-    {
-      char *marker = strchr (cplus_markers, (*mangled)[8]);
-      if (marker != NULL && *marker == (*mangled)[10])
-	{
-	  if ((*mangled)[9] == 'D')
-	    {
-	      /* it's a GNU global destructor to be executed at program exit */
-	      (*mangled) += 11;
-	      work->destructor = 2;
-	      if (gnu_special (work, mangled, declp))
-		return success;
-	    }
-	  else if ((*mangled)[9] == 'I')
-	    {
-	      /* it's a GNU global constructor to be executed at program init */
-	      (*mangled) += 11;
-	      work->constructor = 2;
-	      if (gnu_special (work, mangled, declp))
-		return success;
-	    }
-	}
-    }
-  else if ((ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING) && strncmp(*mangled, "__std__", 7) == 0)
-    {
-      /* it's a ARM global destructor to be executed at program exit */
-      (*mangled) += 7;
-      work->destructor = 2;
-    }
-  else if ((ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING) && strncmp(*mangled, "__sti__", 7) == 0)
-    {
-      /* it's a ARM global constructor to be executed at program initial */
-      (*mangled) += 7;
-      work->constructor = 2;
-    }
-
-  /*  This block of code is a reduction in strength time optimization
-      of:
-      scan = strstr (*mangled, "__"); */
-
-  {
-    scan = *mangled;
-
-    do {
-      scan = strchr (scan, '_');
-    } while (scan != NULL && *++scan != '_');
-
-    if (scan != NULL) --scan;
-  }
-
-  if (scan != NULL)
-    {
-      /* We found a sequence of two or more '_', ensure that we start at
-	 the last pair in the sequence.  */
-      i = strspn (scan, "_");
-      if (i > 2)
-	{
-	  scan += (i - 2);
-	}
-    }
-
-  if (scan == NULL)
-    {
-      success = 0;
-    }
-  else if (work -> static_type)
-    {
-      if (!ISDIGIT ((unsigned char)scan[0]) && (scan[0] != 't'))
-	{
-	  success = 0;
-	}
-    }
-  else if ((scan == *mangled)
-	   && (ISDIGIT ((unsigned char)scan[2]) || (scan[2] == 'Q')
-	       || (scan[2] == 't') || (scan[2] == 'K') || (scan[2] == 'H')))
-    {
-      /* The ARM says nothing about the mangling of local variables.
-	 But cfront mangles local variables by prepending __<nesting_level>
-	 to them. As an extension to ARM demangling we handle this case.  */
-      if ((LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING)
-	  && ISDIGIT ((unsigned char)scan[2]))
-	{
-	  *mangled = scan + 2;
-	  consume_count (mangled);
-	  string_append (declp, *mangled);
-	  *mangled += strlen (*mangled);
-	  success = 1;
-	}
-      else
-	{
-	  /* A GNU style constructor starts with __[0-9Qt].  But cfront uses
-	     names like __Q2_3foo3bar for nested type names.  So don't accept
-	     this style of constructor for cfront demangling.  A GNU
-	     style member-template constructor starts with 'H'. */
-	  if (!(LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING))
-	    work -> constructor += 1;
-	  *mangled = scan + 2;
-	}
-    }
-  else if (ARM_DEMANGLING && scan[2] == 'p' && scan[3] == 't')
-    {
-      /* Cfront-style parameterized type.  Handled later as a signature. */
-      success = 1;
-
-      /* ARM template? */
-      demangle_arm_hp_template (work, mangled, strlen (*mangled), declp);
-    }
-  else if (EDG_DEMANGLING && ((scan[2] == 't' && scan[3] == 'm')
-                              || (scan[2] == 'p' && scan[3] == 's')
-                              || (scan[2] == 'p' && scan[3] == 't')))
-    {
-      /* EDG-style parameterized type.  Handled later as a signature. */
-      success = 1;
-
-      /* EDG template? */
-      demangle_arm_hp_template (work, mangled, strlen (*mangled), declp);
-    }
-  else if ((scan == *mangled) && !ISDIGIT ((unsigned char)scan[2])
-	   && (scan[2] != 't'))
-    {
-      /* Mangled name starts with "__".  Skip over any leading '_' characters,
-	 then find the next "__" that separates the prefix from the signature.
-	 */
-      if (!(ARM_DEMANGLING || LUCID_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING)
-	  || (arm_special (mangled, declp) == 0))
-	{
-	  while (*scan == '_')
-	    {
-	      scan++;
-	    }
-	  if ((scan = strstr (scan, "__")) == NULL || (*(scan + 2) == '\0'))
-	    {
-	      /* No separator (I.E. "__not_mangled"), or empty signature
-		 (I.E. "__not_mangled_either__") */
-	      success = 0;
-	    }
-	  else
-	    return iterate_demangle_function (work, mangled, declp, scan);
-	}
-    }
-  else if (*(scan + 2) != '\0')
-    {
-      /* Mangled name does not start with "__" but does have one somewhere
-	 in there with non empty stuff after it.  Looks like a global
-	 function name.  Iterate over all "__":s until the right
-	 one is found.  */
-      return iterate_demangle_function (work, mangled, declp, scan);
-    }
-  else
-    {
-      /* Doesn't look like a mangled name */
-      success = 0;
-    }
-
-  if (!success && (work->constructor == 2 || work->destructor == 2))
-    {
-      string_append (declp, *mangled);
-      *mangled += strlen (*mangled);
-      success = 1;
-    }
-  return (success);
-}
-
-/*
-
-LOCAL FUNCTION
-
-	gnu_special -- special handling of gnu mangled strings
-
-SYNOPSIS
-
-	static int
-	gnu_special (struct work_stuff *work, const char **mangled,
-		     string *declp);
-
-
-DESCRIPTION
-
-	Process some special GNU style mangling forms that don't fit
-	the normal pattern.  For example:
-
-		_$_3foo		(destructor for class foo)
-		_vt$foo		(foo virtual table)
-		_vt$foo$bar	(foo::bar virtual table)
-		__vt_foo	(foo virtual table, new style with thunks)
-		_3foo$varname	(static data member)
-		_Q22rs2tu$vw	(static data member)
-		__t6vector1Zii	(constructor with template)
-		__thunk_4__$_7ostream (virtual function thunk)
- */
-
-static int
-gnu_special (struct work_stuff *work, const char **mangled, string *declp)
-{
-  int n;
-  int success = 1;
-  const char *p;
-
-  if ((*mangled)[0] == '_' && (*mangled)[1] != '\0'
-      && strchr (cplus_markers, (*mangled)[1]) != NULL
-      && (*mangled)[2] == '_')
-    {
-      /* Found a GNU style destructor, get past "_<CPLUS_MARKER>_" */
-      (*mangled) += 3;
-      work -> destructor += 1;
-    }
-  else if ((*mangled)[0] == '_'
-	   && (((*mangled)[1] == '_'
-		&& (*mangled)[2] == 'v'
-		&& (*mangled)[3] == 't'
-		&& (*mangled)[4] == '_')
-	       || ((*mangled)[1] == 'v'
-		   && (*mangled)[2] == 't' && (*mangled)[3] != '\0'
-		   && strchr (cplus_markers, (*mangled)[3]) != NULL)))
-    {
-      /* Found a GNU style virtual table, get past "_vt<CPLUS_MARKER>"
-         and create the decl.  Note that we consume the entire mangled
-	 input string, which means that demangle_signature has no work
-	 to do.  */
-      if ((*mangled)[2] == 'v')
-	(*mangled) += 5; /* New style, with thunks: "__vt_" */
-      else
-	(*mangled) += 4; /* Old style, no thunks: "_vt<CPLUS_MARKER>" */
-      while (**mangled != '\0')
-	{
-	  switch (**mangled)
-	    {
-	    case 'Q':
-	    case 'K':
-	      success = demangle_qualified (work, mangled, declp, 0, 1);
-	      break;
-	    case 't':
-	      success = demangle_template (work, mangled, declp, 0, 1,
-					   1);
-	      break;
-	    default:
-	      if (ISDIGIT((unsigned char)*mangled[0]))
-		{
-		  n = consume_count(mangled);
-		  /* We may be seeing a too-large size, or else a
-		     ".<digits>" indicating a static local symbol.  In
-		     any case, declare victory and move on; *don't* try
-		     to use n to allocate.  */
-		  if (n > (int) strlen (*mangled))
-		    {
-		      success = 1;
-		      break;
-		    }
-		  else if (n == -1)
-		    {
-		      success = 0;
-		      break;
-		    }
-		}
-	      else
-		{
-		  n = strcspn (*mangled, cplus_markers);
-		}
-	      string_appendn (declp, *mangled, n);
-	      (*mangled) += n;
-	    }
-
-	  p = strpbrk (*mangled, cplus_markers);
-	  if (success && ((p == NULL) || (p == *mangled)))
-	    {
-	      if (p != NULL)
-		{
-		  string_append (declp, SCOPE_STRING (work));
-		  (*mangled)++;
-		}
-	    }
-	  else
-	    {
-	      success = 0;
-	      break;
-	    }
-	}
-      if (success)
-	string_append (declp, " virtual table");
-    }
-  else if ((*mangled)[0] == '_'
-	   && (strchr("0123456789Qt", (*mangled)[1]) != NULL)
-	   && (p = strpbrk (*mangled, cplus_markers)) != NULL)
-    {
-      /* static data member, "_3foo$varname" for example */
-      (*mangled)++;
-      switch (**mangled)
-	{
-	case 'Q':
-	case 'K':
-	  success = demangle_qualified (work, mangled, declp, 0, 1);
-	  break;
-	case 't':
-	  success = demangle_template (work, mangled, declp, 0, 1, 1);
-	  break;
-	default:
-	  n = consume_count (mangled);
-	  if (n < 0 || n > (long) strlen (*mangled))
-	    {
-	      success = 0;
-	      break;
-	    }
-
-	  if (n > 10 && strncmp (*mangled, "_GLOBAL_", 8) == 0
-	      && (*mangled)[9] == 'N'
-	      && (*mangled)[8] == (*mangled)[10]
-	      && strchr (cplus_markers, (*mangled)[8]))
-	    {
-	      /* A member of the anonymous namespace.  There's information
-		 about what identifier or filename it was keyed to, but
-		 it's just there to make the mangled name unique; we just
-		 step over it.  */
-	      string_append (declp, "{anonymous}");
-	      (*mangled) += n;
-
-	      /* Now p points to the marker before the N, so we need to
-		 update it to the first marker after what we consumed.  */
-	      p = strpbrk (*mangled, cplus_markers);
-	      break;
-	    }
-
-	  string_appendn (declp, *mangled, n);
-	  (*mangled) += n;
-	}
-      if (success && (p == *mangled))
-	{
-	  /* Consumed everything up to the cplus_marker, append the
-	     variable name.  */
-	  (*mangled)++;
-	  string_append (declp, SCOPE_STRING (work));
-	  n = strlen (*mangled);
-	  string_appendn (declp, *mangled, n);
-	  (*mangled) += n;
-	}
-      else
-	{
-	  success = 0;
-	}
-    }
-  else if (strncmp (*mangled, "__thunk_", 8) == 0)
-    {
-      int delta;
-
-      (*mangled) += 8;
-      delta = consume_count (mangled);
-      if (delta == -1)
-	success = 0;
-      else if (**mangled != '_')
-        success = 0;
-      else
-	{
-	  char *method = internal_cplus_demangle (work, ++*mangled);
-
-	  if (method)
-	    {
-	      char buf[50];
-	      sprintf (buf, "virtual function thunk (delta:%d) for ", -delta);
-	      string_append (declp, buf);
-	      string_append (declp, method);
-	      free (method);
-	      n = strlen (*mangled);
-	      (*mangled) += n;
-	    }
-	  else
-	    {
-	      success = 0;
-	    }
-	}
-    }
-  else if (strncmp (*mangled, "__t", 3) == 0
-	   && ((*mangled)[3] == 'i' || (*mangled)[3] == 'f'))
-    {
-      p = (*mangled)[3] == 'i' ? " type_info node" : " type_info function";
-      (*mangled) += 4;
-      switch (**mangled)
-	{
-	case 'Q':
-	case 'K':
-	  success = demangle_qualified (work, mangled, declp, 0, 1);
-	  break;
-	case 't':
-	  success = demangle_template (work, mangled, declp, 0, 1, 1);
-	  break;
-	default:
-	  success = do_type (work, mangled, declp);
-	  break;
-	}
-      if (success && **mangled != '\0')
-	success = 0;
-      if (success)
-	string_append (declp, p);
-    }
-  else
-    {
-      success = 0;
-    }
-  return (success);
-}
-
-static void
-recursively_demangle(struct work_stuff *work, const char **mangled,
-                     string *result, int namelength)
-{
-  char * recurse = (char *)NULL;
-  char * recurse_dem = (char *)NULL;
-
-  recurse = XNEWVEC (char, namelength + 1);
-  memcpy (recurse, *mangled, namelength);
-  recurse[namelength] = '\000';
-
-  recurse_dem = cplus_demangle (recurse, work->options);
-
-  if (recurse_dem)
-    {
-      string_append (result, recurse_dem);
-      free (recurse_dem);
-    }
-  else
-    {
-      string_appendn (result, *mangled, namelength);
-    }
-  free (recurse);
-  *mangled += namelength;
-}
-
-/*
-
-LOCAL FUNCTION
-
-	arm_special -- special handling of ARM/lucid mangled strings
-
-SYNOPSIS
-
-	static int
-	arm_special (const char **mangled,
-		     string *declp);
-
-
-DESCRIPTION
-
-	Process some special ARM style mangling forms that don't fit
-	the normal pattern.  For example:
-
-		__vtbl__3foo		(foo virtual table)
-		__vtbl__3foo__3bar	(bar::foo virtual table)
-
- */
-
-static int
-arm_special (const char **mangled, string *declp)
-{
-  int n;
-  int success = 1;
-  const char *scan;
-
-  if (strncmp (*mangled, ARM_VTABLE_STRING, ARM_VTABLE_STRLEN) == 0)
-    {
-      /* Found a ARM style virtual table, get past ARM_VTABLE_STRING
-         and create the decl.  Note that we consume the entire mangled
-	 input string, which means that demangle_signature has no work
-	 to do.  */
-      scan = *mangled + ARM_VTABLE_STRLEN;
-      while (*scan != '\0')        /* first check it can be demangled */
-        {
-          n = consume_count (&scan);
-          if (n == -1)
-	    {
-	      return (0);           /* no good */
-	    }
-          scan += n;
-          if (scan[0] == '_' && scan[1] == '_')
-	    {
-	      scan += 2;
-	    }
-        }
-      (*mangled) += ARM_VTABLE_STRLEN;
-      while (**mangled != '\0')
-	{
-	  n = consume_count (mangled);
-          if (n == -1
-	      || n > (long) strlen (*mangled))
-	    return 0;
-	  string_prependn (declp, *mangled, n);
-	  (*mangled) += n;
-	  if ((*mangled)[0] == '_' && (*mangled)[1] == '_')
-	    {
-	      string_prepend (declp, "::");
-	      (*mangled) += 2;
-	    }
-	}
-      string_append (declp, " virtual table");
-    }
-  else
-    {
-      success = 0;
-    }
-  return (success);
-}
-
-/*
-
-LOCAL FUNCTION
-
-	demangle_qualified -- demangle 'Q' qualified name strings
-
-SYNOPSIS
-
-	static int
-	demangle_qualified (struct work_stuff *, const char *mangled,
-			    string *result, int isfuncname, int append);
-
-DESCRIPTION
-
-	Demangle a qualified name, such as "Q25Outer5Inner" which is
-	the mangled form of "Outer::Inner".  The demangled output is
-	prepended or appended to the result string according to the
-	state of the append flag.
-
-	If isfuncname is nonzero, then the qualified name we are building
-	is going to be used as a member function name, so if it is a
-	constructor or destructor function, append an appropriate
-	constructor or destructor name.  I.E. for the above example,
-	the result for use as a constructor is "Outer::Inner::Inner"
-	and the result for use as a destructor is "Outer::Inner::~Inner".
-
-BUGS
-
-	Numeric conversion is ASCII dependent (FIXME).
-
- */
-
-static int
-demangle_qualified (struct work_stuff *work, const char **mangled,
-                    string *result, int isfuncname, int append)
-{
-  int qualifiers = 0;
-  int success = 1;
-  char num[2];
-  string temp;
-  string last_name;
-  int bindex = register_Btype (work);
-
-  /* We only make use of ISFUNCNAME if the entity is a constructor or
-     destructor.  */
-  isfuncname = (isfuncname
-		&& ((work->constructor & 1) || (work->destructor & 1)));
-
-  string_init (&temp);
-  string_init (&last_name);
-
-  if ((*mangled)[0] == 'K')
-    {
-    /* Squangling qualified name reuse */
-      int idx;
-      (*mangled)++;
-      idx = consume_count_with_underscores (mangled);
-      if (idx == -1 || idx >= work -> numk)
-        success = 0;
-      else
-        string_append (&temp, work -> ktypevec[idx]);
-    }
-  else
-    switch ((*mangled)[1])
-    {
-    case '_':
-      /* GNU mangled name with more than 9 classes.  The count is preceded
-	 by an underscore (to distinguish it from the <= 9 case) and followed
-	 by an underscore.  */
-      (*mangled)++;
-      qualifiers = consume_count_with_underscores (mangled);
-      if (qualifiers == -1)
-	success = 0;
-      break;
-
-    case '1':
-    case '2':
-    case '3':
-    case '4':
-    case '5':
-    case '6':
-    case '7':
-    case '8':
-    case '9':
-      /* The count is in a single digit.  */
-      num[0] = (*mangled)[1];
-      num[1] = '\0';
-      qualifiers = atoi (num);
-
-      /* If there is an underscore after the digit, skip it.  This is
-	 said to be for ARM-qualified names, but the ARM makes no
-	 mention of such an underscore.  Perhaps cfront uses one.  */
-      if ((*mangled)[2] == '_')
-	{
-	  (*mangled)++;
-	}
-      (*mangled) += 2;
-      break;
-
-    case '0':
-    default:
-      success = 0;
-    }
-
-  if (!success)
-    return success;
-
-  /* Pick off the names and collect them in the temp buffer in the order
-     in which they are found, separated by '::'.  */
-
-  while (qualifiers-- > 0)
-    {
-      int remember_K = 1;
-      string_clear (&last_name);
-
-      if (*mangled[0] == '_')
-	(*mangled)++;
-
-      if (*mangled[0] == 't')
-	{
-	  /* Here we always append to TEMP since we will want to use
-	     the template name without the template parameters as a
-	     constructor or destructor name.  The appropriate
-	     (parameter-less) value is returned by demangle_template
-	     in LAST_NAME.  We do not remember the template type here,
-	     in order to match the G++ mangling algorithm.  */
-	  success = demangle_template(work, mangled, &temp,
-				      &last_name, 1, 0);
-	  if (!success)
-	    break;
-	}
-      else if (*mangled[0] == 'K')
-	{
-          int idx;
-          (*mangled)++;
-          idx = consume_count_with_underscores (mangled);
-          if (idx == -1 || idx >= work->numk)
-            success = 0;
-          else
-            string_append (&temp, work->ktypevec[idx]);
-          remember_K = 0;
-
-	  if (!success) break;
-	}
-      else
-	{
-	  if (EDG_DEMANGLING)
-            {
-	      int namelength;
- 	      /* Now recursively demangle the qualifier
- 	       * This is necessary to deal with templates in
- 	       * mangling styles like EDG */
-	      namelength = consume_count (mangled);
-	      if (namelength == -1)
-		{
-		  success = 0;
-		  break;
-		}
- 	      recursively_demangle(work, mangled, &temp, namelength);
-            }
-          else
-            {
-              string_delete (&last_name);
-              success = do_type (work, mangled, &last_name);
-              if (!success)
-                break;
-              string_appends (&temp, &last_name);
-            }
-	}
-
-      if (remember_K)
-	remember_Ktype (work, temp.b, LEN_STRING (&temp));
-
-      if (qualifiers > 0)
-	string_append (&temp, SCOPE_STRING (work));
-    }
-
-  remember_Btype (work, temp.b, LEN_STRING (&temp), bindex);
-
-  /* If we are using the result as a function name, we need to append
-     the appropriate '::' separated constructor or destructor name.
-     We do this here because this is the most convenient place, where
-     we already have a pointer to the name and the length of the name.  */
-
-  if (isfuncname)
-    {
-      string_append (&temp, SCOPE_STRING (work));
-      if (work -> destructor & 1)
-	string_append (&temp, "~");
-      string_appends (&temp, &last_name);
-    }
-
-  /* Now either prepend the temp buffer to the result, or append it,
-     depending upon the state of the append flag.  */
-
-  if (append)
-    string_appends (result, &temp);
-  else
-    {
-      if (!STRING_EMPTY (result))
-	string_append (&temp, SCOPE_STRING (work));
-      string_prepends (result, &temp);
-    }
-
-  string_delete (&last_name);
-  string_delete (&temp);
-  return (success);
-}
-
-/*
-
-LOCAL FUNCTION
-
-	get_count -- convert an ascii count to integer, consuming tokens
-
-SYNOPSIS
-
-	static int
-	get_count (const char **type, int *count)
-
-DESCRIPTION
-
-	Assume that *type points at a count in a mangled name; set
-	*count to its value, and set *type to the next character after
-	the count.  There are some weird rules in effect here.
-
-	If *type does not point at a string of digits, return zero.
-
-	If *type points at a string of digits followed by an
-	underscore, set *count to their value as an integer, advance
-	*type to point *after the underscore, and return 1.
-
-	If *type points at a string of digits not followed by an
-	underscore, consume only the first digit.  Set *count to its
-	value as an integer, leave *type pointing after that digit,
-	and return 1.
-
-        The excuse for this odd behavior: in the ARM and HP demangling
-        styles, a type can be followed by a repeat count of the form
-        `Nxy', where:
-
-        `x' is a single digit specifying how many additional copies
-            of the type to append to the argument list, and
-
-        `y' is one or more digits, specifying the zero-based index of
-            the first repeated argument in the list.  Yes, as you're
-            unmangling the name you can figure this out yourself, but
-            it's there anyway.
-
-        So, for example, in `bar__3fooFPiN51', the first argument is a
-        pointer to an integer (`Pi'), and then the next five arguments
-        are the same (`N5'), and the first repeat is the function's
-        second argument (`1').
-*/
-
-static int
-get_count (const char **type, int *count)
-{
-  const char *p;
-  int n;
-
-  if (!ISDIGIT ((unsigned char)**type))
-    return (0);
-  else
-    {
-      *count = **type - '0';
-      (*type)++;
-      if (ISDIGIT ((unsigned char)**type))
-	{
-	  p = *type;
-	  n = *count;
-	  do
-	    {
-	      n *= 10;
-	      n += *p - '0';
-	      p++;
-	    }
-	  while (ISDIGIT ((unsigned char)*p));
-	  if (*p == '_')
-	    {
-	      *type = p + 1;
-	      *count = n;
-	    }
-	}
-    }
-  return (1);
-}
-
-/* RESULT will be initialised here; it will be freed on failure.  The
-   value returned is really a type_kind_t.  */
-
-static int
-do_type (struct work_stuff *work, const char **mangled, string *result)
-{
-  int n;
-  int i;
-  int is_proctypevec;
-  int done;
-  int success;
-  string decl;
-  const char *remembered_type;
-  int type_quals;
-  type_kind_t tk = tk_none;
-
-  string_init (&decl);
-  string_init (result);
-
-  done = 0;
-  success = 1;
-  is_proctypevec = 0;
-  while (success && !done)
-    {
-      int member;
-      switch (**mangled)
-	{
-
-	  /* A pointer type */
-	case 'P':
-	case 'p':
-	  (*mangled)++;
-	  if (! (work -> options & DMGL_JAVA))
-	    string_prepend (&decl, "*");
-	  if (tk == tk_none)
-	    tk = tk_pointer;
-	  break;
-
-	  /* A reference type */
-	case 'R':
-	  (*mangled)++;
-	  string_prepend (&decl, "&");
-	  if (tk == tk_none)
-	    tk = tk_reference;
-	  break;
-
-	  /* An rvalue reference type */
-	case 'O':
-	  (*mangled)++;
-	  string_prepend (&decl, "&&");
-	  if (tk == tk_none)
-	    tk = tk_rvalue_reference;
-	  break;
-
-	  /* An array */
-	case 'A':
-	  {
-	    ++(*mangled);
-	    if (!STRING_EMPTY (&decl)
-		&& (decl.b[0] == '*' || decl.b[0] == '&'))
-	      {
-		string_prepend (&decl, "(");
-		string_append (&decl, ")");
-	      }
-	    string_append (&decl, "[");
-	    if (**mangled != '_')
-	      success = demangle_template_value_parm (work, mangled, &decl,
-						      tk_integral);
-	    if (**mangled == '_')
-	      ++(*mangled);
-	    string_append (&decl, "]");
-	    break;
-	  }
-
-	/* A back reference to a previously seen type */
-	case 'T':
-	  (*mangled)++;
-	  if (!get_count (mangled, &n) || n < 0 || n >= work -> ntypes)
-	    {
-	      success = 0;
-	    }
-	  else
-	    for (i = 0; i < work->nproctypes; i++)
-	      if (work -> proctypevec [i] == n)
-	        success = 0;
-
-	  if (success)
-	    {    
-	      is_proctypevec = 1;
-	      push_processed_type (work, n);
-	      remembered_type = work->typevec[n];
-	      mangled = &remembered_type;
-	    }
-	  break;
-
-	  /* A function */
-	case 'F':
-	  (*mangled)++;
-	    if (!STRING_EMPTY (&decl)
-		&& (decl.b[0] == '*' || decl.b[0] == '&'))
-	    {
-	      string_prepend (&decl, "(");
-	      string_append (&decl, ")");
-	    }
-	  /* After picking off the function args, we expect to either find the
-	     function return type (preceded by an '_') or the end of the
-	     string.  */
-	  if (!demangle_nested_args (work, mangled, &decl)
-	      || (**mangled != '_' && **mangled != '\0'))
-	    {
-	      success = 0;
-	      break;
-	    }
-	  if (success && (**mangled == '_'))
-	    (*mangled)++;
-	  break;
-
-	case 'M':
-	  {
-	    type_quals = TYPE_UNQUALIFIED;
-
-	    member = **mangled == 'M';
-	    (*mangled)++;
-
-	    string_append (&decl, ")");
-
-	    /* We don't need to prepend `::' for a qualified name;
-	       demangle_qualified will do that for us.  */
-	    if (**mangled != 'Q')
-	      string_prepend (&decl, SCOPE_STRING (work));
-
-	    if (ISDIGIT ((unsigned char)**mangled))
-	      {
-		n = consume_count (mangled);
-		if (n == -1
-		    || (int) strlen (*mangled) < n)
-		  {
-		    success = 0;
-		    break;
-		  }
-		string_prependn (&decl, *mangled, n);
-		*mangled += n;
-	      }
-	    else if (**mangled == 'X' || **mangled == 'Y')
-	      {
-		string temp;
-		do_type (work, mangled, &temp);
-		string_prepends (&decl, &temp);
-		string_delete (&temp);
-	      }
-	    else if (**mangled == 't')
-	      {
-		string temp;
-		string_init (&temp);
-		success = demangle_template (work, mangled, &temp,
-					     NULL, 1, 1);
-		if (success)
-		  {
-		    string_prependn (&decl, temp.b, temp.p - temp.b);
-		    string_delete (&temp);
-		  }
-		else
-		  {
-		    string_delete (&temp);
-		    break;
-		  }
-	      }
-	    else if (**mangled == 'Q')
-	      {
-		success = demangle_qualified (work, mangled, &decl,
-					      /*isfuncnam=*/0, 
-					      /*append=*/0);
-		if (!success)
-		  break;
-	      }
-	    else
-	      {
-		success = 0;
-		break;
-	      }
-
-	    string_prepend (&decl, "(");
-	    if (member)
-	      {
-		switch (**mangled)
-		  {
-		  case 'C':
-		  case 'V':
-		  case 'u':
-		    type_quals |= code_for_qualifier (**mangled);
-		    (*mangled)++;
-		    break;
-
-		  default:
-		    break;
-		  }
-
-		if (*(*mangled) != 'F')
-		  {
-		    success = 0;
-		    break;
-		  }
-		(*mangled)++;
-	      }
-	    if ((member && !demangle_nested_args (work, mangled, &decl))
-		|| **mangled != '_')
-	      {
-		success = 0;
-		break;
-	      }
-	    (*mangled)++;
-	    if (! PRINT_ANSI_QUALIFIERS)
-	      {
-		break;
-	      }
-	    if (type_quals != TYPE_UNQUALIFIED)
-	      {
-		APPEND_BLANK (&decl);
-		string_append (&decl, qualifier_string (type_quals));
-	      }
-	    break;
-	  }
-        case 'G':
-	  (*mangled)++;
-	  break;
-
-	case 'C':
-	case 'V':
-	case 'u':
-	  if (PRINT_ANSI_QUALIFIERS)
-	    {
-	      if (!STRING_EMPTY (&decl))
-		string_prepend (&decl, " ");
-
-	      string_prepend (&decl, demangle_qualifier (**mangled));
-	    }
-	  (*mangled)++;
-	  break;
-	  /*
-	    }
-	    */
-
-	  /* fall through */
-	default:
-	  done = 1;
-	  break;
-	}
-    }
-
-  if (success) switch (**mangled)
-    {
-      /* A qualified name, such as "Outer::Inner".  */
-    case 'Q':
-    case 'K':
-      {
-        success = demangle_qualified (work, mangled, result, 0, 1);
-        break;
-      }
-
-    /* A back reference to a previously seen squangled type */
-    case 'B':
-      (*mangled)++;
-      if (!get_count (mangled, &n) || n < 0 || n >= work -> numb)
-	success = 0;
-      else
-	string_append (result, work->btypevec[n]);
-      break;
-
-    case 'X':
-    case 'Y':
-      /* A template parm.  We substitute the corresponding argument. */
-      {
-	int idx;
-
-	(*mangled)++;
-	idx = consume_count_with_underscores (mangled);
-
-	if (idx == -1
-	    || (work->tmpl_argvec && idx >= work->ntmpl_args)
-	    || consume_count_with_underscores (mangled) == -1)
-	  {
-	    success = 0;
-	    break;
-	  }
-
-	if (work->tmpl_argvec)
-	  string_append (result, work->tmpl_argvec[idx]);
-	else
-	  string_append_template_idx (result, idx);
-
-	success = 1;
-      }
-    break;
-
-    default:
-      success = demangle_fund_type (work, mangled, result);
-      if (tk == tk_none)
-	tk = (type_kind_t) success;
-      break;
-    }
-
-  if (success)
-    {
-      if (!STRING_EMPTY (&decl))
-	{
-	  string_append (result, " ");
-	  string_appends (result, &decl);
-	}
-    }
-  else
-    string_delete (result);
-  string_delete (&decl);
-
-  if (is_proctypevec)
-    pop_processed_type (work); 
-
-  if (success)
-    /* Assume an integral type, if we're not sure.  */
-    return (int) ((tk == tk_none) ? tk_integral : tk);
-  else
-    return 0;
-}
-
-/* Given a pointer to a type string that represents a fundamental type
-   argument (int, long, unsigned int, etc) in TYPE, a pointer to the
-   string in which the demangled output is being built in RESULT, and
-   the WORK structure, decode the types and add them to the result.
-
-   For example:
-
-   	"Ci"	=>	"const int"
-	"Sl"	=>	"signed long"
-	"CUs"	=>	"const unsigned short"
-
-   The value returned is really a type_kind_t.  */
-
-static int
-demangle_fund_type (struct work_stuff *work,
-                    const char **mangled, string *result)
-{
-  int done = 0;
-  int success = 1;
-  char buf[INTBUF_SIZE + 5 /* 'int%u_t' */];
-  unsigned int dec = 0;
-  type_kind_t tk = tk_integral;
-
-  /* First pick off any type qualifiers.  There can be more than one.  */
-
-  while (!done)
-    {
-      switch (**mangled)
-	{
-	case 'C':
-	case 'V':
-	case 'u':
-	  if (PRINT_ANSI_QUALIFIERS)
-	    {
-              if (!STRING_EMPTY (result))
-                string_prepend (result, " ");
-	      string_prepend (result, demangle_qualifier (**mangled));
-	    }
-	  (*mangled)++;
-	  break;
-	case 'U':
-	  (*mangled)++;
-	  APPEND_BLANK (result);
-	  string_append (result, "unsigned");
-	  break;
-	case 'S': /* signed char only */
-	  (*mangled)++;
-	  APPEND_BLANK (result);
-	  string_append (result, "signed");
-	  break;
-	case 'J':
-	  (*mangled)++;
-	  APPEND_BLANK (result);
-	  string_append (result, "__complex");
-	  break;
-	default:
-	  done = 1;
-	  break;
-	}
-    }
-
-  /* Now pick off the fundamental type.  There can be only one.  */
-
-  switch (**mangled)
-    {
-    case '\0':
-    case '_':
-      break;
-    case 'v':
-      (*mangled)++;
-      APPEND_BLANK (result);
-      string_append (result, "void");
-      break;
-    case 'x':
-      (*mangled)++;
-      APPEND_BLANK (result);
-      string_append (result, "long long");
-      break;
-    case 'l':
-      (*mangled)++;
-      APPEND_BLANK (result);
-      string_append (result, "long");
-      break;
-    case 'i':
-      (*mangled)++;
-      APPEND_BLANK (result);
-      string_append (result, "int");
-      break;
-    case 's':
-      (*mangled)++;
-      APPEND_BLANK (result);
-      string_append (result, "short");
-      break;
-    case 'b':
-      (*mangled)++;
-      APPEND_BLANK (result);
-      string_append (result, "bool");
-      tk = tk_bool;
-      break;
-    case 'c':
-      (*mangled)++;
-      APPEND_BLANK (result);
-      string_append (result, "char");
-      tk = tk_char;
-      break;
-    case 'w':
-      (*mangled)++;
-      APPEND_BLANK (result);
-      string_append (result, "wchar_t");
-      tk = tk_char;
-      break;
-    case 'r':
-      (*mangled)++;
-      APPEND_BLANK (result);
-      string_append (result, "long double");
-      tk = tk_real;
-      break;
-    case 'd':
-      (*mangled)++;
-      APPEND_BLANK (result);
-      string_append (result, "double");
-      tk = tk_real;
-      break;
-    case 'f':
-      (*mangled)++;
-      APPEND_BLANK (result);
-      string_append (result, "float");
-      tk = tk_real;
-      break;
-    case 'G':
-      (*mangled)++;
-      if (!ISDIGIT ((unsigned char)**mangled))
-	{
-	  success = 0;
-	  break;
-	}
-      /* fall through */
-    case 'I':
-      (*mangled)++;
-      if (**mangled == '_')
-	{
-	  int i;
-	  (*mangled)++;
-	  for (i = 0;
-	       i < (long) sizeof (buf) - 1 && **mangled && **mangled != '_';
-	       (*mangled)++, i++)
-	    buf[i] = **mangled;
-	  if (**mangled != '_')
-	    {
-	      success = 0;
-	      break;
-	    }
-	  buf[i] = '\0';
-	  (*mangled)++;
-	}
-      else
-	{
-	  strncpy (buf, *mangled, 2);
-	  buf[2] = '\0';
-	  *mangled += min (strlen (*mangled), 2);
-	}
-      sscanf (buf, "%x", &dec);
-      sprintf (buf, "int%u_t", dec);
-      APPEND_BLANK (result);
-      string_append (result, buf);
-      break;
-
-      /* fall through */
-      /* An explicit type, such as "6mytype" or "7integer" */
-    case '0':
-    case '1':
-    case '2':
-    case '3':
-    case '4':
-    case '5':
-    case '6':
-    case '7':
-    case '8':
-    case '9':
-      {
-        int bindex = register_Btype (work);
-        string btype;
-        string_init (&btype);
-        if (demangle_class_name (work, mangled, &btype)) {
-          remember_Btype (work, btype.b, LEN_STRING (&btype), bindex);
-          APPEND_BLANK (result);
-          string_appends (result, &btype);
-        }
-        else
-          success = 0;
-        string_delete (&btype);
-        break;
-      }
-    case 't':
-      {
-        string btype;
-        string_init (&btype);
-        success = demangle_template (work, mangled, &btype, 0, 1, 1);
-        string_appends (result, &btype);
-        string_delete (&btype);
-        break;
-      }
-    default:
-      success = 0;
-      break;
-    }
-
-  return success ? ((int) tk) : 0;
-}
-
-
-/* Handle a template's value parameter for HP aCC (extension from ARM)
-   **mangled points to 'S' or 'U' */
-
-static int
-do_hpacc_template_const_value (struct work_stuff *work ATTRIBUTE_UNUSED,
-                               const char **mangled, string *result)
-{
-  int unsigned_const;
-
-  if (**mangled != 'U' && **mangled != 'S')
-    return 0;
-
-  unsigned_const = (**mangled == 'U');
-
-  (*mangled)++;
-
-  switch (**mangled)
-    {
-      case 'N':
-        string_append (result, "-");
-        /* fall through */
-      case 'P':
-        (*mangled)++;
-        break;
-      case 'M':
-        /* special case for -2^31 */
-        string_append (result, "-2147483648");
-        (*mangled)++;
-        return 1;
-      default:
-        return 0;
-    }
-
-  /* We have to be looking at an integer now */
-  if (!(ISDIGIT ((unsigned char)**mangled)))
-    return 0;
-
-  /* We only deal with integral values for template
-     parameters -- so it's OK to look only for digits */
-  while (ISDIGIT ((unsigned char)**mangled))
-    {
-      char_str[0] = **mangled;
-      string_append (result, char_str);
-      (*mangled)++;
-    }
-
-  if (unsigned_const)
-    string_append (result, "U");
-
-  /* FIXME? Some day we may have 64-bit (or larger :-) ) constants
-     with L or LL suffixes. pai/1997-09-03 */
-
-  return 1; /* success */
-}
-
-/* Handle a template's literal parameter for HP aCC (extension from ARM)
-   **mangled is pointing to the 'A' */
-
-static int
-do_hpacc_template_literal (struct work_stuff *work, const char **mangled,
-                           string *result)
-{
-  int literal_len = 0;
-  char * recurse;
-  char * recurse_dem;
-
-  if (**mangled != 'A')
-    return 0;
-
-  (*mangled)++;
-
-  literal_len = consume_count (mangled);
-
-  if (literal_len <= 0
-      || literal_len > (long) strlen (*mangled))
-    return 0;
-
-  /* Literal parameters are names of arrays, functions, etc.  and the
-     canonical representation uses the address operator */
-  string_append (result, "&");
-
-  /* Now recursively demangle the literal name */
-  recurse = XNEWVEC (char, literal_len + 1);
-  memcpy (recurse, *mangled, literal_len);
-  recurse[literal_len] = '\000';
-
-  recurse_dem = cplus_demangle (recurse, work->options);
-
-  if (recurse_dem)
-    {
-      string_append (result, recurse_dem);
-      free (recurse_dem);
-    }
-  else
-    {
-      string_appendn (result, *mangled, literal_len);
-    }
-  (*mangled) += literal_len;
-  free (recurse);
-
-  return 1;
-}
-
-static int
-snarf_numeric_literal (const char **args, string *arg)
-{
-  if (**args == '-')
-    {
-      char_str[0] = '-';
-      string_append (arg, char_str);
-      (*args)++;
-    }
-  else if (**args == '+')
-    (*args)++;
-
-  if (!ISDIGIT ((unsigned char)**args))
-    return 0;
-
-  while (ISDIGIT ((unsigned char)**args))
-    {
-      char_str[0] = **args;
-      string_append (arg, char_str);
-      (*args)++;
-    }
-
-  return 1;
-}
-
-/* Demangle the next argument, given by MANGLED into RESULT, which
-   *should be an uninitialized* string.  It will be initialized here,
-   and free'd should anything go wrong.  */
-
-static int
-do_arg (struct work_stuff *work, const char **mangled, string *result)
-{
-  /* Remember where we started so that we can record the type, for
-     non-squangling type remembering.  */
-  const char *start = *mangled;
-
-  string_init (result);
-
-  if (work->nrepeats > 0)
-    {
-      --work->nrepeats;
-
-      if (work->previous_argument == 0)
-	return 0;
-
-      /* We want to reissue the previous type in this argument list.  */
-      string_appends (result, work->previous_argument);
-      return 1;
-    }
-
-  if (**mangled == 'n')
-    {
-      /* A squangling-style repeat.  */
-      (*mangled)++;
-      work->nrepeats = consume_count(mangled);
-
-      if (work->nrepeats <= 0)
-	/* This was not a repeat count after all.  */
-	return 0;
-
-      if (work->nrepeats > 9)
-	{
-	  if (**mangled != '_')
-	    /* The repeat count should be followed by an '_' in this
-	       case.  */
-	    return 0;
-	  else
-	    (*mangled)++;
-	}
-
-      /* Now, the repeat is all set up.  */
-      return do_arg (work, mangled, result);
-    }
-
-  /* Save the result in WORK->previous_argument so that we can find it
-     if it's repeated.  Note that saving START is not good enough: we
-     do not want to add additional types to the back-referenceable
-     type vector when processing a repeated type.  */
-  if (work->previous_argument)
-    string_delete (work->previous_argument);
-  else
-    work->previous_argument = XNEW (string);
-
-  if (!do_type (work, mangled, work->previous_argument))
-    return 0;
-
-  string_appends (result, work->previous_argument);
-
-  remember_type (work, start, *mangled - start);
-  return 1;
-}
-
-static void
-push_processed_type (struct work_stuff *work, int typevec_index)
-{
-  if (work->nproctypes >= work->proctypevec_size)
-    {
-      if (!work->proctypevec_size)
-	{
-	  work->proctypevec_size = 4;
-	  work->proctypevec = XNEWVEC (int, work->proctypevec_size);
-	}
-      else 
-	{
-	  if (work->proctypevec_size < 16)
-	    /* Double when small.  */
-	    work->proctypevec_size *= 2;
-	  else
-	    {
-	      /* Grow slower when large.  */
-	      if (work->proctypevec_size > (INT_MAX / 3) * 2)
-                xmalloc_failed (INT_MAX);
-              work->proctypevec_size = (work->proctypevec_size * 3 / 2);
-	    }   
-          work->proctypevec
-            = XRESIZEVEC (int, work->proctypevec, work->proctypevec_size);
-	}
-    }
-    work->proctypevec [work->nproctypes++] = typevec_index;
-}
-
-static void
-pop_processed_type (struct work_stuff *work)
-{
-  work->nproctypes--;
-}
-
-static void
-remember_type (struct work_stuff *work, const char *start, int len)
-{
-  char *tem;
-
-  if (work->forgetting_types)
-    return;
-
-  if (work -> ntypes >= work -> typevec_size)
-    {
-      if (work -> typevec_size == 0)
-	{
-	  work -> typevec_size = 3;
-	  work -> typevec = XNEWVEC (char *, work->typevec_size);
-	}
-      else
-	{
-          if (work -> typevec_size > INT_MAX / 2)
-	    xmalloc_failed (INT_MAX);
-	  work -> typevec_size *= 2;
-	  work -> typevec
-	    = XRESIZEVEC (char *, work->typevec, work->typevec_size);
-	}
-    }
-  tem = XNEWVEC (char, len + 1);
-  memcpy (tem, start, len);
-  tem[len] = '\0';
-  work -> typevec[work -> ntypes++] = tem;
-}
-
-
-/* Remember a K type class qualifier. */
-static void
-remember_Ktype (struct work_stuff *work, const char *start, int len)
-{
-  char *tem;
-
-  if (work -> numk >= work -> ksize)
-    {
-      if (work -> ksize == 0)
-	{
-	  work -> ksize = 5;
-	  work -> ktypevec = XNEWVEC (char *, work->ksize);
-	}
-      else
-	{
-          if (work -> ksize > INT_MAX / 2)
-	    xmalloc_failed (INT_MAX);
-	  work -> ksize *= 2;
-	  work -> ktypevec
-	    = XRESIZEVEC (char *, work->ktypevec, work->ksize);
-	}
-    }
-  tem = XNEWVEC (char, len + 1);
-  memcpy (tem, start, len);
-  tem[len] = '\0';
-  work -> ktypevec[work -> numk++] = tem;
-}
-
-/* Register a B code, and get an index for it. B codes are registered
-   as they are seen, rather than as they are completed, so map<temp<char> >
-   registers map<temp<char> > as B0, and temp<char> as B1 */
-
-static int
-register_Btype (struct work_stuff *work)
-{
-  int ret;
-
-  if (work -> numb >= work -> bsize)
-    {
-      if (work -> bsize == 0)
-	{
-	  work -> bsize = 5;
-	  work -> btypevec = XNEWVEC (char *, work->bsize);
-	}
-      else
-	{
-          if (work -> bsize > INT_MAX / 2)
-	    xmalloc_failed (INT_MAX);
-	  work -> bsize *= 2;
-	  work -> btypevec
-	    = XRESIZEVEC (char *, work->btypevec, work->bsize);
-	}
-    }
-  ret = work -> numb++;
-  work -> btypevec[ret] = NULL;
-  return(ret);
-}
-
-/* Store a value into a previously registered B code type. */
-
-static void
-remember_Btype (struct work_stuff *work, const char *start,
-                int len, int index)
-{
-  char *tem;
-
-  tem = XNEWVEC (char, len + 1);
-  if (len > 0)
-    memcpy (tem, start, len);
-  tem[len] = '\0';
-  work -> btypevec[index] = tem;
-}
-
-/* Lose all the info related to B and K type codes. */
-
-static void
-forget_B_and_K_types (struct work_stuff *work)
-{
-  int i;
-
-  while (work -> numk > 0)
-    {
-      i = --(work -> numk);
-      if (work -> ktypevec[i] != NULL)
-	{
-	  free (work -> ktypevec[i]);
-	  work -> ktypevec[i] = NULL;
-	}
-    }
-
-  while (work -> numb > 0)
-    {
-      i = --(work -> numb);
-      if (work -> btypevec[i] != NULL)
-	{
-	  free (work -> btypevec[i]);
-	  work -> btypevec[i] = NULL;
-	}
-    }
-}
-
-/* Forget the remembered types, but not the type vector itself.  */
-
-static void
-forget_types (struct work_stuff *work)
-{
-  int i;
-
-  while (work -> ntypes > 0)
-    {
-      i = --(work -> ntypes);
-      if (work -> typevec[i] != NULL)
-	{
-	  free (work -> typevec[i]);
-	  work -> typevec[i] = NULL;
-	}
-    }
-}
-
-/* Process the argument list part of the signature, after any class spec
-   has been consumed, as well as the first 'F' character (if any).  For
-   example:
-
-   "__als__3fooRT0"		=>	process "RT0"
-   "complexfunc5__FPFPc_PFl_i"	=>	process "PFPc_PFl_i"
-
-   DECLP must be already initialised, usually non-empty.  It won't be freed
-   on failure.
-
-   Note that g++ differs significantly from ARM and lucid style mangling
-   with regards to references to previously seen types.  For example, given
-   the source fragment:
-
-     class foo {
-       public:
-       foo::foo (int, foo &ia, int, foo &ib, int, foo &ic);
-     };
-
-     foo::foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
-     void foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
-
-   g++ produces the names:
-
-     __3fooiRT0iT2iT2
-     foo__FiR3fooiT1iT1
-
-   while lcc (and presumably other ARM style compilers as well) produces:
-
-     foo__FiR3fooT1T2T1T2
-     __ct__3fooFiR3fooT1T2T1T2
-
-   Note that g++ bases its type numbers starting at zero and counts all
-   previously seen types, while lucid/ARM bases its type numbers starting
-   at one and only considers types after it has seen the 'F' character
-   indicating the start of the function args.  For lucid/ARM style, we
-   account for this difference by discarding any previously seen types when
-   we see the 'F' character, and subtracting one from the type number
-   reference.
-
- */
-
-static int
-demangle_args (struct work_stuff *work, const char **mangled,
-               string *declp)
-{
-  string arg;
-  int need_comma = 0;
-  int r;
-  int t;
-  const char *tem;
-  char temptype;
-
-  if (PRINT_ARG_TYPES)
-    {
-      string_append (declp, "(");
-      if (**mangled == '\0')
-	{
-	  string_append (declp, "void");
-	}
-    }
-
-  while ((**mangled != '_' && **mangled != '\0' && **mangled != 'e')
-	 || work->nrepeats > 0)
-    {
-      if ((**mangled == 'N') || (**mangled == 'T'))
-	{
-	  temptype = *(*mangled)++;
-
-	  if (temptype == 'N')
-	    {
-	      if (!get_count (mangled, &r))
-		{
-		  return (0);
-		}
-	    }
-	  else
-	    {
-	      r = 1;
-	    }
-          if ((HP_DEMANGLING || ARM_DEMANGLING || EDG_DEMANGLING) && work -> ntypes >= 10)
-            {
-              /* If we have 10 or more types we might have more than a 1 digit
-                 index so we'll have to consume the whole count here. This
-                 will lose if the next thing is a type name preceded by a
-                 count but it's impossible to demangle that case properly
-                 anyway. Eg if we already have 12 types is T12Pc "(..., type1,
-                 Pc, ...)"  or "(..., type12, char *, ...)" */
-              if ((t = consume_count(mangled)) <= 0)
-                {
-                  return (0);
-                }
-            }
-          else
-	    {
-	      if (!get_count (mangled, &t))
-	    	{
-	          return (0);
-	    	}
-	    }
-	  if (LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING)
-	    {
-	      t--;
-	    }
-	  /* Validate the type index.  Protect against illegal indices from
-	     malformed type strings.  */
-	  if ((t < 0) || (t >= work -> ntypes))
-	    {
-	      return (0);
-	    }
-	  while (work->nrepeats > 0 || --r >= 0)
-	    {
-	      tem = work -> typevec[t];
-	      if (need_comma && PRINT_ARG_TYPES)
-		{
-		  string_append (declp, ", ");
-		}
-	      push_processed_type (work, t);  
-	      if (!do_arg (work, &tem, &arg))
-		{
-		  pop_processed_type (work);
-		  return (0);
-		}
-	      pop_processed_type (work);
-	      if (PRINT_ARG_TYPES)
-		{
-		  string_appends (declp, &arg);
-		}
-	      string_delete (&arg);
-	      need_comma = 1;
-	    }
-	}
-      else
-	{
-	  if (need_comma && PRINT_ARG_TYPES)
-	    string_append (declp, ", ");
-	  if (!do_arg (work, mangled, &arg))
-	    return (0);
-	  if (PRINT_ARG_TYPES)
-	    string_appends (declp, &arg);
-	  string_delete (&arg);
-	  need_comma = 1;
-	}
-    }
-
-  if (**mangled == 'e')
-    {
-      (*mangled)++;
-      if (PRINT_ARG_TYPES)
-	{
-	  if (need_comma)
-	    {
-	      string_append (declp, ",");
-	    }
-	  string_append (declp, "...");
-	}
-    }
-
-  if (PRINT_ARG_TYPES)
-    {
-      string_append (declp, ")");
-    }
-  return (1);
-}
-
-/* Like demangle_args, but for demangling the argument lists of function
-   and method pointers or references, not top-level declarations.  */
-
-static int
-demangle_nested_args (struct work_stuff *work, const char **mangled,
-                      string *declp)
-{
-  string* saved_previous_argument;
-  int result;
-  int saved_nrepeats;
-
-  if ((work->options & DMGL_NO_RECURSE_LIMIT) == 0)
-    {
-      if (work->recursion_level > DEMANGLE_RECURSION_LIMIT)
-	/* FIXME: There ought to be a way to report
-	   that the recursion limit has been reached.  */
-	return 0;
-
-      work->recursion_level ++;
-    }
-
-  /* The G++ name-mangling algorithm does not remember types on nested
-     argument lists, unless -fsquangling is used, and in that case the
-     type vector updated by remember_type is not used.  So, we turn
-     off remembering of types here.  */
-  ++work->forgetting_types;
-
-  /* For the repeat codes used with -fsquangling, we must keep track of
-     the last argument.  */
-  saved_previous_argument = work->previous_argument;
-  saved_nrepeats = work->nrepeats;
-  work->previous_argument = 0;
-  work->nrepeats = 0;
-
-  /* Actually demangle the arguments.  */
-  result = demangle_args (work, mangled, declp);
-
-  /* Restore the previous_argument field.  */
-  if (work->previous_argument)
-    {
-      string_delete (work->previous_argument);
-      free ((char *) work->previous_argument);
-    }
-  work->previous_argument = saved_previous_argument;
-  --work->forgetting_types;
-  work->nrepeats = saved_nrepeats;
-
-  if ((work->options & DMGL_NO_RECURSE_LIMIT) == 0)
-    --work->recursion_level;
-
-  return result;
-}
-
-/* Returns 1 if a valid function name was found or 0 otherwise.  */
-
-static int 
-demangle_function_name (struct work_stuff *work, const char **mangled,
-                        string *declp, const char *scan)
-{
-  size_t i;
-  string type;
-  const char *tem;
-
-  string_appendn (declp, (*mangled), scan - (*mangled));
-  string_need (declp, 1);
-  *(declp -> p) = '\0';
-
-  /* Consume the function name, including the "__" separating the name
-     from the signature.  We are guaranteed that SCAN points to the
-     separator.  */
-
-  (*mangled) = scan + 2;
-  /* We may be looking at an instantiation of a template function:
-     foo__Xt1t2_Ft3t4, where t1, t2, ... are template arguments and a
-     following _F marks the start of the function arguments.  Handle
-     the template arguments first. */
-
-  if (HP_DEMANGLING && (**mangled == 'X'))
-    {
-      demangle_arm_hp_template (work, mangled, 0, declp);
-      /* This leaves MANGLED pointing to the 'F' marking func args */
-    }
-
-  if (LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING)
-    {
-
-      /* See if we have an ARM style constructor or destructor operator.
-	 If so, then just record it, clear the decl, and return.
-	 We can't build the actual constructor/destructor decl until later,
-	 when we recover the class name from the signature.  */
-
-      if (strcmp (declp -> b, "__ct") == 0)
-	{
-	  work -> constructor += 1;
-	  string_clear (declp);
-	  return 1;
-	}
-      else if (strcmp (declp -> b, "__dt") == 0)
-	{
-	  work -> destructor += 1;
-	  string_clear (declp);
-	  return 1;
-	}
-    }
-
-  if (declp->p - declp->b >= 3
-      && declp->b[0] == 'o'
-      && declp->b[1] == 'p'
-      && strchr (cplus_markers, declp->b[2]) != NULL)
-    {
-      /* see if it's an assignment expression */
-      if (declp->p - declp->b >= 10 /* op$assign_ */
-	  && memcmp (declp->b + 3, "assign_", 7) == 0)
-	{
-	  for (i = 0; i < ARRAY_SIZE (optable); i++)
-	    {
-	      int len = declp->p - declp->b - 10;
-	      if ((int) strlen (optable[i].in) == len
-		  && memcmp (optable[i].in, declp->b + 10, len) == 0)
-		{
-		  string_clear (declp);
-		  string_append (declp, "operator");
-		  string_append (declp, optable[i].out);
-		  string_append (declp, "=");
-		  break;
-		}
-	    }
-	}
-      else
-	{
-	  for (i = 0; i < ARRAY_SIZE (optable); i++)
-	    {
-	      int len = declp->p - declp->b - 3;
-	      if ((int) strlen (optable[i].in) == len
-		  && memcmp (optable[i].in, declp->b + 3, len) == 0)
-		{
-		  string_clear (declp);
-		  string_append (declp, "operator");
-		  string_append (declp, optable[i].out);
-		  break;
-		}
-	    }
-	}
-    }
-  else if (declp->p - declp->b >= 5 && memcmp (declp->b, "type", 4) == 0
-	   && strchr (cplus_markers, declp->b[4]) != NULL)
-    {
-      /* type conversion operator */
-      tem = declp->b + 5;
-      if (do_type (work, &tem, &type))
-	{
-	  string_clear (declp);
-	  string_append (declp, "operator ");
-	  string_appends (declp, &type);
-	  string_delete (&type);
-	}
-    }
-  else if (declp->b[0] == '_' && declp->b[1] == '_'
-	   && declp->b[2] == 'o' && declp->b[3] == 'p')
-    {
-      /* ANSI.  */
-      /* type conversion operator.  */
-      tem = declp->b + 4;
-      if (do_type (work, &tem, &type))
-	{
-	  string_clear (declp);
-	  string_append (declp, "operator ");
-	  string_appends (declp, &type);
-	  string_delete (&type);
-	}
-    }
-  else if (declp->b[0] == '_' && declp->b[1] == '_'
-	   && ISLOWER((unsigned char)declp->b[2])
-	   && ISLOWER((unsigned char)declp->b[3]))
-    {
-      if (declp->b[4] == '\0')
-	{
-	  /* Operator.  */
-	  for (i = 0; i < ARRAY_SIZE (optable); i++)
-	    {
-	      if (strlen (optable[i].in) == 2
-		  && memcmp (optable[i].in, declp->b + 2, 2) == 0)
-		{
-		  string_clear (declp);
-		  string_append (declp, "operator");
-		  string_append (declp, optable[i].out);
-		  break;
-		}
-	    }
-	}
-      else
-	{
-	  if (declp->b[2] == 'a' && declp->b[5] == '\0')
-	    {
-	      /* Assignment.  */
-	      for (i = 0; i < ARRAY_SIZE (optable); i++)
-		{
-		  if (strlen (optable[i].in) == 3
-		      && memcmp (optable[i].in, declp->b + 2, 3) == 0)
-		    {
-		      string_clear (declp);
-		      string_append (declp, "operator");
-		      string_append (declp, optable[i].out);
-		      break;
-		    }
-		}
-	    }
-	}
-    }
-
-  /* If a function name was obtained but it's not valid, we were not
-     successful.  */
-  if (LEN_STRING (declp) == 1 && declp->b[0] == '.')
-    return 0;
-  else
-    return 1;
-}
-
-/* a mini string-handling package */
-
-static void
-string_need (string *s, int n)
-{
-  int tem;
-
-  if (s->b == NULL)
-    {
-      if (n < 32)
-	{
-	  n = 32;
-	}
-      s->p = s->b = XNEWVEC (char, n);
-      s->e = s->b + n;
-    }
-  else if (s->e - s->p < n)
-    {
-      tem = s->p - s->b;
-      if (n > INT_MAX / 2 - tem)
-        xmalloc_failed (INT_MAX); 
-      n += tem;
-      n *= 2;
-      s->b = XRESIZEVEC (char, s->b, n);
-      s->p = s->b + tem;
-      s->e = s->b + n;
-    }
-}
-
-static void
-string_delete (string *s)
-{
-  if (s->b != NULL)
-    {
-      free (s->b);
-      s->b = s->e = s->p = NULL;
-    }
-}
-
-static void
-string_init (string *s)
-{
-  s->b = s->p = s->e = NULL;
-}
-
-static void
-string_clear (string *s)
-{
-  s->p = s->b;
-}
-
-#if 0
-
-static int
-string_empty (string *s)
-{
-  return (s->b == s->p);
-}
-
-#endif
-
-static void
-string_append (string *p, const char *s)
-{
-  int n;
-  if (s == NULL || *s == '\0')
-    return;
-  n = strlen (s);
-  string_need (p, n);
-  memcpy (p->p, s, n);
-  p->p += n;
-}
-
-static void
-string_appends (string *p, string *s)
-{
-  int n;
-
-  if (s->b != s->p)
-    {
-      n = s->p - s->b;
-      string_need (p, n);
-      memcpy (p->p, s->b, n);
-      p->p += n;
-    }
-}
-
-static void
-string_appendn (string *p, const char *s, int n)
-{
-  if (n != 0)
-    {
-      string_need (p, n);
-      memcpy (p->p, s, n);
-      p->p += n;
-    }
-}
-
-static void
-string_prepend (string *p, const char *s)
-{
-  if (s != NULL && *s != '\0')
-    {
-      string_prependn (p, s, strlen (s));
-    }
-}
-
-static void
-string_prepends (string *p, string *s)
-{
-  if (s->b != s->p)
-    {
-      string_prependn (p, s->b, s->p - s->b);
-    }
-}
-
-static void
-string_prependn (string *p, const char *s, int n)
-{
-  char *q;
-
-  if (n != 0)
-    {
-      string_need (p, n);
-      for (q = p->p - 1; q >= p->b; q--)
-	{
-	  q[n] = q[0];
-	}
-      memcpy (p->b, s, n);
-      p->p += n;
-    }
-}
-
-static void
-string_append_template_idx (string *s, int idx)
-{
-  char buf[INTBUF_SIZE + 1 /* 'T' */];
-  sprintf(buf, "T%d", idx);
-  string_append (s, buf);
-}
diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog
index 5772008976e..644c57d1e35 100644
--- a/libiberty/ChangeLog
+++ b/libiberty/ChangeLog
@@ -1,3 +1,7 @@
+2018-11-20  Jason Merrill  <jason@redhat.com>
+
+	* cplus-dem.c (cplus_demangle): Turn off the old demangler.
+
 2018-12-07  Nick Clifton  <nickc@redhat.com>
 
 	PR 87681
diff --git a/libiberty/testsuite/demangle-expected b/libiberty/testsuite/demangle-expected
index 40038365c83..3723b7a90f1 100644
--- a/libiberty/testsuite/demangle-expected
+++ b/libiberty/testsuite/demangle-expected
@@ -20,3315 +20,64 @@
 # A line starting with `#' is ignored.
 # However, blank lines in this file are NOT ignored.
 #
---format=gnu --no-params
-AddAlignment__9ivTSolverUiP12ivInteractorP7ivTGlue
-ivTSolver::AddAlignment(unsigned int, ivInteractor *, ivTGlue *)
-ivTSolver::AddAlignment
 #
---format=gnu --no-params
-ArrowheadIntersects__9ArrowLineP9ArrowheadR6BoxObjP7Graphic
-ArrowLine::ArrowheadIntersects(Arrowhead *, BoxObj &, Graphic *)
-ArrowLine::ArrowheadIntersects
-#
---format=gnu --no-params
-ArrowheadIntersects__9ArrowLineP9ArrowheadO6BoxObjP7Graphic
-ArrowLine::ArrowheadIntersects(Arrowhead *, BoxObj &&, Graphic *)
-ArrowLine::ArrowheadIntersects
-#
---format=gnu --no-params
-AtEnd__13ivRubberGroup
-ivRubberGroup::AtEnd(void)
-ivRubberGroup::AtEnd
-#
---format=gnu --no-params
-BgFilter__9ivTSolverP12ivInteractor
-ivTSolver::BgFilter(ivInteractor *)
-ivTSolver::BgFilter
-#
---format=gnu --no-params
-Check__6UArrayi
-UArray::Check(int)
-UArray::Check
-#
---format=gnu --no-params
-CoreConstDecls__8TextCodeR7ostream
-TextCode::CoreConstDecls(ostream &)
-TextCode::CoreConstDecls
-#
---format=gnu --no-params
-CoreConstDecls__8TextCodeO7ostream
-TextCode::CoreConstDecls(ostream &&)
-TextCode::CoreConstDecls
-#
---format=gnu --no-params
-Detach__8StateVarP12StateVarView
-StateVar::Detach(StateVarView *)
-StateVar::Detach
-#
---format=gnu --no-params
-Done__9ComponentG8Iterator
-Component::Done(Iterator)
-Component::Done
-#
---format=gnu --no-params
-Effect__11RelateManipR7ivEvent
-RelateManip::Effect(ivEvent &)
-RelateManip::Effect
-#
---format=gnu --no-params
-Effect__11RelateManipO7ivEvent
-RelateManip::Effect(ivEvent &&)
-RelateManip::Effect
-#
---format=gnu --no-params
-FindFixed__FRP4CNetP4CNet
-FindFixed(CNet *&, CNet *)
-FindFixed
-#
---format=gnu --no-params
-FindFixed__FOP4CNetP4CNet
-FindFixed(CNet *&&, CNet *)
-FindFixed
-#
---format=gnu --no-params
-Fix48_abort__FR8twolongs
-Fix48_abort(twolongs &)
-Fix48_abort
-#
---format=gnu --no-params
-Fix48_abort__FO8twolongs
-Fix48_abort(twolongs &&)
-Fix48_abort
-#
---format=gnu --no-params
-GetBarInfo__15iv2_6_VScrollerP13ivPerspectiveRiT2
-iv2_6_VScroller::GetBarInfo(ivPerspective *, int &, int &)
-iv2_6_VScroller::GetBarInfo
-#
---format=gnu --no-params
-GetBarInfo__15iv2_6_VScrollerP13ivPerspectiveOiT2
-iv2_6_VScroller::GetBarInfo(ivPerspective *, int &&, int &&)
-iv2_6_VScroller::GetBarInfo
-#
---format=gnu --no-params
-GetBgColor__C9ivPainter
-ivPainter::GetBgColor(void) const
-ivPainter::GetBgColor
-#
---format=gnu --no-params
-InsertBody__15H_PullrightMenuii
-H_PullrightMenu::InsertBody(int, int)
-H_PullrightMenu::InsertBody
-#
---format=gnu --no-params
-InsertCharacter__9TextManipc
-TextManip::InsertCharacter(char)
-TextManip::InsertCharacter
-#
---format=gnu --no-params
-InsertToplevel__7ivWorldP12ivInteractorT1
-ivWorld::InsertToplevel(ivInteractor *, ivInteractor *)
-ivWorld::InsertToplevel
-#
---format=gnu --no-params
-InsertToplevel__7ivWorldP12ivInteractorT1iiUi
-ivWorld::InsertToplevel(ivInteractor *, ivInteractor *, int, int, unsigned int)
-ivWorld::InsertToplevel
-#
---format=gnu --no-params
-IsAGroup__FP11GraphicViewP11GraphicComp
-IsAGroup(GraphicView *, GraphicComp *)
-IsAGroup
-#
---format=gnu --no-params
-IsA__10ButtonCodeUl
-ButtonCode::IsA(unsigned long)
-ButtonCode::IsA
-#
---format=gnu --no-params
-ReadName__FR7istreamPc
-ReadName(istream &, char *)
-ReadName
-#
---format=gnu --no-params
-Redraw__13StringBrowseriiii
-StringBrowser::Redraw(int, int, int, int)
-StringBrowser::Redraw
-#
---format=gnu --no-params
-Rotate__13ivTransformerf
-ivTransformer::Rotate(float)
-ivTransformer::Rotate
-#
---format=gnu --no-params
-Rotated__C13ivTransformerf
-ivTransformer::Rotated(float) const
-ivTransformer::Rotated
-#
---format=gnu --no-params
-Round__Ff
-Round(float)
-Round
-#
---format=gnu --no-params
-SetExport__16MemberSharedNameUi
-MemberSharedName::SetExport(unsigned int)
-MemberSharedName::SetExport
-#
---format=gnu --no-params
-Set__14ivControlState13ControlStatusUi
-ivControlState::Set(ControlStatus, unsigned int)
-ivControlState::Set
-#
---format=gnu --no-params
-Set__5DFacePcii
-DFace::Set(char *, int, int)
-DFace::Set
-#
---format=gnu --no-params
-VConvert__9ivTSolverP12ivInteractorRP8TElementT2
-ivTSolver::VConvert(ivInteractor *, TElement *&, TElement *&)
-ivTSolver::VConvert
-#
---format=gnu --no-params
-VConvert__9ivTSolverP7ivTGlueRP8TElement
-ivTSolver::VConvert(ivTGlue *, TElement *&)
-ivTSolver::VConvert
-#
---format=gnu --no-params
-VOrder__9ivTSolverUiRP12ivInteractorT2
-ivTSolver::VOrder(unsigned int, ivInteractor *&, ivInteractor *&)
-ivTSolver::VOrder
-#
---format=gnu --no-params
-_10PageButton$__both
-PageButton::__both
-PageButton::__both
-#
---format=gnu --no-params
-_3RNG$singleMantissa
-RNG::singleMantissa
-RNG::singleMantissa
-#
---format=gnu --no-params
-_5IComp$_release
-IComp::_release
-IComp::_release
-#
---format=gnu --no-params
-_$_10BitmapComp
-BitmapComp::~BitmapComp(void)
-BitmapComp::~BitmapComp
-#
---format=gnu --no-params
-_$_9__io_defs
-__io_defs::~__io_defs(void)
-__io_defs::~__io_defs
-#
---format=gnu --no-params
-_$_Q23foo3bar
-foo::bar::~bar(void)
-foo::bar::~bar
-#
---format=gnu --no-params
-_$_Q33foo3bar4bell
-foo::bar::bell::~bell(void)
-foo::bar::bell::~bell
-#
---format=gnu --no-params
-__10ivTelltaleiP7ivGlyph
-ivTelltale::ivTelltale(int, ivGlyph *)
-ivTelltale::ivTelltale
-#
---format=gnu --no-params
-__10ivViewportiP12ivInteractorUi
-ivViewport::ivViewport(int, ivInteractor *, unsigned int)
-ivViewport::ivViewport
-#
---format=gnu --no-params
-__10ostrstream
-ostrstream::ostrstream(void)
-ostrstream::ostrstream
-#
---format=gnu --no-params
-__10ostrstreamPcii
-ostrstream::ostrstream(char *, int, int)
-ostrstream::ostrstream
-#
---format=gnu --no-params
-__11BitmapTablei
-BitmapTable::BitmapTable(int)
-BitmapTable::BitmapTable
-#
---format=gnu --no-params
-__12ViewportCodeP12ViewportComp
-ViewportCode::ViewportCode(ViewportComp *)
-ViewportCode::ViewportCode
-#
---format=gnu --no-params
-__12iv2_6_Borderii
-iv2_6_Border::iv2_6_Border(int, int)
-iv2_6_Border::iv2_6_Border
-#
---format=gnu --no-params
-__12ivBreak_Listl
-ivBreak_List::ivBreak_List(long)
-ivBreak_List::ivBreak_List
-#
---format=gnu --no-params
-__14iv2_6_MenuItemiP12ivInteractor
-iv2_6_MenuItem::iv2_6_MenuItem(int, ivInteractor *)
-iv2_6_MenuItem::iv2_6_MenuItem
-#
---format=gnu --no-params
-__20DisplayList_IteratorR11DisplayList
-DisplayList_Iterator::DisplayList_Iterator(DisplayList &)
-DisplayList_Iterator::DisplayList_Iterator
-#
---format=gnu --no-params
-__3fooRT0
-foo::foo(foo &)
-foo::foo
-#
---format=gnu --no-params
-__3fooiN31
-foo::foo(int, int, int, int)
-foo::foo
-#
---format=gnu --no-params
-__3fooiRT0iT2iT2
-foo::foo(int, foo &, int, foo &, int, foo &)
-foo::foo
-#
---format=gnu --no-params
-__6KeyMapPT0
-KeyMap::KeyMap(KeyMap *)
-KeyMap::KeyMap
-#
---format=gnu --no-params
-__8ArrowCmdP6EditorUiUi
-ArrowCmd::ArrowCmd(Editor *, unsigned int, unsigned int)
-ArrowCmd::ArrowCmd
-#
---format=gnu --no-params
-__9F_EllipseiiiiP7Graphic
-F_Ellipse::F_Ellipse(int, int, int, int, Graphic *)
-F_Ellipse::F_Ellipse
-#
---format=gnu --no-params
-__9FrameDataP9FrameCompi
-FrameData::FrameData(FrameComp *, int)
-FrameData::FrameData
-#
---format=gnu --no-params
-__9HVGraphicP9CanvasVarP7Graphic
-HVGraphic::HVGraphic(CanvasVar *, Graphic *)
-HVGraphic::HVGraphic
-#
---format=gnu --no-params
-__Q23foo3bar
-foo::bar::bar(void)
-foo::bar::bar
-#
---format=gnu --no-params
-__Q33foo3bar4bell
-foo::bar::bell::bell(void)
-foo::bar::bell::bell
-#
---format=gnu --no-params
-__aa__3fooRT0
-foo::operator&&(foo &)
-foo::operator&&
-#
---format=gnu --no-params
-__aad__3fooRT0
-foo::operator&=(foo &)
-foo::operator&=
-#
---format=gnu --no-params
-__ad__3fooRT0
-foo::operator&(foo &)
-foo::operator&
-#
---format=gnu --no-params
-__adv__3fooRT0
-foo::operator/=(foo &)
-foo::operator/=
-#
---format=gnu --no-params
-__aer__3fooRT0
-foo::operator^=(foo &)
-foo::operator^=
-#
---format=gnu --no-params
-__als__3fooRT0
-foo::operator<<=(foo &)
-foo::operator<<=
-#
---format=gnu --no-params
-__amd__3fooRT0
-foo::operator%=(foo &)
-foo::operator%=
-#
---format=gnu --no-params
-__ami__3fooRT0
-foo::operator-=(foo &)
-foo::operator-=
-#
---format=gnu --no-params
-__aml__3FixRT0
-Fix::operator*=(Fix &)
-Fix::operator*=
-#
---format=gnu --no-params
-__aml__5Fix16i
-Fix16::operator*=(int)
-Fix16::operator*=
-#
---format=gnu --no-params
-__aml__5Fix32RT0
-Fix32::operator*=(Fix32 &)
-Fix32::operator*=
-#
---format=gnu --no-params
-__aor__3fooRT0
-foo::operator|=(foo &)
-foo::operator|=
-#
---format=gnu --no-params
-__apl__3fooRT0
-foo::operator+=(foo &)
-foo::operator+=
-#
---format=gnu --no-params
-__ars__3fooRT0
-foo::operator>>=(foo &)
-foo::operator>>=
-#
---format=gnu --no-params
-__as__3fooRT0
-foo::operator=(foo &)
-foo::operator=
-#
---format=gnu --no-params
-__cl__3fooRT0
-foo::operator()(foo &)
-foo::operator()
-#
---format=gnu --no-params
-__cl__6Normal
-Normal::operator()(void)
-Normal::operator()
-#
---format=gnu --no-params
-__cl__6Stringii
-String::operator()(int, int)
-String::operator()
-#
---format=gnu --no-params
-__cm__3fooRT0
-foo::operator, (foo &)
-foo::operator, 
-#
---format=gnu --no-params
-__co__3foo
-foo::operator~(void)
-foo::operator~
-#
---format=gnu --no-params
-__dl__3fooPv
-foo::operator delete(void *)
-foo::operator delete
-#
---format=gnu --no-params
-__dv__3fooRT0
-foo::operator/(foo &)
-foo::operator/
-#
---format=gnu --no-params
-__eq__3fooRT0
-foo::operator==(foo &)
-foo::operator==
-#
---format=gnu --no-params
-__er__3fooRT0
-foo::operator^(foo &)
-foo::operator^
-#
---format=gnu --no-params
-__ge__3fooRT0
-foo::operator>=(foo &)
-foo::operator>=
-#
---format=gnu --no-params
-__gt__3fooRT0
-foo::operator>(foo &)
-foo::operator>
-#
---format=gnu --no-params
-__le__3fooRT0
-foo::operator<=(foo &)
-foo::operator<=
-#
---format=gnu --no-params
-__ls__3fooRT0
-foo::operator<<(foo &)
-foo::operator<<
-#
---format=gnu --no-params
-__ls__FR7ostreamPFR3ios_R3ios
-operator<<(ostream &, ios &(*)(ios &))
-operator<<
-#
---format=gnu --no-params
-__ls__FR7ostreamR3Fix
-operator<<(ostream &, Fix &)
-operator<<
-#
---format=gnu --no-params
-__lt__3fooRT0
-foo::operator<(foo &)
-foo::operator<
-#
---format=gnu --no-params
-__md__3fooRT0
-foo::operator%(foo &)
-foo::operator%
-#
---format=gnu --no-params
-__mi__3fooRT0
-foo::operator-(foo &)
-foo::operator-
-#
---format=gnu --no-params
-__ml__3fooRT0
-foo::operator*(foo &)
-foo::operator*
-#
---format=gnu --no-params
-__mm__3fooi
-foo::operator--(int)
-foo::operator--
-#
---format=gnu --no-params
-__ne__3fooRT0
-foo::operator!=(foo &)
-foo::operator!=
-#
---format=gnu --no-params
-__nt__3foo
-foo::operator!(void)
-foo::operator!
-#
---format=gnu --no-params
-__nw__3fooi
-foo::operator new(int)
-foo::operator new
-#
---format=gnu --no-params
-__oo__3fooRT0
-foo::operator||(foo &)
-foo::operator||
-#
---format=gnu --no-params
-__opPc__3foo
-foo::operator char *(void)
-foo::operator char *
-#
---format=gnu --no-params
-__opi__3foo
-foo::operator int(void)
-foo::operator int
-#
---format=gnu --no-params
-__or__3fooRT0
-foo::operator|(foo &)
-foo::operator|
-#
---format=gnu --no-params
-__pl__3fooRT0
-foo::operator+(foo &)
-foo::operator+
-#
---format=gnu --no-params
-__pp__3fooi
-foo::operator++(int)
-foo::operator++
-#
---format=gnu --no-params
-__rf__3foo
-foo::operator->(void)
-foo::operator->
-#
---format=gnu --no-params
-__rm__3fooRT0
-foo::operator->*(foo &)
-foo::operator->*
-#
---format=gnu --no-params
-__rs__3fooRT0
-foo::operator>>(foo &)
-foo::operator>>
-#
---format=gnu --no-params
-_new_Fix__FUs
-_new_Fix(unsigned short)
-_new_Fix
-#
---format=gnu --no-params
-_vt.foo
-foo virtual table
-foo virtual table
-#
---format=gnu --no-params
-_vt.foo.bar
-foo::bar virtual table
-foo::bar virtual table
-#
---format=gnu --no-params
-_vt$foo
-foo virtual table
-foo virtual table
-#
---format=gnu --no-params
-_vt$foo$bar
-foo::bar virtual table
-foo::bar virtual table
-#
---format=gnu --no-params
-append__7ivGlyphPT0
-ivGlyph::append(ivGlyph *)
-ivGlyph::append
-#
---format=gnu --no-params
-clearok__FP7_win_sti
-clearok(_win_st *, int)
-clearok
-#
---format=gnu --no-params
-complexfunc2__FPFPc_i
-complexfunc2(int (*)(char *))
-complexfunc2
-#
---format=gnu --no-params
-complexfunc3__FPFPFPl_s_i
-complexfunc3(int (*)(short (*)(long *)))
-complexfunc3
-#
---format=gnu --no-params
-complexfunc4__FPFPFPc_s_i
-complexfunc4(int (*)(short (*)(char *)))
-complexfunc4
-#
---format=gnu --no-params
-complexfunc5__FPFPc_PFl_i
-complexfunc5(int (*(*)(char *))(long))
-complexfunc5
-#
---format=gnu --no-params
-complexfunc6__FPFPi_PFl_i
-complexfunc6(int (*(*)(int *))(long))
-complexfunc6
-#
---format=gnu --no-params
-complexfunc7__FPFPFPc_i_PFl_i
-complexfunc7(int (*(*)(int (*)(char *)))(long))
-complexfunc7
-#
---format=gnu --no-params
-foo__FiN30
-foo(int, int, int, int)
-foo
-#
---format=gnu --no-params
-foo__FiR3fooiT1iT1
-foo(int, foo &, int, foo &, int, foo &)
-foo
-#
---format=gnu --no-params
-foo___3barl
-bar::foo_(long)
-bar::foo_
-#
---format=gnu --no-params
-insert__15ivClippingStacklRP8_XRegion
-ivClippingStack::insert(long, _XRegion *&)
-ivClippingStack::insert
-#
---format=gnu --no-params
-insert__16ChooserInfo_ListlR11ChooserInfo
-ChooserInfo_List::insert(long, ChooserInfo &)
-ChooserInfo_List::insert
-#
---format=gnu --no-params
-insert__17FontFamilyRepListlRP15ivFontFamilyRep
-FontFamilyRepList::insert(long, ivFontFamilyRep *&)
-FontFamilyRepList::insert
-#
---format=gnu --no-params
-leaveok__FP7_win_stc
-leaveok(_win_st *, char)
-leaveok
-#
---format=gnu --no-params
-left_mover__C7ivMFKitP12ivAdjustableP7ivStyle
-ivMFKit::left_mover(ivAdjustable *, ivStyle *) const
-ivMFKit::left_mover
-#
---format=gnu --no-params
-overload1arg__FSc
-overload1arg(signed char)
-overload1arg
-#
---format=gnu --no-params
-overload1arg__FUc
-overload1arg(unsigned char)
-overload1arg
-#
---format=gnu --no-params
-overload1arg__FUi
-overload1arg(unsigned int)
-overload1arg
-#
---format=gnu --no-params
-overload1arg__FUl
-overload1arg(unsigned long)
-overload1arg
-#
---format=gnu --no-params
-overload1arg__FUs
-overload1arg(unsigned short)
-overload1arg
-#
---format=gnu --no-params
-overload1arg__Fc
-overload1arg(char)
-overload1arg
-#
---format=gnu --no-params
-overload1arg__Fd
-overload1arg(double)
-overload1arg
-#
---format=gnu --no-params
-overload1arg__Ff
-overload1arg(float)
-overload1arg
-#
---format=gnu --no-params
-overload1arg__Fi
-overload1arg(int)
-overload1arg
-#
---format=gnu --no-params
-overload1arg__Fl
-overload1arg(long)
-overload1arg
-#
---format=gnu --no-params
-overload1arg__Fs
-overload1arg(short)
-overload1arg
-#
---format=gnu --no-params
-overload1arg__Fv
-overload1arg(void)
-overload1arg
-#
---format=gnu --no-params
-overloadargs__Fi
-overloadargs(int)
-overloadargs
-#
---format=gnu --no-params
-overloadargs__Fii
-overloadargs(int, int)
-overloadargs
-#
---format=gnu --no-params
-overloadargs__Fiii
-overloadargs(int, int, int)
-overloadargs
-#
---format=gnu --no-params
-overloadargs__Fiiii
-overloadargs(int, int, int, int)
-overloadargs
-#
---format=gnu --no-params
-overloadargs__Fiiiii
-overloadargs(int, int, int, int, int)
-overloadargs
-#
---format=gnu --no-params
-overloadargs__Fiiiiii
-overloadargs(int, int, int, int, int, int)
-overloadargs
-#
---format=gnu --no-params
-overloadargs__Fiiiiiii
-overloadargs(int, int, int, int, int, int, int)
-overloadargs
-#
---format=gnu --no-params
-overloadargs__Fiiiiiiii
-overloadargs(int, int, int, int, int, int, int, int)
-overloadargs
-#
---format=gnu --no-params
-overloadargs__Fiiiiiiiii
-overloadargs(int, int, int, int, int, int, int, int, int)
-overloadargs
-#
---format=gnu --no-params
-overloadargs__Fiiiiiiiiii
-overloadargs(int, int, int, int, int, int, int, int, int, int)
-overloadargs
-#
---format=gnu --no-params
-overloadargs__Fiiiiiiiiiii
-overloadargs(int, int, int, int, int, int, int, int, int, int, int)
-overloadargs
-#
---format=gnu --no-params
-poke__8ivRasterUlUlffff
-ivRaster::poke(unsigned long, unsigned long, float, float, float, float)
-ivRaster::poke
-#
---format=gnu --no-params
-polar__Fdd
-polar(double, double)
-polar
-#
---format=gnu --no-params
-scale__13ivTransformerff
-ivTransformer::scale(float, float)
-ivTransformer::scale
-#
---format=gnu --no-params
-sgetn__7filebufPci
-filebuf::sgetn(char *, int)
-filebuf::sgetn
-#
---format=gnu --no-params
-shift__FP5_FrepiT0
-shift(_Frep *, int, _Frep *)
-shift
-#
---format=gnu --no-params
-test__C6BitSeti
-BitSet::test(int) const
-BitSet::test
-#
---format=gnu --no-params
-test__C6BitSetii
-BitSet::test(int, int) const
-BitSet::test
-#
---format=gnu --no-params
-text_source__8Documentl
-Document::text_source(long)
-Document::text_source
-#
---format=gnu --no-params
-variance__6Erlangd
-Erlang::variance(double)
-Erlang::variance
-#
---format=gnu --no-params
-view__14DocumentViewerP8ItemViewP11TabularItem
-DocumentViewer::view(ItemView *, TabularItem *)
-DocumentViewer::view
-#
---format=gnu --no-params
-xy_extents__11ivExtensionffff
-ivExtension::xy_extents(float, float, float, float)
-ivExtension::xy_extents
-#
---format=gnu --no-params
-zero__8osMemoryPvUi
-osMemory::zero(void *, unsigned int)
-osMemory::zero
-#
---format=gnu --no-params
-_2T4$N
-T4::N
-T4::N
-#
---format=gnu --no-params
-_Q22T42t1$N
-T4::t1::N
-T4::t1::N
-#
---format=gnu --no-params
-get__2T1
-T1::get(void)
-T1::get
-#
---format=gnu --no-params
-get__Q22T11a
-T1::a::get(void)
-T1::a::get
-#
---format=gnu --no-params
-get__Q32T11a1b
-T1::a::b::get(void)
-T1::a::b::get
-#
---format=gnu --no-params
-get__Q42T11a1b1c
-T1::a::b::c::get(void)
-T1::a::b::c::get
-#
---format=gnu --no-params
-get__Q52T11a1b1c1d
-T1::a::b::c::d::get(void)
-T1::a::b::c::d::get
-#
---format=gnu --no-params
-put__2T1i
-T1::put(int)
-T1::put
-#
---format=gnu --no-params
-put__Q22T11ai
-T1::a::put(int)
-T1::a::put
-#
---format=gnu --no-params
-put__Q32T11a1bi
-T1::a::b::put(int)
-T1::a::b::put
-#
---format=gnu --no-params
-put__Q42T11a1b1ci
-T1::a::b::c::put(int)
-T1::a::b::c::put
-#
---format=gnu --no-params
-put__Q52T11a1b1c1di
-T1::a::b::c::d::put(int)
-T1::a::b::c::d::put
-#
---format=gnu --no-params
-bar__3fooPv
-foo::bar(void *)
-foo::bar
-#
---format=gnu --no-params
-bar__C3fooPv
-foo::bar(void *) const
-foo::bar
-#
---format=gnu --no-params
-__eq__3fooRT0
-foo::operator==(foo &)
-foo::operator==
-#
---format=gnu --no-params
-__eq__C3fooR3foo
-foo::operator==(foo &) const
-foo::operator==
-#
---format=gnu --no-params
-elem__t6vector1Zdi
-vector<double>::elem(int)
-vector<double>::elem
-#
---format=gnu --no-params
-elem__t6vector1Zii
-vector<int>::elem(int)
-vector<int>::elem
-#
---format=gnu --no-params
-__t6vector1Zdi
-vector<double>::vector(int)
-vector<double>::vector
-#
---format=gnu --no-params
-__t6vector1Zii
-vector<int>::vector(int)
-vector<int>::vector
-#
---format=gnu --no-params
-_$_t6vector1Zdi
-vector<double>::~vector(int)
-vector<double>::~vector
-#
---format=gnu --no-params
-_$_t6vector1Zii
-vector<int>::~vector(int)
-vector<int>::~vector
-#
---format=gnu --no-params
-__nw__t2T11ZcUi
-T1<char>::operator new(unsigned int)
-T1<char>::operator new
-#
---format=gnu --no-params
-__nw__t2T11Z1tUi
-T1<t>::operator new(unsigned int)
-T1<t>::operator new
-#
---format=gnu --no-params
-__dl__t2T11ZcPv
-T1<char>::operator delete(void *)
-T1<char>::operator delete
-#
---format=gnu --no-params
-__dl__t2T11Z1tPv
-T1<t>::operator delete(void *)
-T1<t>::operator delete
-#
---format=gnu --no-params
-__t2T11Zci
-T1<char>::T1(int)
-T1<char>::T1
-#
---format=gnu --no-params
-__t2T11Zc
-T1<char>::T1(void)
-T1<char>::T1
-#
---format=gnu --no-params
-__t2T11Z1ti
-T1<t>::T1(int)
-T1<t>::T1
-#
---format=gnu --no-params
-__t2T11Z1t
-T1<t>::T1(void)
-T1<t>::T1
-#
---format=gnu --no-params
-__Q2t4List1Z10VHDLEntity3Pix
-List<VHDLEntity>::Pix::Pix(void)
-List<VHDLEntity>::Pix::Pix
-#
---format=gnu --no-params
-__Q2t4List1Z10VHDLEntity3PixPQ2t4List1Z10VHDLEntity7element
-List<VHDLEntity>::Pix::Pix(List<VHDLEntity>::element *)
-List<VHDLEntity>::Pix::Pix
-#
---format=gnu --no-params
-__Q2t4List1Z10VHDLEntity3PixRCQ2t4List1Z10VHDLEntity3Pix
-List<VHDLEntity>::Pix::Pix(List<VHDLEntity>::Pix const &)
-List<VHDLEntity>::Pix::Pix
-#
---format=gnu --no-params
-__Q2t4List1Z10VHDLEntity3PixOCQ2t4List1Z10VHDLEntity3Pix
-List<VHDLEntity>::Pix::Pix(List<VHDLEntity>::Pix const &&)
-List<VHDLEntity>::Pix::Pix
-#
---format=gnu --no-params
-__Q2t4List1Z10VHDLEntity7elementRC10VHDLEntityPT0
-List<VHDLEntity>::element::element(VHDLEntity const &, List<VHDLEntity>::element *)
-List<VHDLEntity>::element::element
-#
---format=gnu --no-params
-__Q2t4List1Z10VHDLEntity7elementOC10VHDLEntityPT0
-List<VHDLEntity>::element::element(VHDLEntity const &&, List<VHDLEntity>::element *)
-List<VHDLEntity>::element::element
-#
---format=gnu --no-params
-__Q2t4List1Z10VHDLEntity7elementRCQ2t4List1Z10VHDLEntity7element
-List<VHDLEntity>::element::element(List<VHDLEntity>::element const &)
-List<VHDLEntity>::element::element
-#
---format=gnu --no-params
-__cl__C11VHDLLibraryGt4PixX3Z11VHDLLibraryZ14VHDLLibraryRepZt4List1Z10VHDLEntity
-VHDLLibrary::operator()(PixX<VHDLLibrary, VHDLLibraryRep, List<VHDLEntity> >) const
-VHDLLibrary::operator()
-#
---format=gnu --no-params
-__cl__Ct4List1Z10VHDLEntityRCQ2t4List1Z10VHDLEntity3Pix
-List<VHDLEntity>::operator()(List<VHDLEntity>::Pix const &) const
-List<VHDLEntity>::operator()
-#
---format=gnu --no-params
-__ne__FPvRCQ2t4List1Z10VHDLEntity3Pix
-operator!=(void *, List<VHDLEntity>::Pix const &)
-operator!=
-#
---format=gnu --no-params
-__ne__FPvRCt4PixX3Z11VHDLLibraryZ14VHDLLibraryRepZt4List1Z10VHDLEntity
-operator!=(void *, PixX<VHDLLibrary, VHDLLibraryRep, List<VHDLEntity> > const &)
-operator!=
-#
---format=gnu --no-params
-__t4List1Z10VHDLEntityRCt4List1Z10VHDLEntity
-List<VHDLEntity>::List(List<VHDLEntity> const &)
-List<VHDLEntity>::List
-#
---format=gnu --no-params
-__t4PixX3Z11VHDLLibraryZ14VHDLLibraryRepZt4List1Z10VHDLEntity
-PixX<VHDLLibrary, VHDLLibraryRep, List<VHDLEntity> >::PixX(void)
-PixX<VHDLLibrary, VHDLLibraryRep, List<VHDLEntity> >::PixX
-#
---format=gnu --no-params
-__t4PixX3Z11VHDLLibraryZ14VHDLLibraryRepZt4List1Z10VHDLEntityP14VHDLLibraryRepGQ2t4List1Z10VHDLEntity3Pix
-PixX<VHDLLibrary, VHDLLibraryRep, List<VHDLEntity> >::PixX(VHDLLibraryRep *, List<VHDLEntity>::Pix)
-PixX<VHDLLibrary, VHDLLibraryRep, List<VHDLEntity> >::PixX
-#
---format=gnu --no-params
-__t4PixX3Z11VHDLLibraryZ14VHDLLibraryRepZt4List1Z10VHDLEntityRCt4PixX3Z11VHDLLibraryZ14VHDLLibraryRepZt4List1Z10VHDLEntity
-PixX<VHDLLibrary, VHDLLibraryRep, List<VHDLEntity> >::PixX(PixX<VHDLLibrary, VHDLLibraryRep, List<VHDLEntity> > const &)
-PixX<VHDLLibrary, VHDLLibraryRep, List<VHDLEntity> >::PixX
-#
---format=gnu --no-params
-__t4PixX3Z11VHDLLibraryZ14VHDLLibraryRepZt4List1Z10VHDLEntityOCt4PixX3Z11VHDLLibraryZ14VHDLLibraryRepZt4List1Z10VHDLEntity
-PixX<VHDLLibrary, VHDLLibraryRep, List<VHDLEntity> >::PixX(PixX<VHDLLibrary, VHDLLibraryRep, List<VHDLEntity> > const &&)
-PixX<VHDLLibrary, VHDLLibraryRep, List<VHDLEntity> >::PixX
-#
---format=gnu --no-params
-nextE__C11VHDLLibraryRt4PixX3Z11VHDLLibraryZ14VHDLLibraryRepZt4List1Z10VHDLEntity
-VHDLLibrary::nextE(PixX<VHDLLibrary, VHDLLibraryRep, List<VHDLEntity> > &) const
-VHDLLibrary::nextE
-#
---format=gnu --no-params
-next__Ct4List1Z10VHDLEntityRQ2t4List1Z10VHDLEntity3Pix
-List<VHDLEntity>::next(List<VHDLEntity>::Pix &) const
-List<VHDLEntity>::next
-#
---format=gnu --no-params
-_GLOBAL_$D$set
-global destructors keyed to set
-global destructors keyed to set
-#
---format=gnu --no-params
-_GLOBAL_$I$set
-global constructors keyed to set
-global constructors keyed to set
-#
---format=gnu --no-params
-__as__t5ListS1ZUiRCt5ListS1ZUi
-ListS<unsigned int>::operator=(ListS<unsigned int> const &)
-ListS<unsigned int>::operator=
-#
---format=gnu --no-params
-__cl__Ct5ListS1ZUiRCQ2t5ListS1ZUi3Vix
-ListS<unsigned int>::operator()(ListS<unsigned int>::Vix const &) const
-ListS<unsigned int>::operator()
-#
---format=gnu --no-params
-__cl__Ct5SetLS1ZUiRCQ2t5SetLS1ZUi3Vix
-SetLS<unsigned int>::operator()(SetLS<unsigned int>::Vix const &) const
-SetLS<unsigned int>::operator()
-#
---format=gnu --no-params
-__t10ListS_link1ZUiRCUiPT0
-ListS_link<unsigned int>::ListS_link(unsigned int const &, ListS_link<unsigned int> *)
-ListS_link<unsigned int>::ListS_link
-#
---format=gnu --no-params
-__t10ListS_link1ZUiRCt10ListS_link1ZUi
-ListS_link<unsigned int>::ListS_link(ListS_link<unsigned int> const &)
-ListS_link<unsigned int>::ListS_link
-#
---format=gnu --no-params
-__t5ListS1ZUiRCt5ListS1ZUi
-ListS<unsigned int>::ListS(ListS<unsigned int> const &)
-ListS<unsigned int>::ListS
-#
---format=gnu --no-params
-next__Ct5ListS1ZUiRQ2t5ListS1ZUi3Vix
-ListS<unsigned int>::next(ListS<unsigned int>::Vix &) const
-ListS<unsigned int>::next
-#
---format=gnu --no-params
-__ne__FPvRCQ2t5SetLS1ZUi3Vix
-operator!=(void *, SetLS<unsigned int>::Vix const &)
-operator!=
-#
---format=gnu --no-params
-__t8ListElem1Z5LabelRt4List1Z5Label
-ListElem<Label>::ListElem(List<Label> &)
-ListElem<Label>::ListElem
-#
---format=gnu --no-params
-__t8BDDHookV1ZPcRCPc
-BDDHookV<char *>::BDDHookV(char *const &)
-BDDHookV<char *>::BDDHookV
-#
---format=gnu --no-params
-_vt$t8BDDHookV1ZPc
-BDDHookV<char *> virtual table
-BDDHookV<char *> virtual table
-#
---format=gnu --no-params
-__ne__FPvRCQ211BDDFunction4VixB
-operator!=(void *, BDDFunction::VixB const &)
-operator!=
-#
---format=gnu --no-params
-__eq__FPvRCQ211BDDFunction4VixB
-operator==(void *, BDDFunction::VixB const &)
-operator==
-#
---format=gnu --no-params
-relativeId__CQ36T_phi210T_preserve8FPC_nextRCQ26T_phi210T_preserveRC10Parameters
-T_phi2::T_preserve::FPC_next::relativeId(T_phi2::T_preserve const &, Parameters const &) const
-T_phi2::T_preserve::FPC_next::relativeId
-#
---format=lucid --no-params
-WS__FR7istream
-WS(istream &)
-WS
-#
---format=lucid --no-params
-__aa__3fooFR3foo
-foo::operator&&(foo &)
-foo::operator&&
-#
---format=lucid --no-params
-__aad__3fooFR3foo
-foo::operator&=(foo &)
-foo::operator&=
-#
---format=lucid --no-params
-__ad__3fooFR3foo
-foo::operator&(foo &)
-foo::operator&
-#
---format=lucid --no-params
-__adv__3fooFR3foo
-foo::operator/=(foo &)
-foo::operator/=
-#
---format=lucid --no-params
-__adv__7complexF7complex
-complex::operator/=(complex)
-complex::operator/=
-#
---format=lucid --no-params
-__aer__3fooFR3foo
-foo::operator^=(foo &)
-foo::operator^=
-#
---format=lucid --no-params
-__als__3fooFR3foo
-foo::operator<<=(foo &)
-foo::operator<<=
-#
---format=lucid --no-params
-__amd__3fooFR3foo
-foo::operator%=(foo &)
-foo::operator%=
-#
---format=lucid --no-params
-__ami__3fooFR3foo
-foo::operator-=(foo &)
-foo::operator-=
-#
---format=lucid --no-params
-__amu__3fooFR3foo
-foo::operator*=(foo &)
-foo::operator*=
-#
---format=lucid --no-params
-__amu__7complexF7complex
-complex::operator*=(complex)
-complex::operator*=
-#
---format=lucid --no-params
-__aor__3fooFR3foo
-foo::operator|=(foo &)
-foo::operator|=
-#
---format=lucid --no-params
-__apl__3fooFR3foo
-foo::operator+=(foo &)
-foo::operator+=
-#
---format=lucid --no-params
-__ars__3fooFR3foo
-foo::operator>>=(foo &)
-foo::operator>>=
-#
---format=lucid --no-params
-__as__18istream_withassignFP9streambuf
-istream_withassign::operator=(streambuf *)
-istream_withassign::operator=
-#
---format=lucid --no-params
-__as__18istream_withassignFR7istream
-istream_withassign::operator=(istream &)
-istream_withassign::operator=
-#
---format=lucid --no-params
-__as__3fooFR3foo
-foo::operator=(foo &)
-foo::operator=
-#
---format=lucid --no-params
-__as__3iosFR3ios
-ios::operator=(ios &)
-ios::operator=
-#
---format=lucid --no-params
-__cl__3fooFR3foo
-foo::operator()(foo &)
-foo::operator()
-#
---format=lucid --no-params
-__cm__3fooFR3foo
-foo::operator, (foo &)
-foo::operator, 
-#
---format=lucid --no-params
-__co__3fooFv
-foo::operator~(void)
-foo::operator~
-#
---format=lucid --no-params
-__ct__10istrstreamFPc
-istrstream::istrstream(char *)
-istrstream::istrstream
-#
---format=lucid --no-params
-__ct__10istrstreamFPci
-istrstream::istrstream(char *, int)
-istrstream::istrstream
-#
---format=lucid --no-params
-__ct__10ostrstreamFPciT2
-ostrstream::ostrstream(char *, int, int)
-ostrstream::ostrstream
-#
---format=lucid --no-params
-__ct__10ostrstreamFv
-ostrstream::ostrstream(void)
-ostrstream::ostrstream
-#
---format=lucid --no-params
-__ct__10smanip_intFPFR3iosi_R3iosi
-smanip_int::smanip_int(ios &(*)(ios &, int), int)
-smanip_int::smanip_int
-#
---format=lucid --no-params
-__ct__10smanip_intFPFO3iosi_O3iosi
-smanip_int::smanip_int(ios &&(*)(ios &&, int), int)
-smanip_int::smanip_int
-#
---format=lucid --no-params
-__ct__11fstreambaseFi
-fstreambase::fstreambase(int)
-fstreambase::fstreambase
-#
---format=lucid --no-params
-__ct__11fstreambaseFiPcT1
-fstreambase::fstreambase(int, char *, int)
-fstreambase::fstreambase
-#
---format=lucid --no-params
-__ct__11fstreambaseFv
-fstreambase::fstreambase(void)
-fstreambase::fstreambase
-#
---format=lucid --no-params
-__ct__11smanip_longFPFR3iosl_R3iosl
-smanip_long::smanip_long(ios &(*)(ios &, long), long)
-smanip_long::smanip_long
-#
---format=lucid --no-params
-__ct__11smanip_longFPFO3iosl_O3iosl
-smanip_long::smanip_long(ios &&(*)(ios &&, long), long)
-smanip_long::smanip_long
-#
---format=lucid --no-params
-__ct__11stdiostreamFP4FILE
-stdiostream::stdiostream(FILE *)
-stdiostream::stdiostream
-#
---format=lucid --no-params
-__ct__12strstreambufFPFl_PvPFPv_v
-strstreambuf::strstreambuf(void *(*)(long), void (*)(void *))
-strstreambuf::strstreambuf
-#
---format=lucid --no-params
-__ct__12strstreambufFPUciT1
-strstreambuf::strstreambuf(unsigned char *, int, unsigned char *)
-strstreambuf::strstreambuf
-#
---format=lucid --no-params
-__ct__12strstreambufFPciT1
-strstreambuf::strstreambuf(char *, int, char *)
-strstreambuf::strstreambuf
-#
---format=lucid --no-params
-__ct__12strstreambufFi
-strstreambuf::strstreambuf(int)
-strstreambuf::strstreambuf
-#
---format=lucid --no-params
-__ct__12strstreambufFv
-strstreambuf::strstreambuf(void)
-strstreambuf::strstreambuf
-#
---format=lucid --no-params
-__ct__13strstreambaseFPciT1
-strstreambase::strstreambase(char *, int, char *)
-strstreambase::strstreambase
-#
---format=lucid --no-params
-__ct__3fooFR3foo
-foo::foo(foo &)
-foo::foo
-#
---format=lucid --no-params
-__ct__3fooFO3foo
-foo::foo(foo &&)
-foo::foo
-#
---format=lucid --no-params
-__ct__3fooFi
-foo::foo(int)
-foo::foo
-#
---format=lucid --no-params
-__ct__3fooFiN31
-foo::foo(int, int, int, int)
-foo::foo
-#
---format=lucid --no-params
-__ct__3fooFiR3fooT1T2T1T2
-foo::foo(int, foo &, int, foo &, int, foo &)
-foo::foo
-#
---format=lucid --no-params
-__ct__3fooFiO3fooT1T2T1T2
-foo::foo(int, foo &&, int, foo &&, int, foo &&)
-foo::foo
-#
---format=lucid --no-params
-__ct__3iosFP9streambuf
-ios::ios(streambuf *)
-ios::ios
-#
---format=lucid --no-params
-__ct__7filebufFiPcT1
-filebuf::filebuf(int, char *, int)
-filebuf::filebuf
-#
---format=lucid --no-params
-__ct__7fstreamFiPcT1
-fstream::fstream(int, char *, int)
-fstream::fstream
-#
---format=lucid --no-params
-__ct__7istreamFP9streambuf
-istream::istream(streambuf *)
-istream::istream
-#
---format=lucid --no-params
-__ct__7istreamFP9streambufiP7ostream
-istream::istream(streambuf *, int, ostream *)
-istream::istream
-#
---format=lucid --no-params
-__ct__7istreamFiPcT1
-istream::istream(int, char *, int)
-istream::istream
-#
---format=lucid --no-params
-__ct__7istreamFiT1P7ostream
-istream::istream(int, int, ostream *)
-istream::istream
-#
---format=lucid --no-params
-__ct__7ostreamFP9streambuf
-ostream::ostream(streambuf *)
-ostream::ostream
-#
---format=lucid --no-params
-__ct__7ostreamFiPc
-ostream::ostream(int, char *)
-ostream::ostream
-#
---format=lucid --no-params
-__ct__8ifstreamFiPcT1
-ifstream::ifstream(int, char *, int)
-ifstream::ifstream
-#
---format=lucid --no-params
-__ct__Q23foo3barFv
-foo::bar::bar(void)
-foo::bar::bar
-#
---format=lucid --no-params
-__ct__Q33foo3bar4bellFv
-foo::bar::bell::bell(void)
-foo::bar::bell::bell
-#
---format=lucid --no-params
-__dl__3fooSFPv
-foo::operator delete(void *) static
-foo::operator delete
-#
---format=lucid --no-params
-__dl__FPv
-operator delete(void *)
-operator delete
-#
---format=lucid --no-params
-__dt__10istrstreamFv
-istrstream::~istrstream(void)
-istrstream::~istrstream
-#
---format=lucid --no-params
-__dt__Q23foo3barFv
-foo::bar::~bar(void)
-foo::bar::~bar
-#
---format=lucid --no-params
-__dt__Q33foo3bar4bellFv
-foo::bar::bell::~bell(void)
-foo::bar::bell::~bell
-#
---format=lucid --no-params
-__dv__3fooFR3foo
-foo::operator/(foo &)
-foo::operator/
-#
---format=lucid --no-params
-__dv__F7complexT1
-operator/(complex, complex)
-operator/
-#
---format=lucid --no-params
-__eq__3fooFR3foo
-foo::operator==(foo &)
-foo::operator==
-#
---format=lucid --no-params
-__er__3fooFR3foo
-foo::operator^(foo &)
-foo::operator^
-#
---format=lucid --no-params
-__ge__3fooFR3foo
-foo::operator>=(foo &)
-foo::operator>=
-#
---format=lucid --no-params
-__gt__3fooFR3foo
-foo::operator>(foo &)
-foo::operator>
-#
---format=lucid --no-params
-__le__3fooFR3foo
-foo::operator<=(foo &)
-foo::operator<=
-#
---format=lucid --no-params
-__ls__3fooFR3foo
-foo::operator<<(foo &)
-foo::operator<<
-#
---format=lucid --no-params
-__ls__7ostreamFP9streambuf
-ostream::operator<<(streambuf *)
-ostream::operator<<
-#
---format=lucid --no-params
-__ls__7ostreamFPFR3ios_R3ios
-ostream::operator<<(ios &(*)(ios &))
-ostream::operator<<
-#
---format=lucid --no-params
-__ls__7ostreamFPv
-ostream::operator<<(void *)
-ostream::operator<<
-#
---format=lucid --no-params
-__ls__7ostreamFUi
-ostream::operator<<(unsigned int)
-ostream::operator<<
-#
---format=lucid --no-params
-__ls__7ostreamFUl
-ostream::operator<<(unsigned long)
-ostream::operator<<
-#
---format=lucid --no-params
-__ls__7ostreamFd
-ostream::operator<<(double)
-ostream::operator<<
-#
---format=lucid --no-params
-__ls__7ostreamFf
-ostream::operator<<(float)
-ostream::operator<<
-#
---format=lucid --no-params
-__ls__7ostreamFi
-ostream::operator<<(int)
-ostream::operator<<
-#
---format=lucid --no-params
-__ls__7ostreamFl
-ostream::operator<<(long)
-ostream::operator<<
-#
---format=lucid --no-params
-__ls__FR7ostream7complex
-operator<<(ostream &, complex)
-operator<<
-#
---format=lucid --no-params
-__lt__3fooFR3foo
-foo::operator<(foo &)
-foo::operator<
-#
---format=lucid --no-params
-__md__3fooFR3foo
-foo::operator%(foo &)
-foo::operator%
-#
---format=lucid --no-params
-__mi__3fooFR3foo
-foo::operator-(foo &)
-foo::operator-
-#
---format=lucid --no-params
-__ml__3fooFR3foo
-foo::operator*(foo &)
-foo::operator*
-#
---format=lucid --no-params
-__ml__F7complexT1
-operator*(complex, complex)
-operator*
-#
---format=lucid --no-params
-__mm__3fooFi
-foo::operator--(int)
-foo::operator--
-#
---format=lucid --no-params
-__ne__3fooFR3foo
-foo::operator!=(foo &)
-foo::operator!=
-#
---format=lucid --no-params
-__nt__3fooFv
-foo::operator!(void)
-foo::operator!
-#
---format=lucid --no-params
-__nw__3fooSFi
-foo::operator new(int) static
-foo::operator new
-#
---format=lucid --no-params
-__nw__FUi
-operator new(unsigned int)
-operator new
-#
---format=lucid --no-params
-__nw__FUiPv
-operator new(unsigned int, void *)
-operator new
-#
---format=lucid --no-params
-__oo__3fooFR3foo
-foo::operator||(foo &)
-foo::operator||
-#
---format=lucid --no-params
-__opPc__3fooFv
-foo::operator char *(void)
-foo::operator char *
-#
---format=lucid --no-params
-__opi__3fooFv
-foo::operator int(void)
-foo::operator int
-#
---format=lucid --no-params
-__or__3fooFR3foo
-foo::operator|(foo &)
-foo::operator|
-#
---format=lucid --no-params
-__pl__3fooFR3foo
-foo::operator+(foo &)
-foo::operator+
-#
---format=lucid --no-params
-__pp__3fooFi
-foo::operator++(int)
-foo::operator++
-#
---format=lucid --no-params
-__pt__3fooFv
-foo::operator->(void)
-foo::operator->
-#
---format=lucid --no-params
-__rm__3fooFR3foo
-foo::operator->*(foo &)
-foo::operator->*
-#
---format=lucid --no-params
-__rs__3fooFR3foo
-foo::operator>>(foo &)
-foo::operator>>
-#
---format=lucid --no-params
-__rs__7istreamFP9streambuf
-istream::operator>>(streambuf *)
-istream::operator>>
-#
---format=lucid --no-params
-__rs__7istreamFPFR3ios_R3ios
-istream::operator>>(ios &(*)(ios &))
-istream::operator>>
-#
---format=lucid --no-params
-__rs__7istreamFPFR7istream_R7istream
-istream::operator>>(istream &(*)(istream &))
-istream::operator>>
-#
---format=lucid --no-params
-__rs__7istreamFPUc
-istream::operator>>(unsigned char *)
-istream::operator>>
-#
---format=lucid --no-params
-__rs__7istreamFPc
-istream::operator>>(char *)
-istream::operator>>
-#
---format=lucid --no-params
-__rs__7istreamFRUi
-istream::operator>>(unsigned int &)
-istream::operator>>
-#
---format=lucid --no-params
-__rs__7istreamFRUl
-istream::operator>>(unsigned long &)
-istream::operator>>
-#
---format=lucid --no-params
-__rs__7istreamFRUs
-istream::operator>>(unsigned short &)
-istream::operator>>
-#
---format=lucid --no-params
-__rs__7istreamFRd
-istream::operator>>(double &)
-istream::operator>>
-#
---format=lucid --no-params
-__rs__7istreamFRf
-istream::operator>>(float &)
-istream::operator>>
-#
---format=lucid --no-params
-__rs__7istreamFRi
-istream::operator>>(int &)
-istream::operator>>
-#
---format=lucid --no-params
-__rs__7istreamFRl
-istream::operator>>(long &)
-istream::operator>>
-#
---format=lucid --no-params
-__rs__7istreamFRs
-istream::operator>>(short &)
-istream::operator>>
-#
---format=lucid --no-params
-__rs__FR7istreamR7complex
-operator>>(istream &, complex &)
-operator>>
-#
---format=lucid --no-params
-__vtbl__10istrstream
-istrstream virtual table
-istrstream virtual table
-#
---format=lucid --no-params
-__vtbl__17ostream__iostream__19iostream_withassign
-iostream_withassign::ostream__iostream virtual table
-iostream_withassign::ostream__iostream virtual table
-#
---format=lucid --no-params
-__vtbl__3ios
-ios virtual table
-ios virtual table
-#
---format=lucid --no-params
-__vtbl__3ios__13strstreambase
-strstreambase::ios virtual table
-strstreambase::ios virtual table
-#
---format=lucid --no-params
-abs__F7complex
-abs(complex)
-abs
-#
---format=lucid --no-params
-allocate__9streambufFv
-streambuf::allocate(void)
-streambuf::allocate
-#
---format=lucid --no-params
-attach__11fstreambaseFi
-fstreambase::attach(int)
-fstreambase::attach
-#
---format=lucid --no-params
-bitalloc__3iosSFv
-ios::bitalloc(void) static
-ios::bitalloc
-#
---format=lucid --no-params
-chr__FiT1
-chr(int, int)
-chr
-#
---format=lucid --no-params
-complex_error__FR11c_exception
-complex_error(c_exception &)
-complex_error
-#
---format=lucid --no-params
-complexfunc2__FPFPc_i
-complexfunc2(int (*)(char *))
-complexfunc2
-#
---format=lucid --no-params
-complexfunc3__FPFPFPl_s_i
-complexfunc3(int (*)(short (*)(long *)))
-complexfunc3
-#
---format=lucid --no-params
-complexfunc4__FPFPFPc_s_i
-complexfunc4(int (*)(short (*)(char *)))
-complexfunc4
-#
---format=lucid --no-params
-complexfunc5__FPFPc_PFl_i
-complexfunc5(int (*(*)(char *))(long))
-complexfunc5
-#
---format=lucid --no-params
-complexfunc6__FPFPi_PFl_i
-complexfunc6(int (*(*)(int *))(long))
-complexfunc6
-#
---format=lucid --no-params
-complexfunc7__FPFPFPc_i_PFl_i
-complexfunc7(int (*(*)(int (*)(char *)))(long))
-complexfunc7
-#
---format=lucid --no-params
-complicated_put__7ostreamFc
-ostream::complicated_put(char)
-ostream::complicated_put
-#
---format=lucid --no-params
-conv10__FlPc
-conv10(long, char *)
-conv10
-#
---format=lucid --no-params
-conv16__FUlPc
-conv16(unsigned long, char *)
-conv16
-#
---format=lucid --no-params
-dec__FR3ios
-dec(ios &)
-dec
-#
---format=lucid --no-params
-dec__Fli
-dec(long, int)
-dec
-#
---format=lucid --no-params
-dofield__FP7ostreamPciT2T3
-dofield(ostream *, char *, int, char *, int)
-dofield
-#
---format=lucid --no-params
-flags__3iosFl
-ios::flags(long)
-ios::flags
-#
---format=lucid --no-params
-flags__3iosFv
-ios::flags(void)
-ios::flags
-#
---format=lucid --no-params
-foo__FiN31
-foo(int, int, int, int)
-foo
-#
---format=lucid --no-params
-foo__FiR3fooT1T2T1T2
-foo(int, foo &, int, foo &, int, foo &)
-foo
-#
---format=lucid --no-params
-foo__FiO3fooT1T2T1T2
-foo(int, foo &&, int, foo &&, int, foo &&)
-foo
-#
---format=lucid --no-params
-foo___3barFl
-bar::foo_(long)
-bar::foo_
-#
---format=lucid --no-params
-get__7istreamFPcic
-istream::get(char *, int, char)
-istream::get
-#
---format=lucid --no-params
-get__7istreamFR9streambufc
-istream::get(streambuf &, char)
-istream::get
-#
---format=lucid --no-params
-get_complicated__7istreamFRUc
-istream::get_complicated(unsigned char &)
-istream::get_complicated
-#
---format=lucid --no-params
-get_complicated__7istreamFRc
-istream::get_complicated(char &)
-istream::get_complicated
-#
---format=lucid --no-params
-getline__7istreamFPUcic
-istream::getline(unsigned char *, int, char)
-istream::getline
-#
---format=lucid --no-params
-getline__7istreamFPcic
-istream::getline(char *, int, char)
-istream::getline
-#
---format=lucid --no-params
-ignore__7istreamFiT1
-istream::ignore(int, int)
-istream::ignore
-#
---format=lucid --no-params
-init__12strstreambufFPciT1
-strstreambuf::init(char *, int, char *)
-strstreambuf::init
-#
---format=lucid --no-params
-init__3iosFP9streambuf
-ios::init(streambuf *)
-ios::init
-#
---format=lucid --no-params
-initcount__13Iostream_init
-Iostream_init::initcount
-Iostream_init::initcount
-#
---format=lucid --no-params
-ipfx__7istreamFi
-istream::ipfx(int)
-istream::ipfx
-#
---format=lucid --no-params
-ls_complicated__7ostreamFUc
-ostream::ls_complicated(unsigned char)
-ostream::ls_complicated
-#
---format=lucid --no-params
-ls_complicated__7ostreamFc
-ostream::ls_complicated(char)
-ostream::ls_complicated
-#
---format=lucid --no-params
-overload1arg__FSc
-overload1arg(signed char)
-overload1arg
-#
---format=lucid --no-params
-overload1arg__FUc
-overload1arg(unsigned char)
-overload1arg
-#
---format=lucid --no-params
-overload1arg__FUi
-overload1arg(unsigned int)
-overload1arg
-#
---format=lucid --no-params
-overload1arg__FUl
-overload1arg(unsigned long)
-overload1arg
-#
---format=lucid --no-params
-overload1arg__FUs
-overload1arg(unsigned short)
-overload1arg
-#
---format=lucid --no-params
-overload1arg__Fc
-overload1arg(char)
-overload1arg
-#
---format=lucid --no-params
-overload1arg__Fd
-overload1arg(double)
-overload1arg
-#
---format=lucid --no-params
-overload1arg__Ff
-overload1arg(float)
-overload1arg
-#
---format=lucid --no-params
-overload1arg__Fi
-overload1arg(int)
-overload1arg
-#
---format=lucid --no-params
-overload1arg__Fl
-overload1arg(long)
-overload1arg
-#
---format=lucid --no-params
-overload1arg__Fs
-overload1arg(short)
-overload1arg
-#
---format=lucid --no-params
-overload1arg__Fv
-overload1arg(void)
-overload1arg
-#
---format=lucid --no-params
-overloadargs__FiN21
-overloadargs(int, int, int)
-overloadargs
-#
---format=lucid --no-params
-overloadargs__FiN31
-overloadargs(int, int, int, int)
-overloadargs
-#
---format=lucid --no-params
-overloadargs__FiN41
-overloadargs(int, int, int, int, int)
-overloadargs
-#
---format=lucid --no-params
-overloadargs__FiN51
-overloadargs(int, int, int, int, int, int)
-overloadargs
-#
---format=lucid --no-params
-overloadargs__FiN61
-overloadargs(int, int, int, int, int, int, int)
-overloadargs
-#
---format=lucid --no-params
-overloadargs__FiN71
-overloadargs(int, int, int, int, int, int, int, int)
-overloadargs
-#
---format=lucid --no-params
-overloadargs__FiN81
-overloadargs(int, int, int, int, int, int, int, int, int)
-overloadargs
-#
---format=lucid --no-params
-overloadargs__FiN91
-overloadargs(int, int, int, int, int, int, int, int, int, int)
-overloadargs
-#
---format=lucid --no-params
-overloadargs__FiN91N11
-overloadargs(int, int, int, int, int, int, int, int, int, int, int)
-overloadargs
-#
---format=lucid --no-params
-overloadargs__FiT1
-overloadargs(int, int)
-overloadargs
-#
---format=lucid --no-params
-polar__FdT1
-polar(double, double)
-polar
-#
---format=lucid --no-params
-pow__F7complexT1
-pow(complex, complex)
-pow
-#
---format=lucid --no-params
-pow__F7complexd
-pow(complex, double)
-pow
-#
---format=lucid --no-params
-pow__F7complexi
-pow(complex, int)
-pow
-#
---format=lucid --no-params
-pow__Fd7complex
-pow(double, complex)
-pow
-#
---format=lucid --no-params
-pstart__FPciT2
-pstart(char *, int, int)
-pstart
-#
---format=lucid --no-params
-put__7ostreamFc
-ostream::put(char)
-ostream::put
-#
---format=lucid --no-params
-read__7istreamFPci
-istream::read(char *, int)
-istream::read
-#
---format=lucid --no-params
-resetiosflags__FR3iosl
-resetiosflags(ios &, long)
-resetiosflags
-#
---format=lucid --no-params
-restore_errno__FRi
-restore_errno(int &)
-restore_errno
-#
---format=lucid --no-params
-rs_complicated__7istreamFRUc
-istream::rs_complicated(unsigned char &)
-istream::rs_complicated
-#
---format=lucid --no-params
-rs_complicated__7istreamFRc
-istream::rs_complicated(char &)
-istream::rs_complicated
-#
---format=lucid --no-params
-seekg__7istreamFl8seek_dir
-istream::seekg(long, seek_dir)
-istream::seekg
-#
---format=lucid --no-params
-seekoff__12strstreambufFl8seek_diri
-strstreambuf::seekoff(long, seek_dir, int)
-strstreambuf::seekoff
-#
---format=lucid --no-params
-seekoff__9streambufFlQ2_3ios12ios_seek_diri
-streambuf::seekoff(long, ios::ios_seek_dir, int)
-streambuf::seekoff
-#
---format=lucid --no-params
-seekpos__9streambufFli
-streambuf::seekpos(long, int)
-streambuf::seekpos
-#
---format=lucid --no-params
-set_new_handler__FPFv_v
-set_new_handler(void (*)(void))
-set_new_handler
-#
---format=lucid --no-params
-setb__9streambufFPcT1i
-streambuf::setb(char *, char *, int)
-streambuf::setb
-#
---format=lucid --no-params
-setb__FR3iosi
-setb(ios &, int)
-setb
-#
---format=lucid --no-params
-setbuf__11fstreambaseFPci
-fstreambase::setbuf(char *, int)
-fstreambase::setbuf
-#
---format=lucid --no-params
-setbuf__9streambufFPUci
-streambuf::setbuf(unsigned char *, int)
-streambuf::setbuf
-#
---format=lucid --no-params
-setbuf__9streambufFPciT2
-streambuf::setbuf(char *, int, int)
-streambuf::setbuf
-#
---format=lucid --no-params
-setf__3iosFlT1
-ios::setf(long, long)
-ios::setf
-#
---format=lucid --no-params
-setfill__FR3iosi
-setfill(ios &, int)
-setfill
-#
---format=lucid --no-params
-setg__9streambufFPcN21
-streambuf::setg(char *, char *, char *)
-streambuf::setg
-#
---format=lucid --no-params
-setp__9streambufFPcT1
-streambuf::setp(char *, char *)
-streambuf::setp
-#
---format=lucid --no-params
-tie__3iosFP7ostream
-ios::tie(ostream *)
-ios::tie
-#
---format=lucid --no-params
-uconv10__FUlPc
-uconv10(unsigned long, char *)
-uconv10
-#
---format=lucid --no-params
-xget__7istreamFPc
-istream::xget(char *)
-istream::xget
-#
---format=lucid --no-params
-xsgetn__9streambufFPci
-streambuf::xsgetn(char *, int)
-streambuf::xsgetn
-#
---format=arm --no-params
-__dt__21T5__pt__11_PFiPPdPv_iFv
-T5<int (*)(int, double **, void *)>::~T5(void)
-T5<int (*)(int, double **, void *)>::~T5
-#
---format=arm --no-params
-__ct__1cFi
-c::c(int)
-c::c
-#
---format=arm --no-params
-__dt__11T5__pt__2_iFv
-T5<int>::~T5(void)
-T5<int>::~T5
-#
---format=arm --no-params
-__dt__11T5__pt__2_cFv
-T5<char>::~T5(void)
-T5<char>::~T5
-#
---format=arm --no-params
-__ct__2T2Fi
-T2::T2(int)
-T2::T2
-#
---format=arm --no-params
-__dt__2T1Fv
-T1::~T1(void)
-T1::~T1
-#
---format=arm --no-params
-__dt__12T5__pt__3_1xFv
-T5<x>::~T5(void)
-T5<x>::~T5
-#
---format=arm --no-params
-__dt__17T5__pt__8_PFcPv_iFv
-T5<int (*)(char, void *)>::~T5(void)
-T5<int (*)(char, void *)>::~T5
-#
---format=arm --no-params
-__ct__21T5__pt__11_PFiPPdPv_iFi
-T5<int (*)(int, double **, void *)>::T5(int)
-T5<int (*)(int, double **, void *)>::T5
-#
---format=arm --no-params
-__amd__FR2T2i
-operator%=(T2 &, int)
-operator%=
-#
---format=arm --no-params
-__adv__FR2T2i
-operator/=(T2 &, int)
-operator/=
-#
---format=arm --no-params
-__amu__FR2T2i
-operator*=(T2 &, int)
-operator*=
-#
---format=arm --no-params
-__ami__FR2T2i
-operator-=(T2 &, int)
-operator-=
-#
---format=arm --no-params
-__apl__FR2T2i
-operator+=(T2 &, int)
-operator+=
-#
---format=arm --no-params
-__nw__2T1SFUi
-T1::operator new(unsigned int) static
-T1::operator new
-#
---format=arm --no-params
-__dl__2T1SFPv
-T1::operator delete(void *) static
-T1::operator delete
-#
---format=arm --no-params
-put__2T7SFi
-T7::put(int) static
-T7::put
-#
---format=arm --no-params
-__dl__12T5__pt__3_1xSFPv
-T5<x>::operator delete(void *) static
-T5<x>::operator delete
-#
---format=arm --no-params
-h__FUc
-h(unsigned char)
-h
-#
---format=arm --no-params
-f__Fic
-f(int, char)
-f
-#
---format=arm --no-params
-h__FUi
-h(unsigned int)
-h
-#
---format=arm --no-params
-h__Fci
-h(char, int)
-h
-#
---format=arm --no-params
-h__FUl
-h(unsigned long)
-h
-#
---format=arm --no-params
-h__Fcl
-h(char, long)
-h
-#
---format=arm --no-params
-h__FUs
-h(unsigned short)
-h
-#
---format=arm --no-params
-h__Fcs
-h(char, short)
-h
-#
---format=arm --no-params
-X__12T5__pt__3_1x
-T5<x>::X
-T5<x>::X
-#
---format=arm --no-params
-__ct__11T5__pt__2_iFi
-T5<int>::T5(int)
-T5<int>::T5
-#
---format=arm --no-params
-__ct__11T5__pt__2_cFi
-T5<char>::T5(int)
-T5<char>::T5
-#
---format=arm --no-params
-h__FcT1
-h(char, char)
-h
-#
---format=arm --no-params
-f__Ficd
-f(int, char, double)
-f
-#
---format=arm --no-params
-__dl__17T5__pt__8_PFcPv_iSFPv
-T5<int (*)(char, void *)>::operator delete(void *) static
-T5<int (*)(char, void *)>::operator delete
-#
---format=arm --no-params
-X__17T5__pt__8_PFcPv_i
-T5<int (*)(char, void *)>::X
-T5<int (*)(char, void *)>::X
-#
---format=arm --no-params
-__ct__12T5__pt__3_1xFi
-T5<x>::T5(int)
-T5<x>::T5
-#
---format=arm --no-params
-__dl__21T5__pt__11_PFiPPdPv_iSFPv
-T5<int (*)(int, double **, void *)>::operator delete(void *) static
-T5<int (*)(int, double **, void *)>::operator delete
-#
---format=arm --no-params
-__std__foo
-global destructors keyed to foo
-global destructors keyed to foo
-#
---format=arm --no-params
-__sti__bar
-global constructors keyed to bar
-global constructors keyed to bar
-#
---format=arm --no-params
-f__FicdPcPFci_v
-f(int, char, double, char *, void (*)(char, int))
-f
-#
---format=arm --no-params
-f__FicdPcPFic_v
-f(int, char, double, char *, void (*)(int, char))
-f
-#
---format=arm --no-params
-get__2T7SFv
-T7::get(void) static
-T7::get
-#
---format=arm --no-params
-X__21T5__pt__11_PFiPPdPv_i
-T5<int (*)(int, double **, void *)>::X
-T5<int (*)(int, double **, void *)>::X
-#
---format=arm --no-params
-__dl__11T5__pt__2_iSFPv
-T5<int>::operator delete(void *) static
-T5<int>::operator delete
-#
---format=arm --no-params
-__dl__11T5__pt__2_cSFPv
-T5<char>::operator delete(void *) static
-T5<char>::operator delete
-#
---format=arm --no-params
-h__Fc
-h(char)
-h
-#
---format=arm --no-params
-h__Fd
-h(double)
-h
-#
---format=arm --no-params
-h__Ff
-h(float)
-h
-#
---format=arm --no-params
-h__Fi
-h(int)
-h
-#
---format=arm --no-params
-f__Fi
-f(int)
-f
-#
---format=arm --no-params
-h__Fl
-h(long)
-h
-#
---format=arm --no-params
-h__Fs
-h(short)
-h
-#
---format=arm --no-params
-X__11T5__pt__2_c
-T5<char>::X
-T5<char>::X
-#
---format=arm --no-params
-X__11T5__pt__2_i
-T5<int>::X
-T5<int>::X
-#
---format=arm --no-params
-__ct__17T5__pt__8_PFcPv_iFi
-T5<int (*)(char, void *)>::T5(int)
-T5<int (*)(char, void *)>::T5
-#
---format=arm --no-params
-f__FicdPc
-f(int, char, double, char *)
-f
-#
---format=arm --no-params
-__nw__FUi
-operator new(unsigned int)
-operator new
-#
---format=arm --no-params
-__ct__Q3_2T11a1bSFi
-T1::a::b::b(int) static
-T1::a::b::b
-#
---format=arm --no-params
-__dt__Q3_2T11a1bSFi
-T1::a::b::~b(int) static
-T1::a::b::~b
-#
---format=arm --no-params
-put__Q3_2T11a1bSFi
-T1::a::b::put(int) static
-T1::a::b::put
-#
---format=arm --no-params
-get__Q2_2T11aSFv
-T1::a::get(void) static
-T1::a::get
-#
---format=arm --no-params
-put__2T1SFi
-T1::put(int) static
-T1::put
-#
---format=arm --no-params
-put__Q5_2T11a1b1c1dSFi
-T1::a::b::c::d::put(int) static
-T1::a::b::c::d::put
-#
---format=arm --no-params
-get__Q4_2T11a1b1cSFv
-T1::a::b::c::get(void) static
-T1::a::b::c::get
-#
---format=arm --no-params
-put__Q2_2T11aSFi
-T1::a::put(int) static
-T1::a::put
-#
---format=arm --no-params
-put__Q4_2T11a1b1cSFi
-T1::a::b::c::put(int) static
-T1::a::b::c::put
-#
---format=arm --no-params
-get__Q3_2T11a1bSFv
-T1::a::b::get(void) static
-T1::a::b::get
-#
---format=arm --no-params
-get__2T1SFv
-T1::get(void) static
-T1::get
-#
---format=arm --no-params
-get__Q5_2T11a1b1c1dSFv
-T1::a::b::c::d::get(void) static
-T1::a::b::c::d::get
-#
---format=arm --no-params
-__dt__11T1__pt__2_cFv
-T1<char>::~T1(void)
-T1<char>::~T1
-#
---format=arm --no-params
-__dt__12T1__pt__3_1tFv
-T1<t>::~T1(void)
-T1<t>::~T1
-#
---format=arm --no-params
-__dl__12T1__pt__3_1tSFPv
-T1<t>::operator delete(void *) static
-T1<t>::operator delete
-#
---format=arm --no-params
-__ct__11T1__pt__2_cFi
-T1<char>::T1(int)
-T1<char>::T1
-#
---format=arm --no-params
-__ct__11T1__pt__2_cFv
-T1<char>::T1(void)
-T1<char>::T1
-#
---format=arm --no-params
-__ct__12T1__pt__3_1tFi
-T1<t>::T1(int)
-T1<t>::T1
-#
---format=arm --no-params
-__ct__12T1__pt__3_1tFv
-T1<t>::T1(void)
-T1<t>::T1
-#
---format=arm --no-params
-__dl__11T1__pt__2_cSFPv
-T1<char>::operator delete(void *) static
-T1<char>::operator delete
-#
---format=arm --no-params
-bar__3fooFPv
-foo::bar(void *)
-foo::bar
-#
---format=arm --no-params
-bar__3fooCFPv
-foo::bar(void *) const
-foo::bar
-#
---format=arm --no-params
-__eq__3fooFR3foo
-foo::operator==(foo &)
-foo::operator==
-#
---format=arm --no-params
-__eq__3fooCFR3foo
-foo::operator==(foo &) const
-foo::operator==
-#
---format=arm --no-params
-elem__15vector__pt__2_dFi
-vector<double>::elem(int)
-vector<double>::elem
-#
---format=arm --no-params
-elem__15vector__pt__2_iFi
-vector<int>::elem(int)
-vector<int>::elem
-#
---format=arm --no-params
-__ct__15vector__pt__2_dFi
-vector<double>::vector(int)
-vector<double>::vector
-#
---format=arm --no-params
-__ct__15vector__pt__2_iFi
-vector<int>::vector(int)
-vector<int>::vector
-#
---format=arm --no-params
-__ct__25DListNode__pt__9_R6RLabelFR6RLabelP25DListNode__pt__9_R6RLabelT2
-DListNode<RLabel &>::DListNode(RLabel &, DListNode<RLabel &> *, DListNode<RLabel &> *)
-DListNode<RLabel &>::DListNode
-#
---format=arm --no-params
-__ct__25DListNode__pt__9_O6RLabelFO6RLabelP25DListNode__pt__9_O6RLabelT2
-DListNode<RLabel &&>::DListNode(RLabel &&, DListNode<RLabel &&> *, DListNode<RLabel &&> *)
-DListNode<RLabel &&>::DListNode
-#
---format=arm --no-params
-bar__3fooFiT16FooBar
-foo::bar(int, int, FooBar)
-foo::bar
-#
---format=arm --no-params
-bar__3fooFPiN51PdN37PcN211T1iN215
-foo::bar(int *, int *, int *, int *, int *, int *, double *, double *, double *, double *, char *, char *, char *, int *, int, int, int)
-foo::bar
-#
---format=hp --no-params
-__amd__FR2T2i
-operator%=(T2 &, int)
-operator%=
-#
---format=hp --no-params
-__adv__FR2T2i
-operator/=(T2 &, int)
-operator/=
-#
---format=hp --no-params
-__amu__FR2T2i
-operator*=(T2 &, int)
-operator*=
-#
---format=hp --no-params
-__ami__FR2T2i
-operator-=(T2 &, int)
-operator-=
-#
---format=hp --no-params
-__apl__FR2T2i
-operator+=(T2 &, int)
-operator+=
-#
---format=hp --no-params
-__nw__2T1SFUi
-T1::operator new(unsigned int) static
-T1::operator new
-#
---format=hp --no-params
-__dl__2T1SFPv
-T1::operator delete(void *) static
-T1::operator delete
-#
---format=hp --no-params
-put__2T7SFi
-T7::put(int) static
-T7::put
-#
---format=hp --no-params
-h__FUc
-h(unsigned char)
-h
-#
---format=hp --no-params
-f__Fic
-f(int, char)
-f
-#
---format=hp --no-params
-h__FUi
-h(unsigned int)
-h
-#
---format=hp --no-params
-h__Fci
-h(char, int)
-h
-#
---format=hp --no-params
-h__FUl
-h(unsigned long)
-h
-#
---format=hp --no-params
-h__Fcl
-h(char, long)
-h
-#
---format=hp --no-params
-h__FUs
-h(unsigned short)
-h
-#
---format=hp --no-params
-h__Fcs
-h(char, short)
-h
-#
---format=hp --no-params
-h__FcT1
-h(char, char)
-h
-#
---format=hp --no-params
-f__Ficd
-f(int, char, double)
-f
-#
---format=hp --no-params
-f__FicdPcPFci_v
-f(int, char, double, char *, void (*)(char, int))
-f
-#
---format=hp --no-params
-f__FicdPcPFic_v
-f(int, char, double, char *, void (*)(int, char))
-f
-#
---format=hp --no-params
-get__2T7SFv
-T7::get(void) static
-T7::get
-#
---format=hp --no-params
-h__Fc
-h(char)
-h
-#
---format=hp --no-params
-h__Fd
-h(double)
-h
-#
---format=hp --no-params
-h__Ff
-h(float)
-h
-#
---format=hp --no-params
-h__Fi
-h(int)
-h
-#
---format=hp --no-params
-f__Fi
-f(int)
-f
-#
---format=hp --no-params
-h__Fl
-h(long)
-h
-#
---format=hp --no-params
-h__Fs
-h(short)
-h
-#
---format=hp --no-params
-f__FicdPc
-f(int, char, double, char *)
-f
-#
---format=hp --no-params
-__nw__FUi
-operator new(unsigned int)
-operator new
-#
---format=hp --no-params
-__ct__Q3_2T11a1bSFi
-T1::a::b::b(int) static
-T1::a::b::b
-#
---format=hp --no-params
-__dt__Q3_2T11a1bSFi
-T1::a::b::~b(int) static
-T1::a::b::~b
-#
---format=hp --no-params
-put__Q3_2T11a1bSFi
-T1::a::b::put(int) static
-T1::a::b::put
-#
---format=hp --no-params
-get__Q2_2T11aSFv
-T1::a::get(void) static
-T1::a::get
-#
---format=hp --no-params
-put__2T1SFi
-T1::put(int) static
-T1::put
-#
---format=hp --no-params
-put__Q5_2T11a1b1c1dSFi
-T1::a::b::c::d::put(int) static
-T1::a::b::c::d::put
-#
---format=hp --no-params
-get__Q4_2T11a1b1cSFv
-T1::a::b::c::get(void) static
-T1::a::b::c::get
-#
---format=hp --no-params
-put__Q2_2T11aSFi
-T1::a::put(int) static
-T1::a::put
-#
---format=hp --no-params
-put__Q4_2T11a1b1cSFi
-T1::a::b::c::put(int) static
-T1::a::b::c::put
-#
---format=hp --no-params
-get__Q3_2T11a1bSFv
-T1::a::b::get(void) static
-T1::a::b::get
-#
---format=hp --no-params
-get__2T1SFv
-T1::get(void) static
-T1::get
-#
---format=hp --no-params
-get__Q5_2T11a1b1c1dSFv
-T1::a::b::c::d::get(void) static
-T1::a::b::c::d::get
-#
---format=hp --no-params
-bar__3fooFPv
-foo::bar(void *)
-foo::bar
-#
---format=hp --no-params
-bar__3fooCFPv
-foo::bar(void *) const
-foo::bar
-#
---format=hp --no-params
-__eq__3fooFR3foo
-foo::operator==(foo &)
-foo::operator==
-#
---format=hp --no-params
-__eq__3fooCFR3foo
-foo::operator==(foo &) const
-foo::operator==
-#
---format=hp --no-params
-bar__3fooFiT16FooBar
-foo::bar(int, int, FooBar)
-foo::bar
-#
---format=hp --no-params
-bar__3fooFPiN51PdN37PcN211T1iN215
-foo::bar(int *, int *, int *, int *, int *, int *, double *, double *, double *, double *, char *, char *, char *, int *, int, int, int)
-foo::bar
-#
---format=hp --no-params
-__dt__2T5XTPFiPPdPv_i__Fv
-T5<int (*)(int, double **, void *)>::~T5(void)
-T5<int (*)(int, double **, void *)>::~T5
-#
---format=hp --no-params
-__ct__1cFi
-c::c(int)
-c::c
-#
---format=hp --no-params
-__dt__2T5XTi__Fv
-T5<int>::~T5(void)
-T5<int>::~T5
-#
---format=hp --no-params
-__dt__2T5XTc__Fv
-T5<char>::~T5(void)
-T5<char>::~T5
-#
---format=hp --no-params
-__ct__2T2Fi
-T2::T2(int)
-T2::T2
-#
---format=hp --no-params
-__dt__2T1Fv
-T1::~T1(void)
-T1::~T1
-#
---format=hp --no-params
-__dt__2T5XT1x__Fv
-T5<x>::~T5(void)
-T5<x>::~T5
-#
---format=hp --no-params
-__dt__2T5XTPFcPv_i__Fv
-T5<int (*)(char, void *)>::~T5(void)
-T5<int (*)(char, void *)>::~T5
-#
---format=hp --no-params
-__ct__2T5XTPFiPPdPv_i__Fi
-T5<int (*)(int, double **, void *)>::T5(int)
-T5<int (*)(int, double **, void *)>::T5
-#
---format=hp --no-params
-__dl__2T5XT1x__SFPv
-T5<x>::operator delete(void *) static
-T5<x>::operator delete
-#
---format=hp --no-params
-X__2T5XT1x
-T5<x>::X
-T5<x>::X
-#
---format=hp --no-params
-__ct__2T5XTi__Fi
-T5<int>::T5(int)
-T5<int>::T5
-#
---format=hp --no-params
-__ct__2T5XTc__Fi
-T5<char>::T5(int)
-T5<char>::T5
-#
---format=hp --no-params
-__dl__2T5XTPFcPv_i__SFPv
-T5<int (*)(char, void *)>::operator delete(void *) static
-T5<int (*)(char, void *)>::operator delete
-#
---format=hp --no-params
-X__2T5XTPFcPv_i
-T5<int (*)(char, void *)>::X
-T5<int (*)(char, void *)>::X
-#
---format=hp --no-params
-__ct__2T5XT1x__Fi
-T5<x>::T5(int)
-T5<x>::T5
-#
---format=hp --no-params
-__dl__2T5XTPFiPPdPv_i__SFPv
-T5<int (*)(int, double **, void *)>::operator delete(void *) static
-T5<int (*)(int, double **, void *)>::operator delete
-#
---format=hp --no-params
-X__2T5XTPFiPPdPv_i
-T5<int (*)(int, double **, void *)>::X
-T5<int (*)(int, double **, void *)>::X
-#
---format=hp --no-params
-__dl__2T5XTi__SFPv
-T5<int>::operator delete(void *) static
-T5<int>::operator delete
-#
---format=hp --no-params
-__dl__2T5XTc__SFPv
-T5<char>::operator delete(void *) static
-T5<char>::operator delete
-#
---format=hp --no-params
-X__2T5XTc
-T5<char>::X
-T5<char>::X
-#
---format=hp --no-params
-X__2T5XTi
-T5<int>::X
-T5<int>::X
-#
---format=hp --no-params
-__ct__2T5XTPFcPv_i__Fi
-T5<int (*)(char, void *)>::T5(int)
-T5<int (*)(char, void *)>::T5
-#
---format=hp --no-params
-__dt__2T1XTc__Fv
-T1<char>::~T1(void)
-T1<char>::~T1
-#
---format=hp --no-params
-__dt__2T1XT1t__Fv
-T1<t>::~T1(void)
-T1<t>::~T1
-#
---format=hp --no-params
-__dl__2T1XT1t__SFPv
-T1<t>::operator delete(void *) static
-T1<t>::operator delete
-#
---format=hp --no-params
-__ct__2T1XTc__Fi
-T1<char>::T1(int)
-T1<char>::T1
-#
---format=hp --no-params
-__ct__2T1XTc__Fv
-T1<char>::T1(void)
-T1<char>::T1
-#
---format=hp --no-params
-__ct__2T1XT1t__Fi
-T1<t>::T1(int)
-T1<t>::T1
-#
---format=hp --no-params
-__ct__2T1XT1t__Fv
-T1<t>::T1(void)
-T1<t>::T1
-#
---format=hp --no-params
-__dl__2T1XTc__SFPv
-T1<char>::operator delete(void *) static
-T1<char>::operator delete
-#
---format=hp --no-params
-elem__6vectorXTd__Fi
-vector<double>::elem(int)
-vector<double>::elem
-#
---format=hp --no-params
-elem__6vectorXTi__Fi
-vector<int>::elem(int)
-vector<int>::elem
-#
---format=hp --no-params
-__ct__6vectorXTd__Fi
-vector<double>::vector(int)
-vector<double>::vector
-#
---format=hp --no-params
-__ct__6vectorXTi__Fi
-vector<int>::vector(int)
-vector<int>::vector
-#
---format=hp --no-params
-__ct__9DListNodeXTR6RLabel__FR6RLabelP9DListNodeXTR6RLabel_T2
-DListNode<RLabel &>::DListNode(RLabel &, DListNode<RLabel &> *, DListNode<RLabel &> *)
-DListNode<RLabel &>::DListNode
-#
---format=hp --no-params
-__ct__9DListNodeXTO6RLabel__FO6RLabelP9DListNodeXTO6RLabel_T2
-DListNode<RLabel &&>::DListNode(RLabel &&, DListNode<RLabel &&> *, DListNode<RLabel &&> *)
-DListNode<RLabel &&>::DListNode
-#
---format=hp --no-params
-elem__6vectorXTiUP34__Fi
-vector<int,34U>::elem(int)
-vector<int,34U>::elem
-#
---format=hp --no-params
-elem__6vectorXUP2701Td__Fi
-vector<2701U,double>::elem(int)
-vector<2701U,double>::elem
-#
---format=hp --no-params
-elem__6vectorXTiSP334__Fi
-vector<int,334>::elem(int)
-vector<int,334>::elem
-#
---format=hp --no-params
-elem__6vectorXTiSN67__Fi
-vector<int,-67>::elem(int)
-vector<int,-67>::elem
-#
---format=hp --no-params
-elem__6vectorXTiSM__SCFPPd
-vector<int,-2147483648>::elem(double **) static const
-vector<int,-2147483648>::elem
-#
---format=hp --no-params
-elem__6vectorXTiSN67UP4000TRs__Fi
-vector<int,-67,4000U,short &>::elem(int)
-vector<int,-67,4000U,short &>::elem
-#
---format=hp --no-params
-elem__6vectorXTiSN67UP4000TOs__Fi
-vector<int,-67,4000U,short &&>::elem(int)
-vector<int,-67,4000U,short &&>::elem
-#
---format=hp --no-params
-elem__6vectorXTiSN67TRdTFPv_i__Fi
-vector<int,-67,double &,int (void *)>::elem(int)
-vector<int,-67,double &,int (void *)>::elem
-#
---format=hp --no-params
-elem__6vectorXTiSN67TOdTFPv_i__Fi
-vector<int,-67,double &&,int (void *)>::elem(int)
-vector<int,-67,double &&,int (void *)>::elem
-#
---format=hp --no-params
-X__6vectorXTiSN67TdTPvUP5TRs
-vector<int,-67,double,void *,5U,short &>::X
-vector<int,-67,double,void *,5U,short &>::X
-#
---format=hp --no-params
-X__6vectorXTiSN67TdTPvUP5TOs
-vector<int,-67,double,void *,5U,short &&>::X
-vector<int,-67,double,void *,5U,short &&>::X
-#
---format=hp --no-params
-elem__6vectorXTiA3foo__Fi
-vector<int,&foo>::elem(int)
-vector<int,&foo>::elem
-#
---format=hp --no-params
-elem__6vectorXTiA3fooTPvA5Label__FiPPvT2
-vector<int,&foo,void *,&Label>::elem(int, void **, void **)
-vector<int,&foo,void *,&Label>::elem
-#
---format=hp --no-params
-elem__6vectorXTiSN42A3foo__Fi
-vector<int,-42,&foo>::elem(int)
-vector<int,-42,&foo>::elem
-#
---format=hp --no-params
-__ct__2T5XTPFcPv_i__Fi_2
-T5<int (*)(char, void *)>::T5(int)
-T5<int (*)(char, void *)>::T5
-#
---format=hp --no-params
-__ct__2T5XTPFcPv_i__Fi_19
-T5<int (*)(char, void *)>::T5(int)
-T5<int (*)(char, void *)>::T5
-#
---format=hp --no-params
-f__FicdPcPFci_v_34
-f(int, char, double, char *, void (*)(char, int))
-f
-#
---format=hp --no-params
-spec__13Spec<#1,#1.*>XTiTPi_FPi
-Spec<int,int *>::spec(int *)
-Spec<int,int *>::spec
-#
---format=hp --no-params
-spec__16Spec<#1,#1.&,#1>XTiTRiTi_FPi
-Spec<int,int &,int>::spec(int *)
-Spec<int,int &,int>::spec
-#
---format=hp --no-params
-spec__17Spec<#1,#1.&&,#1>XTiTOiTi_FPi
-Spec<int,int &&,int>::spec(int *)
-Spec<int,int &&,int>::spec
-#
---format=hp --no-params
-add__XTc_FcT1
-add<char>(char, char)
-add<char>
-#
---format=hp --no-params
-add__XTcSP9A5label_FcPPlT1
-add<char,9,&label>(char, long **, char)
-add<char,9,&label>
-#
---format=hp --no-params
-add__XTPfTFPd_f_FcT1
-add<float *,float (double *)>(char, char)
-add<float *,float (double *)>
-#
---format=hp --no-params
-unLink__12basic_stringXTcT18string_char_traitsXTc_T9allocator_Fv
-basic_string<char,string_char_traits<char>,allocator>::unLink(void)
-basic_string<char,string_char_traits<char>,allocator>::unLink
-#
-# A regression test with no args.  This used to cause a segv.
+# Tests integer overflow problem PR70492
 
-_Utf390_1__1_9223372036854775807__9223372036854775
-_Utf390_1__1_9223372036854775807__9223372036854775
+__vt_90000000000cafebabe
+__vt_90000000000cafebabe
 #
---format=gnu --no-params
-call__H1Z4Test_RX01_t1C2ZX01PMX01FPX01i_vQ2X016output
-C<Test, Test::output> call<Test>(Test &)
-C<Test, Test::output> call<Test>
-#
---format=gnu --no-params
-call__H1Z4Test_OX01_t1C2ZX01PMX01FPX01i_vQ2X016output
-C<Test, Test::output> call<Test>(Test &&)
-C<Test, Test::output> call<Test>
-#
---format=gnu --no-params
-fn__FPQ21n1cPMQ21n1cFPQ21n1c_i
-fn(n::c *, int (n::c::*)(n::c *))
-fn
-#
---format=gnu --no-params
-f__FGt3Bar1i2G1i
-f(Bar<2>, i)
-f
-#
---format=gnu --no-params
-f__FGt3Bar1i21i
-f(Bar<21>, int)
-f
-#
---format=gnu --no-params
-f__FGt3Bar1i2G4XY_t
-f(Bar<2>, XY_t)
-f
-#
---format=gnu --no-params
-foo__H1Zt2TA2ZRCiZt2NA1Ui9_X01_i
-int foo<TA<int const &, NA<9> > >(TA<int const &, NA<9> >)
-int foo<TA<int const &, NA<9> > >
-#
---format=gnu --no-params
-foo__H1Zt2TA2ZOCiZt2NA1Ui9_X01_i
-int foo<TA<int const &&, NA<9> > >(TA<int const &&, NA<9> >)
-int foo<TA<int const &&, NA<9> > >
-#
---format=gnu --no-params
-foo__H1Zt2TA2ZcZt2NA1Ui20_X01_i
-int foo<TA<char, NA<20> > >(TA<char, NA<20> >)
-int foo<TA<char, NA<20> > >
-#
---format=gnu --no-params
-foo__H1Zt2TA2ZiZt8N___A___1Ui99_X01_i
-int foo<TA<int, N___A___<99> > >(TA<int, N___A___<99> >)
-int foo<TA<int, N___A___<99> > >
-#
---format=gnu --no-params
-foo__H1Zt2TA2ZRCiZt2NA1im1_X01_i
-int foo<TA<int const &, NA<-1> > >(TA<int const &, NA<-1> >)
-int foo<TA<int const &, NA<-1> > >
-#
---format=gnu --no-params
-foo__H1Zt2TA2ZRCiZt2NA1im9_X01_i
-int foo<TA<int const &, NA<-9> > >(TA<int const &, NA<-9> >)
-int foo<TA<int const &, NA<-9> > >
-#
---format=gnu --no-params
-foo__H1Zt2TA2ZcZt2NA1i_m20__X01_i
-int foo<TA<char, NA<-20> > >(TA<char, NA<-20> >)
-int foo<TA<char, NA<-20> > >
-#
---format=gnu --no-params
-foo__H1Zt2TA2ZcZt2NA1im1_X01_i
-int foo<TA<char, NA<-1> > >(TA<char, NA<-1> >)
-int foo<TA<char, NA<-1> > >
-#
---format=gnu --no-params
-foo__H1Zt2TA2ZiZt4N__A1im9_X01_i
-int foo<TA<int, N__A<-9> > >(TA<int, N__A<-9> >)
-int foo<TA<int, N__A<-9> > >
-#
---format=gnu --no-params
-foo__H1Zt2TA2ZiZt4N__A1i_m99__X01_i
-int foo<TA<int, N__A<-99> > >(TA<int, N__A<-99> >)
-int foo<TA<int, N__A<-99> > >
-#
---format=gnu --no-params
-__opi__t2TA2ZiZt4N__A1i9
-TA<int, N__A<9> >::operator int(void)
-TA<int, N__A<9> >::operator int
-#
---format=gnu --no-params
-__opi__t2TA2ZiZt8N___A___1i_m99_
-TA<int, N___A___<-99> >::operator int(void)
-TA<int, N___A___<-99> >::operator int
-#
---format=gnu --no-params
-foo___bar__baz_____H1Zt2TA2ZiZt8N___A___1i99_X01_i
-int foo___bar__baz___<TA<int, N___A___<99> > >(TA<int, N___A___<99> >)
-int foo___bar__baz___<TA<int, N___A___<99> > >
-#
---format=gnu --no-params
-foo__bar___foobar_____t2TA2ZiZt8N___A___1i_m99_
-TA<int, N___A___<-99> >::foo__bar___foobar___(void)
-TA<int, N___A___<-99> >::foo__bar___foobar___
-#
---format=gnu --no-params
-foo__bar___foobar_____t2TA2ZiZt4N__A1i9
-TA<int, N__A<9> >::foo__bar___foobar___(void)
-TA<int, N__A<9> >::foo__bar___foobar___
-#
---format=gnu --no-params
-__tfP8sockaddr
-sockaddr * type_info function
-sockaddr * type_info function
+# Tests write access violation PR70498
+
+_Z80800000000000000000000
+_Z80800000000000000000000
 #
---format=gnu --no-params
-__tfPQ25libcwt16option_event_tct1Z12burst_app_ct
-libcw::option_event_tct<burst_app_ct> * type_info function
-libcw::option_event_tct<burst_app_ct> * type_info function
+# Tests write access violation PR70926
+
+0__Ot2m02R5T0000500000
+0__Ot2m02R5T0000500000
 #
---format=gnu --no-params
-__tiP8sockaddr
-sockaddr * type_info node
-sockaddr * type_info node
+
+0__GT50000000000_
+0__GT50000000000_
 #
---format=gnu --no-params
-__tiPQ25libcwt16option_event_tct1Z12burst_app_ct
-libcw::option_event_tct<burst_app_ct> * type_info node
-libcw::option_event_tct<burst_app_ct> * type_info node
+
+__t2m05B500000000000000000_
+__t2m05B500000000000000000_
+##
+## Tests stack overflow PR71696
+#
+#__10%0__S4_0T0T0
+#%0<>::%0(%0<>)
+# Could crash
+
+_
+_
+# Could crash
+
+_vt
+_vt
+# Could crash
+
+_$_1Acitz
+_$_1Acitz
+# Could crash
+
+_$_H1R
+_$_H1R
+# Could crash
+
+_Q8ccQ4M2e.
+_Q8ccQ4M2e.
 #
---format=gnu --no-params
-_27_GLOBAL_.N.__12burst_app_ct.app_instance
-{anonymous}::app_instance
-{anonymous}::app_instance
+# demangler/80513 Test for bogus characters after __thunk_
+
+__thunk_16a_$_1x
+__thunk_16a_$_1x
 #
---format=gnu --no-params
-_26_GLOBAL_$N$_tmp_n.iilg4Gya$app_instance
-{anonymous}::app_instance
-{anonymous}::app_instance
+# demangler/80513 Test for overflow in consume_count
+
+__thunk_4294967297__$_1x
+__thunk_4294967297__$_1x
 #
 --format=gnu-v3 --no-params
 _Z3fo5n
@@ -3368,7 +117,7 @@ java.util.Map$Entry.class$
 _ZN3org7eclipse3cdt5debug8internal4core5model9CVariable6sizeof$Ev
 org.eclipse.cdt.debug.internal.core.model.CVariable.sizeof()
 #
---format=hp --no-params
+--format=auto --no-params
 _Utf58_0_1__1_2147483647__2147483648
 _Utf58_0_1__1_2147483647__2147483648
 _Utf58_0_1__1_2147483647__2147483648
@@ -3904,24 +653,6 @@ _ZNSdD1Ev
 _ZNSdD1Ev
 2
 #
-# This caused an infinite loop.
-#
-# This is generated by an EDG compiler (kcc 4.0).  To demangle it
-# correctly, I believe that we have to understand that the J37J deep
-# in the string somehow refers back to the type starting 37 characters
-# in from some starting point, so that it winds up being the type
-# starting with 41THandle....  However, lacking a spec for EDG
-# demangling, it's hard to implement this.
-#
-# In the meantime, this symbol can be successfully demangled in GNU
-# mode.  Of course the result is more or less nonsense, but an older
-# version of g++ would indeed generate this mangled name given the
-# appropriate input, so the demangling is correct.
---format=auto --no-params
-__CPR212____ct__Q3_3std141list__tm__128_Q2_3edm41THandle__tm__26_Q2_4emid15EMparticleChunkQ2_3std68allocator__tm__51_Q2_3edmJ37J14const_iteratorFRCQ3_3std18list__tm__7_Z1ZZ2Z8iterator
-_Z1ZZ2Z::__CPR212____ct__Q3_3std141list__tm__128_Q2_3edm41THandle__tm__26_Q2_4emid15EMparticleChunkQ2_3std68allocator__tm__51_Q2_3edmJ37J14const_iteratorFRCQ3_3std18list__tm(iterator)
-_Z1ZZ2Z::__CPR212____ct__Q3_3std141list__tm__128_Q2_3edm41THandle__tm__26_Q2_4emid15EMparticleChunkQ2_3std68allocator__tm__51_Q2_3edmJ37J14const_iteratorFRCQ3_3std18list__tm
-#
 # This used to cause a crash. It doesn't follow the C++ encoding so
 # the demangled name should be identical to the original symbol name.
 --format=auto --no-params
@@ -4557,50 +1288,12 @@ void binary_left<1, 2, 3>(A<((42)+...+(1, 2, 3))>)
 
 _Z12binary_rightIJLi1ELi2ELi3EEEv1AIXfRplT_Li42EEE
 void binary_right<1, 2, 3>(A<((1, 2, 3)+...+(42))>)
-#
-# Tests a use-after-free problem PR70481
-
-_Q.__0
-::Q.(void)
-#
-# Tests a use-after-free problem PR70481
-
-_Q10-__9cafebabe.
-cafebabe.::-(void)
-#
-# Tests integer overflow problem PR70492
-
-__vt_90000000000cafebabe
-__vt_90000000000cafebabe
-#
-# Tests write access violation PR70498
-
-_Z80800000000000000000000
-_Z80800000000000000000000
-#
-# Tests write access violation PR70926
-
-0__Ot2m02R5T0000500000
-0__Ot2m02R5T0000500000
-#
-
-0__GT50000000000_
-0__GT50000000000_
-#
-
-__t2m05B500000000000000000_
-__t2m05B500000000000000000_
-#
-# Tests stack overflow PR71696
-
-__10%0__S4_0T0T0
-%0<>::%0(%0<>)
-
 # Inheriting constructor
+
 _ZN1DCI11BEi
 D::B(int)
-
 # exception-specification (C++17)
+
 _Z1fIvJiELb0EEvPDOT1_EFT_DpT0_E
 void f<void, int, false>(void (*)(int) noexcept(false))
 
@@ -4610,26 +1303,6 @@ void f<void, int, false>(void (*)(int) noexcept)
 _Z1fIvJiELb0EEvPDwiEFT_DpT0_E
 void f<void, int, false>(void (*)(int) throw(int))
 
-# Could crash
-_
-_
-
-# Could crash
-_vt
-_vt
-
-# Could crash
-_$_1Acitz
-_$_1Acitz
-
-# Could crash
-_$_H1R
-_$_H1R
-
-# Could crash
-_Q8ccQ4M2e.
-_Q8ccQ4M2e.
-
 # fold-expression with missing third component could crash.
 _Z12binary_rightIJLi1ELi2ELi3EEEv1AIXfRplT_LiEEE
 _Z12binary_rightIJLi1ELi2ELi3EEEv1AIXfRplT_LiEEE
@@ -4732,16 +1405,6 @@ _Z1MA_aMMMMA_MMA_MMMMMMMMSt1MS_o11T0000000000t2M0oooozoooo
 _Z4294967297x
 _Z4294967297x
 #
-# demangler/80513 Test for bogus characters after __thunk_
-
-__thunk_16a_$_1x
-__thunk_16a_$_1x
-#
-# demangler/80513 Test for overflow in consume_count
-
-__thunk_4294967297__$_1x
-__thunk_4294967297__$_1x
-#
 # demangler/82195 members of lambdas
 --no-params
 _ZZZ3FoovENKUlT_E_clIiEEfS_EN5Local2fnEv

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: RFC: libiberty PATCH to disable demangling of ancient mangling schemes
  2018-12-07 15:49                             ` Jason Merrill
@ 2018-12-10  1:04                               ` Eric Gallager
  0 siblings, 0 replies; 55+ messages in thread
From: Eric Gallager @ 2018-12-10  1:04 UTC (permalink / raw)
  To: Jason Merrill
  Cc: Richard Biener, Nick Clifton, Pedro Alves, Ian Lance Taylor,
	Jakub Jelinek, matz, sgayou, tom, GCC Patches, Binutils

On 12/7/18, Jason Merrill <jason@redhat.com> wrote:
> On 12/7/18 6:36 AM, Richard Biener wrote:
>> On Thu, Dec 6, 2018 at 10:22 PM Jason Merrill <jason@redhat.com> wrote:
>>>
>>> On Thu, Dec 6, 2018 at 11:14 AM Jason Merrill <jason@redhat.com> wrote:
>>>>
>>>> Looks good to me.  Independently, do you see a reason not to disable
>>>> the
>>>> old demangler entirely?
>>>
>>> Like so.  Does anyone object to this?  These mangling schemes haven't
>>> been relevant in decades.
>>
>> Why #ifdef the code?  Just rip it out?
>
> I was thinking as an intermediate measure in case some user wanted it
> for some reason, but I'd be fine with that as well.
>
> Jason
>

A compromise could be to do the #ifdef for GCC 9, see if anyone
complains, and then if no one complains, rip it out entirely for GCC
10.

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH] Set DEMANGLE_RECURSION_LIMIT to 1536
  2018-12-07 16:25                               ` [PATCH] Set DEMANGLE_RECURSION_LIMIT to 1536 H.J. Lu
@ 2018-12-10 14:52                                 ` Michael Matz
  2018-12-10 15:10                                   ` Jakub Jelinek
                                                     ` (2 more replies)
  0 siblings, 3 replies; 55+ messages in thread
From: Michael Matz @ 2018-12-10 14:52 UTC (permalink / raw)
  To: Nick Clifton
  Cc: Ian Lance Taylor, H.J. Lu, Pedro Alves, Richard Guenther,
	Jakub Jelinek, sgayou, Tom Tromey, GCC Patches, Binutils,
	Jason Merrill

Hi,

On Fri, 7 Dec 2018, H.J. Lu wrote:

> > > On Thu, Dec 6, 2018 at 3:12 AM Nick Clifton <nickc@redhat.com> wrote:
> > > >
> > > >   Is the patch OK with you ?
> > >
> >
> > This caused:
> >
> > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88409
> >
> 
> Here is the fix.   OK for trunk?

I think this points toward the limit being _much_ too low.  With template 
meta programming you easily get these mangled names, it's not even a 
particularly long one.  But I'm wondering a bit, without tracing the 
demangler, just looking at the symbol name and demangled result I don't 
readily see where the depth of recursion really is more than 1024, are 
there perhaps some recursion_level-- statements skipped?


Ciao,
Michael.

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH] Set DEMANGLE_RECURSION_LIMIT to 1536
  2018-12-10 14:52                                 ` Michael Matz
@ 2018-12-10 15:10                                   ` Jakub Jelinek
  2018-12-10 15:34                                     ` Jason Merrill
  2018-12-10 15:12                                   ` Nick Clifton
  2018-12-10 15:18                                   ` David Malcolm
  2 siblings, 1 reply; 55+ messages in thread
From: Jakub Jelinek @ 2018-12-10 15:10 UTC (permalink / raw)
  To: Michael Matz
  Cc: Nick Clifton, Ian Lance Taylor, H.J. Lu, Pedro Alves,
	Richard Guenther, sgayou, Tom Tromey, GCC Patches, Binutils,
	Jason Merrill

On Mon, Dec 10, 2018 at 02:52:39PM +0000, Michael Matz wrote:
> On Fri, 7 Dec 2018, H.J. Lu wrote:
> 
> > > > On Thu, Dec 6, 2018 at 3:12 AM Nick Clifton <nickc@redhat.com> wrote:
> > > > >
> > > > >   Is the patch OK with you ?
> > > >
> > >
> > > This caused:
> > >
> > > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88409
> > >
> > 
> > Here is the fix.   OK for trunk?
> 
> I think this points toward the limit being _much_ too low.  With template 
> meta programming you easily get these mangled names, it's not even a 
> particularly long one.  But I'm wondering a bit, without tracing the 
> demangler, just looking at the symbol name and demangled result I don't 
> readily see where the depth of recursion really is more than 1024, are 
> there perhaps some recursion_level-- statements skipped?

That is because the recursion_level limit isn't hit in this case at all (far
from it).

What breaks it is this:

  /* PR 87675 - Check for a mangled string that is so long
     that we do not have enough stack space to demangle it.  */
  if (((options & DMGL_NO_RECURSE_LIMIT) == 0)
      /* This check is a bit arbitrary, since what we really want to do is to
         compare the sizes of the di.comps and di.subs arrays against the
         amount of stack space remaining.  But there is no portable way to do
         this, so instead we use the recursion limit as a guide to the maximum
         size of the arrays.  */
      && (unsigned long) di.num_comps > DEMANGLE_RECURSION_LIMIT)
    {
      /* FIXME: We need a way to indicate that a stack limit has been reached.  */
      return 0;
    }

where di.num_comps is just strlen (mangled) * 2.  Without any analysis
whatsoever, bumping the "recursion" limit will just mean we can process 1.5
times long names.  Either we need more precise analysis on what we are
looking for (how big arrays we'll need) or it needs to be an independent
limit and certainly should allow say 10KB symbols too if they are
reasonable.

	Jakub

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH] Set DEMANGLE_RECURSION_LIMIT to 1536
  2018-12-10 14:52                                 ` Michael Matz
  2018-12-10 15:10                                   ` Jakub Jelinek
@ 2018-12-10 15:12                                   ` Nick Clifton
  2018-12-10 15:18                                     ` Jakub Jelinek
  2018-12-10 15:18                                   ` David Malcolm
  2 siblings, 1 reply; 55+ messages in thread
From: Nick Clifton @ 2018-12-10 15:12 UTC (permalink / raw)
  To: Michael Matz
  Cc: Ian Lance Taylor, H.J. Lu, Pedro Alves, Richard Guenther,
	Jakub Jelinek, sgayou, Tom Tromey, GCC Patches, Binutils,
	Jason Merrill

Hi Michael,

> I think this points toward the limit being _much_ too low.

Fair enough - several other people have said this as well.  So
I have proposed an alternative patch instead.  My current suggestion
is to raise the limit to 2048, which allows the libiberty patch to 
pass.  But do you have a feel for how much is a realistic limit ?


> demangler, just looking at the symbol name and demangled result I don't 
> readily see where the depth of recursion really is more than 1024, are 
> there perhaps some recursion_level-- statements skipped?

I do not think so.  Unless there are some long jumps in the demangling code ?
I did a quick scan and did not find any, but I could have missed something.
Plus of course I cannot guarantee that my patch is bug free, although looking
at it again I do not see where I missed a level decrement.  

I think that the demangling code just is really recursive...

Cheers
  Nick

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH] Set DEMANGLE_RECURSION_LIMIT to 1536
  2018-12-10 14:52                                 ` Michael Matz
  2018-12-10 15:10                                   ` Jakub Jelinek
  2018-12-10 15:12                                   ` Nick Clifton
@ 2018-12-10 15:18                                   ` David Malcolm
  2018-12-10 15:31                                     ` Nick Clifton
  2 siblings, 1 reply; 55+ messages in thread
From: David Malcolm @ 2018-12-10 15:18 UTC (permalink / raw)
  To: Michael Matz, Nick Clifton
  Cc: Ian Lance Taylor, H.J. Lu, Pedro Alves, Richard Guenther,
	Jakub Jelinek, sgayou, Tom Tromey, GCC Patches, Binutils,
	Jason Merrill

On Mon, 2018-12-10 at 14:52 +0000, Michael Matz wrote:
> Hi,
> 
> On Fri, 7 Dec 2018, H.J. Lu wrote:
> 
> > > > On Thu, Dec 6, 2018 at 3:12 AM Nick Clifton <nickc@redhat.com>
> > > > wrote:
> > > > > 
> > > > >   Is the patch OK with you ?
> > > 
> > > This caused:
> > > 
> > > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88409
> > > 
> > 
> > Here is the fix.   OK for trunk?
> 
> I think this points toward the limit being _much_ too low.  With
> template 
> meta programming you easily get these mangled names, it's not even a 
> particularly long one.  But I'm wondering a bit, without tracing the 
> demangler, just looking at the symbol name and demangled result I
> don't 
> readily see where the depth of recursion really is more than 1024,
> are 
> there perhaps some recursion_level-- statements skipped?

Apologies in advance if this has been covered, as I've only been half-
watching this thread, but is it always the case that the recursion
depth can be bounded by some scalar multiple of the number of
characters in the name?

The name that's causing trouble is 654 characters long, and the
proposed limit of 1306 is slightly below double that.  There may well
be a bug in the implementation as Michael points out, but is the
recursion depth always guaranteed to be less than 2 * num_chars seen,
or somesuch limit.  If so, could the limit be dynamic, rather than
hardcoded?  That would trap cases where we're consuming stack frames
without consuming input characters, and eliminate having a hardcoded
limit that's bound to eventually become wrong as people write more and
more complicated C++ programs.

Hope this is constructive
Dave

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH] Set DEMANGLE_RECURSION_LIMIT to 1536
  2018-12-10 15:12                                   ` Nick Clifton
@ 2018-12-10 15:18                                     ` Jakub Jelinek
  2018-12-10 15:26                                       ` Nick Clifton
  0 siblings, 1 reply; 55+ messages in thread
From: Jakub Jelinek @ 2018-12-10 15:18 UTC (permalink / raw)
  To: Nick Clifton
  Cc: Michael Matz, Ian Lance Taylor, H.J. Lu, Pedro Alves,
	Richard Guenther, sgayou, Tom Tromey, GCC Patches, Binutils,
	Jason Merrill

On Mon, Dec 10, 2018 at 03:12:53PM +0000, Nick Clifton wrote:
> Hi Michael,
> 
> > I think this points toward the limit being _much_ too low.
> 
> Fair enough - several other people have said this as well.  So
> I have proposed an alternative patch instead.  My current suggestion
> is to raise the limit to 2048, which allows the libiberty patch to 
> pass.  But do you have a feel for how much is a realistic limit ?

For recursion limit I think that is fine.
For just stack size limit, I think it is extremely small.
I see that in the function it allocates on 64-bit 24 bytes times
num_comps using alloca, so 48 bytes per character in the mangled name,
and a pointer for each character in the mangled name.
That is 112KB per 2048 bytes long mangled name.

Dunno how much stack can we expect to be usable.

	Jakub

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH] Set DEMANGLE_RECURSION_LIMIT to 1536
  2018-12-10 15:18                                     ` Jakub Jelinek
@ 2018-12-10 15:26                                       ` Nick Clifton
  2018-12-10 15:35                                         ` Jakub Jelinek
  0 siblings, 1 reply; 55+ messages in thread
From: Nick Clifton @ 2018-12-10 15:26 UTC (permalink / raw)
  To: Jakub Jelinek
  Cc: Michael Matz, Ian Lance Taylor, H.J. Lu, Pedro Alves,
	Richard Guenther, sgayou, Tom Tromey, GCC Patches, Binutils,
	Jason Merrill

Hi Jakub,

>> My current suggestion
>> is to raise the limit to 2048, which allows the libiberty patch to 
>> pass.  But do you have a feel for how much is a realistic limit ?
> 
> For recursion limit I think that is fine.
> For just stack size limit, I think it is extremely small.
> I see that in the function it allocates on 64-bit 24 bytes times
> num_comps using alloca, so 48 bytes per character in the mangled name,
> and a pointer for each character in the mangled name.
> That is 112KB per 2048 bytes long mangled name.
> 
> Dunno how much stack can we expect to be usable.

Currently the patched libiberty uses the DEMANGLE_RECURSION_LIMIT value
in two ways.  The first is as a limit on the number of levels of recursion
of specific functions inside the demangler.  The second is as a check on
the number of component structures that will be allocated on the stack.
(See cp-demangle.c:d_demangle_callback).  One of the CVEs that I was checking
was triggering stack exhaustion this way, which is why I added the check.

There is at least one other function where a similar stack allocation
happens (cplus_demangle_print_callback) but I was not sure if this could
be triggered with the other limits in place, and I did not have a reproducer
that touched it, so I left it alone.

Cheers
  Nick


^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH] Set DEMANGLE_RECURSION_LIMIT to 1536
  2018-12-10 15:18                                   ` David Malcolm
@ 2018-12-10 15:31                                     ` Nick Clifton
  0 siblings, 0 replies; 55+ messages in thread
From: Nick Clifton @ 2018-12-10 15:31 UTC (permalink / raw)
  To: David Malcolm, Michael Matz
  Cc: Ian Lance Taylor, H.J. Lu, Pedro Alves, Richard Guenther,
	Jakub Jelinek, sgayou, Tom Tromey, GCC Patches, Binutils,
	Jason Merrill

Hi David,

> Apologies in advance if this has been covered, as I've only been half-
> watching this thread, but is it always the case that the recursion
> depth can be bounded by some scalar multiple of the number of
> characters in the name?

Probably, but the point of this patch is to add a fixed limit that
prevents too much recursion from being performed.  The CVEs that I
have been trying to fix have been using mangled names with 20K-30K
characters in them, so creating a recursion limit based on the 
length of the input would not prevent the stack exhaustion. :-(

My hope is that we can choose a value that will allow any realistic
mangled name to be decoded, but which will prevent these fuzzers from
generating arbitrary length strings which exhaust the machines resources.

Cheers
  Nick






^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH] Set DEMANGLE_RECURSION_LIMIT to 1536
  2018-12-10 15:10                                   ` Jakub Jelinek
@ 2018-12-10 15:34                                     ` Jason Merrill
  2018-12-11  0:33                                       ` Jeff Law
  0 siblings, 1 reply; 55+ messages in thread
From: Jason Merrill @ 2018-12-10 15:34 UTC (permalink / raw)
  To: Jakub Jelinek
  Cc: Michael Matz, Nick Clifton, Ian Lance Taylor, H.J. Lu,
	Pedro Alves, Richard Biener, Scott Gayou, Tom Tromey,
	gcc-patches List, Binutils

On Mon, Dec 10, 2018 at 10:10 AM Jakub Jelinek <jakub@redhat.com> wrote:
> On Mon, Dec 10, 2018 at 02:52:39PM +0000, Michael Matz wrote:
> > On Fri, 7 Dec 2018, H.J. Lu wrote:
> >
> > > > > On Thu, Dec 6, 2018 at 3:12 AM Nick Clifton <nickc@redhat.com> wrote:
> > > > > >
> > > > > >   Is the patch OK with you ?
> > > > >
> > > >
> > > > This caused:
> > > >
> > > > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88409
> > > >
> > >
> > > Here is the fix.   OK for trunk?
> >
> > I think this points toward the limit being _much_ too low.  With template
> > meta programming you easily get these mangled names, it's not even a
> > particularly long one.  But I'm wondering a bit, without tracing the
> > demangler, just looking at the symbol name and demangled result I don't
> > readily see where the depth of recursion really is more than 1024, are
> > there perhaps some recursion_level-- statements skipped?
>
> That is because the recursion_level limit isn't hit in this case at all (far
> from it).
>
> What breaks it is this:
>
>   /* PR 87675 - Check for a mangled string that is so long
>      that we do not have enough stack space to demangle it.  */
>   if (((options & DMGL_NO_RECURSE_LIMIT) == 0)
>       /* This check is a bit arbitrary, since what we really want to do is to
>          compare the sizes of the di.comps and di.subs arrays against the
>          amount of stack space remaining.  But there is no portable way to do
>          this, so instead we use the recursion limit as a guide to the maximum
>          size of the arrays.  */
>       && (unsigned long) di.num_comps > DEMANGLE_RECURSION_LIMIT)
>     {
>       /* FIXME: We need a way to indicate that a stack limit has been reached.  */
>       return 0;
>     }

> where di.num_comps is just strlen (mangled) * 2.  Without any analysis
> whatsoever, bumping the "recursion" limit will just mean we can process 1.5
> times long names.  Either we need more precise analysis on what we are
> looking for (how big arrays we'll need) or it needs to be an independent
> limit and certainly should allow say 10KB symbols too if they are
> reasonable.

If the problem is alloca, we could avoid using alloca if the size
passes a threshold.  Perhaps even use a better data structure than a
preallocated array based on a guess about the number of components...

Jason

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH] Set DEMANGLE_RECURSION_LIMIT to 1536
  2018-12-10 15:26                                       ` Nick Clifton
@ 2018-12-10 15:35                                         ` Jakub Jelinek
  2018-12-10 18:20                                           ` Ian Lance Taylor via gcc-patches
  0 siblings, 1 reply; 55+ messages in thread
From: Jakub Jelinek @ 2018-12-10 15:35 UTC (permalink / raw)
  To: Nick Clifton
  Cc: Michael Matz, Ian Lance Taylor, H.J. Lu, Pedro Alves,
	Richard Guenther, sgayou, Tom Tromey, GCC Patches, Binutils,
	Jason Merrill

On Mon, Dec 10, 2018 at 03:26:18PM +0000, Nick Clifton wrote:
> >> My current suggestion
> >> is to raise the limit to 2048, which allows the libiberty patch to 
> >> pass.  But do you have a feel for how much is a realistic limit ?
> > 
> > For recursion limit I think that is fine.
> > For just stack size limit, I think it is extremely small.
> > I see that in the function it allocates on 64-bit 24 bytes times
> > num_comps using alloca, so 48 bytes per character in the mangled name,
> > and a pointer for each character in the mangled name.
> > That is 112KB per 2048 bytes long mangled name.
> > 
> > Dunno how much stack can we expect to be usable.
> 
> Currently the patched libiberty uses the DEMANGLE_RECURSION_LIMIT value
> in two ways.  The first is as a limit on the number of levels of recursion
> of specific functions inside the demangler.  The second is as a check on
> the number of component structures that will be allocated on the stack.
> (See cp-demangle.c:d_demangle_callback).  One of the CVEs that I was checking
> was triggering stack exhaustion this way, which is why I added the check.
> 
> There is at least one other function where a similar stack allocation
> happens (cplus_demangle_print_callback) but I was not sure if this could
> be triggered with the other limits in place, and I did not have a reproducer
> that touched it, so I left it alone.

I think it is a bad idea to use the same macro and value for both the
recursion limit and essentially stack limit.  For the latter, it should
actually compute expected stack size
(i.e. di.num_comps * sizeof (*di.comps) + di.num_subs * sizeof (*di.subs))
and rather than just giving up should say that memory up to 64KB this
way will be handled via alloca, more through say mmap (I'd avoid malloc
because some users are using these APIs in cases where malloc isn't usable).
And have only much larger limit, like say 1MB for these arrays on which to
give up.

	Jakub

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH] Set DEMANGLE_RECURSION_LIMIT to 1536
  2018-12-10 15:35                                         ` Jakub Jelinek
@ 2018-12-10 18:20                                           ` Ian Lance Taylor via gcc-patches
  2018-12-10 18:55                                             ` Jakub Jelinek
  0 siblings, 1 reply; 55+ messages in thread
From: Ian Lance Taylor via gcc-patches @ 2018-12-10 18:20 UTC (permalink / raw)
  To: Jakub Jelinek
  Cc: Nick Clifton, Michael Matz, H.J. Lu, Pedro Alves,
	Richard Guenther, sgayou, Tom Tromey, gcc-patches, Binutils,
	Jason Merrill

On Mon, Dec 10, 2018 at 7:35 AM Jakub Jelinek <jakub@redhat.com> wrote:
>
> On Mon, Dec 10, 2018 at 03:26:18PM +0000, Nick Clifton wrote:
> > >> My current suggestion
> > >> is to raise the limit to 2048, which allows the libiberty patch to
> > >> pass.  But do you have a feel for how much is a realistic limit ?
> > >
> > > For recursion limit I think that is fine.
> > > For just stack size limit, I think it is extremely small.
> > > I see that in the function it allocates on 64-bit 24 bytes times
> > > num_comps using alloca, so 48 bytes per character in the mangled name,
> > > and a pointer for each character in the mangled name.
> > > That is 112KB per 2048 bytes long mangled name.
> > >
> > > Dunno how much stack can we expect to be usable.
> >
> > Currently the patched libiberty uses the DEMANGLE_RECURSION_LIMIT value
> > in two ways.  The first is as a limit on the number of levels of recursion
> > of specific functions inside the demangler.  The second is as a check on
> > the number of component structures that will be allocated on the stack.
> > (See cp-demangle.c:d_demangle_callback).  One of the CVEs that I was checking
> > was triggering stack exhaustion this way, which is why I added the check.
> >
> > There is at least one other function where a similar stack allocation
> > happens (cplus_demangle_print_callback) but I was not sure if this could
> > be triggered with the other limits in place, and I did not have a reproducer
> > that touched it, so I left it alone.
>
> I think it is a bad idea to use the same macro and value for both the
> recursion limit and essentially stack limit.  For the latter, it should
> actually compute expected stack size
> (i.e. di.num_comps * sizeof (*di.comps) + di.num_subs * sizeof (*di.subs))
> and rather than just giving up should say that memory up to 64KB this
> way will be handled via alloca, more through say mmap (I'd avoid malloc
> because some users are using these APIs in cases where malloc isn't usable).
> And have only much larger limit, like say 1MB for these arrays on which to
> give up.

That makes sense.

We've wanted to avoid malloc in this code because some programs call
the demangler from a signal handler.  But using mmap should be fine in
practice.

Ian

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH] Set DEMANGLE_RECURSION_LIMIT to 1536
  2018-12-10 18:20                                           ` Ian Lance Taylor via gcc-patches
@ 2018-12-10 18:55                                             ` Jakub Jelinek
  2018-12-10 23:47                                               ` Jason Merrill
  0 siblings, 1 reply; 55+ messages in thread
From: Jakub Jelinek @ 2018-12-10 18:55 UTC (permalink / raw)
  To: Ian Lance Taylor
  Cc: Nick Clifton, Michael Matz, H.J. Lu, Pedro Alves,
	Richard Guenther, sgayou, Tom Tromey, gcc-patches, Binutils,
	Jason Merrill

On Mon, Dec 10, 2018 at 10:20:24AM -0800, Ian Lance Taylor wrote:
> > I think it is a bad idea to use the same macro and value for both the
> > recursion limit and essentially stack limit.  For the latter, it should
> > actually compute expected stack size
> > (i.e. di.num_comps * sizeof (*di.comps) + di.num_subs * sizeof (*di.subs))
> > and rather than just giving up should say that memory up to 64KB this
> > way will be handled via alloca, more through say mmap (I'd avoid malloc
> > because some users are using these APIs in cases where malloc isn't usable).
> > And have only much larger limit, like say 1MB for these arrays on which to
> > give up.
> 
> That makes sense.
> 
> We've wanted to avoid malloc in this code because some programs call
> the demangler from a signal handler.  But using mmap should be fine in
> practice.

mmap is not available everywhere, but we could just have a smaller limit
on how big mangled names we handle on targets where mmap isn't available or
if it fails.

And, the other option is just try to parse the string without doing all the
processing first and compute (perhaps upper bound) on how many components
and substitutions we need.  Many components have longish names, or numbers,
etc. so the 2 * strlen is really very upper bound and strlen for number of
substitutions too.

	Jakub

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH] Set DEMANGLE_RECURSION_LIMIT to 1536
  2018-12-10 18:55                                             ` Jakub Jelinek
@ 2018-12-10 23:47                                               ` Jason Merrill
  0 siblings, 0 replies; 55+ messages in thread
From: Jason Merrill @ 2018-12-10 23:47 UTC (permalink / raw)
  To: Jakub Jelinek
  Cc: Ian Lance Taylor, Nick Clifton, Michael Matz, H.J. Lu,
	Pedro Alves, Richard Biener, Scott Gayou, Tom Tromey,
	gcc-patches List, Binutils

On Mon, Dec 10, 2018 at 1:55 PM Jakub Jelinek <jakub@redhat.com> wrote:
>
> On Mon, Dec 10, 2018 at 10:20:24AM -0800, Ian Lance Taylor wrote:
> > > I think it is a bad idea to use the same macro and value for both the
> > > recursion limit and essentially stack limit.  For the latter, it should
> > > actually compute expected stack size
> > > (i.e. di.num_comps * sizeof (*di.comps) + di.num_subs * sizeof (*di.subs))
> > > and rather than just giving up should say that memory up to 64KB this
> > > way will be handled via alloca, more through say mmap (I'd avoid malloc
> > > because some users are using these APIs in cases where malloc isn't usable).
> > > And have only much larger limit, like say 1MB for these arrays on which to
> > > give up.
> >
> > That makes sense.
> >
> > We've wanted to avoid malloc in this code because some programs call
> > the demangler from a signal handler.  But using mmap should be fine in
> > practice.
>
> mmap is not available everywhere, but we could just have a smaller limit
> on how big mangled names we handle on targets where mmap isn't available or
> if it fails.
>
> And, the other option is just try to parse the string without doing all the
> processing first and compute (perhaps upper bound) on how many components
> and substitutions we need.  Many components have longish names, or numbers,
> etc. so the 2 * strlen is really very upper bound and strlen for number of
> substitutions too.

Or, in that situation, we could put an upper bound on the number of
components and substitutions, and fail if we end up needing more than
that.

Jason

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH] Set DEMANGLE_RECURSION_LIMIT to 1536
  2018-12-10 15:34                                     ` Jason Merrill
@ 2018-12-11  0:33                                       ` Jeff Law
  2018-12-11  6:58                                         ` Jakub Jelinek
  2018-12-11 10:34                                         ` Pedro Alves
  0 siblings, 2 replies; 55+ messages in thread
From: Jeff Law @ 2018-12-11  0:33 UTC (permalink / raw)
  To: Jason Merrill, Jakub Jelinek
  Cc: Michael Matz, Nick Clifton, Ian Lance Taylor, H.J. Lu,
	Pedro Alves, Richard Biener, Scott Gayou, Tom Tromey,
	gcc-patches List, Binutils

On 12/10/18 8:34 AM, Jason Merrill wrote:
> On Mon, Dec 10, 2018 at 10:10 AM Jakub Jelinek <jakub@redhat.com> wrote:
>> On Mon, Dec 10, 2018 at 02:52:39PM +0000, Michael Matz wrote:
>>> On Fri, 7 Dec 2018, H.J. Lu wrote:
>>>
>>>>>> On Thu, Dec 6, 2018 at 3:12 AM Nick Clifton <nickc@redhat.com> wrote:
>>>>>>>
>>>>>>>   Is the patch OK with you ?
>>>>>>
>>>>>
>>>>> This caused:
>>>>>
>>>>> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88409
>>>>>
>>>>
>>>> Here is the fix.   OK for trunk?
>>>
>>> I think this points toward the limit being _much_ too low.  With template
>>> meta programming you easily get these mangled names, it's not even a
>>> particularly long one.  But I'm wondering a bit, without tracing the
>>> demangler, just looking at the symbol name and demangled result I don't
>>> readily see where the depth of recursion really is more than 1024, are
>>> there perhaps some recursion_level-- statements skipped?
>>
>> That is because the recursion_level limit isn't hit in this case at all (far
>> from it).
>>
>> What breaks it is this:
>>
>>   /* PR 87675 - Check for a mangled string that is so long
>>      that we do not have enough stack space to demangle it.  */
>>   if (((options & DMGL_NO_RECURSE_LIMIT) == 0)
>>       /* This check is a bit arbitrary, since what we really want to do is to
>>          compare the sizes of the di.comps and di.subs arrays against the
>>          amount of stack space remaining.  But there is no portable way to do
>>          this, so instead we use the recursion limit as a guide to the maximum
>>          size of the arrays.  */
>>       && (unsigned long) di.num_comps > DEMANGLE_RECURSION_LIMIT)
>>     {
>>       /* FIXME: We need a way to indicate that a stack limit has been reached.  */
>>       return 0;
>>     }
> 
>> where di.num_comps is just strlen (mangled) * 2.  Without any analysis
>> whatsoever, bumping the "recursion" limit will just mean we can process 1.5
>> times long names.  Either we need more precise analysis on what we are
>> looking for (how big arrays we'll need) or it needs to be an independent
>> limit and certainly should allow say 10KB symbols too if they are
>> reasonable.
> 
> If the problem is alloca, we could avoid using alloca if the size
> passes a threshold.  Perhaps even use a better data structure than a
> preallocated array based on a guess about the number of components...
Actually I would strongly suggest avoiding alloca completely.  This
isn't particularly performance sensitive code and alloca can be abused
in all kinds of interesting ways.

jeff

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH] Set DEMANGLE_RECURSION_LIMIT to 1536
  2018-12-11  0:33                                       ` Jeff Law
@ 2018-12-11  6:58                                         ` Jakub Jelinek
  2018-12-11 11:05                                           ` Pedro Alves
  2018-12-11 10:34                                         ` Pedro Alves
  1 sibling, 1 reply; 55+ messages in thread
From: Jakub Jelinek @ 2018-12-11  6:58 UTC (permalink / raw)
  To: Jeff Law
  Cc: Jason Merrill, Michael Matz, Nick Clifton, Ian Lance Taylor,
	H.J. Lu, Pedro Alves, Richard Biener, Scott Gayou, Tom Tromey,
	gcc-patches List, Binutils

On Mon, Dec 10, 2018 at 05:33:19PM -0700, Jeff Law wrote:
> >> where di.num_comps is just strlen (mangled) * 2.  Without any analysis
> >> whatsoever, bumping the "recursion" limit will just mean we can process 1.5
> >> times long names.  Either we need more precise analysis on what we are
> >> looking for (how big arrays we'll need) or it needs to be an independent
> >> limit and certainly should allow say 10KB symbols too if they are
> >> reasonable.
> > 
> > If the problem is alloca, we could avoid using alloca if the size
> > passes a threshold.  Perhaps even use a better data structure than a
> > preallocated array based on a guess about the number of components...
> Actually I would strongly suggest avoiding alloca completely.  This
> isn't particularly performance sensitive code and alloca can be abused
> in all kinds of interesting ways.

We can't use malloc, therefore on some targets alloca (or VLAs) are the only
option, and for small sizes even if mmap is available using it is too
costly.

Though, I like Jason's suggestion of just adding a maxinum of the number
of components and number of substitutions and failing if we need more.

	Jakub

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH] Set DEMANGLE_RECURSION_LIMIT to 1536
  2018-12-11  0:33                                       ` Jeff Law
  2018-12-11  6:58                                         ` Jakub Jelinek
@ 2018-12-11 10:34                                         ` Pedro Alves
  1 sibling, 0 replies; 55+ messages in thread
From: Pedro Alves @ 2018-12-11 10:34 UTC (permalink / raw)
  To: Jeff Law, Jason Merrill, Jakub Jelinek
  Cc: Michael Matz, Nick Clifton, Ian Lance Taylor, H.J. Lu,
	Richard Biener, Scott Gayou, Tom Tromey, gcc-patches List,
	Binutils

On 12/11/2018 12:33 AM, Jeff Law wrote:

> Actually I would strongly suggest avoiding alloca completely.  This
> isn't particularly performance sensitive code 

On the contrary, the demangler is very performance-sensitive code for GDB.

See <https://sourceware.org/ml/binutils/2018-11/msg00257.html>
and Tromey's response.

> and alloca can be abused
> in all kinds of interesting ways.

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH] Set DEMANGLE_RECURSION_LIMIT to 1536
  2018-12-11  6:58                                         ` Jakub Jelinek
@ 2018-12-11 11:05                                           ` Pedro Alves
  2018-12-11 14:26                                             ` Ian Lance Taylor via gcc-patches
  0 siblings, 1 reply; 55+ messages in thread
From: Pedro Alves @ 2018-12-11 11:05 UTC (permalink / raw)
  To: Jakub Jelinek, Jeff Law
  Cc: Jason Merrill, Michael Matz, Nick Clifton, Ian Lance Taylor,
	H.J. Lu, Richard Biener, Scott Gayou, Tom Tromey,
	gcc-patches List, Binutils

On 12/11/2018 06:58 AM, Jakub Jelinek wrote:
> On Mon, Dec 10, 2018 at 05:33:19PM -0700, Jeff Law wrote:
>>>> where di.num_comps is just strlen (mangled) * 2.  Without any analysis
>>>> whatsoever, bumping the "recursion" limit will just mean we can process 1.5
>>>> times long names.  Either we need more precise analysis on what we are
>>>> looking for (how big arrays we'll need) or it needs to be an independent
>>>> limit and certainly should allow say 10KB symbols too if they are
>>>> reasonable.
>>>
>>> If the problem is alloca, we could avoid using alloca if the size
>>> passes a threshold.  Perhaps even use a better data structure than a
>>> preallocated array based on a guess about the number of components...
>> Actually I would strongly suggest avoiding alloca completely.  This
>> isn't particularly performance sensitive code and alloca can be abused
>> in all kinds of interesting ways.
> 
> We can't use malloc, 

I noticed that the comment on top of __cxa_demangle says:

  "If OUTPUT_BUFFER is not long enough, it is expanded using realloc."

and __cxa_demangle calls 'free'.

And d_demangle, seemingly the workhorse for __cxa_demangle says:

/* Entry point for the demangler.  If MANGLED is a g++ v3 ABI mangled
   name, return a buffer allocated with malloc holding the demangled
   name.  OPTIONS is the usual libiberty demangler options.  On
   success, this sets *PALC to the allocated size of the returned
   buffer.  On failure, this sets *PALC to 0 for a bad name, or 1 for
   a memory allocation failure, and returns NULL.  */

cplus_demangle, the entry point that gdb uses, also relies on malloc.

Ian earlier mentioned that we've wanted to avoid malloc because some
programs call the demangler from a signal handler, but it seems like
we already do, these functions already aren't safe to use from
signal handlers as is.  Where does the "we can't use malloc" idea
come from?  Is there some entry point that avoids
the malloc/realloc/free calls?

Not advocating for adding to the number of malloc calls willy-nilly BTW.
I'd prefer to reduce the number of mallocs/rellocs calls within the
demangler and also within the bfd_demangle wrapper, for performance
reasons, for example by making it possible to reuse a growing buffer
across demangling invocations.

> therefore on some targets alloca (or VLAs) are the only
> option, and for small sizes even if mmap is available using it is too
> costly.
> 
> Though, I like Jason's suggestion of just adding a maxinum of the number
> of components and number of substitutions and failing if we need more.
> 
> 	Jakub

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH] Set DEMANGLE_RECURSION_LIMIT to 1536
  2018-12-11 11:05                                           ` Pedro Alves
@ 2018-12-11 14:26                                             ` Ian Lance Taylor via gcc-patches
  2018-12-11 15:07                                               ` Pedro Alves
  0 siblings, 1 reply; 55+ messages in thread
From: Ian Lance Taylor via gcc-patches @ 2018-12-11 14:26 UTC (permalink / raw)
  To: Pedro Alves
  Cc: Jakub Jelinek, Jeff Law, Jason Merrill, Michael Matz,
	Nick Clifton, H.J. Lu, Richard Guenther, sgayou, Tom Tromey,
	gcc-patches, Binutils

On Tue, Dec 11, 2018 at 3:05 AM Pedro Alves <palves@redhat.com> wrote:
>
> I noticed that the comment on top of __cxa_demangle says:
>
>   "If OUTPUT_BUFFER is not long enough, it is expanded using realloc."
>
> and __cxa_demangle calls 'free'.
>
> And d_demangle, seemingly the workhorse for __cxa_demangle says:
>
> /* Entry point for the demangler.  If MANGLED is a g++ v3 ABI mangled
>    name, return a buffer allocated with malloc holding the demangled
>    name.  OPTIONS is the usual libiberty demangler options.  On
>    success, this sets *PALC to the allocated size of the returned
>    buffer.  On failure, this sets *PALC to 0 for a bad name, or 1 for
>    a memory allocation failure, and returns NULL.  */
>
> cplus_demangle, the entry point that gdb uses, also relies on malloc.
>
> Ian earlier mentioned that we've wanted to avoid malloc because some
> programs call the demangler from a signal handler, but it seems like
> we already do, these functions already aren't safe to use from
> signal handlers as is.  Where does the "we can't use malloc" idea
> come from?  Is there some entry point that avoids
> the malloc/realloc/free calls?

cplus_demangle_v3_callback and cplus_demangle_print_callback.

Ian

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH] Set DEMANGLE_RECURSION_LIMIT to 1536
  2018-12-11 14:26                                             ` Ian Lance Taylor via gcc-patches
@ 2018-12-11 15:07                                               ` Pedro Alves
  0 siblings, 0 replies; 55+ messages in thread
From: Pedro Alves @ 2018-12-11 15:07 UTC (permalink / raw)
  To: Ian Lance Taylor
  Cc: Jakub Jelinek, Jeff Law, Jason Merrill, Michael Matz,
	Nick Clifton, H.J. Lu, Richard Guenther, sgayou, Tom Tromey,
	gcc-patches, Binutils

On 12/11/2018 02:25 PM, Ian Lance Taylor wrote:
> On Tue, Dec 11, 2018 at 3:05 AM Pedro Alves <palves@redhat.com> wrote:

>> Ian earlier mentioned that we've wanted to avoid malloc because some
>> programs call the demangler from a signal handler, but it seems like
>> we already do, these functions already aren't safe to use from
>> signal handlers as is.  Where does the "we can't use malloc" idea
>> come from?  Is there some entry point that avoids
>> the malloc/realloc/free calls?
> 
> cplus_demangle_v3_callback and cplus_demangle_print_callback.

Ah, gotcha.  Thanks!  Interesting.

Pedro Alves

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: RFC: libiberty PATCH to disable demangling of ancient mangling schemes
  2018-12-07 21:00                                   ` Jason Merrill
@ 2018-12-14 22:39                                     ` Jason Merrill
  2018-12-16  4:50                                       ` Simon Marchi
  0 siblings, 1 reply; 55+ messages in thread
From: Jason Merrill @ 2018-12-14 22:39 UTC (permalink / raw)
  To: Tom Tromey, Pedro Alves
  Cc: Jakub Jelinek, Nick Clifton, Ian Lance Taylor, Richard Biener,
	matz, Scott Gayou, gcc-patches List, Binutils, GDB Patches

On Fri, Dec 7, 2018 at 4:00 PM Jason Merrill <jason@redhat.com> wrote:
> On 12/7/18 12:48 PM, Tom Tromey wrote:
> >>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:
> >
> > Pedro> I would say that it's very, very unlikely, and not worth it of the
> > Pedro> maintenance burden.
> >
> > Agreed, and especially true for the more unusual demanglings like Lucid
> > or EDG.
> >
> > On the gdb side perhaps we can get rid of "demangle-style" now.  It
> > probably hasn't worked properly in years, and after this it would be
> > guaranteed not to.
>
> So, here's the patch to tear out the old code, which passes the GCC
> regression testsuite.  I also tried building binutils/gdb with it, and
> both will need to remove code that calls cplus_mangle_opname for dealing
> with the old mangling scheme.

GDB/binutils folks, how do you want to handle this? Shall I go ahead
with this patch, with the understanding that there will be associated
changes necessary when merging it into the binutils-gdb repository, or
go with the small disabling patch to start with?

Jason

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: RFC: libiberty PATCH to disable demangling of ancient mangling schemes
  2018-12-14 22:39                                     ` Jason Merrill
@ 2018-12-16  4:50                                       ` Simon Marchi
  0 siblings, 0 replies; 55+ messages in thread
From: Simon Marchi @ 2018-12-16  4:50 UTC (permalink / raw)
  To: Jason Merrill, Tom Tromey, Pedro Alves
  Cc: Jakub Jelinek, Nick Clifton, Ian Lance Taylor, Richard Biener,
	matz, Scott Gayou, gcc-patches List, Binutils, GDB Patches

On 2018-12-14 5:39 p.m., Jason Merrill wrote:
> GDB/binutils folks, how do you want to handle this? Shall I go ahead
> with this patch, with the understanding that there will be associated
> changes necessary when merging it into the binutils-gdb repository, or
> go with the small disabling patch to start with?

Hi Jason

From the GDB point of view, I don't see any problem.  Please proceed with
the cleanup, it should be quite easy to adjust our code when we sync libiberty.

There is a usage of cplus_mangle_opname in binutils/stabs.c, and I can't
speak for binutils.  But speaking of cplus_mangle_opname, shouldn't you also
remove the declaration in include/demangle.h?

Simon

^ permalink raw reply	[flat|nested] 55+ messages in thread

end of thread, other threads:[~2018-12-16  4:50 UTC | newest]

Thread overview: 55+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-11-30  8:38 RFA/RFC: Add stack recursion limit to libiberty's demangler Nick Clifton
2018-11-30  8:42 ` Jakub Jelinek
2018-11-30 10:27   ` Nick Clifton
2018-11-30 13:46     ` Michael Matz
2018-11-30 14:57       ` Ian Lance Taylor
2018-12-02  0:49         ` Cary Coutant
2018-12-03 14:53           ` Nick Clifton
2018-12-03 22:00           ` Joseph Myers
2018-11-30 13:56     ` Ian Lance Taylor
2018-11-30 14:03       ` Jakub Jelinek
2018-11-30 17:41         ` RFA/RFC: Add stack recursion limit to libiberty's demangler [v3] Nick Clifton
2018-11-30 17:49           ` Jakub Jelinek
2018-11-30 18:19           ` Pedro Alves
2018-12-03 10:28           ` Richard Biener
2018-12-03 14:45             ` Nick Clifton
2018-12-03 18:49               ` Ian Lance Taylor via gcc-patches
2018-12-04 14:00                 ` RFA/RFC: Add stack recursion limit to libiberty's demangler [v4] Nick Clifton
2018-12-04 15:02                   ` Pedro Alves
2018-12-04 16:57                     ` RFA/RFC: Add stack recursion limit to libiberty's demangler [v5] Nick Clifton
2018-12-04 17:08                       ` Pedro Alves
2018-12-06 11:12                         ` Nick Clifton
2018-12-06 18:04                           ` Ian Lance Taylor via gcc-patches
2018-12-07 16:17                             ` H.J. Lu
2018-12-07 16:25                               ` [PATCH] Set DEMANGLE_RECURSION_LIMIT to 1536 H.J. Lu
2018-12-10 14:52                                 ` Michael Matz
2018-12-10 15:10                                   ` Jakub Jelinek
2018-12-10 15:34                                     ` Jason Merrill
2018-12-11  0:33                                       ` Jeff Law
2018-12-11  6:58                                         ` Jakub Jelinek
2018-12-11 11:05                                           ` Pedro Alves
2018-12-11 14:26                                             ` Ian Lance Taylor via gcc-patches
2018-12-11 15:07                                               ` Pedro Alves
2018-12-11 10:34                                         ` Pedro Alves
2018-12-10 15:12                                   ` Nick Clifton
2018-12-10 15:18                                     ` Jakub Jelinek
2018-12-10 15:26                                       ` Nick Clifton
2018-12-10 15:35                                         ` Jakub Jelinek
2018-12-10 18:20                                           ` Ian Lance Taylor via gcc-patches
2018-12-10 18:55                                             ` Jakub Jelinek
2018-12-10 23:47                                               ` Jason Merrill
2018-12-10 15:18                                   ` David Malcolm
2018-12-10 15:31                                     ` Nick Clifton
2018-12-06 16:14                       ` RFA/RFC: Add stack recursion limit to libiberty's demangler [v5] Jason Merrill
2018-12-06 21:22                         ` RFC: libiberty PATCH to disable demangling of ancient mangling schemes Jason Merrill
2018-12-07 10:27                           ` Nick Clifton
2018-12-07 10:40                             ` Jakub Jelinek
2018-12-07 16:11                               ` Pedro Alves
2018-12-07 17:49                                 ` Tom Tromey
2018-12-07 21:00                                   ` Jason Merrill
2018-12-14 22:39                                     ` Jason Merrill
2018-12-16  4:50                                       ` Simon Marchi
2018-12-07 16:28                               ` Nick Clifton
2018-12-07 11:37                           ` Richard Biener
2018-12-07 15:49                             ` Jason Merrill
2018-12-10  1:04                               ` Eric Gallager

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).