Move type stack handling to a new class
authorTom Tromey <tom@tromey.com>
Sun, 31 Mar 2019 19:43:54 +0000 (13:43 -0600)
committerTom Tromey <tom@tromey.com>
Fri, 5 Apr 2019 01:55:11 +0000 (19:55 -0600)
This introduces a new "type_stack" class, and moves all the parser
type stack handling to this class.  Parsers that wish to use this
facility must now instantiate this class somehow.  I chose this
approach because a minority of the existing parsers require this.

gdb/ChangeLog
2019-04-04  Tom Tromey  <tom@tromey.com>

* type-stack.h: New file.
* type-stack.c: New file.
* parser-defs.h (enum type_pieces, union type_stack_elt): Move to
type-stack.h.
(insert_into_type_stack, insert_type, push_type, push_type_int)
(insert_type_address_space, pop_type, pop_type_int)
(pop_typelist, pop_type_stack, append_type_stack)
(push_type_stack, get_type_stack, push_typelist)
(follow_type_instance_flags, follow_types): Don't declare.
* parse.c (type_stack): Remove global.
(parse_exp_in_context): Update.
(insert_into_type_stack, insert_type, push_type, push_type_int)
(insert_type_address_space, pop_type, pop_type_int)
(pop_typelist, pop_type_stack, append_type_stack)
(push_type_stack, get_type_stack, push_typelist)
(follow_type_instance_flags, follow_types): Remove (moved to
type-stack.c).
* f-exp.y (type_stack): New global.
Update rules.
(push_kind_type, f_parse): Update.
* d-exp.y (type_stack): New global.
Update rules.
(d_parse): Update.
* c-exp.y (struct c_parse_state) <type_stack>: New member.
Update rules.
* Makefile.in (COMMON_SFILES): Add type-stack.c.
(HFILES_NO_SRCDIR): Add type-stack.h.

gdb/ChangeLog
gdb/Makefile.in
gdb/c-exp.y
gdb/d-exp.y
gdb/f-exp.y
gdb/parse.c
gdb/parser-defs.h
gdb/type-stack.c [new file with mode: 0644]
gdb/type-stack.h [new file with mode: 0644]

index 7d415d2..238d678 100644 (file)
@@ -1,5 +1,35 @@
 2019-04-04  Tom Tromey  <tom@tromey.com>
 
+       * type-stack.h: New file.
+       * type-stack.c: New file.
+       * parser-defs.h (enum type_pieces, union type_stack_elt): Move to
+       type-stack.h.
+       (insert_into_type_stack, insert_type, push_type, push_type_int)
+       (insert_type_address_space, pop_type, pop_type_int)
+       (pop_typelist, pop_type_stack, append_type_stack)
+       (push_type_stack, get_type_stack, push_typelist)
+       (follow_type_instance_flags, follow_types): Don't declare.
+       * parse.c (type_stack): Remove global.
+       (parse_exp_in_context): Update.
+       (insert_into_type_stack, insert_type, push_type, push_type_int)
+       (insert_type_address_space, pop_type, pop_type_int)
+       (pop_typelist, pop_type_stack, append_type_stack)
+       (push_type_stack, get_type_stack, push_typelist)
+       (follow_type_instance_flags, follow_types): Remove (moved to
+       type-stack.c).
+       * f-exp.y (type_stack): New global.
+       Update rules.
+       (push_kind_type, f_parse): Update.
+       * d-exp.y (type_stack): New global.
+       Update rules.
+       (d_parse): Update.
+       * c-exp.y (struct c_parse_state) <type_stack>: New member.
+       Update rules.
+       * Makefile.in (COMMON_SFILES): Add type-stack.c.
+       (HFILES_NO_SRCDIR): Add type-stack.h.
+
+2019-04-04  Tom Tromey  <tom@tromey.com>
+
        * rust-exp.y (rust_parser::lex_identifier, rustyylex)
        (rust_parser::convert_ast_to_expression, rust_parse)
        (rust_lex_test_completion, rust_lex_tests): Update.
index 5614cc3..0f49578 100644 (file)
@@ -1131,6 +1131,7 @@ COMMON_SFILES = \
        trad-frame.c \
        tramp-frame.c \
        target-float.c \
+       type-stack.c \
        typeprint.c \
        ui-file.c \
        ui-out.c \
@@ -1406,6 +1407,7 @@ HFILES_NO_SRCDIR = \
        trad-frame.h \
        target-float.h \
        tramp-frame.h \
+       type-stack.h \
        typeprint.h \
        ui-file.h \
        ui-out.h \
index 842b492..627ea1f 100644 (file)
@@ -53,6 +53,7 @@
 #include "objc-lang.h"
 #include "typeprint.h"
 #include "cp-abi.h"
+#include "type-stack.h"
 
 #define parse_type(ps) builtin_type (ps->gdbarch ())
 
@@ -104,6 +105,9 @@ struct c_parse_state
      token, we simply keep it all and delete it after parsing has
      completed.  */
   auto_obstack expansion_obstack;
+
+  /* The type stack.  */
+  struct type_stack type_stack;
 };
 
 /* This is set and cleared in c_parse.  */
@@ -604,8 +608,10 @@ function_method:       exp '(' parameter_typelist ')' const_or_volatile
                          /* Save the const/volatile qualifiers as
                             recorded by the const_or_volatile
                             production's actions.  */
-                         write_exp_elt_longcst (pstate,
-                                                follow_type_instance_flags ());
+                         write_exp_elt_longcst
+                           (pstate,
+                            (cpstate->type_stack
+                             .follow_type_instance_flags ()));
                          write_exp_elt_longcst (pstate, len);
                          for (type *type_elt : *type_list)
                            write_exp_elt_type (pstate, type_elt);
@@ -617,8 +623,9 @@ function_method:       exp '(' parameter_typelist ')' const_or_volatile
 function_method_void:      exp '(' ')' const_or_volatile
                       { write_exp_elt_opcode (pstate, TYPE_INSTANCE);
                         /* See above.  */
-                        write_exp_elt_longcst (pstate,
-                                               follow_type_instance_flags ());
+                        write_exp_elt_longcst
+                          (pstate,
+                           cpstate->type_stack.follow_type_instance_flags ());
                         write_exp_elt_longcst (pstate, 0);
                         write_exp_elt_longcst (pstate, 0);
                         write_exp_elt_opcode (pstate, TYPE_INSTANCE);
@@ -1158,7 +1165,9 @@ variable: name_not_typename
        ;
 
 space_identifier : '@' NAME
-               { insert_type_address_space (pstate, copy_name ($2.stoken)); }
+               {
+                 cpstate->type_stack.insert (pstate, copy_name ($2.stoken));
+               }
        ;
 
 const_or_volatile: const_or_volatile_noopt
@@ -1179,30 +1188,30 @@ const_or_volatile_or_space_identifier:
 
 ptr_operator:
                ptr_operator '*'
-                       { insert_type (tp_pointer); }
+                       { cpstate->type_stack.insert (tp_pointer); }
                const_or_volatile_or_space_identifier
        |       '*'
-                       { insert_type (tp_pointer); }
+                       { cpstate->type_stack.insert (tp_pointer); }
                const_or_volatile_or_space_identifier
        |       '&'
-                       { insert_type (tp_reference); }
+                       { cpstate->type_stack.insert (tp_reference); }
        |       '&' ptr_operator
-                       { insert_type (tp_reference); }
+                       { cpstate->type_stack.insert (tp_reference); }
        |       ANDAND
-                       { insert_type (tp_rvalue_reference); }
+                       { cpstate->type_stack.insert (tp_rvalue_reference); }
        |       ANDAND ptr_operator
-                       { insert_type (tp_rvalue_reference); }
+                       { cpstate->type_stack.insert (tp_rvalue_reference); }
        ;
 
 ptr_operator_ts: ptr_operator
                        {
-                         $$ = get_type_stack ();
+                         $$ = cpstate->type_stack.create ();
                          cpstate->type_stacks.emplace_back ($$);
                        }
        ;
 
 abs_decl:      ptr_operator_ts direct_abs_decl
-                       { $$ = append_type_stack ($2, $1); }
+                       { $$ = $2->append ($1); }
        |       ptr_operator_ts
        |       direct_abs_decl
        ;
@@ -1211,31 +1220,31 @@ direct_abs_decl: '(' abs_decl ')'
                        { $$ = $2; }
        |       direct_abs_decl array_mod
                        {
-                         push_type_stack ($1);
-                         push_type_int ($2);
-                         push_type (tp_array);
-                         $$ = get_type_stack ();
+                         cpstate->type_stack.push ($1);
+                         cpstate->type_stack.push ($2);
+                         cpstate->type_stack.push (tp_array);
+                         $$ = cpstate->type_stack.create ();
                          cpstate->type_stacks.emplace_back ($$);
                        }
        |       array_mod
                        {
-                         push_type_int ($1);
-                         push_type (tp_array);
-                         $$ = get_type_stack ();
+                         cpstate->type_stack.push ($1);
+                         cpstate->type_stack.push (tp_array);
+                         $$ = cpstate->type_stack.create ();
                          cpstate->type_stacks.emplace_back ($$);
                        }
 
        |       direct_abs_decl func_mod
                        {
-                         push_type_stack ($1);
-                         push_typelist ($2);
-                         $$ = get_type_stack ();
+                         cpstate->type_stack.push ($1);
+                         cpstate->type_stack.push ($2);
+                         $$ = cpstate->type_stack.create ();
                          cpstate->type_stacks.emplace_back ($$);
                        }
        |       func_mod
                        {
-                         push_typelist ($1);
-                         $$ = get_type_stack ();
+                         cpstate->type_stack.push ($1);
+                         $$ = cpstate->type_stack.create ();
                          cpstate->type_stacks.emplace_back ($$);
                        }
        ;
@@ -1489,9 +1498,9 @@ typebase
                             pstate->expression_context_block);
                        }
        | const_or_volatile_or_space_identifier_noopt typebase
-                       { $$ = follow_types ($2); }
+                       { $$ = cpstate->type_stack.follow_types ($2); }
        | typebase const_or_volatile_or_space_identifier_noopt
-                       { $$ = follow_types ($1); }
+                       { $$ = cpstate->type_stack.follow_types ($1); }
        ;
 
 type_name:     TYPENAME
@@ -1552,13 +1561,13 @@ nonempty_typelist
 ptype  :       typebase
        |       ptype abs_decl
                {
-                 push_type_stack ($2);
-                 $$ = follow_types ($1);
+                 cpstate->type_stack.push ($2);
+                 $$ = cpstate->type_stack.follow_types ($1);
                }
        ;
 
 conversion_type_id: typebase conversion_declarator
-               { $$ = follow_types ($1); }
+               { $$ = cpstate->type_stack.follow_types ($1); }
        ;
 
 conversion_declarator:  /* Nothing.  */
@@ -1570,13 +1579,13 @@ const_and_volatile:     CONST_KEYWORD VOLATILE_KEYWORD
        ;
 
 const_or_volatile_noopt:       const_and_volatile
-                       { insert_type (tp_const);
-                         insert_type (tp_volatile);
+                       { cpstate->type_stack.insert (tp_const);
+                         cpstate->type_stack.insert (tp_volatile);
                        }
        |               CONST_KEYWORD
-                       { insert_type (tp_const); }
+                       { cpstate->type_stack.insert (tp_const); }
        |               VOLATILE_KEYWORD
-                       { insert_type (tp_volatile); }
+                       { cpstate->type_stack.insert (tp_volatile); }
        ;
 
 oper:  OPERATOR NEW
index 4d51cfd..ca9aaf8 100644 (file)
@@ -51,6 +51,7 @@
 #include "objfiles.h" /* For have_full_symbols and have_partial_symbols */
 #include "charset.h"
 #include "block.h"
+#include "type-stack.h"
 
 #define parse_type(ps) builtin_type (ps->gdbarch ())
 #define parse_d_type(ps) builtin_d_type (ps->gdbarch ())
@@ -65,6 +66,9 @@
 
 static struct parser_state *pstate = NULL;
 
+/* The current type stack.  */
+static struct type_stack *type_stack;
+
 int yyparse (void);
 
 static int yylex (void);
@@ -606,7 +610,7 @@ TypeExp:
                  write_exp_elt_type (pstate, $1);
                  write_exp_elt_opcode (pstate, OP_TYPE); }
 |      BasicType BasicType2
-               { $$ = follow_types ($1);
+               { $$ = type_stack->follow_types ($1);
                  write_exp_elt_opcode (pstate, OP_TYPE);
                  write_exp_elt_type (pstate, $$);
                  write_exp_elt_opcode (pstate, OP_TYPE);
@@ -615,15 +619,15 @@ TypeExp:
 
 BasicType2:
        '*'
-               { push_type (tp_pointer); }
+               { type_stack->push (tp_pointer); }
 |      '*' BasicType2
-               { push_type (tp_pointer); }
+               { type_stack->push (tp_pointer); }
 |      '[' INTEGER_LITERAL ']'
-               { push_type_int ($2.val);
-                 push_type (tp_array); }
+               { type_stack->push ($2.val);
+                 type_stack->push (tp_array); }
 |      '[' INTEGER_LITERAL ']' BasicType2
-               { push_type_int ($2.val);
-                 push_type (tp_array); }
+               { type_stack->push ($2.val);
+                 type_stack->push (tp_array); }
 ;
 
 BasicType:
@@ -1619,6 +1623,10 @@ d_parse (struct parser_state *par_state)
   scoped_restore restore_yydebug = make_scoped_restore (&yydebug,
                                                        parser_debug);
 
+  struct type_stack stack;
+  scoped_restore restore_type_stack = make_scoped_restore (&type_stack,
+                                                          &stack);
+
   /* Initialize some state used by the lexer.  */
   last_was_structop = 0;
   saw_name_at_eof = 0;
index da47322..403dfa2 100644 (file)
@@ -54,6 +54,7 @@
 #include "block.h"
 #include <ctype.h>
 #include <algorithm>
+#include "type-stack.h"
 
 #define parse_type(ps) builtin_type (ps->gdbarch ())
 #define parse_f_type(ps) builtin_f_type (ps->gdbarch ())
@@ -71,6 +72,9 @@ static struct parser_state *pstate = NULL;
 /* Depth of parentheses.  */
 static int paren_depth;
 
+/* The current type stack.  */
+static struct type_stack *type_stack;
+
 int yyparse (void);
 
 static int yylex (void);
@@ -515,7 +519,7 @@ ptype       :       typebase
                  struct type *range_type;
                  
                  while (!done)
-                   switch (pop_type ())
+                   switch (type_stack->pop ())
                      {
                      case tp_end:
                        done = 1;
@@ -527,7 +531,7 @@ ptype       :       typebase
                        follow_type = lookup_lvalue_reference_type (follow_type);
                        break;
                      case tp_array:
-                       array_size = pop_type_int ();
+                       array_size = type_stack->pop_int ();
                        if (array_size != -1)
                          {
                            range_type =
@@ -547,7 +551,7 @@ ptype       :       typebase
                        break;
                      case tp_kind:
                        {
-                         int kind_val = pop_type_int ();
+                         int kind_val = type_stack->pop_int ();
                          follow_type
                            = convert_to_kind_type (follow_type, kind_val);
                        }
@@ -558,13 +562,13 @@ ptype     :       typebase
        ;
 
 abs_decl:      '*'
-                       { push_type (tp_pointer); $$ = 0; }
+                       { type_stack->push (tp_pointer); $$ = 0; }
        |       '*' abs_decl
-                       { push_type (tp_pointer); $$ = $2; }
+                       { type_stack->push (tp_pointer); $$ = $2; }
        |       '&'
-                       { push_type (tp_reference); $$ = 0; }
+                       { type_stack->push (tp_reference); $$ = 0; }
        |       '&' abs_decl
-                       { push_type (tp_reference); $$ = $2; }
+                       { type_stack->push (tp_reference); $$ = $2; }
        |       direct_abs_decl
        ;
 
@@ -575,9 +579,9 @@ direct_abs_decl: '(' abs_decl ')'
        |       '*' INT
                        { push_kind_type ($2.val, $2.type); }
        |       direct_abs_decl func_mod
-                       { push_type (tp_function); }
+                       { type_stack->push (tp_function); }
        |       func_mod
-                       { push_type (tp_function); }
+                       { type_stack->push (tp_function); }
        ;
 
 func_mod:      '(' ')'
@@ -821,8 +825,8 @@ push_kind_type (LONGEST val, struct type *type)
       ival = static_cast <int> (val);
     }
 
-  push_type_int (ival);
-  push_type (tp_kind);
+  type_stack->push (ival);
+  type_stack->push (tp_kind);
 }
 
 /* Called when a type has a '(kind=N)' modifier after it, for example
@@ -1333,6 +1337,10 @@ f_parse (struct parser_state *par_state)
   pstate = par_state;
   paren_depth = 0;
 
+  struct type_stack stack;
+  scoped_restore restore_type_stack = make_scoped_restore (&type_stack,
+                                                          &stack);
+
   return yyparse ();
 }
 
index 7984a32..89a29f0 100644 (file)
@@ -67,7 +67,6 @@ const struct exp_descriptor exp_descriptor_standard =
 \f
 /* Global variables declared in parser-defs.h (and commented there).  */
 innermost_block_tracker innermost_block;
-static struct type_stack type_stack;
 
 \f
 static unsigned int expressiondebug = 0;
@@ -1073,7 +1072,6 @@ parse_exp_in_context (const char **stringptr, CORE_ADDR pc,
   const struct language_defn *lang = NULL;
   int subexp;
 
-  type_stack.elements.clear ();
   innermost_block.reset (tracker_types);
 
   if (*stringptr == 0 || **stringptr == 0)
@@ -1287,337 +1285,6 @@ parse_float (const char *p, int len,
   return target_float_from_string (data, type, std::string (p, len));
 }
 \f
-/* Stuff for maintaining a stack of types.  Currently just used by C, but
-   probably useful for any language which declares its types "backwards".  */
-
-/* A helper function for insert_type and insert_type_address_space.
-   This does work of expanding the type stack and inserting the new
-   element, ELEMENT, into the stack at location SLOT.  */
-
-static void
-insert_into_type_stack (int slot, union type_stack_elt element)
-{
-  gdb_assert (slot <= type_stack.elements.size ());
-  type_stack.elements.insert (type_stack.elements.begin () + slot, element);
-}
-
-/* Insert a new type, TP, at the bottom of the type stack.  If TP is
-   tp_pointer, tp_reference or tp_rvalue_reference, it is inserted at the
-   bottom.  If TP is a qualifier, it is inserted at slot 1 (just above a
-   previous tp_pointer) if there is anything on the stack, or simply pushed
-   if the stack is empty.  Other values for TP are invalid.  */
-
-void
-insert_type (enum type_pieces tp)
-{
-  union type_stack_elt element;
-  int slot;
-
-  gdb_assert (tp == tp_pointer || tp == tp_reference
-             || tp == tp_rvalue_reference || tp == tp_const
-             || tp == tp_volatile);
-
-  /* If there is anything on the stack (we know it will be a
-     tp_pointer), insert the qualifier above it.  Otherwise, simply
-     push this on the top of the stack.  */
-  if (!type_stack.elements.empty () && (tp == tp_const || tp == tp_volatile))
-    slot = 1;
-  else
-    slot = 0;
-
-  element.piece = tp;
-  insert_into_type_stack (slot, element);
-}
-
-void
-push_type (enum type_pieces tp)
-{
-  type_stack_elt elt;
-  elt.piece = tp;
-  type_stack.elements.push_back (elt);
-}
-
-void
-push_type_int (int n)
-{
-  type_stack_elt elt;
-  elt.int_val = n;
-  type_stack.elements.push_back (elt);
-}
-
-/* Insert a tp_space_identifier and the corresponding address space
-   value into the stack.  STRING is the name of an address space, as
-   recognized by address_space_name_to_int.  If the stack is empty,
-   the new elements are simply pushed.  If the stack is not empty,
-   this function assumes that the first item on the stack is a
-   tp_pointer, and the new values are inserted above the first
-   item.  */
-
-void
-insert_type_address_space (struct expr_builder *pstate, char *string)
-{
-  union type_stack_elt element;
-  int slot;
-
-  /* If there is anything on the stack (we know it will be a
-     tp_pointer), insert the address space qualifier above it.
-     Otherwise, simply push this on the top of the stack.  */
-  if (!type_stack.elements.empty ())
-    slot = 1;
-  else
-    slot = 0;
-
-  element.piece = tp_space_identifier;
-  insert_into_type_stack (slot, element);
-  element.int_val = address_space_name_to_int (pstate->gdbarch (),
-                                              string);
-  insert_into_type_stack (slot, element);
-}
-
-enum type_pieces
-pop_type (void)
-{
-  if (!type_stack.elements.empty ())
-    {
-      type_stack_elt elt = type_stack.elements.back ();
-      type_stack.elements.pop_back ();
-      return elt.piece;
-    }
-  return tp_end;
-}
-
-int
-pop_type_int (void)
-{
-  if (!type_stack.elements.empty ())
-    {
-      type_stack_elt elt = type_stack.elements.back ();
-      type_stack.elements.pop_back ();
-      return elt.int_val;
-    }
-  /* "Can't happen".  */
-  return 0;
-}
-
-/* Pop a type list element from the global type stack.  */
-
-static std::vector<struct type *> *
-pop_typelist (void)
-{
-  gdb_assert (!type_stack.elements.empty ());
-  type_stack_elt elt = type_stack.elements.back ();
-  type_stack.elements.pop_back ();
-  return elt.typelist_val;
-}
-
-/* Pop a type_stack element from the global type stack.  */
-
-static struct type_stack *
-pop_type_stack (void)
-{
-  gdb_assert (!type_stack.elements.empty ());
-  type_stack_elt elt = type_stack.elements.back ();
-  type_stack.elements.pop_back ();
-  return elt.stack_val;
-}
-
-/* Append the elements of the type stack FROM to the type stack TO.
-   Always returns TO.  */
-
-struct type_stack *
-append_type_stack (struct type_stack *to, struct type_stack *from)
-{
-  to->elements.insert (to->elements.end (), from->elements.begin (),
-                      from->elements.end ());
-  return to;
-}
-
-/* Push the type stack STACK as an element on the global type stack.  */
-
-void
-push_type_stack (struct type_stack *stack)
-{
-  type_stack_elt elt;
-  elt.stack_val = stack;
-  type_stack.elements.push_back (elt);
-  push_type (tp_type_stack);
-}
-
-/* Copy the global type stack into a newly allocated type stack and
-   return it.  The global stack is cleared.  The returned type stack
-   must be freed with delete.  */
-
-struct type_stack *
-get_type_stack (void)
-{
-  struct type_stack *result = new struct type_stack (std::move (type_stack));
-  type_stack.elements.clear ();
-  return result;
-}
-
-/* Push a function type with arguments onto the global type stack.
-   LIST holds the argument types.  If the final item in LIST is NULL,
-   then the function will be varargs.  */
-
-void
-push_typelist (std::vector<struct type *> *list)
-{
-  type_stack_elt elt;
-  elt.typelist_val = list;
-  type_stack.elements.push_back (elt);
-  push_type (tp_function_with_arguments);
-}
-
-/* Pop the type stack and return a type_instance_flags that
-   corresponds the const/volatile qualifiers on the stack.  This is
-   called by the C++ parser when parsing methods types, and as such no
-   other kind of type in the type stack is expected.  */
-
-type_instance_flags
-follow_type_instance_flags ()
-{
-  type_instance_flags flags = 0;
-
-  for (;;)
-    switch (pop_type ())
-      {
-      case tp_end:
-       return flags;
-      case tp_const:
-       flags |= TYPE_INSTANCE_FLAG_CONST;
-       break;
-      case tp_volatile:
-       flags |= TYPE_INSTANCE_FLAG_VOLATILE;
-       break;
-      default:
-       gdb_assert_not_reached ("unrecognized tp_ value in follow_types");
-      }
-}
-
-
-/* Pop the type stack and return the type which corresponds to FOLLOW_TYPE
-   as modified by all the stuff on the stack.  */
-struct type *
-follow_types (struct type *follow_type)
-{
-  int done = 0;
-  int make_const = 0;
-  int make_volatile = 0;
-  int make_addr_space = 0;
-  int array_size;
-
-  while (!done)
-    switch (pop_type ())
-      {
-      case tp_end:
-       done = 1;
-       if (make_const)
-         follow_type = make_cv_type (make_const, 
-                                     TYPE_VOLATILE (follow_type), 
-                                     follow_type, 0);
-       if (make_volatile)
-         follow_type = make_cv_type (TYPE_CONST (follow_type), 
-                                     make_volatile, 
-                                     follow_type, 0);
-       if (make_addr_space)
-         follow_type = make_type_with_address_space (follow_type, 
-                                                     make_addr_space);
-       make_const = make_volatile = 0;
-       make_addr_space = 0;
-       break;
-      case tp_const:
-       make_const = 1;
-       break;
-      case tp_volatile:
-       make_volatile = 1;
-       break;
-      case tp_space_identifier:
-       make_addr_space = pop_type_int ();
-       break;
-      case tp_pointer:
-       follow_type = lookup_pointer_type (follow_type);
-       if (make_const)
-         follow_type = make_cv_type (make_const, 
-                                     TYPE_VOLATILE (follow_type), 
-                                     follow_type, 0);
-       if (make_volatile)
-         follow_type = make_cv_type (TYPE_CONST (follow_type), 
-                                     make_volatile, 
-                                     follow_type, 0);
-       if (make_addr_space)
-         follow_type = make_type_with_address_space (follow_type, 
-                                                     make_addr_space);
-       make_const = make_volatile = 0;
-       make_addr_space = 0;
-       break;
-      case tp_reference:
-        follow_type = lookup_lvalue_reference_type (follow_type);
-        goto process_reference;
-       case tp_rvalue_reference:
-        follow_type = lookup_rvalue_reference_type (follow_type);
-       process_reference:
-        if (make_const)
-          follow_type = make_cv_type (make_const,
-                                      TYPE_VOLATILE (follow_type),
-                                      follow_type, 0);
-        if (make_volatile)
-          follow_type = make_cv_type (TYPE_CONST (follow_type),
-                                      make_volatile,
-                                      follow_type, 0);
-        if (make_addr_space)
-          follow_type = make_type_with_address_space (follow_type,
-                                                      make_addr_space);
-       make_const = make_volatile = 0;
-       make_addr_space = 0;
-       break;
-      case tp_array:
-       array_size = pop_type_int ();
-       /* FIXME-type-allocation: need a way to free this type when we are
-          done with it.  */
-       follow_type =
-         lookup_array_range_type (follow_type,
-                                  0, array_size >= 0 ? array_size - 1 : 0);
-       if (array_size < 0)
-         TYPE_HIGH_BOUND_KIND (TYPE_INDEX_TYPE (follow_type))
-           = PROP_UNDEFINED;
-       break;
-      case tp_function:
-       /* FIXME-type-allocation: need a way to free this type when we are
-          done with it.  */
-       follow_type = lookup_function_type (follow_type);
-       break;
-
-      case tp_function_with_arguments:
-       {
-         std::vector<struct type *> *args = pop_typelist ();
-
-         follow_type
-           = lookup_function_type_with_arguments (follow_type,
-                                                  args->size (),
-                                                  args->data ());
-       }
-       break;
-
-      case tp_type_stack:
-       {
-         struct type_stack *stack = pop_type_stack ();
-         /* Sort of ugly, but not really much worse than the
-            alternatives.  */
-         struct type_stack save = type_stack;
-
-         type_stack = *stack;
-         follow_type = follow_types (follow_type);
-         gdb_assert (type_stack.elements.empty ());
-
-         type_stack = save;
-       }
-       break;
-      default:
-       gdb_assert_not_reached ("unrecognized tp_ value in follow_types");
-      }
-  return follow_type;
-}
-\f
 /* This function avoids direct calls to fprintf 
    in the parser generated debug code.  */
 void
index 2c1ea15..edbd3b7 100644 (file)
@@ -299,40 +299,6 @@ struct objc_class_str
     int theclass;
   };
 
-/* For parsing of complicated types.
-   An array should be preceded in the list by the size of the array.  */
-enum type_pieces
-  {
-    tp_end = -1, 
-    tp_pointer, 
-    tp_reference, 
-    tp_rvalue_reference,
-    tp_array, 
-    tp_function,
-    tp_function_with_arguments,
-    tp_const, 
-    tp_volatile, 
-    tp_space_identifier,
-    tp_type_stack,
-    tp_kind
-  };
-/* The stack can contain either an enum type_pieces or an int.  */
-union type_stack_elt
-  {
-    enum type_pieces piece;
-    int int_val;
-    struct type_stack *stack_val;
-    std::vector<struct type *> *typelist_val;
-  };
-
-/* The type stack is an instance of this structure.  */
-
-struct type_stack
-{
-  /* Elements on the stack.  */
-  std::vector<union type_stack_elt> elements;
-};
-
 /* Reverse an expression from suffix form (in which it is constructed)
    to prefix form (in which we can conveniently print or execute it).
    Ordinarily this always returns -1.  However, if LAST_STRUCT
@@ -376,27 +342,6 @@ extern const char *find_template_name_end (const char *);
 
 extern char *copy_name (struct stoken);
 
-extern void insert_type (enum type_pieces);
-
-extern void push_type (enum type_pieces);
-
-extern void push_type_int (int);
-
-extern void insert_type_address_space (struct expr_builder *, char *);
-
-extern enum type_pieces pop_type (void);
-
-extern int pop_type_int (void);
-
-extern struct type_stack *get_type_stack (void);
-
-extern struct type_stack *append_type_stack (struct type_stack *to,
-                                            struct type_stack *from);
-
-extern void push_type_stack (struct type_stack *stack);
-
-extern void push_typelist (std::vector<struct type *> *typelist);
-
 extern int dump_subexp (struct expression *, struct ui_file *, int);
 
 extern int dump_subexp_body_standard (struct expression *, 
@@ -414,10 +359,6 @@ extern int operator_check_standard (struct expression *exp, int pos,
 
 extern const char *op_name_standard (enum exp_opcode);
 
-extern struct type *follow_types (struct type *);
-
-extern type_instance_flags follow_type_instance_flags ();
-
 extern void null_post_parser (expression_up *, int, int);
 
 extern bool parse_float (const char *p, int len,
diff --git a/gdb/type-stack.c b/gdb/type-stack.c
new file mode 100644 (file)
index 0000000..cb0c147
--- /dev/null
@@ -0,0 +1,209 @@
+/* Type stack for GDB parser.
+
+   Copyright (C) 1986-2019 Free Software Foundation, Inc.
+
+   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 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "defs.h"
+#include "type-stack.h"
+
+#include "gdbtypes.h"
+#include "parser-defs.h"
+
+/* See type-stack.h.  */
+
+void
+type_stack::insert (enum type_pieces tp)
+{
+  union type_stack_elt element;
+  int slot;
+
+  gdb_assert (tp == tp_pointer || tp == tp_reference
+             || tp == tp_rvalue_reference || tp == tp_const
+             || tp == tp_volatile);
+
+  /* If there is anything on the stack (we know it will be a
+     tp_pointer), insert the qualifier above it.  Otherwise, simply
+     push this on the top of the stack.  */
+  if (!m_elements.empty () && (tp == tp_const || tp == tp_volatile))
+    slot = 1;
+  else
+    slot = 0;
+
+  element.piece = tp;
+  insert_into (slot, element);
+}
+
+/* See type-stack.h.  */
+
+void
+type_stack::insert (struct expr_builder *pstate, char *string)
+{
+  union type_stack_elt element;
+  int slot;
+
+  /* If there is anything on the stack (we know it will be a
+     tp_pointer), insert the address space qualifier above it.
+     Otherwise, simply push this on the top of the stack.  */
+  if (!m_elements.empty ())
+    slot = 1;
+  else
+    slot = 0;
+
+  element.piece = tp_space_identifier;
+  insert_into (slot, element);
+  element.int_val = address_space_name_to_int (pstate->gdbarch (),
+                                              string);
+  insert_into (slot, element);
+}
+
+/* See type-stack.h.  */
+
+type_instance_flags
+type_stack::follow_type_instance_flags ()
+{
+  type_instance_flags flags = 0;
+
+  for (;;)
+    switch (pop ())
+      {
+      case tp_end:
+       return flags;
+      case tp_const:
+       flags |= TYPE_INSTANCE_FLAG_CONST;
+       break;
+      case tp_volatile:
+       flags |= TYPE_INSTANCE_FLAG_VOLATILE;
+       break;
+      default:
+       gdb_assert_not_reached ("unrecognized tp_ value in follow_types");
+      }
+}
+
+/* See type-stack.h.  */
+
+struct type *
+type_stack::follow_types (struct type *follow_type)
+{
+  int done = 0;
+  int make_const = 0;
+  int make_volatile = 0;
+  int make_addr_space = 0;
+  int array_size;
+
+  while (!done)
+    switch (pop ())
+      {
+      case tp_end:
+       done = 1;
+       if (make_const)
+         follow_type = make_cv_type (make_const, 
+                                     TYPE_VOLATILE (follow_type), 
+                                     follow_type, 0);
+       if (make_volatile)
+         follow_type = make_cv_type (TYPE_CONST (follow_type), 
+                                     make_volatile, 
+                                     follow_type, 0);
+       if (make_addr_space)
+         follow_type = make_type_with_address_space (follow_type, 
+                                                     make_addr_space);
+       make_const = make_volatile = 0;
+       make_addr_space = 0;
+       break;
+      case tp_const:
+       make_const = 1;
+       break;
+      case tp_volatile:
+       make_volatile = 1;
+       break;
+      case tp_space_identifier:
+       make_addr_space = pop_int ();
+       break;
+      case tp_pointer:
+       follow_type = lookup_pointer_type (follow_type);
+       if (make_const)
+         follow_type = make_cv_type (make_const, 
+                                     TYPE_VOLATILE (follow_type), 
+                                     follow_type, 0);
+       if (make_volatile)
+         follow_type = make_cv_type (TYPE_CONST (follow_type), 
+                                     make_volatile, 
+                                     follow_type, 0);
+       if (make_addr_space)
+         follow_type = make_type_with_address_space (follow_type, 
+                                                     make_addr_space);
+       make_const = make_volatile = 0;
+       make_addr_space = 0;
+       break;
+      case tp_reference:
+        follow_type = lookup_lvalue_reference_type (follow_type);
+        goto process_reference;
+       case tp_rvalue_reference:
+        follow_type = lookup_rvalue_reference_type (follow_type);
+       process_reference:
+        if (make_const)
+          follow_type = make_cv_type (make_const,
+                                      TYPE_VOLATILE (follow_type),
+                                      follow_type, 0);
+        if (make_volatile)
+          follow_type = make_cv_type (TYPE_CONST (follow_type),
+                                      make_volatile,
+                                      follow_type, 0);
+        if (make_addr_space)
+          follow_type = make_type_with_address_space (follow_type,
+                                                      make_addr_space);
+       make_const = make_volatile = 0;
+       make_addr_space = 0;
+       break;
+      case tp_array:
+       array_size = pop_int ();
+       /* FIXME-type-allocation: need a way to free this type when we are
+          done with it.  */
+       follow_type =
+         lookup_array_range_type (follow_type,
+                                  0, array_size >= 0 ? array_size - 1 : 0);
+       if (array_size < 0)
+         TYPE_HIGH_BOUND_KIND (TYPE_INDEX_TYPE (follow_type))
+           = PROP_UNDEFINED;
+       break;
+      case tp_function:
+       /* FIXME-type-allocation: need a way to free this type when we are
+          done with it.  */
+       follow_type = lookup_function_type (follow_type);
+       break;
+
+      case tp_function_with_arguments:
+       {
+         std::vector<struct type *> *args = pop_typelist ();
+
+         follow_type
+           = lookup_function_type_with_arguments (follow_type,
+                                                  args->size (),
+                                                  args->data ());
+       }
+       break;
+
+      case tp_type_stack:
+       {
+         struct type_stack *stack = pop_type_stack ();
+         follow_type = stack->follow_types (follow_type);
+       }
+       break;
+      default:
+       gdb_assert_not_reached ("unrecognized tp_ value in follow_types");
+      }
+  return follow_type;
+}
diff --git a/gdb/type-stack.h b/gdb/type-stack.h
new file mode 100644 (file)
index 0000000..672ad05
--- /dev/null
@@ -0,0 +1,203 @@
+/* Type stack for GDB parser.
+
+   Copyright (C) 1986-2019 Free Software Foundation, Inc.
+
+   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 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef TYPE_STACK_H
+#define TYPE_STACK_H
+
+#include <vector>
+
+struct type;
+struct expr_builder;
+
+/* For parsing of complicated types.
+   An array should be preceded in the list by the size of the array.  */
+enum type_pieces
+  {
+    tp_end = -1, 
+    tp_pointer, 
+    tp_reference, 
+    tp_rvalue_reference,
+    tp_array, 
+    tp_function,
+    tp_function_with_arguments,
+    tp_const, 
+    tp_volatile, 
+    tp_space_identifier,
+    tp_type_stack,
+    tp_kind
+  };
+
+/* The stack can contain either an enum type_pieces or an int.  */
+union type_stack_elt
+  {
+    enum type_pieces piece;
+    int int_val;
+    struct type_stack *stack_val;
+    std::vector<struct type *> *typelist_val;
+  };
+
+/* The type stack is an instance of this structure.  */
+
+struct type_stack
+{
+public:
+
+  type_stack () = default;
+
+  DISABLE_COPY_AND_ASSIGN (type_stack);
+
+  type_stack *create ()
+  {
+    type_stack *result = new type_stack ();
+    result->m_elements = std::move (m_elements);
+    return result;
+  }
+
+  /* Insert a new type, TP, at the bottom of the type stack.  If TP is
+     tp_pointer, tp_reference or tp_rvalue_reference, it is inserted at the
+     bottom.  If TP is a qualifier, it is inserted at slot 1 (just above a
+     previous tp_pointer) if there is anything on the stack, or simply pushed
+     if the stack is empty.  Other values for TP are invalid.  */
+
+  void insert (enum type_pieces tp);
+
+  void push (enum type_pieces tp)
+  {
+    type_stack_elt elt;
+    elt.piece = tp;
+    m_elements.push_back (elt);
+  }
+
+  void push (int n)
+  {
+    type_stack_elt elt;
+    elt.int_val = n;
+    m_elements.push_back (elt);
+  }
+
+  /* Push the type stack STACK as an element on this type stack.  */
+
+  void push (struct type_stack *stack)
+  {
+    type_stack_elt elt;
+    elt.stack_val = stack;
+    m_elements.push_back (elt);
+    push (tp_type_stack);
+  }
+
+  /* Push a function type with arguments onto the global type stack.
+     LIST holds the argument types.  If the final item in LIST is NULL,
+     then the function will be varargs.  */
+
+  void push (std::vector<struct type *> *list)
+  {
+    type_stack_elt elt;
+    elt.typelist_val = list;
+    m_elements.push_back (elt);
+    push (tp_function_with_arguments);
+  }
+
+  enum type_pieces pop ()
+  {
+    if (m_elements.empty ())
+      return tp_end;
+    type_stack_elt elt = m_elements.back ();
+    m_elements.pop_back ();
+    return elt.piece;
+  }
+
+  int pop_int ()
+  {
+    if (m_elements.empty ())
+      {
+       /* "Can't happen".  */
+       return 0;
+      }
+    type_stack_elt elt = m_elements.back ();
+    m_elements.pop_back ();
+    return elt.int_val;
+  }
+
+  std::vector<struct type *> *pop_typelist ()
+  {
+    gdb_assert (!m_elements.empty ());
+    type_stack_elt elt = m_elements.back ();
+    m_elements.pop_back ();
+    return elt.typelist_val;
+  }
+
+  /* Pop a type_stack element.  */
+
+  struct type_stack *pop_type_stack ()
+  {
+    gdb_assert (!m_elements.empty ());
+    type_stack_elt elt = m_elements.back ();
+    m_elements.pop_back ();
+    return elt.stack_val;
+  }
+
+  /* Insert a tp_space_identifier and the corresponding address space
+     value into the stack.  STRING is the name of an address space, as
+     recognized by address_space_name_to_int.  If the stack is empty,
+     the new elements are simply pushed.  If the stack is not empty,
+     this function assumes that the first item on the stack is a
+     tp_pointer, and the new values are inserted above the first
+     item.  */
+
+  void insert (struct expr_builder *pstate, char *string);
+
+  /* Append the elements of the type stack FROM to the type stack
+     THIS.  Always returns THIS.  */
+
+  struct type_stack *append (struct type_stack *from)
+  {
+    m_elements.insert (m_elements.end (), from->m_elements.begin (),
+                      from->m_elements.end ());
+    return this;
+  }
+
+  /* Pop the type stack and return a type_instance_flags that
+     corresponds the const/volatile qualifiers on the stack.  This is
+     called by the C++ parser when parsing methods types, and as such no
+     other kind of type in the type stack is expected.  */
+
+  type_instance_flags follow_type_instance_flags ();
+
+  /* Pop the type stack and return the type which corresponds to
+     FOLLOW_TYPE as modified by all the stuff on the stack.  */
+  struct type *follow_types (struct type *follow_type);
+
+private:
+
+  /* A helper function for insert_type and insert_type_address_space.
+     This does work of expanding the type stack and inserting the new
+     element, ELEMENT, into the stack at location SLOT.  */
+
+  void insert_into (int slot, union type_stack_elt element)
+  {
+    gdb_assert (slot <= m_elements.size ());
+    m_elements.insert (m_elements.begin () + slot, element);
+  }
+
+
+  /* Elements on the stack.  */
+  std::vector<union type_stack_elt> m_elements;
+};
+
+#endif /* TYPE_STACK_H */