#include "c-lang.h"
#include "charset.h"
#include "cp-support.h"
-#include "f-lang.h"
+#include "demangle.h"
#include "gdbarch.h"
#include "infcall.h"
#include "objfiles.h"
#include "rust-lang.h"
#include "valprint.h"
#include "varobj.h"
+#include <string>
+#include <vector>
extern initialize_file_ftype _initialize_rust_language;
struct disr_info
{
- /* Name of field. Must be freed by caller. */
- char *name;
+ /* Name of field. */
+ std::string name;
/* Field number in union. Negative on error. For an encoded enum,
the "hidden" member will always be field 1, and the "real" member
will always be field 0. */
#define RUST_ENCODED_ENUM_HIDDEN 1
+/* Whether or not a TYPE_CODE_UNION value is an untagged union
+ as opposed to being a regular Rust enum. */
+static bool
+rust_union_is_untagged (struct type *type)
+{
+ /* Unions must have at least one field. */
+ if (TYPE_NFIELDS (type) == 0)
+ return false;
+ /* If the first field is named, but the name has the rust enum prefix,
+ it is an enum. */
+ if (strncmp (TYPE_FIELD_NAME (type, 0), RUST_ENUM_PREFIX,
+ strlen (RUST_ENUM_PREFIX)) == 0)
+ return false;
+ /* Unions only have named fields. */
+ for (int i = 0; i < TYPE_NFIELDS (type); ++i)
+ {
+ if (strlen (TYPE_FIELD_NAME (type, i)) == 0)
+ return false;
+ }
+ return true;
+}
+
/* Utility function to get discriminant info for a given value. */
static struct disr_info
rust_get_disr_info (struct type *type, const gdb_byte *valaddr,
int embedded_offset, CORE_ADDR address,
- const struct value *val)
+ struct value *val)
{
int i;
struct disr_info ret;
if (strncmp (TYPE_FIELD_NAME (type, 0), RUST_ENUM_PREFIX,
strlen (RUST_ENUM_PREFIX)) == 0)
{
- char *tail;
+ char *tail, *token, *name, *saveptr = NULL;
unsigned long fieldno;
struct type *member_type;
LONGEST value;
if (TYPE_NFIELDS (type) != 1)
error (_("Only expected one field in %s type"), RUST_ENUM_PREFIX);
- fieldno = strtoul (TYPE_FIELD_NAME (type, 0) + strlen (RUST_ENUM_PREFIX),
- &tail, 10);
- if (*tail != '$')
- error (_("Invalid form for %s"), RUST_ENUM_PREFIX);
-
+ /* Optimized enums have only one field. */
member_type = TYPE_FIELD_TYPE (type, 0);
- if (fieldno >= TYPE_NFIELDS (member_type))
- error (_("%s refers to field after end of member type"),
- RUST_ENUM_PREFIX);
- embedded_offset += TYPE_FIELD_BITPOS (member_type, fieldno) / 8;
- value = unpack_long (TYPE_FIELD_TYPE (member_type, fieldno),
- valaddr + embedded_offset);
+ name = xstrdup (TYPE_FIELD_NAME (type, 0));
+ cleanup = make_cleanup (xfree, name);
+ tail = name + strlen (RUST_ENUM_PREFIX);
+
+ /* The location of the value that doubles as a discriminant is
+ stored in the name of the field, as
+ RUST$ENCODED$ENUM$<fieldno>$<fieldno>$...$<variantname>
+ where the fieldnos are the indices of the fields that should be
+ traversed in order to find the field (which may be several fields deep)
+ and the variantname is the name of the variant of the case when the
+ field is zero. */
+ for (token = strtok_r (tail, "$", &saveptr);
+ token != NULL;
+ token = strtok_r (NULL, "$", &saveptr))
+ {
+ if (sscanf (token, "%lu", &fieldno) != 1)
+ {
+ /* We have reached the enum name, which cannot start
+ with a digit. */
+ break;
+ }
+ if (fieldno >= TYPE_NFIELDS (member_type))
+ error (_("%s refers to field after end of member type"),
+ RUST_ENUM_PREFIX);
+
+ embedded_offset += TYPE_FIELD_BITPOS (member_type, fieldno) / 8;
+ member_type = TYPE_FIELD_TYPE (member_type, fieldno);
+ }
+
+ if (token == NULL)
+ error (_("Invalid form for %s"), RUST_ENUM_PREFIX);
+ value = unpack_long (member_type, valaddr + embedded_offset);
+
if (value == 0)
{
ret.field_no = RUST_ENCODED_ENUM_HIDDEN;
- ret.name = concat (TYPE_NAME (type), "::", tail + 1, (char *) NULL);
+ ret.name = std::string (TYPE_NAME (type)) + "::" + token;
}
else
{
ret.field_no = RUST_ENCODED_ENUM_REAL;
- ret.name = concat (TYPE_NAME (type), "::",
- rust_last_path_segment (TYPE_NAME (member_type)),
- (char *) NULL);
+ ret.name = (std::string (TYPE_NAME (type)) + "::"
+ + rust_last_path_segment (TYPE_NAME (TYPE_FIELD_TYPE (type, 0))));
}
+ do_cleanups (cleanup);
return ret;
}
has changed its debuginfo format. */
error (_("Could not find enum discriminant field"));
}
+ else if (TYPE_NFIELDS (type) == 1)
+ {
+ /* Sometimes univariant enums are encoded without a
+ discriminant. In that case, treating it as an encoded enum
+ with the first field being the actual type works. */
+ const char *field_name = TYPE_NAME (TYPE_FIELD_TYPE (type, 0));
+ const char *last = rust_last_path_segment (field_name);
+ ret.name = concat (TYPE_NAME (type), "::", last, (char *) NULL);
+ ret.field_no = RUST_ENCODED_ENUM_REAL;
+ ret.is_encoded = 1;
+ return ret;
+ }
if (strcmp (TYPE_FIELD_NAME (disr_type, 0), "RUST$ENUM$DISR") != 0)
error (_("Rust debug format has changed"));
cleanup = make_cleanup_ui_file_delete (temp_file);
/* The first value of the first field (or any field)
is the discriminant value. */
- c_val_print (TYPE_FIELD_TYPE (disr_type, 0), valaddr,
+ c_val_print (TYPE_FIELD_TYPE (disr_type, 0),
(embedded_offset + TYPE_FIELD_BITPOS (type, 0) / 8
+ TYPE_FIELD_BITPOS (disr_type, 0) / 8),
address, temp_file,
0, val, &opts);
- ret.name = ui_file_xstrdup (temp_file, NULL);
- name_segment = rust_last_path_segment (ret.name);
+ ret.name = ui_file_as_string (temp_file);
+ name_segment = rust_last_path_segment (ret.name.c_str ());
if (name_segment != NULL)
{
for (i = 0; i < TYPE_NFIELDS (type); ++i)
}
}
- if (ret.field_no == -1 && ret.name != NULL)
+ if (ret.field_no == -1 && !ret.name.empty ())
{
/* Somehow the discriminant wasn't found. */
- make_cleanup (xfree, ret.name);
error (_("Could not find variant of %s with discriminant %s"),
- TYPE_TAG_NAME (type), ret.name);
+ TYPE_TAG_NAME (type), ret.name.c_str ());
}
do_cleanups (cleanup);
int
rust_tuple_struct_type_p (struct type *type)
{
- return rust_underscore_fields (type, 0);
+ /* This is just an approximation until DWARF can represent Rust more
+ precisely. We exclude zero-length structs because they may not
+ be tuple structs, and there's no way to tell. */
+ return TYPE_NFIELDS (type) > 0 && rust_underscore_fields (type, 0);
}
/* Return true if a variant TYPE is a tuple variant, false otherwise. */
\f
+/* rust_print_type branch for structs and untagged unions. */
+
+static void
+val_print_struct (struct type *type, int embedded_offset,
+ CORE_ADDR address, struct ui_file *stream,
+ int recurse, struct value *val,
+ const struct value_print_options *options)
+{
+ int i;
+ int first_field;
+ int is_tuple = rust_tuple_type_p (type);
+ int is_tuple_struct = !is_tuple && rust_tuple_struct_type_p (type);
+ struct value_print_options opts;
+
+ if (!is_tuple)
+ {
+ if (TYPE_TAG_NAME (type) != NULL)
+ fprintf_filtered (stream, "%s", TYPE_TAG_NAME (type));
+
+ if (TYPE_NFIELDS (type) == 0)
+ return;
+
+ if (TYPE_TAG_NAME (type) != NULL)
+ fputs_filtered (" ", stream);
+ }
+
+ if (is_tuple || is_tuple_struct)
+ fputs_filtered ("(", stream);
+ else
+ fputs_filtered ("{", stream);
+
+ opts = *options;
+ opts.deref_ref = 0;
+
+ first_field = 1;
+ for (i = 0; i < TYPE_NFIELDS (type); ++i)
+ {
+ if (field_is_static (&TYPE_FIELD (type, i)))
+ continue;
+
+ if (!first_field)
+ fputs_filtered (",", stream);
+
+ if (options->prettyformat)
+ {
+ fputs_filtered ("\n", stream);
+ print_spaces_filtered (2 + 2 * recurse, stream);
+ }
+ else if (!first_field)
+ fputs_filtered (" ", stream);
+
+ first_field = 0;
+
+ if (!is_tuple && !is_tuple_struct)
+ {
+ fputs_filtered (TYPE_FIELD_NAME (type, i), stream);
+ fputs_filtered (": ", stream);
+ }
+
+ val_print (TYPE_FIELD_TYPE (type, i),
+ embedded_offset + TYPE_FIELD_BITPOS (type, i) / 8,
+ address,
+ stream, recurse + 1, val, &opts,
+ current_language);
+ }
+
+ if (options->prettyformat)
+ {
+ fputs_filtered ("\n", stream);
+ print_spaces_filtered (2 * recurse, stream);
+ }
+
+ if (is_tuple || is_tuple_struct)
+ fputs_filtered (")", stream);
+ else
+ fputs_filtered ("}", stream);
+}
+
static const struct generic_val_print_decorations rust_decorations =
{
/* Complex isn't used in Rust, but we provide C-ish values just in
" * I",
"true",
"false",
- "void",
+ "()",
"[",
"]"
};
/* la_val_print implementation for Rust. */
static void
-rust_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
+rust_val_print (struct type *type, int embedded_offset,
CORE_ADDR address, struct ui_file *stream, int recurse,
- const struct value *val,
+ struct value *val,
const struct value_print_options *options)
{
+ const gdb_byte *valaddr = value_contents_for_printing (val);
+
type = check_typedef (type);
switch (TYPE_CODE (type))
{
case TYPE_CODE_METHODPTR:
case TYPE_CODE_MEMBERPTR:
- c_val_print (type, valaddr, embedded_offset, address, stream,
+ c_val_print (type, embedded_offset, address, stream,
recurse, val, options);
break;
struct type *variant_type;
struct disr_info disr;
struct value_print_options opts;
- struct cleanup *cleanup;
+
+ /* Untagged unions are printed as if they are structs.
+ Since the field bit positions overlap in the debuginfo,
+ the code for printing a union is same as that for a struct,
+ the only difference is that the input type will have overlapping
+ fields. */
+ if (rust_union_is_untagged (type))
+ {
+ val_print_struct (type, embedded_offset, address, stream,
+ recurse, val, options);
+ break;
+ }
opts = *options;
opts.deref_ref = 0;
disr = rust_get_disr_info (type, valaddr, embedded_offset, address,
val);
- cleanup = make_cleanup (xfree, disr.name);
if (disr.is_encoded && disr.field_no == RUST_ENCODED_ENUM_HIDDEN)
{
- fprintf_filtered (stream, "%s", disr.name);
- goto cleanup;
+ fprintf_filtered (stream, "%s", disr.name.c_str ());
+ break;
}
first_field = 1;
{
/* In case of a non-nullary variant, we output 'Foo(x,y,z)'. */
if (is_tuple)
- fprintf_filtered (stream, "%s(", disr.name);
+ fprintf_filtered (stream, "%s(", disr.name.c_str ());
else
{
/* struct variant. */
- fprintf_filtered (stream, "%s{", disr.name);
+ fprintf_filtered (stream, "%s{", disr.name.c_str ());
}
}
else
{
/* In case of a nullary variant like 'None', just output
the name. */
- fprintf_filtered (stream, "%s", disr.name);
- goto cleanup;
+ fprintf_filtered (stream, "%s", disr.name.c_str ());
+ break;
}
for (j = start; j < TYPE_NFIELDS (variant_type); j++)
TYPE_FIELD_NAME (variant_type, j));
val_print (TYPE_FIELD_TYPE (variant_type, j),
- valaddr,
(embedded_offset
+ TYPE_FIELD_BITPOS (type, disr.field_no) / 8
+ TYPE_FIELD_BITPOS (variant_type, j) / 8),
fputs_filtered (")", stream);
else
fputs_filtered ("}", stream);
-
- cleanup:
- do_cleanups (cleanup);
}
break;
case TYPE_CODE_STRUCT:
- {
- int i;
- int first_field;
- int is_tuple = rust_tuple_type_p (type);
- int is_tuple_struct = !is_tuple && rust_tuple_struct_type_p (type);
- struct value_print_options opts;
+ val_print_struct (type, embedded_offset, address, stream,
+ recurse, val, options);
+ break;
- if (!is_tuple)
- {
- if (TYPE_TAG_NAME (type) != NULL)
- fprintf_filtered (stream, "%s", TYPE_TAG_NAME (type));
+ default:
+ generic_print:
+ /* Nothing special yet. */
+ generic_val_print (type, embedded_offset, address, stream,
+ recurse, val, options, &rust_decorations);
+ }
+}
- if (TYPE_NFIELDS (type) == 0)
- break;
+\f
- if (TYPE_TAG_NAME (type) != NULL)
- fputs_filtered (" ", stream);
+static void
+rust_print_type (struct type *type, const char *varstring,
+ struct ui_file *stream, int show, int level,
+ const struct type_print_options *flags);
+
+/* 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)
+{
+ int is_tuple_struct, i;
+
+ /* Print a tuple type simply. */
+ if (rust_tuple_type_p (type))
+ {
+ fputs_filtered (TYPE_TAG_NAME (type), stream);
+ return;
}
- if (is_tuple || is_tuple_struct)
- fputs_filtered ("(", stream);
- else
- fputs_filtered ("{", stream);
+ /* If we see a base class, delegate to C. */
+ if (TYPE_N_BASECLASSES (type) > 0)
+ c_print_type (type, varstring, stream, show, level, flags);
- opts = *options;
- opts.deref_ref = 0;
+ /* This code path is also used by unions. */
+ if (TYPE_CODE (type) == TYPE_CODE_STRUCT)
+ fputs_filtered ("struct ", stream);
+ else
+ fputs_filtered ("union ", stream);
+
+ if (TYPE_TAG_NAME (type) != NULL)
+ fputs_filtered (TYPE_TAG_NAME (type), stream);
+
+ is_tuple_struct = rust_tuple_struct_type_p (type);
+
+ if (TYPE_NFIELDS (type) == 0 && !rust_tuple_type_p (type))
+ return;
+ fputs_filtered (is_tuple_struct ? " (\n" : " {\n", stream);
- first_field = 1;
for (i = 0; i < TYPE_NFIELDS (type); ++i)
{
+ const char *name;
+
+ QUIT;
if (field_is_static (&TYPE_FIELD (type, i)))
continue;
- if (!first_field)
- fputs_filtered (",", stream);
-
- if (options->prettyformat)
- {
- fputs_filtered ("\n", stream);
- print_spaces_filtered (2 + 2 * recurse, stream);
- }
- else if (!first_field)
- fputs_filtered (" ", stream);
-
- first_field = 0;
-
- if (!is_tuple && !is_tuple_struct)
- {
- fputs_filtered (TYPE_FIELD_NAME (type, i), stream);
- fputs_filtered (": ", stream);
- }
+ /* We'd like to print "pub" here as needed, but rustc
+ doesn't emit the debuginfo, and our types don't have
+ cplus_struct_type attached. */
- val_print (TYPE_FIELD_TYPE (type, i),
- valaddr,
- embedded_offset + TYPE_FIELD_BITPOS (type, i) / 8,
- address,
- stream, recurse + 1, val, &opts,
- current_language);
- }
+ /* For a tuple struct we print the type but nothing
+ else. */
+ print_spaces_filtered (level + 2, stream);
+ if (!is_tuple_struct)
+ fprintf_filtered (stream, "%s: ", TYPE_FIELD_NAME (type, i));
- if (options->prettyformat)
- {
- fputs_filtered ("\n", stream);
- print_spaces_filtered (2 * recurse, stream);
+ rust_print_type (TYPE_FIELD_TYPE (type, i), NULL,
+ stream, show - 1, level + 2,
+ flags);
+ fputs_filtered (",\n", stream);
}
- if (is_tuple || is_tuple_struct)
- fputs_filtered (")", stream);
- else
- fputs_filtered ("}", stream);
- }
- break;
-
- default:
- generic_print:
- /* Nothing special yet. */
- generic_val_print (type, valaddr, embedded_offset, address, stream,
- recurse, val, options, &rust_decorations);
- }
+ fprintfi_filtered (level, stream, is_tuple_struct ? ")" : "}");
}
-\f
-
/* la_print_typedef implementation for Rust. */
static void
if (show <= 0
&& TYPE_NAME (type) != NULL)
{
- fputs_filtered (TYPE_NAME (type), stream);
+ /* Rust calls the unit type "void" in its debuginfo,
+ but we don't want to print it as that. */
+ if (TYPE_CODE (type) == TYPE_CODE_VOID)
+ fputs_filtered ("()", stream);
+ else
+ fputs_filtered (TYPE_NAME (type), stream);
return;
}
type = check_typedef (type);
switch (TYPE_CODE (type))
{
+ case TYPE_CODE_VOID:
+ fputs_filtered ("()", stream);
+ break;
+
case TYPE_CODE_FUNC:
/* Delegate varargs to the C printer. */
if (TYPE_VARARGS (type))
rust_print_type (TYPE_FIELD_TYPE (type, i), "", stream, -1, 0,
flags);
}
- fputs_filtered (") -> ", stream);
- rust_print_type (TYPE_TARGET_TYPE (type), "", stream, -1, 0, flags);
+ fputs_filtered (")", stream);
+ /* If it returns unit, we can omit the return type. */
+ if (TYPE_CODE (TYPE_TARGET_TYPE (type)) != TYPE_CODE_VOID)
+ {
+ fputs_filtered (" -> ", stream);
+ rust_print_type (TYPE_TARGET_TYPE (type), "", stream, -1, 0, flags);
+ }
break;
case TYPE_CODE_ARRAY:
break;
case TYPE_CODE_STRUCT:
- {
- int is_tuple_struct;
-
- /* Print a tuple type simply. */
- if (rust_tuple_type_p (type))
- {
- fputs_filtered (TYPE_TAG_NAME (type), stream);
- break;
- }
-
- /* If we see a base class, delegate to C. */
- if (TYPE_N_BASECLASSES (type) > 0)
- goto c_printer;
-
- fputs_filtered ("struct ", stream);
- if (TYPE_TAG_NAME (type) != NULL)
- fputs_filtered (TYPE_TAG_NAME (type), stream);
-
- is_tuple_struct = rust_tuple_struct_type_p (type);
-
- if (TYPE_NFIELDS (type) == 0 && !rust_tuple_type_p (type))
- break;
- fputs_filtered (is_tuple_struct ? " (\n" : " {\n", stream);
-
- for (i = 0; i < TYPE_NFIELDS (type); ++i)
- {
- const char *name;
-
- QUIT;
- if (field_is_static (&TYPE_FIELD (type, i)))
- continue;
-
- /* We'd like to print "pub" here as needed, but rustc
- doesn't emit the debuginfo, and our types don't have
- cplus_struct_type attached. */
-
- /* For a tuple struct we print the type but nothing
- else. */
- print_spaces_filtered (level + 2, stream);
- if (!is_tuple_struct)
- fprintf_filtered (stream, "%s: ", TYPE_FIELD_NAME (type, i));
-
- rust_print_type (TYPE_FIELD_TYPE (type, i), NULL,
- stream, show - 1, level + 2,
- flags);
- fputs_filtered (",\n", stream);
- }
-
- fprintfi_filtered (level, stream, is_tuple_struct ? ")" : "}");
- }
+ rust_print_struct_def (type, varstring, stream, show, level, flags);
break;
case TYPE_CODE_ENUM:
case TYPE_CODE_UNION:
{
- /* ADT enums */
+ /* ADT enums. */
int i, len = 0;
+ /* Skip the discriminant field. */
+ int skip_to = 1;
+
+ /* Unions and structs have the same syntax in Rust,
+ the only difference is that structs are declared with `struct`
+ and union with `union`. This difference is handled in the struct
+ printer. */
+ if (rust_union_is_untagged (type))
+ {
+ rust_print_struct_def (type, varstring, stream, show, level, flags);
+ break;
+ }
fputs_filtered ("enum ", stream);
if (TYPE_TAG_NAME (type) != NULL)
{
fputs_filtered (TYPE_TAG_NAME (type), stream);
fputs_filtered (" ", stream);
- len = strlen (TYPE_TAG_NAME (type));
}
- fputs_filtered ("{\n", stream);
+ fputs_filtered ("{\n", stream);
+
+ if (strncmp (TYPE_FIELD_NAME (type, 0), RUST_ENUM_PREFIX,
+ strlen (RUST_ENUM_PREFIX)) == 0)
+ {
+ const char *zero_field = strrchr (TYPE_FIELD_NAME (type, 0), '$');
+ if (zero_field != NULL && strlen (zero_field) > 1)
+ {
+ fprintfi_filtered (level + 2, stream, "%s,\n", zero_field + 1);
+ /* There is no explicit discriminant field, skip nothing. */
+ skip_to = 0;
+ }
+ }
for (i = 0; i < TYPE_NFIELDS (type); ++i)
{
fprintfi_filtered (level + 2, stream, "%s", name);
- if (TYPE_NFIELDS (variant_type) > 1)
+ if (TYPE_NFIELDS (variant_type) > skip_to)
{
int first = 1;
int is_tuple = rust_tuple_variant_type_p (variant_type);
int j;
fputs_filtered (is_tuple ? "(" : "{", stream);
- for (j = 1; j < TYPE_NFIELDS (variant_type); j++)
+ for (j = skip_to; j < TYPE_NFIELDS (variant_type); j++)
{
if (first)
first = 0;
types[rust_primitive_isize] = arch_integer_type (gdbarch, length, 0, "isize");
types[rust_primitive_usize] = arch_integer_type (gdbarch, length, 1, "usize");
- types[rust_primitive_f32] = arch_float_type (gdbarch, 32, "f32", NULL);
- types[rust_primitive_f64] = arch_float_type (gdbarch, 64, "f64", NULL);
+ types[rust_primitive_f32] = arch_float_type (gdbarch, 32, "f32",
+ floatformats_ieee_single);
+ types[rust_primitive_f64] = arch_float_type (gdbarch, 64, "f64",
+ floatformats_ieee_double);
types[rust_primitive_unit] = arch_integer_type (gdbarch, 0, 1, "()");
int i;
int num_args = exp->elts[*pos + 1].longconst;
const char *method;
- char *name;
struct value *function, *result, *arg0;
- struct value **args;
- struct cleanup *cleanup;
struct type *type, *fn_type;
const struct block *block;
struct block_symbol sym;
return arg0;
}
- args = XNEWVEC (struct value *, num_args + 1);
- cleanup = make_cleanup (xfree, args);
+ std::vector<struct value *> args (num_args + 1);
args[0] = arg0;
/* We don't yet implement real Deref semantics. */
if (TYPE_TAG_NAME (type) == NULL)
error (_("Method call on nameless type"));
- name = concat (TYPE_TAG_NAME (type), "::", method, (char *) NULL);
- make_cleanup (xfree, name);
+ std::string name = std::string (TYPE_TAG_NAME (type)) + "::" + method;
block = get_selected_block (0);
- sym = lookup_symbol (name, block, VAR_DOMAIN, NULL);
+ sym = lookup_symbol (name.c_str (), block, VAR_DOMAIN, NULL);
if (sym.symbol == NULL)
- error (_("Could not find function named '%s'"), name);
+ error (_("Could not find function named '%s'"), name.c_str ());
fn_type = SYMBOL_TYPE (sym.symbol);
if (TYPE_NFIELDS (fn_type) == 0)
- error (_("Function '%s' takes no arguments"), name);
+ error (_("Function '%s' takes no arguments"), name.c_str ());
if (TYPE_CODE (TYPE_FIELD_TYPE (fn_type, 0)) == TYPE_CODE_PTR)
args[0] = value_addr (args[0]);
if (noside == EVAL_AVOID_SIDE_EFFECTS)
result = value_zero (TYPE_TARGET_TYPE (fn_type), not_lval);
else
- result = call_function_by_hand (function, num_args + 1, args);
- do_cleanups (cleanup);
+ result = call_function_by_hand (function, num_args + 1, args.data ());
return result;
}
-/* A helper for rust_evaluate_subexp that handles OP_F90_RANGE. */
+/* A helper for rust_evaluate_subexp that handles OP_RANGE. */
static struct value *
rust_range (struct expression *exp, int *pos, enum noside noside)
{
- enum f90_range_type kind;
+ enum range_type kind;
struct value *low = NULL, *high = NULL;
struct value *addrval, *result;
CORE_ADDR addr;
struct type *temp_type;
const char *name;
- kind = (enum f90_range_type) longest_to_int (exp->elts[*pos + 1].longconst);
+ kind = (enum range_type) longest_to_int (exp->elts[*pos + 1].longconst);
*pos += 3;
if (kind == HIGH_BOUND_DEFAULT || kind == NONE_BOUND_DEFAULT)
static void
rust_compute_range (struct type *type, struct value *range,
LONGEST *low, LONGEST *high,
- enum f90_range_type *kind)
+ enum range_type *kind)
{
int i;
{
struct value *lhs, *rhs, *result;
struct type *rhstype;
- LONGEST low, high, high_bound;
+ LONGEST low, high_bound;
/* Initialized to appease the compiler. */
- enum f90_range_type kind = BOTH_BOUND_DEFAULT;
+ enum range_type kind = BOTH_BOUND_DEFAULT;
+ LONGEST high = 0;
int want_slice = 0;
++*pos;
low_bound = 0;
high_bound = value_as_long (len);
}
+ else if (TYPE_CODE (type) == TYPE_CODE_PTR)
+ {
+ base = lhs;
+ low_bound = 0;
+ high_bound = LONGEST_MAX;
+ }
else
error (_("Cannot subscript non-array type"));
{
CORE_ADDR addr;
int i;
- struct value **eltvec = XNEWVEC (struct value *, copies);
- struct cleanup *cleanup = make_cleanup (xfree, eltvec);
+ std::vector<struct value *> eltvec (copies);
for (i = 0; i < copies; ++i)
eltvec[i] = elt;
- result = value_array (0, copies - 1, eltvec);
-
- do_cleanups (cleanup);
+ result = value_array (0, copies - 1, eltvec.data ());
}
else
{
lhs = evaluate_subexp (NULL_TYPE, exp, pos, noside);
type = value_type (lhs);
- if (TYPE_CODE (type) == TYPE_CODE_UNION)
+ /* Untagged unions can't have anonymous field access since
+ they can only have named fields. */
+ if (TYPE_CODE (type) == TYPE_CODE_UNION
+ && !rust_union_is_untagged (type))
{
- struct cleanup *cleanup;
-
disr = rust_get_disr_info (type, value_contents (lhs),
value_embedded_offset (lhs),
value_address (lhs), lhs);
- cleanup = make_cleanup (xfree, disr.name);
-
if (disr.is_encoded && disr.field_no == RUST_ENCODED_ENUM_HIDDEN)
{
variant_type = NULL;
error(_("Cannot access field %d of variant %s, \
there are only %d fields"),
disr.is_encoded ? field_number : field_number - 1,
- disr.name,
+ disr.name.c_str (),
disr.is_encoded ? nfields : nfields - 1);
if (!(disr.is_encoded
? rust_tuple_struct_type_p (variant_type)
: rust_tuple_variant_type_p (variant_type)))
- error(_("Variant %s is not a tuple variant"), disr.name);
+ error(_("Variant %s is not a tuple variant"), disr.name.c_str ());
result = value_primitive_field (lhs, 0, field_number,
variant_type);
- do_cleanups (cleanup);
}
else if (TYPE_CODE (type) == TYPE_CODE_STRUCT)
{
lhs = evaluate_subexp (NULL_TYPE, exp, pos, noside);
type = value_type (lhs);
-
- if (TYPE_CODE (type) == TYPE_CODE_UNION)
+ if (TYPE_CODE (type) == TYPE_CODE_UNION
+ && !rust_union_is_untagged (type))
{
int i, start;
struct disr_info disr;
- struct cleanup* cleanup;
struct type* variant_type;
char* field_name;
value_embedded_offset (lhs),
value_address (lhs), lhs);
- cleanup = make_cleanup (xfree, disr.name);
-
if (disr.is_encoded && disr.field_no == RUST_ENCODED_ENUM_HIDDEN)
error(_("Could not find field %s of struct variant %s"),
- field_name, disr.name);
+ field_name, disr.name.c_str ());
variant_type = TYPE_FIELD_TYPE (type, disr.field_no);
if (variant_type == NULL
- || rust_tuple_variant_type_p (variant_type))
+ || (disr.is_encoded
+ ? rust_tuple_struct_type_p (variant_type)
+ : rust_tuple_variant_type_p (variant_type)))
error(_("Attempting to access named field %s of tuple variant %s, \
which has only anonymous fields"),
- field_name, disr.name);
+ field_name, disr.name.c_str ());
start = disr.is_encoded ? 0 : 1;
for (i = start; i < TYPE_NFIELDS (variant_type); i++)
if (i == TYPE_NFIELDS (variant_type))
/* We didn't find it. */
error(_("Could not find field %s of struct variant %s"),
- field_name, disr.name);
-
- do_cleanups (cleanup);
+ field_name, disr.name.c_str ());
}
else
{
+ /* Field access in structs and untagged unions works like C. */
*pos = pc;
result = evaluate_subexp_standard (expect_type, exp, pos, noside);
}
}
break;
- case OP_F90_RANGE:
+ case OP_RANGE:
result = rust_range (exp, pos, noside);
break;
if (scope[0] != '\0')
{
- char *scopedname = concat (scope, "::", name, (char *) NULL);
- struct cleanup *cleanup = make_cleanup (xfree, scopedname);
+ std::string scopedname = std::string (scope) + "::" + name;
- result = lookup_symbol_in_static_block (scopedname, block,
+ result = lookup_symbol_in_static_block (scopedname.c_str (), block,
domain);
if (result.symbol == NULL)
- result = lookup_global_symbol (scopedname, block, domain);
- do_cleanups (cleanup);
+ result = lookup_global_symbol (scopedname.c_str (), block, domain);
}
}
return result;
\f
+/* la_sniff_from_mangled_name for Rust. */
+
+static int
+rust_sniff_from_mangled_name (const char *mangled, char **demangled)
+{
+ *demangled = gdb_demangle (mangled, DMGL_PARAMS | DMGL_ANSI);
+ return *demangled != NULL;
+}
+
+\f
+
static const struct exp_descriptor exp_descriptor_rust =
{
rust_print_subexp,
rust_evaluate_subexp
};
+static const char *rust_extensions[] =
+{
+ ".rs", NULL
+};
+
static const struct language_defn rust_language_defn =
{
"rust",
case_sensitive_on,
array_row_major,
macro_expansion_no,
+ rust_extensions,
&exp_descriptor_rust,
rust_parse,
rustyyerror,
rust_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
basic_lookup_transparent_type,/* lookup_transparent_type */
gdb_demangle, /* Language specific symbol demangler */
+ rust_sniff_from_mangled_name,
NULL, /* Language specific
class_name_from_physname */
c_op_print_tab, /* expression operators for printing */