#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/UniqueCStringMap.h"
+#include "lldb/Core/ValueObjectVariable.h"
#include "lldb/DataFormatters/CXXFunctionPointer.h"
#include "lldb/DataFormatters/DataVisualization.h"
#include "lldb/DataFormatters/FormattersHelpers.h"
#include "lldb/DataFormatters/VectorType.h"
#include "lldb/Symbol/SymbolFile.h"
+#include "lldb/Symbol/VariableList.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
return idx == basename.size();
}
+/// Writes out the function name in 'full_name' to 'out_stream'
+/// but replaces each argument type with the variable name
+/// and the corresponding pretty-printed value
+static bool PrettyPrintFunctionNameWithArgs(Stream &out_stream,
+ char const *full_name,
+ ExecutionContextScope *exe_scope,
+ VariableList const &args) {
+ CPlusPlusLanguage::MethodName cpp_method{ConstString(full_name)};
+
+ if (!cpp_method.IsValid())
+ return false;
+
+ llvm::StringRef return_type = cpp_method.GetReturnType();
+ if (!return_type.empty()) {
+ out_stream.PutCString(return_type);
+ out_stream.PutChar(' ');
+ }
+
+ out_stream.PutCString(cpp_method.GetScopeQualifiedName());
+ out_stream.PutChar('(');
+
+ FormatEntity::PrettyPrintFunctionArguments(out_stream, args, exe_scope);
+
+ out_stream.PutChar(')');
+
+ llvm::StringRef qualifiers = cpp_method.GetQualifiers();
+ if (!qualifiers.empty()) {
+ out_stream.PutChar(' ');
+ out_stream.PutCString(qualifiers);
+ }
+
+ return true;
+}
+
bool CPlusPlusLanguage::MethodName::TrySimplifiedParse() {
// This method tries to parse simple method definitions which are presumably
// most comman in user programs. Definitions that can be parsed by this
// that we could check for.
return file_path.contains("/usr/include/c++/");
}
+
+bool CPlusPlusLanguage::GetFunctionDisplayName(
+ const SymbolContext *sc, const ExecutionContext *exe_ctx,
+ FunctionNameRepresentation representation, Stream &s) {
+ switch (representation) {
+ case FunctionNameRepresentation::eNameWithArgs: {
+ // Print the function name with arguments in it
+ if (sc->function) {
+ ExecutionContextScope *exe_scope =
+ exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr;
+ const char *cstr = sc->function->GetName().AsCString(nullptr);
+ if (cstr) {
+ const InlineFunctionInfo *inline_info = nullptr;
+ VariableListSP variable_list_sp;
+ bool get_function_vars = true;
+ if (sc->block) {
+ Block *inline_block = sc->block->GetContainingInlinedBlock();
+
+ if (inline_block) {
+ get_function_vars = false;
+ inline_info = sc->block->GetInlinedFunctionInfo();
+ if (inline_info)
+ variable_list_sp = inline_block->GetBlockVariableList(true);
+ }
+ }
+
+ if (get_function_vars) {
+ variable_list_sp =
+ sc->function->GetBlock(true).GetBlockVariableList(true);
+ }
+
+ if (inline_info) {
+ s.PutCString(cstr);
+ s.PutCString(" [inlined] ");
+ cstr = inline_info->GetName().GetCString();
+ }
+
+ VariableList args;
+ if (variable_list_sp)
+ variable_list_sp->AppendVariablesWithScope(eValueTypeVariableArgument,
+ args);
+ if (args.GetSize() > 0) {
+ if (!PrettyPrintFunctionNameWithArgs(s, cstr, exe_scope, args))
+ return false;
+ } else {
+ s.PutCString(cstr);
+ }
+ return true;
+ }
+ } else if (sc->symbol) {
+ const char *cstr = sc->symbol->GetName().AsCString(nullptr);
+ if (cstr) {
+ s.PutCString(cstr);
+ return true;
+ }
+ }
+ } break;
+ default:
+ return false;
+ }
+
+ return false;
+}
--- /dev/null
+#include <functional>
+
+namespace detail {
+template <typename T> struct Quux {};
+} // namespace detail
+
+using FuncPtr = detail::Quux<double> (*(*)(int))(float);
+
+struct Foo {
+ template <typename T> void foo(T const &t) const noexcept(true) {}
+
+ template <size_t T> void operator<<(size_t) {}
+
+ template <typename T> FuncPtr returns_func_ptr(detail::Quux<int> &&) const noexcept(false) { return nullptr; }
+};
+
+namespace ns {
+template <typename T> int foo(T const &t) noexcept(false) { return 0; }
+
+template <typename T> FuncPtr returns_func_ptr(detail::Quux<int> &&) { return nullptr; }
+} // namespace ns
+
+int bar() { return 1; }
+
+namespace {
+int anon_bar() { return 1; }
+auto anon_lambda = [](std::function<int(int (*)(int))>) mutable {};
+} // namespace
+
+int main() {
+ ns::foo(bar);
+ ns::foo(std::function{bar});
+ ns::foo(anon_lambda);
+ ns::foo(std::function{anon_bar});
+ ns::foo(&Foo::foo<std::function<int(int)>>);
+ ns::returns_func_ptr<int>(detail::Quux<int>{});
+ Foo f;
+ f.foo(std::function{bar});
+ f.foo(std::function{anon_bar});
+ f.operator<< <(2 > 1)>(0);
+ f.returns_func_ptr<int>(detail::Quux<int>{});
+ return 0;
+}
--- /dev/null
+# RUN: %clangxx_host -g -O0 %S/Inputs/names.cpp -std=c++17 -o %t.out
+# RUN: %lldb -b -s %s %t.out | FileCheck %s
+settings set -f frame-format "frame ${function.name-with-args}\n"
+break set -n foo
+break set -n operator<<
+break set -n returns_func_ptr
+run
+# CHECK: frame int ns::foo<int ()>(t={{.*}})
+c
+# CHECK: frame int ns::foo<std::__1::function<int ()>>(t= Function = bar() )
+c
+# CHECK: frame int ns::foo<(anonymous namespace)::$_0>(t={{.*}})
+c
+# CHECK: frame int ns::foo<std::__1::function<int ()>>(t= Function = (anonymous namespace)::anon_bar() )
+c
+# CHECK: frame int ns::foo<void (Foo::*)(std::__1::function<int (int)> const&) const noexcept>(t={{.*}})
+c
+# CHECK: frame ns::returns_func_ptr<int>((null)={{.*}})
+c
+# CHECK: frame void Foo::foo<std::__1::function<int ()>>(this={{.*}}, t= Function = bar() ) const
+c
+# CHECK: frame void Foo::foo<std::__1::function<int ()>>(this={{.*}}, t= Function = (anonymous namespace)::anon_bar() ) const
+c
+# CHECK: frame void Foo::operator<<<1ul>(this={{.*}}, (null)=0)
+c
+# CHECK: frame Foo::returns_func_ptr<int>(this={{.*}}, (null)={{.*}})
+q