aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog9
-rw-r--r--gdb/rust-lang.c82
-rw-r--r--gdb/testsuite/ChangeLog6
-rw-r--r--gdb/testsuite/gdb.rust/simple.exp18
-rw-r--r--gdb/testsuite/gdb.rust/simple.rs8
-rw-r--r--gdb/typeprint.c3
6 files changed, 106 insertions, 20 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 677328b..2baf252 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,14 @@
2018-06-26 Tom Tromey <tom@tromey.com>
+ PR rust/22574:
+ * typeprint.c (whatis_exp): Allow ptype/o for Rust.
+ * rust-lang.c (rust_print_struct_def): Add podata parameter.
+ Update.
+ (rust_internal_print_type): Add podata parameter.
+ (rust_print_type): Update.
+
+2018-06-26 Tom Tromey <tom@tromey.com>
+
* typeprint.h (struct print_offset_data) <update, finish,
maybe_print_hole>: New methods.
<indentation>: New constant.
diff --git a/gdb/rust-lang.c b/gdb/rust-lang.c
index d9807d0..5f4aceb 100644
--- a/gdb/rust-lang.c
+++ b/gdb/rust-lang.c
@@ -31,8 +31,10 @@
#include "objfiles.h"
#include "psymtab.h"
#include "rust-lang.h"
+#include "typeprint.h"
#include "valprint.h"
#include "varobj.h"
+#include <algorithm>
#include <string>
#include <vector>
@@ -616,14 +618,14 @@ static void
rust_internal_print_type (struct type *type, const char *varstring,
struct ui_file *stream, int show, int level,
const struct type_print_options *flags,
- bool for_rust_enum);
+ bool for_rust_enum, print_offset_data *podata);
/* Print a struct or union typedef. */
static void
rust_print_struct_def (struct type *type, const char *varstring,
struct ui_file *stream, int show, int level,
const struct type_print_options *flags,
- bool for_rust_enum)
+ bool for_rust_enum, print_offset_data *podata)
{
/* Print a tuple type simply. */
if (rust_tuple_type_p (type))
@@ -636,6 +638,13 @@ rust_print_struct_def (struct type *type, const char *varstring,
if (TYPE_N_BASECLASSES (type) > 0)
c_print_type (type, varstring, stream, show, level, flags);
+ if (flags->print_offsets)
+ {
+ /* Temporarily bump the level so that the output lines up
+ correctly. */
+ level += 2;
+ }
+
/* Compute properties of TYPE here because, in the enum case, the
rest of the code ends up looking only at the variant part. */
const char *tagname = TYPE_NAME (type);
@@ -674,16 +683,41 @@ rust_print_struct_def (struct type *type, const char *varstring,
if (TYPE_NFIELDS (type) == 0 && !is_tuple)
return;
- if (for_rust_enum)
+ if (for_rust_enum && !flags->print_offsets)
fputs_filtered (is_tuple_struct ? "(" : "{", stream);
else
fputs_filtered (is_tuple_struct ? " (\n" : " {\n", stream);
+ /* When printing offsets, we rearrange the fields into storage
+ order. This lets us show holes more clearly. We work using
+ field indices here because it simplifies calls to
+ print_offset_data::update below. */
+ std::vector<int> fields;
for (int i = 0; i < TYPE_NFIELDS (type); ++i)
{
- QUIT;
if (field_is_static (&TYPE_FIELD (type, i)))
continue;
+ if (is_enum && i == enum_discriminant_index)
+ continue;
+ fields.push_back (i);
+ }
+ if (flags->print_offsets)
+ std::sort (fields.begin (), fields.end (),
+ [&] (int a, int b)
+ {
+ return (TYPE_FIELD_BITPOS (type, a)
+ < TYPE_FIELD_BITPOS (type, b));
+ });
+
+ for (int i : fields)
+ {
+ QUIT;
+
+ gdb_assert (!field_is_static (&TYPE_FIELD (type, i)));
+ gdb_assert (! (is_enum && i == enum_discriminant_index));
+
+ if (flags->print_offsets)
+ podata->update (type, i, stream);
/* We'd like to print "pub" here as needed, but rustc
doesn't emit the debuginfo, and our types don't have
@@ -691,27 +725,35 @@ rust_print_struct_def (struct type *type, const char *varstring,
/* For a tuple struct we print the type but nothing
else. */
- if (!for_rust_enum)
+ if (!for_rust_enum || flags->print_offsets)
print_spaces_filtered (level + 2, stream);
if (is_enum)
- {
- if (i == enum_discriminant_index)
- continue;
- fputs_filtered (TYPE_FIELD_NAME (type, i), stream);
- }
+ fputs_filtered (TYPE_FIELD_NAME (type, i), stream);
else if (!is_tuple_struct)
fprintf_filtered (stream, "%s: ", TYPE_FIELD_NAME (type, i));
rust_internal_print_type (TYPE_FIELD_TYPE (type, i), NULL,
stream, (is_enum ? show : show - 1),
- level + 2, flags, is_enum);
- if (!for_rust_enum)
+ level + 2, flags, is_enum, podata);
+ if (!for_rust_enum || flags->print_offsets)
fputs_filtered (",\n", stream);
+ /* Note that this check of "I" is ok because we only sorted the
+ fields by offset when print_offsets was set, so we won't take
+ this branch in that case. */
else if (i + 1 < TYPE_NFIELDS (type))
fputs_filtered (", ", stream);
}
- if (!for_rust_enum)
+ if (flags->print_offsets)
+ {
+ /* Undo the temporary level increase we did above. */
+ level -= 2;
+ podata->finish (type, level, stream);
+ print_spaces_filtered (print_offset_data::indentation, stream);
+ if (level == 0)
+ print_spaces_filtered (2, stream);
+ }
+ if (!for_rust_enum || flags->print_offsets)
print_spaces_filtered (level, stream);
fputs_filtered (is_tuple_struct ? ")" : "}", stream);
}
@@ -735,7 +777,7 @@ static void
rust_internal_print_type (struct type *type, const char *varstring,
struct ui_file *stream, int show, int level,
const struct type_print_options *flags,
- bool for_rust_enum)
+ bool for_rust_enum, print_offset_data *podata)
{
int i;
@@ -778,7 +820,7 @@ rust_internal_print_type (struct type *type, const char *varstring,
if (i > 0)
fputs_filtered (", ", stream);
rust_internal_print_type (TYPE_FIELD_TYPE (type, i), "", stream,
- -1, 0, flags, false);
+ -1, 0, flags, false, podata);
}
fputs_filtered (")", stream);
/* If it returns unit, we can omit the return type. */
@@ -786,7 +828,7 @@ rust_internal_print_type (struct type *type, const char *varstring,
{
fputs_filtered (" -> ", stream);
rust_internal_print_type (TYPE_TARGET_TYPE (type), "", stream,
- -1, 0, flags, false);
+ -1, 0, flags, false, podata);
}
break;
@@ -796,7 +838,8 @@ rust_internal_print_type (struct type *type, const char *varstring,
fputs_filtered ("[", stream);
rust_internal_print_type (TYPE_TARGET_TYPE (type), NULL,
- stream, show - 1, level, flags, false);
+ stream, show - 1, level, flags, false,
+ podata);
if (TYPE_HIGH_BOUND_KIND (TYPE_INDEX_TYPE (type)) == PROP_LOCEXPR
|| TYPE_HIGH_BOUND_KIND (TYPE_INDEX_TYPE (type)) == PROP_LOCLIST)
@@ -811,7 +854,7 @@ rust_internal_print_type (struct type *type, const char *varstring,
case TYPE_CODE_UNION:
case TYPE_CODE_STRUCT:
rust_print_struct_def (type, varstring, stream, show, level, flags,
- for_rust_enum);
+ for_rust_enum, podata);
break;
case TYPE_CODE_ENUM:
@@ -856,8 +899,9 @@ rust_print_type (struct type *type, const char *varstring,
struct ui_file *stream, int show, int level,
const struct type_print_options *flags)
{
+ print_offset_data podata;
rust_internal_print_type (type, varstring, stream, show, level,
- flags, false);
+ flags, false, &podata);
}
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 73f5545..b2901db 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2018-06-26 Tom Tromey <tom@tromey.com>
+
+ PR rust/22574:
+ * gdb.rust/simple.exp (test_one_slice): Add ptype/o tests.
+ * gdb.rust/simple.rs (struct SimpleLayout): New.
+
2018-06-22 Simon Marchi <simon.marchi@ericsson.com>
* gdb.base/jit-reader.exp (jit_reader_test): Expect spaces in
diff --git a/gdb/testsuite/gdb.rust/simple.exp b/gdb/testsuite/gdb.rust/simple.exp
index ba90e06..20fe8dd 100644
--- a/gdb/testsuite/gdb.rust/simple.exp
+++ b/gdb/testsuite/gdb.rust/simple.exp
@@ -285,6 +285,24 @@ gdb_test "print parametrized" \
gdb_test "print u" " = simple::Union {f1: -1, f2: 255}"
+gdb_test_sequence "ptype/o Union" "" {
+ "/\\* offset | size \\*/ type = union simple::Union {"
+ "/\\* 1 \\*/ f1: i8,"
+ "/\\* 1 \\*/ f2: u8,"
+ ""
+ " /\\* total size \\(bytes\\): 1 \\*/"
+ " }"
+}
+
+gdb_test_sequence "ptype/o SimpleLayout" "" {
+ "/\\* offset | size \\*/ type = struct simple::SimpleLayout {"
+ "/\\* 0 | 2 \\*/ f1: u16,"
+ "/\\* 2 | 2 \\*/ f2: u16,"
+ ""
+ " /\\* total size \\(bytes\\): 4 \\*/"
+ " }"
+}
+
load_lib gdb-python.exp
if {[skip_python_tests]} {
continue
diff --git a/gdb/testsuite/gdb.rust/simple.rs b/gdb/testsuite/gdb.rust/simple.rs
index e5bbe52..9d89361 100644
--- a/gdb/testsuite/gdb.rust/simple.rs
+++ b/gdb/testsuite/gdb.rust/simple.rs
@@ -85,6 +85,13 @@ union Union {
f2: u8,
}
+// A simple structure whose layout won't be changed by the compiler,
+// so that ptype/o testing will work on any platform.
+struct SimpleLayout {
+ f1: u16,
+ f2: u16
+}
+
fn main () {
let a = ();
let b : [i32; 0] = [];
@@ -159,6 +166,7 @@ fn main () {
};
let u = Union { f2: 255 };
+ let v = SimpleLayout { f1: 8, f2: 9 };
println!("{}, {}", x.0, x.1); // set breakpoint here
println!("{}", diff2(92, 45));
diff --git a/gdb/typeprint.c b/gdb/typeprint.c
index b29ad5f..7a0b762 100644
--- a/gdb/typeprint.c
+++ b/gdb/typeprint.c
@@ -490,7 +490,8 @@ whatis_exp (const char *exp, int show)
feature. */
if (show > 0
&& (current_language->la_language == language_c
- || current_language->la_language == language_cplus))
+ || current_language->la_language == language_cplus
+ || current_language->la_language == language_rust))
{
flags.print_offsets = 1;
flags.print_typedefs = 0;