Bug 18282 - Pretty Printers - unable to create variable object (string value from children())
Summary: Pretty Printers - unable to create variable object (string value from childre...
Status: RESOLVED FIXED
Alias: None
Product: gdb
Classification: Unclassified
Component: varobj (show other bugs)
Version: 7.3
: P2 normal
Target Milestone: 14.1
Assignee: Tom Tromey
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2015-04-20 14:32 UTC by David Docteur
Modified: 2023-09-07 20:07 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments
Unable to create variable object issue (16.37 KB, image/png)
2015-04-20 14:32 UTC, David Docteur
Details
using same name as in class attributes (15.31 KB, image/png)
2015-04-21 13:02 UTC, David Docteur
Details

Note You need to log in before you can comment on or make changes to this bug.
Description David Docteur 2015-04-20 14:32:47 UTC
Created attachment 8255 [details]
Unable to create variable object issue

Hi guys,

I am using Eclipse Kepler, GDB 7.3.1 and working on a project with pretty printers (Python 2.7).

The problem is that I am trying to display a "prettyfied" object having children and the string type is displayed as characters array.
Types such as int or long are displayed properly.
Those children are obtained from a Python list object such as follow:



class TestPrinter:
    "Print a test printer"

    def __init__(self, val):
        self.val = val

    def to_string(self):
        return "map"

    def children(self):
        
        streetno = {"1":"testing", "2":"Dravid", "3":"Sehwag", 
                    "4":"Laxman","5":"Kohli"}
        
        for field in sorted(streetno.keys()):
            if field is not None:
                yield field, str(streetno[field])


def str_lookup_function(val):
       lookup_tag = val.type.tag
       if lookup_tag == None:
           return None
       regex = re.compile("^test$")
       if regex.match(lookup_tag):
         return TestPrinter(val)


If I return a simple string from to_string() (without calling the children() function) then it works well, and displayed as a string within Eclipse in the "Value" column.

But in this case, the children of my object are displayed as char[].
I can expand the content of each, which displays character by character and its ASCII value. Then, once I click on the child itself I get the following error:

1	char [33]	Error: Multiple errors reported.\ Failed to execute MI command: -var-create - * &((((this)->test_object)).1) Error message from debugger back end: -var-create: unable to create variable object\ Failed to execute MI command: -var-create - * &((((this)->test_object)).1) Error message from debugger back end: -var-create: unable to create variable object\ Unable to create variable object


The expected behavior would be, of course, to see the full string instead of "Error: Failed to execute MI ..."

Thank you very much for your help !
Comment 1 Doug Evans 2015-04-20 15:37:53 UTC
This is related to bug 17529.
There may even be an existing bug for this (Eclipse printing value as a char array).  Not sure about the MI errors though.
Comment 2 David Docteur 2015-04-21 12:58:24 UTC
Thanks for your answer.

I just read what you wrote:
"Eclipse is taking "name" and assuming it's a class member."

The MI errors were due to the fact that I was using different names in my pretty printer than the ones in my class.

Now, I can see the "char[N]" in the 'Type' column and the address of the object in the 'Value' column within Eclipse.
Comment 3 David Docteur 2015-04-21 13:02:59 UTC
Created attachment 8258 [details]
using same name as in class attributes
Comment 4 Alex 2021-07-02 20:32:54 UTC
Any workaround for this problem? How to return string from children()?
Comment 5 Tom Tromey 2023-08-31 16:13:19 UTC
This seems to be two different bugs.

First, if children returns strings, they don't seem to appear.
I get this from my test:

^done,numchild="5",children=[child={name="tval.1",exp="1",numchild="8",value="[8]",type="char [8]"},child={name="tval.2",exp="2",numchild="7",value="[7]",type="char [7]"},child={name="tval.3",exp="3",numchild="7",value="[7]",type="char [7]"},child={name="tval.4",exp="4",numchild="7",value="[7]",type="char [7]"},child={name="tval.5",exp="5",numchild="6",value="[6]",type="char [6]"}],has_more="0"

The string values don't appear at all, instead for some reason
we're getting map "indices".


Second, the name returned by the printer doesn't necessarily
correspond to any kind of sub-object.  This is the part that is
bug#17529.
Comment 6 Tom Tromey 2023-08-31 17:54:19 UTC
This turns out to be this code in c_value_of_variable:

    case TYPE_CODE_ARRAY:
      return string_printf ("[%d]", var->num_children);

i.e., the weird short-circuiting thing strikes again.
Comment 7 Tom Tromey 2023-08-31 18:21:56 UTC
I have a mildly hacky (given varobj, what else) patch for this.
Comment 8 Sourceware Commits 2023-09-07 20:06:01 UTC
The master branch has been updated by Tom Tromey <tromey@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=aa15623fe68b3151ed54a7365b5a5226b538851a

commit aa15623fe68b3151ed54a7365b5a5226b538851a
Author: Tom Tromey <tromey@adacore.com>
Date:   Thu Aug 31 13:01:00 2023 -0600

    Allow pretty-printer 'children' method to return strings
    
    A user noticed that, while a pretty-printer can return Python strings
    from its "children" method, this does not really work for MI.  I
    tracked this down to my_value_of_variable calling into
    c_value_of_variable, which specially handles arrays and structures --
    not using the actual contents of the string.
    
    Now, this part of MI seems bad to me, but rather than change that,
    this applies the fix to only dynamic varobjs, which is the only
    scenario where a string like this can really be returned.
    
    Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=18282
    Reviewed-by: Keith Seitz <keiths@redhat.com>
Comment 9 Tom Tromey 2023-09-07 20:07:08 UTC
Fixed.