Enable support for the AArch64 dot-prod instruction in the Cortex A55 and A75 cpus.
[deliverable/binutils-gdb.git] / gdb / cp-name-parser.y
index 889ef9193fe89f26d9f76d9e8f0f3a99ff667a48..d430ae762d6d9ec6f1a96d8c7c07736c5da21c46 100644 (file)
@@ -1,25 +1,23 @@
 /* YACC parser for C++ names, for GDB.
 
-   Copyright 2003, 2004, 2005
-   Free Software Foundation, Inc.
+   Copyright (C) 2003-2017 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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
@@ -31,14 +29,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 %{
 
-#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"
 
 /* Bison does not make it easy to create a parser without global
    state, unfortunately.  Here are all the global variables used
@@ -54,13 +50,37 @@ static const char *lexptr, *prev_lexptr, *error_lexptr, *global_errmsg;
 /* The components built by the parser are allocated ahead of time,
    and cached in this structure.  */
 
+#define ALLOC_CHUNK 100
+
 struct demangle_info {
   int used;
-  struct demangle_component comps[1];
+  struct demangle_info *next;
+  struct demangle_component comps[ALLOC_CHUNK];
 };
 
 static struct demangle_info *demangle_info;
-#define d_grab() (&demangle_info->comps[demangle_info->used++])
+
+static struct demangle_component *
+d_grab (void)
+{
+  struct demangle_info *more;
+
+  if (demangle_info->used >= ALLOC_CHUNK)
+    {
+      if (demangle_info->next == NULL)
+       {
+         more = XNEW (struct demangle_info);
+         more->next = NULL;
+         demangle_info->next = more;
+       }
+      else
+       more = demangle_info->next;
+
+      more->used = 0;
+      demangle_info = more;
+    }
+  return &demangle_info->comps[demangle_info->used++];
+}
 
 /* The parse tree created by the parser is stored here after a successful
    parse.  */
@@ -144,10 +164,16 @@ static struct demangle_component *d_binary (const char *,
 #define yygindex cpname_yygindex
 #define yytable         cpname_yytable
 #define yycheck         cpname_yycheck
+#define yyss   cpname_yyss
+#define yysslim        cpname_yysslim
+#define yyssp  cpname_yyssp
+#define yystacksize cpname_yystacksize
+#define yyvs   cpname_yyvs
+#define yyvsp  cpname_yyvsp
 
 int yyparse (void);
 static int yylex (void);
-static void yyerror (char *);
+static void yyerror (const char *);
 
 /* Enable yydebug for the stand-alone parser.  */
 #ifdef TEST_CPNAMES
@@ -162,15 +188,11 @@ 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;
 }
 
@@ -178,7 +200,11 @@ static struct demangle_component *
 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;
 }
 
@@ -186,7 +212,11 @@ static struct demangle_component *
 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;
 }
 
@@ -194,7 +224,11 @@ static struct demangle_component *
 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;
 }
 
@@ -202,7 +236,11 @@ static struct demangle_component *
 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;
 }
 
@@ -228,16 +266,12 @@ make_name (const char *name, int len)
       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
@@ -286,14 +320,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.  */
 
@@ -398,25 +424,35 @@ function
 
 demangler_special
                :       DEMANGLER_SPECIAL start
-                       { $$ = make_empty ($1);
-                         d_left ($$) = $2;
-                         d_right ($$) = NULL; }
+                       { $$ = 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; }
                ;
 
-operator       :       OPERATOR NEW
-                       { $$ = make_operator ("new", 1); }
+oper   :       OPERATOR NEW
+                       {
+                         /* Match the whitespacing of cplus_demangle_operators.
+                            It would abort on unrecognized string otherwise.  */
+                         $$ = make_operator ("new", 3);
+                       }
                |       OPERATOR DELETE
-                       { $$ = make_operator ("delete", 1); }
+                       {
+                         /* Match the whitespacing of cplus_demangle_operators.
+                            It would abort on unrecognized string otherwise.  */
+                         $$ = make_operator ("delete ", 1);
+                       }
                |       OPERATOR NEW '[' ']'
-                       { $$ = make_operator ("new[]", 1); }
+                       {
+                         /* Match the whitespacing of cplus_demangle_operators.
+                            It would abort on unrecognized string otherwise.  */
+                         $$ = make_operator ("new[]", 3);
+                       }
                |       OPERATOR DELETE '[' ']'
-                       { $$ = make_operator ("delete[]", 1); }
+                       {
+                         /* Match the whitespacing of cplus_demangle_operators.
+                            It would abort on unrecognized string otherwise.  */
+                         $$ = make_operator ("delete[] ", 1);
+                       }
                |       OPERATOR '+'
                        { $$ = make_operator ("+", 2); }
                |       OPERATOR '-'
@@ -472,7 +508,7 @@ operator    :       OPERATOR NEW
                |       OPERATOR ARROW
                        { $$ = make_operator ("->", 2); }
                |       OPERATOR '(' ')'
-                       { $$ = make_operator ("()", 0); }
+                       { $$ = make_operator ("()", 2); }
                |       OPERATOR '[' ']'
                        { $$ = make_operator ("[]", 2); }
                ;
@@ -482,7 +518,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); }
+                       { $$ = fill_comp (DEMANGLE_COMPONENT_CONVERSION, $2, NULL); }
                ;
 
 conversion_op_name
@@ -508,8 +544,8 @@ conversion_op_name
 
 /* DEMANGLE_COMPONENT_NAME */
 /* This accepts certain invalid placements of '~'.  */
-unqualified_name:      operator
-               |       operator '<' template_params '>'
+unqualified_name:      oper
+               |       oper '<' template_params '>'
                        { $$ = fill_comp (DEMANGLE_COMPONENT_TEMPLATE, $1, $3.comp); }
                |       '~' NAME
                        { $$ = make_dtor (gnu_v3_complete_object_dtor, $2); }
@@ -533,9 +569,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
@@ -553,36 +589,28 @@ 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 = 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) = 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 = 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) = 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 '>'
+templ  :       NAME '<' template_params '>'
                        { $$ = fill_comp (DEMANGLE_COMPONENT_TEMPLATE, $1, $3.comp); }
                ;
 
@@ -714,41 +742,34 @@ builtin_type      :       int_seq
                ;
 
 ptr_operator   :       '*' qualifiers_opt
-                       { $$.comp = make_empty (DEMANGLE_COMPONENT_POINTER);
-                         $$.comp->u.s_binary.left = $$.comp->u.s_binary.right = NULL;
+                       { $$.comp = fill_comp (DEMANGLE_COMPONENT_POINTER, NULL, NULL);
                          $$.last = &d_left ($$.comp);
                          $$.comp = 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 = fill_comp (DEMANGLE_COMPONENT_REFERENCE, NULL, NULL);
+                         $$.last = &d_left ($$.comp); }
+               |       ANDAND
+                       { $$.comp = 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 = 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); }
                |       COLONCOLON nested_name '*' qualifiers_opt
-                       { $$.comp = make_empty (DEMANGLE_COMPONENT_PTRMEM_TYPE);
-                         $$.comp->u.s_binary.left = $2.comp;
+                       { $$.comp = 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); }
                ;
 
 array_indicator        :       '[' ']'
-                       { $$ = make_empty (DEMANGLE_COMPONENT_ARRAY_TYPE);
-                         d_left ($$) = NULL;
-                       }
+                       { $$ = fill_comp (DEMANGLE_COMPONENT_ARRAY_TYPE, NULL, NULL); }
                |       '[' INT ']'
-                       { $$ = make_empty (DEMANGLE_COMPONENT_ARRAY_TYPE);
-                         d_left ($$) = $2;
-                       }
+                       { $$ = fill_comp (DEMANGLE_COMPONENT_ARRAY_TYPE, $2, NULL); }
                ;
 
 /* Details of this approach inspired by the G++ < 3.4 parser.  */
@@ -901,8 +922,7 @@ direct_declarator
                          $$.last = &d_right ($2);
                        }
                |       colon_ext_name
-                       { $$.comp = make_empty (DEMANGLE_COMPONENT_TYPED_NAME);
-                         d_left ($$.comp) = $1;
+                       { $$.comp = fill_comp (DEMANGLE_COMPONENT_TYPED_NAME, $1, NULL);
                          $$.last = &d_right ($$.comp);
                        }
                ;
@@ -918,8 +938,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 = fill_comp (DEMANGLE_COMPONENT_TYPED_NAME, $1, NULL);
                          $$.last = &d_right ($$.comp);
                        }
                |       direct_declarator_1
@@ -986,6 +1005,8 @@ exp1       :       exp '>' exp
    in parentheses.  */
 exp1   :       '&' start
                { $$ = fill_comp (DEMANGLE_COMPONENT_UNARY, make_operator ("&", 1), $2); }
+       |       '&' '(' start ')'
+               { $$ = fill_comp (DEMANGLE_COMPONENT_UNARY, make_operator ("&", 1), $3); }
        ;
 
 /* Expressions, not including the comma operator.  */
@@ -1041,18 +1062,13 @@ exp     :       REINTERPRET_CAST '<' type '>' '(' exp1 ')' %prec UNARY
                }
        ;
 
-/* Another form of C++-style cast.  "type ( exp1 )" is not allowed (it's too
-   ambiguous), but "name ( exp1 )" is.  Because we don't need to support
-   function types, we can handle this unambiguously (the use of typespec_2
-   prevents a silly, harmless conflict with qualifiers_opt).  This does not
-   appear in demangler output so it's not a great loss if we need to
-   disable it.  */
-exp    :       typespec_2 '(' exp1 ')' %prec UNARY
-               { $$ = fill_comp (DEMANGLE_COMPONENT_UNARY,
-                                   fill_comp (DEMANGLE_COMPONENT_CAST, $1, NULL),
-                                   $3);
-               }
-       ;
+/* Another form of C++-style cast is "type ( exp1 )".  This creates too many
+   conflicts to support.  For a while we supported the simpler
+   "typespec_2 ( exp1 )", but that conflicts with "& ( start )" as a
+   reference, deep within the wilderness of abstract declarators:
+   Qux<int(&(*))> vs Qux<int(&(var))>, a shift-reduce conflict at the
+   innermost left parenthesis.  So we do not support function-like casts.
+   Fortunately they never appear in demangler output.  */
 
 /* TO INVESTIGATE: ._0 style anonymous names; anonymous namespaces */
 
@@ -1150,7 +1166,11 @@ 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.  */
+                 $$ = d_unary ("sizeof ", $3);
+               }
        ;
 
 /* C++.  */
@@ -1438,7 +1458,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)++;
@@ -1459,7 +1479,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;
 
@@ -1498,7 +1518,7 @@ parse_escape (const char **string_ptr)
          return i;
        }
       default:
-       return target_char;
+       return c;
       }
 }
 
@@ -1533,7 +1553,7 @@ yylex (void)
 {
   int c;
   int namelen;
-  const char *tokstart, *tokptr;
+  const char *tokstart;
 
  retry:
   prev_lexptr = lexptr;
@@ -1557,17 +1577,17 @@ yylex (void)
       lexptr++;
       c = *lexptr++;
       if (c == '\\')
-       c = parse_escape (&lexptr);
+       c = cp_parse_escape (&lexptr);
       else if (c == '\'')
        {
-         yyerror ("empty character constant");
+         yyerror (_("empty character constant"));
          return ERROR;
        }
 
       c = *lexptr++;
       if (c != '\'')
        {
-         yyerror ("invalid character constant");
+         yyerror (_("invalid character constant"));
          return ERROR;
        }
 
@@ -1691,7 +1711,7 @@ yylex (void)
 
            memcpy (err_copy, tokstart, p - tokstart);
            err_copy[p - tokstart] = 0;
-           yyerror ("invalid number");
+           yyerror (_("invalid number"));
            return ERROR;
          }
        lexptr = p;
@@ -1767,14 +1787,14 @@ yylex (void)
 
     case '"':
       /* These can't occur in C++ names.  */
-      yyerror ("unexpected string literal");
+      yyerror (_("unexpected string literal"));
       return ERROR;
     }
 
   if (!(c == '_' || c == '$' || ISALPHA (c)))
     {
       /* We must have come across a bad character (e.g. ';').  */
-      yyerror ("invalid character");
+      yyerror (_("invalid character"));
       return ERROR;
     }
 
@@ -1837,23 +1857,23 @@ yylex (void)
        {
          const char *p;
          lexptr = tokstart + 29;
-         yylval.typed_val_int.val = GLOBAL_CONSTRUCTORS;
+         yylval.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);
+         yylval.comp = make_name (lexptr, p - lexptr);
          lexptr = p;
-         return GLOBAL;
+         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;
+         yylval.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);
+         yylval.comp = make_name (lexptr, p - lexptr);
          lexptr = p;
-         return GLOBAL;
+         return DEMANGLER_SPECIAL;
        }
 
       HANDLE_SPECIAL ("vtable for ", DEMANGLE_COMPONENT_VTABLE);
@@ -1914,7 +1934,7 @@ yylex (void)
 }
 
 static void
-yyerror (char *msg)
+yyerror (const char *msg)
 {
   if (global_errmsg)
     return;
@@ -1923,19 +1943,18 @@ yyerror (char *msg)
   global_errmsg = msg ? msg : "parse error";
 }
 
-/* Allocate all 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.  If we start keeping the trees for
-   a longer lifetime we'll need to be cleverer.  */
+/* 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 struct demangle_info *
-allocate_info (int comps)
+allocate_info (void)
 {
-  struct demangle_info *ret;
+  struct demangle_info *info = XNEW (struct demangle_info);
 
-  ret = malloc (sizeof (struct demangle_info)
-               + sizeof (struct demangle_component) * (comps - 1));
-  ret->used = 0;
-  return ret;
+  info->next = NULL;
+  info->used = 0;
+  return info;
 }
 
 /* Convert RESULT to a string.  The return value is allocated
@@ -1944,57 +1963,90 @@ allocate_info (int comps)
    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.  *MEMORY is set to the
-   block of used memory that should be freed when finished with the
-   tree.  On error, NULL is returned, and an error message will be
-   set in *ERRMSG (which does not need to be freed).  */
+/* Convert a demangled name to a demangle_component tree.  On success,
+   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 (which does not need to be freed).  */
 
-struct demangle_component *
-cp_demangled_name_to_comp (const char *demangled_name, void **memory,
-                          const char **errmsg)
+struct std::unique_ptr<demangle_parse_info>
+cp_demangled_name_to_comp (const char *demangled_name, const char **errmsg)
 {
   static char errbuf[60];
-  struct demangle_component *result;
-
-  int len = strlen (demangled_name);
 
-  len = len + len / 8;
   prev_lexptr = lexptr = demangled_name;
   error_lexptr = NULL;
   global_errmsg = NULL;
 
-  demangle_info = allocate_info (len);
+  demangle_info = allocate_info ();
+
+  std::unique_ptr<demangle_parse_info> result (new demangle_parse_info);
+  result->info = demangle_info;
 
   if (yyparse ())
     {
@@ -2005,12 +2057,10 @@ cp_demangled_name_to_comp (const char *demangled_name, void **memory,
          strcat (errbuf, "'");
          *errmsg = errbuf;
        }
-      free (demangle_info);
       return NULL;
     }
 
-  *memory = demangle_info;
-  result = global_result;
+  result->tree = global_result;
   global_result = NULL;
 
   return result;
@@ -2024,17 +2074,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;
@@ -2060,15 +2099,40 @@ 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;
-  void *memory;
-  struct demangle_component *result;
 
   arg = 1;
   if (argv[arg] && strcmp (argv[arg], "--debug") == 0)
@@ -2087,14 +2151,16 @@ main (int argc, char **argv)
        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, &memory, &errmsg);
+
+       std::unique_ptr<demangle_parse_info> result
+         = cp_demangled_name_to_comp (str2, &errmsg);
        if (result == NULL)
          {
            fputs (errmsg, stderr);
@@ -2102,8 +2168,7 @@ main (int argc, char **argv)
            continue;
          }
 
-       cp_print (result);
-       free (memory);
+       cp_print (result->tree);
 
        free (str2);
        if (c)
@@ -2115,16 +2180,16 @@ main (int argc, char **argv)
       }
   else
     {
-      result = cp_demangled_name_to_comp (argv[arg], &memory, &errmsg);
+      std::unique_ptr<demangle_parse_info> result
+       = cp_demangled_name_to_comp (argv[arg], &errmsg);
       if (result == NULL)
        {
          fputs (errmsg, stderr);
          fputc ('\n', stderr);
          return 0;
        }
-      cp_print (result);
+      cp_print (result->tree);
       putchar ('\n');
-      free (memory);
     }
   return 0;
 }
This page took 0.037575 seconds and 4 git commands to generate.