https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87308

            Bug ID: 87308
           Summary: pretty printer for std::any fails with: Python
                    Exception <type 'exceptions.ValueError'> Unknown
                    manager function in std::any
           Product: gcc
           Version: 8.1.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: debug
          Assignee: unassigned at gcc dot gnu.org
          Reporter: jeff at jgarrett dot org
  Target Milestone: ---

Using g++-8.1 and gdb-8.2 both built from source on a CentOS 7.3 host, pretty
printing a std::any fails with an exception for unknown manager function.

    $ gdb ./erased-lambda
    GNU gdb (GDB) 8.2
    (gdb) run
    Starting program: .../erased-lambda

    Program received signal SIGILL, Illegal instruction.
    main () at erased-lambda.cpp:6
    6       __builtin_trap();
    (gdb) print a1
    $1 = Python Exception <type 'exceptions.ValueError'> Unknown manager
function in std::any:
    Python Exception <type 'exceptions.ValueError'> Unknown manager function in
std::any:
    {
      _M_manager = 0x4007b2 <std::any::_Manager_internal<main()::<lambda()>
>::_S_manage(std::any::_Op, const std::any *, std::any::_Arg *)>, _M_storage =
{_M_ptr = 0x1, _M_buffer = {__data = "\001\000\000\000\000\000\000",
          __align = {<No data fields>}}}}

It would appear that the printer attempts to match the manager function name
with the following regex:

    rx = r"""({0}::_Manager_\w+<.*>)::_S_manage\({0}::_Op, {0} const\*,
{0}::_Arg\*\)""".format(typename)

Note that the second argument as printed by my gdb is 'const std::any *' versus
the regex 'std::any const*' (east vs west const and space before *) and the
third argument as printed by gdb is 'std::any::_Arg *' versus the regex
'std::any::_Arg*' (space before *). Applying the following patch "fixed" the
regex for my particular set of versions:

    --- a/printers.py
    +++ b/printers.py
    @@ -1040,7 +1040,7 @@ class StdExpAnyPrinter(SingleObjContainerPrinter):
                 func =
gdb.block_for_pc(int(mgr.cast(gdb.lookup_type('intptr_t'))))
                 if not func:
                     raise ValueError("Invalid function pointer in %s" %
self.typename)
    -            rx = r"""({0}::_Manager_\w+<.*>)::_S_manage\({0}::_Op, {0}
const\*, {0}::_Arg\*\)""".format(typename)
    +            rx = r"""({0}::_Manager_\w+<.*>)::_S_manage\({0}::_Op, const
{0} \*, {0}::_Arg \*\)""".format(typename)
                 m = re.match(rx, func.function.name)
                 if not m:
                     raise ValueError("Unknown manager function in %s" %
self.typename)

However, even with that applied, pretty printing a lambda prints the wrong type
due to a bad type lookup:

    (gdb) print a1
    $1 = std::any containing <lambda()> = {[contained value] = {__j = 1, __k =
0}}
    (gdb) print a2
    $2 = std::any containing <lambda()> = {[contained value] = {__j = 2, __k =
3}}

Note that both a1 and a2 are interpreted as holding type main::{lambda()#2},
but a1 actually holds main::{lambda()#1}.

GCC version:

    $ g++-8.1 -v
    Using built-in specs.
    COLLECT_GCC=/usr/local/gcc-8.1.0/bin/g++-8.1
   
COLLECT_LTO_WRAPPER=/usr/local/gcc-8.1.0/libexec/gcc/x86_64-pc-linux-gnu/8.1.0/lto-wrapper
    Target: x86_64-pc-linux-gnu
    Configured with: ../gcc-8.1.0/configure --program-suffix=-8.1
--prefix=/usr/local/gcc-8.1.0 --disable-multilib --enable-gold --enable-ld
--enable-lto
    Thread model: posix
    gcc version 8.1.0 (GCC)

Please let me know if I can provide anything else to help.

== erased-lambda.cpp ==
// g++-8.1 -g -std=c++17 erased-lambda.cpp -o erased-lambda
#include <any>
int main() {
    std::any a1 = [i=1] {};
    std::any a2 = [j=2,k=3] {};
    __builtin_trap();
}

Reply via email to