Skip to content

[lldb] Recursively resolve type aliases when canonicalizing types #9913

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 29, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 20 additions & 15 deletions lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<swift::Demangle::NodePointer, CompilerType>
TypeSystemSwiftTypeRef::ResolveTypeAlias(swift::Demangle::Demangler &dem,
swift::Demangle::NodePointer node,
Expand Down Expand Up @@ -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;
Expand All @@ -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:
Expand Down
20 changes: 17 additions & 3 deletions lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.h
Original file line number Diff line number Diff line change
Expand Up @@ -502,9 +502,23 @@ class TypeSystemSwiftTypeRef : public TypeSystemSwift {
CompilerType LookupClangForwardType(llvm::StringRef name,
llvm::ArrayRef<CompilerContext> decl_context);

std::pair<swift::Demangle::NodePointer, CompilerType> 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<swift::Demangle::NodePointer, CompilerType>
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,
Expand Down
3 changes: 3 additions & 0 deletions lldb/test/API/lang/swift/typealias_recursive/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
SWIFT_SOURCES = main.swift

include Makefile.rules
Original file line number Diff line number Diff line change
@@ -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"])
12 changes: 12 additions & 0 deletions lldb/test/API/lang/swift/typealias_recursive/main.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
open class MyClass<A, B> {}
public typealias LocalAlias = Bool
let anchor : LocalAlias = true
public typealias ClassAlias = MyClass<LocalAlias, Bool>
class Repro {
let field: ClassAlias?
init(cls: ClassAlias?) {
self.field = cls // break here
}
}

Repro(cls: ClassAlias())