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> 2019-04-04 Tom Tromey <tom@tromey.com>
* rust-exp.y (rust_parser::lex_identifier, rustyylex) * rust-exp.y (rust_parser::lex_identifier, rustyylex)

View File

@ -1131,6 +1131,7 @@ COMMON_SFILES = \
trad-frame.c \ trad-frame.c \
tramp-frame.c \ tramp-frame.c \
target-float.c \ target-float.c \
type-stack.c \
typeprint.c \ typeprint.c \
ui-file.c \ ui-file.c \
ui-out.c \ ui-out.c \
@ -1406,6 +1407,7 @@ HFILES_NO_SRCDIR = \
trad-frame.h \ trad-frame.h \
target-float.h \ target-float.h \
tramp-frame.h \ tramp-frame.h \
type-stack.h \
typeprint.h \ typeprint.h \
ui-file.h \ ui-file.h \
ui-out.h \ ui-out.h \

View File

@ -53,6 +53,7 @@
#include "objc-lang.h" #include "objc-lang.h"
#include "typeprint.h" #include "typeprint.h"
#include "cp-abi.h" #include "cp-abi.h"
#include "type-stack.h"
#define parse_type(ps) builtin_type (ps->gdbarch ()) #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 token, we simply keep it all and delete it after parsing has
completed. */ completed. */
auto_obstack expansion_obstack; auto_obstack expansion_obstack;
/* The type stack. */
struct type_stack type_stack;
}; };
/* This is set and cleared in c_parse. */ /* 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 /* Save the const/volatile qualifiers as
recorded by the const_or_volatile recorded by the const_or_volatile
production's actions. */ production's actions. */
write_exp_elt_longcst (pstate, write_exp_elt_longcst
follow_type_instance_flags ()); (pstate,
(cpstate->type_stack
.follow_type_instance_flags ()));
write_exp_elt_longcst (pstate, len); write_exp_elt_longcst (pstate, len);
for (type *type_elt : *type_list) for (type *type_elt : *type_list)
write_exp_elt_type (pstate, type_elt); 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 function_method_void: exp '(' ')' const_or_volatile
{ write_exp_elt_opcode (pstate, TYPE_INSTANCE); { write_exp_elt_opcode (pstate, TYPE_INSTANCE);
/* See above. */ /* See above. */
write_exp_elt_longcst (pstate, write_exp_elt_longcst
follow_type_instance_flags ()); (pstate,
cpstate->type_stack.follow_type_instance_flags ());
write_exp_elt_longcst (pstate, 0); write_exp_elt_longcst (pstate, 0);
write_exp_elt_longcst (pstate, 0); write_exp_elt_longcst (pstate, 0);
write_exp_elt_opcode (pstate, TYPE_INSTANCE); write_exp_elt_opcode (pstate, TYPE_INSTANCE);
@ -1158,7 +1165,9 @@ variable: name_not_typename
; ;
space_identifier : '@' NAME 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 const_or_volatile: const_or_volatile_noopt
@ -1179,30 +1188,30 @@ const_or_volatile_or_space_identifier:
ptr_operator: ptr_operator:
ptr_operator '*' ptr_operator '*'
{ insert_type (tp_pointer); } { cpstate->type_stack.insert (tp_pointer); }
const_or_volatile_or_space_identifier const_or_volatile_or_space_identifier
| '*' | '*'
{ insert_type (tp_pointer); } { cpstate->type_stack.insert (tp_pointer); }
const_or_volatile_or_space_identifier const_or_volatile_or_space_identifier
| '&' | '&'
{ insert_type (tp_reference); } { cpstate->type_stack.insert (tp_reference); }
| '&' ptr_operator | '&' ptr_operator
{ insert_type (tp_reference); } { cpstate->type_stack.insert (tp_reference); }
| ANDAND | ANDAND
{ insert_type (tp_rvalue_reference); } { cpstate->type_stack.insert (tp_rvalue_reference); }
| ANDAND ptr_operator | ANDAND ptr_operator
{ insert_type (tp_rvalue_reference); } { cpstate->type_stack.insert (tp_rvalue_reference); }
; ;
ptr_operator_ts: ptr_operator ptr_operator_ts: ptr_operator
{ {
$$ = get_type_stack (); $$ = cpstate->type_stack.create ();
cpstate->type_stacks.emplace_back ($$); cpstate->type_stacks.emplace_back ($$);
} }
; ;
abs_decl: ptr_operator_ts direct_abs_decl abs_decl: ptr_operator_ts direct_abs_decl
{ $$ = append_type_stack ($2, $1); } { $$ = $2->append ($1); }
| ptr_operator_ts | ptr_operator_ts
| direct_abs_decl | direct_abs_decl
; ;
@ -1211,31 +1220,31 @@ direct_abs_decl: '(' abs_decl ')'
{ $$ = $2; } { $$ = $2; }
| direct_abs_decl array_mod | direct_abs_decl array_mod
{ {
push_type_stack ($1); cpstate->type_stack.push ($1);
push_type_int ($2); cpstate->type_stack.push ($2);
push_type (tp_array); cpstate->type_stack.push (tp_array);
$$ = get_type_stack (); $$ = cpstate->type_stack.create ();
cpstate->type_stacks.emplace_back ($$); cpstate->type_stacks.emplace_back ($$);
} }
| array_mod | array_mod
{ {
push_type_int ($1); cpstate->type_stack.push ($1);
push_type (tp_array); cpstate->type_stack.push (tp_array);
$$ = get_type_stack (); $$ = cpstate->type_stack.create ();
cpstate->type_stacks.emplace_back ($$); cpstate->type_stacks.emplace_back ($$);
} }
| direct_abs_decl func_mod | direct_abs_decl func_mod
{ {
push_type_stack ($1); cpstate->type_stack.push ($1);
push_typelist ($2); cpstate->type_stack.push ($2);
$$ = get_type_stack (); $$ = cpstate->type_stack.create ();
cpstate->type_stacks.emplace_back ($$); cpstate->type_stacks.emplace_back ($$);
} }
| func_mod | func_mod
{ {
push_typelist ($1); cpstate->type_stack.push ($1);
$$ = get_type_stack (); $$ = cpstate->type_stack.create ();
cpstate->type_stacks.emplace_back ($$); cpstate->type_stacks.emplace_back ($$);
} }
; ;
@ -1489,9 +1498,9 @@ typebase
pstate->expression_context_block); pstate->expression_context_block);
} }
| const_or_volatile_or_space_identifier_noopt typebase | 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 | typebase const_or_volatile_or_space_identifier_noopt
{ $$ = follow_types ($1); } { $$ = cpstate->type_stack.follow_types ($1); }
; ;
type_name: TYPENAME type_name: TYPENAME
@ -1552,13 +1561,13 @@ nonempty_typelist
ptype : typebase ptype : typebase
| ptype abs_decl | ptype abs_decl
{ {
push_type_stack ($2); cpstate->type_stack.push ($2);
$$ = follow_types ($1); $$ = cpstate->type_stack.follow_types ($1);
} }
; ;
conversion_type_id: typebase conversion_declarator conversion_type_id: typebase conversion_declarator
{ $$ = follow_types ($1); } { $$ = cpstate->type_stack.follow_types ($1); }
; ;
conversion_declarator: /* Nothing. */ conversion_declarator: /* Nothing. */
@ -1570,13 +1579,13 @@ const_and_volatile: CONST_KEYWORD VOLATILE_KEYWORD
; ;
const_or_volatile_noopt: const_and_volatile const_or_volatile_noopt: const_and_volatile
{ insert_type (tp_const); { cpstate->type_stack.insert (tp_const);
insert_type (tp_volatile); cpstate->type_stack.insert (tp_volatile);
} }
| CONST_KEYWORD | CONST_KEYWORD
{ insert_type (tp_const); } { cpstate->type_stack.insert (tp_const); }
| VOLATILE_KEYWORD | VOLATILE_KEYWORD
{ insert_type (tp_volatile); } { cpstate->type_stack.insert (tp_volatile); }
; ;
oper: OPERATOR NEW oper: OPERATOR NEW

View File

@ -51,6 +51,7 @@
#include "objfiles.h" /* For have_full_symbols and have_partial_symbols */ #include "objfiles.h" /* For have_full_symbols and have_partial_symbols */
#include "charset.h" #include "charset.h"
#include "block.h" #include "block.h"
#include "type-stack.h"
#define parse_type(ps) builtin_type (ps->gdbarch ()) #define parse_type(ps) builtin_type (ps->gdbarch ())
#define parse_d_type(ps) builtin_d_type (ps->gdbarch ()) #define parse_d_type(ps) builtin_d_type (ps->gdbarch ())
@ -65,6 +66,9 @@
static struct parser_state *pstate = NULL; static struct parser_state *pstate = NULL;
/* The current type stack. */
static struct type_stack *type_stack;
int yyparse (void); int yyparse (void);
static int yylex (void); static int yylex (void);
@ -606,7 +610,7 @@ TypeExp:
write_exp_elt_type (pstate, $1); write_exp_elt_type (pstate, $1);
write_exp_elt_opcode (pstate, OP_TYPE); } write_exp_elt_opcode (pstate, OP_TYPE); }
| BasicType BasicType2 | BasicType BasicType2
{ $$ = follow_types ($1); { $$ = type_stack->follow_types ($1);
write_exp_elt_opcode (pstate, OP_TYPE); write_exp_elt_opcode (pstate, OP_TYPE);
write_exp_elt_type (pstate, $$); write_exp_elt_type (pstate, $$);
write_exp_elt_opcode (pstate, OP_TYPE); write_exp_elt_opcode (pstate, OP_TYPE);
@ -615,15 +619,15 @@ TypeExp:
BasicType2: BasicType2:
'*' '*'
{ push_type (tp_pointer); } { type_stack->push (tp_pointer); }
| '*' BasicType2 | '*' BasicType2
{ push_type (tp_pointer); } { type_stack->push (tp_pointer); }
| '[' INTEGER_LITERAL ']' | '[' INTEGER_LITERAL ']'
{ push_type_int ($2.val); { type_stack->push ($2.val);
push_type (tp_array); } type_stack->push (tp_array); }
| '[' INTEGER_LITERAL ']' BasicType2 | '[' INTEGER_LITERAL ']' BasicType2
{ push_type_int ($2.val); { type_stack->push ($2.val);
push_type (tp_array); } type_stack->push (tp_array); }
; ;
BasicType: BasicType:
@ -1619,6 +1623,10 @@ d_parse (struct parser_state *par_state)
scoped_restore restore_yydebug = make_scoped_restore (&yydebug, scoped_restore restore_yydebug = make_scoped_restore (&yydebug,
parser_debug); parser_debug);
struct type_stack stack;
scoped_restore restore_type_stack = make_scoped_restore (&type_stack,
&stack);
/* Initialize some state used by the lexer. */ /* Initialize some state used by the lexer. */
last_was_structop = 0; last_was_structop = 0;
saw_name_at_eof = 0; saw_name_at_eof = 0;

View File

@ -54,6 +54,7 @@
#include "block.h" #include "block.h"
#include <ctype.h> #include <ctype.h>
#include <algorithm> #include <algorithm>
#include "type-stack.h"
#define parse_type(ps) builtin_type (ps->gdbarch ()) #define parse_type(ps) builtin_type (ps->gdbarch ())
#define parse_f_type(ps) builtin_f_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. */ /* Depth of parentheses. */
static int paren_depth; static int paren_depth;
/* The current type stack. */
static struct type_stack *type_stack;
int yyparse (void); int yyparse (void);
static int yylex (void); static int yylex (void);
@ -515,7 +519,7 @@ ptype : typebase
struct type *range_type; struct type *range_type;
while (!done) while (!done)
switch (pop_type ()) switch (type_stack->pop ())
{ {
case tp_end: case tp_end:
done = 1; done = 1;
@ -527,7 +531,7 @@ ptype : typebase
follow_type = lookup_lvalue_reference_type (follow_type); follow_type = lookup_lvalue_reference_type (follow_type);
break; break;
case tp_array: case tp_array:
array_size = pop_type_int (); array_size = type_stack->pop_int ();
if (array_size != -1) if (array_size != -1)
{ {
range_type = range_type =
@ -547,7 +551,7 @@ ptype : typebase
break; break;
case tp_kind: case tp_kind:
{ {
int kind_val = pop_type_int (); int kind_val = type_stack->pop_int ();
follow_type follow_type
= convert_to_kind_type (follow_type, kind_val); = convert_to_kind_type (follow_type, kind_val);
} }
@ -558,13 +562,13 @@ ptype : typebase
; ;
abs_decl: '*' abs_decl: '*'
{ push_type (tp_pointer); $$ = 0; } { type_stack->push (tp_pointer); $$ = 0; }
| '*' abs_decl | '*' 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 | '&' abs_decl
{ push_type (tp_reference); $$ = $2; } { type_stack->push (tp_reference); $$ = $2; }
| direct_abs_decl | direct_abs_decl
; ;
@ -575,9 +579,9 @@ direct_abs_decl: '(' abs_decl ')'
| '*' INT | '*' INT
{ push_kind_type ($2.val, $2.type); } { push_kind_type ($2.val, $2.type); }
| direct_abs_decl func_mod | direct_abs_decl func_mod
{ push_type (tp_function); } { type_stack->push (tp_function); }
| func_mod | func_mod
{ push_type (tp_function); } { type_stack->push (tp_function); }
; ;
func_mod: '(' ')' func_mod: '(' ')'
@ -821,8 +825,8 @@ push_kind_type (LONGEST val, struct type *type)
ival = static_cast <int> (val); ival = static_cast <int> (val);
} }
push_type_int (ival); type_stack->push (ival);
push_type (tp_kind); type_stack->push (tp_kind);
} }
/* Called when a type has a '(kind=N)' modifier after it, for example /* 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; pstate = par_state;
paren_depth = 0; paren_depth = 0;
struct type_stack stack;
scoped_restore restore_type_stack = make_scoped_restore (&type_stack,
&stack);
return yyparse (); 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). */ /* Global variables declared in parser-defs.h (and commented there). */
innermost_block_tracker innermost_block; innermost_block_tracker innermost_block;
static struct type_stack type_stack;
static unsigned int expressiondebug = 0; 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; const struct language_defn *lang = NULL;
int subexp; int subexp;
type_stack.elements.clear ();
innermost_block.reset (tracker_types); innermost_block.reset (tracker_types);
if (*stringptr == 0 || **stringptr == 0) 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)); 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 /* This function avoids direct calls to fprintf
in the parser generated debug code. */ in the parser generated debug code. */
void void

View File

@ -299,40 +299,6 @@ struct objc_class_str
int theclass; 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) /* Reverse an expression from suffix form (in which it is constructed)
to prefix form (in which we can conveniently print or execute it). to prefix form (in which we can conveniently print or execute it).
Ordinarily this always returns -1. However, if LAST_STRUCT 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 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 (struct expression *, struct ui_file *, int);
extern int dump_subexp_body_standard (struct expression *, 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 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 void null_post_parser (expression_up *, int, int);
extern bool parse_float (const char *p, int len, 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 */