* c-exp.y (%union) <type_stack>: New field.
authorTom Tromey <tromey@redhat.com>
Fri, 6 Jul 2012 14:44:22 +0000 (14:44 +0000)
committerTom Tromey <tromey@redhat.com>
Fri, 6 Jul 2012 14:44:22 +0000 (14:44 +0000)
(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.

gdb/ChangeLog
gdb/c-exp.y
gdb/parse.c
gdb/parser-defs.h
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.base/whatis.exp

index b69c56a..073c93a 100644 (file)
@@ -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.
index f86f76f..5ea5704 100644 (file)
@@ -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
index 83f7fec..b1ad832 100644 (file)
@@ -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,
index de283d0..0649189 100644 (file)
@@ -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);
index 5c67be8..ed2fcf1 100644 (file)
@@ -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
index dda3a02..71f2e79 100644 (file)
@@ -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"