aboutsummaryrefslogtreecommitdiff
path: root/gdb
diff options
context:
space:
mode:
Diffstat (limited to 'gdb')
-rw-r--r--gdb/ChangeLog25
-rw-r--r--gdb/Makefile.in6
-rw-r--r--gdb/doc/ChangeLog7
-rw-r--r--gdb/doc/gdb.texinfo286
-rw-r--r--gdb/python/python-internal.h4
-rw-r--r--gdb/python/python-type.c799
-rw-r--r--gdb/python/python-value.c58
-rw-r--r--gdb/python/python.c6
-rw-r--r--gdb/testsuite/ChangeLog15
-rw-r--r--gdb/testsuite/gdb.python/python-template.cc30
-rw-r--r--gdb/testsuite/gdb.python/python-template.exp75
-rw-r--r--gdb/testsuite/gdb.python/python-value.c6
-rw-r--r--gdb/testsuite/gdb.python/python-value.exp28
13 files changed, 1339 insertions, 6 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 6cf87ec..b5df971 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,6 +1,31 @@
2009-05-27 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-05-27 Tom Tromey <tromey@redhat.com>
+ Thiago Jung Bauermann <bauerman@br.ibm.com>
+ Phil Muldoon <pmuldoon@redhat.com>
* python/python.c: Include objfiles.h, observer.h.
(gdbpy_auto_load): New global.
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index df157bf..50e4e8d 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -268,6 +268,7 @@ SUBDIR_PYTHON_OBS = \
python-frame.o \
python-function.o \
python-objfile.o \
+ python-type.o \
python-utils.o \
python-value.o
SUBDIR_PYTHON_SRCS = \
@@ -276,6 +277,7 @@ SUBDIR_PYTHON_SRCS = \
python/python-frame.c \
python/python-function.c \
python/python-objfile.c \
+ python/python-type.c \
python/python-utils.c \
python/python-value.c
SUBDIR_PYTHON_DEPS =
@@ -1870,6 +1872,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/ChangeLog b/gdb/doc/ChangeLog
index c5594ff..1677900 100644
--- a/gdb/doc/ChangeLog
+++ b/gdb/doc/ChangeLog
@@ -1,3 +1,10 @@
+2009-05-27 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-05-27 Tom Tromey <tromey@redhat.com>
Thiago Jung Bauermann <bauerman@br.ibm.com>
Phil Muldoon <pmuldoon@redhat.com>
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index ba06b42..5fccb30 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -18516,6 +18516,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.
@@ -18701,17 +18702,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:
@@ -18766,6 +18772,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@t{++} 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@t{++} 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 f16b509..819867f 100644
--- a/gdb/python/python-internal.h
+++ b/gdb/python/python-internal.h
@@ -66,17 +66,21 @@ extern PyTypeObject value_object_type;
PyObject *gdbpy_history (PyObject *self, PyObject *args);
PyObject *gdbpy_frame_stop_reason_string (PyObject *, PyObject *);
PyObject *gdbpy_selected_frame (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_frames (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 78a23c7..701a931 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -552,6 +552,7 @@ Enables or disables auto-loading of Python code when an object is opened."),
gdbpy_initialize_frames ();
gdbpy_initialize_commands ();
gdbpy_initialize_functions ();
+ gdbpy_initialize_types ();
gdbpy_initialize_objfile ();
PyRun_SimpleString ("import gdb");
@@ -618,6 +619,11 @@ Return the selected frame object." },
"stop_reason_string (Integer) -> String.\n\
Return a string explaining unwind stop reason." },
+ { "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/ChangeLog b/gdb/testsuite/ChangeLog
index ff1cfea..818b2f7 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,18 @@
+2009-05-27 Thiago Jung Bauermann <bauerman@br.ibm.com>
+ Tom Tromey <tromey@redhat.com>
+ Pedro Alves <pedro@codesourcery.com>
+ Paul Pluzhnikov <ppluzhnikov@google.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.
+ (test_value_after_death): New proc.
+ * gdb.python/python-value.c (PTR): New typedef.
+ (main): New variable 'x'.
+
2009-05-27 Tom Tromey <tromey@redhat.com>
* gdb.python/python.exp (gdb_py_test_multiple): Add two objfile
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