Skip to content

Commit 0b13bae

Browse files
Merge pull request llvm#2408 from adrian-prantl/73842894-5.4
Be more flexible when handling bridged Swift/ObjC CoreFoundation types.
2 parents 0af844b + f863b6d commit 0b13bae

File tree

8 files changed

+70
-9
lines changed

8 files changed

+70
-9
lines changed

lldb/source/Plugins/Language/Swift/SwiftLanguage.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -889,8 +889,15 @@ std::vector<ConstString> SwiftLanguage::GetPossibleFormattersMatches(
889889

890890
const bool check_cpp = false;
891891
const bool check_objc = false;
892-
bool canBeSwiftDynamic = compiler_type.IsPossibleDynamicType(
893-
nullptr, check_cpp, check_objc);
892+
bool canBeSwiftDynamic =
893+
compiler_type.IsPossibleDynamicType(nullptr, check_cpp, check_objc) ||
894+
// Foundation (but really any library) may create new
895+
// Objective-C classes at runtime and LLDB's ObjC runtime
896+
// implementation doesn't yet get notified about this. As a
897+
// workaround we try to interpret ObjC id pointers as Swift
898+
// classes to make them available.
899+
(compiler_type.GetCanonicalType().GetTypeClass() ==
900+
eTypeClassObjCObjectPointer);
894901

895902
if (canBeSwiftDynamic) {
896903
do {

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4805,6 +4805,12 @@ CompilerType SwiftASTContext::GetErrorType() {
48054805
return {};
48064806
}
48074807

4808+
CompilerType SwiftASTContext::GetObjCObjectType() {
4809+
// FIXME: ClangImporter::Implementation stores this type, but it's not
4810+
// exposed.
4811+
return GetCompilerType(ConstString("$sSo8NSObjectCD"));
4812+
}
4813+
48084814
SwiftASTContext *SwiftASTContext::GetSwiftASTContext(swift::ASTContext *ast) {
48094815
SwiftASTContext *swift_ast = GetASTMap().Lookup(ast);
48104816
return swift_ast;

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,7 @@ class SwiftASTContext : public TypeSystemSwift {
356356
CreateTupleType(const std::vector<TupleElement> &elements) override;
357357

358358
CompilerType GetErrorType() override;
359+
CompilerType GetObjCObjectType() override;
359360

360361
bool HasErrors();
361362

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ class TypeSystemSwift : public TypeSystem {
116116
virtual bool IsImportedType(lldb::opaque_compiler_type_t type,
117117
CompilerType *original_type) = 0;
118118
virtual CompilerType GetErrorType() = 0;
119+
virtual CompilerType GetObjCObjectType() = 0;
119120
virtual CompilerType GetReferentType(lldb::opaque_compiler_type_t type) = 0;
120121
static CompilerType GetInstanceType(CompilerType ct);
121122
virtual CompilerType GetInstanceType(lldb::opaque_compiler_type_t type) = 0;

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

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2755,6 +2755,23 @@ CompilerType TypeSystemSwiftTypeRef::GetErrorType() {
27552755
VALIDATE_AND_RETURN_STATIC(impl, GetErrorType);
27562756
}
27572757

2758+
CompilerType TypeSystemSwiftTypeRef::GetObjCObjectType() {
2759+
auto impl = [&]() {
2760+
using namespace swift::Demangle;
2761+
Demangler dem;
2762+
auto *obj_type = dem.createNode(Node::Kind::Type);
2763+
NodePointer s = dem.createNode(Node::Kind::Structure);
2764+
NodePointer m =
2765+
dem.createNode(Node::Kind::Module, swift::MANGLING_MODULE_OBJC);
2766+
NodePointer ident = dem.createNode(Node::Kind::Identifier, "NSObject");
2767+
s->addChild(m, dem);
2768+
s->addChild(ident, dem);
2769+
obj_type->addChild(s, dem);
2770+
return RemangleAsType(dem, obj_type);
2771+
};
2772+
VALIDATE_AND_RETURN_STATIC(impl, GetObjCObjectType);
2773+
}
2774+
27582775
CompilerType
27592776
TypeSystemSwiftTypeRef::GetReferentType(opaque_compiler_type_t type) {
27602777
auto impl = [&]() -> CompilerType {

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,7 @@ class TypeSystemSwiftTypeRef : public TypeSystemSwift {
235235
/// builtins (int <-> Swift.Int) as Clang types.
236236
CompilerType GetAsClangTypeOrNull(lldb::opaque_compiler_type_t type);
237237
CompilerType GetErrorType() override;
238+
CompilerType GetObjCObjectType() override;
238239
CompilerType GetReferentType(lldb::opaque_compiler_type_t type) override;
239240
CompilerType GetInstanceType(lldb::opaque_compiler_type_t type) override;
240241
TypeAllocationStrategy

lldb/source/Target/SwiftLanguageRuntimeDynamicTypeResolution.cpp

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2486,7 +2486,8 @@ static bool CouldHaveDynamicValue(ValueObject &in_value) {
24862486
// disable it.
24872487
return !in_value.IsBaseClass();
24882488
}
2489-
return var_type.IsPossibleDynamicType(nullptr, false, false);
2489+
bool check_objc = true;
2490+
return var_type.IsPossibleDynamicType(nullptr, false, check_objc);
24902491
}
24912492

24922493
bool SwiftLanguageRuntimeImpl::GetDynamicTypeAndAddress(
@@ -2497,10 +2498,6 @@ bool SwiftLanguageRuntimeImpl::GetDynamicTypeAndAddress(
24972498
if (use_dynamic == lldb::eNoDynamicValues)
24982499
return false;
24992500

2500-
// Try to import a Clang type into Swift.
2501-
if (in_value.GetObjectRuntimeLanguage() == eLanguageTypeObjC)
2502-
return GetDynamicTypeAndAddress_ClangType(
2503-
in_value, use_dynamic, class_type_or_name, address, value_type);
25042501

25052502
if (!CouldHaveDynamicValue(in_value))
25062503
return false;
@@ -2509,11 +2506,33 @@ bool SwiftLanguageRuntimeImpl::GetDynamicTypeAndAddress(
25092506
// use the scratch context where such operations are legal and safe.
25102507
assert(IsScratchContextLocked(in_value.GetTargetSP()) &&
25112508
"Swift scratch context not locked ahead of dynamic type resolution");
2509+
CompilerType val_type(in_value.GetCompilerType());
2510+
25122511
llvm::Optional<SwiftASTContextReader> maybe_scratch_ctx =
25132512
in_value.GetScratchSwiftASTContext();
2513+
2514+
// Try to import a Clang type into Swift.
2515+
if (in_value.GetObjectRuntimeLanguage() == eLanguageTypeObjC) {
2516+
if (GetDynamicTypeAndAddress_ClangType(
2517+
in_value, use_dynamic, class_type_or_name, address, value_type))
2518+
return true;
2519+
// If the type couldn't be resolved by the Clang runtime:
2520+
// Foundation, for example, generates new Objective-C classes on
2521+
// the fly (such as instances of _DictionaryStorage<T1, T2>) and
2522+
// LLDB's ObjC runtime implementation isn't set up to recognize
2523+
// these. As a workaround, try to resolve them as Swift types.
2524+
if (val_type.GetCanonicalType().GetTypeClass() ==
2525+
eTypeClassObjCObjectPointer)
2526+
if (maybe_scratch_ctx)
2527+
if (auto *scratch_ctx = maybe_scratch_ctx->get())
2528+
val_type = scratch_ctx->GetObjCObjectType();
2529+
}
2530+
25142531
if (!maybe_scratch_ctx)
25152532
return false;
25162533
SwiftASTContextForExpressions *scratch_ctx = maybe_scratch_ctx->get();
2534+
if (!scratch_ctx)
2535+
return false;
25172536

25182537
auto retry_once = [&]() {
25192538
// Retry exactly once using the per-module fallback scratch context.
@@ -2536,7 +2555,6 @@ bool SwiftLanguageRuntimeImpl::GetDynamicTypeAndAddress(
25362555

25372556
// Import the type into the scratch context. Any form of dynamic
25382557
// type resolution may trigger a cross-module import.
2539-
CompilerType val_type(in_value.GetCompilerType());
25402558
Flags type_info(val_type.GetTypeInfo());
25412559
if (!type_info.AnySet(eTypeIsSwift))
25422560
return false;

lldb/test/Shell/SwiftREPL/DictBridging.test

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,17 @@ let d_objc2 = NSArray(object: [1: 2] as [NSNumber: NSNumber] as NSDictionary)
6767
let d_objc3 = NSArray(object: [1: 2] as [Int: Int] as NSDictionary)
6868
// DICT-LABEL: d_objc3: NSArray = 1 element {
6969
// DICT-NEXT: [0] = 1 key/value pair {
70-
// DICT-NEXT: [0] = (key = 1, value = 2)
70+
//
71+
// Allowing for both multi-line and single-line
72+
// formatting, depending on CoreFoundation
73+
// implementation:
74+
//
75+
// DICT-NOT: }
76+
// DICT: [0] =
77+
// DICT-NOT: }
78+
// DICT: key = 1
79+
// DICT-NOT: }
80+
// DICT: value = 2
7181
// DICT-NEXT: }
7282
// DICT-NEXT: }
7383

0 commit comments

Comments
 (0)