Index: gdb/value.c |
diff --git a/gdb/value.c b/gdb/value.c |
index 218d4d5cbadf035deac53abf00cd8fe40233fb3c..a64e7e117ee64b83905146a0a4250b6650ad549d 100644 |
--- a/gdb/value.c |
+++ b/gdb/value.c |
@@ -1,6 +1,6 @@ |
/* Low level packing and unpacking of values for GDB, the GNU Debugger. |
- Copyright (C) 1986-2000, 2002-2012 Free Software Foundation, Inc. |
+ Copyright (C) 1986-2013 Free Software Foundation, Inc. |
This file is part of GDB. |
@@ -19,7 +19,7 @@ |
#include "defs.h" |
#include "arch-utils.h" |
-#include "gdb_string.h" |
+#include <string.h> |
#include "symtab.h" |
#include "gdbtypes.h" |
#include "value.h" |
@@ -42,6 +42,7 @@ |
#include <ctype.h> |
#include "tracepoint.h" |
#include "cp-abi.h" |
+#include "user-regs.h" |
/* Prototypes for exported functions. */ |
@@ -196,8 +197,13 @@ struct value |
reset, be sure to consider this use as well! */ |
unsigned int lazy : 1; |
- /* If nonzero, this is the value of a variable which does not |
- actually exist in the program. */ |
+ /* If nonzero, this is the value of a variable that does not |
+ actually exist in the program. If nonzero, and LVAL is |
+ lval_register, this is a register ($pc, $sp, etc., never a |
+ program variable) that has not been saved in the frame. All |
+ optimized-out values are treated pretty much the same, except |
+ registers have a different string representation and related |
+ error strings. */ |
unsigned int optimized_out : 1; |
/* If value is a variable, is it initialized or not. */ |
@@ -352,6 +358,26 @@ value_entirely_available (struct value *value) |
return 0; |
} |
+int |
+value_entirely_unavailable (struct value *value) |
+{ |
+ /* We can only tell whether the whole value is available when we try |
+ to read it. */ |
+ if (value->lazy) |
+ value_fetch_lazy (value); |
+ |
+ if (VEC_length (range_s, value->unavailable) == 1) |
+ { |
+ struct range *t = VEC_index (range_s, value->unavailable, 0); |
+ |
+ if (t->offset == 0 |
+ && t->length == TYPE_LENGTH (value_enclosing_type (value))) |
+ return 1; |
+ } |
+ |
+ return 0; |
+} |
+ |
void |
mark_value_bytes_unavailable (struct value *value, int offset, int length) |
{ |
@@ -543,9 +569,7 @@ value_available_contents_eq (const struct value *val1, int offset1, |
{ |
int idx1 = 0, idx2 = 0; |
- /* This routine is used by printing routines, where we should |
- already have read the value. Note that we only know whether a |
- value chunk is available if we've tried to read it. */ |
+ /* See function description in value.h. */ |
gdb_assert (!val1->lazy && !val2->lazy); |
while (length > 0) |
@@ -688,7 +712,7 @@ allocate_value_lazy (struct type *type) |
/* Allocate the contents of VAL if it has not been allocated yet. */ |
-void |
+static void |
allocate_value_contents (struct value *val) |
{ |
if (!val->contents) |
@@ -744,7 +768,7 @@ allocate_optimized_out_value (struct type *type) |
struct value *retval = allocate_value_lazy (type); |
set_value_optimized_out (retval, 1); |
- |
+ set_value_lazy (retval, 0); |
return retval; |
} |
@@ -811,7 +835,12 @@ value_parent (struct value *value) |
void |
set_value_parent (struct value *value, struct value *parent) |
{ |
+ struct value *old = value->parent; |
+ |
value->parent = parent; |
+ if (parent != NULL) |
+ value_incref (parent); |
+ value_free (old); |
} |
gdb_byte * |
@@ -878,11 +907,22 @@ value_actual_type (struct value *value, int resolve_simple_types, |
return result; |
} |
+void |
+error_value_optimized_out (void) |
+{ |
+ error (_("value has been optimized out")); |
+} |
+ |
static void |
require_not_optimized_out (const struct value *value) |
{ |
if (value->optimized_out) |
- error (_("value has been optimized out")); |
+ { |
+ if (value->lval == lval_register) |
+ error (_("register has not been saved in frame")); |
+ else |
+ error_value_optimized_out (); |
+ } |
} |
static void |
@@ -1037,20 +1077,30 @@ value_contents_equal (struct value *val1, struct value *val2) |
{ |
struct type *type1; |
struct type *type2; |
- int len; |
type1 = check_typedef (value_type (val1)); |
type2 = check_typedef (value_type (val2)); |
- len = TYPE_LENGTH (type1); |
- if (len != TYPE_LENGTH (type2)) |
+ if (TYPE_LENGTH (type1) != TYPE_LENGTH (type2)) |
return 0; |
- return (memcmp (value_contents (val1), value_contents (val2), len) == 0); |
+ return (memcmp (value_contents (val1), value_contents (val2), |
+ TYPE_LENGTH (type1)) == 0); |
} |
int |
value_optimized_out (struct value *value) |
{ |
+ /* We can only know if a value is optimized out once we have tried to |
+ fetch it. */ |
+ if (!value->optimized_out && value->lazy) |
+ value_fetch_lazy (value); |
+ |
+ return value->optimized_out; |
+} |
+ |
+int |
+value_optimized_out_const (const struct value *value) |
+{ |
return value->optimized_out; |
} |
@@ -1199,11 +1249,6 @@ deprecated_value_modifiable (struct value *value) |
{ |
return value->modifiable; |
} |
-void |
-deprecated_set_value_modifiable (struct value *value, int modifiable) |
-{ |
- value->modifiable = modifiable; |
-} |
/* Return a mark in the value chain. All values allocated after the |
mark is obtained (except for those released) are subject to being freed |
@@ -1404,9 +1449,7 @@ value_copy (struct value *arg) |
} |
val->unavailable = VEC_copy (range_s, arg->unavailable); |
- val->parent = arg->parent; |
- if (val->parent) |
- value_incref (val->parent); |
+ set_value_parent (val, arg->parent); |
if (VALUE_LVAL (val) == lval_computed) |
{ |
const struct lval_funcs *funcs = val->location.computed.funcs; |
@@ -2136,7 +2179,7 @@ function_command (char *command, int from_tty) |
static void |
function_destroyer (struct cmd_list_element *self, void *ignore) |
{ |
- xfree (self->name); |
+ xfree ((char *) self->name); |
xfree (self->doc); |
} |
@@ -2259,11 +2302,17 @@ show_convenience (char *ignore, int from_tty) |
printf_filtered (("\n")); |
} |
if (!varseen) |
- printf_unfiltered (_("No debugger convenience variables now defined.\n" |
- "Convenience variables have " |
- "names starting with \"$\";\n" |
- "use \"set\" as in \"set " |
- "$foo = 5\" to define them.\n")); |
+ { |
+ /* This text does not mention convenience functions on purpose. |
+ The user can't create them except via Python, and if Python support |
+ is installed this message will never be printed ($_streq will |
+ exist). */ |
+ printf_unfiltered (_("No debugger convenience variables now defined.\n" |
+ "Convenience variables have " |
+ "names starting with \"$\";\n" |
+ "use \"set\" as in \"set " |
+ "$foo = 5\" to define them.\n")); |
+ } |
} |
/* Extract a value as a C number (either long or double). |
@@ -2541,8 +2590,7 @@ unpack_pointer (struct type *type, const gdb_byte *valaddr) |
/* Get the value of the FIELDNO'th field (which must be static) of |
- TYPE. Return NULL if the field doesn't exist or has been |
- optimized out. */ |
+ TYPE. */ |
struct value * |
value_static_field (struct type *type, int fieldno) |
@@ -2569,7 +2617,7 @@ value_static_field (struct type *type, int fieldno) |
NULL, NULL); |
if (!msym) |
- return NULL; |
+ return allocate_optimized_out_value (type); |
else |
{ |
retval = value_at_lazy (TYPE_FIELD_TYPE (type, fieldno), |
@@ -2626,9 +2674,7 @@ value_primitive_field (struct value *arg1, int offset, |
description correctly. */ |
check_typedef (type); |
- if (value_optimized_out (arg1)) |
- v = allocate_optimized_out_value (type); |
- else if (TYPE_FIELD_BITSIZE (arg_type, fieldno)) |
+ if (TYPE_FIELD_BITSIZE (arg_type, fieldno)) |
{ |
/* Handle packed fields. |
@@ -2642,20 +2688,24 @@ value_primitive_field (struct value *arg1, int offset, |
int bitpos = TYPE_FIELD_BITPOS (arg_type, fieldno); |
int container_bitsize = TYPE_LENGTH (type) * 8; |
- v = allocate_value_lazy (type); |
- v->bitsize = TYPE_FIELD_BITSIZE (arg_type, fieldno); |
- if ((bitpos % container_bitsize) + v->bitsize <= container_bitsize |
- && TYPE_LENGTH (type) <= (int) sizeof (LONGEST)) |
- v->bitpos = bitpos % container_bitsize; |
+ if (arg1->optimized_out) |
+ v = allocate_optimized_out_value (type); |
else |
- v->bitpos = bitpos % 8; |
- v->offset = (value_embedded_offset (arg1) |
- + offset |
- + (bitpos - v->bitpos) / 8); |
- v->parent = arg1; |
- value_incref (v->parent); |
- if (!value_lazy (arg1)) |
- value_fetch_lazy (v); |
+ { |
+ v = allocate_value_lazy (type); |
+ v->bitsize = TYPE_FIELD_BITSIZE (arg_type, fieldno); |
+ if ((bitpos % container_bitsize) + v->bitsize <= container_bitsize |
+ && TYPE_LENGTH (type) <= (int) sizeof (LONGEST)) |
+ v->bitpos = bitpos % container_bitsize; |
+ else |
+ v->bitpos = bitpos % 8; |
+ v->offset = (value_embedded_offset (arg1) |
+ + offset |
+ + (bitpos - v->bitpos) / 8); |
+ set_value_parent (v, arg1); |
+ if (!value_lazy (arg1)) |
+ value_fetch_lazy (v); |
+ } |
} |
else if (fieldno < TYPE_N_BASECLASSES (arg_type)) |
{ |
@@ -2668,29 +2718,37 @@ value_primitive_field (struct value *arg1, int offset, |
if (VALUE_LVAL (arg1) == lval_register && value_lazy (arg1)) |
value_fetch_lazy (arg1); |
- /* We special case virtual inheritance here because this |
- requires access to the contents, which we would rather avoid |
- for references to ordinary fields of unavailable values. */ |
- if (BASETYPE_VIA_VIRTUAL (arg_type, fieldno)) |
- boffset = baseclass_offset (arg_type, fieldno, |
- value_contents (arg1), |
- value_embedded_offset (arg1), |
- value_address (arg1), |
- arg1); |
- else |
- boffset = TYPE_FIELD_BITPOS (arg_type, fieldno) / 8; |
- |
- if (value_lazy (arg1)) |
- v = allocate_value_lazy (value_enclosing_type (arg1)); |
+ /* The optimized_out flag is only set correctly once a lazy value is |
+ loaded, having just loaded some lazy values we should check the |
+ optimized out case now. */ |
+ if (arg1->optimized_out) |
+ v = allocate_optimized_out_value (type); |
else |
{ |
- v = allocate_value (value_enclosing_type (arg1)); |
- value_contents_copy_raw (v, 0, arg1, 0, |
- TYPE_LENGTH (value_enclosing_type (arg1))); |
+ /* We special case virtual inheritance here because this |
+ requires access to the contents, which we would rather avoid |
+ for references to ordinary fields of unavailable values. */ |
+ if (BASETYPE_VIA_VIRTUAL (arg_type, fieldno)) |
+ boffset = baseclass_offset (arg_type, fieldno, |
+ value_contents (arg1), |
+ value_embedded_offset (arg1), |
+ value_address (arg1), |
+ arg1); |
+ else |
+ boffset = TYPE_FIELD_BITPOS (arg_type, fieldno) / 8; |
+ |
+ if (value_lazy (arg1)) |
+ v = allocate_value_lazy (value_enclosing_type (arg1)); |
+ else |
+ { |
+ v = allocate_value (value_enclosing_type (arg1)); |
+ value_contents_copy_raw (v, 0, arg1, 0, |
+ TYPE_LENGTH (value_enclosing_type (arg1))); |
+ } |
+ v->type = type; |
+ v->offset = value_offset (arg1); |
+ v->embedded_offset = offset + value_embedded_offset (arg1) + boffset; |
} |
- v->type = type; |
- v->offset = value_offset (arg1); |
- v->embedded_offset = offset + value_embedded_offset (arg1) + boffset; |
} |
else |
{ |
@@ -2701,7 +2759,12 @@ value_primitive_field (struct value *arg1, int offset, |
if (VALUE_LVAL (arg1) == lval_register && value_lazy (arg1)) |
value_fetch_lazy (arg1); |
- if (value_lazy (arg1)) |
+ /* The optimized_out flag is only set correctly once a lazy value is |
+ loaded, having just loaded some lazy values we should check for |
+ the optimized out case now. */ |
+ if (arg1->optimized_out) |
+ v = allocate_optimized_out_value (type); |
+ else if (value_lazy (arg1)) |
v = allocate_value_lazy (type); |
else |
{ |
@@ -2745,18 +2808,18 @@ value_fn_field (struct value **arg1p, struct fn_field *f, |
struct type *ftype = TYPE_FN_FIELD_TYPE (f, j); |
const char *physname = TYPE_FN_FIELD_PHYSNAME (f, j); |
struct symbol *sym; |
- struct minimal_symbol *msym; |
+ struct bound_minimal_symbol msym; |
sym = lookup_symbol (physname, 0, VAR_DOMAIN, 0); |
if (sym != NULL) |
{ |
- msym = NULL; |
+ memset (&msym, 0, sizeof (msym)); |
} |
else |
{ |
gdb_assert (sym == NULL); |
- msym = lookup_minimal_symbol (physname, NULL, NULL); |
- if (msym == NULL) |
+ msym = lookup_bound_minimal_symbol (physname); |
+ if (msym.minsym == NULL) |
return NULL; |
} |
@@ -2769,12 +2832,12 @@ value_fn_field (struct value **arg1p, struct fn_field *f, |
{ |
/* The minimal symbol might point to a function descriptor; |
resolve it to the actual code address instead. */ |
- struct objfile *objfile = msymbol_objfile (msym); |
+ struct objfile *objfile = msym.objfile; |
struct gdbarch *gdbarch = get_objfile_arch (objfile); |
set_value_address (v, |
gdbarch_convert_from_func_ptr_addr |
- (gdbarch, SYMBOL_VALUE_ADDRESS (msym), ¤t_target)); |
+ (gdbarch, SYMBOL_VALUE_ADDRESS (msym.minsym), ¤t_target)); |
} |
if (arg1p) |
@@ -3140,10 +3203,7 @@ value_from_contents_and_address (struct type *type, |
if (valaddr == NULL) |
v = allocate_value_lazy (type); |
else |
- { |
- v = allocate_value (type); |
- memcpy (value_contents_raw (v), valaddr, TYPE_LENGTH (type)); |
- } |
+ v = value_from_contents (type, valaddr); |
set_value_address (v, address); |
VALUE_LVAL (v) = lval_memory; |
return v; |
@@ -3323,6 +3383,23 @@ coerce_array (struct value *arg) |
} |
+/* Return the return value convention that will be used for the |
+ specified type. */ |
+ |
+enum return_value_convention |
+struct_return_convention (struct gdbarch *gdbarch, |
+ struct value *function, struct type *value_type) |
+{ |
+ enum type_code code = TYPE_CODE (value_type); |
+ |
+ if (code == TYPE_CODE_ERROR) |
+ error (_("Function return type unknown.")); |
+ |
+ /* Probe the architecture for the return-value convention. */ |
+ return gdbarch_return_value (gdbarch, function, value_type, |
+ NULL, NULL, NULL); |
+} |
+ |
/* Return true if the function returning the specified type is using |
the convention of returning structures in memory (passing in the |
address as a hidden first parameter). */ |
@@ -3331,19 +3408,12 @@ int |
using_struct_return (struct gdbarch *gdbarch, |
struct value *function, struct type *value_type) |
{ |
- enum type_code code = TYPE_CODE (value_type); |
- |
- if (code == TYPE_CODE_ERROR) |
- error (_("Function return type unknown.")); |
- |
- if (code == TYPE_CODE_VOID) |
+ if (TYPE_CODE (value_type) == TYPE_CODE_VOID) |
/* A void return value is never in memory. See also corresponding |
code in "print_return_value". */ |
return 0; |
- /* Probe the architecture for the return-value convention. */ |
- return (gdbarch_return_value (gdbarch, function, value_type, |
- NULL, NULL, NULL) |
+ return (struct_return_convention (gdbarch, function, value_type) |
!= RETURN_VALUE_REGISTER_CONVENTION); |
} |
@@ -3363,18 +3433,227 @@ value_initialized (struct value *val) |
return val->initialized; |
} |
+/* Called only from the value_contents and value_contents_all() |
+ macros, if the current data for a variable needs to be loaded into |
+ value_contents(VAL). Fetches the data from the user's process, and |
+ clears the lazy flag to indicate that the data in the buffer is |
+ valid. |
+ |
+ If the value is zero-length, we avoid calling read_memory, which |
+ would abort. We mark the value as fetched anyway -- all 0 bytes of |
+ it. |
+ |
+ This function returns a value because it is used in the |
+ value_contents macro as part of an expression, where a void would |
+ not work. The value is ignored. */ |
+ |
+int |
+value_fetch_lazy (struct value *val) |
+{ |
+ gdb_assert (value_lazy (val)); |
+ allocate_value_contents (val); |
+ if (value_bitsize (val)) |
+ { |
+ /* To read a lazy bitfield, read the entire enclosing value. This |
+ prevents reading the same block of (possibly volatile) memory once |
+ per bitfield. It would be even better to read only the containing |
+ word, but we have no way to record that just specific bits of a |
+ value have been fetched. */ |
+ struct type *type = check_typedef (value_type (val)); |
+ enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type)); |
+ struct value *parent = value_parent (val); |
+ LONGEST offset = value_offset (val); |
+ LONGEST num; |
+ |
+ if (value_lazy (parent)) |
+ value_fetch_lazy (parent); |
+ |
+ if (!value_bits_valid (parent, |
+ TARGET_CHAR_BIT * offset + value_bitpos (val), |
+ value_bitsize (val))) |
+ set_value_optimized_out (val, 1); |
+ else if (!unpack_value_bits_as_long (value_type (val), |
+ value_contents_for_printing (parent), |
+ offset, |
+ value_bitpos (val), |
+ value_bitsize (val), parent, &num)) |
+ mark_value_bytes_unavailable (val, |
+ value_embedded_offset (val), |
+ TYPE_LENGTH (type)); |
+ else |
+ store_signed_integer (value_contents_raw (val), TYPE_LENGTH (type), |
+ byte_order, num); |
+ } |
+ else if (VALUE_LVAL (val) == lval_memory) |
+ { |
+ CORE_ADDR addr = value_address (val); |
+ struct type *type = check_typedef (value_enclosing_type (val)); |
+ |
+ if (TYPE_LENGTH (type)) |
+ read_value_memory (val, 0, value_stack (val), |
+ addr, value_contents_all_raw (val), |
+ TYPE_LENGTH (type)); |
+ } |
+ else if (VALUE_LVAL (val) == lval_register) |
+ { |
+ struct frame_info *frame; |
+ int regnum; |
+ struct type *type = check_typedef (value_type (val)); |
+ struct value *new_val = val, *mark = value_mark (); |
+ |
+ /* Offsets are not supported here; lazy register values must |
+ refer to the entire register. */ |
+ gdb_assert (value_offset (val) == 0); |
+ |
+ while (VALUE_LVAL (new_val) == lval_register && value_lazy (new_val)) |
+ { |
+ struct frame_id frame_id = VALUE_FRAME_ID (new_val); |
+ |
+ frame = frame_find_by_id (frame_id); |
+ regnum = VALUE_REGNUM (new_val); |
+ |
+ gdb_assert (frame != NULL); |
+ |
+ /* Convertible register routines are used for multi-register |
+ values and for interpretation in different types |
+ (e.g. float or int from a double register). Lazy |
+ register values should have the register's natural type, |
+ so they do not apply. */ |
+ gdb_assert (!gdbarch_convert_register_p (get_frame_arch (frame), |
+ regnum, type)); |
+ |
+ new_val = get_frame_register_value (frame, regnum); |
+ |
+ /* If we get another lazy lval_register value, it means the |
+ register is found by reading it from the next frame. |
+ get_frame_register_value should never return a value with |
+ the frame id pointing to FRAME. If it does, it means we |
+ either have two consecutive frames with the same frame id |
+ in the frame chain, or some code is trying to unwind |
+ behind get_prev_frame's back (e.g., a frame unwind |
+ sniffer trying to unwind), bypassing its validations. In |
+ any case, it should always be an internal error to end up |
+ in this situation. */ |
+ if (VALUE_LVAL (new_val) == lval_register |
+ && value_lazy (new_val) |
+ && frame_id_eq (VALUE_FRAME_ID (new_val), frame_id)) |
+ internal_error (__FILE__, __LINE__, |
+ _("infinite loop while fetching a register")); |
+ } |
+ |
+ /* If it's still lazy (for instance, a saved register on the |
+ stack), fetch it. */ |
+ if (value_lazy (new_val)) |
+ value_fetch_lazy (new_val); |
+ |
+ /* If the register was not saved, mark it optimized out. */ |
+ if (value_optimized_out (new_val)) |
+ set_value_optimized_out (val, 1); |
+ else |
+ { |
+ set_value_lazy (val, 0); |
+ value_contents_copy (val, value_embedded_offset (val), |
+ new_val, value_embedded_offset (new_val), |
+ TYPE_LENGTH (type)); |
+ } |
+ |
+ if (frame_debug) |
+ { |
+ struct gdbarch *gdbarch; |
+ frame = frame_find_by_id (VALUE_FRAME_ID (val)); |
+ regnum = VALUE_REGNUM (val); |
+ gdbarch = get_frame_arch (frame); |
+ |
+ fprintf_unfiltered (gdb_stdlog, |
+ "{ value_fetch_lazy " |
+ "(frame=%d,regnum=%d(%s),...) ", |
+ frame_relative_level (frame), regnum, |
+ user_reg_map_regnum_to_name (gdbarch, regnum)); |
+ |
+ fprintf_unfiltered (gdb_stdlog, "->"); |
+ if (value_optimized_out (new_val)) |
+ { |
+ fprintf_unfiltered (gdb_stdlog, " "); |
+ val_print_optimized_out (new_val, gdb_stdlog); |
+ } |
+ else |
+ { |
+ int i; |
+ const gdb_byte *buf = value_contents (new_val); |
+ |
+ if (VALUE_LVAL (new_val) == lval_register) |
+ fprintf_unfiltered (gdb_stdlog, " register=%d", |
+ VALUE_REGNUM (new_val)); |
+ else if (VALUE_LVAL (new_val) == lval_memory) |
+ fprintf_unfiltered (gdb_stdlog, " address=%s", |
+ paddress (gdbarch, |
+ value_address (new_val))); |
+ else |
+ fprintf_unfiltered (gdb_stdlog, " computed"); |
+ |
+ fprintf_unfiltered (gdb_stdlog, " bytes="); |
+ fprintf_unfiltered (gdb_stdlog, "["); |
+ for (i = 0; i < register_size (gdbarch, regnum); i++) |
+ fprintf_unfiltered (gdb_stdlog, "%02x", buf[i]); |
+ fprintf_unfiltered (gdb_stdlog, "]"); |
+ } |
+ |
+ fprintf_unfiltered (gdb_stdlog, " }\n"); |
+ } |
+ |
+ /* Dispose of the intermediate values. This prevents |
+ watchpoints from trying to watch the saved frame pointer. */ |
+ value_free_to_mark (mark); |
+ } |
+ else if (VALUE_LVAL (val) == lval_computed |
+ && value_computed_funcs (val)->read != NULL) |
+ value_computed_funcs (val)->read (val); |
+ /* Don't call value_optimized_out on val, doing so would result in a |
+ recursive call back to value_fetch_lazy, instead check the |
+ optimized_out flag directly. */ |
+ else if (val->optimized_out) |
+ /* Keep it optimized out. */; |
+ else |
+ internal_error (__FILE__, __LINE__, _("Unexpected lazy value type.")); |
+ |
+ set_value_lazy (val, 0); |
+ return 0; |
+} |
+ |
+/* Implementation of the convenience function $_isvoid. */ |
+ |
+static struct value * |
+isvoid_internal_fn (struct gdbarch *gdbarch, |
+ const struct language_defn *language, |
+ void *cookie, int argc, struct value **argv) |
+{ |
+ int ret; |
+ |
+ if (argc != 1) |
+ error (_("You must provide one argument for $_isvoid.")); |
+ |
+ ret = TYPE_CODE (value_type (argv[0])) == TYPE_CODE_VOID; |
+ |
+ return value_from_longest (builtin_type (gdbarch)->builtin_int, ret); |
+} |
+ |
void |
_initialize_values (void) |
{ |
add_cmd ("convenience", no_class, show_convenience, _("\ |
-Debugger convenience (\"$foo\") variables.\n\ |
-These variables are created when you assign them values;\n\ |
-thus, \"print $foo=1\" gives \"$foo\" the value 1. Values may be any type.\n\ |
+Debugger convenience (\"$foo\") variables and functions.\n\ |
+Convenience variables are created when you assign them values;\n\ |
+thus, \"set $foo=1\" gives \"$foo\" the value 1. Values may be any type.\n\ |
\n\ |
A few convenience variables are given values automatically:\n\ |
\"$_\"holds the last address examined with \"x\" or \"info lines\",\n\ |
-\"$__\" holds the contents of the last address examined with \"x\"."), |
- &showlist); |
+\"$__\" holds the contents of the last address examined with \"x\"." |
+#ifdef HAVE_PYTHON |
+"\n\n\ |
+Convenience functions are defined via the Python API." |
+#endif |
+ ), &showlist); |
+ add_alias_cmd ("conv", "convenience", no_class, 1, &showlist); |
add_cmd ("values", no_set_class, show_values, _("\ |
Elements of value history around item number IDX (or last ten)."), |
@@ -3390,4 +3669,10 @@ VARIABLE is already initialized.")); |
add_prefix_cmd ("function", no_class, function_command, _("\ |
Placeholder command for showing help on convenience functions."), |
&functionlist, "function ", 0, &cmdlist); |
+ |
+ add_internal_function ("_isvoid", _("\ |
+Check whether an expression is void.\n\ |
+Usage: $_isvoid (expression)\n\ |
+Return 1 if the expression is void, zero otherwise."), |
+ isvoid_internal_fn, NULL); |
} |