From: Tom Tromey Date: Fri, 6 Jul 2012 14:44:22 +0000 (+0000) Subject: * c-exp.y (%union) : New field. X-Git-Tag: gdb_7_5-2012-07-18-branchpoint~80 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=fcde5961ebacc85a85adcf858c751dc9c11f8d58;p=external%2Fbinutils.git * c-exp.y (%union) : New field. (abs_decl, direct_abs_decl): Use type. Update. (ptr_operator_ts): New production. (ptype): Update. * parse.c (type_stack_reserve): New function. (check_type_stack_depth): Use it. (pop_type_stack, append_type_stack, push_type_stack) (get_type_stack, type_stack_cleanup): New functions. (follow_types): Handle tp_type_stack. (_initialize_parse): Simplify initialization. * parser-defs.h (enum type_pieces) : New constant. (union type_stack_elt) : New field. (get_type_stack, append_type_stack, push_type_stack) (type_stack_cleanup): Declare. testsuite * gdb.base/whatis.exp: Add tests. --- diff --git a/gdb/ChangeLog b/gdb/ChangeLog index b69c56a..073c93a 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,23 @@ 2012-07-06 Tom Tromey + * c-exp.y (%union) : New field. + (abs_decl, direct_abs_decl): Use type. Update. + (ptr_operator_ts): New production. + (ptype): Update. + * parse.c (type_stack_reserve): New function. + (check_type_stack_depth): Use it. + (pop_type_stack, append_type_stack, push_type_stack) + (get_type_stack, type_stack_cleanup): New functions. + (follow_types): Handle tp_type_stack. + (_initialize_parse): Simplify initialization. + * parser-defs.h (enum type_pieces) : New + constant. + (union type_stack_elt) : New field. + (get_type_stack, append_type_stack, push_type_stack) + (type_stack_cleanup): Declare. + +2012-07-06 Tom Tromey + * parser-defs.h (type_stack, type_stack_size, type_stack_depth): Remove. (struct type_stack): New. diff --git a/gdb/c-exp.y b/gdb/c-exp.y index f86f76f..5ea5704 100644 --- a/gdb/c-exp.y +++ b/gdb/c-exp.y @@ -157,6 +157,8 @@ void yyerror (char *); struct stoken_vector svec; struct type **tvec; int *ivec; + + struct type_stack *type_stack; } %{ @@ -176,6 +178,8 @@ static struct stoken operator_stoken (const char *); %type array_mod %type conversion_type_id +%type ptr_operator_ts abs_decl direct_abs_decl + %token INT %token FLOAT %token DECFLOAT @@ -963,27 +967,48 @@ ptr_operator: { insert_type (tp_reference); } ; -abs_decl: ptr_operator direct_abs_decl - | ptr_operator +ptr_operator_ts: ptr_operator + { + $$ = get_type_stack (); + /* This cleanup is eventually run by + c_parse. */ + make_cleanup (type_stack_cleanup, $$); + } + ; + +abs_decl: ptr_operator_ts direct_abs_decl + { $$ = append_type_stack ($2, $1); } + | ptr_operator_ts | direct_abs_decl ; 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 (); } | array_mod { push_type_int ($1); push_type (tp_array); + $$ = get_type_stack (); } | direct_abs_decl func_mod - { push_type (tp_function); } + { + push_type_stack ($1); + push_type (tp_function); + $$ = get_type_stack (); + } | func_mod - { push_type (tp_function); } + { + push_type (tp_function); + $$ = get_type_stack (); + } ; array_mod: '[' ']' @@ -1206,7 +1231,10 @@ nonempty_typelist ptype : typebase | ptype abs_decl - { $$ = follow_types ($1); } + { + push_type_stack ($2); + $$ = follow_types ($1); + } ; conversion_type_id: typebase conversion_declarator diff --git a/gdb/parse.c b/gdb/parse.c index 83f7fec..b1ad832 100644 --- a/gdb/parse.c +++ b/gdb/parse.c @@ -1358,18 +1358,29 @@ parse_c_float (struct gdbarch *gdbarch, const char *p, int len, /* Stuff for maintaining a stack of types. Currently just used by C, but probably useful for any language which declares its types "backwards". */ +/* Ensure that there are HOWMUCH open slots on the type stack STACK. */ + static void -check_type_stack_depth (void) +type_stack_reserve (struct type_stack *stack, int howmuch) { - if (type_stack.depth == type_stack.size) + if (stack->depth + howmuch >= stack->size) { - type_stack.size *= 2; - type_stack.elements - = xrealloc (type_stack.elements, - type_stack.size * sizeof (union type_stack_elt)); + stack->size *= 2; + if (stack->size < howmuch) + stack->size = howmuch; + stack->elements = xrealloc (stack->elements, + stack->size * sizeof (union type_stack_elt)); } } +/* Ensure that there is a single open slot in the global type stack. */ + +static void +check_type_stack_depth (void) +{ + type_stack_reserve (&type_stack, 1); +} + /* 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. */ @@ -1472,6 +1483,68 @@ pop_type_int (void) return 0; } +/* Pop a type_stack element from the global type stack. */ + +static struct type_stack * +pop_type_stack (void) +{ + gdb_assert (type_stack.depth); + return type_stack.elements[--type_stack.depth].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) +{ + type_stack_reserve (to, from->depth); + + memcpy (&to->elements[to->depth], &from->elements[0], + from->depth * sizeof (union type_stack_elt)); + to->depth += from->depth; + + return to; +} + +/* Push the type stack STACK as an element on the global type stack. */ + +void +push_type_stack (struct type_stack *stack) +{ + check_type_stack_depth (); + type_stack.elements[type_stack.depth++].stack_val = stack; + 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 type_stack_cleanup. */ + +struct type_stack * +get_type_stack (void) +{ + struct type_stack *result = XNEW (struct type_stack); + + *result = type_stack; + type_stack.depth = 0; + type_stack.size = 0; + type_stack.elements = NULL; + + return result; +} + +/* A cleanup function that destroys a single type stack. */ + +void +type_stack_cleanup (void *arg) +{ + struct type_stack *stack = arg; + + xfree (stack->elements); + xfree (stack); +} + /* Pop the type stack and return the type which corresponds to FOLLOW_TYPE as modified by all the stuff on the stack. */ struct type * @@ -1558,6 +1631,23 @@ follow_types (struct type *follow_type) done with it. */ follow_type = lookup_function_type (follow_type); 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.depth == 0); + + type_stack = save; + } + break; + default: + gdb_assert_not_reached ("unrecognized tp_ value in follow_types"); } return follow_type; } @@ -1725,10 +1815,9 @@ exp_uses_objfile (struct expression *exp, struct objfile *objfile) void _initialize_parse (void) { - type_stack.size = 80; + type_stack.size = 0; type_stack.depth = 0; - type_stack.elements = xmalloc (type_stack.size - * sizeof (union type_stack_elt)); + type_stack.elements = NULL; add_setshow_zinteger_cmd ("expression", class_maintenance, &expressiondebug, diff --git a/gdb/parser-defs.h b/gdb/parser-defs.h index de283d0..0649189 100644 --- a/gdb/parser-defs.h +++ b/gdb/parser-defs.h @@ -119,13 +119,15 @@ enum type_pieces tp_function, tp_const, tp_volatile, - tp_space_identifier + tp_space_identifier, + tp_type_stack }; /* 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; }; /* The type stack is an instance of this structure. */ @@ -214,6 +216,15 @@ 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 type_stack_cleanup (void *arg); + extern int length_of_subexp (struct expression *, int); extern int dump_subexp (struct expression *, struct ui_file *, int); diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 5c67be8..ed2fcf1 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2012-07-06 Tom Tromey + + * gdb.base/whatis.exp: Add tests. + 2012-07-04 Jan Kratochvil PR 12649 diff --git a/gdb/testsuite/gdb.base/whatis.exp b/gdb/testsuite/gdb.base/whatis.exp index dda3a02..71f2e79 100644 --- a/gdb/testsuite/gdb.base/whatis.exp +++ b/gdb/testsuite/gdb.base/whatis.exp @@ -479,3 +479,15 @@ gdb_test "whatis void (** const)()" \ gdb_test "whatis void (* const *)()" \ "type = void \\(\\* const \\*\\)\\(\\)" \ "whatis applied to pointer to const pointer to function" + +gdb_test "whatis int *(*)()" \ + "type = int \\*\\(\\*\\)\\(\\)" \ + "whatis applied to pointer to function returning pointer to int" + +gdb_test "whatis int *(**)()" \ + "type = int \\*\\(\\*\\*\\)\\(\\)" \ + "whatis applied to pointer to pointer to function returning pointer to int" + +gdb_test "whatis char (*(*)())\[23\]" \ + "type = char \\(\\*\\(\\*\\)\\(\\)\\)\\\[23\\\]" \ + "whatis applied to pointer to function returning pointer to array"