Fix &str printing in Rust
authorTom Tromey <tom@tromey.com>
Mon, 2 Oct 2017 19:55:42 +0000 (13:55 -0600)
committerTom Tromey <tom@tromey.com>
Mon, 2 Oct 2017 20:06:48 +0000 (14:06 -0600)
Printing a string slice ("&str") in Rust would print until the
terminating \0; but that is incorrect because a slice has a length.
This fixes &str printing, and arranges to preserve the type name when
slicing a slice, so that printing a slice of an "&str" works as well.

This is PR rust/22236.

2017-10-02  Tom Tromey  <tom@tromey.com>

PR rust/22236:
* rust-lang.c (rust_val_print_str): New function.
(val_print_struct): Call it.
(rust_subscript): Preserve name of slice type.

2017-10-02  Tom Tromey  <tom@tromey.com>

PR rust/22236:
* gdb.rust/simple.rs (main): New variable "fslice".
* gdb.rust/simple.exp: Add slice tests.  Update string tests.

gdb/ChangeLog
gdb/rust-lang.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.rust/simple.exp
gdb/testsuite/gdb.rust/simple.rs

index 11c1ca374ef3896481b15c213f9fe43391edd01d..e0cf4c027099b4c289e5fa8bd2e77fcf5490e382 100644 (file)
@@ -1,3 +1,10 @@
+2017-10-02  Tom Tromey  <tom@tromey.com>
+
+       PR rust/22236:
+       * rust-lang.c (rust_val_print_str): New function.
+       (val_print_struct): Call it.
+       (rust_subscript): Preserve name of slice type.
+
 2017-10-02  Tom Tromey  <tom@tromey.com>
 
        * rust-lang.c (rust_subscript): Handle slices in
index 9b64efad78f9a8e027db1df66b33b79f668eec9c..261ddb1a10970cea89881638646d131eb1f22f13 100644 (file)
@@ -467,6 +467,21 @@ rust_printstr (struct ui_file *stream, struct type *type,
 
 \f
 
+/* Helper function to print a string slice.  */
+
+static void
+rust_val_print_str (struct ui_file *stream, struct value *val,
+                   const struct value_print_options *options)
+{
+  struct value *base = value_struct_elt (&val, NULL, "data_ptr", NULL,
+                                        "slice");
+  struct value *len = value_struct_elt (&val, NULL, "length", NULL, "slice");
+
+  val_print_string (TYPE_TARGET_TYPE (value_type (base)), "UTF-8",
+                   value_as_address (base), value_as_long (len), stream,
+                   options);
+}
+
 /* rust_print_type branch for structs and untagged unions.  */
 
 static void
@@ -477,6 +492,13 @@ val_print_struct (struct type *type, int embedded_offset,
 {
   int i;
   int first_field;
+
+  if (rust_slice_type_p (type) && strcmp (TYPE_NAME (type), "&str") == 0)
+    {
+      rust_val_print_str (stream, val, options);
+      return;
+    }
+
   bool is_tuple = rust_tuple_type_p (type);
   bool is_tuple_struct = !is_tuple && rust_tuple_struct_type_p (type);
   struct value_print_options opts;
@@ -1562,8 +1584,11 @@ rust_subscript (struct expression *exp, int *pos, enum noside noside,
          usize = language_lookup_primitive_type (exp->language_defn,
                                                  exp->gdbarch,
                                                  "usize");
-         slice = rust_slice_type ("&[*gdb*]", value_type (result),
-                                  usize);
+         const char *new_name = ((type != nullptr
+                                  && rust_slice_type_p (type))
+                                 ? TYPE_NAME (type) : "&[*gdb*]");
+
+         slice = rust_slice_type (new_name, value_type (result), usize);
 
          addrval = value_allocate_space_in_inferior (TYPE_LENGTH (slice));
          addr = value_as_long (addrval);
index 296878c33f24c9aa104324f41496fc184594abb5..4de56f76be0bdb8c8022684799f3647dab4afb74 100644 (file)
@@ -1,3 +1,9 @@
+2017-10-02  Tom Tromey  <tom@tromey.com>
+
+       PR rust/22236:
+       * gdb.rust/simple.rs (main): New variable "fslice".
+       * gdb.rust/simple.exp: Add slice tests.  Update string tests.
+
 2017-10-02  Tom Tromey  <tom@tromey.com>
 
        * gdb.rust/simple.exp: Test ptype of a slice.
index b01841f1e0262f3f9facd59170231941119a4dd8..90516b96df6c55dfe02a451c600a2185797e0369 100644 (file)
@@ -64,6 +64,10 @@ gdb_test "ptype j2" " = struct simple::Unit"
 gdb_test "print simple::Unit" " = simple::Unit"
 gdb_test "print simple::Unit{}" " = simple::Unit"
 
+gdb_test "print f" " = \"hi bob\""
+gdb_test "print fslice" " = \"bob\""
+gdb_test "print &f\[3..\]" " = \"bob\""
+
 gdb_test "print g" " = \\(u8 \\(\\*\\)\\\[6\\\]\\) $hex b\"hi bob\""
 gdb_test "ptype g" " = u8 \\(\\*\\)\\\[6\\\]"
 
@@ -200,13 +204,9 @@ gdb_test "ptype empty" "fn \\(\\)"
 
 gdb_test "print (diff2 as fn(i32, i32) -> i32)(19, -2)" " = 21"
 
-# We need the ".*" because currently we don't extract the length and
-# use it to intelligently print the string data.
-gdb_test "print \"hello rust\"" \
-    " = &str \\{data_ptr: $hex \"hello rust.*\", length: 10\\}"
+gdb_test "print \"hello rust\"" " = \"hello rust.*\""
 gdb_test "print \"hello" "Unexpected EOF in string"
-gdb_test "print r##\"hello \" rust\"##" \
-    " = &str \\{data_ptr: $hex \"hello \\\\\" rust.*\", length: 12\\}"
+gdb_test "print r##\"hello \" rust\"##" " = \"hello \\\\\" rust.*\""
 gdb_test "print r\"hello" "Unexpected EOF in string"
 gdb_test "print r###\"###hello\"" "Unexpected EOF in string"
 gdb_test "print r###\"###hello\"##" "Unexpected EOF in string"
index 9c154e7c4914ee76b1c6ce5c9eda41a7ebeb37f9..d6d1755e4d5229d43bc846013fe29e48bdb27c6d 100644 (file)
@@ -95,6 +95,8 @@ fn main () {
     let g = b"hi bob";
     let h = b'9';
 
+    let fslice = &f[3..];
+
     let i = ["whatever"; 8];
 
     let j = Unit;