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:
Tom Tromey
2019-03-31 13:43:54 -06:00
parent 2a61252965
commit dac43e327d
9 changed files with 521 additions and 444 deletions

View File

@ -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)

View 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 \

View 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

View 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;

View 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 ();
}

View File

@ -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

View 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,

209
gdb/type-stack.c Normal file
View 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
View 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 */