(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]>
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]
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.
(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]
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.
duplicate of bug 11797?
(In reply to Christian Biesinger from comment #5) > duplicate of bug 11797? Yes, although this bug has a lot more info, and comment 4 is a separate issue.
Bug 11797 suggests a new 'parse_type' function that applies the language's type-parsing rules. This is more or less what 'ptype' does, with the caveat being that ptype really accepts any expression and yields its type, which can be resolved in favor of parsing as if the string were an expression if there is some ambiguity. What would be really better is a separate "type" entry point to the parsers.