Fix "fall through" comments
[deliverable/binutils-gdb.git] / gdb / cp-name-parser.y
index d85a5bf2b7907d6d463c7d6c3e5525594fa19312..f522e464191574c878ff65dbfb7ed022a318a951 100644 (file)
@@ -1,6 +1,6 @@
 /* YACC parser for C++ names, for GDB.
 
-   Copyright (C) 2003-2005, 2007-2012 Free Software Foundation, Inc.
+   Copyright (C) 2003-2018 Free Software Foundation, Inc.
 
    Parts of the lexer are based on c-exp.y from GDB.
 
 
 #include "defs.h"
 
-#include <stdio.h>
-#include <stdlib.h>
 #include <unistd.h>
-#include <string.h>
-
 #include "safe-ctype.h"
-#include "libiberty.h"
 #include "demangle.h"
 #include "cp-support.h"
-#include "gdb_assert.h"
 
 /* Bison does not make it easy to create a parser without global
    state, unfortunately.  Here are all the global variables used
@@ -75,7 +69,7 @@ d_grab (void)
     {
       if (demangle_info->next == NULL)
        {
-         more = malloc (sizeof (struct demangle_info));
+         more = XNEW (struct demangle_info);
          more->next = NULL;
          demangle_info->next = more;
        }
@@ -170,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
@@ -196,14 +196,6 @@ fill_comp (enum demangle_component_type d_type, struct demangle_component *lhs,
   return ret;
 }
 
-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)
 {
@@ -277,9 +269,9 @@ make_name (const char *name, int len)
     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
@@ -432,21 +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); }
                ;
 
-operator       :       OPERATOR NEW
-                       { $$ = make_operator ("new", 3); }
+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[]", 3); }
+                       {
+                         /* 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 '-'
@@ -512,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
@@ -538,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); }
@@ -563,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
@@ -583,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); }
                ;
 
@@ -744,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.  */
@@ -931,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);
                        }
                ;
@@ -948,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
@@ -1177,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++.  */
@@ -1311,6 +1304,28 @@ d_binary (const char *name, struct demangle_component *lhs, struct demangle_comp
                      fill_comp (DEMANGLE_COMPONENT_BINARY_ARGS, lhs, rhs));
 }
 
+/* Like ISALPHA, but also returns true for the union of all UTF-8
+   multi-byte sequence bytes and non-ASCII characters in
+   extended-ASCII charsets (e.g., Latin1).  I.e., returns true if the
+   high bit is set.  Note that not all UTF-8 ranges are allowed in C++
+   identifiers, but we don't need to be pedantic so for simplicity we
+   ignore that here.  Plus this avoids the complication of actually
+   knowing what was the right encoding.  */
+
+static inline bool
+cp_ident_is_alpha (unsigned char ch)
+{
+  return ISALPHA (ch) || ch >= 0x80;
+}
+
+/* Similarly, but Like ISALNUM.  */
+
+static inline bool
+cp_ident_is_alnum (unsigned char ch)
+{
+  return ISALNUM (ch) || ch >= 0x80;
+}
+
 /* Find the end of a symbol name starting at LEXPTR.  */
 
 static const char *
@@ -1318,7 +1333,7 @@ symbol_end (const char *lexptr)
 {
   const char *p = lexptr;
 
-  while (*p && (ISALNUM (*p) || *p == '_' || *p == '$' || *p == '.'))
+  while (*p && (cp_ident_is_alnum (*p) || *p == '_' || *p == '$' || *p == '.'))
     p++;
 
   return p;
@@ -1653,7 +1668,7 @@ yylex (void)
          lexptr++;
          return '-';
        }
-      /* FALL THRU into number case.  */
+      /* FALL THRU.  */
 
     try_number:
     case '0':
@@ -1798,7 +1813,7 @@ yylex (void)
       return ERROR;
     }
 
-  if (!(c == '_' || c == '$' || ISALPHA (c)))
+  if (!(c == '_' || c == '$' || cp_ident_is_alpha (c)))
     {
       /* We must have come across a bad character (e.g. ';').  */
       yyerror (_("invalid character"));
@@ -1809,7 +1824,7 @@ yylex (void)
   namelen = 0;
   do
     c = tokstart[++namelen];
-  while (ISALNUM (c) || c == '_' || c == '$');
+  while (cp_ident_is_alnum (c) || c == '_' || c == '$');
 
   lexptr += namelen;
 
@@ -1941,7 +1956,7 @@ yylex (void)
 }
 
 static void
-yyerror (char *msg)
+yyerror (const char *msg)
 {
   if (global_errmsg)
     return;
@@ -1957,7 +1972,7 @@ yyerror (char *msg)
 static struct demangle_info *
 allocate_info (void)
 {
-  struct demangle_info *info = malloc (sizeof (struct demangle_info));
+  struct demangle_info *info = XNEW (struct demangle_info);
 
   info->next = NULL;
   info->used = 0;
@@ -1970,38 +1985,29 @@ 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)
 {
   size_t err;
 
-  return cplus_demangle_print (DMGL_PARAMS | DMGL_ANSI, result, estimated_len,
-                              &err);
+  char *res = cplus_demangle_print (DMGL_PARAMS | DMGL_ANSI,
+                                   result, estimated_len, &err);
+  return gdb::unique_xmalloc_ptr<char> (res);
 }
 
-/* A convenience function to allocate and initialize a new struct
-   demangled_parse_info.  */
+/* Constructor for demangle_parse_info.  */
 
-struct demangle_parse_info *
-cp_new_demangle_parse_info (void)
+demangle_parse_info::demangle_parse_info ()
+: info (NULL),
+  tree (NULL)
 {
-  struct demangle_parse_info *info;
-
-  info = malloc (sizeof (struct demangle_parse_info));
-  info->info = NULL;
-  info->tree = NULL;
-  obstack_init (&info->obstack);
-
-  return info;
+  obstack_init (&obstack);
 }
 
-/* Free any memory associated with the given PARSE_INFO.  */
+/* Destructor for demangle_parse_info.  */
 
-void
-cp_demangled_name_parse_free (struct demangle_parse_info *parse_info)
+demangle_parse_info::~demangle_parse_info ()
 {
-  struct demangle_info *info = parse_info->info;
-
   /* Free any allocated chunks of memory for the parse.  */
   while (info != NULL)
     {
@@ -2012,15 +2018,11 @@ cp_demangled_name_parse_free (struct demangle_parse_info *parse_info)
     }
 
   /* Free any memory allocated during typedef replacement.  */
-  obstack_free (&parse_info->obstack, NULL);
-
-  /* Free the parser info.  */
-  free (parse_info);
+  obstack_free (&obstack, NULL);
 }
 
 /* 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.
-   SRC is then freed.
 
    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.
@@ -2047,22 +2049,17 @@ cp_merge_demangle_parse_infos (struct demangle_parse_info *dest,
   /* 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;
-
-  /* Free SRC.  */
-  cp_demangled_name_parse_free (src);
 }
 
 /* Convert a demangled name to a demangle_component tree.  On success,
-   a structure containing the root of the new tree is returned; it must
-   be freed by calling cp_demangled_name_parse_free. 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 (which does not need to be freed).  */
 
-struct demangle_parse_info *
+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_parse_info *result;
 
   prev_lexptr = lexptr = demangled_name;
   error_lexptr = NULL;
@@ -2070,7 +2067,7 @@ cp_demangled_name_to_comp (const char *demangled_name, const char **errmsg)
 
   demangle_info = allocate_info ();
 
-  result = cp_new_demangle_parse_info ();
+  std::unique_ptr<demangle_parse_info> result (new demangle_parse_info);
   result->info = demangle_info;
 
   if (yyparse ())
@@ -2082,7 +2079,6 @@ cp_demangled_name_to_comp (const char *demangled_name, const char **errmsg)
          strcat (errbuf, "'");
          *errmsg = errbuf;
        }
-      cp_demangled_name_parse_free (result);
       return NULL;
     }
 
@@ -2155,11 +2151,10 @@ internal_error (const char *file, int line, const char *fmt, ...)
 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_parse_info *result;
 
   arg = 1;
   if (argv[arg] && strcmp (argv[arg], "--debug") == 0)
@@ -2185,7 +2180,9 @@ main (int argc, char **argv)
              printf ("%s\n", buf);
            continue;
          }
-       result = cp_demangled_name_to_comp (str2, &errmsg);
+
+       std::unique_ptr<demangle_parse_info> result
+         = cp_demangled_name_to_comp (str2, &errmsg);
        if (result == NULL)
          {
            fputs (errmsg, stderr);
@@ -2194,7 +2191,6 @@ main (int argc, char **argv)
          }
 
        cp_print (result->tree);
-       cp_demangled_name_parse_free (result);
 
        free (str2);
        if (c)
@@ -2206,7 +2202,8 @@ main (int argc, char **argv)
       }
   else
     {
-      result = cp_demangled_name_to_comp (argv[arg], &errmsg);
+      std::unique_ptr<demangle_parse_info> result
+       = cp_demangled_name_to_comp (argv[arg], &errmsg);
       if (result == NULL)
        {
          fputs (errmsg, stderr);
@@ -2214,7 +2211,6 @@ main (int argc, char **argv)
          return 0;
        }
       cp_print (result->tree);
-      cp_demangled_name_parse_free (result);
       putchar ('\n');
     }
   return 0;
This page took 0.035529 seconds and 4 git commands to generate.