[lldb] Redesign Target::GetUtilityFunctionForLanguage API

This patch redesigns the Target::GetUtilityFunctionForLanguage API:

 - Use a unique_ptr instead of a raw pointer for the return type.
 - Wrap the result in an llvm::Expected instead of using a Status object as an I/O parameter.
 - Combine the action of "getting" and "installing" the UtilityFunction as they always get called together.
 - Pass std::strings instead of const char* and std::move them where appropriate.

There's more room for improvement but I think this tackles the most
prevalent issues with the current API.

Differential revision: https://reviews.llvm.org/D90011
This commit is contained in:
Jonas Devlieghere 2020-10-23 09:26:11 -07:00
parent 9df832d1c3
commit de346cf2ac
18 changed files with 186 additions and 275 deletions

View File

@ -465,9 +465,9 @@ public:
return nullptr;
}
virtual UtilityFunction *GetUtilityFunction(const char *text,
const char *name) {
return nullptr;
virtual std::unique_ptr<UtilityFunction>
CreateUtilityFunction(std::string text, std::string name) {
return {};
}
virtual PersistentExpressionState *GetPersistentExpressionState() {

View File

@ -221,7 +221,6 @@ public:
void UpdateLaunchInfoFromProperties();
private:
// Callbacks for m_launch_info.
void Arg0ValueChangedCallback();
@ -1074,14 +1073,10 @@ public:
const ValueList &arg_value_list,
const char *name, Status &error);
// Creates a UtilityFunction for the given language, the rest of the
// parameters have the same meaning as for the UtilityFunction constructor.
// Returns a new-ed object which the caller owns.
UtilityFunction *GetUtilityFunctionForLanguage(const char *expr,
lldb::LanguageType language,
const char *name,
Status &error);
/// Creates and installs a UtilityFunction for the given language.
llvm::Expected<std::unique_ptr<UtilityFunction>>
CreateUtilityFunction(std::string expression, std::string name,
lldb::LanguageType language, ExecutionContext &exe_ctx);
// Install any files through the platform that need be to installed prior to
// launching or attaching.

View File

@ -48,29 +48,27 @@ ClangDynamicCheckerFunctions::~ClangDynamicCheckerFunctions() = default;
bool ClangDynamicCheckerFunctions::Install(
DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx) {
Status error;
m_valid_pointer_check.reset(
exe_ctx.GetTargetRef().GetUtilityFunctionForLanguage(
g_valid_pointer_check_text, lldb::eLanguageTypeC,
VALID_POINTER_CHECK_NAME, error));
if (error.Fail())
auto utility_fn_or_error = exe_ctx.GetTargetRef().CreateUtilityFunction(
g_valid_pointer_check_text, VALID_POINTER_CHECK_NAME,
lldb::eLanguageTypeC, exe_ctx);
if (!utility_fn_or_error) {
llvm::consumeError(utility_fn_or_error.takeError());
return false;
}
m_valid_pointer_check = std::move(*utility_fn_or_error);
if (!m_valid_pointer_check->Install(diagnostic_manager, exe_ctx))
return false;
Process *process = exe_ctx.GetProcessPtr();
if (process) {
if (Process *process = exe_ctx.GetProcessPtr()) {
ObjCLanguageRuntime *objc_language_runtime =
ObjCLanguageRuntime::Get(*process);
if (objc_language_runtime) {
m_objc_object_check.reset(objc_language_runtime->CreateObjectChecker(
VALID_OBJC_OBJECT_CHECK_NAME));
if (!m_objc_object_check->Install(diagnostic_manager, exe_ctx))
auto utility_fn_or_error = objc_language_runtime->CreateObjectChecker(
VALID_OBJC_OBJECT_CHECK_NAME, exe_ctx);
if (!utility_fn_or_error) {
llvm::consumeError(utility_fn_or_error.takeError());
return false;
}
m_objc_object_check = std::move(*utility_fn_or_error);
}
}

View File

@ -122,58 +122,60 @@ struct BufStruct {
char contents[2048];
};
UtilityFunction *AppleObjCRuntimeV1::CreateObjectChecker(const char *name) {
llvm::Expected<std::unique_ptr<UtilityFunction>>
AppleObjCRuntimeV1::CreateObjectChecker(std::string name,
ExecutionContext &exe_ctx) {
std::unique_ptr<BufStruct> buf(new BufStruct);
int strformatsize = snprintf(&buf->contents[0], sizeof(buf->contents),
"struct __objc_class "
" \n"
"{ "
" \n"
" struct __objc_class *isa; "
" \n"
" struct __objc_class *super_class; "
" \n"
" const char *name; "
" \n"
" // rest of struct elided because unused "
" \n"
"}; "
" \n"
" "
" \n"
"struct __objc_object "
" \n"
"{ "
" \n"
" struct __objc_class *isa; "
" \n"
"}; "
" \n"
" "
" \n"
"extern \"C\" void "
" \n"
"%s(void *$__lldb_arg_obj, void *$__lldb_arg_selector) "
" \n"
"{ "
" \n"
" struct __objc_object *obj = (struct "
"__objc_object*)$__lldb_arg_obj; \n"
" if ($__lldb_arg_obj == (void *)0) "
" \n"
" return; // nil is ok "
" (int)strlen(obj->isa->name); "
" \n"
"} "
" \n",
name);
int strformatsize =
snprintf(&buf->contents[0], sizeof(buf->contents),
"struct __objc_class "
" \n"
"{ "
" \n"
" struct __objc_class *isa; "
" \n"
" struct __objc_class *super_class; "
" \n"
" const char *name; "
" \n"
" // rest of struct elided because unused "
" \n"
"}; "
" \n"
" "
" \n"
"struct __objc_object "
" \n"
"{ "
" \n"
" struct __objc_class *isa; "
" \n"
"}; "
" \n"
" "
" \n"
"extern \"C\" void "
" \n"
"%s(void *$__lldb_arg_obj, void *$__lldb_arg_selector) "
" \n"
"{ "
" \n"
" struct __objc_object *obj = (struct "
"__objc_object*)$__lldb_arg_obj; \n"
" if ($__lldb_arg_obj == (void *)0) "
" \n"
" return; // nil is ok "
" (int)strlen(obj->isa->name); "
" \n"
"} "
" \n",
name.c_str());
assert(strformatsize < (int)sizeof(buf->contents));
(void)strformatsize;
Status error;
return GetTargetRef().GetUtilityFunctionForLanguage(
buf->contents, eLanguageTypeObjC, name, error);
return GetTargetRef().CreateUtilityFunction(buf->contents, std::move(name),
eLanguageTypeC, exe_ctx);
}
AppleObjCRuntimeV1::ClassDescriptorV1::ClassDescriptorV1(

View File

@ -97,7 +97,8 @@ public:
Address &address,
Value::ValueType &value_type) override;
UtilityFunction *CreateObjectChecker(const char *) override;
llvm::Expected<std::unique_ptr<UtilityFunction>>
CreateObjectChecker(std::string, ExecutionContext &exe_ctx) override;
// PluginInterface protocol
ConstString GetPluginName() override;

View File

@ -840,7 +840,9 @@ AppleObjCRuntimeV2::CreateExceptionResolver(const BreakpointSP &bkpt,
return resolver_sp;
}
UtilityFunction *AppleObjCRuntimeV2::CreateObjectChecker(const char *name) {
llvm::Expected<std::unique_ptr<UtilityFunction>>
AppleObjCRuntimeV2::CreateObjectChecker(std::string name,
ExecutionContext &exe_ctx) {
char check_function_code[2048];
int len = 0;
@ -861,7 +863,8 @@ UtilityFunction *AppleObjCRuntimeV2::CreateObjectChecker(const char *name) {
if ($responds == (signed char) 0)
*((volatile int *)0) = 'ocgc';
}
})", name);
})",
name.c_str());
} else {
len = ::snprintf(check_function_code, sizeof(check_function_code), R"(
extern "C" void *gdb_class_getClass(void *);
@ -881,15 +884,15 @@ UtilityFunction *AppleObjCRuntimeV2::CreateObjectChecker(const char *name) {
if ($responds == (signed char) 0)
*((volatile int *)0) = 'ocgc';
}
})", name);
})",
name.c_str());
}
assert(len < (int)sizeof(check_function_code));
UNUSED_IF_ASSERT_DISABLED(len);
Status error;
return GetTargetRef().GetUtilityFunctionForLanguage(
check_function_code, eLanguageTypeObjC, name, error);
return GetTargetRef().CreateUtilityFunction(check_function_code, name,
eLanguageTypeC, exe_ctx);
}
size_t AppleObjCRuntimeV2::GetByteOffsetForIvar(CompilerType &parent_ast_type,
@ -1340,8 +1343,6 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic(
Address function_address;
DiagnosticManager diagnostics;
const uint32_t addr_size = process->GetAddressByteSize();
Status err;
@ -1363,28 +1364,16 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic(
FunctionCaller *get_class_info_function = nullptr;
if (!m_get_class_info_code) {
Status error;
m_get_class_info_code.reset(GetTargetRef().GetUtilityFunctionForLanguage(
g_get_dynamic_class_info_body, eLanguageTypeObjC,
g_get_dynamic_class_info_name, error));
if (error.Fail()) {
LLDB_LOGF(log,
"Failed to get Utility Function for implementation lookup: %s",
error.AsCString());
m_get_class_info_code.reset();
} else {
diagnostics.Clear();
if (!m_get_class_info_code->Install(diagnostics, exe_ctx)) {
if (log) {
LLDB_LOGF(log, "Failed to install implementation lookup");
diagnostics.Dump(log);
}
m_get_class_info_code.reset();
}
}
if (!m_get_class_info_code)
auto utility_fn_or_error = GetTargetRef().CreateUtilityFunction(
g_get_dynamic_class_info_body, g_get_dynamic_class_info_name,
eLanguageTypeC, exe_ctx);
if (!utility_fn_or_error) {
LLDB_LOG_ERROR(
log, utility_fn_or_error.takeError(),
"Failed to get utility function for implementation lookup: {0}");
return DescriptorMapUpdateResult::Fail();
}
m_get_class_info_code = std::move(*utility_fn_or_error);
// Next make the runner function for our implementation utility function.
Value value;
@ -1398,6 +1387,7 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic(
arguments.PushValue(value);
arguments.PushValue(value);
Status error;
get_class_info_function = m_get_class_info_code->MakeFunctionCaller(
clang_uint32_t_type, arguments, thread_sp, error);
@ -1410,17 +1400,13 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic(
} else {
get_class_info_function = m_get_class_info_code->GetFunctionCaller();
if (!get_class_info_function) {
if (log) {
LLDB_LOGF(log, "Failed to get implementation lookup function caller.");
diagnostics.Dump(log);
}
LLDB_LOGF(log, "Failed to get implementation lookup function caller.");
return DescriptorMapUpdateResult::Fail();
}
arguments = get_class_info_function->GetArgumentValues();
}
diagnostics.Clear();
DiagnosticManager diagnostics;
const uint32_t class_info_byte_size = addr_size + 4;
const uint32_t class_infos_byte_size = num_classes * class_info_byte_size;
@ -1600,8 +1586,6 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache() {
Address function_address;
DiagnosticManager diagnostics;
const uint32_t addr_size = process->GetAddressByteSize();
Status err;
@ -1663,29 +1647,17 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache() {
shared_class_expression += g_get_shared_cache_class_info_body;
m_get_shared_cache_class_info_code.reset(
GetTargetRef().GetUtilityFunctionForLanguage(
shared_class_expression.c_str(), eLanguageTypeObjC,
g_get_shared_cache_class_info_name, error));
if (error.Fail()) {
LLDB_LOGF(log,
"Failed to get Utility function for implementation lookup: %s.",
error.AsCString());
m_get_shared_cache_class_info_code.reset();
} else {
diagnostics.Clear();
if (!m_get_shared_cache_class_info_code->Install(diagnostics, exe_ctx)) {
if (log) {
LLDB_LOGF(log, "Failed to install implementation lookup.");
diagnostics.Dump(log);
}
m_get_shared_cache_class_info_code.reset();
}
auto utility_fn_or_error = exe_ctx.GetTargetRef().CreateUtilityFunction(
std::move(shared_class_expression), g_get_shared_cache_class_info_name,
eLanguageTypeC, exe_ctx);
if (!utility_fn_or_error) {
LLDB_LOG_ERROR(
log, utility_fn_or_error.takeError(),
"Failed to get utility function for implementation lookup: {0}");
return DescriptorMapUpdateResult::Fail();
}
if (!m_get_shared_cache_class_info_code)
return DescriptorMapUpdateResult::Fail();
m_get_shared_cache_class_info_code = std::move(*utility_fn_or_error);
// Next make the function caller for our implementation utility function.
Value value;
@ -1714,7 +1686,7 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache() {
arguments = get_shared_cache_class_info_function->GetArgumentValues();
}
diagnostics.Clear();
DiagnosticManager diagnostics;
const uint32_t class_info_byte_size = addr_size + 4;
const uint32_t class_infos_byte_size = num_classes * class_info_byte_size;

View File

@ -53,7 +53,8 @@ public:
Address &address,
Value::ValueType &value_type) override;
UtilityFunction *CreateObjectChecker(const char *) override;
llvm::Expected<std::unique_ptr<UtilityFunction>>
CreateObjectChecker(std::string name, ExecutionContext &exe_ctx) override;
// PluginInterface protocol
ConstString GetPluginName() override;

View File

@ -798,7 +798,6 @@ AppleObjCTrampolineHandler::SetupDispatchFunction(Thread &thread,
ValueList &dispatch_values) {
ThreadSP thread_sp(thread.shared_from_this());
ExecutionContext exe_ctx(thread_sp);
DiagnosticManager diagnostics;
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
lldb::addr_t args_addr = LLDB_INVALID_ADDRESS;
@ -812,27 +811,16 @@ AppleObjCTrampolineHandler::SetupDispatchFunction(Thread &thread,
if (!m_impl_code) {
if (m_lookup_implementation_function_code != nullptr) {
Status error;
m_impl_code.reset(exe_ctx.GetTargetRef().GetUtilityFunctionForLanguage(
m_lookup_implementation_function_code, eLanguageTypeObjC,
g_lookup_implementation_function_name, error));
if (error.Fail()) {
LLDB_LOGF(
log,
"Failed to get Utility Function for implementation lookup: %s.",
error.AsCString());
m_impl_code.reset();
return args_addr;
}
if (!m_impl_code->Install(diagnostics, exe_ctx)) {
if (log) {
LLDB_LOGF(log, "Failed to install implementation lookup.");
diagnostics.Dump(log);
}
m_impl_code.reset();
auto utility_fn_or_error = exe_ctx.GetTargetRef().CreateUtilityFunction(
m_lookup_implementation_function_code,
g_lookup_implementation_function_name, eLanguageTypeC, exe_ctx);
if (!utility_fn_or_error) {
LLDB_LOG_ERROR(
log, utility_fn_or_error.takeError(),
"Failed to get Utility Function for implementation lookup: {0}.");
return args_addr;
}
m_impl_code = std::move(*utility_fn_or_error);
} else {
LLDB_LOGF(log, "No method lookup implementation code.");
return LLDB_INVALID_ADDRESS;
@ -861,14 +849,13 @@ AppleObjCTrampolineHandler::SetupDispatchFunction(Thread &thread,
}
}
diagnostics.Clear();
// Now write down the argument values for this particular call.
// This looks like it might be a race condition if other threads
// were calling into here, but actually it isn't because we allocate
// a new args structure for this call by passing args_addr =
// LLDB_INVALID_ADDRESS...
DiagnosticManager diagnostics;
if (!impl_function_caller->WriteFunctionArguments(
exe_ctx, args_addr, dispatch_values, diagnostics)) {
if (log) {

View File

@ -251,7 +251,8 @@ public:
llvm::Optional<CompilerType> GetRuntimeType(CompilerType base_type) override;
virtual UtilityFunction *CreateObjectChecker(const char *) = 0;
virtual llvm::Expected<std::unique_ptr<UtilityFunction>>
CreateObjectChecker(std::string name, ExecutionContext &exe_ctx) = 0;
virtual ObjCRuntimeVersions GetRuntimeVersion() const {
return ObjCRuntimeVersions::eObjC_VersionUnknown;

View File

@ -631,23 +631,18 @@ PlatformPOSIX::MakeLoadImageUtilityFunction(ExecutionContext &exe_ctx,
expr.append(dlopen_wrapper_code);
Status utility_error;
DiagnosticManager diagnostics;
std::unique_ptr<UtilityFunction> dlopen_utility_func_up(process
->GetTarget().GetUtilityFunctionForLanguage(expr.c_str(),
eLanguageTypeObjC,
dlopen_wrapper_name,
utility_error));
if (utility_error.Fail()) {
error.SetErrorStringWithFormat("dlopen error: could not make utility"
"function: %s", utility_error.AsCString());
return nullptr;
}
if (!dlopen_utility_func_up->Install(diagnostics, exe_ctx)) {
error.SetErrorStringWithFormat("dlopen error: could not install utility"
"function: %s",
diagnostics.GetString().c_str());
auto utility_fn_or_error = process->GetTarget().CreateUtilityFunction(
std::move(expr), dlopen_wrapper_name, eLanguageTypeObjC, exe_ctx);
if (!utility_fn_or_error) {
std::string error_str = llvm::toString(utility_fn_or_error.takeError());
error.SetErrorStringWithFormat("dlopen error: could not create utility"
"function: %s",
error_str.c_str());
return nullptr;
}
std::unique_ptr<UtilityFunction> dlopen_utility_func_up =
std::move(*utility_fn_or_error);
Value value;
ValueList arguments;

View File

@ -2647,7 +2647,7 @@ addr_t ProcessGDBRemote::GetImageInfoAddress() {
llvm::Expected<LoadedModuleInfoList> list = GetLoadedModuleList();
if (!list) {
Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
LLDB_LOG_ERROR(log, list.takeError(), "Failed to read module list: {0}");
LLDB_LOG_ERROR(log, list.takeError(), "Failed to read module list: {0}.");
} else {
addr = list->m_link_map;
}

View File

@ -142,25 +142,14 @@ lldb::addr_t AppleGetItemInfoHandler::SetupGetItemInfoFunction(
if (!m_get_item_info_impl_code) {
if (g_get_item_info_function_code != nullptr) {
Status error;
m_get_item_info_impl_code.reset(
exe_ctx.GetTargetRef().GetUtilityFunctionForLanguage(
g_get_item_info_function_code, eLanguageTypeObjC,
g_get_item_info_function_name, error));
if (error.Fail()) {
LLDB_LOGF(log, "Failed to get utility function: %s.",
error.AsCString());
return args_addr;
}
if (!m_get_item_info_impl_code->Install(diagnostics, exe_ctx)) {
if (log) {
LLDB_LOGF(log, "Failed to install get-item-info introspection.");
diagnostics.Dump(log);
}
m_get_item_info_impl_code.reset();
return args_addr;
auto utility_fn_or_error = exe_ctx.GetTargetRef().CreateUtilityFunction(
g_get_item_info_function_code, g_get_item_info_function_name,
eLanguageTypeObjC, exe_ctx);
if (!utility_fn_or_error) {
LLDB_LOG_ERROR(log, utility_fn_or_error.takeError(),
"Failed to create utility function: {0}.");
}
m_get_item_info_impl_code = std::move(*utility_fn_or_error);
} else {
LLDB_LOGF(log, "No get-item-info introspection code found.");
return LLDB_INVALID_ADDRESS;

View File

@ -146,27 +146,16 @@ lldb::addr_t AppleGetPendingItemsHandler::SetupGetPendingItemsFunction(
if (!m_get_pending_items_impl_code) {
if (g_get_pending_items_function_code != nullptr) {
Status error;
m_get_pending_items_impl_code.reset(
exe_ctx.GetTargetRef().GetUtilityFunctionForLanguage(
g_get_pending_items_function_code, eLanguageTypeObjC,
g_get_pending_items_function_name, error));
if (error.Fail()) {
LLDB_LOGF(log,
"Failed to get UtilityFunction for pending-items "
"introspection: %s.",
error.AsCString());
return args_addr;
}
if (!m_get_pending_items_impl_code->Install(diagnostics, exe_ctx)) {
if (log) {
LLDB_LOGF(log, "Failed to install pending-items introspection.");
diagnostics.Dump(log);
}
m_get_pending_items_impl_code.reset();
auto utility_fn_or_error = exe_ctx.GetTargetRef().CreateUtilityFunction(
g_get_pending_items_function_code,
g_get_pending_items_function_name, eLanguageTypeC, exe_ctx);
if (!utility_fn_or_error) {
LLDB_LOG_ERROR(log, utility_fn_or_error.takeError(),
"Failed to create UtilityFunction for pending-items "
"introspection: {0}.");
return args_addr;
}
m_get_pending_items_impl_code = std::move(*utility_fn_or_error);
} else {
LLDB_LOGF(log, "No pending-items introspection code found.");
return LLDB_INVALID_ADDRESS;

View File

@ -159,27 +159,16 @@ AppleGetQueuesHandler::SetupGetQueuesFunction(Thread &thread,
if (!m_get_queues_impl_code_up) {
if (g_get_current_queues_function_code != nullptr) {
Status error;
m_get_queues_impl_code_up.reset(
exe_ctx.GetTargetRef().GetUtilityFunctionForLanguage(
g_get_current_queues_function_code, eLanguageTypeC,
g_get_current_queues_function_name, error));
if (error.Fail()) {
LLDB_LOGF(
log,
"Failed to get UtilityFunction for queues introspection: %s.",
error.AsCString());
return args_addr;
}
if (!m_get_queues_impl_code_up->Install(diagnostics, exe_ctx)) {
if (log) {
LLDB_LOGF(log, "Failed to install queues introspection");
diagnostics.Dump(log);
}
m_get_queues_impl_code_up.reset();
auto utility_fn_or_error = exe_ctx.GetTargetRef().CreateUtilityFunction(
g_get_current_queues_function_code,
g_get_current_queues_function_name, eLanguageTypeC, exe_ctx);
if (!utility_fn_or_error) {
LLDB_LOG_ERROR(log, utility_fn_or_error.takeError(),
"Failed to create UtilityFunction for queues "
"introspection: {0}.");
return args_addr;
}
m_get_queues_impl_code_up = std::move(*utility_fn_or_error);
} else {
if (log) {
LLDB_LOGF(log, "No queues introspection code found.");

View File

@ -153,29 +153,16 @@ lldb::addr_t AppleGetThreadItemInfoHandler::SetupGetThreadItemInfoFunction(
if (!m_get_thread_item_info_impl_code) {
Status error;
if (g_get_thread_item_info_function_code != nullptr) {
m_get_thread_item_info_impl_code.reset(
exe_ctx.GetTargetRef().GetUtilityFunctionForLanguage(
g_get_thread_item_info_function_code, eLanguageTypeC,
g_get_thread_item_info_function_name, error));
if (error.Fail()) {
LLDB_LOGF(log,
"Failed to get UtilityFunction for "
"get-thread-item-info introspection: %s.",
error.AsCString());
m_get_thread_item_info_impl_code.reset();
return args_addr;
}
if (!m_get_thread_item_info_impl_code->Install(diagnostics, exe_ctx)) {
if (log) {
LLDB_LOGF(log,
"Failed to install get-thread-item-info introspection.");
diagnostics.Dump(log);
}
m_get_thread_item_info_impl_code.reset();
auto utility_fn_or_error = exe_ctx.GetTargetRef().CreateUtilityFunction(
g_get_thread_item_info_function_code,
g_get_thread_item_info_function_name, eLanguageTypeC, exe_ctx);
if (!utility_fn_or_error) {
LLDB_LOG_ERROR(log, utility_fn_or_error.takeError(),
"Failed to get UtilityFunction for "
"get-thread-item-info introspection: {0}.");
return args_addr;
}
m_get_thread_item_info_impl_code = std::move(*utility_fn_or_error);
} else {
LLDB_LOGF(log, "No get-thread-item-info introspection code found.");
return LLDB_INVALID_ADDRESS;

View File

@ -9574,14 +9574,15 @@ FunctionCaller *TypeSystemClangForExpressions::GetFunctionCaller(
arg_value_list, name);
}
UtilityFunction *
TypeSystemClangForExpressions::GetUtilityFunction(const char *text,
const char *name) {
std::unique_ptr<UtilityFunction>
TypeSystemClangForExpressions::CreateUtilityFunction(std::string text,
std::string name) {
TargetSP target_sp = m_target_wp.lock();
if (!target_sp)
return nullptr;
return {};
return new ClangUtilityFunction(*target_sp.get(), text, name);
return std::make_unique<ClangUtilityFunction>(
*target_sp.get(), std::move(text), std::move(name));
}
PersistentExpressionState *

View File

@ -1134,8 +1134,8 @@ public:
const ValueList &arg_value_list,
const char *name) override;
UtilityFunction *GetUtilityFunction(const char *text,
const char *name) override;
std::unique_ptr<UtilityFunction>
CreateUtilityFunction(std::string text, std::string name) override;
PersistentExpressionState *GetPersistentExpressionState() override;
private:

View File

@ -27,9 +27,11 @@
#include "lldb/Core/StreamFile.h"
#include "lldb/Core/StructuredDataImpl.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Expression/DiagnosticManager.h"
#include "lldb/Expression/ExpressionVariable.h"
#include "lldb/Expression/REPL.h"
#include "lldb/Expression/UserExpression.h"
#include "lldb/Expression/UtilityFunction.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/PosixApi.h"
#include "lldb/Interpreter/CommandInterpreter.h"
@ -2242,25 +2244,27 @@ FunctionCaller *Target::GetFunctionCallerForLanguage(
return persistent_fn;
}
UtilityFunction *
Target::GetUtilityFunctionForLanguage(const char *text,
lldb::LanguageType language,
const char *name, Status &error) {
llvm::Expected<std::unique_ptr<UtilityFunction>>
Target::CreateUtilityFunction(std::string expression, std::string name,
lldb::LanguageType language,
ExecutionContext &exe_ctx) {
auto type_system_or_err = GetScratchTypeSystemForLanguage(language);
if (!type_system_or_err)
return type_system_or_err.takeError();
if (auto err = type_system_or_err.takeError()) {
error.SetErrorStringWithFormat(
"Could not find type system for language %s: %s",
Language::GetNameForLanguageType(language),
llvm::toString(std::move(err)).c_str());
return nullptr;
}
auto *utility_fn = type_system_or_err->GetUtilityFunction(text, name);
std::unique_ptr<UtilityFunction> utility_fn =
type_system_or_err->CreateUtilityFunction(std::move(expression),
std::move(name));
if (!utility_fn)
error.SetErrorStringWithFormat(
"Could not create an expression for language %s",
Language::GetNameForLanguageType(language));
return llvm::make_error<llvm::StringError>(
llvm::StringRef("Could not create an expression for language") +
Language::GetNameForLanguageType(language),
llvm::inconvertibleErrorCode());
DiagnosticManager diagnostics;
if (!utility_fn->Install(diagnostics, exe_ctx))
return llvm::make_error<llvm::StringError>(diagnostics.GetString(),
llvm::inconvertibleErrorCode());
return utility_fn;
}