/* Python interface to types.
- Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc.
+ Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
This file is part of GDB.
#include "demangle.h"
#include "objfiles.h"
#include "language.h"
+#include "vec.h"
+#include "bcache.h"
typedef struct pyty_type_object
{
PyObject *result;
int i;
struct type *type = ((type_object *) self)->type;
+ volatile struct gdb_exception except;
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ CHECK_TYPEDEF (type);
+ }
+ GDB_PY_HANDLE_EXCEPTION (except);
/* We would like to make a tuple here, make fields immutable, and
then memoize the result (and perhaps make Field.type() lazy).
static PyObject *
typy_array (PyObject *self, PyObject *args)
{
- int n1, n2;
+ long n1, n2;
PyObject *n2_obj = NULL;
struct type *array = NULL;
struct type *type = ((type_object *) self)->type;
volatile struct gdb_exception except;
- if (! PyArg_ParseTuple (args, "i|O", &n1, &n2_obj))
+ if (! PyArg_ParseTuple (args, "l|O", &n1, &n2_obj))
return NULL;
if (n2_obj)
_("Array bound must be an integer"));
return NULL;
}
- n2 = (int) PyInt_AsLong (n2_obj);
- if (PyErr_Occurred ())
+
+ if (! gdb_py_int_as_long (n2_obj, &n2))
return NULL;
}
else
}
static struct type *
-typy_lookup_typename (char *type_name, struct block *block)
+typy_lookup_typename (const char *type_name, struct block *block)
{
struct type *type = NULL;
volatile struct gdb_exception except;
{
int i;
struct demangle_component *demangled;
+ struct demangle_parse_info *info;
const char *err;
struct type *argtype;
+ struct cleanup *cleanup;
if (TYPE_NAME (type) == NULL)
{
}
/* Note -- this is not thread-safe. */
- demangled = cp_demangled_name_to_comp (TYPE_NAME (type), &err);
- if (! demangled)
+ info = cp_demangled_name_to_comp (TYPE_NAME (type), &err);
+ if (! info)
{
PyErr_SetString (PyExc_RuntimeError, err);
return NULL;
}
+ demangled = info->tree;
+ cleanup = make_cleanup_cp_demangled_name_parse_free (info);
/* Strip off component names. */
while (demangled->type == DEMANGLE_COMPONENT_QUAL_NAME
if (demangled->type != DEMANGLE_COMPONENT_TEMPLATE)
{
+ do_cleanups (cleanup);
PyErr_SetString (PyExc_RuntimeError, _("Type is not a template."));
return NULL;
}
if (! demangled)
{
+ do_cleanups (cleanup);
PyErr_Format (PyExc_RuntimeError, _("No argument %d in template."),
argno);
return NULL;
}
argtype = typy_lookup_type (demangled->u.s_binary.left, block);
+ do_cleanups (cleanup);
if (! argtype)
return NULL;
}
}
- type = check_typedef (type);
- if (TYPE_CODE (type) == TYPE_CODE_REF)
- type = check_typedef (TYPE_TARGET_TYPE (type));
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ type = check_typedef (type);
+ if (TYPE_CODE (type) == TYPE_CODE_REF)
+ type = check_typedef (TYPE_TARGET_TYPE (type));
+ }
+ GDB_PY_HANDLE_EXCEPTION (except);
/* We might not have DW_TAG_template_*, so try to parse the type's
name. This is inefficient if we do not have a template type --
return result;
}
+/* An entry in the type-equality bcache. */
+
+typedef struct type_equality_entry
+{
+ struct type *type1, *type2;
+} type_equality_entry_d;
+
+DEF_VEC_O (type_equality_entry_d);
+
+/* A helper function to compare two strings. Returns 1 if they are
+ the same, 0 otherwise. Handles NULLs properly. */
+
+static int
+compare_strings (const char *s, const char *t)
+{
+ if (s == NULL && t != NULL)
+ return 0;
+ else if (s != NULL && t == NULL)
+ return 0;
+ else if (s == NULL && t== NULL)
+ return 1;
+ return strcmp (s, t) == 0;
+}
+
+/* A helper function for typy_richcompare that checks two types for
+ "deep" equality. Returns Py_EQ if the types are considered the
+ same, Py_NE otherwise. */
+
+static int
+check_types_equal (struct type *type1, struct type *type2,
+ VEC (type_equality_entry_d) **worklist)
+{
+ CHECK_TYPEDEF (type1);
+ CHECK_TYPEDEF (type2);
+
+ if (type1 == type2)
+ return Py_EQ;
+
+ if (TYPE_CODE (type1) != TYPE_CODE (type2)
+ || TYPE_LENGTH (type1) != TYPE_LENGTH (type2)
+ || TYPE_UNSIGNED (type1) != TYPE_UNSIGNED (type2)
+ || TYPE_NOSIGN (type1) != TYPE_NOSIGN (type2)
+ || TYPE_VARARGS (type1) != TYPE_VARARGS (type2)
+ || TYPE_VECTOR (type1) != TYPE_VECTOR (type2)
+ || TYPE_NOTTEXT (type1) != TYPE_NOTTEXT (type2)
+ || TYPE_INSTANCE_FLAGS (type1) != TYPE_INSTANCE_FLAGS (type2)
+ || TYPE_NFIELDS (type1) != TYPE_NFIELDS (type2))
+ return Py_NE;
+
+ if (!compare_strings (TYPE_TAG_NAME (type1), TYPE_TAG_NAME (type2)))
+ return Py_NE;
+ if (!compare_strings (TYPE_NAME (type1), TYPE_NAME (type2)))
+ return Py_NE;
+
+ if (TYPE_CODE (type1) == TYPE_CODE_RANGE)
+ {
+ if (memcmp (TYPE_RANGE_DATA (type1), TYPE_RANGE_DATA (type2),
+ sizeof (*TYPE_RANGE_DATA (type1))) != 0)
+ return Py_NE;
+ }
+ else
+ {
+ int i;
+
+ for (i = 0; i < TYPE_NFIELDS (type1); ++i)
+ {
+ const struct field *field1 = &TYPE_FIELD (type1, i);
+ const struct field *field2 = &TYPE_FIELD (type2, i);
+ struct type_equality_entry entry;
+
+ if (FIELD_ARTIFICIAL (*field1) != FIELD_ARTIFICIAL (*field2)
+ || FIELD_BITSIZE (*field1) != FIELD_BITSIZE (*field2)
+ || FIELD_LOC_KIND (*field1) != FIELD_LOC_KIND (*field2))
+ return Py_NE;
+ if (!compare_strings (FIELD_NAME (*field1), FIELD_NAME (*field2)))
+ return Py_NE;
+ switch (FIELD_LOC_KIND (*field1))
+ {
+ case FIELD_LOC_KIND_BITPOS:
+ if (FIELD_BITPOS (*field1) != FIELD_BITPOS (*field2))
+ return Py_NE;
+ break;
+ case FIELD_LOC_KIND_PHYSADDR:
+ if (FIELD_STATIC_PHYSADDR (*field1)
+ != FIELD_STATIC_PHYSADDR (*field2))
+ return Py_NE;
+ break;
+ case FIELD_LOC_KIND_PHYSNAME:
+ if (!compare_strings (FIELD_STATIC_PHYSNAME (*field1),
+ FIELD_STATIC_PHYSNAME (*field2)))
+ return Py_NE;
+ break;
+ }
+
+ entry.type1 = FIELD_TYPE (*field1);
+ entry.type2 = FIELD_TYPE (*field2);
+ VEC_safe_push (type_equality_entry_d, *worklist, &entry);
+ }
+ }
+
+ if (TYPE_TARGET_TYPE (type1) != NULL)
+ {
+ struct type_equality_entry entry;
+ int added;
+
+ if (TYPE_TARGET_TYPE (type2) == NULL)
+ return Py_NE;
+
+ entry.type1 = TYPE_TARGET_TYPE (type1);
+ entry.type2 = TYPE_TARGET_TYPE (type2);
+ VEC_safe_push (type_equality_entry_d, *worklist, &entry);
+ }
+ else if (TYPE_TARGET_TYPE (type2) != NULL)
+ return Py_NE;
+
+ return Py_EQ;
+}
+
+/* Check types on a worklist for equality. Returns Py_NE if any pair
+ is not equal, Py_EQ if they are all considered equal. */
+
+static int
+check_types_worklist (VEC (type_equality_entry_d) **worklist,
+ struct bcache *cache)
+{
+ while (!VEC_empty (type_equality_entry_d, *worklist))
+ {
+ struct type_equality_entry entry;
+ int added;
+
+ entry = *VEC_last (type_equality_entry_d, *worklist);
+ VEC_pop (type_equality_entry_d, *worklist);
+
+ /* If the type pair has already been visited, we know it is
+ ok. */
+ bcache_full (&entry, sizeof (entry), cache, &added);
+ if (!added)
+ continue;
+
+ if (check_types_equal (entry.type1, entry.type2, worklist) == Py_NE)
+ return Py_NE;
+ }
+
+ return Py_EQ;
+}
+
+/* Implement the richcompare method. */
+
+static PyObject *
+typy_richcompare (PyObject *self, PyObject *other, int op)
+{
+ int result = Py_NE;
+ struct type *type1 = type_object_to_type (self);
+ struct type *type2 = type_object_to_type (other);
+ volatile struct gdb_exception except;
+
+ /* We can only compare ourselves to another Type object, and only
+ for equality or inequality. */
+ if (type2 == NULL || (op != Py_EQ && op != Py_NE))
+ {
+ Py_INCREF (Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+
+ if (type1 == type2)
+ result = Py_EQ;
+ else
+ {
+ struct bcache *cache;
+ VEC (type_equality_entry_d) *worklist = NULL;
+ struct type_equality_entry entry;
+
+ cache = bcache_xmalloc (NULL, NULL);
+
+ entry.type1 = type1;
+ entry.type2 = type2;
+ VEC_safe_push (type_equality_entry_d, worklist, &entry);
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ result = check_types_worklist (&worklist, cache);
+ }
+ if (except.reason < 0)
+ result = Py_NE;
+
+ bcache_xfree (cache);
+ VEC_free (type_equality_entry_d, worklist);
+ }
+
+ if (op == result)
+ Py_RETURN_TRUE;
+ Py_RETURN_FALSE;
+}
+
\f
static const struct objfile_data *typy_objfile_data_key;
gdbpy_lookup_type (PyObject *self, PyObject *args, PyObject *kw)
{
static char *keywords[] = { "name", "block", NULL };
- char *type_name = NULL;
+ const char *type_name = NULL;
struct type *type = NULL;
PyObject *block_obj = NULL;
struct block *block = NULL;
"GDB type object", /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
- 0, /* tp_richcompare */
+ typy_richcompare, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */