Bug 13111 - -var-update doesn't handle type changes of array childs
Summary: -var-update doesn't handle type changes of array childs
Status: NEW
Alias: None
Product: gdb
Classification: Unclassified
Component: python (show other bugs)
Version: 7.3
: P2 minor
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2011-08-19 11:03 UTC by Mathias Kunter
Modified: 2012-12-11 13:33 UTC (History)
1 user (show)

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


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Mathias Kunter 2011-08-19 11:03:17 UTC
The gdb/mi command "-var-update" may return an incorrect value for "type_changed" when pretty-printers are used.

Consider the following example. The struct "printMePretty" should be pretty-printed by using the Python TestPrinter class from below. It should be printed as an integer "array" (it doesn't actually makes sense here, it's just for testing) if the structure's "printAsInt" member is true, and as a floating point "array" otherwise.


****************** File: main.cpp *****************

struct printMePretty
{
	bool printAsInt;
	int intMember;
	float floatMember;

	printMePretty() :
		printAsInt(true),
		intMember(0xFF),
		floatMember(3.1415)
	{ }
};

void main()
{
	printMePretty pretty;
	pretty.printAsInt = false;
}


****************** File: printer.py *****************

[...]

class TestPrinter:
    class _iterator:
        def __init__(self, val):
            self.val = val
            self.index = 0

        def __iter__(self):
            return self

        def next(self):
            if self.index == 1:
                raise StopIteration
            
            if self.val['printAsInt']:
                childValue = self.val['intMember']
            else:
                childValue = self.val['floatMember']
            
            self.index += 1
            return ('Value', childValue)
    
    def __init__(self, val):
        self.val = val

    def children(self):
        return self._iterator(self.val)

    def display_hint(self):
        return 'array'


****************** End of file *****************


Using Eclipse CDT to trace gdb/mi commands, one encounters the following until the line "pretty.printAsInt = false;":


-var-create --thread 1 --frame 0 - * pretty
^done,name="var1",numchild="0",value="{...}",type="printMePretty",thread-id="1",displayhint="array",dynamic="1",has_more="1"

-var-list-children var1 0 1
^done,numchild="1",displayhint="array",children=[child={name="var1.Value",exp="Value",numchild="0",type="int",thread-id="1"}],has_more="0"


OK, so "var1.Value" has type "int". Now, stepping over the line "pretty.printAsInt = false;" results in:


-var-update 1 var1
^done,changelist=[{name="var1.Value",value="3.1415",in_scope="true",type_changed="false",displayhint="array",dynamic="1",has_more="0"}]


It now says that "var1.Value" would have a "value" of "3.1415" - that's obviously a strange value for an "int" (since "type_changed" reports "false" - I suppose it should actually report that the type has changed to "float").

This seems like a bug within gdb to me. The same problem may also apply if a pretty-printer's toString() method returns gdb.Values which have different gdb.Types, depending on the data members of the structure which should be pretty-printed.
Comment 1 Andre' 2012-11-17 19:16:17 UTC
-var-update was created to keep track of standard situations, like watching data members of C style structures.

They can conceptually not work for "complex" pretty-printing in the presence of arbitrary changes to the environment like the value of global variables or the return value of function calls.

The only safe approach for a gdb frontend is to not rely on -var-update (or varobj at all for that matter) and re-run all pretty printers everytime something could have changed.
Comment 2 Mathias Kunter 2012-12-10 19:23:07 UTC
Well, the -var-update command apparently successfully recognizes the updated pretty printer expression, since we can see the updated value "3.1415".

If -var-update can recognize the updated value of the gdb.Value returned from the pretty printer, then it must also be able to recognize a type change of that gdb.Value, correct?
Comment 3 Andre' 2012-12-11 06:45:44 UTC
Your particular problem might be indeed fixable, as all "state" is locally available. However, this does not solve the general problem, see http://sourceware.org/bugzilla/show_bug.cgi?id=14854
Comment 4 Mathias Kunter 2012-12-11 13:29:12 UTC
I understand that -var-update can't work if the pretty printer depends on non-local data, as described in bug 14854. However, I don't think this bug is related to that problem.

The problem here is that -var-update apparently doesn't handle type changes of childs of array-printed types, but only value changes. Note that this doesn't apply to string types, as they can't change their types when pretty-printed. As an example, printing the above "printMePretty" structure as string type results in:

If printAsInt is true: Type is "printMePretty", value is "255"
If printAsInt is false: Type is "printMePretty", value is "3.1415"

Everything OK here, the type will always just be "printMePretty" and won't change. However, printing the same structure in array form results in:

If printAsInt is true: Parent type is "printMePretty", child type is "int", child value is "255"
If printAsInt is false: Parent type is "printMePretty", child type is "float", child value is "3.1415"


-var-update recognizes a value change of the child, but fails to recognize the type change.
Comment 5 Mathias Kunter 2012-12-11 13:33:35 UTC
I've changed the bug title in order to improve the description of the problem.