/* Rust language support routines for GDB, the GNU debugger.
- Copyright (C) 2016 Free Software Foundation, Inc.
+ Copyright (C) 2016-2017 Free Software Foundation, Inc.
This file is part of GDB.
#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 *name, *tail, *token;
+ char *tail, *token, *saveptr = NULL;
unsigned long fieldno;
struct type *member_type;
LONGEST value;
/* Optimized enums have only one field. */
member_type = TYPE_FIELD_TYPE (type, 0);
- name = xstrdup (TYPE_FIELD_NAME (type, 0));
- cleanup = make_cleanup (xfree, name);
- tail = name + strlen (RUST_ENUM_PREFIX);
+ gdb::unique_xmalloc_ptr<char> name (xstrdup (TYPE_FIELD_NAME (type, 0)));
+ tail = name.get () + strlen (RUST_ENUM_PREFIX);
/* The location of the value that doubles as a discriminant is
stored in the name of the field, as
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. */
- while ((token = strsep (&tail, "$")) != NULL)
+ for (token = strtok_r (tail, "$", &saveptr);
+ token != NULL;
+ token = strtok_r (NULL, "$", &saveptr))
{
if (sscanf (token, "%lu", &fieldno) != 1)
{
member_type = TYPE_FIELD_TYPE (member_type, fieldno);
}
- if (token >= name + strlen (TYPE_FIELD_NAME (type, 0)))
+ 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), "::", token, (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 (TYPE_FIELD_TYPE (type, 0))),
- (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 = std::string (TYPE_NAME (type)) + "::" + last;
+ 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:
/* 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);
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;
}
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);
}
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;