[Lldb-commits] [lldb] [lldb] All ValueObjectSP instances are now valid (non-null) but have an error state (In-progress | Take 2) (PR #77375)

Pete Lawrence via lldb-commits lldb-commits at lists.llvm.org
Mon Jan 8 13:08:36 PST 2024


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

> **Note**
> I originally proposed this change with [PR 74912](https://github.com/llvm/llvm-project/pull/74912) before renaming the branch.

### Purpose
For now, we'd like to get people's thought's on the goal, design, and scope of this PR by reviewing these preliminary changes.

I recommend focussing (or starting) on these files:
* `ValueObject.h`
* `ValueObject.cpp`


### Goal
Every `ValueObjectSP` will have an actual value and will never be equal to `nullptr`.


### Design
To force each `ValueObjectSP` to contain _something_, we're considering changing the type from a typedef…
```cpp
typedef std::shared_ptr<lldb_private::ValueObject> ValueObjectSP;

```

to this subclass:
```cpp
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);
  }
};
```

This class removes the default constructor to force each `ValueObjectSP` to point to a real `ValueObject` instance. It also removes `operator bool()` because no instance will ever equal `nullptr`. 


### Change Patterns
The bulk of the changes into one of these two camps:
1. 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.
* This means that callers of these methods need to check the return value's error state.
  * `return_value->GetError.Success()`
  * `return_value->GetError.Fail()`

2. For all other methods that return a `ValueObjectSP` but don't have a `Status &` parameter, they now return `std::optional<ValueObjectSP>`.
* This changes a fair amount of code in these ways:
  * Code which had been using the `std::shared_ptr` Boolean operator now uses the `std::optional` Boolean operator.
  * Nearby code has to call the optional's `value()` method to get the shared pointer inside.
  * Methods with lines that return `ValueObjectSP()` now return `{}`, which creates an optional with nothing in it.

Again, I recommend focussing (or starting) on these files:
* `ValueObject.h`
* `ValueObject.cpp`


### Remaining work
This is very much a work-in-progress for a proof of concept, which means:
* It doesn't compile (yet)
* So far I've modified 53 files
* I estimate another 100-250 more files need to change based on the ninja build progress indicator.

The remaining changes will just be more of the same but now's a good time to take a look at this sample to get a sense of the magnitude and trajectory of the remaining changes.

>From c416cad26ed3e84918f639cc5a408682afff451f 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/Breakpoint/Watchpoint.h     |   4 +-
 lldb/include/lldb/Core/ValueObject.h          |  66 +-
 .../lldb/Core/ValueObjectConstResult.h        |   8 +-
 .../lldb/Core/ValueObjectConstResultCast.h    |   6 +-
 .../lldb/Core/ValueObjectConstResultChild.h   |   6 +-
 .../lldb/Core/ValueObjectConstResultImpl.h    |   8 +-
 lldb/include/lldb/Core/ValueObjectList.h      |  17 +-
 lldb/include/lldb/Core/ValueObjectRegister.h  |   4 +-
 .../lldb/Core/ValueObjectSyntheticFilter.h    |  10 +-
 lldb/include/lldb/Core/ValueObjectUpdater.h   |   6 +-
 .../lldb/DataFormatters/TypeSynthetic.h       |  22 +-
 .../lldb/DataFormatters/ValueObjectPrinter.h  |   3 +-
 .../lldb/DataFormatters/VectorIterator.h      |   2 +-
 .../lldb/Expression/ExpressionVariable.h      |  53 +-
 lldb/include/lldb/Expression/UserExpression.h |   2 +-
 .../lldb/Interpreter/ScriptInterpreter.h      |   8 +-
 lldb/include/lldb/Target/LanguageRuntime.h    |   6 +-
 lldb/include/lldb/Target/StackFrame.h         |  12 +-
 .../lldb/Target/StackFrameRecognizer.h        |   4 +-
 lldb/include/lldb/Target/Target.h             |   2 +-
 lldb/include/lldb/Target/Thread.h             |   4 +-
 lldb/include/lldb/Target/ThreadPlan.h         |   4 +-
 .../lldb/Target/ThreadPlanCallFunction.h      |   2 +-
 lldb/include/lldb/lldb-forward.h              |  13 +-
 lldb/source/Breakpoint/BreakpointLocation.cpp |   6 +-
 lldb/source/Breakpoint/Watchpoint.cpp         |  22 +-
 .../Commands/CommandObjectDWIMPrint.cpp       |  23 +-
 .../Commands/CommandObjectExpression.cpp      |  25 +-
 lldb/source/Commands/CommandObjectFrame.cpp   |  36 +-
 lldb/source/Commands/CommandObjectMemory.cpp  |  25 +-
 lldb/source/Commands/CommandObjectTarget.cpp  |   7 +-
 lldb/source/Commands/CommandObjectThread.cpp  |  15 +-
 lldb/source/Commands/CommandObjectType.cpp    |  12 +-
 .../Commands/CommandObjectWatchpoint.cpp      |  18 +-
 lldb/source/Core/FormatEntity.cpp             |  29 +-
 lldb/source/Core/IOHandlerCursesGUI.cpp       |  29 +-
 lldb/source/Core/ValueObject.cpp              | 640 +++++++++---------
 lldb/source/Core/ValueObjectConstResult.cpp   |  20 +-
 .../Core/ValueObjectConstResultCast.cpp       |  11 +-
 .../Core/ValueObjectConstResultChild.cpp      |  11 +-
 .../Core/ValueObjectConstResultImpl.cpp       |  49 +-
 lldb/source/Core/ValueObjectList.cpp          |  65 +-
 lldb/source/Core/ValueObjectRegister.cpp      |   4 +-
 .../Core/ValueObjectSyntheticFilter.cpp       |  46 +-
 lldb/source/Core/ValueObjectUpdater.cpp       |  18 +-
 lldb/source/DataFormatters/FormatManager.cpp  |  37 +-
 lldb/source/DataFormatters/TypeSynthetic.cpp  |  26 +-
 .../DataFormatters/ValueObjectPrinter.cpp     |  26 +-
 lldb/source/DataFormatters/VectorType.cpp     |  14 +-
 lldb/source/Expression/ExpressionVariable.cpp |  14 +-
 lldb/source/Target/StackFrame.cpp             | 368 +++++-----
 lldb/source/Target/Target.cpp                 |   2 +-
 lldb/source/Target/Thread.cpp                 |  23 +-
 53 files changed, 983 insertions(+), 910 deletions(-)

diff --git a/lldb/include/lldb/Breakpoint/Watchpoint.h b/lldb/include/lldb/Breakpoint/Watchpoint.h
index 851162af24c74e0..78b81218bfcf450 100644
--- a/lldb/include/lldb/Breakpoint/Watchpoint.h
+++ b/lldb/include/lldb/Breakpoint/Watchpoint.h
@@ -219,8 +219,8 @@ class Watchpoint : public std::enable_shared_from_this<Watchpoint>,
   uint32_t m_ignore_count;      // Number of times to ignore this watchpoint
   std::string m_decl_str;       // Declaration information, if any.
   std::string m_watch_spec_str; // Spec for the watchpoint.
-  lldb::ValueObjectSP m_old_value_sp;
-  lldb::ValueObjectSP m_new_value_sp;
+  std::optional<lldb::ValueObjectSP> m_old_value_sp;
+  std::optional<lldb::ValueObjectSP> m_new_value_sp;
   CompilerType m_type;
   Status m_error; // An error object describing errors associated with this
                   // watchpoint.
diff --git a/lldb/include/lldb/Core/ValueObject.h b/lldb/include/lldb/Core/ValueObject.h
index 3f8005ba696ce84..0f1b8c98aee1df3 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,14 +465,18 @@ 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);
 
-  // The method always creates missing children in the path, if necessary.
-  lldb::ValueObjectSP GetChildAtNamePath(llvm::ArrayRef<llvm::StringRef> names);
 
   virtual lldb::ValueObjectSP GetChildMemberWithName(llvm::StringRef name,
                                                      bool can_create = true);
+  /// The method always creates missing children in the path, if necessary.
+  std::optional<lldb::ValueObjectSP>
+  GetChildAtNamePath(llvm::ArrayRef<llvm::StringRef> names);
+
+  virtual std::optional<lldb::ValueObjectSP>
+  GetChildMemberWithName(llvm::StringRef name, bool can_create = true);
 
   virtual size_t GetIndexOfChildWithName(llvm::StringRef name);
 
@@ -536,7 +540,11 @@ class ValueObject {
 
   bool UpdateFormatsIfNeeded();
 
-  lldb::ValueObjectSP GetSP() { return m_manager->GetSharedPointer(this); }
+  lldb::ValueObjectSP GetSP() {
+    auto 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
@@ -548,26 +556,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();
 
@@ -575,7 +585,7 @@ class ValueObject {
 
   virtual lldb::ValueObjectSP GetNonSyntheticValue() { return GetSP(); }
 
-  lldb::ValueObjectSP GetSyntheticValue();
+  std::optional<lldb::ValueObjectSP> GetSyntheticValue();
 
   virtual bool HasSyntheticValue();
 
@@ -587,7 +597,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
@@ -595,7 +605,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; }
 
@@ -606,11 +616,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
@@ -642,18 +652,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);
@@ -662,7 +672,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.
@@ -874,7 +884,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;
@@ -998,7 +1008,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 d61df859bebce4c..2fedb0f99f0af4b 100644
--- a/lldb/include/lldb/Core/ValueObjectConstResult.h
+++ b/lldb/include/lldb/Core/ValueObjectConstResult.h
@@ -77,16 +77,16 @@ class ValueObjectConstResult : public ValueObject {
 
   void SetByteSize(size_t size);
 
-  lldb::ValueObjectSP Dereference(Status &error) override;
+  lldb::ValueObjectSP Dereference() override;
 
   ValueObject *CreateChildAtIndex(size_t idx, bool synthetic_array_member,
                                   int32_t synthetic_index) override;
 
-  lldb::ValueObjectSP GetSyntheticChildAtOffset(
+  std::optional<lldb::ValueObjectSP> GetSyntheticChildAtOffset(
       uint32_t offset, const CompilerType &type, bool can_create,
       ConstString name_const_str = ConstString()) override;
 
-  lldb::ValueObjectSP AddressOf(Status &error) override;
+  lldb::ValueObjectSP AddressOf() override;
 
   lldb::addr_t GetAddressOf(bool scalar_is_load_address = true,
                             AddressType *address_type = nullptr) override;
@@ -101,7 +101,7 @@ class ValueObjectConstResult : public ValueObject {
     m_impl.SetLiveAddress(addr, address_type);
   }
 
-  lldb::ValueObjectSP
+  std::optional<lldb::ValueObjectSP>
   GetDynamicValue(lldb::DynamicValueType valueType) override;
 
   lldb::LanguageType GetPreferredDisplayLanguage() override;
diff --git a/lldb/include/lldb/Core/ValueObjectConstResultCast.h b/lldb/include/lldb/Core/ValueObjectConstResultCast.h
index efcbe0dc6a0bd9f..8c36320125bbc9b 100644
--- a/lldb/include/lldb/Core/ValueObjectConstResultCast.h
+++ b/lldb/include/lldb/Core/ValueObjectConstResultCast.h
@@ -33,7 +33,7 @@ class ValueObjectConstResultCast : public ValueObjectCast {
 
   ~ValueObjectConstResultCast() override;
 
-  lldb::ValueObjectSP Dereference(Status &error) override;
+  lldb::ValueObjectSP Dereference() override;
 
   ValueObject *CreateChildAtIndex(size_t idx, bool synthetic_array_member,
                                   int32_t synthetic_index) override;
@@ -42,11 +42,11 @@ class ValueObjectConstResultCast : public ValueObjectCast {
     return ValueObjectCast::GetCompilerType();
   }
 
-  lldb::ValueObjectSP GetSyntheticChildAtOffset(
+  std::optional<lldb::ValueObjectSP> GetSyntheticChildAtOffset(
       uint32_t offset, const CompilerType &type, bool can_create,
       ConstString name_const_str = ConstString()) override;
 
-  lldb::ValueObjectSP AddressOf(Status &error) override;
+  lldb::ValueObjectSP AddressOf() override;
 
   size_t GetPointeeData(DataExtractor &data, uint32_t item_idx = 0,
                         uint32_t item_count = 1) override;
diff --git a/lldb/include/lldb/Core/ValueObjectConstResultChild.h b/lldb/include/lldb/Core/ValueObjectConstResultChild.h
index 7e9da14e8e97f76..b58e0995086ce60 100644
--- a/lldb/include/lldb/Core/ValueObjectConstResultChild.h
+++ b/lldb/include/lldb/Core/ValueObjectConstResultChild.h
@@ -39,7 +39,7 @@ class ValueObjectConstResultChild : public ValueObjectChild {
 
   ~ValueObjectConstResultChild() override;
 
-  lldb::ValueObjectSP Dereference(Status &error) override;
+  lldb::ValueObjectSP Dereference() override;
 
   ValueObject *CreateChildAtIndex(size_t idx, bool synthetic_array_member,
                                   int32_t synthetic_index) override;
@@ -48,11 +48,11 @@ class ValueObjectConstResultChild : public ValueObjectChild {
     return ValueObjectChild::GetCompilerType();
   }
 
-  lldb::ValueObjectSP GetSyntheticChildAtOffset(
+  std::optional<lldb::ValueObjectSP> GetSyntheticChildAtOffset(
       uint32_t offset, const CompilerType &type, bool can_create,
       ConstString name_const_str = ConstString()) override;
 
-  lldb::ValueObjectSP AddressOf(Status &error) override;
+  lldb::ValueObjectSP AddressOf() override;
 
   lldb::addr_t GetAddressOf(bool scalar_is_load_address = true,
                             AddressType *address_type = nullptr) override;
diff --git a/lldb/include/lldb/Core/ValueObjectConstResultImpl.h b/lldb/include/lldb/Core/ValueObjectConstResultImpl.h
index 5a7a079d3095c93..19a4c206f7a9b79 100644
--- a/lldb/include/lldb/Core/ValueObjectConstResultImpl.h
+++ b/lldb/include/lldb/Core/ValueObjectConstResultImpl.h
@@ -36,17 +36,17 @@ class ValueObjectConstResultImpl {
 
   virtual ~ValueObjectConstResultImpl() = default;
 
-  lldb::ValueObjectSP Dereference(Status &error);
+  lldb::ValueObjectSP Dereference();
 
   ValueObject *CreateChildAtIndex(size_t idx, bool synthetic_array_member,
                                   int32_t synthetic_index);
 
-  lldb::ValueObjectSP
+  std::optional<lldb::ValueObjectSP>
   GetSyntheticChildAtOffset(uint32_t offset, const CompilerType &type,
                             bool can_create,
                             ConstString name_const_str = ConstString());
 
-  lldb::ValueObjectSP AddressOf(Status &error);
+  lldb::ValueObjectSP AddressOf();
 
   lldb::addr_t GetLiveAddress() { return m_live_address; }
 
@@ -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 fcb358e21a26b4a..42b7d64d6a36c89 100644
--- a/lldb/include/lldb/Core/ValueObjectList.h
+++ b/lldb/include/lldb/Core/ValueObjectList.h
@@ -28,31 +28,34 @@ 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);
 
   void Clear() { m_value_objects.clear(); }
 
-  const std::vector<lldb::ValueObjectSP> &GetObjects() const {
+  const std::vector<std::optional<lldb::ValueObjectSP>> &GetObjects() const {
     return m_value_objects;
   }
+
 protected:
-  typedef std::vector<lldb::ValueObjectSP> collection;
+  typedef std::vector<std::optional<lldb::ValueObjectSP>> collection;
   // Classes that inherit from ValueObjectList can see and modify these
   collection m_value_objects;
 };
diff --git a/lldb/include/lldb/Core/ValueObjectRegister.h b/lldb/include/lldb/Core/ValueObjectRegister.h
index 2e47eee3d7f793f..b4f6cad3b817f6b 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 67596232eafd1e9..127db2857f684d9 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 54fcb31076added..52ccf9416cbe852 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 41be9b7efda8fdb..be88b44aed962a7 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
@@ -79,12 +79,12 @@ class SyntheticChildrenFrontEnd {
   typedef std::unique_ptr<SyntheticChildrenFrontEnd> AutoPointer;
 
 protected:
-  lldb::ValueObjectSP
+  std::optional<lldb::ValueObjectSP>
   CreateValueObjectFromExpression(llvm::StringRef name,
                                   llvm::StringRef expression,
                                   const ExecutionContext &exe_ctx);
 
-  lldb::ValueObjectSP
+  std::optional<lldb::ValueObjectSP>
   CreateValueObjectFromAddress(llvm::StringRef name, uint64_t address,
                                const ExecutionContext &exe_ctx,
                                CompilerType type);
@@ -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/DataFormatters/ValueObjectPrinter.h b/lldb/include/lldb/DataFormatters/ValueObjectPrinter.h
index 2b3936eaa707f26..70175e347dd2dd3 100644
--- a/lldb/include/lldb/DataFormatters/ValueObjectPrinter.h
+++ b/lldb/include/lldb/DataFormatters/ValueObjectPrinter.h
@@ -101,7 +101,8 @@ class ValueObjectPrinter {
 
   void PrintChildrenPostamble(bool print_dotdotdot);
 
-  lldb::ValueObjectSP GenerateChild(ValueObject *synth_valobj, size_t idx);
+  std::optional<lldb::ValueObjectSP> GenerateChild(ValueObject *synth_valobj,
+                                                   size_t idx);
 
   void PrintChild(lldb::ValueObjectSP child_sp,
                   const DumpValueObjectOptions::PointerDepth &curr_ptr_depth);
diff --git a/lldb/include/lldb/DataFormatters/VectorIterator.h b/lldb/include/lldb/DataFormatters/VectorIterator.h
index 3414298f255b6a2..8ed4b3fe6b3d62a 100644
--- a/lldb/include/lldb/DataFormatters/VectorIterator.h
+++ b/lldb/include/lldb/DataFormatters/VectorIterator.h
@@ -26,7 +26,7 @@ class VectorIteratorSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
 
   size_t CalculateNumChildren() override;
 
-  lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;
+  std::optional<lldb::ValueObjectSP> GetChildAtIndex(size_t idx) override;
 
   bool Update() override;
 
diff --git a/lldb/include/lldb/Expression/ExpressionVariable.h b/lldb/include/lldb/Expression/ExpressionVariable.h
index 277b00a91668682..83643878c459f28 100644
--- a/lldb/include/lldb/Expression/ExpressionVariable.h
+++ b/lldb/include/lldb/Expression/ExpressionVariable.h
@@ -33,32 +33,52 @@ class ExpressionVariable
 
   virtual ~ExpressionVariable() = default;
 
-  std::optional<uint64_t> GetByteSize() { return m_frozen_sp->GetByteSize(); }
+  std::optional<uint64_t> GetByteSize() {
+    if (m_frozen_sp)
+      return m_frozen_sp.value()->GetByteSize();
+    else
+      return {};
+  }
 
-  ConstString GetName() { return m_frozen_sp->GetName(); }
+  ConstString GetName() {
+    return m_frozen_sp ? m_frozen_sp.value()->GetName() : ConstString("");
+  }
 
-  lldb::ValueObjectSP GetValueObject() { return m_frozen_sp; }
+  std::optional<lldb::ValueObjectSP> GetValueObject() { return m_frozen_sp; }
 
   uint8_t *GetValueBytes();
 
-  void ValueUpdated() { m_frozen_sp->ValueUpdated(); }
+  void ValueUpdated() {
+    if (m_frozen_sp)
+      m_frozen_sp.value()->ValueUpdated();
+  }
 
   RegisterInfo *GetRegisterInfo() {
-    return m_frozen_sp->GetValue().GetRegisterInfo();
+    if (m_frozen_sp)
+      return m_frozen_sp.value()->GetValue().GetRegisterInfo();
+    return nullptr;
   }
 
   void SetRegisterInfo(const RegisterInfo *reg_info) {
-    return m_frozen_sp->GetValue().SetContext(
-        Value::ContextType::RegisterInfo, const_cast<RegisterInfo *>(reg_info));
+    if (m_frozen_sp)
+      return m_frozen_sp.value()->GetValue().SetContext(
+          Value::ContextType::RegisterInfo,
+          const_cast<RegisterInfo *>(reg_info));
   }
 
-  CompilerType GetCompilerType() { return m_frozen_sp->GetCompilerType(); }
+  CompilerType GetCompilerType() {
+    return m_frozen_sp.value()->GetCompilerType();
+  }
 
   void SetCompilerType(const CompilerType &compiler_type) {
-    m_frozen_sp->GetValue().SetCompilerType(compiler_type);
+    if (m_frozen_sp)
+      m_frozen_sp.value()->GetValue().SetCompilerType(compiler_type);
   }
 
-  void SetName(ConstString name) { m_frozen_sp->SetName(name); }
+  void SetName(ConstString name) {
+    if (m_frozen_sp)
+      m_frozen_sp.value()->SetName(name);
+  }
 
   // this function is used to copy the address-of m_live_sp into m_frozen_sp
   // this is necessary because the results of certain cast and pointer-
@@ -68,14 +88,15 @@ class ExpressionVariable
   // Transferring the address-of the live object solves these issues and
   // provides the expected user-level behavior
   void TransferAddress(bool force = false) {
-    if (m_live_sp.get() == nullptr)
+    if (!m_live_sp)
       return;
 
-    if (m_frozen_sp.get() == nullptr)
+    if (!m_frozen_sp)
       return;
 
-    if (force || (m_frozen_sp->GetLiveAddress() == LLDB_INVALID_ADDRESS))
-      m_frozen_sp->SetLiveAddress(m_live_sp->GetLiveAddress());
+    if (force ||
+        (m_frozen_sp.value()->GetLiveAddress() == LLDB_INVALID_ADDRESS))
+      m_frozen_sp.value()->SetLiveAddress(m_live_sp.value()->GetLiveAddress());
   }
 
   enum Flags {
@@ -108,8 +129,8 @@ class ExpressionVariable
   FlagType m_flags; // takes elements of Flags
 
   // these should be private
-  lldb::ValueObjectSP m_frozen_sp;
-  lldb::ValueObjectSP m_live_sp;
+  std::optional<lldb::ValueObjectSP> m_frozen_sp;
+  std::optional<lldb::ValueObjectSP> m_live_sp;
 };
 
 /// \class ExpressionVariableList ExpressionVariable.h
diff --git a/lldb/include/lldb/Expression/UserExpression.h b/lldb/include/lldb/Expression/UserExpression.h
index b6cfeec7e899330..d3a5970ed689635 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 b941f6012a117b6..1b55e6eeaba691c 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/LanguageRuntime.h b/lldb/include/lldb/Target/LanguageRuntime.h
index a2a9c0163f082fb..f7d1a278f6aff1c 100644
--- a/lldb/include/lldb/Target/LanguageRuntime.h
+++ b/lldb/include/lldb/Target/LanguageRuntime.h
@@ -149,9 +149,9 @@ class LanguageRuntime : public Runtime, public PluginInterface {
   static lldb::BreakpointPreconditionSP
   GetExceptionPrecondition(lldb::LanguageType language, bool throw_bp);
 
-  virtual lldb::ValueObjectSP GetExceptionObjectForThread(
-      lldb::ThreadSP thread_sp) {
-    return lldb::ValueObjectSP();
+  virtual std::optional<lldb::ValueObjectSP>
+  GetExceptionObjectForThread(lldb::ThreadSP thread_sp) {
+    return {};
   }
 
   virtual lldb::ThreadSP GetBacktraceThreadFromException(
diff --git a/lldb/include/lldb/Target/StackFrame.h b/lldb/include/lldb/Target/StackFrame.h
index 6c18511c6e1ac36..2f5ae9d1033d6fb 100644
--- a/lldb/include/lldb/Target/StackFrame.h
+++ b/lldb/include/lldb/Target/StackFrame.h
@@ -307,7 +307,7 @@ class StackFrame : public ExecutionContextScope,
   ///
   /// \return
   ///     A shared pointer to the ValueObject described by var_expr.
-  lldb::ValueObjectSP GetValueForVariableExpressionPath(
+  std::optional<lldb::ValueObjectSP> GetValueForVariableExpressionPath(
       llvm::StringRef var_expr, lldb::DynamicValueType use_dynamic,
       uint32_t options, lldb::VariableSP &var_sp, Status &error);
 
@@ -439,7 +439,7 @@ class StackFrame : public ExecutionContextScope,
   ///
   /// \return
   ///     A ValueObject for this variable.
-  lldb::ValueObjectSP
+  std::optional<lldb::ValueObjectSP>
   GetValueObjectForFrameVariable(const lldb::VariableSP &variable_sp,
                                  lldb::DynamicValueType use_dynamic);
 
@@ -463,7 +463,7 @@ class StackFrame : public ExecutionContextScope,
   ///
   /// \return
   ///   The ValueObject if found.  If valid, it has a valid ExpressionPath.
-  lldb::ValueObjectSP GuessValueForAddress(lldb::addr_t addr);
+  std::optional<lldb::ValueObjectSP> GuessValueForAddress(lldb::addr_t addr);
 
   /// Attempt to reconstruct the ValueObject for the address contained in a
   /// given register plus an offset.  The ExpressionPath should indicate how
@@ -477,8 +477,8 @@ class StackFrame : public ExecutionContextScope,
   ///
   /// \return
   ///   The ValueObject if found.  If valid, it has a valid ExpressionPath.
-  lldb::ValueObjectSP GuessValueForRegisterAndOffset(ConstString reg,
-                                                     int64_t offset);
+  std::optional<lldb::ValueObjectSP>
+  GuessValueForRegisterAndOffset(ConstString reg, int64_t offset);
 
   /// Attempt to reconstruct the ValueObject for a variable with a given \a name
   /// from within the current StackFrame, within the current block. The search
@@ -491,7 +491,7 @@ class StackFrame : public ExecutionContextScope,
   ///
   /// \return
   ///   The ValueObject if found.
-  lldb::ValueObjectSP FindVariable(ConstString name);
+  std::optional<lldb::ValueObjectSP> FindVariable(ConstString name);
 
   // lldb::ExecutionContextScope pure virtual functions
   lldb::TargetSP CalculateTarget() override;
diff --git a/lldb/include/lldb/Target/StackFrameRecognizer.h b/lldb/include/lldb/Target/StackFrameRecognizer.h
index 419f0c0aac1f869..84046a2bc8978e5 100644
--- a/lldb/include/lldb/Target/StackFrameRecognizer.h
+++ b/lldb/include/lldb/Target/StackFrameRecognizer.h
@@ -34,9 +34,7 @@ class RecognizedStackFrame
   virtual lldb::ValueObjectListSP GetRecognizedArguments() {
     return m_arguments;
   }
-  virtual lldb::ValueObjectSP GetExceptionObject() {
-    return lldb::ValueObjectSP();
-  }
+  virtual std::optional<lldb::ValueObjectSP> GetExceptionObject() { return {}; }
   virtual lldb::StackFrameSP GetMostRelevantFrame() { return nullptr; };
   virtual ~RecognizedStackFrame() = default;
 
diff --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h
index c37682e2a03859f..f83acb1d6bfd49d 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/Target/Thread.h b/lldb/include/lldb/Target/Thread.h
index e423dd4a6d2baa7..d2261a883b3d109 100644
--- a/lldb/include/lldb/Target/Thread.h
+++ b/lldb/include/lldb/Target/Thread.h
@@ -414,7 +414,7 @@ class Thread : public std::enable_shared_from_this<Thread>,
                                   bool broadcast = false);
 
   Status ReturnFromFrame(lldb::StackFrameSP frame_sp,
-                         lldb::ValueObjectSP return_value_sp,
+                         std::optional<lldb::ValueObjectSP> return_value_sp,
                          bool broadcast = false);
 
   Status JumpToLine(const FileSpec &file, uint32_t line,
@@ -1213,7 +1213,7 @@ class Thread : public std::enable_shared_from_this<Thread>,
   ///     LLDB_INVALID_ADDRESS is returned if no token is available.
   virtual uint64_t GetExtendedBacktraceToken() { return LLDB_INVALID_ADDRESS; }
 
-  lldb::ValueObjectSP GetCurrentException();
+  std::optional<lldb::ValueObjectSP> GetCurrentException();
 
   lldb::ThreadSP GetCurrentExceptionBacktrace();
 
diff --git a/lldb/include/lldb/Target/ThreadPlan.h b/lldb/include/lldb/Target/ThreadPlan.h
index bf68a42e54d18f3..e0a60624cf3cd9d 100644
--- a/lldb/include/lldb/Target/ThreadPlan.h
+++ b/lldb/include/lldb/Target/ThreadPlan.h
@@ -450,8 +450,8 @@ class ThreadPlan : public std::enable_shared_from_this<ThreadPlan>,
   // (currently only ThreadPlanStepOut does this.) If so, the ReturnValueObject
   // can be retrieved from here.
 
-  virtual lldb::ValueObjectSP GetReturnValueObject() {
-    return lldb::ValueObjectSP();
+  virtual std::optional<lldb::ValueObjectSP> GetReturnValueObject() {
+    return {};
   }
 
   // If the thread plan managing the evaluation of a user expression lives
diff --git a/lldb/include/lldb/Target/ThreadPlanCallFunction.h b/lldb/include/lldb/Target/ThreadPlanCallFunction.h
index cb6e7caebb4adfe..892c498fe8c55a4 100644
--- a/lldb/include/lldb/Target/ThreadPlanCallFunction.h
+++ b/lldb/include/lldb/Target/ThreadPlanCallFunction.h
@@ -59,7 +59,7 @@ class ThreadPlanCallFunction : public ThreadPlan {
   // plan is complete, you can call "GetReturnValue()" to retrieve the value
   // that was extracted.
 
-  lldb::ValueObjectSP GetReturnValueObject() override {
+  std::optional<lldb::ValueObjectSP> GetReturnValueObject() override {
     return m_return_valobj_sp;
   }
 
diff --git a/lldb/include/lldb/lldb-forward.h b/lldb/include/lldb/lldb-forward.h
index 4e0c62fa26cae44..430c56eb7caf2ce 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 {
@@ -466,7 +468,16 @@ 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);
+  }
+};
 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/Breakpoint/BreakpointLocation.cpp b/lldb/source/Breakpoint/BreakpointLocation.cpp
index 99f94d04bb31843..d0cc7a4f6b2480b 100644
--- a/lldb/source/Breakpoint/BreakpointLocation.cpp
+++ b/lldb/source/Breakpoint/BreakpointLocation.cpp
@@ -285,8 +285,6 @@ bool BreakpointLocation::ConditionSaysStop(ExecutionContext &exe_ctx,
   // We need to make sure the user sees any parse errors in their condition, so
   // we'll hook the constructor errors up to the debugger's Async I/O.
 
-  ValueObjectSP result_value_sp;
-
   EvaluateExpressionOptions options;
   options.SetUnwindOnError(true);
   options.SetIgnoreBreakpoints(true);
@@ -311,10 +309,10 @@ bool BreakpointLocation::ConditionSaysStop(ExecutionContext &exe_ctx,
       return false;
     }
 
-    result_value_sp = result_variable_sp->GetValueObject();
+    auto result_value_sp = result_variable_sp->GetValueObject();
 
     if (result_value_sp) {
-      ret = result_value_sp->IsLogicalTrue(error);
+      ret = result_value_sp.value()->IsLogicalTrue(error);
       if (log) {
         if (error.Success()) {
           LLDB_LOGF(log, "Condition successfully evaluated, result is %s.\n",
diff --git a/lldb/source/Breakpoint/Watchpoint.cpp b/lldb/source/Breakpoint/Watchpoint.cpp
index 4602ce4213b9cda..b489601d3181f83 100644
--- a/lldb/source/Breakpoint/Watchpoint.cpp
+++ b/lldb/source/Breakpoint/Watchpoint.cpp
@@ -210,8 +210,8 @@ bool Watchpoint::CaptureWatchedValue(const ExecutionContext &exe_ctx) {
   m_new_value_sp = ValueObjectMemory::Create(
       exe_ctx.GetBestExecutionContextScope(), g_watch_name.GetStringRef(),
       watch_address, m_type);
-  m_new_value_sp = m_new_value_sp->CreateConstantValue(g_watch_name);
-  return (m_new_value_sp && m_new_value_sp->GetError().Success());
+  m_new_value_sp = m_new_value_sp.value()->CreateConstantValue(g_watch_name);
+  return (m_new_value_sp && m_new_value_sp.value()->GetError().Success());
 }
 
 bool Watchpoint::WatchedValueReportable(const ExecutionContext &exe_ctx) {
@@ -234,7 +234,9 @@ bool Watchpoint::WatchedValueReportable(const ExecutionContext &exe_ctx) {
   newest_valueobj_sp->GetData(new_data, error);
   if (error.Fail())
     return true;
-  m_new_value_sp->GetData(old_data, error);
+  if (!m_new_value_sp)
+    return true;
+  m_new_value_sp.value()->GetData(old_data, error);
   if (error.Fail())
     return true;
 
@@ -283,10 +285,11 @@ bool Watchpoint::DumpSnapshots(Stream *s, const char *prefix) const {
     values_ss.Indent(prefix);
 
   if (m_old_value_sp) {
-    if (auto *old_value_cstr = m_old_value_sp->GetValueAsCString()) {
+    if (auto *old_value_cstr = m_old_value_sp.value()->GetValueAsCString()) {
       values_ss.Printf("old value: %s", old_value_cstr);
     } else {
-      if (auto *old_summary_cstr = m_old_value_sp->GetSummaryAsCString())
+      if (auto *old_summary_cstr =
+              m_old_value_sp.value()->GetSummaryAsCString())
         values_ss.Printf("old value: %s", old_summary_cstr);
       else {
         StreamString strm;
@@ -295,7 +298,7 @@ bool Watchpoint::DumpSnapshots(Stream *s, const char *prefix) const {
             .SetHideRootType(true)
             .SetHideRootName(true)
             .SetHideName(true);
-        m_old_value_sp->Dump(strm, options);
+        m_old_value_sp.value()->Dump(strm, options);
         if (strm.GetData())
           values_ss.Printf("old value: %s", strm.GetData());
       }
@@ -306,10 +309,11 @@ bool Watchpoint::DumpSnapshots(Stream *s, const char *prefix) const {
     if (values_ss.GetSize())
       values_ss.Printf("\n");
 
-    if (auto *new_value_cstr = m_new_value_sp->GetValueAsCString())
+    if (auto *new_value_cstr = m_new_value_sp.value()->GetValueAsCString())
       values_ss.Printf("new value: %s", new_value_cstr);
     else {
-      if (auto *new_summary_cstr = m_new_value_sp->GetSummaryAsCString())
+      if (auto *new_summary_cstr =
+              m_new_value_sp.value()->GetSummaryAsCString())
         values_ss.Printf("new value: %s", new_summary_cstr);
       else {
         StreamString strm;
@@ -318,7 +322,7 @@ bool Watchpoint::DumpSnapshots(Stream *s, const char *prefix) const {
             .SetHideRootType(true)
             .SetHideRootName(true)
             .SetHideName(true);
-        m_new_value_sp->Dump(strm, options);
+        m_new_value_sp.value()->Dump(strm, options);
         if (strm.GetData())
           values_ss.Printf("new value: %s", strm.GetData());
       }
diff --git a/lldb/source/Commands/CommandObjectDWIMPrint.cpp b/lldb/source/Commands/CommandObjectDWIMPrint.cpp
index 695f3d7931cd0a2..0d7be5e16ac4154 100644
--- a/lldb/source/Commands/CommandObjectDWIMPrint.cpp
+++ b/lldb/source/Commands/CommandObjectDWIMPrint.cpp
@@ -140,9 +140,9 @@ void CommandObjectDWIMPrint::DoExecute(StringRef command,
   // First, try `expr` as the name of a frame variable.
   if (frame) {
     auto valobj_sp = frame->FindVariable(ConstString(expr));
-    if (valobj_sp && valobj_sp->GetError().Success()) {
+    if (valobj_sp && valobj_sp.value()->GetError().Success()) {
       if (!suppress_result) {
-        if (auto persisted_valobj = valobj_sp->Persist())
+        if (auto persisted_valobj = valobj_sp.value()->Persist())
           valobj_sp = persisted_valobj;
       }
 
@@ -156,12 +156,12 @@ void CommandObjectDWIMPrint::DoExecute(StringRef command,
 
       if (is_po) {
         StreamString temp_result_stream;
-        valobj_sp->Dump(temp_result_stream, dump_options);
+        valobj_sp.value()->Dump(temp_result_stream, dump_options);
         llvm::StringRef output = temp_result_stream.GetString();
         maybe_add_hint(output);
         result.GetOutputStream() << output;
       } else {
-        valobj_sp->Dump(result.GetOutputStream(), dump_options);
+        valobj_sp.value()->Dump(result.GetOutputStream(), dump_options);
       }
       result.SetStatus(eReturnStatusSuccessFinishResult);
       return;
@@ -171,7 +171,7 @@ void CommandObjectDWIMPrint::DoExecute(StringRef command,
   // Second, also lastly, try `expr` as a source expression to evaluate.
   {
     auto *exe_scope = m_exe_ctx.GetBestExecutionContextScope();
-    ValueObjectSP valobj_sp;
+    std::optional<lldb::ValueObjectSP> valobj_sp;
     std::string fixed_expression;
 
     ExpressionResults expr_result = target.EvaluateExpression(
@@ -194,22 +194,23 @@ void CommandObjectDWIMPrint::DoExecute(StringRef command,
                                         expr);
       }
 
-      if (valobj_sp->GetError().GetError() != UserExpression::kNoResult) {
+      if (valobj_sp && valobj_sp.value()->GetError().GetError() !=
+                           UserExpression::kNoResult) {
         if (is_po) {
           StreamString temp_result_stream;
-          valobj_sp->Dump(temp_result_stream, dump_options);
+          valobj_sp.value()->Dump(temp_result_stream, dump_options);
           llvm::StringRef output = temp_result_stream.GetString();
           maybe_add_hint(output);
           result.GetOutputStream() << output;
         } else {
-          valobj_sp->Dump(result.GetOutputStream(), dump_options);
+          valobj_sp.value()->Dump(result.GetOutputStream(), dump_options);
         }
       }
 
       if (suppress_result)
         if (auto result_var_sp =
-                target.GetPersistentVariable(valobj_sp->GetName())) {
-          auto language = valobj_sp->GetPreferredDisplayLanguage();
+                target.GetPersistentVariable(valobj_sp.value()->GetName())) {
+          auto language = valobj_sp.value()->GetPreferredDisplayLanguage();
           if (auto *persistent_state =
                   target.GetPersistentExpressionStateForLanguage(language))
             persistent_state->RemovePersistentVariable(result_var_sp);
@@ -218,7 +219,7 @@ void CommandObjectDWIMPrint::DoExecute(StringRef command,
       result.SetStatus(eReturnStatusSuccessFinishResult);
     } else {
       if (valobj_sp)
-        result.SetError(valobj_sp->GetError());
+        result.SetError(valobj_sp.value()->GetError());
       else
         result.AppendErrorWithFormatv(
             "unknown error evaluating expression `{0}`", expr);
diff --git a/lldb/source/Commands/CommandObjectExpression.cpp b/lldb/source/Commands/CommandObjectExpression.cpp
index 3a2dc11e1e71cc4..14fa231b4e4a364 100644
--- a/lldb/source/Commands/CommandObjectExpression.cpp
+++ b/lldb/source/Commands/CommandObjectExpression.cpp
@@ -421,7 +421,7 @@ bool CommandObjectExpression::EvaluateExpression(llvm::StringRef expr,
   Target *exe_target = exe_ctx.GetTargetPtr();
   Target &target = exe_target ? *exe_target : GetDummyTarget();
 
-  lldb::ValueObjectSP result_valobj_sp;
+  std::optional<lldb::ValueObjectSP> result_valobj_sp;
   StackFrame *frame = exe_ctx.GetFramePtr();
 
   if (m_command_options.top_level && !m_command_options.allow_jit) {
@@ -449,13 +449,14 @@ bool CommandObjectExpression::EvaluateExpression(llvm::StringRef expr,
   if (result_valobj_sp) {
     Format format = m_format_options.GetFormat();
 
-    if (result_valobj_sp->GetError().Success()) {
+    if (result_valobj_sp.value()->GetError().Success()) {
       if (format != eFormatVoid) {
         if (format != eFormatDefault)
-          result_valobj_sp->SetFormat(format);
+          result_valobj_sp.value()->SetFormat(format);
 
         if (m_varobj_options.elem_count > 0) {
-          Status error(CanBeUsedForElementCountPrinting(*result_valobj_sp));
+          Status error(
+              CanBeUsedForElementCountPrinting(*result_valobj_sp.value()));
           if (error.Fail()) {
             result.AppendErrorWithFormat(
                 "expression cannot be used with --element-count %s\n",
@@ -471,14 +472,15 @@ bool CommandObjectExpression::EvaluateExpression(llvm::StringRef expr,
             m_command_options.m_verbosity, format));
         options.SetHideRootName(suppress_result);
         options.SetVariableFormatDisplayLanguage(
-            result_valobj_sp->GetPreferredDisplayLanguage());
+            result_valobj_sp.value()->GetPreferredDisplayLanguage());
 
-        result_valobj_sp->Dump(output_stream, options);
+        result_valobj_sp.value()->Dump(output_stream, options);
 
         if (suppress_result)
-          if (auto result_var_sp =
-                  target.GetPersistentVariable(result_valobj_sp->GetName())) {
-            auto language = result_valobj_sp->GetPreferredDisplayLanguage();
+          if (auto result_var_sp = target.GetPersistentVariable(
+                  result_valobj_sp.value()->GetName())) {
+            auto language =
+                result_valobj_sp.value()->GetPreferredDisplayLanguage();
             if (auto *persistent_state =
                     target.GetPersistentExpressionStateForLanguage(language))
               persistent_state->RemovePersistentVariable(result_var_sp);
@@ -486,7 +488,7 @@ bool CommandObjectExpression::EvaluateExpression(llvm::StringRef expr,
         result.SetStatus(eReturnStatusSuccessFinishResult);
       }
     } else {
-      if (result_valobj_sp->GetError().GetError() ==
+      if (result_valobj_sp.value()->GetError().GetError() ==
           UserExpression::kNoResult) {
         if (format != eFormatVoid && GetDebugger().GetNotifyVoid()) {
           error_stream.PutCString("(void)\n");
@@ -494,7 +496,8 @@ bool CommandObjectExpression::EvaluateExpression(llvm::StringRef expr,
 
         result.SetStatus(eReturnStatusSuccessFinishResult);
       } else {
-        const char *error_cstr = result_valobj_sp->GetError().AsCString();
+        const char *error_cstr =
+            result_valobj_sp.value()->GetError().AsCString();
         if (error_cstr && error_cstr[0]) {
           const size_t error_cstr_len = strlen(error_cstr);
           const bool ends_with_newline = error_cstr[error_cstr_len - 1] == '\n';
diff --git a/lldb/source/Commands/CommandObjectFrame.cpp b/lldb/source/Commands/CommandObjectFrame.cpp
index e7cb861c2b01c63..ae87411aeb00994 100644
--- a/lldb/source/Commands/CommandObjectFrame.cpp
+++ b/lldb/source/Commands/CommandObjectFrame.cpp
@@ -137,7 +137,7 @@ class CommandObjectFrameDiagnose : public CommandObjectParsed {
     Thread *thread = m_exe_ctx.GetThreadPtr();
     StackFrameSP frame_sp = thread->GetSelectedFrame(SelectMostRelevantFrame);
 
-    ValueObjectSP valobj_sp;
+    std::optional<lldb::ValueObjectSP> valobj_sp;
 
     if (m_options.address) {
       if (m_options.reg || m_options.offset) {
@@ -170,15 +170,15 @@ class CommandObjectFrameDiagnose : public CommandObjectParsed {
                      Stream &stream) -> bool {
       const ValueObject::GetExpressionPathFormat format = ValueObject::
           GetExpressionPathFormat::eGetExpressionPathFormatHonorPointers;
-      valobj_sp->GetExpressionPath(stream, format);
+      valobj_sp.value()->GetExpressionPath(stream, format);
       stream.PutCString(" =");
       return true;
     };
 
     DumpValueObjectOptions options;
     options.SetDeclPrintingHelper(helper);
-    ValueObjectPrinter printer(valobj_sp.get(), &result.GetOutputStream(),
-                               options);
+    ValueObjectPrinter printer(valobj_sp.value().get(),
+                               &result.GetOutputStream(), options);
     printer.PrintValueObject();
   }
 
@@ -544,7 +544,7 @@ may even involve JITing and running code in the target program.)");
       result.AppendError(error.AsCString());
 
     }
-    ValueObjectSP valobj_sp;
+    std::optional<ValueObjectSP> valobj_sp;
 
     TypeSummaryImplSP summary_format_sp;
     if (!m_option_variable.summary.IsCurrentValueEmpty())
@@ -606,7 +606,7 @@ may even involve JITing and running code in the target program.)");
                                                 show_module))
                       s.PutCString(": ");
                   }
-                  valobj_sp->Dump(result.GetOutputStream(), options);
+                  valobj_sp.value()->Dump(result.GetOutputStream(), options);
                 }
               }
             } else {
@@ -643,12 +643,12 @@ may even involve JITing and running code in the target program.)");
 
               options.SetFormat(format);
               options.SetVariableFormatDisplayLanguage(
-                  valobj_sp->GetPreferredDisplayLanguage());
+                  valobj_sp.value()->GetPreferredDisplayLanguage());
 
               Stream &output_stream = result.GetOutputStream();
               options.SetRootValueObjectName(
-                  valobj_sp->GetParent() ? entry.c_str() : nullptr);
-              valobj_sp->Dump(output_stream, options);
+                  valobj_sp.value()->GetParent() ? entry.c_str() : nullptr);
+              valobj_sp.value()->Dump(output_stream, options);
             } else {
               if (auto error_cstr = error.AsCString(nullptr))
                 result.AppendError(error_cstr);
@@ -679,10 +679,11 @@ may even involve JITing and running code in the target program.)");
             if (valobj_sp) {
               // When dumping all variables, don't print any variables that are
               // not in scope to avoid extra unneeded output
-              if (valobj_sp->IsInScope()) {
-                if (!valobj_sp->GetTargetSP()
+              if (valobj_sp.value()->IsInScope()) {
+                if (!valobj_sp.value()
+                         ->GetTargetSP()
                          ->GetDisplayRuntimeSupportValues() &&
-                    valobj_sp->IsRuntimeSupportValue())
+                    valobj_sp.value()->IsRuntimeSupportValue())
                   continue;
 
                 if (!scope_string.empty())
@@ -696,10 +697,10 @@ may even involve JITing and running code in the target program.)");
 
                 options.SetFormat(format);
                 options.SetVariableFormatDisplayLanguage(
-                    valobj_sp->GetPreferredDisplayLanguage());
+                    valobj_sp.value()->GetPreferredDisplayLanguage());
                 options.SetRootValueObjectName(
                     var_sp ? var_sp->GetName().AsCString() : nullptr);
-                valobj_sp->Dump(result.GetOutputStream(), options);
+                valobj_sp.value()->Dump(result.GetOutputStream(), options);
               }
             }
           }
@@ -718,9 +719,10 @@ may even involve JITing and running code in the target program.)");
           for (auto &rec_value_sp : recognized_arg_list->GetObjects()) {
             options.SetFormat(m_option_format.GetFormat());
             options.SetVariableFormatDisplayLanguage(
-                rec_value_sp->GetPreferredDisplayLanguage());
-            options.SetRootValueObjectName(rec_value_sp->GetName().AsCString());
-            rec_value_sp->Dump(result.GetOutputStream(), options);
+                rec_value_sp.value()->GetPreferredDisplayLanguage());
+            options.SetRootValueObjectName(
+                rec_value_sp.value()->GetName().AsCString());
+            rec_value_sp.value()->Dump(result.GetOutputStream(), options);
           }
         }
       }
diff --git a/lldb/source/Commands/CommandObjectMemory.cpp b/lldb/source/Commands/CommandObjectMemory.cpp
index b78a0492cca558f..5e8192437588fd6 100644
--- a/lldb/source/Commands/CommandObjectMemory.cpp
+++ b/lldb/source/Commands/CommandObjectMemory.cpp
@@ -807,21 +807,14 @@ class CommandObjectMemoryRead : public CommandObjectParsed {
         name_strm.Printf("0x%" PRIx64, item_addr);
         ValueObjectSP valobj_sp(ValueObjectMemory::Create(
             exe_scope, name_strm.GetString(), address, compiler_type));
-        if (valobj_sp) {
-          Format format = m_format_options.GetFormat();
-          if (format != eFormatDefault)
-            valobj_sp->SetFormat(format);
+        Format format = m_format_options.GetFormat();
+        if (format != eFormatDefault)
+          valobj_sp->SetFormat(format);
 
-          DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(
-              eLanguageRuntimeDescriptionDisplayVerbosityFull, format));
+        DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(
+            eLanguageRuntimeDescriptionDisplayVerbosityFull, format));
 
-          valobj_sp->Dump(*output_stream_p, options);
-        } else {
-          result.AppendErrorWithFormat(
-              "failed to create a value object for: (%s) %s\n",
-              view_as_type_cstr, name_strm.GetData());
-          return;
-        }
+        valobj_sp->Dump(*output_stream_p, options);
       }
       return;
     }
@@ -1052,16 +1045,16 @@ class CommandObjectMemoryFind : public CommandObjectParsed {
       buffer.CopyData(str);
     } else if (m_memory_options.m_expr.OptionWasSet()) {
       StackFrame *frame = m_exe_ctx.GetFramePtr();
-      ValueObjectSP result_sp;
+      std::optional<lldb::ValueObjectSP> result_sp;
       if ((eExpressionCompleted ==
            process->GetTarget().EvaluateExpression(
                m_memory_options.m_expr.GetValueAs<llvm::StringRef>().value_or(
                    ""),
                frame, result_sp)) &&
           result_sp) {
-        uint64_t value = result_sp->GetValueAsUnsigned(0);
+        uint64_t value = result_sp.value()->GetValueAsUnsigned(0);
         std::optional<uint64_t> size =
-            result_sp->GetCompilerType().GetByteSize(nullptr);
+            result_sp.value()->GetCompilerType().GetByteSize(nullptr);
         if (!size)
           return;
         switch (*size) {
diff --git a/lldb/source/Commands/CommandObjectTarget.cpp b/lldb/source/Commands/CommandObjectTarget.cpp
index bc8bc51356c8caa..71a19e366481806 100644
--- a/lldb/source/Commands/CommandObjectTarget.cpp
+++ b/lldb/source/Commands/CommandObjectTarget.cpp
@@ -854,8 +854,7 @@ class CommandObjectTargetVariable : public CommandObjectParsed {
       ValueObjectSP valobj_sp(ValueObjectVariable::Create(
           exe_ctx.GetBestExecutionContextScope(), var_sp));
 
-      if (valobj_sp)
-        DumpValueObject(s, var_sp, valobj_sp, var_sp->GetName().GetCString());
+      DumpValueObject(s, var_sp, valobj_sp, var_sp->GetName().GetCString());
     }
   }
 
@@ -897,14 +896,14 @@ class CommandObjectTargetVariable : public CommandObjectParsed {
           for (uint32_t global_idx = 0; global_idx < matches; ++global_idx) {
             VariableSP var_sp(variable_list.GetVariableAtIndex(global_idx));
             if (var_sp) {
-              ValueObjectSP valobj_sp(
+              std::optional<ValueObjectSP> valobj_sp(
                   valobj_list.GetValueObjectAtIndex(global_idx));
               if (!valobj_sp)
                 valobj_sp = ValueObjectVariable::Create(
                     m_exe_ctx.GetBestExecutionContextScope(), var_sp);
 
               if (valobj_sp)
-                DumpValueObject(s, var_sp, valobj_sp,
+                DumpValueObject(s, var_sp, valobj_sp.value(),
                                 use_var_name ? var_sp->GetName().GetCString()
                                              : arg.c_str());
             }
diff --git a/lldb/source/Commands/CommandObjectThread.cpp b/lldb/source/Commands/CommandObjectThread.cpp
index a1e7e3f11361e76..1484b1690d53d16 100644
--- a/lldb/source/Commands/CommandObjectThread.cpp
+++ b/lldb/source/Commands/CommandObjectThread.cpp
@@ -1422,10 +1422,8 @@ class CommandObjectThreadException : public CommandObjectIterateOverThreads {
     }
 
     Stream &strm = result.GetOutputStream();
-    ValueObjectSP exception_object_sp = thread_sp->GetCurrentException();
-    if (exception_object_sp) {
-      exception_object_sp->Dump(strm);
-    }
+    if (auto exception_object_sp = thread_sp->GetCurrentException())
+      exception_object_sp.value()->Dump(strm);
 
     ThreadSP exception_thread_sp = thread_sp->GetCurrentExceptionBacktrace();
     if (exception_thread_sp && exception_thread_sp->IsValid()) {
@@ -1476,10 +1474,7 @@ class CommandObjectThreadSiginfo : public CommandObjectIterateOverThreads {
       return false;
     }
     ValueObjectSP exception_object_sp = thread_sp->GetSiginfoValue();
-    if (exception_object_sp)
-      exception_object_sp->Dump(strm);
-    else
-      strm.Printf("(no siginfo)\n");
+    exception_object_sp->Dump(strm);
     strm.PutChar('\n');
 
     return true;
@@ -1601,7 +1596,7 @@ class CommandObjectThreadReturn : public CommandObjectRaw {
       return;
     }
 
-    ValueObjectSP return_valobj_sp;
+    std::optional<ValueObjectSP> return_valobj_sp;
 
     StackFrameSP frame_sp = m_exe_ctx.GetFrameSP();
     uint32_t frame_idx = frame_sp->GetFrameIndex();
@@ -1625,7 +1620,7 @@ class CommandObjectThreadReturn : public CommandObjectRaw {
         if (return_valobj_sp)
           result.AppendErrorWithFormat(
               "Error evaluating result expression: %s",
-              return_valobj_sp->GetError().AsCString());
+              return_valobj_sp.value()->GetError().AsCString());
         else
           result.AppendErrorWithFormat(
               "Unknown error evaluating result expression.");
diff --git a/lldb/source/Commands/CommandObjectType.cpp b/lldb/source/Commands/CommandObjectType.cpp
index f76420f3cc6837f..5beadc42a666424 100644
--- a/lldb/source/Commands/CommandObjectType.cpp
+++ b/lldb/source/Commands/CommandObjectType.cpp
@@ -2855,28 +2855,30 @@ class CommandObjectFormatterInfo : public CommandObjectRaw {
 
     StackFrameSP frame_sp =
         thread->GetSelectedFrame(DoNoSelectMostRelevantFrame);
-    ValueObjectSP result_valobj_sp;
+    std::optional<ValueObjectSP> result_valobj_sp;
     EvaluateExpressionOptions options;
     lldb::ExpressionResults expr_result = target_sp->EvaluateExpression(
         command, frame_sp.get(), result_valobj_sp, options);
     if (expr_result == eExpressionCompleted && result_valobj_sp) {
       result_valobj_sp =
-          result_valobj_sp->GetQualifiedRepresentationIfAvailable(
+          result_valobj_sp.value()->GetQualifiedRepresentationIfAvailable(
               target_sp->GetPreferDynamicValue(),
               target_sp->GetEnableSyntheticValue());
       typename FormatterType::SharedPointer formatter_sp =
-          m_discovery_function(*result_valobj_sp);
+          m_discovery_function(*result_valobj_sp.value());
       if (formatter_sp) {
         std::string description(formatter_sp->GetDescription());
         result.GetOutputStream()
             << m_formatter_name << " applied to ("
-            << result_valobj_sp->GetDisplayTypeName().AsCString("<unknown>")
+            << result_valobj_sp.value()->GetDisplayTypeName().AsCString(
+                   "<unknown>")
             << ") " << command << " is: " << description << "\n";
         result.SetStatus(lldb::eReturnStatusSuccessFinishResult);
       } else {
         result.GetOutputStream()
             << "no " << m_formatter_name << " applies to ("
-            << result_valobj_sp->GetDisplayTypeName().AsCString("<unknown>")
+            << result_valobj_sp.value()->GetDisplayTypeName().AsCString(
+                   "<unknown>")
             << ") " << command << "\n";
         result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult);
       }
diff --git a/lldb/source/Commands/CommandObjectWatchpoint.cpp b/lldb/source/Commands/CommandObjectWatchpoint.cpp
index c80868d33905e92..f22affc6b2cfcc1 100644
--- a/lldb/source/Commands/CommandObjectWatchpoint.cpp
+++ b/lldb/source/Commands/CommandObjectWatchpoint.cpp
@@ -877,7 +877,7 @@ corresponding to the byte size of the data type.");
     size_t size = 0;
 
     VariableSP var_sp;
-    ValueObjectSP valobj_sp;
+    std::optional<ValueObjectSP> valobj_sp;
     Stream &output_stream = result.GetOutputStream();
 
     // A simple watch variable gesture allows only one argument.
@@ -914,15 +914,15 @@ corresponding to the byte size of the data type.");
 
     if (valobj_sp) {
       AddressType addr_type;
-      addr = valobj_sp->GetAddressOf(false, &addr_type);
+      addr = valobj_sp.value()->GetAddressOf(false, &addr_type);
       if (addr_type == eAddressTypeLoad) {
         // We're in business.
         // Find out the size of this variable.
         size = m_option_watchpoint.watch_size.GetCurrentValue() == 0
-                   ? valobj_sp->GetByteSize().value_or(0)
+                   ? valobj_sp.value()->GetByteSize().value_or(0)
                    : m_option_watchpoint.watch_size.GetCurrentValue();
       }
-      compiler_type = valobj_sp->GetCompilerType();
+      compiler_type = valobj_sp.value()->GetCompilerType();
     } else {
       const char *error_cstr = error.AsCString(nullptr);
       if (error_cstr)
@@ -1083,7 +1083,7 @@ class CommandObjectWatchpointSetExpression : public CommandObjectRaw {
     lldb::addr_t addr = 0;
     size_t size = 0;
 
-    ValueObjectSP valobj_sp;
+    std::optional<ValueObjectSP> valobj_sp;
 
     // Use expression evaluation to arrive at the address to watch.
     EvaluateExpressionOptions options;
@@ -1100,14 +1100,14 @@ class CommandObjectWatchpointSetExpression : public CommandObjectRaw {
     if (expr_result != eExpressionCompleted) {
       result.AppendError("expression evaluation of address to watch failed");
       result.AppendErrorWithFormat("expression evaluated: \n%s", expr.data());
-      if (valobj_sp && !valobj_sp->GetError().Success())
-        result.AppendError(valobj_sp->GetError().AsCString());
+      if (valobj_sp && valobj_sp.value()->GetError().Fail())
+        result.AppendError(valobj_sp.value()->GetError().AsCString());
       return;
     }
 
     // Get the address to watch.
     bool success = false;
-    addr = valobj_sp->GetValueAsUnsigned(0, &success);
+    addr = valobj_sp.value()->GetValueAsUnsigned(0, &success);
     if (!success) {
       result.AppendError("expression did not evaluate to an address");
       return;
@@ -1140,7 +1140,7 @@ class CommandObjectWatchpointSetExpression : public CommandObjectRaw {
     // Fetch the type from the value object, the type of the watched object is
     // the pointee type
     /// of the expression, so convert to that if we  found a valid type.
-    CompilerType compiler_type(valobj_sp->GetCompilerType());
+    CompilerType compiler_type(valobj_sp.value()->GetCompilerType());
 
     Status error;
     WatchpointSP watch_sp =
diff --git a/lldb/source/Core/FormatEntity.cpp b/lldb/source/Core/FormatEntity.cpp
index 94986457552d949..680cb0d44de6e59 100644
--- a/lldb/source/Core/FormatEntity.cpp
+++ b/lldb/source/Core/FormatEntity.cpp
@@ -608,8 +608,8 @@ static bool DumpRegister(Stream &s, StackFrame *frame, RegisterKind reg_kind,
   return false;
 }
 
-static ValueObjectSP ExpandIndexedExpression(ValueObject *valobj, size_t index,
-                                             bool deref_pointer) {
+static std::optional<ValueObjectSP>
+ExpandIndexedExpression(ValueObject *valobj, size_t index, bool deref_pointer) {
   Log *log = GetLog(LLDBLog::DataFormatters);
   std::string name_to_deref = llvm::formatv("[{0}]", index);
   LLDB_LOG(log, "[ExpandIndexedExpression] name to deref: {0}", name_to_deref);
@@ -619,7 +619,7 @@ static ValueObjectSP ExpandIndexedExpression(ValueObject *valobj, size_t index,
   ValueObject::ExpressionPathAftermath what_next =
       (deref_pointer ? ValueObject::eExpressionPathAftermathDereference
                      : ValueObject::eExpressionPathAftermathNothing);
-  ValueObjectSP item = valobj->GetValueForExpressionPath(
+  std::optional<ValueObjectSP> item = valobj->GetValueForExpressionPath(
       name_to_deref, &reason_to_stop, &final_value_type, options, &what_next);
   if (!item) {
     LLDB_LOGF(log,
@@ -690,8 +690,9 @@ static bool DumpValue(Stream &s, const SymbolContext *sc,
     custom_format = entry.fmt;
     val_obj_display = (ValueObject::ValueObjectRepresentationStyle)entry.number;
     if (!valobj->IsSynthetic()) {
-      valobj = valobj->GetSyntheticValue().get();
-      if (valobj == nullptr)
+      if (std::optional<ValueObjectSP> temp = valobj->GetSyntheticValue())
+        valobj = temp.value().get();
+      else
         return false;
     }
     break;
@@ -756,7 +757,7 @@ static bool DumpValue(Stream &s, const SymbolContext *sc,
         valobj
             ->GetValueForExpressionPath(expr_path.c_str(), &reason_to_stop,
                                         &final_value_type, options, &what_next)
-            .get();
+            ->get();
 
     if (!target) {
       LLDB_LOGF(log,
@@ -789,13 +790,13 @@ static bool DumpValue(Stream &s, const SymbolContext *sc,
     // I have not deref-ed yet, let's do it
     // this happens when we are not going through
     // GetValueForVariableExpressionPath to get to the target ValueObject
-    Status error;
-    target = target->Dereference(error).get();
-    if (error.Fail()) {
+    ValueObjectSP temp = target->Dereference();
+    if (temp->GetError().Fail()) {
       LLDB_LOGF(log, "[Debugger::FormatPrompt] ERROR: %s\n",
-                error.AsCString("unknown"));
+                temp->GetError().AsCString("unknown"));
       return false;
     }
+    target = temp.get();
     do_deref_pointer = false;
   }
 
@@ -933,7 +934,7 @@ static bool DumpValue(Stream &s, const SymbolContext *sc,
 
     bool success = true;
     for (int64_t index = index_lower; index <= index_higher; ++index) {
-      ValueObject *item = ExpandIndexedExpression(target, index, false).get();
+      ValueObject *item = ExpandIndexedExpression(target, index, false)->get();
 
       if (!item) {
         LLDB_LOGF(log,
@@ -1343,10 +1344,10 @@ bool FormatEntity::Format(const Entry &entry, Stream &s,
       if (thread) {
         StopInfoSP stop_info_sp = thread->GetStopInfo();
         if (stop_info_sp && stop_info_sp->IsValid()) {
-          ValueObjectSP return_valobj_sp =
+          std::optional<ValueObjectSP> return_valobj_sp =
               StopInfo::GetReturnValueObject(stop_info_sp);
           if (return_valobj_sp) {
-            return_valobj_sp->Dump(s);
+            return_valobj_sp.value()->Dump(s);
             return true;
           }
         }
@@ -1363,7 +1364,7 @@ bool FormatEntity::Format(const Entry &entry, Stream &s,
           ExpressionVariableSP expression_var_sp =
               StopInfo::GetExpressionVariable(stop_info_sp);
           if (expression_var_sp && expression_var_sp->GetValueObject()) {
-            expression_var_sp->GetValueObject()->Dump(s);
+            expression_var_sp->GetValueObject().value()->Dump(s);
             return true;
           }
         }
diff --git a/lldb/source/Core/IOHandlerCursesGUI.cpp b/lldb/source/Core/IOHandlerCursesGUI.cpp
index 620e68a28510ef9..fb0a41fe6939548 100644
--- a/lldb/source/Core/IOHandlerCursesGUI.cpp
+++ b/lldb/source/Core/IOHandlerCursesGUI.cpp
@@ -4496,8 +4496,7 @@ struct Row {
   std::vector<Row> children;
 
   Row(const ValueObjectSP &v, Row *p)
-      : value(v), parent(p),
-        might_have_children(v ? v->MightHaveChildren() : false) {}
+      : value(v), parent(p), might_have_children(v->MightHaveChildren()) {}
 
   size_t GetDepth() const {
     if (parent)
@@ -4517,11 +4516,12 @@ struct Row {
     if (!calculated_children) {
       children.clear();
       calculated_children = true;
-      ValueObjectSP valobj = value.GetSP();
+      std::optional<ValueObjectSP> valobj = value.GetSP();
       if (valobj) {
-        const size_t num_children = valobj->GetNumChildren();
+        const size_t num_children = valobj.value()->GetNumChildren();
         for (size_t i = 0; i < num_children; ++i) {
-          children.push_back(Row(valobj->GetChildAtIndex(i), this));
+          if (auto child = valobj.value()->GetChildAtIndex(i))
+            children.push_back(Row(child.value(), this));
         }
       }
     }
@@ -5549,7 +5549,7 @@ class ValueObjectListDelegate : public WindowDelegate {
     m_num_rows = 0;
     m_rows.clear();
     for (auto &valobj_sp : valobj_list.GetObjects())
-      m_rows.push_back(Row(valobj_sp, nullptr));
+      m_rows.push_back(Row(valobj_sp.value(), nullptr));
   }
 
   bool WindowDelegateDraw(Window &window, bool force) override {
@@ -5640,7 +5640,7 @@ class ValueObjectListDelegate : public WindowDelegate {
       if (m_selected_row) {
         auto valobj_sp = m_selected_row->value.GetSP();
         if (valobj_sp)
-          valobj_sp->SetFormat(FormatForChar(c));
+          valobj_sp.value()->SetFormat(FormatForChar(c));
       }
       return eKeyHandled;
 
@@ -5765,11 +5765,13 @@ class ValueObjectListDelegate : public WindowDelegate {
 
   bool DisplayRowObject(Window &window, Row &row, DisplayOptions &options,
                         bool highlight, bool last_child) {
-    ValueObject *valobj = row.value.GetSP().get();
+    std::optional<ValueObjectSP> valobj_opt = row.value.GetSP();
 
-    if (valobj == nullptr)
+    if (!valobj_opt)
       return false;
 
+    ValueObject *valobj = row.value.GetSP()->get();
+
     const char *type_name =
         options.show_types ? valobj->GetTypeName().GetCString() : nullptr;
     const char *name = valobj->GetName().GetCString();
@@ -5933,14 +5935,15 @@ class FrameVariablesWindowDelegate : public ValueObjectListDelegate {
         if (locals) {
           const DynamicValueType use_dynamic = eDynamicDontRunTarget;
           for (const VariableSP &local_sp : *locals) {
-            ValueObjectSP value_sp =
+            std::optional<ValueObjectSP> value_sp =
                 frame->GetValueObjectForFrameVariable(local_sp, use_dynamic);
             if (value_sp) {
-              ValueObjectSP synthetic_value_sp = value_sp->GetSyntheticValue();
+              std::optional<ValueObjectSP> synthetic_value_sp =
+                  value_sp.value()->GetSyntheticValue();
               if (synthetic_value_sp)
-                local_values.Append(synthetic_value_sp);
+                local_values.Append(synthetic_value_sp.value());
               else
-                local_values.Append(value_sp);
+                local_values.Append(value_sp.value());
             }
           }
           // Update the values
diff --git a/lldb/source/Core/ValueObject.cpp b/lldb/source/Core/ValueObject.cpp
index b2a6d9412ab40b6..341aee80948aa96 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<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,21 +389,19 @@ ValueObjectSP ValueObject::GetChildAtIndex(size_t idx, bool can_create) {
     if (child != nullptr)
       return child->GetSP();
   }
-  return child_sp;
+  return {};
 }
 
-lldb::ValueObjectSP
+std::optional<ValueObjectSP>
 ValueObject::GetChildAtNamePath(llvm::ArrayRef<llvm::StringRef> names) {
-  if (names.size() == 0)
-    return GetSP();
-  ValueObjectSP root(GetSP());
+  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) {
@@ -412,8 +410,8 @@ size_t ValueObject::GetIndexOfChildWithName(llvm::StringRef name) {
                                                    omit_empty_base_classes);
 }
 
-ValueObjectSP ValueObject::GetChildMemberWithName(llvm::StringRef name,
-                                                  bool can_create) {
+std::optional<ValueObjectSP>
+ValueObject::GetChildMemberWithName(llvm::StringRef name, bool can_create) {
   // We may need to update our value if we are dynamic.
   if (IsPossibleDynamicType())
     UpdateValueIfNeeded(false);
@@ -425,19 +423,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) {
@@ -519,10 +519,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;
     }
   }
 
@@ -640,17 +640,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) */
@@ -1185,12 +1185,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);
           }
@@ -1226,12 +1226,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);
           }
 
@@ -1523,13 +1523,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<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() {
@@ -1581,83 +1581,79 @@ 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;
+std::optional<ValueObjectSP>
+ValueObject::GetSyntheticArrayMember(size_t index, bool can_create) {
   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;
-      }
+    if (auto existing_synthetic_child = GetSyntheticChild(index_const_str))
+      return existing_synthetic_child;
+
+    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);
+      ValueObjectSP 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;
     }
   }
-  return synthetic_child_sp;
+  return {};
 }
 
-ValueObjectSP ValueObject::GetSyntheticBitFieldChild(uint32_t from, uint32_t to,
-                                                     bool can_create) {
-  ValueObjectSP synthetic_child_sp;
+std::optional<ValueObjectSP>
+ValueObject::GetSyntheticBitFieldChild(uint32_t from, uint32_t to,
+                                       bool can_create) {
   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;
-      }
+    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) {
+      AddSyntheticChild(index_const_str, synthetic_child);
+      ValueObjectSP 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;
     }
   }
-  return synthetic_child_sp;
+  return {};
 }
 
-ValueObjectSP ValueObject::GetSyntheticChildAtOffset(
+std::optional<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 {};
@@ -1670,21 +1666,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<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",
@@ -1694,10 +1688,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 {};
@@ -1712,11 +1704,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;
 }
 
@@ -1734,31 +1727,29 @@ static const char *SkipLeadingExpressionPathSeparators(const char *expression) {
   return expression;
 }
 
-ValueObjectSP
+std::optional<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 synthetic_child_sp = GetValueForExpressionPath(
+      expression, nullptr, nullptr,
+      GetValueForExpressionPathOptions().SetSyntheticChildrenTraversal(
+          GetValueForExpressionPathOptions::SyntheticChildrenTraversal::None));
+
+  // Cache the value if we got one back...
+  if (synthetic_child_sp) {
+    // 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.value().get());
+    synthetic_child_sp.value()->SetName(
+        ConstString(SkipLeadingExpressionPathSeparators(expression)));
   }
   return synthetic_child_sp;
 }
@@ -1798,9 +1789,10 @@ void ValueObject::CalculateDynamicValue(DynamicValueType use_dynamic) {
   }
 }
 
-ValueObjectSP ValueObject::GetDynamicValue(DynamicValueType use_dynamic) {
+std::optional<ValueObjectSP>
+ValueObject::GetDynamicValue(DynamicValueType use_dynamic) {
   if (use_dynamic == eNoDynamicValues)
-    return ValueObjectSP();
+    return {};
 
   if (!IsDynamic() && m_dynamic_value == nullptr) {
     CalculateDynamicValue(use_dynamic);
@@ -1808,16 +1800,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<ValueObjectSP> ValueObject::GetSyntheticValue() {
   CalculateSyntheticValue();
 
   if (m_synthetic_value)
     return m_synthetic_value->GetSP();
   else
-    return ValueObjectSP();
+    return {};
 }
 
 bool ValueObject::HasSyntheticValue() {
@@ -1951,7 +1943,7 @@ void ValueObject::GetExpressionPath(Stream &s,
   }
 }
 
-ValueObjectSP ValueObject::GetValueForExpressionPath(
+std::optional<ValueObjectSP> ValueObject::GetValueForExpressionPath(
     llvm::StringRef expression, ExpressionPathScanEndReason *reason_to_stop,
     ExpressionPathEndResultType *final_value_type,
     const GetValueForExpressionPathOptions &options,
@@ -1964,7 +1956,7 @@ ValueObjectSP ValueObject::GetValueForExpressionPath(
   ExpressionPathAftermath dummy_final_task_on_target =
       ValueObject::eExpressionPathAftermathNothing;
 
-  ValueObjectSP ret_val = GetValueForExpressionPath_Impl(
+  auto 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
@@ -1974,7 +1966,7 @@ ValueObjectSP ValueObject::GetValueForExpressionPath(
       *final_task_on_target == ValueObject::eExpressionPathAftermathNothing)
     return ret_val;
 
-  if (ret_val.get() &&
+  if (ret_val &&
       ((final_value_type ? *final_value_type : dummy_final_value_type) ==
        eExpressionPathEndResultTypePlain)) // I can only deref and takeaddress
                                            // of plain objects
@@ -1982,15 +1974,14 @@ ValueObjectSP ValueObject::GetValueForExpressionPath(
     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()) {
+      auto final_value = ret_val.value()->Dereference();
+      if (final_value->GetError().Fail()) {
         if (reason_to_stop)
           *reason_to_stop =
               ValueObject::eExpressionPathScanEndReasonDereferencingFailed;
         if (final_value_type)
           *final_value_type = ValueObject::eExpressionPathEndResultTypeInvalid;
-        return ValueObjectSP();
+        return {};
       } else {
         if (final_task_on_target)
           *final_task_on_target = ValueObject::eExpressionPathAftermathNothing;
@@ -1999,15 +1990,14 @@ ValueObjectSP ValueObject::GetValueForExpressionPath(
     }
     if (*final_task_on_target ==
         ValueObject::eExpressionPathAftermathTakeAddress) {
-      Status error;
-      ValueObjectSP final_value = ret_val->AddressOf(error);
-      if (error.Fail() || !final_value.get()) {
+      ValueObjectSP final_value = ret_val.value()->AddressOf();
+      if (final_value->GetError().Fail()) {
         if (reason_to_stop)
           *reason_to_stop =
               ValueObject::eExpressionPathScanEndReasonTakingAddressFailed;
         if (final_value_type)
           *final_value_type = ValueObject::eExpressionPathEndResultTypeInvalid;
-        return ValueObjectSP();
+        return {};
       } else {
         if (final_task_on_target)
           *final_task_on_target = ValueObject::eExpressionPathAftermathNothing;
@@ -2019,16 +2009,13 @@ ValueObjectSP ValueObject::GetValueForExpressionPath(
                   // you know I did not do it
 }
 
-ValueObjectSP ValueObject::GetValueForExpressionPath_Impl(
+std::optional<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) {
@@ -2060,7 +2047,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
@@ -2070,13 +2057,13 @@ ValueObjectSP ValueObject::GetValueForExpressionPath_Impl(
         *reason_to_stop =
             ValueObject::eExpressionPathScanEndReasonFragileIVarNotAllowed;
         *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
-        return ValueObjectSP();
+        return {};
       }
       if (!temp_expression.starts_with(">")) {
         *reason_to_stop =
             ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol;
         *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
-        return ValueObjectSP();
+        return {};
       }
     }
       [[fallthrough]];
@@ -2092,7 +2079,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 >
 
@@ -2101,15 +2088,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::
@@ -2118,33 +2104,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;
           }
@@ -2153,28 +2135,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;
@@ -2186,33 +2167,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;
           }
@@ -2221,9 +2198,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;
@@ -2231,7 +2208,7 @@ ValueObjectSP ValueObject::GetValueForExpressionPath_Impl(
           *reason_to_stop =
               ValueObject::eExpressionPathScanEndReasonNoSuchChild;
           *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
-          return nullptr;
+          return {};
         }
       }
       break;
@@ -2252,7 +2229,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
@@ -2261,7 +2238,7 @@ ValueObjectSP ValueObject::GetValueForExpressionPath_Impl(
           *reason_to_stop =
               ValueObject::eExpressionPathScanEndReasonRangeOperatorNotAllowed;
           *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
-          return ValueObjectSP();
+          return {};
         }
       }
       if (temp_expression[1] ==
@@ -2271,7 +2248,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
         {
@@ -2290,7 +2267,7 @@ ValueObjectSP ValueObject::GetValueForExpressionPath_Impl(
         *reason_to_stop =
             ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol;
         *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
-        return nullptr;
+        return {};
       }
 
       llvm::StringRef bracket_expr =
@@ -2309,21 +2286,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;
@@ -2332,7 +2311,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 ==
@@ -2347,18 +2326,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<ValueObjectSP> child;
             if (root->GetCompilerType().GetMinimumLanguage() ==
                     eLanguageTypeObjC &&
                 pointee_compiler_type_info.AllClear(eTypeIsPointer) &&
@@ -2369,15 +2348,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;
@@ -2385,28 +2365,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;
@@ -2419,29 +2401,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;
@@ -2451,7 +2428,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
@@ -2463,7 +2440,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
@@ -2472,13 +2449,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;
@@ -2492,13 +2471,12 @@ ValueObjectSP ValueObject::GetValueForExpressionPath_Impl(
                    *what_next ==
                        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;
@@ -2517,7 +2495,7 @@ ValueObjectSP ValueObject::GetValueForExpressionPath_Impl(
       *reason_to_stop =
           ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol;
       *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
-      return nullptr;
+      return {};
     }
     }
   }
@@ -2531,8 +2509,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());
 
@@ -2546,51 +2522,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();
 
@@ -2654,19 +2623,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>"),
@@ -2675,26 +2646,42 @@ 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) {
+
+  StreamString expr_path_strm;
+  GetExpressionPath(expr_path_strm);
+
+  Status error;
+  ExecutionContext exe_ctx(GetExecutionContextRef());
+  auto scope = exe_ctx.GetBestExecutionContextScope();
+
+  if (addr != LLDB_INVALID_ADDRESS) {
     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;
+      return ValueObjectConstResult::Create(scope, error);
+    }
+    case eAddressTypeHost: {
+      error.SetErrorStringWithFormat("'%s' is in host process (LLDB) memory",
+                                     expr_path_strm.GetData());
+      return ValueObjectConstResult::Create(scope, error);
+    }
 
     case eAddressTypeFile:
     case eAddressTypeLoad: {
@@ -2703,23 +2690,26 @@ ValueObjectSP ValueObject::AddressOf(Status &error) {
         std::string name(1, '&');
         name.append(m_name.AsCString(""));
         ExecutionContext exe_ctx(GetExecutionContextRef());
-        m_addr_of_valobj_sp = ValueObjectConstResult::Create(
+
+        ValueObjectSP value_object_sp = ValueObjectConstResult::Create(
             exe_ctx.GetBestExecutionContextScope(),
             compiler_type.GetPointerType(), ConstString(name.c_str()), addr,
             eAddressTypeInvalid, m_data.GetAddressByteSize());
+        m_addr_of_valobj_sp = value_object_sp;
+        return value_object_sp;
       }
-    } break;
-    default:
-      break;
+      error.SetErrorStringWithFormat("'%s' doesn't have a compiler type",
+                                     expr_path_strm.GetData());
+      return ValueObjectConstResult::Create(scope, error);
+    }
     }
   } else {
     StreamString expr_path_strm;
     GetExpressionPath(expr_path_strm);
     error.SetErrorStringWithFormat("'%s' doesn't have a valid address",
                                    expr_path_strm.GetData());
+    return ValueObjectConstResult::Create(scope, error);
   }
-
-  return m_addr_of_valobj_sp;
 }
 
 ValueObjectSP ValueObject::DoCast(const CompilerType &compiler_type) {
@@ -2748,37 +2738,36 @@ ValueObjectSP ValueObject::Cast(const CompilerType &compiler_type) {
                        error);
 }
 
-lldb::ValueObjectSP ValueObject::Clone(ConstString new_name) {
+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<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<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() {}
@@ -2940,7 +2929,7 @@ SymbolContextScope *ValueObject::GetSymbolContextScope() {
   return nullptr;
 }
 
-lldb::ValueObjectSP
+std::optional<ValueObjectSP>
 ValueObject::CreateValueObjectFromExpression(llvm::StringRef name,
                                              llvm::StringRef expression,
                                              const ExecutionContext &exe_ctx) {
@@ -2948,10 +2937,10 @@ ValueObject::CreateValueObjectFromExpression(llvm::StringRef name,
                                          EvaluateExpressionOptions());
 }
 
-lldb::ValueObjectSP ValueObject::CreateValueObjectFromExpression(
+std::optional<ValueObjectSP> ValueObject::CreateValueObjectFromExpression(
     llvm::StringRef name, llvm::StringRef expression,
     const ExecutionContext &exe_ctx, const EvaluateExpressionOptions &options) {
-  lldb::ValueObjectSP retval_sp;
+  std::optional<ValueObjectSP> retval_sp;
   lldb::TargetSP target_sp(exe_ctx.GetTargetSP());
   if (!target_sp)
     return retval_sp;
@@ -2960,11 +2949,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) {
@@ -2972,33 +2961,30 @@ lldb::ValueObjectSP ValueObject::CreateValueObjectFromAddress(
     if (pointer_type) {
       lldb::DataBufferSP buffer(
           new lldb_private::DataBufferHeap(&address, sizeof(lldb::addr_t)));
-      lldb::ValueObjectSP ptr_result_valobj_sp(ValueObjectConstResult::Create(
+      ValueObjectSP ptr_result_valobj_sp(ValueObjectConstResult::Create(
           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(
+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(
+  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;
 }
@@ -3090,22 +3076,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();
 
@@ -3120,6 +3104,6 @@ ValueObjectSP ValueObject::Persist() {
   return persistent_var_sp->GetValueObject();
 }
 
-lldb::ValueObjectSP ValueObject::GetVTable() {
+ValueObjectSP ValueObject::GetVTable() {
   return ValueObjectVTable::Create(*this);
 }
diff --git a/lldb/source/Core/ValueObjectConstResult.cpp b/lldb/source/Core/ValueObjectConstResult.cpp
index 693da1a551f8eb1..05edacbfe345d07 100644
--- a/lldb/source/Core/ValueObjectConstResult.cpp
+++ b/lldb/source/Core/ValueObjectConstResult.cpp
@@ -244,19 +244,21 @@ bool ValueObjectConstResult::IsInScope() {
   return true;
 }
 
-lldb::ValueObjectSP ValueObjectConstResult::Dereference(Status &error) {
-  return m_impl.Dereference(error);
+lldb::ValueObjectSP ValueObjectConstResult::Dereference() {
+  return m_impl.Dereference();
 }
 
-lldb::ValueObjectSP ValueObjectConstResult::GetSyntheticChildAtOffset(
-    uint32_t offset, const CompilerType &type, bool can_create,
-    ConstString name_const_str) {
+std::optional<lldb::ValueObjectSP>
+ValueObjectConstResult::GetSyntheticChildAtOffset(uint32_t offset,
+                                                  const CompilerType &type,
+                                                  bool can_create,
+                                                  ConstString name_const_str) {
   return m_impl.GetSyntheticChildAtOffset(offset, type, can_create,
                                           name_const_str);
 }
 
-lldb::ValueObjectSP ValueObjectConstResult::AddressOf(Status &error) {
-  return m_impl.AddressOf(error);
+lldb::ValueObjectSP ValueObjectConstResult::AddressOf() {
+  return m_impl.AddressOf();
 }
 
 lldb::addr_t ValueObjectConstResult::GetAddressOf(bool scalar_is_load_address,
@@ -276,7 +278,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 +292,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/ValueObjectConstResultCast.cpp b/lldb/source/Core/ValueObjectConstResultCast.cpp
index fceb2635f876f0a..57c711b8b543c59 100644
--- a/lldb/source/Core/ValueObjectConstResultCast.cpp
+++ b/lldb/source/Core/ValueObjectConstResultCast.cpp
@@ -29,19 +29,20 @@ ValueObjectConstResultCast::ValueObjectConstResultCast(
 
 ValueObjectConstResultCast::~ValueObjectConstResultCast() = default;
 
-lldb::ValueObjectSP ValueObjectConstResultCast::Dereference(Status &error) {
-  return m_impl.Dereference(error);
+lldb::ValueObjectSP ValueObjectConstResultCast::Dereference() {
+  return m_impl.Dereference();
 }
 
-lldb::ValueObjectSP ValueObjectConstResultCast::GetSyntheticChildAtOffset(
+std::optional<lldb::ValueObjectSP>
+ValueObjectConstResultCast::GetSyntheticChildAtOffset(
     uint32_t offset, const CompilerType &type, bool can_create,
     ConstString name_const_str) {
   return m_impl.GetSyntheticChildAtOffset(offset, type, can_create,
                                           name_const_str);
 }
 
-lldb::ValueObjectSP ValueObjectConstResultCast::AddressOf(Status &error) {
-  return m_impl.AddressOf(error);
+lldb::ValueObjectSP ValueObjectConstResultCast::AddressOf() {
+  return m_impl.AddressOf();
 }
 
 ValueObject *ValueObjectConstResultCast::CreateChildAtIndex(
diff --git a/lldb/source/Core/ValueObjectConstResultChild.cpp b/lldb/source/Core/ValueObjectConstResultChild.cpp
index 36bf11a0b73af27..a789702774a52ca 100644
--- a/lldb/source/Core/ValueObjectConstResultChild.cpp
+++ b/lldb/source/Core/ValueObjectConstResultChild.cpp
@@ -36,19 +36,20 @@ ValueObjectConstResultChild::ValueObjectConstResultChild(
 
 ValueObjectConstResultChild::~ValueObjectConstResultChild() = default;
 
-lldb::ValueObjectSP ValueObjectConstResultChild::Dereference(Status &error) {
-  return m_impl.Dereference(error);
+lldb::ValueObjectSP ValueObjectConstResultChild::Dereference() {
+  return m_impl.Dereference();
 }
 
-lldb::ValueObjectSP ValueObjectConstResultChild::GetSyntheticChildAtOffset(
+std::optional<lldb::ValueObjectSP>
+ValueObjectConstResultChild::GetSyntheticChildAtOffset(
     uint32_t offset, const CompilerType &type, bool can_create,
     ConstString name_const_str) {
   return m_impl.GetSyntheticChildAtOffset(offset, type, can_create,
                                           name_const_str);
 }
 
-lldb::ValueObjectSP ValueObjectConstResultChild::AddressOf(Status &error) {
-  return m_impl.AddressOf(error);
+lldb::ValueObjectSP ValueObjectConstResultChild::AddressOf() {
+  return m_impl.AddressOf();
 }
 
 lldb::addr_t ValueObjectConstResultChild::GetAddressOf(
diff --git a/lldb/source/Core/ValueObjectConstResultImpl.cpp b/lldb/source/Core/ValueObjectConstResultImpl.cpp
index e2db3ace19247b0..cd26f6873e34662 100644
--- a/lldb/source/Core/ValueObjectConstResultImpl.cpp
+++ b/lldb/source/Core/ValueObjectConstResultImpl.cpp
@@ -37,11 +37,15 @@ ValueObjectConstResultImpl::ValueObjectConstResultImpl(
       m_live_address_type(eAddressTypeLoad),
       m_address_of_backend() {}
 
-lldb::ValueObjectSP ValueObjectConstResultImpl::Dereference(Status &error) {
-  if (m_impl_backend == nullptr)
-    return lldb::ValueObjectSP();
+lldb::ValueObjectSP ValueObjectConstResultImpl::Dereference() {
+  if (m_impl_backend == nullptr) {
+    Status error;
+    error.SetErrorString("Unable to dereference result because the "
+                         "implementation details backend is null.");
+    return ValueObjectConstResult::Create(nullptr, error);
+  }
 
-  return m_impl_backend->ValueObject::Dereference(error);
+  return m_impl_backend->ValueObject::Dereference();
 }
 
 ValueObject *ValueObjectConstResultImpl::CreateChildAtIndex(
@@ -109,22 +113,28 @@ ValueObject *ValueObjectConstResultImpl::CreateChildAtIndex(
   return valobj;
 }
 
-lldb::ValueObjectSP ValueObjectConstResultImpl::GetSyntheticChildAtOffset(
+std::optional<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);
 }
 
-lldb::ValueObjectSP ValueObjectConstResultImpl::AddressOf(Status &error) {
-  if (m_address_of_backend.get() != nullptr)
-    return m_address_of_backend;
+lldb::ValueObjectSP ValueObjectConstResultImpl::AddressOf() {
+  if (m_address_of_backend)
+    return m_address_of_backend.value();
+
+  if (m_impl_backend == nullptr) {
+    Status error;
+    error.SetErrorString("Unable to get address because the implementation "
+                         "details backend is null.");
+    return ValueObjectConstResult::Create(nullptr, error);
+  }
 
-  if (m_impl_backend == nullptr)
-    return lldb::ValueObjectSP();
   if (m_live_address != LLDB_INVALID_ADDRESS) {
     CompilerType compiler_type(m_impl_backend->GetCompilerType());
 
@@ -139,18 +149,23 @@ lldb::ValueObjectSP ValueObjectConstResultImpl::AddressOf(Status &error) {
         ConstString(new_name.c_str()), buffer, endian::InlHostByteOrder(),
         exe_ctx.GetAddressByteSize());
 
-    m_address_of_backend->GetValue().SetValueType(Value::ValueType::Scalar);
-    m_address_of_backend->GetValue().GetScalar() = m_live_address;
+    m_address_of_backend.value()->GetValue().SetValueType(
+        Value::ValueType::Scalar);
+    m_address_of_backend.value()->GetValue().GetScalar() = m_live_address;
 
-    return m_address_of_backend;
+    return m_address_of_backend.value();
   } else
-    return m_impl_backend->ValueObject::AddressOf(error);
+    return m_impl_backend->ValueObject::AddressOf();
 }
 
 lldb::ValueObjectSP
 ValueObjectConstResultImpl::Cast(const CompilerType &compiler_type) {
-  if (m_impl_backend == nullptr)
-    return lldb::ValueObjectSP();
+  if (m_impl_backend == nullptr) {
+    Status error;
+    error.SetErrorString(
+        "Unable to cast because the implementation details backend is null.");
+    return ValueObjectConstResult::Create(nullptr, error);
+  }
 
   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 28907261f0a60e8..5f56393d3b07181 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 {};
+
+  std::optional<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;
-    }
+    ValueObject *valobj = (*pos)->get();
+    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;
-    }
+    ValueObject *valobj = (*pos)->get();
+    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;
-    }
+    ValueObject *valobj = (*pos)->get();
+    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 c2b84c113473592..569f6b686ab8a26 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 43bc532c4a0410b..cdc9cc29eed900a 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 af7f976a6d2722f..7c6a51ab641773c 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/FormatManager.cpp b/lldb/source/DataFormatters/FormatManager.cpp
index f1f135de32ca874..b540c231d5e118c 100644
--- a/lldb/source/DataFormatters/FormatManager.cpp
+++ b/lldb/source/DataFormatters/FormatManager.cpp
@@ -283,10 +283,9 @@ void FormatManager::GetPossibleMatches(
     // if all else fails, go to static type
     if (valobj.IsDynamic()) {
       lldb::ValueObjectSP static_value_sp(valobj.GetStaticValue());
-      if (static_value_sp)
-        GetPossibleMatches(*static_value_sp.get(),
-                           static_value_sp->GetCompilerType(), use_dynamic,
-                           entries, current_flags, true);
+      GetPossibleMatches(*static_value_sp.get(),
+                         static_value_sp->GetCompilerType(), use_dynamic,
+                         entries, current_flags, true);
     }
   }
 }
@@ -476,15 +475,16 @@ bool FormatManager::ShouldPrintAsOneLiner(ValueObject &valobj) {
 
   for (size_t idx = 0; idx < valobj.GetNumChildren(); idx++) {
     bool is_synth_val = false;
-    ValueObjectSP child_sp(valobj.GetChildAtIndex(idx));
+    std::optional<ValueObjectSP> child_sp(valobj.GetChildAtIndex(idx));
     // something is wrong here - bail out
     if (!child_sp)
       return false;
 
     // also ask the child's type if it has any opinion
-    CompilerType child_compiler_type(child_sp->GetCompilerType());
+    CompilerType child_compiler_type(child_sp.value()->GetCompilerType());
     if (child_compiler_type.IsValid()) {
-      switch (child_compiler_type.ShouldPrintAsOneLiner(child_sp.get())) {
+      switch (
+          child_compiler_type.ShouldPrintAsOneLiner(child_sp.value().get())) {
       case eLazyBoolYes:
       // an opinion of yes is only binding for the child, so keep going
       case eLazyBoolCalculate:
@@ -497,20 +497,21 @@ bool FormatManager::ShouldPrintAsOneLiner(ValueObject &valobj) {
 
     // if we decided to define synthetic children for a type, we probably care
     // enough to show them, but avoid nesting children in children
-    if (child_sp->GetSyntheticChildren().get() != nullptr) {
-      ValueObjectSP synth_sp(child_sp->GetSyntheticValue());
+    if (child_sp.value()->GetSyntheticChildren().get() != nullptr) {
+      std::optional<ValueObjectSP> synth_sp(
+          child_sp.value()->GetSyntheticValue());
       // wait.. wat? just get out of here..
       if (!synth_sp)
         return false;
       // but if we only have them to provide a value, keep going
-      if (!synth_sp->MightHaveChildren() &&
-          synth_sp->DoesProvideSyntheticValue())
+      if (!synth_sp.value()->MightHaveChildren() &&
+          synth_sp.value()->DoesProvideSyntheticValue())
         is_synth_val = true;
       else
         return false;
     }
 
-    total_children_name_len += child_sp->GetName().GetLength();
+    total_children_name_len += child_sp.value()->GetName().GetLength();
 
     // 50 itself is a "randomly" chosen number - the idea is that
     // overly long structs should not get this treatment
@@ -519,20 +520,22 @@ bool FormatManager::ShouldPrintAsOneLiner(ValueObject &valobj) {
       return false;
 
     // if a summary is there..
-    if (child_sp->GetSummaryFormat()) {
+    if (child_sp.value()->GetSummaryFormat()) {
       // and it wants children, then bail out
-      if (child_sp->GetSummaryFormat()->DoesPrintChildren(child_sp.get()))
+      if (child_sp.value()->GetSummaryFormat()->DoesPrintChildren(
+              child_sp->get()))
         return false;
     }
 
     // if this child has children..
-    if (child_sp->GetNumChildren()) {
+    if (child_sp.value()->GetNumChildren()) {
       // ...and no summary...
       // (if it had a summary and the summary wanted children, we would have
       // bailed out anyway
       //  so this only makes us bail out if this has no summary and we would
       //  then print children)
-      if (!child_sp->GetSummaryFormat() && !is_synth_val) // but again only do
+      if (!child_sp.value()->GetSummaryFormat() &&
+          !is_synth_val)                                  // but again only do
                                                           // that if not a
                                                           // synthetic valued
                                                           // child
@@ -546,7 +549,7 @@ ConstString FormatManager::GetTypeForCache(ValueObject &valobj,
                                            lldb::DynamicValueType use_dynamic) {
   ValueObjectSP valobj_sp = valobj.GetQualifiedRepresentationIfAvailable(
       use_dynamic, valobj.IsSynthetic());
-  if (valobj_sp && valobj_sp->GetCompilerType().IsValid()) {
+  if (valobj_sp->GetCompilerType().IsValid()) {
     if (!valobj_sp->GetCompilerType().IsMeaninglessWithoutDynamicResolution())
       return valobj_sp->GetQualifiedTypeName();
   }
diff --git a/lldb/source/DataFormatters/TypeSynthetic.cpp b/lldb/source/DataFormatters/TypeSynthetic.cpp
index de042e474903e55..2e1722ca5701b92 100644
--- a/lldb/source/DataFormatters/TypeSynthetic.cpp
+++ b/lldb/source/DataFormatters/TypeSynthetic.cpp
@@ -115,23 +115,25 @@ std::string CXXSyntheticChildren::GetDescription() {
   return std::string(sstr.GetString());
 }
 
-lldb::ValueObjectSP SyntheticChildrenFrontEnd::CreateValueObjectFromExpression(
+std::optional<lldb::ValueObjectSP>
+SyntheticChildrenFrontEnd::CreateValueObjectFromExpression(
     llvm::StringRef name, llvm::StringRef expression,
     const ExecutionContext &exe_ctx) {
-  ValueObjectSP valobj_sp(
+  std::optional<ValueObjectSP> valobj_sp(
       ValueObject::CreateValueObjectFromExpression(name, expression, exe_ctx));
   if (valobj_sp)
-    valobj_sp->SetSyntheticChildrenGenerated(true);
+    valobj_sp.value()->SetSyntheticChildrenGenerated(true);
   return valobj_sp;
 }
 
-lldb::ValueObjectSP SyntheticChildrenFrontEnd::CreateValueObjectFromAddress(
+std::optional<lldb::ValueObjectSP>
+SyntheticChildrenFrontEnd::CreateValueObjectFromAddress(
     llvm::StringRef name, uint64_t address, const ExecutionContext &exe_ctx,
     CompilerType type) {
-  ValueObjectSP valobj_sp(
+  std::optional<ValueObjectSP> valobj_sp(
       ValueObject::CreateValueObjectFromAddress(name, address, exe_ctx, type));
   if (valobj_sp)
-    valobj_sp->SetSyntheticChildrenGenerated(true);
+    valobj_sp.value()->SetSyntheticChildrenGenerated(true);
   return valobj_sp;
 }
 
@@ -140,8 +142,7 @@ lldb::ValueObjectSP SyntheticChildrenFrontEnd::CreateValueObjectFromData(
     const ExecutionContext &exe_ctx, CompilerType type) {
   ValueObjectSP valobj_sp(
       ValueObject::CreateValueObjectFromData(name, data, exe_ctx, type));
-  if (valobj_sp)
-    valobj_sp->SetSyntheticChildrenGenerated(true);
+  valobj_sp->SetSyntheticChildrenGenerated(true);
   return valobj_sp;
 }
 
@@ -166,10 +167,10 @@ ScriptedSyntheticChildren::FrontEnd::FrontEnd(std::string pclass,
 
 ScriptedSyntheticChildren::FrontEnd::~FrontEnd() = default;
 
-lldb::ValueObjectSP
+std::optional<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);
 }
@@ -212,9 +213,10 @@ size_t ScriptedSyntheticChildren::FrontEnd::GetIndexOfChildWithName(
                                                 name.GetCString());
 }
 
-lldb::ValueObjectSP ScriptedSyntheticChildren::FrontEnd::GetSyntheticValue() {
+std::optional<ValueObjectSP>
+ScriptedSyntheticChildren::FrontEnd::GetSyntheticValue() {
   if (!m_wrapper_sp || m_interpreter == nullptr)
-    return nullptr;
+    return {};
 
   return m_interpreter->GetSyntheticValue(m_wrapper_sp);
 }
diff --git a/lldb/source/DataFormatters/ValueObjectPrinter.cpp b/lldb/source/DataFormatters/ValueObjectPrinter.cpp
index 074d0b648e6fa9f..ccb1053069283ad 100644
--- a/lldb/source/DataFormatters/ValueObjectPrinter.cpp
+++ b/lldb/source/DataFormatters/ValueObjectPrinter.cpp
@@ -126,7 +126,7 @@ bool ValueObjectPrinter::GetMostSpecializedValue() {
     } else {
       if (m_options.m_use_dynamic != eNoDynamicValues) {
         ValueObject *dynamic_value =
-            m_orig_valobj->GetDynamicValue(m_options.m_use_dynamic).get();
+            m_orig_valobj->GetDynamicValue(m_options.m_use_dynamic)->get();
         if (dynamic_value)
           m_valobj = dynamic_value;
         else
@@ -143,7 +143,7 @@ bool ValueObjectPrinter::GetMostSpecializedValue() {
       }
     } else {
       if (m_options.m_use_synthetic) {
-        ValueObject *synthetic = m_valobj->GetSyntheticValue().get();
+        ValueObject *synthetic = m_valobj->GetSyntheticValue()->get();
         if (synthetic)
           m_valobj = synthetic;
       }
@@ -679,8 +679,8 @@ static constexpr size_t PhysicalIndexForLogicalIndex(size_t base, size_t stride,
   return base + logical * stride;
 }
 
-ValueObjectSP ValueObjectPrinter::GenerateChild(ValueObject *synth_valobj,
-                                                size_t idx) {
+std::optional<ValueObjectSP>
+ValueObjectPrinter::GenerateChild(ValueObject *synth_valobj, size_t idx) {
   if (m_options.m_pointer_as_array) {
     // if generating pointer-as-array children, use GetSyntheticArrayMember
     return synth_valobj->GetSyntheticArrayMember(
@@ -705,15 +705,16 @@ void ValueObjectPrinter::PrintChildren(
     bool any_children_printed = false;
 
     for (size_t idx = 0; idx < num_children; ++idx) {
-      if (ValueObjectSP child_sp = GenerateChild(synth_m_valobj, idx)) {
+      if (std::optional<ValueObjectSP> child_sp =
+              GenerateChild(synth_m_valobj, idx)) {
         if (m_options.m_child_printing_decider &&
-            !m_options.m_child_printing_decider(child_sp->GetName()))
+            !m_options.m_child_printing_decider(child_sp.value()->GetName()))
           continue;
         if (!any_children_printed) {
           PrintChildrenPreamble(value_printed, summary_printed);
           any_children_printed = true;
         }
-        PrintChild(child_sp, curr_ptr_depth);
+        PrintChild(child_sp.value(), curr_ptr_depth);
       }
     }
 
@@ -759,25 +760,26 @@ bool ValueObjectPrinter::PrintChildrenOneLiner(bool hide_names) {
 
     bool did_print_children = false;
     for (uint32_t idx = 0; idx < num_children; ++idx) {
-      lldb::ValueObjectSP child_sp(synth_m_valobj->GetChildAtIndex(idx));
+      std::optional<ValueObjectSP> child_sp(
+          synth_m_valobj->GetChildAtIndex(idx));
       if (child_sp)
-        child_sp = child_sp->GetQualifiedRepresentationIfAvailable(
+        child_sp = child_sp.value()->GetQualifiedRepresentationIfAvailable(
             m_options.m_use_dynamic, m_options.m_use_synthetic);
       if (child_sp) {
         if (m_options.m_child_printing_decider &&
-            !m_options.m_child_printing_decider(child_sp->GetName()))
+            !m_options.m_child_printing_decider(child_sp.value()->GetName()))
           continue;
         if (idx && did_print_children)
           m_stream->PutCString(", ");
         did_print_children = true;
         if (!hide_names) {
-          const char *name = child_sp.get()->GetName().AsCString();
+          const char *name = child_sp.value()->GetName().AsCString();
           if (name && *name) {
             m_stream->PutCString(name);
             m_stream->PutCString(" = ");
           }
         }
-        child_sp->DumpPrintableRepresentation(
+        child_sp.value()->DumpPrintableRepresentation(
             *m_stream, ValueObject::eValueObjectRepresentationStyleSummary,
             m_options.m_format,
             ValueObject::PrintableRepresentationSpecialCases::eDisable);
diff --git a/lldb/source/DataFormatters/VectorType.cpp b/lldb/source/DataFormatters/VectorType.cpp
index 57dae0b2c71f0fa..a833a68828c3d73 100644
--- a/lldb/source/DataFormatters/VectorType.cpp
+++ b/lldb/source/DataFormatters/VectorType.cpp
@@ -226,7 +226,7 @@ class VectorTypeSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
 
   size_t CalculateNumChildren() override { return m_num_children; }
 
-  lldb::ValueObjectSP GetChildAtIndex(size_t idx) override {
+  std::optional<ValueObjectSP> GetChildAtIndex(size_t idx) override {
     if (idx >= CalculateNumChildren())
       return {};
     std::optional<uint64_t> size = m_child_type.GetByteSize(nullptr);
@@ -235,12 +235,12 @@ class VectorTypeSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
     auto offset = idx * *size;
     StreamString idx_name;
     idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
-    ValueObjectSP child_sp(m_backend.GetSyntheticChildAtOffset(
+    std::optional<ValueObjectSP> child_sp(m_backend.GetSyntheticChildAtOffset(
         offset, m_child_type, true, ConstString(idx_name.GetString())));
     if (!child_sp)
-      return child_sp;
+      return {};
 
-    child_sp->SetFormat(m_item_format);
+    child_sp.value()->SetFormat(m_item_format);
 
     return child_sp;
   }
@@ -299,10 +299,10 @@ bool lldb_private::formatters::VectorTypeSummaryProvider(
     auto child_sp = synthetic_children->GetChildAtIndex(idx);
     if (!child_sp)
       continue;
-    child_sp = child_sp->GetQualifiedRepresentationIfAvailable(
+    child_sp = child_sp.value()->GetQualifiedRepresentationIfAvailable(
         lldb::eDynamicDontRunTarget, true);
 
-    const char *child_value = child_sp->GetValueAsCString();
+    const char *child_value = child_sp.value()->GetValueAsCString();
     if (child_value && *child_value) {
       if (first) {
         s.Printf("%s", child_value);
@@ -321,7 +321,5 @@ bool lldb_private::formatters::VectorTypeSummaryProvider(
 lldb_private::SyntheticChildrenFrontEnd *
 lldb_private::formatters::VectorTypeSyntheticFrontEndCreator(
     CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
-  if (!valobj_sp)
-    return nullptr;
   return new VectorTypeSyntheticFrontEnd(valobj_sp);
 }
diff --git a/lldb/source/Expression/ExpressionVariable.cpp b/lldb/source/Expression/ExpressionVariable.cpp
index f0a28988822faf9..0ee3d8bcca30f1e 100644
--- a/lldb/source/Expression/ExpressionVariable.cpp
+++ b/lldb/source/Expression/ExpressionVariable.cpp
@@ -20,14 +20,18 @@ char ExpressionVariable::ID;
 ExpressionVariable::ExpressionVariable() : m_flags(0) {}
 
 uint8_t *ExpressionVariable::GetValueBytes() {
-  std::optional<uint64_t> byte_size = m_frozen_sp->GetByteSize();
+  if (!m_frozen_sp)
+    return nullptr;
+
+  std::optional<uint64_t> byte_size = m_frozen_sp.value()->GetByteSize();
   if (byte_size && *byte_size) {
-    if (m_frozen_sp->GetDataExtractor().GetByteSize() < *byte_size) {
-      m_frozen_sp->GetValue().ResizeData(*byte_size);
-      m_frozen_sp->GetValue().GetData(m_frozen_sp->GetDataExtractor());
+    if (m_frozen_sp.value()->GetDataExtractor().GetByteSize() < *byte_size) {
+      m_frozen_sp.value()->GetValue().ResizeData(*byte_size);
+      m_frozen_sp.value()->GetValue().GetData(
+          m_frozen_sp.value()->GetDataExtractor());
     }
     return const_cast<uint8_t *>(
-        m_frozen_sp->GetDataExtractor().GetDataStart());
+        m_frozen_sp.value()->GetDataExtractor().GetDataStart());
   }
   return nullptr;
 }
diff --git a/lldb/source/Target/StackFrame.cpp b/lldb/source/Target/StackFrame.cpp
index 50cf01e63cd493d..013d6e8900084ba 100644
--- a/lldb/source/Target/StackFrame.cpp
+++ b/lldb/source/Target/StackFrame.cpp
@@ -505,18 +505,18 @@ StackFrame::GetInScopeVariableList(bool get_file_globals,
   return var_list_sp;
 }
 
-ValueObjectSP StackFrame::GetValueForVariableExpressionPath(
+std::optional<ValueObjectSP> StackFrame::GetValueForVariableExpressionPath(
     llvm::StringRef var_expr, DynamicValueType use_dynamic, uint32_t options,
     VariableSP &var_sp, Status &error) {
   llvm::StringRef original_var_expr = var_expr;
   // We can't fetch variable information for a history stack frame.
   if (IsHistorical())
-    return ValueObjectSP();
+    return {};
 
   if (var_expr.empty()) {
     error.SetErrorStringWithFormat("invalid variable path '%s'",
                                    var_expr.str().c_str());
-    return ValueObjectSP();
+    return {};
   }
 
   const bool check_ptr_vs_member =
@@ -530,7 +530,7 @@ ValueObjectSP StackFrame::GetValueForVariableExpressionPath(
   error.Clear();
   bool deref = false;
   bool address_of = false;
-  ValueObjectSP valobj_sp;
+  std::optional<ValueObjectSP> valobj_sp;
   const bool get_file_globals = true;
   // When looking up a variable for an expression, we need only consider the
   // variables that are in scope.
@@ -538,7 +538,7 @@ ValueObjectSP StackFrame::GetValueForVariableExpressionPath(
   VariableList *variable_list = var_list_sp.get();
 
   if (!variable_list)
-    return ValueObjectSP();
+    return {};
 
   // If first character is a '*', then show pointer contents
   std::string var_expr_storage;
@@ -604,7 +604,7 @@ ValueObjectSP StackFrame::GetValueForVariableExpressionPath(
       valobj_sp = GetValueObjectForFrameVariable(variable_sp, use_dynamic);
       if (!valobj_sp)
         return valobj_sp;
-      valobj_sp = valobj_sp->GetChildMemberWithName(name_const_string);
+      valobj_sp = valobj_sp.value()->GetChildMemberWithName(name_const_string);
       if (valobj_sp)
         break;
     }
@@ -618,57 +618,60 @@ ValueObjectSP StackFrame::GetValueForVariableExpressionPath(
   if (!valobj_sp) {
     error.SetErrorStringWithFormat("no variable named '%s' found in this frame",
                                    name_const_string.GetCString());
-    return ValueObjectSP();
+    return {};
   }
 
   // We are dumping at least one child
   while (!var_expr.empty()) {
     // Calculate the next separator index ahead of time
-    ValueObjectSP child_valobj_sp;
+    std::optional<ValueObjectSP> child_valobj_sp;
     const char separator_type = var_expr[0];
     bool expr_is_ptr = false;
     switch (separator_type) {
     case '-':
       expr_is_ptr = true;
       if (var_expr.size() >= 2 && var_expr[1] != '>')
-        return ValueObjectSP();
+        return {};
 
       if (no_fragile_ivar) {
         // Make sure we aren't trying to deref an objective
         // C ivar if this is not allowed
         const uint32_t pointer_type_flags =
-            valobj_sp->GetCompilerType().GetTypeInfo(nullptr);
+            valobj_sp.value()->GetCompilerType().GetTypeInfo(nullptr);
         if ((pointer_type_flags & eTypeIsObjC) &&
             (pointer_type_flags & eTypeIsPointer)) {
           // This was an objective C object pointer and it was requested we
           // skip any fragile ivars so return nothing here
-          return ValueObjectSP();
+          return {};
         }
       }
 
       // If we have a non pointer type with a sythetic value then lets check if
       // we have an sythetic dereference specified.
-      if (!valobj_sp->IsPointerType() && valobj_sp->HasSyntheticValue()) {
-        Status deref_error;
-        if (valobj_sp->GetCompilerType().IsReferenceType()) {
-          valobj_sp = valobj_sp->GetSyntheticValue()->Dereference(deref_error);
-          if (!valobj_sp || deref_error.Fail()) {
+      if (!valobj_sp.value()->IsPointerType() &&
+          valobj_sp.value()->HasSyntheticValue()) {
+        if (valobj_sp.value()->GetCompilerType().IsReferenceType()) {
+          valobj_sp =
+              valobj_sp.value()->GetSyntheticValue().value()->Dereference();
+          if (valobj_sp.value()->GetError().Fail()) {
             error.SetErrorStringWithFormatv(
-                "Failed to dereference reference type: %s", deref_error);
-            return ValueObjectSP();
+                "Failed to dereference reference type: %s",
+                valobj_sp.value()->GetError());
+            return {};
           }
         }
 
-        valobj_sp = valobj_sp->Dereference(deref_error);
-        if (!valobj_sp || deref_error.Fail()) {
+        valobj_sp = valobj_sp.value()->Dereference();
+        if (valobj_sp.value()->GetError().Fail()) {
           error.SetErrorStringWithFormatv(
-              "Failed to dereference sythetic value: {0}", deref_error);
-          return ValueObjectSP();
+              "Failed to dereference sythetic value: {0}",
+              valobj_sp.value()->GetError());
+          return {};
         }
         // Some synthetic plug-ins fail to set the error in Dereference
         if (!valobj_sp) {
           error.SetErrorString("Failed to dereference sythetic value");
-          return ValueObjectSP();
+          return {};
         }
         expr_is_ptr = false;
       }
@@ -684,12 +687,12 @@ ValueObjectSP StackFrame::GetValueForVariableExpressionPath(
         // We either have a pointer type and need to verify valobj_sp is a
         // pointer, or we have a member of a class/union/struct being accessed
         // with the . syntax and need to verify we don't have a pointer.
-        const bool actual_is_ptr = valobj_sp->IsPointerType();
+        const bool actual_is_ptr = valobj_sp.value()->IsPointerType();
 
         if (actual_is_ptr != expr_is_ptr) {
           // Incorrect use of "." with a pointer, or "->" with a
           // class/union/struct instance or reference.
-          valobj_sp->GetExpressionPath(var_expr_path_strm);
+          valobj_sp.value()->GetExpressionPath(var_expr_path_strm);
           if (actual_is_ptr)
             error.SetErrorStringWithFormat(
                 "\"%s\" is a pointer and . was used to attempt to access "
@@ -702,16 +705,16 @@ ValueObjectSP StackFrame::GetValueForVariableExpressionPath(
                 "access \"%s\". Did you mean \"%s.%s\"?",
                 var_expr_path_strm.GetData(), child_name.GetCString(),
                 var_expr_path_strm.GetData(), var_expr.str().c_str());
-          return ValueObjectSP();
+          return {};
         }
       }
-      child_valobj_sp = valobj_sp->GetChildMemberWithName(child_name);
+      child_valobj_sp = valobj_sp.value()->GetChildMemberWithName(child_name);
       if (!child_valobj_sp) {
         if (!no_synth_child) {
-          child_valobj_sp = valobj_sp->GetSyntheticValue();
+          child_valobj_sp = valobj_sp.value()->GetSyntheticValue();
           if (child_valobj_sp)
             child_valobj_sp =
-                child_valobj_sp->GetChildMemberWithName(child_name);
+                child_valobj_sp.value()->GetChildMemberWithName(child_name);
         }
 
         if (no_synth_child || !child_valobj_sp) {
@@ -725,12 +728,12 @@ ValueObjectSP StackFrame::GetValueForVariableExpressionPath(
                 "this frame",
                 name_const_string.GetCString());
           } else {
-            valobj_sp->GetExpressionPath(var_expr_path_strm);
+            valobj_sp.value()->GetExpressionPath(var_expr_path_strm);
             if (child_name) {
               error.SetErrorStringWithFormat(
                   "\"%s\" is not a member of \"(%s) %s\"",
                   child_name.GetCString(),
-                  valobj_sp->GetTypeName().AsCString("<invalid type>"),
+                  valobj_sp.value()->GetTypeName().AsCString("<invalid type>"),
                   var_expr_path_strm.GetData());
             } else {
               error.SetErrorStringWithFormat(
@@ -739,15 +742,15 @@ ValueObjectSP StackFrame::GetValueForVariableExpressionPath(
                   original_var_expr.str().c_str());
             }
           }
-          return ValueObjectSP();
+          return {};
         }
       }
       synthetically_added_instance_object = false;
       // Remove the child name from the path
       var_expr = var_expr.drop_front(child_name.GetLength());
       if (use_dynamic != eNoDynamicValues) {
-        ValueObjectSP dynamic_value_sp(
-            child_valobj_sp->GetDynamicValue(use_dynamic));
+        std::optional<ValueObjectSP> dynamic_value_sp(
+            child_valobj_sp.value()->GetDynamicValue(use_dynamic));
         if (dynamic_value_sp)
           child_valobj_sp = dynamic_value_sp;
       }
@@ -760,7 +763,7 @@ ValueObjectSP StackFrame::GetValueForVariableExpressionPath(
         error.SetErrorStringWithFormat(
             "invalid square bracket encountered after \"%s\" in \"%s\"",
             var_expr_path_strm.GetData(), var_expr.str().c_str());
-        return ValueObjectSP();
+        return {};
       }
 
       // Drop the open brace.
@@ -773,7 +776,7 @@ ValueObjectSP StackFrame::GetValueForVariableExpressionPath(
         error.SetErrorStringWithFormat(
             "missing closing square bracket in expression \"%s\"",
             var_expr_path_strm.GetData());
-        return ValueObjectSP();
+        return {};
       }
       llvm::StringRef index_expr = var_expr.take_front(end_pos);
       llvm::StringRef original_index_expr = index_expr;
@@ -785,166 +788,167 @@ ValueObjectSP StackFrame::GetValueForVariableExpressionPath(
         // erroneous expression.
         error.SetErrorStringWithFormat("invalid index expression \"%s\"",
                                        index_expr.str().c_str());
-        return ValueObjectSP();
+        return {};
       }
 
       if (index_expr.empty()) {
         // The entire index expression was a single integer.
 
-        if (valobj_sp->GetCompilerType().IsPointerToScalarType() && deref) {
+        if (valobj_sp.value()->GetCompilerType().IsPointerToScalarType() &&
+            deref) {
           // what we have is *ptr[low]. the most similar C++ syntax is to deref
           // ptr and extract bit low out of it. reading array item low would be
           // done by saying ptr[low], without a deref * sign
-          Status deref_error;
-          ValueObjectSP temp(valobj_sp->Dereference(deref_error));
-          if (!temp || deref_error.Fail()) {
-            valobj_sp->GetExpressionPath(var_expr_path_strm);
+          ValueObjectSP temp(valobj_sp.value()->Dereference());
+          if (temp->GetError().Fail()) {
+            valobj_sp.value()->GetExpressionPath(var_expr_path_strm);
             error.SetErrorStringWithFormat(
                 "could not dereference \"(%s) %s\"",
-                valobj_sp->GetTypeName().AsCString("<invalid type>"),
+                valobj_sp.value()->GetTypeName().AsCString("<invalid type>"),
                 var_expr_path_strm.GetData());
-            return ValueObjectSP();
+            return {};
           }
           valobj_sp = temp;
           deref = false;
-        } else if (valobj_sp->GetCompilerType().IsArrayOfScalarType() &&
+        } else if (valobj_sp.value()->GetCompilerType().IsArrayOfScalarType() &&
                    deref) {
           // what we have is *arr[low]. the most similar C++ syntax is to get
           // arr[0] (an operation that is equivalent to deref-ing arr) and
           // extract bit low out of it. reading array item low would be done by
           // saying arr[low], without a deref * sign
-          ValueObjectSP temp(valobj_sp->GetChildAtIndex(0));
+          std::optional<ValueObjectSP> temp(
+              valobj_sp.value()->GetChildAtIndex(0));
           if (!temp) {
-            valobj_sp->GetExpressionPath(var_expr_path_strm);
+            valobj_sp.value()->GetExpressionPath(var_expr_path_strm);
             error.SetErrorStringWithFormat(
                 "could not get item 0 for \"(%s) %s\"",
-                valobj_sp->GetTypeName().AsCString("<invalid type>"),
+                valobj_sp.value()->GetTypeName().AsCString("<invalid type>"),
                 var_expr_path_strm.GetData());
-            return ValueObjectSP();
+            return {};
           }
           valobj_sp = temp;
           deref = false;
         }
 
         bool is_incomplete_array = false;
-        if (valobj_sp->IsPointerType()) {
+        if (valobj_sp.value()->IsPointerType()) {
           bool is_objc_pointer = true;
 
-          if (valobj_sp->GetCompilerType().GetMinimumLanguage() !=
+          if (valobj_sp.value()->GetCompilerType().GetMinimumLanguage() !=
               eLanguageTypeObjC)
             is_objc_pointer = false;
-          else if (!valobj_sp->GetCompilerType().IsPointerType())
+          else if (!valobj_sp.value()->GetCompilerType().IsPointerType())
             is_objc_pointer = false;
 
           if (no_synth_child && is_objc_pointer) {
             error.SetErrorStringWithFormat(
                 "\"(%s) %s\" is an Objective-C pointer, and cannot be "
                 "subscripted",
-                valobj_sp->GetTypeName().AsCString("<invalid type>"),
+                valobj_sp.value()->GetTypeName().AsCString("<invalid type>"),
                 var_expr_path_strm.GetData());
 
-            return ValueObjectSP();
+            return {};
           } else if (is_objc_pointer) {
             // dereferencing ObjC variables is not valid.. so let's try and
             // recur to synthetic children
-            ValueObjectSP synthetic = valobj_sp->GetSyntheticValue();
+            std::optional<ValueObjectSP> synthetic =
+                valobj_sp.value()->GetSyntheticValue();
             if (!synthetic                 /* no synthetic */
                 || synthetic == valobj_sp) /* synthetic is the same as
                                               the original object */
             {
-              valobj_sp->GetExpressionPath(var_expr_path_strm);
+              valobj_sp.value()->GetExpressionPath(var_expr_path_strm);
               error.SetErrorStringWithFormat(
                   "\"(%s) %s\" is not an array type",
-                  valobj_sp->GetTypeName().AsCString("<invalid type>"),
+                  valobj_sp.value()->GetTypeName().AsCString("<invalid type>"),
                   var_expr_path_strm.GetData());
             } else if (
-                static_cast<uint32_t>(child_index) >=
-                synthetic
-                    ->GetNumChildren() /* synthetic does not have that many values */) {
-              valobj_sp->GetExpressionPath(var_expr_path_strm);
+                static_cast<uint32_t>(child_index) >= synthetic.value()
+                                                          ->GetNumChildren() /* synthetic does not have that many values */) {
+              valobj_sp.value()->GetExpressionPath(var_expr_path_strm);
               error.SetErrorStringWithFormat(
                   "array index %ld is not valid for \"(%s) %s\"", child_index,
-                  valobj_sp->GetTypeName().AsCString("<invalid type>"),
+                  valobj_sp.value()->GetTypeName().AsCString("<invalid type>"),
                   var_expr_path_strm.GetData());
             } else {
-              child_valobj_sp = synthetic->GetChildAtIndex(child_index);
+              child_valobj_sp = synthetic.value()->GetChildAtIndex(child_index);
               if (!child_valobj_sp) {
-                valobj_sp->GetExpressionPath(var_expr_path_strm);
+                valobj_sp.value()->GetExpressionPath(var_expr_path_strm);
                 error.SetErrorStringWithFormat(
                     "array index %ld is not valid for \"(%s) %s\"", child_index,
-                    valobj_sp->GetTypeName().AsCString("<invalid type>"),
+                    valobj_sp.value()->GetTypeName().AsCString(
+                        "<invalid type>"),
                     var_expr_path_strm.GetData());
               }
             }
           } else {
             child_valobj_sp =
-                valobj_sp->GetSyntheticArrayMember(child_index, true);
+                valobj_sp.value()->GetSyntheticArrayMember(child_index, true);
             if (!child_valobj_sp) {
-              valobj_sp->GetExpressionPath(var_expr_path_strm);
+              valobj_sp.value()->GetExpressionPath(var_expr_path_strm);
               error.SetErrorStringWithFormat(
                   "failed to use pointer as array for index %ld for "
                   "\"(%s) %s\"",
                   child_index,
-                  valobj_sp->GetTypeName().AsCString("<invalid type>"),
+                  valobj_sp.value()->GetTypeName().AsCString("<invalid type>"),
                   var_expr_path_strm.GetData());
             }
           }
-        } else if (valobj_sp->GetCompilerType().IsArrayType(
+        } else if (valobj_sp.value()->GetCompilerType().IsArrayType(
                        nullptr, nullptr, &is_incomplete_array)) {
           // Pass false to dynamic_value here so we can tell the difference
           // between no dynamic value and no member of this type...
-          child_valobj_sp = valobj_sp->GetChildAtIndex(child_index);
+          child_valobj_sp = valobj_sp.value()->GetChildAtIndex(child_index);
           if (!child_valobj_sp && (is_incomplete_array || !no_synth_child))
             child_valobj_sp =
-                valobj_sp->GetSyntheticArrayMember(child_index, true);
+                valobj_sp.value()->GetSyntheticArrayMember(child_index, true);
 
           if (!child_valobj_sp) {
-            valobj_sp->GetExpressionPath(var_expr_path_strm);
+            valobj_sp.value()->GetExpressionPath(var_expr_path_strm);
             error.SetErrorStringWithFormat(
                 "array index %ld is not valid for \"(%s) %s\"", child_index,
-                valobj_sp->GetTypeName().AsCString("<invalid type>"),
+                valobj_sp.value()->GetTypeName().AsCString("<invalid type>"),
                 var_expr_path_strm.GetData());
           }
-        } else if (valobj_sp->GetCompilerType().IsScalarType()) {
+        } else if (valobj_sp.value()->GetCompilerType().IsScalarType()) {
           // this is a bitfield asking to display just one bit
-          child_valobj_sp = valobj_sp->GetSyntheticBitFieldChild(
+          child_valobj_sp = valobj_sp.value()->GetSyntheticBitFieldChild(
               child_index, child_index, true);
           if (!child_valobj_sp) {
-            valobj_sp->GetExpressionPath(var_expr_path_strm);
+            valobj_sp.value()->GetExpressionPath(var_expr_path_strm);
             error.SetErrorStringWithFormat(
                 "bitfield range %ld-%ld is not valid for \"(%s) %s\"",
                 child_index, child_index,
-                valobj_sp->GetTypeName().AsCString("<invalid type>"),
+                valobj_sp.value()->GetTypeName().AsCString("<invalid type>"),
                 var_expr_path_strm.GetData());
           }
         } else {
-          ValueObjectSP synthetic = valobj_sp->GetSyntheticValue();
+          std::optional<ValueObjectSP> synthetic =
+              valobj_sp.value()->GetSyntheticValue();
           if (no_synth_child /* synthetic is forbidden */ ||
               !synthetic                 /* no synthetic */
               || synthetic == valobj_sp) /* synthetic is the same as the
                                             original object */
           {
-            valobj_sp->GetExpressionPath(var_expr_path_strm);
+            valobj_sp.value()->GetExpressionPath(var_expr_path_strm);
             error.SetErrorStringWithFormat(
                 "\"(%s) %s\" is not an array type",
-                valobj_sp->GetTypeName().AsCString("<invalid type>"),
+                valobj_sp.value()->GetTypeName().AsCString("<invalid type>"),
                 var_expr_path_strm.GetData());
-          } else if (
-              static_cast<uint32_t>(child_index) >=
-              synthetic
-                  ->GetNumChildren() /* synthetic does not have that many values */) {
-            valobj_sp->GetExpressionPath(var_expr_path_strm);
+          } else if (static_cast<uint32_t>(
+                         child_index) >= synthetic.value()->GetNumChildren() /* synthetic does not have that many values */) {
+            valobj_sp.value()->GetExpressionPath(var_expr_path_strm);
             error.SetErrorStringWithFormat(
                 "array index %ld is not valid for \"(%s) %s\"", child_index,
-                valobj_sp->GetTypeName().AsCString("<invalid type>"),
+                valobj_sp.value()->GetTypeName().AsCString("<invalid type>"),
                 var_expr_path_strm.GetData());
           } else {
-            child_valobj_sp = synthetic->GetChildAtIndex(child_index);
+            child_valobj_sp = synthetic.value()->GetChildAtIndex(child_index);
             if (!child_valobj_sp) {
-              valobj_sp->GetExpressionPath(var_expr_path_strm);
+              valobj_sp.value()->GetExpressionPath(var_expr_path_strm);
               error.SetErrorStringWithFormat(
                   "array index %ld is not valid for \"(%s) %s\"", child_index,
-                  valobj_sp->GetTypeName().AsCString("<invalid type>"),
+                  valobj_sp.value()->GetTypeName().AsCString("<invalid type>"),
                   var_expr_path_strm.GetData());
             }
           }
@@ -952,12 +956,12 @@ ValueObjectSP StackFrame::GetValueForVariableExpressionPath(
 
         if (!child_valobj_sp) {
           // Invalid array index...
-          return ValueObjectSP();
+          return {};
         }
 
         if (use_dynamic != eNoDynamicValues) {
-          ValueObjectSP dynamic_value_sp(
-              child_valobj_sp->GetDynamicValue(use_dynamic));
+          std::optional<ValueObjectSP> dynamic_value_sp(
+              child_valobj_sp.value()->GetDynamicValue(use_dynamic));
           if (dynamic_value_sp)
             child_valobj_sp = dynamic_value_sp;
         }
@@ -970,7 +974,7 @@ ValueObjectSP StackFrame::GetValueForVariableExpressionPath(
       if (index_expr.front() != '-') {
         error.SetErrorStringWithFormat("invalid range expression \"'%s'\"",
                                        original_index_expr.str().c_str());
-        return ValueObjectSP();
+        return {};
       }
 
       index_expr = index_expr.drop_front();
@@ -978,7 +982,7 @@ ValueObjectSP StackFrame::GetValueForVariableExpressionPath(
       if (index_expr.getAsInteger(0, final_index)) {
         error.SetErrorStringWithFormat("invalid range expression \"'%s'\"",
                                        original_index_expr.str().c_str());
-        return ValueObjectSP();
+        return {};
       }
 
       // if the format given is [high-low], swap range
@@ -988,59 +992,62 @@ ValueObjectSP StackFrame::GetValueForVariableExpressionPath(
         final_index = temp;
       }
 
-      if (valobj_sp->GetCompilerType().IsPointerToScalarType() && deref) {
+      if (valobj_sp.value()->GetCompilerType().IsPointerToScalarType() &&
+          deref) {
         // what we have is *ptr[low-high]. the most similar C++ syntax is to
         // deref ptr and extract bits low thru high out of it. reading array
         // items low thru high would be done by saying ptr[low-high], without a
         // deref * sign
-        Status deref_error;
-        ValueObjectSP temp(valobj_sp->Dereference(deref_error));
-        if (!temp || deref_error.Fail()) {
-          valobj_sp->GetExpressionPath(var_expr_path_strm);
+        ValueObjectSP temp(valobj_sp.value()->Dereference());
+        if (temp->GetError().Fail()) {
+          valobj_sp.value()->GetExpressionPath(var_expr_path_strm);
           error.SetErrorStringWithFormat(
               "could not dereference \"(%s) %s\"",
-              valobj_sp->GetTypeName().AsCString("<invalid type>"),
+              valobj_sp.value()->GetTypeName().AsCString("<invalid type>"),
               var_expr_path_strm.GetData());
-          return ValueObjectSP();
+          return {};
         }
         valobj_sp = temp;
         deref = false;
-      } else if (valobj_sp->GetCompilerType().IsArrayOfScalarType() && deref) {
+      } else if (valobj_sp.value()->GetCompilerType().IsArrayOfScalarType() &&
+                 deref) {
         // what we have is *arr[low-high]. the most similar C++ syntax is to
         // get arr[0] (an operation that is equivalent to deref-ing arr) and
         // extract bits low thru high out of it. reading array items low thru
         // high would be done by saying arr[low-high], without a deref * sign
-        ValueObjectSP temp(valobj_sp->GetChildAtIndex(0));
+        std::optional<ValueObjectSP> temp(
+            valobj_sp.value()->GetChildAtIndex(0));
         if (!temp) {
-          valobj_sp->GetExpressionPath(var_expr_path_strm);
+          valobj_sp.value()->GetExpressionPath(var_expr_path_strm);
           error.SetErrorStringWithFormat(
               "could not get item 0 for \"(%s) %s\"",
-              valobj_sp->GetTypeName().AsCString("<invalid type>"),
+              valobj_sp.value()->GetTypeName().AsCString("<invalid type>"),
               var_expr_path_strm.GetData());
-          return ValueObjectSP();
+          return {};
         }
         valobj_sp = temp;
         deref = false;
       }
 
-      child_valobj_sp =
-          valobj_sp->GetSyntheticBitFieldChild(child_index, final_index, true);
+      child_valobj_sp = valobj_sp.value()->GetSyntheticBitFieldChild(
+          child_index, final_index, true);
       if (!child_valobj_sp) {
-        valobj_sp->GetExpressionPath(var_expr_path_strm);
+        valobj_sp.value()->GetExpressionPath(var_expr_path_strm);
         error.SetErrorStringWithFormat(
             "bitfield range %ld-%ld is not valid for \"(%s) %s\"", child_index,
-            final_index, valobj_sp->GetTypeName().AsCString("<invalid type>"),
+            final_index,
+            valobj_sp.value()->GetTypeName().AsCString("<invalid type>"),
             var_expr_path_strm.GetData());
       }
 
       if (!child_valobj_sp) {
         // Invalid bitfield range...
-        return ValueObjectSP();
+        return {};
       }
 
       if (use_dynamic != eNoDynamicValues) {
-        ValueObjectSP dynamic_value_sp(
-            child_valobj_sp->GetDynamicValue(use_dynamic));
+        std::optional<ValueObjectSP> dynamic_value_sp(
+            child_valobj_sp.value()->GetDynamicValue(use_dynamic));
         if (dynamic_value_sp)
           child_valobj_sp = dynamic_value_sp;
       }
@@ -1051,13 +1058,13 @@ ValueObjectSP StackFrame::GetValueForVariableExpressionPath(
     default:
       // Failure...
       {
-        valobj_sp->GetExpressionPath(var_expr_path_strm);
+        valobj_sp.value()->GetExpressionPath(var_expr_path_strm);
         error.SetErrorStringWithFormat(
             "unexpected char '%c' encountered after \"%s\" in \"%s\"",
             separator_type, var_expr_path_strm.GetData(),
             var_expr.str().c_str());
 
-        return ValueObjectSP();
+        return {};
       }
     }
 
@@ -1066,12 +1073,17 @@ ValueObjectSP StackFrame::GetValueForVariableExpressionPath(
   }
   if (valobj_sp) {
     if (deref) {
-      ValueObjectSP deref_valobj_sp(valobj_sp->Dereference(error));
+      ValueObjectSP deref_valobj_sp(valobj_sp.value()->Dereference());
       valobj_sp = deref_valobj_sp;
     } else if (address_of) {
-      ValueObjectSP address_of_valobj_sp(valobj_sp->AddressOf(error));
+      ValueObjectSP address_of_valobj_sp(valobj_sp.value()->AddressOf());
       valobj_sp = address_of_valobj_sp;
     }
+
+    if (valobj_sp.value()->GetError().Fail()) {
+      error = valobj_sp.value()->GetError();
+      return {};
+    }
   }
   return valobj_sp;
 }
@@ -1148,10 +1160,10 @@ bool StackFrame::HasDebugInformation() {
   return m_sc.line_entry.IsValid();
 }
 
-ValueObjectSP
+std::optional<ValueObjectSP>
 StackFrame::GetValueObjectForFrameVariable(const VariableSP &variable_sp,
                                            DynamicValueType use_dynamic) {
-  ValueObjectSP valobj_sp;
+  std::optional<ValueObjectSP> valobj_sp;
   { // Scope for stack frame mutex.  We need to drop this mutex before we figure
     // out the dynamic value.  That will require converting the StackID in the
     // VO back to a StackFrame, which will in turn require locking the
@@ -1160,7 +1172,7 @@ StackFrame::GetValueObjectForFrameVariable(const VariableSP &variable_sp,
     // then the stack frame, which is fairly common.
     std::lock_guard<std::recursive_mutex> guard(m_mutex);
     if (IsHistorical()) {
-      return valobj_sp;
+      return {};
     }
     VariableList *var_list = GetVariableList(true, nullptr);
     if (var_list) {
@@ -1172,15 +1184,18 @@ StackFrame::GetValueObjectForFrameVariable(const VariableSP &variable_sp,
         if (!valobj_sp) {
           if (m_variable_list_value_objects.GetSize() < num_variables)
             m_variable_list_value_objects.Resize(num_variables);
-          valobj_sp = ValueObjectVariable::Create(this, variable_sp);
+          ValueObjectSP variable =
+              ValueObjectVariable::Create(this, variable_sp);
           m_variable_list_value_objects.SetValueObjectAtIndex(var_idx,
-                                                              valobj_sp);
+                                                              variable);
+          valobj_sp = variable;
         }
       }
     }
   } // End of StackFrame mutex scope.
   if (use_dynamic != eNoDynamicValues && valobj_sp) {
-    ValueObjectSP dynamic_sp = valobj_sp->GetDynamicValue(use_dynamic);
+    std::optional<ValueObjectSP> dynamic_sp =
+        valobj_sp.value()->GetDynamicValue(use_dynamic);
     if (dynamic_sp)
       return dynamic_sp;
   }
@@ -1304,7 +1319,8 @@ GetBaseExplainingDereference(const Instruction::Operand &operand,
 }
 }
 
-lldb::ValueObjectSP StackFrame::GuessValueForAddress(lldb::addr_t addr) {
+std::optional<ValueObjectSP>
+StackFrame::GuessValueForAddress(lldb::addr_t addr) {
   TargetSP target_sp = CalculateTarget();
 
   const ArchSpec &target_arch = target_sp->GetArchitecture();
@@ -1322,7 +1338,7 @@ lldb::ValueObjectSP StackFrame::GuessValueForAddress(lldb::addr_t addr) {
                                      *target_sp, pc_range, force_live_memory);
 
   if (!disassembler_sp || !disassembler_sp->GetInstructionList().GetSize()) {
-    return ValueObjectSP();
+    return {};
   }
 
   InstructionSP instruction_sp =
@@ -1331,13 +1347,13 @@ lldb::ValueObjectSP StackFrame::GuessValueForAddress(lldb::addr_t addr) {
   llvm::SmallVector<Instruction::Operand, 3> operands;
 
   if (!instruction_sp->ParseOperands(operands)) {
-    return ValueObjectSP();
+    return {};
   }
 
   RegisterContextSP register_context_sp = GetRegisterContext();
 
   if (!register_context_sp) {
-    return ValueObjectSP();
+    return {};
   }
 
   for (const Instruction::Operand &operand : operands) {
@@ -1359,7 +1375,7 @@ lldb::ValueObjectSP StackFrame::GuessValueForAddress(lldb::addr_t addr) {
         if (auto err = c_type_system_or_err.takeError()) {
           LLDB_LOG_ERROR(GetLog(LLDBLog::Thread), std::move(err),
                          "Unable to guess value for given address: {0}");
-          return ValueObjectSP();
+          return {};
         } else {
           auto ts = *c_type_system_or_err;
           if (!ts)
@@ -1370,7 +1386,7 @@ lldb::ValueObjectSP StackFrame::GuessValueForAddress(lldb::addr_t addr) {
           return ValueObjectMemory::Create(this, "", addr, void_ptr_type);
         }
       } else {
-        return ValueObjectSP();
+        return {};
       }
       break;
     }
@@ -1379,18 +1395,18 @@ lldb::ValueObjectSP StackFrame::GuessValueForAddress(lldb::addr_t addr) {
                                             base_and_offset.second);
     }
     default:
-      return ValueObjectSP();
+      return {};
     }
   }
 
-  return ValueObjectSP();
+  return {};
 }
 
 namespace {
-ValueObjectSP GetValueForOffset(StackFrame &frame, ValueObjectSP &parent,
-                                int64_t offset) {
+std::optional<ValueObjectSP>
+GetValueForOffset(StackFrame &frame, ValueObjectSP &parent, int64_t offset) {
   if (offset < 0 || uint64_t(offset) >= parent->GetByteSize()) {
-    return ValueObjectSP();
+    return {};
   }
 
   if (parent->IsPointerOrReferenceType()) {
@@ -1398,57 +1414,55 @@ ValueObjectSP GetValueForOffset(StackFrame &frame, ValueObjectSP &parent,
   }
 
   for (int ci = 0, ce = parent->GetNumChildren(); ci != ce; ++ci) {
-    ValueObjectSP child_sp = parent->GetChildAtIndex(ci);
+    std::optional<ValueObjectSP> child_sp = parent->GetChildAtIndex(ci);
 
     if (!child_sp) {
-      return ValueObjectSP();
+      return {};
     }
 
-    int64_t child_offset = child_sp->GetByteOffset();
-    int64_t child_size = child_sp->GetByteSize().value_or(0);
+    int64_t child_offset = child_sp.value()->GetByteOffset();
+    int64_t child_size = child_sp.value()->GetByteSize().value_or(0);
 
     if (offset >= child_offset && offset < (child_offset + child_size)) {
-      return GetValueForOffset(frame, child_sp, offset - child_offset);
+      return GetValueForOffset(frame, child_sp.value(), offset - child_offset);
     }
   }
 
   if (offset == 0) {
     return parent;
   } else {
-    return ValueObjectSP();
+    return {};
   }
 }
 
-ValueObjectSP GetValueForDereferincingOffset(StackFrame &frame,
-                                             ValueObjectSP &base,
-                                             int64_t offset) {
+std::optional<ValueObjectSP> GetValueForDereferincingOffset(StackFrame &frame,
+                                                            ValueObjectSP &base,
+                                                            int64_t offset) {
   // base is a pointer to something
   // offset is the thing to add to the pointer We return the most sensible
   // ValueObject for the result of *(base+offset)
 
   if (!base->IsPointerOrReferenceType()) {
-    return ValueObjectSP();
+    return {};
   }
 
-  Status error;
-  ValueObjectSP pointee = base->Dereference(error);
+  std::optional<ValueObjectSP> pointee = base->Dereference();
 
-  if (!pointee) {
-    return ValueObjectSP();
+  if (!pointee || pointee.value()->GetError().Fail()) {
+    return {};
   }
 
-  if (offset >= 0 && uint64_t(offset) >= pointee->GetByteSize()) {
-    int64_t index = offset / pointee->GetByteSize().value_or(1);
-    offset = offset % pointee->GetByteSize().value_or(1);
+  if (offset >= 0 && uint64_t(offset) >= pointee.value()->GetByteSize()) {
+    int64_t index = offset / pointee.value()->GetByteSize().value_or(1);
+    offset = offset % pointee.value()->GetByteSize().value_or(1);
     const bool can_create = true;
     pointee = base->GetSyntheticArrayMember(index, can_create);
   }
 
-  if (!pointee || error.Fail()) {
-    return ValueObjectSP();
-  }
+  if (!pointee)
+    return {};
 
-  return GetValueForOffset(frame, pointee, offset);
+  return GetValueForOffset(frame, pointee.value(), offset);
 }
 
 /// Attempt to reconstruct the ValueObject for the address contained in a
@@ -1476,9 +1490,11 @@ ValueObjectSP GetValueForDereferincingOffset(StackFrame &frame,
 ///   A string describing the base for the ExpressionPath.  This could be a
 ///     variable, a register value, an argument, or a function return value.
 ///   The ValueObject if found.  If valid, it has a valid ExpressionPath.
-lldb::ValueObjectSP DoGuessValueAt(StackFrame &frame, ConstString reg,
-                                   int64_t offset, Disassembler &disassembler,
-                                   VariableList &variables, const Address &pc) {
+std::optional<ValueObjectSP> DoGuessValueAt(StackFrame &frame, ConstString reg,
+                                            int64_t offset,
+                                            Disassembler &disassembler,
+                                            VariableList &variables,
+                                            const Address &pc) {
   // Example of operation for Intel:
   //
   // +14: movq   -0x8(%rbp), %rdi
@@ -1508,7 +1524,7 @@ lldb::ValueObjectSP DoGuessValueAt(StackFrame &frame, ConstString reg,
   const RegisterInfo *reg_info =
       frame.GetRegisterContext()->GetRegisterInfoByName(reg.AsCString());
   if (!reg_info) {
-    return ValueObjectSP();
+    return {};
   }
 
   Instruction::Operand op =
@@ -1527,7 +1543,7 @@ lldb::ValueObjectSP DoGuessValueAt(StackFrame &frame, ConstString reg,
   const uint32_t current_inst =
       disassembler.GetInstructionList().GetIndexOfInstructionAtAddress(pc);
   if (current_inst == UINT32_MAX) {
-    return ValueObjectSP();
+    return {};
   }
 
   for (uint32_t ii = current_inst - 1; ii != (uint32_t)-1; --ii) {
@@ -1632,7 +1648,7 @@ lldb::ValueObjectSP DoGuessValueAt(StackFrame &frame, ConstString reg,
     }
 
     // We have an origin operand.  Can we track its value down?
-    ValueObjectSP source_path;
+    std::optional<ValueObjectSP> source_path;
     ConstString origin_register;
     int64_t origin_offset = 0;
 
@@ -1654,7 +1670,7 @@ lldb::ValueObjectSP DoGuessValueAt(StackFrame &frame, ConstString reg,
         continue;
       }
       source_path =
-          GetValueForDereferincingOffset(frame, source_path, offset);
+          GetValueForDereferincingOffset(frame, source_path.value(), offset);
     }
 
     if (source_path) {
@@ -1662,12 +1678,12 @@ lldb::ValueObjectSP DoGuessValueAt(StackFrame &frame, ConstString reg,
     }
   }
 
-  return ValueObjectSP();
+  return {};
 }
 }
 
-lldb::ValueObjectSP StackFrame::GuessValueForRegisterAndOffset(ConstString reg,
-                                                               int64_t offset) {
+std::optional<ValueObjectSP>
+StackFrame::GuessValueForRegisterAndOffset(ConstString reg, int64_t offset) {
   TargetSP target_sp = CalculateTarget();
 
   const ArchSpec &target_arch = target_sp->GetArchitecture();
@@ -1675,12 +1691,12 @@ lldb::ValueObjectSP StackFrame::GuessValueForRegisterAndOffset(ConstString reg,
   Block *frame_block = GetFrameBlock();
 
   if (!frame_block) {
-    return ValueObjectSP();
+    return {};
   }
 
   Function *function = frame_block->CalculateSymbolContextFunction();
   if (!function) {
-    return ValueObjectSP();
+    return {};
   }
 
   AddressRange pc_range = function->GetAddressRange();
@@ -1690,7 +1706,7 @@ lldb::ValueObjectSP StackFrame::GuessValueForRegisterAndOffset(ConstString reg,
       GetFrameCodeAddress().GetFileAddress() -
               pc_range.GetBaseAddress().GetFileAddress() >=
           pc_range.GetByteSize()) {
-    return ValueObjectSP();
+    return {};
   }
 
   const char *plugin_name = nullptr;
@@ -1701,31 +1717,29 @@ lldb::ValueObjectSP StackFrame::GuessValueForRegisterAndOffset(ConstString reg,
                                      *target_sp, pc_range, force_live_memory);
 
   if (!disassembler_sp || !disassembler_sp->GetInstructionList().GetSize()) {
-    return ValueObjectSP();
+    return {};
   }
 
   const bool get_file_globals = false;
   VariableList *variables = GetVariableList(get_file_globals, nullptr);
 
   if (!variables) {
-    return ValueObjectSP();
+    return {};
   }
 
   return DoGuessValueAt(*this, reg, offset, *disassembler_sp, *variables,
                         GetFrameCodeAddress());
 }
 
-lldb::ValueObjectSP StackFrame::FindVariable(ConstString name) {
-  ValueObjectSP value_sp;
-
+std::optional<lldb::ValueObjectSP> StackFrame::FindVariable(ConstString name) {
   if (!name)
-    return value_sp;
+    return {};
 
   TargetSP target_sp = CalculateTarget();
   ProcessSP process_sp = CalculateProcess();
 
   if (!target_sp && !process_sp)
-    return value_sp;
+    return {};
 
   VariableList variable_list;
   VariableSP var_sp;
@@ -1744,10 +1758,10 @@ lldb::ValueObjectSP StackFrame::FindVariable(ConstString name) {
     }
 
     if (var_sp)
-      value_sp = GetValueObjectForFrameVariable(var_sp, eNoDynamicValues);
+      return GetValueObjectForFrameVariable(var_sp, eNoDynamicValues);
   }
 
-  return value_sp;
+  return {};
 }
 
 TargetSP StackFrame::CalculateTarget() {
diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp
index 302c2bad7021b9f..22ce02d0b94801d 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();
diff --git a/lldb/source/Target/Thread.cpp b/lldb/source/Target/Thread.cpp
index 865cee97e6d8783..73cbc23cbc2277a 100644
--- a/lldb/source/Target/Thread.cpp
+++ b/lldb/source/Target/Thread.cpp
@@ -1443,9 +1443,10 @@ Status Thread::ReturnFromFrameWithIndex(uint32_t frame_idx,
   return ReturnFromFrame(frame_sp, return_value_sp, broadcast);
 }
 
-Status Thread::ReturnFromFrame(lldb::StackFrameSP frame_sp,
-                               lldb::ValueObjectSP return_value_sp,
-                               bool broadcast) {
+Status
+Thread::ReturnFromFrame(lldb::StackFrameSP frame_sp,
+                        std::optional<lldb::ValueObjectSP> return_value_sp,
+                        bool broadcast) {
   Status return_error;
 
   if (!frame_sp) {
@@ -1480,8 +1481,9 @@ Status Thread::ReturnFromFrame(lldb::StackFrameSP frame_sp,
         if (return_type) {
           StreamString s;
           return_type.DumpTypeDescription(&s);
-          ValueObjectSP cast_value_sp = return_value_sp->Cast(return_type);
-          if (cast_value_sp) {
+          ValueObjectSP cast_value_sp =
+              return_value_sp.value()->Cast(return_type);
+          if (cast_value_sp->GetError().Success()) {
             cast_value_sp->SetFormat(eFormatHex);
             return_value_sp = cast_value_sp;
           }
@@ -1489,7 +1491,8 @@ Status Thread::ReturnFromFrame(lldb::StackFrameSP frame_sp,
       }
     }
 
-    return_error = abi->SetReturnValueObject(older_frame_sp, return_value_sp);
+    return_error =
+        abi->SetReturnValueObject(older_frame_sp, return_value_sp.value());
     if (!return_error.Success())
       return return_error;
   }
@@ -1994,7 +1997,7 @@ Status Thread::StepOut(uint32_t frame_idx) {
   return error;
 }
 
-ValueObjectSP Thread::GetCurrentException() {
+std::optional<ValueObjectSP> Thread::GetCurrentException() {
   if (auto frame_sp = GetStackFrameAtIndex(0))
     if (auto recognized_frame = frame_sp->GetRecognizedFrame())
       if (auto e = recognized_frame->GetExceptionObject())
@@ -2007,18 +2010,18 @@ ValueObjectSP Thread::GetCurrentException() {
       return e;
   }
 
-  return ValueObjectSP();
+  return {};
 }
 
 ThreadSP Thread::GetCurrentExceptionBacktrace() {
-  ValueObjectSP exception = GetCurrentException();
+  std::optional<ValueObjectSP> exception = GetCurrentException();
   if (!exception)
     return ThreadSP();
 
   // NOTE: Even though this behavior is generalized, only ObjC is actually
   // supported at the moment.
   for (LanguageRuntime *runtime : GetProcess()->GetLanguageRuntimes()) {
-    if (auto bt = runtime->GetBacktraceThreadFromException(exception))
+    if (auto bt = runtime->GetBacktraceThreadFromException(exception.value()))
       return bt;
   }
 



More information about the lldb-commits mailing list