]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - gdb/python/py-type.c
Update copyright year range in all GDB files.
[thirdparty/binutils-gdb.git] / gdb / python / py-type.c
index 44a20386e5bf1df60eebbd4908efcb8a9f5e7dc6..b19cad098a46410262080cd2b1aaa8f8f1729ea6 100644 (file)
@@ -1,6 +1,6 @@
 /* Python interface to types.
 
-   Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+   Copyright (C) 2008-2020 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -19,7 +19,6 @@
 
 #include "defs.h"
 #include "value.h"
-#include "exceptions.h"
 #include "python-internal.h"
 #include "charset.h"
 #include "gdbtypes.h"
@@ -27,9 +26,7 @@
 #include "demangle.h"
 #include "objfiles.h"
 #include "language.h"
-#include "vec.h"
-#include "bcache.h"
-#include "dwarf2loc.h"
+#include "typeprint.h"
 
 typedef struct pyty_type_object
 {
@@ -43,7 +40,8 @@ typedef struct pyty_type_object
   struct pyty_type_object *next;
 } type_object;
 
-static PyTypeObject type_object_type;
+extern PyTypeObject type_object_type
+    CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("type_object");
 
 /* A Field object.  */
 typedef struct pyty_field_object
@@ -54,7 +52,8 @@ typedef struct pyty_field_object
   PyObject *dict;
 } field_object;
 
-static PyTypeObject field_object_type;
+extern PyTypeObject field_object_type
+    CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("field_object");
 
 /* A type iterator object.  */
 typedef struct {
@@ -67,7 +66,8 @@ typedef struct {
   struct pyty_type_object *source;
 } typy_iterator_object;
 
-static PyTypeObject type_iterator_object_type;
+extern PyTypeObject type_iterator_object_type
+    CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("typy_iterator_object");
 
 /* This is used to initialize various gdb.TYPE_ constants.  */
 struct pyty_code
@@ -85,6 +85,7 @@ static PyObject *typy_make_iter (PyObject *self, enum gdbpy_iter_kind kind);
 
 static struct pyty_code pyty_codes[] =
 {
+  ENTRY (TYPE_CODE_BITSTRING),
   ENTRY (TYPE_CODE_PTR),
   ENTRY (TYPE_CODE_ARRAY),
   ENTRY (TYPE_CODE_STRUCT),
@@ -98,12 +99,12 @@ static struct pyty_code pyty_codes[] =
   ENTRY (TYPE_CODE_SET),
   ENTRY (TYPE_CODE_RANGE),
   ENTRY (TYPE_CODE_STRING),
-  ENTRY (TYPE_CODE_BITSTRING),
   ENTRY (TYPE_CODE_ERROR),
   ENTRY (TYPE_CODE_METHOD),
   ENTRY (TYPE_CODE_METHODPTR),
   ENTRY (TYPE_CODE_MEMBERPTR),
   ENTRY (TYPE_CODE_REF),
+  ENTRY (TYPE_CODE_RVALUE_REF),
   ENTRY (TYPE_CODE_CHAR),
   ENTRY (TYPE_CODE_BOOL),
   ENTRY (TYPE_CODE_COMPLEX),
@@ -122,28 +123,34 @@ field_dealloc (PyObject *obj)
   field_object *f = (field_object *) obj;
 
   Py_XDECREF (f->dict);
-  f->ob_type->tp_free (obj);
+  Py_TYPE (obj)->tp_free (obj);
 }
 
 static PyObject *
 field_new (void)
 {
-  field_object *result = PyObject_New (field_object, &field_object_type);
+  gdbpy_ref<field_object> result (PyObject_New (field_object,
+                                               &field_object_type));
 
-  if (result)
+  if (result != NULL)
     {
       result->dict = PyDict_New ();
       if (!result->dict)
-       {
-         Py_DECREF (result);
-         result = NULL;
-       }
+       return NULL;
     }
-  return (PyObject *) result;
+  return (PyObject *) result.release ();
 }
 
 \f
 
+/* Return true if OBJ is of type gdb.Field, false otherwise.  */
+
+int
+gdbpy_is_field (PyObject *obj)
+{
+  return PyObject_TypeCheck (obj, &field_object_type);
+}
+
 /* Return the code for this type.  */
 static PyObject *
 typy_get_code (PyObject *self, void *closure)
@@ -156,93 +163,107 @@ typy_get_code (PyObject *self, void *closure)
 /* Helper function for typy_fields which converts a single field to a
    gdb.Field object.  Returns NULL on error.  */
 
-static PyObject *
+static gdbpy_ref<>
 convert_field (struct type *type, int field)
 {
-  PyObject *result = field_new ();
-  PyObject *arg;
+  gdbpy_ref<> result (field_new ());
 
-  if (!result)
+  if (result == NULL)
+    return NULL;
+
+  gdbpy_ref<> arg (type_to_type_object (type));
+  if (arg == NULL)
+    return NULL;
+  if (PyObject_SetAttrString (result.get (), "parent_type", arg.get ()) < 0)
     return NULL;
 
   if (!field_is_static (&TYPE_FIELD (type, field)))
     {
-      arg = PyLong_FromLong (TYPE_FIELD_BITPOS (type, field));
-      if (!arg)
-       goto fail;
+      const char *attrstring;
+
+      if (TYPE_CODE (type) == TYPE_CODE_ENUM)
+       {
+         arg.reset (gdb_py_long_from_longest (TYPE_FIELD_ENUMVAL (type,
+                                                                  field)));
+         attrstring = "enumval";
+       }
+      else
+       {
+         arg.reset (gdb_py_long_from_longest (TYPE_FIELD_BITPOS (type,
+                                                                 field)));
+         attrstring = "bitpos";
+       }
 
-      if (PyObject_SetAttrString (result, "bitpos", arg) < 0)
-       goto failarg;
+      if (arg == NULL)
+       return NULL;
+
+      if (PyObject_SetAttrString (result.get (), attrstring, arg.get ()) < 0)
+       return NULL;
     }
 
+  arg.reset (NULL);
   if (TYPE_FIELD_NAME (type, field))
-    arg = PyString_FromString (TYPE_FIELD_NAME (type, field));
-  else
     {
-      arg = Py_None;
-      Py_INCREF (arg);
+      const char *field_name = TYPE_FIELD_NAME (type, field);
+
+      if (field_name[0] != '\0')
+       {
+         arg.reset (PyString_FromString (TYPE_FIELD_NAME (type, field)));
+         if (arg == NULL)
+           return NULL;
+       }
     }
-  if (!arg)
-    goto fail;
-  if (PyObject_SetAttrString (result, "name", arg) < 0)
-    goto failarg;
+  if (arg == NULL)
+    arg = gdbpy_ref<>::new_reference (Py_None);
 
-  arg = TYPE_FIELD_ARTIFICIAL (type, field) ? Py_True : Py_False;
-  Py_INCREF (arg);
-  if (PyObject_SetAttrString (result, "artificial", arg) < 0)
-    goto failarg;
+  if (PyObject_SetAttrString (result.get (), "name", arg.get ()) < 0)
+    return NULL;
 
-  if (TYPE_CODE (type) == TYPE_CODE_CLASS)
-    arg = field < TYPE_N_BASECLASSES (type) ? Py_True : Py_False;
+  arg = gdbpy_ref<>::new_reference (TYPE_FIELD_ARTIFICIAL (type, field)
+                                   ? Py_True : Py_False);
+  if (PyObject_SetAttrString (result.get (), "artificial", arg.get ()) < 0)
+    return NULL;
+
+  if (TYPE_CODE (type) == TYPE_CODE_STRUCT)
+    arg = gdbpy_ref<>::new_reference (field < TYPE_N_BASECLASSES (type)
+                                     ? Py_True : Py_False);
   else
-    arg = Py_False;
-  Py_INCREF (arg);
-  if (PyObject_SetAttrString (result, "is_base_class", arg) < 0)
-    goto failarg;
+    arg = gdbpy_ref<>::new_reference (Py_False);
+  if (PyObject_SetAttrString (result.get (), "is_base_class", arg.get ()) < 0)
+    return NULL;
 
-  arg = PyLong_FromLong (TYPE_FIELD_BITSIZE (type, field));
-  if (!arg)
-    goto fail;
-  if (PyObject_SetAttrString (result, "bitsize", arg) < 0)
-    goto failarg;
+  arg.reset (PyLong_FromLong (TYPE_FIELD_BITSIZE (type, field)));
+  if (arg == NULL)
+    return NULL;
+  if (PyObject_SetAttrString (result.get (), "bitsize", arg.get ()) < 0)
+    return NULL;
 
   /* A field can have a NULL type in some situations.  */
   if (TYPE_FIELD_TYPE (type, field) == NULL)
-    {
-      arg = Py_None;
-      Py_INCREF (arg);
-    }
+    arg = gdbpy_ref<>::new_reference (Py_None);
   else
-    arg = type_to_type_object (TYPE_FIELD_TYPE (type, field));
-  if (!arg)
-    goto fail;
-  if (PyObject_SetAttrString (result, "type", arg) < 0)
-    goto failarg;
+    arg.reset (type_to_type_object (TYPE_FIELD_TYPE (type, field)));
+  if (arg == NULL)
+    return NULL;
+  if (PyObject_SetAttrString (result.get (), "type", arg.get ()) < 0)
+    return NULL;
 
   return result;
-
- failarg:
-  Py_DECREF (arg);
- fail:
-  Py_DECREF (result);
-  return NULL;
 }
 
 /* Helper function to return the name of a field, as a gdb.Field object.
    If the field doesn't have a name, None is returned.  */
 
-static PyObject *
+static gdbpy_ref<>
 field_name (struct type *type, int field)
 {
-  PyObject *result;
+  gdbpy_ref<> result;
 
   if (TYPE_FIELD_NAME (type, field))
-    result = PyString_FromString (TYPE_FIELD_NAME (type, field));
+    result.reset (PyString_FromString (TYPE_FIELD_NAME (type, field)));
   else
-    {
-      result = Py_None;
-      Py_INCREF (result);
-    }
+    result = gdbpy_ref<>::new_reference (Py_None);
+
   return result;
 }
 
@@ -252,40 +273,32 @@ field_name (struct type *type, int field)
    the field, or a tuple consisting of field name and gdb.Field
    object.  */
 
-static PyObject *
+static gdbpy_ref<>
 make_fielditem (struct type *type, int i, enum gdbpy_iter_kind kind)
 {
-  PyObject *item = NULL, *key = NULL, *value = NULL;
-
   switch (kind)
     {
     case iter_items:
-      key = field_name (type, i);
-      if (key == NULL)
-       goto fail;
-      value = convert_field (type, i);
-      if (value == NULL)
-       goto fail;
-      item = PyTuple_New (2);
-      if (item == NULL)
-       goto fail;
-      PyTuple_SET_ITEM (item, 0, key);
-      PyTuple_SET_ITEM (item, 1, value);
-      break;
+      {
+       gdbpy_ref<> key (field_name (type, i));
+       if (key == NULL)
+         return NULL;
+       gdbpy_ref<> value = convert_field (type, i);
+       if (value == NULL)
+         return NULL;
+       gdbpy_ref<> item (PyTuple_New (2));
+       if (item == NULL)
+         return NULL;
+       PyTuple_SET_ITEM (item.get (), 0, key.release ());
+       PyTuple_SET_ITEM (item.get (), 1, value.release ());
+       return item;
+      }
     case iter_keys:
-      item = field_name (type, i);
-      break;
+      return field_name (type, i);
     case iter_values:
-      item =  convert_field (type, i);
-      break;
+      return convert_field (type, i);
     }
-  return item;
-  
- fail:
-  Py_XDECREF (key);
-  Py_XDECREF (value);
-  Py_XDECREF (item);
-  return NULL;
+  gdb_assert_not_reached ("invalid gdbpy_iter_kind");
 }
 
 /* Return a sequence of all field names, fields, or (name, field) pairs.
@@ -294,25 +307,65 @@ make_fielditem (struct type *type, int i, enum gdbpy_iter_kind kind)
 static PyObject *
 typy_fields_items (PyObject *self, enum gdbpy_iter_kind kind)
 {
-  PyObject *result = NULL, *iter = NULL;
-  
-  iter = typy_make_iter (self, kind);
-  if (iter == NULL)
-    return NULL;
-    
-  result = PySequence_List (iter);
-  Py_DECREF (iter);
-  return result;
+  PyObject *py_type = self;
+  struct type *type = ((type_object *) py_type)->type;
+  struct type *checked_type = type;
+
+  try
+    {
+      checked_type = check_typedef (checked_type);
+    }
+  catch (const gdb_exception &except)
+    {
+      GDB_PY_HANDLE_EXCEPTION (except);
+    }
+
+  gdbpy_ref<> type_holder;
+  if (checked_type != type)
+    {
+      type_holder.reset (type_to_type_object (checked_type));
+      if (type_holder == nullptr)
+       return nullptr;
+      py_type = type_holder.get ();
+    }
+  gdbpy_ref<> iter (typy_make_iter (py_type, kind));
+  if (iter == nullptr)
+    return nullptr;
+
+  return PySequence_List (iter.get ());
 }
 
 /* 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;
+
+  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.  */
+  gdbpy_ref<> r = convert_field (type, 0);
+  if (r == NULL)
+    return NULL;
+
+  return Py_BuildValue ("[O]", r.get ());
+}
+
 /* Return a sequence of all field names.  Each field is a gdb.Field object.  */
 
 static PyObject *
@@ -321,7 +374,7 @@ typy_field_names (PyObject *self, PyObject *args)
   return typy_fields_items (self, iter_keys);
 }
 
-/* Return a sequence of all (name, fields) pairs.  Each field is a 
+/* Return a sequence of all (name, fields) pairs.  Each field is a
    gdb.Field object.  */
 
 static PyObject *
@@ -330,15 +383,45 @@ typy_items (PyObject *self, PyObject *args)
   return typy_fields_items (self, iter_items);
 }
 
+/* Return the type's name, or None.  */
+
+static PyObject *
+typy_get_name (PyObject *self, void *closure)
+{
+  struct type *type = ((type_object *) self)->type;
+
+  if (TYPE_NAME (type) == NULL)
+    Py_RETURN_NONE;
+  return PyString_FromString (TYPE_NAME (type));
+}
+
 /* Return the type's tag, or None.  */
 static PyObject *
 typy_get_tag (PyObject *self, void *closure)
 {
   struct type *type = ((type_object *) self)->type;
+  const char *tagname = nullptr;
+
+  if (TYPE_CODE (type) == TYPE_CODE_STRUCT
+      || TYPE_CODE (type) == TYPE_CODE_UNION
+      || TYPE_CODE (type) == TYPE_CODE_ENUM)
+    tagname = TYPE_NAME (type);
+
+  if (tagname == nullptr)
+    Py_RETURN_NONE;
+  return PyString_FromString (tagname);
+}
+
+/* Return the type's objfile, or None.  */
+static PyObject *
+typy_get_objfile (PyObject *self, void *closure)
+{
+  struct type *type = ((type_object *) self)->type;
+  struct objfile *objfile = TYPE_OBJFILE (type);
 
-  if (!TYPE_TAG_NAME (type))
+  if (objfile == nullptr)
     Py_RETURN_NONE;
-  return PyString_FromString (TYPE_TAG_NAME (type));
+  return objfile_to_objfile_object (objfile).release ();
 }
 
 /* Return the type, stripped of typedefs. */
@@ -347,19 +430,65 @@ typy_strip_typedefs (PyObject *self, PyObject *args)
 {
   struct type *type = ((type_object *) self)->type;
 
-  return type_to_type_object (check_typedef (type));
+  try
+    {
+      type = check_typedef (type);
+    }
+  catch (const gdb_exception &except)
+    {
+      GDB_PY_HANDLE_EXCEPTION (except);
+    }
+
+  return type_to_type_object (type);
 }
 
-/* Return an array 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)
+{
+
+  for (;;)
+    {
+      try
+       {
+         type = check_typedef (type);
+       }
+      catch (const gdb_exception &except)
+       {
+         GDB_PY_HANDLE_EXCEPTION (except);
+       }
+
+      if (TYPE_CODE (type) != TYPE_CODE_PTR && !TYPE_IS_REFERENCE (type))
+       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
+      && TYPE_CODE (type) != TYPE_CODE_FUNC)
+    {
+      PyErr_SetString (PyExc_TypeError,
+                      "Type is not a structure, union, enum, or function type.");
+      return NULL;
+    }
+
+  return type;
+}
+
+/* Helper for typy_array and typy_vector.  */
 
 static PyObject *
-typy_array (PyObject *self, PyObject *args)
+typy_array_1 (PyObject *self, PyObject *args, int is_vector)
 {
   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, "l|O", &n1, &n2_obj))
     return NULL;
@@ -382,34 +511,57 @@ typy_array (PyObject *self, PyObject *args)
       n1 = 0;
     }
 
-  if (n2 < n1)
+  if (n2 < n1 - 1) /* Note: An empty array has n2 == n1 - 1.  */
     {
       PyErr_SetString (PyExc_ValueError,
                       _("Array length must not be negative"));
       return NULL;
     }
 
-  TRY_CATCH (except, RETURN_MASK_ALL)
+  try
     {
       array = lookup_array_range_type (type, n1, n2);
+      if (is_vector)
+       make_vector_type (array);
+    }
+  catch (const gdb_exception &except)
+    {
+      GDB_PY_HANDLE_EXCEPTION (except);
     }
-  GDB_PY_HANDLE_EXCEPTION (except);
 
   return type_to_type_object (array);
 }
 
+/* Return an array type.  */
+
+static PyObject *
+typy_array (PyObject *self, PyObject *args)
+{
+  return typy_array_1 (self, args, 0);
+}
+
+/* Return a vector type.  */
+
+static PyObject *
+typy_vector (PyObject *self, PyObject *args)
+{
+  return typy_array_1 (self, args, 1);
+}
+
 /* Return a Type object which represents a pointer to SELF.  */
 static PyObject *
 typy_pointer (PyObject *self, PyObject *args)
 {
   struct type *type = ((type_object *) self)->type;
-  volatile struct gdb_exception except;
 
-  TRY_CATCH (except, RETURN_MASK_ALL)
+  try
     {
       type = lookup_pointer_type (type);
     }
-  GDB_PY_HANDLE_EXCEPTION (except);
+  catch (const gdb_exception &except)
+    {
+      GDB_PY_HANDLE_EXCEPTION (except);
+    }
 
   return type_to_type_object (type);
 }
@@ -421,8 +573,6 @@ static PyObject *
 typy_range (PyObject *self, PyObject *args)
 {
   struct type *type = ((type_object *) self)->type;
-  PyObject *result;
-  PyObject *low_bound = NULL, *high_bound = NULL;
   /* Initialize these to appease GCC warnings.  */
   LONGEST low = 0, high = 0;
 
@@ -448,35 +598,22 @@ typy_range (PyObject *self, PyObject *args)
       break;
     }
 
-  low_bound = PyLong_FromLong (low);
-  if (!low_bound)
-    goto failarg;
+  gdbpy_ref<> low_bound (PyLong_FromLong (low));
+  if (low_bound == NULL)
+    return NULL;
 
-  high_bound = PyLong_FromLong (high);
-  if (!high_bound)
-    goto failarg;
+  gdbpy_ref<> high_bound (PyLong_FromLong (high));
+  if (high_bound == NULL)
+    return NULL;
 
-  result = PyTuple_New (2);
-  if (!result)
-    goto failarg;
+  gdbpy_ref<> result (PyTuple_New (2));
+  if (result == NULL)
+    return NULL;
 
-  if (PyTuple_SetItem (result, 0, low_bound) != 0)
-    {
-      Py_DECREF (result);
-      goto failarg;
-    }
-  if (PyTuple_SetItem (result, 1, high_bound) != 0)
-    {
-      Py_DECREF (high_bound);
-      Py_DECREF (result);
-      return NULL;
-    }
-  return result;
-  
- failarg:
-  Py_XDECREF (high_bound);
-  Py_XDECREF (low_bound);
-  return NULL;
+  if (PyTuple_SetItem (result.get (), 0, low_bound.release ()) != 0
+      || PyTuple_SetItem (result.get (), 1, high_bound.release ()) != 0)
+    return NULL;
+  return result.release ();
 }
 
 /* Return a Type object which represents a reference to SELF.  */
@@ -484,13 +621,15 @@ static PyObject *
 typy_reference (PyObject *self, PyObject *args)
 {
   struct type *type = ((type_object *) self)->type;
-  volatile struct gdb_exception except;
 
-  TRY_CATCH (except, RETURN_MASK_ALL)
+  try
     {
-      type = lookup_reference_type (type);
+      type = lookup_lvalue_reference_type (type);
+    }
+  catch (const gdb_exception &except)
+    {
+      GDB_PY_HANDLE_EXCEPTION (except);
     }
-  GDB_PY_HANDLE_EXCEPTION (except);
 
   return type_to_type_object (type);
 }
@@ -503,7 +642,7 @@ typy_target (PyObject *self, PyObject *args)
 
   if (!TYPE_TARGET_TYPE (type))
     {
-      PyErr_SetString (PyExc_RuntimeError, 
+      PyErr_SetString (PyExc_RuntimeError,
                       _("Type does not have a target."));
       return NULL;
     }
@@ -516,13 +655,15 @@ static PyObject *
 typy_const (PyObject *self, PyObject *args)
 {
   struct type *type = ((type_object *) self)->type;
-  volatile struct gdb_exception except;
 
-  TRY_CATCH (except, RETURN_MASK_ALL)
+  try
     {
       type = make_cv_type (1, 0, type, NULL);
     }
-  GDB_PY_HANDLE_EXCEPTION (except);
+  catch (const gdb_exception &except)
+    {
+      GDB_PY_HANDLE_EXCEPTION (except);
+    }
 
   return type_to_type_object (type);
 }
@@ -532,13 +673,15 @@ static PyObject *
 typy_volatile (PyObject *self, PyObject *args)
 {
   struct type *type = ((type_object *) self)->type;
-  volatile struct gdb_exception except;
 
-  TRY_CATCH (except, RETURN_MASK_ALL)
+  try
     {
       type = make_cv_type (0, 1, type, NULL);
     }
-  GDB_PY_HANDLE_EXCEPTION (except);
+  catch (const gdb_exception &except)
+    {
+      GDB_PY_HANDLE_EXCEPTION (except);
+    }
 
   return type_to_type_object (type);
 }
@@ -548,13 +691,15 @@ static PyObject *
 typy_unqualified (PyObject *self, PyObject *args)
 {
   struct type *type = ((type_object *) self)->type;
-  volatile struct gdb_exception except;
 
-  TRY_CATCH (except, RETURN_MASK_ALL)
+  try
     {
       type = make_cv_type (0, 0, type, NULL);
     }
-  GDB_PY_HANDLE_EXCEPTION (except);
+  catch (const gdb_exception &except)
+    {
+      GDB_PY_HANDLE_EXCEPTION (except);
+    }
 
   return type_to_type_object (type);
 }
@@ -564,41 +709,61 @@ static PyObject *
 typy_get_sizeof (PyObject *self, void *closure)
 {
   struct type *type = ((type_object *) self)->type;
-  volatile struct gdb_exception except;
 
-  TRY_CATCH (except, RETURN_MASK_ALL)
+  try
     {
       check_typedef (type);
     }
+  catch (const gdb_exception &except)
+    {
+    }
+
   /* Ignore exceptions.  */
 
-  return PyLong_FromLong (TYPE_LENGTH (type));
+  return gdb_py_long_from_longest (TYPE_LENGTH (type));
+}
+
+/* Return the alignment of the type represented by SELF, in bytes.  */
+static PyObject *
+typy_get_alignof (PyObject *self, void *closure)
+{
+  struct type *type = ((type_object *) self)->type;
+
+  ULONGEST align = 0;
+  try
+    {
+      align = type_align (type);
+    }
+  catch (const gdb_exception &except)
+    {
+      align = 0;
+    }
+
+  /* Ignore exceptions.  */
+
+  return gdb_py_object_from_ulongest (align).release ();
 }
 
 static struct type *
-typy_lookup_typename (const char *type_name, struct block *block)
+typy_lookup_typename (const char *type_name, const struct block *block)
 {
   struct type *type = NULL;
-  volatile struct gdb_exception except;
 
-  TRY_CATCH (except, RETURN_MASK_ALL)
+  try
     {
-      if (!strncmp (type_name, "struct ", 7))
+      if (startswith (type_name, "struct "))
        type = lookup_struct (type_name + 7, NULL);
-      else if (!strncmp (type_name, "union ", 6))
+      else if (startswith (type_name, "union "))
        type = lookup_union (type_name + 6, NULL);
-      else if (!strncmp (type_name, "enum ", 5))
+      else if (startswith (type_name, "enum "))
        type = lookup_enum (type_name + 5, NULL);
       else
-       type = lookup_typename (python_language, python_gdbarch,
+       type = lookup_typename (python_language,
                                type_name, block, 0);
     }
-  if (except.reason < 0)
+  catch (const gdb_exception &except)
     {
-      PyErr_Format (except.reason == RETURN_QUIT
-                   ? PyExc_KeyboardInterrupt : PyExc_RuntimeError,
-                   "%s", except.message);
-      return NULL;
+      GDB_PY_HANDLE_EXCEPTION (except);
     }
 
   return type;
@@ -606,10 +771,9 @@ typy_lookup_typename (const char *type_name, struct block *block)
 
 static struct type *
 typy_lookup_type (struct demangle_component *demangled,
-                 struct block *block)
+                 const struct block *block)
 {
-  struct type *type;
-  char *type_name;
+  struct type *type, *rtype = NULL;
   enum demangle_component_type demangled_type;
 
   /* Save the type: typy_lookup_type() may (indirectly) overwrite
@@ -618,6 +782,7 @@ typy_lookup_type (struct demangle_component *demangled,
 
   if (demangled_type == DEMANGLE_COMPONENT_POINTER
       || demangled_type == DEMANGLE_COMPONENT_REFERENCE
+      || demangled_type == DEMANGLE_COMPONENT_RVALUE_REFERENCE
       || demangled_type == DEMANGLE_COMPONENT_CONST
       || demangled_type == DEMANGLE_COMPONENT_VOLATILE)
     {
@@ -625,24 +790,45 @@ typy_lookup_type (struct demangle_component *demangled,
       if (! type)
        return NULL;
 
-      switch (demangled_type)
+      try
+       {
+         /* If the demangled_type matches with one of the types
+            below, run the corresponding function and save the type
+            to return later.  We cannot just return here as we are in
+            an exception handler.  */
+         switch (demangled_type)
+           {
+           case DEMANGLE_COMPONENT_REFERENCE:
+             rtype = lookup_lvalue_reference_type (type);
+             break;
+           case DEMANGLE_COMPONENT_RVALUE_REFERENCE:
+             rtype = lookup_rvalue_reference_type (type);
+             break;
+           case DEMANGLE_COMPONENT_POINTER:
+             rtype = lookup_pointer_type (type);
+             break;
+           case DEMANGLE_COMPONENT_CONST:
+             rtype = make_cv_type (1, 0, type, NULL);
+             break;
+           case DEMANGLE_COMPONENT_VOLATILE:
+             rtype = make_cv_type (0, 1, type, NULL);
+             break;
+           }
+       }
+      catch (const gdb_exception &except)
        {
-       case DEMANGLE_COMPONENT_REFERENCE:
-         return lookup_reference_type (type);
-       case DEMANGLE_COMPONENT_POINTER:
-         return lookup_pointer_type (type);
-       case DEMANGLE_COMPONENT_CONST:
-         return make_cv_type (1, 0, type, NULL);
-       case DEMANGLE_COMPONENT_VOLATILE:
-         return make_cv_type (0, 1, type, NULL);
+         GDB_PY_HANDLE_EXCEPTION (except);
        }
     }
 
-  type_name = cp_comp_to_string (demangled, 10);
-  type = typy_lookup_typename (type_name, block);
-  xfree (type_name);
+  /* If we have a type from the switch statement above, just return
+     that.  */
+  if (rtype)
+    return rtype;
 
-  return type;
+  /* We don't have a type, so lookup the type.  */
+  gdb::unique_xmalloc_ptr<char> type_name = cp_comp_to_string (demangled, 10);
+  return typy_lookup_typename (type_name.get (), block);
 }
 
 /* This is a helper function for typy_template_argument that is used
@@ -651,15 +837,14 @@ typy_lookup_type (struct demangle_component *demangled,
    versions of GCC, that do not emit DW_TAG_template_*.  */
 
 static PyObject *
-typy_legacy_template_argument (struct type *type, struct block *block,
+typy_legacy_template_argument (struct type *type, const struct block *block,
                               int argno)
 {
   int i;
   struct demangle_component *demangled;
-  struct demangle_parse_info *info;
-  const char *err;
+  std::unique_ptr<demangle_parse_info> info;
+  std::string err;
   struct type *argtype;
-  struct cleanup *cleanup;
 
   if (TYPE_NAME (type) == NULL)
     {
@@ -667,15 +852,22 @@ typy_legacy_template_argument (struct type *type, struct block *block,
       return NULL;
     }
 
-  /* Note -- this is not thread-safe.  */
-  info = cp_demangled_name_to_comp (TYPE_NAME (type), &err);
+  try
+    {
+      /* Note -- this is not thread-safe.  */
+      info = cp_demangled_name_to_comp (TYPE_NAME (type), &err);
+    }
+  catch (const gdb_exception &except)
+    {
+      GDB_PY_HANDLE_EXCEPTION (except);
+    }
+
   if (! info)
     {
-      PyErr_SetString (PyExc_RuntimeError, err);
+      PyErr_SetString (PyExc_RuntimeError, err.c_str ());
       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
@@ -684,7 +876,6 @@ typy_legacy_template_argument (struct type *type, struct block *block,
 
   if (demangled->type != DEMANGLE_COMPONENT_TEMPLATE)
     {
-      do_cleanups (cleanup);
       PyErr_SetString (PyExc_RuntimeError, _("Type is not a template."));
       return NULL;
     }
@@ -697,14 +888,12 @@ typy_legacy_template_argument (struct type *type, struct block *block,
 
   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;
 
@@ -716,15 +905,21 @@ typy_template_argument (PyObject *self, PyObject *args)
 {
   int argno;
   struct type *type = ((type_object *) self)->type;
-  struct block *block = NULL;
+  const struct block *block = NULL;
   PyObject *block_obj = NULL;
   struct symbol *sym;
   struct value *val = NULL;
-  volatile struct gdb_exception except;
 
   if (! PyArg_ParseTuple (args, "i|O", &argno, &block_obj))
     return NULL;
 
+  if (argno < 0)
+    {
+      PyErr_SetString (PyExc_RuntimeError,
+                      _("Template argument number must be non-negative"));
+      return NULL;
+    }
+
   if (block_obj)
     {
       block = block_object_to_block (block_obj);
@@ -736,13 +931,16 @@ typy_template_argument (PyObject *self, PyObject *args)
        }
     }
 
-  TRY_CATCH (except, RETURN_MASK_ALL)
+  try
     {
       type = check_typedef (type);
-      if (TYPE_CODE (type) == TYPE_CODE_REF)
+      if (TYPE_IS_REFERENCE (type))
        type = check_typedef (TYPE_TARGET_TYPE (type));
     }
-  GDB_PY_HANDLE_EXCEPTION (except);
+  catch (const gdb_exception &except)
+    {
+      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 --
@@ -767,11 +965,14 @@ typy_template_argument (PyObject *self, PyObject *args)
       return NULL;
     }
 
-  TRY_CATCH (except, RETURN_MASK_ALL)
+  try
     {
       val = value_of_variable (sym, block);
     }
-  GDB_PY_HANDLE_EXCEPTION (except);
+  catch (const gdb_exception &except)
+    {
+      GDB_PY_HANDLE_EXCEPTION (except);
+    }
 
   return value_to_value_object (val);
 }
@@ -779,196 +980,20 @@ typy_template_argument (PyObject *self, PyObject *args)
 static PyObject *
 typy_str (PyObject *self)
 {
-  volatile struct gdb_exception except;
-  char *thetype = NULL;
-  long length = 0;
-  PyObject *result;
+  string_file thetype;
 
-  TRY_CATCH (except, RETURN_MASK_ALL)
+  try
     {
-      struct cleanup *old_chain;
-      struct ui_file *stb;
-
-      stb = mem_fileopen ();
-      old_chain = make_cleanup_ui_file_delete (stb);
-
-      type_print (type_object_to_type (self), "", stb, -1);
-
-      thetype = ui_file_xstrdup (stb, &length);
-      do_cleanups (old_chain);
+      LA_PRINT_TYPE (type_object_to_type (self), "", &thetype, -1, 0,
+                    &type_print_raw_options);
     }
-  if (except.reason < 0)
+  catch (const gdb_exception &except)
     {
-      xfree (thetype);
       GDB_PY_HANDLE_EXCEPTION (except);
     }
 
-  result = PyUnicode_Decode (thetype, length, host_charset (), NULL);
-  xfree (thetype);
-
-  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;
-           case FIELD_LOC_KIND_DWARF_BLOCK:
-             {
-               struct dwarf2_locexpr_baton *block1, *block2;
-
-               block1 = FIELD_DWARF_BLOCK (*field1);
-               block2 = FIELD_DWARF_BLOCK (*field2);
-               if (block1->per_cu != block2->per_cu
-                   || block1->size != block2->size
-                   || memcmp (block1->data, block2->data, block1->size) != 0)
-               return Py_NE;
-             }
-             break;
-           default:
-             internal_error (__FILE__, __LINE__, _("Unsupported field kind "
-                                                   "%d by check_types_equal"),
-                             FIELD_LOC_KIND (*field1));
-           }
-
-         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;
+  return PyUnicode_Decode (thetype.c_str (), thetype.size (),
+                          host_charset (), NULL);
 }
 
 /* Implement the richcompare method.  */
@@ -976,10 +1001,9 @@ check_types_worklist (VEC (type_equality_entry_d) **worklist,
 static PyObject *
 typy_richcompare (PyObject *self, PyObject *other, int op)
 {
-  int result = Py_NE;
+  bool result = false;
   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.  */
@@ -990,31 +1014,22 @@ typy_richcompare (PyObject *self, PyObject *other, int op)
     }
 
   if (type1 == type2)
-    result = Py_EQ;
+    result = true;
   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)
+      try
        {
-         result = check_types_worklist (&worklist, cache);
+         result = types_deeply_equal (type1, type2);
+       }
+      catch (const gdb_exception &except)
+       {
+         /* If there is a GDB exception, a comparison is not capable
+            (or trusted), so exit.  */
+         GDB_PY_HANDLE_EXCEPTION (except);
        }
-      if (except.reason < 0)
-       result = Py_NE;
-
-      bcache_xfree (cache);
-      VEC_free (type_equality_entry_d, worklist);
     }
 
-  if (op == result)
+  if (op == (result ? Py_EQ : Py_NE))
     Py_RETURN_TRUE;
   Py_RETURN_FALSE;
 }
@@ -1026,13 +1041,15 @@ static const struct objfile_data *typy_objfile_data_key;
 static void
 save_objfile_types (struct objfile *objfile, void *datum)
 {
-  type_object *obj = datum;
+  type_object *obj = (type_object *) datum;
   htab_t copied_types;
-  struct cleanup *cleanup;
+
+  if (!gdb_python_initialized)
+    return;
 
   /* This prevents another thread from freeing the objects we're
      operating on.  */
-  cleanup = ensure_python_env (get_objfile_arch (objfile), current_language);
+  gdbpy_enter enter_py (get_objfile_arch (objfile), current_language);
 
   copied_types = create_copied_types_hash (objfile);
 
@@ -1051,8 +1068,6 @@ save_objfile_types (struct objfile *objfile, void *datum)
     }
 
   htab_delete (copied_types);
-
-  do_cleanups (cleanup);
 }
 
 static void
@@ -1064,7 +1079,8 @@ set_type (type_object *obj, struct type *type)
     {
       struct objfile *objfile = TYPE_OBJFILE (type);
 
-      obj->next = objfile_data (objfile, typy_objfile_data_key);
+      obj->next = ((struct pyty_type_object *)
+                  objfile_data (objfile, typy_objfile_data_key));
       if (obj->next)
        obj->next->prev = obj;
       set_objfile_data (objfile, typy_objfile_data_key, obj);
@@ -1091,7 +1107,7 @@ typy_dealloc (PyObject *obj)
   if (type->next)
     type->next->prev = type->prev;
 
-  type->ob_type->tp_free (type);
+  Py_TYPE (type)->tp_free (type);
 }
 
 /* Return number of fields ("length" of the field dictionary).  */
@@ -1101,49 +1117,65 @@ 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 optimized out value of this type.  */
+
+static PyObject *
+typy_optimized_out (PyObject *self, PyObject *args)
+{
+  struct type *type = ((type_object *) self)->type;
+
+  return value_to_value_object (allocate_optimized_out_value (type));
+}
+
 /* Return a gdb.Field object for the field named by the argument.  */
 
 static PyObject *
 typy_getitem (PyObject *self, PyObject *key)
 {
   struct type *type = ((type_object *) self)->type;
-  char *field;
   int i;
-  
-  field = python_string_to_host_string (key);
+
+  gdb::unique_xmalloc_ptr<char> field = python_string_to_host_string (key);
   if (field == NULL)
     return NULL;
 
-  /* We want just fields of this type, not of base types, so instead of 
+  /* We want just fields of this type, not of base types, so instead of
      using lookup_struct_elt_type, portions of that function are
      copied here.  */
 
-  for (;;)
-    {
-      CHECK_TYPEDEF (type);
-      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);
+      const char *t_field_name = TYPE_FIELD_NAME (type, i);
 
-      if (t_field_name && (strcmp_iw (t_field_name, field) == 0))
-       {
-         return convert_field (type, i);
-       }
+      if (t_field_name && (strcmp_iw (t_field_name, field.get ()) == 0))
+       return convert_field (type, i).release ();
     }
   PyErr_SetObject (PyExc_KeyError, key);
   return NULL;
 }
 
-/* Implement the "get" method on the type object.  This is the 
+/* Implement the "get" method on the type object.  This is the
    same as getitem if the key is present, but returns the supplied
    default value or None if the key is not found.  */
 
@@ -1151,20 +1183,20 @@ static PyObject *
 typy_get (PyObject *self, PyObject *args)
 {
   PyObject *key, *defval = Py_None, *result;
-  
+
   if (!PyArg_UnpackTuple (args, "get", 1, 2, &key, &defval))
     return NULL;
-  
+
   result = typy_getitem (self, key);
   if (result != NULL)
     return result;
-  
+
   /* typy_getitem returned error status.  If the exception is
      KeyError, clear the exception status and return the defval
      instead.  Otherwise return the exception unchanged.  */
   if (!PyErr_ExceptionMatches (PyExc_KeyError))
     return NULL;
-  
+
   PyErr_Clear ();
   Py_INCREF (defval);
   return defval;
@@ -1176,28 +1208,23 @@ static PyObject *
 typy_has_key (PyObject *self, PyObject *args)
 {
   struct type *type = ((type_object *) self)->type;
-  char *field;
+  const char *field;
   int i;
-  
+
   if (!PyArg_ParseTuple (args, "s", &field))
     return NULL;
 
-  /* We want just fields of this type, not of base types, so instead of 
+  /* We want just fields of this type, not of base types, so instead of
      using lookup_struct_elt_type, portions of that function are
      copied here.  */
 
-  for (;;)
-    {
-      CHECK_TYPEDEF (type);
-      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);
+      const char *t_field_name = TYPE_FIELD_NAME (type, i);
 
       if (t_field_name && (strcmp_iw (t_field_name, field) == 0))
        Py_RETURN_TRUE;
@@ -1212,6 +1239,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)
@@ -1275,15 +1306,14 @@ typy_iterator_iternext (PyObject *self)
 {
   typy_iterator_object *iter_obj = (typy_iterator_object *) self;
   struct type *type = iter_obj->source->type;
-  int i;
-  PyObject *result;
-  
+
   if (iter_obj->field < TYPE_NFIELDS (type))
     {
-      result = make_fielditem (type, iter_obj->field, iter_obj->kind);
+      gdbpy_ref<> result = make_fielditem (type, iter_obj->field,
+                                          iter_obj->kind);
       if (result != NULL)
        iter_obj->field++;
-      return result;
+      return result.release ();
     }
 
   return NULL;
@@ -1295,6 +1325,7 @@ typy_iterator_dealloc (PyObject *obj)
   typy_iterator_object *iter_obj = (typy_iterator_object *) obj;
 
   Py_DECREF (iter_obj->source);
+  Py_TYPE (obj)->tp_free (obj);
 }
 
 /* Create a new Type referring to TYPE.  */
@@ -1303,6 +1334,17 @@ type_to_type_object (struct type *type)
 {
   type_object *type_obj;
 
+  try
+    {
+      /* Try not to let stub types leak out to Python.  */
+      if (TYPE_STUB (type))
+       type = check_typedef (type);
+    }
+  catch (...)
+    {
+      /* Just ignore failures in check_typedef.  */
+    }
+
   type_obj = PyObject_New (type_object, &type_object_type);
   if (type_obj)
     set_type (type_obj, type);
@@ -1324,14 +1366,14 @@ type_object_to_type (PyObject *obj)
 PyObject *
 gdbpy_lookup_type (PyObject *self, PyObject *args, PyObject *kw)
 {
-  static char *keywords[] = { "name", "block", NULL };
+  static const char *keywords[] = { "name", "block", NULL };
   const char *type_name = NULL;
   struct type *type = NULL;
   PyObject *block_obj = NULL;
-  struct block *block = NULL;
+  const struct block *block = NULL;
 
-  if (! PyArg_ParseTupleAndKeywords (args, kw, "s|O", keywords,
-                                    &type_name, &block_obj))
+  if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "s|O", keywords,
+                                       &type_name, &block_obj))
     return NULL;
 
   if (block_obj)
@@ -1349,10 +1391,10 @@ gdbpy_lookup_type (PyObject *self, PyObject *args, PyObject *kw)
   if (! type)
     return NULL;
 
-  return (PyObject *) type_to_type_object (type);
+  return type_to_type_object (type);
 }
 
-void
+int
 gdbpy_initialize_types (void)
 {
   int i;
@@ -1361,55 +1403,73 @@ gdbpy_initialize_types (void)
     = register_objfile_data_with_cleanup (save_objfile_types, NULL);
 
   if (PyType_Ready (&type_object_type) < 0)
-    return;
+    return -1;
   if (PyType_Ready (&field_object_type) < 0)
-    return;
+    return -1;
   if (PyType_Ready (&type_iterator_object_type) < 0)
-    return;
+    return -1;
 
   for (i = 0; pyty_codes[i].name; ++i)
     {
-      if (PyModule_AddIntConstant (gdb_module,
-                                  /* Cast needed for Python 2.4.  */
-                                  (char *) pyty_codes[i].name,
+      if (PyModule_AddIntConstant (gdb_module, pyty_codes[i].name,
                                   pyty_codes[i].code) < 0)
-       return;
+       return -1;
     }
 
-  Py_INCREF (&type_object_type);
-  PyModule_AddObject (gdb_module, "Type", (PyObject *) &type_object_type);
+  if (gdb_pymodule_addobject (gdb_module, "Type",
+                             (PyObject *) &type_object_type) < 0)
+    return -1;
 
-  Py_INCREF (&type_iterator_object_type);
-  PyModule_AddObject (gdb_module, "TypeIterator",
-                     (PyObject *) &type_iterator_object_type);
+  if (gdb_pymodule_addobject (gdb_module, "TypeIterator",
+                             (PyObject *) &type_iterator_object_type) < 0)
+    return -1;
 
-  Py_INCREF (&field_object_type);
-  PyModule_AddObject (gdb_module, "Field", (PyObject *) &field_object_type);
+  return gdb_pymodule_addobject (gdb_module, "Field",
+                                (PyObject *) &field_object_type);
 }
 
 \f
 
-static PyGetSetDef type_object_getset[] =
+static gdb_PyGetSetDef type_object_getset[] =
 {
+  { "alignof", typy_get_alignof, NULL,
+    "The alignment of this type, in bytes.", NULL },
   { "code", typy_get_code, NULL,
     "The code for this type.", NULL },
+  { "name", typy_get_name, NULL,
+    "The name for this type, or None.", NULL },
   { "sizeof", typy_get_sizeof, NULL,
     "The size of this type, in bytes.", NULL },
   { "tag", typy_get_tag, NULL,
     "The tag name for this type, or None.", NULL },
+  { "objfile", typy_get_objfile, NULL,
+    "The objfile this type was defined in, or None.", NULL },
   { NULL }
 };
 
 static PyMethodDef type_object_methods[] =
 {
   { "array", typy_array, METH_VARARGS,
-    "array (N) -> Type\n\
-Return a type which represents an array of N objects of this type." },
+    "array ([LOW_BOUND,] HIGH_BOUND) -> Type\n\
+Return a type which represents an array of objects of this type.\n\
+The bounds of the array are [LOW_BOUND, HIGH_BOUND] inclusive.\n\
+If LOW_BOUND is omitted, a value of zero is used." },
+  { "vector", typy_vector, METH_VARARGS,
+    "vector ([LOW_BOUND,] HIGH_BOUND) -> Type\n\
+Return a type which represents a vector of objects of this type.\n\
+The bounds of the array are [LOW_BOUND, HIGH_BOUND] inclusive.\n\
+If LOW_BOUND is omitted, a value of zero is used.\n\
+Vectors differ from arrays in that if the current language has C-style\n\
+arrays, vectors don't decay to a pointer to the first element.\n\
+They are first class values." },
    { "__contains__", typy_has_key, METH_VARARGS,
      "T.__contains__(k) -> True if T has a field named k, else False" },
   { "const", typy_const, METH_NOARGS,
     "const () -> Type\n\
 Return a const variant of this type." },
+  { "optimized_out", typy_optimized_out, METH_NOARGS,
+    "optimized_out() -> Value\n\
+Return optimized out value of this type." },
   { "fields", typy_fields, METH_NOARGS,
     "fields () -> list\n\
 Return a list holding all the fields of this type.\n\
@@ -1455,7 +1515,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." },
@@ -1465,16 +1525,50 @@ Return a volatile variant of this type" },
   { NULL }
 };
 
+static PyNumberMethods type_object_as_number = {
+  NULL,                              /* nb_add */
+  NULL,                              /* nb_subtract */
+  NULL,                              /* nb_multiply */
+#ifndef IS_PY3K
+  NULL,                              /* nb_divide */
+#endif
+  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 */
+#ifdef IS_PY3K
+  NULL,                              /* nb_int */
+  NULL,                              /* reserved */
+#else
+  NULL,                              /* nb_coerce */
+  NULL,                              /* nb_int */
+  NULL,                              /* nb_long */
+#endif
+  NULL,                              /* nb_float */
+#ifndef IS_PY3K
+  NULL,                              /* nb_oct */
+  NULL                       /* nb_hex */
+#endif
+};
+
 static PyMappingMethods typy_mapping = {
   typy_length,
   typy_getitem,
   NULL                           /* no "set" method */
 };
 
-static PyTypeObject type_object_type =
+PyTypeObject type_object_type =
 {
-  PyObject_HEAD_INIT (NULL)
-  0,                             /*ob_size*/
+  PyVarObject_HEAD_INIT (NULL, 0)
   "gdb.Type",                    /*tp_name*/
   sizeof (type_object),                  /*tp_basicsize*/
   0,                             /*tp_itemsize*/
@@ -1484,7 +1578,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 */
@@ -1514,10 +1608,16 @@ static PyTypeObject type_object_type =
   0,                             /* tp_new */
 };
 
-static PyTypeObject field_object_type =
+static gdb_PyGetSetDef field_object_getset[] =
+{
+  { "__dict__", gdb_py_generic_dict, NULL,
+    "The __dict__ for this field.", &field_object_type },
+  { NULL }
+};
+
+PyTypeObject field_object_type =
 {
-  PyObject_HEAD_INIT (NULL)
-  0,                             /*ob_size*/
+  PyVarObject_HEAD_INIT (NULL, 0)
   "gdb.Field",                   /*tp_name*/
   sizeof (field_object),         /*tp_basicsize*/
   0,                             /*tp_itemsize*/
@@ -1546,7 +1646,7 @@ static PyTypeObject field_object_type =
   0,                             /* tp_iternext */
   0,                             /* tp_methods */
   0,                             /* tp_members */
-  0,                             /* tp_getset */
+  field_object_getset,           /* tp_getset */
   0,                             /* tp_base */
   0,                             /* tp_dict */
   0,                             /* tp_descr_get */
@@ -1557,9 +1657,8 @@ static PyTypeObject field_object_type =
   0,                             /* tp_new */
 };
 
-static PyTypeObject type_iterator_object_type = {
-  PyObject_HEAD_INIT (NULL)
-  0,                             /*ob_size*/
+PyTypeObject type_iterator_object_type = {
+  PyVarObject_HEAD_INIT (NULL, 0)
   "gdb.TypeIterator",            /*tp_name*/
   sizeof (typy_iterator_object),  /*tp_basicsize*/
   0,                             /*tp_itemsize*/