This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH][RFC] Malloc-less demangler interface


Attached is a proposed patch to libiberty's demangler.  It allows a careful
caller to demangle a name without using any heap allocation functions.
This makes it useful for functions such as __verbose_terminate_handler in
libstdc++, which might need to operate in conditions where the heap or the
malloc arena have been corrupted by a problem in user code.

The patch works by separating out the string growing components of the
original demangler from the demangling engine itself, and exposing name
demangling via an alternative interface that returns elements of the
demangled string through a callback function as they are produced by the
engine.  The primary entry point for callback-based demangling is the
__cxa_demangle_callback() function; this augments  __cxa_demangle(), which
remains available.  There is also a callback version of cplus_demangle(),
though this will probably be less useful than __cxa_demangle_callback().
All prior public interfaces to demangling remain, and are unchanged.

Primary testing is with the libiberty/testsuite, run on i686-pc-linux-gnu
and powerpc-apple-darwin8.8.0.  It's also confirmed to work with all tests
in gcc-4.1.1/libstdc++-v3/testsuite/demangle when built into libstdc++.

Performance, measured over ~250,000 mangled names, is identical to the
original version within the limits of benchmark stability.  Valgrind
confirms no memory leaks are introduced with the new growable strings,
and gdb with a small test program confirms that no heap allocations are
made by the demangler when __cxa_demangle_callback() is called.

Once this patch is submitted, I plan to activate it by creating a patch
to libstdc++v3 to call __cxa_demangle_callback() in place of the call to
__cxa_demangle() in __verbose_terminate_handler() within libsupc++'s
vterminate.cc.


2007-01-09  Simon Baldwin <simonb@google.com>

	* demangle.h: New cplus_demangle_callback function prototype and
	demangle_callbackref type definition.
	* cp-demangle.h (cplus_demangle_operators): Explicitly sized.
	* cp-demangle.c (__cxa_demangle_callback): Augmented interface
	to demangling, provides a malloc-less version of __cxa_demangle.
	(cplus_demangle_callback): Public callback version of cplus_demangle.
	(struct d_growable_string): New growable string structure.
	(d_growable_string_init): New function, provides support for
	growable strings separate from print info.
	(d_growable_string_resize): Likewise.
	(d_growable_string_append_buffer): Likewise.
	(d_growable_string_callback_adapter):): Likewise.
	(d_print_init): New print info initialization function.
	(d_print_error): Macro replace by inline function.
	(d_print_saw_error): Likewise.
	(d_append_char): Likewise.
	(d_append_buffer): Likewise.
	(d_append_string): New inline function, replaces the
	d_append_string_constant macro.
	(d_flush_buffer): New function, flushes buffer to callback.
	(d_demangle_callback, is_ctor_or_dtor): Malloc-based fallback
	for unsupported dynamic arrays replaced by alloca().
	(d_demangle): Return string length estimating removed.
	(d_dump): Moved error case handling from call site into function.
	(d_print_resize: Function removed.
	(d_print_append_char): Likewise.
	(d_print_append_buffer): Likewise.
	(d_print_error): Likewise.


diff -rcp3 orig/include/demangle.h new/include/demangle.h
*** orig/include/demangle.h	Wed Dec 27 12:03:11 2006
--- new/include/demangle.h	Tue Jan  9 10:01:25 2007
*************** cplus_demangle_print (int options,
*** 529,534 ****
--- 529,555 ----
                        int estimated_length,
                        size_t *p_allocated_size);
  
+ /* This function takes a struct demangle_component tree and passes back
+    a demangled string in one or more calls to a callback function.
+    The first argument is DMGL_* options.  The second is the tree to
+    demangle.  The third is an opaque value used as a callback argument.
+    The fourth is a pointer to a callback function, called with opaque
+    as its first argument, and its second and third arguments an element
+    of the demangled string and its length.  The callback is called once
+    or more to return the full demangled string; the demangled element
+    string is always nul-terminated, although its length is also provided
+    for convenience.  In contrast to cplus_demangle_print(), this function
+    does not allocate heap memory to grow output strings (except perhaps
+    where alloca() is implemented by malloc()), and so is normally safe
+    for use where the heap has been corrupted.  On success, this function
+    returns 1; on failure, 0.  */
+ 
+ typedef void (*demangle_callbackref) (void*, const char*, size_t);
+ extern int
+ cplus_demangle_callback (int options,
+                          const struct demangle_component *tree,
+                          void *opaque, demangle_callbackref);
+ 
  #ifdef __cplusplus
  }
  #endif /* __cplusplus */
diff -rcp3 orig/libiberty/cp-demangle.c new/libiberty/cp-demangle.c
*** orig/libiberty/cp-demangle.c	Wed Dec 27 12:02:06 2006
--- new/libiberty/cp-demangle.c	Tue Jan  9 15:08:13 2007
***************
*** 50,61 ****
--- 50,63 ----
     defined in demangle.h:
        enum demangle_component_type
        struct demangle_component
+       demangle_callbackref
     and these functions defined in this file:
        cplus_demangle_fill_name
        cplus_demangle_fill_extended_operator
        cplus_demangle_fill_ctor
        cplus_demangle_fill_dtor
        cplus_demangle_print
+       cplus_demangle_callback
     and other functions defined in the file cp-demint.c.
  
     This file also defines some other functions and variables which are
***************
*** 64,77 ****
     Preprocessor macros you can define while compiling this file:
  
     IN_LIBGCC2
!       If defined, this file defines the following function, q.v.:
           char *__cxa_demangle (const char *mangled, char *buf, size_t *len,
                                 int *status)
        instead of cplus_demangle_v3() and java_demangle_v3().
  
     IN_GLIBCPP_V3
!       If defined, this file defines only __cxa_demangle(), and no other
!       publically visible functions or variables.
  
     STANDALONE_DEMANGLER
        If defined, this file defines a main() function which demangles
--- 66,82 ----
     Preprocessor macros you can define while compiling this file:
  
     IN_LIBGCC2
!       If defined, this file defines the following functions, q.v.:
           char *__cxa_demangle (const char *mangled, char *buf, size_t *len,
                                 int *status)
+          int __cxa_demangle_callback (const char *, void *,
+                                       void (*) (void *, const char *, size_t))
        instead of cplus_demangle_v3() and java_demangle_v3().
  
     IN_GLIBCPP_V3
!       If defined, this file defines only __cxa_demangle() and
!       __cxa_demangle_callback(), and no other publically visible functions
!       or variables.
  
     STANDALONE_DEMANGLER
        If defined, this file defines a main() function which demangles
***************
*** 95,100 ****
--- 100,117 ----
  #include <string.h>
  #endif
  
+ #ifdef HAVE_ALLOCA_H
+ # include <alloca.h>
+ #else
+ # ifndef alloca
+ #  ifdef __GNUC__
+ #   define alloca __builtin_alloca
+ #  else
+ extern char *alloca ();
+ #  endif /* __GNUC__ */
+ # endif /* alloca */
+ #endif /* HAVE_ALLOCA_H */
+ 
  #include "ansidecl.h"
  #include "libiberty.h"
  #include "demangle.h"
*************** static struct demangle_component *d_type
*** 135,140 ****
--- 152,161 ----
  #define cplus_demangle_print d_print
  static char *d_print (int, const struct demangle_component *, int, size_t *);
  
+ #define cplus_demangle_callback d_callback
+ static int d_callback (int, const struct demangle_component *,
+                        void *, demangle_callbackref);
+ 
  #define cplus_demangle_init_info d_init_info
  static void d_init_info (const char *, int, size_t, struct d_info *);
  
*************** static void d_init_info (const char *, i
*** 162,169 ****
     V3 demangler code.
  
     As of this writing this file has the following undefined references
!    when compiled with -DIN_GLIBCPP_V3: malloc, realloc, free, memcpy,
!    strcpy, strcat, strlen.  */
  
  #define IS_DIGIT(c) ((c) >= '0' && (c) <= '9')
  #define IS_UPPER(c) ((c) >= 'A' && (c) <= 'Z')
--- 183,190 ----
     V3 demangler code.
  
     As of this writing this file has the following undefined references
!    when compiled with -DIN_GLIBCPP_V3: realloc, free, memcpy, strcpy,
!    strcat, strlen.  */
  
  #define IS_DIGIT(c) ((c) >= '0' && (c) <= '9')
  #define IS_UPPER(c) ((c) >= 'A' && (c) <= 'Z')
*************** struct d_print_mod
*** 228,285 ****
    struct d_print_template *templates;
  };
  
! /* We use this structure to hold information during printing.  */
  
! struct d_print_info
  {
-   /* The options passed to the demangler.  */
-   int options;
    /* Buffer holding the result.  */
    char *buf;
    /* Current length of data in buffer.  */
    size_t len;
    /* Allocated size of buffer.  */
    size_t alc;
    /* The current list of templates, if any.  */
    struct d_print_template *templates;
    /* The current list of modifiers (e.g., pointer, reference, etc.),
       if any.  */
    struct d_print_mod *modifiers;
!   /* Set to 1 if we had a memory allocation failure.  */
!   int allocation_failure;
  };
  
- #define d_print_saw_error(dpi) ((dpi)->buf == NULL)
- 
- #define d_append_char(dpi, c) \
-   do \
-     { \
-       if ((dpi)->buf != NULL && (dpi)->len < (dpi)->alc) \
-         (dpi)->buf[(dpi)->len++] = (c); \
-       else \
-         d_print_append_char ((dpi), (c)); \
-     } \
-   while (0)
- 
- #define d_append_buffer(dpi, s, l) \
-   do \
-     { \
-       if ((dpi)->buf != NULL && (dpi)->len + (l) <= (dpi)->alc) \
-         { \
-           memcpy ((dpi)->buf + (dpi)->len, (s), (l)); \
-           (dpi)->len += l; \
-         } \
-       else \
-         d_print_append_buffer ((dpi), (s), (l)); \
-     } \
-   while (0)
- 
- #define d_append_string_constant(dpi, s) \
-   d_append_buffer (dpi, (s), sizeof (s) - 1)
- 
- #define d_last_char(dpi) \
-   ((dpi)->buf == NULL || (dpi)->len == 0 ? '\0' : (dpi)->buf[(dpi)->len - 1])
- 
  #ifdef CP_DEMANGLE_DEBUG
  static void d_dump (struct demangle_component *, int);
  #endif
--- 249,291 ----
    struct d_print_template *templates;
  };
  
! /* We use these structures to hold information during printing.  */
  
! struct d_growable_string
  {
    /* Buffer holding the result.  */
    char *buf;
    /* Current length of data in buffer.  */
    size_t len;
    /* Allocated size of buffer.  */
    size_t alc;
+   /* Set to 1 if we had a memory allocation failure.  */
+   int allocation_failure;
+ };
+ 
+ enum { D_PRINT_BUFFER_LENGTH = 256 };
+ struct d_print_info
+ {
+   /* The options passed to the demangler.  */
+   int options;
+   /* Fixed-length allocated buffer for demangled data, flushed to the
+      callback with a NUL termination once full.  */
+   char buf[D_PRINT_BUFFER_LENGTH];
+   /* Current length of data in buffer.  */
+   size_t len;
+   /* Callback function to handle demangled buffer flush.  */
+   demangle_callbackref callback;
+   /* Opaque callback argument.  */
+   void *opaque;
    /* The current list of templates, if any.  */
    struct d_print_template *templates;
    /* The current list of modifiers (e.g., pointer, reference, etc.),
       if any.  */
    struct d_print_mod *modifiers;
!   /* Set to 1 if we saw a demangling error.  */
!   int demangle_failure;
  };
  
  #ifdef CP_DEMANGLE_DEBUG
  static void d_dump (struct demangle_component *, int);
  #endif
*************** d_add_substitution (struct d_info *, str
*** 389,402 ****
  
  static struct demangle_component *d_substitution (struct d_info *, int);
  
! static void d_print_resize (struct d_print_info *, size_t);
  
! static void d_print_append_char (struct d_print_info *, int);
  
  static void
! d_print_append_buffer (struct d_print_info *, const char *, size_t);
  
! static void d_print_error (struct d_print_info *);
  
  static void
  d_print_comp (struct d_print_info *, const struct demangle_component *);
--- 395,427 ----
  
  static struct demangle_component *d_substitution (struct d_info *, int);
  
! static void d_growable_string_init (struct d_growable_string *, size_t);
! 
! static inline void
! d_growable_string_resize (struct d_growable_string *, size_t);
  
! static inline void
! d_growable_string_append_buffer (struct d_growable_string *,
!                                  const char*, size_t);
! static void
! d_growable_string_callback_adapter (void *, const char*, size_t);
  
  static void
! d_print_init (struct d_print_info *, int, void *, demangle_callbackref);
! 
! static inline void d_print_error (struct d_print_info *);
! 
! static inline int d_print_saw_error (struct d_print_info *);
! 
! static inline void d_print_flush (struct d_print_info *);
! 
! static inline void d_append_char (struct d_print_info *, char);
! 
! static inline void d_append_buffer (struct d_print_info*, const char*, size_t);
  
! static inline void d_append_string (struct d_print_info*, const char*);
! 
! static inline char d_last_char (struct d_print_info*);
  
  static void
  d_print_comp (struct d_print_info *, const struct demangle_component *);
*************** d_dump (struct demangle_component *dc, i
*** 436,442 ****
    int i;
  
    if (dc == NULL)
!     return;
  
    for (i = 0; i < indent; ++i)
      putchar (' ');
--- 461,471 ----
    int i;
  
    if (dc == NULL)
!     {
!       if (indent == 0)
!         printf ("failed demangling\n");
!       return;
!     }
  
    for (i = 0; i < indent; ++i)
      putchar (' ');
*************** d_identifier (struct d_info *di, int len
*** 1333,1339 ****
  #define NL(s) s, (sizeof s) - 1
  
  CP_STATIC_IF_GLIBCPP_V3
! const struct demangle_operator_info cplus_demangle_operators[] =
  {
    { "aN", NL ("&="),        2 },
    { "aS", NL ("="),         2 },
--- 1362,1369 ----
  #define NL(s) s, (sizeof s) - 1
  
  CP_STATIC_IF_GLIBCPP_V3
! const struct demangle_operator_info
! cplus_demangle_operators[D_OPERATORS_COUNT] =
  {
    { "aN", NL ("&="),        2 },
    { "aS", NL ("="),         2 },
*************** d_substitution (struct d_info *di, int p
*** 2568,2647 ****
      }
  }
  
! /* Resize the print buffer.  */
  
  static void
! d_print_resize (struct d_print_info *dpi, size_t add)
  {
!   size_t need;
  
!   if (dpi->buf == NULL)
      return;
-   need = dpi->len + add;
-   while (need > dpi->alc)
-     {
-       size_t newalc;
-       char *newbuf;
  
!       newalc = dpi->alc * 2;
!       newbuf = (char *) realloc (dpi->buf, newalc);
!       if (newbuf == NULL)
! 	{
! 	  free (dpi->buf);
! 	  dpi->buf = NULL;
! 	  dpi->allocation_failure = 1;
! 	  return;
! 	}
!       dpi->buf = newbuf;
!       dpi->alc = newalc;
      }
  }
  
! /* Append a character to the print buffer.  */
  
! static void
! d_print_append_char (struct d_print_info *dpi, int c)
  {
!   if (dpi->buf != NULL)
!     {
!       if (dpi->len >= dpi->alc)
! 	{
! 	  d_print_resize (dpi, 1);
! 	  if (dpi->buf == NULL)
! 	    return;
! 	}
  
!       dpi->buf[dpi->len] = c;
!       ++dpi->len;
!     }
  }
  
! /* Append a buffer to the print buffer.  */
  
  static void
! d_print_append_buffer (struct d_print_info *dpi, const char *s, size_t l)
  {
!   if (dpi->buf != NULL)
!     {
!       if (dpi->len + l > dpi->alc)
! 	{
! 	  d_print_resize (dpi, l);
! 	  if (dpi->buf == NULL)
! 	    return;
! 	}
  
!       memcpy (dpi->buf + dpi->len, s, l);
!       dpi->len += l;
!     }
  }
  
! /* Indicate that an error occurred during printing.  */
  
  static void
  d_print_error (struct d_print_info *dpi)
  {
!   free (dpi->buf);
!   dpi->buf = NULL;
  }
  
  /* Turn components into a human readable string.  OPTIONS is the
--- 2598,2775 ----
      }
  }
  
! /* Initialize a growable string.  */
  
  static void
! d_growable_string_init (struct d_growable_string *dgs, size_t estimate)
  {
!   dgs->buf = NULL;
!   dgs->len = 0;
!   dgs->alc = 0;
!   dgs->allocation_failure = 0;
  
!   if (estimate > 0)
!     d_growable_string_resize (dgs, estimate);
! }
! 
! /* Grow a growable string to a given size.  */
! 
! static inline void
! d_growable_string_resize (struct d_growable_string *dgs, size_t need)
! {
!   size_t newalc;
!   char *newbuf;
! 
!   if (dgs->allocation_failure == 1)
      return;
  
!   /* Start allocation at two bytes to avoid any possibility of confusion
!      with the special value of 1 used as a return in *palc to indicate
!      allocation failures.  */
!   newalc = dgs->alc > 0 ? dgs->alc : 2;
!   while (newalc < need)
!     newalc <<= 1;
! 
!   newbuf = (char *) realloc (dgs->buf, newalc);
!   if (newbuf == NULL)
!     {
!       free (dgs->buf);
!       dgs->buf = NULL;
!       dgs->len = 0;
!       dgs->alc = 0;
!       dgs->allocation_failure = 1;
!       return;
      }
+   dgs->buf = newbuf;
+   dgs->alc = newalc;
  }
  
! /* Append a buffer to a growable string.  */
  
! static inline void
! d_growable_string_append_buffer (struct d_growable_string *dgs,
!                                  const char *s, size_t l)
  {
!   size_t need;
  
!   need = dgs->len + l + 1;
!   if (need > dgs->alc)
!     d_growable_string_resize (dgs, need);
! 
!   if (dgs->allocation_failure == 1)
!     return;
! 
!   memcpy (dgs->buf + dgs->len, s, l);
!   dgs->buf[dgs->len + l] = '\0';
!   dgs->len += l;
  }
  
! /* Bridge growable strings to the callback mechanism.  */
  
  static void
! d_growable_string_callback_adapter (void *opaque, const char *s, size_t l)
  {
!   struct d_growable_string* dgs = (struct d_growable_string*) opaque;
  
!   d_growable_string_append_buffer (dgs, s, l);
  }
  
! /* Initialize a print information structure.  */
  
  static void
+ d_print_init (struct d_print_info *dpi, int options,
+               void *opaque, demangle_callbackref callback)
+ {
+   dpi->options = options;
+   dpi->len = 0;
+   dpi->templates = NULL;
+   dpi->modifiers = NULL;
+ 
+   dpi->opaque = opaque;
+   dpi->callback = callback;
+ 
+   dpi->demangle_failure = 0;
+ }
+ 
+ /* Indicate that an error occurred during printing, and test for error.  */
+ 
+ static inline void
  d_print_error (struct d_print_info *dpi)
  {
!   dpi->demangle_failure = 1;
! }
! 
! static inline int
! d_print_saw_error (struct d_print_info *dpi)
! {
!   return dpi->demangle_failure == 1;
! }
! 
! /* Flush buffered characters to the callback.  */
! 
! static inline void
! d_print_flush (struct d_print_info *dpi)
! {
!   dpi->buf[dpi->len] = '\0';
!   dpi->callback (dpi->opaque, dpi->buf, dpi->len);
!   dpi->len = 0;
! }
! 
! /* Append characters and buffers for printing.  */
! 
! static inline void
! d_append_char (struct d_print_info *dpi, char c)
! {
!   if (dpi->len == sizeof (dpi->buf) - 1)
!     d_print_flush (dpi);
! 
!   dpi->buf[dpi->len++] = c;
! }
! 
! static inline void
! d_append_buffer (struct d_print_info *dpi, const char *s, size_t l)
! {
!   size_t i;
! 
!   for (i = 0; i < l; i++)
!     d_append_char (dpi, s[i]);
! }
! 
! static inline void
! d_append_string (struct d_print_info *dpi, const char *s)
! {
!   d_append_buffer (dpi, s, strlen (s));
! }
! 
! static inline char
! d_last_char (struct d_print_info *dpi)
! {
!   return dpi->len > 0 ? dpi->buf[dpi->len - 1] : '\0';
! }
! 
! /* Turn components into a human readable string.  OPTIONS is the
!    options bits passed to the demangler.  DC is the tree to print.
!    OPAQUE is a generalized callback argument, and CALLBACK is a
!    function to call to flush demangled string segments as they fill
!    the intermediate buffer.  On success, this returns 1.  On failure,
!    it returns 0, indicating a bad parse.  It does not use heap
!    memory to build an output string, so cannot encounter memory
!    allocation failure.  */
! 
! CP_STATIC_IF_GLIBCPP_V3
! int
! cplus_demangle_callback (int options, const struct demangle_component *dc,
!                          void *opaque, demangle_callbackref callback)
! {
!   struct d_print_info dpi;
! 
!   d_print_init (&dpi, options, opaque, callback);
! 
!   d_print_comp (&dpi, dc);
! 
!   d_print_flush (&dpi);
! 
!   return ! d_print_saw_error (&dpi);
  }
  
  /* Turn components into a human readable string.  OPTIONS is the
*************** char *
*** 2657,2690 ****
  cplus_demangle_print (int options, const struct demangle_component *dc,
                        int estimate, size_t *palc)
  {
!   struct d_print_info dpi;
  
!   dpi.options = options;
  
!   dpi.alc = estimate + 1;
!   dpi.buf = (char *) malloc (dpi.alc);
!   if (dpi.buf == NULL)
      {
!       *palc = 1;
        return NULL;
      }
  
!   dpi.len = 0;
!   dpi.templates = NULL;
!   dpi.modifiers = NULL;
! 
!   dpi.allocation_failure = 0;
! 
!   d_print_comp (&dpi, dc);
! 
!   d_append_char (&dpi, '\0');
! 
!   if (dpi.buf != NULL)
!     *palc = dpi.alc;
!   else
!     *palc = dpi.allocation_failure;
! 
!   return dpi.buf;
  }
  
  /* Subroutine to handle components.  */
--- 2785,2804 ----
  cplus_demangle_print (int options, const struct demangle_component *dc,
                        int estimate, size_t *palc)
  {
!   struct d_growable_string dgs;
  
!   d_growable_string_init (&dgs, estimate);
  
!   if (! cplus_demangle_callback (options, dc,
!                                  &dgs, d_growable_string_callback_adapter))
      {
!       free (dgs.buf);
!       *palc = 0;
        return NULL;
      }
  
!   *palc = (dgs.allocation_failure == 1) ? 1 : dgs.alc;
!   return dgs.buf;
  }
  
  /* Subroutine to handle components.  */
*************** d_print_comp (struct d_print_info *dpi,
*** 2714,2720 ****
      case DEMANGLE_COMPONENT_LOCAL_NAME:
        d_print_comp (dpi, d_left (dc));
        if ((dpi->options & DMGL_JAVA) == 0)
! 	d_append_string_constant (dpi, "::");
        else
  	d_append_char (dpi, '.');
        d_print_comp (dpi, d_right (dc));
--- 2828,2834 ----
      case DEMANGLE_COMPONENT_LOCAL_NAME:
        d_print_comp (dpi, d_left (dc));
        if ((dpi->options & DMGL_JAVA) == 0)
! 	d_append_string (dpi, "::");
        else
  	d_append_char (dpi, '.');
        d_print_comp (dpi, d_right (dc));
*************** d_print_comp (struct d_print_info *dpi,
*** 2903,2971 ****
        return;
  
      case DEMANGLE_COMPONENT_VTABLE:
!       d_append_string_constant (dpi, "vtable for ");
        d_print_comp (dpi, d_left (dc));
        return;
  
      case DEMANGLE_COMPONENT_VTT:
!       d_append_string_constant (dpi, "VTT for ");
        d_print_comp (dpi, d_left (dc));
        return;
  
      case DEMANGLE_COMPONENT_CONSTRUCTION_VTABLE:
!       d_append_string_constant (dpi, "construction vtable for ");
        d_print_comp (dpi, d_left (dc));
!       d_append_string_constant (dpi, "-in-");
        d_print_comp (dpi, d_right (dc));
        return;
  
      case DEMANGLE_COMPONENT_TYPEINFO:
!       d_append_string_constant (dpi, "typeinfo for ");
        d_print_comp (dpi, d_left (dc));
        return;
  
      case DEMANGLE_COMPONENT_TYPEINFO_NAME:
!       d_append_string_constant (dpi, "typeinfo name for ");
        d_print_comp (dpi, d_left (dc));
        return;
  
      case DEMANGLE_COMPONENT_TYPEINFO_FN:
!       d_append_string_constant (dpi, "typeinfo fn for ");
        d_print_comp (dpi, d_left (dc));
        return;
  
      case DEMANGLE_COMPONENT_THUNK:
!       d_append_string_constant (dpi, "non-virtual thunk to ");
        d_print_comp (dpi, d_left (dc));
        return;
  
      case DEMANGLE_COMPONENT_VIRTUAL_THUNK:
!       d_append_string_constant (dpi, "virtual thunk to ");
        d_print_comp (dpi, d_left (dc));
        return;
  
      case DEMANGLE_COMPONENT_COVARIANT_THUNK:
!       d_append_string_constant (dpi, "covariant return thunk to ");
        d_print_comp (dpi, d_left (dc));
        return;
  
      case DEMANGLE_COMPONENT_JAVA_CLASS:
!       d_append_string_constant (dpi, "java Class for ");
        d_print_comp (dpi, d_left (dc));
        return;
  
      case DEMANGLE_COMPONENT_GUARD:
!       d_append_string_constant (dpi, "guard variable for ");
        d_print_comp (dpi, d_left (dc));
        return;
  
      case DEMANGLE_COMPONENT_REFTEMP:
!       d_append_string_constant (dpi, "reference temporary for ");
        d_print_comp (dpi, d_left (dc));
        return;
  
      case DEMANGLE_COMPONENT_HIDDEN_ALIAS:
!       d_append_string_constant (dpi, "hidden alias for ");
        d_print_comp (dpi, d_left (dc));
        return;
  
--- 3017,3085 ----
        return;
  
      case DEMANGLE_COMPONENT_VTABLE:
!       d_append_string (dpi, "vtable for ");
        d_print_comp (dpi, d_left (dc));
        return;
  
      case DEMANGLE_COMPONENT_VTT:
!       d_append_string (dpi, "VTT for ");
        d_print_comp (dpi, d_left (dc));
        return;
  
      case DEMANGLE_COMPONENT_CONSTRUCTION_VTABLE:
!       d_append_string (dpi, "construction vtable for ");
        d_print_comp (dpi, d_left (dc));
!       d_append_string (dpi, "-in-");
        d_print_comp (dpi, d_right (dc));
        return;
  
      case DEMANGLE_COMPONENT_TYPEINFO:
!       d_append_string (dpi, "typeinfo for ");
        d_print_comp (dpi, d_left (dc));
        return;
  
      case DEMANGLE_COMPONENT_TYPEINFO_NAME:
!       d_append_string (dpi, "typeinfo name for ");
        d_print_comp (dpi, d_left (dc));
        return;
  
      case DEMANGLE_COMPONENT_TYPEINFO_FN:
!       d_append_string (dpi, "typeinfo fn for ");
        d_print_comp (dpi, d_left (dc));
        return;
  
      case DEMANGLE_COMPONENT_THUNK:
!       d_append_string (dpi, "non-virtual thunk to ");
        d_print_comp (dpi, d_left (dc));
        return;
  
      case DEMANGLE_COMPONENT_VIRTUAL_THUNK:
!       d_append_string (dpi, "virtual thunk to ");
        d_print_comp (dpi, d_left (dc));
        return;
  
      case DEMANGLE_COMPONENT_COVARIANT_THUNK:
!       d_append_string (dpi, "covariant return thunk to ");
        d_print_comp (dpi, d_left (dc));
        return;
  
      case DEMANGLE_COMPONENT_JAVA_CLASS:
!       d_append_string (dpi, "java Class for ");
        d_print_comp (dpi, d_left (dc));
        return;
  
      case DEMANGLE_COMPONENT_GUARD:
!       d_append_string (dpi, "guard variable for ");
        d_print_comp (dpi, d_left (dc));
        return;
  
      case DEMANGLE_COMPONENT_REFTEMP:
!       d_append_string (dpi, "reference temporary for ");
        d_print_comp (dpi, d_left (dc));
        return;
  
      case DEMANGLE_COMPONENT_HIDDEN_ALIAS:
!       d_append_string (dpi, "hidden alias for ");
        d_print_comp (dpi, d_left (dc));
        return;
  
*************** d_print_comp (struct d_print_info *dpi,
*** 3164,3170 ****
  	  {
  	    d_append_char (dpi, ' ');
  	    d_print_comp (dpi, d_left (dc));
! 	    d_append_string_constant (dpi, "::*");
  	  }
  
  	dpi->modifiers = dpm.next;
--- 3278,3284 ----
  	  {
  	    d_append_char (dpi, ' ');
  	    d_print_comp (dpi, d_left (dc));
! 	    d_append_string (dpi, "::*");
  	  }
  
  	dpi->modifiers = dpm.next;
*************** d_print_comp (struct d_print_info *dpi,
*** 3177,3183 ****
        d_print_comp (dpi, d_left (dc));
        if (d_right (dc) != NULL)
  	{
! 	  d_append_string_constant (dpi, ", ");
  	  d_print_comp (dpi, d_right (dc));
  	}
        return;
--- 3291,3297 ----
        d_print_comp (dpi, d_left (dc));
        if (d_right (dc) != NULL)
  	{
! 	  d_append_string (dpi, ", ");
  	  d_print_comp (dpi, d_right (dc));
  	}
        return;
*************** d_print_comp (struct d_print_info *dpi,
*** 3186,3192 ****
        {
  	char c;
  
! 	d_append_string_constant (dpi, "operator");
  	c = dc->u.s_operator.op->name[0];
  	if (IS_LOWER (c))
  	  d_append_char (dpi, ' ');
--- 3300,3306 ----
        {
  	char c;
  
! 	d_append_string (dpi, "operator");
  	c = dc->u.s_operator.op->name[0];
  	if (IS_LOWER (c))
  	  d_append_char (dpi, ' ');
*************** d_print_comp (struct d_print_info *dpi,
*** 3196,3207 ****
        }
  
      case DEMANGLE_COMPONENT_EXTENDED_OPERATOR:
!       d_append_string_constant (dpi, "operator ");
        d_print_comp (dpi, dc->u.s_extended_operator.name);
        return;
  
      case DEMANGLE_COMPONENT_CAST:
!       d_append_string_constant (dpi, "operator ");
        d_print_cast (dpi, dc);
        return;
  
--- 3310,3321 ----
        }
  
      case DEMANGLE_COMPONENT_EXTENDED_OPERATOR:
!       d_append_string (dpi, "operator ");
        d_print_comp (dpi, dc->u.s_extended_operator.name);
        return;
  
      case DEMANGLE_COMPONENT_CAST:
!       d_append_string (dpi, "operator ");
        d_print_cast (dpi, dc);
        return;
  
*************** d_print_comp (struct d_print_info *dpi,
*** 3236,3244 ****
  
        d_append_char (dpi, '(');
        d_print_comp (dpi, d_left (d_right (dc)));
!       d_append_string_constant (dpi, ") ");
        d_print_expr_op (dpi, d_left (dc));
!       d_append_string_constant (dpi, " (");
        d_print_comp (dpi, d_right (d_right (dc)));
        d_append_char (dpi, ')');
  
--- 3350,3358 ----
  
        d_append_char (dpi, '(');
        d_print_comp (dpi, d_left (d_right (dc)));
!       d_append_string (dpi, ") ");
        d_print_expr_op (dpi, d_left (dc));
!       d_append_string (dpi, " (");
        d_print_comp (dpi, d_right (d_right (dc)));
        d_append_char (dpi, ')');
  
*************** d_print_comp (struct d_print_info *dpi,
*** 3263,3273 ****
  	}
        d_append_char (dpi, '(');
        d_print_comp (dpi, d_left (d_right (dc)));
!       d_append_string_constant (dpi, ") ");
        d_print_expr_op (dpi, d_left (dc));
!       d_append_string_constant (dpi, " (");
        d_print_comp (dpi, d_left (d_right (d_right (dc))));
!       d_append_string_constant (dpi, ") : (");
        d_print_comp (dpi, d_right (d_right (d_right (dc))));
        d_append_char (dpi, ')');
        return;
--- 3377,3387 ----
  	}
        d_append_char (dpi, '(');
        d_print_comp (dpi, d_left (d_right (dc)));
!       d_append_string (dpi, ") ");
        d_print_expr_op (dpi, d_left (dc));
!       d_append_string (dpi, " (");
        d_print_comp (dpi, d_left (d_right (d_right (dc))));
!       d_append_string (dpi, ") : (");
        d_print_comp (dpi, d_right (d_right (d_right (dc))));
        d_append_char (dpi, ')');
        return;
*************** d_print_comp (struct d_print_info *dpi,
*** 3312,3324 ****
  			d_append_char (dpi, 'l');
  			break;
  		      case D_PRINT_UNSIGNED_LONG:
! 			d_append_string_constant (dpi, "ul");
  			break;
  		      case D_PRINT_LONG_LONG:
! 			d_append_string_constant (dpi, "ll");
  			break;
  		      case D_PRINT_UNSIGNED_LONG_LONG:
! 			d_append_string_constant (dpi, "ull");
  			break;
  		      }
  		    return;
--- 3426,3438 ----
  			d_append_char (dpi, 'l');
  			break;
  		      case D_PRINT_UNSIGNED_LONG:
! 			d_append_string (dpi, "ul");
  			break;
  		      case D_PRINT_LONG_LONG:
! 			d_append_string (dpi, "ll");
  			break;
  		      case D_PRINT_UNSIGNED_LONG_LONG:
! 			d_append_string (dpi, "ull");
  			break;
  		      }
  		    return;
*************** d_print_comp (struct d_print_info *dpi,
*** 3333,3342 ****
  		    switch (d_right (dc)->u.s_name.s[0])
  		      {
  		      case '0':
! 			d_append_string_constant (dpi, "false");
  			return;
  		      case '1':
! 			d_append_string_constant (dpi, "true");
  			return;
  		      default:
  			break;
--- 3447,3456 ----
  		    switch (d_right (dc)->u.s_name.s[0])
  		      {
  		      case '0':
! 			d_append_string (dpi, "false");
  			return;
  		      case '1':
! 			d_append_string (dpi, "true");
  			return;
  		      default:
  			break;
*************** d_print_mod_list (struct d_print_info *d
*** 3475,3481 ****
        dpi->modifiers = hold_modifiers;
  
        if ((dpi->options & DMGL_JAVA) == 0)
! 	d_append_string_constant (dpi, "::");
        else
  	d_append_char (dpi, '.');
  
--- 3589,3595 ----
        dpi->modifiers = hold_modifiers;
  
        if ((dpi->options & DMGL_JAVA) == 0)
! 	d_append_string (dpi, "::");
        else
  	d_append_char (dpi, '.');
  
*************** d_print_mod (struct d_print_info *dpi,
*** 3508,3522 ****
      {
      case DEMANGLE_COMPONENT_RESTRICT:
      case DEMANGLE_COMPONENT_RESTRICT_THIS:
!       d_append_string_constant (dpi, " restrict");
        return;
      case DEMANGLE_COMPONENT_VOLATILE:
      case DEMANGLE_COMPONENT_VOLATILE_THIS:
!       d_append_string_constant (dpi, " volatile");
        return;
      case DEMANGLE_COMPONENT_CONST:
      case DEMANGLE_COMPONENT_CONST_THIS:
!       d_append_string_constant (dpi, " const");
        return;
      case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL:
        d_append_char (dpi, ' ');
--- 3622,3636 ----
      {
      case DEMANGLE_COMPONENT_RESTRICT:
      case DEMANGLE_COMPONENT_RESTRICT_THIS:
!       d_append_string (dpi, " restrict");
        return;
      case DEMANGLE_COMPONENT_VOLATILE:
      case DEMANGLE_COMPONENT_VOLATILE_THIS:
!       d_append_string (dpi, " volatile");
        return;
      case DEMANGLE_COMPONENT_CONST:
      case DEMANGLE_COMPONENT_CONST_THIS:
!       d_append_string (dpi, " const");
        return;
      case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL:
        d_append_char (dpi, ' ');
*************** d_print_mod (struct d_print_info *dpi,
*** 3531,3546 ****
        d_append_char (dpi, '&');
        return;
      case DEMANGLE_COMPONENT_COMPLEX:
!       d_append_string_constant (dpi, "complex ");
        return;
      case DEMANGLE_COMPONENT_IMAGINARY:
!       d_append_string_constant (dpi, "imaginary ");
        return;
      case DEMANGLE_COMPONENT_PTRMEM_TYPE:
        if (d_last_char (dpi) != '(')
  	d_append_char (dpi, ' ');
        d_print_comp (dpi, d_left (mod));
!       d_append_string_constant (dpi, "::*");
        return;
      case DEMANGLE_COMPONENT_TYPED_NAME:
        d_print_comp (dpi, d_left (mod));
--- 3645,3660 ----
        d_append_char (dpi, '&');
        return;
      case DEMANGLE_COMPONENT_COMPLEX:
!       d_append_string (dpi, "complex ");
        return;
      case DEMANGLE_COMPONENT_IMAGINARY:
!       d_append_string (dpi, "imaginary ");
        return;
      case DEMANGLE_COMPONENT_PTRMEM_TYPE:
        if (d_last_char (dpi) != '(')
  	d_append_char (dpi, ' ');
        d_print_comp (dpi, d_left (mod));
!       d_append_string (dpi, "::*");
        return;
      case DEMANGLE_COMPONENT_TYPED_NAME:
        d_print_comp (dpi, d_left (mod));
*************** d_print_array_type (struct d_print_info 
*** 3673,3679 ****
  	}
  
        if (need_paren)
! 	d_append_string_constant (dpi, " (");
  
        d_print_mod_list (dpi, mods, 0);
  
--- 3787,3793 ----
  	}
  
        if (need_paren)
! 	d_append_string (dpi, " (");
  
        d_print_mod_list (dpi, mods, 0);
  
*************** cplus_demangle_init_info (const char *ma
*** 3779,3804 ****
    di->expansion = 0;
  }
  
! /* 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.  On failure, this returns NULL.  */
  
! static char *
! d_demangle (const char* mangled, int options, size_t *palc)
  {
-   size_t len;
    int type;
    struct d_info di;
    struct demangle_component *dc;
!   int estimate;
!   char *ret;
! 
!   *palc = 0;
! 
!   len = strlen (mangled);
  
    if (mangled[0] == '_' && mangled[1] == 'Z')
      type = 0;
--- 3893,3911 ----
    di->expansion = 0;
  }
  
! /* Internal implementation for the demangler.  If MANGLED is a g++ v3 ABI
!    mangled name, return strings in repeated callback giving the demangled
!    name.  OPTIONS is the usual libiberty demangler options.  On success,
!    this returns 1.  On failure, returns 0.  */
  
! static int
! d_demangle_callback (const char* mangled, int options,
!                      void *opaque, demangle_callbackref callback)
  {
    int type;
    struct d_info di;
    struct demangle_component *dc;
!   int status;
  
    if (mangled[0] == '_' && mangled[1] == 'Z')
      type = 0;
*************** d_demangle (const char* mangled, int opt
*** 3807,3863 ****
  	   && (mangled[9] == 'D' || mangled[9] == 'I')
  	   && mangled[10] == '_')
      {
!       char *r;
  
!       r = (char *) malloc (40 + len - 11);
!       if (r == NULL)
! 	*palc = 1;
!       else
! 	{
! 	  if (mangled[9] == 'I')
! 	    strcpy (r, "global constructors keyed to ");
! 	  else
! 	    strcpy (r, "global destructors keyed to ");
! 	  strcat (r, mangled + 11);
! 	}
!       return r;
      }
    else
      {
        if ((options & DMGL_TYPES) == 0)
! 	return NULL;
        type = 1;
      }
  
!   cplus_demangle_init_info (mangled, options, len, &di);
  
    {
  #ifdef CP_DYNAMIC_ARRAYS
      __extension__ struct demangle_component comps[di.num_comps];
      __extension__ struct demangle_component *subs[di.num_subs];
  
!     di.comps = &comps[0];
!     di.subs = &subs[0];
  #else
!     di.comps = ((struct demangle_component *)
! 		malloc (di.num_comps * sizeof (struct demangle_component)));
!     di.subs = ((struct demangle_component **)
! 	       malloc (di.num_subs * sizeof (struct demangle_component *)));
!     if (di.comps == NULL || di.subs == NULL)
!       {
! 	if (di.comps != NULL)
! 	  free (di.comps);
! 	if (di.subs != NULL)
! 	  free (di.subs);
! 	*palc = 1;
! 	return NULL;
!       }
  #endif
  
!     if (! type)
!       dc = cplus_demangle_mangled_name (&di, 1);
!     else
        dc = cplus_demangle_type (&di);
  
      /* If DMGL_PARAMS is set, then if we didn't consume the entire
         mangled string, then we didn't successfully demangle it.  If
--- 3914,3954 ----
  	   && (mangled[9] == 'D' || mangled[9] == 'I')
  	   && mangled[10] == '_')
      {
!       const char *intro;
  
!       intro = (mangled[9] == 'I')
!               ? "global constructors keyed to "
!               : "global destructors keyed to ";
! 
!       callback (opaque, intro, strlen (intro));
!       callback (opaque, mangled + 11, strlen (mangled + 11));
!       return 1;
      }
    else
      {
        if ((options & DMGL_TYPES) == 0)
! 	return 0;
        type = 1;
      }
  
!   cplus_demangle_init_info (mangled, options, strlen (mangled), &di);
  
    {
  #ifdef CP_DYNAMIC_ARRAYS
      __extension__ struct demangle_component comps[di.num_comps];
      __extension__ struct demangle_component *subs[di.num_subs];
  
!     di.comps = comps;
!     di.subs = subs;
  #else
!     di.comps = alloca (di.num_comps * sizeof (*di.comps));
!     di.subs = alloca (di.num_subs * sizeof (*di.subs));
  #endif
  
!     if (type)
        dc = cplus_demangle_type (&di);
+     else
+       dc = cplus_demangle_mangled_name (&di, 1);
  
      /* If DMGL_PARAMS is set, then if we didn't consume the entire
         mangled string, then we didn't successfully demangle it.  If
*************** d_demangle (const char* mangled, int opt
*** 3867,3912 ****
        dc = NULL;
  
  #ifdef CP_DEMANGLE_DEBUG
!     if (dc == NULL)
!       printf ("failed demangling\n");
!     else
!       d_dump (dc, 0);
  #endif
  
!     /* We try to guess the length of the demangled string, to minimize
!        calls to realloc during demangling.  */
!     estimate = len + di.expansion + 10 * di.did_subs;
!     estimate += estimate / 8;
! 
!     ret = NULL;
!     if (dc != NULL)
!       ret = cplus_demangle_print (options, dc, estimate, palc);
! 
! #ifndef CP_DYNAMIC_ARRAYS
!     free (di.comps);
!     free (di.subs);
! #endif
  
! #ifdef CP_DEMANGLE_DEBUG
!     if (ret != NULL)
!       {
! 	int rlen;
  
! 	rlen = strlen (ret);
! 	if (rlen > 2 * estimate)
! 	  printf ("*** Length %d much greater than estimate %d\n",
! 		  rlen, estimate);
! 	else if (rlen > estimate)
! 	  printf ("*** Length %d greater than estimate %d\n",
! 		  rlen, estimate);
! 	else if (rlen < estimate / 2)
! 	  printf ("*** Length %d much less than estimate %d\n",
! 		  rlen, estimate);
!       }
! #endif
!   }
  
!   return ret;
  }
  
  #if defined(IN_LIBGCC2) || defined(IN_GLIBCPP_V3)
--- 3958,3999 ----
        dc = NULL;
  
  #ifdef CP_DEMANGLE_DEBUG
!     d_dump (dc, 0);
  #endif
  
!     status = (dc != NULL)
!              ? cplus_demangle_callback (options, dc, opaque, callback) : 0;
!   }
  
!   return status;
! }
  
! /* 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.  */
  
! static char *
! d_demangle (const char* mangled, int options, size_t *palc)
! {
!   struct d_growable_string dgs;
!   int status;
! 
!   d_growable_string_init (&dgs, 0);
! 
!   status = d_demangle_callback (mangled, options,
!                                 &dgs, d_growable_string_callback_adapter);
!   if (status == 0)
!     {
!       free (dgs.buf);
!       *palc = 0;
!       return NULL;
!     }
! 
!   *palc = (dgs.allocation_failure == 1) ? 1 : 0;
!   return dgs.buf;
  }
  
  #if defined(IN_LIBGCC2) || defined(IN_GLIBCPP_V3)
*************** extern char *__cxa_demangle (const char 
*** 3923,3929 ****
     OUTPUT_BUFFER may instead be NULL; in that case, the demangled name
     is placed in a region of memory allocated with malloc.
  
!    If LENGTH is non-NULL, the length of the buffer conaining the
     demangled name, is placed in *LENGTH.
  
     The return value is a pointer to the start of the NUL-terminated
--- 4010,4016 ----
     OUTPUT_BUFFER may instead be NULL; in that case, the demangled name
     is placed in a region of memory allocated with malloc.
  
!    If LENGTH is non-NULL, the length of the buffer containing the
     demangled name, is placed in *LENGTH.
  
     The return value is a pointer to the start of the NUL-terminated
*************** __cxa_demangle (const char *mangled_name
*** 4000,4005 ****
--- 4087,4132 ----
    return demangled;
  }
  
+ extern int __cxa_demangle_callback (const char *, void *,
+                                     void (*) (void *, const char *, size_t));
+ 
+ /* Alternative, allocationless entry point in the C++ runtime library
+    for performing demangling.  MANGLED_NAME is a NUL-terminated character
+    string containing the name to be demangled.
+ 
+    OPAQUE is a generalized pointer used as a callback argument.
+    CALLBACK is a callback function, called with demangled string
+    segments as demangling progresses; it is called at least once,
+    but may be called more than once.  
+ 
+    The return code is one of the following values, equivalent to
+    the STATUS values of __cxa_demangle() (excluding -1, since this
+    function performs no memory allocations):
+       0: The demangling operation succeeded.
+      -2: MANGLED_NAME is not a valid name under the C++ ABI mangling rules.
+      -3: One of the arguments is invalid.
+ 
+    The demangling is performed using the C++ ABI mangling rules, with
+    GNU extensions.  */
+ 
+ int
+ __cxa_demangle_callback (const char *mangled_name,
+                          void *opaque,
+                          void (*callback) (void *, const char *, size_t))
+ {
+   int status;
+ 
+   if (mangled_name == NULL || callback == NULL)
+     return -3;
+ 
+   status = d_demangle_callback (mangled_name, DMGL_PARAMS | DMGL_TYPES,
+                                 opaque, callback);
+   if (status == 0)
+     return -2;
+ 
+   return 0;
+ }
+ 
  #else /* ! (IN_LIBGCC2 || IN_GLIBCPP_V3) */
  
  /* Entry point for libiberty demangler.  If MANGLED is a g++ v3 ABI
*************** is_ctor_or_dtor (const char *mangled,
*** 4091,4111 ****
      __extension__ struct demangle_component comps[di.num_comps];
      __extension__ struct demangle_component *subs[di.num_subs];
  
!     di.comps = &comps[0];
!     di.subs = &subs[0];
  #else
!     di.comps = ((struct demangle_component *)
! 		malloc (di.num_comps * sizeof (struct demangle_component)));
!     di.subs = ((struct demangle_component **)
! 	       malloc (di.num_subs * sizeof (struct demangle_component *)));
!     if (di.comps == NULL || di.subs == NULL)
!       {
! 	if (di.comps != NULL)
! 	  free (di.comps);
! 	if (di.subs != NULL)
! 	  free (di.subs);
! 	return 0;
!       }
  #endif
  
      dc = cplus_demangle_mangled_name (&di, 1);
--- 4218,4228 ----
      __extension__ struct demangle_component comps[di.num_comps];
      __extension__ struct demangle_component *subs[di.num_subs];
  
!     di.comps = comps;
!     di.subs = subs;
  #else
!     di.comps = alloca (di.num_comps * sizeof (*di.comps));
!     di.subs = alloca (di.num_subs * sizeof (*di.subs));
  #endif
  
      dc = cplus_demangle_mangled_name (&di, 1);
*************** is_ctor_or_dtor (const char *mangled,
*** 4144,4154 ****
  	    break;
  	  }
        }
- 
- #ifndef CP_DYNAMIC_ARRAYS
-     free (di.subs);
-     free (di.comps);
- #endif
    }
  
    return ret;
--- 4261,4266 ----
diff -rcp3 orig/libiberty/cp-demangle.h new/libiberty/cp-demangle.h
*** orig/libiberty/cp-demangle.h	Wed Dec 27 12:02:06 2006
--- new/libiberty/cp-demangle.h	Fri Jan  5 15:55:11 2007
*************** struct d_info
*** 137,144 ****
  #define CP_STATIC_IF_GLIBCPP_V3 extern
  #endif
  
  CP_STATIC_IF_GLIBCPP_V3
! const struct demangle_operator_info cplus_demangle_operators[];
  
  #define D_BUILTIN_TYPE_COUNT (26)
  
--- 137,147 ----
  #define CP_STATIC_IF_GLIBCPP_V3 extern
  #endif
  
+ #define D_OPERATORS_COUNT (50)
+ 
  CP_STATIC_IF_GLIBCPP_V3
! const struct demangle_operator_info
! cplus_demangle_operators[D_OPERATORS_COUNT];
  
  #define D_BUILTIN_TYPE_COUNT (26)
  


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]