From 0a2539e8cc597f17e9fbf1277f85576b98d005d7 Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Tue, 23 Sep 2025 17:40:19 -0700 Subject: [PATCH 1/5] [LLDB] Support nested generic type aliases (and thus Swift.Array) in Embedded Swift In order to format a Swift.Array in Swift it is necessary to properly resolve type aliases to generic types from DWARF. This patch adds support for properly generic type aliases in and out of context when reconstructing them from DWARF. rdar://159429896 (cherry picked from commit 4d607884bf906381df01806bb4e97d255faf2cd2) Conflicts: lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp (cherry picked from commit b74f2e9f0373fbdfd49274b412f71840e946b5c6) --- ...ftLanguageRuntimeDynamicTypeResolution.cpp | 85 ++++++-- .../SymbolFile/DWARF/DWARFASTParserSwift.cpp | 5 +- .../SymbolFile/DWARF/DWARFASTParserSwift.h | 2 + .../DWARFASTParserSwiftDescriptorFinder.cpp | 95 ++++++++- .../Plugins/SymbolFile/DWARF/DWARFDIE.cpp | 21 ++ .../Swift/TypeSystemSwiftTypeRef.cpp | 186 ++++++++++++++++- .../TypeSystem/Swift/TypeSystemSwiftTypeRef.h | 11 +- .../TestSwiftEmbeddedFrameVariable.py | 189 +++++++++++------- .../swift/embedded/frame_variable/main.swift | 43 +++- 9 files changed, 522 insertions(+), 115 deletions(-) diff --git a/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp b/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp index 277a4967fcc8d..3470975d4033f 100644 --- a/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp +++ b/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// #include "LLDBMemoryReader.h" +#include "Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.h" #include "ReflectionContextInterface.h" #include "SwiftLanguageRuntime.h" #include "SwiftMetadataCache.h" @@ -607,13 +608,14 @@ std::optional SwiftLanguageRuntime::GetMemberVariableOffset( namespace { CompilerType GetTypeFromTypeRef(TypeSystemSwiftTypeRef &ts, - const swift::reflection::TypeRef *type_ref) { + const swift::reflection::TypeRef *type_ref, + swift::Mangle::ManglingFlavor flavor) { if (!type_ref) return {}; swift::Demangle::Demangler dem; swift::Demangle::NodePointer node = type_ref->getDemangling(dem); // TODO: the mangling flavor should come from the TypeRef. - return ts.RemangleAsType(dem, node, ts.GetManglingFlavor()); + return ts.RemangleAsType(dem, node, flavor); } struct ExistentialSyntheticChild { @@ -627,7 +629,8 @@ struct ExistentialSyntheticChild { llvm::SmallVector GetExistentialSyntheticChildren(TypeSystemSwiftTypeRef &ts, const swift::reflection::TypeRef *tr, - const swift::reflection::TypeInfo *ti) { + const swift::reflection::TypeInfo *ti, + swift::Mangle::ManglingFlavor flavor) { llvm::SmallVector children; auto *protocol_composition_tr = llvm::dyn_cast(tr); @@ -641,7 +644,8 @@ GetExistentialSyntheticChildren(TypeSystemSwiftTypeRef &ts, children.push_back({"object", [=]() { if (auto *super_class_tr = protocol_composition_tr->getSuperclass()) - return GetTypeFromTypeRef(*ts_sp, super_class_tr); + return GetTypeFromTypeRef(*ts_sp, super_class_tr, + flavor); else return rti ? ts_sp->GetBuiltinUnknownObjectType() : ts_sp->GetBuiltinRawPointerType(); @@ -652,9 +656,9 @@ GetExistentialSyntheticChildren(TypeSystemSwiftTypeRef &ts, for (unsigned i = 1; i < fields.size(); ++i) { TypeSystemSwiftTypeRefSP ts_sp = ts.GetTypeSystemSwiftTypeRef(); auto *type_ref = fields[i].TR; - children.push_back({fields[i].Name, [=]() { - return GetTypeFromTypeRef(*ts_sp, type_ref); - }}); + children.push_back( + {fields[i].Name, + [=]() { return GetTypeFromTypeRef(*ts_sp, type_ref, flavor); }}); } } } @@ -702,12 +706,20 @@ CompilerType GetTypedefedTypeRecursive(CompilerType type) { class SwiftRuntimeTypeVisitor { SwiftLanguageRuntime &m_runtime; ExecutionContext m_exe_ctx; + swift::Mangle::ManglingFlavor m_flavor = + swift::Mangle::ManglingFlavor::Default; CompilerType m_type; ValueObject *m_valobj = nullptr; bool m_hide_superclass = false; bool m_include_clang_types = false; bool m_visit_superclass = false; + void SetFlavor() { + if (auto ts_sp = + m_type.GetTypeSystem().dyn_cast_or_null()) + m_flavor = ts_sp->GetManglingFlavor(&m_exe_ctx); + } + public: struct ChildInfo { uint32_t byte_size = 0; @@ -732,6 +744,7 @@ class SwiftRuntimeTypeVisitor { : m_runtime(runtime), m_type(type), m_valobj(valobj) { if (valobj) m_exe_ctx = valobj->GetExecutionContextRef(); + SetFlavor(); } SwiftRuntimeTypeVisitor(SwiftLanguageRuntime &runtime, CompilerType type, ExecutionContextScope *exe_scope, @@ -740,6 +753,7 @@ class SwiftRuntimeTypeVisitor { m_include_clang_types(include_clang_types) { if (exe_scope) exe_scope->CalculateExecutionContext(m_exe_ctx); + SetFlavor(); } SwiftRuntimeTypeVisitor(SwiftLanguageRuntime &runtime, CompilerType type, ExecutionContext *exe_ctx, bool hide_superclass, @@ -749,6 +763,7 @@ class SwiftRuntimeTypeVisitor { m_visit_superclass(visit_superclass) { if (exe_ctx) m_exe_ctx = *exe_ctx; + SetFlavor(); } llvm::Error VisitAllChildren(VisitCallback callback) { return VisitImpl({}, callback).takeError(); @@ -871,7 +886,7 @@ SwiftRuntimeTypeVisitor::VisitImpl(std::optional visit_only, field_type = tuple->element_type; else { if (!field_type) - field_type = GetTypeFromTypeRef(ts, field.TR); + field_type = GetTypeFromTypeRef(ts, field.TR, m_flavor); } auto get_info = [&]() -> llvm::Expected { ChildInfo child; @@ -968,7 +983,7 @@ SwiftRuntimeTypeVisitor::VisitImpl(std::optional visit_only, if (rti->getRecordKind() == swift::reflection::RecordKind::ClassExistential) { // Compatibility with SwiftASTContext. - auto children = GetExistentialSyntheticChildren(ts, tr, ti); + auto children = GetExistentialSyntheticChildren(ts, tr, ti, m_flavor); if (count_only) return children.size(); auto visit_existential = [&](ExistentialSyntheticChild c, unsigned idx) { @@ -1019,7 +1034,7 @@ SwiftRuntimeTypeVisitor::VisitImpl(std::optional visit_only, llvm::dyn_cast_or_null(ti)) { // Is this an Existential? unsigned i = 0; - auto children = GetExistentialSyntheticChildren(ts, tr, ti); + auto children = GetExistentialSyntheticChildren(ts, tr, ti, m_flavor); if (children.size()) { if (count_only) return children.size(); @@ -1109,7 +1124,7 @@ SwiftRuntimeTypeVisitor::VisitImpl(std::optional visit_only, if (auto *super_tr = reflection_ctx->LookupSuperclass( *tr, ts.GetDescriptorFinder())) if (auto error = visit_callback( - GetTypeFromTypeRef(ts, super_tr), depth, + GetTypeFromTypeRef(ts, super_tr, m_flavor), depth, []() -> std::string { return ""; }, []() -> llvm::Expected { return ChildInfo(); @@ -1143,8 +1158,9 @@ SwiftRuntimeTypeVisitor::VisitImpl(std::optional visit_only, return ChildInfo(); }; - if (auto error = visit_callback(GetTypeFromTypeRef(ts, super_tr), 0, - get_name, get_info)) + if (auto error = + visit_callback(GetTypeFromTypeRef(ts, super_tr, m_flavor), 0, + get_name, get_info)) return error; } @@ -1263,7 +1279,7 @@ SwiftRuntimeTypeVisitor::VisitImpl(std::optional visit_only, return success; } - CompilerType super_type = GetTypeFromTypeRef(ts, type_ref); + CompilerType super_type = GetTypeFromTypeRef(ts, type_ref, m_flavor); auto get_name = [&]() -> std::string { auto child_name = super_type.GetTypeName().GetStringRef().str(); // FIXME: This should be fixed in GetDisplayTypeName instead! @@ -1471,6 +1487,8 @@ SwiftLanguageRuntime::ProjectEnum(ValueObject &valobj) { if (!ti_or_err) return ti_or_err.takeError(); auto *ti = &*ti_or_err; + auto flavor = + SwiftLanguageRuntime::GetManglingFlavor(enum_type.GetMangledTypeName()); auto project_indirect_enum = [&](uint64_t offset, std::string name) -> llvm::Expected { @@ -1496,13 +1514,14 @@ SwiftLanguageRuntime::ProjectEnum(ValueObject &valobj) { auto &field = rti->getFields()[0]; auto *type_ref = field.TR; payload += field.Offset; - payload_type = GetTypeFromTypeRef(ts, type_ref); + payload_type = GetTypeFromTypeRef(ts, type_ref, flavor); break; } case swift::reflection::RecordKind::Tuple: { std::vector elts; for (auto &field : rti->getFields()) - elts.emplace_back(ConstString(), GetTypeFromTypeRef(ts, field.TR)); + elts.emplace_back(ConstString(), + GetTypeFromTypeRef(ts, field.TR, flavor)); payload_type = ts.CreateTupleType(elts); break; } @@ -1570,7 +1589,7 @@ SwiftLanguageRuntime::ProjectEnum(ValueObject &valobj) { if (is_indirect_enum) return project_indirect_enum(field_info.Offset, field_info.Name); - CompilerType projected_type = GetTypeFromTypeRef(ts, field_info.TR); + CompilerType projected_type = GetTypeFromTypeRef(ts, field_info.TR, flavor); if (field_info.Offset != 0) { assert(false); return llvm::createStringError("enum with unexpected offset"); @@ -1678,7 +1697,9 @@ CompilerType SwiftLanguageRuntime::GetBaseClass(CompilerType class_ty) { } auto *super_tr = reflection_ctx->LookupSuperclass( *type_ref_or_err, tr_ts->GetDescriptorFinder()); - return GetTypeFromTypeRef(*tr_ts, super_tr); + auto flavor = + SwiftLanguageRuntime::GetManglingFlavor(class_ty.GetMangledTypeName()); + return GetTypeFromTypeRef(*tr_ts, super_tr, flavor); } bool SwiftLanguageRuntime::ForEachSuperClassType( @@ -3393,9 +3414,9 @@ SwiftLanguageRuntime::GetSwiftRuntimeTypeInfo( // Resolve all generic type parameters in the type for the current // frame. Generic parameter binding has to happen in the scratch // context. + ExecutionContext exe_ctx; if (exe_scope) if (StackFrame *frame = exe_scope->CalculateStackFrame().get()) { - ExecutionContext exe_ctx; frame->CalculateExecutionContext(exe_ctx); auto bound_type_or_err = BindGenericTypeParameters(*frame, type); if (!bound_type_or_err) @@ -3417,6 +3438,30 @@ SwiftLanguageRuntime::GetSwiftRuntimeTypeInfo( if (!reflection_ctx) return llvm::createStringError("no reflection context"); + // The TypeSystemSwiftTypeRefForExpressions doesn't ve a SymbolFile, + // so any DWARF lookups for Embedded Swift fail. + // + // FIXME: It's unclear whether this is safe to do in a non-LTO Swift program. + if (llvm::isa(tr_ts.get()) && + tr_ts->GetManglingFlavor(&exe_ctx) == + swift::Mangle::ManglingFlavor::Embedded) { + if (auto frame_sp = exe_ctx.GetFrameSP()) { + auto &sc = frame_sp->GetSymbolContext(eSymbolContextModule); + if (sc.module_sp) { + auto ts_or_err = + sc.module_sp->GetTypeSystemForLanguage(eLanguageTypeSwift); + if (!ts_or_err) + return ts_or_err.takeError(); + if (auto *tr_ts = llvm::dyn_cast_or_null( + ts_or_err->get())) { + LLDBTypeInfoProvider provider(*this, *tr_ts); + return reflection_ctx->GetTypeInfo(*type_ref_or_err, &provider, + tr_ts->GetDescriptorFinder()); + } + } + } + } + LLDBTypeInfoProvider provider(*this, ts); return reflection_ctx->GetTypeInfo(*type_ref_or_err, &provider, tr_ts->GetDescriptorFinder()); @@ -3555,7 +3600,7 @@ SwiftLanguageRuntime::ResolveTypeAlias(CompilerType alias) { type_ref = &*type_ref_or_err; } - CompilerType resolved = GetTypeFromTypeRef(*tr_ts, type_ref); + CompilerType resolved = GetTypeFromTypeRef(*tr_ts, type_ref, flavor); LLDB_LOG(GetLog(LLDBLog::Types), "Resolved type alias {0} = {1} using reflection metadata.", alias.GetMangledTypeName(), resolved.GetMangledTypeName()); diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserSwift.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserSwift.cpp index 9d576340420eb..3a146cd06375f 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserSwift.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserSwift.cpp @@ -184,10 +184,9 @@ lldb::TypeSP DWARFASTParserSwift::ParseTypeFromDWARF(const SymbolContext &sc, if (TypeSP desugared_type = get_type(die)) { // For a typedef, store the once desugared type as the name. CompilerType type = desugared_type->GetForwardCompilerType(); - if (auto swift_ast_ctx = + if (auto ts = type.GetTypeSystem().dyn_cast_or_null()) - preferred_name = - swift_ast_ctx->GetMangledTypeName(type.GetOpaqueQualType()); + preferred_name = ts->GetMangledTypeName(type.GetOpaqueQualType()); } } } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserSwift.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserSwift.h index 03f7f73c19444..ff6abf12e52c4 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserSwift.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserSwift.h @@ -37,6 +37,8 @@ class DWARFASTParserSwift : public lldb_private::plugin::dwarf::DWARFASTParser, virtual ~DWARFASTParserSwift(); + static std::pair + ResolveTypeAlias(lldb_private::CompilerType alias); lldb::TypeSP ParseTypeFromDWARF(const lldb_private::SymbolContext &sc, const DWARFDIE &die, bool *type_is_new_ptr) override; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserSwiftDescriptorFinder.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserSwiftDescriptorFinder.cpp index dc9e73d2137b2..9c2b089e852b0 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserSwiftDescriptorFinder.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserSwiftDescriptorFinder.cpp @@ -55,6 +55,87 @@ findUnsubstitutedGenericTypeAndDIE(TypeSystemSwiftTypeRef &ts, ts.GetTypeFromMangledTypename(ConstString(mangled_name)); return {{unsubstituted_type, unsubstituted_die}}; } + +lldb_private::CompilerType static MapTypeIntoContext( + TypeSystemSwiftTypeRef &ts, lldb_private::CompilerType context, + lldb_private::CompilerType type) { + return ts.ApplySubstitutions( + type.GetOpaqueQualType(), + ts.GetSubstitutions(context.GetOpaqueQualType())); +} + +std::pair +DWARFASTParserSwift::ResolveTypeAlias(lldb_private::CompilerType alias) { + if (!alias) + return {}; + auto ts_sp = alias.GetTypeSystem().dyn_cast_or_null(); + if (!ts_sp) + return {}; + auto &ts = *ts_sp; + auto *dwarf = llvm::dyn_cast_or_null(ts.GetSymbolFile()); + if (!dwarf) + return {}; + + // Type aliases are (for LLVM implementation reasons) using the + // DW_AT_name as linkage name, so they can't be looked up by base + // name. This should be fixed. + // Meanwhile, instead find them inside their parent type. + CompilerType parent_ctx = ts.GetParentType(alias.GetOpaqueQualType()); + if (!parent_ctx) + return {}; + + DWARFDIE parent_die; + if (TypeSP parent_type = + ts.FindTypeInModule(parent_ctx.GetOpaqueQualType())) { + parent_die = dwarf->GetDIE(parent_type->GetID()); + auto unsubstituted_pair = + findUnsubstitutedGenericTypeAndDIE(ts, parent_die); + if (unsubstituted_pair) + parent_die = unsubstituted_pair->second; + } + if (!parent_die) + return {}; + std::string alias_name = ts.GetBaseName(alias.GetOpaqueQualType()); + for (DWARFDIE child_die : parent_die.children()) { + auto tag = child_die.Tag(); + if (tag == DW_TAG_member) + continue; + std::string base_name; + const auto *name = + child_die.GetAttributeValueAsString(llvm::dwarf::DW_AT_name, ""); + if (name && *name == '$') { + CompilerType candidate = ts.GetTypeFromMangledTypename(ConstString(name)); + base_name = ts.GetBaseName(candidate.GetOpaqueQualType()); + } else { + base_name = name; + } + if (base_name != alias_name) + continue; + + // Follow the typedef. + auto *dwarf_parser = ts.GetDWARFParser(); + if (!dwarf_parser) + return {}; + Type *t = dwarf_parser->GetTypeForDIE(child_die); + if (!t) + return {}; + CompilerType cty = t->GetForwardCompilerType(); + if (ts.IsMeaninglessWithoutDynamicResolution(cty.GetOpaqueQualType())) { + // Substitute the parameters in the LHS of the BGTAT. + if (ts.IsBoundGenericAliasType(alias.GetOpaqueQualType())) { + auto subs = ts.GetSubstitutions(alias.GetOpaqueQualType()); + while (subs.size() > 1) + subs.erase(subs.begin()); + cty = ts.ApplySubstitutions(cty.GetOpaqueQualType(), subs); + } + // Substitute the parameters of the RHS of the (BGT)AT. + return {t->shared_from_this(), MapTypeIntoContext(ts, parent_ctx, cty)}; + } + return {t->shared_from_this(), cty}; + } + return {}; +} + /// Given a type system and a typeref, return the compiler type and die of the /// type that matches that mangled name, looking up the in the type system's /// module's debug information. @@ -78,10 +159,17 @@ getTypeAndDie(TypeSystemSwiftTypeRef &ts, auto *dwarf = llvm::cast_or_null(ts.GetSymbolFile()); if (!dwarf) return {}; - auto lldb_type = ts.FindTypeInModule(type.GetOpaqueQualType()); + TypeSP lldb_type = ts.FindTypeInModule(type.GetOpaqueQualType()); + if (!lldb_type) { + std::tie(lldb_type, type) = DWARFASTParserSwift::ResolveTypeAlias(type); + if (lldb_type) { + auto die = dwarf->GetDIE(lldb_type->GetID()); + return {{type, die}}; + } + } if (!lldb_type) { - // TODO: for embedded Swift this is fine but consult other modules here for - // general case? + // TODO: for embedded Swift this is fine but consult other modules + // here for general case? LLDB_LOGV(GetLog(LLDBLog::Types), "Could not find type {0} in module", type.GetMangledTypeName()); return {}; @@ -374,7 +462,6 @@ DWARFASTParserSwift::getFieldDescriptor(const swift::reflection::TypeRef *TR) { lldb_private::AutoBool::False && "Full DWARF debugging for Swift is disabled!"); - auto pair = getTypeAndDie(m_swift_typesystem, TR); if (!pair) return nullptr; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp index 37a7c5ab694a5..f0ab7e1625e43 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp @@ -14,6 +14,7 @@ #include "DWARFDeclContext.h" #include "DWARFUnit.h" #include "LogChannelDWARF.h" +#include "Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.h" #include "lldb/Symbol/Type.h" #include "llvm/ADT/iterator.h" @@ -439,6 +440,26 @@ static void GetDeclContextImpl(DWARFDIE die, bool derive_template_names, } // Add this DIE's contribution at the end of the chain. + auto push_ctx = [&](CompilerContextKind kind, llvm::StringRef name) { + // BEGIN SWIFT + // + // FIXME: This layering violation works around a limitation in + // LLVM that prevents swiftc from emitting both DW_AT_name and + // DW_AT_linkage_name on forward declarations and typedefs. + // + // We should not upstream this but instead fix the Swift compiler. + std::string base_name; + if (!name.empty() && name[0] == '$') { + // We should also check the unit's DW_LANG here. + const char *mangled = ConstString(name).AsCString(); + base_name = TypeSystemSwiftTypeRef::GetBaseName( + (lldb::opaque_compiler_type_t)mangled); + if (!base_name.empty()) + name = base_name; + } + // END SWIFT + context.push_back({kind, ConstString(name)}); + }; switch (die.Tag()) { case DW_TAG_module: case DW_TAG_namespace: diff --git a/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp b/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp index 01c6afeb3db67..19f65fafe8ec4 100644 --- a/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp +++ b/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp @@ -38,6 +38,7 @@ #include "lldb/Utility/Timer.h" #include "lldb/lldb-enumerations.h" +#include "lldb/lldb-types.h" #include "swift/../../lib/ClangImporter/ClangAdapter.h" #include "swift/ClangImporter/ClangImporter.h" #include "swift/Demangling/Demangle.h" @@ -366,6 +367,14 @@ TypeSystemSwiftTypeRef::GetBaseName(swift::Demangle::NodePointer node) { } return {}; } + case Node::Kind::TypeAlias: { + if (node->getNumChildren() != 2) + return {}; + NodePointer ident = node->getChild(1); + if (ident && ident->hasText()) + return ident->getText(); + return {}; + } default: // Visit the child nodes. for (NodePointer child : *node) @@ -374,6 +383,15 @@ TypeSystemSwiftTypeRef::GetBaseName(swift::Demangle::NodePointer node) { } } +std::string +TypeSystemSwiftTypeRef::GetBaseName(lldb::opaque_compiler_type_t type) { + using namespace swift::Demangle; + Demangler dem; + NodePointer node = + swift_demangle::GetDemangledTypeMangling(dem, AsMangledName(type)); + return GetBaseName(node).str(); +} + CompilerType TypeSystemSwiftTypeRef::GetTypeFromTypeMetadataNode( llvm::StringRef mangled_name) { Demangler dem; @@ -1053,7 +1071,22 @@ TypeSystemSwiftTypeRef::ResolveTypeAlias(swift::Demangle::Demangler &dem, } } - if (prefer_clang_types || !results.Done(query)) { + TypeSP type; + if (results.Done(query)) + type = results.GetFirstType(); + + // Find the type by declcontext (-gdwarf-types). + if (!type) { + auto resolved = DWARFASTParserSwift::ResolveTypeAlias( + GetTypeFromMangledTypename(mangled)); + if (resolved.second) { + NodePointer n = + GetDemangledType(dem, resolved.second.GetMangledTypeName()); + return {n, {}}; + } + } + + if (prefer_clang_types || !type) { // No Swift type found -- this could be a Clang typedef. This // check is not done earlier because a Clang typedef that points // to a builtin type, e.g., "typedef unsigned uint32_t", could @@ -1066,7 +1099,6 @@ TypeSystemSwiftTypeRef::ResolveTypeAlias(swift::Demangle::Demangler &dem, return {{}, clang_type}; } - TypeSP type = results.GetFirstType(); if (!type) { LLDB_LOGF(GetLog(LLDBLog::Types), "Found empty type alias %s", mangled.AsCString()); @@ -1097,6 +1129,151 @@ TypeSystemSwiftTypeRef::ResolveTypeAlias(swift::Demangle::Demangler &dem, return {n, {}}; } +static swift::Demangle::NodePointer +GetParentNode(swift::Demangle::NodePointer node) { + if (!node || !node->hasChildren()) + return {}; + if (node->getKind() == Node::Kind::Type) + node = node->getChild(0); + if (!node || !node->hasChildren()) + return {}; + NodePointer parent_node = nullptr; + switch (node->getKind()) { + case Node::Kind::Class: + case Node::Kind::Enum: + case Node::Kind::Structure: + case Node::Kind::TypeAlias: + parent_node = node->getChild(0); + break; + case Node::Kind::BoundGenericClass: + case Node::Kind::BoundGenericEnum: + case Node::Kind::BoundGenericStructure: + case Node::Kind::BoundGenericTypeAlias: { + NodePointer ty = swift_demangle::ChildAtPath(node, {Node::Kind::Type}); + if (!ty || ty->getNumChildren() != 1) + return {}; + + NodePointer inner = ty->getChild(0); + if (!inner || !inner->hasChildren()) + return {}; + parent_node = inner->getChild(0); + break; + } + default: + break; + } + return parent_node; +} + +CompilerType +TypeSystemSwiftTypeRef::GetParentType(lldb::opaque_compiler_type_t type) { + using namespace swift::Demangle; + Demangler dem; + const char *mangled_typename = AsMangledName(type); + auto flavor = SwiftLanguageRuntime::GetManglingFlavor(mangled_typename); + NodePointer node = + swift_demangle::GetDemangledTypeMangling(dem, mangled_typename); + NodePointer parent_node = GetParentNode(node); + if (!parent_node) { + LLDB_LOGF(GetLog(LLDBLog::Types), "Could not determine declcontext of %s.", + mangled_typename); + return {}; + } + if (parent_node->getKind() == Node::Kind::Module) + return {}; + NodePointer type_node = dem.createNode(Node::Kind::Type); + type_node->addChild(parent_node, dem); + return RemangleAsType(dem, type_node, flavor); +} + +std::vector> +TypeSystemSwiftTypeRef::GetSubstitutions(lldb::opaque_compiler_type_t type) { + using namespace swift::Demangle; + Demangler dem; + const char *mangled_typename = AsMangledName(type); + + std::vector> all_subs; + auto flavor = SwiftLanguageRuntime::GetManglingFlavor(mangled_typename); + NodePointer type_node = + swift_demangle::GetDemangledTypeMangling(dem, mangled_typename); + if (!type_node || type_node->getKind() != Node::Kind::Type || + !type_node->hasChildren()) + return all_subs; + + for (NodePointer node = type_node->getChild(0); node; + node = GetParentNode(node)) { + switch (node->getKind()) { + case Node::Kind::BoundGenericClass: + case Node::Kind::BoundGenericEnum: + case Node::Kind::BoundGenericStructure: + case Node::Kind::BoundGenericTypeAlias: { + auto &subs = all_subs.emplace_back(); + if (node->getNumChildren() == 2) { + if (NodePointer params = node->getChild(1)) + for (NodePointer t : *params) { + subs.push_back(RemangleAsType(dem, t, flavor)); + } + } + break; + } + default: + break; + } + } + std::reverse(all_subs.begin(), all_subs.end()); + return all_subs; +} + +CompilerType TypeSystemSwiftTypeRef::ApplySubstitutions( + lldb::opaque_compiler_type_t type, + std::vector> subs) { + using namespace swift::Demangle; + Demangler dem; + const char *mangled_typename = AsMangledName(type); + auto flavor = SwiftLanguageRuntime::GetManglingFlavor(mangled_typename); + NodePointer node = + swift_demangle::GetDemangledTypeMangling(dem, mangled_typename); + + node = Transform(dem, node, [&](NodePointer node) { + if (!node || node->getKind() != Node::Kind::DependentGenericParamType || + node->getNumChildren() != 2) + return node; + NodePointer depth_node = node->getChild(0); + NodePointer index_node = node->getChild(1); + if (!depth_node->hasIndex() || !index_node->hasIndex()) + return node; + unsigned depth = depth_node->getIndex(); + unsigned index = index_node->getIndex(); + if (depth >= subs.size()) + return node; + if (index >= subs[depth].size()) + return node; + CompilerType sub = subs[depth][index]; + return swift_demangle::GetDemangledTypeMangling(dem, + sub.GetMangledTypeName()); + }); + + NodePointer type_node = dem.createNode(Node::Kind::Type); + type_node->addChild(node, dem); + return RemangleAsType(dem, type_node, flavor); +} + +bool TypeSystemSwiftTypeRef::IsBoundGenericAliasType( + lldb::opaque_compiler_type_t type) { + using namespace swift::Demangle; + Demangler dem; + const char *mangled_typename = AsMangledName(type); + + NodePointer node = + swift_demangle::GetDemangledTypeMangling(dem, mangled_typename); + if (!node || node->getKind() != Node::Kind::Type || !node->hasChildren()) + return false; + node = node->getChild(0); + if (!node) + return false; + return node->getKind() == Node::Kind::BoundGenericTypeAlias; +} + std::optional TypeSystemSwiftTypeRef::GetTupleElement(lldb::opaque_compiler_type_t type, size_t idx) { @@ -4282,8 +4459,7 @@ size_t TypeSystemSwiftTypeRef::GetIndexOfChildMemberWithName( } LLDB_LOGF(GetLog(LLDBLog::Types), - "Using SwiftASTContext::GetIndexOfChildMemberWithName fallback for " - "type %s", + "GetIndexOfChildMemberWithName failed for type %s", AsMangledName(type)); // Runtime failed, fallback to SwiftASTContext. @@ -5473,7 +5649,7 @@ TypeSystemSwiftTypeRef::GetDependentGenericParamListForType( } swift::Mangle::ManglingFlavor -TypeSystemSwiftTypeRef::GetManglingFlavor(ExecutionContext *exe_ctx) { +TypeSystemSwiftTypeRef::GetManglingFlavor(const ExecutionContext *exe_ctx) { auto sc = GetSymbolContext(exe_ctx); auto *cu = sc.comp_unit; // Cache the result for the last recently used CU. diff --git a/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.h b/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.h index 9263983f3f158..091e50dcd8f1c 100644 --- a/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.h +++ b/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.h @@ -19,6 +19,7 @@ #include "lldb/Target/ExecutionContext.h" #include "lldb/Utility/ThreadSafeDenseMap.h" #include "lldb/Utility/ThreadSafeStringMap.h" +#include "lldb/lldb-types.h" #include "swift/Demangling/ManglingFlavor.h" // FIXME: needed only for the DenseMap. @@ -137,6 +138,12 @@ class TypeSystemSwiftTypeRef : public TypeSystemSwift { return false; } + CompilerType GetParentType(lldb::opaque_compiler_type_t type); + std::vector> + GetSubstitutions(lldb::opaque_compiler_type_t type); + CompilerType ApplySubstitutions(lldb::opaque_compiler_type_t type, + std::vector> subs); + Module *GetModule() const { return m_module; } /// Return a key for the SwiftASTContext map. If there is debug info it's the @@ -358,6 +365,7 @@ class TypeSystemSwiftTypeRef : public TypeSystemSwift { CompilerType GetRawPointerType(); /// Determine whether \p type is a protocol. bool IsExistentialType(lldb::opaque_compiler_type_t type); + bool IsBoundGenericAliasType(lldb::opaque_compiler_type_t type); /// Recursively transform the demangle tree starting a \p node by /// doing a post-order traversal and replacing each node with @@ -416,6 +424,7 @@ class TypeSystemSwiftTypeRef : public TypeSystemSwift { llvm::StringRef mangled_name); /// Return the base name of the topmost nominal type. static llvm::StringRef GetBaseName(swift::Demangle::NodePointer node); + static std::string GetBaseName(lldb::opaque_compiler_type_t type); /// Given a mangled name that mangles a "type metadata for Type", return a /// CompilerType with that Type. @@ -457,7 +466,7 @@ class TypeSystemSwiftTypeRef : public TypeSystemSwift { /// Returns the mangling flavor associated with the ASTContext corresponding /// with this TypeSystem. swift::Mangle::ManglingFlavor - GetManglingFlavor(ExecutionContext *exe_ctx = nullptr); + GetManglingFlavor(const ExecutionContext *exe_ctx = nullptr); protected: /// Determine whether the fallback is enabled via setting. diff --git a/lldb/test/API/lang/swift/embedded/frame_variable/TestSwiftEmbeddedFrameVariable.py b/lldb/test/API/lang/swift/embedded/frame_variable/TestSwiftEmbeddedFrameVariable.py index f241831d999e1..5eb1e3f8443b9 100644 --- a/lldb/test/API/lang/swift/embedded/frame_variable/TestSwiftEmbeddedFrameVariable.py +++ b/lldb/test/API/lang/swift/embedded/frame_variable/TestSwiftEmbeddedFrameVariable.py @@ -5,6 +5,7 @@ @skipIf(bugnumber = "rdar://159531308") class TestSwiftEmbeddedFrameVariable(TestBase): + @skipUnlessDarwin @swiftTest def test(self): @@ -21,17 +22,54 @@ def test_without_ast(self): def implementation(self, ast): self.runCmd("setting set symbols.swift-enable-full-dwarf-debugging true") - # FIXME: "$s1a1BVD" cannot be found. - self.runCmd("settings set symbols.swift-typesystem-compiler-fallback true") - self.runCmd("settings set symbols.swift-validate-typesystem false") target, process, thread, _ = lldbutil.run_to_source_breakpoint( self, "break here", lldb.SBFileSpec("main.swift") ) frame = thread.frames[0] self.assertTrue(frame, "Frame 0 is valid.") + if self.TraceOn(): + self.expect("log enable lldb types") self.expect("frame variable") + + alias1 = frame.FindVariable("alias1") + field = alias1.GetChildMemberWithName("t") + lldbutil.check_variable(self, field, False, value='1') + + alias2 = frame.FindVariable("alias2") + a3 = alias2.GetChildMemberWithName("a3") + lldbutil.check_variable(self, a3.GetChildAtIndex(0), False, value='3') + a4 = alias2.GetChildMemberWithName("a4") + lldbutil.check_variable(self, a4.GetChildAtIndex(0), False, value='4') + a5 = alias2.GetChildMemberWithName("a5") + a5t = a5.GetChildAtIndex(0) + lldbutil.check_variable(self, a5t.GetChildAtIndex(0), False, value='5') + lldbutil.check_variable(self, a5t.GetChildAtIndex(1), False, value='6') + + alias3 = frame.FindVariable("alias3") + r = alias3.GetChildMemberWithName("r") + a3 = r.GetChildMemberWithName("a3") + lldbutil.check_variable(self, a3.GetChildAtIndex(0), False, value='3') + a4 = r.GetChildMemberWithName("a4") + lldbutil.check_variable(self, a4.GetChildAtIndex(0), False, value='4') + a5 = r.GetChildMemberWithName("a5") + a5t = a5.GetChildAtIndex(0) + lldbutil.check_variable(self, a5t.GetChildAtIndex(0), False, value='5') + lldbutil.check_variable(self, a5t.GetChildAtIndex(1), False, value='6') + q1 = alias3.GetChildMemberWithName("q1") + lldbutil.check_variable(self, q1.GetChildAtIndex(0), False, value='11') + q2 = alias3.GetChildMemberWithName("q2") + q2t = q2.GetChildAtIndex(0) + lldbutil.check_variable(self, q2t.GetChildAtIndex(0), False, value='12') + lldbutil.check_variable(self, q2t.GetChildAtIndex(1), False, value='13') + + + array = frame.FindVariable("array") + lldbutil.check_variable(self, array, False, num_children=4) + for i in range(4): + lldbutil.check_variable(self, array.GetChildAtIndex(i), + False, value=str(i+1)) varB = frame.FindVariable("varB") field = varB.GetChildMemberWithName("a").GetChildMemberWithName("field") @@ -59,55 +97,53 @@ def implementation(self, ast): singlePayload = frame.FindVariable("singlePayload") payload = singlePayload.GetChildMemberWithName("payload") field = payload.GetChildMemberWithName("a").GetChildMemberWithName("field") - # FIXME: - if str(payload.GetError()) != 'error: Cannot compute size of type $s1a1BVD using static debug info.': - lldbutil.check_variable(self, field, False, value="4.5") - b = payload.GetChildMemberWithName("b") - lldbutil.check_variable(self, b, False, value="123456") - - emptySinglePayload = frame.FindVariable("emptySinglePayload") - lldbutil.check_variable(self, emptySinglePayload, False, value="nonPayloadTwo") - - smallMultipayloadEnum1 = frame.FindVariable("smallMultipayloadEnum1") - one = smallMultipayloadEnum1.GetChildMemberWithName("one") - if not ast: # FIXME! - lldbutil.check_variable(self, one, False, value="two") - - smallMultipayloadEnum2 = frame.FindVariable("smallMultipayloadEnum2") - two = smallMultipayloadEnum2.GetChildMemberWithName("two") - if not ast: # FIXME! - lldbutil.check_variable(self, two, False, value="one") - - bigMultipayloadEnum1 = frame.FindVariable("bigMultipayloadEnum1") - one = bigMultipayloadEnum1.GetChildMemberWithName("one") - first = one.GetChildAtIndex(0).GetChildMemberWithName("supField") - second = one.GetChildAtIndex(1).GetChildMemberWithName("supField") - third = one.GetChildAtIndex(2).GetChildMemberWithName("supField") - lldbutil.check_variable(self, first, False, value="42") - lldbutil.check_variable(self, second, False, value="43") - lldbutil.check_variable(self, third, False, value="44") - - fullMultipayloadEnum1 = frame.FindVariable("fullMultipayloadEnum1") - one = fullMultipayloadEnum1.GetChildMemberWithName("one") - lldbutil.check_variable(self, one, False, value="120") - - fullMultipayloadEnum2 = frame.FindVariable("fullMultipayloadEnum2") - two = fullMultipayloadEnum2.GetChildMemberWithName("two") - lldbutil.check_variable(self, two, False, value="9.5") - - bigFullMultipayloadEnum1 = frame.FindVariable("bigFullMultipayloadEnum1") - one = bigFullMultipayloadEnum1.GetChildMemberWithName("one") - first = one.GetChildAtIndex(0) - second = one.GetChildAtIndex(1) - lldbutil.check_variable(self, first, False, value="209") - lldbutil.check_variable(self, second, False, value="315") - - bigFullMultipayloadEnum2 = frame.FindVariable("bigFullMultipayloadEnum2") - two = bigFullMultipayloadEnum2.GetChildMemberWithName("two") - first = two.GetChildAtIndex(0) - second = two.GetChildAtIndex(1) - lldbutil.check_variable(self, first, False, value="452.5") - lldbutil.check_variable(self, second, False, value="753.5") + lldbutil.check_variable(self, field, False, value="4.5") + b = payload.GetChildMemberWithName("b") + lldbutil.check_variable(self, b, False, value="123456") + + emptySinglePayload = frame.FindVariable("emptySinglePayload") + lldbutil.check_variable(self, emptySinglePayload, False, value="nonPayloadTwo") + + smallMultipayloadEnum1 = frame.FindVariable("smallMultipayloadEnum1") + one = smallMultipayloadEnum1.GetChildMemberWithName("one") + lldbutil.check_variable(self, one, False, value="two") + + smallMultipayloadEnum2 = frame.FindVariable("smallMultipayloadEnum2") + two = smallMultipayloadEnum2.GetChildMemberWithName("two") + lldbutil.check_variable(self, two, False, value="one") + + bigMultipayloadEnum1 = frame.FindVariable("bigMultipayloadEnum1") + one = bigMultipayloadEnum1.GetChildMemberWithName("one") + first = one.GetChildAtIndex(0).GetChildMemberWithName("supField") + second = one.GetChildAtIndex(1).GetChildMemberWithName("supField") + third = one.GetChildAtIndex(2).GetChildMemberWithName("supField") + + if False: # FIXME! + lldbutil.check_variable(self, first, False, value="42") + lldbutil.check_variable(self, second, False, value="43") + lldbutil.check_variable(self, third, False, value="44") + + fullMultipayloadEnum1 = frame.FindVariable("fullMultipayloadEnum1") + one = fullMultipayloadEnum1.GetChildMemberWithName("one") + lldbutil.check_variable(self, one, False, value="120") + + fullMultipayloadEnum2 = frame.FindVariable("fullMultipayloadEnum2") + two = fullMultipayloadEnum2.GetChildMemberWithName("two") + lldbutil.check_variable(self, two, False, value="9.5") + + bigFullMultipayloadEnum1 = frame.FindVariable("bigFullMultipayloadEnum1") + one = bigFullMultipayloadEnum1.GetChildMemberWithName("one") + first = one.GetChildAtIndex(0) + second = one.GetChildAtIndex(1) + lldbutil.check_variable(self, first, False, value="209") + lldbutil.check_variable(self, second, False, value="315") + + bigFullMultipayloadEnum2 = frame.FindVariable("bigFullMultipayloadEnum2") + two = bigFullMultipayloadEnum2.GetChildMemberWithName("two") + first = two.GetChildAtIndex(0) + second = two.GetChildAtIndex(1) + lldbutil.check_variable(self, first, False, value="452.5") + lldbutil.check_variable(self, second, False, value="753.5") sup = frame.FindVariable("sup") supField = sup.GetChildMemberWithName("supField") @@ -160,13 +196,11 @@ def implementation(self, ast): one = t.GetChildMemberWithName("one") first = one.GetChildAtIndex(0) second = one.GetChildAtIndex(1) - if str(one.GetError()) != 'error: Cannot compute size of type $sSi_SitD using static debug info.': - lldbutil.check_variable(self, first, False, value="209") - lldbutil.check_variable(self, second, False, value="315") - u = gsp3.GetChildMemberWithName("u") - two = u.GetChildMemberWithName("two") - if not ast: # FIXME! - lldbutil.check_variable(self, two, False, value="one") + lldbutil.check_variable(self, first, False, value="209") + lldbutil.check_variable(self, second, False, value="315") + u = gsp3.GetChildMemberWithName("u") + two = u.GetChildMemberWithName("two") + lldbutil.check_variable(self, two, False, value="one") gcp = frame.FindVariable("gcp") t = gcp.GetChildMemberWithName("t") @@ -176,21 +210,19 @@ def implementation(self, ast): either = frame.FindVariable("either") left = either.GetChildMemberWithName("left") - if str(left.GetError()) != 'error: Cannot compute size of type $sSiD using static debug info.': - lldbutil.check_variable(self, left, False, value="1234") - - either2 = frame.FindVariable("either2") - right = either2.GetChildMemberWithName("right") - t = right.GetChildMemberWithName("t") - one = t.GetChildMemberWithName("one") - first = one.GetChildAtIndex(0) - second = one.GetChildAtIndex(1) - if not ast: # FIXME! - lldbutil.check_variable(self, first, False, value="209") - lldbutil.check_variable(self, second, False, value="315") - u = right.GetChildMemberWithName("u") - two = u.GetChildMemberWithName("two") - lldbutil.check_variable(self, two, False, value='one') + lldbutil.check_variable(self, left, False, value="1234") + + either2 = frame.FindVariable("either2") + right = either2.GetChildMemberWithName("right") + t = right.GetChildMemberWithName("t") + one = t.GetChildMemberWithName("one") + first = one.GetChildAtIndex(0) + second = one.GetChildAtIndex(1) + lldbutil.check_variable(self, first, False, value="209") + lldbutil.check_variable(self, second, False, value="315") + u = right.GetChildMemberWithName("u") + two = u.GetChildMemberWithName("two") + lldbutil.check_variable(self, two, False, value='one') inner = frame.FindVariable("inner") value = inner.GetChildMemberWithName("value") @@ -222,8 +254,11 @@ def implementation(self, ast): innerFuncField = innerFunctionType.GetChildMemberWithName("innerFuncField") lldbutil.check_variable(self, innerFuncField, False, value='8479') - array = frame.FindVariable("array") - lldbutil.check_variable(self, array, False, num_children=4) + inlineArray = frame.FindVariable("inlineArray") + lldbutil.check_variable(self, inlineArray, False, num_children=4) for i in range(4): - lldbutil.check_variable(self, array.GetChildAtIndex(i), + lldbutil.check_variable(self, inlineArray.GetChildAtIndex(i), False, value=str(i+1)) + + string = frame.FindVariable("string") + lldbutil.check_variable(self, string, False, summary='"Hello"') diff --git a/lldb/test/API/lang/swift/embedded/frame_variable/main.swift b/lldb/test/API/lang/swift/embedded/frame_variable/main.swift index c2fd8cda7bcb9..033ac534973f4 100644 --- a/lldb/test/API/lang/swift/embedded/frame_variable/main.swift +++ b/lldb/test/API/lang/swift/embedded/frame_variable/main.swift @@ -109,6 +109,29 @@ struct OuterGeneric { } } +struct TypeAliases { + struct Q { let t: T } + + struct S { + typealias A1 = Q + typealias A2 = Q + struct R { + typealias A3 = Q // Q + typealias A4 = Q // Q + typealias A5 = Q // Q + typealias A6 = Q<(R, V, T)> + let a3 : A3 + let a4 : A4 + let a5 : A5 + let a6 : A6 + } + let r : R + let q1 : A2 + let q2 : A2<(T, T)> + } + typealias A7 = Q +} + func g() { struct FunctionType { let funcField = 67 @@ -120,6 +143,18 @@ func g() { let varB = B() let tuple = (A(), B()) + let alias1 = TypeAliases.A7(t: 1) + let alias2 = TypeAliases.S.R( + a3: TypeAliases.Q(t: 3), + a4: TypeAliases.Q(t: 4), + a5: TypeAliases.Q(t: (5, 6)), + a6: TypeAliases.Q(t: (7, (8, 9), 10)) + ) + let alias3 = TypeAliases.S(r: alias2, + q1: TypeAliases.Q(t: 11), + q2: TypeAliases.Q(t: (12, 13)) + ) + let array : [Int] = [1, 2, 3, 4] let trivial = TrivialEnum.theCase let nonPayload1 = NonPayloadEnum.one let nonPayload2 = NonPayloadEnum.two @@ -158,13 +193,11 @@ func g() { let genericInner = OuterGeneric.GenericInner(t: 647, u: 674.5) let functionType = FunctionType() let innerFunctionType = InnerFunctionType() + var inlineArray: InlineArray<4, Int> = [1, 2, 3, 4] - var array: InlineArray<4, Int> = [1, 2, 3, 4] - - // Dummy statement to set breakpoint print can't be used in embedded Swift for now. - let dummy = A() // break here + let dummy = A() let string = StaticString("Hello") - print(string) + print(string) // break here } f() } From 3e9f0f9173b0b350e29e1471b623ff974f2fcee8 Mon Sep 17 00:00:00 2001 From: Augusto Noronha Date: Thu, 2 Oct 2025 13:58:35 -0700 Subject: [PATCH 2/5] [lldb] Remove unconditional include of Swift header on generic code DWARFDIE can be compiled without Swift support. (cherry picked from commit fdca57a0976429d19b4f2da0ddfbe1f692a82ff7) --- lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp index f0ab7e1625e43..2b1b2b639773a 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp @@ -13,8 +13,9 @@ #include "DWARFDebugInfoEntry.h" #include "DWARFDeclContext.h" #include "DWARFUnit.h" -#include "LogChannelDWARF.h" +#ifdef LLDB_ENABLE_SWIFT #include "Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.h" +#endif #include "lldb/Symbol/Type.h" #include "llvm/ADT/iterator.h" @@ -441,8 +442,7 @@ static void GetDeclContextImpl(DWARFDIE die, bool derive_template_names, // Add this DIE's contribution at the end of the chain. auto push_ctx = [&](CompilerContextKind kind, llvm::StringRef name) { - // BEGIN SWIFT - // +#ifdef LLDB_ENABLE_SWIFT // FIXME: This layering violation works around a limitation in // LLVM that prevents swiftc from emitting both DW_AT_name and // DW_AT_linkage_name on forward declarations and typedefs. @@ -457,7 +457,7 @@ static void GetDeclContextImpl(DWARFDIE die, bool derive_template_names, if (!base_name.empty()) name = base_name; } - // END SWIFT +#endif context.push_back({kind, ConstString(name)}); }; switch (die.Tag()) { From e48cfe4fa5caef7d386684006e034373101d39cd Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Mon, 29 Sep 2025 17:01:01 -0700 Subject: [PATCH 3/5] Restrict DWARF alias type resolution to embedded Swift (cherry picked from commit 9fd171930df5a148e35bedf7bfb2e786b6448fcb) --- lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp b/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp index 19f65fafe8ec4..5b6b5c738a1b9 100644 --- a/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp +++ b/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp @@ -1076,7 +1076,7 @@ TypeSystemSwiftTypeRef::ResolveTypeAlias(swift::Demangle::Demangler &dem, type = results.GetFirstType(); // Find the type by declcontext (-gdwarf-types). - if (!type) { + if (!type && flavor == swift::Mangle::ManglingFlavor::Embedded) { auto resolved = DWARFASTParserSwift::ResolveTypeAlias( GetTypeFromMangledTypename(mangled)); if (resolved.second) { From 5d31bb6c082f22f530fbf5004c2d191836ee2aa3 Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Mon, 6 Oct 2025 15:09:35 -0700 Subject: [PATCH 4/5] [LLDB] Remove Swift customizations from DWARFDIE --- .../DWARFASTParserSwiftDescriptorFinder.cpp | 2 +- .../Plugins/SymbolFile/DWARF/DWARFDIE.cpp | 23 +------------------ .../Swift/TypeSystemSwiftTypeRef.cpp | 11 ++++++++- 3 files changed, 12 insertions(+), 24 deletions(-) diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserSwiftDescriptorFinder.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserSwiftDescriptorFinder.cpp index 9c2b089e852b0..d6e69d0f56149 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserSwiftDescriptorFinder.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserSwiftDescriptorFinder.cpp @@ -98,7 +98,7 @@ DWARFASTParserSwift::ResolveTypeAlias(lldb_private::CompilerType alias) { std::string alias_name = ts.GetBaseName(alias.GetOpaqueQualType()); for (DWARFDIE child_die : parent_die.children()) { auto tag = child_die.Tag(); - if (tag == DW_TAG_member) + if (tag == llvm::dwarf::DW_TAG_member) continue; std::string base_name; const auto *name = diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp index 2b1b2b639773a..37a7c5ab694a5 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp @@ -13,9 +13,7 @@ #include "DWARFDebugInfoEntry.h" #include "DWARFDeclContext.h" #include "DWARFUnit.h" -#ifdef LLDB_ENABLE_SWIFT -#include "Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.h" -#endif +#include "LogChannelDWARF.h" #include "lldb/Symbol/Type.h" #include "llvm/ADT/iterator.h" @@ -441,25 +439,6 @@ static void GetDeclContextImpl(DWARFDIE die, bool derive_template_names, } // Add this DIE's contribution at the end of the chain. - auto push_ctx = [&](CompilerContextKind kind, llvm::StringRef name) { -#ifdef LLDB_ENABLE_SWIFT - // FIXME: This layering violation works around a limitation in - // LLVM that prevents swiftc from emitting both DW_AT_name and - // DW_AT_linkage_name on forward declarations and typedefs. - // - // We should not upstream this but instead fix the Swift compiler. - std::string base_name; - if (!name.empty() && name[0] == '$') { - // We should also check the unit's DW_LANG here. - const char *mangled = ConstString(name).AsCString(); - base_name = TypeSystemSwiftTypeRef::GetBaseName( - (lldb::opaque_compiler_type_t)mangled); - if (!base_name.empty()) - name = base_name; - } -#endif - context.push_back({kind, ConstString(name)}); - }; switch (die.Tag()) { case DW_TAG_module: case DW_TAG_namespace: diff --git a/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp b/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp index 5b6b5c738a1b9..2b66ef417742d 100644 --- a/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp +++ b/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp @@ -1040,6 +1040,16 @@ TypeSystemSwiftTypeRef::ResolveTypeAlias(swift::Demangle::Demangler &dem, }; TypeResults results; + + + std::vector decl_context; + BuildDeclContext(node, decl_context); + if (decl_context.size() && + decl_context[0].kind == CompilerContextKind::Module && + decl_context[0].name.GetStringRef().starts_with("__lldb")) + decl_context.erase(decl_context.begin()); + + // TypeQuery query(decl_context, TypeQueryOptions::e_find_one); TypeQuery query(mangled.GetStringRef(), TypeQueryOptions::e_find_one); if (!prefer_clang_types) { // First check if this type has already been parsed from DWARF. @@ -1059,7 +1069,6 @@ TypeSystemSwiftTypeRef::ResolveTypeAlias(swift::Demangle::Demangler &dem, "Could not resolve type alias {0}: {1}", mangled.AsCString()); } - // Do an even more expensive global search. target_sp->GetImages().FindTypes(/*search_first=*/nullptr, query, results); From 8345786d4f9b80fd55d5fafd88dfc681435731e5 Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Tue, 7 Oct 2025 09:06:54 -0700 Subject: [PATCH 5/5] [LLDB] Add support for Dictionary in embedded Swift --- .../Swift/SwiftLanguageRuntime.h | 4 + ...ftLanguageRuntimeDynamicTypeResolution.cpp | 108 +++++++++------- .../DWARFASTParserSwiftDescriptorFinder.cpp | 6 + .../Swift/TypeSystemSwiftTypeRef.cpp | 122 +++++++++++++++++- .../TypeSystem/Swift/TypeSystemSwiftTypeRef.h | 6 + .../TestSwiftEmbeddedFrameVariable.py | 6 +- .../swift/embedded/frame_variable/main.swift | 1 + 7 files changed, 203 insertions(+), 50 deletions(-) diff --git a/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.h b/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.h index b9c0a570d1e96..86f2c9d937b50 100644 --- a/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.h +++ b/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.h @@ -582,6 +582,10 @@ class SwiftLanguageRuntime : public LanguageRuntime { llvm::Expected GetTypeRef(CompilerType type, TypeSystemSwiftTypeRef *module_holder); + /// Returns a non-null type system or an error. + static llvm::Expected + GetReflectionTypeSystem(CompilerType for_type, ExecutionContext exe_ctx); + /// Ask Remote Mirrors for the type info about a Swift type. /// This will return a nullptr if the lookup fails. llvm::Expected diff --git a/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp b/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp index 3470975d4033f..98c4a34a821e8 100644 --- a/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp +++ b/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp @@ -32,6 +32,7 @@ #include "lldb/ValueObject/ValueObjectCast.h" #include "lldb/ValueObject/ValueObjectMemory.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/Support/Casting.h" #include "swift/AST/ASTContext.h" #include "swift/AST/ASTMangler.h" @@ -791,11 +792,11 @@ SwiftRuntimeTypeVisitor::VisitImpl(std::optional visit_only, const unsigned success = 0; bool count_only = !visit_callback; - auto ts_sp = - m_type.GetTypeSystem().dyn_cast_or_null(); - if (!ts_sp) - return llvm::createStringError("no type system"); - auto &ts = *ts_sp; + auto ts_or_err = + SwiftLanguageRuntime::GetReflectionTypeSystem(m_type, m_exe_ctx); + if (!ts_or_err) + return ts_or_err.takeError(); + auto &ts = *ts_or_err->get(); // Deal with the LLDB-only SILPackType variant. if (auto pack_type_info = ts.IsSILPackType(m_type)) { @@ -3383,6 +3384,42 @@ SwiftLanguageRuntime::GetTypeRef(CompilerType type, return type_ref_or_err; } +llvm::Expected +SwiftLanguageRuntime::GetReflectionTypeSystem(CompilerType for_type, + ExecutionContext exe_ctx) { + auto ts_sp = for_type.GetTypeSystem().dyn_cast_or_null(); + if (!ts_sp) + return llvm::createStringError("not a Swift type"); + + // The TypeSystemSwiftTypeRefForExpressions doesn't have a SymbolFile, + // so any DWARF lookups for Embedded Swift fail. + // + // FIXME: It's unclear whether this is safe to do in a non-LTO Swift program. + if (auto *tr_ts = + llvm::dyn_cast_or_null( + ts_sp.get())) { + if (tr_ts->GetManglingFlavor(&exe_ctx) == + swift::Mangle::ManglingFlavor::Embedded) { + if (auto *frame = exe_ctx.GetFramePtr()) { + auto &sc = frame->GetSymbolContext(eSymbolContextModule); + if (sc.module_sp) { + auto ts_or_err = + sc.module_sp->GetTypeSystemForLanguage(eLanguageTypeSwift); + if (!ts_or_err) + return ts_or_err.takeError(); + if (auto *tr_ts = + llvm::dyn_cast_or_null(ts_or_err->get())) + ts_sp = tr_ts->GetTypeSystemSwiftTypeRef(); + } + } + } + } + auto tr_ts = ts_sp->GetTypeSystemSwiftTypeRef(); + if (!tr_ts) + return llvm::createStringError("no Swift typesystem"); + return tr_ts; +} + llvm::Expected SwiftLanguageRuntime::GetSwiftRuntimeTypeInfo( CompilerType type, ExecutionContextScope *exe_scope, @@ -3393,14 +3430,17 @@ SwiftLanguageRuntime::GetSwiftRuntimeTypeInfo( "[SwiftLanguageRuntime::GetSwiftRuntimeTypeInfo] Getting " "type info for type: {0}", type.GetMangledTypeName()); - - auto ts_sp = type.GetTypeSystem().dyn_cast_or_null(); - if (!ts_sp) - return llvm::createStringError("not a Swift type"); - auto tr_ts = ts_sp->GetTypeSystemSwiftTypeRef(); - if (!tr_ts) - return llvm::createStringError("no Swift typesystem"); - auto &ts = *tr_ts; + StackFrame *frame = nullptr; + ExecutionContext exe_ctx; + if (exe_scope) { + frame = exe_scope->CalculateStackFrame().get(); + if (frame) + frame->CalculateExecutionContext(exe_ctx); + } + auto ts_or_err = GetReflectionTypeSystem(type, exe_ctx); + if (!ts_or_err) + return ts_or_err.takeError(); + auto &ts = *ts_or_err->get(); // Resolve all type aliases. type = type.GetCanonicalType(); @@ -3414,15 +3454,13 @@ SwiftLanguageRuntime::GetSwiftRuntimeTypeInfo( // Resolve all generic type parameters in the type for the current // frame. Generic parameter binding has to happen in the scratch // context. - ExecutionContext exe_ctx; - if (exe_scope) - if (StackFrame *frame = exe_scope->CalculateStackFrame().get()) { - frame->CalculateExecutionContext(exe_ctx); - auto bound_type_or_err = BindGenericTypeParameters(*frame, type); - if (!bound_type_or_err) - return bound_type_or_err.takeError(); - type = *bound_type_or_err; - } + if (frame) { + frame->CalculateExecutionContext(exe_ctx); + auto bound_type_or_err = BindGenericTypeParameters(*frame, type); + if (!bound_type_or_err) + return bound_type_or_err.takeError(); + type = *bound_type_or_err; + } // BindGenericTypeParameters imports the type into the scratch // context, but we need to resolve (any DWARF links in) the typeref @@ -3438,33 +3476,9 @@ SwiftLanguageRuntime::GetSwiftRuntimeTypeInfo( if (!reflection_ctx) return llvm::createStringError("no reflection context"); - // The TypeSystemSwiftTypeRefForExpressions doesn't ve a SymbolFile, - // so any DWARF lookups for Embedded Swift fail. - // - // FIXME: It's unclear whether this is safe to do in a non-LTO Swift program. - if (llvm::isa(tr_ts.get()) && - tr_ts->GetManglingFlavor(&exe_ctx) == - swift::Mangle::ManglingFlavor::Embedded) { - if (auto frame_sp = exe_ctx.GetFrameSP()) { - auto &sc = frame_sp->GetSymbolContext(eSymbolContextModule); - if (sc.module_sp) { - auto ts_or_err = - sc.module_sp->GetTypeSystemForLanguage(eLanguageTypeSwift); - if (!ts_or_err) - return ts_or_err.takeError(); - if (auto *tr_ts = llvm::dyn_cast_or_null( - ts_or_err->get())) { - LLDBTypeInfoProvider provider(*this, *tr_ts); - return reflection_ctx->GetTypeInfo(*type_ref_or_err, &provider, - tr_ts->GetDescriptorFinder()); - } - } - } - } - LLDBTypeInfoProvider provider(*this, ts); return reflection_ctx->GetTypeInfo(*type_ref_or_err, &provider, - tr_ts->GetDescriptorFinder()); + ts.GetDescriptorFinder()); } bool SwiftLanguageRuntime::IsStoredInlineInBuffer(CompilerType type) { diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserSwiftDescriptorFinder.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserSwiftDescriptorFinder.cpp index d6e69d0f56149..6a2f3328da097 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserSwiftDescriptorFinder.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserSwiftDescriptorFinder.cpp @@ -160,6 +160,12 @@ getTypeAndDie(TypeSystemSwiftTypeRef &ts, if (!dwarf) return {}; TypeSP lldb_type = ts.FindTypeInModule(type.GetOpaqueQualType()); + if (!lldb_type) { + if (ts.ContainsBoundGenericType(type.GetOpaqueQualType())) { + CompilerType generic_type = ts.MapOutOfContext(type.GetOpaqueQualType()); + lldb_type = ts.FindTypeInModule(generic_type.GetOpaqueQualType()); + } + } if (!lldb_type) { std::tie(lldb_type, type) = DWARFASTParserSwift::ResolveTypeAlias(type); if (lldb_type) { diff --git a/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp b/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp index 2b66ef417742d..fe1dd56d8a672 100644 --- a/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp +++ b/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp @@ -1267,6 +1267,91 @@ CompilerType TypeSystemSwiftTypeRef::ApplySubstitutions( return RemangleAsType(dem, type_node, flavor); } +CompilerType +TypeSystemSwiftTypeRef::MapOutOfContext(lldb::opaque_compiler_type_t type) { + using namespace swift::Demangle; + Demangler dem; + const char *mangled_typename = AsMangledName(type); + auto flavor = SwiftLanguageRuntime::GetManglingFlavor(mangled_typename); + NodePointer type_node = + swift_demangle::GetDemangledTypeMangling(dem, mangled_typename); + if (!type_node) + return {}; + + // First perform a pre-order traversal to record the depths of the type + // parameters. + bool error = false; + unsigned depth = 0; + using ParamVector = llvm::SmallVector, 4>; + llvm::SmallDenseMap subs; + PreOrderTraversal(type_node, [&](NodePointer node) { + switch (node->getKind()) { + case Node::Kind::BoundGenericClass: + case Node::Kind::BoundGenericEnum: + case Node::Kind::BoundGenericFunction: + case Node::Kind::BoundGenericProtocol: + case Node::Kind::BoundGenericOtherNominalType: + case Node::Kind::BoundGenericStructure: + case Node::Kind::BoundGenericTypeAlias: { + if (node->getNumChildren() != 2) { + error = true; + return false; + } + NodePointer type_list = + swift_demangle::NodeAtPath(node->getChild(1), {Node::Kind::TypeList}); + if (!type_list) { + error = true; + return false; + } + unsigned i = 0; + auto it = subs.insert({node, {}}); + if (!it.second) { + error = true; + return false; + } + ParamVector &types = it.first->second; + for (NodePointer type : *type_list) + if (type && type->getKind() == Node::Kind::Type) + types.push_back({depth, i++}); + + depth += 1; + + return true; + } + default: + return true; + } + }); + if (error) + return {}; + + // Now perform a post-order traversal to substitute the nodes with the right + // depth. + type_node = Transform(dem, type_node, [&](NodePointer node) -> NodePointer { + auto it = subs.find(node); + if (it == subs.end()) + return node; + ParamVector &types = it->second; + NodePointer remapped = dem.createNode(node->getKind()); + remapped->addChild(node->getChild(0), dem); + NodePointer type_list = dem.createNode(Node::Kind::TypeList); + remapped->addChild(type_list, dem); + for (auto &type : types) { + NodePointer dgpt = dem.createNode(Node::Kind::DependentGenericParamType); + dgpt->addChild(dem.createNode(Node::Kind::Index, type.first), dem); + dgpt->addChild(dem.createNode(Node::Kind::Index, type.second), dem); + type_list->addChild(dgpt, dem); + } + for (auto &constraint : *node->getChild(1)) + if (constraint->getKind() != Node::Kind::Type) + type_list->addChild(constraint, dem); + + return remapped; + }); + + return RemangleAsType(dem, type_node, flavor); +} + bool TypeSystemSwiftTypeRef::IsBoundGenericAliasType( lldb::opaque_compiler_type_t type) { using namespace swift::Demangle; @@ -1283,6 +1368,39 @@ bool TypeSystemSwiftTypeRef::IsBoundGenericAliasType( return node->getKind() == Node::Kind::BoundGenericTypeAlias; } +static bool ContainsBoundGenericTypeNode(swift::Demangle::NodePointer node) { + if (!node) + return false; + switch (node->getKind()) { + case Node::Kind::BoundGenericClass: + case Node::Kind::BoundGenericEnum: + case Node::Kind::BoundGenericFunction: + case Node::Kind::BoundGenericProtocol: + case Node::Kind::BoundGenericOtherNominalType: + case Node::Kind::BoundGenericTypeAlias: + case Node::Kind::BoundGenericStructure: + return true; + default: + if (NodePointer parent = GetParentNode(node)) + return ContainsBoundGenericTypeNode(parent); + return false; + } +} + +bool TypeSystemSwiftTypeRef::ContainsBoundGenericType( + lldb::opaque_compiler_type_t type) { + using namespace swift::Demangle; + Demangler dem; + const char *mangled_typename = AsMangledName(type); + + NodePointer node = + swift_demangle::GetDemangledTypeMangling(dem, mangled_typename); + if (!node || node->getKind() != Node::Kind::Type || !node->hasChildren()) + return false; + node = node->getChild(0); + return ContainsBoundGenericTypeNode(node); +} + std::optional TypeSystemSwiftTypeRef::GetTupleElement(lldb::opaque_compiler_type_t type, size_t idx) { @@ -2632,7 +2750,9 @@ TypeSystemSwiftTypeRef::FindTypeInModule(opaque_compiler_type_t opaque_type) { TypeResults results; M->FindTypes(query, results); - return results.GetFirstType(); + if (results.Done(query)) + return results.GetFirstType(); + return {}; } // Tests diff --git a/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.h b/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.h index 091e50dcd8f1c..180af21eab6d7 100644 --- a/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.h +++ b/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.h @@ -140,9 +140,13 @@ class TypeSystemSwiftTypeRef : public TypeSystemSwift { CompilerType GetParentType(lldb::opaque_compiler_type_t type); std::vector> + /// Extract the substitutions from a bound generic type. GetSubstitutions(lldb::opaque_compiler_type_t type); + /// Apply substitutions to a bound generic type that is mapped out of context. CompilerType ApplySubstitutions(lldb::opaque_compiler_type_t type, std::vector> subs); + /// Apply substitutions to a bound generic type that is mapped out of context. + CompilerType MapOutOfContext(lldb::opaque_compiler_type_t type); Module *GetModule() const { return m_module; } @@ -366,6 +370,7 @@ class TypeSystemSwiftTypeRef : public TypeSystemSwift { /// Determine whether \p type is a protocol. bool IsExistentialType(lldb::opaque_compiler_type_t type); bool IsBoundGenericAliasType(lldb::opaque_compiler_type_t type); + bool ContainsBoundGenericType(lldb::opaque_compiler_type_t type); /// Recursively transform the demangle tree starting a \p node by /// doing a post-order traversal and replacing each node with @@ -389,6 +394,7 @@ class TypeSystemSwiftTypeRef : public TypeSystemSwift { /// A left-to-right preorder traversal. Don't visit children if /// visitor returns false. + /// The NodePointer passed to \p fn is guaranteed to be non-null. static void PreOrderTraversal(swift::Demangle::NodePointer node, std::function); diff --git a/lldb/test/API/lang/swift/embedded/frame_variable/TestSwiftEmbeddedFrameVariable.py b/lldb/test/API/lang/swift/embedded/frame_variable/TestSwiftEmbeddedFrameVariable.py index 5eb1e3f8443b9..9c738f85a3a31 100644 --- a/lldb/test/API/lang/swift/embedded/frame_variable/TestSwiftEmbeddedFrameVariable.py +++ b/lldb/test/API/lang/swift/embedded/frame_variable/TestSwiftEmbeddedFrameVariable.py @@ -3,7 +3,6 @@ from lldbsuite.test.decorators import * import lldbsuite.test.lldbutil as lldbutil -@skipIf(bugnumber = "rdar://159531308") class TestSwiftEmbeddedFrameVariable(TestBase): @skipUnlessDarwin @@ -32,7 +31,7 @@ def implementation(self, ast): if self.TraceOn(): self.expect("log enable lldb types") self.expect("frame variable") - + alias1 = frame.FindVariable("alias1") field = alias1.GetChildMemberWithName("t") lldbutil.check_variable(self, field, False, value='1') @@ -262,3 +261,6 @@ def implementation(self, ast): string = frame.FindVariable("string") lldbutil.check_variable(self, string, False, summary='"Hello"') + + dictionary = frame.FindVariable("dict") + lldbutil.check_variable(self, dictionary, False, summary='4 key/value pairs') diff --git a/lldb/test/API/lang/swift/embedded/frame_variable/main.swift b/lldb/test/API/lang/swift/embedded/frame_variable/main.swift index 033ac534973f4..c65c214ee3e9c 100644 --- a/lldb/test/API/lang/swift/embedded/frame_variable/main.swift +++ b/lldb/test/API/lang/swift/embedded/frame_variable/main.swift @@ -194,6 +194,7 @@ func g() { let functionType = FunctionType() let innerFunctionType = InnerFunctionType() var inlineArray: InlineArray<4, Int> = [1, 2, 3, 4] + var dict: Dictionary = [1:4, 2:3, 3:2, 4:1] let dummy = A() let string = StaticString("Hello")