-
Notifications
You must be signed in to change notification settings - Fork 15.2k
Open
Labels
Description
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:
llvm-project/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp
Lines 293 to 311 in 8ebd401
| // 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;
}