gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / gdb / cp-name-parser.y
index 18c959e13b15b2eed909f39ee517e2759daaaf2b..a209b350674bcba29a5514432bee9f9e45ddd916 100644 (file)
@@ -1,25 +1,23 @@
 /* YACC parser for C++ names, for GDB.
 
-   Copyright (C) 2003, 2004, 2005, 2007, 2008 Free Software Foundation, Inc.
+   Copyright (C) 2003-2020 Free Software Foundation, Inc.
 
    Parts of the lexer are based on c-exp.y from GDB.
 
-This file is part of GDB.
+   This file is part of GDB.
 
-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 2 of the License, or
-(at your option) any later version.
+   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.
+   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.  */
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 /* Note that malloc's and realloc's in this file are transformed to
    xmalloc and xrealloc respectively by the same sed command in the
@@ -29,27 +27,27 @@ Boston, MA 02110-1301, USA.  */
    too messy, particularly when such includes can be inserted at random
    times by the parser generator.  */
 
+/* The Bison manual says that %pure-parser is deprecated, but we use
+   it anyway because it also works with Byacc.  That is also why
+   this uses %lex-param and %parse-param rather than the simpler
+   %param -- Byacc does not support the latter.  */
+%pure-parser
+%lex-param {struct cpname_state *state}
+%parse-param {struct cpname_state *state}
+
 %{
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
+#include "defs.h"
 
+#include <unistd.h>
 #include "safe-ctype.h"
-#include "libiberty.h"
 #include "demangle.h"
+#include "cp-support.h"
+#include "c-support.h"
+#include "parser-defs.h"
 
-/* Bison does not make it easy to create a parser without global
-   state, unfortunately.  Here are all the global variables used
-   in this parser.  */
-
-/* LEXPTR is the current pointer into our lex buffer.  PREV_LEXPTR
-   is the start of the last token lexed, only used for diagnostics.
-   ERROR_LEXPTR is the first place an error occurred.  GLOBAL_ERRMSG
-   is the first error message encountered.  */
-
-static const char *lexptr, *prev_lexptr, *error_lexptr, *global_errmsg;
+#define GDB_YY_REMAP_PREFIX cpname
+#include "yy-remap.h"
 
 /* The components built by the parser are allocated ahead of time,
    and cached in this structure.  */
@@ -58,14 +56,86 @@ static const char *lexptr, *prev_lexptr, *error_lexptr, *global_errmsg;
 
 struct demangle_info {
   int used;
-  struct demangle_info *prev, *next;
+  struct demangle_info *next;
   struct demangle_component comps[ALLOC_CHUNK];
 };
 
-static struct demangle_info *demangle_info;
+%}
+
+%union
+  {
+    struct demangle_component *comp;
+    struct nested {
+      struct demangle_component *comp;
+      struct demangle_component **last;
+    } nested;
+    struct {
+      struct demangle_component *comp, *last;
+    } nested1;
+    struct {
+      struct demangle_component *comp, **last;
+      struct nested fn;
+      struct demangle_component *start;
+      int fold_flag;
+    } abstract;
+    int lval;
+    const char *opname;
+  }
+
+%{
 
-static struct demangle_component *
-d_grab (void)
+struct cpname_state
+{
+  /* LEXPTR is the current pointer into our lex buffer.  PREV_LEXPTR
+     is the start of the last token lexed, only used for diagnostics.
+     ERROR_LEXPTR is the first place an error occurred.  GLOBAL_ERRMSG
+     is the first error message encountered.  */
+
+  const char *lexptr, *prev_lexptr, *error_lexptr, *global_errmsg;
+
+  struct demangle_info *demangle_info;
+
+  /* The parse tree created by the parser is stored here after a
+     successful parse.  */
+
+  struct demangle_component *global_result;
+
+  struct demangle_component *d_grab ();
+
+  /* Helper functions.  These wrap the demangler tree interface,
+     handle allocation from our global store, and return the allocated
+     component.  */
+
+  struct demangle_component *fill_comp (enum demangle_component_type d_type,
+                                       struct demangle_component *lhs,
+                                       struct demangle_component *rhs);
+
+  struct demangle_component *make_operator (const char *name, int args);
+
+  struct demangle_component *make_dtor (enum gnu_v3_dtor_kinds kind,
+                                       struct demangle_component *name);
+
+  struct demangle_component *make_builtin_type (const char *name);
+
+  struct demangle_component *make_name (const char *name, int len);
+
+  struct demangle_component *d_qualify (struct demangle_component *lhs,
+                                       int qualifiers, int is_method);
+
+  struct demangle_component *d_int_type (int flags);
+
+  struct demangle_component *d_unary (const char *name,
+                                     struct demangle_component *lhs);
+
+  struct demangle_component *d_binary (const char *name,
+                                      struct demangle_component *lhs,
+                                      struct demangle_component *rhs);
+
+  int parse_number (const char *p, int len, int parsed_float, YYSTYPE *lvalp);
+};
+
+struct demangle_component *
+cpname_state::d_grab ()
 {
   struct demangle_info *more;
 
@@ -73,8 +143,7 @@ d_grab (void)
     {
       if (demangle_info->next == NULL)
        {
-         more = malloc (sizeof (struct demangle_info));
-         more->prev = demangle_info;
+         more = XNEW (struct demangle_info);
          more->next = NULL;
          demangle_info->next = more;
        }
@@ -87,25 +156,6 @@ d_grab (void)
   return &demangle_info->comps[demangle_info->used++];
 }
 
-/* The parse tree created by the parser is stored here after a successful
-   parse.  */
-
-static struct demangle_component *global_result;
-
-/* Prototypes for helper functions used when constructing the parse
-   tree.  */
-
-static struct demangle_component *d_qualify (struct demangle_component *, int,
-                                            int);
-
-static struct demangle_component *d_int_type (int);
-
-static struct demangle_component *d_unary (const char *,
-                                          struct demangle_component *);
-static struct demangle_component *d_binary (const char *,
-                                           struct demangle_component *,
-                                           struct demangle_component *);
-
 /* Flags passed to d_qualify.  */
 
 #define QUAL_CONST 1
@@ -122,58 +172,6 @@ static struct demangle_component *d_binary (const char *,
 #define INT_SIGNED     (1 << 4)
 #define INT_UNSIGNED   (1 << 5)
 
-/* Remap normal yacc parser interface names (yyparse, yylex, yyerror, etc),
-   as well as gratuitiously global symbol names, so we can have multiple
-   yacc generated parsers in gdb.  Note that these are only the variables
-   produced by yacc.  If other parser generators (bison, byacc, etc) produce
-   additional global names that conflict at link time, then those parser
-   generators need to be fixed instead of adding those names to this list. */
-
-#define        yymaxdepth cpname_maxdepth
-#define        yyparse cpname_parse
-#define        yylex   cpname_lex
-#define        yyerror cpname_error
-#define        yylval  cpname_lval
-#define        yychar  cpname_char
-#define        yydebug cpname_debug
-#define        yypact  cpname_pact     
-#define        yyr1    cpname_r1                       
-#define        yyr2    cpname_r2                       
-#define        yydef   cpname_def              
-#define        yychk   cpname_chk              
-#define        yypgo   cpname_pgo              
-#define        yyact   cpname_act              
-#define        yyexca  cpname_exca
-#define yyerrflag cpname_errflag
-#define yynerrs        cpname_nerrs
-#define        yyps    cpname_ps
-#define        yypv    cpname_pv
-#define        yys     cpname_s
-#define        yy_yys  cpname_yys
-#define        yystate cpname_state
-#define        yytmp   cpname_tmp
-#define        yyv     cpname_v
-#define        yy_yyv  cpname_yyv
-#define        yyval   cpname_val
-#define        yylloc  cpname_lloc
-#define yyreds cpname_reds             /* With YYDEBUG defined */
-#define yytoks cpname_toks             /* With YYDEBUG defined */
-#define yyname cpname_name             /* With YYDEBUG defined */
-#define yyrule cpname_rule             /* With YYDEBUG defined */
-#define yylhs  cpname_yylhs
-#define yylen  cpname_yylen
-#define yydefred cpname_yydefred
-#define yydgoto        cpname_yydgoto
-#define yysindex cpname_yysindex
-#define yyrindex cpname_yyrindex
-#define yygindex cpname_yygindex
-#define yytable         cpname_yytable
-#define yycheck         cpname_yycheck
-
-int yyparse (void);
-static int yylex (void);
-static void yyerror (char *);
-
 /* Enable yydebug for the stand-alone parser.  */
 #ifdef TEST_CPNAMES
 # define YYDEBUG       1
@@ -182,87 +180,79 @@ static void yyerror (char *);
 /* Helper functions.  These wrap the demangler tree interface, handle
    allocation from our global store, and return the allocated component.  */
 
-static struct demangle_component *
-fill_comp (enum demangle_component_type d_type, struct demangle_component *lhs,
-          struct demangle_component *rhs)
+struct demangle_component *
+cpname_state::fill_comp (enum demangle_component_type d_type,
+                        struct demangle_component *lhs,
+                        struct demangle_component *rhs)
 {
   struct demangle_component *ret = d_grab ();
-  cplus_demangle_fill_component (ret, d_type, lhs, rhs);
-  return ret;
-}
+  int i;
+
+  i = cplus_demangle_fill_component (ret, d_type, lhs, rhs);
+  gdb_assert (i);
 
-static struct demangle_component *
-make_empty (enum demangle_component_type d_type)
-{
-  struct demangle_component *ret = d_grab ();
-  ret->type = d_type;
   return ret;
 }
 
-static struct demangle_component *
-make_operator (const char *name, int args)
+struct demangle_component *
+cpname_state::make_operator (const char *name, int args)
 {
   struct demangle_component *ret = d_grab ();
-  cplus_demangle_fill_operator (ret, name, args);
+  int i;
+
+  i = cplus_demangle_fill_operator (ret, name, args);
+  gdb_assert (i);
+
   return ret;
 }
 
-static struct demangle_component *
-make_dtor (enum gnu_v3_dtor_kinds kind, struct demangle_component *name)
+struct demangle_component *
+cpname_state::make_dtor (enum gnu_v3_dtor_kinds kind,
+                        struct demangle_component *name)
 {
   struct demangle_component *ret = d_grab ();
-  cplus_demangle_fill_dtor (ret, kind, name);
+  int i;
+
+  i = cplus_demangle_fill_dtor (ret, kind, name);
+  gdb_assert (i);
+
   return ret;
 }
 
-static struct demangle_component *
-make_builtin_type (const char *name)
+struct demangle_component *
+cpname_state::make_builtin_type (const char *name)
 {
   struct demangle_component *ret = d_grab ();
-  cplus_demangle_fill_builtin_type (ret, name);
+  int i;
+
+  i = cplus_demangle_fill_builtin_type (ret, name);
+  gdb_assert (i);
+
   return ret;
 }
 
-static struct demangle_component *
-make_name (const char *name, int len)
+struct demangle_component *
+cpname_state::make_name (const char *name, int len)
 {
   struct demangle_component *ret = d_grab ();
-  cplus_demangle_fill_name (ret, name, len);
+  int i;
+
+  i = cplus_demangle_fill_name (ret, name, len);
+  gdb_assert (i);
+
   return ret;
 }
 
 #define d_left(dc) (dc)->u.s_binary.left
 #define d_right(dc) (dc)->u.s_binary.right
 
+static int yylex (YYSTYPE *, cpname_state *);
+static void yyerror (cpname_state *, const char *);
 %}
 
-%union
-  {
-    struct demangle_component *comp;
-    struct nested {
-      struct demangle_component *comp;
-      struct demangle_component **last;
-    } nested;
-    struct {
-      struct demangle_component *comp, *last;
-    } nested1;
-    struct {
-      struct demangle_component *comp, **last;
-      struct nested fn;
-      struct demangle_component *start;
-      int fold_flag;
-    } abstract;
-    int lval;
-    struct {
-      int val;
-      struct demangle_component *type;
-    } typed_val_int;
-    const char *opname;
-  }
-
-%type <comp> exp exp1 type start start_opt operator colon_name
+%type <comp> exp exp1 type start start_opt oper colon_name
 %type <comp> unqualified_name colon_ext_name
-%type <comp> template template_arg
+%type <comp> templ template_arg
 %type <comp> builtin_type
 %type <comp> typespec_2 array_indicator
 %type <comp> colon_ext_only ext_only_name
@@ -311,14 +301,6 @@ make_name (const char *name, int len)
 /* Non-C++ things we get from the demangler.  */
 %token <lval> DEMANGLER_SPECIAL
 %token CONSTRUCTION_VTABLE CONSTRUCTION_IN
-%token <typed_val_int> GLOBAL
-
-%{
-enum {
-  GLOBAL_CONSTRUCTORS = DEMANGLE_COMPONENT_LITERAL + 20,
-  GLOBAL_DESTRUCTORS = DEMANGLE_COMPONENT_LITERAL + 21
-};
-%}
 
 /* Precedence declarations.  */
 
@@ -364,7 +346,7 @@ enum {
 %%
 
 result         :       start
-                       { global_result = $1; }
+                       { state->global_result = $1; }
                ;
 
 start          :       type
@@ -394,15 +376,19 @@ function
                   start_opt is used to handle "function-local" variables and
                   types.  */
                |       typespec_2 function_arglist start_opt
-                       { $$ = fill_comp (DEMANGLE_COMPONENT_TYPED_NAME, $1, $2.comp);
-                         if ($3) $$ = fill_comp (DEMANGLE_COMPONENT_LOCAL_NAME, $$, $3); }
+                       { $$ = state->fill_comp (DEMANGLE_COMPONENT_TYPED_NAME,
+                                         $1, $2.comp);
+                         if ($3)
+                           $$ = state->fill_comp (DEMANGLE_COMPONENT_LOCAL_NAME,
+                                                  $$, $3);
+                       }
                |       colon_ext_only function_arglist start_opt
-                       { $$ = fill_comp (DEMANGLE_COMPONENT_TYPED_NAME, $1, $2.comp);
-                         if ($3) $$ = fill_comp (DEMANGLE_COMPONENT_LOCAL_NAME, $$, $3); }
+                       { $$ = state->fill_comp (DEMANGLE_COMPONENT_TYPED_NAME, $1, $2.comp);
+                         if ($3) $$ = state->fill_comp (DEMANGLE_COMPONENT_LOCAL_NAME, $$, $3); }
 
                |       conversion_op_name start_opt
                        { $$ = $1.comp;
-                         if ($2) $$ = fill_comp (DEMANGLE_COMPONENT_LOCAL_NAME, $$, $2); }
+                         if ($2) $$ = state->fill_comp (DEMANGLE_COMPONENT_LOCAL_NAME, $$, $2); }
                |       conversion_op_name abstract_declarator_fn
                        { if ($2.last)
                            {
@@ -414,92 +400,102 @@ function
                            }
                          /* If we have an arglist, build a function type.  */
                          if ($2.fn.comp)
-                           $$ = fill_comp (DEMANGLE_COMPONENT_TYPED_NAME, $1.comp, $2.fn.comp);
+                           $$ = state->fill_comp (DEMANGLE_COMPONENT_TYPED_NAME, $1.comp, $2.fn.comp);
                          else
                            $$ = $1.comp;
-                         if ($2.start) $$ = fill_comp (DEMANGLE_COMPONENT_LOCAL_NAME, $$, $2.start);
+                         if ($2.start) $$ = state->fill_comp (DEMANGLE_COMPONENT_LOCAL_NAME, $$, $2.start);
                        }
                ;
 
 demangler_special
                :       DEMANGLER_SPECIAL start
-                       { $$ = make_empty ($1);
-                         d_left ($$) = $2;
-                         d_right ($$) = NULL; }
+                       { $$ = state->fill_comp ((enum demangle_component_type) $1, $2, NULL); }
                |       CONSTRUCTION_VTABLE start CONSTRUCTION_IN start
-                       { $$ = fill_comp (DEMANGLE_COMPONENT_CONSTRUCTION_VTABLE, $2, $4); }
-               |       GLOBAL
-                       { $$ = make_empty ($1.val);
-                         d_left ($$) = $1.type;
-                         d_right ($$) = NULL; }
+                       { $$ = state->fill_comp (DEMANGLE_COMPONENT_CONSTRUCTION_VTABLE, $2, $4); }
                ;
 
-operator       :       OPERATOR NEW
-                       { $$ = make_operator ("new", 1); }
+oper   :       OPERATOR NEW
+                       {
+                         /* Match the whitespacing of cplus_demangle_operators.
+                            It would abort on unrecognized string otherwise.  */
+                         $$ = state->make_operator ("new", 3);
+                       }
                |       OPERATOR DELETE
-                       { $$ = make_operator ("delete", 1); }
+                       {
+                         /* Match the whitespacing of cplus_demangle_operators.
+                            It would abort on unrecognized string otherwise.  */
+                         $$ = state->make_operator ("delete ", 1);
+                       }
                |       OPERATOR NEW '[' ']'
-                       { $$ = make_operator ("new[]", 1); }
+                       {
+                         /* Match the whitespacing of cplus_demangle_operators.
+                            It would abort on unrecognized string otherwise.  */
+                         $$ = state->make_operator ("new[]", 3);
+                       }
                |       OPERATOR DELETE '[' ']'
-                       { $$ = make_operator ("delete[]", 1); }
+                       {
+                         /* Match the whitespacing of cplus_demangle_operators.
+                            It would abort on unrecognized string otherwise.  */
+                         $$ = state->make_operator ("delete[] ", 1);
+                       }
                |       OPERATOR '+'
-                       { $$ = make_operator ("+", 2); }
+                       { $$ = state->make_operator ("+", 2); }
                |       OPERATOR '-'
-                       { $$ = make_operator ("-", 2); }
+                       { $$ = state->make_operator ("-", 2); }
                |       OPERATOR '*'
-                       { $$ = make_operator ("*", 2); }
+                       { $$ = state->make_operator ("*", 2); }
                |       OPERATOR '/'
-                       { $$ = make_operator ("/", 2); }
+                       { $$ = state->make_operator ("/", 2); }
                |       OPERATOR '%'
-                       { $$ = make_operator ("%", 2); }
+                       { $$ = state->make_operator ("%", 2); }
                |       OPERATOR '^'
-                       { $$ = make_operator ("^", 2); }
+                       { $$ = state->make_operator ("^", 2); }
                |       OPERATOR '&'
-                       { $$ = make_operator ("&", 2); }
+                       { $$ = state->make_operator ("&", 2); }
                |       OPERATOR '|'
-                       { $$ = make_operator ("|", 2); }
+                       { $$ = state->make_operator ("|", 2); }
                |       OPERATOR '~'
-                       { $$ = make_operator ("~", 1); }
+                       { $$ = state->make_operator ("~", 1); }
                |       OPERATOR '!'
-                       { $$ = make_operator ("!", 1); }
+                       { $$ = state->make_operator ("!", 1); }
                |       OPERATOR '='
-                       { $$ = make_operator ("=", 2); }
+                       { $$ = state->make_operator ("=", 2); }
                |       OPERATOR '<'
-                       { $$ = make_operator ("<", 2); }
+                       { $$ = state->make_operator ("<", 2); }
                |       OPERATOR '>'
-                       { $$ = make_operator (">", 2); }
+                       { $$ = state->make_operator (">", 2); }
                |       OPERATOR ASSIGN_MODIFY
-                       { $$ = make_operator ($2, 2); }
+                       { $$ = state->make_operator ($2, 2); }
                |       OPERATOR LSH
-                       { $$ = make_operator ("<<", 2); }
+                       { $$ = state->make_operator ("<<", 2); }
                |       OPERATOR RSH
-                       { $$ = make_operator (">>", 2); }
+                       { $$ = state->make_operator (">>", 2); }
                |       OPERATOR EQUAL
-                       { $$ = make_operator ("==", 2); }
+                       { $$ = state->make_operator ("==", 2); }
                |       OPERATOR NOTEQUAL
-                       { $$ = make_operator ("!=", 2); }
+                       { $$ = state->make_operator ("!=", 2); }
                |       OPERATOR LEQ
-                       { $$ = make_operator ("<=", 2); }
+                       { $$ = state->make_operator ("<=", 2); }
                |       OPERATOR GEQ
-                       { $$ = make_operator (">=", 2); }
+                       { $$ = state->make_operator (">=", 2); }
                |       OPERATOR ANDAND
-                       { $$ = make_operator ("&&", 2); }
+                       { $$ = state->make_operator ("&&", 2); }
                |       OPERATOR OROR
-                       { $$ = make_operator ("||", 2); }
+                       { $$ = state->make_operator ("||", 2); }
                |       OPERATOR INCREMENT
-                       { $$ = make_operator ("++", 1); }
+                       { $$ = state->make_operator ("++", 1); }
                |       OPERATOR DECREMENT
-                       { $$ = make_operator ("--", 1); }
+                       { $$ = state->make_operator ("--", 1); }
                |       OPERATOR ','
-                       { $$ = make_operator (",", 2); }
+                       { $$ = state->make_operator (",", 2); }
                |       OPERATOR ARROW '*'
-                       { $$ = make_operator ("->*", 2); }
+                       { $$ = state->make_operator ("->*", 2); }
                |       OPERATOR ARROW
-                       { $$ = make_operator ("->", 2); }
+                       { $$ = state->make_operator ("->", 2); }
                |       OPERATOR '(' ')'
-                       { $$ = make_operator ("()", 0); }
+                       { $$ = state->make_operator ("()", 2); }
                |       OPERATOR '[' ']'
-                       { $$ = make_operator ("[]", 2); }
+                       { $$ = state->make_operator ("[]", 2); }
                ;
 
                /* Conversion operators.  We don't try to handle some of
@@ -507,7 +503,7 @@ operator    :       OPERATOR NEW
                   since it's not clear that it's parseable.  */
 conversion_op
                :       OPERATOR typespec_2
-                       { $$ = fill_comp (DEMANGLE_COMPONENT_CAST, $2, NULL); }
+                       { $$ = state->fill_comp (DEMANGLE_COMPONENT_CONVERSION, $2, NULL); }
                ;
 
 conversion_op_name
@@ -533,11 +529,11 @@ conversion_op_name
 
 /* DEMANGLE_COMPONENT_NAME */
 /* This accepts certain invalid placements of '~'.  */
-unqualified_name:      operator
-               |       operator '<' template_params '>'
-                       { $$ = fill_comp (DEMANGLE_COMPONENT_TEMPLATE, $1, $3.comp); }
+unqualified_name:      oper
+               |       oper '<' template_params '>'
+                       { $$ = state->fill_comp (DEMANGLE_COMPONENT_TEMPLATE, $1, $3.comp); }
                |       '~' NAME
-                       { $$ = make_dtor (gnu_v3_complete_object_dtor, $2); }
+                       { $$ = state->make_dtor (gnu_v3_complete_object_dtor, $2); }
                ;
 
 /* This rule is used in name and nested_name, and expanded inline there
@@ -558,9 +554,9 @@ colon_name  :       name
 name           :       nested_name NAME %prec NAME
                        { $$ = $1.comp; d_right ($1.last) = $2; }
                |       NAME %prec NAME
-               |       nested_name template %prec NAME
+               |       nested_name templ %prec NAME
                        { $$ = $1.comp; d_right ($1.last) = $2; }
-               |       template %prec NAME
+               |       templ %prec NAME
                ;
 
 colon_ext_name :       colon_name
@@ -578,45 +574,37 @@ ext_only_name     :       nested_name unqualified_name
                ;
 
 nested_name    :       NAME COLONCOLON
-                       { $$.comp = make_empty (DEMANGLE_COMPONENT_QUAL_NAME);
-                         d_left ($$.comp) = $1;
-                         d_right ($$.comp) = NULL;
+                       { $$.comp = state->fill_comp (DEMANGLE_COMPONENT_QUAL_NAME, $1, NULL);
                          $$.last = $$.comp;
                        }
                |       nested_name NAME COLONCOLON
                        { $$.comp = $1.comp;
-                         d_right ($1.last) = make_empty (DEMANGLE_COMPONENT_QUAL_NAME);
+                         d_right ($1.last) = state->fill_comp (DEMANGLE_COMPONENT_QUAL_NAME, $2, NULL);
                          $$.last = d_right ($1.last);
-                         d_left ($$.last) = $2;
-                         d_right ($$.last) = NULL;
                        }
-               |       template COLONCOLON
-                       { $$.comp = make_empty (DEMANGLE_COMPONENT_QUAL_NAME);
-                         d_left ($$.comp) = $1;
-                         d_right ($$.comp) = NULL;
+               |       templ COLONCOLON
+                       { $$.comp = state->fill_comp (DEMANGLE_COMPONENT_QUAL_NAME, $1, NULL);
                          $$.last = $$.comp;
                        }
-               |       nested_name template COLONCOLON
+               |       nested_name templ COLONCOLON
                        { $$.comp = $1.comp;
-                         d_right ($1.last) = make_empty (DEMANGLE_COMPONENT_QUAL_NAME);
+                         d_right ($1.last) = state->fill_comp (DEMANGLE_COMPONENT_QUAL_NAME, $2, NULL);
                          $$.last = d_right ($1.last);
-                         d_left ($$.last) = $2;
-                         d_right ($$.last) = NULL;
                        }
                ;
 
 /* DEMANGLE_COMPONENT_TEMPLATE */
 /* DEMANGLE_COMPONENT_TEMPLATE_ARGLIST */
-template       :       NAME '<' template_params '>'
-                       { $$ = fill_comp (DEMANGLE_COMPONENT_TEMPLATE, $1, $3.comp); }
+templ  :       NAME '<' template_params '>'
+                       { $$ = state->fill_comp (DEMANGLE_COMPONENT_TEMPLATE, $1, $3.comp); }
                ;
 
 template_params        :       template_arg
-                       { $$.comp = fill_comp (DEMANGLE_COMPONENT_TEMPLATE_ARGLIST, $1, NULL);
+                       { $$.comp = state->fill_comp (DEMANGLE_COMPONENT_TEMPLATE_ARGLIST, $1, NULL);
                        $$.last = &d_right ($$.comp); }
                |       template_params ',' template_arg
                        { $$.comp = $1.comp;
-                         *$1.last = fill_comp (DEMANGLE_COMPONENT_TEMPLATE_ARGLIST, $3, NULL);
+                         *$1.last = state->fill_comp (DEMANGLE_COMPONENT_TEMPLATE_ARGLIST, $3, NULL);
                          $$.last = &d_right (*$1.last);
                        }
                ;
@@ -631,36 +619,36 @@ template_arg      :       typespec_2
                          *$2.last = $1;
                        }
                |       '&' start
-                       { $$ = fill_comp (DEMANGLE_COMPONENT_UNARY, make_operator ("&", 1), $2); }
+                       { $$ = state->fill_comp (DEMANGLE_COMPONENT_UNARY, state->make_operator ("&", 1), $2); }
                |       '&' '(' start ')'
-                       { $$ = fill_comp (DEMANGLE_COMPONENT_UNARY, make_operator ("&", 1), $3); }
+                       { $$ = state->fill_comp (DEMANGLE_COMPONENT_UNARY, state->make_operator ("&", 1), $3); }
                |       exp
                ;
 
 function_args  :       typespec_2
-                       { $$.comp = fill_comp (DEMANGLE_COMPONENT_ARGLIST, $1, NULL);
+                       { $$.comp = state->fill_comp (DEMANGLE_COMPONENT_ARGLIST, $1, NULL);
                          $$.last = &d_right ($$.comp);
                        }
                |       typespec_2 abstract_declarator
                        { *$2.last = $1;
-                         $$.comp = fill_comp (DEMANGLE_COMPONENT_ARGLIST, $2.comp, NULL);
+                         $$.comp = state->fill_comp (DEMANGLE_COMPONENT_ARGLIST, $2.comp, NULL);
                          $$.last = &d_right ($$.comp);
                        }
                |       function_args ',' typespec_2
-                       { *$1.last = fill_comp (DEMANGLE_COMPONENT_ARGLIST, $3, NULL);
+                       { *$1.last = state->fill_comp (DEMANGLE_COMPONENT_ARGLIST, $3, NULL);
                          $$.comp = $1.comp;
                          $$.last = &d_right (*$1.last);
                        }
                |       function_args ',' typespec_2 abstract_declarator
                        { *$4.last = $3;
-                         *$1.last = fill_comp (DEMANGLE_COMPONENT_ARGLIST, $4.comp, NULL);
+                         *$1.last = state->fill_comp (DEMANGLE_COMPONENT_ARGLIST, $4.comp, NULL);
                          $$.comp = $1.comp;
                          $$.last = &d_right (*$1.last);
                        }
                |       function_args ',' ELLIPSIS
                        { *$1.last
-                           = fill_comp (DEMANGLE_COMPONENT_ARGLIST,
-                                          make_builtin_type ("..."),
+                           = state->fill_comp (DEMANGLE_COMPONENT_ARGLIST,
+                                          state->make_builtin_type ("..."),
                                           NULL);
                          $$.comp = $1.comp;
                          $$.last = &d_right (*$1.last);
@@ -668,17 +656,17 @@ function_args     :       typespec_2
                ;
 
 function_arglist:      '(' function_args ')' qualifiers_opt %prec NAME
-                       { $$.comp = fill_comp (DEMANGLE_COMPONENT_FUNCTION_TYPE, NULL, $2.comp);
+                       { $$.comp = state->fill_comp (DEMANGLE_COMPONENT_FUNCTION_TYPE, NULL, $2.comp);
                          $$.last = &d_left ($$.comp);
-                         $$.comp = d_qualify ($$.comp, $4, 1); }
+                         $$.comp = state->d_qualify ($$.comp, $4, 1); }
                |       '(' VOID ')' qualifiers_opt
-                       { $$.comp = fill_comp (DEMANGLE_COMPONENT_FUNCTION_TYPE, NULL, NULL);
+                       { $$.comp = state->fill_comp (DEMANGLE_COMPONENT_FUNCTION_TYPE, NULL, NULL);
                          $$.last = &d_left ($$.comp);
-                         $$.comp = d_qualify ($$.comp, $4, 1); }
+                         $$.comp = state->d_qualify ($$.comp, $4, 1); }
                |       '(' ')' qualifiers_opt
-                       { $$.comp = fill_comp (DEMANGLE_COMPONENT_FUNCTION_TYPE, NULL, NULL);
+                       { $$.comp = state->fill_comp (DEMANGLE_COMPONENT_FUNCTION_TYPE, NULL, NULL);
                          $$.last = &d_left ($$.comp);
-                         $$.comp = d_qualify ($$.comp, $3, 1); }
+                         $$.comp = state->d_qualify ($$.comp, $3, 1); }
                ;
 
 /* Should do something about DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL */
@@ -723,57 +711,50 @@ int_seq           :       int_part
                ;
 
 builtin_type   :       int_seq
-                       { $$ = d_int_type ($1); }
+                       { $$ = state->d_int_type ($1); }
                |       FLOAT_KEYWORD
-                       { $$ = make_builtin_type ("float"); }
+                       { $$ = state->make_builtin_type ("float"); }
                |       DOUBLE_KEYWORD
-                       { $$ = make_builtin_type ("double"); }
+                       { $$ = state->make_builtin_type ("double"); }
                |       LONG DOUBLE_KEYWORD
-                       { $$ = make_builtin_type ("long double"); }
+                       { $$ = state->make_builtin_type ("long double"); }
                |       BOOL
-                       { $$ = make_builtin_type ("bool"); }
+                       { $$ = state->make_builtin_type ("bool"); }
                |       WCHAR_T
-                       { $$ = make_builtin_type ("wchar_t"); }
+                       { $$ = state->make_builtin_type ("wchar_t"); }
                |       VOID
-                       { $$ = make_builtin_type ("void"); }
+                       { $$ = state->make_builtin_type ("void"); }
                ;
 
 ptr_operator   :       '*' qualifiers_opt
-                       { $$.comp = make_empty (DEMANGLE_COMPONENT_POINTER);
-                         $$.comp->u.s_binary.left = $$.comp->u.s_binary.right = NULL;
+                       { $$.comp = state->fill_comp (DEMANGLE_COMPONENT_POINTER, NULL, NULL);
                          $$.last = &d_left ($$.comp);
-                         $$.comp = d_qualify ($$.comp, $2, 0); }
+                         $$.comp = state->d_qualify ($$.comp, $2, 0); }
                /* g++ seems to allow qualifiers after the reference?  */
                |       '&'
-                       { $$.comp = make_empty (DEMANGLE_COMPONENT_REFERENCE);
-                         $$.comp->u.s_binary.left = $$.comp->u.s_binary.right = NULL;
+                       { $$.comp = state->fill_comp (DEMANGLE_COMPONENT_REFERENCE, NULL, NULL);
+                         $$.last = &d_left ($$.comp); }
+               |       ANDAND
+                       { $$.comp = state->fill_comp (DEMANGLE_COMPONENT_RVALUE_REFERENCE, NULL, NULL);
                          $$.last = &d_left ($$.comp); }
                |       nested_name '*' qualifiers_opt
-                       { $$.comp = make_empty (DEMANGLE_COMPONENT_PTRMEM_TYPE);
-                         $$.comp->u.s_binary.left = $1.comp;
+                       { $$.comp = state->fill_comp (DEMANGLE_COMPONENT_PTRMEM_TYPE, $1.comp, NULL);
                          /* Convert the innermost DEMANGLE_COMPONENT_QUAL_NAME to a DEMANGLE_COMPONENT_NAME.  */
                          *$1.last = *d_left ($1.last);
-                         $$.comp->u.s_binary.right = NULL;
                          $$.last = &d_right ($$.comp);
-                         $$.comp = d_qualify ($$.comp, $3, 0); }
+                         $$.comp = state->d_qualify ($$.comp, $3, 0); }
                |       COLONCOLON nested_name '*' qualifiers_opt
-                       { $$.comp = make_empty (DEMANGLE_COMPONENT_PTRMEM_TYPE);
-                         $$.comp->u.s_binary.left = $2.comp;
+                       { $$.comp = state->fill_comp (DEMANGLE_COMPONENT_PTRMEM_TYPE, $2.comp, NULL);
                          /* Convert the innermost DEMANGLE_COMPONENT_QUAL_NAME to a DEMANGLE_COMPONENT_NAME.  */
                          *$2.last = *d_left ($2.last);
-                         $$.comp->u.s_binary.right = NULL;
                          $$.last = &d_right ($$.comp);
-                         $$.comp = d_qualify ($$.comp, $4, 0); }
+                         $$.comp = state->d_qualify ($$.comp, $4, 0); }
                ;
 
 array_indicator        :       '[' ']'
-                       { $$ = make_empty (DEMANGLE_COMPONENT_ARRAY_TYPE);
-                         d_left ($$) = NULL;
-                       }
+                       { $$ = state->fill_comp (DEMANGLE_COMPONENT_ARRAY_TYPE, NULL, NULL); }
                |       '[' INT ']'
-                       { $$ = make_empty (DEMANGLE_COMPONENT_ARRAY_TYPE);
-                         d_left ($$) = $2;
-                       }
+                       { $$ = state->fill_comp (DEMANGLE_COMPONENT_ARRAY_TYPE, $2, NULL); }
                ;
 
 /* Details of this approach inspired by the G++ < 3.4 parser.  */
@@ -787,29 +768,29 @@ typespec  :       builtin_type
 */
 
 typespec_2     :       builtin_type qualifiers
-                       { $$ = d_qualify ($1, $2, 0); }
+                       { $$ = state->d_qualify ($1, $2, 0); }
                |       builtin_type
                |       qualifiers builtin_type qualifiers
-                       { $$ = d_qualify ($2, $1 | $3, 0); }
+                       { $$ = state->d_qualify ($2, $1 | $3, 0); }
                |       qualifiers builtin_type
-                       { $$ = d_qualify ($2, $1, 0); }
+                       { $$ = state->d_qualify ($2, $1, 0); }
 
                |       name qualifiers
-                       { $$ = d_qualify ($1, $2, 0); }
+                       { $$ = state->d_qualify ($1, $2, 0); }
                |       name
                |       qualifiers name qualifiers
-                       { $$ = d_qualify ($2, $1 | $3, 0); }
+                       { $$ = state->d_qualify ($2, $1 | $3, 0); }
                |       qualifiers name
-                       { $$ = d_qualify ($2, $1, 0); }
+                       { $$ = state->d_qualify ($2, $1, 0); }
 
                |       COLONCOLON name qualifiers
-                       { $$ = d_qualify ($2, $3, 0); }
+                       { $$ = state->d_qualify ($2, $3, 0); }
                |       COLONCOLON name
                        { $$ = $2; }
                |       qualifiers COLONCOLON name qualifiers
-                       { $$ = d_qualify ($3, $1 | $4, 0); }
+                       { $$ = state->d_qualify ($3, $1 | $4, 0); }
                |       qualifiers COLONCOLON name
-                       { $$ = d_qualify ($3, $1, 0); }
+                       { $$ = state->d_qualify ($3, $1, 0); }
                ;
 
 abstract_declarator
@@ -926,8 +907,7 @@ direct_declarator
                          $$.last = &d_right ($2);
                        }
                |       colon_ext_name
-                       { $$.comp = make_empty (DEMANGLE_COMPONENT_TYPED_NAME);
-                         d_left ($$.comp) = $1;
+                       { $$.comp = state->fill_comp (DEMANGLE_COMPONENT_TYPED_NAME, $1, NULL);
                          $$.last = &d_right ($$.comp);
                        }
                ;
@@ -943,8 +923,7 @@ declarator_1        :       ptr_operator declarator_1
                          $$.last = $1.last;
                          *$2.last = $1.comp; }
                |       colon_ext_name
-                       { $$.comp = make_empty (DEMANGLE_COMPONENT_TYPED_NAME);
-                         d_left ($$.comp) = $1;
+                       { $$.comp = state->fill_comp (DEMANGLE_COMPONENT_TYPED_NAME, $1, NULL);
                          $$.last = &d_right ($$.comp);
                        }
                |       direct_declarator_1
@@ -956,15 +935,15 @@ declarator_1      :       ptr_operator declarator_1
                           members will not be mangled.  If they are hopefully
                           they'll end up to the right of the ::.  */
                |       colon_ext_name function_arglist COLONCOLON start
-                       { $$.comp = fill_comp (DEMANGLE_COMPONENT_TYPED_NAME, $1, $2.comp);
+                       { $$.comp = state->fill_comp (DEMANGLE_COMPONENT_TYPED_NAME, $1, $2.comp);
                          $$.last = $2.last;
-                         $$.comp = fill_comp (DEMANGLE_COMPONENT_LOCAL_NAME, $$.comp, $4);
+                         $$.comp = state->fill_comp (DEMANGLE_COMPONENT_LOCAL_NAME, $$.comp, $4);
                        }
                |       direct_declarator_1 function_arglist COLONCOLON start
                        { $$.comp = $1.comp;
                          *$1.last = $2.comp;
                          $$.last = $2.last;
-                         $$.comp = fill_comp (DEMANGLE_COMPONENT_LOCAL_NAME, $$.comp, $4);
+                         $$.comp = state->fill_comp (DEMANGLE_COMPONENT_LOCAL_NAME, $$.comp, $4);
                        }
                ;
 
@@ -984,11 +963,11 @@ direct_declarator_1
                          $$.last = &d_right ($2);
                        }
                |       colon_ext_name function_arglist
-                       { $$.comp = fill_comp (DEMANGLE_COMPONENT_TYPED_NAME, $1, $2.comp);
+                       { $$.comp = state->fill_comp (DEMANGLE_COMPONENT_TYPED_NAME, $1, $2.comp);
                          $$.last = $2.last;
                        }
                |       colon_ext_name array_indicator
-                       { $$.comp = fill_comp (DEMANGLE_COMPONENT_TYPED_NAME, $1, $2);
+                       { $$.comp = state->fill_comp (DEMANGLE_COMPONENT_TYPED_NAME, $1, $2);
                          $$.last = &d_right ($2);
                        }
                ;
@@ -1003,29 +982,29 @@ exp1     :       exp
        ;
 
 exp1   :       exp '>' exp
-               { $$ = d_binary (">", $1, $3); }
+               { $$ = state->d_binary (">", $1, $3); }
        ;
 
 /* References.  Not allowed everywhere in template parameters, only
    at the top level, but treat them as expressions in case they are wrapped
    in parentheses.  */
 exp1   :       '&' start
-               { $$ = fill_comp (DEMANGLE_COMPONENT_UNARY, make_operator ("&", 1), $2); }
+               { $$ = state->fill_comp (DEMANGLE_COMPONENT_UNARY, state->make_operator ("&", 1), $2); }
        |       '&' '(' start ')'
-               { $$ = fill_comp (DEMANGLE_COMPONENT_UNARY, make_operator ("&", 1), $3); }
+               { $$ = state->fill_comp (DEMANGLE_COMPONENT_UNARY, state->make_operator ("&", 1), $3); }
        ;
 
 /* Expressions, not including the comma operator.  */
 exp    :       '-' exp    %prec UNARY
-               { $$ = d_unary ("-", $2); }
+               { $$ = state->d_unary ("-", $2); }
        ;
 
 exp    :       '!' exp    %prec UNARY
-               { $$ = d_unary ("!", $2); }
+               { $$ = state->d_unary ("!", $2); }
        ;
 
 exp    :       '~' exp    %prec UNARY
-               { $$ = d_unary ("~", $2); }
+               { $$ = state->d_unary ("~", $2); }
        ;
 
 /* Casts.  First your normal C-style cast.  If exp is a LITERAL, just change
@@ -1039,8 +1018,8 @@ exp       :       '(' type ')' exp  %prec UNARY
                      d_left ($4) = $2;
                    }
                  else
-                   $$ = fill_comp (DEMANGLE_COMPONENT_UNARY,
-                                     fill_comp (DEMANGLE_COMPONENT_CAST, $2, NULL),
+                   $$ = state->fill_comp (DEMANGLE_COMPONENT_UNARY,
+                                     state->fill_comp (DEMANGLE_COMPONENT_CAST, $2, NULL),
                                      $4);
                }
        ;
@@ -1048,22 +1027,22 @@ exp     :       '(' type ')' exp  %prec UNARY
 /* Mangling does not differentiate between these, so we don't need to
    either.  */
 exp    :       STATIC_CAST '<' type '>' '(' exp1 ')' %prec UNARY
-               { $$ = fill_comp (DEMANGLE_COMPONENT_UNARY,
-                                   fill_comp (DEMANGLE_COMPONENT_CAST, $3, NULL),
+               { $$ = state->fill_comp (DEMANGLE_COMPONENT_UNARY,
+                                   state->fill_comp (DEMANGLE_COMPONENT_CAST, $3, NULL),
                                    $6);
                }
        ;
 
 exp    :       DYNAMIC_CAST '<' type '>' '(' exp1 ')' %prec UNARY
-               { $$ = fill_comp (DEMANGLE_COMPONENT_UNARY,
-                                   fill_comp (DEMANGLE_COMPONENT_CAST, $3, NULL),
+               { $$ = state->fill_comp (DEMANGLE_COMPONENT_UNARY,
+                                   state->fill_comp (DEMANGLE_COMPONENT_CAST, $3, NULL),
                                    $6);
                }
        ;
 
 exp    :       REINTERPRET_CAST '<' type '>' '(' exp1 ')' %prec UNARY
-               { $$ = fill_comp (DEMANGLE_COMPONENT_UNARY,
-                                   fill_comp (DEMANGLE_COMPONENT_CAST, $3, NULL),
+               { $$ = state->fill_comp (DEMANGLE_COMPONENT_UNARY,
+                                   state->fill_comp (DEMANGLE_COMPONENT_CAST, $3, NULL),
                                    $6);
                }
        ;
@@ -1081,86 +1060,86 @@ exp     :       REINTERPRET_CAST '<' type '>' '(' exp1 ')' %prec UNARY
 /* Binary operators in order of decreasing precedence.  */
 
 exp    :       exp '*' exp
-               { $$ = d_binary ("*", $1, $3); }
+               { $$ = state->d_binary ("*", $1, $3); }
        ;
 
 exp    :       exp '/' exp
-               { $$ = d_binary ("/", $1, $3); }
+               { $$ = state->d_binary ("/", $1, $3); }
        ;
 
 exp    :       exp '%' exp
-               { $$ = d_binary ("%", $1, $3); }
+               { $$ = state->d_binary ("%", $1, $3); }
        ;
 
 exp    :       exp '+' exp
-               { $$ = d_binary ("+", $1, $3); }
+               { $$ = state->d_binary ("+", $1, $3); }
        ;
 
 exp    :       exp '-' exp
-               { $$ = d_binary ("-", $1, $3); }
+               { $$ = state->d_binary ("-", $1, $3); }
        ;
 
 exp    :       exp LSH exp
-               { $$ = d_binary ("<<", $1, $3); }
+               { $$ = state->d_binary ("<<", $1, $3); }
        ;
 
 exp    :       exp RSH exp
-               { $$ = d_binary (">>", $1, $3); }
+               { $$ = state->d_binary (">>", $1, $3); }
        ;
 
 exp    :       exp EQUAL exp
-               { $$ = d_binary ("==", $1, $3); }
+               { $$ = state->d_binary ("==", $1, $3); }
        ;
 
 exp    :       exp NOTEQUAL exp
-               { $$ = d_binary ("!=", $1, $3); }
+               { $$ = state->d_binary ("!=", $1, $3); }
        ;
 
 exp    :       exp LEQ exp
-               { $$ = d_binary ("<=", $1, $3); }
+               { $$ = state->d_binary ("<=", $1, $3); }
        ;
 
 exp    :       exp GEQ exp
-               { $$ = d_binary (">=", $1, $3); }
+               { $$ = state->d_binary (">=", $1, $3); }
        ;
 
 exp    :       exp '<' exp
-               { $$ = d_binary ("<", $1, $3); }
+               { $$ = state->d_binary ("<", $1, $3); }
        ;
 
 exp    :       exp '&' exp
-               { $$ = d_binary ("&", $1, $3); }
+               { $$ = state->d_binary ("&", $1, $3); }
        ;
 
 exp    :       exp '^' exp
-               { $$ = d_binary ("^", $1, $3); }
+               { $$ = state->d_binary ("^", $1, $3); }
        ;
 
 exp    :       exp '|' exp
-               { $$ = d_binary ("|", $1, $3); }
+               { $$ = state->d_binary ("|", $1, $3); }
        ;
 
 exp    :       exp ANDAND exp
-               { $$ = d_binary ("&&", $1, $3); }
+               { $$ = state->d_binary ("&&", $1, $3); }
        ;
 
 exp    :       exp OROR exp
-               { $$ = d_binary ("||", $1, $3); }
+               { $$ = state->d_binary ("||", $1, $3); }
        ;
 
 /* Not 100% sure these are necessary, but they're harmless.  */
 exp    :       exp ARROW NAME
-               { $$ = d_binary ("->", $1, $3); }
+               { $$ = state->d_binary ("->", $1, $3); }
        ;
 
 exp    :       exp '.' NAME
-               { $$ = d_binary (".", $1, $3); }
+               { $$ = state->d_binary (".", $1, $3); }
        ;
 
 exp    :       exp '?' exp ':' exp     %prec '?'
-               { $$ = fill_comp (DEMANGLE_COMPONENT_TRINARY, make_operator ("?", 3),
-                                   fill_comp (DEMANGLE_COMPONENT_TRINARY_ARG1, $1,
-                                                fill_comp (DEMANGLE_COMPONENT_TRINARY_ARG2, $3, $5)));
+               { $$ = state->fill_comp (DEMANGLE_COMPONENT_TRINARY, state->make_operator ("?", 3),
+                                   state->fill_comp (DEMANGLE_COMPONENT_TRINARY_ARG1, $1,
+                                                state->fill_comp (DEMANGLE_COMPONENT_TRINARY_ARG2, $3, $5)));
                }
        ;
                          
@@ -1172,24 +1151,28 @@ exp     :       FLOAT
        ;
 
 exp    :       SIZEOF '(' type ')'     %prec UNARY
-               { $$ = d_unary ("sizeof", $3); }
+               {
+                 /* Match the whitespacing of cplus_demangle_operators.
+                    It would abort on unrecognized string otherwise.  */
+                 $$ = state->d_unary ("sizeof ", $3);
+               }
        ;
 
 /* C++.  */
 exp     :       TRUEKEYWORD    
                { struct demangle_component *i;
-                 i = make_name ("1", 1);
-                 $$ = fill_comp (DEMANGLE_COMPONENT_LITERAL,
-                                   make_builtin_type ("bool"),
+                 i = state->make_name ("1", 1);
+                 $$ = state->fill_comp (DEMANGLE_COMPONENT_LITERAL,
+                                   state->make_builtin_type ( "bool"),
                                    i);
                }
        ;
 
 exp     :       FALSEKEYWORD   
                { struct demangle_component *i;
-                 i = make_name ("0", 1);
-                 $$ = fill_comp (DEMANGLE_COMPONENT_LITERAL,
-                                   make_builtin_type ("bool"),
+                 i = state->make_name ("0", 1);
+                 $$ = state->fill_comp (DEMANGLE_COMPONENT_LITERAL,
+                                   state->make_builtin_type ("bool"),
                                    i);
                }
        ;
@@ -1204,7 +1187,8 @@ exp     :       FALSEKEYWORD
    may already be qualified; duplicate qualifiers are not created.  */
 
 struct demangle_component *
-d_qualify (struct demangle_component *lhs, int qualifiers, int is_method)
+cpname_state::d_qualify (struct demangle_component *lhs, int qualifiers,
+                        int is_method)
 {
   struct demangle_component **inner_p;
   enum demangle_component_type type;
@@ -1214,8 +1198,8 @@ d_qualify (struct demangle_component *lhs, int qualifiers, int is_method)
 #define HANDLE_QUAL(TYPE, MTYPE, QUAL)                         \
   if ((qualifiers & QUAL) && (type != TYPE) && (type != MTYPE))        \
     {                                                          \
-      *inner_p = fill_comp (is_method ? MTYPE : TYPE,  \
-                             *inner_p, NULL);                  \
+      *inner_p = fill_comp (is_method ? MTYPE : TYPE,          \
+                           *inner_p, NULL);                    \
       inner_p = &d_left (*inner_p);                            \
       type = (*inner_p)->type;                                 \
     }                                                          \
@@ -1238,8 +1222,8 @@ d_qualify (struct demangle_component *lhs, int qualifiers, int is_method)
 
 /* Return a builtin type corresponding to FLAGS.  */
 
-static struct demangle_component *
-d_int_type (int flags)
+struct demangle_component *
+cpname_state::d_int_type (int flags)
 {
   const char *name;
 
@@ -1291,19 +1275,20 @@ d_int_type (int flags)
 
 /* Wrapper to create a unary operation.  */
 
-static struct demangle_component *
-d_unary (const char *name, struct demangle_component *lhs)
+struct demangle_component *
+cpname_state::d_unary (const char *name, struct demangle_component *lhs)
 {
   return fill_comp (DEMANGLE_COMPONENT_UNARY, make_operator (name, 1), lhs);
 }
 
 /* Wrapper to create a binary operation.  */
 
-static struct demangle_component *
-d_binary (const char *name, struct demangle_component *lhs, struct demangle_component *rhs)
+struct demangle_component *
+cpname_state::d_binary (const char *name, struct demangle_component *lhs,
+                       struct demangle_component *rhs)
 {
   return fill_comp (DEMANGLE_COMPONENT_BINARY, make_operator (name, 2),
-                     fill_comp (DEMANGLE_COMPONENT_BINARY_ARGS, lhs, rhs));
+                   fill_comp (DEMANGLE_COMPONENT_BINARY_ARGS, lhs, rhs));
 }
 
 /* Find the end of a symbol name starting at LEXPTR.  */
@@ -1313,7 +1298,7 @@ symbol_end (const char *lexptr)
 {
   const char *p = lexptr;
 
-  while (*p && (ISALNUM (*p) || *p == '_' || *p == '$' || *p == '.'))
+  while (*p && (c_ident_is_alnum (*p) || *p == '_' || *p == '$' || *p == '.'))
     p++;
 
   return p;
@@ -1323,8 +1308,9 @@ symbol_end (const char *lexptr)
    The number starts at P and contains LEN characters.  Store the result in
    YYLVAL.  */
 
-static int
-parse_number (const char *p, int len, int parsed_float)
+int
+cpname_state::parse_number (const char *p, int len, int parsed_float,
+                           YYSTYPE *lvalp)
 {
   int unsigned_p = 0;
 
@@ -1374,7 +1360,7 @@ parse_number (const char *p, int len, int parsed_float)
        return ERROR;
 
       name = make_name (p, len);
-      yylval.comp = fill_comp (literal_type, type, name);
+      lvalp->comp = fill_comp (literal_type, type, name);
 
       return FLOAT;
     }
@@ -1423,13 +1409,13 @@ parse_number (const char *p, int len, int parsed_float)
      type = signed_type;
 
    name = make_name (p, len);
-   yylval.comp = fill_comp (literal_type, type, name);
+   lvalp->comp = fill_comp (literal_type, type, name);
 
    return INT;
 }
 
-static char backslashable[] = "abefnrtv";
-static char represented[] = "\a\b\e\f\n\r\t\v";
+static const char backslashable[] = "abefnrtv";
+static const char represented[] = "\a\b\e\f\n\r\t\v";
 
 /* Translate the backslash the way we would in the host character set.  */
 static int
@@ -1460,7 +1446,7 @@ c_parse_backslash (int host_char, int *target_char)
    after the zeros.  A value of 0 does not mean end of string.  */
 
 static int
-parse_escape (const char **string_ptr)
+cp_parse_escape (const char **string_ptr)
 {
   int target_char;
   int c = *(*string_ptr)++;
@@ -1481,7 +1467,7 @@ parse_escape (const char **string_ptr)
          if (c == '?')
            return 0177;
          else if (c == '\\')
-           target_char = parse_escape (string_ptr);
+           target_char = cp_parse_escape (string_ptr);
          else
            target_char = c;
 
@@ -1527,39 +1513,39 @@ parse_escape (const char **string_ptr)
 #define HANDLE_SPECIAL(string, comp)                           \
   if (strncmp (tokstart, string, sizeof (string) - 1) == 0)    \
     {                                                          \
-      lexptr = tokstart + sizeof (string) - 1;                 \
-      yylval.lval = comp;                                      \
+      state->lexptr = tokstart + sizeof (string) - 1;                  \
+      lvalp->lval = comp;                                      \
       return DEMANGLER_SPECIAL;                                        \
     }
 
 #define HANDLE_TOKEN2(string, token)                   \
-  if (lexptr[1] == string[1])                          \
+  if (state->lexptr[1] == string[1])                           \
     {                                                  \
-      lexptr += 2;                                     \
-      yylval.opname = string;                          \
+      state->lexptr += 2;                                      \
+      lvalp->opname = string;                          \
       return token;                                    \
     }      
 
 #define HANDLE_TOKEN3(string, token)                   \
-  if (lexptr[1] == string[1] && lexptr[2] == string[2])        \
+  if (state->lexptr[1] == string[1] && state->lexptr[2] == string[2])  \
     {                                                  \
-      lexptr += 3;                                     \
-      yylval.opname = string;                          \
+      state->lexptr += 3;                                      \
+      lvalp->opname = string;                          \
       return token;                                    \
     }      
 
 /* Read one token, getting characters through LEXPTR.  */
 
 static int
-yylex (void)
+yylex (YYSTYPE *lvalp, cpname_state *state)
 {
   int c;
   int namelen;
-  const char *tokstart, *tokptr;
+  const char *tokstart;
 
  retry:
-  prev_lexptr = lexptr;
-  tokstart = lexptr;
+  state->prev_lexptr = state->lexptr;
+  tokstart = state->lexptr;
 
   switch (c = *tokstart)
     {
@@ -1569,27 +1555,27 @@ yylex (void)
     case ' ':
     case '\t':
     case '\n':
-      lexptr++;
+      state->lexptr++;
       goto retry;
 
     case '\'':
       /* We either have a character constant ('0' or '\177' for example)
         or we have a quoted symbol reference ('foo(int,int)' in C++
         for example). */
-      lexptr++;
-      c = *lexptr++;
+      state->lexptr++;
+      c = *state->lexptr++;
       if (c == '\\')
-       c = parse_escape (&lexptr);
+       c = cp_parse_escape (&state->lexptr);
       else if (c == '\'')
        {
-         yyerror ("empty character constant");
+         yyerror (state, _("empty character constant"));
          return ERROR;
        }
 
-      c = *lexptr++;
+      c = *state->lexptr++;
       if (c != '\'')
        {
-         yyerror ("invalid character constant");
+         yyerror (state, _("invalid character constant"));
          return ERROR;
        }
 
@@ -1597,36 +1583,38 @@ yylex (void)
         presumably the same one that appears in manglings - the decimal
         representation.  But if that isn't in our input then we have to
         allocate memory for it somewhere.  */
-      yylval.comp = fill_comp (DEMANGLE_COMPONENT_LITERAL,
-                                make_builtin_type ("char"),
-                                make_name (tokstart, lexptr - tokstart));
+      lvalp->comp
+       = state->fill_comp (DEMANGLE_COMPONENT_LITERAL,
+                           state->make_builtin_type ("char"),
+                           state->make_name (tokstart,
+                                             state->lexptr - tokstart));
 
       return INT;
 
     case '(':
       if (strncmp (tokstart, "(anonymous namespace)", 21) == 0)
        {
-         lexptr += 21;
-         yylval.comp = make_name ("(anonymous namespace)",
-                                    sizeof "(anonymous namespace)" - 1);
+         state->lexptr += 21;
+         lvalp->comp = state->make_name ("(anonymous namespace)",
+                                         sizeof "(anonymous namespace)" - 1);
          return NAME;
        }
        /* FALL THROUGH */
 
     case ')':
     case ',':
-      lexptr++;
+      state->lexptr++;
       return c;
 
     case '.':
-      if (lexptr[1] == '.' && lexptr[2] == '.')
+      if (state->lexptr[1] == '.' && state->lexptr[2] == '.')
        {
-         lexptr += 3;
+         state->lexptr += 3;
          return ELLIPSIS;
        }
 
       /* Might be a floating point number.  */
-      if (lexptr[1] < '0' || lexptr[1] > '9')
+      if (state->lexptr[1] < '0' || state->lexptr[1] > '9')
        goto symbol;            /* Nope, must be a symbol. */
 
       goto try_number;
@@ -1639,16 +1627,16 @@ yylex (void)
       /* For construction vtables.  This is kind of hokey.  */
       if (strncmp (tokstart, "-in-", 4) == 0)
        {
-         lexptr += 4;
+         state->lexptr += 4;
          return CONSTRUCTION_IN;
        }
 
-      if (lexptr[1] < '0' || lexptr[1] > '9')
+      if (state->lexptr[1] < '0' || state->lexptr[1] > '9')
        {
-         lexptr++;
+         state->lexptr++;
          return '-';
        }
-      /* FALL THRU into number case.  */
+      /* FALL THRU.  */
 
     try_number:
     case '0':
@@ -1706,74 +1694,75 @@ yylex (void)
            else if (! ISALNUM (*p))
              break;
          }
-       toktype = parse_number (tokstart, p - tokstart, got_dot|got_e);
+       toktype = state->parse_number (tokstart, p - tokstart, got_dot|got_e,
+                                      lvalp);
         if (toktype == ERROR)
          {
            char *err_copy = (char *) alloca (p - tokstart + 1);
 
            memcpy (err_copy, tokstart, p - tokstart);
            err_copy[p - tokstart] = 0;
-           yyerror ("invalid number");
+           yyerror (state, _("invalid number"));
            return ERROR;
          }
-       lexptr = p;
+       state->lexptr = p;
        return toktype;
       }
 
     case '+':
       HANDLE_TOKEN2 ("+=", ASSIGN_MODIFY);
       HANDLE_TOKEN2 ("++", INCREMENT);
-      lexptr++;
+      state->lexptr++;
       return c;
     case '*':
       HANDLE_TOKEN2 ("*=", ASSIGN_MODIFY);
-      lexptr++;
+      state->lexptr++;
       return c;
     case '/':
       HANDLE_TOKEN2 ("/=", ASSIGN_MODIFY);
-      lexptr++;
+      state->lexptr++;
       return c;
     case '%':
       HANDLE_TOKEN2 ("%=", ASSIGN_MODIFY);
-      lexptr++;
+      state->lexptr++;
       return c;
     case '|':
       HANDLE_TOKEN2 ("|=", ASSIGN_MODIFY);
       HANDLE_TOKEN2 ("||", OROR);
-      lexptr++;
+      state->lexptr++;
       return c;
     case '&':
       HANDLE_TOKEN2 ("&=", ASSIGN_MODIFY);
       HANDLE_TOKEN2 ("&&", ANDAND);
-      lexptr++;
+      state->lexptr++;
       return c;
     case '^':
       HANDLE_TOKEN2 ("^=", ASSIGN_MODIFY);
-      lexptr++;
+      state->lexptr++;
       return c;
     case '!':
       HANDLE_TOKEN2 ("!=", NOTEQUAL);
-      lexptr++;
+      state->lexptr++;
       return c;
     case '<':
       HANDLE_TOKEN3 ("<<=", ASSIGN_MODIFY);
       HANDLE_TOKEN2 ("<=", LEQ);
       HANDLE_TOKEN2 ("<<", LSH);
-      lexptr++;
+      state->lexptr++;
       return c;
     case '>':
       HANDLE_TOKEN3 (">>=", ASSIGN_MODIFY);
       HANDLE_TOKEN2 (">=", GEQ);
       HANDLE_TOKEN2 (">>", RSH);
-      lexptr++;
+      state->lexptr++;
       return c;
     case '=':
       HANDLE_TOKEN2 ("==", EQUAL);
-      lexptr++;
+      state->lexptr++;
       return c;
     case ':':
       HANDLE_TOKEN2 ("::", COLONCOLON);
-      lexptr++;
+      state->lexptr++;
       return c;
 
     case '[':
@@ -1784,19 +1773,19 @@ yylex (void)
     case '{':
     case '}':
     symbol:
-      lexptr++;
+      state->lexptr++;
       return c;
 
     case '"':
       /* These can't occur in C++ names.  */
-      yyerror ("unexpected string literal");
+      yyerror (state, _("unexpected string literal"));
       return ERROR;
     }
 
-  if (!(c == '_' || c == '$' || ISALPHA (c)))
+  if (!(c == '_' || c == '$' || c_ident_is_alpha (c)))
     {
       /* We must have come across a bad character (e.g. ';').  */
-      yyerror ("invalid character");
+      yyerror (state, _("invalid character"));
       return ERROR;
     }
 
@@ -1804,9 +1793,9 @@ yylex (void)
   namelen = 0;
   do
     c = tokstart[++namelen];
-  while (ISALNUM (c) || c == '_' || c == '$');
+  while (c_ident_is_alnum (c) || c == '_' || c == '$');
 
-  lexptr += namelen;
+  state->lexptr += namelen;
 
   /* Catch specific keywords.  Notice that some of the keywords contain
      spaces, and are sorted by the length of the first word.  They must
@@ -1820,7 +1809,7 @@ yylex (void)
     case 12:
       if (strncmp (tokstart, "construction vtable for ", 24) == 0)
        {
-         lexptr = tokstart + 24;
+         state->lexptr = tokstart + 24;
          return CONSTRUCTION_VTABLE;
        }
       if (strncmp (tokstart, "dynamic_cast", 12) == 0)
@@ -1858,24 +1847,24 @@ yylex (void)
       if (strncmp (tokstart, "global constructors keyed to ", 29) == 0)
        {
          const char *p;
-         lexptr = tokstart + 29;
-         yylval.typed_val_int.val = GLOBAL_CONSTRUCTORS;
+         state->lexptr = tokstart + 29;
+         lvalp->lval = DEMANGLE_COMPONENT_GLOBAL_CONSTRUCTORS;
          /* Find the end of the symbol.  */
-         p = symbol_end (lexptr);
-         yylval.typed_val_int.type = make_name (lexptr, p - lexptr);
-         lexptr = p;
-         return GLOBAL;
+         p = symbol_end (state->lexptr);
+         lvalp->comp = state->make_name (state->lexptr, p - state->lexptr);
+         state->lexptr = p;
+         return DEMANGLER_SPECIAL;
        }
       if (strncmp (tokstart, "global destructors keyed to ", 28) == 0)
        {
          const char *p;
-         lexptr = tokstart + 28;
-         yylval.typed_val_int.val = GLOBAL_DESTRUCTORS;
+         state->lexptr = tokstart + 28;
+         lvalp->lval = DEMANGLE_COMPONENT_GLOBAL_DESTRUCTORS;
          /* Find the end of the symbol.  */
-         p = symbol_end (lexptr);
-         yylval.typed_val_int.type = make_name (lexptr, p - lexptr);
-         lexptr = p;
-         return GLOBAL;
+         p = symbol_end (state->lexptr);
+         lvalp->comp = state->make_name (state->lexptr, p - state->lexptr);
+         state->lexptr = p;
+         return DEMANGLER_SPECIAL;
        }
 
       HANDLE_SPECIAL ("vtable for ", DEMANGLE_COMPONENT_VTABLE);
@@ -1931,38 +1920,32 @@ yylex (void)
       break;
     }
 
-  yylval.comp = make_name (tokstart, namelen);
+  lvalp->comp = state->make_name (tokstart, namelen);
   return NAME;
 }
 
 static void
-yyerror (char *msg)
+yyerror (cpname_state *state, const char *msg)
 {
-  if (global_errmsg)
+  if (state->global_errmsg)
     return;
 
-  error_lexptr = prev_lexptr;
-  global_errmsg = msg ? msg : "parse error";
+  state->error_lexptr = state->prev_lexptr;
+  state->global_errmsg = msg ? msg : "parse error";
 }
 
 /* Allocate a chunk of the components we'll need to build a tree.  We
    generally allocate too many components, but the extra memory usage
    doesn't hurt because the trees are temporary and the storage is
    reused.  More may be allocated later, by d_grab.  */
-static void
+static struct demangle_info *
 allocate_info (void)
 {
-  if (demangle_info == NULL)
-    {
-      demangle_info = malloc (sizeof (struct demangle_info));
-      demangle_info->prev = NULL;
-      demangle_info->next = NULL;
-    }
-  else
-    while (demangle_info->prev)
-      demangle_info = demangle_info->prev;
+  struct demangle_info *info = XNEW (struct demangle_info);
 
-  demangle_info->used = 0;
+  info->next = NULL;
+  info->used = 0;
+  return info;
 }
 
 /* Convert RESULT to a string.  The return value is allocated
@@ -1971,69 +1954,100 @@ allocate_info (void)
    cplus_demangle_print does not, specifically the global destructor
    and constructor labels.  */
 
-char *
+gdb::unique_xmalloc_ptr<char>
 cp_comp_to_string (struct demangle_component *result, int estimated_len)
 {
-  char *str, *prefix = NULL, *buf;
-  size_t err = 0;
+  size_t err;
 
-  if (result->type == GLOBAL_DESTRUCTORS)
-    {
-      result = d_left (result);
-      prefix = "global destructors keyed to ";
-    }
-  else if (result->type == GLOBAL_CONSTRUCTORS)
+  char *res = cplus_demangle_print (DMGL_PARAMS | DMGL_ANSI,
+                                   result, estimated_len, &err);
+  return gdb::unique_xmalloc_ptr<char> (res);
+}
+
+/* Constructor for demangle_parse_info.  */
+
+demangle_parse_info::demangle_parse_info ()
+: info (NULL),
+  tree (NULL)
+{
+  obstack_init (&obstack);
+}
+
+/* Destructor for demangle_parse_info.  */
+
+demangle_parse_info::~demangle_parse_info ()
+{
+  /* Free any allocated chunks of memory for the parse.  */
+  while (info != NULL)
     {
-      result = d_left (result);
-      prefix = "global constructors keyed to ";
+      struct demangle_info *next = info->next;
+
+      free (info);
+      info = next;
     }
 
-  str = cplus_demangle_print (DMGL_PARAMS | DMGL_ANSI, result, estimated_len, &err);
-  if (str == NULL)
-    return NULL;
+  /* Free any memory allocated during typedef replacement.  */
+  obstack_free (&obstack, NULL);
+}
 
-  if (prefix == NULL)
-    return str;
+/* Merge the two parse trees given by DEST and SRC.  The parse tree
+   in SRC is attached to DEST at the node represented by TARGET.
 
-  buf = malloc (strlen (str) + strlen (prefix) + 1);
-  strcpy (buf, prefix);
-  strcat (buf, str);
-  free (str);
-  return (buf);
+   NOTE 1: Since there is no API to merge obstacks, this function does
+   even attempt to try it.  Fortunately, we do not (yet?) need this ability.
+   The code will assert if SRC->obstack is not empty.
+
+   NOTE 2: The string from which SRC was parsed must not be freed, since
+   this function will place pointers to that string into DEST.  */
+
+void
+cp_merge_demangle_parse_infos (struct demangle_parse_info *dest,
+                              struct demangle_component *target,
+                              struct demangle_parse_info *src)
+
+{
+  struct demangle_info *di;
+
+  /* Copy the SRC's parse data into DEST.  */
+  *target = *src->tree;
+  di = dest->info;
+  while (di->next != NULL)
+    di = di->next;
+  di->next = src->info;
+
+  /* Clear the (pointer to) SRC's parse data so that it is not freed when
+     cp_demangled_parse_info_free is called.  */
+  src->info = NULL;
 }
 
 /* Convert a demangled name to a demangle_component tree.  On success,
-   the root of the new tree is returned; it is valid until the next
-   call to this function and should not be freed.  On error, NULL is
-   returned, and an error message will be set in *ERRMSG (which does
-   not need to be freed).  */
+   a structure containing the root of the new tree is returned.  On
+   error, NULL is returned, and an error message will be set in
+   *ERRMSG.  */
 
-struct demangle_component *
-cp_demangled_name_to_comp (const char *demangled_name, const char **errmsg)
+struct std::unique_ptr<demangle_parse_info>
+cp_demangled_name_to_comp (const char *demangled_name,
+                          std::string *errmsg)
 {
-  static char errbuf[60];
-  struct demangle_component *result;
+  cpname_state state;
+
+  state.prev_lexptr = state.lexptr = demangled_name;
+  state.error_lexptr = NULL;
+  state.global_errmsg = NULL;
 
-  prev_lexptr = lexptr = demangled_name;
-  error_lexptr = NULL;
-  global_errmsg = NULL;
+  state.demangle_info = allocate_info ();
 
-  allocate_info ();
+  std::unique_ptr<demangle_parse_info> result (new demangle_parse_info);
+  result->info = state.demangle_info;
 
-  if (yyparse ())
+  if (yyparse (&state))
     {
-      if (global_errmsg && errmsg)
-       {
-         snprintf (errbuf, sizeof (errbuf) - 2, "%s, near `%s",
-                   global_errmsg, error_lexptr);
-         strcat (errbuf, "'");
-         *errmsg = errbuf;
-       }
+      if (state.global_errmsg && errmsg)
+       *errmsg = state.global_errmsg;
       return NULL;
     }
 
-  result = global_result;
-  global_result = NULL;
+  result->tree = state.global_result;
 
   return result;
 }
@@ -2046,17 +2060,6 @@ cp_print (struct demangle_component *result)
   char *str;
   size_t err = 0;
 
-  if (result->type == GLOBAL_DESTRUCTORS)
-    {
-      result = d_left (result);
-      fputs ("global destructors keyed to ", stdout);
-    }
-  else if (result->type == GLOBAL_CONSTRUCTORS)
-    {
-      result = d_left (result);
-      fputs ("global constructors keyed to ", stdout);
-    }
-
   str = cplus_demangle_print (DMGL_PARAMS | DMGL_ANSI, result, 64, &err);
   if (str == NULL)
     return;
@@ -2082,14 +2085,39 @@ trim_chars (char *lexptr, char **extra_chars)
   return c;
 }
 
+/* When this file is built as a standalone program, xmalloc comes from
+   libiberty --- in which case we have to provide xfree ourselves.  */
+
+void
+xfree (void *ptr)
+{
+  if (ptr != NULL)
+    {
+      /* Literal `free' would get translated back to xfree again.  */
+      CONCAT2 (fr,ee) (ptr);
+    }
+}
+
+/* GDB normally defines internal_error itself, but when this file is built
+   as a standalone program, we must also provide an implementation.  */
+
+void
+internal_error (const char *file, int line, const char *fmt, ...)
+{
+  va_list ap;
+
+  va_start (ap, fmt);
+  fprintf (stderr, "%s:%d: internal error: ", file, line);
+  vfprintf (stderr, fmt, ap);
+  exit (1);
+}
+
 int
 main (int argc, char **argv)
 {
-  char *str2, *extra_chars = "", c;
+  char *str2, *extra_chars, c;
   char buf[65536];
   int arg;
-  const char *errmsg;
-  struct demangle_component *result;
 
   arg = 1;
   if (argv[arg] && strcmp (argv[arg], "--debug") == 0)
@@ -2101,29 +2129,31 @@ main (int argc, char **argv)
   if (argv[arg] == NULL)
     while (fgets (buf, 65536, stdin) != NULL)
       {
-       int len;
        buf[strlen (buf) - 1] = 0;
        /* Use DMGL_VERBOSE to get expanded standard substitutions.  */
        c = trim_chars (buf, &extra_chars);
        str2 = cplus_demangle (buf, DMGL_PARAMS | DMGL_ANSI | DMGL_VERBOSE);
        if (str2 == NULL)
          {
-           /* printf ("Demangling error\n"); */
+           printf ("Demangling error\n");
            if (c)
              printf ("%s%c%s\n", buf, c, extra_chars);
            else
              printf ("%s\n", buf);
            continue;
          }
-       result = cp_demangled_name_to_comp (str2, &errmsg);
+
+       std::string errmsg;
+       std::unique_ptr<demangle_parse_info> result
+         = cp_demangled_name_to_comp (str2, &errmsg);
        if (result == NULL)
          {
-           fputs (errmsg, stderr);
+           fputs (errmsg.c_str (), stderr);
            fputc ('\n', stderr);
            continue;
          }
 
-       cp_print (result);
+       cp_print (result->tree);
 
        free (str2);
        if (c)
@@ -2135,14 +2165,16 @@ main (int argc, char **argv)
       }
   else
     {
-      result = cp_demangled_name_to_comp (argv[arg], &errmsg);
+      std::string errmsg;
+      std::unique_ptr<demangle_parse_info> result
+       = cp_demangled_name_to_comp (argv[arg], &errmsg);
       if (result == NULL)
        {
-         fputs (errmsg, stderr);
+         fputs (errmsg.c_str (), stderr);
          fputc ('\n', stderr);
          return 0;
        }
-      cp_print (result);
+      cp_print (result->tree);
       putchar ('\n');
     }
   return 0;
This page took 0.056108 seconds and 4 git commands to generate.