diff --git a/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp b/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp
index 4eea3687adc1b..021858308f27e 100644
--- a/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp
@@ -815,6 +815,10 @@ SwiftLanguageRuntime::GetNumChildren(CompilerType type,
       return llvm::createStringError("could not typeref for " +
                                      type.GetMangledTypeName().GetString());
 
+    // Indirect enums.
+    if (type.GetTypeInfo() & lldb::eTypeIsEnumeration)
+      return 1;
+
     // Existentials.
     if (size_t n = GetExistentialSyntheticChildren(ts, tr, ti).size())
       return n;
@@ -1029,6 +1033,8 @@ SwiftLanguageRuntime::GetIndexOfChildMemberWithName(
   auto ts = type.GetTypeSystem().dyn_cast_or_null<TypeSystemSwiftTypeRef>();
   if (!ts)
     return {SwiftLanguageRuntime::eError, {}};
+  if (!exe_ctx)
+    return {SwiftLanguageRuntime::eError, {}};
 
   using namespace swift::reflection;
   // Try the static type metadata.
@@ -1086,6 +1092,29 @@ SwiftLanguageRuntime::GetIndexOfChildMemberWithName(
                                            exe_ctx, omit_empty_base_classes,
                                            child_indexes);
     case ReferenceKind::Strong: {
+      // Indirect enums.
+      if (type.GetTypeInfo() & lldb::eTypeIsEnumeration) {
+        const swift::reflection::TypeRef *tr = nullptr;
+        auto ti_or_err = GetSwiftRuntimeTypeInfo(
+            type, exe_ctx->GetBestExecutionContextScope(), &tr);
+        if (!ti_or_err) {
+          LLDB_LOG_ERROR(GetLog(LLDBLog::Types), ti_or_err.takeError(),
+                         "Could not get enum type info: {0}");
+          return {SwiftLanguageRuntime::eError, {}};
+        }
+        auto *eti = llvm::dyn_cast<EnumTypeInfo>(&*ti_or_err);
+        if (!eti) {
+          // This is probably a generic single-payload enum.
+          // Let's pretend we found it.
+          LLDB_LOG(GetLog(LLDBLog::Types),
+                   "Presuming generic single-payload enum.");
+          child_indexes.push_back(0);
+          return {SwiftLanguageRuntime::eFound, child_indexes.size()};
+        }
+        return findFieldWithName(eti->getCases(), tr, name, true,
+                                 child_indexes);
+      }
+
       ThreadSafeReflectionContext reflection_ctx = GetReflectionContext();
       if (!reflection_ctx)
         return {SwiftLanguageRuntime::eError, {}};
@@ -1197,6 +1226,47 @@ llvm::Expected<CompilerType> SwiftLanguageRuntime::GetChildCompilerTypeAtIndex(
     return pack_element_type;
   }
 
+  auto get_from_indirect_enum = [&]() -> llvm::Expected<CompilerType> {
+    ThreadSafeReflectionContext reflection_ctx = GetReflectionContext();
+    if (!reflection_ctx)
+      return llvm::createStringError("no reflection context");
+    // The indirect enum field should point to a closure context.
+    LLDBTypeInfoProvider tip(*this, &exe_ctx);
+    lldb::addr_t instance = ::MaskMaybeBridgedPointer(GetProcess(), pointer);
+    auto ti_or_err = reflection_ctx->GetTypeInfoFromInstance(
+        instance, &tip, ts->GetDescriptorFinder());
+    if (!ti_or_err) {
+      llvm::consumeError(ti_or_err.takeError());
+      return CompilerType();
+    }
+    auto *ti = &*ti_or_err;
+    if (auto *rti = llvm::dyn_cast<swift::reflection::RecordTypeInfo>(ti)) {
+      switch (rti->getRecordKind()) {
+      case swift::reflection::RecordKind::ClosureContext: {
+        auto &field = rti->getFields()[0];
+        auto *type_ref = field.TR;
+        language_flags |= TypeSystemSwift::LanguageFlags::eIsIndirectEnumCase;
+        child_byte_offset = field.Offset;
+        child_byte_size = field.TI.getSize();
+        return GetTypeFromTypeRef(*ts, type_ref);
+      }
+      case swift::reflection::RecordKind::Tuple: {
+        std::vector<TypeSystemSwift::TupleElement> elts;
+        for (auto &field : rti->getFields())
+          elts.emplace_back(ConstString(), GetTypeFromTypeRef(*ts, field.TR));
+        return ts->CreateTupleType(elts);
+      }
+      default:
+        return llvm::createStringError(
+            "unexpected kind of indirect record enum");
+      }
+    }
+    language_flags |= TypeSystemSwift::LanguageFlags::eIsIndirectEnumCase;
+    child_byte_offset = 0;
+    child_byte_size = ti->getSize();
+    return ts->GetBuiltinRawPointerType();
+  };
+
   // The actual conversion from the FieldInfo record.
   auto get_from_field_info =
       [&](const swift::reflection::FieldInfo &field,
@@ -1225,27 +1295,16 @@ llvm::Expected<CompilerType> SwiftLanguageRuntime::GetChildCompilerTypeAtIndex(
     CompilerType result;
     if (tuple)
       result = tuple->element_type;
-    else if (is_indirect_enum) {
-      ThreadSafeReflectionContext reflection_ctx = GetReflectionContext();
-      if (!reflection_ctx)
-        return llvm::createStringError("no reflection context");
-      // The indirect enum field should point to a closure context.
-      LLDBTypeInfoProvider tip(*this, &exe_ctx);
-      lldb::addr_t instance = ::MaskMaybeBridgedPointer(GetProcess(), pointer);
-      auto ti_or_err = reflection_ctx->GetTypeInfoFromInstance(
-          instance, &tip, ts->GetDescriptorFinder());
-      if (!ti_or_err)
-        return ti_or_err.takeError();
-      auto *ti = &*ti_or_err;
-      auto *rti = llvm::dyn_cast_or_null<swift::reflection::RecordTypeInfo>(ti);
-      if (rti->getFields().size() < 1)
-        return llvm::createStringError("no fields in indirect enum");
-      auto &field = rti->getFields()[0];
-      auto *type_ref = field.TR;
-      result = GetTypeFromTypeRef(*ts, type_ref);
-      child_byte_offset = field.Offset;
-    } else
+    else {
+      if (is_indirect_enum) {
+        auto type_or_err = get_from_indirect_enum();
+        // Only if this couldn't be resolved as an instance pointer, carry on.
+        if (!type_or_err || *type_or_err)
+          return type_or_err;
+      }
       result = GetTypeFromTypeRef(*ts, field.TR);
+    }
+
     // Bug-for-bug compatibility. See comment in
     // SwiftASTContext::GetBitSize().
     if (result.IsFunctionType())
@@ -1395,6 +1454,10 @@ llvm::Expected<CompilerType> SwiftLanguageRuntime::GetChildCompilerTypeAtIndex(
     if (!reflection_ctx)
       return llvm::createStringError("no reflection context");
 
+    // Indirect enums.
+    if (type.GetTypeInfo() & lldb::eTypeIsEnumeration)
+      return get_from_indirect_enum();
+
     CompilerType instance_type = valobj->GetCompilerType();
     auto instance_ts =
         instance_type.GetTypeSystem().dyn_cast_or_null<TypeSystemSwift>();
diff --git a/lldb/test/API/lang/swift/enums/indirect/Makefile b/lldb/test/API/lang/swift/enums/indirect/Makefile
new file mode 100644
index 0000000000000..2a69023633b34
--- /dev/null
+++ b/lldb/test/API/lang/swift/enums/indirect/Makefile
@@ -0,0 +1,3 @@
+SWIFT_SOURCES := main.swift
+
+include Makefile.rules
diff --git a/lldb/test/API/lang/swift/enums/indirect/TestSwiftEnumIndirect.py b/lldb/test/API/lang/swift/enums/indirect/TestSwiftEnumIndirect.py
new file mode 100644
index 0000000000000..0fca490458286
--- /dev/null
+++ b/lldb/test/API/lang/swift/enums/indirect/TestSwiftEnumIndirect.py
@@ -0,0 +1,64 @@
+import lldb
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test.decorators import *
+import lldbsuite.test.lldbutil as lldbutil
+
+class TestCase(TestBase):
+    @swiftTest
+    def test(self):
+        """Test indirect enums"""
+        self.build()
+        target, process, thread, bkpt = lldbutil.run_to_source_breakpoint(
+            self, "break here", lldb.SBFileSpec("main.swift")
+        )
+        if self.TraceOn():
+            self.expect('v')
+        frame = thread.frames[0]
+        generic_s = frame.FindVariable("generic_s")
+        s = generic_s.GetChildMemberWithName("s")
+        t = s.GetChildMemberWithName("t")
+        lldbutil.check_variable(self, t, False, value="123")
+
+        generic_large_s = frame.FindVariable("generic_large_s")
+        s = generic_s.GetChildMemberWithName("s")
+        t = s.GetChildMemberWithName("t")
+        lldbutil.check_variable(self, t, False, value="123")
+
+        generic_c = frame.FindVariable("generic_c")
+        c = generic_c.GetChildMemberWithName("c")
+        t = c.GetChildMemberWithName("t")
+        lldbutil.check_variable(self, t, False, value="123")
+
+        multi_s = frame.FindVariable("multi_s")
+        s = multi_s.GetChildMemberWithName("s")
+        t = s.GetChildMemberWithName("t")
+        lldbutil.check_variable(self, t, False, value="123")
+
+        multi_c = frame.FindVariable("multi_c")
+        lldbutil.check_variable(self, multi_c, False, value="c")
+
+        tuple_a = frame.FindVariable("tuple_a")
+        a = tuple_a.GetChildMemberWithName("a")
+        self.assertEqual(a.GetNumChildren(), 2)
+        lldbutil.check_variable(self, a.GetChildAtIndex(0), False, value="23")
+        lldbutil.check_variable(self, a.GetChildAtIndex(1), False, summary='"hello"')
+        tuple_b = frame.FindVariable("tuple_b")
+        b = tuple_b.GetChildMemberWithName("b")
+        self.assertEqual(b.GetNumChildren(), 1)
+        lldbutil.check_variable(self, b.GetChildAtIndex(0), False, value="42")
+        tuple_c = frame.FindVariable("tuple_c")
+        c = tuple_c.GetChildMemberWithName("c")
+        lldbutil.check_variable(self, c, False, value="32")
+        tuple_d = frame.FindVariable("tuple_d")
+        lldbutil.check_variable(self, tuple_d, False, value="d")
+
+        tree = frame.FindVariable("tree")
+        n0 = tree.GetChildMemberWithName("node")
+        n1 = n0.GetChildAtIndex(0)
+        n2 = n1.GetChildAtIndex(0)
+        l0 = n2.GetChildAtIndex(0)
+        lldbutil.check_variable(self, l0.GetChildAtIndex(0), False, value="1")
+        l1 = n2.GetChildAtIndex(1)
+        lldbutil.check_variable(self, l1.GetChildAtIndex(0), False, value="2")
+        l2 = n0.GetChildAtIndex(1)
+        lldbutil.check_variable(self, l2.GetChildAtIndex(0), False, value="3")
diff --git a/lldb/test/API/lang/swift/enums/indirect/main.swift b/lldb/test/API/lang/swift/enums/indirect/main.swift
new file mode 100644
index 0000000000000..b8ba92f9a530c
--- /dev/null
+++ b/lldb/test/API/lang/swift/enums/indirect/main.swift
@@ -0,0 +1,61 @@
+struct S<T> {
+  let t: T
+}
+
+enum EGenericS<T> {
+  indirect case s(S<T>)
+}
+
+class C<T> {
+  init(t: T) { self.t = t }
+  let t: T
+}
+
+struct LargeS<T> {
+  let t: T
+  let space = (0, 1, 2, 3, 4, 5, 6, 7)
+}
+
+enum EGenericLargeS<T> {
+  indirect case s(LargeS<T>)
+}
+
+enum EGenericC<T> {
+  indirect case c(C<T>)
+}
+
+enum EGenericMulti<T> {
+  indirect case s(S<T>)
+  indirect case c(C<T>)
+}
+
+enum ETuple {
+  indirect case a(Int, String)
+  indirect case b(Int)
+  case c(Int)
+  case d
+}
+
+enum ETree<T> {
+  indirect case node(ETree<T>, ETree<T>)
+  case leaf(T)
+}
+
+func main() {
+  let generic_s = EGenericS<Int>.s(S(t: 123))
+  let generic_large_s = EGenericLargeS<Int>.s(LargeS(t: 123))
+  let generic_c = EGenericC<Int>.c(C(t: 123))
+  let multi_s = EGenericMulti<Int>.s(S(t: 123))
+  let multi_c = EGenericMulti<Int>.c(C(t: 123))
+  let tuple_a = ETuple.a(23, "hello")
+  let tuple_b = ETuple.b(42)
+  let tuple_c = ETuple.c(32)
+  let tuple_d = ETuple.d
+  let tree = ETree<Int>.node(
+      ETree<Int>.node(ETree<Int>.leaf(1),
+                      ETree<Int>.leaf(2)),
+      ETree<Int>.leaf(3))
+  print("break here")
+}
+
+main()