aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog11
-rw-r--r--gdb/python/py-type.c155
2 files changed, 137 insertions, 29 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 98f7c7d..8328273 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,14 @@
+2011-11-15 Paul Koning <paul_koning@dell.com>
+
+ * python/py-type.c (typy_get_composite): New function.
+ (typy_nonzero): New function.
+ (typy_values): Rename from typy_fields.
+ (typy_fields): New function.
+ (typy_length): Raise exception if not struct, union, or enum type.
+ (typy_getitem): Ditto.
+ (typy_has_key): Ditto.
+ (typy_make_iter): Ditto.
+
2011-11-15 Doug Evans <dje@google.com>
* NEWS: Mention new parameter basenames-may-differ.
diff --git a/gdb/python/py-type.c b/gdb/python/py-type.c
index 44a2223..f76b1c7 100644
--- a/gdb/python/py-type.c
+++ b/gdb/python/py-type.c
@@ -327,11 +327,41 @@ typy_fields_items (PyObject *self, enum gdbpy_iter_kind kind)
/* Return a sequence of all fields. Each field is a gdb.Field object. */
static PyObject *
-typy_fields (PyObject *self, PyObject *args)
+typy_values (PyObject *self, PyObject *args)
{
return typy_fields_items (self, iter_values);
}
+/* Return a sequence of all fields. Each field is a gdb.Field object.
+ This method is similar to typy_values, except where the supplied
+ gdb.Type is an array, in which case it returns a list of one entry
+ which is a gdb.Field object for a range (the array bounds). */
+
+static PyObject *
+typy_fields (PyObject *self, PyObject *args)
+{
+ struct type *type = ((type_object *) self)->type;
+ PyObject *r, *rl;
+
+ if (TYPE_CODE (type) != TYPE_CODE_ARRAY)
+ return typy_fields_items (self, iter_values);
+
+ /* Array type. Handle this as a special case because the common
+ machinery wants struct or union or enum types. Build a list of
+ one entry which is the range for the array. */
+ r = convert_field (type, 0);
+ if (r == NULL)
+ return NULL;
+
+ rl = Py_BuildValue ("[O]", r);
+ if (rl == NULL)
+ {
+ Py_DECREF (r);
+ }
+
+ return rl;
+}
+
/* Return a sequence of all field names. Each field is a gdb.Field object. */
static PyObject *
@@ -369,6 +399,48 @@ typy_strip_typedefs (PyObject *self, PyObject *args)
return type_to_type_object (check_typedef (type));
}
+/* Strip typedefs and pointers/reference from a type. Then check that
+ it is a struct, union, or enum type. If not, raise TypeError. */
+
+static struct type *
+typy_get_composite (struct type *type)
+{
+ volatile struct gdb_exception except;
+
+ for (;;)
+ {
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ CHECK_TYPEDEF (type);
+ }
+ /* Don't use GDB_PY_HANDLE_EXCEPTION here because that returns
+ a (NULL) pointer of the wrong type. */
+ if (except.reason < 0)
+ {
+ gdbpy_convert_exception (except);
+ return NULL;
+ }
+
+ if (TYPE_CODE (type) != TYPE_CODE_PTR
+ && TYPE_CODE (type) != TYPE_CODE_REF)
+ break;
+ type = TYPE_TARGET_TYPE (type);
+ }
+
+ /* If this is not a struct, union, or enum type, raise TypeError
+ exception. */
+ if (TYPE_CODE (type) != TYPE_CODE_STRUCT
+ && TYPE_CODE (type) != TYPE_CODE_UNION
+ && TYPE_CODE (type) != TYPE_CODE_ENUM)
+ {
+ PyErr_SetString (PyExc_TypeError,
+ "Type is not a structure, union, or enum type.");
+ return NULL;
+ }
+
+ return type;
+}
+
/* Return an array type. */
static PyObject *
@@ -1143,9 +1215,23 @@ typy_length (PyObject *self)
{
struct type *type = ((type_object *) self)->type;
+ type = typy_get_composite (type);
+ if (type == NULL)
+ return -1;
+
return TYPE_NFIELDS (type);
}
+/* Implements boolean evaluation of gdb.Type. Handle this like other
+ Python objects that don't have a meaningful truth value -- all
+ values are true. */
+
+static int
+typy_nonzero (PyObject *self)
+{
+ return 1;
+}
+
/* Return a gdb.Field object for the field named by the argument. */
static PyObject *
@@ -1164,20 +1250,10 @@ typy_getitem (PyObject *self, PyObject *key)
using lookup_struct_elt_type, portions of that function are
copied here. */
- for (;;)
- {
- TRY_CATCH (except, RETURN_MASK_ALL)
- {
- CHECK_TYPEDEF (type);
- }
- GDB_PY_HANDLE_EXCEPTION (except);
-
- if (TYPE_CODE (type) != TYPE_CODE_PTR
- && TYPE_CODE (type) != TYPE_CODE_REF)
- break;
- type = TYPE_TARGET_TYPE (type);
- }
-
+ type = typy_get_composite (type);
+ if (type == NULL)
+ return NULL;
+
for (i = 0; i < TYPE_NFIELDS (type); i++)
{
char *t_field_name = TYPE_FIELD_NAME (type, i);
@@ -1235,18 +1311,9 @@ typy_has_key (PyObject *self, PyObject *args)
using lookup_struct_elt_type, portions of that function are
copied here. */
- for (;;)
- {
- TRY_CATCH (except, RETURN_MASK_ALL)
- {
- CHECK_TYPEDEF (type);
- }
- GDB_PY_HANDLE_EXCEPTION (except);
- if (TYPE_CODE (type) != TYPE_CODE_PTR
- && TYPE_CODE (type) != TYPE_CODE_REF)
- break;
- type = TYPE_TARGET_TYPE (type);
- }
+ type = typy_get_composite (type);
+ if (type == NULL)
+ return NULL;
for (i = 0; i < TYPE_NFIELDS (type); i++)
{
@@ -1265,6 +1332,10 @@ typy_make_iter (PyObject *self, enum gdbpy_iter_kind kind)
{
typy_iterator_object *typy_iter_obj;
+ /* Check that "self" is a structure or union type. */
+ if (typy_get_composite (((type_object *) self)->type) == NULL)
+ return NULL;
+
typy_iter_obj = PyObject_New (typy_iterator_object,
&type_iterator_object_type);
if (typy_iter_obj == NULL)
@@ -1508,7 +1579,7 @@ Return the type of a template argument." },
{ "unqualified", typy_unqualified, METH_NOARGS,
"unqualified () -> Type\n\
Return a variant of this type without const or volatile attributes." },
- { "values", typy_fields, METH_NOARGS,
+ { "values", typy_values, METH_NOARGS,
"values () -> list\n\
Return a list holding all the fields of this type.\n\
Each field is a gdb.Field object." },
@@ -1518,6 +1589,32 @@ Return a volatile variant of this type" },
{ NULL }
};
+static PyNumberMethods type_object_as_number = {
+ NULL, /* nb_add */
+ NULL, /* nb_subtract */
+ NULL, /* nb_multiply */
+ NULL, /* nb_divide */
+ NULL, /* nb_remainder */
+ NULL, /* nb_divmod */
+ NULL, /* nb_power */
+ NULL, /* nb_negative */
+ NULL, /* nb_positive */
+ NULL, /* nb_absolute */
+ typy_nonzero, /* nb_nonzero */
+ NULL, /* nb_invert */
+ NULL, /* nb_lshift */
+ NULL, /* nb_rshift */
+ NULL, /* nb_and */
+ NULL, /* nb_xor */
+ NULL, /* nb_or */
+ NULL, /* nb_coerce */
+ NULL, /* nb_int */
+ NULL, /* nb_long */
+ NULL, /* nb_float */
+ NULL, /* nb_oct */
+ NULL /* nb_hex */
+};
+
static PyMappingMethods typy_mapping = {
typy_length,
typy_getitem,
@@ -1537,7 +1634,7 @@ static PyTypeObject type_object_type =
0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
- 0, /*tp_as_number*/
+ &type_object_as_number, /*tp_as_number*/
0, /*tp_as_sequence*/
&typy_mapping, /*tp_as_mapping*/
0, /*tp_hash */