This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
PING: Re: [PATCH] Improve MI -var-info-path-expression for nested struct/union case.
- From: Andrew Burgess <aburgess at broadcom dot com>
- To: "gdb-patches at sourceware dot org" <gdb-patches at sourceware dot org>
- Date: Tue, 29 Apr 2014 15:17:50 +0100
- Subject: PING: Re: [PATCH] Improve MI -var-info-path-expression for nested struct/union case.
- Authentication-results: sourceware.org; auth=none
- References: <1397736351-20306-1-git-send-email-aburgess at broadcom dot com>
Ping.
On 17/04/2014 1:05 PM, Andrew Burgess wrote:
> 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. */
>