(abs_decl, direct_abs_decl): Use <type_stack> 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) <tp_type_stack>: New
constant.
(union type_stack_elt) <stack_val>: New field.
(get_type_stack, append_type_stack, push_type_stack)
(type_stack_cleanup): Declare.
testsuite
* gdb.base/whatis.exp: Add tests.
+2012-07-06 Tom Tromey <tromey@redhat.com>
+
+ * c-exp.y (%union) <type_stack>: New field.
+ (abs_decl, direct_abs_decl): Use <type_stack> 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) <tp_type_stack>: New
+ constant.
+ (union type_stack_elt) <stack_val>: New field.
+ (get_type_stack, append_type_stack, push_type_stack)
+ (type_stack_cleanup): Declare.
+
2012-07-06 Tom Tromey <tromey@redhat.com>
* parser-defs.h (type_stack, type_stack_size, type_stack_depth):
struct stoken_vector svec;
struct type **tvec;
int *ivec;
+
+ struct type_stack *type_stack;
}
%{
%type <lval> array_mod
%type <tval> conversion_type_id
+%type <type_stack> ptr_operator_ts abs_decl direct_abs_decl
+
%token <typed_val_int> INT
%token <typed_val_float> FLOAT
%token <typed_val_decfloat> DECFLOAT
{ 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: '[' ']'
ptype : typebase
| ptype abs_decl
- { $$ = follow_types ($1); }
+ {
+ push_type_stack ($2);
+ $$ = follow_types ($1);
+ }
;
conversion_type_id: typebase conversion_declarator
/* 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. */
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 *
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;
}
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,
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. */
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);
+2012-07-06 Tom Tromey <tromey@redhat.com>
+
+ * gdb.base/whatis.exp: Add tests.
+
2012-07-04 Jan Kratochvil <jan.kratochvil@redhat.com>
PR 12649
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"