================ @@ -174,6 +174,233 @@ CPPLanguageRuntime::FindLibCppStdFunctionCallableInfo( if (!valobj_sp) return optional_info; + // std::function has many variants, try to disambiguate + ValueObjectSP func_as_base_ptr; + { + ValueObjectSP outer_f = valobj_sp->GetChildMemberWithName("__f_"); + + if (!outer_f) + return optional_info; // Unrecognized implementation + + if (outer_f->IsPointerType()) { + // git: 3e519524c118651123eecf60c2bbc5d65ad9bac3 + // + // class function<_Rp()> { + // aligned_storage<3*sizeof(void*)>::type __buf_; + // __base<_Rp>* __f_; + // } + + func_as_base_ptr = std::move(outer_f); + } else if (auto inner_f = outer_f->GetChildMemberWithName("__f_")) { + // git: 050b064f15ee56ee0b42c9b957a3dd0f32532394 + // + // class function<_Rp(_ArgTypes...)> { + // __value_func<_Rp(_ArgTypes...)> __f_; + // } + // + // class __value_func<_Rp(_ArgTypes...)> { + // aligned_storage<3 * sizeof(void*)>::type __buf_; + // __base<_Rp(_ArgTypes...)>* __f_; + // } + + func_as_base_ptr = std::move(inner_f); + } else + return optional_info; // Unrecognized implementation + } + + // __base<...> is a pure virtual class with an interface to create/copy/destroy/invoke + // the underlying value. This interface is implemented by partial specializations of the + // __func<_Fp, _Alloc, ...> template where _Fp is the wrapped functor object + Status status; + ValueObjectSP func_as_base = func_as_base_ptr->Dereference(status); + if (status.Fail()) + return optional_info; + + // First we'll try to extract the __func<...> template instantiation's type by looking up + // the declarations of the member function pointers in it's vtable + CompilerType func_type; + Address func_method_addr; + { + ValueObjectSP vtable = func_as_base->GetVTable(); + + llvm::Expected<uint32_t> num_entries = vtable->GetNumChildren(); + if (num_entries.takeError()) + return optional_info; + + // __base is pure virtual, __func is final. All member function pointers are equally + // good candidates to find the enclosing class. + // + // In practice the first two vtable entries point to artificial destructors which the + // type system refuses to elaborate as their artificial specifications are not added + // to the enclosing class' declaration context. This causes various warnings, and dont + // get us any closer to the concrete type thus we skip them. + for (uint32_t idx = 2; idx < *num_entries; idx++) { + ValueObjectSP entry = vtable->GetChildAtIndex(idx); + + // Points to a potentially interesting member function + addr_t mfunc_load_addr = entry->GetValueAsUnsigned(0); + if (!mfunc_load_addr) + continue; + + if (!valobj_sp->GetTargetSP()->ResolveLoadAddress(mfunc_load_addr, func_method_addr)) + continue; + + Function* func = func_method_addr.CalculateSymbolContextFunction(); + if (!func) + continue; + + CompilerDeclContext mfunc_decl_ctx = func->GetDeclContext(); + if (!mfunc_decl_ctx.IsClassMethod()) + continue; + + // Member functions are contained in their enclosing class' decl context + CompilerDeclContext mfunc_parent = mfunc_decl_ctx.GetDecl().GetDeclContext(); + if (!mfunc_parent.IsValid()) + continue; + + func_type = mfunc_parent.GetDecl().GetType(); + break; + } + } + + CompilerType callable_type = func_type.GetTypeTemplateArgument(0); + if (!callable_type) + return optional_info; + + // Now that the __func is a known type we can dig for the wrapped callable + ValueObjectSP callable; + { + // class __func<_Fp, _Alloc, _Rp(_ArgTypes...)> : __base<_Rp(_ArgTypes...)> { + // __alloc_func<_Fp, _Alloc, _Rp(_ArgTypes...)> __f_; + // } + // + // class __alloc_func<_Fp, _Ap, _Rp(_ArgTypes...)> { + // __compressed_pair<_Fp, _Ap> __f_; + // } + // + // class __compressed_pair : __compressed_pair_elem<_T1, 0>, + // __compressed_pair_elem<_T2, 1> { + // } + // + // struct __compressed_pair_elem { + // _Tp __value_; + // } ---------------- mentlerd wrote:
I am developing this using the SDK shipped with Xcode 16 - that's where I mostly intend to use the improvements too. Perhaps it isn't worth putting library code excerpts into comments if they are doomed to get out of sync eventually? https://github.com/llvm/llvm-project/pull/111892 _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits