Handle sizeof(type) in Rust
authorTom Tromey <tom@tromey.com>
Fri, 14 Jul 2017 14:10:39 +0000 (08:10 -0600)
committerTom Tromey <tom@tromey.com>
Fri, 14 Jul 2017 18:30:56 +0000 (12:30 -0600)
PR rust/21764 notes that "sizeof" does not work correctly for all types
in Rust.  The bug turns out to be an error in the conversion of the AST
to gdb expressions.  This patch fixes the bug and also avoids generating
incorrect expressions in another case.

Tested on the buildbot.  I'm checking this in.

2017-07-14  Tom Tromey  <tom@tromey.com>

PR rust/21764:
* rust-exp.y (convert_ast_to_expression): Add "want_type"
parameter.
<UNOP_SIZEOF>: Split into separate case.
<UNOP_VAR_VALUE>: Handle want_type.  Add error case.

2017-07-14  Tom Tromey  <tom@tromey.com>

PR rust/21764:
* gdb.rust/simple.exp: Add tests.

gdb/ChangeLog
gdb/rust-exp.y
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.rust/simple.exp

index 513cb6b0bcb56327aa837ed371819ef7e82b1e94..1da495ff4cadb96a4484d46926cbe4c79a7ae0f7 100644 (file)
@@ -1,3 +1,11 @@
+2017-07-14  Tom Tromey  <tom@tromey.com>
+
+       PR rust/21764:
+       * rust-exp.y (convert_ast_to_expression): Add "want_type"
+       parameter.
+       <UNOP_SIZEOF>: Split into separate case.
+       <UNOP_VAR_VALUE>: Handle want_type.  Add error case.
+
 2017-07-14  Tom Tromey  <tom@tromey.com>
 
        PR rust/21763:
index 821abcdca2f899043f4b4d5b2434c791cd17384c..3ac78a390339a9b5c0151d7ab8e93ffc132cb64a 100644 (file)
@@ -2100,7 +2100,8 @@ convert_name (struct parser_state *state, const struct rust_op *operation)
 
 static void convert_ast_to_expression (struct parser_state *state,
                                       const struct rust_op *operation,
-                                      const struct rust_op *top);
+                                      const struct rust_op *top,
+                                      bool want_type = false);
 
 /* A helper function that converts a vec of rust_ops to a gdb
    expression.  */
@@ -2121,12 +2122,16 @@ convert_params_to_expression (struct parser_state *state,
    OPERATION is the operation to lower.  TOP is a pointer to the
    top-most operation; it is used to handle the special case where the
    top-most expression is an identifier and can be optionally lowered
-   to OP_TYPE.  */
+   to OP_TYPE.  WANT_TYPE is a flag indicating that, if the expression
+   is the name of a type, then emit an OP_TYPE for it (rather than
+   erroring).  If WANT_TYPE is set, then the similar TOP handling is
+   not done.  */
 
 static void
 convert_ast_to_expression (struct parser_state *state,
                           const struct rust_op *operation,
-                          const struct rust_op *top)
+                          const struct rust_op *top,
+                          bool want_type)
 {
   switch (operation->opcode)
     {
@@ -2166,12 +2171,16 @@ convert_ast_to_expression (struct parser_state *state,
       }
       break;
 
+    case UNOP_SIZEOF:
+      convert_ast_to_expression (state, operation->left.op, top, true);
+      write_exp_elt_opcode (state, UNOP_SIZEOF);
+      break;
+
     case UNOP_PLUS:
     case UNOP_NEG:
     case UNOP_COMPLEMENT:
     case UNOP_IND:
     case UNOP_ADDR:
-    case UNOP_SIZEOF:
       convert_ast_to_expression (state, operation->left.op, top);
       write_exp_elt_opcode (state, operation->opcode);
       break;
@@ -2337,7 +2346,8 @@ convert_ast_to_expression (struct parser_state *state,
            if (type == NULL)
              error (_("No symbol '%s' in current context"), varname);
 
-           if (TYPE_CODE (type) == TYPE_CODE_STRUCT
+           if (!want_type
+               && TYPE_CODE (type) == TYPE_CODE_STRUCT
                && TYPE_NFIELDS (type) == 0)
              {
                /* A unit-like struct.  */
@@ -2346,13 +2356,16 @@ convert_ast_to_expression (struct parser_state *state,
                write_exp_elt_longcst (state, 0);
                write_exp_elt_opcode (state, OP_AGGREGATE);
              }
-           else if (operation == top)
+           else if (want_type || operation == top)
              {
                write_exp_elt_opcode (state, OP_TYPE);
                write_exp_elt_type (state, type);
                write_exp_elt_opcode (state, OP_TYPE);
-               break;
              }
+           else
+             error (_("Found type '%s', which can't be "
+                      "evaluated in this context"),
+                    varname);
          }
       }
       break;
index b715bfd7fe1bb542fae9744724309ba1931e7a7a..3fac8daa06bb2c404bfcebab81ea5f87e939e886 100644 (file)
@@ -1,3 +1,8 @@
+2017-07-14  Tom Tromey  <tom@tromey.com>
+
+       PR rust/21764:
+       * gdb.rust/simple.exp: Add tests.
+
 2017-07-14  Tom Tromey  <tom@tromey.com>
 
        * gdb.rust/simple.exp: Add regression test for PR rust/21763.
index db231623a4d262cb091aa69e0ded394d4764c90a..83dab17022989dda5149e33a2244304787d11525 100644 (file)
@@ -135,6 +135,9 @@ gdb_test "print simple::ByeBob\{field1: 0xff, field2:5\}" \
 
 gdb_test "print simple::HiBob(0xff, 5)" \
     "Type simple::HiBob is not a tuple struct"
+gdb_test "print sizeof(simple::HiBob)" " = \[0-9\]+"
+gdb_test "print simple::HiBob + 5" \
+    "Found type 'simple::HiBob', which can't be evaluated in this context"
 gdb_test "print nosuchsymbol" \
     "No symbol 'nosuchsymbol' in current context"