[Bug python/22686] New: gdb.lookup_type fails for array types

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

[Bug python/22686] New: gdb.lookup_type fails for array types

macro@linux-mips.org
https://sourceware.org/bugzilla/show_bug.cgi?id=22686

            Bug ID: 22686
           Summary: gdb.lookup_type fails for array types
           Product: gdb
           Version: 8.0.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P2
         Component: python
          Assignee: unassigned at sourceware dot org
          Reporter: jwakely.gcc at gmail dot com
  Target Milestone: ---

(gdb) py gdb.lookup_type("int []")
Traceback (most recent call last):
  File "<string>", line 1, in <module>
gdb.error: No type named int [].
Error while executing Python code.
(gdb) py gdb.lookup_type("int [2]")
Traceback (most recent call last):
  File "<string>", line 1, in <module>
gdb.error: No type named int [2].
Error while executing Python code.

Such types can occur as C++ template parameters, e.g. std::unique_ptr<int[]> or
std::is_array<int[2]>

--
You are receiving this mail because:
You are on the CC list for the bug.
Reply | Threaded
Open this post in threaded view
|

[Bug python/22686] gdb.lookup_type fails for array types

macro@linux-mips.org
https://sourceware.org/bugzilla/show_bug.cgi?id=22686

Simon Marchi <simon.marchi at ericsson dot com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |simon.marchi at ericsson dot com

--- Comment #1 from Simon Marchi <simon.marchi at ericsson dot com> ---
Hi Jonathan,

I think this is expected with the current code, as lookup_type looks up type by
name only.  In your case, you could do

  >>> print(gdb.lookup_type('int').array(0, 1))                                
  int [2]
  >>> print(gdb.lookup_type('int').array(1))
  int [2]

In both cases, the 1 is the inclusive upper bound of the array.

It would be handy to be able to do lookup_type('int[2]') though.  And it might
allow things that can't be done today.  For example, I don't know how you would
make a function pointer type from scratch.  It would be nice if you could just
do lookup_type('int (*)(const char *)').

Well, as a workaround you could always do

  >>> print(gdb.parse_and_eval('(int (*)(const char *)) 0').type)
  int (*)(const char *)

and for the int[2] example:

  >>> print(gdb.parse_and_eval('{int[2]} 0').type)
  int [2]

--
You are receiving this mail because:
You are on the CC list for the bug.
Reply | Threaded
Open this post in threaded view
|

[Bug python/22686] gdb.lookup_type fails for array types

macro@linux-mips.org
In reply to this post by macro@linux-mips.org
https://sourceware.org/bugzilla/show_bug.cgi?id=22686

--- Comment #2 from Jonathan Wakely <jwakely.gcc at gmail dot com> ---
I see. The place I hit this limitation I don't know the type to lookup, I just
have a string "int []" and am trying to find out what its type is.

The specific situation is something like:

std::vector<std::unique_ptr<int[]>> v;

GDB (quite correctly) says the real type is:

std::vector<std::unique_ptr<int [], std::default_delete<int []> >,
std::allocator<std::unique_ptr<int [], std::default_delete<int []> > > >

This is ugly, and not what the user wrote, so the libstdc++ pretty printers
apply type  printers to remove the default template arguments, so it's
displayed as simply std::vector<std::unique_ptr<int[]>>.

See
https://gcc.gnu.org/viewcvs/gcc/trunk/libstdc%2B%2B-v3/python/libstdcxx/v6/printers.py?revision=256400&view=markup#l1295

This is done with regular expressions, and recursively applying type printers
to the remaining template arguments. So first I turn vector<T, allocator<T>>
into vector<T>, then I process T, which turns unique_ptr<int[],
default_delete<int[]>> into unique_ptr<int[]>. Then I try to do the same to
"int[]" as well, which is when I try to look that up. Because I'm using a regex
I only have strings, not gdb.Type objects.

I suppose I could use a regex to match the type in the first place, but do the
actual substitutions using gdb.Type not regex substitutions.

--
You are receiving this mail because:
You are on the CC list for the bug.
Reply | Threaded
Open this post in threaded view
|

[Bug python/22686] gdb.lookup_type fails for array types

macro@linux-mips.org
In reply to this post by macro@linux-mips.org
https://sourceware.org/bugzilla/show_bug.cgi?id=22686

--- Comment #3 from Jonathan Wakely <jwakely.gcc at gmail dot com> ---
(In reply to Jonathan Wakely from comment #2)
> I suppose I could use a regex to match the type in the first place, but do
> the actual substitutions using gdb.Type not regex substitutions.

I've rewritten the type printers to not need to lookup types from strings, so
no longer need gdb.lookup_type("int[]"), however this revealed some related
problems.

I can't see any way to use the Python API to distinguish int[] and int[1]. Both
types are arrays, and gdb.Type.range() returns (0,0) for both.

Type recognizers don't handle T*, T&, T&& or T[N], so to print std::string[2]
as std::string (rather than std::basic_string<char, std::char_traits<char>,
std::allocator<char> >[2]) I need to do extra work. I can use gdb.Type.target()
to strip off the array bounds, apply the recognizers again, then append "[2]"
to the result, but for the case of "[]" and "[1]" I have no way to distinguish
them except parsing the string by hand.

Could gdb.types.apply_type_recognizers handle pointers and arrays for me?

Could I have a way to distinguish T[] and T[1] in the Python API?

Also, there seems to be no way to create the type T[] given the gdb.Type for T.
Unless I'm mistaken, type_obj.array(0) will create the type for T[1]

--
You are receiving this mail because:
You are on the CC list for the bug.
Reply | Threaded
Open this post in threaded view
|

[Bug python/22686] gdb.lookup_type fails for array types

macro@linux-mips.org
In reply to this post by macro@linux-mips.org
https://sourceware.org/bugzilla/show_bug.cgi?id=22686

--- Comment #4 from Jonathan Wakely <jwakely.gcc at gmail dot com> ---
Actually the recognizers do get used for arrays and compound types, but with
inconsistent results. The recognizer only gets used for the name of the type,
but the full definition of the type is still printed out.

##########

cat > x.cc << EOT
struct X { int i; };

int main()
{
  X x;
  X x2[2];
  return 0;
}
EOT

cat > xprinter.py << EOT
import gdb

class XPrinter(gdb.types.TypePrinter):
  def __init__(self):
    super(XPrinter, self).__init__('X')

  def instantiate(self):
    return self._recognizer()

  class _recognizer:
    def recognize(self, typ):
      if typ.name == 'X':
        return '__X__'
      return None

gdb.types.register_type_printer(gdb.current_objfile(), XPrinter())
EOT

g++ -g x.cc

gdb -q -ex 'py sys.path.insert(0, ".")' -ex "py import xprinter" \
  -ex start -ex "ptype x" -ex "ptype x2" -ex cont -ex quit a.out

##########

The GDB output is:

Reading symbols from a.out...done.
Temporary breakpoint 1 at 0x4004ab: file x.cc, line 7.
Starting program: /tmp/a.out

Temporary breakpoint 1, main () at x.cc:7
7         return 0;
type = __X__
type = struct __X__ {
    int i;
} [2]
Continuing.
[Inferior 1 (process 29374) exited normally]


The first ptype has the expected result, but the second prints:

type = struct __X__ {
    int i;
} [2]

I expected it to be something like "__X__ [2]" instead.

--
You are receiving this mail because:
You are on the CC list for the bug.