This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Python pretty-printing [3/6]


Here is the updated version of this patch.

Tom

2009-04-01  Tom Tromey  <tromey@redhat.com>
	    Thiago Jung Bauermann  <bauerman@br.ibm.com>
	    Phil Muldoon  <pmuldoon@redhat.com>
	    Paul Pluzhnikov  <ppluzhnikov@google.com>

	* python/python.c (_initialize_python): Call
	gdbpy_initialize_types.
	(GdbMethods): Add "lookup_type".
	* python/python-value.c (value_object) <type>: New field.
	(valpy_dealloc): Decref type.
	(valpy_new): Initialize type.
	(valpy_get_type): New function.
	(value_to_value_object): Initialize type.
	(valpy_cast): New function.
	(value_object_getset): Add "type".
	(value_object_methods): Add "cast".
	* python/python-internal.h (type_to_type_object): Declare.
	(type_object_to_type): Likewise.
	(gdbpy_initialize_types): Likewise.
	(gdbpy_lookup_type): Declare.
	* Makefile.in (SUBDIR_PYTHON_OBS): Add python-type.o.
	(SUBDIR_PYTHON_SRCS): Add python-type.c.
	(python-type.o): New target.
	* python/python-type.c: New file.

2009-04-01  Thiago Jung Bauermann  <bauerman@br.ibm.com>
	    Tom Tromey  <tromey@redhat.com>

	* gdb.texinfo (Types In Python): New node.
	(Values From Inferior): "type" is now an attribute.
	(Python API): Update.

2009-04-08  Tom Tromey  <tromey@redhat.com>
	    Paul Pluzhnikov  <ppluzhnikov@google.com>
	    Thiago Jung Bauermann  <bauerman@br.ibm.com>

	* gdb.python/python-template.exp: New file.
	* gdb.python/python-template.cc: New file.
	* gdb.python/python.exp (gdb_py_test_multiple): Add two objfile
	tests.
	* gdb.python/python-value.exp (py_objfile_tests): New proc.
	Call it.

 gdb/ChangeLog                                |   25 +
 gdb/Makefile.in                              |    6 +
 gdb/doc/ChangeLog                            |    7 +
 gdb/doc/gdb.texinfo                          |  286 +++++++++-
 gdb/python/python-internal.h                 |    4 +
 gdb/python/python-type.c                     |  799 ++++++++++++++++++++++++++
 gdb/python/python-value.c                    |   58 ++
 gdb/python/python.c                          |    6 +
 gdb/testsuite/ChangeLog                      |   15 +-
 gdb/testsuite/gdb.python/python-template.cc  |   30 +
 gdb/testsuite/gdb.python/python-template.exp |   75 +++
 gdb/testsuite/gdb.python/python-value.c      |    6 +-
 gdb/testsuite/gdb.python/python-value.exp    |   28 +
 13 files changed, 1338 insertions(+), 7 deletions(-)
 create mode 100644 gdb/python/python-type.c
 create mode 100644 gdb/testsuite/gdb.python/python-template.cc
 create mode 100644 gdb/testsuite/gdb.python/python-template.exp

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index dbd2126..265ec94 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -268,6 +268,7 @@ SUBDIR_PYTHON_OBS = \
 	python-cmd.o \
 	python-function.o \
 	python-objfile.o \
+	python-type.o \
 	python-utils.o \
 	python-value.o
 SUBDIR_PYTHON_SRCS = \
@@ -275,6 +276,7 @@ SUBDIR_PYTHON_SRCS = \
 	python/python-cmd.c \
 	python/python-function.c \
 	python/python-objfile.c \
+	python/python-type.c \
 	python/python-utils.c \
 	python/python-value.c
 SUBDIR_PYTHON_DEPS =
@@ -1857,6 +1859,10 @@ python-objfile.o: $(srcdir)/python/python-objfile.c
 	$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/python-objfile.c
 	$(POSTCOMPILE)
 
+python-type.o: $(srcdir)/python/python-type.c
+	$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/python-type.c
+	$(POSTCOMPILE)
+
 python-utils.o: $(srcdir)/python/python-utils.c
 	$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/python-utils.c
 	$(POSTCOMPILE)
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index ca3c99b..45ee8cf 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -18225,6 +18225,7 @@ situation, a Python @code{KeyboardInterrupt} exception is thrown.
 * Exception Handling::
 * Auto-loading::                Automatically loading Python code.
 * Values From Inferior::
+* Types In Python::		Python representation of types.
 * Commands In Python::          Implementing new commands in Python.
 * Functions In Python::         Writing new convenience functions.
 * Objfiles In Python::          Object files.
@@ -18409,17 +18410,22 @@ Again, @code{bar} will also be a @code{gdb.Value} object.
 The following attributes are provided:
 
 @table @code
-@defmethod Value address
+@defivar Value address
 If this object is addressable, this read-only attribute holds a
 @code{gdb.Value} object representing the address.  Otherwise,
 this attribute holds @code{None}.
-@end defmethod
+@end defivar
 
 @cindex optimized out value in Python
-@defmethod Value is_optimized_out
+@defivar Value is_optimized_out
 This read-only boolean attribute is true if the compiler optimized out
 this value, thus it is not available for fetching from the inferior.
-@end defmethod
+@end defivar
+
+@defivar Value type
+The type of this @code{gdb.Value}.  The value of this attribute is a
+@code{gdb.Type} object.
+@end defivar
 @end table
 
 The following methods are provided:
@@ -18474,6 +18480,278 @@ argument to Python's @code{string.decode} method.
 @end defmethod
 @end table
 
+@node Types In Python
+@subsubsection Types In Python
+@cindex types in Python
+@cindex Python, working with types
+
+@tindex gdb.Type
+@value{GDBN} represents types from the inferior using the class
+@code{gdb.Type}.
+
+The following type-related functions are available in the @code{gdb}
+module:
+
+@findex gdb.lookup_type
+@defun lookup_type name [block]
+This function looks up a type by name.  @var{name} is the name of the
+type to look up.  It must be a string.
+
+Ordinarily, this function will return an instance of @code{gdb.Type}.
+If the named type cannot be found, it will throw an exception.
+@end defun
+
+An instance of @code{Type} has the following attributes:
+
+@table @code
+@defivar Type code
+The type code for this type.  The type code will be one of the
+@code{TYPE_CODE_} constants defined below.
+@end defivar
+
+@defivar Type sizeof
+The size of this type, in target @code{char} units.  Usually, a
+target's @code{char} type will be an 8-bit byte.  However, on some
+unusual platforms, this type may have a different size.
+@end defivar
+
+@defivar Type tag
+The tag name for this type.  The tag name is the name after
+@code{struct}, @code{union}, or @code{enum} in C and C@t{++}; not all
+languages have this concept.  If this type has no tag name, then
+@code{None} is returned.
+@end defivar
+@end table
+
+The following methods are provided:
+
+@table @code
+@defmethod Type fields
+For structure and union types, this method returns the fields.  Range
+types have two fields, the minimum and maximum values.  Enum types
+have one field per enum constant.  Function and method types have one
+field per parameter.  The base types of C@t{++} classes are also
+represented as fields.  If the type has no fields, or does not fit
+into one of these categories, an empty sequence will be returned.
+
+Each field is an object, with some pre-defined attributes:
+@table @code
+@item bitpos
+This attribute is not available for @code{static} fields (as in
+C@t{++} or Java).  For non-@code{static} fields, the value is the bit
+position of the field.
+
+@item name
+The name of the field, or @code{None} for anonymous fields.
+
+@item artificial
+This is @code{True} if the field is artificial, usually meaning that
+it was provided by the compiler and not the user.  This attribute is
+always provided, and is @code{False} if the field is not artificial.
+
+@item bitsize
+If the field is packed, or is a bitfield, then this will have a
+non-zero value, which is the size of the field in bits.  Otherwise,
+this will be zero; in this case the field's size is given by its type.
+
+@item type
+The type of the field.  This is usually an instance of @code{Type},
+but it can be @code{None} in some situations.
+@end table
+@end defmethod
+
+@defmethod Type const
+Return a new @code{gdb.Type} object which represents a
+@code{const}-qualified variant of this type.
+@end defmethod
+
+@defmethod Type volatile
+Return a new @code{gdb.Type} object which represents a
+@code{volatile}-qualified variant of this type.
+@end defmethod
+
+@defmethod Type unqualified
+Return a new @code{gdb.Type} object which represents an unqualified
+variant of this type.  That is, the result is neither @code{const} nor
+@code{volatile}.
+@end defmethod
+
+@defmethod Type reference
+Return a new @code{gdb.Type} object which represents a reference to this
+type.
+@end defmethod
+
+@defmethod Type strip_typedefs
+Return a new @code{gdb.Type} that represents the real type,
+after removing all layers of typedefs.
+@end defmethod
+
+@defmethod Type target
+Return a new @code{gdb.Type} object which represents the target type
+of this type.
+
+For a pointer type, the target type is the type of the pointed-to
+object.  For an array type (meaning C-like arrays), the target type is
+the type of the elements of the array.  For a function or method type,
+the target type is the type of the return value.  For a complex type,
+the target type is the type of the elements.  For a typedef, the
+target type is the aliased type.
+
+If the type does not have a target, this method will throw an
+exception.
+@end defmethod
+
+@defmethod Type template_argument n
+If this @code{gdb.Type} is an instantiation of a template, this will
+return a new @code{gdb.Type} which represents the type of the
+@var{n}th template argument.
+
+If this @code{gdb.Type} is not a template type, this will throw an
+exception.  Ordinarily, only C@t{++} code will have template types.
+
+@var{name} is searched for globally.
+@end defmethod
+@end table
+
+
+Each type has a code, which indicates what category this type falls
+into.  The available type categories are represented by constants
+defined in the @code{gdb} module:
+
+@table @code
+@findex TYPE_CODE_PTR
+@findex gdb.TYPE_CODE_PTR
+@item TYPE_CODE_PTR
+The type is a pointer.
+
+@findex TYPE_CODE_ARRAY
+@findex gdb.TYPE_CODE_ARRAY
+@item TYPE_CODE_ARRAY
+The type is an array.
+
+@findex TYPE_CODE_STRUCT
+@findex gdb.TYPE_CODE_STRUCT
+@item TYPE_CODE_STRUCT
+The type is a structure.
+
+@findex TYPE_CODE_UNION
+@findex gdb.TYPE_CODE_UNION
+@item TYPE_CODE_UNION
+The type is a union.
+
+@findex TYPE_CODE_ENUM
+@findex gdb.TYPE_CODE_ENUM
+@item TYPE_CODE_ENUM
+The type is an enum.
+
+@findex TYPE_CODE_FLAGS
+@findex gdb.TYPE_CODE_FLAGS
+@item TYPE_CODE_FLAGS
+A bit flags type, used for things such as status registers.
+
+@findex TYPE_CODE_FUNC
+@findex gdb.TYPE_CODE_FUNC
+@item TYPE_CODE_FUNC
+The type is a function.
+
+@findex TYPE_CODE_INT
+@findex gdb.TYPE_CODE_INT
+@item TYPE_CODE_INT
+The type is an integer type.
+
+@findex TYPE_CODE_FLT
+@findex gdb.TYPE_CODE_FLT
+@item TYPE_CODE_FLT
+A floating point type.
+
+@findex TYPE_CODE_VOID
+@findex gdb.TYPE_CODE_VOID
+@item TYPE_CODE_VOID
+The special type @code{void}.
+
+@findex TYPE_CODE_SET
+@findex gdb.TYPE_CODE_SET
+@item TYPE_CODE_SET
+A Pascal set type.
+
+@findex TYPE_CODE_RANGE
+@findex gdb.TYPE_CODE_RANGE
+@item TYPE_CODE_RANGE
+A range type, that is, an integer type with bounds.
+
+@findex TYPE_CODE_STRING
+@findex gdb.TYPE_CODE_STRING
+@item TYPE_CODE_STRING
+A string type.  Note that this is only used for certain languages with
+language-defined string types; C strings are not represented this way.
+
+@findex TYPE_CODE_BITSTRING
+@findex gdb.TYPE_CODE_BITSTRING
+@item TYPE_CODE_BITSTRING
+A string of bits.
+
+@findex TYPE_CODE_ERROR
+@findex gdb.TYPE_CODE_ERROR
+@item TYPE_CODE_ERROR
+An unknown or erroneous type.
+
+@findex TYPE_CODE_METHOD
+@findex gdb.TYPE_CODE_METHOD
+@item TYPE_CODE_METHOD
+A method type, as found in C++ or Java.
+
+@findex TYPE_CODE_METHODPTR
+@findex gdb.TYPE_CODE_METHODPTR
+@item TYPE_CODE_METHODPTR
+A pointer-to-member-function.
+
+@findex TYPE_CODE_MEMBERPTR
+@findex gdb.TYPE_CODE_MEMBERPTR
+@item TYPE_CODE_MEMBERPTR
+A pointer-to-member.
+
+@findex TYPE_CODE_REF
+@findex gdb.TYPE_CODE_REF
+@item TYPE_CODE_REF
+A reference type.
+
+@findex TYPE_CODE_CHAR
+@findex gdb.TYPE_CODE_CHAR
+@item TYPE_CODE_CHAR
+A character type.
+
+@findex TYPE_CODE_BOOL
+@findex gdb.TYPE_CODE_BOOL
+@item TYPE_CODE_BOOL
+A boolean type.
+
+@findex TYPE_CODE_COMPLEX
+@findex gdb.TYPE_CODE_COMPLEX
+@item TYPE_CODE_COMPLEX
+A complex float type.
+
+@findex TYPE_CODE_TYPEDEF
+@findex gdb.TYPE_CODE_TYPEDEF
+@item TYPE_CODE_TYPEDEF
+A typedef to some other type.
+
+@findex TYPE_CODE_NAMESPACE
+@findex gdb.TYPE_CODE_NAMESPACE
+@item TYPE_CODE_NAMESPACE
+A C++ namespace.
+
+@findex TYPE_CODE_DECFLOAT
+@findex gdb.TYPE_CODE_DECFLOAT
+@item TYPE_CODE_DECFLOAT
+A decimal floating point type.
+
+@findex TYPE_CODE_INTERNAL_FUNCTION
+@findex gdb.TYPE_CODE_INTERNAL_FUNCTION
+@item TYPE_CODE_INTERNAL_FUNCTION
+A function internal to @value{GDBN}.  This is the type used to represent
+convenience functions.
+@end table
+
 @node Commands In Python
 @subsubsection Commands In Python
 
diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h
index 9764f4f..408d329 100644
--- a/gdb/python/python-internal.h
+++ b/gdb/python/python-internal.h
@@ -64,16 +64,20 @@ extern PyObject *gdb_module;
 extern PyTypeObject value_object_type;
 
 PyObject *gdbpy_history (PyObject *self, PyObject *args);
+PyObject *gdbpy_lookup_type (PyObject *self, PyObject *args, PyObject *kw);
 
 PyObject *value_to_value_object (struct value *v);
+PyObject *type_to_type_object (struct type *);
 PyObject *objfile_to_objfile_object (struct objfile *);
 
 PyObject *objfpy_get_printers (PyObject *, void *);
 
 struct value *convert_value_from_python (PyObject *obj);
+struct type *type_object_to_type (PyObject *obj);
 
 void gdbpy_initialize_values (void);
 void gdbpy_initialize_commands (void);
+void gdbpy_initialize_types (void);
 void gdbpy_initialize_functions (void);
 void gdbpy_initialize_objfile (void);
 
diff --git a/gdb/python/python-type.c b/gdb/python/python-type.c
new file mode 100644
index 0000000..577ebd2
--- /dev/null
+++ b/gdb/python/python-type.c
@@ -0,0 +1,799 @@
+/* Python interface to types.
+
+   Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "defs.h"
+#include "value.h"
+#include "exceptions.h"
+#include "python-internal.h"
+#include "charset.h"
+#include "gdbtypes.h"
+#include "cp-support.h"
+#include "demangle.h"
+#include "objfiles.h"
+
+typedef struct pyty_type_object
+{
+  PyObject_HEAD
+  struct type *type;
+
+  /* If a Type object is associated with an objfile, it is kept on a
+     doubly-linked list, rooted in the objfile.  This lets us copy the
+     underlying struct type when the objfile is deleted.  */
+  struct pyty_type_object *prev;
+  struct pyty_type_object *next;
+} type_object;
+
+static PyTypeObject type_object_type;
+
+/* A Field object.  */
+typedef struct pyty_field_object
+{
+  PyObject_HEAD
+
+  /* Dictionary holding our attributes.  */
+  PyObject *dict;
+} field_object;
+
+static PyTypeObject field_object_type;
+
+/* This is used to initialize various gdb.TYPE_ constants.  */
+struct pyty_code
+{
+  /* The code.  */
+  enum type_code code;
+  /* The name.  */
+  const char *name;
+};
+
+#define ENTRY(X) { X, #X }
+
+static struct pyty_code pyty_codes[] =
+{
+  ENTRY (TYPE_CODE_PTR),
+  ENTRY (TYPE_CODE_ARRAY),
+  ENTRY (TYPE_CODE_STRUCT),
+  ENTRY (TYPE_CODE_UNION),
+  ENTRY (TYPE_CODE_ENUM),
+  ENTRY (TYPE_CODE_FLAGS),
+  ENTRY (TYPE_CODE_FUNC),
+  ENTRY (TYPE_CODE_INT),
+  ENTRY (TYPE_CODE_FLT),
+  ENTRY (TYPE_CODE_VOID),
+  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_CHAR),
+  ENTRY (TYPE_CODE_BOOL),
+  ENTRY (TYPE_CODE_COMPLEX),
+  ENTRY (TYPE_CODE_TYPEDEF),
+  ENTRY (TYPE_CODE_NAMESPACE),
+  ENTRY (TYPE_CODE_DECFLOAT),
+  ENTRY (TYPE_CODE_INTERNAL_FUNCTION),
+  { TYPE_CODE_UNDEF, NULL }
+};
+
+
+
+static void
+field_dealloc (PyObject *obj)
+{
+  field_object *f = (field_object *) obj;
+  Py_XDECREF (f->dict);
+  f->ob_type->tp_free (obj);
+}
+
+static PyObject *
+field_new (void)
+{
+  field_object *result = PyObject_New (field_object, &field_object_type);
+  if (result)
+    {
+      result->dict = PyDict_New ();
+      if (!result->dict)
+	{
+	  Py_DECREF (result);
+	  result = NULL;
+	}
+    }
+  return (PyObject *) result;
+}
+
+
+
+/* Return the code for this type.  */
+static PyObject *
+typy_get_code (PyObject *self, void *closure)
+{
+  struct type *type = ((type_object *) self)->type;
+  return PyInt_FromLong (TYPE_CODE (type));
+}
+
+/* Helper function for typy_fields which converts a single field to a
+   dictionary.  Returns NULL on error.  */
+static PyObject *
+convert_field (struct type *type, int field)
+{
+  PyObject *result = field_new ();
+  PyObject *arg;
+
+  if (!result)
+    return NULL;
+
+  if (!field_is_static (&TYPE_FIELD (type, field)))
+    {
+      arg = PyLong_FromLong (TYPE_FIELD_BITPOS (type, field));
+      if (!arg)
+	goto fail;
+
+      if (PyObject_SetAttrString (result, "bitpos", arg) < 0)
+	goto failarg;
+    }
+
+  if (TYPE_FIELD_NAME (type, field))
+    arg = PyString_FromString (TYPE_FIELD_NAME (type, field));
+  else
+    {
+      arg = Py_None;
+      Py_INCREF (arg);
+    }
+  if (!arg)
+    goto fail;
+  if (PyObject_SetAttrString (result, "name", arg) < 0)
+    goto failarg;
+
+  arg = TYPE_FIELD_ARTIFICIAL (type, field) ? Py_True : Py_False;
+  Py_INCREF (arg);
+  if (PyObject_SetAttrString (result, "artificial", arg) < 0)
+    goto failarg;
+
+  arg = PyLong_FromLong (TYPE_FIELD_BITSIZE (type, field));
+  if (!arg)
+    goto fail;
+  if (PyObject_SetAttrString (result, "bitsize", arg) < 0)
+    goto failarg;
+
+  /* A field can have a NULL type in some situations.  */
+  if (TYPE_FIELD_TYPE (type, field) == NULL)
+    {
+      arg = Py_None;
+      Py_INCREF (arg);
+    }
+  else
+    arg = type_to_type_object (TYPE_FIELD_TYPE (type, field));
+  if (!arg)
+    goto fail;
+  if (PyObject_SetAttrString (result, "type", arg) < 0)
+    goto failarg;
+
+  return result;
+
+ failarg:
+  Py_DECREF (arg);
+ fail:
+  Py_DECREF (result);
+  return NULL;
+}
+
+/* Return a sequence of all fields.  Each field is a dictionary with
+   some pre-defined keys.  */
+static PyObject *
+typy_fields (PyObject *self, PyObject *args)
+{
+  PyObject *result;
+  int i;
+  struct type *type = ((type_object *) self)->type;
+
+  /* We would like to make a tuple here, make fields immutable, and
+     then memoize the result (and perhaps make Field.type() lazy).
+     However, that can lead to cycles.  */
+  result = PyList_New (0);
+
+  for (i = 0; i < TYPE_NFIELDS (type); ++i)
+    {
+      PyObject *dict = convert_field (type, i);
+      if (!dict)
+	{
+	  Py_DECREF (result);
+	  return NULL;
+	}
+      if (PyList_Append (result, dict))
+	{
+	  Py_DECREF (dict);
+	  Py_DECREF (result);
+	  return NULL;
+	}
+    }
+
+  return result;
+}
+
+/* Return the type's tag, or None.  */
+static PyObject *
+typy_get_tag (PyObject *self, void *closure)
+{
+  struct type *type = ((type_object *) self)->type;
+  if (!TYPE_TAG_NAME (type))
+    Py_RETURN_NONE;
+  return PyString_FromString (TYPE_TAG_NAME (type));
+}
+
+/* Return the type, stripped of typedefs. */
+static PyObject *
+typy_strip_typedefs (PyObject *self, PyObject *args)
+{
+  struct type *type = ((type_object *) self)->type;
+
+  return type_to_type_object (check_typedef (type));
+}
+
+/* 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)
+    {
+      type = lookup_pointer_type (type);
+    }
+  GDB_PY_HANDLE_EXCEPTION (except);
+
+  return type_to_type_object (type);
+}
+
+/* Return a Type object which represents a reference to SELF.  */
+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)
+    {
+      type = lookup_reference_type (type);
+    }
+  GDB_PY_HANDLE_EXCEPTION (except);
+
+  return type_to_type_object (type);
+}
+
+/* Return a Type object which represents the target type of SELF.  */
+static PyObject *
+typy_target (PyObject *self, PyObject *args)
+{
+  struct type *type = ((type_object *) self)->type;
+
+  if (!TYPE_TARGET_TYPE (type))
+    {
+      PyErr_SetString (PyExc_RuntimeError, "type does not have a target");
+      return NULL;
+    }
+
+  return type_to_type_object (TYPE_TARGET_TYPE (type));
+}
+
+/* Return a const-qualified type variant.  */
+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)
+    {
+      type = make_cv_type (1, 0, type, NULL);
+    }
+  GDB_PY_HANDLE_EXCEPTION (except);
+
+  return type_to_type_object (type);
+}
+
+/* Return a volatile-qualified type variant.  */
+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)
+    {
+      type = make_cv_type (0, 1, type, NULL);
+    }
+  GDB_PY_HANDLE_EXCEPTION (except);
+
+  return type_to_type_object (type);
+}
+
+/* Return an unqualified type variant.  */
+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)
+    {
+      type = make_cv_type (0, 0, type, NULL);
+    }
+  GDB_PY_HANDLE_EXCEPTION (except);
+
+  return type_to_type_object (type);
+}
+
+/* Return the size of the type represented by SELF, in bytes.  */
+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)
+    {
+      check_typedef (type);
+    }
+  /* Ignore exceptions.  */
+
+  return PyLong_FromLong (TYPE_LENGTH (type));
+}
+
+static struct type *
+typy_lookup_typename (char *type_name)
+{
+  struct type *type = NULL;
+  volatile struct gdb_exception except;
+  TRY_CATCH (except, RETURN_MASK_ALL)
+    {
+      if (!strncmp (type_name, "struct ", 7))
+	type = lookup_struct (type_name + 7, NULL);
+      else if (!strncmp (type_name, "union ", 6))
+	type = lookup_union (type_name + 6, NULL);
+      else if (!strncmp (type_name, "enum ", 5))
+	type = lookup_enum (type_name + 5, NULL);
+      else
+	type = lookup_typename (type_name, NULL, 0);
+    }
+  if (except.reason < 0)
+    {
+      PyErr_Format (except.reason == RETURN_QUIT
+		    ? PyExc_KeyboardInterrupt : PyExc_RuntimeError,
+		    "%s", except.message);
+      return NULL;
+    }
+
+  return type;
+}
+
+static struct type *
+typy_lookup_type (struct demangle_component *demangled)
+{
+  struct type *type;
+  char *type_name;
+  enum demangle_component_type demangled_type;
+
+  /* Save the type: typy_lookup_type() may (indirectly) overwrite
+     memory pointed by demangled.  */
+  demangled_type = demangled->type;
+
+  if (demangled_type == DEMANGLE_COMPONENT_POINTER
+      || demangled_type == DEMANGLE_COMPONENT_REFERENCE
+      || demangled_type == DEMANGLE_COMPONENT_CONST
+      || demangled_type == DEMANGLE_COMPONENT_VOLATILE)
+    {
+      type = typy_lookup_type (demangled->u.s_binary.left);
+      if (! type)
+	return NULL;
+
+      switch (demangled_type)
+	{
+	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);
+	}
+    }
+
+  type_name = cp_comp_to_string (demangled, 10);
+  type = typy_lookup_typename (type_name);
+  xfree (type_name);
+
+  return type;
+}
+
+static PyObject *
+typy_template_argument (PyObject *self, PyObject *args)
+{
+  int i, argno, n_pointers;
+  struct type *type = ((type_object *) self)->type;
+  struct demangle_component *demangled;
+  const char *err;
+  struct type *argtype;
+
+  if (! PyArg_ParseTuple (args, "i", &argno))
+    return NULL;
+
+  type = check_typedef (type);
+  if (TYPE_CODE (type) == TYPE_CODE_REF)
+    type = check_typedef (TYPE_TARGET_TYPE (type));
+
+  if (TYPE_NAME (type) == NULL)
+    {
+      PyErr_SetString (PyExc_RuntimeError, "null type name");
+      return NULL;
+    }
+
+  /* Note -- this is not thread-safe.  */
+  demangled = cp_demangled_name_to_comp (TYPE_NAME (type), &err);
+  if (! demangled)
+    {
+      PyErr_SetString (PyExc_RuntimeError, err);
+      return NULL;
+    }
+
+  /* Strip off component names.  */
+  while (demangled->type == DEMANGLE_COMPONENT_QUAL_NAME
+	 || demangled->type == DEMANGLE_COMPONENT_LOCAL_NAME)
+    demangled = demangled->u.s_binary.right;
+
+  if (demangled->type != DEMANGLE_COMPONENT_TEMPLATE)
+    {
+      PyErr_SetString (PyExc_RuntimeError, "type is not a template");
+      return NULL;
+    }
+
+  /* Skip from the template to the arguments.  */
+  demangled = demangled->u.s_binary.right;
+
+  for (i = 0; demangled && i < argno; ++i)
+    demangled = demangled->u.s_binary.right;
+
+  if (! demangled)
+    {
+      PyErr_Format (PyExc_RuntimeError, "no argument %d in template",
+		    argno);
+      return NULL;
+    }
+
+  argtype = typy_lookup_type (demangled->u.s_binary.left);
+  if (! argtype)
+    return NULL;
+
+  return type_to_type_object (argtype);
+}
+
+static PyObject *
+typy_str (PyObject *self)
+{
+  volatile struct gdb_exception except;
+  char *thetype = NULL;
+  PyObject *result;
+
+  TRY_CATCH (except, RETURN_MASK_ALL)
+    {
+      struct cleanup *old_chain;
+      struct ui_file *stb;
+      long length;
+
+      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);
+    }
+  if (except.reason < 0)
+    {
+      xfree (thetype);
+      GDB_PY_HANDLE_EXCEPTION (except);
+    }
+
+  result = PyUnicode_Decode (thetype, strlen (thetype), host_charset (), NULL);
+  xfree (thetype);
+
+  return result;
+}
+
+
+
+static const struct objfile_data *typy_objfile_data_key;
+
+static void
+clean_up_objfile_types (struct objfile *objfile, void *datum)
+{
+  type_object *obj = datum;
+  htab_t copied_types;
+  struct cleanup *cleanup;
+  PyGILState_STATE state;
+
+  /* This prevents another thread from freeing the objects we're
+     operating on.  */
+  state = PyGILState_Ensure ();
+  cleanup = make_cleanup_py_restore_gil (&state);
+
+  copied_types = create_copied_types_hash (objfile);
+
+  while (obj)
+    {
+      type_object *next = obj->next;
+
+      htab_empty (copied_types);
+
+      obj->type = copy_type_recursive (objfile, obj->type, copied_types);
+
+      obj->next = NULL;
+      obj->prev = NULL;
+
+      obj = next;
+    }
+
+  htab_delete (copied_types);
+
+  do_cleanups (cleanup);
+}
+
+static void
+set_type (type_object *obj, struct type *type)
+{
+  obj->type = type;
+  obj->prev = NULL;
+  if (type && TYPE_OBJFILE (type))
+    {
+      struct objfile *objfile = TYPE_OBJFILE (type);
+
+      obj->next = objfile_data (objfile, typy_objfile_data_key);
+      if (obj->next)
+	obj->next->prev = obj;
+      set_objfile_data (objfile, typy_objfile_data_key, obj);
+    }
+  else
+    obj->next = NULL;
+}
+
+static void
+typy_dealloc (PyObject *obj)
+{
+  type_object *type = (type_object *) obj;
+
+  if (type->prev)
+    type->prev->next = type->next;
+  else if (type->type && TYPE_OBJFILE (type->type))
+    {
+      /* Must reset head of list.  */
+      struct objfile *objfile = TYPE_OBJFILE (type->type);
+      if (objfile)
+	set_objfile_data (objfile, typy_objfile_data_key, type->next);
+    }
+  if (type->next)
+    type->next->prev = type->prev;
+
+  type->ob_type->tp_free (type);
+}
+
+/* Create a new Type referring to TYPE.  */
+PyObject *
+type_to_type_object (struct type *type)
+{
+  type_object *type_obj;
+
+  type_obj = PyObject_New (type_object, &type_object_type);
+  if (type_obj)
+    set_type (type_obj, type);
+
+  return (PyObject *) type_obj;
+}
+
+struct type *
+type_object_to_type (PyObject *obj)
+{
+  if (! PyObject_TypeCheck (obj, &type_object_type))
+    return NULL;
+  return ((type_object *) obj)->type;
+}
+
+
+
+/* Implementation of gdb.lookup_type.  */
+PyObject *
+gdbpy_lookup_type (PyObject *self, PyObject *args, PyObject *kw)
+{
+  static char *keywords[] = { "name", NULL };
+  char *type_name = NULL;
+  struct type *type = NULL;
+
+  if (! PyArg_ParseTupleAndKeywords (args, kw, "s", keywords, &type_name))
+    return NULL;
+
+  type = typy_lookup_typename (type_name);
+  if (! type)
+    return NULL;
+
+  return (PyObject *) type_to_type_object (type);
+}
+
+void
+gdbpy_initialize_types (void)
+{
+  int i;
+
+  typy_objfile_data_key
+    = register_objfile_data_with_cleanup (clean_up_objfile_types);
+
+  if (PyType_Ready (&type_object_type) < 0)
+    return;
+  if (PyType_Ready (&field_object_type) < 0)
+    return;
+
+  for (i = 0; pyty_codes[i].name; ++i)
+    {
+      if (PyModule_AddIntConstant (gdb_module,
+				   /* Cast needed for Python 2.4.  */
+				   (char *) pyty_codes[i].name,
+				   pyty_codes[i].code) < 0)
+	return;
+    }
+
+  Py_INCREF (&type_object_type);
+  PyModule_AddObject (gdb_module, "Type", (PyObject *) &type_object_type);
+
+  Py_INCREF (&field_object_type);
+  PyModule_AddObject (gdb_module, "Field", (PyObject *) &field_object_type);
+}
+
+
+
+static PyGetSetDef type_object_getset[] =
+{
+  { "code", typy_get_code, NULL,
+    "The code for this type.", 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 },
+  { NULL }
+};
+
+static PyMethodDef type_object_methods[] =
+{
+  { "const", typy_const, METH_NOARGS,
+    "const () -> Type\n\
+Return a const variant of this type." },
+  { "fields", typy_fields, METH_NOARGS,
+    "field () -> list\n\
+Return a sequence holding all the fields of this type.\n\
+Each field is a dictionary." },
+  { "pointer", typy_pointer, METH_NOARGS,
+    "pointer () -> Type\n\
+Return a type of pointer to this type." },
+  { "reference", typy_reference, METH_NOARGS,
+    "reference () -> Type\n\
+Return a type of reference to this type." },
+  { "strip_typedefs", typy_strip_typedefs, METH_NOARGS,
+    "strip_typedefs () -> Type\n\
+Return a type formed by stripping this type of all typedefs."},
+  { "target", typy_target, METH_NOARGS,
+    "target () -> Type\n\
+Return the target type of this type." },
+  { "template_argument", typy_template_argument, METH_VARARGS,
+    "template_argument (arg) -> Type\n\
+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." },
+  { "volatile", typy_volatile, METH_NOARGS,
+    "volatile () -> Type\n\
+Return a volatile variant of this type" },
+  { NULL }
+};
+
+static PyTypeObject type_object_type =
+{
+  PyObject_HEAD_INIT (NULL)
+  0,				  /*ob_size*/
+  "gdb.Type",			  /*tp_name*/
+  sizeof (type_object),		  /*tp_basicsize*/
+  0,				  /*tp_itemsize*/
+  typy_dealloc,			  /*tp_dealloc*/
+  0,				  /*tp_print*/
+  0,				  /*tp_getattr*/
+  0,				  /*tp_setattr*/
+  0,				  /*tp_compare*/
+  0,				  /*tp_repr*/
+  0,				  /*tp_as_number*/
+  0,				  /*tp_as_sequence*/
+  0,				  /*tp_as_mapping*/
+  0,				  /*tp_hash */
+  0,				  /*tp_call*/
+  typy_str,			  /*tp_str*/
+  0,				  /*tp_getattro*/
+  0,				  /*tp_setattro*/
+  0,				  /*tp_as_buffer*/
+  Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_ITER,  /*tp_flags*/
+  "GDB type object",		  /* tp_doc */
+  0,				  /* tp_traverse */
+  0,				  /* tp_clear */
+  0,				  /* tp_richcompare */
+  0,				  /* tp_weaklistoffset */
+  0,				  /* tp_iter */
+  0,				  /* tp_iternext */
+  type_object_methods,		  /* tp_methods */
+  0,				  /* tp_members */
+  type_object_getset,		  /* tp_getset */
+  0,				  /* tp_base */
+  0,				  /* tp_dict */
+  0,				  /* tp_descr_get */
+  0,				  /* tp_descr_set */
+  0,				  /* tp_dictoffset */
+  0,				  /* tp_init */
+  0,				  /* tp_alloc */
+  0,				  /* tp_new */
+};
+
+static PyTypeObject field_object_type =
+{
+  PyObject_HEAD_INIT (NULL)
+  0,				  /*ob_size*/
+  "gdb.Field",			  /*tp_name*/
+  sizeof (field_object),	  /*tp_basicsize*/
+  0,				  /*tp_itemsize*/
+  field_dealloc,		  /*tp_dealloc*/
+  0,				  /*tp_print*/
+  0,				  /*tp_getattr*/
+  0,				  /*tp_setattr*/
+  0,				  /*tp_compare*/
+  0,				  /*tp_repr*/
+  0,				  /*tp_as_number*/
+  0,				  /*tp_as_sequence*/
+  0,				  /*tp_as_mapping*/
+  0,				  /*tp_hash */
+  0,				  /*tp_call*/
+  0,				  /*tp_str*/
+  0,				  /*tp_getattro*/
+  0,				  /*tp_setattro*/
+  0,				  /*tp_as_buffer*/
+  Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_ITER,  /*tp_flags*/
+  "GDB field object",		  /* tp_doc */
+  0,				  /* tp_traverse */
+  0,				  /* tp_clear */
+  0,				  /* tp_richcompare */
+  0,				  /* tp_weaklistoffset */
+  0,				  /* tp_iter */
+  0,				  /* tp_iternext */
+  0,				  /* tp_methods */
+  0,				  /* tp_members */
+  0,				  /* tp_getset */
+  0,				  /* tp_base */
+  0,				  /* tp_dict */
+  0,				  /* tp_descr_get */
+  0,				  /* tp_descr_set */
+  offsetof (field_object, dict),  /* tp_dictoffset */
+  0,				  /* tp_init */
+  0,				  /* tp_alloc */
+  0,				  /* tp_new */
+};
diff --git a/gdb/python/python-value.c b/gdb/python/python-value.c
index 5faa281..76f5cde 100644
--- a/gdb/python/python-value.c
+++ b/gdb/python/python-value.c
@@ -59,6 +59,7 @@ typedef struct {
   PyObject_HEAD
   struct value *value;
   PyObject *address;
+  PyObject *type;
 } value_object;
 
 /* Called by the Python interpreter when deallocating a value object.  */
@@ -77,6 +78,11 @@ valpy_dealloc (PyObject *obj)
       Py_DECREF (self->address);
     }
 
+  if (self->type)
+    {
+      Py_DECREF (self->type);
+    }
+
   self->ob_type->tp_free (self);
 }
 
@@ -111,6 +117,7 @@ valpy_new (PyTypeObject *subtype, PyObject *args, PyObject *keywords)
 
   value_obj->value = value;
   value_obj->address = NULL;
+  value_obj->type = NULL;
   release_value (value);
   value_prepend_to_list (&values_in_python, value);
 
@@ -161,6 +168,24 @@ valpy_get_address (PyObject *self, void *closure)
   return val_obj->address;
 }
 
+/* Return type of the value.  */
+static PyObject *
+valpy_get_type (PyObject *self, void *closure)
+{
+  value_object *obj = (value_object *) self;
+  if (!obj->type)
+    {
+      obj->type = type_to_type_object (value_type (obj->value));
+      if (!obj->type)
+	{
+	  obj->type = Py_None;
+	  Py_INCREF (obj->type);
+	}
+    }
+  Py_INCREF (obj->type);
+  return obj->type;
+}
+
 /* Implementation of gdb.Value.string ([encoding] [, errors]) -> string
    Return Unicode string with value contents.  If ENCODING is not given,
    the string is assumed to be encoded in the target's charset.  */
@@ -195,6 +220,34 @@ valpy_string (PyObject *self, PyObject *args, PyObject *kw)
   return unicode;
 }
 
+/* Cast a value to a given type.  */
+static PyObject *
+valpy_cast (PyObject *self, PyObject *args)
+{
+  PyObject *type_obj;
+  struct type *type;
+  struct value *res_val = NULL;	  /* Initialize to appease gcc warning.  */
+  volatile struct gdb_exception except;
+
+  if (! PyArg_ParseTuple (args, "O", &type_obj))
+    return NULL;
+
+  type = type_object_to_type (type_obj);
+  if (! type)
+    {
+      PyErr_SetString (PyExc_RuntimeError, "argument must be a Type");
+      return NULL;
+    }
+
+  TRY_CATCH (except, RETURN_MASK_ALL)
+    {
+      res_val = value_cast (type, ((value_object *) self)->value);
+    }
+  GDB_PY_HANDLE_EXCEPTION (except);
+
+  return value_to_value_object (res_val);
+}
+
 static Py_ssize_t
 valpy_length (PyObject *self)
 {
@@ -744,6 +797,7 @@ value_to_value_object (struct value *val)
     {
       val_obj->value = val;
       val_obj->address = NULL;
+      val_obj->type = NULL;
       release_value (val);
       value_prepend_to_list (&values_in_python, val);
     }
@@ -855,16 +909,20 @@ gdbpy_initialize_values (void)
   values_in_python = NULL;
 }
 
+
+
 static PyGetSetDef value_object_getset[] = {
   { "address", valpy_get_address, NULL, "The address of the value.",
     NULL },
   { "is_optimized_out", valpy_get_is_optimized_out, NULL,
     "Boolean telling whether the value is optimized out (i.e., not available).",
     NULL },
+  { "type", valpy_get_type, NULL, "Type of the value.", NULL },
   {NULL}  /* Sentinel */
 };
 
 static PyMethodDef value_object_methods[] = {
+  { "cast", valpy_cast, METH_VARARGS, "Cast the value to the supplied type." },
   { "dereference", valpy_dereference, METH_NOARGS, "Dereferences the value." },
   { "string", (PyCFunction) valpy_string, METH_VARARGS | METH_KEYWORDS,
     "string ([encoding] [, errors]) -> string\n\
diff --git a/gdb/python/python.c b/gdb/python/python.c
index fcf351f..1330cd1 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -551,6 +551,7 @@ Enables or disables auto-loading of Python code when an object is opened."),
   gdbpy_initialize_values ();
   gdbpy_initialize_commands ();
   gdbpy_initialize_functions ();
+  gdbpy_initialize_types ();
   gdbpy_initialize_objfile ();
 
   PyRun_SimpleString ("import gdb");
@@ -610,6 +611,11 @@ static PyMethodDef GdbMethods[] =
   { "objfiles", gdbpy_objfiles, METH_NOARGS,
     "Return a sequence of all loaded objfiles." },
 
+  { "lookup_type", (PyCFunction) gdbpy_lookup_type,
+    METH_VARARGS | METH_KEYWORDS,
+    "lookup_type (name [, block]) -> type\n\
+Return a Type corresponding to the given name." },
+
   { "write", gdbpy_write, METH_VARARGS,
     "Write a string using gdb's filtered stream." },
   { "flush", gdbpy_flush, METH_NOARGS,
diff --git a/gdb/testsuite/gdb.python/python-template.cc b/gdb/testsuite/gdb.python/python-template.cc
new file mode 100644
index 0000000..bd6a212
--- /dev/null
+++ b/gdb/testsuite/gdb.python/python-template.cc
@@ -0,0 +1,30 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2008 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+template <typename T>
+struct Foo {
+};
+
+#ifndef TYPE
+#define TYPE int
+#endif
+
+int main()
+{
+  Foo<TYPE> foo;
+  return 0; // break here
+}
diff --git a/gdb/testsuite/gdb.python/python-template.exp b/gdb/testsuite/gdb.python/python-template.exp
new file mode 100644
index 0000000..1ace5d6
--- /dev/null
+++ b/gdb/testsuite/gdb.python/python-template.exp
@@ -0,0 +1,75 @@
+# Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# This file is part of the GDB testsuite.  It tests the mechanism
+# exposing values to Python.
+
+if $tracelevel then {
+    strace $tracelevel
+}
+
+set testfile "python-template"
+set srcfile ${testfile}.cc
+set binfile ${objdir}/${subdir}/${testfile}
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable \
+	  {debug c++}] != "" } {
+    untested "Couldn't compile ${srcfile}"
+    return -1
+}
+
+# Start with a fresh gdb.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+
+gdb_test_multiple "python print 23" "verify python support" {
+    -re "not supported.*$gdb_prompt $"	{
+      unsupported "python support is disabled"
+      return -1
+    }
+    -re "$gdb_prompt $"	{}
+}
+
+proc test_template_arg {type} {
+    global testfile srcdir subdir srcfile binfile
+    if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" \
+		executable \
+	  	[list debug c++ additional_flags="-DTYPE=$type"]] != "" } {
+	untested $type
+	return -1
+    }
+    gdb_load ${binfile}
+    if ![runto_main ] then {
+	perror "couldn't run to breakpoint"
+	return
+    }
+    # There is no executable code in main(), so we are where we want to be
+    gdb_test "print foo" ""
+    gdb_test "python foo = gdb.history(0)" ""
+
+    # Replace '*' with '\*' in regex.
+    regsub -all {\*} $type {\*} t
+    gdb_test "python print foo.type.template_argument(0)" $t $type
+}
+
+test_template_arg "const int"
+test_template_arg "volatile int"
+test_template_arg "const int &"
+test_template_arg "volatile int &"
+test_template_arg "volatile int * const"
+test_template_arg "volatile int * const *"
+test_template_arg "const int * volatile"
+test_template_arg "const int * volatile * const * volatile *"
diff --git a/gdb/testsuite/gdb.python/python-value.c b/gdb/testsuite/gdb.python/python-value.c
index 17e5c62..092c520 100644
--- a/gdb/testsuite/gdb.python/python-value.c
+++ b/gdb/testsuite/gdb.python/python-value.c
@@ -33,19 +33,21 @@ enum e
     TWO = 2
   };
 
+typedef struct s *PTR;
+
 enum e evalue = TWO;
 
 int
 main (int argc, char *argv[])
 {
+  char *cp = argv[0]; /* Prevent gcc from optimizing argv[] out.  */
   struct s s;
   union u u;
+  PTR x = &s;
 
   s.a = 3;
   s.b = 5;
   u.a = 7;
 
-  argv[0][0] = 'a';   /* Just to avoid getting argv optimized out.  */
-
   return 0;      /* break to inspect struct and union */
 }
diff --git a/gdb/testsuite/gdb.python/python-value.exp b/gdb/testsuite/gdb.python/python-value.exp
index 93e9d89..20333f6 100644
--- a/gdb/testsuite/gdb.python/python-value.exp
+++ b/gdb/testsuite/gdb.python/python-value.exp
@@ -246,6 +246,33 @@ proc test_objfiles {} {
       "pretty_printers attribute must be a list.*Error while executing Python code."
 }
 
+proc test_value_after_death {} {
+  # Construct a type while the inferior is still running.
+  gdb_py_test_silent_cmd "python ptrtype = gdb.lookup_type('PTR')" \
+    "create PTR type" 1
+
+  # Kill the inferior and remove the symbols.
+  gdb_test "kill" "" "kill the inferior" \
+    "Kill the program being debugged. .y or n. $" \
+    "y"
+  gdb_test "file" "" "Discard the symbols" \
+    "Discard symbol table from.*y or n. $" \
+    "y"
+
+  # Now create a value using that type.  Relies on arg0, created by
+  # test_value_in_inferior.
+  gdb_py_test_silent_cmd "python castval = arg0.cast(ptrtype.pointer())" \
+    "cast arg0 to PTR" 1
+
+  # Make sure the type is deleted.
+  gdb_py_test_silent_cmd "python ptrtype = None" \
+    "delete PTR type" 1
+
+  # Now see if the value's type is still valid.
+  gdb_test "python print castval.type" "PTR ." \
+    "print value's type"
+}
+
 # Start with a fresh gdb.
 
 gdb_exit
@@ -275,3 +302,4 @@ if ![runto_main] then {
 }
 
 test_value_in_inferior
+test_value_after_death
-- 
1.6.0.6


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]