diff --git a/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp b/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp index be36f51ecf9ae..5bb372c8d7e50 100644 --- a/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp +++ b/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp @@ -943,13 +943,6 @@ IsClangImportedType(NodePointer node, } } -/// Resolve a type alias node and return a demangle tree for the -/// resolved type. If the type alias resolves to a Clang type, return -/// a Clang CompilerType. -/// -/// \param prefer_clang_types if this is true, type aliases in the -/// __C module are resolved as Clang types. -/// std::pair TypeSystemSwiftTypeRef::ResolveTypeAlias(swift::Demangle::Demangler &dem, swift::Demangle::NodePointer node, @@ -1202,7 +1195,7 @@ TypeSystemSwiftTypeRef::Canonicalize(swift::Demangle::Demangler &dem, Node::Kind::Structure, "Array"); } case Node::Kind::SugaredDictionary: - // FIXME: This isnt covered by any test. + // FIXME: This isn't covered by any test. assert(node->getNumChildren() == 2); if (node->getNumChildren() != 2) return node; @@ -1216,15 +1209,27 @@ TypeSystemSwiftTypeRef::Canonicalize(swift::Demangle::Demangler &dem, case Node::Kind::BoundGenericTypeAlias: case Node::Kind::TypeAlias: { - auto node_clangtype = ResolveTypeAlias(dem, node, flavor); - if (CompilerType clang_type = node_clangtype.second) { - if (auto result = GetClangTypeNode(clang_type, dem)) - return result; - else + // Safeguard against cyclic aliases. + for (unsigned alias_depth = 0; alias_depth < 64; ++alias_depth) { + auto node_clangtype = ResolveTypeAlias(dem, node, flavor); + if (CompilerType clang_type = node_clangtype.second) { + if (auto result = GetClangTypeNode(clang_type, dem)) + return result; + // Failed to convert that clang type into a demangle node. + return node; + } + if (!node_clangtype.first) + return node; + if (node_clangtype.first == node) return node; + node = node_clangtype.first; + if (node->getKind() != Node::Kind::BoundGenericTypeAlias && + node->getKind() != Node::Kind::TypeAlias) + // Resolve any type aliases in the resolved type. + return GetCanonicalNode(dem, node); + // This type alias resolved to another type alias. } - if (node_clangtype.first) - return node_clangtype.first; + // Hit the safeguard limit. return node; } default: diff --git a/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.h b/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.h index ce49280eedec4..20e7ffc06b05b 100644 --- a/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.h +++ b/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.h @@ -502,9 +502,23 @@ class TypeSystemSwiftTypeRef : public TypeSystemSwift { CompilerType LookupClangForwardType(llvm::StringRef name, llvm::ArrayRef decl_context); - std::pair ResolveTypeAlias( - swift::Demangle::Demangler &dem, swift::Demangle::NodePointer node, - swift::Mangle::ManglingFlavor flavor, bool prefer_clang_types = false); + /// Recursively resolves all type aliases. + swift::Demangle::NodePointer + ResolveAllTypeAliases(swift::Demangle::Demangler &dem, + swift::Demangle::NodePointer node); + + /// Resolve a type alias node and return a demangle tree for the + /// resolved type. If the type alias resolves to a Clang type, return + /// a Clang CompilerType. + /// + /// \param prefer_clang_types if this is true, type aliases in the + /// __C module are resolved as Clang types. + /// + std::pair + ResolveTypeAlias(swift::Demangle::Demangler &dem, + swift::Demangle::NodePointer node, + swift::Mangle::ManglingFlavor flavor, + bool prefer_clang_types = false); swift::Demangle::NodePointer GetCanonicalNode(swift::Demangle::Demangler &dem, diff --git a/lldb/test/API/lang/swift/typealias_recursive/Makefile b/lldb/test/API/lang/swift/typealias_recursive/Makefile new file mode 100644 index 0000000000000..1770a003e2920 --- /dev/null +++ b/lldb/test/API/lang/swift/typealias_recursive/Makefile @@ -0,0 +1,3 @@ +SWIFT_SOURCES = main.swift + +include Makefile.rules diff --git a/lldb/test/API/lang/swift/typealias_recursive/TestSwiftTypeAliasRecursive.py b/lldb/test/API/lang/swift/typealias_recursive/TestSwiftTypeAliasRecursive.py new file mode 100644 index 0000000000000..3d4975922cf8b --- /dev/null +++ b/lldb/test/API/lang/swift/typealias_recursive/TestSwiftTypeAliasRecursive.py @@ -0,0 +1,14 @@ +from lldbsuite.test.lldbtest import * +from lldbsuite.test.decorators import * +import lldbsuite.test.lldbutil as lldbutil + +class TestSwiftTypeAliasRecurtsive(TestBase): + @swiftTest + def test(self): + """Test that type aliases of type aliases can be resolved""" + self.build() + self.runCmd("settings set symbols.swift-validate-typesystem false") + self.expect("log enable lldb types") + target, process, _, _ = lldbutil.run_to_source_breakpoint( + self, "break here", lldb.SBFileSpec("main.swift")) + self.expect("frame variable cls", substrs=["ClassAlias?", "0x"]) diff --git a/lldb/test/API/lang/swift/typealias_recursive/main.swift b/lldb/test/API/lang/swift/typealias_recursive/main.swift new file mode 100644 index 0000000000000..70d3c660e9538 --- /dev/null +++ b/lldb/test/API/lang/swift/typealias_recursive/main.swift @@ -0,0 +1,12 @@ +open class MyClass {} +public typealias LocalAlias = Bool +let anchor : LocalAlias = true +public typealias ClassAlias = MyClass +class Repro { + let field: ClassAlias? + init(cls: ClassAlias?) { + self.field = cls // break here + } +} + +Repro(cls: ClassAlias())