Skip to content

Commit c97b798

Browse files
authored
Merge pull request #6420 from augusto2112/test-namespace-interop
[lldb] Build decl contexts when looking up clang types
2 parents 670b79b + 3d54620 commit c97b798

File tree

8 files changed

+222
-69
lines changed

8 files changed

+222
-69
lines changed

lldb/source/Plugins/TypeSystem/Swift/DWARFImporterDelegate.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@ class SwiftDWARFImporterDelegate : public swift::DWARFImporterDelegate {
219219

220220
// Find the type in the debug info.
221221
TypeSP clang_type_sp;
222+
// FIXME: LookupClangType won't work for nested C++ types.
222223
if (m_swift_typesystem.GetModule())
223224
clang_type_sp = m_swift_typesystem.LookupClangType(name);
224225
else if (TargetSP target_sp = m_swift_typesystem.GetTargetWP().lock()) {
@@ -242,6 +243,7 @@ class SwiftDWARFImporterDelegate : public swift::DWARFImporterDelegate {
242243
auto swift_ts = llvm::dyn_cast_or_null<TypeSystemSwift>(ts->get());
243244
if (!swift_ts)
244245
continue;
246+
// FIXME: LookupClangType won't work for nested C++ types.
245247
clang_type_sp = swift_ts->GetTypeSystemSwiftTypeRef().LookupClangType(name);
246248
if (clang_type_sp)
247249
break;

lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp

Lines changed: 109 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -196,10 +196,17 @@ GetMangledName(swift::Demangle::Demangler &dem,
196196

197197
/// Find a Clang type by name in the modules in \p module_holder.
198198
TypeSP TypeSystemSwiftTypeRef::LookupClangType(StringRef name_ref) {
199-
auto lookup = [](Module &M, ConstString name) -> TypeSP {
200-
llvm::SmallVector<CompilerContext, 2> decl_context;
201-
decl_context.push_back({CompilerContextKind::AnyModule, ConstString()});
202-
decl_context.push_back({CompilerContextKind::AnyType, ConstString(name)});
199+
llvm::SmallVector<CompilerContext, 2> decl_context;
200+
// Make up a decl context for non-nested types.
201+
decl_context.push_back({CompilerContextKind::AnyModule, ConstString()});
202+
decl_context.push_back({CompilerContextKind::AnyType, ConstString(name_ref)});
203+
return LookupClangType(name_ref, decl_context);
204+
}
205+
206+
/// Find a Clang type by name in the modules in \p module_holder.
207+
TypeSP TypeSystemSwiftTypeRef::LookupClangType(
208+
StringRef name_ref, llvm::ArrayRef<CompilerContext> decl_context) {
209+
auto lookup = [&decl_context](Module &M, ConstString name) -> TypeSP {
203210
llvm::DenseSet<SymbolFile *> searched_symbol_files;
204211
TypeMap clang_types;
205212
M.FindTypes(decl_context, TypeSystemClang::GetSupportedLanguagesForTypes(),
@@ -241,8 +248,9 @@ TypeSP TypeSystemSwiftTypeRef::LookupClangType(StringRef name_ref) {
241248
}
242249

243250
/// Find a Clang type by name in module \p M.
244-
CompilerType TypeSystemSwiftTypeRef::LookupClangForwardType(StringRef name) {
245-
if (TypeSP type = LookupClangType(name))
251+
CompilerType TypeSystemSwiftTypeRef::LookupClangForwardType(
252+
StringRef name, llvm::ArrayRef<CompilerContext> decl_context) {
253+
if (TypeSP type = LookupClangType(name, decl_context))
246254
return type->GetForwardCompilerType();
247255
return {};
248256
}
@@ -467,6 +475,38 @@ GetBuiltinAnyObjectNode(swift::Demangle::Demangler &dem) {
467475
return proto_list_any;
468476
}
469477

478+
/// Builds the decl context to look up clang types with.
479+
static bool
480+
IsClangImportedType(NodePointer node,
481+
llvm::SmallVectorImpl<CompilerContext> &decl_context) {
482+
if (node->getKind() == Node::Kind::Module && node->hasText() &&
483+
node->getText() == swift::MANGLING_MODULE_OBJC) {
484+
decl_context.push_back({CompilerContextKind::AnyModule, ConstString()});
485+
return true;
486+
}
487+
488+
if (node->getNumChildren() != 2 || !node->getLastChild()->hasText())
489+
return false;
490+
491+
switch (node->getKind()) {
492+
case Node::Kind::Structure:
493+
case Node::Kind::Class:
494+
case Node::Kind::Enum:
495+
case Node::Kind::TypeAlias:
496+
if (!IsClangImportedType(node->getFirstChild(), decl_context))
497+
return false;
498+
499+
// When C++ interop is enabled, Swift enums represent Swift namespaces.
500+
decl_context.push_back({node->getKind() == Node::Kind::Enum
501+
? CompilerContextKind::Namespace
502+
: CompilerContextKind::AnyType,
503+
ConstString(node->getLastChild()->getText())});
504+
return true;
505+
default:
506+
return false;
507+
}
508+
}
509+
470510
/// Resolve a type alias node and return a demangle tree for the
471511
/// resolved type. If the type alias resolves to a Clang type, return
472512
/// a Clang CompilerType.
@@ -479,22 +519,6 @@ TypeSystemSwiftTypeRef::ResolveTypeAlias(swift::Demangle::Demangler &dem,
479519
swift::Demangle::NodePointer node,
480520
bool prefer_clang_types) {
481521
LLDB_SCOPED_TIMER();
482-
auto resolve_clang_type = [&]() -> CompilerType {
483-
auto maybe_module_and_type_names = GetNominal(dem, node);
484-
if (!maybe_module_and_type_names)
485-
return {};
486-
487-
auto module_name = maybe_module_and_type_names->first;
488-
if (module_name != swift::MANGLING_MODULE_OBJC)
489-
return {};
490-
491-
// Resolve the typedef within the Clang debug info.
492-
auto clang_type = LookupClangForwardType(node->getChild(1)->getText());
493-
if (!clang_type)
494-
return {};
495-
496-
return clang_type.GetCanonicalType();
497-
};
498522

499523
// Hardcode that the Swift.AnyObject type alias always resolves to
500524
// the builtin AnyObject type.
@@ -513,6 +537,25 @@ TypeSystemSwiftTypeRef::ResolveTypeAlias(swift::Demangle::Demangler &dem,
513537
return {{}, {}};
514538
}
515539
ConstString mangled(mangling.result());
540+
541+
auto resolve_clang_type = [&]() -> CompilerType {
542+
auto maybe_module_and_type_names = GetNominal(dem, node);
543+
if (!maybe_module_and_type_names)
544+
return {};
545+
546+
// This is an imported Objective-C type; look it up in the debug info.
547+
llvm::SmallVector<CompilerContext, 2> decl_context;
548+
if (!IsClangImportedType(node, decl_context))
549+
return {};
550+
551+
// Resolve the typedef within the Clang debug info.
552+
auto clang_type = LookupClangForwardType(mangled.GetStringRef(), decl_context);
553+
if (!clang_type)
554+
return {};
555+
556+
return clang_type.GetCanonicalType();
557+
};
558+
516559
TypeList types;
517560
if (!prefer_clang_types) {
518561
llvm::DenseSet<SymbolFile *> searched_symbol_files;
@@ -869,31 +912,27 @@ CompilerType TypeSystemSwiftTypeRef::GetBuiltinRawPointerType() {
869912
return GetTypeFromMangledTypename(ConstString("$sBpD"));
870913
}
871914

872-
/// Determine whether \p node is an Objective-C type and return its name.
873-
static StringRef GetObjCTypeName(swift::Demangle::NodePointer node) {
874-
if (node && node->getNumChildren() == 2 && node->getChild(0)->hasText() &&
875-
node->getChild(0)->getText() == swift::MANGLING_MODULE_OBJC &&
876-
node->getChild(1)->hasText())
877-
return node->getChild(1)->getText();
878-
return {};
879-
}
880915

881916
swift::Demangle::NodePointer
882917
TypeSystemSwiftTypeRef::GetSwiftified(swift::Demangle::Demangler &dem,
883918
swift::Demangle::NodePointer node,
884919
bool resolve_objc_module) {
885920
LLDB_SCOPED_TIMER();
886921

887-
using namespace swift::Demangle;
888-
StringRef ident = GetObjCTypeName(node);
889-
if (ident.empty())
922+
auto mangling = GetMangledName(dem, node);
923+
if (!mangling.isSuccess()) {
924+
LLDB_LOGF(GetLog(LLDBLog::Types), "Failed while getting swiftified (%d:%u)",
925+
mangling.error().code, mangling.error().line);
926+
return node;
927+
}
928+
929+
llvm::SmallVector<CompilerContext, 2> decl_context;
930+
if (!IsClangImportedType(node, decl_context))
890931
return node;
891932

892-
if (ident.equals("NSURL") || ident.equals("URL"))
893-
llvm::errs();
894933
// This is an imported Objective-C type; look it up in the
895934
// debug info.
896-
TypeSP clang_type = LookupClangType(ident);
935+
TypeSP clang_type = LookupClangType(mangling.result(), decl_context);
897936
if (!clang_type)
898937
return node;
899938

@@ -1199,33 +1238,38 @@ TypeSystemSwiftTypeRef::CollectTypeInfo(swift::Demangle::Demangler &dem,
11991238
}
12001239
case Node::Kind::BoundGenericStructure:
12011240
case Node::Kind::Structure: {
1202-
swift_flags |= eTypeHasChildren | eTypeIsStructUnion;
1203-
if (node->getNumChildren() != 2)
1204-
break;
1205-
auto module = node->getChild(0);
1206-
auto ident = node->getChild(1);
1207-
// Builtin types.
1208-
if (module->hasText() && module->getText() == swift::STDLIB_NAME) {
1209-
if (ident->hasText() &&
1210-
ident->getText().startswith(swift::BUILTIN_TYPE_NAME_INT))
1211-
swift_flags |= eTypeIsScalar | eTypeIsInteger;
1212-
else if (ident->hasText() &&
1213-
ident->getText().startswith(swift::BUILTIN_TYPE_NAME_FLOAT))
1214-
swift_flags |= eTypeIsScalar | eTypeIsFloat;
1215-
}
1216-
1217-
// Clang-imported types.
1218-
if (module->hasText() &&
1219-
module->getText() == swift::MANGLING_MODULE_OBJC) {
1220-
if (ident->getKind() != Node::Kind::Identifier || !ident->hasText())
1221-
break;
1241+
swift_flags |= eTypeHasChildren | eTypeIsStructUnion;
1242+
if (node->getNumChildren() != 2)
1243+
break;
1244+
auto module = node->getChild(0);
1245+
auto ident = node->getChild(1);
1246+
// Builtin types.
1247+
if (module->hasText() && module->getText() == swift::STDLIB_NAME) {
1248+
if (ident->hasText() &&
1249+
ident->getText().startswith(swift::BUILTIN_TYPE_NAME_INT))
1250+
swift_flags |= eTypeIsScalar | eTypeIsInteger;
1251+
else if (ident->hasText() &&
1252+
ident->getText().startswith(swift::BUILTIN_TYPE_NAME_FLOAT))
1253+
swift_flags |= eTypeIsScalar | eTypeIsFloat;
1254+
}
12221255

1223-
// Look up the Clang type in DWARF.
1224-
CompilerType clang_type = LookupClangForwardType(ident->getText());
1225-
collect_clang_type(clang_type.GetCanonicalType());
1226-
return swift_flags;
1227-
}
1256+
// Clang-imported types.
1257+
llvm::SmallVector<CompilerContext, 2> decl_context;
1258+
if (!IsClangImportedType(node, decl_context))
12281259
break;
1260+
1261+
auto mangling = GetMangledName(dem, node);
1262+
if (!mangling.isSuccess()) {
1263+
LLDB_LOGF(GetLog(LLDBLog::Types),
1264+
"Failed mangling while collecting type infos (%d:%u)",
1265+
mangling.error().code, mangling.error().line);
1266+
1267+
return {};
1268+
}
1269+
// Resolve the typedef within the Clang debug info.
1270+
auto clang_type = LookupClangForwardType(mangling.result(), decl_context);
1271+
collect_clang_type(clang_type.GetCanonicalType());
1272+
return swift_flags;
12291273
}
12301274
case Node::Kind::BoundGenericClass:
12311275
case Node::Kind::Class:
@@ -3230,11 +3274,11 @@ bool TypeSystemSwiftTypeRef::IsImportedType(opaque_compiler_type_t type,
32303274
AsMangledName(type));
32313275

32323276
// This is an imported Objective-C type; look it up in the debug info.
3233-
StringRef ident = GetObjCTypeName(node);
3234-
if (ident.empty())
3235-
return {};
3277+
llvm::SmallVector<CompilerContext, 2> decl_context;
3278+
if (!IsClangImportedType(node, decl_context))
3279+
return false;
32363280
if (original_type)
3237-
if (TypeSP clang_type = LookupClangType(ident))
3281+
if (TypeSP clang_type = LookupClangType(AsMangledName(type), decl_context))
32383282
*original_type = clang_type->GetForwardCompilerType();
32393283
return true;
32403284
};

lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.h

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -339,9 +339,15 @@ class TypeSystemSwiftTypeRef : public TypeSystemSwift {
339339
CompilerType RemangleAsType(swift::Demangle::Demangler &dem,
340340
swift::Demangle::NodePointer node);
341341

342-
/// Search the debug info for a Clang type with the specified name and cache
343-
/// the result.
344-
lldb::TypeSP LookupClangType(llvm::StringRef name);
342+
/// Search the debug info for a non-nested Clang type with the specified name
343+
/// and cache the result. Users should prefer the version that takes in the
344+
/// decl_context.
345+
lldb::TypeSP LookupClangType(llvm::StringRef name_ref);
346+
347+
/// Search the debug info for a Clang type with the specified name and decl
348+
/// context, and cache the result.
349+
lldb::TypeSP LookupClangType(llvm::StringRef name_ref,
350+
llvm::ArrayRef<CompilerContext> decl_context);
345351

346352
protected:
347353
/// Helper that creates an AST type from \p type.
@@ -387,7 +393,8 @@ class TypeSystemSwiftTypeRef : public TypeSystemSwift {
387393
clang::api_notes::APINotesManager *
388394
GetAPINotesManager(ClangExternalASTSourceCallbacks *source, unsigned id);
389395

390-
CompilerType LookupClangForwardType(llvm::StringRef name);
396+
CompilerType LookupClangForwardType(llvm::StringRef name,
397+
llvm::ArrayRef<CompilerContext> decl_context);
391398

392399
std::pair<swift::Demangle::NodePointer, CompilerType>
393400
ResolveTypeAlias(swift::Demangle::Demangler &dem,
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
SWIFT_SOURCES := main.swift
2+
SWIFT_CXX_INTEROP := 1
3+
SWIFTFLAGS_EXTRAS = -Xcc -I$(SRCDIR)
4+
include Makefile.rules
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
2+
"""
3+
Test that C++ classes defined in namespaces are displayed correctly in Swift.
4+
"""
5+
from lldbsuite.test.lldbtest import *
6+
from lldbsuite.test.decorators import *
7+
8+
9+
class TestClassInNamespace(TestBase):
10+
11+
@skipIf(setting=('symbols.use-swift-clangimporter', 'false'))
12+
@swiftTest
13+
def test_class(self):
14+
self.build()
15+
self.runCmd('settings set target.experimental.swift-enable-cxx-interop true')
16+
_, _, _, _= lldbutil.run_to_source_breakpoint(
17+
self, 'Set breakpoint here', lldb.SBFileSpec('main.swift'))
18+
19+
self.expect('v fooClass', substrs=['foo::CxxClass', 'foo_field = 10'])
20+
self.expect('expr fooClass', substrs=['foo::CxxClass', 'foo_field = 10'])
21+
22+
self.expect('v barClass', substrs=['bar::CxxClass', 'bar_field = 30'])
23+
self.expect('expr barClass', substrs=['bar::CxxClass', 'bar_field = 30'])
24+
25+
26+
self.expect('v bazClass', substrs=['baz::CxxClass', 'baz_field = 50'])
27+
self.expect('expr bazClass', substrs=['baz::CxxClass', 'baz_field = 50'])
28+
29+
self.expect('v bazClass', substrs=['baz::CxxClass', 'baz_field = 50'])
30+
self.expect('expr bazClass', substrs=['baz::CxxClass', 'baz_field = 50'])
31+
32+
self.expect('v fooInherited', substrs=['foo::InheritedCxxClass',
33+
'foo::CxxClass = (foo_field = 10)', 'foo_subfield = 20'])
34+
self.expect('e fooInherited', substrs=['foo::InheritedCxxClass',
35+
'foo::CxxClass = (foo_field = 10)', 'foo_subfield = 20'])
36+
37+
self.expect('v barInherited', substrs=['bar::InheritedCxxClass',
38+
'bar::CxxClass = (bar_field = 30)', 'bar_subfield = 40'])
39+
self.expect('expr barInherited', substrs=['bar::InheritedCxxClass',
40+
'bar::CxxClass = (bar_field = 30)', 'bar_subfield = 40'])
41+
42+
43+
self.expect('v bazInherited', substrs=['bar::baz::InheritedCxxClass',
44+
'bar::baz::CxxClass = (baz_field = 50)', 'baz_subfield = 60'])
45+
self.expect('expr bazInherited', substrs=['bar::baz::InheritedCxxClass',
46+
'bar::baz::CxxClass = (baz_field = 50)', 'baz_subfield = 60'])
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import ReturnsClass
2+
3+
func main() {
4+
let fooClass = foo.CxxClass()
5+
let fooInherited = foo.InheritedCxxClass()
6+
7+
let barClass = bar.CxxClass()
8+
let barInherited = bar.InheritedCxxClass()
9+
10+
let bazClass = bar.baz.CxxClass()
11+
let bazInherited = bar.baz.InheritedCxxClass()
12+
13+
print(1) // Set breakpoint here
14+
}
15+
main()
16+
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module ReturnsClass {
2+
header "returns-class.h"
3+
requires cplusplus
4+
}
5+
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
2+
namespace foo {
3+
struct CxxClass {
4+
long long foo_field = 10;
5+
};
6+
7+
struct InheritedCxxClass: CxxClass {
8+
long long foo_subfield = 20;
9+
};
10+
} // namespace foo
11+
namespace bar {
12+
struct CxxClass {
13+
long long bar_field = 30;
14+
};
15+
16+
struct InheritedCxxClass: CxxClass {
17+
long long bar_subfield = 40;
18+
};
19+
20+
namespace baz {
21+
struct CxxClass {
22+
long long baz_field = 50;
23+
};
24+
25+
struct InheritedCxxClass: CxxClass {
26+
long long baz_subfield = 60;
27+
};
28+
} // namespace baz
29+
} // namespace bar

0 commit comments

Comments
 (0)