mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-20 09:58:19 +08:00
Move type stack handling to a new class
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.
This commit is contained in:
@ -1,3 +1,33 @@
|
||||
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)
|
||||
|
@ -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 \
|
||||
|
77
gdb/c-exp.y
77
gdb/c-exp.y
@ -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
|
||||
|
22
gdb/d-exp.y
22
gdb/d-exp.y
@ -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;
|
||||
|
30
gdb/f-exp.y
30
gdb/f-exp.y
@ -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 ();
|
||||
}
|
||||
|
||||
|
333
gdb/parse.c
333
gdb/parse.c
@ -67,7 +67,6 @@ const struct exp_descriptor exp_descriptor_standard =
|
||||
|
||||
/* Global variables declared in parser-defs.h (and commented there). */
|
||||
innermost_block_tracker innermost_block;
|
||||
static struct type_stack type_stack;
|
||||
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* This function avoids direct calls to fprintf
|
||||
in the parser generated debug code. */
|
||||
void
|
||||
|
@ -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,
|
||||
|
209
gdb/type-stack.c
Normal file
209
gdb/type-stack.c
Normal file
@ -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;
|
||||
}
|
203
gdb/type-stack.h
Normal file
203
gdb/type-stack.h
Normal file
@ -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 */
|
Reference in New Issue
Block a user