PR exp/9514:
authorTom Tromey <tromey@redhat.com>
Tue, 19 Jun 2012 19:49:42 +0000 (19:49 +0000)
committerTom Tromey <tromey@redhat.com>
Tue, 19 Jun 2012 19:49:42 +0000 (19:49 +0000)
* parser-defs.h (insert_type, insert_type_address_space): Declare.
(push_type_address_space): Remove.
* parse.c (insert_into_type_stack): New function.
(insert_type): Likewise.
(insert_type_address_space): Rename from push_type_address_space.
Insert tp_space_identifier.
* c-exp.y (ptr_operator): New production.
(abs_decl): Use ptr_operator.
(space_identifier): Call insert_type_address_space.
(ptype): Don't use const_or_volatile_or_space_identifier.
(const_or_volatile_noopt): Call insert_type.
(conversion_type_id, conversion_declarator): New productions.
(operator): Use conversion_type_id.
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 37e1272cf5fb484c553f2b29124b50500a0e89d0..36a04bae67740c8b487db77722e1241f898e82bc 100644 (file)
@@ -1,3 +1,20 @@
+2012-06-19  Tom Tromey  <tromey@redhat.com>
+
+       PR exp/9514:
+       * parser-defs.h (insert_type, insert_type_address_space): Declare.
+       (push_type_address_space): Remove.
+       * parse.c (insert_into_type_stack): New function.
+       (insert_type): Likewise.
+       (insert_type_address_space): Rename from push_type_address_space.
+       Insert tp_space_identifier.
+       * c-exp.y (ptr_operator): New production.
+       (abs_decl): Use ptr_operator.
+       (space_identifier): Call insert_type_address_space.
+       (ptype): Don't use const_or_volatile_or_space_identifier.
+       (const_or_volatile_noopt): Call insert_type.
+       (conversion_type_id, conversion_declarator): New productions.
+       (operator): Use conversion_type_id.
+
 2012-06-18  Doug Evans  <dje@google.com>
 
        * symtab.h (minimal_symbol): New member created_by_gdb.
index bf53fbcc384f669a65ddab0cd8f6dfd159fa761e..7afce770e20861f8c85b8253305df6ce6ae21ebc 100644 (file)
@@ -172,9 +172,10 @@ static struct stoken operator_stoken (const char *);
 /* %type <bval> block */
 
 /* Fancy type parsing.  */
-%type <voidval> func_mod direct_abs_decl abs_decl
+%type <voidval> func_mod direct_abs_decl abs_decl ptr_operator
 %type <tval> ptype
 %type <lval> array_mod
+%type <tval> conversion_type_id
 
 %token <typed_val_int> INT
 %token <typed_val_float> FLOAT
@@ -931,9 +932,7 @@ variable:   name_not_typename
        ;
 
 space_identifier : '@' NAME
-               { push_type_address_space (copy_name ($2.stoken));
-                 push_type (tp_space_identifier);
-               }
+               { insert_type_address_space (copy_name ($2.stoken)); }
        ;
 
 const_or_volatile: const_or_volatile_noopt
@@ -952,14 +951,23 @@ const_or_volatile_or_space_identifier:
        |
        ;
 
-abs_decl:      '*'
-                       { push_type (tp_pointer); $$ = 0; }
-       |       '*' abs_decl
-                       { push_type (tp_pointer); $$ = $2; }
+ptr_operator:
+               ptr_operator '*'
+                       { insert_type (tp_pointer); }
+               const_or_volatile_or_space_identifier
+                       { $$ = 0; }
+       |       '*' 
+                       { insert_type (tp_pointer); }
+               const_or_volatile_or_space_identifier
+                       { $$ = 0; }
        |       '&'
-                       { push_type (tp_reference); $$ = 0; }
-       |       '&' abs_decl
-                       { push_type (tp_reference); $$ = $2; }
+                       { insert_type (tp_reference); $$ = 0; }
+       |       '&' ptr_operator
+                       { insert_type (tp_reference); $$ = 0; }
+       ;
+
+abs_decl:      ptr_operator direct_abs_decl
+       |       ptr_operator
        |       direct_abs_decl
        ;
 
@@ -1203,22 +1211,30 @@ nonempty_typelist
        ;
 
 ptype  :       typebase
-       |       ptype const_or_volatile_or_space_identifier abs_decl const_or_volatile_or_space_identifier
+       |       ptype abs_decl
                { $$ = follow_types ($1); }
        ;
 
+conversion_type_id: typebase conversion_declarator
+               { $$ = follow_types ($1); }
+       ;
+
+conversion_declarator:  /* Nothing.  */
+       | ptr_operator conversion_declarator
+       ;
+
 const_and_volatile:    CONST_KEYWORD VOLATILE_KEYWORD
        |               VOLATILE_KEYWORD CONST_KEYWORD
        ;
 
 const_or_volatile_noopt:       const_and_volatile 
-                       { push_type (tp_const);
-                         push_type (tp_volatile); 
+                       { insert_type (tp_const);
+                         insert_type (tp_volatile); 
                        }
        |               CONST_KEYWORD
-                       { push_type (tp_const); }
+                       { insert_type (tp_const); }
        |               VOLATILE_KEYWORD
-                       { push_type (tp_volatile); }
+                       { insert_type (tp_volatile); }
        ;
 
 operator:      OPERATOR NEW
@@ -1325,7 +1341,7 @@ operator: OPERATOR NEW
                        { $$ = operator_stoken ("()"); }
        |       OPERATOR '[' ']'
                        { $$ = operator_stoken ("[]"); }
-       |       OPERATOR ptype
+       |       OPERATOR conversion_type_id
                        { char *name;
                          long length;
                          struct ui_file *buf = mem_fileopen ();
index f54c6f21e79a4992b417c93d5ff8954f3a044fc2..0d0467d9ce23cb7882b2de80b38e29eb873cf774 100644 (file)
@@ -1367,6 +1367,49 @@ check_type_stack_depth (void)
     }
 }
 
+/* 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)
+{
+  check_type_stack_depth ();
+
+  if (slot < type_stack_depth)
+    memmove (&type_stack[slot + 1], &type_stack[slot],
+            (type_stack_depth - slot) * sizeof (union type_stack_elt));
+  type_stack[slot] = element;
+  ++type_stack_depth;
+}
+
+/* Insert a new type, TP, at the bottom of the type stack.  If TP is
+   tp_pointer or tp_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_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_depth && (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)
 {
@@ -1381,10 +1424,32 @@ push_type_int (int n)
   type_stack[type_stack_depth++].int_val = n;
 }
 
+/* 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
-push_type_address_space (char *string)
+insert_type_address_space (char *string)
 {
-  push_type_int (address_space_name_to_int (parse_gdbarch, 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_depth)
+    slot = 1;
+  else
+    slot = 0;
+
+  element.piece = tp_space_identifier;
+  insert_into_type_stack (slot, element);
+  element.int_val = address_space_name_to_int (parse_gdbarch, string);
+  insert_into_type_stack (slot, element);
 }
 
 enum type_pieces
index 72b9e2fa44c3ee598f53ddd796528d3b6888e3d0..aa600a19c44eae59f02f28ce5b85424d6d694dd4 100644 (file)
@@ -192,11 +192,13 @@ extern int end_arglist (void);
 
 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 push_type_address_space (char *);
+extern void insert_type_address_space (char *);
 
 extern enum type_pieces pop_type (void);
 
index 26e4ce0f6c828c58f2ab84bde833f826dd73c246..f123984587338bca5a28571d3b9cef81e9911636 100644 (file)
@@ -1,3 +1,7 @@
+2012-06-19  Tom Tromey  <tromey@redhat.com>
+
+       * gdb.base/whatis.exp: Add tests.
+
 2012-06-19  Tom Tromey  <tromey@redhat.com>
 
        * gdb.cp/m-static.cc (keepalive): New function.
index 9198ef28affa6659fcf83511d164a5bb3f7513ca..793bf0be01b173524a4a7a046040e055eef68a2f 100644 (file)
@@ -465,3 +465,17 @@ gdb_test "whatis char_addr" \
 gdb_test "whatis a_char_addr" \
     "type = char_addr" \
     "whatis applied to variable defined by typedef"
+
+# Regression tests for PR 9514.
+
+gdb_test "whatis void (**)()" \
+  "type = void \\(\\*\\*\\)\\(\\)" \
+  "whatis applied to pointer to pointer to function"
+
+gdb_test "whatis void (** const)()" \
+  "type = void \\(\\*\\* const\\)\\(\\)" \
+  "whatis applied to const pointer to pointer to function"
+
+gdb_test "whatis void (* const *)()" \
+  "type = void \\(\\* const \\*\\)\\(\\)" \
+  "whatis applied to pointer to const pointer to function"