+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)
trad-frame.c \
tramp-frame.c \
target-float.c \
+ type-stack.c \
typeprint.c \
ui-file.c \
ui-out.c \
trad-frame.h \
target-float.h \
tramp-frame.h \
+ type-stack.h \
typeprint.h \
ui-file.h \
ui-out.h \
#include "objc-lang.h"
#include "typeprint.h"
#include "cp-abi.h"
+#include "type-stack.h"
#define parse_type(ps) builtin_type (ps->gdbarch ())
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. */
/* 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);
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);
;
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
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
;
{ $$ = $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 ($$);
}
;
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
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. */
;
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
#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 ())
static struct parser_state *pstate = NULL;
+/* The current type stack. */
+static struct type_stack *type_stack;
+
int yyparse (void);
static int yylex (void);
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);
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:
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;
#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 ())
/* Depth of parentheses. */
static int paren_depth;
+/* The current type stack. */
+static struct type_stack *type_stack;
+
int yyparse (void);
static int yylex (void);
struct type *range_type;
while (!done)
- switch (pop_type ())
+ switch (type_stack->pop ())
{
case tp_end:
done = 1;
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 =
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);
}
;
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
;
| '*' 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: '(' ')'
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
pstate = par_state;
paren_depth = 0;
+ struct type_stack stack;
+ scoped_restore restore_type_stack = make_scoped_restore (&type_stack,
+ &stack);
+
return yyparse ();
}
\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;
const struct language_defn *lang = NULL;
int subexp;
- type_stack.elements.clear ();
innermost_block.reset (tracker_types);
if (*stringptr == 0 || **stringptr == 0)
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
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
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 *,
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,
--- /dev/null
+/* 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;
+}
--- /dev/null
+/* 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 */