diff options
author | Adrian Prantl <aprantl@apple.com> | 2024-06-17 17:07:36 -0700 |
---|---|---|
committer | Adrian Prantl <aprantl@apple.com> | 2024-06-20 10:32:06 -0700 |
commit | f900644ae2b6c7a485673974688a62c3f3301dcc (patch) | |
tree | 6c336655fbaec0accde760dce9c060b548960de5 /lldb | |
parent | d1bc75c0bce141b94f9afadfde4e784760735ec0 (diff) | |
download | llvm-f900644ae2b6c7a485673974688a62c3f3301dcc.zip llvm-f900644ae2b6c7a485673974688a62c3f3301dcc.tar.gz llvm-f900644ae2b6c7a485673974688a62c3f3301dcc.tar.bz2 |
Refactor GetObjectDescription() to return llvm::Expected (NFC)
This is de facto an NFC change for Objective-C but will benefit the
Swift language plugin.
Diffstat (limited to 'lldb')
12 files changed, 143 insertions, 103 deletions
diff --git a/lldb/include/lldb/Core/ValueObject.h b/lldb/include/lldb/Core/ValueObject.h index 205d9ad..93eb3e8 100644 --- a/lldb/include/lldb/Core/ValueObject.h +++ b/lldb/include/lldb/Core/ValueObject.h @@ -537,7 +537,7 @@ public: std::string &destination, const TypeSummaryOptions &options); - const char *GetObjectDescription(); + llvm::Expected<std::string> GetObjectDescription(); bool HasSpecialPrintableRepresentation( ValueObjectRepresentationStyle val_obj_display, diff --git a/lldb/include/lldb/DataFormatters/ValueObjectPrinter.h b/lldb/include/lldb/DataFormatters/ValueObjectPrinter.h index 7460370..f9deb6e 100644 --- a/lldb/include/lldb/DataFormatters/ValueObjectPrinter.h +++ b/lldb/include/lldb/DataFormatters/ValueObjectPrinter.h @@ -75,7 +75,7 @@ protected: void SetupMostSpecializedValue(); - const char *GetDescriptionForDisplay(); + llvm::Expected<std::string> GetDescriptionForDisplay(); const char *GetRootNameForDisplay(); @@ -108,7 +108,8 @@ protected: bool PrintValueAndSummaryIfNeeded(bool &value_printed, bool &summary_printed); - bool PrintObjectDescriptionIfNeeded(bool value_printed, bool summary_printed); + llvm::Error PrintObjectDescriptionIfNeeded(bool value_printed, + bool summary_printed); bool ShouldPrintChildren(DumpValueObjectOptions::PointerDepth &curr_ptr_depth); @@ -132,7 +133,7 @@ protected: PrintChildren(bool value_printed, bool summary_printed, const DumpValueObjectOptions::PointerDepth &curr_ptr_depth); - void PrintChildrenIfNeeded(bool value_printed, bool summary_printed); + llvm::Error PrintChildrenIfNeeded(bool value_printed, bool summary_printed); bool PrintChildrenOneLiner(bool hide_names); diff --git a/lldb/include/lldb/Target/LanguageRuntime.h b/lldb/include/lldb/Target/LanguageRuntime.h index a2a9c016..d093dcc 100644 --- a/lldb/include/lldb/Target/LanguageRuntime.h +++ b/lldb/include/lldb/Target/LanguageRuntime.h @@ -73,11 +73,12 @@ public: return nullptr; } - virtual bool GetObjectDescription(Stream &str, ValueObject &object) = 0; - - virtual bool GetObjectDescription(Stream &str, Value &value, - ExecutionContextScope *exe_scope) = 0; + virtual llvm::Error GetObjectDescription(Stream &str, + ValueObject &object) = 0; + virtual llvm::Error + GetObjectDescription(Stream &str, Value &value, + ExecutionContextScope *exe_scope) = 0; struct VTableInfo { Address addr; /// Address of the vtable's virtual function table diff --git a/lldb/source/API/SBValue.cpp b/lldb/source/API/SBValue.cpp index 1b9cae6..10a691c 100644 --- a/lldb/source/API/SBValue.cpp +++ b/lldb/source/API/SBValue.cpp @@ -379,7 +379,10 @@ const char *SBValue::GetObjectDescription() { if (!value_sp) return nullptr; - return ConstString(value_sp->GetObjectDescription()).GetCString(); + llvm::Expected<std::string> str = value_sp->GetObjectDescription(); + if (!str) + return ConstString("error: " + toString(str.takeError())).AsCString(); + return ConstString(*str).AsCString(); } SBType SBValue::GetType() { diff --git a/lldb/source/Core/ValueObject.cpp b/lldb/source/Core/ValueObject.cpp index cf0f557..8f72efc 100644 --- a/lldb/source/Core/ValueObject.cpp +++ b/lldb/source/Core/ValueObject.cpp @@ -989,41 +989,46 @@ ValueObject::ReadPointedString(lldb::WritableDataBufferSP &buffer_sp, return {total_bytes_read, was_capped}; } -const char *ValueObject::GetObjectDescription() { +llvm::Expected<std::string> ValueObject::GetObjectDescription() { if (!UpdateValueIfNeeded(true)) - return nullptr; + return llvm::createStringError("could not update value"); // Return cached value. if (!m_object_desc_str.empty()) - return m_object_desc_str.c_str(); + return m_object_desc_str; ExecutionContext exe_ctx(GetExecutionContextRef()); Process *process = exe_ctx.GetProcessPtr(); if (!process) - return nullptr; + return llvm::createStringError("no process"); // Returns the object description produced by one language runtime. - auto get_object_description = [&](LanguageType language) -> const char * { + auto get_object_description = + [&](LanguageType language) -> llvm::Expected<std::string> { if (LanguageRuntime *runtime = process->GetLanguageRuntime(language)) { StreamString s; - if (runtime->GetObjectDescription(s, *this)) { - m_object_desc_str.append(std::string(s.GetString())); - return m_object_desc_str.c_str(); - } + if (llvm::Error error = runtime->GetObjectDescription(s, *this)) + return error; + m_object_desc_str = s.GetString(); + return m_object_desc_str; } - return nullptr; + return llvm::createStringError("no native language runtime"); }; // Try the native language runtime first. LanguageType native_language = GetObjectRuntimeLanguage(); - if (const char *desc = get_object_description(native_language)) + llvm::Expected<std::string> desc = get_object_description(native_language); + if (desc) return desc; // Try the Objective-C language runtime. This fallback is necessary // for Objective-C++ and mixed Objective-C / C++ programs. - if (Language::LanguageIsCFamily(native_language)) + if (Language::LanguageIsCFamily(native_language)) { + // We're going to try again, so let's drop the first error. + llvm::consumeError(desc.takeError()); return get_object_description(eLanguageTypeObjC); - return nullptr; + } + return desc; } bool ValueObject::GetValueAsCString(const lldb_private::TypeFormatImpl &format, @@ -1472,9 +1477,16 @@ bool ValueObject::DumpPrintableRepresentation( str = GetSummaryAsCString(); break; - case eValueObjectRepresentationStyleLanguageSpecific: - str = GetObjectDescription(); - break; + case eValueObjectRepresentationStyleLanguageSpecific: { + llvm::Expected<std::string> desc = GetObjectDescription(); + if (!desc) { + strm << "error: " << toString(desc.takeError()); + str = strm.GetString(); + } else { + strm << *desc; + str = strm.GetString(); + } + } break; case eValueObjectRepresentationStyleLocation: str = GetLocationAsCString(); diff --git a/lldb/source/DataFormatters/ValueObjectPrinter.cpp b/lldb/source/DataFormatters/ValueObjectPrinter.cpp index a81a5172..ce24a78 100644 --- a/lldb/source/DataFormatters/ValueObjectPrinter.cpp +++ b/lldb/source/DataFormatters/ValueObjectPrinter.cpp @@ -91,9 +91,8 @@ llvm::Error ValueObjectPrinter::PrintValueObject() { PrintValueAndSummaryIfNeeded(value_printed, summary_printed); if (m_val_summary_ok) - PrintChildrenIfNeeded(value_printed, summary_printed); - else - m_stream->EOL(); + return PrintChildrenIfNeeded(value_printed, summary_printed); + m_stream->EOL(); return llvm::Error::success(); } @@ -145,13 +144,21 @@ void ValueObjectPrinter::SetupMostSpecializedValue() { "SetupMostSpecialized value must compute a valid ValueObject"); } -const char *ValueObjectPrinter::GetDescriptionForDisplay() { +llvm::Expected<std::string> ValueObjectPrinter::GetDescriptionForDisplay() { ValueObject &valobj = GetMostSpecializedValue(); - const char *str = valobj.GetObjectDescription(); + llvm::Expected<std::string> maybe_str = valobj.GetObjectDescription(); + if (maybe_str) + return maybe_str; + + const char *str = nullptr; if (!str) str = valobj.GetSummaryAsCString(); if (!str) str = valobj.GetValueAsCString(); + + if (!str) + return maybe_str; + llvm::consumeError(maybe_str.takeError()); return str; } @@ -461,34 +468,38 @@ bool ValueObjectPrinter::PrintValueAndSummaryIfNeeded(bool &value_printed, return !error_printed; } -bool ValueObjectPrinter::PrintObjectDescriptionIfNeeded(bool value_printed, - bool summary_printed) { +llvm::Error +ValueObjectPrinter::PrintObjectDescriptionIfNeeded(bool value_printed, + bool summary_printed) { if (ShouldPrintValueObject()) { // let's avoid the overly verbose no description error for a nil thing if (m_options.m_use_objc && !IsNil() && !IsUninitialized() && (!m_options.m_pointer_as_array)) { if (!m_options.m_hide_value || ShouldShowName()) - m_stream->Printf(" "); - const char *object_desc = nullptr; - if (value_printed || summary_printed) - object_desc = GetMostSpecializedValue().GetObjectDescription(); - else - object_desc = GetDescriptionForDisplay(); - if (object_desc && *object_desc) { + *m_stream << ' '; + llvm::Expected<std::string> object_desc = + (value_printed || summary_printed) + ? GetMostSpecializedValue().GetObjectDescription() + : GetDescriptionForDisplay(); + if (!object_desc) { + // If no value or summary was printed, surface the error. + if (!value_printed && !summary_printed) + return object_desc.takeError(); + // Otherwise gently nudge the user that they should have used + // `p` instead of `po`. Unfortunately we cannot be more direct + // about this, because we don't actually know what the user did. + *m_stream << "warning: no object description available\n"; + llvm::consumeError(object_desc.takeError()); + } else { + *m_stream << *object_desc; // If the description already ends with a \n don't add another one. - size_t object_end = strlen(object_desc) - 1; - if (object_desc[object_end] == '\n') - m_stream->Printf("%s", object_desc); - else - m_stream->Printf("%s\n", object_desc); - return true; - } else if (!value_printed && !summary_printed) - return true; - else - return false; + if (object_desc->empty() || object_desc->back() != '\n') + *m_stream << '\n'; + } + return llvm::Error::success(); } } - return true; + return llvm::Error::success(); } bool DumpValueObjectOptions::PointerDepth::CanAllowExpansion() const { @@ -812,9 +823,12 @@ bool ValueObjectPrinter::PrintChildrenOneLiner(bool hide_names) { return true; } -void ValueObjectPrinter::PrintChildrenIfNeeded(bool value_printed, - bool summary_printed) { - PrintObjectDescriptionIfNeeded(value_printed, summary_printed); +llvm::Error ValueObjectPrinter::PrintChildrenIfNeeded(bool value_printed, + bool summary_printed) { + auto error = PrintObjectDescriptionIfNeeded(value_printed, summary_printed); + if (error) + return error; + ValueObject &valobj = GetMostSpecializedValue(); DumpValueObjectOptions::PointerDepth curr_ptr_depth = m_ptr_depth; @@ -830,7 +844,7 @@ void ValueObjectPrinter::PrintChildrenIfNeeded(bool value_printed, if (m_printed_instance_pointers->count(instance_ptr_value)) { // We already printed this instance-is-pointer thing, so don't expand it. m_stream->PutCString(" {...}\n"); - return; + return llvm::Error::success(); } else { // Remember this guy for future reference. m_printed_instance_pointers->emplace(instance_ptr_value); @@ -858,6 +872,7 @@ void ValueObjectPrinter::PrintChildrenIfNeeded(bool value_printed, .SetReachedMaximumDepth(); } else m_stream->EOL(); + return llvm::Error::success(); } bool ValueObjectPrinter::HasReachedMaximumDepth() { diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp index 300ecc8..c7202a4 100644 --- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp +++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp @@ -47,16 +47,17 @@ bool CPPLanguageRuntime::IsAllowedRuntimeValue(ConstString name) { return name == g_this || name == g_promise || name == g_coro_frame; } -bool CPPLanguageRuntime::GetObjectDescription(Stream &str, - ValueObject &object) { +llvm::Error CPPLanguageRuntime::GetObjectDescription(Stream &str, + ValueObject &object) { // C++ has no generic way to do this. - return false; + return llvm::createStringError("C++ does not support object descriptions"); } -bool CPPLanguageRuntime::GetObjectDescription( - Stream &str, Value &value, ExecutionContextScope *exe_scope) { +llvm::Error +CPPLanguageRuntime::GetObjectDescription(Stream &str, Value &value, + ExecutionContextScope *exe_scope) { // C++ has no generic way to do this. - return false; + return llvm::createStringError("C++ does not support object descriptions"); } bool contains_lambda_identifier(llvm::StringRef &str_ref) { diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h index 1be58b7..57cfe282 100644 --- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h +++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h @@ -59,10 +59,10 @@ public: process.GetLanguageRuntime(lldb::eLanguageTypeC_plus_plus)); } - bool GetObjectDescription(Stream &str, ValueObject &object) override; + llvm::Error GetObjectDescription(Stream &str, ValueObject &object) override; - bool GetObjectDescription(Stream &str, Value &value, - ExecutionContextScope *exe_scope) override; + llvm::Error GetObjectDescription(Stream &str, Value &value, + ExecutionContextScope *exe_scope) override; /// Obtain a ThreadPlan to get us into C++ constructs such as std::function. /// diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp index 9434376..800eda9 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp @@ -67,20 +67,21 @@ void AppleObjCRuntime::Terminate() { AppleObjCRuntimeV1::Terminate(); } -bool AppleObjCRuntime::GetObjectDescription(Stream &str, ValueObject &valobj) { +llvm::Error AppleObjCRuntime::GetObjectDescription(Stream &str, + ValueObject &valobj) { CompilerType compiler_type(valobj.GetCompilerType()); bool is_signed; // ObjC objects can only be pointers (or numbers that actually represents // pointers but haven't been typecast, because reasons..) if (!compiler_type.IsIntegerType(is_signed) && !compiler_type.IsPointerType()) - return false; + return llvm::createStringError("not a pointer type"); // Make the argument list: we pass one arg, the address of our pointer, to // the print function. Value val; if (!valobj.ResolveValue(val.GetScalar())) - return false; + return llvm::createStringError("pointer value could not be resolved"); // Value Objects may not have a process in their ExecutionContextRef. But we // need to have one in the ref we pass down to eventually call description. @@ -91,20 +92,22 @@ bool AppleObjCRuntime::GetObjectDescription(Stream &str, ValueObject &valobj) { } else { exe_ctx.SetContext(valobj.GetTargetSP(), true); if (!exe_ctx.HasProcessScope()) - return false; + return llvm::createStringError("no process"); } return GetObjectDescription(str, val, exe_ctx.GetBestExecutionContextScope()); } -bool AppleObjCRuntime::GetObjectDescription(Stream &strm, Value &value, - ExecutionContextScope *exe_scope) { + +llvm::Error +AppleObjCRuntime::GetObjectDescription(Stream &strm, Value &value, + ExecutionContextScope *exe_scope) { if (!m_read_objc_library) - return false; + return llvm::createStringError("Objective-C runtime not loaded"); ExecutionContext exe_ctx; exe_scope->CalculateExecutionContext(exe_ctx); Process *process = exe_ctx.GetProcessPtr(); if (!process) - return false; + return llvm::createStringError("no process"); // We need other parts of the exe_ctx, but the processes have to match. assert(m_process == process); @@ -112,25 +115,25 @@ bool AppleObjCRuntime::GetObjectDescription(Stream &strm, Value &value, // Get the function address for the print function. const Address *function_address = GetPrintForDebuggerAddr(); if (!function_address) - return false; + return llvm::createStringError("no print function"); Target *target = exe_ctx.GetTargetPtr(); CompilerType compiler_type = value.GetCompilerType(); if (compiler_type) { - if (!TypeSystemClang::IsObjCObjectPointerType(compiler_type)) { - strm.Printf("Value doesn't point to an ObjC object.\n"); - return false; - } + if (!TypeSystemClang::IsObjCObjectPointerType(compiler_type)) + return llvm::createStringError( + "Value doesn't point to an ObjC object.\n"); } else { // If it is not a pointer, see if we can make it into a pointer. TypeSystemClangSP scratch_ts_sp = ScratchTypeSystemClang::GetForTarget(*target); if (!scratch_ts_sp) - return false; + return llvm::createStringError("no scratch type system"); CompilerType opaque_type = scratch_ts_sp->GetBasicType(eBasicTypeObjCID); if (!opaque_type) - opaque_type = scratch_ts_sp->GetBasicType(eBasicTypeVoid).GetPointerType(); + opaque_type = + scratch_ts_sp->GetBasicType(eBasicTypeVoid).GetPointerType(); // value.SetContext(Value::eContextTypeClangType, opaque_type_ptr); value.SetCompilerType(opaque_type); } @@ -142,14 +145,14 @@ bool AppleObjCRuntime::GetObjectDescription(Stream &strm, Value &value, TypeSystemClangSP scratch_ts_sp = ScratchTypeSystemClang::GetForTarget(*target); if (!scratch_ts_sp) - return false; + return llvm::createStringError("no scratch type system"); CompilerType return_compiler_type = scratch_ts_sp->GetCStringType(true); Value ret; // ret.SetContext(Value::eContextTypeClangType, return_compiler_type); ret.SetCompilerType(return_compiler_type); - if (exe_ctx.GetFramePtr() == nullptr) { + if (!exe_ctx.GetFramePtr()) { Thread *thread = exe_ctx.GetThreadPtr(); if (thread == nullptr) { exe_ctx.SetThreadSP(process->GetThreadList().GetSelectedThread()); @@ -173,10 +176,11 @@ bool AppleObjCRuntime::GetObjectDescription(Stream &strm, Value &value, arg_value_list, "objc-object-description", error)); if (error.Fail()) { m_print_object_caller_up.reset(); - strm.Printf("Could not get function runner to call print for debugger " - "function: %s.", - error.AsCString()); - return false; + return llvm::createStringError( + llvm::Twine( + "could not get function runner to call print for debugger " + "function: ") + + error.AsCString()); } m_print_object_caller_up->InsertFunction(exe_ctx, wrapper_struct_addr, diagnostics); @@ -195,10 +199,9 @@ bool AppleObjCRuntime::GetObjectDescription(Stream &strm, Value &value, ExpressionResults results = m_print_object_caller_up->ExecuteFunction( exe_ctx, &wrapper_struct_addr, options, diagnostics, ret); - if (results != eExpressionCompleted) { - strm.Printf("Error evaluating Print Object function: %d.\n", results); - return false; - } + if (results != eExpressionCompleted) + return llvm::createStringError( + "Error evaluating Print Object function: %d.\n", results); addr_t result_ptr = ret.GetScalar().ULongLong(LLDB_INVALID_ADDRESS); @@ -213,7 +216,9 @@ bool AppleObjCRuntime::GetObjectDescription(Stream &strm, Value &value, strm.Write(buf, curr_len); cstr_len += curr_len; } - return cstr_len > 0; + if (cstr_len > 0) + return llvm::Error::success(); + return llvm::createStringError("empty object description"); } lldb::ModuleSP AppleObjCRuntime::GetObjCModule() { diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h index cfeec3d6..da58d44 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h @@ -44,10 +44,10 @@ public: } // These are generic runtime functions: - bool GetObjectDescription(Stream &str, Value &value, - ExecutionContextScope *exe_scope) override; + llvm::Error GetObjectDescription(Stream &str, Value &value, + ExecutionContextScope *exe_scope) override; - bool GetObjectDescription(Stream &str, ValueObject &object) override; + llvm::Error GetObjectDescription(Stream &str, ValueObject &object) override; bool CouldHaveDynamicValue(ValueObject &in_value) override; diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/GNUstepObjCRuntime/GNUstepObjCRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/GNUstepObjCRuntime/GNUstepObjCRuntime.cpp index 39b3e81..58b8387 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/GNUstepObjCRuntime/GNUstepObjCRuntime.cpp +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/GNUstepObjCRuntime/GNUstepObjCRuntime.cpp @@ -104,15 +104,17 @@ GNUstepObjCRuntime::GNUstepObjCRuntime(Process *process) ReadObjCLibraryIfNeeded(process->GetTarget().GetImages()); } -bool GNUstepObjCRuntime::GetObjectDescription(Stream &str, - ValueObject &valobj) { - // TODO: ObjC has a generic way to do this - return false; +llvm::Error GNUstepObjCRuntime::GetObjectDescription(Stream &str, + ValueObject &valobj) { + return llvm::createStringError( + "LLDB's GNUStep runtime does not support object description"); } -bool GNUstepObjCRuntime::GetObjectDescription( - Stream &strm, Value &value, ExecutionContextScope *exe_scope) { - // TODO: ObjC has a generic way to do this - return false; + +llvm::Error +GNUstepObjCRuntime::GetObjectDescription(Stream &strm, Value &value, + ExecutionContextScope *exe_scope) { + return llvm::createStringError( + "LLDB's GNUStep runtime does not support object description"); } bool GNUstepObjCRuntime::CouldHaveDynamicValue(ValueObject &in_value) { diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/GNUstepObjCRuntime/GNUstepObjCRuntime.h b/lldb/source/Plugins/LanguageRuntime/ObjC/GNUstepObjCRuntime/GNUstepObjCRuntime.h index b220888..de24466 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/GNUstepObjCRuntime/GNUstepObjCRuntime.h +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/GNUstepObjCRuntime/GNUstepObjCRuntime.h @@ -57,10 +57,10 @@ public: // // LanguageRuntime implementation // - bool GetObjectDescription(Stream &str, Value &value, - ExecutionContextScope *exe_scope) override; + llvm::Error GetObjectDescription(Stream &str, Value &value, + ExecutionContextScope *exe_scope) override; - bool GetObjectDescription(Stream &str, ValueObject &object) override; + llvm::Error GetObjectDescription(Stream &str, ValueObject &object) override; bool CouldHaveDynamicValue(ValueObject &in_value) override; |