Bug 14386 - std::bitset not iterable
Summary: std::bitset not iterable
Status: RESOLVED FIXED
Alias: None
Product: gdb
Classification: Unclassified
Component: python (show other bugs)
Version: 7.4
: P2 normal
Target Milestone: 7.5
Assignee: Tom Tromey
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2012-07-23 08:01 UTC by andreasheimberger
Modified: 2012-08-16 17:10 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:
Project(s) to access:
ssh public key:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description andreasheimberger 2012-07-23 08:01:51 UTC
What is the expected result for an std::bitset using -enable-pretty-printing in gdb/mi. Following happens to me:

(gdb) 
-var-create - * bits
^error,msg="Returned value is not iterable"

(gdb) 
whatis bits
&"whatis bits\n"
~"type = std::bitset<8ul>\n"

Normal print or -data-evaluate-expression works as expected
print bits
&"print bits\n"
~"$2 = std::bitset = {[0] = 1"
~", [2] = 1"
~", [4] = 1"
~", [6] = 1"


What I expected was a result like the print of a std::map with the given index to the bit that is set.
Comment 1 Tom Tromey 2012-07-31 16:00:23 UTC
I can't reproduce this.
I used this test program:

#include <bitset>

std::bitset<8> bits;

int main()
{
  bits[1] = 1;
}

I get:

(gdb) 
-var-create - * bits
^done,name="var1",numchild="1",value="{...}",type="std::bitset<8ul>",has_more="0"


What version of g++ are you using?
The libstdc++ printers actually live there.
Comment 2 andreasheimberger 2012-07-31 21:27:42 UTC
g++ (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3
GNU gdb (Ubuntu/Linaro 7.4-2012.04-0ubuntu2) 7.4-2012.04
STL Support Implementation -> http://sourceware.org/gdb/wiki/STLSupport

-------------------------------------------------------------------------------- That should be your printer implementation
--------------------------------------------------------------------------------
class StdBitsetPrinter:
    "Print a std::bitset"

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

    def to_string (self):
        # If template_argument handled values, we could print the
        # size.  Or we could use a regexp on the type.
        return '%s' % (self.typename)

    def children (self):
        words = self.val['_M_w']
        wtype = words.type

        # The _M_w member can be either an unsigned long, or an
        # array.  This depends on the template specialization used.
        # If it is a single long, convert to a single element list.
        if wtype.code == gdb.TYPE_CODE_ARRAY:
            tsize = wtype.target ().sizeof
        else:
            words = [words]
            tsize = wtype.sizeof 

        nwords = wtype.sizeof / tsize
        result = []
        byte = 0
        while byte < nwords:
            w = words[byte]
            bit = 0
            while w != 0:
                if (w & 1) != 0:
                    # Another spot where we could use 'set'?
                    result.append(('[%d]' % (byte * tsize * 8 + bit), 1))
                bit = bit + 1
                w = w >> 1
            byte = byte + 1
        return result

--------------------------------------------------------------------------------
 That's my source file
--------------------------------------------------------------------------------
#include <bitset>

int main()
{
	const int bitsetsize = 8;
	std::bitset<bitsetsize> bits;
	for(int i = 0; i < bitsetsize; i++) {
		if(i%2 == 0 || i == 0) {bits[i].flip(); }
	}

	return 0;
}

--------------------------------------------------------------------------------
 My Debug Commands
--------------------------------------------------------------------------------
-enable-pretty-printing
-break-insert 10
-exec-run
-var-create - * bits


Thanks for your reply
Comment 3 Tom Tromey 2012-08-01 16:01:59 UTC
(In reply to comment #2)

> -enable-pretty-printing

Oops, somehow I forgot this step.
Thanks for the very clear directions.
I can reproduce it now.
Comment 4 Tom Tromey 2012-08-01 16:20:54 UTC
The bug is that varobj.c calls PyIter_Check.
It should just try to get the iterator and possibly fail.
Arguably this is a bug in Python, in that PyIter_Check 
returns 0 if its argument is a Python list.
Comment 5 andreasheimberger 2012-08-01 19:17:32 UTC
Sorry, I'm missing the routine in coding C. Just learned many languages, but none of them perfect. There is still so much I have to learn. I tried to watch varobj.c and found your line for the PyIter Check, but couldn't find the impl of the error function, just think that i will cause an exception.

The thing is, that the message for -var-list-children is correct, because the returned value is not iterable. As much as i know bitset doesn't have an iterator.

The question that I have is more or less, why there is an implemented methode for children. I thought this methode should be used to resolve the output for -var-list-children and the to_string should resolve the object for the print and -data-evaluate-expression of gdb.

But now I see that children is used to print the items, and appends them to the to _string methode. Is there a way to leave the output for the var-list-children methode as it was but using the new output for print and -data-eval...

Would be nice to have some workaround, but bitset is not iterable is the worst output i can get, even the old is better.

Really appreciate your work. Made debugging much easier.
Comment 6 Tom Tromey 2012-08-06 18:41:30 UTC
(In reply to comment #5)

> The thing is, that the message for -var-list-children is correct, because the
> returned value is not iterable. As much as i know bitset doesn't have an
> iterator.

This message does not refer to the bitset in your program, but rather to
a Python object created by the pretty-printer for the bitset.

> The question that I have is more or less, why there is an implemented methode
> for children.

This approach lets MI clients decide how many children to show (consider,
e.g., a vector of 1000 elements), and it lets the CLI apply various
"set print" settings, like "set print elements", to pretty-printed values.

> Is there a way to leave the output for the
> var-list-children methode as it was but using the new output for print and
> -data-eval...

MI clients can disable pretty-printing per-varobj.  See the manual for details.

> Would be nice to have some workaround, but bitset is not iterable is the worst
> output i can get, even the old is better.

If you encounter a pretty-printer bug you can bypass the Python code with
"print/r"
Comment 7 Sourceware Commits 2012-08-06 18:44:49 UTC
CVSROOT:	/cvs/src
Module name:	src
Changes by:	tromey@sourceware.org	2012-08-06 18:44:45

Modified files:
	gdb            : ChangeLog varobj.c 
	gdb/testsuite  : ChangeLog 
	gdb/testsuite/gdb.python: py-mi.exp py-prettyprint.c 
	                          py-prettyprint.py 

Log message:
	PR python/14386:
	* varobj.c (update_dynamic_varobj_children): Don't call
	PyIter_Check.
	gdb/testsuite
	* gdb.python/py-mi.exp: Add test for printer whose children
	are a list.
	* gdb.python/py-prettyprint.c (struct children_as_list): New.
	(main): New variable children_as_list.
	* gdb.python/py-prettyprint.py (class pp_children_as_list):
	New.
	(register_pretty_printers): Register new printer.

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/ChangeLog.diff?cvsroot=src&r1=1.14561&r2=1.14562
http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/varobj.c.diff?cvsroot=src&r1=1.199&r2=1.200
http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/testsuite/ChangeLog.diff?cvsroot=src&r1=1.3324&r2=1.3325
http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/testsuite/gdb.python/py-mi.exp.diff?cvsroot=src&r1=1.16&r2=1.17
http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/testsuite/gdb.python/py-prettyprint.c.diff?cvsroot=src&r1=1.15&r2=1.16
http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/testsuite/gdb.python/py-prettyprint.py.diff?cvsroot=src&r1=1.14&r2=1.15
Comment 8 Tom Tromey 2012-08-06 18:45:18 UTC
Fixed.
Comment 9 Sourceware Commits 2012-08-16 17:08:54 UTC
CVSROOT:	/cvs/src
Module name:	src
Branch: 	gdb_7_5-branch
Changes by:	tromey@sourceware.org	2012-08-16 17:08:44

Modified files:
	gdb            : ChangeLog varobj.c 
	gdb/testsuite  : ChangeLog 
	gdb/testsuite/gdb.python: py-mi.exp py-prettyprint.c 
	                          py-prettyprint.py 

Log message:
	PR python/14386:
	* varobj.c (update_dynamic_varobj_children): Don't call
	PyIter_Check.
	gdb/testsuite
	* gdb.python/py-mi.exp: Add test for printer whose children
	are a list.
	* gdb.python/py-prettyprint.c (struct children_as_list): New.
	(main): New variable children_as_list.
	* gdb.python/py-prettyprint.py (class pp_children_as_list):
	New.
	(register_pretty_printers): Register new printer.

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/ChangeLog.diff?cvsroot=src&only_with_tag=gdb_7_5-branch&r1=1.14469.2.21&r2=1.14469.2.22
http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/varobj.c.diff?cvsroot=src&only_with_tag=gdb_7_5-branch&r1=1.196&r2=1.196.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/testsuite/ChangeLog.diff?cvsroot=src&only_with_tag=gdb_7_5-branch&r1=1.3295.2.19&r2=1.3295.2.20
http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/testsuite/gdb.python/py-mi.exp.diff?cvsroot=src&only_with_tag=gdb_7_5-branch&r1=1.16&r2=1.16.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/testsuite/gdb.python/py-prettyprint.c.diff?cvsroot=src&only_with_tag=gdb_7_5-branch&r1=1.15&r2=1.15.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/testsuite/gdb.python/py-prettyprint.py.diff?cvsroot=src&only_with_tag=gdb_7_5-branch&r1=1.14&r2=1.14.2.1