Skip to content

[LLDB] Unreliable CPPLanguageRuntime::FindLibCppStdFunctionCallableInfo  #111291

@mentlerd

Description

@mentlerd

CPPLanguageRuntime::FindLibCppStdFunctionCallableInfo fails to extract the callable information from an std::function which is constructed from a lambda inside a function which has multiple parameters due to this part of it's implementation:

// Given case 1 or 3 we have a vtable name, we are want to extract the first
// template parameter
//
// ... __func<main::$_0, std::__1::allocator<main::$_0> ...
// ^^^^^^^^^
//
// We could see names such as:
// main::$_0
// Bar::add_num2(int)::'lambda'(int)
// Bar
//
// We do this by find the first < and , and extracting in between.
//
// This covers the case of the lambda known at compile time.
size_t first_open_angle_bracket = vtable_name.find('<') + 1;
size_t first_comma = vtable_name.find(',');
llvm::StringRef first_template_parameter =
vtable_name.slice(first_open_angle_bracket, first_comma);

As a consequence, std::function summary cannot print the target function's description, and stepping into operator() does not work.

I have augmented LLDB's logging locally to confirm that this is indeed where things go wrong:

#include <functional>

std::function<void()> GetFunc() {
    return []{ printf("func\n"); };
}
std::function<void()> GetFunc1(int a) {
    return [=]{ printf("func1(%d)\n", a); };
}
std::function<void()> GetFunc2(int a, int b) {
    return [=]{ printf("func2(%d,%d)\n", a, b); };
}

int main() {
    auto f1 = GetFunc();
    auto f2 = GetFunc1(10);
    auto f3 = GetFunc2(10, 10);
    
    printf("Breakpoint here\n");
    /*
        vtable_name='vtable for std::__1::__function::__func<GetFunc()::$_0, std::__1::allocator<GetFunc()::$_0>, void ()>'
        first_template_parameter='GetFunc()::$_0'

        vtable_name='vtable for std::__1::__function::__func<GetFunc1(int)::$_0, std::__1::allocator<GetFunc1(int)::$_0>, void ()>'
        first_template_parameter='GetFunc1(int)::$_0'

        vtable_name='vtable for std::__1::__function::__func<GetFunc2(int, int)::$_0, std::__1::allocator<GetFunc2(int, int)::$_0>, void ()>'
        first_template_parameter='GetFunc2(int'
    */
    return 0;
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions