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]

FYI: fix PR 11060


I am checking this in.

This fixes PR 11060.  The bug is that the Python type API cannot extract
template arguments which are not types themselves.

This fix relies on my earlier fix for PR 9946.  As such, it only works
with a new-enough GCC -- one that emits DW_TAG_template_*.

I've included some new test cases.  These only pass if you have a newish
gcc.  I was not sure what to do here, so I opted to have them FAIL by
default, rather than try to check GCC versions or whatever.  I am happy
to change this to whatever is appropriate.

Built and regtested on x86-64 (compile farm).  I also ran the new
py-type.exp against svn trunk gcc locally.

This code could be updated to allow Type.template_argument to work even
when DW_TAG_template_* is not available.  I don't think I am going to do
that, but I will take a stab at it if people think it is important
enough.

Tom

2010-07-28  Tom Tromey  <tromey@redhat.com>

	PR python/11060:
	* python/py-type.c (typy_legacy_template_argument): New function,
	extracted from typy_template_argument.
	(typy_template_argument): Use TYPE_TEMPLATE_ARGUMENT.  Return a
	value when needed.

2010-07-28  Tom Tromey  <tromey@redhat.com>

	PR python/11060:
	* gdb.python/py-type.c (Temargs): New template.
	(temvar): New variable.
	* gdb.python/py-type.exp (test_template): New proc.

diff --git a/gdb/python/py-type.c b/gdb/python/py-type.c
index b901255..529f301 100644
--- a/gdb/python/py-type.c
+++ b/gdb/python/py-type.c
@@ -509,34 +509,19 @@ typy_lookup_type (struct demangle_component *demangled,
   return type;
 }
 
+/* This is a helper function for typy_template_argument that is used
+   when the type does not have template symbols attached.  It works by
+   parsing the type name.  This happens with compilers, like older
+   versions of GCC, that do not emit DW_TAG_template_*.  */
+
 static PyObject *
-typy_template_argument (PyObject *self, PyObject *args)
+typy_legacy_template_argument (struct type *type, struct block *block,
+			       int argno)
 {
-  int i, argno;
-  struct type *type = ((type_object *) self)->type;
+  int i;
   struct demangle_component *demangled;
   const char *err;
   struct type *argtype;
-  struct block *block = NULL;
-  PyObject *block_obj = NULL;
-
-  if (! PyArg_ParseTuple (args, "i|O", &argno, &block_obj))
-    return NULL;
-
-  if (block_obj)
-    {
-      block = block_object_to_block (block_obj);
-      if (! block)
-	{
-	  PyErr_SetString (PyExc_RuntimeError,
-			   _("Second argument must be block."));
-	  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)
     {
@@ -584,6 +569,67 @@ typy_template_argument (PyObject *self, PyObject *args)
 }
 
 static PyObject *
+typy_template_argument (PyObject *self, PyObject *args)
+{
+  int argno;
+  struct type *type = ((type_object *) self)->type;
+  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 (block_obj)
+    {
+      block = block_object_to_block (block_obj);
+      if (! block)
+	{
+	  PyErr_SetString (PyExc_RuntimeError,
+			   _("Second argument must be block."));
+	  return NULL;
+	}
+    }
+
+  type = check_typedef (type);
+  if (TYPE_CODE (type) == TYPE_CODE_REF)
+    type = check_typedef (TYPE_TARGET_TYPE (type));
+
+  /* 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 --
+     but that is going to wind up as an error anyhow.  */
+  if (! TYPE_N_TEMPLATE_ARGUMENTS (type))
+    return typy_legacy_template_argument (type, block, argno);
+
+  if (argno >= TYPE_N_TEMPLATE_ARGUMENTS (type))
+    {
+      PyErr_Format (PyExc_RuntimeError, _("No argument %d in template."),
+		    argno);
+      return NULL;
+    }
+
+  sym = TYPE_TEMPLATE_ARGUMENT (type, argno);
+  if (SYMBOL_CLASS (sym) == LOC_TYPEDEF)
+    return type_to_type_object (SYMBOL_TYPE (sym));
+  else if (SYMBOL_CLASS (sym) == LOC_OPTIMIZED_OUT)
+    {
+      PyErr_Format (PyExc_RuntimeError,
+		    _("Template argument is optimized out"));
+      return NULL;
+    }
+
+  TRY_CATCH (except, RETURN_MASK_ALL)
+    {
+      val = value_of_variable (sym, block);
+    }
+  GDB_PY_HANDLE_EXCEPTION (except);
+
+  return value_to_value_object (val);
+}
+
+static PyObject *
 typy_str (PyObject *self)
 {
   volatile struct gdb_exception except;
diff --git a/gdb/testsuite/gdb.python/py-type.c b/gdb/testsuite/gdb.python/py-type.c
index f9c15cc..4650525 100644
--- a/gdb/testsuite/gdb.python/py-type.c
+++ b/gdb/testsuite/gdb.python/py-type.c
@@ -33,6 +33,14 @@ struct D : C
   int e;
   int f;
 };
+
+template<typename T, int I, int C::*MP>
+struct Temargs
+{
+};
+
+Temargs<D, 23, &C::c> temvar;
+
 #endif
 
 int
diff --git a/gdb/testsuite/gdb.python/py-type.exp b/gdb/testsuite/gdb.python/py-type.exp
index 63117ad..1cdb1c1 100644
--- a/gdb/testsuite/gdb.python/py-type.exp
+++ b/gdb/testsuite/gdb.python/py-type.exp
@@ -126,6 +126,23 @@ proc test_range {} {
   gdb_test "python print st.type.range()" "RuntimeError: This type does not have a range.*" "Check range for non ranged type."
 }
 
+# Some tests of template arguments.
+proc test_template {} {
+    gdb_py_test_silent_cmd \
+	"python ttype = gdb.parse_and_eval('temvar').type" \
+	"get type of temvar" \
+	1
+
+    gdb_test "python print ttype.template_argument(0)" "D"
+    gdb_test "python print isinstance(ttype.template_argument(0), gdb.Type)" \
+	"True"
+    # The next two tests require a GCC that emits DW_TAG_template_*.
+    gdb_test "python print ttype.template_argument(1)" "23"
+    gdb_test "python print isinstance(ttype.template_argument(1), gdb.Value)" \
+	"True"
+    setup_kfail "gcc/41736" *-*-*
+    gdb_test "python print ttype.template_argument(2)" "&C::c"
+}
 
 # Perform C Tests.
 build_inferior "c"
@@ -144,3 +161,4 @@ runto_bp "break to inspect struct and array."
 test_fields "c++"
 test_base_class
 test_range
+test_template


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