aboutsummaryrefslogtreecommitdiff
path: root/gdb
diff options
context:
space:
mode:
authorTom Tromey <tromey@redhat.com>2012-07-06 14:44:22 +0000
committerTom Tromey <tromey@redhat.com>2012-07-06 14:44:22 +0000
commitfcde5961ebacc85a85adcf858c751dc9c11f8d58 (patch)
treeaa3300bf1a72493745909459933cefb0256899f8 /gdb
parent1a7d0ce4eb4d724a3853500b45b379e746d7077a (diff)
downloadgdb-fcde5961ebacc85a85adcf858c751dc9c11f8d58.zip
gdb-fcde5961ebacc85a85adcf858c751dc9c11f8d58.tar.gz
gdb-fcde5961ebacc85a85adcf858c751dc9c11f8d58.tar.bz2
* 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. testsuite * gdb.base/whatis.exp: Add tests.
Diffstat (limited to 'gdb')
-rw-r--r--gdb/ChangeLog18
-rw-r--r--gdb/c-exp.y38
-rw-r--r--gdb/parse.c107
-rw-r--r--gdb/parser-defs.h13
-rw-r--r--gdb/testsuite/ChangeLog4
-rw-r--r--gdb/testsuite/gdb.base/whatis.exp12
6 files changed, 177 insertions, 15 deletions
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 <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):
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 <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
@@ -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 <tromey@redhat.com>
+
+ * gdb.base/whatis.exp: Add tests.
+
2012-07-04 Jan Kratochvil <jan.kratochvil@redhat.com>
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"