From dac43e327d002107f6bc9481749de039f410df73 Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Sun, 31 Mar 2019 13:43:54 -0600 Subject: [PATCH] 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 * 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) : New member. Update rules. * Makefile.in (COMMON_SFILES): Add type-stack.c. (HFILES_NO_SRCDIR): Add type-stack.h. --- gdb/ChangeLog | 30 +++++ gdb/Makefile.in | 2 + gdb/c-exp.y | 77 ++++++----- gdb/d-exp.y | 22 ++- gdb/f-exp.y | 30 +++-- gdb/parse.c | 333 ---------------------------------------------- gdb/parser-defs.h | 59 -------- gdb/type-stack.c | 209 +++++++++++++++++++++++++++++ gdb/type-stack.h | 203 ++++++++++++++++++++++++++++ 9 files changed, 521 insertions(+), 444 deletions(-) create mode 100644 gdb/type-stack.c create mode 100644 gdb/type-stack.h diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 7d415d29e10..238d6782155 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,33 @@ +2019-04-04 Tom Tromey + + * 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) : New member. + Update rules. + * Makefile.in (COMMON_SFILES): Add type-stack.c. + (HFILES_NO_SRCDIR): Add type-stack.h. + 2019-04-04 Tom Tromey * rust-exp.y (rust_parser::lex_identifier, rustyylex) diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 5614cc3386c..0f495783600 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -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 \ diff --git a/gdb/c-exp.y b/gdb/c-exp.y index 842b492e58a..627ea1f3bae 100644 --- a/gdb/c-exp.y +++ b/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 diff --git a/gdb/d-exp.y b/gdb/d-exp.y index 4d51cfdcb71..ca9aaf85802 100644 --- a/gdb/d-exp.y +++ b/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; diff --git a/gdb/f-exp.y b/gdb/f-exp.y index da4732237d3..403dfa20687 100644 --- a/gdb/f-exp.y +++ b/gdb/f-exp.y @@ -54,6 +54,7 @@ #include "block.h" #include #include +#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 (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 (); } diff --git a/gdb/parse.c b/gdb/parse.c index 7984a324fe0..89a29f0f602 100644 --- a/gdb/parse.c +++ b/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 * -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 *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 *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 diff --git a/gdb/parser-defs.h b/gdb/parser-defs.h index 2c1ea15d05e..edbd3b7b673 100644 --- a/gdb/parser-defs.h +++ b/gdb/parser-defs.h @@ -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 *typelist_val; - }; - -/* The type stack is an instance of this structure. */ - -struct type_stack -{ - /* Elements on the stack. */ - std::vector 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 *typelist); - extern int dump_subexp (struct expression *, struct ui_file *, int); extern int dump_subexp_body_standard (struct expression *, @@ -414,10 +359,6 @@ extern int operator_check_standard (struct expression *exp, int pos, extern const char *op_name_standard (enum exp_opcode); -extern struct type *follow_types (struct type *); - -extern type_instance_flags follow_type_instance_flags (); - extern void null_post_parser (expression_up *, int, int); extern bool parse_float (const char *p, int len, diff --git a/gdb/type-stack.c b/gdb/type-stack.c new file mode 100644 index 00000000000..cb0c147d307 --- /dev/null +++ b/gdb/type-stack.c @@ -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 . */ + +#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 *args = pop_typelist (); + + follow_type + = lookup_function_type_with_arguments (follow_type, + args->size (), + args->data ()); + } + break; + + case tp_type_stack: + { + struct type_stack *stack = pop_type_stack (); + follow_type = stack->follow_types (follow_type); + } + break; + default: + gdb_assert_not_reached ("unrecognized tp_ value in follow_types"); + } + return follow_type; +} diff --git a/gdb/type-stack.h b/gdb/type-stack.h new file mode 100644 index 00000000000..672ad054837 --- /dev/null +++ b/gdb/type-stack.h @@ -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 . */ + +#ifndef TYPE_STACK_H +#define TYPE_STACK_H + +#include + +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 *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 *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 *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 m_elements; +}; + +#endif /* TYPE_STACK_H */ -- 2.30.2