[Lldb-commits] [lldb] [lldb] All ValueObjectSP instances are now valid (non-null) but have an error state (PR #74912)

Pete Lawrence via lldb-commits lldb-commits at lists.llvm.org
Fri Dec 8 20:30:27 PST 2023


https://github.com/PortalPete created https://github.com/llvm/llvm-project/pull/74912



Many methods return `nullptr` or `ValueObjectSP()` to represent an invalid result.

For methods that have a `Status &error` parameter and return an `ValueObjectSP`, the return value *becomes* the container for the error state, which eliminate the need for a parameter.

For all other methods that return a `ValueObjectSP` but don't have a `Status` parameter, they now return `std::optional<ValueObjectSP>`.

The implication here is that that callers of the former methods need to call one of these methods:
* `return_value->GetError.Success()`
* `return_value->GetError.Fail()`

Callers of latter methods need only check whether the optional has a value or not, and if it does, to call its `value()` method to get the `ValueObjectSP` within.

>From 2cdc04fa607f62df2dfdf96e3322cdf34bcd15db Mon Sep 17 00:00:00 2001
From: Pete Lawrence <plawrence at apple.com>
Date: Thu, 7 Dec 2023 12:14:01 -1000
Subject: [PATCH] [lldb] All ValueObjectSP instances are now valid (non-null)
 but may be in an error state

Many methods return `nullptr` or `ValueObjectSP()` to represent an invalid result.

For methods that have a `Status &error` parameter and return an `ValueObjectSP`, the return value *becomes* the container for the error state, which eliminate the need for a parameter.

For all other methods that return a `ValueObjectSP` but don't have a `Status` parameter, they now return `std::optional<ValueObjectSP>`.

The implication here is that that callers of the former methods need to call one of these methods:
* `return_value->GetError.Success()`
* `return_value->GetError.Fail()`

Callers of latter methods need only check whether the optional has a value or not,
and if it does, to call its `value()` method to get the `ValueObjectSP` within.
---
 lldb/include/lldb/Core/ValueObject.h          |  77 +-
 .../lldb/Core/ValueObjectConstResult.h        |   2 +-
 .../lldb/Core/ValueObjectConstResultImpl.h    |   2 +-
 lldb/include/lldb/Core/ValueObjectList.h      |  12 +-
 lldb/include/lldb/Core/ValueObjectRegister.h  |   4 +-
 .../lldb/Core/ValueObjectSyntheticFilter.h    |  10 +-
 lldb/include/lldb/Core/ValueObjectUpdater.h   |   6 +-
 .../lldb/DataFormatters/TypeSynthetic.h       |  18 +-
 lldb/include/lldb/Expression/UserExpression.h |   2 +-
 .../lldb/Interpreter/ScriptInterpreter.h      |   8 +-
 lldb/include/lldb/Target/Target.h             |   2 +-
 lldb/include/lldb/lldb-forward.h              |  20 +-
 lldb/source/Core/ValueObject.cpp              | 832 +++++++++---------
 lldb/source/Core/ValueObjectConstResult.cpp   |   4 +-
 .../Core/ValueObjectConstResultImpl.cpp       |   8 +-
 lldb/source/Core/ValueObjectList.cpp          |  59 +-
 lldb/source/Core/ValueObjectRegister.cpp      |   4 +-
 .../Core/ValueObjectSyntheticFilter.cpp       |  46 +-
 lldb/source/Core/ValueObjectUpdater.cpp       |  18 +-
 lldb/source/DataFormatters/TypeSynthetic.cpp  |   2 +-
 lldb/source/Target/Target.cpp                 |   2 +-
 21 files changed, 574 insertions(+), 564 deletions(-)

diff --git a/lldb/include/lldb/Core/ValueObject.h b/lldb/include/lldb/Core/ValueObject.h
index 20b3086138457f..06184a5bde0715 100644
--- a/lldb/include/lldb/Core/ValueObject.h
+++ b/lldb/include/lldb/Core/ValueObject.h
@@ -409,7 +409,7 @@ class ValueObject {
       Stream &s,
       GetExpressionPathFormat = eGetExpressionPathFormatDereferencePointers);
 
-  lldb::ValueObjectSP GetValueForExpressionPath(
+  std::optional<lldb::ValueObjectSP> GetValueForExpressionPath(
       llvm::StringRef expression,
       ExpressionPathScanEndReason *reason_to_stop = nullptr,
       ExpressionPathEndResultType *final_value_type = nullptr,
@@ -465,22 +465,24 @@ class ValueObject {
   /// Returns a unique id for this ValueObject.
   lldb::user_id_t GetID() const { return m_id.GetID(); }
 
-  virtual lldb::ValueObjectSP GetChildAtIndex(size_t idx,
-                                              bool can_create = true);
+  virtual std::optional<lldb::ValueObjectSP>
+  GetChildAtIndex(size_t idx, bool can_create = true);
 
-  // this will always create the children if necessary
-  lldb::ValueObjectSP GetChildAtIndexPath(llvm::ArrayRef<size_t> idxs,
-                                          size_t *index_of_error = nullptr);
+  /// The method always creates missing children in the path, if necessary.
+  std::optional<lldb::ValueObjectSP>
+  GetChildAtIndexPath(llvm::ArrayRef<size_t> idxs,
+                      size_t *index_of_error = nullptr);
 
-  lldb::ValueObjectSP
+  std::optional<lldb::ValueObjectSP>
   GetChildAtIndexPath(llvm::ArrayRef<std::pair<size_t, bool>> idxs,
                       size_t *index_of_error = nullptr);
 
-  // this will always create the children if necessary
-  lldb::ValueObjectSP GetChildAtNamePath(llvm::ArrayRef<llvm::StringRef> names);
+  /// The method always creates missing children in the path, if necessary.
+  std::optional<lldb::ValueObjectSP>
+  GetChildAtNamePath(llvm::ArrayRef<llvm::StringRef> names);
 
-  virtual lldb::ValueObjectSP GetChildMemberWithName(llvm::StringRef name,
-                                                     bool can_create = true);
+  virtual std::optional<lldb::ValueObjectSP>
+  GetChildMemberWithName(llvm::StringRef name, bool can_create = true);
 
   virtual size_t GetIndexOfChildWithName(llvm::StringRef name);
 
@@ -544,7 +546,12 @@ class ValueObject {
 
   bool UpdateFormatsIfNeeded();
 
-  lldb::ValueObjectSP GetSP() { return m_manager->GetSharedPointer(this); }
+  lldb::ValueObjectSP GetSP() {
+    std::shared_ptr<ValueObject> shared_pointer =
+        m_manager->GetSharedPointer(this);
+    lldb::ValueObjectSP value_object_sp(std::move(shared_pointer));
+    return value_object_sp;
+  }
 
   /// Change the name of the current ValueObject. Should *not* be used from a
   /// synthetic child provider as it would change the name of the non synthetic
@@ -556,26 +563,28 @@ class ValueObject {
 
   lldb::addr_t GetPointerValue(AddressType *address_type = nullptr);
 
-  lldb::ValueObjectSP GetSyntheticChild(ConstString key) const;
+  std::optional<lldb::ValueObjectSP> GetSyntheticChild(ConstString key) const;
 
-  lldb::ValueObjectSP GetSyntheticArrayMember(size_t index, bool can_create);
+  std::optional<lldb::ValueObjectSP> GetSyntheticArrayMember(size_t index,
+                                                             bool can_create);
 
-  lldb::ValueObjectSP GetSyntheticBitFieldChild(uint32_t from, uint32_t to,
-                                                bool can_create);
+  std::optional<lldb::ValueObjectSP>
+  GetSyntheticBitFieldChild(uint32_t from, uint32_t to, bool can_create);
 
-  lldb::ValueObjectSP GetSyntheticExpressionPathChild(const char *expression,
-                                                      bool can_create);
+  std::optional<lldb::ValueObjectSP>
+  GetSyntheticExpressionPathChild(const char *expression, bool can_create);
 
-  virtual lldb::ValueObjectSP
+  virtual std::optional<lldb::ValueObjectSP>
   GetSyntheticChildAtOffset(uint32_t offset, const CompilerType &type,
                             bool can_create,
                             ConstString name_const_str = ConstString());
 
-  virtual lldb::ValueObjectSP
+  virtual std::optional<lldb::ValueObjectSP>
   GetSyntheticBase(uint32_t offset, const CompilerType &type, bool can_create,
                    ConstString name_const_str = ConstString());
 
-  virtual lldb::ValueObjectSP GetDynamicValue(lldb::DynamicValueType valueType);
+  virtual std::optional<lldb::ValueObjectSP>
+  GetDynamicValue(lldb::DynamicValueType valueType);
 
   lldb::DynamicValueType GetDynamicValueType();
 
@@ -583,7 +592,7 @@ class ValueObject {
 
   virtual lldb::ValueObjectSP GetNonSyntheticValue() { return GetSP(); }
 
-  lldb::ValueObjectSP GetSyntheticValue();
+  std::optional<lldb::ValueObjectSP> GetSyntheticValue();
 
   virtual bool HasSyntheticValue();
 
@@ -595,7 +604,7 @@ class ValueObject {
 
   virtual lldb::ValueObjectSP CreateConstantValue(ConstString name);
 
-  virtual lldb::ValueObjectSP Dereference(Status &error);
+  virtual lldb::ValueObjectSP Dereference();
 
   /// Creates a copy of the ValueObject with a new name and setting the current
   /// ValueObject as its parent. It should be used when we want to change the
@@ -603,7 +612,7 @@ class ValueObject {
   /// (e.g. sythetic child provider).
   virtual lldb::ValueObjectSP Clone(ConstString new_name);
 
-  virtual lldb::ValueObjectSP AddressOf(Status &error);
+  virtual lldb::ValueObjectSP AddressOf();
 
   virtual lldb::addr_t GetLiveAddress() { return LLDB_INVALID_ADDRESS; }
 
@@ -614,11 +623,11 @@ class ValueObject {
 
   virtual lldb::ValueObjectSP DoCast(const CompilerType &compiler_type);
 
-  virtual lldb::ValueObjectSP CastPointerType(const char *name,
-                                              CompilerType &ast_type);
+  virtual std::optional<lldb::ValueObjectSP>
+  CastPointerType(const char *name, CompilerType &ast_type);
 
-  virtual lldb::ValueObjectSP CastPointerType(const char *name,
-                                              lldb::TypeSP &type_sp);
+  virtual std::optional<lldb::ValueObjectSP>
+  CastPointerType(const char *name, lldb::TypeSP &type_sp);
 
   /// If this object represents a C++ class with a vtable, return an object
   /// that represents the virtual function table. If the object isn't a class
@@ -650,18 +659,18 @@ class ValueObject {
 
   void Dump(Stream &s, const DumpValueObjectOptions &options);
 
-  static lldb::ValueObjectSP
+  static std::optional<lldb::ValueObjectSP>
   CreateValueObjectFromExpression(llvm::StringRef name,
                                   llvm::StringRef expression,
                                   const ExecutionContext &exe_ctx);
 
-  static lldb::ValueObjectSP
+  static std::optional<lldb::ValueObjectSP>
   CreateValueObjectFromExpression(llvm::StringRef name,
                                   llvm::StringRef expression,
                                   const ExecutionContext &exe_ctx,
                                   const EvaluateExpressionOptions &options);
 
-  static lldb::ValueObjectSP
+  static std::optional<lldb::ValueObjectSP>
   CreateValueObjectFromAddress(llvm::StringRef name, uint64_t address,
                                const ExecutionContext &exe_ctx,
                                CompilerType type);
@@ -670,7 +679,7 @@ class ValueObject {
   CreateValueObjectFromData(llvm::StringRef name, const DataExtractor &data,
                             const ExecutionContext &exe_ctx, CompilerType type);
 
-  lldb::ValueObjectSP Persist();
+  std::optional<lldb::ValueObjectSP> Persist();
 
   /// Returns true if this is a char* or a char[] if it is a char* and
   /// check_pointer is true, it also checks that the pointer is valid.
@@ -882,7 +891,7 @@ class ValueObject {
 
   /// We have to hold onto a shared  pointer to this one because it is created
   /// as an independent ValueObjectConstResult, which isn't managed by us.
-  lldb::ValueObjectSP m_addr_of_valobj_sp;
+  std::optional<lldb::ValueObjectSP> m_addr_of_valobj_sp;
 
   lldb::Format m_format = lldb::eFormatDefault;
   lldb::Format m_last_format = lldb::eFormatDefault;
@@ -1006,7 +1015,7 @@ class ValueObject {
     GetRoot()->DoUpdateChildrenAddressType(*this);
   }
 
-  lldb::ValueObjectSP GetValueForExpressionPath_Impl(
+  std::optional<lldb::ValueObjectSP> GetValueForExpressionPath_Impl(
       llvm::StringRef expression_cstr,
       ExpressionPathScanEndReason *reason_to_stop,
       ExpressionPathEndResultType *final_value_type,
diff --git a/lldb/include/lldb/Core/ValueObjectConstResult.h b/lldb/include/lldb/Core/ValueObjectConstResult.h
index d61df859bebce4..37896c1d9c8960 100644
--- a/lldb/include/lldb/Core/ValueObjectConstResult.h
+++ b/lldb/include/lldb/Core/ValueObjectConstResult.h
@@ -101,7 +101,7 @@ class ValueObjectConstResult : public ValueObject {
     m_impl.SetLiveAddress(addr, address_type);
   }
 
-  lldb::ValueObjectSP
+  std::optional<ValueObjectSP>
   GetDynamicValue(lldb::DynamicValueType valueType) override;
 
   lldb::LanguageType GetPreferredDisplayLanguage() override;
diff --git a/lldb/include/lldb/Core/ValueObjectConstResultImpl.h b/lldb/include/lldb/Core/ValueObjectConstResultImpl.h
index 5a7a079d3095c9..bca698cc5a9638 100644
--- a/lldb/include/lldb/Core/ValueObjectConstResultImpl.h
+++ b/lldb/include/lldb/Core/ValueObjectConstResultImpl.h
@@ -68,7 +68,7 @@ class ValueObjectConstResultImpl {
   ValueObject *m_impl_backend;
   lldb::addr_t m_live_address;
   AddressType m_live_address_type;
-  lldb::ValueObjectSP m_address_of_backend;
+  std::optional<lldb::ValueObjectSP> m_address_of_backend;
 
   ValueObjectConstResultImpl(const ValueObjectConstResultImpl &) = delete;
   const ValueObjectConstResultImpl &
diff --git a/lldb/include/lldb/Core/ValueObjectList.h b/lldb/include/lldb/Core/ValueObjectList.h
index fcb358e21a26b4..cddd272c50f8ec 100644
--- a/lldb/include/lldb/Core/ValueObjectList.h
+++ b/lldb/include/lldb/Core/ValueObjectList.h
@@ -28,21 +28,23 @@ class ValueObjectList {
 
   void Append(const ValueObjectList &valobj_list);
 
-  lldb::ValueObjectSP FindValueObjectByPointer(ValueObject *valobj);
+  std::optional<lldb::ValueObjectSP>
+  FindValueObjectByPointer(ValueObject *valobj);
 
   size_t GetSize() const;
 
   void Resize(size_t size);
 
-  lldb::ValueObjectSP GetValueObjectAtIndex(size_t idx);
+  std::optional<lldb::ValueObjectSP> GetValueObjectAtIndex(size_t idx);
 
-  lldb::ValueObjectSP RemoveValueObjectAtIndex(size_t idx);
+  std::optional<lldb::ValueObjectSP> RemoveValueObjectAtIndex(size_t idx);
 
   void SetValueObjectAtIndex(size_t idx, const lldb::ValueObjectSP &valobj_sp);
 
-  lldb::ValueObjectSP FindValueObjectByValueName(const char *name);
+  std::optional<lldb::ValueObjectSP>
+  FindValueObjectByValueName(const char *name);
 
-  lldb::ValueObjectSP FindValueObjectByUID(lldb::user_id_t uid);
+  std::optional<lldb::ValueObjectSP> FindValueObjectByUID(lldb::user_id_t uid);
 
   void Swap(ValueObjectList &value_object_list);
 
diff --git a/lldb/include/lldb/Core/ValueObjectRegister.h b/lldb/include/lldb/Core/ValueObjectRegister.h
index 2e47eee3d7f793..b4f6cad3b817f6 100644
--- a/lldb/include/lldb/Core/ValueObjectRegister.h
+++ b/lldb/include/lldb/Core/ValueObjectRegister.h
@@ -52,8 +52,8 @@ class ValueObjectRegisterSet : public ValueObject {
   ValueObject *CreateChildAtIndex(size_t idx, bool synthetic_array_member,
                                   int32_t synthetic_index) override;
 
-  lldb::ValueObjectSP GetChildMemberWithName(llvm::StringRef name,
-                                             bool can_create = true) override;
+  std::optional<lldb::ValueObjectSP>
+  GetChildMemberWithName(llvm::StringRef name, bool can_create = true) override;
 
   size_t GetIndexOfChildWithName(llvm::StringRef name) override;
 
diff --git a/lldb/include/lldb/Core/ValueObjectSyntheticFilter.h b/lldb/include/lldb/Core/ValueObjectSyntheticFilter.h
index 67596232eafd1e..127db2857f684d 100644
--- a/lldb/include/lldb/Core/ValueObjectSyntheticFilter.h
+++ b/lldb/include/lldb/Core/ValueObjectSyntheticFilter.h
@@ -51,15 +51,15 @@ class ValueObjectSynthetic : public ValueObject {
 
   lldb::ValueType GetValueType() const override;
 
-  lldb::ValueObjectSP GetChildAtIndex(size_t idx,
-                                      bool can_create = true) override;
+  std::optional<lldb::ValueObjectSP>
+  GetChildAtIndex(size_t idx, bool can_create = true) override;
 
-  lldb::ValueObjectSP GetChildMemberWithName(llvm::StringRef name,
-                                             bool can_create = true) override;
+  std::optional<lldb::ValueObjectSP>
+  GetChildMemberWithName(llvm::StringRef name, bool can_create = true) override;
 
   size_t GetIndexOfChildWithName(llvm::StringRef name) override;
 
-  lldb::ValueObjectSP
+  std::optional<lldb::ValueObjectSP>
   GetDynamicValue(lldb::DynamicValueType valueType) override;
 
   bool IsInScope() override;
diff --git a/lldb/include/lldb/Core/ValueObjectUpdater.h b/lldb/include/lldb/Core/ValueObjectUpdater.h
index 54fcb31076adde..52ccf9416cbe85 100644
--- a/lldb/include/lldb/Core/ValueObjectUpdater.h
+++ b/lldb/include/lldb/Core/ValueObjectUpdater.h
@@ -20,9 +20,9 @@ namespace lldb_private {
 /// process' stop ID and will update the user type when needed.
 class ValueObjectUpdater {
   /// The root value object is the static typed variable object.
-  lldb::ValueObjectSP m_root_valobj_sp;
+  std::optional<lldb::ValueObjectSP> m_root_valobj_sp;
   /// The user value object is the value object the user wants to see.
-  lldb::ValueObjectSP m_user_valobj_sp;
+  std::optional<lldb::ValueObjectSP> m_user_valobj_sp;
   /// The stop ID that m_user_valobj_sp is valid for.
   uint32_t m_stop_id = UINT32_MAX;
 
@@ -33,7 +33,7 @@ class ValueObjectUpdater {
   /// stop ID. If dynamic values are enabled, or if synthetic children are
   /// enabled, the value object that the user wants to see might change while
   /// debugging.
-  lldb::ValueObjectSP GetSP();
+  std::optional<lldb::ValueObjectSP> GetSP();
 
   lldb::ProcessSP GetProcessSP() const;
 };
diff --git a/lldb/include/lldb/DataFormatters/TypeSynthetic.h b/lldb/include/lldb/DataFormatters/TypeSynthetic.h
index 41be9b7efda8fd..fca5f0cfa48ce4 100644
--- a/lldb/include/lldb/DataFormatters/TypeSynthetic.h
+++ b/lldb/include/lldb/DataFormatters/TypeSynthetic.h
@@ -45,7 +45,7 @@ class SyntheticChildrenFrontEnd {
     return count <= max ? count : max;
   }
 
-  virtual lldb::ValueObjectSP GetChildAtIndex(size_t idx) = 0;
+  virtual std::optional<lldb::ValueObjectSP> GetChildAtIndex(size_t idx) = 0;
 
   virtual size_t GetIndexOfChildWithName(ConstString name) = 0;
 
@@ -68,7 +68,7 @@ class SyntheticChildrenFrontEnd {
   // if this function returns a non-null ValueObject, then the returned
   // ValueObject will stand for this ValueObject whenever a "value" request is
   // made to this ValueObject
-  virtual lldb::ValueObjectSP GetSyntheticValue() { return nullptr; }
+  virtual std::optional<lldb::ValueObjectSP> GetSyntheticValue() { return {}; }
 
   // if this function returns a non-empty ConstString, then clients are
   // expected to use the return as the name of the type of this ValueObject for
@@ -110,7 +110,9 @@ class SyntheticValueProviderFrontEnd : public SyntheticChildrenFrontEnd {
 
   size_t CalculateNumChildren() override { return 0; }
 
-  lldb::ValueObjectSP GetChildAtIndex(size_t idx) override { return nullptr; }
+  std::optional<lldb::ValueObjectSP> GetChildAtIndex(size_t idx) override {
+    return {};
+  }
 
   size_t GetIndexOfChildWithName(ConstString name) override {
     return UINT32_MAX;
@@ -120,7 +122,7 @@ class SyntheticValueProviderFrontEnd : public SyntheticChildrenFrontEnd {
 
   bool MightHaveChildren() override { return false; }
 
-  lldb::ValueObjectSP GetSyntheticValue() override = 0;
+  std::optional<lldb::ValueObjectSP> GetSyntheticValue() override = 0;
 
 private:
   SyntheticValueProviderFrontEnd(const SyntheticValueProviderFrontEnd &) =
@@ -321,9 +323,9 @@ class TypeFilterImpl : public SyntheticChildren {
 
     size_t CalculateNumChildren() override { return filter->GetCount(); }
 
-    lldb::ValueObjectSP GetChildAtIndex(size_t idx) override {
+    std::optional<lldb::ValueObjectSP> GetChildAtIndex(size_t idx) override {
       if (idx >= filter->GetCount())
-        return lldb::ValueObjectSP();
+        return {};
       return m_backend.GetSyntheticExpressionPathChild(
           filter->GetExpressionPathAtIndex(idx), true);
     }
@@ -425,7 +427,7 @@ class ScriptedSyntheticChildren : public SyntheticChildren {
 
     size_t CalculateNumChildren(uint32_t max) override;
 
-    lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;
+    std::optional<lldb::ValueObjectSP> GetChildAtIndex(size_t idx) override;
 
     bool Update() override;
 
@@ -433,7 +435,7 @@ class ScriptedSyntheticChildren : public SyntheticChildren {
 
     size_t GetIndexOfChildWithName(ConstString name) override;
 
-    lldb::ValueObjectSP GetSyntheticValue() override;
+    std::optional<lldb::ValueObjectSP> GetSyntheticValue() override;
 
     ConstString GetSyntheticTypeName() override;
 
diff --git a/lldb/include/lldb/Expression/UserExpression.h b/lldb/include/lldb/Expression/UserExpression.h
index b6cfeec7e89933..d3a5970ed68963 100644
--- a/lldb/include/lldb/Expression/UserExpression.h
+++ b/lldb/include/lldb/Expression/UserExpression.h
@@ -266,7 +266,7 @@ class UserExpression : public Expression {
   static lldb::ExpressionResults
   Evaluate(ExecutionContext &exe_ctx, const EvaluateExpressionOptions &options,
            llvm::StringRef expr_cstr, llvm::StringRef expr_prefix,
-           lldb::ValueObjectSP &result_valobj_sp, Status &error,
+           std::optional<lldb::ValueObjectSP> result_valobj_sp, Status &error,
            std::string *fixed_expression = nullptr,
            ValueObject *ctx_obj = nullptr);
 
diff --git a/lldb/include/lldb/Interpreter/ScriptInterpreter.h b/lldb/include/lldb/Interpreter/ScriptInterpreter.h
index b941f6012a117b..1b55e6eeaba691 100644
--- a/lldb/include/lldb/Interpreter/ScriptInterpreter.h
+++ b/lldb/include/lldb/Interpreter/ScriptInterpreter.h
@@ -425,9 +425,9 @@ class ScriptInterpreter : public PluginInterface {
     return 0;
   }
 
-  virtual lldb::ValueObjectSP
+  virtual std::optional<lldb::ValueObjectSP>
   GetChildAtIndex(const StructuredData::ObjectSP &implementor, uint32_t idx) {
-    return lldb::ValueObjectSP();
+    return {};
   }
 
   virtual int
@@ -446,9 +446,9 @@ class ScriptInterpreter : public PluginInterface {
     return true;
   }
 
-  virtual lldb::ValueObjectSP
+  virtual std::optional<lldb::ValueObjectSP>
   GetSyntheticValue(const StructuredData::ObjectSP &implementor) {
-    return nullptr;
+    return {};
   }
 
   virtual ConstString
diff --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h
index c37682e2a03859..f83acb1d6bfd49 100644
--- a/lldb/include/lldb/Target/Target.h
+++ b/lldb/include/lldb/Target/Target.h
@@ -1239,7 +1239,7 @@ class Target : public std::enable_shared_from_this<Target>,
   // the execution context.
   lldb::ExpressionResults EvaluateExpression(
       llvm::StringRef expression, ExecutionContextScope *exe_scope,
-      lldb::ValueObjectSP &result_valobj_sp,
+      std::optional<lldb::ValueObjectSP> &result_valobj_sp,
       const EvaluateExpressionOptions &options = EvaluateExpressionOptions(),
       std::string *fixed_expression = nullptr, ValueObject *ctx_obj = nullptr);
 
diff --git a/lldb/include/lldb/lldb-forward.h b/lldb/include/lldb/lldb-forward.h
index 068fce4976ed26..d7c81d76a0250a 100644
--- a/lldb/include/lldb/lldb-forward.h
+++ b/lldb/include/lldb/lldb-forward.h
@@ -9,7 +9,9 @@
 #ifndef LLDB_LLDB_FORWARD_H
 #define LLDB_LLDB_FORWARD_H
 
+#include <assert.h>
 #include <memory>
+#include <optional>
 
 // lldb forward declarations
 namespace lldb_private {
@@ -464,7 +466,23 @@ typedef std::shared_ptr<lldb_private::UnixSignals> UnixSignalsSP;
 typedef std::weak_ptr<lldb_private::UnixSignals> UnixSignalsWP;
 typedef std::shared_ptr<lldb_private::UnwindAssembly> UnwindAssemblySP;
 typedef std::shared_ptr<lldb_private::UnwindPlan> UnwindPlanSP;
-typedef std::shared_ptr<lldb_private::ValueObject> ValueObjectSP;
+class ValueObjectSP : public std::shared_ptr<lldb_private::ValueObject> {
+  ValueObjectSP() = delete;
+  operator bool() = delete;
+
+public:
+  ValueObjectSP(std::shared_ptr<lldb_private::ValueObject> &&pointer)
+      : std::shared_ptr<lldb_private::ValueObject>(std::move(pointer)) {
+    assert(pointer);
+  }
+
+  static std::optional<ValueObjectSP>
+  createFromSP(std::shared_ptr<lldb_private::ValueObject> &&pointer) {
+    if (!pointer)
+      return {};
+    return ValueObjectSP(std::move(pointer));
+  }
+};
 typedef std::shared_ptr<lldb_private::Value> ValueSP;
 typedef std::shared_ptr<lldb_private::Variable> VariableSP;
 typedef std::shared_ptr<lldb_private::VariableList> VariableListSP;
diff --git a/lldb/source/Core/ValueObject.cpp b/lldb/source/Core/ValueObject.cpp
index a7f7ee64282d89..41fd43e579f5cb 100644
--- a/lldb/source/Core/ValueObject.cpp
+++ b/lldb/source/Core/ValueObject.cpp
@@ -372,8 +372,8 @@ bool ValueObject::IsLogicalTrue(Status &error) {
   return ret;
 }
 
-ValueObjectSP ValueObject::GetChildAtIndex(size_t idx, bool can_create) {
-  ValueObjectSP child_sp;
+std::optional<lldb::ValueObjectSP>
+ValueObject::GetChildAtIndex(size_t idx, bool can_create) {
   // We may need to update our value if we are dynamic
   if (IsPossibleDynamicType())
     UpdateValueIfNeeded(false);
@@ -389,54 +389,51 @@ ValueObjectSP ValueObject::GetChildAtIndex(size_t idx, bool can_create) {
     if (child != nullptr)
       return child->GetSP();
   }
-  return child_sp;
+  return {};
 }
 
-lldb::ValueObjectSP
+std::optional<lldb::ValueObjectSP>
 ValueObject::GetChildAtIndexPath(llvm::ArrayRef<size_t> idxs,
                                  size_t *index_of_error) {
-  if (idxs.size() == 0)
-    return GetSP();
-  ValueObjectSP root(GetSP());
+  lldb::ValueObjectSP value_object = GetSP();
   for (size_t idx : idxs) {
-    root = root->GetChildAtIndex(idx);
-    if (!root) {
+    auto child = value_object->GetChildAtIndex(idx);
+    if (!child) {
       if (index_of_error)
         *index_of_error = idx;
-      return root;
+      return {};
     }
+    value_object = child.value();
   }
-  return root;
+  return value_object;
 }
 
-lldb::ValueObjectSP ValueObject::GetChildAtIndexPath(
-  llvm::ArrayRef<std::pair<size_t, bool>> idxs, size_t *index_of_error) {
-  if (idxs.size() == 0)
-    return GetSP();
-  ValueObjectSP root(GetSP());
+std::optional<lldb::ValueObjectSP>
+ValueObject::GetChildAtIndexPath(llvm::ArrayRef<std::pair<size_t, bool>> idxs,
+                                 size_t *index_of_error) {
+  lldb::ValueObjectSP value_object = GetSP();
   for (std::pair<size_t, bool> idx : idxs) {
-    root = root->GetChildAtIndex(idx.first, idx.second);
-    if (!root) {
+    auto child = value_object->GetChildAtIndex(idx.first, idx.second);
+    if (!child) {
       if (index_of_error)
         *index_of_error = idx.first;
-      return root;
+      return {};
     }
+    value_object = child.value();
   }
-  return root;
+  return value_object;
 }
 
-lldb::ValueObjectSP
+std::optional<lldb::ValueObjectSP>
 ValueObject::GetChildAtNamePath(llvm::ArrayRef<llvm::StringRef> names) {
-  if (names.size() == 0)
-    return GetSP();
-  ValueObjectSP root(GetSP());
+  lldb::ValueObjectSP value_object = GetSP();
   for (llvm::StringRef name : names) {
-    root = root->GetChildMemberWithName(name);
-    if (!root) {
-      return root;
-    }
+    auto child = value_object->GetChildMemberWithName(name);
+    if (!child)
+      return {};
+    value_object = child.value();
   }
-  return root;
+  return value_object;
 }
 
 size_t ValueObject::GetIndexOfChildWithName(llvm::StringRef name) {
@@ -445,8 +442,8 @@ size_t ValueObject::GetIndexOfChildWithName(llvm::StringRef name) {
                                                    omit_empty_base_classes);
 }
 
-ValueObjectSP ValueObject::GetChildMemberWithName(llvm::StringRef name,
-                                                  bool can_create) {
+std::optional<lldb::ValueObjectSP>
+ValueObject::GetChildMemberWithName(llvm::StringRef name, bool can_create) {
   // We may need to update our value if we are dynamic.
   if (IsPossibleDynamicType())
     UpdateValueIfNeeded(false);
@@ -458,19 +455,21 @@ ValueObjectSP ValueObject::GetChildMemberWithName(llvm::StringRef name,
   bool omit_empty_base_classes = true;
 
   if (!GetCompilerType().IsValid())
-    return ValueObjectSP();
+    return {};
 
   const size_t num_child_indexes =
       GetCompilerType().GetIndexOfChildMemberWithName(
           name, omit_empty_base_classes, child_indexes);
   if (num_child_indexes == 0)
-    return nullptr;
+    return {};
 
-  ValueObjectSP child_sp = GetSP();
-  for (uint32_t idx : child_indexes)
-    if (child_sp)
-      child_sp = child_sp->GetChildAtIndex(idx, can_create);
-  return child_sp;
+  ValueObjectSP value_object = GetSP();
+  for (uint32_t idx : child_indexes) {
+    auto child = value_object->GetChildAtIndex(idx, can_create);
+    if (child)
+      value_object = child.value();
+  }
+  return value_object;
 }
 
 size_t ValueObject::GetNumChildren(uint32_t max) {
@@ -552,10 +551,10 @@ ValueObject *ValueObject::CreateChildAtIndex(size_t idx,
   // In case of an incomplete type, try to use the ValueObject's
   // synthetic value to create the child ValueObject.
   if (!valobj && synthetic_array_member) {
-    if (ValueObjectSP synth_valobj_sp = GetSyntheticValue()) {
-      valobj = synth_valobj_sp
-                   ->GetChildAtIndex(synthetic_index, synthetic_array_member)
-                   .get();
+    if (auto synth_valobj_sp = GetSyntheticValue()) {
+      auto child = synth_valobj_sp.value()->GetChildAtIndex(
+          synthetic_index, synthetic_array_member);
+      valobj = child.has_value() ? child->get() : nullptr;
     }
   }
 
@@ -673,17 +672,17 @@ size_t ValueObject::GetPointeeData(DataExtractor &data, uint32_t item_idx,
   if (item_idx == 0 && item_count == 1) // simply a deref
   {
     if (is_pointer_type) {
-      Status error;
-      ValueObjectSP pointee_sp = Dereference(error);
-      if (error.Fail() || pointee_sp.get() == nullptr)
+      ValueObjectSP pointee_sp = Dereference();
+      if (pointee_sp->GetError().Fail() || pointee_sp.get() == nullptr)
         return 0;
+      Status error;
       return pointee_sp->GetData(data, error);
     } else {
-      ValueObjectSP child_sp = GetChildAtIndex(0);
-      if (child_sp.get() == nullptr)
+      auto child = GetChildAtIndex(0);
+      if (!child)
         return 0;
       Status error;
-      return child_sp->GetData(data, error);
+      return child.value()->GetData(data, error);
     }
     return true;
   } else /* (items > 1) */
@@ -1218,12 +1217,12 @@ bool ValueObject::DumpPrintableRepresentation(
             if (low)
               s << ',';
 
-            ValueObjectSP child = GetChildAtIndex(low);
-            if (!child.get()) {
+            auto child = GetChildAtIndex(low);
+            if (!child) {
               s << "<invalid child>";
               continue;
             }
-            child->DumpPrintableRepresentation(
+            child.value()->DumpPrintableRepresentation(
                 s, ValueObject::eValueObjectRepresentationStyleValue,
                 custom_format);
           }
@@ -1259,12 +1258,12 @@ bool ValueObject::DumpPrintableRepresentation(
             if (low)
               s << ',';
 
-            ValueObjectSP child = GetChildAtIndex(low);
-            if (!child.get()) {
+            auto child = GetChildAtIndex(low);
+            if (!child) {
               s << "<invalid child>";
               continue;
             }
-            child->DumpPrintableRepresentation(
+            child.value()->DumpPrintableRepresentation(
                 s, ValueObject::eValueObjectRepresentationStyleValue, format);
           }
 
@@ -1556,13 +1555,13 @@ void ValueObject::AddSyntheticChild(ConstString key,
   m_synthetic_children[key] = valobj;
 }
 
-ValueObjectSP ValueObject::GetSyntheticChild(ConstString key) const {
-  ValueObjectSP synthetic_child_sp;
-  std::map<ConstString, ValueObject *>::const_iterator pos =
+std::optional<lldb::ValueObjectSP>
+ValueObject::GetSyntheticChild(ConstString key) const {
+  std::map<ConstString, ValueObject *>::const_iterator position =
       m_synthetic_children.find(key);
-  if (pos != m_synthetic_children.end())
-    synthetic_child_sp = pos->second->GetSP();
-  return synthetic_child_sp;
+  if (position != m_synthetic_children.end())
+    return {};
+  return position->second->GetSP();
 }
 
 bool ValueObject::IsPossibleDynamicType() {
@@ -1614,83 +1613,86 @@ bool ValueObject::IsUninitializedReference() {
 // The size of the "item_array" is 1, but many times in practice there are more
 // items in "item_array".
 
-ValueObjectSP ValueObject::GetSyntheticArrayMember(size_t index,
-                                                   bool can_create) {
-  ValueObjectSP synthetic_child_sp;
-  if (IsPointerType() || IsArrayType()) {
-    std::string index_str = llvm::formatv("[{0}]", index);
-    ConstString index_const_str(index_str);
-    // Check if we have already created a synthetic array member in this valid
-    // object. If we have we will re-use it.
-    synthetic_child_sp = GetSyntheticChild(index_const_str);
-    if (!synthetic_child_sp) {
-      ValueObject *synthetic_child;
-      // We haven't made a synthetic array member for INDEX yet, so lets make
-      // one and cache it for any future reference.
-      synthetic_child = CreateChildAtIndex(0, true, index);
-
-      // Cache the value if we got one back...
-      if (synthetic_child) {
-        AddSyntheticChild(index_const_str, synthetic_child);
-        synthetic_child_sp = synthetic_child->GetSP();
-        synthetic_child_sp->SetName(ConstString(index_str));
-        synthetic_child_sp->m_flags.m_is_array_item_for_pointer = true;
-      }
-    }
+std::optional<lldb::ValueObjectSP>
+ValueObject::GetSyntheticArrayMember(size_t index, bool can_create) {
+  if (!IsPointerType() && !IsArrayType()) {
+    return {};
   }
+
+  std::string index_str = llvm::formatv("[{0}]", index);
+  ConstString index_const_str(index_str);
+  // Check if we have already created a synthetic array member in this valid
+  // object. If we have we will re-use it.
+  if (auto existing_synthetic_child = GetSyntheticChild(index_const_str)) {
+    return existing_synthetic_child;
+  }
+
+  // We haven't made a synthetic array member for INDEX yet, so lets make
+  // one and cache it for any future reference.
+  ValueObject *synthetic_child = CreateChildAtIndex(0, true, index);
+
+  if (!synthetic_child) {
+    return {};
+  }
+
+  // Cache the value if we got one back...
+  AddSyntheticChild(index_const_str, synthetic_child);
+  auto synthetic_child_sp = synthetic_child->GetSP();
+  synthetic_child_sp->SetName(ConstString(index_str));
+  synthetic_child_sp->m_flags.m_is_array_item_for_pointer = true;
   return synthetic_child_sp;
 }
 
-ValueObjectSP ValueObject::GetSyntheticBitFieldChild(uint32_t from, uint32_t to,
-                                                     bool can_create) {
-  ValueObjectSP synthetic_child_sp;
-  if (IsScalarType()) {
-    std::string index_str = llvm::formatv("[{0}-{1}]", from, to);
-    ConstString index_const_str(index_str);
-    // Check if we have already created a synthetic array member in this valid
-    // object. If we have we will re-use it.
-    synthetic_child_sp = GetSyntheticChild(index_const_str);
-    if (!synthetic_child_sp) {
-      uint32_t bit_field_size = to - from + 1;
-      uint32_t bit_field_offset = from;
-      if (GetDataExtractor().GetByteOrder() == eByteOrderBig)
-        bit_field_offset =
-            GetByteSize().value_or(0) * 8 - bit_field_size - bit_field_offset;
-      // We haven't made a synthetic array member for INDEX yet, so lets make
-      // one and cache it for any future reference.
-      ValueObjectChild *synthetic_child = new ValueObjectChild(
-          *this, GetCompilerType(), index_const_str, GetByteSize().value_or(0),
-          0, bit_field_size, bit_field_offset, false, false,
-          eAddressTypeInvalid, 0);
-
-      // Cache the value if we got one back...
-      if (synthetic_child) {
-        AddSyntheticChild(index_const_str, synthetic_child);
-        synthetic_child_sp = synthetic_child->GetSP();
-        synthetic_child_sp->SetName(ConstString(index_str));
-        synthetic_child_sp->m_flags.m_is_bitfield_for_scalar = true;
-      }
-    }
+std::optional<lldb::ValueObjectSP>
+ValueObject::GetSyntheticBitFieldChild(uint32_t from, uint32_t to,
+                                       bool can_create) {
+  if (!IsScalarType()) {
+    return {};
+  }
+  std::string index_str = llvm::formatv("[{0}-{1}]", from, to);
+  ConstString index_const_str(index_str);
+
+  // Check if we have already created a synthetic array member in this valid
+  // object. If we have we will re-use it.
+  if (auto existing_synthetic_child = GetSyntheticChild(index_const_str)) {
+    return existing_synthetic_child;
   }
+
+  uint32_t bit_field_size = to - from + 1;
+  uint32_t bit_field_offset = from;
+  if (GetDataExtractor().GetByteOrder() == eByteOrderBig)
+    bit_field_offset =
+        GetByteSize().value_or(0) * 8 - bit_field_size - bit_field_offset;
+
+  // We haven't made a synthetic array member for INDEX yet, so lets make
+  // one and cache it for any future reference.
+  ValueObjectChild *synthetic_child = new ValueObjectChild(
+      *this, GetCompilerType(), index_const_str, GetByteSize().value_or(0), 0,
+      bit_field_size, bit_field_offset, false, false, eAddressTypeInvalid, 0);
+
+  // Cache the value if we got one back...
+  if (!synthetic_child)
+    return {};
+
+  AddSyntheticChild(index_const_str, synthetic_child);
+  auto synthetic_child_sp = synthetic_child->GetSP();
+  synthetic_child_sp->SetName(ConstString(index_str));
+  synthetic_child_sp->m_flags.m_is_bitfield_for_scalar = true;
   return synthetic_child_sp;
 }
 
-ValueObjectSP ValueObject::GetSyntheticChildAtOffset(
+std::optional<lldb::ValueObjectSP> ValueObject::GetSyntheticChildAtOffset(
     uint32_t offset, const CompilerType &type, bool can_create,
     ConstString name_const_str) {
 
-  ValueObjectSP synthetic_child_sp;
-
   if (name_const_str.IsEmpty()) {
     name_const_str.SetString("@" + std::to_string(offset));
   }
 
   // Check if we have already created a synthetic array member in this valid
   // object. If we have we will re-use it.
-  synthetic_child_sp = GetSyntheticChild(name_const_str);
-
-  if (synthetic_child_sp.get())
-    return synthetic_child_sp;
+  if (auto existing_synthetic_child = GetSyntheticChild(name_const_str))
+    return existing_synthetic_child;
 
   if (!can_create)
     return {};
@@ -1703,21 +1705,19 @@ ValueObjectSP ValueObject::GetSyntheticChildAtOffset(
   ValueObjectChild *synthetic_child =
       new ValueObjectChild(*this, type, name_const_str, *size, offset, 0, 0,
                            false, false, eAddressTypeInvalid, 0);
-  if (synthetic_child) {
-    AddSyntheticChild(name_const_str, synthetic_child);
-    synthetic_child_sp = synthetic_child->GetSP();
-    synthetic_child_sp->SetName(name_const_str);
-    synthetic_child_sp->m_flags.m_is_child_at_offset = true;
-  }
+  if (!synthetic_child)
+    return {};
+
+  AddSyntheticChild(name_const_str, synthetic_child);
+  auto synthetic_child_sp = synthetic_child->GetSP();
+  synthetic_child_sp->SetName(name_const_str);
+  synthetic_child_sp->m_flags.m_is_child_at_offset = true;
   return synthetic_child_sp;
 }
 
-ValueObjectSP ValueObject::GetSyntheticBase(uint32_t offset,
-                                            const CompilerType &type,
-                                            bool can_create,
-                                            ConstString name_const_str) {
-  ValueObjectSP synthetic_child_sp;
-
+std::optional<lldb::ValueObjectSP>
+ValueObject::GetSyntheticBase(uint32_t offset, const CompilerType &type,
+                              bool can_create, ConstString name_const_str) {
   if (name_const_str.IsEmpty()) {
     char name_str[128];
     snprintf(name_str, sizeof(name_str), "base%s@%i",
@@ -1727,10 +1727,8 @@ ValueObjectSP ValueObject::GetSyntheticBase(uint32_t offset,
 
   // Check if we have already created a synthetic array member in this valid
   // object. If we have we will re-use it.
-  synthetic_child_sp = GetSyntheticChild(name_const_str);
-
-  if (synthetic_child_sp.get())
-    return synthetic_child_sp;
+  if (auto existing_synthetic_child = GetSyntheticChild(name_const_str))
+    return existing_synthetic_child;
 
   if (!can_create)
     return {};
@@ -1745,11 +1743,12 @@ ValueObjectSP ValueObject::GetSyntheticBase(uint32_t offset,
   ValueObjectChild *synthetic_child =
       new ValueObjectChild(*this, type, name_const_str, *size, offset, 0, 0,
                            is_base_class, false, eAddressTypeInvalid, 0);
-  if (synthetic_child) {
-    AddSyntheticChild(name_const_str, synthetic_child);
-    synthetic_child_sp = synthetic_child->GetSP();
-    synthetic_child_sp->SetName(name_const_str);
-  }
+  if (!synthetic_child)
+    return {};
+
+  AddSyntheticChild(name_const_str, synthetic_child);
+  auto synthetic_child_sp = synthetic_child->GetSP();
+  synthetic_child_sp->SetName(name_const_str);
   return synthetic_child_sp;
 }
 
@@ -1767,33 +1766,33 @@ static const char *SkipLeadingExpressionPathSeparators(const char *expression) {
   return expression;
 }
 
-ValueObjectSP
+std::optional<lldb::ValueObjectSP>
 ValueObject::GetSyntheticExpressionPathChild(const char *expression,
                                              bool can_create) {
-  ValueObjectSP synthetic_child_sp;
   ConstString name_const_string(expression);
   // Check if we have already created a synthetic array member in this valid
   // object. If we have we will re-use it.
-  synthetic_child_sp = GetSyntheticChild(name_const_string);
-  if (!synthetic_child_sp) {
-    // We haven't made a synthetic array member for expression yet, so lets
-    // make one and cache it for any future reference.
-    synthetic_child_sp = GetValueForExpressionPath(
-        expression, nullptr, nullptr,
-        GetValueForExpressionPathOptions().SetSyntheticChildrenTraversal(
-            GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
-                None));
-
-    // Cache the value if we got one back...
-    if (synthetic_child_sp.get()) {
-      // FIXME: this causes a "real" child to end up with its name changed to
-      // the contents of expression
-      AddSyntheticChild(name_const_string, synthetic_child_sp.get());
-      synthetic_child_sp->SetName(
-          ConstString(SkipLeadingExpressionPathSeparators(expression)));
-    }
+  if (auto existing_synthetic_child = GetSyntheticChild(name_const_string))
+    return existing_synthetic_child;
+
+  // We haven't made a synthetic array member for expression yet, so lets
+  // make one and cache it for any future reference.
+  auto path_options = GetValueForExpressionPathOptions();
+  auto traversal_none =
+      GetValueForExpressionPathOptions::SyntheticChildrenTraversal::None;
+  path_options.SetSyntheticChildrenTraversal(traversal_none);
+  auto synthetic_child =
+      GetValueForExpressionPath(expression, nullptr, nullptr, path_options);
+
+  // Cache the value if we got one back...
+  if (synthetic_child) {
+    // FIXME: this causes a "real" child to end up with its name changed to
+    // the contents of expression
+    AddSyntheticChild(name_const_string, synthetic_child->get());
+    synthetic_child.value()->SetName(
+        ConstString(SkipLeadingExpressionPathSeparators(expression)));
   }
-  return synthetic_child_sp;
+  return synthetic_child;
 }
 
 void ValueObject::CalculateSyntheticValue() {
@@ -1831,9 +1830,10 @@ void ValueObject::CalculateDynamicValue(DynamicValueType use_dynamic) {
   }
 }
 
-ValueObjectSP ValueObject::GetDynamicValue(DynamicValueType use_dynamic) {
+std::optional<lldb::ValueObjectSP>
+ValueObject::GetDynamicValue(DynamicValueType use_dynamic) {
   if (use_dynamic == eNoDynamicValues)
-    return ValueObjectSP();
+    return {};
 
   if (!IsDynamic() && m_dynamic_value == nullptr) {
     CalculateDynamicValue(use_dynamic);
@@ -1841,16 +1841,16 @@ ValueObjectSP ValueObject::GetDynamicValue(DynamicValueType use_dynamic) {
   if (m_dynamic_value && m_dynamic_value->GetError().Success())
     return m_dynamic_value->GetSP();
   else
-    return ValueObjectSP();
+    return {};
 }
 
-ValueObjectSP ValueObject::GetSyntheticValue() {
+std::optional<lldb::ValueObjectSP> ValueObject::GetSyntheticValue() {
   CalculateSyntheticValue();
 
   if (m_synthetic_value)
     return m_synthetic_value->GetSP();
   else
-    return ValueObjectSP();
+    return {};
 }
 
 bool ValueObject::HasSyntheticValue() {
@@ -1984,84 +1984,75 @@ void ValueObject::GetExpressionPath(Stream &s,
   }
 }
 
-ValueObjectSP ValueObject::GetValueForExpressionPath(
-    llvm::StringRef expression, ExpressionPathScanEndReason *reason_to_stop,
-    ExpressionPathEndResultType *final_value_type,
+std::optional<lldb::ValueObjectSP> ValueObject::GetValueForExpressionPath(
+    llvm::StringRef expression, ExpressionPathScanEndReason *reason_to_stop_ptr,
+    ExpressionPathEndResultType *final_value_type_ptr,
     const GetValueForExpressionPathOptions &options,
-    ExpressionPathAftermath *final_task_on_target) {
-
-  ExpressionPathScanEndReason dummy_reason_to_stop =
-      ValueObject::eExpressionPathScanEndReasonUnknown;
-  ExpressionPathEndResultType dummy_final_value_type =
-      ValueObject::eExpressionPathEndResultTypeInvalid;
-  ExpressionPathAftermath dummy_final_task_on_target =
-      ValueObject::eExpressionPathAftermathNothing;
-
-  ValueObjectSP ret_val = GetValueForExpressionPath_Impl(
-      expression, reason_to_stop ? reason_to_stop : &dummy_reason_to_stop,
-      final_value_type ? final_value_type : &dummy_final_value_type, options,
-      final_task_on_target ? final_task_on_target
-                           : &dummy_final_task_on_target);
-
-  if (!final_task_on_target ||
-      *final_task_on_target == ValueObject::eExpressionPathAftermathNothing)
-    return ret_val;
-
-  if (ret_val.get() &&
-      ((final_value_type ? *final_value_type : dummy_final_value_type) ==
-       eExpressionPathEndResultTypePlain)) // I can only deref and takeaddress
-                                           // of plain objects
-  {
-    if ((final_task_on_target ? *final_task_on_target
-                              : dummy_final_task_on_target) ==
-        ValueObject::eExpressionPathAftermathDereference) {
-      Status error;
-      ValueObjectSP final_value = ret_val->Dereference(error);
-      if (error.Fail() || !final_value.get()) {
-        if (reason_to_stop)
-          *reason_to_stop =
-              ValueObject::eExpressionPathScanEndReasonDereferencingFailed;
-        if (final_value_type)
-          *final_value_type = ValueObject::eExpressionPathEndResultTypeInvalid;
-        return ValueObjectSP();
-      } else {
-        if (final_task_on_target)
-          *final_task_on_target = ValueObject::eExpressionPathAftermathNothing;
-        return final_value;
-      }
-    }
-    if (*final_task_on_target ==
-        ValueObject::eExpressionPathAftermathTakeAddress) {
-      Status error;
-      ValueObjectSP final_value = ret_val->AddressOf(error);
-      if (error.Fail() || !final_value.get()) {
-        if (reason_to_stop)
-          *reason_to_stop =
-              ValueObject::eExpressionPathScanEndReasonTakingAddressFailed;
-        if (final_value_type)
-          *final_value_type = ValueObject::eExpressionPathEndResultTypeInvalid;
-        return ValueObjectSP();
-      } else {
-        if (final_task_on_target)
-          *final_task_on_target = ValueObject::eExpressionPathAftermathNothing;
-        return final_value;
-      }
-    }
+    ExpressionPathAftermath *final_task_on_target_ptr) {
+
+  auto stop_reason_unknown = eExpressionPathScanEndReasonUnknown;
+  auto value_type_invalid = eExpressionPathEndResultTypeInvalid;
+  auto final_task_nothing = eExpressionPathAftermathNothing;
+
+  auto ret_value = GetValueForExpressionPath_Impl(
+      expression,
+      reason_to_stop_ptr ? reason_to_stop_ptr : &stop_reason_unknown,
+      final_value_type_ptr ? final_value_type_ptr : &value_type_invalid,
+      options,
+      final_task_on_target_ptr ? final_task_on_target_ptr
+                               : &final_task_nothing);
+
+  // The caller knows that nothing happened because `final_task_on_target` still
+  // has its original value.
+  if (!ret_value)
+    return {};
+
+  if (!final_value_type_ptr)
+    return ret_value;
+
+  if ((*final_value_type_ptr) != eExpressionPathEndResultTypePlain)
+    return ret_value;
+
+  if (!final_task_on_target_ptr)
+    return ret_value;
+
+  ExpressionPathAftermath &final_task_on_target = (*final_task_on_target_ptr);
+  ExpressionPathScanEndReason stop_reason_for_error;
+  // The method can only dereference and take the address of plain objects.
+  switch (final_task_on_target) {
+  case eExpressionPathAftermathNothing: {
+    return ret_value;
+  }
+  case eExpressionPathAftermathDereference: {
+    ret_value = ret_value.value()->Dereference();
+    stop_reason_for_error = eExpressionPathScanEndReasonDereferencingFailed;
+  }
+  case eExpressionPathAftermathTakeAddress: {
+    ret_value = ret_value.value()->AddressOf();
+    stop_reason_for_error = eExpressionPathScanEndReasonTakingAddressFailed;
+  }
+  }
+
+  if (ret_value && ret_value.value()->GetError().Success()) {
+    final_task_on_target = eExpressionPathAftermathNothing;
+    return ret_value;
+  } else {
+    if (reason_to_stop_ptr)
+      *reason_to_stop_ptr = stop_reason_for_error;
+
+    if (final_value_type_ptr)
+      *final_value_type_ptr = eExpressionPathEndResultTypeInvalid;
+    return {};
   }
-  return ret_val; // final_task_on_target will still have its original value, so
-                  // you know I did not do it
 }
 
-ValueObjectSP ValueObject::GetValueForExpressionPath_Impl(
+std::optional<lldb::ValueObjectSP> ValueObject::GetValueForExpressionPath_Impl(
     llvm::StringRef expression, ExpressionPathScanEndReason *reason_to_stop,
     ExpressionPathEndResultType *final_result,
     const GetValueForExpressionPathOptions &options,
     ExpressionPathAftermath *what_next) {
   ValueObjectSP root = GetSP();
 
-  if (!root)
-    return nullptr;
-
   llvm::StringRef remainder = expression;
 
   while (true) {
@@ -2093,7 +2084,7 @@ ValueObjectSP ValueObject::GetValueForExpressionPath_Impl(
         *reason_to_stop =
             ValueObject::eExpressionPathScanEndReasonArrowInsteadOfDot;
         *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
-        return ValueObjectSP();
+        return {};
       }
       if (root_compiler_type_info.Test(eTypeIsObjC) && // if yo are trying to
                                                        // extract an ObjC IVar
@@ -2103,13 +2094,13 @@ ValueObjectSP ValueObject::GetValueForExpressionPath_Impl(
         *reason_to_stop =
             ValueObject::eExpressionPathScanEndReasonFragileIVarNotAllowed;
         *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
-        return ValueObjectSP();
+        return {};
       }
       if (!temp_expression.startswith(">")) {
         *reason_to_stop =
             ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol;
         *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
-        return ValueObjectSP();
+        return {};
       }
     }
       [[fallthrough]];
@@ -2125,7 +2116,7 @@ ValueObjectSP ValueObject::GetValueForExpressionPath_Impl(
         *reason_to_stop =
             ValueObject::eExpressionPathScanEndReasonDotInsteadOfArrow;
         *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
-        return nullptr;
+        return {};
       }
       temp_expression = temp_expression.drop_front(); // skip . or >
 
@@ -2134,15 +2125,14 @@ ValueObjectSP ValueObject::GetValueForExpressionPath_Impl(
                                                  // expand this last layer
       {
         llvm::StringRef child_name = temp_expression;
-        ValueObjectSP child_valobj_sp =
-            root->GetChildMemberWithName(child_name);
 
-        if (child_valobj_sp.get()) // we know we are done, so just return
-        {
+        auto child = root->GetChildMemberWithName(child_name);
+        if (child) {
+          // we know we are done, so just return
           *reason_to_stop =
               ValueObject::eExpressionPathScanEndReasonEndOfString;
           *final_result = ValueObject::eExpressionPathEndResultTypePlain;
-          return child_valobj_sp;
+          return child;
         } else {
           switch (options.m_synthetic_children_traversal) {
           case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
@@ -2151,33 +2141,29 @@ ValueObjectSP ValueObject::GetValueForExpressionPath_Impl(
           case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
               FromSynthetic:
             if (root->IsSynthetic()) {
-              child_valobj_sp = root->GetNonSyntheticValue();
-              if (child_valobj_sp.get())
-                child_valobj_sp =
-                    child_valobj_sp->GetChildMemberWithName(child_name);
+              child = root->GetNonSyntheticValue();
+              if (child)
+                child = child.value()->GetChildMemberWithName(child_name);
             }
             break;
           case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
               ToSynthetic:
             if (!root->IsSynthetic()) {
-              child_valobj_sp = root->GetSyntheticValue();
-              if (child_valobj_sp.get())
-                child_valobj_sp =
-                    child_valobj_sp->GetChildMemberWithName(child_name);
+              child = root->GetSyntheticValue();
+              if (child)
+                child = child.value()->GetChildMemberWithName(child_name);
             }
             break;
           case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
               Both:
             if (root->IsSynthetic()) {
-              child_valobj_sp = root->GetNonSyntheticValue();
-              if (child_valobj_sp.get())
-                child_valobj_sp =
-                    child_valobj_sp->GetChildMemberWithName(child_name);
+              child = root->GetNonSyntheticValue();
+              if (child)
+                child = child.value()->GetChildMemberWithName(child_name);
             } else {
-              child_valobj_sp = root->GetSyntheticValue();
-              if (child_valobj_sp.get())
-                child_valobj_sp =
-                    child_valobj_sp->GetChildMemberWithName(child_name);
+              child = root->GetSyntheticValue();
+              if (child)
+                child = child.value()->GetChildMemberWithName(child_name);
             }
             break;
           }
@@ -2186,28 +2172,27 @@ ValueObjectSP ValueObject::GetValueForExpressionPath_Impl(
         // if we are here and options.m_no_synthetic_children is true,
         // child_valobj_sp is going to be a NULL SP, so we hit the "else"
         // branch, and return an error
-        if (child_valobj_sp.get()) // if it worked, just return
+        if (child) // if it worked, just return
         {
           *reason_to_stop =
               ValueObject::eExpressionPathScanEndReasonEndOfString;
           *final_result = ValueObject::eExpressionPathEndResultTypePlain;
-          return child_valobj_sp;
+          return child;
         } else {
           *reason_to_stop =
               ValueObject::eExpressionPathScanEndReasonNoSuchChild;
           *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
-          return nullptr;
+          return {};
         }
       } else // other layers do expand
       {
         llvm::StringRef next_separator = temp_expression.substr(next_sep_pos);
         llvm::StringRef child_name = temp_expression.slice(0, next_sep_pos);
 
-        ValueObjectSP child_valobj_sp =
-            root->GetChildMemberWithName(child_name);
-        if (child_valobj_sp.get()) // store the new root and move on
+        auto child = root->GetChildMemberWithName(child_name);
+        if (child) // store the new root and move on
         {
-          root = child_valobj_sp;
+          root = child.value();
           remainder = next_separator;
           *final_result = ValueObject::eExpressionPathEndResultTypePlain;
           continue;
@@ -2219,33 +2204,29 @@ ValueObjectSP ValueObject::GetValueForExpressionPath_Impl(
           case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
               FromSynthetic:
             if (root->IsSynthetic()) {
-              child_valobj_sp = root->GetNonSyntheticValue();
-              if (child_valobj_sp.get())
-                child_valobj_sp =
-                    child_valobj_sp->GetChildMemberWithName(child_name);
+              child = root->GetNonSyntheticValue();
+              if (child)
+                child = child.value()->GetChildMemberWithName(child_name);
             }
             break;
           case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
               ToSynthetic:
             if (!root->IsSynthetic()) {
-              child_valobj_sp = root->GetSyntheticValue();
-              if (child_valobj_sp.get())
-                child_valobj_sp =
-                    child_valobj_sp->GetChildMemberWithName(child_name);
+              child = root->GetSyntheticValue();
+              if (child)
+                child = child.value()->GetChildMemberWithName(child_name);
             }
             break;
           case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
               Both:
             if (root->IsSynthetic()) {
-              child_valobj_sp = root->GetNonSyntheticValue();
-              if (child_valobj_sp.get())
-                child_valobj_sp =
-                    child_valobj_sp->GetChildMemberWithName(child_name);
+              child = root->GetNonSyntheticValue();
+              if (child)
+                child = child.value()->GetChildMemberWithName(child_name);
             } else {
-              child_valobj_sp = root->GetSyntheticValue();
-              if (child_valobj_sp.get())
-                child_valobj_sp =
-                    child_valobj_sp->GetChildMemberWithName(child_name);
+              child = root->GetSyntheticValue();
+              if (child)
+                child = child.value()->GetChildMemberWithName(child_name);
             }
             break;
           }
@@ -2254,9 +2235,9 @@ ValueObjectSP ValueObject::GetValueForExpressionPath_Impl(
         // if we are here and options.m_no_synthetic_children is true,
         // child_valobj_sp is going to be a NULL SP, so we hit the "else"
         // branch, and return an error
-        if (child_valobj_sp.get()) // if it worked, move on
+        if (child) // if it worked, move on
         {
-          root = child_valobj_sp;
+          root = child.value();
           remainder = next_separator;
           *final_result = ValueObject::eExpressionPathEndResultTypePlain;
           continue;
@@ -2264,7 +2245,7 @@ ValueObjectSP ValueObject::GetValueForExpressionPath_Impl(
           *reason_to_stop =
               ValueObject::eExpressionPathScanEndReasonNoSuchChild;
           *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
-          return nullptr;
+          return {};
         }
       }
       break;
@@ -2285,7 +2266,7 @@ ValueObjectSP ValueObject::GetValueForExpressionPath_Impl(
             *reason_to_stop =
                 ValueObject::eExpressionPathScanEndReasonRangeOperatorInvalid;
             *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
-            return ValueObjectSP();
+            return {};
           }
         } else if (!options.m_allow_bitfields_syntax) // if this is a scalar,
                                                       // check that we can
@@ -2294,7 +2275,7 @@ ValueObjectSP ValueObject::GetValueForExpressionPath_Impl(
           *reason_to_stop =
               ValueObject::eExpressionPathScanEndReasonRangeOperatorNotAllowed;
           *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
-          return ValueObjectSP();
+          return {};
         }
       }
       if (temp_expression[1] ==
@@ -2304,7 +2285,7 @@ ValueObjectSP ValueObject::GetValueForExpressionPath_Impl(
           *reason_to_stop =
               ValueObject::eExpressionPathScanEndReasonEmptyRangeNotAllowed;
           *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
-          return nullptr;
+          return {};
         } else // even if something follows, we cannot expand unbounded ranges,
                // just let the caller do it
         {
@@ -2323,7 +2304,7 @@ ValueObjectSP ValueObject::GetValueForExpressionPath_Impl(
         *reason_to_stop =
             ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol;
         *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
-        return nullptr;
+        return {};
       }
 
       llvm::StringRef bracket_expr =
@@ -2342,21 +2323,23 @@ ValueObjectSP ValueObject::GetValueForExpressionPath_Impl(
           *reason_to_stop =
               ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol;
           *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
-          return nullptr;
+          return {};
         }
 
         // from here on we do have a valid index
         if (root_compiler_type_info.Test(eTypeIsArray)) {
-          ValueObjectSP child_valobj_sp = root->GetChildAtIndex(index);
-          if (!child_valobj_sp)
-            child_valobj_sp = root->GetSyntheticArrayMember(index, true);
-          if (!child_valobj_sp)
+          auto child = root->GetChildAtIndex(index);
+          if (!child)
+            child = root->GetSyntheticArrayMember(index, true);
+          if (!child)
             if (root->HasSyntheticValue() &&
-                root->GetSyntheticValue()->GetNumChildren() > index)
-              child_valobj_sp =
-                  root->GetSyntheticValue()->GetChildAtIndex(index);
-          if (child_valobj_sp) {
-            root = child_valobj_sp;
+                root->GetSyntheticValue().value()->GetNumChildren() > index)
+              child = root->GetSyntheticValue()
+                          .value()
+                          ->GetChildAtIndex(index)
+                          .value();
+          if (child) {
+            root = child.value();
             remainder =
                 temp_expression.substr(close_bracket_position + 1); // skip ]
             *final_result = ValueObject::eExpressionPathEndResultTypePlain;
@@ -2365,7 +2348,7 @@ ValueObjectSP ValueObject::GetValueForExpressionPath_Impl(
             *reason_to_stop =
                 ValueObject::eExpressionPathScanEndReasonNoSuchChild;
             *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
-            return nullptr;
+            return {};
           }
         } else if (root_compiler_type_info.Test(eTypeIsPointer)) {
           if (*what_next ==
@@ -2380,18 +2363,18 @@ ValueObjectSP ValueObject::GetValueForExpressionPath_Impl(
                                                              // and use this as
                                                              // a bitfield
               pointee_compiler_type_info.Test(eTypeIsScalar)) {
-            Status error;
-            root = root->Dereference(error);
-            if (error.Fail() || !root) {
+            root = root->Dereference();
+            if (root->GetError().Fail()) {
               *reason_to_stop =
                   ValueObject::eExpressionPathScanEndReasonDereferencingFailed;
               *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
-              return nullptr;
+              return {};
             } else {
               *what_next = eExpressionPathAftermathNothing;
               continue;
             }
           } else {
+            std::optional<lldb::ValueObjectSP> child;
             if (root->GetCompilerType().GetMinimumLanguage() ==
                     eLanguageTypeObjC &&
                 pointee_compiler_type_info.AllClear(eTypeIsPointer) &&
@@ -2402,15 +2385,16 @@ ValueObjectSP ValueObject::GetValueForExpressionPath_Impl(
                  options.m_synthetic_children_traversal ==
                      GetValueForExpressionPathOptions::
                          SyntheticChildrenTraversal::Both)) {
-              root = root->GetSyntheticValue()->GetChildAtIndex(index);
+              child = root->GetSyntheticValue().value()->GetChildAtIndex(index);
             } else
-              root = root->GetSyntheticArrayMember(index, true);
-            if (!root) {
+              child = root->GetSyntheticArrayMember(index, true);
+            if (!child) {
               *reason_to_stop =
                   ValueObject::eExpressionPathScanEndReasonNoSuchChild;
               *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
-              return nullptr;
+              return {};
             } else {
+              root = child.value();
               remainder =
                   temp_expression.substr(close_bracket_position + 1); // skip ]
               *final_result = ValueObject::eExpressionPathEndResultTypePlain;
@@ -2418,28 +2402,30 @@ ValueObjectSP ValueObject::GetValueForExpressionPath_Impl(
             }
           }
         } else if (root_compiler_type_info.Test(eTypeIsScalar)) {
-          root = root->GetSyntheticBitFieldChild(index, index, true);
-          if (!root) {
+          auto child = root->GetSyntheticBitFieldChild(index, index, true);
+          if (!child) {
             *reason_to_stop =
                 ValueObject::eExpressionPathScanEndReasonNoSuchChild;
             *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
-            return nullptr;
+            return {};
           } else // we do not know how to expand members of bitfields, so we
                  // just return and let the caller do any further processing
           {
+            root = child.value();
             *reason_to_stop = ValueObject::
                 eExpressionPathScanEndReasonBitfieldRangeOperatorMet;
             *final_result = ValueObject::eExpressionPathEndResultTypeBitfield;
             return root;
           }
         } else if (root_compiler_type_info.Test(eTypeIsVector)) {
-          root = root->GetChildAtIndex(index);
-          if (!root) {
+          auto child = root->GetChildAtIndex(index);
+          if (!child) {
             *reason_to_stop =
                 ValueObject::eExpressionPathScanEndReasonNoSuchChild;
             *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
-            return ValueObjectSP();
+            return {};
           } else {
+            root = child.value();
             remainder =
                 temp_expression.substr(close_bracket_position + 1); // skip ]
             *final_result = ValueObject::eExpressionPathEndResultTypePlain;
@@ -2452,29 +2438,24 @@ ValueObjectSP ValueObject::GetValueForExpressionPath_Impl(
                        GetValueForExpressionPathOptions::
                            SyntheticChildrenTraversal::Both) {
           if (root->HasSyntheticValue())
-            root = root->GetSyntheticValue();
+            root = root->GetSyntheticValue().value();
           else if (!root->IsSynthetic()) {
             *reason_to_stop =
                 ValueObject::eExpressionPathScanEndReasonSyntheticValueMissing;
             *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
-            return nullptr;
+            return {};
           }
           // if we are here, then root itself is a synthetic VO.. should be
           // good to go
 
-          if (!root) {
-            *reason_to_stop =
-                ValueObject::eExpressionPathScanEndReasonSyntheticValueMissing;
-            *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
-            return nullptr;
-          }
-          root = root->GetChildAtIndex(index);
-          if (!root) {
+          auto child = root->GetChildAtIndex(index);
+          if (!child) {
             *reason_to_stop =
                 ValueObject::eExpressionPathScanEndReasonNoSuchChild;
             *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
-            return nullptr;
+            return {};
           } else {
+            root = child.value();
             remainder =
                 temp_expression.substr(close_bracket_position + 1); // skip ]
             *final_result = ValueObject::eExpressionPathEndResultTypePlain;
@@ -2484,7 +2465,7 @@ ValueObjectSP ValueObject::GetValueForExpressionPath_Impl(
           *reason_to_stop =
               ValueObject::eExpressionPathScanEndReasonNoSuchChild;
           *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
-          return nullptr;
+          return {};
         }
       } else {
         // we have a low and a high index
@@ -2496,7 +2477,7 @@ ValueObjectSP ValueObject::GetValueForExpressionPath_Impl(
           *reason_to_stop =
               ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol;
           *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
-          return nullptr;
+          return {};
         }
 
         if (low_index > high_index) // swap indices if required
@@ -2505,13 +2486,15 @@ ValueObjectSP ValueObject::GetValueForExpressionPath_Impl(
         if (root_compiler_type_info.Test(
                 eTypeIsScalar)) // expansion only works for scalars
         {
-          root = root->GetSyntheticBitFieldChild(low_index, high_index, true);
-          if (!root) {
+          auto child =
+              root->GetSyntheticBitFieldChild(low_index, high_index, true);
+          if (!child) {
             *reason_to_stop =
                 ValueObject::eExpressionPathScanEndReasonNoSuchChild;
             *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
-            return nullptr;
+            return {};
           } else {
+            root = child.value();
             *reason_to_stop = ValueObject::
                 eExpressionPathScanEndReasonBitfieldRangeOperatorMet;
             *final_result = ValueObject::eExpressionPathEndResultTypeBitfield;
@@ -2526,12 +2509,12 @@ ValueObjectSP ValueObject::GetValueForExpressionPath_Impl(
                        ValueObject::eExpressionPathAftermathDereference &&
                    pointee_compiler_type_info.Test(eTypeIsScalar)) {
           Status error;
-          root = root->Dereference(error);
-          if (error.Fail() || !root) {
+          root = root->Dereference();
+          if (root->GetError().Fail()) {
             *reason_to_stop =
                 ValueObject::eExpressionPathScanEndReasonDereferencingFailed;
             *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
-            return nullptr;
+            return {};
           } else {
             *what_next = ValueObject::eExpressionPathAftermathNothing;
             continue;
@@ -2550,7 +2533,7 @@ ValueObjectSP ValueObject::GetValueForExpressionPath_Impl(
       *reason_to_stop =
           ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol;
       *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
-      return nullptr;
+      return {};
     }
     }
   }
@@ -2564,8 +2547,6 @@ void ValueObject::Dump(Stream &s, const DumpValueObjectOptions &options) {
 }
 
 ValueObjectSP ValueObject::CreateConstantValue(ConstString name) {
-  ValueObjectSP valobj_sp;
-
   if (UpdateValueIfNeeded(false) && m_error.Success()) {
     ExecutionContext exe_ctx(GetExecutionContextRef());
 
@@ -2579,51 +2560,44 @@ ValueObjectSP ValueObject::CreateConstantValue(ConstString name) {
     } else
       m_error = m_value.GetValueAsData(&exe_ctx, data, GetModule().get());
 
-    valobj_sp = ValueObjectConstResult::Create(
+    return ValueObjectConstResult::Create(
         exe_ctx.GetBestExecutionContextScope(), GetCompilerType(), name, data,
         GetAddressOf());
-  }
-
-  if (!valobj_sp) {
+  } else {
     ExecutionContext exe_ctx(GetExecutionContextRef());
-    valobj_sp = ValueObjectConstResult::Create(
+    return ValueObjectConstResult::Create(
         exe_ctx.GetBestExecutionContextScope(), m_error);
   }
-  return valobj_sp;
 }
 
 ValueObjectSP ValueObject::GetQualifiedRepresentationIfAvailable(
     lldb::DynamicValueType dynValue, bool synthValue) {
-  ValueObjectSP result_sp;
+  ValueObjectSP result_sp = GetSP();
   switch (dynValue) {
   case lldb::eDynamicCanRunTarget:
   case lldb::eDynamicDontRunTarget: {
     if (!IsDynamic())
-      result_sp = GetDynamicValue(dynValue);
+      if (auto dynamic_value = GetDynamicValue(dynValue))
+        result_sp = dynamic_value.value();
   } break;
   case lldb::eNoDynamicValues: {
     if (IsDynamic())
       result_sp = GetStaticValue();
   } break;
   }
-  if (!result_sp)
-    result_sp = GetSP();
-  assert(result_sp);
 
   bool is_synthetic = result_sp->IsSynthetic();
   if (synthValue && !is_synthetic) {
     if (auto synth_sp = result_sp->GetSyntheticValue())
-      return synth_sp;
-  }
-  if (!synthValue && is_synthetic) {
-    if (auto non_synth_sp = result_sp->GetNonSyntheticValue())
-      return non_synth_sp;
+      return synth_sp.value();
   }
+  if (!synthValue && is_synthetic)
+    return result_sp->GetNonSyntheticValue();
 
   return result_sp;
 }
 
-ValueObjectSP ValueObject::Dereference(Status &error) {
+ValueObjectSP ValueObject::Dereference() {
   if (m_deref_valobj)
     return m_deref_valobj->GetSP();
 
@@ -2687,19 +2661,21 @@ ValueObjectSP ValueObject::Dereference(Status &error) {
     }
 
   } else if (HasSyntheticValue()) {
-    m_deref_valobj =
-        GetSyntheticValue()->GetChildMemberWithName("$$dereference$$").get();
+    m_deref_valobj = GetSyntheticValue()
+                         .value()
+                         ->GetChildMemberWithName("$$dereference$$")
+                         ->get();
   } else if (IsSynthetic()) {
-    m_deref_valobj = GetChildMemberWithName("$$dereference$$").get();
+    m_deref_valobj = GetChildMemberWithName("$$dereference$$")->get();
   }
 
   if (m_deref_valobj) {
-    error.Clear();
     return m_deref_valobj->GetSP();
   } else {
     StreamString strm;
     GetExpressionPath(strm);
 
+    Status error;
     if (is_pointer_or_reference_type)
       error.SetErrorStringWithFormat("dereference failed: (%s) %s",
                                      GetTypeName().AsCString("<invalid type>"),
@@ -2708,51 +2684,63 @@ ValueObjectSP ValueObject::Dereference(Status &error) {
       error.SetErrorStringWithFormat("not a pointer or reference type: (%s) %s",
                                      GetTypeName().AsCString("<invalid type>"),
                                      strm.GetData());
-    return ValueObjectSP();
+
+    ExecutionContext exe_ctx(GetExecutionContextRef());
+    auto scope = exe_ctx.GetBestExecutionContextScope();
+    return ValueObjectConstResult::Create(scope, error);
   }
 }
 
-ValueObjectSP ValueObject::AddressOf(Status &error) {
+ValueObjectSP ValueObject::AddressOf() {
   if (m_addr_of_valobj_sp)
-    return m_addr_of_valobj_sp;
+    return m_addr_of_valobj_sp.value();
 
   AddressType address_type = eAddressTypeInvalid;
   const bool scalar_is_load_address = false;
   addr_t addr = GetAddressOf(scalar_is_load_address, &address_type);
-  error.Clear();
-  if (addr != LLDB_INVALID_ADDRESS && address_type != eAddressTypeHost) {
-    switch (address_type) {
-    case eAddressTypeInvalid: {
-      StreamString expr_path_strm;
-      GetExpressionPath(expr_path_strm);
-      error.SetErrorStringWithFormat("'%s' is not in memory",
-                                     expr_path_strm.GetData());
-    } break;
 
-    case eAddressTypeFile:
-    case eAddressTypeLoad: {
-      CompilerType compiler_type = GetCompilerType();
-      if (compiler_type) {
-        std::string name(1, '&');
-        name.append(m_name.AsCString(""));
-        ExecutionContext exe_ctx(GetExecutionContextRef());
-        m_addr_of_valobj_sp = ValueObjectConstResult::Create(
-            exe_ctx.GetBestExecutionContextScope(),
-            compiler_type.GetPointerType(), ConstString(name.c_str()), addr,
-            eAddressTypeInvalid, m_data.GetAddressByteSize());
-      }
-    } break;
-    default:
-      break;
-    }
-  } else {
-    StreamString expr_path_strm;
-    GetExpressionPath(expr_path_strm);
+  StreamString expr_path_strm;
+  GetExpressionPath(expr_path_strm);
+  const char *expr_path_str = expr_path_strm.GetData();
+
+  Status error;
+  ExecutionContext exe_ctx(GetExecutionContextRef());
+  auto scope = exe_ctx.GetBestExecutionContextScope();
+
+  if (addr == LLDB_INVALID_ADDRESS) {
     error.SetErrorStringWithFormat("'%s' doesn't have a valid address",
-                                   expr_path_strm.GetData());
+                                   expr_path_str);
+    return ValueObjectConstResult::Create(scope, error);
+  }
+
+  switch (address_type) {
+  case eAddressTypeInvalid: {
+    error.SetErrorStringWithFormat("'%s' is not in memory", expr_path_str);
+    return ValueObjectConstResult::Create(scope, error);
+  }
+  case eAddressTypeHost: {
+    error.SetErrorStringWithFormat("'%s' is in host process (LLDB) memory",
+                                   expr_path_str);
+    return ValueObjectConstResult::Create(scope, error);
   }
 
-  return m_addr_of_valobj_sp;
+  case eAddressTypeFile:
+  case eAddressTypeLoad: {
+    CompilerType compiler_type = GetCompilerType();
+    if (!compiler_type) {
+      error.SetErrorStringWithFormat("'%s' doesn't have a compiler type",
+                                     expr_path_str);
+      return ValueObjectConstResult::Create(scope, error);
+    }
+
+    std::string name(1, '&');
+    name.append(m_name.AsCString(""));
+    m_addr_of_valobj_sp = ValueObjectConstResult::Create(
+        scope, compiler_type.GetPointerType(), ConstString(name.c_str()), addr,
+        eAddressTypeInvalid, m_data.GetAddressByteSize());
+    return m_addr_of_valobj_sp.value();
+  }
+  }
 }
 
 ValueObjectSP ValueObject::DoCast(const CompilerType &compiler_type) {
@@ -2785,33 +2773,32 @@ lldb::ValueObjectSP ValueObject::Clone(ConstString new_name) {
   return ValueObjectCast::Create(*this, new_name, GetCompilerType());
 }
 
-ValueObjectSP ValueObject::CastPointerType(const char *name,
-                                           CompilerType &compiler_type) {
-  ValueObjectSP valobj_sp;
+std::optional<lldb::ValueObjectSP>
+ValueObject::CastPointerType(const char *name, CompilerType &compiler_type) {
   AddressType address_type;
   addr_t ptr_value = GetPointerValue(&address_type);
 
   if (ptr_value != LLDB_INVALID_ADDRESS) {
     Address ptr_addr(ptr_value);
     ExecutionContext exe_ctx(GetExecutionContextRef());
-    valobj_sp = ValueObjectMemory::Create(
-        exe_ctx.GetBestExecutionContextScope(), name, ptr_addr, compiler_type);
+    return ValueObjectMemory::Create(exe_ctx.GetBestExecutionContextScope(),
+                                     name, ptr_addr, compiler_type);
   }
-  return valobj_sp;
+  return {};
 }
 
-ValueObjectSP ValueObject::CastPointerType(const char *name, TypeSP &type_sp) {
-  ValueObjectSP valobj_sp;
+std::optional<lldb::ValueObjectSP>
+ValueObject::CastPointerType(const char *name, TypeSP &type_sp) {
   AddressType address_type;
   addr_t ptr_value = GetPointerValue(&address_type);
 
   if (ptr_value != LLDB_INVALID_ADDRESS) {
     Address ptr_addr(ptr_value);
     ExecutionContext exe_ctx(GetExecutionContextRef());
-    valobj_sp = ValueObjectMemory::Create(
-        exe_ctx.GetBestExecutionContextScope(), name, ptr_addr, type_sp);
+    return ValueObjectMemory::Create(exe_ctx.GetBestExecutionContextScope(),
+                                     name, ptr_addr, type_sp);
   }
-  return valobj_sp;
+  return {};
 }
 
 ValueObject::EvaluationPoint::EvaluationPoint() : m_mod_id(), m_exe_ctx_ref() {}
@@ -2973,7 +2960,7 @@ SymbolContextScope *ValueObject::GetSymbolContextScope() {
   return nullptr;
 }
 
-lldb::ValueObjectSP
+std::optional<lldb::ValueObjectSP>
 ValueObject::CreateValueObjectFromExpression(llvm::StringRef name,
                                              llvm::StringRef expression,
                                              const ExecutionContext &exe_ctx) {
@@ -2981,10 +2968,10 @@ ValueObject::CreateValueObjectFromExpression(llvm::StringRef name,
                                          EvaluateExpressionOptions());
 }
 
-lldb::ValueObjectSP ValueObject::CreateValueObjectFromExpression(
+std::optional<lldb::ValueObjectSP> ValueObject::CreateValueObjectFromExpression(
     llvm::StringRef name, llvm::StringRef expression,
     const ExecutionContext &exe_ctx, const EvaluateExpressionOptions &options) {
-  lldb::ValueObjectSP retval_sp;
+  std::optional<lldb::ValueObjectSP> retval_sp;
   lldb::TargetSP target_sp(exe_ctx.GetTargetSP());
   if (!target_sp)
     return retval_sp;
@@ -2993,11 +2980,11 @@ lldb::ValueObjectSP ValueObject::CreateValueObjectFromExpression(
   target_sp->EvaluateExpression(expression, exe_ctx.GetFrameSP().get(),
                                 retval_sp, options);
   if (retval_sp && !name.empty())
-    retval_sp->SetName(ConstString(name));
+    retval_sp.value()->SetName(ConstString(name));
   return retval_sp;
 }
 
-lldb::ValueObjectSP ValueObject::CreateValueObjectFromAddress(
+std::optional<ValueObjectSP> ValueObject::CreateValueObjectFromAddress(
     llvm::StringRef name, uint64_t address, const ExecutionContext &exe_ctx,
     CompilerType type) {
   if (type) {
@@ -3009,29 +2996,26 @@ lldb::ValueObjectSP ValueObject::CreateValueObjectFromAddress(
           exe_ctx.GetBestExecutionContextScope(), pointer_type,
           ConstString(name), buffer, exe_ctx.GetByteOrder(),
           exe_ctx.GetAddressByteSize()));
-      if (ptr_result_valobj_sp) {
-        ptr_result_valobj_sp->GetValue().SetValueType(
-            Value::ValueType::LoadAddress);
-        Status err;
-        ptr_result_valobj_sp = ptr_result_valobj_sp->Dereference(err);
-        if (ptr_result_valobj_sp && !name.empty())
-          ptr_result_valobj_sp->SetName(ConstString(name));
-      }
+
+      ptr_result_valobj_sp->GetValue().SetValueType(
+          Value::ValueType::LoadAddress);
+      ptr_result_valobj_sp = ptr_result_valobj_sp->Dereference();
+      if (ptr_result_valobj_sp->GetError().Success() && !name.empty())
+        ptr_result_valobj_sp->SetName(ConstString(name));
       return ptr_result_valobj_sp;
     }
   }
-  return lldb::ValueObjectSP();
+  return {};
 }
 
 lldb::ValueObjectSP ValueObject::CreateValueObjectFromData(
     llvm::StringRef name, const DataExtractor &data,
     const ExecutionContext &exe_ctx, CompilerType type) {
-  lldb::ValueObjectSP new_value_sp;
-  new_value_sp = ValueObjectConstResult::Create(
+  lldb::ValueObjectSP new_value_sp = ValueObjectConstResult::Create(
       exe_ctx.GetBestExecutionContextScope(), type, ConstString(name), data,
       LLDB_INVALID_ADDRESS);
   new_value_sp->SetAddressTypeOfChildren(eAddressTypeLoad);
-  if (new_value_sp && !name.empty())
+  if (!name.empty())
     new_value_sp->SetName(ConstString(name));
   return new_value_sp;
 }
@@ -3123,22 +3107,20 @@ bool ValueObject::CanProvideValue() {
   return (!type.IsValid()) || (0 != (type.GetTypeInfo() & eTypeHasValue));
 }
 
-
-
-ValueObjectSP ValueObject::Persist() {
+std::optional<ValueObjectSP> ValueObject::Persist() {
   if (!UpdateValueIfNeeded())
-    return nullptr;
+    return {};
 
   TargetSP target_sp(GetTargetSP());
   if (!target_sp)
-    return nullptr;
+    return {};
 
   PersistentExpressionState *persistent_state =
       target_sp->GetPersistentExpressionStateForLanguage(
           GetPreferredDisplayLanguage());
 
   if (!persistent_state)
-    return nullptr;
+    return {};
 
   ConstString name = persistent_state->GetNextPersistentVariableName();
 
diff --git a/lldb/source/Core/ValueObjectConstResult.cpp b/lldb/source/Core/ValueObjectConstResult.cpp
index 693da1a551f8eb..f7c86c9ff47c58 100644
--- a/lldb/source/Core/ValueObjectConstResult.cpp
+++ b/lldb/source/Core/ValueObjectConstResult.cpp
@@ -276,7 +276,7 @@ size_t ValueObjectConstResult::GetPointeeData(DataExtractor &data,
   return m_impl.GetPointeeData(data, item_idx, item_count);
 }
 
-lldb::ValueObjectSP
+std::optional<ValueObjectSP>
 ValueObjectConstResult::GetDynamicValue(lldb::DynamicValueType use_dynamic) {
   // Always recalculate dynamic values for const results as the memory that
   // they might point to might have changed at any time.
@@ -290,7 +290,7 @@ ValueObjectConstResult::GetDynamicValue(lldb::DynamicValueType use_dynamic) {
     if (m_dynamic_value && m_dynamic_value->GetError().Success())
       return m_dynamic_value->GetSP();
   }
-  return ValueObjectSP();
+  return {};
 }
 
 lldb::ValueObjectSP
diff --git a/lldb/source/Core/ValueObjectConstResultImpl.cpp b/lldb/source/Core/ValueObjectConstResultImpl.cpp
index e2db3ace19247b..8e2d9182521c1e 100644
--- a/lldb/source/Core/ValueObjectConstResultImpl.cpp
+++ b/lldb/source/Core/ValueObjectConstResultImpl.cpp
@@ -39,7 +39,7 @@ ValueObjectConstResultImpl::ValueObjectConstResultImpl(
 
 lldb::ValueObjectSP ValueObjectConstResultImpl::Dereference(Status &error) {
   if (m_impl_backend == nullptr)
-    return lldb::ValueObjectSP();
+    return {};
 
   return m_impl_backend->ValueObject::Dereference(error);
 }
@@ -113,7 +113,7 @@ lldb::ValueObjectSP ValueObjectConstResultImpl::GetSyntheticChildAtOffset(
     uint32_t offset, const CompilerType &type, bool can_create,
     ConstString name_const_str) {
   if (m_impl_backend == nullptr)
-    return lldb::ValueObjectSP();
+    return {};
 
   return m_impl_backend->ValueObject::GetSyntheticChildAtOffset(
       offset, type, can_create, name_const_str);
@@ -124,7 +124,7 @@ lldb::ValueObjectSP ValueObjectConstResultImpl::AddressOf(Status &error) {
     return m_address_of_backend;
 
   if (m_impl_backend == nullptr)
-    return lldb::ValueObjectSP();
+    return {};
   if (m_live_address != LLDB_INVALID_ADDRESS) {
     CompilerType compiler_type(m_impl_backend->GetCompilerType());
 
@@ -150,7 +150,7 @@ lldb::ValueObjectSP ValueObjectConstResultImpl::AddressOf(Status &error) {
 lldb::ValueObjectSP
 ValueObjectConstResultImpl::Cast(const CompilerType &compiler_type) {
   if (m_impl_backend == nullptr)
-    return lldb::ValueObjectSP();
+    return {};
 
   ValueObjectConstResultCast *result_cast =
       new ValueObjectConstResultCast(*m_impl_backend, m_impl_backend->GetName(),
diff --git a/lldb/source/Core/ValueObjectList.cpp b/lldb/source/Core/ValueObjectList.cpp
index 28907261f0a60e..c011c331f96c1f 100644
--- a/lldb/source/Core/ValueObjectList.cpp
+++ b/lldb/source/Core/ValueObjectList.cpp
@@ -36,19 +36,21 @@ size_t ValueObjectList::GetSize() const { return m_value_objects.size(); }
 
 void ValueObjectList::Resize(size_t size) { m_value_objects.resize(size); }
 
-lldb::ValueObjectSP ValueObjectList::GetValueObjectAtIndex(size_t idx) {
-  lldb::ValueObjectSP valobj_sp;
-  if (idx < m_value_objects.size())
-    valobj_sp = m_value_objects[idx];
-  return valobj_sp;
+std::optional<ValueObjectSP>
+ValueObjectList::GetValueObjectAtIndex(size_t idx) {
+  if (idx >= m_value_objects.size())
+    return {};
+
+  return m_value_objects[idx];
 }
 
-lldb::ValueObjectSP ValueObjectList::RemoveValueObjectAtIndex(size_t idx) {
-  lldb::ValueObjectSP valobj_sp;
-  if (idx < m_value_objects.size()) {
-    valobj_sp = m_value_objects[idx];
-    m_value_objects.erase(m_value_objects.begin() + idx);
-  }
+std::optional<ValueObjectSP>
+ValueObjectList::RemoveValueObjectAtIndex(size_t idx) {
+  if (idx >= m_value_objects.size())
+    return {};
+
+  lldb::ValueObjectSP valobj_sp = m_value_objects[idx];
+  m_value_objects.erase(m_value_objects.begin() + idx);
   return valobj_sp;
 }
 
@@ -59,49 +61,42 @@ void ValueObjectList::SetValueObjectAtIndex(size_t idx,
   m_value_objects[idx] = valobj_sp;
 }
 
-ValueObjectSP ValueObjectList::FindValueObjectByValueName(const char *name) {
+std::optional<ValueObjectSP>
+ValueObjectList::FindValueObjectByValueName(const char *name) {
   ConstString name_const_str(name);
-  ValueObjectSP val_obj_sp;
   collection::iterator pos, end = m_value_objects.end();
   for (pos = m_value_objects.begin(); pos != end; ++pos) {
     ValueObject *valobj = (*pos).get();
-    if (valobj && valobj->GetName() == name_const_str) {
-      val_obj_sp = *pos;
-      break;
-    }
+    if (valobj && valobj->GetName() == name_const_str)
+      return (*pos);
   }
-  return val_obj_sp;
+  return {};
 }
 
-ValueObjectSP ValueObjectList::FindValueObjectByUID(lldb::user_id_t uid) {
-  ValueObjectSP valobj_sp;
+std::optional<ValueObjectSP>
+ValueObjectList::FindValueObjectByUID(lldb::user_id_t uid) {
   collection::iterator pos, end = m_value_objects.end();
 
   for (pos = m_value_objects.begin(); pos != end; ++pos) {
     // Watch out for NULL objects in our list as the list might get resized to
     // a specific size and lazily filled in
     ValueObject *valobj = (*pos).get();
-    if (valobj && valobj->GetID() == uid) {
-      valobj_sp = *pos;
-      break;
-    }
+    if (valobj && valobj->GetID() == uid)
+      return (*pos);
   }
-  return valobj_sp;
+  return {};
 }
 
-ValueObjectSP
+std::optional<ValueObjectSP>
 ValueObjectList::FindValueObjectByPointer(ValueObject *find_valobj) {
-  ValueObjectSP valobj_sp;
   collection::iterator pos, end = m_value_objects.end();
 
   for (pos = m_value_objects.begin(); pos != end; ++pos) {
     ValueObject *valobj = (*pos).get();
-    if (valobj && valobj == find_valobj) {
-      valobj_sp = *pos;
-      break;
-    }
+    if (valobj && valobj == find_valobj)
+      return (*pos);
   }
-  return valobj_sp;
+  return {};
 }
 
 void ValueObjectList::Swap(ValueObjectList &value_object_list) {
diff --git a/lldb/source/Core/ValueObjectRegister.cpp b/lldb/source/Core/ValueObjectRegister.cpp
index c2b84c11347359..569f6b686ab8a2 100644
--- a/lldb/source/Core/ValueObjectRegister.cpp
+++ b/lldb/source/Core/ValueObjectRegister.cpp
@@ -127,7 +127,7 @@ ValueObject *ValueObjectRegisterSet::CreateChildAtIndex(
   return valobj;
 }
 
-lldb::ValueObjectSP
+std::optional<ValueObjectSP>
 ValueObjectRegisterSet::GetChildMemberWithName(llvm::StringRef name,
                                                bool can_create) {
   ValueObject *valobj = nullptr;
@@ -139,7 +139,7 @@ ValueObjectRegisterSet::GetChildMemberWithName(llvm::StringRef name,
   if (valobj)
     return valobj->GetSP();
   else
-    return ValueObjectSP();
+    return {};
 }
 
 size_t ValueObjectRegisterSet::GetIndexOfChildWithName(llvm::StringRef name) {
diff --git a/lldb/source/Core/ValueObjectSyntheticFilter.cpp b/lldb/source/Core/ValueObjectSyntheticFilter.cpp
index 43bc532c4a0410..cdc9cc29eed900 100644
--- a/lldb/source/Core/ValueObjectSyntheticFilter.cpp
+++ b/lldb/source/Core/ValueObjectSyntheticFilter.cpp
@@ -33,7 +33,7 @@ class DummySyntheticFrontEnd : public SyntheticChildrenFrontEnd {
 
   size_t CalculateNumChildren() override { return m_backend.GetNumChildren(); }
 
-  lldb::ValueObjectSP GetChildAtIndex(size_t idx) override {
+  std::optional<lldb::ValueObjectSP> GetChildAtIndex(size_t idx) override {
     return m_backend.GetChildAtIndex(idx);
   }
 
@@ -107,10 +107,10 @@ size_t ValueObjectSynthetic::CalculateNumChildren(uint32_t max) {
   }
 }
 
-lldb::ValueObjectSP
+std::optional<lldb::ValueObjectSP>
 ValueObjectSynthetic::GetDynamicValue(lldb::DynamicValueType valueType) {
   if (!m_parent)
-    return lldb::ValueObjectSP();
+    return {};
   if (IsDynamic() && GetDynamicValueType() == valueType)
     return GetSP();
   return m_parent->GetDynamicValue(valueType);
@@ -138,9 +138,8 @@ void ValueObjectSynthetic::CreateSynthFilter() {
     CompilerType type = m_parent->GetCompilerType();
     if (type.IsValid() && type.IsPointerOrReferenceType())
     {
-      Status error;
-      lldb::ValueObjectSP deref_sp = m_parent->Dereference(error);
-      if (error.Success())
+      lldb::ValueObjectSP deref_sp = m_parent->Dereference();
+      if (deref_sp->GetError().Success())
         valobj_for_frontend = deref_sp.get();
     }
   }
@@ -208,16 +207,17 @@ bool ValueObjectSynthetic::UpdateValue() {
 
   m_provides_value = eLazyBoolCalculate;
 
-  lldb::ValueObjectSP synth_val(m_synth_filter_up->GetSyntheticValue());
+  std::optional<lldb::ValueObjectSP> synth_val(
+      m_synth_filter_up->GetSyntheticValue());
 
-  if (synth_val && synth_val->CanProvideValue()) {
+  if (synth_val.has_value() && synth_val.value()->CanProvideValue()) {
     LLDB_LOGF(log,
               "[ValueObjectSynthetic::UpdateValue] name=%s, synthetic "
               "filter said it can provide a value",
               GetName().AsCString());
 
     m_provides_value = eLazyBoolYes;
-    CopyValueData(synth_val.get());
+    CopyValueData(synth_val->get());
   } else {
     LLDB_LOGF(log,
               "[ValueObjectSynthetic::UpdateValue] name=%s, synthetic "
@@ -234,8 +234,8 @@ bool ValueObjectSynthetic::UpdateValue() {
   return true;
 }
 
-lldb::ValueObjectSP ValueObjectSynthetic::GetChildAtIndex(size_t idx,
-                                                          bool can_create) {
+std::optional<lldb::ValueObjectSP>
+ValueObjectSynthetic::GetChildAtIndex(size_t idx, bool can_create) {
   Log *log = GetLog(LLDBLog::DataFormatters);
 
   LLDB_LOGF(log,
@@ -262,16 +262,18 @@ lldb::ValueObjectSP ValueObjectSynthetic::GetChildAtIndex(size_t idx,
                 "index %zu not cached and will be created",
                 GetName().AsCString(), idx);
 
-      lldb::ValueObjectSP synth_guy = m_synth_filter_up->GetChildAtIndex(idx);
+      std::optional<lldb::ValueObjectSP> synth_guy =
+          m_synth_filter_up->GetChildAtIndex(idx);
 
       LLDB_LOGF(
           log,
           "[ValueObjectSynthetic::GetChildAtIndex] name=%s, child at index "
           "%zu created as %p (is "
           "synthetic: %s)",
-          GetName().AsCString(), idx, static_cast<void *>(synth_guy.get()),
-          synth_guy.get()
-              ? (synth_guy->IsSyntheticChildrenGenerated() ? "yes" : "no")
+          GetName().AsCString(), idx, static_cast<void *>(synth_guy->get()),
+          synth_guy.has_value()
+              ? (synth_guy.value()->IsSyntheticChildrenGenerated() ? "yes"
+                                                                   : "no")
               : "no");
 
       if (!synth_guy)
@@ -279,11 +281,11 @@ lldb::ValueObjectSP ValueObjectSynthetic::GetChildAtIndex(size_t idx,
 
       {
         std::lock_guard<std::mutex> guard(m_child_mutex);
-        if (synth_guy->IsSyntheticChildrenGenerated())
-          m_synthetic_children_cache.push_back(synth_guy);
-        m_children_byindex[idx] = synth_guy.get();
+        if (synth_guy.value()->IsSyntheticChildrenGenerated())
+          m_synthetic_children_cache.push_back(synth_guy.value());
+        m_children_byindex[idx] = synth_guy->get();
       }
-      synth_guy->SetPreferredDisplayLanguageIfNeeded(
+      synth_guy.value()->SetPreferredDisplayLanguageIfNeeded(
           GetPreferredDisplayLanguage());
       return synth_guy;
     } else {
@@ -294,7 +296,7 @@ lldb::ValueObjectSP ValueObjectSynthetic::GetChildAtIndex(size_t idx,
                 GetName().AsCString(), idx, can_create ? "yes" : "no",
                 static_cast<void *>(m_synth_filter_up.get()));
 
-      return lldb::ValueObjectSP();
+      return {};
     }
   } else {
     LLDB_LOGF(log,
@@ -306,7 +308,7 @@ lldb::ValueObjectSP ValueObjectSynthetic::GetChildAtIndex(size_t idx,
   }
 }
 
-lldb::ValueObjectSP
+std::optional<lldb::ValueObjectSP>
 ValueObjectSynthetic::GetChildMemberWithName(llvm::StringRef name,
                                              bool can_create) {
   UpdateValueIfNeeded();
@@ -314,7 +316,7 @@ ValueObjectSynthetic::GetChildMemberWithName(llvm::StringRef name,
   uint32_t index = GetIndexOfChildWithName(name);
 
   if (index == UINT32_MAX)
-    return lldb::ValueObjectSP();
+    return {};
 
   return GetChildAtIndex(index, can_create);
 }
diff --git a/lldb/source/Core/ValueObjectUpdater.cpp b/lldb/source/Core/ValueObjectUpdater.cpp
index af7f976a6d2722..7c6a51ab641773 100644
--- a/lldb/source/Core/ValueObjectUpdater.cpp
+++ b/lldb/source/Core/ValueObjectUpdater.cpp
@@ -11,18 +11,16 @@
 using namespace lldb_private;
 
 ValueObjectUpdater::ValueObjectUpdater(lldb::ValueObjectSP in_valobj_sp) {
-  if (!in_valobj_sp)
-    return;
   // If the user passes in a value object that is dynamic or synthetic, then
   // water it down to the static type.
   m_root_valobj_sp = in_valobj_sp->GetQualifiedRepresentationIfAvailable(
       lldb::eNoDynamicValues, false);
 }
 
-lldb::ValueObjectSP ValueObjectUpdater::GetSP() {
+std::optional<lldb::ValueObjectSP> ValueObjectUpdater::GetSP() {
   lldb::ProcessSP process_sp = GetProcessSP();
   if (!process_sp)
-    return lldb::ValueObjectSP();
+    return {};
 
   const uint32_t current_stop_id = process_sp->GetLastNaturalStopID();
   if (current_stop_id == m_stop_id)
@@ -31,18 +29,20 @@ lldb::ValueObjectSP ValueObjectUpdater::GetSP() {
   m_stop_id = current_stop_id;
 
   if (!m_root_valobj_sp) {
-    m_user_valobj_sp.reset();
+    if (m_user_valobj_sp)
+      m_user_valobj_sp.value().reset();
     return m_root_valobj_sp;
   }
 
   m_user_valobj_sp = m_root_valobj_sp;
 
-  lldb::ValueObjectSP dynamic_sp =
-      m_user_valobj_sp->GetDynamicValue(lldb::eDynamicDontRunTarget);
+  std::optional<lldb::ValueObjectSP> dynamic_sp =
+      m_user_valobj_sp.value()->GetDynamicValue(lldb::eDynamicDontRunTarget);
   if (dynamic_sp)
     m_user_valobj_sp = dynamic_sp;
 
-  lldb::ValueObjectSP synthetic_sp = m_user_valobj_sp->GetSyntheticValue();
+  std::optional<lldb::ValueObjectSP> synthetic_sp =
+      m_user_valobj_sp.value()->GetSyntheticValue();
   if (synthetic_sp)
     m_user_valobj_sp = synthetic_sp;
 
@@ -51,6 +51,6 @@ lldb::ValueObjectSP ValueObjectUpdater::GetSP() {
 
 lldb::ProcessSP ValueObjectUpdater::GetProcessSP() const {
   if (m_root_valobj_sp)
-    return m_root_valobj_sp->GetProcessSP();
+    return m_root_valobj_sp.value()->GetProcessSP();
   return lldb::ProcessSP();
 }
diff --git a/lldb/source/DataFormatters/TypeSynthetic.cpp b/lldb/source/DataFormatters/TypeSynthetic.cpp
index de042e474903e5..7477ce43450428 100644
--- a/lldb/source/DataFormatters/TypeSynthetic.cpp
+++ b/lldb/source/DataFormatters/TypeSynthetic.cpp
@@ -169,7 +169,7 @@ ScriptedSyntheticChildren::FrontEnd::~FrontEnd() = default;
 lldb::ValueObjectSP
 ScriptedSyntheticChildren::FrontEnd::GetChildAtIndex(size_t idx) {
   if (!m_wrapper_sp || !m_interpreter)
-    return lldb::ValueObjectSP();
+    return {};
 
   return m_interpreter->GetChildAtIndex(m_wrapper_sp, idx);
 }
diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp
index 2e8d1dfdaa1769..beaacd989a3bdd 100644
--- a/lldb/source/Target/Target.cpp
+++ b/lldb/source/Target/Target.cpp
@@ -2656,7 +2656,7 @@ Target *Target::GetTargetFromContexts(const ExecutionContext *exe_ctx_ptr,
 
 ExpressionResults Target::EvaluateExpression(
     llvm::StringRef expr, ExecutionContextScope *exe_scope,
-    lldb::ValueObjectSP &result_valobj_sp,
+    std::optional<lldb::ValueObjectSP> &result_valobj_sp,
     const EvaluateExpressionOptions &options, std::string *fixed_expression,
     ValueObject *ctx_obj) {
   result_valobj_sp.reset();



More information about the lldb-commits mailing list