/* Python interface to values.
- Copyright (C) 2008-2017 Free Software Foundation, Inc.
+ Copyright (C) 2008-2019 Free Software Foundation, Inc.
This file is part of GDB.
#include "charset.h"
#include "value.h"
#include "language.h"
-#include "dfp.h"
+#include "target-float.h"
#include "valprint.h"
#include "infcall.h"
#include "expression.h"
if (self->next)
self->next->prev = self->prev;
- value_free (self->value);
-
- if (self->address)
- /* Use braces to appease gcc warning. *sigh* */
- {
- Py_DECREF (self->address);
- }
-
- if (self->type)
- {
- Py_DECREF (self->type);
- }
+ value_decref (self->value);
+ Py_XDECREF (self->address);
+ Py_XDECREF (self->type);
Py_XDECREF (self->dynamic_type);
Py_TYPE (self)->tp_free (self);
return NULL;
}
- value_obj->value = value;
- release_value_or_incref (value);
+ value_obj->value = release_value (value).release ();
value_obj->address = NULL;
value_obj->type = NULL;
value_obj->dynamic_type = NULL;
res_val = value_ind (self_val);
break;
case TYPE_CODE_REF:
+ case TYPE_CODE_RVALUE_REF:
res_val = coerce_ref (self_val);
break;
default:
/* Return a value which is a reference to the value. */
static PyObject *
-valpy_reference_value (PyObject *self, PyObject *args)
+valpy_reference_value (PyObject *self, PyObject *args, enum type_code refcode)
{
PyObject *result = NULL;
scoped_value_mark free_values;
self_val = ((value_object *) self)->value;
- result = value_to_value_object (value_ref (self_val));
+ result = value_to_value_object (value_ref (self_val, refcode));
}
CATCH (except, RETURN_MASK_ALL)
{
return result;
}
+static PyObject *
+valpy_lvalue_reference_value (PyObject *self, PyObject *args)
+{
+ return valpy_reference_value (self, args, TYPE_CODE_REF);
+}
+
+static PyObject *
+valpy_rvalue_reference_value (PyObject *self, PyObject *args)
+{
+ return valpy_reference_value (self, args, TYPE_CODE_RVALUE_REF);
+}
+
/* Return a "const" qualified version of the value. */
static PyObject *
type = value_type (val);
type = check_typedef (type);
- if (((TYPE_CODE (type) == TYPE_CODE_PTR)
- || (TYPE_CODE (type) == TYPE_CODE_REF))
+ if (((TYPE_CODE (type) == TYPE_CODE_PTR) || TYPE_IS_REFERENCE (type))
&& (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_STRUCT))
{
struct value *target;
if (was_pointer)
type = lookup_pointer_type (type);
else
- type = lookup_reference_type (type);
+ type = lookup_lvalue_reference_type (type);
}
}
else if (TYPE_CODE (type) == TYPE_CODE_STRUCT)
A lazy string is a pointer to a string with an optional encoding and
length. If ENCODING is not given, encoding is set to None. If an
ENCODING is provided the encoding parameter is set to ENCODING, but
- the string is not encoded. If LENGTH is provided then the length
- parameter is set to LENGTH, otherwise length will be set to -1 (first
- null of appropriate with). */
+ the string is not encoded.
+ If LENGTH is provided then the length parameter is set to LENGTH.
+ Otherwise if the value is an array of known length then the array's length
+ is used. Otherwise the length will be set to -1 (meaning first null of
+ appropriate with).
+
+ Note: In order to not break any existing uses this allows creating
+ lazy strings from anything. PR 20769. E.g.,
+ gdb.parse_and_eval("my_int_variable").lazy_string().
+ "It's easier to relax restrictions than it is to impose them after the
+ fact." So we should be flagging any unintended uses as errors, but it's
+ perhaps too late for that. */
+
static PyObject *
valpy_lazy_string (PyObject *self, PyObject *args, PyObject *kw)
{
gdb_py_longest length = -1;
struct value *value = ((value_object *) self)->value;
const char *user_encoding = NULL;
- static char *keywords[] = { "encoding", "length", NULL };
+ static const char *keywords[] = { "encoding", "length", NULL };
PyObject *str_obj = NULL;
- if (!PyArg_ParseTupleAndKeywords (args, kw, "|s" GDB_PY_LL_ARG, keywords,
- &user_encoding, &length))
+ if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "|s" GDB_PY_LL_ARG,
+ keywords, &user_encoding, &length))
return NULL;
+ if (length < -1)
+ {
+ PyErr_SetString (PyExc_ValueError, _("Invalid length."));
+ return NULL;
+ }
+
TRY
{
scoped_value_mark free_values;
+ struct type *type, *realtype;
+ CORE_ADDR addr;
+
+ type = value_type (value);
+ realtype = check_typedef (type);
- if (TYPE_CODE (value_type (value)) == TYPE_CODE_PTR)
- value = value_ind (value);
+ switch (TYPE_CODE (realtype))
+ {
+ case TYPE_CODE_ARRAY:
+ {
+ LONGEST array_length = -1;
+ LONGEST low_bound, high_bound;
+
+ /* PR 20786: There's no way to specify an array of length zero.
+ Record a length of [0,-1] which is how Ada does it. Anything
+ we do is broken, but this one possible solution. */
+ if (get_array_bounds (realtype, &low_bound, &high_bound))
+ array_length = high_bound - low_bound + 1;
+ if (length == -1)
+ length = array_length;
+ else if (array_length == -1)
+ {
+ type = lookup_array_range_type (TYPE_TARGET_TYPE (realtype),
+ 0, length - 1);
+ }
+ else if (length != array_length)
+ {
+ /* We need to create a new array type with the
+ specified length. */
+ if (length > array_length)
+ error (_("Length is larger than array size."));
+ type = lookup_array_range_type (TYPE_TARGET_TYPE (realtype),
+ low_bound,
+ low_bound + length - 1);
+ }
+ addr = value_address (value);
+ break;
+ }
+ case TYPE_CODE_PTR:
+ /* If a length is specified we defer creating an array of the
+ specified width until we need to. */
+ addr = value_as_address (value);
+ break;
+ default:
+ /* Should flag an error here. PR 20769. */
+ addr = value_address (value);
+ break;
+ }
- str_obj = gdbpy_create_lazy_string_object (value_address (value), length,
- user_encoding,
- value_type (value));
+ str_obj = gdbpy_create_lazy_string_object (addr, length, user_encoding,
+ type);
}
CATCH (except, RETURN_MASK_ALL)
{
valpy_string (PyObject *self, PyObject *args, PyObject *kw)
{
int length = -1;
- gdb_byte *buffer;
+ gdb::unique_xmalloc_ptr<gdb_byte> buffer;
struct value *value = ((value_object *) self)->value;
- PyObject *unicode;
const char *encoding = NULL;
const char *errors = NULL;
const char *user_encoding = NULL;
const char *la_encoding = NULL;
struct type *char_type;
- static char *keywords[] = { "encoding", "errors", "length", NULL };
+ static const char *keywords[] = { "encoding", "errors", "length", NULL };
- if (!PyArg_ParseTupleAndKeywords (args, kw, "|ssi", keywords,
- &user_encoding, &errors, &length))
+ if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "|ssi", keywords,
+ &user_encoding, &errors, &length))
return NULL;
TRY
END_CATCH
encoding = (user_encoding && *user_encoding) ? user_encoding : la_encoding;
- unicode = PyUnicode_Decode ((const char *) buffer,
- length * TYPE_LENGTH (char_type),
- encoding, errors);
- xfree (buffer);
-
- return unicode;
+ return PyUnicode_Decode ((const char *) buffer.get (),
+ length * TYPE_LENGTH (char_type),
+ encoding, errors);
}
/* A helper function that implements the various cast operators. */
{
val_type = value_type (v);
val_type = check_typedef (val_type);
- if (TYPE_CODE (val_type) == TYPE_CODE_REF
- || TYPE_CODE (val_type) == TYPE_CODE_PTR)
+ if (TYPE_IS_REFERENCE (val_type) || TYPE_CODE (val_type) == TYPE_CODE_PTR)
val_type = check_typedef (TYPE_TARGET_TYPE (val_type));
type_code = TYPE_CODE (val_type);
if (TYPE_CODE (val_type) == TYPE_CODE_PTR)
res_val = value_cast (lookup_pointer_type (base_class_type), tmp);
else if (TYPE_CODE (val_type) == TYPE_CODE_REF)
- res_val = value_cast (lookup_reference_type (base_class_type), tmp);
+ res_val = value_cast (lookup_lvalue_reference_type (base_class_type),
+ tmp);
+ else if (TYPE_CODE (val_type) == TYPE_CODE_RVALUE_REF)
+ res_val = value_cast (lookup_rvalue_reference_type (base_class_type),
+ tmp);
else
res_val = value_cast (base_class_type, tmp);
}
struct value *function = ((value_object *) self)->value;
struct value **vargs = NULL;
struct type *ftype = NULL;
- struct value *mark = value_mark ();
PyObject *result = NULL;
TRY
TRY
{
scoped_value_mark free_values;
- struct value *return_value;
- return_value = call_function_by_hand (function, args_count, vargs);
+ value *return_value
+ = call_function_by_hand (function, NULL,
+ gdb::make_array_view (vargs, args_count));
result = value_to_value_object (return_value);
}
CATCH (except, RETURN_MASK_ALL)
/* If TYPE is a reference, return the target; otherwise return TYPE. */
#define STRIP_REFERENCE(TYPE) \
- ((TYPE_CODE (TYPE) == TYPE_CODE_REF) ? (TYPE_TARGET_TYPE (TYPE)) : (TYPE))
+ (TYPE_IS_REFERENCE (TYPE) ? (TYPE_TARGET_TYPE (TYPE)) : (TYPE))
/* Helper for valpy_binop. Returns a value object which is the result
of applying the operation specified by OPCODE to the given
if (is_integral_type (type) || TYPE_CODE (type) == TYPE_CODE_PTR)
nonzero = !!value_as_long (self_value->value);
- else if (TYPE_CODE (type) == TYPE_CODE_FLT)
- nonzero = value_as_double (self_value->value) != 0;
- else if (TYPE_CODE (type) == TYPE_CODE_DECFLOAT)
- nonzero = !decimal_is_zero (value_contents (self_value->value),
- TYPE_LENGTH (type),
- gdbarch_byte_order (get_type_arch (type)));
+ else if (is_floating_value (self_value->value))
+ nonzero = !target_float_is_zero (value_contents (self_value->value),
+ type);
else
/* All other values are True. */
nonzero = 1;
int result;
struct value *value_other;
struct value *value_self;
- struct cleanup *cleanup;
scoped_value_mark free_values;
TRY
{
- if (!is_integral_type (type))
+ if (is_floating_value (value))
+ {
+ type = builtin_type_pylong;
+ value = value_cast (type, value);
+ }
+
+ if (!is_integral_type (type)
+ && TYPE_CODE (type) != TYPE_CODE_PTR)
error (_("Cannot convert value to int."));
l = value_as_long (value);
}
END_CATCH
- return gdb_py_object_from_longest (l);
+ if (TYPE_UNSIGNED (type))
+ return gdb_py_object_from_ulongest (l).release ();
+ else
+ return gdb_py_object_from_longest (l).release ();
}
#endif
TRY
{
+ if (is_floating_value (value))
+ {
+ type = builtin_type_pylong;
+ value = value_cast (type, value);
+ }
+
type = check_typedef (type);
if (!is_integral_type (type)
{
type = check_typedef (type);
- if (TYPE_CODE (type) != TYPE_CODE_FLT)
+ if (TYPE_CODE (type) == TYPE_CODE_FLT && is_floating_value (value))
+ d = target_float_to_host_double (value_contents (value), type);
+ else if (TYPE_CODE (type) == TYPE_CODE_INT)
+ {
+ /* Note that valpy_long accepts TYPE_CODE_PTR and some
+ others here here -- but casting a pointer or bool to a
+ float seems wrong. */
+ d = value_as_long (value);
+ }
+ else
error (_("Cannot convert value to float."));
-
- d = value_as_double (value);
}
CATCH (except, RETURN_MASK_ALL)
{
val_obj = PyObject_New (value_object, &value_object_type);
if (val_obj != NULL)
{
- val_obj->value = val;
- release_value_or_incref (val);
+ val_obj->value = release_value (val).release ();
val_obj->address = NULL;
val_obj->type = NULL;
val_obj->dynamic_type = NULL;
ULONGEST instead. */
if (PyErr_ExceptionMatches (PyExc_OverflowError))
{
- PyObject *etype, *evalue, *etraceback;
-
- PyErr_Fetch (&etype, &evalue, &etraceback);
+ gdbpy_err_fetch fetched_error;
gdbpy_ref<> zero (PyInt_FromLong (0));
/* Check whether obj is positive. */
value = value_from_ulongest (builtin_type_upylong, ul);
}
else
- /* There's nothing we can do. */
- PyErr_Restore (etype, evalue, etraceback);
+ {
+ /* There's nothing we can do. */
+ fetched_error.restore ();
+ }
}
}
else
double d = PyFloat_AsDouble (obj);
if (! PyErr_Occurred ())
- value = value_from_double (builtin_type_pyfloat, d);
+ {
+ value = allocate_value (builtin_type_pyfloat);
+ target_float_from_host_double (value_contents_raw (value),
+ value_type (value), d);
+ }
}
else if (gdbpy_is_string (obj))
{
}
CATCH (except, RETURN_MASK_ALL)
{
- PyErr_Format (except.reason == RETURN_QUIT
- ? PyExc_KeyboardInterrupt : PyExc_RuntimeError,
- "%s", except.message);
+ gdbpy_convert_exception (except);
return NULL;
}
END_CATCH
return value_to_value_object (res_val);
}
+/* Return the value of a convenience variable. */
+PyObject *
+gdbpy_convenience_variable (PyObject *self, PyObject *args)
+{
+ const char *varname;
+ struct value *res_val = NULL;
+
+ if (!PyArg_ParseTuple (args, "s", &varname))
+ return NULL;
+
+ TRY
+ {
+ struct internalvar *var = lookup_only_internalvar (varname);
+
+ if (var != NULL)
+ {
+ res_val = value_of_internalvar (python_gdbarch, var);
+ if (TYPE_CODE (value_type (res_val)) == TYPE_CODE_VOID)
+ res_val = NULL;
+ }
+ }
+ CATCH (except, RETURN_MASK_ALL)
+ {
+ GDB_PY_HANDLE_EXCEPTION (except);
+ }
+ END_CATCH
+
+ if (res_val == NULL)
+ Py_RETURN_NONE;
+
+ return value_to_value_object (res_val);
+}
+
+/* Set the value of a convenience variable. */
+PyObject *
+gdbpy_set_convenience_variable (PyObject *self, PyObject *args)
+{
+ const char *varname;
+ PyObject *value_obj;
+ struct value *value = NULL;
+
+ if (!PyArg_ParseTuple (args, "sO", &varname, &value_obj))
+ return NULL;
+
+ /* None means to clear the variable. */
+ if (value_obj != Py_None)
+ {
+ value = convert_value_from_python (value_obj);
+ if (value == NULL)
+ return NULL;
+ }
+
+ TRY
+ {
+ if (value == NULL)
+ {
+ struct internalvar *var = lookup_only_internalvar (varname);
+
+ if (var != NULL)
+ clear_internalvar (var);
+ }
+ else
+ {
+ struct internalvar *var = lookup_internalvar (varname);
+
+ set_internalvar (var, value);
+ }
+ }
+ CATCH (except, RETURN_MASK_ALL)
+ {
+ GDB_PY_HANDLE_EXCEPTION (except);
+ }
+ END_CATCH
+
+ Py_RETURN_NONE;
+}
+
/* Returns 1 in OBJ is a gdb.Value object, 0 otherwise. */
int
\f
-static PyGetSetDef value_object_getset[] = {
+static gdb_PyGetSetDef value_object_getset[] = {
{ "address", valpy_get_address, NULL, "The address of the value.",
NULL },
{ "is_optimized_out", valpy_get_is_optimized_out, NULL,
{ "dereference", valpy_dereference, METH_NOARGS, "Dereferences the value." },
{ "referenced_value", valpy_referenced_value, METH_NOARGS,
"Return the value referenced by a TYPE_CODE_REF or TYPE_CODE_PTR value." },
- { "reference_value", valpy_reference_value, METH_NOARGS,
+ { "reference_value", valpy_lvalue_reference_value, METH_NOARGS,
"Return a value of type TYPE_CODE_REF referencing this value." },
+ { "rvalue_reference_value", valpy_rvalue_reference_value, METH_NOARGS,
+ "Return a value of type TYPE_CODE_RVALUE_REF referencing this value." },
{ "const_value", valpy_const_value, METH_NOARGS,
"Return a 'const' qualied version of the same value." },
{ "lazy_string", (PyCFunction) valpy_lazy_string,