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]

[PATCH] Improve MI -var-info-path-expression for nested struct/union case.


The MI command -var-info-path-expression currently does not handle some
cases of nested structures / unions correctly, consider the following
source file:

int
main ( void )
{
  struct a_t
  {
    int var;
  };

  struct s_t
  {
    struct a_t a;
  };

  struct s_t s;

  return 0; /* Break Here (line 16) */
}

And this gdb session:

(gdb) break 16
Breakpoint 1 at 0x400550: file nested.c, line 16.
(gdb) run
Starting program: /projects/firepath_work/aburgess/tmp/nested.x 
Can't read symbols from system-supplied DSO at 0x2aaaaaaab000: File truncated

Breakpoint 1, main () at nested.c:16
16        return 0; /* Break Here (line 16) */
(gdb) interpreter-exec mi "-var-create var1 @ s"
^done,name="var1",numchild="1",value="{...}",type="struct s_t",thread-id="1",has_more="0"
(gdb) interpreter-exec mi "-var-list-children var1"
^done,numchild="1",children=[child={name="var1.a",exp="a",numchild="1",type="struct a_t",thread-id="1"}],has_more="0"
(gdb) interpreter-exec mi "-var-list-children var1.a"
^done,numchild="1",children=[child={name="var1.a.var",exp="var",numchild="0",type="int",thread-id="1"}],has_more="0"
(gdb) interpreter-exec mi "-var-info-path-expression var1.a.var"
^done,path_expr="(s).var"
(gdb) interpreter-exec mi "-data-evaluate-expression (s).var"
^error,msg="There is no member named var."

Notice that the result of the -var-info-path-expression is wrong, and, not
surprisingly causes and error when passed into -data-evaluate-expression.

With this patch the result is instead this:

(gdb)  interpreter-exec mi "-var-info-path-expression var1.a.var"
^done,path_expr="((s).a).var"
(gdb) interpreter-exec mi "-data-evaluate-expression ((s).a).var"
^done,value="-8320"

The changes to varobj.c feel like it might be possible to simplify them,
but I can't figure out how, any change I make seems to regress something,
so for now I'm proposing this patch.  The change is very contained anyway,
so if someone can improve it later it's not going to cause any disruption.

OK to apply?

Thanks,
Andrew


gdb/ChangeLog:

	* varobj.c (is_path_expr_parent): Improve test for anonymous
	structures and unions.

gdb/testsuite/ChangeLog:

	* gdb.mi/var-cmd.c (do_nested_struct_union_tests): New function
	setting up test structures.
	(main): Call new test function.
	* gdb.mi/mi2-var-child.exp: Create additional breakpoint in new
	test function, continue into test function and walk test
	structures.
---
 gdb/testsuite/gdb.mi/mi2-var-child.exp | 61 +++++++++++++++++++++++++++++++
 gdb/testsuite/gdb.mi/var-cmd.c         | 65 ++++++++++++++++++++++++++++++++++
 gdb/varobj.c                           | 30 +++++++++++++---
 3 files changed, 152 insertions(+), 4 deletions(-)

diff --git a/gdb/testsuite/gdb.mi/mi2-var-child.exp b/gdb/testsuite/gdb.mi/mi2-var-child.exp
index d2f65c5..d9f5991 100644
--- a/gdb/testsuite/gdb.mi/mi2-var-child.exp
+++ b/gdb/testsuite/gdb.mi/mi2-var-child.exp
@@ -1162,6 +1162,10 @@ set lineno [gdb_get_line_number "anonymous type tests breakpoint"]
 mi_create_breakpoint \
     "$srcfile:$lineno" {[0-9]+} keep {do_anonymous_type_tests} \
     ".*var-cmd.c" $lineno $hex "break in do_anonymous_type_tests"
+set lineno [gdb_get_line_number "nested struct union tests breakpoint"]
+mi_create_breakpoint \
+    "$srcfile:$lineno" {[0-9]+} keep {do_nested_struct_union_tests} \
+    ".*var-cmd.c" $lineno $hex "break in do_nested_struct_union_tests"
 mi_execute_to "exec-continue" "breakpoint-hit" "do_anonymous_type_tests" ""\
     ".*" ".*" {"" "disp=\"keep\""} \
     "continue to do_anonymous_type_tests breakpoint"
@@ -1235,5 +1239,62 @@ set tree {
 
 mi_walk_varobj_tree c $tree verify_everything
 
+mi_send_resuming_command "exec-continue" \
+    "continuing execution to enter do_nested_struct_union_tests"
+mi_expect_stop "breakpoint-hit" "do_nested_struct_union_tests" ".*" ".*" ".*" \
+    {.* disp="keep"} "Run till MI stops in do_nested_struct_union_tests"
+
+set tree {
+  {struct ss} var {
+    {struct s_a} a1 {
+      int a {}
+    }
+    {struct s_b} b1 {
+      int b {}
+    }
+    {union u_ab} u1 {
+      {struct s_a} a {
+        int a {}
+      }
+      {struct s_b} b {
+        int b {}
+      }
+    }
+    anonymous union {
+      {struct s_a} a2 {
+        int a {}
+      }
+      {struct s_b} b2 {
+        int b {}
+      }
+    }
+    {union {...}} u2 {
+      {struct s_a} a3 {
+        int a {}
+      }
+      {struct s_b} b3 {
+        int b {}
+      }
+    }
+  }
+}
+
+mi_walk_varobj_tree c $tree verify_everything
+
+set tree {
+  {struct {...}} var2 {
+    {td_u_ab} ab {
+      {td_s_a} a {
+	int a {}
+      }
+      {td_s_b} b {
+	int b {}
+      }
+    }
+  }
+}
+
+mi_walk_varobj_tree c $tree verify_everything
+
 mi_gdb_exit
 return 0
diff --git a/gdb/testsuite/gdb.mi/var-cmd.c b/gdb/testsuite/gdb.mi/var-cmd.c
index 698b294..c519aa1 100644
--- a/gdb/testsuite/gdb.mi/var-cmd.c
+++ b/gdb/testsuite/gdb.mi/var-cmd.c
@@ -552,6 +552,70 @@ do_anonymous_type_tests (void)
   return; /* anonymous type tests breakpoint */
 }
 
+void
+do_nested_struct_union_tests (void)
+{
+  struct s_a
+  {
+    int a;
+  };
+  struct s_b
+  {
+    int b;
+  };
+  union u_ab
+  {
+    struct s_a a;
+    struct s_b b;
+  };
+  struct ss
+  {
+    struct s_a a1;
+    struct s_b b1;
+    union u_ab u1;
+
+    /* Anonymous union.  */
+    union
+    {
+      struct s_a a2;
+      struct s_b b2;
+    };
+
+    union
+    {
+      struct s_a a3;
+      struct s_b b3;
+    } u2;
+  };
+
+  typedef struct
+  {
+    int a;
+  } td_s_a;
+
+  typedef struct
+  {
+    int b;
+  } td_s_b;
+
+  typedef union
+  {
+    td_s_a a;
+    td_s_b b;
+  } td_u_ab;
+
+  struct ss var;
+  struct
+  {
+    td_u_ab ab;
+  } var2;
+
+  memset (&var, 0, sizeof (var));
+  memset (&var2, 0, sizeof (var2));
+
+  return; /* nested struct union tests breakpoint */
+}
+
 int
 main (int argc, char *argv [])
 {
@@ -563,6 +627,7 @@ main (int argc, char *argv [])
   do_at_tests ();
   do_bitfield_tests ();
   do_anonymous_type_tests ();
+  do_nested_struct_union_tests ();
   exit (0);
 }
 
diff --git a/gdb/varobj.c b/gdb/varobj.c
index 10ef5b7..33083b2 100644
--- a/gdb/varobj.c
+++ b/gdb/varobj.c
@@ -1075,12 +1075,34 @@ is_path_expr_parent (struct varobj *var)
   if (CPLUS_FAKE_CHILD (var))
     return 0;
 
-  type = varobj_get_value_type (var);
+  type = varobj_get_gdb_type (var);
 
   /* Anonymous unions and structs are also not path_expr parents.  */
-  return !((TYPE_CODE (type) == TYPE_CODE_STRUCT
-	    || TYPE_CODE (type) == TYPE_CODE_UNION)
-	   && TYPE_NAME (type) == NULL);
+  if ((TYPE_CODE (type) == TYPE_CODE_STRUCT
+       || TYPE_CODE (type) == TYPE_CODE_UNION)
+      && TYPE_NAME (type) == NULL
+      && TYPE_TAG_NAME (type) == NULL)
+    {
+      if (var->parent != NULL)
+	{
+	  const struct type *parent_type;
+
+	  parent_type = varobj_get_gdb_type (var->parent);
+	  if (TYPE_CODE (parent_type) == TYPE_CODE_STRUCT
+	      || TYPE_CODE (parent_type) == TYPE_CODE_UNION)
+	    {
+	      const char *field_name;
+
+	      gdb_assert (var->index < TYPE_NFIELDS (parent_type));
+	      field_name = TYPE_FIELD_NAME (parent_type, var->index);
+	      return !(field_name == NULL || *field_name == '\0');
+	    }
+	}
+
+      return 0;
+    }
+
+  return 1;
 }
 
 /* Return the path expression parent for VAR.  */
-- 
1.8.1.3


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